diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-04-16 13:40:46 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-04-16 13:40:46 +0800 |
commit | e945ea798cc53053365fc9aa302ec027705c4154 (patch) | |
tree | f4934ac9c408b740a2dfaa09126fc43803250093 | |
parent | a38ce8fbc7b7b18ad75f86278fe25fd85ba485d2 (diff) | |
download | pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar.gz pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar.bz2 pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar.lz pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar.xz pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.tar.zst pttbbs-e945ea798cc53053365fc9aa302ec027705c4154.zip |
- (internal) visio: add vfill/vfillw, with more flexity to vcols.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4171 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | include/visio.h | 60 | ||||
-rw-r--r-- | mbbsd/visio.c | 209 |
2 files changed, 128 insertions, 141 deletions
diff --git a/include/visio.h b/include/visio.h index af8cf4dd..b3164709 100644 --- a/include/visio.h +++ b/include/visio.h @@ -32,43 +32,57 @@ #define VMSG_HDR_POSTFIX " 】" // CONSTANT DEFINITION ------------------------------------------------- -#define VCOL_ALIGN_LEFT (0) -#define VCOL_ALIGN_RIGHT (1) -// #define VCOL_ALIGN_MIDDLE (2) #define VCOL_MAXW (INT16_MAX) +#define VFILL_DEFAULT (0x00) +#define VFILL_NO_ANSI VFILL_DEFAULT +#define VFILL_HAS_ANSI (0x01) +#define VVILL_LEFT_ALIGN VFILL_DEFAULT +#define VFILL_RIGHT_ALIGN (0x02) +#define VFILL_HAS_BORDER VFILL_DEFAULT +#define VFILL_NO_BORDER (0x08) + // DATATYPE DEFINITION ------------------------------------------------- typedef void * VREFSCR; typedef long VREFCUR; typedef short VCOLW; typedef struct { - char *caption; char *attr; // default attribute VCOLW minw; // minimal width VCOLW maxw; // max width - char has_ansi; // support ANSI escape sequence - char align; // alignment - char usewhole; // draw entire column, not leaving borders - char flag; // reserved + + struct { + char has_ansi; // field data have ANSI escapes + char right_align; // align output to right side + char usewhole; // draw entire column and prevent borders + } flags; + } VCOL; // API DEFINITION ---------------------------------------------------- -// int vans(char *prompt); // prompt at bottom and return y/n in lower case. -// void vs_bar(char *title); // like stand_title -void vpad (int n, const char *pattern); - int vgety (void); -void vbarf (const char *s, ...) GCC_CHECK_FORMAT(1,2); -void vbarlr (const char *l, const char *r); -int vmsgf (const char *fmt,...) GCC_CHECK_FORMAT(1,2); -int vmsg (const char *msg); -int vansf (const char *fmt,...) GCC_CHECK_FORMAT(1,2); -int vans (const char *msg); -void vshowmsg(const char *msg); +// curses flavor void prints(const char *fmt, ...) GCC_CHECK_FORMAT(1,2); void mvouts(int y, int x, const char *str); +// v*: primitive rendering +void vpad (int n, const char *pattern); /// pad n fields by pattern + int vgety (void); /// return cursor position (y) +void vfill (int n, int flags, const char *s); /// fill n-width space with s +void vfillf (int n, int flags, const char *s, ...) GCC_CHECK_FORMAT(3,4); // formatted version of vfill +void vbarlr (const char *l, const char *r); /// draw a left-right expanded bar with (l,r) +void vbarf (const char *s, ...) GCC_CHECK_FORMAT(1,2); /// vbarlr with formatted input (\t splits (l,r) +void vshowmsg(const char *msg); /// draw standard pause/message + +// v*: input widgets +// int vans(char *prompt); // prompt at bottom and return y/n in lower case. + int vmsg (const char *msg); /// draw standard pause/message and return input + int vmsgf (const char *fmt,...) GCC_CHECK_FORMAT(1,2); /// formatted input of vmsg + int vans (const char *msg); /// prompt and return (lowercase) single byte input + int vansf (const char *fmt,...) GCC_CHECK_FORMAT(1,2); /// formatted input of vans + + // vs_*: formatted and themed virtual screen layout // you cannot use ANSI escapes in these APIs. void vs_header (const char *title, const char *mid, const char *right); // vs_head, showtitle @@ -76,14 +90,10 @@ void vs_hdr (const char *title); // vs_bar, stand_title void vs_footer (const char *caption, const char *prompt); // columned output -void vs_cols_layout (const VCOL* cols, VCOLW *ws, int n); -void vs_cols_hdr (const VCOL* cols, const VCOLW *ws, int n); +void vs_cols_layout (const VCOL* cols, VCOLW *ws, int n); /// calculate VCOL to fit current screen in ws void vs_cols (const VCOL* cols, const VCOLW *ws, int n, ...); -// compatible macros -#define stand_title vs_hdr - -// VREF API: +// VREF: save and storing temporary objects (restore will also free object). VREFSCR vscr_save (void); void vscr_restore(VREFSCR); VREFCUR vcur_save (void); diff --git a/mbbsd/visio.c b/mbbsd/visio.c index 43b9ff3e..7001f23e 100644 --- a/mbbsd/visio.c +++ b/mbbsd/visio.c @@ -49,7 +49,7 @@ nblank(int n) outnc(n, ' '); } -inline void +static inline void fillns(int n, const char *s) { while (n > 0 && *s) @@ -58,8 +58,8 @@ fillns(int n, const char *s) outnc(n, ' '); } -inline void -fillns_ansi(int n, char *s) +static inline void +fillns_ansi(int n, const char *s) { int d = strat_ansi(n, s); if (d < 0) { @@ -156,6 +156,86 @@ mvouts(int y, int x, const char *str) } /** + * vfill(n, flags, s): 印出並填滿 n 個字元的空間 + * + * @param n space to occupy + * @param flags VFILL_* parameters + * @param s string to display + */ +void +vfill(int n, int flags, const char *s) +{ + // warning: flag determination must take care of default values. + char has_ansi = ((flags & VFILL_HAS_ANSI) || (*s == ESC_CHR)); + char has_border = !(flags & VFILL_NO_BORDER); + + if (n < 1) + return; + + // quick return + if (!*s) + { + nblank(n); + return; + } + + // calculate border size (always draw because n > 0) + if (has_border) + n--; + + if (n > 0) + { + if (flags & VFILL_RIGHT_ALIGN) + { + // right-align + int l = has_ansi ? strlen_noansi(s) : strlen(s); + + if (l >= n) // '=' prevents blanks + l = n; + else { + nblank(n - l); + n = l; + } + // leave the task to left-align + } + + // left-align + if (has_ansi) + fillns_ansi(n, s); + else + fillns(n, s); + } + + // print border if required + if (has_border) + outc(' '); + + // close fill. + if (has_ansi) + outs(ANSI_RESET); +} + +/** + * vfill(n, flags, fmt, ...): 使用 vfill 輸出並格式化字串。 + * + * @param n space to occupy + * @param flags VFILL_* parameters + * @param fmt string to display + */ +void +vfillf(int n, int flags, const char *s, ...) +{ + va_list args; + char buff[VBUFLEN]; + + va_start(args, s); + vsnprintf(buff, sizeof(buff), s, args); + va_end(args); + + vfill(n, flags, s); +} + +/** * vpad(n, pattern): 填滿 n 個字元 (使用的格式為 pattern) * * @param n 要填滿的字元數 (無法填滿時會使用空白填補) @@ -514,7 +594,7 @@ vs_footer(const char *caption, const char *msg) } /** - * vs_cols_layout(cols, ws, n): 依據 cols (大小寫 n) 的定義計算適合的行寬於 ws + * vs_cols_layout(cols, ws, n): 依據 cols (大小 n) 的定義計算適合的行寬於 ws */ void @@ -535,6 +615,7 @@ vs_cols_layout(const VCOL *cols, VCOLW *ws, int n) // try to iterate through all. while (tw < MAX_COL) { + // TODO process priority? char run = 0; d++; for (i = 0; i < n; i++) @@ -552,59 +633,6 @@ vs_cols_layout(const VCOL *cols, VCOLW *ws, int n) } /** - * vs_cols_hdr: 依照已經算好的欄位輸出標題列 - */ -void -vs_cols_hdr (const VCOL* cols, const VCOLW *ws, int n) -{ - int i; - char *s; - - outs(ANSI_COLOR(5)); // TODO use theme color? - for (i = 0; i < n; i++, cols++, ws++) - { - int w = *ws; - - s = cols->caption; - if (!s) s = ""; - - if (!cols->usewhole) - w--; - - if (w > 0) { - switch(cols->align) - { - case VCOL_ALIGN_LEFT: - fillns(w, s); - break; - - case VCOL_ALIGN_RIGHT: - { - int l = strlen(s); - - if (l >= w) - l = w; - else - nblank(w - l); - - // simular to left align - fillns(l, s); - } - break; - - default: - assert(0); - } - } - - // only drop if w < 0 (no space for whole) - if (!cols->usewhole && w >= 0) - outc(' '); - } - outs(ANSI_RESET "\n"); -} - -/** * vs_cols: 依照已經算好的欄位大小進行輸出 */ void @@ -612,13 +640,13 @@ vs_cols(const VCOL *cols, const VCOLW *ws, int n, ...) { int i = 0, w = 0; char *s = NULL; - char ovattr = 0; va_list ap; va_start(ap, n); for (i = 0; i < n; i++, cols++, ws++) { + int flags = 0; s = va_arg(ap, char*); // quick check input. @@ -626,70 +654,19 @@ vs_cols(const VCOL *cols, const VCOLW *ws, int n, ...) { s = ""; } - else if (*s == ESC_CHR && !cols->has_ansi) // special rule to escape - { - outs(s); i--; // one more parameter! - ovattr = 1; - continue; - } + w = *ws; - if (cols->attr && !ovattr) + if (cols->attr) outs(cols->attr); - w = *ws; - - if (!cols->usewhole) - w--; - - // render value if field has enough space. - if (w > 0) { - switch (cols->align) - { - case VCOL_ALIGN_LEFT: - if (cols->has_ansi) - fillns_ansi(w, s); - else - fillns(w, s); - break; - - case VCOL_ALIGN_RIGHT: - // complex... - { - int l = 0; - if (cols->has_ansi) - l = strlen_noansi(s); - else - l = strlen(s); - - if (l >= w) - l = w; - else - nblank(w - l); - - // simular to left align - if (cols->has_ansi) - fillns_ansi(l, s); - else - fillns(l, s); - } - break; - - default: - assert(0); - break; - } - } + // build vfill flag + if (cols->flags.right_align) flags |= VFILL_RIGHT_ALIGN; + if (cols->flags.usewhole) flags |= VFILL_NO_BORDER; - // only drop if w < 0 (no space for whole) - if (!cols->usewhole && w >= 0) - outc(' '); + vfill(w, flags, s); - if (cols->attr || cols->has_ansi || ovattr) - { - if (ovattr) - ovattr = 0; + if (cols->attr) outs(ANSI_RESET); - } } va_end(ap); |