summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/visio.h60
-rw-r--r--mbbsd/visio.c209
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);