*************************** Motivation **********************************

Many interactive programs read input line by line, but would like to
provide line editing and history functionality to the end-user that 
runs the program.

The input-edit package provides that functionality.  As far as the 
programmer is concerned, the program only asks for the next line
of input. However, until the user presses the RETURN key they can use
emacs-style line editing commands and can traverse the history of lines
previously typed.

Other packages, such as GNU's readline, have greater capability but are
also substantially larger.  Input-edit is small, since it uses neither
stdio nor any termcap features, and is also quite portable.  It only uses
\b to backspace and \007 to ring the bell on errors.  Since it cannot
edit multiple lines it scrolls long lines left and right on the same line.

Input edit uses classic (not ANSI) C, and should run on any Unix 
system (BSD, SYSV or POSIX), PC's under DOS with MSC, TurboC or djgpp,  
PC's under OS/2 with gcc (EMX), or Vax/VMS.  Porting the package to new 
systems basicaly requires code to read a character when it is typed without 
echoing it, everything else should be OK.

I have run the package on:

	DECstation 5000, Ultrix 4.3 with cc 2.1 and gcc 2.3.3
	Sun Sparc 2, SunOS 4.1.1, with cc
	SGI Iris, IRIX System V.3, with cc
	PC using DOS with MSC

The description below is broken into two parts, the end-user (editing) 
interface and the programmer interface.  Send bug reports, fixes and 
enhancements to:

Chris Thewalt (thewalt@ce.berkeley.edu)   
5/3/93

Thanks to the following people who have provided enhancements and fixes:
  Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
  DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
  Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler

PS: I don't have, and don't want to add, a vi mode, sorry.

This version is with modifications by R Core, including a Windows port, support
for multi-byte characters and partial support for Unicode sequences.

************************** End-User Interface ***************************

Entering printable keys generally inserts new text into the buffer (unless
in overwrite mode, see below).  Other special keys can be used to modify
the text in the buffer.  In the description of the keys below, ^n means
Control-n, or holding the CONTROL key down while pressing "n".  Errors
will ring the terminal bell.

^A/^E	: Move cursor to beginning/end of the line.
^F/^B   : Move cursor forward/backward one character.
ESC-F	: Move cursor forward one word.
ESC-B   : Move cursor backward one word.
^D	: Delete the character under the cursor.
^H, DEL : Delete the character to the left of the cursor.
^K	: Kill from the cursor to the end of line.
^L	: Redraw current line (after a line feed).
^O	: Toggle overwrite/insert mode. Initially in insert mode. Text
	  added in overwrite mode (including yanks) overwrite
	  existing text, while insert mode does not overwrite.
^P/^N   : Move to previous/next item on history list.
^R/^S   : Perform incremental reverse/forward search for string on
	  the history list.  Typing normal characters adds to the current
	  search string and searches for a match. Typing ^R/^S marks
	  the start of a new search, and moves on to the next match.
	  Typing ^H or DEL deletes the last character from the search 
	  string, and searches from the starting location of the last search.  
	  Therefore, repeated DEL's appear to unwind to the match nearest 
	  the point at which the last ^R or ^S was typed.  If DEL is 
	  repeated until the search string is empty the search location 
	  begins from the start of the history list.  Typing ESC or 
	  any other editing character accepts the current match and 
	  loads it into the buffer, terminating the search.
^T	: Toggle the characters under and to the left of the cursor.
^U      : Deletes the entire line
^Y	: Yank previously killed text back at current location.  Note that
	  this will overwrite or insert, depending on the current mode.
TAB	: By default adds spaces to buffer to get to next TAB stop 
	  (just after every 8th column), although this may be rebound by the 
	  programmer, as described below.
NL, CR  : returns current buffer to the program.

DOS and ANSI terminal arrow key sequences are recognized, and act like:

  up    : same as ^P
  down  : same as ^N
  left  : same as ^B
  right : same as ^F

Debugging of keyboard input on Windows:

  Alt+I : Toggle debug mode.

Entering characters by code:

  Alt+ xxx           : hold Alt, type up to 3 digits, release Alt
                       produces byte (0-255) in the current OEM code page
                       
  Alt+ +xxxxxxxx     : hold Alt, press + on numpad, type up to 8 digits and hex
                       letters; produces Unicode character of the given number

  Note: Windows automatically interprets Alt+xxx when "xxx" are digits on the
  numpad when NumLock is on. It is therefore advisable to have NumLock off to
  avoid interference with the Windows processing, and it is necessary for
  entering the hex codes on the numpad. A similar interference would exist when
  Windows support for Alt+ +xxxx (hex codes) are enabled. Note that R/getline
  support even Unicode supplementary characters.

