OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.24/] [sim/] [getline/] [getline.c] - Diff between revs 8 and 211

Only display areas with differences | Details | Blame | View Log

Rev 8 Rev 211
#ifndef lint
#ifndef lint
static char     rcsid[] =
static char     rcsid[] =
"$Id: getline.c,v 3.11 1993/12/02 15:54:31 thewalt Exp thewalt $";
"$Id: getline.c,v 3.11 1993/12/02 15:54:31 thewalt Exp thewalt $";
static char    *copyright = "Copyright (C) 1991, 1992, 1993, Chris Thewalt";
static char    *copyright = "Copyright (C) 1991, 1992, 1993, Chris Thewalt";
#endif
#endif
 
 
/*
/*
 * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu)
 * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu)
 *
 *
 * Permission to use, copy, modify, and distribute this software
 * Permission to use, copy, modify, and distribute this software
 * for any purpose and without fee is hereby granted, provided
 * for any purpose and without fee is hereby granted, provided
 * that the above copyright notices appear in all copies and that both the
 * that the above copyright notices appear in all copies and that both the
 * copyright notice and this permission notice appear in supporting
 * copyright notice and this permission notice appear in supporting
 * documentation.  This software is provided "as is" without express or
 * documentation.  This software is provided "as is" without express or
 * implied warranty.
 * implied warranty.
 *
 *
 * Thanks to the following people who have provided enhancements and fixes:
 * Thanks to the following people who have provided enhancements and fixes:
 *   Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
 *   Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
 *   DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
 *   DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
 *   Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
 *   Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
 */
 */
 
 
#include       "getline.h"
#include       "getline.h"
static int      gl_tab();  /* forward reference needed for gl_tab_hook */
static int      gl_tab();  /* forward reference needed for gl_tab_hook */
 
 
/******************** imported interface *********************************/
/******************** imported interface *********************************/
 
 
#include <string.h>
#include <string.h>
#include <ctype.h>
#include <ctype.h>
#include <errno.h>
#include <errno.h>
#include <signal.h>
#include <signal.h>
 
 
extern int      isatty();
extern int      isatty();
extern void    *malloc();
extern void    *malloc();
extern void     free();
extern void     free();
 
 
/********************* exported interface ********************************/
/********************* exported interface ********************************/
 
 
char           *gl_getline();           /* read a line of input */
char           *gl_getline();           /* read a line of input */
void            gl_setwidth();          /* specify width of screen */
void            gl_setwidth();          /* specify width of screen */
void            gl_histadd();           /* adds entries to hist */
void            gl_histadd();           /* adds entries to hist */
void            gl_strwidth();          /* to bind gl_strlen */
void            gl_strwidth();          /* to bind gl_strlen */
 
 
int             (*gl_in_hook)() = 0;
int             (*gl_in_hook)() = 0;
int             (*gl_out_hook)() = 0;
int             (*gl_out_hook)() = 0;
int             (*gl_tab_hook)() = gl_tab;
int             (*gl_tab_hook)() = gl_tab;
 
 
/******************** internal interface *********************************/
/******************** internal interface *********************************/
 
 
#define BUF_SIZE 1024
#define BUF_SIZE 1024
 
 
static int      gl_init_done = -1;      /* terminal mode flag  */
static int      gl_init_done = -1;      /* terminal mode flag  */
static int      gl_termw = 80;          /* actual terminal width */
static int      gl_termw = 80;          /* actual terminal width */
static int      gl_scroll = 27;         /* width of EOL scrolling region */
static int      gl_scroll = 27;         /* width of EOL scrolling region */
static int      gl_width = 0;            /* net size available for input */
static int      gl_width = 0;            /* net size available for input */
static int      gl_extent = 0;           /* how far to redraw, 0 means all */
static int      gl_extent = 0;           /* how far to redraw, 0 means all */
static int      gl_overwrite = 0;        /* overwrite mode */
static int      gl_overwrite = 0;        /* overwrite mode */
static int      gl_pos, gl_cnt = 0;     /* position and size of input */
static int      gl_pos, gl_cnt = 0;     /* position and size of input */
static char     gl_buf[BUF_SIZE];       /* input buffer */
static char     gl_buf[BUF_SIZE];       /* input buffer */
static char     gl_killbuf[BUF_SIZE]=""; /* killed text */
static char     gl_killbuf[BUF_SIZE]=""; /* killed text */
static char    *gl_prompt;              /* to save the prompt string */
static char    *gl_prompt;              /* to save the prompt string */
static char     gl_intrc = 0;            /* keyboard SIGINT char */
static char     gl_intrc = 0;            /* keyboard SIGINT char */
static char     gl_quitc = 0;            /* keyboard SIGQUIT char */
static char     gl_quitc = 0;            /* keyboard SIGQUIT char */
static char     gl_suspc = 0;            /* keyboard SIGTSTP char */
static char     gl_suspc = 0;            /* keyboard SIGTSTP char */
static char     gl_dsuspc = 0;           /* delayed SIGTSTP char */
static char     gl_dsuspc = 0;           /* delayed SIGTSTP char */
static int      gl_search_mode = 0;      /* search mode flag */
static int      gl_search_mode = 0;      /* search mode flag */
 
 
static void     gl_init();              /* prepare to edit a line */
static void     gl_init();              /* prepare to edit a line */
static void     gl_cleanup();           /* to undo gl_init */
static void     gl_cleanup();           /* to undo gl_init */
static void     gl_char_init();         /* get ready for no echo input */
static void     gl_char_init();         /* get ready for no echo input */
static void     gl_char_cleanup();      /* undo gl_char_init */
static void     gl_char_cleanup();      /* undo gl_char_init */
static size_t   (*gl_strlen)() = (size_t(*)())strlen;
static size_t   (*gl_strlen)() = (size_t(*)())strlen;
                                        /* returns printable prompt width */
                                        /* returns printable prompt width */
 
 
