diff options
-rw-r--r-- | pttbbs/mbbsd/name.c | 166 |
1 files changed, 160 insertions, 6 deletions
diff --git a/pttbbs/mbbsd/name.c b/pttbbs/mbbsd/name.c index d4cef005..8ed2138b 100644 --- a/pttbbs/mbbsd/name.c +++ b/pttbbs/mbbsd/name.c @@ -1,7 +1,8 @@ /* $Id$ */ #include "bbs.h" -#define MORE_MSG "按空白鍵可列出更多項目" +#define COMPLETE_MORE_MSG "按空白鍵可列出更多項目" +#define COMPLETE_LIST_TITLE "相關資訊一覽表" void ToggleVector(struct Vector *list, int *recipient, const char *listfile, const char *msg) @@ -100,11 +101,11 @@ nc_cb_peek(int key, VGET_RUNTIME *prt, void *instance) move(2, 0); clrtobot(); - printdash("相關資訊一覽表", 0); + printdash(COMPLETE_LIST_TITLE, 0); nc_int->idx = ShowVector(&nc_int->sublist, 3, 0, NULL, nc_int->idx); if (nc_int->idx < Vector_length(&nc_int->sublist)) - vshowmsg(MORE_MSG); + vshowmsg(COMPLETE_MORE_MSG); return VGETCB_NEXT; break; @@ -168,7 +169,6 @@ usercomplete(const char *prompt, char *data) struct Vector namelist; Vector_init_const(&namelist, SHM->userid[0], MAX_USERS, IDLEN+1); - namecomplete2(&namelist, prompt, data); } @@ -234,12 +234,166 @@ gnc_complete(char *data, int *start, int *end, return count; } +typedef struct { + int start, end, nmemb, ptr; + int morelist; + int clearbot; // YEA if screen was dirty + gnc_comp_func compar; + gnc_perm_func permission; + gnc_getname_func getname; +} generalcomplete_int; + +static int +gnc_cb_data(int key, VGET_RUNTIME *prt, void *instance) +{ + generalcomplete_int *gc_int = (generalcomplete_int*) instance; + char *data = prt->buf; + int ret = VGETCB_NEXT; // reject by default + int i; + gc_int->morelist = -1; + + assert(prt->icurr+1 < prt->len); + // try to add character + data[prt->icurr] = key; + data[prt->icurr+1]= 0; + if (gnc_findbound(data, &gc_int->start, &gc_int->end, gc_int->nmemb, gc_int->compar) >= 0) + { + // verify permission + for (i = gc_int->start; i <= gc_int->end; ++i) + if ((*gc_int->permission)(i)) + break; + // found something? accept it + if (i != gc_int->end + 1) + ret = VGETCB_NONE; + } + // restore data buffer + data[prt->icurr]= 0; + return ret; +} + +static int +gnc_cb_peek(int key, VGET_RUNTIME *prt, void *instance) +{ + generalcomplete_int *gc_int = (generalcomplete_int*) instance; + char *data = prt->buf; + + switch(key) { + case KEY_BS: // backspace + gc_int->morelist = -1; + break; + + case ' ': // render complete page + assert(prt->icurr == prt->iend); + if (gc_int->morelist == -1) + { + int i; + char *first; + if (gnc_findbound(data, &gc_int->start, &gc_int->end, + gc_int->nmemb, gc_int->compar) == -1) + return VGETCB_NEXT; + + i = gnc_complete (data, &gc_int->start, &gc_int->end, + gc_int->permission, gc_int->getname); + if (i == 1) { + prt->iend = prt->icurr = strlen(data); + return VGETCB_NEXT; + } + first = (*gc_int->getname)(gc_int->start); + i = prt->icurr; + while (first[i] && (*gc_int->compar)(gc_int->end, first, i + 1) == 0) { + data[i] = first[i]; + ++i; + } + data[i] = '\0'; + prt->iend = prt->icurr = i; + gc_int->morelist = gc_int->start; + } else if (gc_int->morelist > gc_int->end) + return VGETCB_NEXT; + + // rendef list + gc_int->clearbot = YEA; + move(2, 0); + clrtobot(); + printdash(COMPLETE_LIST_TITLE, 0); + { + int col = 0, i = 0; + int len = prt->len; + while (len + col < t_columns-1) { + for (i = 0; gc_int->morelist <= gc_int->end && i < p_lines; ++gc_int->morelist) { + if ((*gc_int->permission)(gc_int->morelist)) { + move(3 + i, col); + prints("%s ", (*gc_int->getname)(gc_int->morelist)); + ++i; + } + } + col += len + 2; + } + } + if (gc_int->morelist != gc_int->end + 1) { + vshowmsg(COMPLETE_MORE_MSG); + } + return VGETCB_NEXT; + } + return VGETCB_NONE; +} + int generalnamecomplete(const char *prompt, char *data, int len, size_t nmemb, gnc_comp_func compar, gnc_perm_func permission, gnc_getname_func getname) { + generalcomplete_int gc_int = { + .start = 0, + .end = nmemb-1, + .nmemb = nmemb, + .morelist = -1, + .clearbot = NA, + .compar = compar, + .permission = permission, + .getname = getname, + }; + const VGET_CALLBACKS vcb = { + .peek = gnc_cb_peek, + .data = gnc_cb_data, + }; + int ret = -1; + + outs(prompt); + clrtoeol(); + + // init vector + ret = vgetstring(data, len, VGET_NO_NAV_EDIT, NULL, &vcb, &gc_int); + outc('\n'); + + // vgetstring() return string length, but namecomplete needs to return + // the index of input string. + + if (ret < 1) + { + data[0] = '\0'; + return -1; + } + + gnc_findbound(data, &gc_int.start, &gc_int.end, nmemb, compar); + if (gnc_complete(data, &gc_int.start, &gc_int.end, permission, getname) == 1 || + (*compar)(gc_int.start, data, len) == 0) + { + strlcpy(data, (*getname)(gc_int.start), len); + ret = gc_int.start; + } else { + data[0] = '\0'; + ret = -1; + } + + return ret; +} + +int +generalnamecomplete_old(const char *prompt, char *data, int len, size_t nmemb, + gnc_comp_func compar, gnc_perm_func permission, + gnc_getname_func getname) +{ int x, y, origx, scrx, ch, i, morelist = -1, col, ret = -1; int start, end, ptr; int clearbot = NA; @@ -310,7 +464,7 @@ generalnamecomplete(const char *prompt, char *data, int len, size_t nmemb, clearbot = YEA; move(2, 0); clrtobot(); - printdash("相關資訊一覽表", 0); + printdash(COMPLETE_LIST_TITLE, 0); col = 0; while (len + col < t_columns-1) { @@ -325,7 +479,7 @@ generalnamecomplete(const char *prompt, char *data, int len, size_t nmemb, col += len + 2; } if (morelist != end + 1) { - vshowmsg(MORE_MSG); + vshowmsg(COMPLETE_MORE_MSG); } continue; |