[BACK]Return to fep_edit.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / fep

Annotation of OpenXM_contrib2/fep/fep_edit.c, Revision 1.4

1.1       noro        1: /*     Copyright (c) 1987, 1988 by Software Research Associates, Inc.  */
                      2:
                      3: #ifndef lint
                      4: static char rcsid[]=
                      5: "$Id: fep_edit.c,v 4.10 1995/01/20 08:15:55 utashiro Exp $ (SRA)";
                      6: #endif /* lint */
                      7:
                      8: #include <stdio.h>
1.4     ! ohara       9: #include <stdlib.h>
        !            10: #include <string.h>
1.1       noro       11: #include <sys/types.h>
                     12: #include <sys/stat.h>
                     13: #include <sys/ioctl.h>
                     14: #ifdef TERMIOS
                     15: #include <termios.h>
                     16: #if defined(__linux__) || defined(__CYGWIN__)
                     17: #ifndef _POSIX_VDISABLE
                     18: #define _POSIX_VDISABLE '\0'
                     19: #endif
                     20: #endif
                     21: #else
                     22: #include <sgtty.h>
                     23: #endif
                     24: #include <sys/time.h>
                     25: #include <ctype.h>
                     26: #if defined(__CYGWIN__)
                     27: #include <sys/dirent.h>
                     28: #define direct dirent
1.4     ! ohara      29: #elif defined(sun) || defined(__FreeBSD__)
1.2       noro       30: #include <dirent.h>
                     31: #define direct dirent
                     32: #include <unistd.h>