static void     gl_addchar();           /* install specified char */
static void     gl_addchar();           /* install specified char */
static void     gl_del();               /* del, either left (-1) or cur (0) */
static void     gl_del();               /* del, either left (-1) or cur (0) */
static void     gl_error();             /* write error msg and die */
static void     gl_error();             /* write error msg and die */
static void     gl_fixup();             /* fixup state variables and screen */
static void     gl_fixup();             /* fixup state variables and screen */
static int      gl_getc();              /* read one char from terminal */
static int      gl_getc();              /* read one char from terminal */
static void     gl_kill();              /* delete to EOL */
static void     gl_kill();              /* delete to EOL */
static void     gl_newline();           /* handle \n or \r */
static void     gl_newline();           /* handle \n or \r */
static void     gl_putc();              /* write one char to terminal */
static void     gl_putc();              /* write one char to terminal */
static void     gl_puts();              /* write a line to terminal */
static void     gl_puts();              /* write a line to terminal */
static void     gl_redraw();            /* issue \n and redraw all */
static void     gl_redraw();            /* issue \n and redraw all */
static void     gl_transpose();         /* transpose two chars */
static void     gl_transpose();         /* transpose two chars */
static void     gl_yank();              /* yank killed text */
static void     gl_yank();              /* yank killed text */
static void     gl_word();              /* move a word */
static void     gl_word();              /* move a word */
 
 
static void     hist_init();    /* initializes hist pointers */
static void     hist_init();    /* initializes hist pointers */
static char    *hist_next();    /* return ptr to next item */
static char    *hist_next();    /* return ptr to next item */
static char    *hist_prev();    /* return ptr to prev item */
static char    *hist_prev();    /* return ptr to prev item */
static char    *hist_save();    /* makes copy of a string, without NL */
static char    *hist_save();    /* makes copy of a string, without NL */
 
 
static void     search_addchar();       /* increment search string */
static void     search_addchar();       /* increment search string */
static void     search_term();          /* reset with current contents */
static void     search_term();          /* reset with current contents */
static void     search_back();          /* look back for current string */
static void     search_back();          /* look back for current string */
static void     search_forw();          /* look forw for current string */
static void     search_forw();          /* look forw for current string */
 
 
/************************ nonportable part *********************************/
/************************ nonportable part *********************************/
 
 
extern int      write();
extern int      write();
extern void     exit();
extern void     exit();
 
 
#ifdef unix
#ifdef unix
#ifndef __unix__
#ifndef __unix__
#define __unix__
#define __unix__
#endif /* not __unix__ */
#endif /* not __unix__ */
#endif /* unix */
#endif /* unix */
 
 
#ifdef _IBMR2
#ifdef _IBMR2
#ifndef __unix__
#ifndef __unix__
#define __unix__
#define __unix__
#endif
#endif
#endif
#endif
 
 
#ifdef __GO32__
#ifdef __GO32__
#include <pc.h>
#include <pc.h>
#undef MSDOS
#undef MSDOS
#undef __unix__
#undef __unix__
#endif
#endif
 
 
#ifdef MSDOS
#ifdef MSDOS
#include <bios.h>
#include <bios.h>
#endif
#endif
 
 
#ifdef __unix__
#ifdef __unix__
#ifndef __convexc__
#ifndef __convexc__
extern int      read();
extern int      read();
extern int      kill();
extern int      kill();
extern int      ioctl();
extern int      ioctl();
#endif /* not __convexc__ */
#endif /* not __convexc__ */
#ifdef POSIX            /* use POSIX interface */
#ifdef POSIX            /* use POSIX interface */
#include <termios.h>
#include <termios.h>
struct termios  new_termios, old_termios;
struct termios  new_termios, old_termios;
#else /* not POSIX */
#else /* not POSIX */
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#ifdef M_XENIX  /* does not really use bsd terminal interface */
#ifdef M_XENIX  /* does not really use bsd terminal interface */
#undef TIOCSETN
#undef TIOCSETN
#endif /* M_XENIX */
#endif /* M_XENIX */
#ifdef TIOCSETN         /* use BSD interface */
#ifdef TIOCSETN         /* use BSD interface */
#include <sgtty.h>
#include <sgtty.h>
struct sgttyb   new_tty, old_tty;
struct sgttyb   new_tty, old_tty;
struct tchars   tch;
struct tchars   tch;
struct ltchars  ltch;
struct ltchars  ltch;
#else                   /* use SYSV interface */
#else                   /* use SYSV interface */
#include <termio.h>
#include <termio.h>
struct termio   new_termio, old_termio;
struct termio   new_termio, old_termio;
#endif /* TIOCSETN */
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* POSIX */
#endif  /* __unix__ */
#endif  /* __unix__ */
 
 
#ifdef vms
#ifdef vms
#include <descrip.h>
#include <descrip.h>
#include <ttdef.h>
#include <ttdef.h>
#include <iodef.h>
#include <iodef.h>
#include unixio
#include unixio
 
 
static int   setbuff[2];             /* buffer to set terminal attributes */
static int   setbuff[2];             /* buffer to set terminal attributes */
static short chan = -1;              /* channel to terminal */
static short chan = -1;              /* channel to terminal */
struct dsc$descriptor_s descrip;     /* VMS descriptor */
struct dsc$descriptor_s descrip;     /* VMS descriptor */
#endif
#endif
 
 
static void
static void
gl_char_init()                  /* turn off input echo */
gl_char_init()                  /* turn off input echo */
{
{
#ifdef __unix__
#ifdef __unix__
#ifdef POSIX
#ifdef POSIX
    tcgetattr(0, &old_termios);
    tcgetattr(0, &old_termios);
    gl_intrc = old_termios.c_cc[VINTR];
    gl_intrc = old_termios.c_cc[VINTR];
    gl_quitc = old_termios.c_cc[VQUIT];
    gl_quitc = old_termios.c_cc[VQUIT];
#ifdef VSUSP
#ifdef VSUSP
    gl_suspc = old_termios.c_cc[VSUSP];
    gl_suspc = old_termios.c_cc[VSUSP];
#endif
#endif
#ifdef VDSUSP
#ifdef VDSUSP
    gl_dsuspc = old_termios.c_cc[VDSUSP];
    gl_dsuspc = old_termios.c_cc[VDSUSP];
#endif
#endif
    new_termios = old_termios;
    new_termios = old_termios;
    new_termios.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
    new_termios.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
    new_termios.c_iflag |= (IGNBRK|IGNPAR);
    new_termios.c_iflag |= (IGNBRK|IGNPAR);
    new_termios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
    new_termios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
    new_termios.c_cc[VMIN] = 1;
    new_termios.c_cc[VMIN] = 1;
    new_termios.c_cc[VTIME] = 0;
    new_termios.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &new_termios);
    tcsetattr(0, TCSANOW, &new_termios);
#else                           /* not POSIX */
#else                           /* not POSIX */
#ifdef TIOCSETN                 /* BSD */
#ifdef TIOCSETN                 /* BSD */
    ioctl(0, TIOCGETC, &tch);
    ioctl(0, TIOCGETC, &tch);
    ioctl(0, TIOCGLTC, &ltch);
    ioctl(0, TIOCGLTC, &ltch);
    gl_intrc = tch.t_intrc;
    gl_intrc = tch.t_intrc;
    gl_quitc = tch.t_quitc;
    gl_quitc = tch.t_quitc;
    gl_suspc = ltch.t_suspc;
    gl_suspc = ltch.t_suspc;
    gl_dsuspc = ltch.t_dsuspc;
    gl_dsuspc = ltch.t_dsuspc;
    ioctl(0, TIOCGETP, &old_tty);
    ioctl(0, TIOCGETP, &old_tty);
    new_tty = old_tty;
    new_tty = old_tty;
    new_tty.sg_flags |= RAW;
    new_tty.sg_flags |= RAW;
    new_tty.sg_flags &= ~ECHO;
    new_tty.sg_flags &= ~ECHO;
    ioctl(0, TIOCSETN, &new_tty);
    ioctl(0, TIOCSETN, &new_tty);
#else                           /* SYSV */
#else                           /* SYSV */
    ioctl(0, TCGETA, &old_termio);
    ioctl(0, TCGETA, &old_termio);
    gl_intrc = old_termio.c_cc[VINTR];
    gl_intrc = old_termio.c_cc[VINTR];
    gl_quitc = old_termio.c_cc[VQUIT];
    gl_quitc = old_termio.c_cc[VQUIT];
    new_termio = old_termio;
    new_termio = old_termio;
    new_termio.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
    new_termio.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
    new_termio.c_iflag |= (IGNBRK|IGNPAR);
    new_termio.c_iflag |= (IGNBRK|IGNPAR);
    new_termio.c_lflag &= ~(ICANON|ISIG|ECHO);
    new_termio.c_lflag &= ~(ICANON|ISIG|ECHO);
    new_termio.c_cc[VMIN] = 1;
    new_termio.c_cc[VMIN] = 1;
    new_termio.c_cc[VTIME] = 0;
    new_termio.c_cc[VTIME] = 0;
    ioctl(0, TCSETA, &new_termio);
    ioctl(0, TCSETA, &new_termio);
#endif /* TIOCSETN */
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* POSIX */
#endif /* __unix__ */
#endif /* __unix__ */
 
 
#ifdef vms
#ifdef vms
    descrip.dsc$w_length  = strlen("tt:");
    descrip.dsc$w_length  = strlen("tt:");
    descrip.dsc$b_dtype   = DSC$K_DTYPE_T;
    descrip.dsc$b_dtype   = DSC$K_DTYPE_T;
    descrip.dsc$b_class   = DSC$K_CLASS_S;
    descrip.dsc$b_class   = DSC$K_CLASS_S;
    descrip.dsc$a_pointer = "tt:";
    descrip.dsc$a_pointer = "tt:";
    (void)sys$assign(&descrip,&chan,0,0);
    (void)sys$assign(&descrip,&chan,0,0);
    (void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0);
    (void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0);
    setbuff[1] |= TT$M_NOECHO;
    setbuff[1] |= TT$M_NOECHO;
    (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
    (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
#endif /* vms */
#endif /* vms */
}
}
 
 
static void
static void
gl_char_cleanup()               /* undo effects of gl_char_init */
gl_char_cleanup()               /* undo effects of gl_char_init */
{
{
#ifdef __unix__
#ifdef __unix__
#ifdef POSIX 
#ifdef POSIX 
    tcsetattr(0, TCSANOW, &old_termios);
    tcsetattr(0, TCSANOW, &old_termios);
#else                   /* not POSIX */
#else                   /* not POSIX */
#ifdef TIOCSETN         /* BSD */
#ifdef TIOCSETN         /* BSD */
    ioctl(0, TIOCSETN, &old_tty);
    ioctl(0, TIOCSETN, &old_tty);
#else                   /* SYSV */
#else                   /* SYSV */
    ioctl(0, TCSETA, &old_termio);
    ioctl(0, TCSETA, &old_termio);
#endif /* TIOCSETN */
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* POSIX */
#endif /* __unix__ */
#endif /* __unix__ */
 
 
#ifdef vms
#ifdef vms
    setbuff[1] &= ~TT$M_NOECHO;
    setbuff[1] &= ~TT$M_NOECHO;
    (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
    (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
    sys$dassgn(chan);
    sys$dassgn(chan);
    chan = -1;
    chan = -1;
#endif 
#endif 
}
}
 
 
#if MSDOS || __EMX__ || __GO32__
#if MSDOS || __EMX__ || __GO32__
int pc_keymap(c)
int pc_keymap(c)
int c;
int c;
{
{
    switch (c) {
    switch (c) {
    case 72: c = 16;   /* up -> ^P */
    case 72: c = 16;   /* up -> ^P */
        break;
        break;
    case 80: c = 14;   /* down -> ^N */
    case 80: c = 14;   /* down -> ^N */
        break;
        break;
    case 75: c = 2;    /* left -> ^B */
    case 75: c = 2;    /* left -> ^B */
        break;
        break;
    case 77: c = 6;    /* right -> ^F */
    case 77: c = 6;    /* right -> ^F */
        break;
        break;
    default: c = 0;    /* make it garbage */
    default: c = 0;    /* make it garbage */
    }
    }
    return c;
    return c;
}
}
#endif /* MSDOS || __EMX__ || __GO32__ */
#endif /* MSDOS || __EMX__ || __GO32__ */
 
 
static int
static int
gl_getc()
gl_getc()
/* get a character without echoing it to screen */
/* get a character without echoing it to screen */
{
{
    int             c;
    int             c;
#ifdef __unix__
#ifdef __unix__
    char            ch;
    char            ch;
#endif
#endif
 
 
#ifdef __unix__
#ifdef __unix__
    while ((c = read(0, &ch, 1)) == -1) {
    while ((c = read(0, &ch, 1)) == -1) {
        if (errno != EINTR)
        if (errno != EINTR)
            break;
            break;
    }
    }
    c = (ch <= 0)? -1 : ch;
    c = (ch <= 0)? -1 : ch;
#endif  /* __unix__ */
#endif  /* __unix__ */
#ifdef MSDOS
#ifdef MSDOS
    c = _bios_keybrd(_NKEYBRD_READ);
    c = _bios_keybrd(_NKEYBRD_READ);
#endif  /* MSDOS */
#endif  /* MSDOS */
#ifdef __GO32__
#ifdef __GO32__
    c = getkey () ;
    c = getkey () ;
    if (c > 255) c = pc_keymap(c & 0377);
    if (c > 255) c = pc_keymap(c & 0377);
#endif /* __GO32__ */
#endif /* __GO32__ */
#ifdef __TURBOC__
#ifdef __TURBOC__
    while(!bioskey(1))
    while(!bioskey(1))
        ;
        ;
    c = bioskey(0);
    c = bioskey(0);
#endif
#endif
#if MSDOS || __TURBOC__
#if MSDOS || __TURBOC__
    if ((c & 0377) == 224) {
    if ((c & 0377) == 224) {
        c = pc_keymap((c >> 8) & 0377);
        c = pc_keymap((c >> 8) & 0377);
    } else {
    } else {
        c &= 0377;
        c &= 0377;
    }
    }
#endif /* MSDOS || __TURBOC__ */
#endif /* MSDOS || __TURBOC__ */
#ifdef __EMX__
#ifdef __EMX__
    c = _read_kbd(0, 1, 0);
    c = _read_kbd(0, 1, 0);
    if (c == 224 || c == 0) {
    if (c == 224 || c == 0) {
        c = pc_keymap(_read_kbd(0, 1, 0));
        c = pc_keymap(_read_kbd(0, 1, 0));
    } else {
    } else {
        c &= 0377;
        c &= 0377;
    }
    }
#endif
#endif
#ifdef vms
#ifdef vms
    if(chan < 0) {
    if(chan < 0) {
       c='\0';
       c='\0';
    }
    }
    (void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0);
    (void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0);
    c &= 0177;                        /* get a char */
    c &= 0177;                        /* get a char */
#endif
#endif
    return c;
    return c;
}
}
 
 
static void
static void
gl_putc(c)
gl_putc(c)
int     c;
int     c;
{
{
    char   ch = c;
    char   ch = c;
 
 
    write(1, &ch, 1);
    write(1, &ch, 1);
    if (ch == '\n') {
    if (ch == '\n') {
        ch = '\r';
        ch = '\r';
        write(1, &ch, 1);       /* RAW mode needs '\r', does not hurt */
        write(1, &ch, 1);       /* RAW mode needs '\r', does not hurt */
    }
    }
}
}
 
 
/******************** fairly portable part *********************************/
/******************** fairly portable part *********************************/
 
 
static void
static void
gl_puts(buf)
gl_puts(buf)
char *buf;
char *buf;
{
{
    int len;
    int len;
 
 
    if (buf) {
    if (buf) {
        len = strlen(buf);
        len = strlen(buf);
        write(1, buf, len);
        write(1, buf, len);
    }
    }
}
}
 
 
static void
static void
gl_error(buf)
gl_error(buf)
char *buf;
char *buf;
{
{
    int len = strlen(buf);
    int len = strlen(buf);
 
 
    gl_cleanup();
    gl_cleanup();
    write(2, buf, len);
    write(2, buf, len);
    exit(1);
    exit(1);
}
}
 
 
static void
static void
gl_init()
gl_init()
/* set up variables and terminal */
/* set up variables and terminal */
{
{
    if (gl_init_done < 0) {              /* -1 only on startup */
    if (gl_init_done < 0) {              /* -1 only on startup */
        hist_init();
        hist_init();
    }
    }
    if (isatty(0) == 0 || isatty(1) == 0)
    if (isatty(0) == 0 || isatty(1) == 0)
        gl_error("\n*** Error: getline(): not interactive, use stdio.\n");
        gl_error("\n*** Error: getline(): not interactive, use stdio.\n");
    gl_char_init();
    gl_char_init();
    gl_init_done = 1;
    gl_init_done = 1;
}
}
 
 
static void
static void
gl_cleanup()
gl_cleanup()
/* undo effects of gl_init, as necessary */
/* undo effects of gl_init, as necessary */
{
{
    if (gl_init_done > 0)
    if (gl_init_done > 0)
        gl_char_cleanup();
        gl_char_cleanup();
    gl_init_done = 0;
    gl_init_done = 0;
}
}
 
 
void
void
gl_setwidth(w)
gl_setwidth(w)
int  w;
int  w;
{
{
    if (w > 20) {
    if (w > 20) {
        gl_termw = w;
        gl_termw = w;
        gl_scroll = w / 3;
        gl_scroll = w / 3;
    } else {
    } else {
        gl_error("\n*** Error: minimum screen width is 21\n");
        gl_error("\n*** Error: minimum screen width is 21\n");
    }
    }
}
}
 
 
char *
char *
gl_getline(prompt)
gl_getline(prompt)
char *prompt;
char *prompt;
{
{
    int             c, loc, tmp;
    int             c, loc, tmp;
 
 
#ifdef __unix__
#ifdef __unix__
    int             sig;
    int             sig;
#endif
#endif
 
 
    gl_init();
    gl_init();
    gl_prompt = (prompt)? prompt : "";
    gl_prompt = (prompt)? prompt : "";
    gl_buf[0] = 0;
    gl_buf[0] = 0;
    if (gl_in_hook)
    if (gl_in_hook)
        gl_in_hook(gl_buf);
        gl_in_hook(gl_buf);
    gl_fixup(gl_prompt, -2, BUF_SIZE);
    gl_fixup(gl_prompt, -2, BUF_SIZE);
    while ((c = gl_getc()) >= 0) {
    while ((c = gl_getc()) >= 0) {
        gl_extent = 0;   /* reset to full extent */
        gl_extent = 0;   /* reset to full extent */
        if (isprint(c)) {
        if (isprint(c)) {
            if (gl_search_mode)
            if (gl_search_mode)
               search_addchar(c);
               search_addchar(c);
            else
            else
               gl_addchar(c);
               gl_addchar(c);
        } else {
        } else {
            if (gl_search_mode) {
            if (gl_search_mode) {
                if (c == '\033' || c == '\016' || c == '\020') {
                if (c == '\033' || c == '\016' || c == '\020') {
                    search_term();
                    search_term();
                    c = 0;               /* ignore the character */
                    c = 0;               /* ignore the character */
                } else if (c == '\010' || c == '\177') {
                } else if (c == '\010' || c == '\177') {
                    search_addchar(-1); /* unwind search string */
                    search_addchar(-1); /* unwind search string */
                    c = 0;
                    c = 0;
                } else if (c != '\022' && c != '\023') {
                } else if (c != '\022' && c != '\023') {
                    search_term();      /* terminate and handle char */
                    search_term();      /* terminate and handle char */
                }
                }
            }
            }
            switch (c) {
            switch (c) {
              case '\n': case '\r':                     /* newline */
              case '\n': case '\r':                     /* newline */
                gl_newline();
                gl_newline();
                gl_cleanup();
                gl_cleanup();
                return gl_buf;
                return gl_buf;
                /*NOTREACHED*/
                /*NOTREACHED*/
                break;
                break;
              case '\001': gl_fixup(gl_prompt, -1, 0);           /* ^A */
              case '\001': gl_fixup(gl_prompt, -1, 0);           /* ^A */
                break;
                break;
              case '\002': gl_fixup(gl_prompt, -1, gl_pos-1);   /* ^B */
              case '\002': gl_fixup(gl_prompt, -1, gl_pos-1);   /* ^B */
                break;
                break;
              case '\004':                                      /* ^D */
              case '\004':                                      /* ^D */
                if (gl_cnt == 0) {
                if (gl_cnt == 0) {
                    gl_buf[0] = 0;
                    gl_buf[0] = 0;
                    gl_cleanup();
                    gl_cleanup();
                    gl_putc('\n');
                    gl_putc('\n');
                    return gl_buf;
                    return gl_buf;
                } else {
                } else {
                    gl_del(0);
                    gl_del(0);
                }
                }
                break;
                break;
              case '\005': gl_fixup(gl_prompt, -1, gl_cnt);     /* ^E */
              case '\005': gl_fixup(gl_prompt, -1, gl_cnt);     /* ^E */
                break;
                break;
              case '\006': gl_fixup(gl_prompt, -1, gl_pos+1);   /* ^F */
              case '\006': gl_fixup(gl_prompt, -1, gl_pos+1);   /* ^F */
                break;
                break;
              case '\010': case '\177': gl_del(-1);     /* ^H and DEL */
              case '\010': case '\177': gl_del(-1);     /* ^H and DEL */
                break;
                break;
              case '\t':                                        /* TAB */
              case '\t':                                        /* TAB */
                if (gl_tab_hook) {
                if (gl_tab_hook) {
                    tmp = gl_pos;
                    tmp = gl_pos;
                    loc = gl_tab_hook(gl_buf, gl_strlen(gl_prompt), &tmp);
                    loc = gl_tab_hook(gl_buf, gl_strlen(gl_prompt), &tmp);
                    if (loc >= 0 || tmp != gl_pos)
                    if (loc >= 0 || tmp != gl_pos)
                        gl_fixup(gl_prompt, loc, tmp);
                        gl_fixup(gl_prompt, loc, tmp);
                }
                }
                break;
                break;
              case '\013': gl_kill(gl_pos);                     /* ^K */
              case '\013': gl_kill(gl_pos);                     /* ^K */
                break;
                break;
              case '\014': gl_redraw();                         /* ^L */
              case '\014': gl_redraw();                         /* ^L */
                break;
                break;
              case '\016':                                      /* ^N */
              case '\016':                                      /* ^N */
                strcpy(gl_buf, hist_next());
                strcpy(gl_buf, hist_next());
                if (gl_in_hook)
                if (gl_in_hook)
                    gl_in_hook(gl_buf);
                    gl_in_hook(gl_buf);
                gl_fixup(gl_prompt, 0, BUF_SIZE);
                gl_fixup(gl_prompt, 0, BUF_SIZE);
                break;
                break;
              case '\017': gl_overwrite = !gl_overwrite;        /* ^O */
              case '\017': gl_overwrite = !gl_overwrite;        /* ^O */
                break;
                break;
              case '\020':                                      /* ^P */
              case '\020':                                      /* ^P */
                strcpy(gl_buf, hist_prev());
                strcpy(gl_buf, hist_prev());
                if (gl_in_hook)
                if (gl_in_hook)
                    gl_in_hook(gl_buf);
                    gl_in_hook(gl_buf);
                gl_fixup(gl_prompt, 0, BUF_SIZE);
                gl_fixup(gl_prompt, 0, BUF_SIZE);
                break;
                break;
              case '\022': search_back(1);                      /* ^R */
              case '\022': search_back(1);                      /* ^R */
                break;
                break;
              case '\023': search_forw(1);                      /* ^S */
              case '\023': search_forw(1);                      /* ^S */
                break;
                break;
              case '\024': gl_transpose();                      /* ^T */
              case '\024': gl_transpose();                      /* ^T */
                break;
                break;
              case '\025': gl_kill(0);                           /* ^U */
              case '\025': gl_kill(0);                           /* ^U */
                break;
                break;
              case '\031': gl_yank();                           /* ^Y */
              case '\031': gl_yank();                           /* ^Y */
                break;
                break;
              case '\033':                              /* ansi arrow keys */
              case '\033':                              /* ansi arrow keys */
                c = gl_getc();
                c = gl_getc();
                if (c == '[') {
                if (c == '[') {
                    switch(c = gl_getc()) {
                    switch(c = gl_getc()) {
                      case 'A':                                 /* up */
                      case 'A':                                 /* up */
                        strcpy(gl_buf, hist_prev());
                        strcpy(gl_buf, hist_prev());
                        if (gl_in_hook)
                        if (gl_in_hook)
                            gl_in_hook(gl_buf);
                            gl_in_hook(gl_buf);
                        gl_fixup(gl_prompt, 0, BUF_SIZE);
                        gl_fixup(gl_prompt, 0, BUF_SIZE);
                        break;
                        break;
                      case 'B':                                 /* down */
                      case 'B':                                 /* down */
                        strcpy(gl_buf, hist_next());
                        strcpy(gl_buf, hist_next());
                        if (gl_in_hook)
                        if (gl_in_hook)
                            gl_in_hook(gl_buf);
                            gl_in_hook(gl_buf);
                        gl_fixup(gl_prompt, 0, BUF_SIZE);
                        gl_fixup(gl_prompt, 0, BUF_SIZE);
                        break;
                        break;
                      case 'C': gl_fixup(gl_prompt, -1, gl_pos+1); /* right */
                      case 'C': gl_fixup(gl_prompt, -1, gl_pos+1); /* right */
                        break;
                        break;
                      case 'D': gl_fixup(gl_prompt, -1, gl_pos-1); /* left */
                      case 'D': gl_fixup(gl_prompt, -1, gl_pos-1); /* left */
                        break;
                        break;
                      default: gl_putc('\007');         /* who knows */
                      default: gl_putc('\007');         /* who knows */
                        break;
                        break;
                    }
                    }
                } else if (c == 'f' || c == 'F') {
                } else if (c == 'f' || c == 'F') {
                    gl_word(1);
                    gl_word(1);
                } else if (c == 'b' || c == 'B') {
                } else if (c == 'b' || c == 'B') {
                    gl_word(-1);
                    gl_word(-1);
                } else
                } else
                    gl_putc('\007');
                    gl_putc('\007');
                break;
                break;
              default:          /* check for a terminal signal */
              default:          /* check for a terminal signal */
#ifdef __unix__
#ifdef __unix__
                if (c > 0) {     /* ignore 0 (reset above) */
                if (c > 0) {     /* ignore 0 (reset above) */
                    sig = 0;
                    sig = 0;
#ifdef SIGINT
#ifdef SIGINT
                    if (c == gl_intrc)
                    if (c == gl_intrc)
                        sig = SIGINT;
                        sig = SIGINT;
#endif
#endif
#ifdef SIGQUIT
#ifdef SIGQUIT
                    if (c == gl_quitc)
                    if (c == gl_quitc)
                        sig = SIGQUIT;
                        sig = SIGQUIT;
#endif
#endif
#ifdef SIGTSTP
#ifdef SIGTSTP
                    if (c == gl_suspc || c == gl_dsuspc)
                    if (c == gl_suspc || c == gl_dsuspc)
                        sig = SIGTSTP;
                        sig = SIGTSTP;
#endif
#endif
                    if (sig != 0) {
                    if (sig != 0) {
                        gl_cleanup();
                        gl_cleanup();
                        kill(0, sig);
                        kill(0, sig);
                        gl_init();
                        gl_init();
                        gl_redraw();
                        gl_redraw();
                        c = 0;
                        c = 0;
                    }
                    }
                }
                }
#endif /* __unix__ */
#endif /* __unix__ */
                if (c > 0)
                if (c > 0)
                    gl_putc('\007');
                    gl_putc('\007');
                break;
                break;
            }
            }
        }
        }
    }
    }
    gl_cleanup();
    gl_cleanup();
    gl_buf[0] = 0;
    gl_buf[0] = 0;
    return gl_buf;
    return gl_buf;
}
}
 
 
static void
static void
gl_addchar(c)
gl_addchar(c)
int c;
int c;
/* adds the character c to the input buffer at current location */
/* adds the character c to the input buffer at current location */
{
{
    int  i;
    int  i;
 
 
    if (gl_cnt >= BUF_SIZE - 1)
    if (gl_cnt >= BUF_SIZE - 1)
        gl_error("\n*** Error: getline(): input buffer overflow\n");
        gl_error("\n*** Error: getline(): input buffer overflow\n");
    if (gl_overwrite == 0 || gl_pos == gl_cnt) {
    if (gl_overwrite == 0 || gl_pos == gl_cnt) {
        for (i=gl_cnt; i >= gl_pos; i--)
        for (i=gl_cnt; i >= gl_pos; i--)
            gl_buf[i+1] = gl_buf[i];
            gl_buf[i+1] = gl_buf[i];
        gl_buf[gl_pos] = c;
        gl_buf[gl_pos] = c;
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
    } else {
    } else {
        gl_buf[gl_pos] = c;
        gl_buf[gl_pos] = c;
        gl_extent = 1;
        gl_extent = 1;
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
    }
    }
}
}
 
 
static void
static void
gl_yank()
gl_yank()
/* adds the kill buffer to the input buffer at current location */
/* adds the kill buffer to the input buffer at current location */
{
{
    int  i, len;
    int  i, len;
 
 
    len = strlen(gl_killbuf);
    len = strlen(gl_killbuf);
    if (len > 0) {
    if (len > 0) {
        if (gl_overwrite == 0) {
        if (gl_overwrite == 0) {
            if (gl_cnt + len >= BUF_SIZE - 1)
            if (gl_cnt + len >= BUF_SIZE - 1)
                gl_error("\n*** Error: getline(): input buffer overflow\n");
                gl_error("\n*** Error: getline(): input buffer overflow\n");
            for (i=gl_cnt; i >= gl_pos; i--)
            for (i=gl_cnt; i >= gl_pos; i--)
                gl_buf[i+len] = gl_buf[i];
                gl_buf[i+len] = gl_buf[i];
            for (i=0; i < len; i++)
            for (i=0; i < len; i++)
                gl_buf[gl_pos+i] = gl_killbuf[i];
                gl_buf[gl_pos+i] = gl_killbuf[i];
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
        } else {
        } else {
            if (gl_pos + len > gl_cnt) {
            if (gl_pos + len > gl_cnt) {
                if (gl_pos + len >= BUF_SIZE - 1)
                if (gl_pos + len >= BUF_SIZE - 1)
                    gl_error("\n*** Error: getline(): input buffer overflow\n");
                    gl_error("\n*** Error: getline(): input buffer overflow\n");
                gl_buf[gl_pos + len] = 0;
                gl_buf[gl_pos + len] = 0;
            }
            }
            for (i=0; i < len; i++)
            for (i=0; i < len; i++)
                gl_buf[gl_pos+i] = gl_killbuf[i];
                gl_buf[gl_pos+i] = gl_killbuf[i];
            gl_extent = len;
            gl_extent = len;
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
        }
        }
    } else
    } else
        gl_putc('\007');
        gl_putc('\007');
}
}
 
 
static void
static void
gl_transpose()
gl_transpose()
/* switch character under cursor and to left of cursor */
/* switch character under cursor and to left of cursor */
{
{
    int    c;
    int    c;
 
 
    if (gl_pos > 0 && gl_cnt > gl_pos) {
    if (gl_pos > 0 && gl_cnt > gl_pos) {
        c = gl_buf[gl_pos-1];
        c = gl_buf[gl_pos-1];
        gl_buf[gl_pos-1] = gl_buf[gl_pos];
        gl_buf[gl_pos-1] = gl_buf[gl_pos];
        gl_buf[gl_pos] = c;
        gl_buf[gl_pos] = c;
        gl_extent = 2;
        gl_extent = 2;
        gl_fixup(gl_prompt, gl_pos-1, gl_pos);
        gl_fixup(gl_prompt, gl_pos-1, gl_pos);
    } else
    } else
        gl_putc('\007');
        gl_putc('\007');
}
}
 
 
static void
static void
gl_newline()
gl_newline()
/*
/*
 * Cleans up entire line before returning to caller. A \n is appended.
 * Cleans up entire line before returning to caller. A \n is appended.
 * If line longer than screen, we redraw starting at beginning
 * If line longer than screen, we redraw starting at beginning
 */
 */
{
{
    int change = gl_cnt;
    int change = gl_cnt;
    int len = gl_cnt;
    int len = gl_cnt;
    int loc = gl_width - 5;     /* shifts line back to start position */
    int loc = gl_width - 5;     /* shifts line back to start position */
 
 
    if (gl_cnt >= BUF_SIZE - 1)
    if (gl_cnt >= BUF_SIZE - 1)
        gl_error("\n*** Error: getline(): input buffer overflow\n");
        gl_error("\n*** Error: getline(): input buffer overflow\n");
    if (gl_out_hook) {
    if (gl_out_hook) {
        change = gl_out_hook(gl_buf);
        change = gl_out_hook(gl_buf);
        len = strlen(gl_buf);
        len = strlen(gl_buf);
    }
    }
    if (loc > len)
    if (loc > len)
        loc = len;
        loc = len;
    gl_fixup(gl_prompt, change, loc);   /* must do this before appending \n */
    gl_fixup(gl_prompt, change, loc);   /* must do this before appending \n */
    gl_buf[len] = '\n';
    gl_buf[len] = '\n';
    gl_buf[len+1] = '\0';
    gl_buf[len+1] = '\0';
    gl_putc('\n');
    gl_putc('\n');
}
}
 
 
static void
static void
gl_del(loc)
gl_del(loc)
int loc;
int loc;
/*
/*
 * Delete a character.  The loc variable can be:
 * Delete a character.  The loc variable can be:
 *    -1 : delete character to left of cursor
 *    -1 : delete character to left of cursor
 *     0 : delete character under cursor
 *     0 : delete character under cursor
 */
 */
{
{
    int i;
    int i;
 
 
    if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
    if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
        for (i=gl_pos+loc; i < gl_cnt; i++)
        for (i=gl_pos+loc; i < gl_cnt; i++)
            gl_buf[i] = gl_buf[i+1];
            gl_buf[i] = gl_buf[i+1];
        gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
        gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
    } else
    } else
        gl_putc('\007');
        gl_putc('\007');
}
}
 
 
static void
static void
gl_kill(pos)
gl_kill(pos)
int pos;
int pos;
/* delete from pos to the end of line */
/* delete from pos to the end of line */
{
{
    if (pos < gl_cnt) {
    if (pos < gl_cnt) {
        strcpy(gl_killbuf, gl_buf + pos);
        strcpy(gl_killbuf, gl_buf + pos);
        gl_buf[pos] = '\0';
        gl_buf[pos] = '\0';
        gl_fixup(gl_prompt, pos, pos);
        gl_fixup(gl_prompt, pos, pos);
    } else
    } else
        gl_putc('\007');
        gl_putc('\007');
}
}
 
 
static void
static void
gl_word(direction)
gl_word(direction)
int direction;
int direction;
/* move forward or backword one word */
/* move forward or backword one word */
{
{
    int pos = gl_pos;
    int pos = gl_pos;
 
 
    if (direction > 0) {         /* forward */
    if (direction > 0) {         /* forward */
        while (!isspace(gl_buf[pos]) && pos < gl_cnt)
        while (!isspace(gl_buf[pos]) && pos < gl_cnt)
            pos++;
            pos++;
        while (isspace(gl_buf[pos]) && pos < gl_cnt)
        while (isspace(gl_buf[pos]) && pos < gl_cnt)
            pos++;
            pos++;
    } else {                            /* backword */
    } else {                            /* backword */
        if (pos > 0)
        if (pos > 0)
            pos--;
            pos--;
        while (isspace(gl_buf[pos]) && pos > 0)
        while (isspace(gl_buf[pos]) && pos > 0)
            pos--;
            pos--;
        while (!isspace(gl_buf[pos]) && pos > 0)
        while (!isspace(gl_buf[pos]) && pos > 0)
            pos--;
            pos--;
        if (pos < gl_cnt && isspace(gl_buf[pos]))   /* move onto word */
        if (pos < gl_cnt && isspace(gl_buf[pos]))   /* move onto word */
            pos++;
            pos++;
    }
    }
    gl_fixup(gl_prompt, -1, pos);
    gl_fixup(gl_prompt, -1, pos);
}
}
 
 
static void
static void
gl_redraw()
gl_redraw()
/* emit a newline, reset and redraw prompt and current input line */
/* emit a newline, reset and redraw prompt and current input line */
{
{
    if (gl_init_done > 0) {
    if (gl_init_done > 0) {
        gl_putc('\n');
        gl_putc('\n');
        gl_fixup(gl_prompt, -2, gl_pos);
        gl_fixup(gl_prompt, -2, gl_pos);
    }
    }
}
}
 
 
static void
static void
gl_fixup(prompt, change, cursor)
gl_fixup(prompt, change, cursor)
char  *prompt;
char  *prompt;
int    change, cursor;
int    change, cursor;
/*
/*
 * This function is used both for redrawing when input changes or for
 * This function is used both for redrawing when input changes or for
 * moving within the input line.  The parameters are:
 * moving within the input line.  The parameters are:
 *   prompt:  compared to last_prompt[] for changes;
 *   prompt:  compared to last_prompt[] for changes;
 *   change : the index of the start of changes in the input buffer,
 *   change : the index of the start of changes in the input buffer,
 *            with -1 indicating no changes, -2 indicating we're on
 *            with -1 indicating no changes, -2 indicating we're on
 *            a new line, redraw everything.
 *            a new line, redraw everything.
 *   cursor : the desired location of the cursor after the call.
 *   cursor : the desired location of the cursor after the call.
 *            A value of BUF_SIZE can be used  to indicate the cursor should
 *            A value of BUF_SIZE can be used  to indicate the cursor should
 *            move just past the end of the input line.
 *            move just past the end of the input line.
 */
 */
{
{
    static int   gl_shift;      /* index of first on screen character */
    static int   gl_shift;      /* index of first on screen character */
    static int   off_right;     /* true if more text right of screen */
    static int   off_right;     /* true if more text right of screen */
    static int   off_left;      /* true if more text left of screen */
    static int   off_left;      /* true if more text left of screen */
    static char  last_prompt[80] = "";
    static char  last_prompt[80] = "";
    int          left = 0, right = -1;           /* bounds for redraw */
    int          left = 0, right = -1;           /* bounds for redraw */
    int          pad;           /* how much to erase at end of line */
    int          pad;           /* how much to erase at end of line */
    int          backup;        /* how far to backup before fixing */
    int          backup;        /* how far to backup before fixing */
    int          new_shift;     /* value of shift based on cursor */
    int          new_shift;     /* value of shift based on cursor */
    int          extra;         /* adjusts when shift (scroll) happens */
    int          extra;         /* adjusts when shift (scroll) happens */
    int          i;
    int          i;
    int          new_right = -1; /* alternate right bound, using gl_extent */
    int          new_right = -1; /* alternate right bound, using gl_extent */
    int          l1, l2;
    int          l1, l2;
 
 
    if (change == -2) {   /* reset */
    if (change == -2) {   /* reset */
        gl_pos = gl_cnt = gl_shift = off_right = off_left = 0;
        gl_pos = gl_cnt = gl_shift = off_right = off_left = 0;
        gl_putc('\r');
        gl_putc('\r');
        gl_puts(prompt);
        gl_puts(prompt);
        strcpy(last_prompt, prompt);
        strcpy(last_prompt, prompt);
        change = 0;
        change = 0;
        gl_width = gl_termw - gl_strlen(prompt);
        gl_width = gl_termw - gl_strlen(prompt);
    } else if (strcmp(prompt, last_prompt) != 0) {
    } else if (strcmp(prompt, last_prompt) != 0) {
        l1 = gl_strlen(last_prompt);
        l1 = gl_strlen(last_prompt);
        l2 = gl_strlen(prompt);
        l2 = gl_strlen(prompt);
        gl_cnt = gl_cnt + l1 - l2;
        gl_cnt = gl_cnt + l1 - l2;
        strcpy(last_prompt, prompt);
        strcpy(last_prompt, prompt);
        gl_putc('\r');
        gl_putc('\r');
        gl_puts(prompt);
        gl_puts(prompt);
        gl_pos = gl_shift;
        gl_pos = gl_shift;
        gl_width = gl_termw - l2;
        gl_width = gl_termw - l2;
        change = 0;
        change = 0;
    }
    }
    pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift;   /* old length */
    pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift;   /* old length */
    backup = gl_pos - gl_shift;
    backup = gl_pos - gl_shift;
    if (change >= 0) {
    if (change >= 0) {
        gl_cnt = strlen(gl_buf);
        gl_cnt = strlen(gl_buf);
        if (change > gl_cnt)
        if (change > gl_cnt)
            change = gl_cnt;
            change = gl_cnt;
    }
    }
    if (cursor > gl_cnt) {
    if (cursor > gl_cnt) {
        if (cursor != BUF_SIZE)         /* BUF_SIZE means end of line */
        if (cursor != BUF_SIZE)         /* BUF_SIZE means end of line */
            gl_putc('\007');
            gl_putc('\007');
        cursor = gl_cnt;
        cursor = gl_cnt;
    }
    }
    if (cursor < 0) {
    if (cursor < 0) {
        gl_putc('\007');
        gl_putc('\007');
        cursor = 0;
        cursor = 0;
    }
    }
    if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2))
    if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2))
        extra = 2;                      /* shift the scrolling boundary */
        extra = 2;                      /* shift the scrolling boundary */
    else
    else
        extra = 0;
        extra = 0;
    new_shift = cursor + extra + gl_scroll - gl_width;
    new_shift = cursor + extra + gl_scroll - gl_width;
    if (new_shift > 0) {
    if (new_shift > 0) {
        new_shift /= gl_scroll;
        new_shift /= gl_scroll;
        new_shift *= gl_scroll;
        new_shift *= gl_scroll;
    } else
    } else
        new_shift = 0;
        new_shift = 0;
    if (new_shift != gl_shift) {        /* scroll occurs */
    if (new_shift != gl_shift) {        /* scroll occurs */
        gl_shift = new_shift;
        gl_shift = new_shift;
        off_left = (gl_shift)? 1 : 0;
        off_left = (gl_shift)? 1 : 0;
        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
        left = gl_shift;
        left = gl_shift;
        new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
        new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
    } else if (change >= 0) {            /* no scroll, but text changed */
    } else if (change >= 0) {            /* no scroll, but text changed */
        if (change < gl_shift + off_left) {
        if (change < gl_shift + off_left) {
            left = gl_shift;
            left = gl_shift;
        } else {
        } else {
            left = change;
            left = change;
            backup = gl_pos - change;
            backup = gl_pos - change;
        }
        }
        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
        right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
        right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
        new_right = (gl_extent && (right > left + gl_extent))?
        new_right = (gl_extent && (right > left + gl_extent))?
                     left + gl_extent : right;
                     left + gl_extent : right;
    }
    }
    pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
    pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
    pad = (pad < 0)? 0 : pad;
    pad = (pad < 0)? 0 : pad;
    if (left <= right) {                /* clean up screen */
    if (left <= right) {                /* clean up screen */
        for (i=0; i < backup; i++)
        for (i=0; i < backup; i++)
            gl_putc('\b');
            gl_putc('\b');
        if (left == gl_shift && off_left) {
        if (left == gl_shift && off_left) {
            gl_putc('$');
            gl_putc('$');
            left++;
            left++;
        }
        }
        for (i=left; i < new_right; i++)
        for (i=left; i < new_right; i++)
            gl_putc(gl_buf[i]);
            gl_putc(gl_buf[i]);
        gl_pos = new_right;
        gl_pos = new_right;
        if (off_right && new_right == right) {
        if (off_right && new_right == right) {
            gl_putc('$');
            gl_putc('$');
            gl_pos++;
            gl_pos++;
        } else {
        } else {
            for (i=0; i < pad; i++)      /* erase remains of prev line */
            for (i=0; i < pad; i++)      /* erase remains of prev line */
                gl_putc(' ');
                gl_putc(' ');
            gl_pos += pad;
            gl_pos += pad;
        }
        }
    }
    }
    i = gl_pos - cursor;                /* move to final cursor location */
    i = gl_pos - cursor;                /* move to final cursor location */
    if (i > 0) {
    if (i > 0) {
        while (i--)
        while (i--)
           gl_putc('\b');
           gl_putc('\b');
    } else {
    } else {
        for (i=gl_pos; i < cursor; i++)
        for (i=gl_pos; i < cursor; i++)
            gl_putc(gl_buf[i]);
            gl_putc(gl_buf[i]);
    }
    }
    gl_pos = cursor;
    gl_pos = cursor;
}
}
 
 
static int
static int
gl_tab(buf, offset, loc)
gl_tab(buf, offset, loc)
char  *buf;
char  *buf;
int    offset;
int    offset;
int   *loc;
int   *loc;
/* default tab handler, acts like tabstops every 8 cols */
/* default tab handler, acts like tabstops every 8 cols */
{
{
    int i, count, len;
    int i, count, len;
 
 
    len = strlen(buf);
    len = strlen(buf);
    count = 8 - (offset + *loc) % 8;
    count = 8 - (offset + *loc) % 8;
    for (i=len; i >= *loc; i--)
    for (i=len; i >= *loc; i--)
        buf[i+count] = buf[i];
        buf[i+count] = buf[i];
    for (i=0; i < count; i++)
    for (i=0; i < count; i++)
        buf[*loc+i] = ' ';
        buf[*loc+i] = ' ';
    i = *loc;
    i = *loc;
    *loc = i + count;
    *loc = i + count;
    return i;
    return i;
}
}
 
 
/******************* strlen stuff **************************************/
/******************* strlen stuff **************************************/
 
 
void gl_strwidth(func)
void gl_strwidth(func)
size_t (*func)();
size_t (*func)();
{
{
    if (func != 0) {
    if (func != 0) {
        gl_strlen = func;
        gl_strlen = func;
    }
    }
}
}
 
 
/******************* History stuff **************************************/
/******************* History stuff **************************************/
 
 
#ifndef HIST_SIZE
#ifndef HIST_SIZE
#define HIST_SIZE 100
#define HIST_SIZE 100
#endif
#endif
 
 
static int      hist_pos = 0, hist_last = 0;
static int      hist_pos = 0, hist_last = 0;
static char    *hist_buf[HIST_SIZE];
static char    *hist_buf[HIST_SIZE];
 
 
static void
static void
hist_init()
hist_init()
{
{
    int i;
    int i;
 
 
    hist_buf[0] = "";
    hist_buf[0] = "";
    for (i=1; i < HIST_SIZE; i++)
    for (i=1; i < HIST_SIZE; i++)
        hist_buf[i] = (char *)0;
        hist_buf[i] = (char *)0;
}
}
 
 
void
void
gl_histadd(buf)
gl_histadd(buf)
char *buf;
char *buf;
{
{
    static char *prev = 0;
    static char *prev = 0;
    char *p = buf;
    char *p = buf;
    int len;
    int len;
 
 
    /* in case we call gl_histadd() before we call gl_getline() */
    /* in case we call gl_histadd() before we call gl_getline() */
    if (gl_init_done < 0) {              /* -1 only on startup */
    if (gl_init_done < 0) {              /* -1 only on startup */
        hist_init();
        hist_init();
        gl_init_done = 0;
        gl_init_done = 0;
    }
    }
    while (*p == ' ' || *p == '\t' || *p == '\n')
    while (*p == ' ' || *p == '\t' || *p == '\n')
        p++;
        p++;
    if (*p) {
    if (*p) {
        len = strlen(buf);
        len = strlen(buf);
        if (strchr(p, '\n'))    /* previously line already has NL stripped */
        if (strchr(p, '\n'))    /* previously line already has NL stripped */
            len--;
            len--;
        if (prev == 0 || strlen(prev) != len ||
        if (prev == 0 || strlen(prev) != len ||
                            strncmp(prev, buf, len) != 0) {
                            strncmp(prev, buf, len) != 0) {
            hist_buf[hist_last] = hist_save(buf);
            hist_buf[hist_last] = hist_save(buf);
            prev = hist_buf[hist_last];
            prev = hist_buf[hist_last];
            hist_last = (hist_last + 1) % HIST_SIZE;
            hist_last = (hist_last + 1) % HIST_SIZE;
            if (hist_buf[hist_last] && *hist_buf[hist_last]) {
            if (hist_buf[hist_last] && *hist_buf[hist_last]) {
                free(hist_buf[hist_last]);
                free(hist_buf[hist_last]);
            }
            }
            hist_buf[hist_last] = "";
            hist_buf[hist_last] = "";
        }
        }
    }
    }
    hist_pos = hist_last;
    hist_pos = hist_last;
}
}
 
 
static char *
static char *
hist_prev()
hist_prev()
/* loads previous hist entry into input buffer, sticks on first */
/* loads previous hist entry into input buffer, sticks on first */
{
{
    char *p = 0;
    char *p = 0;
    int   next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
    int   next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
 
 
    if (hist_buf[hist_pos] != 0 && next != hist_last) {
    if (hist_buf[hist_pos] != 0 && next != hist_last) {
        hist_pos = next;
        hist_pos = next;
        p = hist_buf[hist_pos];
        p = hist_buf[hist_pos];
    }
    }
    if (p == 0) {
    if (p == 0) {
        p = "";
        p = "";
        gl_putc('\007');
        gl_putc('\007');
    }
    }
    return p;
    return p;
}
}
 
 
static char *
static char *
hist_next()
hist_next()
/* loads next hist entry into input buffer, clears on last */
/* loads next hist entry into input buffer, clears on last */
{
{
    char *p = 0;
    char *p = 0;
 
 
    if (hist_pos != hist_last) {
    if (hist_pos != hist_last) {
        hist_pos = (hist_pos+1) % HIST_SIZE;
        hist_pos = (hist_pos+1) % HIST_SIZE;
        p = hist_buf[hist_pos];
        p = hist_buf[hist_pos];
    }
    }
    if (p == 0) {
    if (p == 0) {
        p = "";
        p = "";
        gl_putc('\007');
        gl_putc('\007');
    }
    }
    return p;
    return p;
}
}
 
 
static char *
static char *
hist_save(p)
hist_save(p)
char *p;
char *p;
/* makes a copy of the string */
/* makes a copy of the string */
{
{
    char *s = 0;
    char *s = 0;
    int   len = strlen(p);
    int   len = strlen(p);
    char *nl = strchr(p, '\n');
    char *nl = strchr(p, '\n');
 
 
    if (nl) {
    if (nl) {
        if ((s = malloc(len)) != 0) {
        if ((s = malloc(len)) != 0) {
            strncpy(s, p, len-1);
            strncpy(s, p, len-1);
            s[len-1] = 0;
            s[len-1] = 0;
        }
        }
    } else {
    } else {
        if ((s = malloc(len+1)) != 0) {
        if ((s = malloc(len+1)) != 0) {
            strcpy(s, p);
            strcpy(s, p);
        }
        }
    }
    }
    if (s == 0)
    if (s == 0)
        gl_error("\n*** Error: hist_save() failed on malloc\n");
        gl_error("\n*** Error: hist_save() failed on malloc\n");
    return s;
    return s;
}
}
 
 
/******************* Search stuff **************************************/
/******************* Search stuff **************************************/
 
 
static char  search_prompt[101];  /* prompt includes search string */
static char  search_prompt[101];  /* prompt includes search string */
static char  search_string[100];
static char  search_string[100];
static int   search_pos = 0;      /* current location in search_string */
static int   search_pos = 0;      /* current location in search_string */
static int   search_forw_flg = 0; /* search direction flag */
static int   search_forw_flg = 0; /* search direction flag */
static int   search_last = 0;      /* last match found */
static int   search_last = 0;      /* last match found */
 
 
static void
static void
search_update(c)
search_update(c)
int c;
int c;
{
{
    if (c == 0) {
    if (c == 0) {
        search_pos = 0;
        search_pos = 0;
        search_string[0] = 0;
        search_string[0] = 0;
        search_prompt[0] = '?';
        search_prompt[0] = '?';
        search_prompt[1] = ' ';
        search_prompt[1] = ' ';
        search_prompt[2] = 0;
        search_prompt[2] = 0;
    } else if (c > 0) {
    } else if (c > 0) {
        search_string[search_pos] = c;
        search_string[search_pos] = c;
        search_string[search_pos+1] = 0;
        search_string[search_pos+1] = 0;
        search_prompt[search_pos] = c;
        search_prompt[search_pos] = c;
        search_prompt[search_pos+1] = '?';
        search_prompt[search_pos+1] = '?';
        search_prompt[search_pos+2] = ' ';
        search_prompt[search_pos+2] = ' ';
        search_prompt[search_pos+3] = 0;
        search_prompt[search_pos+3] = 0;
        search_pos++;
        search_pos++;
    } else {
    } else {
        if (search_pos > 0) {
        if (search_pos > 0) {
            search_pos--;
            search_pos--;
            search_string[search_pos] = 0;
            search_string[search_pos] = 0;
            search_prompt[search_pos] = '?';
            search_prompt[search_pos] = '?';
            search_prompt[search_pos+1] = ' ';
            search_prompt[search_pos+1] = ' ';
            search_prompt[search_pos+2] = 0;
            search_prompt[search_pos+2] = 0;
        } else {
        } else {
            gl_putc('\007');
            gl_putc('\007');
            hist_pos = hist_last;
            hist_pos = hist_last;
        }
        }
    }
    }
}
}
 
 
static void
static void
search_addchar(c)
search_addchar(c)
int  c;
int  c;
{
{
    char *loc;
    char *loc;
 
 
    search_update(c);
    search_update(c);
    if (c < 0) {
    if (c < 0) {
        if (search_pos > 0) {
        if (search_pos > 0) {
            hist_pos = search_last;
            hist_pos = search_last;
        } else {
        } else {
            gl_buf[0] = 0;
            gl_buf[0] = 0;
            hist_pos = hist_last;
            hist_pos = hist_last;
        }
        }
        strcpy(gl_buf, hist_buf[hist_pos]);
        strcpy(gl_buf, hist_buf[hist_pos]);
    }
    }
    if ((loc = strstr(gl_buf, search_string)) != 0) {
    if ((loc = strstr(gl_buf, search_string)) != 0) {
        gl_fixup(search_prompt, 0, loc - gl_buf);
        gl_fixup(search_prompt, 0, loc - gl_buf);
    } else if (search_pos > 0) {
    } else if (search_pos > 0) {
        if (search_forw_flg) {
        if (search_forw_flg) {
            search_forw(0);
            search_forw(0);
        } else {
        } else {
            search_back(0);
            search_back(0);
        }
        }
    } else {
    } else {
        gl_fixup(search_prompt, 0, 0);
        gl_fixup(search_prompt, 0, 0);
    }
    }
}
}
 
 
static void
static void
search_term()
search_term()
{
{
    gl_search_mode = 0;
    gl_search_mode = 0;
    if (gl_buf[0] == 0)           /* not found, reset hist list */
    if (gl_buf[0] == 0)           /* not found, reset hist list */
        hist_pos = hist_last;
        hist_pos = hist_last;
    if (gl_in_hook)
    if (gl_in_hook)
        gl_in_hook(gl_buf);
        gl_in_hook(gl_buf);
    gl_fixup(gl_prompt, 0, gl_pos);
    gl_fixup(gl_prompt, 0, gl_pos);
}
}
 
 
static void
static void
search_back(new_search)
search_back(new_search)
int new_search;
int new_search;
{
{
    int    found = 0;
    int    found = 0;
    char  *p, *loc;
    char  *p, *loc;
 
 
    search_forw_flg = 0;
    search_forw_flg = 0;
    if (gl_search_mode == 0) {
    if (gl_search_mode == 0) {
        search_last = hist_pos = hist_last;
        search_last = hist_pos = hist_last;
        search_update(0);
        search_update(0);
        gl_search_mode = 1;
        gl_search_mode = 1;
        gl_buf[0] = 0;
        gl_buf[0] = 0;
        gl_fixup(search_prompt, 0, 0);
        gl_fixup(search_prompt, 0, 0);
    } else if (search_pos > 0) {
    } else if (search_pos > 0) {
        while (!found) {
        while (!found) {
            p = hist_prev();
            p = hist_prev();
            if (*p == 0) {               /* not found, done looking */
            if (*p == 0) {               /* not found, done looking */
               gl_buf[0] = 0;
               gl_buf[0] = 0;
               gl_fixup(search_prompt, 0, 0);
               gl_fixup(search_prompt, 0, 0);
               found = 1;
               found = 1;
            } else if ((loc = strstr(p, search_string)) != 0) {
            } else if ((loc = strstr(p, search_string)) != 0) {
               strcpy(gl_buf, p);
               strcpy(gl_buf, p);
               gl_fixup(search_prompt, 0, loc - p);
               gl_fixup(search_prompt, 0, loc - p);
               if (new_search)
               if (new_search)
                   search_last = hist_pos;
                   search_last = hist_pos;
               found = 1;
               found = 1;
            }
            }
        }
        }
    } else {
    } else {
        gl_putc('\007');
        gl_putc('\007');
    }
    }
}
}
 
 
static void
static void
search_forw(new_search)
search_forw(new_search)
int new_search;
int new_search;
{
{
    int    found = 0;
    int    found = 0;
    char  *p, *loc;
    char  *p, *loc;
 
 
    search_forw_flg = 1;
    search_forw_flg = 1;
    if (gl_search_mode == 0) {
    if (gl_search_mode == 0) {
        search_last = hist_pos = hist_last;
        search_last = hist_pos = hist_last;
        search_update(0);
        search_update(0);
        gl_search_mode = 1;
        gl_search_mode = 1;
        gl_buf[0] = 0;
        gl_buf[0] = 0;
        gl_fixup(search_prompt, 0, 0);
        gl_fixup(search_prompt, 0, 0);
    } else if (search_pos > 0) {
    } else if (search_pos > 0) {
        while (!found) {
        while (!found) {
            p = hist_next();
            p = hist_next();
            if (*p == 0) {               /* not found, done looking */
            if (*p == 0) {               /* not found, done looking */
               gl_buf[0] = 0;
               gl_buf[0] = 0;
               gl_fixup(search_prompt, 0, 0);
               gl_fixup(search_prompt, 0, 0);
               found = 1;
               found = 1;
            } else if ((loc = strstr(p, search_string)) != 0) {
            } else if ((loc = strstr(p, search_string)) != 0) {
               strcpy(gl_buf, p);
               strcpy(gl_buf, p);
               gl_fixup(search_prompt, 0, loc - p);
               gl_fixup(search_prompt, 0, loc - p);
               if (new_search)
               if (new_search)
                   search_last = hist_pos;
                   search_last = hist_pos;
               found = 1;
               found = 1;
            }
            }
        }
        }
    } else {
    } else {
        gl_putc('\007');
        gl_putc('\007');
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.