[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     ! 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>