summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-10 17:39:46 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-10 17:39:46 +0800
commita399a5036f46d71b4bded57ba597d0825ce65d65 (patch)
tree172068e894aa54d234e03a32884cfc9d59eab3e1
parent9797bbf2a4d88a535ef6ec544242d970d2a51be7 (diff)
downloadpttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar.gz
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar.bz2
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar.lz
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar.xz
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.tar.zst
pttbbs-a399a5036f46d71b4bded57ba597d0825ce65d65.zip
* enable customizable footer floating messages
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@4922 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--pttbbs/include/proto.h5
-rw-r--r--pttbbs/mbbsd/more.c58
-rw-r--r--pttbbs/mbbsd/pmore.c384
3 files changed, 267 insertions, 180 deletions
diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h
index bc1970bc..3b520a15 100644
--- a/pttbbs/include/proto.h
+++ b/pttbbs/include/proto.h
@@ -374,8 +374,9 @@ int more(const char *fpath, int promptend);
/* piaip's new pager, pmore.c */
int pmore (const char *fpath, int promptend);
int pmore2(const char *fpath, int promptend, void *ctx,
- int (*key_handler) (int key, void *ctx),
- int (*help_handler)(int y, void *ctx));
+ int (*key_handler) (int key, void *ctx),
+ int (*footer_handler)(int ratio, int width, void *ctx),
+ int (*help_handler) (int y, void *ctx));
/* piaip's new telnet, telnet.c */
extern void telnet_init(int do_init_cmd);
extern ssize_t tty_read(unsigned char *buf, size_t max);
diff --git a/pttbbs/mbbsd/more.c b/pttbbs/mbbsd/more.c
index 2dec50b8..75000aa3 100644
--- a/pttbbs/mbbsd/more.c
+++ b/pttbbs/mbbsd/more.c
@@ -303,6 +303,63 @@ common_pmore_help_handler(int y, void *ctx)
return 0;
}
+static void
+display_hotkey_footer(const char *caption, const char *kattr, const char *vattr)
+{
+ while (*caption)
+ {
+ int c = *caption ++;
+ if (c == '(')
+ outs(kattr);
+ outc(c);
+ if (c == ')')
+ outs(vattr);
+ }
+}
+
+#define MACROSTRLEN(x) (sizeof(x)-1)
+static int
+common_pmore_footer_handler(int ratio, int width, void *ctx)
+{
+#define FOOTERMSG_READ_LONG "(y)回應 (X/%)推文 (h)說明 (←/q)離開 "
+#define FOOTERMSG_MAIL_LONG "(y)回信 (h)說明 (←/q)離開 "
+#define FOOTERMSG_SHORT "(h)說明 (←/q)離開 "
+#define FOOTERMSG_VERYSHORT "(←/q)離開 "
+
+ int w;
+ if (currstat == RMAIL && (w = MACROSTRLEN(FOOTERMSG_MAIL_LONG)) <= width)
+ {
+ if (width > w) prints("%*s", width-w, "");
+ display_hotkey_footer(FOOTERMSG_MAIL_LONG,
+ ANSI_COLOR(31), ANSI_COLOR(30));
+ return 0;
+ }
+ if (currstat == READING && (w = MACROSTRLEN(FOOTERMSG_READ_LONG)) <= width)
+ {
+ if (width > w) prints("%*s", width-w, "");
+ display_hotkey_footer(FOOTERMSG_READ_LONG,
+ ANSI_COLOR(31), ANSI_COLOR(30));
+ return 0;
+ }
+ if ( (w = MACROSTRLEN(FOOTERMSG_SHORT)) <= width)
+ {
+ if (width > w) prints("%*s", width-w, "");
+ display_hotkey_footer(FOOTERMSG_SHORT,
+ ANSI_COLOR(31), ANSI_COLOR(30));
+ return 0;
+ }
+ if ( (w = MACROSTRLEN(FOOTERMSG_VERYSHORT)) <= width)
+ {
+ if (width > w) prints("%*s", width-w, "");
+ display_hotkey_footer(FOOTERMSG_VERYSHORT,
+ ANSI_COLOR(31), ANSI_COLOR(30));
+ return 0;
+ }
+
+ if (width > w) prints("%*s", width-w, "");
+ return -1;
+}
+
/* use new pager: piaip's more. */
int
more(const char *fpath, int promptend)
@@ -310,6 +367,7 @@ more(const char *fpath, int promptend)
int r = pmore2(fpath, promptend,
(void*) fpath,
common_pmore_key_handler,
+ common_pmore_footer_handler,
common_pmore_help_handler);
// post processing
diff --git a/pttbbs/mbbsd/pmore.c b/pttbbs/mbbsd/pmore.c
index c14deb0a..0386741a 100644
--- a/pttbbs/mbbsd/pmore.c
+++ b/pttbbs/mbbsd/pmore.c
@@ -81,7 +81,7 @@
* - (2009) movie: add INCLUDE/INTERRUPT command [done]
* - (2009) Better help system [done]
* - (2009) Customizable key and help handler [done]
- * - Customizable footer bar and floating prompts
+ * - (2009) Customizable footer bar floating prompts [done]
* - Reject waterball (instant message) when playing movie
* - Support Anti-anti-idle (ex, PCMan sends up-down)
* - Deal or disable Ctrl-U (invokes userlist then waiting one more key)
@@ -357,7 +357,7 @@
*/
#ifdef DEBUG
-int debug = 0;
+static int debug = 0;
# define MFPROTO
# define MFFPROTO
#else
@@ -370,6 +370,10 @@ int debug = 0;
#define ustrchr(x,y) (unsigned char*)strchr((char*)x, y)
#define ustrrchr(x,y) (unsigned char*)strrchr((char*)x, y)
+// NOTE: this is a special strlen to speed up processing.
+// WARNING: x MUST be #define x "msg".
+// otherwise you need to use real strlen.
+#define PMORE_MACROSTRLEN(x) (sizeof(x)-1)
// --------------------------------------------- <Defines and constants>
@@ -1953,6 +1957,198 @@ mf_display()
move(b_lines, 0);
}
+MFPROTO void
+mf_display_footer(
+ int (*footer_handler)(int ratio, int width, void *ctx), void *ctx)
+{
+ // format:
+ // |PageNo Percentage|Detail Info|Floating1 (context)|Floating2 (quit)
+ // |SUMMARY|DETAIL|HELP
+
+ char buf[256]; // must be large enough to hold temporary data
+ int avail = t_columns-1; // available space
+ int w; // for width calculation
+
+ /*
+ * page determination is hard.
+ * should we use starting line, or finishing line?
+ */
+ int nowpage =
+ (int)((mf.lineno + mf.dispedlines/2) / MFNAV_PAGE)+1;
+ int allpages = -1; /* unknown yet */
+ int progress =
+ (int)((unsigned long)(mf.dispe-mf.start) * 100 / mf.len);
+
+#ifdef DEBUG
+ if(debug)
+ {
+ /* in debug mode don't print ANSI codes
+ * because themselves are buggy.
+ */
+ prints("L#%ld(w%ld,lp%ld) pmt=%d Dsp:%08X/%08X/%08X, "
+ "F:%08X/%08X(%d) tScr(%dx%d)",
+ mf.lineno, mf.wraplines, mf.lastpagelines,
+ promptend,
+ (unsigned int)mf.disps,
+ (unsigned int)mf.maxdisps,
+ (unsigned int)mf.dispe,
+ (unsigned int)mf.start, (unsigned int)mf.end,
+ (int)mf.len,
+ t_columns,
+ t_lines
+ );
+ return;
+ }
+#endif
+
+ // determine pges
+ if (mf.maxlinenoS >= 0)
+ {
+ allpages =
+ (int)((mf.maxlinenoS + mf.lastpagelines -
+ ((bpref.separator & MFDISP_SEP_WRAP) &&
+ (fh.lines >= 0) ? 0:1)) / MFNAV_PAGE)+1;
+ if (mf.lineno >= mf.maxlinenoS || nowpage > allpages)
+ nowpage = allpages;
+ /*
+ nowpage =
+ (int)((mf.lineno + mf.dispedlines-2) / MFNAV_PAGE)+1 ;
+ */
+ }
+ /* why -2 and -1?
+ * because we want to determine by nav_page,
+ * and mf.dispedlines is based on disp_page (nav_page+1)
+ * mf.lastpagelines is based on nav_page
+ */
+
+ // determine summary colours
+ outs(ANSI_RESET);
+ if(mf_viewedAll())
+ outs(PMORE_COLOR_FOOTER1_VIEWALL);
+ else if (mf_viewedNone())
+ outs(PMORE_COLOR_FOOTER1_VIEWNONE);
+ else
+ outs(PMORE_COLOR_FOOTER1);
+
+ // old status bar: quick draw
+ if(bpref.oldstatusbar)
+ {
+ prints(" 瀏覽 P.%d(%d%%) ", nowpage, progress);
+ outs(
+ PMORE_COLOR_FOOTER3 " "
+ PMORE_COLOR_FOOTER3_KEY "(h)"
+ PMORE_COLOR_FOOTER3_TEXT "求助 "
+ PMORE_COLOR_FOOTER3_KEY
+ "→↓[PgUp][PgDn][Home][End]"
+ PMORE_COLOR_FOOTER3_TEXT "游標移動 "
+ PMORE_COLOR_FOOTER3_KEY "←[q]"
+ PMORE_COLOR_FOOTER3_TEXT "結束 "
+ );
+ return;
+ }
+
+ // pmore style footer
+
+ // part 1, brief report (SUMMAR)
+ if(allpages >= 0)
+ snprintf(buf, sizeof(buf),
+ " 瀏覽 第 %1d/%1d 頁 (%3d%%) ",
+ nowpage,
+ allpages,
+ progress
+ );
+ else
+ snprintf(buf, sizeof(buf),
+ " 瀏覽 第 %1d 頁 (%3d%%) ",
+ nowpage,
+ progress
+ );
+ avail -= strlen(buf);
+ outs(buf);
+
+ // part 2, status report (DETAIL)
+ outs(PMORE_COLOR_FOOTER2);
+ if(override_msg)
+ {
+ buf[0] = 0;
+ if(override_attr) outs(override_attr);
+ snprintf(buf, sizeof(buf), override_msg);
+ RESET_OVERRIDE_MSG();
+ }
+ else
+ {
+ if(mf.xpos > 0)
+ {
+ snprintf(buf, sizeof(buf),
+ " 顯示範圍: %d~%d 欄位, %02d~%02d 行",
+ (int)mf.xpos+1,
+ (int)(mf.xpos + t_columns-(mf.trunclines ? 2 : 1)),
+ (int)(mf.lineno + 1),
+ (int)(mf.lineno + mf.dispedlines)
+ );
+ } else {
+ snprintf(buf, sizeof(buf),
+ " 目前顯示: 第 %02d~%025d 行",
+ (int)(mf.lineno + 1),
+ (int)(mf.lineno + mf.dispedlines)
+ );
+ }
+ }
+ avail -= strlen(buf);
+ outs(buf);
+
+ // usually avail is still > 0 here...
+ if (avail <= 0)
+ return;
+
+ // prepare the part 3
+ outs(PMORE_COLOR_FOOTER3);
+
+ // use customizable footer if available
+ if (footer_handler)
+ {
+ footer_handler(progress, avail, ctx);
+ return;
+ }
+
+ // part 3, help: context help and quit hotkeys
+#define PMORE_MSG_FOOTER_FLOAT_SHORT \
+ PMORE_COLOR_FOOTER3_KEY "(h)" \
+ PMORE_COLOR_FOOTER3_TEXT "按鍵說明 "
+
+#define PMORE_MSG_FOOTER_FLOAT_LONG \
+ PMORE_MSG_FOOTER_FLOAT_SHORT \
+ PMORE_COLOR_FOOTER3_KEY "←[q]" \
+ PMORE_COLOR_FOOTER3_TEXT "離開 "
+
+ // first try: long (context + quit)
+ w = PMORE_MACROSTRLEN(PMORE_MSG_FOOTER_FLOAT_LONG) -
+ PMORE_MACROSTRLEN(PMORE_COLOR_FOOTER3_KEY) *2 -
+ PMORE_MACROSTRLEN(PMORE_COLOR_FOOTER3_TEXT)*2;
+ if (avail >= w)
+ {
+ if (avail > w)
+ prints("%*s", avail-w, "");
+ outs(PMORE_MSG_FOOTER_FLOAT_LONG);
+ return;
+ }
+
+ // next try: short 4 only (quit)
+ w = PMORE_MACROSTRLEN(PMORE_MSG_FOOTER_FLOAT_SHORT) -
+ PMORE_MACROSTRLEN(PMORE_COLOR_FOOTER3_KEY) *1 -
+ PMORE_MACROSTRLEN(PMORE_COLOR_FOOTER3_TEXT)*1;
+ if (avail >= w)
+ {
+ if (avail > w)
+ prints("%*s", avail-w, "");
+ outs(PMORE_MSG_FOOTER_FLOAT_SHORT);
+ return;
+ }
+
+ // final: simply fill the extra space.
+ prints("%*s", avail, "");
+}
+
/* --------------------- MAIN PROCEDURE ------------------------- */
/*
@@ -2001,8 +2197,9 @@ PMORE_UINAV_FORWARDLINE()
int
pmore2(
const char *fpath, int promptend, void *ctx,
- int (*key_handler) (int key, void *ctx),
- int (*help_handler)(int y, void *ctx)
+ int (*key_handler) (int key, void *ctx),
+ int (*footer_handler)(int ratio, int width, void *ctx),
+ int (*help_handler) (int y, void *ctx)
)
{
int flExit = 0, retval = 0;
@@ -2205,179 +2402,10 @@ pmore2(
}
#endif
- /* PRINT BOTTOM STATUS BAR */
-#ifdef DEBUG
- if(debug)
- {
- /* in debug mode don't print ANSI codes
- * because themselves are buggy.
- */
- prints("L#%ld(w%ld,lp%ld) pmt=%d Dsp:%08X/%08X/%08X, "
- "F:%08X/%08X(%d) tScr(%dx%d)",
- mf.lineno, mf.wraplines, mf.lastpagelines,
- promptend,
- (unsigned int)mf.disps,
- (unsigned int)mf.maxdisps,
- (unsigned int)mf.dispe,
- (unsigned int)mf.start, (unsigned int)mf.end,
- (int)mf.len,
- t_columns,
- t_lines
- );
- }
- else
-#endif
- {
- char *printcolor;
-
- char buf[256]; // orz
- int prefixlen = 0;
- int barlen = 0;
- int postfix1len = 0, postfix2len = 0;
-
- int progress =
- (int)((unsigned long)(mf.dispe-mf.start) * 100 / mf.len);
- /*
- * page determination is hard.
- * should we use starting line, or finishing line?
- */
- int nowpage =
- (int)((mf.lineno + mf.dispedlines/2) / MFNAV_PAGE)+1;
- int allpages = -1; /* unknown yet */
- if (mf.maxlinenoS >= 0)
- {
- allpages =
- (int)((mf.maxlinenoS + mf.lastpagelines -
- ((bpref.separator & MFDISP_SEP_WRAP) &&
- (fh.lines >= 0) ? 0:1)) / MFNAV_PAGE)+1;
- if (mf.lineno >= mf.maxlinenoS || nowpage > allpages)
- nowpage = allpages;
- /*
- nowpage =
- (int)((mf.lineno + mf.dispedlines-2) / MFNAV_PAGE)+1 ;
- */
- }
- /* why -2 and -1?
- * because we want to determine by nav_page,
- * and mf.dispedlines is based on disp_page (nav_page+1)
- * mf.lastpagelines is based on nav_page
- */
-
- if(mf_viewedAll())
- printcolor = PMORE_COLOR_FOOTER1_VIEWALL;
- else if (mf_viewedNone())
- printcolor = PMORE_COLOR_FOOTER1_VIEWNONE;
- else
- printcolor = PMORE_COLOR_FOOTER1;
-
- outs(ANSI_RESET);
- outs(printcolor);
-
- if(bpref.oldstatusbar)
- {
-
- prints(" 瀏覽 P.%d(%d%%) %s %-30.30s%s",
- nowpage,
- progress,
- PMORE_COLOR_FOOTER3,
- PMORE_COLOR_FOOTER3_KEY "(h)"
- PMORE_COLOR_FOOTER3_TEXT "求助 "
- PMORE_COLOR_FOOTER3_KEY "→↓[PgUp][",
- "PgDn][Home][End]"
- PMORE_COLOR_FOOTER3_TEXT "游標移動 "
- PMORE_COLOR_FOOTER3_KEY "←[q]"
- PMORE_COLOR_FOOTER3_TEXT "結束 ");
-
- } else {
-
- // part 1, brief report
- if(allpages >= 0)
- sprintf(buf,
- " 瀏覽 第 %1d/%1d 頁 (%3d%%) ",
- nowpage,
- allpages,
- progress
- );
- else
- sprintf(buf,
- " 瀏覽 第 %1d 頁 (%3d%%) ",
- nowpage,
- progress
- );
- outs(buf); prefixlen += strlen(buf);
-
- // part 2, status report
- outs(PMORE_COLOR_FOOTER2);
- if(override_msg)
- {
- buf[0] = 0;
- if(override_attr) outs(override_attr);
- snprintf(buf, sizeof(buf), override_msg);
- RESET_OVERRIDE_MSG();
- }
- else
- if(mf.xpos > 0)
- {
- snprintf(buf, sizeof(buf),
- " 顯示範圍: %d~%d 欄位, %02d~%02d 行",
- (int)mf.xpos+1,
- (int)(mf.xpos + t_columns-(mf.trunclines ? 2 : 1)),
- (int)(mf.lineno + 1),
- (int)(mf.lineno + mf.dispedlines)
- );
- } else {
- snprintf(buf, sizeof(buf),
- " 目前顯示: 第 %02d~%02d 行",
- (int)(mf.lineno + 1),
- (int)(mf.lineno + mf.dispedlines)
- );
- }
-
- outs(buf); prefixlen += strlen(buf);
-
- postfix1len = 12; // check msg below
- postfix2len = 10;
-
-#ifdef PMORE_USE_REPLYKEY_HINTS
- if(mf_viewedAll()) postfix1len = 17;
-#endif // PMORE_USE_REPLYKEY_HINTS
-
- if (prefixlen + postfix1len + postfix2len + 1 > t_columns)
- {
- postfix1len = 0;
- // try again
- if (prefixlen+postfix1len+postfix2len + 1 > t_columns)
- postfix2len = 0;
- }
- barlen = t_columns - 1 - postfix1len - postfix2len - prefixlen;
-
- while(barlen-- > 0)
- outc(' ');
-
- // part 3, floating help
- outs(PMORE_COLOR_FOOTER3);
- if(postfix1len > 0)
- outs(
-#ifdef PMORE_USE_REPLYKEY_HINTS
- mf_viewedAll() ?
- PMORE_COLOR_FOOTER3_KEY "(y)"
- PMORE_COLOR_FOOTER3_TEXT "回應"
- PMORE_COLOR_FOOTER3_KEY "(X/%)"
- PMORE_COLOR_FOOTER3_TEXT "推文 "
- :
-#endif // PMORE_USE_REPLYKEY_HINTS
- PMORE_COLOR_FOOTER3_KEY "(h)"
- PMORE_COLOR_FOOTER3_TEXT "按鍵說明 "
- );
- if(postfix2len > 0)
- outs(
- PMORE_COLOR_FOOTER3_KEY "←[q]"
- PMORE_COLOR_FOOTER3_TEXT "離開 "
- );
- }
- outs(ANSI_RESET);
- FORCE_CLRTOEOL();
- }
+ /* PRINT FOOTER */
+ mf_display_footer(footer_handler, ctx);
+ outs(ANSI_RESET);
+ FORCE_CLRTOEOL();
/* vkey() will do refresh(); */
ch = vkey();
@@ -2724,7 +2752,7 @@ pmore2(
int
pmore(const char *fpath, int promptend)
{
- return pmore2(fpath, promptend, NULL, NULL, NULL);
+ return pmore2(fpath, promptend, NULL, NULL, NULL, NULL);
}
// ---------------------------------------------------- Preference and Help