home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume26
/
input-edit
/
patch01
next >
Wrap
Text File
|
1991-11-30
|
25KB
|
826 lines
Newsgroups: comp.sources.misc
From: thewalt@canuck.CE.Berkeley.EDU (Chris Thewalt)
Subject: v26i092: input-edit - C input functions for line editing with history, Patch01
Message-ID: <1991Nov30.210948.4573@sparky.imd.sterling.com>
X-Md4-Signature: b8bf2ca4014f08c3651aba5c21908e83
Date: Sat, 30 Nov 1991 21:09:48 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: thewalt@canuck.CE.Berkeley.EDU (Chris Thewalt)
Posting-number: Volume 26, Issue 92
Archive-name: input-edit/patch01
Environment: UNIX, MS-DOS
Patch-To: input-edit: Volume 25, Issue 56
The patch to getline.c was larger than a repost of the file, so this
version replaces the original getline.c posted in Volume 25, Issue 56.
The changes since the first version are:
1) removed stdio calls to decrease executable size
(thanks to Scott Schwartz, schwartz@groucho.cs.psu.edu)
2) added VMS support
(thanks to Christoph Keller, keller@bernina.ethz.ch)
3) added some new key bindings and functionality:
^T: transpose current and previous character
arrow keys: motion for ANSI and MSDOS arrow keys
^G: toggles replace (overwrite) mode. Initially
in insert mode.
What is input-edit?
environment: ANSI C, UNIX (sysv or bsd), MSDOS with MSC, VMS
(Converting to K&R C should be fairly simple)
tested on: DECstation 5000, Ultrix 4.2 with gcc
Sun Sparc II, SunOS 4.1.1, gcc
SGI Iris, IRIX System V.3, cc
PC, DR DOS 5.0, MSC 6.0
description: Getline can be used in programs that want to provide
an emacs style line editing cabability with history.
Getline allows the user to edit the current line
and move through the history list of lines previously
typed and returns the buffer to the caller when RETURN
is entered. Long lines are handled by horizontal
scrolling. Does NOT use termcap, uses only \b to move around.
The actual editing capabilites are a very small subset
of emacs commands, but then the package is very small
and quite portable. Get GNU readline if you need more
powerful editing.
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 11/25/1991 16:03 UTC by thewalt@canuck.CE.Berkeley.EDU
# Source directory /usr/users/thewalt/et
#
# existing files WILL be overwritten
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 20798 -rw-r--r-- getline.c
#
# ============= getline.c ==============
echo 'x - extracting getline.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'getline.c' &&
#ifndef lint
static char rcsid[] =
"$Id: getline.c,v 2.1 1991/11/25 15:58:19 thewalt Exp thewalt $";
#endif
X
/*
X * Fairly portable (ANSI C), emacs style line editing input package.
X * This package uses \b to move, and \007 to ring the bell.
X * It uses a fixed screen width, as initialized in the gl_init() call,
X * and does not draw in the last location to avoid line wraps.
X * The only non-portable part is how to turn off character echoing.
X * This code works for *NIX of BSD or SYSV flavor, as well as MSDOS (MSC6.0).
X * No TERMCAP features are used, so long lines are scrolled on one line
X * rather than extending over several lines. The function getline
X * returns a pointer to a static buffer area which holds the input string,
X * including the newline. On EOF the first character is set equal to '\0'.
X * The caller supplies a desired prompt, as shown in the prototype:
X *
X * char *getline(char *prompt)
X *
X * Getline is different from GNU readline in that:
X * - getline has much more limited editing capabilities, but it
X * is also much smaller and doesn't need termcap.
X * - you don't free the buffer when done, since it is static
X * (make a copy yourself if you want one)
X * - the newline is appended to the buffer
X * - you don't add lines to history, it is done automatically.
X *
X * The function gl_init(int screen_width) should be called before
X * calling getline(char *prompt), and gl_cleanup(void) should be
X * called before before exiting. The function gl_redraw(void) may also
X * be called to redraw the screen (as is done when ^L is read).
X * The function gl_replace() is also user callable and toggles getline
X * between insert and replace (overwrite) mode. Getline begins in insert
X * mode.
X *
X * The editing keys are:
X * ^A, ^E - move to beginnning or end of line, respectively.
X * ^F, ^B - nondestructive move forward or back one location, respectively.
X * ^D - delete the character currently under the cursor, or
X * send EOF if no characters in the buffer.
X * ^G - toggle replace (overwrite) mode, initally in insert mode.
X * ^H, DEL - delete character left of the cursor.
X * ^K - delete from cursor to end of line.
X * ^L - redraw the current line.
X * ^P, ^N - move through history, previous and next, respectively.
X * ^T - transpose chars under and to left of cursor
X * TAB - call user defined function if bound, or insert spaces
X * to get to next TAB stop (just past every 8th column).
X * NL, CR - places line on history list if nonblank, calls output
X * cleanup function if bound, appends newline and returns
X * to the caller.
X * arrow keys - appropriate motion
X *
X * In addition, the caller can modify the buffer in certain ways, which
X * may be useful for things like auto-indent modes. There are three
X * function pointers which can be bound to user functions.
X * Each of these functions must return the index of the first location
X * at which the buffer was modified, or -1 if the buffer wasn't modified.
X * Each of the functions receive the current input buffer as the first
X * argument. The screen is automatically cleaned up if the buffer is changed.
X * The user is responsible for not writing beyond the end of the static
X * buffer. The function pointer prototypes are:
X *
X * int (*gl_in_hook)(char *buf)
X * - called on entry to getline, and each time a new history
X * string is loaded, from a ^P or ^N. Initally NULL.
X * int (*gl_out_hook)(char *buf)
X * - called when a \n or \r is read, before appending \n and
X * returning to caller. Initally NULL.
X * int (*gl_tab_hook)(char *buf, int offset, int *loc)
X * - called whenever a TAB is read. The second argument is
X * the current line offset due to the width of the prompt.
X * The third argument is a pointer to the variable holding the
X * current location in the buffer. The location may be reset
X * by the user to move the cursor when the call returns.
X * Initially a built in tabbing function is bound.
X *
X * Please send bug reports, fixes and enhancements to Chris Thewalt,
X * thewalt@ce.berkeley.edu
X */
X
static char *copyright = "Copyright (C) 1991, Chris Thewalt";
/*
X * Copyright (C) 1991 by Chris Thewalt
X *
X * Permission to use, copy, modify, and distribute this software
X * for any purpose and without fee is hereby granted, provided
X * that the above copyright notices appear in all copies and that both the
X * copyright notice and this permission notice appear in supporting
X * documentation. This software is provided "as is" without express or
X * implied warranty.
X */
X
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
X
extern int isatty();
X
#define BUF_SIZE 1024
#define SCROLL 30
X
static int gl_init_done = 0; /* -1 is terminal, 1 is batch */
static int gl_screen = 80; /* screen width */
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_overwrite = 0; /* overwrite mode */
static int gl_pos, gl_cnt = 0; /* position and size of input */
static char gl_buf[BUF_SIZE]; /* input buffer */
static char *gl_prompt; /* to save the prompt string */
X
void gl_init(int);
void gl_cleanup(void); /* to undo gl_init */
void gl_redraw(void); /* issue \n and redraw all */
void gl_replace(void); /* toggle replace/insert mode */
static void gl_char_init(void); /* get ready for no echo input */
static void gl_char_cleanup(void); /* undo gl_char_init */
static int gl_getc(void); /* read one char from terminal */
static void gl_putc(int); /* write one char to terminal */
static void gl_gets(char *, int); /* get a line from terminal */
static void gl_puts(char *); /* write a line to terminal */
static void gl_addchar(int); /* install specified char */
static void gl_transpose(void); /* transpose two chars */
static void gl_newline(void); /* handle \n or \r */
static void gl_fixup(int, int); /* fixup state variables and screen */
static void gl_del(int); /* del, either left (-1) or cur (0) */
static void gl_kill(void); /* delete to EOL */
static int gl_tab(char *, int, int *); /* default TAB handler */
X
static void hist_add(void); /* adds nonblank entries to hist */
static void hist_init(void); /* initializes hist pointers */
static void hist_next(void); /* copies next entry to input buf */
static void hist_prev(void); /* copies prev entry to input buf */
static char *hist_save(char *); /* makes copy of a string */
X
int (*gl_in_hook)(char *) = 0;
int (*gl_out_hook)(char *) = 0;
int (*gl_tab_hook)(char *, int, int *) = gl_tab;
X
/************************ nonportable part *********************************/
extern int write();
extern void _exit();
X
#ifdef MSDOS
#include <bios.h>
#endif
X
#ifdef unix
extern int read();
#include <sys/ioctl.h>
#ifndef TIOCGETP
#include <termio.h>
struct termio tty, old_tty;
#else
#include <sgtty.h>
struct sgttyb tty, old_tty;
#endif /* TIOCGETP */
extern int ioctl();
#endif /* unix */
X
#ifdef vms
#include <descrip.h>
#include <ttdef.h>
#include <iodef.h>
#include unixio
X
static int setbuff[2]; /* buffer to set terminal attributes */
static short chan = -1; /* channel to terminal */
struct dsc$descriptor_s descrip; /* VMS descriptor */
#endif
X
static void
gl_char_init()
/* turn off input echo */
{
#ifdef unix
#ifdef TIOCGETP
X ioctl(0, TIOCGETP, &old_tty);
X tty = old_tty;
X tty.sg_flags |= CBREAK;
X tty.sg_flags &= ~ECHO;
X ioctl(0, TIOCSETP, &tty);
#else
X ioctl(0, TCGETA, &old_tty);
X tty = old_tty;
X tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
X tty.c_cc[VMIN] = 1;
X tty.c_cc[VTIME] = 0;
X ioctl(0, TCSETA, &tty);
#endif
#endif /* unix */
#ifdef vms
X descrip.dsc$w_length = strlen("tt:");
X descrip.dsc$b_dtype = DSC$K_DTYPE_T;
X descrip.dsc$b_class = DSC$K_CLASS_S;
X descrip.dsc$a_pointer = "tt:";
X (void)sys$assign(&descrip,&chan,0,0);
X (void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0);
X setbuff[1] |= TT$M_NOECHO;
X (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
#endif /* vms */
}
X
static void
gl_char_cleanup()
/* undo effects of gl_char_init, as necessary */
{
#ifdef unix
#ifdef TIOCSETP
X ioctl(0, TIOCSETP, &old_tty);
#else
X ioctl(0, TCSETA, &old_tty);
#endif
#endif /* unix */
X
#ifdef vms
X setbuff[1] &= ~TT$M_NOECHO;
X (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
X sys$dassgn(chan);
X chan = -1;
#endif
}
X
static int
gl_getc()
/* get a character without echoing it to screen */
{
X int c;
X char ch;
X
#ifdef unix
X c = (read(0, &ch, 1) > 0)? ch : -1;
#endif
#ifdef MSDOS
X c = _bios_keybrd(_NKEYBRD_READ);
X if ((c & 0377) == 224) {
X switch (c = (c >> 8) & 0377) {
X case 72: c = 16; /* up -> ^P */
X break;
X case 80: c = 14; /* down -> ^N */
X break;
X case 75: c = 2; /* left -> ^B */
X break;
X case 77: c = 6; /* right -> ^F */
X break;
X default: c = 254; /* make it garbage */
X }
X } else {
X c = c & 0377;
X }
#endif
#ifdef vms
X if(chan < 0) {
X c='\0';
X }
X (void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0);
X c &= 0177; /* get a char */
#endif
X return c;
}
X
static void
gl_putc(int c)
{
X char ch = c;
X
X write(1, &ch, 1);
}
X
/******************** fairly portable part *********************************/
X
static void
gl_gets(char *buf, int size) /* slow, only used in batch mode */
{
X char *p = buf;
X int c;
X
X size -= 1;
X while (buf + size > p && (c = gl_getc()) > 0) {
X *p++ = c;
X if (c == '\n')
X break;
X }
X *p = 0;
}
X
static void
gl_puts(char *buf)
{
X while (*buf)
X gl_putc(*buf++);
}
X
void
gl_init(int scrn_wdth)
/* set up variables and terminal */
{
X gl_screen = scrn_wdth;
X if (gl_init_done == 0) {
X hist_init();
X if (isatty(0)) {
X gl_char_init();
X gl_init_done = -1; /* -1 means terminal */
X } else {
X gl_init_done = 1; /* 1 means batch */
X }
X }
X gl_pos = gl_cnt = 0;
}
X
void
gl_cleanup()
/* undo effects of gl_init, as necessary */
{
X if (gl_init_done == -1)
X gl_char_cleanup();
X gl_init_done = 0;
}
X
char *
getline(char *prompt)
{
X int c, loc, tmp;
X
X if (!gl_init_done)
X gl_init(80);
X gl_buf[0] = 0; /* used as end of input indicator */
X if (gl_init_done == 1) { /* no input editing, and no prompt output */
X gl_gets(gl_buf, BUF_SIZE);
X return gl_buf;
X }
X gl_fixup(-1, 0); /* this resets gl_fixup */
X gl_width = gl_screen - strlen(prompt);
X if (prompt == 0)
X prompt = "";
X gl_prompt = prompt;
X gl_pos = gl_cnt = 0;
X gl_puts(prompt);
X if (gl_in_hook) {
X loc = gl_in_hook(gl_buf);
X if (loc >= 0)
X gl_fixup(0, BUF_SIZE);
X }
X while ((c = gl_getc()) >= 0) {
X gl_extent = 0;
X if (isprint(c)) {
X gl_addchar(c);
X } else {
X switch (c) {
X case '\n': case '\r': /* newline */
X gl_newline();
X return gl_buf;
X break;
X case '\001': gl_fixup(-1, 0); /* ^A */
X break;
X case '\002': gl_fixup(-1, gl_pos-1); /* ^B */
X break;
X case '\004': /* ^D */
X if (gl_cnt == 0) {
X gl_buf[0] = 0;
X gl_cleanup();
X gl_putc('\n');
X return gl_buf;
X } else {
X gl_del(0);
X }
X break;
X case '\005': gl_fixup(-1, gl_cnt); /* ^E */
X break;
X case '\006': gl_fixup(-1, gl_pos+1); /* ^F */
X break;
X case '\007': gl_replace(); /* ^G */
X break;
X case '\010': case '\177': gl_del(-1); /* ^H and DEL */
X break;
X case '\t': /* TAB */
X if (gl_tab_hook) {
X tmp = gl_pos;
X loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp);
X if (loc >= 0 || tmp != gl_pos)
X gl_fixup(loc, tmp);
X }
X break;
X case '\013': gl_kill(); /* ^K */
X break;
X case '\014': gl_redraw(); /* ^L */
X break;
X case '\016': hist_next(); /* ^N */
X break;
X case '\020': hist_prev(); /* ^P */
X break;
X case '\024': gl_transpose(); /* ^T */
X break;
X case '\033': /* ansi arrow keys */
X c = gl_getc();
X if (c == '[') {
X switch(c = gl_getc()) {
X case 'A': hist_prev(); /* up */
X break;
X case 'B': hist_next(); /* down */
X break;
X case 'C': gl_fixup(-1, gl_pos+1); /* right */
X break;
X case 'D': gl_fixup(-1, gl_pos-1); /* left */
X break;
X default: gl_putc('\007'); /* who knows */
X break;
X }
X } else
X gl_putc('\007');
X break;
X default:
X gl_putc('\007');
X break;
X }
X }
X }
X gl_cleanup();
X return gl_buf;
}
X
static void
gl_addchar(int c)
/* adds the character c to the input buffer at current location */
{
X int i;
X
X if (gl_cnt >= BUF_SIZE - 1) {
X gl_puts("getline: input buffer overflow\n");
X _exit(1);
X }
X if (gl_overwrite == 0 || gl_pos == gl_cnt) {
X for (i=gl_cnt; i >= gl_pos; i--)
X gl_buf[i+1] = gl_buf[i];
X gl_buf[gl_pos] = c;
X gl_fixup(gl_pos, gl_pos+1);
X } else {
X gl_buf[gl_pos] = c;
X gl_extent = 1;
X gl_fixup(gl_pos, gl_pos+1);
X }
}
X
static void
gl_transpose(void)
/* switch character under cursor and to left of cursor */
{
X int c;
X
X if (gl_pos > 0 && gl_cnt > gl_pos) {
X c = gl_buf[gl_pos-1];
X gl_buf[gl_pos-1] = gl_buf[gl_pos];
X gl_buf[gl_pos] = c;
X gl_extent = 2;
X gl_fixup(gl_pos-1, gl_pos);
X } else
X gl_putc('\007');
}
X
void
gl_replace()
{
X gl_overwrite = !gl_overwrite;
}
X
static void
gl_newline()
/*
X * Cleans up entire line before returning to caller. A \n is appended.
X * If line longer than screen, we redraw starting at beginning
X */
{
X int change = gl_cnt;
X int len = gl_cnt;
X int loc = gl_width - 5; /* shifts line back to start position */
X
X if (gl_cnt >= BUF_SIZE - 1) {
X gl_puts("getline: input buffer overflow\n");
X _exit(1);
X }
X hist_add(); /* only adds if nonblank */
X if (gl_out_hook) {
X change = gl_out_hook(gl_buf);
X len = strlen(gl_buf);
X }
X if (loc > len)
X loc = len;
X gl_fixup(change, loc); /* must do this before appending \n */
X gl_buf[len] = '\n';
X gl_buf[len+1] = '\0';
X gl_putc('\n');
}
X
static void
gl_del(int loc)
/*
X * Delete a character. The loc variable can be:
X * -1 : delete character to left of cursor
X * 0 : delete character under cursor
X */
{
X int i;
X
X if (loc == -1 && gl_pos > 0 || loc == 0 && gl_pos < gl_cnt) {
X for (i=gl_pos+loc; i < gl_cnt; i++)
X gl_buf[i] = gl_buf[i+1];
X gl_fixup(gl_pos+loc, gl_pos+loc);
X } else
X gl_putc('\007');
}
X
static void
gl_kill()
/* delete from current position to the end of line */
{
X if (gl_pos < gl_cnt) {
X gl_buf[gl_pos] = '\0';
X gl_fixup(gl_pos, gl_pos);
X } else
X gl_putc('\007');
}
X
void
gl_redraw()
/* emit a newline, reset and redraw prompt and current input line */
{
X if (gl_init_done == -1) {
X gl_putc('\n');
X gl_puts(gl_prompt);
X gl_pos = 0;
X gl_fixup(0, BUF_SIZE);
X }
}
X
static void
gl_fixup(int change, int cursor)
/*
X * This function is used both for redrawing when input changes or for
X * moving within the input line. The parameters are:
X * change : the index of the start of changes in the input buffer,
X * with -1 indicating no changes.
X * cursor : the desired location of the cursor after the call.
X * A value of BUF_SIZE can be used to indicate the cursor should
X * move just past the end of the input line.
X */
{
X static int gl_shift; /* index of first on screen character */
X static int off_right; /* true if more text right of screen */
X static int off_left; /* true if more text left of screen */
X int left = 0, right = -1; /* bounds for redraw */
X int pad; /* how much to erase at end of line */
X int backup; /* how far to backup before fixing */
X int new_shift; /* value of shift based on cursor */
X int extra; /* adjusts when shift (scroll) happens */
X int i;
X int new_right; /* alternate right bound, using gl_extent */
X
X if (change == -1 && cursor == 0 && gl_buf[0] == 0) { /* reset */
X gl_shift = off_right = off_left = 0;
X return;
X }
X pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */
X backup = gl_pos - gl_shift;
X if (change >= 0) {
X gl_cnt = strlen(gl_buf);
X if (change > gl_cnt)
X change = gl_cnt;
X }
X if (cursor > gl_cnt) {
X if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
X gl_putc('\007');
X cursor = gl_cnt;
X }
X if (cursor < 0) {
X gl_putc('\007');
X cursor = 0;
X }
X if (off_right || off_left && cursor < gl_shift + gl_width - SCROLL / 2)
X extra = 2; /* shift the scrolling boundary */
X else
X extra = 0;
X new_shift = cursor + extra + SCROLL - gl_width;
X if (new_shift > 0) {
X new_shift /= SCROLL;
X new_shift *= SCROLL;
X } else
X new_shift = 0;
X if (new_shift != gl_shift) { /* scroll occurs */
X gl_shift = new_shift;
X off_left = (gl_shift)? 1 : 0;
X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
X left = gl_shift;
X new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
X } else if (change >= 0) { /* no scroll, but text changed */
X if (change < gl_shift + off_left) {
X left = gl_shift;
X } else {
X left = change;
X backup = gl_pos - change;
X }
X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
X right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
X new_right = (gl_extent && (right > left + gl_extent))?
X left + gl_extent : right;
X }
X pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
X pad = (pad < 0)? 0 : pad;
X if (left <= right) { /* clean up screen */
X for (i=0; i < backup; i++)
X gl_putc('\b');
X if (left == gl_shift && off_left) {
X gl_putc('$');
X left++;
X }
X for (i=left; i < new_right; i++)
X gl_putc(gl_buf[i]);
X gl_pos = new_right;
X if (off_right && new_right == right) {
X gl_putc('$');
X gl_pos++;
X } else {
X for (i=0; i < pad; i++) /* erase remains of prev line */
X gl_putc(' ');
X gl_pos += pad;
X }
X }
X i = gl_pos - cursor; /* move to final cursor location */
X if (i > 0) {
X while (i--)
X gl_putc('\b');
X } else {
X for (i=gl_pos; i < cursor; i++)
X gl_putc(gl_buf[i]);
X }
X gl_pos = cursor;
}
X
static int
gl_tab(char *buf, int offset, int *loc)
/* default tab handler, acts like tabstops every 8 cols */
{
X int i, count, len;
X
X len = strlen(buf);
X count = 8 - (offset + *loc) % 8;
X for (i=len; i >= *loc; i--)
X buf[i+count] = buf[i];
X for (i=0; i < count; i++)
X buf[*loc+i] = ' ';
X i = *loc;
X *loc = i + count;
X return i;
}
X
/******************* History stuff **************************************/
X
#ifndef HIST_SIZE
#define HIST_SIZE 100
#endif
X
int hist_pos, hist_last;
char *hist_buf[HIST_SIZE];
X
static void
hist_init()
{
X int i;
X
X for (i=0; i < HIST_SIZE; i++)
X hist_buf[i] = (char *)0;
}
X
static void
hist_add()
{
X char *p = gl_buf;
X
X while (*p == ' ' || *p == '\t') /* only save nonblank line */
X p++;
X if (*p) {
X hist_buf[hist_last] = hist_save(gl_buf);
X hist_last = (hist_last + 1) % HIST_SIZE;
X if (hist_buf[hist_last]) { /* erase next location */
X free(hist_buf[hist_last]);
X hist_buf[hist_last] = 0;
X }
X }
X hist_pos = hist_last;
}
X
static void
hist_prev()
/* loads previous hist entry into input buffer, sticks on first */
{
X int next;
X
X next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
X if (next != hist_last) {
X if (hist_buf[next]) {
X hist_pos = next;
X strcpy(gl_buf, hist_buf[hist_pos]);
X } else
X gl_putc('\007');
X } else
X gl_putc('\007');
X if (gl_in_hook)
X gl_in_hook(gl_buf);
X gl_fixup(0, BUF_SIZE);
}
X
static void
hist_next()
/* loads next hist entry into input buffer, clears on last */
{
X if (hist_pos != hist_last) {
X hist_pos = (hist_pos + 1) % HIST_SIZE;
X if (hist_buf[hist_pos]) {
X strcpy(gl_buf, hist_buf[hist_pos]);
X } else {
X gl_buf[0] = 0;
X }
X } else
X gl_putc('\007');
X if (gl_in_hook)
X gl_in_hook(gl_buf);
X gl_fixup(0, BUF_SIZE);
}
X
static char *
hist_save(char *p)
/* makes a copy of the string */
{
X char *s = 0;
X
X if (p && ((s = malloc(strlen(p)+1)) != 0)) {
X strcpy(s, p);
X }
X return s;
}
SHAR_EOF
chmod 0644 getline.c ||
echo 'restore of getline.c failed'
Wc_c="`wc -c < 'getline.c'`"
test 20798 -eq "$Wc_c" ||
echo 'getline.c: original size 20798, current size' "$Wc_c"
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.