summaryrefslogblamecommitdiffstats
path: root/mbbsd/visio.c
blob: 789b6e60d695233663127c0658f3016a15a878a2 (plain) (tree)





































                                                                      





                                                    
    
                         
 










                                       
 

   






























                                                               
                                               








































                                                           
/* $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);
}