summaryrefslogblamecommitdiffstats
path: root/mbbsd/name.c
blob: 67381b001894db97bf512a263524820919202840 (plain) (tree)
1
2
3
4
5
6
          
                
 
                                         
 
    










                                                                                        
                                                  







                                            
                                       


     

                                                                            
 
               
 

                   
 















                                                                        
                  
         















                                                                            
            







                                                                 
 



                                                                             


                                                                               

                                                      
                  
 




                                                                             
             
 


                                           
 

                                                                                
                                   




































                                                                     
             
     






















                                                                            

 
    
                                            
 
                           
 
                                                                     
 
                                           
 
 
          
                                              
                                                 
 
                                               
                       






                                                                      
                     



                        
                                         

                           
     








                                                                     







                        



                                                                   
 







                                                      

                    





                                        
 
 
 
   
                                                                          

                                                                   
 
                                                                           

                                    
 


                  
                     
 

                  
 
                               



                                                            
                           








                                   
                              



                                                                 
                                                                         

                                                                   
                                
                        
                                   

                             



                               

                                                                           
                             

                                                                          
                                       
                             


                                                    
                                                                           





                                                                    

                                


                                      
                         


                           
                                           

                    
                                             
                                                                         
                                                  
                                         
                                                            






                                      
                                   
             

                     
                                                                       



                          
                          









                                                                     
                                         

                                 
                                    
             









                                                    
         
     
 
               




                   
                       
                   
                   


                              
     

               
 

                                         
                                                         
 

                                                        
 

   

                                   
                                                          
                                              
                                                
                                               
 
 




                                                          
                                               


 


                                
                                                  
 
 

                                          
                                                        
 

                                                                        
 
 


                                  
                                                                       

                                                   
                                                                
                                    
 
 


                               
                                                                     
 
/* $Id$ */
#include "bbs.h"

#define MORE_MSG "按空白鍵可列出更多項目"

void
ToggleVector(struct Vector *list, int *recipient, const char *listfile, const char *msg)
{
    FILE           *fp;
    char            genbuf[STRLEN];

    if ((fp = fopen(listfile, "r"))) {
    while (fgets(genbuf, sizeof(genbuf), fp)) {
        char *space = strpbrk(genbuf, str_space);
        if (space) *space = '\0';
        if (!genbuf[0])
        continue;
        if (Vector_search(list, genbuf) < 0) {
        Vector_add(list, genbuf);
        (*recipient)++;
        } else {
        Vector_remove(list, genbuf);
        (*recipient)--;
        }
    }
    fclose(fp);
    ShowVector(list, 3, 0, msg, 0);
    }
}

int
ShowVector(struct Vector *list, int row, int col, const char * msg, int idx)
{
    int i, len;

    move(row, col);
    clrtobot();

    if (msg) {
    outs(msg);
    row++;
    }
    col = 0;

    len = Vector_MaxLen(list, idx, b_lines - row);
    while (len + col < t_columns) {
    for (i = row; idx < Vector_length(list) && (i < b_lines); i++) {
        move(i, col);
        outs(Vector_get(list, idx));
        idx++;
    }
    col += len + 2;
    if (idx == Vector_length(list)) {
        idx = 0;
        break;
    }
    len = Vector_MaxLen(list, idx, b_lines - row);
    }

    return idx;
}

struct namecomplete_int {
    const struct Vector * base;
    struct Vector sublist;
    int idx, dirty;
};

