[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.6

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

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