Annotation of embedaddon/trafshow/getkey.c, revision 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>