static int
nc_cb_peek(int key, VGET_RUNTIME *prt, void *instance)
{
    struct namecomplete_int * nc_int = (struct namecomplete_int *) instance;
    int tmp;

    prt->buf[prt->iend] = 0;

    if (nc_int->dirty < 0) {
    Vector_sublist(nc_int->base, &nc_int->sublist, prt->buf);
    nc_int->idx = 0;
    nc_int->dirty = 0;
    }

    switch (key) {
    case KEY_ENTER:
        if (Vector_length(&nc_int->sublist) == 1)
        strlcpy(prt->buf, Vector_get(&nc_int->sublist, 0), prt->len);
        else if ((tmp = Vector_search(&nc_int->sublist, prt->buf)) >= 0)
        strlcpy(prt->buf, Vector_get(&nc_int->sublist, tmp), prt->len);
        else
        prt->buf[0] = '\0';
        prt->icurr = prt->iend = strlen(prt->buf);
        break;

    case ' ':
        if (Vector_length(&nc_int->sublist) == 1) {
        strlcpy(prt->buf, Vector_get(&nc_int->sublist, 0), prt->len);
        prt->icurr = prt->iend = strlen(prt->buf);
        return VGETCB_NEXT;
        }

        move(2, 0);
        clrtobot();
        printdash("相關資訊一覽表", 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);
        return VGETCB_NEXT;
        break;

    case KEY_BS2: case KEY_BS:  /* backspace */
        nc_int->dirty = -1;
        break;

    case KEY_HOME:  case Ctrl('A'):
    case KEY_END:   case Ctrl('E'):
    case KEY_LEFT:  case Ctrl('B'):
    case KEY_RIGHT: case Ctrl('F'):
    case KEY_DEL:   case Ctrl('D'):
    case Ctrl('Y'):
    case Ctrl('K'):
        return VGETCB_NEXT;
        break;

    default:
        if (isprint(key)) {
        struct Vector tmplist;

        prt->buf[prt->iend] = key;
        prt->buf[prt->iend + 1] = 0;

        Vector_init(&tmplist, IDLEN + 1);
        Vector_sublist(&nc_int->sublist, &tmplist, prt->buf);

        if (Vector_length(&tmplist) == 0) {
            Vector_delete(&tmplist);
            prt->buf[prt->iend] = 0;
            return VGETCB_NEXT;
        } else {
            Vector_delete(&nc_int->sublist);
            nc_int->sublist = tmplist;
            nc_int->idx = 0;
            prt->buf[prt->iend] = 0;
        }
        }
    }
        
    return VGETCB_NONE;
}

void
namecomplete2(const struct Vector *namelist, const char *prompt, char *data)
{
    struct namecomplete_int nc_int = {
    .base = namelist,
    .dirty = 0,
    };
    VGET_CALLBACKS vcb = {
    .peek = nc_cb_peek,
    .data = NULL,
    .post = NULL,
    };

    outs(prompt);
    clrtoeol();
    Vector_init(&nc_int.sublist, IDLEN+1);
    Vector_sublist(namelist, &nc_int.sublist, "");
    vgetstring(data, IDLEN + 1, VGET_ASCII_ONLY, NULL, &vcb, &nc_int);
    Vector_delete(&nc_int.sublist);
}

void
usercomplete(const char *prompt, char *data)
{
    struct Vector namelist;

    Vector_init_const(&namelist, SHM->userid[0], MAX_USERS, IDLEN+1);

    namecomplete2(&namelist, prompt, data);
}

static int
gnc_findbound(char *str, int *START, int *END,
          size_t nmemb, gnc_comp_func compar)
{
    int             start, end, mid, cmp, strl;
    strl = strlen(str);

    start = -1, end = nmemb - 1;
    /* The first available element is always in the half-open interval
     * (start, end]. (or `end'-th it self if start == end) */
    while (end > start + 1) {
    mid = (start + end) / 2;
    cmp = (*compar)(mid, str, strl);
    if (cmp >= 0)
        end = mid;
    else
        start = mid;
    }
    if ((*compar)(end, str, strl) != 0) {
    *START = *END = -1;
    return -1;
    }
    *START = end;

    start = end;
    end = nmemb;
    /* The last available element is always in the half-open interval
     * [start, end). (or `start'-th it self if start == end) */
    while (end > start + 1) {
    mid = (start + end) / 2;
    cmp = (*compar)(mid, str, strl);
    if (cmp <= 0)
        start = mid;
    else
        end = mid;
    }
    *END = start;
    return 0;
}

static int
gnc_complete(char *data, int *start, int *end,
        gnc_perm_func permission, gnc_getname_func getname)
{
    int             i, count, first = -1, last = *end;
    if (*start < 0 || *end < 0)
    return 0;
    for (i = *start, count = 0; i <= *end; ++i)
    if ((*permission)(i)) {
        if (first == -1)
        first = i;
        last = i;
        ++count;
    }
    if (count == 1)
    strcpy(data, (*getname)(first));

    *start = first;
    *end = last;
    return count;
}


