Annotation of embedaddon/trafshow/getkey.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     Copyright (c) 1998,2004 Rinet Corp., Novosibirsk, Russia
                      3:  *
                      4:  * Redistribution and use in source forms, with and without modification,
                      5:  * are permitted provided that this entire comment appears intact.
                      6:  *
                      7:  * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
                      8:  */
                      9: 
                     10: #ifdef HAVE_CONFIG_H
                     11: #include <config.h>
                     12: #endif
                     13: 
                     14: #ifdef HAVE_SLCURSES
                     15: #include <slcurses.h>
                     16: #elif  HAVE_NCURSES
                     17: #include <ncurses.h>
                     18: #else
                     19: #include <curses.h>
                     20: #endif
                     21: #include <stdio.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
                     24: #include <unistd.h>
                     25: 
                     26: #include "getkey.h"
                     27: #include "screen.h"
                     28: #include "session.h"
                     29: #include "trafshow.h"
                     30: #include "selector.h"
                     31: #include "show_if.h"
                     32: #include "show_stat.h"
                     33: #include "show_dump.h"
                     34: #include "events.h"
                     35: #include "netstat.h"
                     36: #include "help_page.h"
                     37: 
                     38: 
                     39: static void read_key(SESSION *sd, const unsigned char *data, int len);
                     40: static int scan_key(const unsigned char *buf, int len);
                     41: static void parse_key(int key, PCAP_HANDLER *ph);
                     42: static void init_edit_string(const char *prompter, const char *charset, int size);
                     43: static int edit_string(int ch);
                     44: 
                     45: /* edit string stuff */
                     46: static const char *numbers = "1234567890";
                     47: static const char *spaces = " ,.;@/\\";
                     48: static char prompt_buf[MAX_PARAM_LEN], cut_buf[MAX_PARAM_LEN];
                     49: static const char *char_set;
                     50: static int buf_size, cur, nb, win, scr, bartop, barlen, touch, show_win;
                     51: 
                     52: 
                     53: void
                     54: getkey_init(ph)
                     55:        PCAP_HANDLER *ph;
                     56: {
                     57:        SESSION *sd;
                     58: 
                     59:        if ((sd = session_open(0, 0, PlainFile)) == 0) {
                     60:                perror("session_open 0"); /* should not happen */
                     61:                exit(1);
                     62:        }
                     63:        session_setcallback(sd, 0, 0, read_key);
                     64:        session_setcookie(sd, ph);
                     65:        prompt_mode = 0;
                     66: }
                     67: 
                     68: static void
                     69: read_key(sd, data, len)
                     70:        SESSION *sd;
                     71:        const unsigned char *data;
                     72:        int len;
                     73: {
                     74:        /* sanity check */
                     75:        if (sd && data && len > 0) {
                     76:                int key = scan_key(data, len);
                     77:                if (key != -1)
                     78:                        parse_key(key, (PCAP_HANDLER *)session_cookie(sd));
                     79:        }
                     80: }
                     81: 
                     82: static SELECTOR *
                     83: get_selector(ph_list)
                     84:        PCAP_HANDLER *ph_list;
                     85: {
                     86:        /* return current selector */
                     87:        switch (show_mode) {
                     88:        case Interfaces:
                     89:                return show_if_selector();
                     90:        case NetStat:
                     91:                return show_stat_selector(pcap_get_selected(ph_list));
                     92:        case FlowDump:
                     93:                /* nope */
                     94:                break;
                     95:        case HelpPage:
                     96:                return help_page_selector();
                     97:        }
                     98:        return 0;
                     99: }
                    100: 
                    101: static void
                    102: parse_key(key, ph_list)
                    103:        int key;
                    104:        PCAP_HANDLER *ph_list;
                    105: {
                    106:        int ch = key;
                    107:        PCAP_HANDLER *ph = 0;
                    108:        SELECTOR *sp = 0;
                    109:        struct timeval now;
                    110: 
                    111:        if (prompt_mode) {
                    112:                const char *txt = 0;
                    113:                int redraw = 1;
                    114:                if ((ch = edit_string(ch)) == 0) /* still edit */
                    115:                        return;
                    116:                if (ch > 0) {
                    117:                        switch (prompt_mode) {
                    118:                        case 'r':       /* end of getting refresh time */
                    119:                        case 'R':
                    120:                                ch = atoi(prompt_buf);
                    121:                                if (ch > 0 && ch != refresh_time) {
                    122:                                        if (ch < purge_time)
                    123:                                                refresh_time = ch;
                    124:                                        else    txt = "Refresh Time must be less than Purge Time";
                    125:                                }
                    126:                                break;
                    127:                        case 'p':       /* end of getting purge time */
                    128:                        case 'P':
                    129:                                ch = atoi(prompt_buf);
                    130:                                if (ch > 0 && ch != purge_time) {
                    131:                                        if (ch > refresh_time) {
                    132:                                                purge_time = ch;
                    133:                                                add_event(0, pcap_purge, ph_list);
                    134:                                                redraw = 0;
                    135:                                        } else  txt = "Purge Time must be bigger than Refresh Time";
                    136:                                }
                    137:                                break;
                    138:                        case 'f':       /* end of getting filter expression */
                    139:                        case 'F':
                    140:                                if (!expression || strcmp(prompt_buf, expression)) {
                    141:                                        if (expression) free(expression);
                    142:                                        expression = strdup(prompt_buf);
                    143:                                        if ((txt = pcap_setexpr(ph_list, expression)) == 0) {
                    144:                                                if (prompt_mode == 'F') {
                    145:                                                        add_event(0, pcap_clear, ph_list);
                    146:                                                        redraw = 0;
                    147:                                                }
                    148:                                        }
                    149:                                }
                    150:                                break;
                    151:                        case '/':       /* end of getting search string */
                    152:                                if (prompt_buf[0] == '\0') {
                    153:                                        if (search) {
                    154:                                                free(search);
                    155:                                                search = 0;
                    156:                                                txt = "Search mode turned Off";
                    157:                                        }
                    158:                                } else if (!search || strcmp(prompt_buf, search)) {
                    159:                                        if (search) free(search);
                    160:                                        search = strdup(prompt_buf);
                    161:                                }
                    162:                                break;
                    163:                        case 'a':       /* end of getting aggregation masklen */
                    164:                        case 'A':
                    165:                                if (prompt_buf[0]) {
                    166:                                        ch = atoi(prompt_buf);
                    167:                                        if (ch < 0 || ch > ADDRBITLEN) {
                    168:                                                txt = "Wrong netmask length";
                    169:                                                break;
                    170:                                        }
                    171:                                } else  ch = -1;
                    172:                                if (show_mode == NetStat &&
                    173:                                    (ph = pcap_get_selected(ph_list)) != 0) {
                    174:                                        if (ph->masklen != ch) {
                    175:                                                ph->masklen = ch;
                    176:                                                if (prompt_mode == 'A')
                    177:                                                        netstat_purge(ph, 0);
                    178:                                        }
                    179:                                } else {
                    180:                                        aggregate = ch;
                    181:                                        for (ph = ph_list; ph; ph = ph->next) {
                    182:                                                if (ph->masklen != aggregate) {
                    183:                                                        ph->masklen = aggregate;
                    184:                                                        if (prompt_mode == 'A')
                    185:                                                                netstat_purge(ph, 0);
                    186:                                                }
                    187:                                        }
                    188:                                }
                    189:                                break;
                    190:                        }
                    191:                }
                    192:                prompt_mode = 0;
                    193:                if (redraw)
                    194:                        add_event(0, pcap_show, ph_list);
                    195:                if (txt)
                    196:                        screen_status(txt);
                    197:                else    screen_update();
                    198:                return;
                    199:        }
                    200: 
                    201:        /* try global operation keys */
                    202:        switch (ch) {
                    203:        case K_ESC:     /* get back show mode */
                    204:        case 'q':
                    205:        case 'Q':
                    206:                switch (show_mode) {
                    207:                case Interfaces:
                    208:                        exit(0);
                    209:                case NetStat:
                    210:                        if ((ph = pcap_get_selected(ph_list)) != 0 && ph->top)
                    211:                                pcaph_close(ph);
                    212:                        else    show_mode = Interfaces; 
                    213:                        pcap_show(ph_list);
                    214:                        return;
                    215:                case FlowDump:
                    216:                        show_dump_close();
                    217:                        show_mode = NetStat;
                    218:                        pcap_show(ph_list);
                    219:                        return;
                    220:                case HelpPage:
                    221:                        show_mode = help_page_mode();
                    222:                        pcap_show(ph_list);
                    223:                        return;
                    224:                }
                    225:                break;
                    226:        case K_CTRL('L'):       /* refresh screen */
                    227:                clear();
                    228:                refresh();
                    229:                pcap_show(ph_list);
                    230:                return;
                    231:        case 'h':       /* help page if any */
                    232:        case 'H':
                    233:        case '?':
                    234:        case K_F1:
                    235:                if (help_page_list(show_mode)) {
                    236:                        show_mode = HelpPage;
                    237:                        pcap_show(ph_list);
                    238:                        return;
                    239:                }
                    240:                break;
                    241:        case 'r':       /* start to get refresh time */
                    242:        case 'R':
                    243:                if (show_mode != FlowDump) {
                    244:                        prompt_mode = ch;
                    245:                        snprintf(prompt_buf, sizeof(prompt_buf), "%d", refresh_time);
                    246:                        init_edit_string("Refresh seconds: ", numbers, 5);
                    247:                        selector_withdraw(get_selector(ph_list));
                    248:                        screen_update();
                    249:                        return;
                    250:                }
                    251:                break;
                    252:        case 'p':       /* start to get purge time */
                    253:        case 'P':
                    254:                if (show_mode != FlowDump) {
                    255:                        prompt_mode = ch;
                    256:                        snprintf(prompt_buf, sizeof(prompt_buf), "%d", purge_time);
                    257:                        init_edit_string("Purge seconds: ", numbers, 5);
                    258:                        selector_withdraw(get_selector(ph_list));
                    259:                        screen_update();
                    260:                        return;
                    261:                }
                    262:                break;
                    263:        case 'f':       /* start to get filter expression */
                    264:        case 'F':
                    265:                if (show_mode != FlowDump) {
                    266:                        prompt_mode = ch;
                    267:                        prompt_buf[0] = '\0';
                    268:                        if (expression) {
                    269:                                (void)strncpy(prompt_buf, expression, sizeof(prompt_buf));
                    270:                                prompt_buf[sizeof(prompt_buf)-1] = '\0';
                    271:                        }
                    272:                        init_edit_string("Filter expression: ", 0, sizeof(prompt_buf));
                    273:                        selector_withdraw(get_selector(ph_list));
                    274:                        screen_update();
                    275:                        return;
                    276:                }
                    277:                break;
                    278:        case '/':       /* start to get search string */
                    279:                if (show_mode != FlowDump) {
                    280:                        prompt_mode = ch;
                    281:                        prompt_buf[0] = '\0';
                    282:                        if (search) {
                    283:                                (void)strncpy(prompt_buf, search, sizeof(prompt_buf));
                    284:                                prompt_buf[sizeof(prompt_buf)-1] = '\0';
                    285:                        }
                    286:                        init_edit_string("Search string: ", 0, sizeof(prompt_buf));
                    287:                        selector_withdraw(get_selector(ph_list));
                    288:                        screen_update();
                    289:                        return;
                    290:                }
                    291:                break;
                    292:        case K_CTRL('_'):       /* turn off search mode */
                    293:                if (show_mode != FlowDump) {
                    294:                        if (search) {
                    295:                                free(search);
                    296:                                search = 0;
                    297:                                screen_status("Search mode turned Off");
                    298:                        }
                    299:                        return;
                    300:                }
                    301:                break;
                    302:        case 'a':       /* start to get aggregation masklen */
                    303:        case 'A':
                    304:                if (show_mode != FlowDump) {
                    305:                        char buf[100];
                    306:                        prompt_mode = ch;
                    307:                        prompt_buf[0] = '\0';
                    308:                        if (show_mode == NetStat &&
                    309:                            (ph = pcap_get_selected(ph_list)) != 0) {
                    310:                                if (ph->masklen >= 0)
                    311:                                        snprintf(prompt_buf, sizeof(prompt_buf), "%d", ph->masklen);
                    312:                                snprintf(buf, sizeof(buf), "%s aggregation netmask length: ", ph->name);
                    313:                        } else {
                    314:                                if (aggregate >= 0)
                    315:                                        snprintf(prompt_buf, sizeof(prompt_buf), "%d", aggregate);
                    316:                                (void)strcpy(buf, "Aggregation netmask length: ");
                    317:                        }
                    318:                        init_edit_string(buf, numbers, 5);
                    319:                        selector_withdraw(get_selector(ph_list));
                    320:                        screen_update();
                    321:                        return;
                    322:                }
                    323:                break;
                    324:        case K_CTRL('R'): /* reset all netstat hash */
                    325:                if (show_mode == Interfaces) {
                    326:                        add_event(0, pcap_clear, ph_list);
                    327:                        screen_status("Resetting all flows");
                    328:                        return;
                    329:                }
                    330:                break;
                    331:        case 'n':       /* toggle numeric values to names conversion */
                    332:        case 'N':
                    333:                if (show_mode != FlowDump) {
                    334:                        nflag ^= 1;
                    335:                        if (ch == 'N') {
                    336:                                add_event(0, pcap_show, ph_list);
                    337:                        } else {
                    338:                                screen_status("Numeric values turned %s",
                    339:                                              nflag ? "On" : "Off");
                    340:                        }
                    341:                        return;
                    342:                }
                    343:                break;
                    344:        }
                    345: 
                    346:        /* prevent screen refresh overhead */
                    347:        gettimeofday(&now, 0);
                    348:        now.tv_sec += refresh_time;
                    349:        add_event(&now, pcap_show, ph_list);
                    350: 
                    351:        /* get current selector */
                    352:        switch (show_mode) {
                    353:        case Interfaces:
                    354:                sp = show_if_selector();
                    355:                break;
                    356:        case NetStat:
                    357:                if ((ph = pcap_get_selected(ph_list)) == 0)
                    358:                        return;
                    359:                sp = show_stat_selector(ph);
                    360: 
                    361:                /* try special input for the show mode */
                    362:                if (show_stat_input(ph, ch)) {
                    363:                        selector_redraw(sp);
                    364:                        return;
                    365:                }
                    366:                break;
                    367:        case FlowDump:
                    368:                /* special input only for the show mode */
                    369:                show_dump_input(ch);
                    370:                return;
                    371:        case HelpPage:
                    372:                sp = help_page_selector();
                    373:                break;
                    374:        }
                    375: 
                    376:        /* try special input for the selecting */
                    377:        ch = selector_move(ch, sp);
                    378:        if (ch < 0) {
                    379:                selector_redraw(sp);
                    380:                return;
                    381:        }
                    382: 
                    383:        /* something selected */
                    384:        switch (show_mode) {
                    385:        case Interfaces:
                    386:                if ((ph = pcap_set_selected(ph_list, ch)) == 0)
                    387:                        return; /* should not happen */
                    388:                /*selector_withdraw(sp);*/
                    389:                show_mode = NetStat;
                    390:                pcap_show(ph_list);
                    391:                return;
                    392:        case NetStat:
                    393:                /*selector_withdraw(sp);*/
                    394:                if (ph->masklen == -1) {
                    395:                        if (show_dump_open(ph, show_stat_get(ph, ch)) == 0)
                    396:                                show_mode = FlowDump;
                    397:                } else if (pcaph_create(ph, (struct netstat_header *)show_stat_get(ph, ch))) {
                    398:                        pcap_show(ph_list);
                    399:                }
                    400:                return;
                    401:        case FlowDump:
                    402:                /* not reached; just to avoid compiler warning */
                    403:                return;
                    404:        case HelpPage:
                    405:                key = help_page_key(ch);
                    406:                if (key != -1 && key != 0) {
                    407:                        show_mode = help_page_mode(); /* get back show mode */
                    408:                        pcap_show(ph_list);
                    409:                        parse_key(key, ph_list);
                    410:                }
                    411:                return;
                    412:        }
                    413: }
                    414: 
                    415: static int
                    416: scan_key(buf, len)
                    417:        const unsigned char *buf;
                    418:        int len;
                    419: {
                    420:        int i;
                    421: 
                    422:        if (buf[0] != ESCAPE) return buf[0];
                    423:        if (len == 1) return K_ESC;
                    424:        i = 1;
                    425:        if (buf[i] == '[' || buf[i] == 'O')
                    426:                if (++i >= len) return -1;
                    427: 
                    428:        switch (buf[i]) {
                    429:        case '\0':      /* xterm */
                    430:                return K_HOME;
                    431:        case 'A':
                    432:        case 'i':
                    433:                return K_UP;
                    434:        case 'B':
                    435:                return K_DOWN;
                    436:        case 'D':
                    437:                return K_LEFT;
                    438:        case 'C':
                    439:                return K_RIGHT;
                    440:        case 'I':       /* ansi  PgUp */
                    441:        case 'V':       /* at386 PgUp */
                    442:        case 'S':       /* 97801 PgUp */
                    443:        case 'v':       /* emacs style */
                    444:                return K_PAGEUP;
                    445:        case 'G':       /* ansi  PgDn */
                    446:        case 'U':       /* at386 PgDn */
                    447:        case 'T':       /* 97801 PgDn */
                    448:                return K_PAGEDOWN;
                    449:        case 'H':       /* at386  Home */
                    450:                return K_HOME;
                    451:        case 'F':       /* ansi   End */
                    452:        case 'Y':       /* at386  End */
                    453:                return K_END;
                    454:        case '5':       /* vt200 PgUp */
                    455:                return K_PAGEUP;
                    456:        case '6':       /* vt200 PgUp */
                    457:                return K_PAGEDOWN;
                    458:        case '1':       /* vt200 PgUp */
                    459:                if (++i >= len) return -1;
                    460:                switch(buf[i]) {        /* xterm */
                    461:                case '1':
                    462:                        return K_F1;
                    463:                case '2':
                    464:                        return K_F2;
                    465:                case '3':
                    466:                        return K_F3;
                    467:                case '4':
                    468:                        return K_F4;
                    469:                case '5':       /* RS/6000 PgUp is 150g, PgDn is 154g */
                    470:                        if (++i >= len) return -1;
                    471:                        if (buf[i] == '0')
                    472:                                return K_PAGEUP;
                    473:                        if (buf[i] == '4') 
                    474:                                return K_PAGEDOWN;
                    475:                }
                    476:                return K_HOME;
                    477:        case '4':       /* vt200 PgUp */
                    478:                return K_END;
                    479:        case '2':       /* xterm */
                    480:        case 'L':
                    481:                return K_INS;
                    482:        case 'M':
                    483:                return K_F1;
                    484:        case 'N':
                    485:                return K_F2;
                    486:        case 'O':
                    487:                return K_F3;
                    488:        case 'P':
                    489:                return K_F4;
                    490:        }
                    491:        return -1;
                    492: }
                    493: 
                    494: static void
                    495: init_edit_string(prompter, charset, size)
                    496:        const char *prompter, *charset;
                    497:        int size;
                    498: {
                    499:        int i;
                    500: 
                    501:        char_set = charset;
                    502:        touch = 0;
                    503:        show_win = 0;
                    504: 
                    505:        *cut_buf = '\0';
                    506:        bartop = strlen(prompter);
                    507:        i = COLS - (bartop + 3);
                    508:        barlen = buf_size = size;
                    509:        if (barlen < 1 || barlen > i) {
                    510:                barlen = i;
                    511:                show_win = 1;
                    512:        }
                    513: 
                    514:        attrset(A_NORMAL);
                    515:        move(LINES-1, 0);
                    516:        clrtoeol();
                    517:        addstr(prompter);
                    518: 
                    519:        nb = strlen(prompt_buf);
                    520:        if (nb >= buf_size) nb = buf_size - 1;
                    521:        prompt_buf[nb] = '\0';
                    522:        cur = nb;
                    523: 
                    524:        win = cur / barlen;     /* window number */
                    525:        scr = cur % barlen;     /* screen position */
                    526: 
                    527:        if (show_win) mvprintw(LINES-1, COLS-2, "%-2d", win+1);
                    528: 
                    529:        attrset(A_STANDOUT);
                    530:        mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
                    531: 
                    532:        screen_dock_cursor(LINES-1, bartop + scr);
                    533: }
                    534: 
                    535: static int
                    536: edit_string(ch)
                    537:        int ch;
                    538: {
                    539:        int i;
                    540: 
                    541:        switch (ch) {
                    542:        case K_ESC:
                    543:        case K_CR:
                    544:        case K_NL:
                    545:                prompt_buf[nb] = '\0';
                    546:                attrset(A_NORMAL);
                    547:                move(LINES-1, 0);
                    548:                clrtoeol();
                    549:                screen_dock_cursor(0, 0);
                    550:                return (ch == K_ESC ? -1 : 1);
                    551: 
                    552:        case K_PAGEUP:  /* move to begin of window */
                    553:                cur -= cur % barlen;
                    554:                break;
                    555:        case K_PAGEDOWN:/* move to end of window */
                    556:                if (strlen(&prompt_buf[cur]) < barlen)
                    557:                        cur = nb;
                    558:                else    cur += barlen - cur % barlen - 1;
                    559:                break;
                    560:        case K_UP:      /* skip to previous word */
                    561:        case K_CTRL('P'):
                    562:                ch = 0;
                    563:                for (i = cur; i > 0; i--) {
                    564:                        if (!ch) {
                    565:                                if (strchr(spaces, prompt_buf[i-1]))
                    566:                                        ch++;
                    567:                        } else if (!strchr(spaces, prompt_buf[i-1]))
                    568:                                break;
                    569:                }
                    570:                cur = i;
                    571:                break;
                    572:        case K_DOWN:    /* skip to next word */
                    573:        case K_CTRL('N'):
                    574:                ch = 0;
                    575:                for (i = cur; i < nb; i++) {
                    576:                        if (!ch) {
                    577:                                if (strchr(spaces, prompt_buf[i]))
                    578:                                        ch++;
                    579:                        } else if (!strchr(spaces, prompt_buf[i]))
                    580:                                break;
                    581:                }
                    582:                cur = i;
                    583:                break;
                    584:        case K_HOME:    /* move to begin of line */
                    585:        case K_CTRL('A'):
                    586:                cur = 0;
                    587:                break;
                    588:        case K_END:     /* move to end of line */
                    589:        case K_CTRL('E'):
                    590:                cur = nb;
                    591:                break;
                    592:        case K_LEFT:    /* move cursor left */
                    593:        case K_CTRL('B'):
                    594:                if (cur > 0) cur--;
                    595:                break;
                    596:        case K_RIGHT:   /* move cursor right */
                    597:        case K_CTRL('F'):
                    598:                if (cur < nb) cur++;
                    599:                break;
                    600:        case K_BS:      /* backspace */
                    601:                if (nb && cur) {
                    602:                        memmove(&prompt_buf[cur-1], &prompt_buf[cur], nb - cur);
                    603:                        cur--;
                    604:                        nb--;
                    605:                }
                    606:                break;
                    607:        case K_DEL:     /* delete */
                    608:        case K_CTRL('D'):
                    609:                if (nb && cur < nb) {
                    610:                        memmove(&prompt_buf[cur], &prompt_buf[cur+1], nb - cur);
                    611:                        nb--;
                    612:                }
                    613:                break;
                    614:        case K_CTRL('U'):       /* erase entire line */
                    615:                (void)strcpy(cut_buf, prompt_buf);
                    616:                nb = 0;
                    617:                cur = 0;
                    618:                break;
                    619:        case K_CTRL('W'):       /* erase last word */
                    620:                ch = 0;
                    621:                for (i = cur; i > 0; i--) {
                    622:                        if (!ch) {
                    623:                                if (strchr(spaces, prompt_buf[i-1]))
                    624:                                        ch++;
                    625:                        } else if (!strchr(spaces, prompt_buf[i-1]))
                    626:                                break;
                    627:                }
                    628:                if (cur > i) {
                    629:                        memcpy(cut_buf, &prompt_buf[i], cur - i);
                    630:                        cut_buf[cur - i] = '\0';
                    631:                        memmove(&prompt_buf[i], &prompt_buf[cur], cur - i);
                    632:                        nb -= cur - i;
                    633:                        cur = i;
                    634:                }
                    635:                break;
                    636:        case K_CTRL('K'):       /* erase end of line */
                    637:                if (prompt_buf[cur] != '\0')
                    638:                        (void)strcpy(cut_buf, &prompt_buf[cur]);
                    639:                nb = cur;
                    640:                break;
                    641:        case K_TAB:     /* insert cut_buf */
                    642:                i = strlen(cut_buf);
                    643:                if (i && (buf_size - 1) - strlen(prompt_buf) >= i) {
                    644:                        memmove(&prompt_buf[cur+i], &prompt_buf[cur], nb - cur);
                    645:                        memmove(&prompt_buf[cur], cut_buf, i);
                    646:                        nb += i;
                    647:                        cur += i;
                    648:                }
                    649:                break;
                    650:        default:
                    651:                if (ch < 32 || ch > 126)
                    652:                        return 0; /* skip garbage chars */
                    653: 
                    654:                if (char_set && !strchr(char_set, ch)) {
                    655:                        beep();
                    656:                        return 0;
                    657:                }
                    658:                if (!touch) {
                    659:                        nb = 0;
                    660:                        cur = 0;
                    661:                }
                    662:                if (nb >= buf_size - 1) { /* no more space available */
                    663:                        beep();
                    664:                        return 0;
                    665:                }
                    666:                if (nb > cur)
                    667:                        memmove(&prompt_buf[cur+1], &prompt_buf[cur], nb - cur);
                    668:                prompt_buf[cur++] = ch;
                    669:                nb++;
                    670:        }
                    671:        touch = 1;
                    672: 
                    673:        prompt_buf[nb] = '\0';
                    674: 
                    675:        win = cur / barlen;     /* window number */
                    676:        scr = cur % barlen;     /* screen position */
                    677: 
                    678:        attrset(A_STANDOUT);
                    679:        mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
                    680:        if (show_win) {
                    681:                attrset(A_NORMAL);
                    682:                mvprintw(LINES-1, COLS-2, "%-2d", win+1);
                    683:        }
                    684: 
                    685:        screen_dock_cursor(LINES-1, bartop + scr);
                    686:        screen_update();
                    687:        return 0;
                    688: }
                    689: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>