[BACK]Return to readline.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/readline.c, Revision 1.1.1.1

1.1       maekawa     1: #ifndef lint
                      2: static char *RCSid = "$Id: readline.c,v 1.69 1998/04/14 00:16:12 drd Exp $";
                      3: #endif
                      4:
                      5: /* GNUPLOT - readline.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37:
                     38: /*
                     39:  * AUTHORS
                     40:  *
                     41:  *   Original Software:
                     42:  *     Tom Tkacik
                     43:  *
                     44:  *   Msdos port and some enhancements:
                     45:  *     Gershon Elber and many others.
                     46:  *
                     47:  *   In add_history(), do not store duplicated entries:
                     48:  *     Petr Mikulik
                     49:  */
                     50:
                     51: #include <signal.h>
                     52: /* get prototype for alloc and gpfaralloc */
                     53: #include "plot.h"
                     54:
                     55: #if defined(READLINE) && !defined(GNU_READLINE)
                     56:
                     57: /* a small portable version of GNU's readline
                     58:  * this is not the BASH or GNU EMACS version of READLINE due to Copyleft
                     59:  * restrictions
                     60:  * do not need any terminal capabilities except backspace,
                     61:  * and space overwrites a character
                     62:  */
                     63:
                     64: /* NANO-EMACS line editing facility
                     65:  * printable characters print as themselves (insert not overwrite)
                     66:  * ^A moves to the beginning of the line
                     67:  * ^B moves back a single character
                     68:  * ^E moves to the end of the line
                     69:  * ^F moves forward a single character
                     70:  * ^K kills from current position to the end of line
                     71:  * ^P moves back through history
                     72:  * ^N moves forward through history
                     73:  * ^H and DEL delete the previous character
                     74:  * ^D deletes the current character, or EOF if line is empty
                     75:  * ^L/^R redraw line in case it gets trashed
                     76:  * ^U kills the entire line
                     77:  * ^W kills last word
                     78:  * LF and CR return the entire line regardless of the cursor postition
                     79:  * EOF with an empty line returns (char *)NULL
                     80:  *
                     81:  * all other characters are ignored
                     82:  */
                     83:
                     84: #ifdef __linux__
                     85: /* HBB: to get prototype for ioctl() */
                     86: # include <sys/ioctl.h>
                     87: #endif
                     88:
                     89: /* replaces the previous klugde in configure */
                     90: #if defined(HAVE_TERMIOS_H) && defined(HAVE_TCGETATTR)
                     91: # define TERMIOS
                     92: #else /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
                     93: # ifdef HAVE_SGTTY_H
                     94: #  define SGTTY
                     95: # endif
                     96: #endif /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
                     97:
                     98: #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386) && !defined(OSK)
                     99:
                    100: /*
                    101:  * Set up structures using the proper include file
                    102:  */
                    103: # if defined(_IBMR2) || defined(alliant)
                    104: #  define SGTTY
                    105: # endif
                    106:
                    107: /*  submitted by Francois.Dagorn@cicb.fr */
                    108: # ifdef SGTTY
                    109: #  include <sgtty.h>
                    110: static struct sgttyb orig_termio, rl_termio;
                    111: /* define terminal control characters */
                    112: static struct tchars s_tchars;
                    113: #  ifndef VERASE
                    114: #   define VERASE    0
                    115: #  endif                       /* not VERASE */
                    116: #  ifndef VEOF
                    117: #   define VEOF      1
                    118: #  endif                       /* not VEOF */
                    119: #  ifndef VKILL
                    120: #   define VKILL     2
                    121: #  endif                       /* not VKILL */
                    122: #  ifdef TIOCGLTC          /* available only with the 'new' line discipline */
                    123: static struct ltchars s_ltchars;
                    124: #   ifndef VWERASE
                    125: #    define VWERASE   3
                    126: #   endif                      /* not VWERASE */
                    127: #   ifndef VREPRINT
                    128: #    define VREPRINT  4
                    129: #   endif                      /* not VREPRINT */
                    130: #   ifndef VSUSP
                    131: #    define VSUSP     5
                    132: #   endif                      /* not VSUP */
                    133: #  endif                       /* TIOCGLTC */
                    134: #  ifndef NCCS
                    135: #   define NCCS      6
                    136: #  endif                       /* not NCCS */
                    137:
                    138: # else                         /* not SGTTY */
                    139:
                    140: /* SIGTSTP defines job control
                    141:  * if there is job control then we need termios.h instead of termio.h
                    142:  * (Are there any systems with job control that use termio.h?  I hope not.)
                    143:  */
                    144: #  if defined(SIGTSTP) || defined(TERMIOS)
                    145: #   ifndef TERMIOS
                    146: #    define TERMIOS
                    147: #   endif                      /* not TERMIOS */
                    148: #   include <termios.h>
                    149: /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
                    150: #   ifdef ISC22
                    151: #    ifndef ONOCR              /* taken from sys/termio.h */
                    152: #     define ONOCR 0000020     /* true at least for ISC 2.2 */
                    153: #    endif                     /* not ONOCR */
                    154: #    ifndef IUCLC
                    155: #     define IUCLC 0001000
                    156: #    endif                     /* not IUCLC */
                    157: #   endif                      /* ISC22 */
                    158: #   if !defined(IUCLC)
                    159:      /* translate upper to lower case not supported */
                    160: #    define IUCLC 0
                    161: #   endif                      /* not IUCLC */
                    162:
                    163: static struct termios orig_termio, rl_termio;
                    164: #  else                                /* not SIGSTP || TERMIOS */
                    165: #   include <termio.h>
                    166: static struct termio orig_termio, rl_termio;
                    167: /* termio defines NCC instead of NCCS */
                    168: #   define NCCS    NCC
                    169: #  endif                       /* not SIGTSTP || TERMIOS */
                    170: # endif                                /* SGTTY */
                    171:
                    172: /* ULTRIX defines VRPRNT instead of VREPRINT */
                    173: # if defined(VRPRNT) && !defined(VREPRINT)
                    174: #  define VREPRINT VRPRNT
                    175: # endif                                /* VRPRNT */
                    176:
                    177: /* define characters to use with our input character handler */
                    178: static char term_chars[NCCS];
                    179:
                    180: static int term_set = 0;       /* =1 if rl_termio set */
                    181:
                    182: #define special_getc() ansi_getc()
                    183: static int ansi_getc __PROTO((void));
                    184:
                    185: #else /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
                    186:
                    187: # ifdef _Windows
                    188: #  include <windows.h>
                    189: #  include "win/wtext.h"
                    190: #  include "win/wgnuplib.h"
                    191: extern TW textwin;
                    192: #  define TEXTUSER 0xf1
                    193: #  define TEXTGNUPLOT 0xf0
                    194: #  define special_getc() msdos_getch()
                    195: static char msdos_getch __PROTO((void));       /* HBB 980308: PROTO'ed it */
                    196: # endif                                /* _Windows */
                    197:
                    198: # if defined(MSDOS) || defined(DOS386)
                    199: /* MSDOS specific stuff */
                    200: #  ifdef DJGPP
                    201: #   include <pc.h>
                    202: #  endif                       /* DJGPP */
                    203: #  ifdef __EMX__
                    204: #   include <conio.h>
                    205: #  endif                       /* __EMX__ */
                    206: #  define special_getc() msdos_getch()
                    207: static char msdos_getch();
                    208: # endif                                /* MSDOS || DOS386 */
                    209:
                    210: # ifdef OSK
                    211: #  include <sgstat.h>
                    212: #  include <modes.h>
                    213:
                    214: #  define STDIN        0
                    215: static int term_set = 0;       /* =1 if new_settings is set */
                    216:
                    217: static struct _sgs old_settings;       /* old terminal settings        */
                    218: static struct _sgs new_settings;       /* new terminal settings        */
                    219:
                    220: #  define special_getc() ansi_getc()
                    221: static int ansi_getc __PROTO((void));
                    222:
                    223: /* On OS9 a '\n' is a character 13 and '\r' == '\n'. This gives troubles
                    224:    here, so we need a new putc wich handles this correctly and print a
                    225:    character 10 on each place we want a '\n'.
                    226:  */
                    227: #  undef putc                  /* Undefine the macro for putc */
                    228:
                    229: static int putc(c, fp)
                    230: char c;
                    231: FILE *fp;
                    232: {
                    233:     write(fileno(fp), &c, 1);
                    234:     if (c == '\012') {         /* A normal ASCII '\n' */
                    235:        c = '\r';
                    236:        write(fileno(fp), &c, 1);
                    237:     }
                    238: }
                    239:
                    240: # endif                                /* OSK */
                    241:
                    242: # if defined(ATARI) || defined(MTOS)
                    243: #  define special_getc() tos_getch()
                    244: # endif                                /* ATARI || MTOS */
                    245:
                    246: #endif /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
                    247:
                    248: #ifdef OS2
                    249: # if defined( special_getc )
                    250: #  undef special_getc()
                    251: # endif                                /* special_getc */
                    252: # define special_getc() msdos_getch()
                    253: static char msdos_getch __PROTO((void));       /* HBB 980308: PROTO'ed it */
                    254: #endif /* OS2 */
                    255:
                    256:
                    257: /* initial size and increment of input line length */
                    258: #define MAXBUF 1024
                    259: /* ^H */
                    260: #define BACKSPACE 0x08
                    261: #define SPACE  ' '
                    262:
                    263: #ifdef OSK
                    264: # define NEWLINE       '\012'
                    265: #else /* OSK */
                    266: # define NEWLINE       '\n'
                    267: #endif /* not OSK */
                    268:
                    269: struct hist {
                    270:     char *line;
                    271:     struct hist *prev;
                    272:     struct hist *next;
                    273: };
                    274:
                    275: static struct hist *history = NULL;    /* no history yet */
                    276: static struct hist *cur_entry = NULL;
                    277:
                    278: static char *cur_line;         /* current contents of the line */
                    279: static int line_len = 0;
                    280: static int cur_pos = 0;                /* current position of the cursor */
                    281: static int max_pos = 0;                /* maximum character position */
                    282:
                    283:
                    284: static void fix_line __PROTO((void));
                    285: static void redraw_line __PROTO((char *prompt));
                    286: static void clear_line __PROTO((char *prompt));
                    287: static void clear_eoline __PROTO((void));
                    288: static void copy_line __PROTO((char *line));
                    289: static void set_termio __PROTO((void));
                    290: static void reset_termio __PROTO((void));
                    291: static int ansi_getc __PROTO((void));
                    292: static int user_putc __PROTO((int ch));
                    293: static int user_puts __PROTO((char *str));
                    294: static void backspace __PROTO((void));
                    295: static void extend_cur_line __PROTO((void));
                    296:
                    297: /* user_putc and user_puts should be used in the place of
                    298:  * fputc(ch,stderr) and fputs(str,stderr) for all output
                    299:  * of user typed characters.  This allows MS-Windows to
                    300:  * display user input in a different color.
                    301:  */
                    302: static int user_putc(ch)
                    303: int ch;
                    304: {
                    305:     int rv;
                    306: #ifdef _Windows
                    307:     TextAttr(&textwin, TEXTUSER);
                    308: #endif
                    309:     rv = fputc(ch, stderr);
                    310: #ifdef _Windows
                    311:     TextAttr(&textwin, TEXTGNUPLOT);
                    312: #endif
                    313:     return rv;
                    314: }
                    315:
                    316: static int user_puts(str)
                    317: char *str;
                    318: {
                    319:     int rv;
                    320: #ifdef _Windows
                    321:     TextAttr(&textwin, TEXTUSER);
                    322: #endif
                    323:     rv = fputs(str, stderr);
                    324: #ifdef _Windows
                    325:     TextAttr(&textwin, TEXTGNUPLOT);
                    326: #endif
                    327:     return rv;
                    328: }
                    329:
                    330: /* This function provides a centralized non-destructive backspace capability
                    331:  * M. Castro
                    332:  */
                    333: static void backspace()
                    334: {
                    335:     user_putc(BACKSPACE);
                    336: }
                    337:
                    338: static void extend_cur_line()
                    339: {
                    340:     char *new_line;
                    341:
                    342:     /* extent input line length */
                    343:     new_line = gp_realloc(cur_line, line_len + MAXBUF, NULL);
                    344:     if (!new_line) {
                    345:        reset_termio();
                    346:        int_error("Can't extend readline length", NO_CARET);
                    347:     }
                    348:     cur_line = new_line;
                    349:     line_len += MAXBUF;
                    350:     FPRINTF((stderr, "\nextending readline length to %d chars\n", line_len));
                    351: }
                    352:
                    353: char *
                    354:  readline(prompt)
                    355: char *prompt;
                    356: {
                    357:
                    358:     int cur_char;
                    359:     char *new_line;
                    360:
                    361:     /* start with a string of MAXBUF chars */
                    362:
                    363:     if (line_len != 0) {
                    364:        free(cur_line);
                    365:        line_len = 0;
                    366:     }
                    367:     cur_line = gp_alloc((unsigned long) MAXBUF, "readline");
                    368:     line_len = MAXBUF;
                    369:
                    370:     /* set the termio so we can do our own input processing */
                    371:     set_termio();
                    372:
                    373:     /* print the prompt */
                    374:     fputs(prompt, stderr);
                    375:     cur_line[0] = '\0';
                    376:     cur_pos = 0;
                    377:     max_pos = 0;
                    378:     cur_entry = NULL;
                    379:
                    380:     /* get characters */
                    381:     for (;;) {
                    382:        cur_char = special_getc();
                    383:
                    384: /*
                    385:  * The #define CHARSET7BIT should be used when one encounters problems with
                    386:  * 8bit characters that should not be entered on the commandline. I cannot
                    387:  * think on any reasonable example where this could happen, but what do I know?
                    388:  * After all, the unix world still ignores 8bit chars in most applications.
                    389:  *
                    390:  * Note that latin1 defines the chars 0x80-0x9f as control chars. For the
                    391:  * benefit of Atari, MSDOS, Windows and NeXT I have decided to ignore this,
                    392:  * since it would require more #ifs.
                    393:  *
                    394:  */
                    395:
                    396: #ifdef CHARSET7BIT
                    397:        if (isprint(cur_char)) {
                    398: #else /* CHARSET7BIT */
                    399:        if (isprint(cur_char) || (((unsigned char) cur_char > 0x7f) &&
                    400:                                  cur_char != EOF)) {
                    401: #endif /* CHARSET7BIT */
                    402:            int i;
                    403:
                    404:            if (max_pos + 1 >= line_len) {
                    405:                extend_cur_line();
                    406:            }
                    407:            for (i = max_pos; i > cur_pos; i--) {
                    408:                cur_line[i] = cur_line[i - 1];
                    409:            }
                    410:            user_putc(cur_char);
                    411:            cur_line[cur_pos] = cur_char;
                    412:            cur_pos += 1;
                    413:            max_pos += 1;
                    414:            if (cur_pos < max_pos)
                    415:                fix_line();
                    416:            cur_line[max_pos] = '\0';
                    417:
                    418:            /* else interpret unix terminal driver characters */
                    419: #ifdef VERASE
                    420:        } else if (cur_char == term_chars[VERASE]) {    /* DEL? */
                    421:            if (cur_pos > 0) {
                    422:                int i;
                    423:                cur_pos -= 1;
                    424:                backspace();
                    425:                for (i = cur_pos; i < max_pos; i++)
                    426:                    cur_line[i] = cur_line[i + 1];
                    427:                max_pos -= 1;
                    428:                fix_line();
                    429:            }
                    430: #endif /* VERASE */
                    431: #ifdef VEOF
                    432:        } else if (cur_char == term_chars[VEOF]) {      /* ^D? */
                    433:            if (max_pos == 0) {
                    434:                reset_termio();
                    435:                return ((char *) NULL);
                    436:            }
                    437:            if ((cur_pos < max_pos) && (cur_char == 004)) {     /* ^D */
                    438:                int i;
                    439:                for (i = cur_pos; i < max_pos; i++)
                    440:                    cur_line[i] = cur_line[i + 1];
                    441:                max_pos -= 1;
                    442:                fix_line();
                    443:            }
                    444: #endif /* VEOF */
                    445: #ifdef VKILL
                    446:        } else if (cur_char == term_chars[VKILL]) {     /* ^U? */
                    447:            clear_line(prompt);
                    448: #endif /* VKILL */
                    449: #ifdef VWERASE
                    450:        } else if (cur_char == term_chars[VWERASE]) {   /* ^W? */
                    451:            while ((cur_pos > 0) &&
                    452:                   (cur_line[cur_pos - 1] == SPACE)) {
                    453:                cur_pos -= 1;
                    454:                backspace();
                    455:            }
                    456:            while ((cur_pos > 0) &&
                    457:                   (cur_line[cur_pos - 1] != SPACE)) {
                    458:                cur_pos -= 1;
                    459:                backspace();
                    460:            }
                    461:            clear_eoline();
                    462:            max_pos = cur_pos;
                    463: #endif /* VWERASE */
                    464: #ifdef VREPRINT
                    465:        } else if (cur_char == term_chars[VREPRINT]) {  /* ^R? */
                    466:            putc(NEWLINE, stderr);      /* go to a fresh line */
                    467:            redraw_line(prompt);
                    468: #endif /* VREPRINT */
                    469: #ifdef VSUSP
                    470:        } else if (cur_char == term_chars[VSUSP]) {
                    471:            reset_termio();
                    472:            kill(0, SIGTSTP);
                    473:
                    474:            /* process stops here */
                    475:
                    476:            set_termio();
                    477:            /* print the prompt */
                    478:            redraw_line(prompt);
                    479: #endif /* VSUSP */
                    480:        } else {
                    481:            /* do normal editing commands */
                    482:            /* some of these are also done above */
                    483:            int i;
                    484:            switch (cur_char) {
                    485:            case EOF:
                    486:                reset_termio();
                    487:                return ((char *) NULL);
                    488:            case 001:           /* ^A */
                    489:                while (cur_pos > 0) {
                    490:                    cur_pos -= 1;
                    491:                    backspace();
                    492:                }
                    493:                break;
                    494:            case 002:           /* ^B */
                    495:                if (cur_pos > 0) {
                    496:                    cur_pos -= 1;
                    497:                    backspace();
                    498:                }
                    499:                break;
                    500:            case 005:           /* ^E */
                    501:                while (cur_pos < max_pos) {
                    502:                    user_putc(cur_line[cur_pos]);
                    503:                    cur_pos += 1;
                    504:                }
                    505:                break;
                    506:            case 006:           /* ^F */
                    507:                if (cur_pos < max_pos) {
                    508:                    user_putc(cur_line[cur_pos]);
                    509:                    cur_pos += 1;
                    510:                }
                    511:                break;
                    512:            case 013:           /* ^K */
                    513:                clear_eoline();
                    514:                max_pos = cur_pos;
                    515:                break;
                    516:            case 020:           /* ^P */
                    517:                if (history != NULL) {
                    518:                    if (cur_entry == NULL) {
                    519:                        cur_entry = history;
                    520:                        clear_line(prompt);
                    521:                        copy_line(cur_entry->line);
                    522:                    } else if (cur_entry->prev != NULL) {
                    523:                        cur_entry = cur_entry->prev;
                    524:                        clear_line(prompt);
                    525:                        copy_line(cur_entry->line);
                    526:                    }
                    527:                }
                    528:                break;
                    529:            case 016:           /* ^N */
                    530:                if (cur_entry != NULL) {
                    531:                    cur_entry = cur_entry->next;
                    532:                    clear_line(prompt);
                    533:                    if (cur_entry != NULL)
                    534:                        copy_line(cur_entry->line);
                    535:                    else
                    536:                        cur_pos = max_pos = 0;
                    537:                }
                    538:                break;
                    539:            case 014:           /* ^L */
                    540:            case 022:           /* ^R */
                    541:                putc(NEWLINE, stderr);  /* go to a fresh line */
                    542:                redraw_line(prompt);
                    543:                break;
                    544:            case 0177:          /* DEL */
                    545:            case 010:           /* ^H */
                    546:                if (cur_pos > 0) {
                    547:                    cur_pos -= 1;
                    548:                    backspace();
                    549:                    for (i = cur_pos; i < max_pos; i++)
                    550:                        cur_line[i] = cur_line[i + 1];
                    551:                    max_pos -= 1;
                    552:                    fix_line();
                    553:                }
                    554:                break;
                    555:            case 004:           /* ^D */
                    556:                if (max_pos == 0) {
                    557:                    reset_termio();
                    558:                    return ((char *) NULL);
                    559:                }
                    560:                if (cur_pos < max_pos) {
                    561:                    for (i = cur_pos; i < max_pos; i++)
                    562:                        cur_line[i] = cur_line[i + 1];
                    563:                    max_pos -= 1;
                    564:                    fix_line();
                    565:                }
                    566:                break;
                    567:            case 025:           /* ^U */
                    568:                clear_line(prompt);
                    569:                break;
                    570:            case 027:           /* ^W */
                    571:                while ((cur_pos > 0) &&
                    572:                       (cur_line[cur_pos - 1] == SPACE)) {
                    573:                    cur_pos -= 1;
                    574:                    backspace();
                    575:                }
                    576:                while ((cur_pos > 0) &&
                    577:                       (cur_line[cur_pos - 1] != SPACE)) {
                    578:                    cur_pos -= 1;
                    579:                    backspace();
                    580:                }
                    581:                clear_eoline();
                    582:                max_pos = cur_pos;
                    583:                break;
                    584:            case '\n':          /* ^J */
                    585: #ifndef OSK
                    586:            case '\r':          /* ^M */
                    587: #endif
                    588:                cur_line[max_pos + 1] = '\0';
                    589: #ifdef OS2
                    590:                while (cur_pos < max_pos) {
                    591:                    user_putc(cur_line[cur_pos]);
                    592:                    cur_pos += 1;
                    593:                }
                    594: #endif
                    595:                putc(NEWLINE, stderr);
                    596:
                    597:                /* Shrink the block down to fit the string ?
                    598:                 * if the alloc fails, we still own block at cur_line,
                    599:                 * but this shouldn't really fail.
                    600:                 */
                    601:                new_line = (char *) gp_realloc(cur_line, (unsigned long) (strlen(cur_line) + 1), "line resize");
                    602:                if (new_line)
                    603:                    cur_line = new_line;
                    604:                /* else we just hang on to what we had - it's not a problem */
                    605:
                    606:                line_len = 0;
                    607:                FPRINTF((stderr, "Resizing input line to %d chars\n", strlen(cur_line)));
                    608:                reset_termio();
                    609:                return (cur_line);
                    610:            default:
                    611:                break;
                    612:            }
                    613:        }
                    614:     }
                    615: }
                    616:
                    617: /* fix up the line from cur_pos to max_pos
                    618:  * do not need any terminal capabilities except backspace,
                    619:  * and space overwrites a character
                    620:  */
                    621: static void fix_line()
                    622: {
                    623:     int i;
                    624:
                    625:     /* write tail of string */
                    626:     for (i = cur_pos; i < max_pos; i++)
                    627:        user_putc(cur_line[i]);
                    628:
                    629:     /* write a space at the end of the line in case we deleted one */
                    630:     user_putc(SPACE);
                    631:
                    632:     /* backup to original position */
                    633:     for (i = max_pos + 1; i > cur_pos; i--)
                    634:        backspace();
                    635:
                    636: }
                    637:
                    638: /* redraw the entire line, putting the cursor where it belongs */
                    639: static void redraw_line(prompt)
                    640: char *prompt;
                    641: {
                    642:     int i;
                    643:
                    644:     fputs(prompt, stderr);
                    645:     user_puts(cur_line);
                    646:
                    647:     /* put the cursor where it belongs */
                    648:     for (i = max_pos; i > cur_pos; i--)
                    649:        backspace();
                    650: }
                    651:
                    652: /* clear cur_line and the screen line */
                    653: static void clear_line(prompt)
                    654: char *prompt;
                    655: {
                    656:     int i;
                    657:     for (i = 0; i < max_pos; i++)
                    658:        cur_line[i] = '\0';
                    659:
                    660:     for (i = cur_pos; i > 0; i--)
                    661:        backspace();
                    662:
                    663:     for (i = 0; i < max_pos; i++)
                    664:        putc(SPACE, stderr);
                    665:
                    666:     putc('\r', stderr);
                    667:     fputs(prompt, stderr);
                    668:
                    669:     cur_pos = 0;
                    670:     max_pos = 0;
                    671: }
                    672:
                    673: /* clear to end of line and the screen end of line */
                    674: static void clear_eoline()
                    675: {
                    676:     int i;
                    677:     for (i = cur_pos; i < max_pos; i++)
                    678:        cur_line[i] = '\0';
                    679:
                    680:     for (i = cur_pos; i < max_pos; i++)
                    681:        putc(SPACE, stderr);
                    682:     for (i = cur_pos; i < max_pos; i++)
                    683:        backspace();
                    684: }
                    685:
                    686: /* copy line to cur_line, draw it and set cur_pos and max_pos */
                    687: static void copy_line(line)
                    688: char *line;
                    689: {
                    690:     while (strlen(line) + 1 > line_len) {
                    691:        extend_cur_line();
                    692:     }
                    693:     strcpy(cur_line, line);
                    694:     user_puts(cur_line);
                    695:     cur_pos = max_pos = strlen(cur_line);
                    696: }
                    697:
                    698: /* add line to the history */
                    699: void add_history(line)
                    700: char *line;
                    701: {
                    702:     struct hist *entry;
                    703:
                    704:     entry = history;
                    705:     while (entry != NULL) {
                    706:        /* Don't store duplicate entries */
                    707:        if (!strcmp(entry->line, line)) {
                    708:            /* cmd lines are equal, relink entry that was found last */
                    709:            if (entry->next == NULL) {
                    710:                /* previous command repeated, no change */
                    711:                return;
                    712:            }
                    713:            if (entry->prev == NULL) {
                    714:                /* current cmd line equals the first in the history */
                    715:                (entry->next)->prev = NULL;
                    716:                history->next = entry;
                    717:                entry->prev = history;
                    718:                entry->next = NULL;
                    719:                history = entry;
                    720:                return;
                    721:            }
                    722:            /* bridge over entry's vacancy, then move it to the end */
                    723:            (entry->prev)->next = entry->next;
                    724:            (entry->next)->prev = entry->prev;
                    725:            entry->prev = history;
                    726:            history->next = entry;
                    727:            entry->next = NULL;
                    728:            history = entry;
                    729:            return;
                    730:        }
                    731:        entry = entry->prev;
                    732:     }                          /* end of not-storing duplicated entries */
                    733:
                    734:     entry = (struct hist *) gp_alloc((unsigned long) sizeof(struct hist), "history");
                    735:     entry->line = gp_alloc((unsigned long) (strlen(line) + 1), "history");
                    736:     strcpy(entry->line, line);
                    737:
                    738:     entry->prev = history;
                    739:     entry->next = NULL;
                    740:     if (history != NULL) {
                    741:        history->next = entry;
                    742:     }
                    743:     history = entry;
                    744: }
                    745:
                    746:
                    747: /* Convert ANSI arrow keys to control characters */
                    748: static int ansi_getc()
                    749: {
                    750:     int c = getc(stdin);
                    751:     if (c == 033) {
                    752:        c = getc(stdin);        /* check for CSI */
                    753:        if (c == '[') {
                    754:            c = getc(stdin);    /* get command character */
                    755:            switch (c) {
                    756:            case 'D':           /* left arrow key */
                    757:                c = 002;
                    758:                break;
                    759:            case 'C':           /* right arrow key */
                    760:                c = 006;
                    761:                break;
                    762:            case 'A':           /* up arrow key */
                    763:                c = 020;
                    764:                break;
                    765:            case 'B':           /* down arrow key */
                    766:                c = 016;
                    767:                break;
                    768:            }
                    769:        }
                    770:     }
                    771:     return c;
                    772: }
                    773:
                    774: #if defined(MSDOS) || defined(_Windows) || defined(DOS386) || defined(OS2)
                    775:
                    776: /* Convert Arrow keystrokes to Control characters: */
                    777: static char msdos_getch()
                    778: {
                    779: #ifdef DJGPP
                    780:     char c;
                    781:     int ch = getkey();
                    782:     c = (ch & 0xff00) ? 0 : ch & 0xff;
                    783: #else /* not DJGPP */
                    784: # ifdef OS2
                    785:     char c = getc(stdin);
                    786: # else                         /* not OS2 */
                    787:     char c = getch();
                    788: # endif                                /* not OS2 */
                    789: #endif /* not DJGPP */
                    790:
                    791:     if (c == 0) {
                    792: #ifdef DJGPP
                    793:        c = ch & 0xff;
                    794: #else /* not DJGPP */
                    795: # ifdef OS2
                    796:        c = getc(stdin);
                    797: # else                         /* not OS2 */
                    798:        c = getch();            /* Get the extended code. */
                    799: # endif                                /* not OS2 */
                    800: #endif /* not DJGPP */
                    801:        switch (c) {
                    802:        case 75:                /* Left Arrow. */
                    803:            c = 002;
                    804:            break;
                    805:        case 77:                /* Right Arrow. */
                    806:            c = 006;
                    807:            break;
                    808:        case 72:                /* Up Arrow. */
                    809:            c = 020;
                    810:            break;
                    811:        case 80:                /* Down Arrow. */
                    812:            c = 016;
                    813:            break;
                    814:        case 115:               /* Ctl Left Arrow. */
                    815:        case 71:                /* Home */
                    816:            c = 001;
                    817:            break;
                    818:        case 116:               /* Ctl Right Arrow. */
                    819:        case 79:                /* End */
                    820:            c = 005;
                    821:            break;
                    822:        case 83:                /* Delete */
                    823:            c = 004;
                    824:            break;
                    825:        default:
                    826:            c = 0;
                    827:            break;
                    828:        }
                    829:     } else if (c == 033) {     /* ESC */
                    830:        c = 025;
                    831:     }
                    832:     return c;
                    833: }
                    834:
                    835: #endif /* MSDOS || _Windows || DOS386 || OS2 */
                    836:
                    837:
                    838: #if defined(ATARI) || defined(MTOS)
                    839:
                    840: /* Convert Arrow keystrokes to Control characters: TOS version */
                    841:
                    842: long poll_events(int);         /* from term/atariaes.trm */
                    843:
                    844: /* this function is used in help.c as well. this means that the
                    845:  * program doesn't work without -DREADLINE (which would be the case
                    846:  * if help.c didn't use it as well, since no events would be processed)
                    847:  */
                    848: char tos_getch()
                    849: {
                    850:     long rawkey;
                    851:     char c;
                    852:     int scan_code;
                    853:     static int in_help = 0;
                    854:
                    855:     if (strcmp(term->name, "atari") == 0)
                    856:        poll_events(0);
                    857:
                    858:     if (in_help) {
                    859:        switch (in_help) {
                    860:        case 1:
                    861:        case 5:
                    862:            in_help++;
                    863:            return 'e';
                    864:        case 2:
                    865:        case 6:
                    866:            in_help++;
                    867:            return 'l';
                    868:        case 3:
                    869:        case 7:
                    870:            in_help++;
                    871:            return 'p';
                    872:        case 4:
                    873:            in_help = 0;
                    874:            return 0x0d;
                    875:        case 8:
                    876:            in_help = 0;
                    877:            return ' ';
                    878:        }
                    879:     }
                    880:     if (strcmp(term->name, "atari") == 0) {
                    881:        do {
                    882:            if (Bconstat(2))
                    883:                rawkey = Cnecin();
                    884:            else
                    885:                rawkey = poll_events(1);
                    886:        } while (rawkey == 0);
                    887:     } else
                    888:        rawkey = Cnecin();
                    889:
                    890:     c = (char) rawkey;
                    891:     scan_code = ((int) (rawkey >> 16)) & 0xff; /* get the scancode */
                    892:     if (Kbshift(-1) & 0x00000007)
                    893:        scan_code |= 0x80;      /* shift or control ? */
                    894:
                    895:     switch (scan_code) {
                    896:     case 0x62:                 /* HELP         */
                    897:     case 0xe2:                 /* shift HELP   */
                    898:        if (max_pos == 0) {
                    899:            if (scan_code == 0x62) {
                    900:                in_help = 1;
                    901:            } else {
                    902:                in_help = 5;
                    903:            }
                    904:            return 'h';
                    905:        } else {
                    906:            return 0;
                    907:        }
                    908:     case 0x48:                 /* Up Arrow */
                    909:        return 0x10;            /* ^P */
                    910:     case 0x50:                 /* Down Arrow */
                    911:        return 0x0e;            /* ^N */
                    912:     case 0x4b:                 /* Left Arrow */
                    913:        return 0x02;            /* ^B */
                    914:     case 0x4d:                 /* Right Arrow */
                    915:        return 0x06;            /* ^F */
                    916:     case 0xcb:                 /* Shift Left Arrow */
                    917:     case 0xf3:                 /* Ctrl Left Arrow (TOS-bug ?) */
                    918:     case 0x47:                 /* Home */
                    919:        return 0x01;            /* ^A */
                    920:     case 0xcd:                 /* Shift Right Arrow */
                    921:     case 0xf4:                 /* Ctrl Right Arrow (TOS-bug ?) */
                    922:     case 0xc7:                 /* Shift Home */
                    923:     case 0xf7:                 /* Ctrl Home */
                    924:        return 0x05;            /* ^E */
                    925:     case 0x61:                 /* Undo - redraw line */
                    926:        return 0x0c;            /* ^L */
                    927:     default:
                    928:        if (c == 0x1b)
                    929:            return 0x15;        /* ESC becomes ^U */
                    930:        if (c == 0x7f)
                    931:            return 0x04;        /* Del becomes ^D */
                    932:        break;
                    933:     }
                    934:     return c;
                    935: }
                    936:
                    937: #endif /* ATARI || MTOS */
                    938:
                    939:   /* set termio so we can do our own input processing */
                    940: static void set_termio()
                    941: {
                    942: #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
                    943: /* set termio so we can do our own input processing */
                    944: /* and save the old terminal modes so we can reset them later */
                    945:     if (term_set == 0) {
                    946:        /*
                    947:         * Get terminal modes.
                    948:         */
                    949: # ifndef OSK
                    950: #  ifdef SGTTY
                    951:        ioctl(0, TIOCGETP, &orig_termio);
                    952: #  else                                /* not SGTTY */
                    953: #   ifdef TERMIOS
                    954: #    ifdef TCGETS
                    955:        ioctl(0, TCGETS, &orig_termio);
                    956: #    else                      /* not TCGETS */
                    957:        tcgetattr(0, &orig_termio);
                    958: #    endif                     /* not TCGETS */
                    959: #   else                       /* not TERMIOS */
                    960:        ioctl(0, TCGETA, &orig_termio);
                    961: #   endif                      /* TERMIOS */
                    962: #  endif                       /* not SGTTY */
                    963: # else                         /* OSK */
                    964:        setbuf(stdin, (char *) 0);      /* Make stdin and stdout unbuffered */
                    965:        setbuf(stderr, (char *) 0);
                    966:        _gs_opt(STDIN, &new_settings);
                    967: # endif                                /* OSK */
                    968:
                    969:        /*
                    970:         * Save terminal modes
                    971:         */
                    972: # ifndef OSK
                    973:        rl_termio = orig_termio;
                    974: # else                         /* OSK */
                    975:        _gs_opt(STDIN, &old_settings);
                    976: # endif                                /* OSK */
                    977:
                    978:        /*
                    979:         * Set the modes to the way we want them
                    980:         *  and save our input special characters
                    981:         */
                    982: # ifndef OSK
                    983: #  ifdef SGTTY
                    984:        rl_termio.sg_flags |= CBREAK;
                    985:        rl_termio.sg_flags &= ~(ECHO | XTABS);
                    986:        ioctl(0, TIOCSETN, &rl_termio);
                    987:
                    988:        ioctl(0, TIOCGETC, &s_tchars);
                    989:        term_chars[VERASE] = orig_termio.sg_erase;
                    990:        term_chars[VEOF] = s_tchars.t_eofc;
                    991:        term_chars[VKILL] = orig_termio.sg_kill;
                    992: #   ifdef TIOCGLTC
                    993:        ioctl(0, TIOCGLTC, &s_ltchars);
                    994:        term_chars[VWERASE] = s_ltchars.t_werasc;
                    995:        term_chars[VREPRINT] = s_ltchars.t_rprntc;
                    996:        term_chars[VSUSP] = s_ltchars.t_suspc;
                    997:
                    998:        /* disable suspending process on ^Z */
                    999:        s_ltchars.t_suspc = 0;
                   1000:        ioctl(0, TIOCSLTC, &s_ltchars);
                   1001: #   endif                      /* TIOCGLTC */
                   1002: #  else                                /* not SGTTY */
                   1003:        rl_termio.c_iflag &= ~(BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF);
                   1004:        rl_termio.c_iflag |= (IGNBRK | IGNPAR);
                   1005:
                   1006:        /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
                   1007:
                   1008:        rl_termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH);
                   1009: #   ifdef OS2
                   1010:        /* for emx: remove default terminal processing */
                   1011:        rl_termio.c_lflag &= ~(IDEFAULT);
                   1012: #   endif                      /* OS2 */
                   1013:        rl_termio.c_lflag |= (ISIG);
                   1014:        rl_termio.c_cc[VMIN] = 1;
                   1015:        rl_termio.c_cc[VTIME] = 0;
                   1016:
                   1017: #   ifndef VWERASE
                   1018: #    define VWERASE 3
                   1019: #   endif                      /* VWERASE */
                   1020:        term_chars[VERASE] = orig_termio.c_cc[VERASE];
                   1021:        term_chars[VEOF] = orig_termio.c_cc[VEOF];
                   1022:        term_chars[VKILL] = orig_termio.c_cc[VKILL];
                   1023: #   ifdef TERMIOS
                   1024:        term_chars[VWERASE] = orig_termio.c_cc[VWERASE];
                   1025: #    ifdef VREPRINT
                   1026:        term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
                   1027: #    else                      /* not VREPRINT */
                   1028: #     ifdef VRPRNT
                   1029:        term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
                   1030: #     endif                    /* VRPRNT */
                   1031: #    endif                     /* not VREPRINT */
                   1032:        term_chars[VSUSP] = orig_termio.c_cc[VSUSP];
                   1033:
                   1034:        /* disable suspending process on ^Z */
                   1035:        rl_termio.c_cc[VSUSP] = 0;
                   1036: #   endif                      /* TERMIOS */
                   1037: #  endif                       /* not SGTTY */
                   1038: # else                         /* OSK */
                   1039:        new_settings._sgs_echo = 0;     /* switch off terminal echo */
                   1040:        new_settings._sgs_pause = 0;    /* inhibit page pause */
                   1041:        new_settings._sgs_eofch = 0;    /* inhibit eof  */
                   1042:        new_settings._sgs_kbich = 0;    /* inhibit ^C   */
                   1043:        new_settings._sgs_kbach = 0;    /* inhibit ^E   */
                   1044: # endif                                /* OSK */
                   1045:
                   1046:        /*
                   1047:         * Set the new terminal modes.
                   1048:         */
                   1049: # ifndef OSK
                   1050: #  ifdef SGTTY
                   1051:        ioctl(0, TIOCSLTC, &s_ltchars);
                   1052: #  else                                /* not SGTTY */
                   1053: #   ifdef TERMIOS
                   1054: #    ifdef TCSETSW
                   1055:        ioctl(0, TCSETSW, &rl_termio);
                   1056: #    else                      /* not TCSETSW */
                   1057:        tcsetattr(0, TCSADRAIN, &rl_termio);
                   1058: #    endif                     /* not TCSETSW */
                   1059: #   else                       /* not TERMIOS */
                   1060:        ioctl(0, TCSETAW, &rl_termio);
                   1061: #   endif                      /* not TERMIOS */
                   1062: #  endif                       /* not SGTTY */
                   1063: # else                         /* OSK */
                   1064:        _ss_opt(STDIN, &new_settings);
                   1065: # endif                                /* OSK */
                   1066:        term_set = 1;
                   1067:     }
                   1068: #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
                   1069: }
                   1070:
                   1071: static void reset_termio()
                   1072: {
                   1073: #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
                   1074: /* reset saved terminal modes */
                   1075:     if (term_set == 1) {
                   1076: # ifndef OSK
                   1077: #  ifdef SGTTY
                   1078:        ioctl(0, TIOCSETN, &orig_termio);
                   1079: #   ifdef TIOCGLTC
                   1080:        /* enable suspending process on ^Z */
                   1081:        s_ltchars.t_suspc = term_chars[VSUSP];
                   1082:        ioctl(0, TIOCSLTC, &s_ltchars);
                   1083: #   endif                      /* TIOCGLTC */
                   1084: #  else                                /* not SGTTY */
                   1085: #   ifdef TERMIOS
                   1086: #    ifdef TCSETSW
                   1087:        ioctl(0, TCSETSW, &orig_termio);
                   1088: #    else                      /* not TCSETSW */
                   1089:        tcsetattr(0, TCSADRAIN, &orig_termio);
                   1090: #    endif                     /* not TCSETSW */
                   1091: #   else                       /* not TERMIOS */
                   1092:        ioctl(0, TCSETAW, &orig_termio);
                   1093: #   endif                      /* TERMIOS */
                   1094: #  endif                       /* not SGTTY */
                   1095: # else                         /* OSK */
                   1096:        _ss_opt(STDIN, &old_settings);
                   1097: # endif                                /* OSK */
                   1098:        term_set = 0;
                   1099:     }
                   1100: #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
                   1101: }
                   1102:
                   1103:
                   1104: #endif /* READLINE && not GNU_READLINE */

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