int
generalnamecomplete(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;

    outs(prompt);
    clrtoeol();
    getyx(&y, &x);
    scrx = origx = x;

    ptr = 0;
    data[ptr] = 0;

    start = 0; end = nmemb - 1;
    while (1)
    {
    // print input field again
    move(y, scrx); outc(' '); clrtoeol(); move(y, scrx);
    outs(ANSI_REVERSE);
    // data[ptr] = 0;
    prints("%-*s", len, data);
    outs(ANSI_RESET);
    move(y, scrx + ptr);

    // get input
    if ((ch = igetch()) == EOF)
        break;

    if (ch == KEY_ENTER) {
        data[ptr] = 0;
        outc('\n');
        if (ptr != 0) {
        gnc_findbound(data, &start, &end, nmemb, compar);
        if (gnc_complete(data, &start, &end, permission, getname)
            == 1 || (*compar)(start, data, len) == 0) {
            strcpy(data, (*getname)(start));
            ret = start;
        } else {
            data[0] = '\0';
            ret = -1;
        }
        } else
        ptr = -1;
        break;
    } else if (ch == ' ') {
        if (morelist == -1) {
        if (gnc_findbound(data, &start, &end, nmemb, compar) == -1)
            continue;
        i = gnc_complete(data, &start, &end, permission, getname);
        if (i == 1) {
            ptr = strlen(data);
            continue;
        } else {
            char* first = (*getname)(start);
            i = ptr;
            while (first[i] && (*compar)(end, first, i + 1) == 0) {
            data[i] = first[i];
            ++i;
            }
            data[i] = '\0';

            if (i != ptr) { /* did complete several words */
            ptr = i;
            }
        }
        morelist = start;
        } else if (morelist > end)
        continue;
        clearbot = YEA;
        move(2, 0);
        clrtobot();
        printdash("相關資訊一覽表", 0);

        col = 0;
        while (len + col < t_columns-1) {
        for (i = 0; morelist <= end && i < p_lines; ++morelist) {
            if ((*permission)(morelist)) {
            move(3 + i, col);
            prints("%s ", (*getname)(morelist));
            ++i;
            }
        }

        col += len + 2;
        }
        if (morelist != end + 1) {
        vshowmsg(MORE_MSG);
        }
        continue;

    } else if (ch == KEY_BS2 || ch == KEY_BS) { /* backspace */
        if (ptr == 0)
        continue;
        morelist = -1;
        --ptr;
        data[ptr] = 0;
        continue;
    } else if (isprint(ch) && ptr <= (len - 2)) {
        morelist = -1;
        data[ptr] = ch;
        ++ptr;
        data[ptr] = 0;
        if (gnc_findbound(data, &start, &end, nmemb, compar) < 0)
        data[--ptr] = 0;
        else {
        for (i = start; i <= end; ++i)
            if ((*permission)(i))
            break;
        if (i == end + 1)
            data[--ptr] = 0;
        }
    } else if (ch == KEY_UP || ch == KEY_DOWN) {
        if (!InputHistoryExists(data))
        InputHistoryAdd(data);

        if (ch == KEY_DOWN)
        InputHistoryNext(data, len);
        else
        InputHistoryPrev(data, len);

        ptr = strlen(data);
    }
    }

    outc('\n');
    if (clearbot) {
    move(2, 0);
    clrtobot();
    }
    if (*data) {
    move(y, origx);
    outs(data);
    outc('\n');

    // save the history
    InputHistoryAdd(data);
    }
    return ret;
}

/* general complete functions (brdshm) */
int
completeboard_compar(int where, const char *str, int len)
{
    boardheader_t *bh = &bcache[SHM->bsorted[0][where]];
    return strncasecmp(bh->brdname, str, len);
}

int
completeboard_permission(int where)
{
    boardheader_t *bptr = &bcache[SHM->bsorted[0][where]];
    return (!(bptr->brdattr & BRD_SYMBOLIC) &&
        (GROUPOP() || HasBoardPerm(bptr)) &&
        !(bptr->brdattr & BRD_GROUPBOARD));
}

int 
complete_board_and_group_permission(int where)
{
    boardheader_t *bptr = &bcache[SHM->bsorted[0][where]];
    return (!(bptr->brdattr & BRD_SYMBOLIC) &&
        (GROUPOP() || HasBoardPerm(bptr)));

}

char           *
completeboard_getname(int where)
{
    return bcache[SHM->bsorted[0][where]].brdname;
}

/* general complete functions (utmpshm) */
int
completeutmp_compar(int where, const char *str, int len)
{
    userinfo_t *u = &SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]];
    return strncasecmp(u->userid, str, len);
}

int
completeutmp_permission(int where)
{
   userinfo_t *u = &SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]];
    return (unlikely(HasUserPerm(PERM_SYSOP)) ||
        unlikely(HasUserPerm(PERM_SEECLOAK)) ||
//      !SHM->sorted[SHM->currsorted][0][where]->invisible);
        isvisible(currutmp, u));
}

char           *
completeutmp_getname(int where)
{
    return SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]].userid;
}