1.1       noro       33: #else
                     34: #include <sys/dir.h>
                     35: #endif
                     36: #include <sys/file.h>
                     37: #include <setjmp.h>
                     38: #include "fep_defs.h"
                     39: #include "fep_glob.h"
                     40: #include "fep_funcs.h"
                     41:
                     42: CHAR           *CommandLine;           /* pointer to command line buffer */
                     43: CHAR           *KillBuffer;            /* pointer to kill buffer */
                     44: int            CurrentPosition;        /* current cursor position */
                     45: int            MarkPosition = -1;      /* Marked position */
                     46: EDITMODE       editmode = NOTYET;      /* edtimode EMACS, VI */
                     47: EDITSTATUS     editstatus = NOTEDITING;/* EDITING, NOTEDITING */
                     48:
                     49: int    maxline = MAXCMDLEN;            /* maximum length of command line */
                     50: int    NeedNewLine;                    /* add new line flag */
                     51: int    NeedSave;                       /* need to save to history */
                     52: int    Transparency = OFF;             /* transparent flag */
                     53: int    Through = OFF;                  /* through flag */
                     54: int    eof_occured = 0;                /* eof has been occured */
                     55: jmp_buf        jbuf;                           /* jump buffer */
                     56:
                     57: FUNC   *curFuncTab;                    /* current function table */
                     58: FUNC   *altFuncTab;                    /* alternative function table */
                     59:
                     60: /*
                     61:  * Default binding table
                     62:  */
                     63: BINDENT emacsBindings[] = {
                     64:        /* NULL         */      {"\0",          mark},
                     65:        /* ^A           */      {"\\^A",        beginning_of_line},
                     66:        /* ^B           */      {"\\^B",        backward_character},
                     67:        /* ^D           */      {"\\^D",        delete_next_character},
                     68:        /* ^E           */      {"\\^E",        end_of_line},
                     69:        /* ^F           */      {"\\^F",        forward_character},
                     70:        /* ^I           */      {"\\^I",        insert_tab},
                     71:        /* ^J           */      {"\\^J",        new_line},
                     72:        /* ^K           */      {"\\^K",        kill_to_end_of_line},
                     73:        /* ^L           */      {"\\^L",        clear_screen},
                     74:        /* ^M           */      {"\\^M",        new_line},
                     75:        /* ^N           */      {"\\^N",        next_history},
                     76:        /* ^P           */      {"\\^P",        previous_history},
                     77:        /* ^T           */      {"\\^T",        previous_history},
                     78:        /* ^Y           */      {"\\^Y",        yank_from_kill_buffer},
                     79:        /* ^^           */      {"\\^^",        toggle_through},
                     80:        /* esc-b        */      {"\\^[b",       backward_word},
                     81:        /* esc-B        */      {"\\^[B",       backward_Word},
                     82:        /* esc-d        */      {"\\^[d",       delete_next_word},
                     83:        /* esc-D        */      {"\\^[D",       delete_next_Word},
                     84:        /* esc-f        */      {"\\^[f",       forward_word},
                     85:        /* esc-F        */      {"\\^[F",       forward_Word},
                     86:        /* esc-h        */      {"\\^[h",       delete_previous_word},
                     87:        /* esc-H        */      {"\\^[H",       delete_previous_Word},
                     88:        /* esc-l        */      {"\\^[l",       list_file_name},
                     89:        /* esc-L        */      {"\\^[L",       list_file_name},
                     90:        /* esc-n        */      {"\\^[n",       insert_next_history},
                     91:        /* esc-N        */      {"\\^[N",       insert_next_history},
                     92:        /* esc-p        */      {"\\^[p",       insert_previous_history},
                     93:        /* esc-P        */      {"\\^[P",       insert_previous_history},
                     94:        /* esc-.        */      {"\\^[.",       insert_current_history},
                     95:        /* esc-esc      */      {"\\^[\\^[",    expand_file_name},
                     96:        /* esc-"-"      */      {"\\^[-",       toggle_through},
                     97:        /* esc-_        */      {"\\^[_",       invoke_shell},
                     98:        /* esc-<        */      {"\\^[<",       search_reverse},
                     99:        /* esc->        */      {"\\^[>",       search_forward},
                    100:        /* esc-?        */      {"\\^[?",       show_help},
                    101:        /* ^X-^B        */      {"\\^X\\^B",    show_bindings},
                    102:        /* ^X-B         */      {"\\^XB",       show_bindings},
                    103:        /* ^X-b         */      {"\\^Xb",       show_bindings},
                    104:        /* ^X-^H        */      {"\\^X\\^H",    show_history},
                    105:        /* ^X-H         */      {"\\^XH",       show_history},
                    106:        /* ^X-h         */      {"\\^Xh",       show_history},
                    107:        /* ^X-^V        */      {"\\^X\\^V",    view_buffer},
                    108:        /* ^X-^K        */      {"\\^X\\^K",    kill_to_top_of_line},
                    109:        /* ^X-^L        */      {"\\^X\\^L",    fep_repaint},
                    110:        /* ^X-^C        */      {"\\^X\\^C",    (FUNC)terminate},
                    111:        /* ^X-^D        */      {"\\^X\\^D",    send_eof},
                    112:        /* ^X-(         */      {"\\^X(",       fep_start_script},
                    113:        /* ^X-)         */      {"\\^X)",       fep_end_script},
                    114:        /*              */      {NULL,          NULL}
                    115: };
                    116:
                    117: /*
                    118:  * Initialize function table buffer
                    119:  */
                    120: init_bind_table ()
                    121: {
                    122:
                    123:     curFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
                    124:     altFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
                    125:     if (curFuncTab == 0 || altFuncTab == 0) {
                    126:        printf ("Can't allocate space for function table\n");
                    127:        exit (1);
                    128:     }
                    129: }
                    130:
                    131: /*
                    132:  * Initialize function table
                    133:  */
                    134: char strspace [256], *strspace_addr = strspace;
                    135:
                    136: init_edit_params ()
                    137: {
                    138:     struct indirect *idp;
                    139:     char *cp, *getenv();
                    140:     char sbuf[2048], *term, *tgetstr();
                    141:
                    142:     if (term = look_var ("term")) {
                    143:        if (tgetent (sbuf, term) == 1) {
                    144:            if (lines == 0)
                    145:                lines = tgetnum ("li");
                    146:            if (columns == 0)
                    147:                columns = tgetnum ("co");
                    148:            term_clear = tgetstr ("cl", &strspace_addr);
                    149:        }
                    150:     }
                    151:
                    152:     if (lines == 0)
                    153:        lines = 24;
                    154:     if (columns == 0)
                    155:        columns = 80;
                    156:
                    157:     sprintf (sbuf, "%d", lines);
                    158:     set_var ("crt", sbuf);
                    159:
                    160:     if (editmode == NOTYET) {
                    161:        if (look_var ("editmode"))
                    162:            set_var ("editmode", look_var ("editmode"));
                    163:        else
                    164:            set_var ("editmode", "emacs");
                    165:     }
                    166:
                    167:     set_var ("showhist", itoa (lines - 1));
                    168:
                    169:     /*
                    170:      * Read startup file
                    171:      */
                    172:     sourceRcFile ();
                    173:
                    174:     /*
                    175:      * Read history if 'history-file' is set
                    176:      */
                    177:     {
                    178:        char *cp, *mk_home_relative ();
                    179:
                    180:        if (look_var ("savehist") && (cp = look_var ("history-file"))) {
                    181:            cp = mk_home_relative (cp);
                    182:
                    183:            if (access (cp, R_OK) == 0)
                    184:                read_history (cp);
                    185:        }
                    186:     }
                    187:
                    188:     /*
                    189:      * Initialize command line buffer
                    190:      */
                    191:     CommandLine = (CHAR *) calloc (maxline, 1);
                    192:     KillBuffer = (CHAR *) calloc (maxline, 1);
                    193:     if (CommandLine == 0 || KillBuffer == 0) {
                    194:        perror ("Edit line buffer");
                    195:        exit (1);
                    196:     }
                    197:     (void) strcpy (CommandLine, "");
                    198:     (void) strcpy (KillBuffer, "");
                    199:     CurrentPosition = 0;
                    200: }
                    201:
                    202: /*
                    203:  * Initialize emacs bindings
                    204:  */
                    205: initEmacsBindings (cft, aft)
                    206:     FUNC cft[], aft[];
                    207: {
                    208:     register int i;
                    209:     BINDENT *ftp;
                    210:
                    211:     for (i = 0; i < 256; i++)
                    212:        cft[i] = self_insert;
                    213:
                    214: #define import(table,key,fn) if((int)key>0)table[(int)key]=fn
                    215:
                    216: #ifdef TERMIOS
                    217:     /* Now, using cbreak mode
                    218:     import (cft, initial_ttymode.c_cc[VSTART], ignore);
                    219:     import (cft, initial_ttymode.c_cc[VSTOP], ignore);
                    220:     */
                    221: #if 0
                    222:     import (cft, initial_ttymode.c_cc[VINTR], insert_and_flush);
                    223: #else
                    224:        /* added by noro */
                    225:     import (cft, initial_ttymode.c_cc[VINTR], send_int_sig);
                    226:        /* XXX : this may not be necessary */
                    227:     import (aft, initial_ttymode.c_cc[VINTR], send_int_sig);
                    228: #endif
                    229:     import (cft, initial_ttymode.c_cc[VQUIT], insert_and_flush);
                    230:     /* Now, EOF will be sent on empty line.
                    231:     import (cft, initial_ttymode.c_cc[VEOF], send_eof);
                    232:     */
                    233: #ifdef VSWTC
                    234:     import (cft, initial_ttymode.c_cc[VSWTC], insert_and_flush);
                    235: #endif
                    236:     import (cft, initial_ttymode.c_cc[VSUSP], insert_and_flush);
                    237:     /* ^Y is used for yank-from-kill-buffer
                    238:     import (cft, initial_ttymode.c_cc[VDSUSP], self_insert);
                    239:     */
                    240:     import (cft, initial_ttymode.c_cc[VREPRINT], reprint);
1.3       ohara     241: #ifdef VDISCARD
1.1       noro      242:     import (cft, initial_ttymode.c_cc[VDISCARD], self_insert);
1.3       ohara     243: #endif
1.1       noro      244:     import (cft, initial_ttymode.c_cc[VWERASE], delete_previous_word);
                    245:     import (cft, initial_ttymode.c_cc[VLNEXT], literal_next);
                    246:     import (cft, initial_ttymode.c_cc[VERASE], delete_previous_character);
                    247:     import (cft, initial_ttymode.c_cc[VKILL], delete_line);
                    248: #else
                    249:     /* Now, using cbreak mode
                    250:     import (cft, tchars_buf.t_startc, ignore);
                    251:     import (cft, tchars_buf.t_stopc, ignore);
                    252:     */
                    253: #if 0
                    254:     import (cft, tchars_buf.t_intrc, insert_and_flush);
                    255: #else
                    256:     import (cft, tchars_buf.t_intrc, send_int_sig);
                    257:     import (aft, tchars_buf.t_intrc, send_int_sig);
                    258: #endif
                    259:     import (cft, tchars_buf.t_quitc, insert_and_flush);
                    260:     /* Now, EOF will be sent on empty line.
                    261:     import (cft, tchars_buf.t_eofc, send_eof);
                    262:     */
                    263:     import (cft, tchars_buf.t_brkc, insert_and_flush);
                    264:     import (cft, ltchars_buf.t_suspc, insert_and_flush);
                    265:     /* ^Y is used for yank-from-kill-buffer
                    266:     import (cft, ltchars_buf.t_dsuspc, self_insert);
                    267:     */
                    268:     import (cft, ltchars_buf.t_rprntc, reprint);
                    269:     import (cft, ltchars_buf.t_flushc, self_insert);
                    270:     import (cft, ltchars_buf.t_werasc, delete_previous_word);
                    271:     import (cft, ltchars_buf.t_lnextc, literal_next);
                    272:     import (cft, initial_ttymode.sg_erase, delete_previous_character);
                    273:     import (cft, initial_ttymode.sg_kill, delete_line);
                    274: #endif
                    275:
                    276: #undef import
                    277:
                    278:     /*
                    279:      * Set default bindings
                    280:      */
                    281:     for (ftp = emacsBindings; ftp->bt_s; ftp++) {
                    282:        bind_key (cft, ftp->bt_func, ftp->bt_s, fep_abort);
                    283:     }
                    284: }
                    285:
                    286: /*
                    287:  * Main function of front end program
                    288:  */
                    289: CHAR *
                    290: getline()
                    291: {
                    292:     int c;
                    293:     CHAR *execute_command, *check_alias();
                    294:     char *remained;
                    295:     int processed;
                    296:
                    297:     (void) strcpy (CommandLine, "");
                    298:     CurrentPosition = 0;
                    299:     resetCurrentHistory ();
                    300:
                    301: RETRY:
                    302:     (void) fflush (stdout);
                    303:     NeedNewLine = 0;
                    304:     NeedSave = 0;
                    305:     editstatus = EDITING;
                    306:     processed = 0;
                    307:     (void) setjmp (jbuf);
                    308:
                    309:     /*
                    310:      * If there is file pointer for I/O redirection,
                    311:      * read input from the pointer and return
                    312:      */
                    313:     if (redirect_fp) {
                    314:
                    315:        /*
                    316:         * Check output from sub-process
                    317:         */
                    318:        swallow_output();
                    319:
                    320:        if (fgets (CommandLine, MAXCMDLEN, redirect_fp)) {
                    321:            ++redirect_line;
                    322:            execute_command = CommandLine;
                    323:            goto RETURN;
                    324:        }
                    325:        else {
                    326:            if (look_var ("verbose"))
                    327:                printf ("%d lines redirected\n", redirect_line);
                    328:            errorBell ();
                    329:            if (redirect_pid) {
                    330:                pclose (redirect_fp);
                    331:                redirect_pid = 0;
                    332:            }
                    333:            else
                    334:                fclose (redirect_fp);
                    335:            redirect_fp = NULL;
                    336:        }
                    337:     }
                    338:
                    339:     while ((c = getcharacter ()) >= (CHAR) 0) {
                    340:        int status;
                    341:
                    342:        /*
                    343:         * In transparet mode
                    344:         */
                    345:        if (Through == ON || Transparency == ON) {
                    346:            if (*curFuncTab[(int) c] == toggle_through ||
                    347:                *curFuncTab[(int) c] == fix_transparency) {
                    348:                (*curFuncTab[(int) c])();
                    349:                goto RETRY;
                    350:            }
                    351:            else {
                    352:                CommandLine[CurrentPosition] = c;
                    353:                CommandLine[CurrentPosition + 1] = '\0';
                    354:                return (CommandLine);
                    355:            }
                    356:        }
                    357:
                    358:        /*
                    359:         * If find EOF character on top of empty line
                    360:         * and the variable "send-eof-on-empty-line" is set
                    361:         * call send_eof
                    362:         */
                    363:        if (
                    364: #ifdef TERMIOS
                    365:            c == initial_ttymode.c_cc[VEOF]
                    366: #else
                    367:            c == tchars_buf.t_eofc
                    368: #endif
                    369:            && curFuncTab[c] != send_eof
                    370:            && ! look_var ("ignore-eof")
                    371:            && CommandLine [0] == '\0'
                    372:        ) {
                    373:            if (!eof_occured && look_var ("alarm-on-eof")) {
                    374:                eof_occured = 1;
                    375:                status = alarm_on_eof (c);
                    376:            }
                    377:            else
                    378:                status = send_eof (c);
                    379:        }
                    380:        else {
                    381:            eof_occured = 0;
                    382:            status = callfunc (curFuncTab, c);
                    383:        }
                    384:
                    385:        (void) fflush (stdout);
                    386:        if (status == 1)        /* end of line editing */
                    387:            break;
                    388:        else                    /* continue line editing */
                    389:            continue;
                    390:     }
                    391:     editstatus = NOTEDITING;
                    392:
                    393:  REPROCESS:
                    394:
                    395:     /*
                    396:      * Check command line refer history or not
                    397:      */
                    398:     if (refer_history () == PROCESSED)
                    399:        goto RETRY;
                    400:
                    401:     /*
                    402:      * Check alias list
                    403:      */
                    404:     if (!processed && !look_var ("noalias")
                    405:        && (execute_command = check_alias (CommandLine))
                    406:     ) {
                    407:        if (look_var ("verbose"))
                    408:            printf ("%s\n", execute_command);
                    409:     }
                    410:     else
                    411:        execute_command = CommandLine;
                    412:
                    413:
                    414:     /*
                    415:      * Check builtin function, and execute it.
                    416:      */
                    417:     if (executeBuiltInFunction (execute_command, &remained) == PROCESSED) {
                    418:        if (!processed)
                    419:            addHistory (CommandLine);
                    420:        CommandLine[0] = '\0';
                    421:        CurrentPosition = 0;
                    422:        if (remained && *remained) {
                    423:            strcpy (CommandLine, remained);
                    424:            processed = 1;
                    425:            goto REPROCESS;
                    426:        }
                    427:        if (!redirect_fp)
                    428:            fputs (prompt, stdout);
                    429:        goto RETRY;
                    430:     }
                    431:
                    432:     if (NeedSave) {
                    433:        if (!is_empty_line (CommandLine) || !look_var ("ignore-empty-line"))
                    434:            if (!processed)
                    435:                addHistory (CommandLine);
                    436:        /*
                    437:         * put string to buffer
                    438:         */
                    439:        buf_put (output_buffer, CommandLine);
                    440:        if (NeedNewLine == 1)
                    441:            buf_put (output_buffer, "\n");
                    442:     }
                    443:
                    444:     if (NeedNewLine == 1)
                    445:        (void) strcat (execute_command, "\n");
                    446:
                    447: RETURN:
                    448:     return (execute_command);
                    449: }
                    450:
                    451: /*
                    452:  * Invoke appropliate function according to fucntion table
                    453:  * Return value 1 means exit from line editing
                    454:  */
                    455: callfunc (ft, c)
                    456:     FUNC ft[];
                    457:     int c;
                    458: {
                    459:
                    460:     if (isIndirect(ft[(int) c])) {
                    461:        FUNC *nft = maskIndirect (ft[(int)c]);
                    462:        char nc;
                    463:
                    464:        nc = (CHAR) getcharacter();
                    465:        return (callfunc (nft, nc));
                    466:     }
                    467:     else
                    468:        return ((*ft[(int) c]) (c));
                    469: }
                    470:
                    471: /*
                    472:  * Beep and do nothing
                    473:  */
                    474: fep_abort()
                    475: {
                    476:     (void) errorBell ();
                    477:     return (0);
                    478: }
                    479:
                    480: /*
                    481:  * Insert the character self
                    482:  */
                    483: self_insert(c)
                    484:     CHAR c;
                    485: {
                    486:     register int i, nbyte = 1, currentNull;
                    487: #ifdef KANJI
                    488:     CHAR byte2;
                    489: #endif /* KANJI */
                    490:
                    491:     currentNull = strlen (CommandLine);
                    492:
                    493:     if (currentNull >= maxline) {
                    494:         errorBell();
                    495:        return (0);
                    496:     }
                    497:
                    498:     if (isctlchar(CommandLine[CurrentPosition]))
                    499:        (void) putchar (BS);
                    500: #ifdef KANJI
                    501:     if (iskanji (c)) {
                    502:        byte2 = (CHAR) getcharacter ();
                    503:        putchar (c);
                    504:        putchar (byte2);
                    505:        nbyte = 2;
                    506:     }
                    507:     else
                    508: #endif /* KANJI */
                    509:        putChar (c);
                    510:     reverse_strcpy (
                    511:        &CommandLine[CurrentPosition] + nbyte,
                    512:        &CommandLine[CurrentPosition]
                    513:     );
                    514:     CurrentPosition += nbyte;
                    515:     CommandLine[CurrentPosition - nbyte] = c;
                    516: #ifdef KANJI
                    517:     if (nbyte > 1) {
                    518:        CommandLine[CurrentPosition - 1] = byte2;
                    519:     }
                    520: #endif /* KANJI */
                    521:     printS (&CommandLine [CurrentPosition]);
                    522:
                    523:     if (CommandLine[CurrentPosition] != '\0') {
                    524:        repeat (BS, howlong (&CommandLine[CurrentPosition + 1], 0));
                    525:        (void) putchar (BS);
                    526:     }
                    527:     return (0);
                    528: }
                    529:
                    530: /*
                    531:  * Insert string in current position
                    532:  */
                    533: insert_string (s)
                    534:     CHAR *s;
                    535: {
                    536:     register int i, nbyte = strlen (s), currentNull;
                    537:
                    538:     currentNull = strlen (CommandLine);
                    539:
                    540:     if (currentNull + nbyte >= maxline - 1) {
                    541:         errorBell();
                    542:        return (0);
                    543:     }
                    544:
                    545:     if (isctlchar(CommandLine[CurrentPosition]))
                    546:        (void) putchar (BS);
                    547:     printS (s);
                    548:     reverse_strcpy (
                    549:        &CommandLine[CurrentPosition] + nbyte,  /* to */
                    550:        &CommandLine[CurrentPosition]           /* from */
                    551:     );
                    552:     bcopy (s, &CommandLine[CurrentPosition], nbyte);
                    553:     CurrentPosition += nbyte;
                    554:
                    555:     if (CommandLine[CurrentPosition] != '\0') {
                    556:        printS (&CommandLine[CurrentPosition]);
                    557:        repeat (BS, howlong (&CommandLine[CurrentPosition], 0));
                    558:     }
                    559:     return (0);
                    560: }
                    561:
                    562: /*
                    563:  * Yank string from kill buffer.
                    564:  */
                    565: yank_from_kill_buffer ()
                    566: {
                    567:     insert_string (KillBuffer);
                    568: }
                    569:
                    570: /*
                    571:  * Set mark to current position
                    572:  */
                    573: mark ()
                    574: {
                    575:     set_mark (CurrentPosition);
                    576:     return (0);
                    577: }
                    578:
                    579: /*
                    580:  * Set mark to specified position
                    581:  */
                    582: set_mark (pos)
                    583:     int pos;
                    584: {
                    585:     MarkPosition = pos;
                    586:     return (0);
                    587: }
                    588:
                    589: /*
                    590:  * Delete area from mark to current position to kill buffer
                    591:  */
                    592: delete_to_kill_buffer ()
                    593: {
                    594:     int n = abs (CurrentPosition - MarkPosition);
                    595:
                    596:     if (MarkPosition < 0) {
                    597:        errorBell();
                    598:        return (0);
                    599:     }
                    600:
                    601:     if (CurrentPosition == MarkPosition)
                    602:        return;
                    603:
                    604:     if (CurrentPosition > MarkPosition) {
                    605:        (void) moveto (MarkPosition);
                    606:     }
                    607:
                    608:     return (delete_next_n_character (n));
                    609: }
                    610:
                    611: /*
                    612:  * Move to specified position.
                    613:  */
                    614: moveto (position)
                    615: {
                    616:     if (position < CurrentPosition)
                    617:        while (position < CurrentPosition)
                    618:            (void) backward_n_character (1);
                    619:     else
                    620:        while (position > CurrentPosition
                    621: #ifdef KANJI
                    622:            && !(CurrentPosition + 1 == position
                    623:                    && iskanji (CommandLine[CurrentPosition]))
                    624: #endif /* KANJI */
                    625:        )
                    626:            (void) forward_n_character (1);
                    627: }
                    628:
                    629: /*
                    630:  * Move cursor to top of line
                    631:  */
                    632: beginning_of_line()
                    633: {
                    634:     register int i;
                    635:
                    636:     for (i = CurrentPosition; i > 0; i--) {
                    637:        if (isctlchar (CommandLine[i]))
                    638:            (void) putchar (BS);
                    639:        (void) putchar (BS);
                    640:     }
                    641:     CurrentPosition = 0;
                    642:     return (0);
                    643: }
                    644:
                    645: #ifdef KANJI
                    646: #define INC(i) if(iskanji(CommandLine[i])) i+=2; else i++;
                    647: #define DEC(i) if(i>=2 && iskanji_in_string(CommandLine, i-2)) i-=2; else i--;
                    648: #else /* KANJI */
                    649: #define INC(i) i++
                    650: #define DEC(i) i--
                    651: #endif /* KANJI */
                    652:
                    653: /*
                    654:  * Move cursor to end of line
                    655:  */
                    656: end_of_line()
                    657: {
                    658:     register int    i;
                    659:
                    660:     for (i = CurrentPosition; CommandLine[i]; i++) {
                    661:        if (isctlchar (CommandLine[i]))
                    662:            (void) putchar (unctl(CommandLine[i]));
                    663:        else
                    664:            (void) putchar (CommandLine[i]);
                    665:        if (isctlchar(CommandLine[i+1]))
                    666:            (void) putchar ('^');
                    667:     }
                    668:     CurrentPosition = i;
                    669:     return (0);
                    670: }
                    671:
                    672: /*
                    673:  * Move cursor left one space
                    674:  */
                    675: backward_character()
                    676: {
                    677:
                    678:     return (backward_n_character (1));
                    679: }
                    680:
                    681: /*
                    682:  * Move cursor left "n" space
                    683:  */
                    684: backward_n_character(n)
                    685:     int n;
                    686: {
                    687:     int space;
                    688:     int i = CurrentPosition;
                    689:
                    690:     if (n == 0)
                    691:        return (0);
                    692:     else if (n < 0)
                    693:        return (forward_n_character (-n));
                    694:     else if (n > CurrentPosition) {
                    695:        errorBell ();
                    696:        return (0);
                    697:     }
                    698:
                    699:     while (n-- && i >= 0) {
                    700:        if (isctlchar (CommandLine[i]))
                    701:            putchar (BS);
                    702: #ifdef KANJI
                    703:        if (i > 0 && iskanji_in_string (CommandLine, i-2)) {
                    704:            (void) putchar (BS);
                    705:            (void) putchar (BS);
                    706:            i--;
                    707:        }
                    708:        else
                    709: #endif /* KANJI */
                    710:        putchar (BS);
                    711:        i--;
                    712:     }
                    713:     CurrentPosition = i;
                    714:     return (0);
                    715: }
                    716:
                    717: /*
                    718:  * Move cursor backward one word
                    719:  */
                    720: backward_word ()
                    721: {
                    722:
                    723:     return (backward_n_word (1));
                    724: }
                    725:
                    726: /*
                    727:  * Move cursor backward n word
                    728:  */
                    729: backward_n_word (n)
                    730:     int n;
                    731: {
                    732:     register int i = CurrentPosition, nchars = 0;
                    733:
                    734:     if (i == 0) {
                    735:        errorBell ();
                    736:        return (0);
                    737:     }
                    738:
                    739: #ifdef KANJI
                    740:     while (n--) {
                    741:        DEC(i);
                    742:        nchars++;
                    743:
                    744:        while (1) {
                    745:            if (i >= 2 && iskanji_in_string (CommandLine, i-2))
                    746:                break;
                    747:            else if (i > 0 && !iswordchar (CommandLine[i]))
                    748:                i -= 1;
                    749:            else
                    750:                break;
                    751:
                    752:            nchars++;
                    753:        }
                    754:        while (1) {
                    755:            if (i >= 2 && iskanji_in_string (CommandLine, i - 2))
                    756:                i -= 2;
                    757:            else if (i > 0 && iswordchar (CommandLine [i -1]))
                    758:                i -= 1;
                    759:            else
                    760:                break;
                    761:            nchars++;
                    762:        }
                    763:     }
                    764: #else /* KANJI */
                    765:     while (n--) {
                    766:        i--, nchars++;
                    767:        while (i > 0 && !iswordchar (CommandLine [i])) {
                    768:            i--, nchars++;
                    769:        }
                    770:        while (i > 0 && iswordchar (CommandLine [i - 1])) {
                    771:            i--, nchars++;
                    772:        }
                    773:     }
                    774: #endif /* KANJI */
                    775:     return (backward_n_character (nchars));
                    776: }
                    777:
                    778: /*
                    779:  * Move cursor backward one Word
                    780:  */
                    781: backward_Word ()
                    782: {
                    783:
                    784:     return (backward_n_Word (1));
                    785: }
                    786:
                    787: /*
                    788:  * Move cursor backward n Word
                    789:  */
                    790: backward_n_Word (n)
                    791:     int n;
                    792: {
                    793:     register int i = CurrentPosition, nchars = 0;
                    794:
                    795:     if (i == 0) {
                    796:        errorBell ();
                    797:        return (0);
                    798:     }
                    799:
                    800: #ifdef KANJI
                    801:     while (n--) {
                    802:        DEC(i);
                    803:        nchars++;
                    804:
                    805:        while (1) {
                    806:            if (i > 1 && iskanji_in_string (CommandLine, i - 2))
                    807:                break;
                    808:            else if (i > 0 && !iswordchar (CommandLine[i]))
                    809:                i -= 1;
                    810:            else
                    811:                break;
                    812:
                    813:            nchars++;
                    814:        }
                    815:        while (1) {
                    816:            if (i > 2 && iskanji_in_string (CommandLine, i - 2))
                    817:                i -= 2;
                    818:            else if (i > 0 && iswordchar (CommandLine [i - 1]))
                    819:                i -= 1;
                    820:            else
                    821:                break;
                    822:            nchars++;
                    823:        }
                    824:     }
                    825: #else /* KANJI */
                    826:     while (n--) {
                    827:        i--, nchars++;
                    828:        while (i > 0 && !isWordchar (CommandLine [i]))
                    829:            i--, nchars++;
                    830:        while (i > 0 && isWordchar (CommandLine [i - 1]))
                    831:            i--, nchars++;
                    832:     }
                    833: #endif /* KANJI */
                    834:     return (backward_n_character (nchars));
                    835: }
                    836:
                    837: /*
                    838:  * Move cursor forward one character
                    839:  */
                    840: forward_character()
                    841: {
                    842:
                    843:     return (forward_n_character (1));
                    844: }
                    845:
                    846: /*
                    847:  * Move cursor forward n character
                    848:  */
                    849: forward_n_character(n)
                    850:     int n;
                    851: {
                    852:     int space;
                    853:     register int i = CurrentPosition;
                    854:
                    855:     if (n == 0)
                    856:        return (0);
                    857:     else if (n < 0)
                    858:        return (backward_n_character (-n));
                    859:
                    860:     if (CommandLine [CurrentPosition] == '\0') {
                    861:        errorBell ();
                    862:        return (0);
                    863:     }
                    864:
                    865: #ifdef KANJI
                    866:     if (iskanji (CommandLine[i])) {
                    867:        (void) putchar (CommandLine[i++]);
                    868:        (void) putchar (CommandLine[i++]);
                    869:     }
                    870:     else
                    871: #endif /* KANJI */
                    872:     if (isctlchar(CommandLine[i])) {
                    873:        (void) putchar (unctl (CommandLine [i]));
                    874:        i++;
                    875:     }
                    876:     else
                    877:        (void) putchar (CommandLine[i++]);
                    878:
                    879:     while (--n && CommandLine [i]) {
                    880: #ifdef KANJI
                    881:        if (iskanji (CommandLine[i])) {
                    882:            (void) putchar (CommandLine[i++]);
                    883:            (void) putchar (CommandLine[i++]);
                    884:        }
                    885:        else
                    886: #endif /* KANJI */
                    887:        putChar (CommandLine [i++]);
                    888:     }
                    889:
                    890:     if (isctlchar (CommandLine [i]))
                    891:        putchar ('^');
                    892:
                    893:     CurrentPosition = i;
                    894:
                    895:     return (0);
                    896: }
                    897:
                    898: /*
                    899:  * Move cursor forward one word
                    900:  */
                    901: forward_word ()
                    902: {
                    903:     return (forward_n_word (1));
                    904: }
                    905:
                    906: /*
                    907:  * Move cursor forward n word
                    908:  */
                    909: forward_n_word (n)
                    910:     int n;
                    911: {
                    912:     register int i = CurrentPosition, nchars = 0;
                    913:
                    914:     if (CommandLine [i] == '\0') {
                    915:        errorBell ();
                    916:        return (0);
                    917:     }
                    918:
                    919:     while (n--) {
                    920:        while (CommandLine [i] && iswordchar (CommandLine [i])) {
                    921:            INC(i);
                    922:            nchars++;
                    923:        }
                    924:        while (CommandLine [i] && !iswordchar (CommandLine [i])) {
                    925:            INC(i);
                    926:            nchars++;
                    927:        }
                    928:     }
                    929:     return (forward_n_character (nchars));
                    930: }
                    931:
                    932: /*
                    933:  * Move cursor forward one word
                    934:  */
                    935: forward_Word ()
                    936: {
                    937:     return (forward_n_Word (1));
                    938: }
                    939:
                    940: /*
                    941:  * Move cursor forward n word
                    942:  */
                    943: forward_n_Word (n)
                    944:     int n;
                    945: {
                    946:     register int i = CurrentPosition, nchars = 0;
                    947:
                    948:     if (CommandLine [i] == '\0') {
                    949:        errorBell ();
                    950:        return (0);
                    951:     }
                    952:
                    953:     while (n--) {
                    954:        while (CommandLine [i] && isWordchar (CommandLine [i])) {
                    955:            INC(i);
                    956:             nchars++;
                    957:        }
                    958:        while (CommandLine [i] && !isWordchar (CommandLine [i])) {
                    959:            INC(i);
                    960:             nchars++;
                    961:        }
                    962:     }
                    963:     return (forward_n_character (nchars));
                    964: }
                    965:
                    966: /*
                    967:  * Forward to end of word
                    968:  */
                    969: forward_to_end_of_word ()
                    970: {
                    971:
                    972:     return (forward_to_end_of_n_word (1));
                    973: }
                    974:
                    975: /*
                    976:  * Forward to end of n word
                    977:  */
                    978: forward_to_end_of_n_word (n)
                    979: {
                    980:     register int i = CurrentPosition, nchars = 0;
                    981:
                    982:     if (CommandLine [i] == '\0') {
                    983:        errorBell ();
                    984:        return (0);
                    985:     }
                    986:
                    987:     INC(i);
                    988:     while (n--) {
                    989:        while (CommandLine [i] && !iswordchar (CommandLine [i])) {
                    990:            INC(i);
                    991:            nchars++;
                    992:        }
                    993:        while (CommandLine [i] && iswordchar (CommandLine [i])) {
                    994:            INC(i);
                    995:            nchars++;
                    996:        }
                    997:     }
                    998:     DEC(i);
                    999:     return (forward_n_character (nchars));
                   1000: }
                   1001:
                   1002: /*
                   1003:  * Forward to end of word
                   1004:  */
                   1005: forward_to_end_of_Word ()
                   1006: {
                   1007:
                   1008:     return (forward_to_end_of_n_Word (1));
                   1009: }
                   1010:
                   1011: /*
                   1012:  * Forward to end of n word
                   1013:  */
                   1014: forward_to_end_of_n_Word (n)
                   1015: {
                   1016:     register int i = CurrentPosition, nchars = 0;
                   1017:
                   1018:     if (CommandLine [i] == '\0') {
                   1019:        errorBell ();
                   1020:        return (0);
                   1021:     }
                   1022:
                   1023:     INC(i);
                   1024:     while (n--) {
                   1025:        while (CommandLine [i] && !isWordchar (CommandLine [i])) {
                   1026:            INC(i);
                   1027:            nchars++;
                   1028:        }
                   1029:        while (CommandLine [i] && isWordchar (CommandLine [i])) {
                   1030:            INC(i);
                   1031:            nchars++;
                   1032:        }
                   1033:     }
                   1034:     DEC(i);
                   1035:     return (forward_n_character (nchars));
                   1036: }
                   1037:
                   1038: /*
                   1039:  * Delete previous one character
                   1040:  */
                   1041: delete_previous_character()
                   1042: {
                   1043:
                   1044:     return (delete_previous_n_character (1));
                   1045: }
                   1046:
                   1047: /*
                   1048:  * Delete previous n characters
                   1049:  */
                   1050: delete_previous_n_character(n)
                   1051:     int n;
                   1052: {
                   1053:     register int i, nbyte;
                   1054:     int deleteArea, restArea;
                   1055:
                   1056:     if (CurrentPosition < n) {
                   1057:        errorBell ();
                   1058:        return (0);
                   1059:     }
                   1060:
                   1061: #ifdef KANJI
                   1062:     for (nbyte = 0, i = CurrentPosition; n-- > 0 && i;)
                   1063:        if (i > 1 && iskanji_in_string (CommandLine, i - 2))
                   1064:            i -= 2, nbyte += 2;
                   1065:        else
                   1066:            i -= 1, nbyte += 1;
                   1067: #else /* KANJI */
                   1068:     nbyte = n;
                   1069: #endif /* KANJI */
                   1070:
                   1071:     deleteArea = howlong (&CommandLine[CurrentPosition - nbyte], nbyte);
                   1072:     restArea = howlong (&CommandLine[CurrentPosition], 0);
                   1073:     if (isctlchar(CommandLine[CurrentPosition]))
                   1074:        (void) putchar (BS);
                   1075:     repeat(BS, deleteArea);
                   1076:     CurrentPosition -= nbyte;
                   1077:     strcpy (KillBuffer, &CommandLine [CurrentPosition]);
                   1078:     KillBuffer [nbyte] = '\0';
                   1079:     for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
                   1080:        CommandLine[i] = CommandLine[i + nbyte];
                   1081:        putChar (CommandLine[i]);
                   1082:     }
                   1083:     CommandLine[i] = '\0';
                   1084:     repeat(SP, deleteArea);
                   1085:     repeat(BS, deleteArea);
                   1086:     if (isctlchar (CommandLine[CurrentPosition]))
                   1087:        repeat(BS, restArea - 1);
                   1088:     else
                   1089:        repeat(BS, restArea);
                   1090:
                   1091:     return (0);
                   1092: }
                   1093:
                   1094: /*
                   1095:  * Delete previous one word
                   1096:  */
                   1097: delete_previous_word()
                   1098: {
                   1099:
                   1100:     return (delete_previous_n_word (1));
                   1101: }
                   1102:
                   1103: /*
                   1104:  * Delete previous n word
                   1105:  */
                   1106: delete_previous_n_word(n)
                   1107:     int n;
                   1108: {
                   1109:     register int i = CurrentPosition, nchars = 0;
                   1110:
                   1111:     if (i == 0) {
                   1112:        errorBell();
                   1113:        return (0);
                   1114:     }
                   1115:
                   1116: #ifdef KANJI
                   1117:     while (n--) {
                   1118:        if (i>1 && iskanji_in_string (CommandLine, i-2))
                   1119:            i--;
                   1120:        i--, nchars++;
                   1121:
                   1122:        while (1) {
                   1123:            if (i > 1 && iskanji_in_string (CommandLine, i-2))
                   1124:                break;
                   1125:            else if (i > 0 && !iswordchar (CommandLine[i]))
                   1126:                i -= 1;
                   1127:            else
                   1128:                break;
                   1129:
                   1130:            nchars++;
                   1131:        }
                   1132:        while (1) {
                   1133:            if (i > 2 && iskanji_in_string (CommandLine, i - 2))
                   1134:                i -= 2;
                   1135:            else if (i > 0 && iswordchar (CommandLine [i -1]))
                   1136:                i -= 1;
                   1137:            else
                   1138:                break;
                   1139:            nchars++;
                   1140:        }
                   1141:     }
                   1142: #else /* KANJI */
                   1143:     while (n--) {
                   1144:        i--, nchars++;
                   1145:        while (i > 0 && !iswordchar (CommandLine [i]))
                   1146:            i--, nchars++;
                   1147:        while (i > 0 && iswordchar (CommandLine [i - 1]))
                   1148:            i--, nchars++;
                   1149:     }
                   1150: #endif /* KANJI */
                   1151:
                   1152:     return (delete_previous_n_character (nchars));
                   1153: }
                   1154:
                   1155: /*
                   1156:  * Delete previous one word
                   1157:  */
                   1158: delete_previous_Word()
                   1159: {
                   1160:
                   1161:     return (delete_previous_n_Word (1));
                   1162: }
                   1163:
                   1164: /*
                   1165:  * Delete previous n word
                   1166:  */
                   1167: delete_previous_n_Word(n)
                   1168:     int n;
                   1169: {
                   1170:     register int i = CurrentPosition, nchars = 0;
                   1171:
                   1172:     if (i == 0) {
                   1173:        errorBell();
                   1174:        return (0);
                   1175:     }
                   1176:
                   1177: #ifdef KANJI
                   1178:     while (n--) {
                   1179:        if (i>1 && iskanji_in_string (CommandLine, i-2))
                   1180:            i--;
                   1181:        i--, nchars++;
                   1182:
                   1183:        while (1) {
                   1184:            if (i > 1 && iskanji_in_string (CommandLine, i-2))
                   1185:                break;
                   1186:            else if (i > 0 && !isWordchar (CommandLine[i]))
                   1187:                i -= 1;
                   1188:            else
                   1189:                break;
                   1190:
                   1191:            nchars++;
                   1192:        }
                   1193:        while (1) {
                   1194:            if (i > 2 && iskanji_in_string (CommandLine, i - 2))
                   1195:                i -= 2;
                   1196:            else if (i > 0 && isWordchar (CommandLine [i -1]))
                   1197:                i -= 1;
                   1198:            else
                   1199:                break;
                   1200:            nchars++;
                   1201:        }
                   1202:     }
                   1203: #else /* KANJI */
                   1204:     while (n--) {
                   1205:        i--, nchars++;
                   1206:        while (i > 0 && !isWordchar (CommandLine [i]))
                   1207:            i--, nchars++;
                   1208:        while (i > 0 && isWordchar (CommandLine [i - 1]))
                   1209:            i--, nchars++;
                   1210:     }
                   1211: #endif /* KANJI */
                   1212:
                   1213:     return (delete_previous_n_character (nchars));
                   1214: }
                   1215:
                   1216: /*
                   1217:  * Delete next one character
                   1218:  */
                   1219: delete_next_character ()
                   1220: {
                   1221:
                   1222:     return (delete_next_n_character (1));
                   1223: }
                   1224:
                   1225: /*
                   1226:  * Delete next n character
                   1227:  */
                   1228: delete_next_n_character (n)
                   1229:     int n;
                   1230: {
                   1231:     register int i, nbyte;
                   1232:     int deleteArea, restArea;
                   1233:
                   1234:     if (strlen (&CommandLine [CurrentPosition]) < n) {
                   1235:        errorBell ();
                   1236:        return (0);
                   1237:     }
                   1238:
                   1239: #ifdef KANJI
                   1240:     {
                   1241:        register CHAR *cp = &CommandLine[CurrentPosition];
                   1242:
                   1243:        nbyte = 0;
                   1244:        while (n-- > 0 && *cp)
                   1245:            if (iskanji (*cp))
                   1246:                cp += 2, nbyte += 2;
                   1247:            else
                   1248:                cp++, nbyte++;
                   1249:     }
                   1250: #else /* KANJI */
                   1251:     nbyte = n;
                   1252: #endif /* KANJI */
                   1253:
                   1254:     deleteArea = howlong (&CommandLine[CurrentPosition], nbyte);
                   1255:     restArea = howlong (&CommandLine[CurrentPosition + nbyte], 0);
                   1256:     if (isctlchar(CommandLine[CurrentPosition]))
                   1257:        (void) putchar (BS);
                   1258:     strcpy (KillBuffer, CommandLine + CurrentPosition);
                   1259:     KillBuffer [nbyte] = '\0';
                   1260:     for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
                   1261:        CommandLine[i] = CommandLine[i + nbyte];
                   1262:        putChar (CommandLine[i]);
                   1263:     }
                   1264:     CommandLine[i] = '\0';
                   1265:     repeat(SP, deleteArea);
                   1266:     repeat(BS, deleteArea);
                   1267:     if (isctlchar (CommandLine[CurrentPosition]))
                   1268:        repeat(BS, restArea - 1);
                   1269:     else
                   1270:        repeat(BS, restArea);
                   1271:
                   1272:     return (0);
                   1273: }
                   1274:
                   1275: /*
                   1276:  * Delete next one word
                   1277:  */
                   1278: delete_next_word ()
                   1279: {
                   1280:     return (delete_next_n_word (1));
                   1281: }
                   1282:
                   1283: /*
                   1284:  * Delete next n word
                   1285:  */
                   1286: delete_next_n_word (n)
                   1287:     int n;
                   1288: {
                   1289:     register int i = CurrentPosition, nchars = 0;
                   1290:
                   1291:     if (CommandLine [i] == '\0') {
                   1292:        errorBell ();
                   1293:        return (0);
                   1294:     }
                   1295:
                   1296:     while (n--) {
                   1297:        while (CommandLine [i] && iswordchar (CommandLine [i])) {
                   1298:            INC(i);
                   1299:            nchars++;
                   1300:        }
                   1301:        while (CommandLine [i] && !iswordchar (CommandLine [i])) {
                   1302:            INC(i);
                   1303:            nchars++;
                   1304:        }
                   1305:     }
                   1306:     return (delete_next_n_character (nchars));
                   1307: }
                   1308:
                   1309: /*
                   1310:  * Delete next one word
                   1311:  */
                   1312: delete_next_Word ()
                   1313: {
                   1314:     return (delete_next_n_Word (1));
                   1315: }
                   1316:
                   1317: /*
                   1318:  * Delete next n word
                   1319:  */
                   1320: delete_next_n_Word (n)
                   1321:     int n;
                   1322: {
                   1323:     register int i = CurrentPosition, nchars = 0;
                   1324:
                   1325:     if (CommandLine [i] == '\0') {
                   1326:        errorBell ();
                   1327:        return (0);
                   1328:     }
                   1329:
                   1330:     while (n--) {
                   1331:        while (CommandLine [i] && isWordchar (CommandLine [i])) {
                   1332:            INC(i);
                   1333:            nchars++;
                   1334:        }
                   1335:        while (CommandLine [i] && !isWordchar (CommandLine [i])) {
                   1336:            INC(i);
                   1337:            nchars++;
                   1338:        }
                   1339:     }
                   1340:     return (delete_next_n_character (nchars));
                   1341: }
                   1342:
                   1343: /*
                   1344:  * Erase whole line
                   1345:  */
                   1346: delete_line()
                   1347: {
                   1348:     register int i = CurrentPosition;
                   1349:     register int len;
                   1350:
                   1351:     len = howlong (CommandLine, 0);
                   1352:
                   1353:     /*
                   1354:      * If cursor is there right part of line, move it to end of line
                   1355:      * and erase character by character from end
                   1356:      */
                   1357:     if (howlong (CommandLine, CurrentPosition + 1) > len / 2) {
                   1358:        (void) end_of_line ();
                   1359:        repeat_string ("\b \b", len);
                   1360:     }
                   1361:     /*
                   1362:      * If cursor is there on left part of line, move it to top of line
                   1363:      * and erase line at once
                   1364:      */
                   1365:     else {
                   1366:        (void) beginning_of_line ();
                   1367:        if (isctlchar (CommandLine[0]))
                   1368:            putchar (BS);
                   1369:        repeat (SP, len);
                   1370:        repeat (BS, len);
                   1371:     }
                   1372:     strcpy (KillBuffer, CommandLine);
                   1373:     CurrentPosition = 0;
                   1374:     CommandLine [0] = '\0';
                   1375:     return (0);
                   1376: }
                   1377:
                   1378: /*
                   1379:  * Delete characters from current position to top of line
                   1380:  */
                   1381: kill_to_top_of_line()
                   1382: {
                   1383:     int i = CurrentPosition;
                   1384:
                   1385:     (void) beginning_of_line();
                   1386:     return (delete_next_n_character (i));
                   1387: }
                   1388:
                   1389: /*
                   1390:  * Delete characters from current position to end of line
                   1391:  */
                   1392: kill_to_end_of_line()
                   1393: {
                   1394:     register int    i, backCnt = 0;
                   1395:
                   1396:     if (isctlchar(CommandLine[CurrentPosition])) {
                   1397:         (void) putchar(BS);
                   1398:     }
                   1399:     for (i = CurrentPosition; CommandLine[i]; i++) {
                   1400:        if (isctlchar(CommandLine[i])) {
                   1401:            fputs("  ", stdout);
                   1402:            backCnt++;
                   1403:        }
                   1404:        else
                   1405:            (void) putchar (SP);
                   1406:        backCnt++;
                   1407:     }
                   1408:     for (; backCnt; backCnt--)
                   1409:        (void) putchar (BS);
                   1410:     strcpy (KillBuffer, CommandLine + CurrentPosition);
                   1411:     CommandLine[CurrentPosition] = '\0';
                   1412:     return (0);
                   1413: }
                   1414:
                   1415: /*
                   1416:  * Insert tab to current cursor position
                   1417:  */
                   1418: insert_tab()
                   1419: {
                   1420:
                   1421:     /* sorry, not implemented */
                   1422:     return (self_insert ('\t'));
                   1423: }
                   1424:
                   1425: /*
                   1426:  * Process new line
                   1427:  */
                   1428: new_line()
                   1429: {
                   1430:
                   1431:     (void) end_of_line;
                   1432:     fputs ("\r\n", stdout);
                   1433:     NeedNewLine = 1;
                   1434:     NeedSave = 1;
                   1435:
                   1436:     return (1);
                   1437: }
                   1438:
                   1439: /*
                   1440:  * Check current position is top-of-line
                   1441:  */
                   1442: is_tol()
                   1443: {
                   1444:     return (CurrentPosition == 0);
                   1445: }
                   1446:
                   1447: /*
                   1448:  * Check current position is end-of-line
                   1449:  */
                   1450: is_eol()
                   1451: {
                   1452:     return (CommandLine [CurrentPosition] == '\0');
                   1453: }
                   1454:
                   1455: /*
                   1456:  * Check command line if it refer history or not
                   1457:  */
                   1458: refer_history()
                   1459: {
                   1460:     char   *historyExtract ();
                   1461:     char   *his;
                   1462:
                   1463:     if (CommandLine[0] != '!')
                   1464:        return (NOT_PROCESSED);
                   1465:
                   1466:     if (his = historyExtract (CommandLine)) {
                   1467:        (void) strcpy (CommandLine, his);
                   1468:        CurrentPosition = strlen (CommandLine);
                   1469:     }
                   1470:     else {
                   1471:        fputs (CommandLine, stdout);
                   1472:        fputs (" : Event not found.\r\n", stdout);
                   1473:        (void) strcpy (CommandLine, "");
                   1474:        CurrentPosition = 0;
                   1475:     }
                   1476:     fputs (prompt, stdout);
                   1477:     print_com_line ();
                   1478:     return (PROCESSED);
                   1479: }
                   1480:
                   1481: #define FORWARD            1
                   1482: #define REVERSE            2
                   1483:
                   1484: search_reverse ()
                   1485: {
                   1486:     return (search_history (REVERSE));
                   1487: }
                   1488:
                   1489: search_forward ()
                   1490: {
                   1491:     return (search_history (FORWARD));
                   1492: }
                   1493:
                   1494: search_history (direct)
                   1495:     int direct;
                   1496: {
                   1497:     char *his, *search_reverse_history(), *search_forward_history();
                   1498:     char *(*func)();
                   1499:
                   1500:     if (direct == FORWARD)
                   1501:        func = search_forward_history;
                   1502:     else
                   1503:        func = search_reverse_history;
                   1504:
                   1505: AGAIN:
                   1506:     if (his = (*func) (0)) {
                   1507:        if (eq (his, CommandLine))
                   1508:            goto AGAIN;
                   1509:
                   1510:        (void) delete_line ();
                   1511:        (void) insert_string (his);
                   1512:        CurrentPosition = strlen (CommandLine);
                   1513:     }
                   1514:     else {
                   1515:        (void) errorBell ();
                   1516:
                   1517:        if (look_var ("verbose")) {
                   1518:            char *cp;
                   1519:
                   1520:            if ((cp = look_var ("search-string")) == NULL)
                   1521:                cp = "";
                   1522:            (void) clear_edit_line ();
                   1523:            fprintf (stdout, "\"%s\": No match.\r\n", cp);
                   1524:            (void) recover_edit_line (1);
                   1525:        }
                   1526:     }
                   1527:
                   1528:     return 0;
                   1529: }
                   1530:
                   1531:
                   1532: /*
                   1533:  * Insert the character and flush buffer
                   1534:  */
                   1535: insert_and_flush(c)
                   1536:     char c;
                   1537: {
                   1538:     (void) self_insert (c);
                   1539:     return (1);
                   1540: }
                   1541:
                   1542: /*
                   1543:  * Insert the character, but it means EOL. Therefore move cursor backward and
                   1544:  * flush buffer
                   1545:  */
                   1546: send_eof()
                   1547: {
                   1548: #ifdef TERMIOS
                   1549:     char c = initial_ttymode.c_cc[VEOF];
                   1550: #else
                   1551:     char c = tchars_buf.t_eofc;
                   1552: #endif
                   1553:
                   1554:     (void) self_insert (c);
                   1555:     if (isctlchar (c))
                   1556:        fputs ("\b\b", stdout);
                   1557:     else
                   1558:        fputs ("\b", stdout);
                   1559:     return (1);
                   1560: }
                   1561:
                   1562: /*
                   1563:  * Alarm for EOF on only the first time finding eof character
                   1564:  */
                   1565: alarm_on_eof ()
                   1566: {
                   1567:
                   1568:     errorBell ();
                   1569:     (void) clear_edit_line ();
                   1570:     printf ("EOF -- one more eof character to send eof to the process.\n");
                   1571:     (void) recover_edit_line (1);
                   1572: }
                   1573:
                   1574: /*
                   1575:  * Clear screen
                   1576:  */
                   1577: clear_screen()
                   1578: {
                   1579:
                   1580:     if (term_clear) {
                   1581:        (void) clear_edit_line ();
                   1582:        fputs (term_clear, stdout);
                   1583:        (void) recover_edit_line (1);
                   1584:     }
                   1585:     else
                   1586:        errorBell ();
                   1587:
                   1588:     return (0);
                   1589: }
                   1590:
                   1591: typedef enum {HOP_INSERT, HOP_REPLACE} HISTOP;
                   1592: typedef enum {HDIR_PREV, HDIR_CURRENT, HDIR_NEXT} HISTDIR;
                   1593:
                   1594: /*
                   1595:  * Get next history entry
                   1596:  */
                   1597: next_history()
                   1598: {
                   1599:     return (serv_history (HOP_REPLACE, HDIR_NEXT));
                   1600: }
                   1601:
                   1602: /*
                   1603:  * Get next history entry
                   1604:  */
                   1605: previous_history()
                   1606: {
                   1607:     return (serv_history (HOP_REPLACE, HDIR_PREV));
                   1608: }
                   1609:
                   1610: /*
                   1611:  * Insert next history entry
                   1612:  */
                   1613: insert_current_history()
                   1614: {
                   1615:     return (serv_history (HOP_INSERT, HDIR_CURRENT));
                   1616: }
                   1617:
                   1618: /*
                   1619:  * Insert next history entry
                   1620:  */
                   1621: insert_next_history()
                   1622: {
                   1623:     return (serv_history (HOP_INSERT, HDIR_NEXT));
                   1624: }
                   1625:
                   1626: /*
                   1627:  * Insert next history entry
                   1628:  */
                   1629: insert_previous_history()
                   1630: {
                   1631:     return (serv_history (HOP_INSERT, HDIR_PREV));
                   1632: }
                   1633:
                   1634: /*
                   1635:  * Get previous history
                   1636:  */
                   1637: serv_history(op, dir)
                   1638:     HISTOP op;
                   1639:     HISTDIR dir;
                   1640: {
                   1641:     register char *cp;
                   1642:     char *getPreviousHistory (), *getNextHistory (), *getCurrentHistory ();
                   1643:     int diff;
                   1644:
                   1645:     switch (dir) {
                   1646:     case HDIR_PREV: cp = getPreviousHistory (); break;
                   1647:     case HDIR_NEXT: cp = getNextHistory (); break;
                   1648:     case HDIR_CURRENT: cp = getCurrentHistory (); break;
                   1649:     default: cp = (char*)0;
                   1650:     }
                   1651:
                   1652:     if (cp == (char *)0) {
                   1653:        errorBell ();
                   1654:        return (0);
                   1655:     }
                   1656:
                   1657:     if (op == HOP_REPLACE)
                   1658:        (void) delete_line ();
                   1659:     (void) insert_string (cp);
                   1660:     return (0);
                   1661: }
                   1662:
                   1663: /*
                   1664:  * Show history
                   1665:  */
                   1666: show_history()
                   1667: {
                   1668:
                   1669:     (void) clear_edit_line ();
                   1670:     hist_showHistory (lookd_var ("showhist"));
                   1671:     (void) recover_edit_line (1);
                   1672: }
                   1673:
                   1674: /*
                   1675:  * Do nothing
                   1676:  */
                   1677: ignore()
                   1678: {
                   1679:     return(0);
                   1680: }
                   1681:
                   1682: /*
                   1683:  * Next character is literal
                   1684:  */
                   1685: literal_next()
                   1686: {
                   1687:
                   1688:     return (self_insert (getcharacter ()));
                   1689: }
                   1690:
                   1691: /*
                   1692:  * Reprint command line
                   1693:  */
                   1694: reprint()
                   1695: {
                   1696:
                   1697:     (void) clear_edit_line ();
                   1698:     (void) recover_edit_line (1);
                   1699:     return (0);
                   1700: }
                   1701:
                   1702: /*
                   1703:  * Print whole command line and move cursor to the current position
                   1704:  */
                   1705: print_com_line()
                   1706: {
                   1707:
                   1708:     printS (CommandLine);
                   1709:     if (CommandLine[CurrentPosition] != '\0') {
                   1710:        repeat (BS, howlong(&CommandLine[CurrentPosition + 1], 0));
                   1711:        (void) putchar (BS);
                   1712:     }
                   1713: }
                   1714:
                   1715: /*
                   1716:  * Calcurate space of string using "^" for control character
                   1717:  */
                   1718: howlong(s, n)
                   1719:     char *s;
                   1720:     int n;
                   1721: {
                   1722:     register char *sp;
                   1723:     register int area = 0;
                   1724:
                   1725:     if (n == 0)
                   1726:        n = -1;
                   1727:     for (sp = s; *sp && n; sp++, n--) {
                   1728:        if (isctlchar(*sp))
                   1729:            area += 2;
                   1730:        else
                   1731:            area += 1;
                   1732:     }
                   1733:     return (area);
                   1734: }
                   1735:
                   1736: /*
                   1737:  * Repeat puting character n times
                   1738:  */
                   1739: repeat(c, n)
                   1740:     char c;
                   1741:     register int n;
                   1742: {
                   1743:     for (n = n; n; n--)
                   1744:        (void) putchar(c);
                   1745: }
                   1746:
                   1747: /*
                   1748:  * Repeat putting string n times
                   1749:  */
                   1750: repeat_string(s, n)
                   1751:     char *s;
                   1752:     register int n;
                   1753: {
                   1754:     for (n = n; n; n--)
                   1755:        fputs(s, stdout);
                   1756: }
                   1757:
                   1758: /*
                   1759:  * Expand file name
                   1760:  */
                   1761: expand_file_name ()
                   1762: {
                   1763:     CHAR *cp, *start_expand;
                   1764:     char *x_dirname();
                   1765:     char dir[256];
                   1766:     char *fileList[256];
                   1767:     CHAR line[256];
                   1768:     DIR *dirp, *x_opendir();
                   1769:     struct direct *dp;
                   1770:     int found = 0;
                   1771:     int i;
                   1772:     int tilde_expanded = 0;
                   1773:     CHAR *index(), *rindex();
                   1774:
                   1775:     if (delimiters == NULL)
                   1776:         delimiters = DEFAULT_DELIMITERS;
                   1777:     strcpy (line, CommandLine);
                   1778:     for (cp = &line[CurrentPosition] - 1; cp > line ; --cp) {
                   1779:         if (index (delimiters, *(cp - 1)))
                   1780:            break;
                   1781:     }
                   1782:     start_expand = cp;
                   1783:     if (any ('/', cp)) {
                   1784:        (void) strcpy (dir, cp);
                   1785:        *(rindex (dir, '/') + 1) = '\0';
                   1786:        cp = (CHAR *) (rindex (cp, '/') + 1);
                   1787:     }
                   1788:     else
                   1789:        strcpy (dir, ".");
                   1790:
                   1791:     if ((dirp = x_opendir (dir)) == NULL) {
                   1792:        errorBell ();
                   1793:        return (0);
                   1794:     }
                   1795:
                   1796:     for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
                   1797:
                   1798:        if (*cp == '\0')
                   1799:            break;
                   1800:
                   1801:        if (*cp != '.' && *(dp->d_name) == '.')
                   1802:            continue;
                   1803:
                   1804:        if (prefix (cp, dp->d_name)) {
                   1805:            char *fcp;
                   1806:
                   1807: # ifdef ALLOCA
                   1808:            fcp = (char *) alloca (strlen (dp->d_name) + 1);
                   1809: # else /* ALLOCA */
                   1810:            fcp = (char *) malloc (strlen (dp->d_name) + 1);
                   1811: # endif /* ALLOCA */
                   1812:            if (fcp == 0) {
                   1813:                fputs ("\r\n", stdout);
                   1814:                perror ("alloca:");
                   1815:                reprint ();
                   1816:                longjmp (jbuf, 1);
                   1817:            }
                   1818:            strcpy (fcp, dp->d_name);
                   1819:            fileList [i++] = fcp;
                   1820:        }
                   1821:     }
                   1822:     fileList [i] = (char *) 0;
                   1823:
                   1824:     if (*start_expand == '~' && look_var ("expand-tilde")) {
                   1825:        char buf [256], *p;
                   1826:
                   1827:        strcpy (buf, start_expand);
                   1828:        p = x_dirname (buf);
                   1829:        if (!eq (p, buf)) {
                   1830:            (void) moveto (start_expand - line);
                   1831:            (void) kill_to_end_of_line ();
                   1832:            (void) insert_string (x_dirname (buf));
                   1833:            tilde_expanded = 1;
                   1834:        }
                   1835:     }
                   1836:
                   1837:     switch (i) {
                   1838:
                   1839:        case 0:
                   1840:            if (tilde_expanded == 0)
                   1841:                errorBell ();
                   1842:            break;
                   1843:
                   1844:        case 1:
                   1845:            (void) end_of_line ();
                   1846:            (void) insert_string (fileList[0] + strlen (cp));
                   1847:            break;
                   1848:
                   1849:        default:
                   1850:            {
                   1851:                char *one, *other;
                   1852:                char *c1, *c2;
                   1853:                int i;
                   1854:
                   1855:                one = fileList [0];
                   1856:                for (i = 1; other = fileList [i]; i++) {
                   1857:                    for (c1 = one, c2 = other; *c1 && *c2; c1++, c2++)
                   1858:                        if (*c1 != *c2)
                   1859:                            break;
                   1860:                    *c1 = '\0';
                   1861:                }
                   1862:                errorBell ();
                   1863:                (void) end_of_line ();
                   1864:                (void) insert_string (fileList[0] + strlen (cp));
                   1865:            }
                   1866:            break;
                   1867:     }
                   1868:
                   1869: # ifndef ALLOCA
                   1870:     for (i = 0; fileList [i]; i++)
                   1871:        free (fileList [i]);
                   1872: # endif /* ALLOCA */
                   1873:
                   1874:     closedir(dirp);
                   1875:     return (0);
                   1876: }
                   1877:
                   1878: /*
                   1879:  * List file name
                   1880:  */
                   1881: list_file_name ()
                   1882: {
                   1883:     CHAR *cp;
                   1884:     char dir[256];
                   1885:     DIR *dirp, *x_opendir();
                   1886:     CHAR *index(), *rindex();
                   1887:
                   1888:     if (delimiters == NULL)
                   1889:         delimiters = DEFAULT_DELIMITERS;
                   1890:     for (cp = (CHAR *) index (CommandLine, '\0'); cp > CommandLine ; --cp) {
                   1891:         if (index (delimiters, *(cp - 1))) {
                   1892:            break;
                   1893:        }
                   1894:     }
                   1895: #ifdef RINFO
                   1896:     /*
                   1897:      * This is an experimental code for rinfod, which serves remote
                   1898:      * information about file, process, etc.
                   1899:      */
                   1900:     if (any (':', cp)) {
                   1901:        char *host, *pattern;
                   1902:
                   1903:        (void) strcpy (dir, cp);
                   1904:        host = dir;
                   1905:        *(index (host, ':')) = '\0';
                   1906:        pattern = (index (cp, ':') + 1);;
                   1907:
                   1908:        (void) clear_edit_line();
                   1909:        list_remote_file (host, pattern);
                   1910:        (void) recover_edit_line (1);
                   1911:        return;
                   1912:     }
                   1913: #endif
                   1914:     if (any ('/', cp)) {
                   1915:        (void) strcpy (dir, cp);
                   1916:        *(rindex (dir, '/') + 1) = '\0';
                   1917:        cp = (CHAR *) (rindex (cp, '/') + 1);
                   1918:     }
                   1919:     else
                   1920:        strcpy (dir, ".");
                   1921:
                   1922:
                   1923:     if ((dirp = x_opendir (dir)) == NULL) {
                   1924:        errorBell ();
                   1925:        return (0);
                   1926:     }
                   1927:
                   1928:     (void) clear_edit_line();
                   1929:     ls (dirp, cp);
                   1930:     closedir(dirp);
                   1931:     (void) recover_edit_line (1);
                   1932:
                   1933:     return (0);
                   1934: }
                   1935:
                   1936: int    rememberPosition;
                   1937:
                   1938: clear_edit_line ()
                   1939: {
                   1940:
                   1941:     if (editstatus == NOTEDITING)
                   1942:        return;
                   1943:
                   1944:     rememberPosition = CurrentPosition;
                   1945:     (void) end_of_line ();
                   1946:     (void) fputs ("\r\n", stdout);
                   1947: }
                   1948:
                   1949: recover_edit_line (put_prompt)
                   1950:     int put_prompt;
                   1951: {
                   1952:
                   1953:     if (editstatus == NOTEDITING)
                   1954:        return;
                   1955:
                   1956:     if (rememberPosition < 0)
                   1957:        return;
                   1958:     CurrentPosition = rememberPosition;
                   1959:     rememberPosition = -1;
                   1960:     if (put_prompt && prompt)
                   1961:        fputs (prompt, stdout);
                   1962:     (void) print_com_line();
                   1963: }
                   1964:
                   1965: #define MAXFILES 256
                   1966:
                   1967: /*
                   1968:  * Do ls
                   1969:  */
                   1970: ls (dirp, prefixstring)
                   1971:     DIR *dirp;
                   1972:     char *prefixstring;
                   1973: {
                   1974:     struct direct *dp;
                   1975:     char *fileList[MAXFILES + 1];
                   1976:     int i, j;
                   1977:     int maxlen = 0;
                   1978:     int files;         /* number of file */
                   1979:     int fpl;           /* file par line */
                   1980:     int cpf;           /* column par file */
                   1981:     int fpc;           /* file par column */
                   1982:     int COL = 80;
                   1983:     char format[10];
                   1984:     int scmp();
                   1985:
                   1986:     for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
                   1987:        char *fcp;
                   1988:
                   1989:        if (i >= MAXFILES) {
                   1990:            printf ("Too many files\n");
                   1991:            break;
                   1992:        }
                   1993:
                   1994:        if (dp->d_ino == (unsigned long) 0
                   1995:                || (prefixstring[0] != '.' && dp->d_name[0] == '.'))
                   1996:            continue;
                   1997:        if (prefix (prefixstring, dp->d_name)) {
                   1998: # ifdef ALLOCA
                   1999:            fcp = (char *) alloca (strlen (dp->d_name) + 1);
                   2000: # else /* ALLOCA */
                   2001:            fcp = (char *) malloc (strlen (dp->d_name) + 1);
                   2002: # endif /* ALLOCA */
                   2003:            if (fcp == 0) {
                   2004:                fputs ("\r\n", stdout);
                   2005:                perror ("alloca:");
                   2006:                reprint ();
                   2007:                longjmp (jbuf, 1);
                   2008:            }
                   2009:            strcpy (fcp, dp->d_name);
                   2010:            fileList [i++] = fcp;
                   2011:            maxlen = max (maxlen, strlen (dp->d_name));
                   2012:        }
                   2013:     }
                   2014:     fileList [i] = (char *) 0;
                   2015:
                   2016:     if (i == 0)
                   2017:        goto BACK;
                   2018:
                   2019:     files = i;
                   2020:
                   2021:     qsort (fileList, i, sizeof (char *), scmp);
                   2022:
                   2023:     if (debug)
                   2024:        printf ("%d files\n", files);
                   2025:
                   2026:     cpf = maxlen + 1;
                   2027:     fpl = COL / cpf;
                   2028:     if (fpl == 0) fpl = 1;
                   2029:     fpc = (files + fpl - 1) / fpl;
                   2030:
                   2031:     sprintf (format, "%%-%ds", cpf);
                   2032:     for (i = 0; i < fpc; i++) {
                   2033:        for (j = 0; j < fpl - 1; j++)
                   2034:            if (i + j * fpc < files)
                   2035:                printf (format, fileList[i + (j * fpc)]);
                   2036:        if (i + (fpc * (fpl - 1)) < files)
                   2037:            printf ("%s", fileList[i + (fpc * (fpl - 1))]);
                   2038:        fputs ("\n", stdout);
                   2039:     }
                   2040:
                   2041: BACK:
                   2042:
                   2043: # ifndef ALLOCA
                   2044:     for (i = 0; fileList [i]; i++)
                   2045:        free (fileList [i]);
                   2046: # endif /* ALLOCA */
                   2047:     return;
                   2048: }
                   2049:
                   2050: #ifdef RINFO
                   2051:
                   2052: #include "../rinfo/rinfo.h"
                   2053:
                   2054: list_remote_file (host, pattern)
                   2055:     char *host, *pattern;
                   2056: {
                   2057:     struct slist *slp, *getfilelist();
                   2058:     int i, j;
                   2059:     char format [64];
                   2060:     int COL = 80;
                   2061:     int  maxlen, cpf, fpl, fpc;
                   2062:     int files;
                   2063:
                   2064:     slp = getfilelist (host, pattern);
                   2065:     files = slp->s_cnt;
                   2066:
                   2067:     COL = 80;
                   2068:     maxlen = 0;
                   2069:     for (i = 0; i < files; i++) {
                   2070:        int len;
                   2071:
                   2072:        if ((len = strlen (*(slp->s_list + i))) > maxlen)
                   2073:            maxlen = len;
                   2074:     }
                   2075:
                   2076:     cpf = maxlen + 1;
                   2077:     fpl = COL / cpf;
                   2078:     if (fpl == 0)
                   2079:        fpl = 1;
                   2080:     fpc = (files + fpl - 1) / fpl;
                   2081:
                   2082:     sprintf (format, "%%-%ds", cpf);
                   2083:     for (i = 0; i < fpc; i++) {
                   2084:        for (j = 0; j < fpl - 1; j++) {
                   2085:            if (i + j * fpc < slp->s_cnt)
                   2086:                printf (format, *(slp->s_list + (i + (j * fpc))));
                   2087:        }
                   2088:        if (i + (fpc * (fpl - 1)) < files)
                   2089:            printf ("%s", slp->s_list[i + (fpc * (fpl - 1))]);
                   2090:        fputs ("\n", stdout);
                   2091:     }
                   2092: }
                   2093: #endif /* RINFO */
                   2094:
                   2095: bind_key (ft, func, s, dfunc)
                   2096:     FUNC ft[];         /* Function table */
                   2097:     FUNC func;         /* Function to be binded */
                   2098:     char *s;           /* String to bind */
                   2099:     FUNC dfunc;                /* Default function for table allocating */
                   2100: {
                   2101:     char tmps[16];
                   2102:
                   2103:     if (s[0] == '\\' && s[1] == '^' && s[2] != '\0') {
                   2104:        tmps[0] = toctrl (s[2]);
                   2105:        strcpy (&tmps[1], &s[3]);
                   2106:        s = tmps;
                   2107:     }
                   2108:
                   2109:     /*
                   2110:      * If the string contain only one character, put the function to
                   2111:      * appropriate position in the table.
                   2112:      */
                   2113:     if (*(s+1) == '\0') {
                   2114:        if (isIndirect (ft[(int) *s]))
                   2115:            free (maskIndirect (ft[(int) *s]));
                   2116:
                   2117:        ft[(int) *s] = func;
                   2118:        return (1);
                   2119:     }
                   2120:     else {
                   2121:        FUNC *nft = (FUNC *) 0;
                   2122:        int status;
                   2123:
                   2124:        /*
                   2125:         * If the entry doesn't have indirect function table, allocate it.
                   2126:         */
                   2127:        if (! (isIndirect (ft[(int) *s]))) {
                   2128:            register int i;
                   2129:
                   2130:            nft = (FUNC *) calloc (sizeof (FUNC), 256);
                   2131:            /*
                   2132:             * If failed in allocating, return 0.
                   2133:             */
                   2134:            if (nft == 0)
                   2135:                return (0);
                   2136:
                   2137:            /*
                   2138:             * Initialize the table with default function
                   2139:             */
                   2140:            for (i = 0; i < 256; i++)
                   2141:                nft [i] = dfunc;
                   2142:            ft[(int) *s] = setIndirect (nft);
                   2143:        }
                   2144:
                   2145:        status = bind_key (maskIndirect (ft[(int) *s]), func, s+1, dfunc);
                   2146:        /*
                   2147:         * If the binding failed and the table was allocated in this function
                   2148:         * free the table and return with same status.
                   2149:         */
                   2150:        if (status == 0 && nft)
                   2151:            free (nft);
                   2152:        return (status);
                   2153:     }
                   2154: }

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