************************** Programmer Interface ***************************

The programmer accesses input-edit through these functions, and optionally
through three additional function pointer hooks.  The four functions are:

int getline(char *prompt, char *buf, int buflen)

	Prints the prompt and allows the user to edit the current line.  A
        pointer to a buffer to store the line is passed in "buf" with the
        length of "buflen".  The user finishes exiting by typing a newline
        or a return.  The buffer contains the newline character.  The user
        enters an end-of-file by typing ^D on an empty line, in which case
        the first character of the returned buffer is '\0'.  The getline
        functions sets terminal modes needed to make it work, and resets
        them before returning to the caller.  The getline function also
        looks for characters that would generate a signal, and resets the
        terminal modes before raising the signal condition.  If the signal
        handler returns to getline, the screen is automatically redrawn and
        editing can continue.  Getline now requires both the input and
        output stream be connected to the terminal (not redirected) so the
        main program should check to make sure this is true.  If input or
        output have been redirected the main program should use buffered IO
        (stdio) rather than the slow 1 character read()s that getline uses. 
        Returns non-zero on EOF.

void gl_setwidth(int width)

        Set the width of the terminal to the specified width. The default
	width is 80 characters, so this function need only be called if the
	width of the terminal is not 80.  Since horizontal scrolling is
	controlled by this parameter it is important to get it right.

void gl_histadd(const char *buf)

	The gl_histadd function checks to see if the buf is not empty or
	whitespace, and also checks to make sure it is different than
	the last saved buffer to avoid repeats on the history list.
	If the buf is a new non-blank string a copy is made and saved on
	the history list, so the caller can re-use the specified buf.

void gl_strwidth(size_t (*func)())
	The gl_strwidth function allows the caller to supply a pointer to 
	a prompt width calculation function (the default one does not support
        escape sequences). This allows the caller to embed escape sequences
        in the prompt and then tell getline how many screen spaces the prompt
        will take up. The width returned needs to be in screen positions, so it
        needs to take the print width of Unicode characters into account.

The main loop in testgl.c, included in this directory, shows how the
input-edit package can be used (this is for the original version of getline
only, not updated for the updated R version):

extern char *getline();
extern void  gl_histadd();
main()
{
    char *p;
    do {
	p = getline("PROMPT>>>> ");
	gl_histadd(p);
	fputs(p, stdout);
    } while (*p != 0);
}

In order to allow the main program to have additional access to the buffer,
to implement things such as completion or auto-indent modes, three
function pointers can be bound to user functions to modify the buffer as
described below.  By default gl_in_hook and gl_out_hook are set to NULL,
and gl_tab_hook is bound to a function that inserts spaces until the next
logical tab stop is reached.  The user can reassign any of these pointers
to other functions.  Each of the functions bound to these hooks receives
the current buffer as the first argument, and must return the location of
the leftmost change made in the buffer.  If the buffer isn't modified the
functions should return -1.  When the hook function returns the screen is
updated to reflect any changes made by the user function.

int (*gl_in_hook)(char *buf)

	If gl_in_hook is non-NULL the function is called each time a new 
	buffer is loaded. It is called when getline is entered, with an
	empty buffer, it is called each time a new buffer is loaded from
	the history with ^P or ^N, and it is called when an incremental
	search string is accepted (when the search is terminated). The
	buffer can be modified and will be redrawn upon return to getline(). 

int (*gl_out_hook)(char *buf)

	If gl_out_hook is non-NULL it is called when a line has been
	completed by the user entering a newline or return. The buffer
	handed to the hook does not yet have the newline appended. If the
	buffer is modified the screen is redrawn before getline returns the
	buffer to the caller.

int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)

	If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
	In addition to receiving the buffer, the current prompt width is
	given (in screen positions, so taking the print width of Unicode
        characters in account) needed to do tabbing right) and a pointer to
        the cursor offset is given, where a 0 offset means the first character
        in the line.  Not only does the cursor_loc tell the programmer where
        the TAB was received, but it can be reset so that the cursor will end
	up at the specified location after the screen is redrawn.

