/* $Id$ */
#include "bbs.h"
/*
* visio.c
* High-level virtual screen input output control
*
* This is not the original visio.c from maple3.
* m3 visio = (ptt) visio+screen.
* This visio contains only high level UI element/widgets.
* In fact the only APIs from m3 are vmsg/vget...
*
* To add API here, please...
* (1) name the API in prefix of 'v'.
* (2) use only screen.c APIs.
* (3) take care of wide screen.
* (4) utilize the colos in visio.h, and name asa VCLR_* (visio color)
*/
// ---- DEFINITION ---------------------------------------------------
#define MAX_COL (t_columns-1)
#define SAFE_MAX_COL (MAX_COL-1)
// ---- UTILITIES ----------------------------------------------------
inline void
outnc(int n, unsigned char c)
{
while (n-- > 0)
outc(c);
}
inline void
nblank(int n)
{
outnc(n, ' ');
}
// ---- HIGH LEVEL API -----------------------------------------------
/**
* vbarf(s, ...): 格式化輸出左右對齊的字串 (MAX_COL)
*
* s 裡 \t 後的內容會對齊右端。
*/
void
vbarf(const char *s, ...)
{
char msg[512], *s2;
va_list ap;
va_start(ap, s);
vsnprintf(msg, sizeof(msg), s, ap);
va_end(ap);
s2 = strchr(msg, '\t');
if (s2) *s2++ = 0;
else s2 = "";
return vbar(msg, s2);
}
/**
* vbar(l, r): 左右對齊畫滿螢幕 (MAX_COL)
*
* 注意 r 的後面不會補空白。
* l r 都可以含 ANSI 控制碼。
* 注意: 目前的實作自動認定游標已在行開頭。
*/
void
vbar(const char *l, const char *r)
{
// TODO strlen_noansi 跑兩次... 其實 l 可以邊 output 邊算。
int szl = strlen_noansi(l),
szr = strlen_noansi(r);
// assume we are already in (y, 0)
clrtoeol();
outs(l);
szl = MAX_COL - szl;
if (szl > szr)
{
nblank(szl - szr);
szl = szr;
}
if (szl == szr)
outs(r);
else if (szl > 0)
nblank(szl);
outs(ANSI_RESET);
}
/**
* vfooter(caption, msg): 在螢幕底部印出格式化的 caption msg
*
* msg 中若有 () 則會變色, \t 後的文字會靠右。
* 最後面會自動留一個空白 (以避免自動偵測中文字的問題)。
*/
void
vfooter(const char *caption, const char *msg)
{
int i = 0;
move(b_lines, 0); clrtoeol();
if (caption)
{
outs(VCLR_FOOTER_CAPTION);
outs(caption); i+= strlen(caption);
}
if (!msg) msg = "";
outs(VCLR_FOOTER);
while (*msg && i < SAFE_MAX_COL)
{
if (*msg == '(')
outs(VCLR_FOOTER_QUOTE);
else if (*msg == '\t')
{
// if we don't have enough space, ignore whole.
int l = strlen(++msg);
if (i + l > SAFE_MAX_COL) break;
l = SAFE_MAX_COL - l - i;
nblank(l);
i += l;
continue;
}
outc(*msg); i++;
if (*msg == ')')
outs(VCLR_FOOTER);
msg ++;
}
nblank(SAFE_MAX_COL-i);
outc(' ');
outs(ANSI_RESET);
}