Index: 0.35/Modules/Setup.dist
*** 0.35/Modules/Setup.dist Mon, 15 Jan 2001 22:14:59 -0500 nas (python/R/10_Setup.dist 1.5 644)
--- 0.35(w)/Modules/Setup.dist Tue, 16 Jan 2001 00:03:28 -0500 nas (python/R/10_Setup.dist 1.5 644)
***************
*** 113,118 ****
--- 113,123 ----
  
  #*shared*
  
+ # edline library.  Provides command line editing like GNU readline but is
+ # much simpler.  This module should work on any modern Unix-like system
+ # that provides termios.
+ #readline edlinemodule.c edline.c
+ 
  # GNU readline.  Unlike previous Python incarnations, GNU readline is
  # now incorporated in an optional module, configured in the Setup file
  # instead of by a configure script switch.  You may have to insert a
Index: 0.35/Modules/edline.c
*** 0.35/Modules/edline.c Tue, 16 Jan 2001 00:22:52 -0500 nas ()
--- 0.35(w)/Modules/edline.c Mon, 15 Jan 2001 23:46:07 -0500 nas (python/S/22_edline.c  644)
***************
*** 0 ****
--- 1,961 ----
+ /*
+ 
+    This library contains code from editline.  editline was released to the
+    comp.sources.misc newsgroup with the following copyright:
+    
+      Copyright 1992 Simmule Turner and Rich Salz.  All rights reserved.
+ 
+      This software is not subject to any license of the American Telephone
+      and Telegraph Company or of the Regents of the University of California.
+ 
+      Permission is granted to anyone to use this software for any purpose on
+      any computer system, and to alter it and redistribute it freely, subject
+      to the following restrictions:
+      1. The authors are not responsible for the consequences of use of this
+      software, no matter how awful, even if they arise from flaws in it.
+      2. The origin of this software must not be misrepresented, either by
+      explicit claim or by omission.  Since few users ever read sources,
+      credits must appear in the documentation.
+      3. Altered versions must be plainly marked as such, and must not be
+      misrepresented as being the original software.  Since few users ever
+      read sources, credits must appear in the documentation.
+      4. This notice may not be removed or altered.
+ 
+  */
+ 
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <sys/types.h>
+ #include <ctype.h>
+ #include <string.h>
+ 
+ #include <termios.h>
+ #ifndef TIOCGWINSZ
+ #include <sys/ioctl.h> /* needed for 4.3+BSD */
+ #endif
+ 
+ #include "edline.h"
+ 
+ #define SCREEN_WIDTH	80
+ #define SCREEN_ROWS	24
+ #define DEL		127
+ #define CTL(x)		((x) & 0x1F)
+ #define ISCTL(x)	((x) && (x) < ' ')
+ #define UNCTL(x)	((x) + 64)
+ #define META(x)		((x) | 0x80)
+ #define ISMETA(x)	((x) & 0x80)
+ #define UNMETA(x)	((x) & 0x7F)
+ #define NEWLINE		"\r\n"
+ 
+ #ifndef HIST_SIZE
+ #define HIST_SIZE	80
+ #endif
+ 
+ /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
+ #define COOK_META_CHARS
+ 
+ /* Support VT-100 arrow keys. */
+ #define USE_ANSI_ARROWS
+ 
+ #define MEM_INC		64
+ #define SCREEN_INC	256
+ 
+ 
+ /* Command status codes. */
+ typedef enum _status {
+ 	CSdone, CSeof, CSmove, CSdispatch, CSstay
+ } status;
+ 
+ 
+ /* key to command mapping. */
+ typedef struct _keymap {
+ 	char key;
+ 	status (*function)();
+ } keymap;
+ 
+ /* Command history structure. */
+ typedef struct _history {
+ 	int size;
+ 	int	pos;
+ 	char *lines[HIST_SIZE];
+ } history;
+ 
+ /* Globals. */
+ static int Eof;
+ static int Erase;
+ static int Intr;
+ static int Kill;
+ 
+ static const char	*Input = "";
+ static char		*Line;
+ static const char	*Prompt;
+ static char		*Yanked;
+ static char		*Screen;
+ static history		Hist;
+ int			Quit;
+ static int		End;
+ static int		OldPoint;
+ static int		Point;
+ static int		PushBack;
+ static int		Pushed;
+ static size_t		Length;
+ static size_t		ScreenCount;
+ static size_t		ScreenSize;
+ static char		*Backspace;
+ static int		TTYwidth;
+ static int		TTYrows;
+ 
+ /* forward declarations */
+ static keymap		Map[32];
+ static keymap		MetaMap[8];
+ static char *editinput(void);
+ 
+ 
+ /* TTY functions. */
+ 
+ static void
+ TTYset(int reset)
+ {
+ 	static struct termios	old;
+ 	struct termios		new;
+ 
+ 	if (reset == 0) {
+ 		(void)tcgetattr(0, &old);
+ 		Erase = old.c_cc[VERASE];
+ 		Kill = old.c_cc[VKILL];
+ 		Eof = old.c_cc[VEOF];
+ 		Intr = old.c_cc[VINTR];
+ 		Quit = old.c_cc[VQUIT];
+ 
+ 		new = old;
+ 		new.c_cc[VINTR] = -1;
+ 		new.c_cc[VQUIT] = -1;
+ 		new.c_lflag &= ~(ECHO | ICANON);
+ 		new.c_iflag &= ~(ISTRIP | INPCK);
+ 		new.c_cc[VMIN] = 1;
+ 		new.c_cc[VTIME] = 0;
+ 		(void)tcsetattr(0, TCSANOW, &new);
+ 	}
+ 	else
+ 		(void)tcsetattr(0, TCSANOW, &old);
+ }
+ 
+ 
+ static void
+ TTYflush(void)
+ {
+ 	if (ScreenCount) {
+ 		(void)write(1, Screen, ScreenCount);
+ 		ScreenCount = 0;
+ 	}
+ }
+ 
+ static void
+ TTYput(char c)
+ {
+ 	Screen[ScreenCount] = c;
+ 	if (++ScreenCount >= ScreenSize - 1) {
+ 		ScreenSize += SCREEN_INC;
+ 		Screen = realloc(Screen, ScreenSize);
+ 	}
+ }
+ 
+ static void
+ TTYputs(const char *p)
+ {
+ 	while (*p)
+ 		TTYput(*p++);
+ }
+ 
+ static void
+ TTYshow(char c)
+ {
+ 	if (c == DEL) {
+ 		TTYput('^');
+ 		TTYput('?');
+ 	}
+ 	else if (ISCTL(c)) {
+ 		TTYput('^');
+ 		TTYput(UNCTL(c));
+ 	}
+ #ifdef COOK_META_CHARS
+ 	else if (ISMETA(c)) {
+ 		TTYput('M');
+ 		TTYput('-');
+ 		TTYput(UNMETA(c));
+ 	}
+ #endif
+ 	else
+ 		TTYput(c);
+ }
+ 
+ static void
+ TTYstring(char	*p)
+ {
+ 	while (*p)
+ 		TTYshow(*p++);
+ }
+ 
+ static unsigned int
+ TTYget(void)
+ {
+ 	char c;
+ 
+ 	TTYflush();
+ 	if (Pushed) {
+ 		Pushed = 0;
+ 		return PushBack;
+ 	}
+ 	if (*Input)
+ 		return *Input++;
+ 	return read(0, &c, 1) == 1 ? c : EOF;
+ }
+ 
+ #define TTYback() (Backspace ? TTYputs(Backspace) : TTYput('\b'))
+ 
+ static void
+ TTYbackn(int n)
+ {
+ 	while (--n >= 0)
+ 		TTYback();
+ }
+ 
+ static void
+ TTYinfo(void)
+ {
+ 	static int	init;
+ 	struct winsize	W;
+ 
+ 	if (init) {
+ 		/* Perhaps we got resized. */
+ 		if (ioctl(0, TIOCGWINSZ, &W) >= 0
+ 				&& W.ws_col > 0 && W.ws_row > 0) {
+ 			TTYwidth = (int)W.ws_col;
+ 			TTYrows = (int)W.ws_row;
+ 		}
+ 		return;
+ 	}
+ 	init++;
+ 
+ 	TTYwidth = TTYrows = 0;
+ 
+ 	if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
+ 		TTYwidth = (int)W.ws_col;
+ 		TTYrows = (int)W.ws_row;
+ 	}
+ 
+ 	if (TTYwidth <= 0 || TTYrows <= 0) {
+ 		TTYwidth = SCREEN_WIDTH;
+ 		TTYrows = SCREEN_ROWS;
+ 	}
+ }
+ 
+ static void
+ reposition(void)
+ {
+ 	int i;
+ 	char *p;
+ 
+ 	TTYput('\r');
+ 	TTYputs(Prompt);
+ 	for (i = Point, p = Line; --i >= 0; p++)
+ 		TTYshow(*p);
+ }
+ 
+ static void
+ left(status change)
+ {
+ 	TTYback();
+ 	if (Point) {
+ 		if (ISCTL(Line[Point - 1]))
+ 			TTYback();
+ #ifdef COOK_META_CHARS
+ 		else if (ISMETA(Line[Point - 1])) {
+ 			TTYback();
+ 			TTYback();
+ 		}
+ #endif
+ 	}
+ 	if (change == CSmove)
+ 		Point--;
+ }
+ 
+ static void
+ right(status change)
+ {
+ 	TTYshow(Line[Point]);
+ 	if (change == CSmove)
+ 		Point++;
+ }
+ 
+ static status
+ ring_bell(void)
+ {
+ 	TTYput('\07');
+ 	TTYflush();
+ 	return CSstay;
+ }
+ 
+ static status
+ do_forward(status move)
+ {
+ 	char *p;
+ 
+ 	p = &Line[Point];
+ 	for ( ; Point < End && (*p == ' ' || !isalnum(*p));
+ 			Point++, p++)
+ 		if (move == CSmove)
+ 			right(CSstay);
+ 
+ 	for (; Point < End && isalnum(*p); Point++, p++)
+ 		if (move == CSmove)
+ 			right(CSstay);
+ 
+ 	return CSstay;
+ }
+ 
+ static void
+ ceol(void)
+ {
+ 	int extras;
+ 	int i;
+ 	char *p;
+ 
+ 	for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
+ 		TTYput(' ');
+ 		if (ISCTL(*p)) {
+ 			TTYput(' ');
+ 			extras++;
+ 		}
+ #ifdef COOK_META_CHARS
+ 		else if (ISMETA(*p)) {
+ 			TTYput(' ');
+ 			TTYput(' ');
+ 			extras += 2;
+ 		}
+ #endif
+ 	}
+ 
+ 	for (i += extras; i > Point; i--)
+ 		TTYback();
+ }
+ 
+ static void
+ clear_line(void)
+ {
+ 	Point = -strlen(Prompt);
+ 	TTYput('\r');
+ 	ceol();
+ 	Point = 0;
+ 	End = 0;
+ 	Line[0] = '\0';
+ }
+ 
+ static status
+ insert_string(char *p)
+ {
+ 	size_t len;
+ 	int i;
+ 	char *new;
+ 	char *q;
+ 
+ 	len = strlen((char *)p);
+ 	if (End + len >= Length) {
+ 		new = malloc(Length + len + MEM_INC);
+ 		if (new == NULL)
+ 			return CSstay;
+ 		if (Length) {
+ 			memcpy(new, Line, Length);
+ 			free(Line);
+ 		}
+ 		Line = new;
+ 		Length += len + MEM_INC;
+ 	}
+ 
+ 	for (q = &Line[Point], i = End - Point; --i >= 0; )
+ 		q[len + i] = q[i];
+ 	memcpy(&Line[Point], p, len);
+ 	End += len;
+ 	Line[End] = '\0';
+ 	TTYstring(&Line[Point]);
+ 	Point += len;
+ 
+ 	return Point == End ? CSstay : CSmove;
+ }
+ 
+ static char *
+ next_hist(void)
+ {
+ 	if (Hist.pos >= Hist.size - 1)
+ 		return NULL;
+ 	else
+ 		return Hist.lines[++Hist.pos];
+ }
+ 
+ static char *
+ prev_hist(void)
+ {
+ 	if (Hist.pos == 0)
+ 		return NULL;
+ 	else
+ 		return Hist.lines[--Hist.pos];
+ }
+ 
+ static status
+ do_insert_hist(char *p)
+ {
+ 	if (p == NULL)
+ 		return ring_bell();
+ 	Point = 0;
+ 	reposition();
+ 	ceol();
+ 	End = 0;
+ 	return insert_string(p);
+ }
+ 
+ static status
+ do_hist(char *(*move)())
+ {
+ 	char *p;
+ 
+ 	if ((p = (*move)()) == NULL)
+ 		return ring_bell();
+ 	return do_insert_hist(p);
+ }
+ 
+ static status
+ h_next(void)
+ {
+ 	return do_hist(next_hist);
+ }
+ 
+ static status
+ h_prev(void)
+ {
+ 	return do_hist(prev_hist);
+ }
+ 
+ static status
+ h_first(void)
+ {
+ 	return do_insert_hist(Hist.lines[Hist.pos = 0]);
+ }
+ 
+ static status
+ h_last(void)
+ {
+ 	return do_insert_hist(Hist.lines[Hist.pos = Hist.size - 1]);
+ }
+ 
+ /* Return zero if pat appears as a substring in text. */
+ static int
+ substrcmp(char *text, char *pat, int len)
+ {
+ 	char c;
+ 
+ 	if ((c = *pat) == '\0')
+ 		return *text == '\0';
+ 	for ( ; *text; text++)
+ 		if (*text == c && strncmp(text, pat, len) == 0)
+ 			return 0;
+ 	return 1;
+ }
+ 
+ #ifndef HAVE_STRDUP
+ char *
+ strdup(const char *p)
+ {
+ 	char *new;
+ 	if ((new = malloc(strlen(p) + 1)) != NULL)
+ 		(void)strcpy(new, p);
+ 	return new;
+ }
+ #endif
+ 
+ static char *
+ search_hist(char *search, char *(*move)())
+ {
+ 	static char *old_search;
+ 	int		len;
+ 	int		pos;
+ 	int		(*match)();
+ 	char	*pat;
+ 
+ 	/* Save or get remembered search pattern. */
+ 	if (search && *search) {
+ 		if (old_search)
+ 			free(old_search);
+ 		old_search = strdup(search);
+ 	}
+ 	else {
+ 		if (old_search == NULL || *old_search == '\0')
+ 			return NULL;
+ 		search = old_search;
+ 	}
+ 
+ 	/* Set up pattern-finder. */
+ 	if (*search == '^') {
+ 		match = strncmp;
+ 		pat = (char *)(search + 1);
+ 	}
+ 	else {
+ 		match = substrcmp;
+ 		pat = (char *)search;
+ 	}
+ 	len = strlen(pat);
+ 
+ 	for (pos = Hist.pos; (*move)() != NULL; )
+ 		if ((*match)((char *)Hist.lines[Hist.pos], pat, len) == 0)
+ 			return Hist.lines[Hist.pos];
+ 	Hist.pos = pos;
+ 	return NULL;
+ }
+ 
+ static status
+ h_search(void)
+ {
+ 	static int searching;
+ 	const char *old_prompt;
+ 	char *p;
+ 
+ 	if (searching)
+ 		return ring_bell();
+ 	searching = 1;
+ 
+ 	clear_line();
+ 	old_prompt = Prompt;
+ 	Prompt = "Search: ";
+ 	TTYputs(Prompt);
+ 	p = search_hist(editinput(), prev_hist);
+ 	clear_line();
+ 	Prompt = old_prompt;
+ 	TTYputs(Prompt);
+ 
+ 	searching = 0;
+ 	return do_insert_hist(p);
+ }
+ 
+ static status
+ fd_char(void)
+ {
+ 	right(CSmove);
+ 	return CSstay;
+ }
+ 
+ static void
+ save_yank(int begin, int i)
+ {
+ 	if (Yanked) {
+ 		free(Yanked);
+ 		Yanked = NULL;
+ 	}
+ 
+ 	if (i < 1)
+ 		return;
+ 
+ 	if ((Yanked = malloc(i + 1)) != NULL) {
+ 		memcpy(Yanked, &Line[begin], i);
+ 		Yanked[i] = '\0';
+ 	}
+ }
+ 
+ static status
+ delete_string(int count)
+ {
+ 	int i;
+ 	char *p;
+ 
+ 	if (count <= 0 || End == Point)
+ 		return ring_bell();
+ 
+ 	if (count == 1 && Point == End - 1) {
+ 		/* Optimize common case of delete at end of line. */
+ 		End--;
+ 		p = &Line[Point];
+ 		i = 1;
+ 		TTYput(' ');
+ 		if (ISCTL(*p)) {
+ 			i = 2;
+ 			TTYput(' ');
+ 		}
+ #ifdef COOK_META_CHARS
+ 		else if (ISMETA(*p)) {
+ 			i = 3;
+ 			TTYput(' ');
+ 			TTYput(' ');
+ 		}
+ #endif
+ 		TTYbackn(i);
+ 		*p = '\0';
+ 		return CSmove;
+ 	}
+ 	if (Point + count > End && (count = End - Point) <= 0)
+ 		return CSstay;
+ 
+ 	if (count > 1)
+ 		save_yank(Point, count);
+ 
+ 	for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
+ 		p[0] = p[count];
+ 	ceol();
+ 	End -= count;
+ 	TTYstring(&Line[Point]);
+ 	return CSmove;
+ }
+ 
+ static status
+ bk_char(void)
+ {
+ 	left(CSmove);
+ 	return CSstay;
+ }
+ 
+ static status
+ bk_del_char(void)
+ {
+ 	left(CSmove);
+ 	return delete_string(1);
+ }
+ 
+ static status
+ redisplay(void)
+ {
+ 	TTYputs(NEWLINE);
+ 	TTYputs(Prompt);
+ 	TTYstring(Line);
+ 	return CSmove;
+ }
+ 
+ static status
+ kill_line(void)
+ {
+ 	save_yank(Point, End - Point);
+ 	Line[Point] = '\0';
+ 	ceol();
+ 	End = Point;
+ 	return CSstay;
+ }
+ 
+ static status
+ insert_char(int c)
+ {
+ 	char buff[2];
+ 	buff[0] = c;
+ 	buff[1] = '\0';
+ 	return insert_string(buff);
+ }
+ 
+ static status
+ meta(void)
+ {
+ 	int c;
+ 	keymap *kp;
+ 
+ 	if ((c = TTYget()) == EOF)
+ 		return CSeof;
+ #ifdef USE_ANSI_ARROWS
+ 	if (c == '[' || c == 'O')
+ 		switch (c = TTYget()) {
+ 			default:	return ring_bell();
+ 			case EOF:	return CSeof;
+ 			case 'A':	return h_prev();
+ 			case 'B':	return h_next();
+ 			case 'C':	return fd_char();
+ 			case 'D':	return bk_char();
+ 		}
+ #endif
+ 
+ 	for (OldPoint = Point, kp = MetaMap; kp->function; kp++)
+ 		if (kp->key == c)
+ 			return (*kp->function)();
+ 
+ 	return ring_bell();
+ }
+ 
+ static status
+ emacs(int c)
+ {
+ 	status s;
+ 	keymap *kp;
+ 
+ 	if (ISMETA(c)) {
+ 		Pushed = 1;
+ 		PushBack = UNMETA(c);
+ 		return meta();
+ 	}
+ 	for (kp = Map; kp->function; kp++)
+ 		if (kp->key == c)
+ 			break;
+ 	s = kp->function ? (*kp->function)() : insert_char((int)c);
+ 	return s;
+ }
+ 
+ static status
+ TTYspecial(int c)
+ {
+ 	if (ISMETA(c))
+ 		return CSdispatch;
+ 
+ 	if (c == Erase || c == DEL)
+ 		return bk_del_char();
+ 	if (c == Kill) {
+ 		if (Point != 0) {
+ 			Point = 0;
+ 			reposition();
+ 		}
+ 		return kill_line();
+ 	}
+ 	if (c == Intr || c == Quit) {
+ 		Point = End = 0;
+ 		Line[0] = '\0';
+ 		return redisplay();
+ 	}
+ 	if (c == Eof && Point == 0 && End == 0)
+ 		return CSeof;
+ 
+ 	return CSdispatch;
+ }
+ 
+ static char *
+ editinput(void)
+ {
+ 	unsigned int	c;
+ 
+ 	OldPoint = Point = End = 0;
+ 	Line[0] = '\0';
+ 
+ 	while ((c = TTYget()) != EOF)
+ 		switch (TTYspecial(c)) {
+ 			case CSdone:
+ 				return Line;
+ 			case CSeof:
+ 				return NULL;
+ 			case CSmove:
+ 				reposition();
+ 				break;
+ 			case CSdispatch:
+ 				switch (emacs(c)) {
+ 					case CSdone:
+ 						return Line;
+ 					case CSeof:
+ 						return NULL;
+ 					case CSmove:
+ 						reposition();
+ 						break;
+ 					case CSdispatch:
+ 					case CSstay:
+ 						break;
+ 				}
+ 				break;
+ 			case CSstay:
+ 				break;
+ 		}
+ 	return NULL;
+ }
+ 
+ static void
+ hist_add(const char *p)
+ {
+ 	int		i;
+ 	char *np;
+ 
+ 	if ((np = strdup(p)) == NULL)
+ 		return;
+ 	if (Hist.size < HIST_SIZE)
+ 		Hist.lines[Hist.size++] = np;
+ 	else {
+ 		free(Hist.lines[0]);
+ 		for (i = 0; i < HIST_SIZE - 1; i++)
+ 			Hist.lines[i] = Hist.lines[i + 1];
+ 		Hist.lines[i] = np;
+ 	}
+ 	Hist.pos = Hist.size - 1;
+ }
+ 
+ char *
+ readline(const char *prompt)
+ {
+ 	char *line;
+ 
+ 	if (Line == NULL) {
+ 		Length = MEM_INC;
+ 		if ((Line = malloc(Length)) == NULL)
+ 			return NULL;
+ 	}
+ 
+ 	TTYinfo();
+ 	TTYset(0);
+ 	hist_add("");
+ 	ScreenSize = SCREEN_INC;
+ 	Screen = malloc(ScreenSize);
+ 	Prompt = prompt ? prompt : "";
+ 	TTYputs(Prompt);
+ 	if ((line = editinput()) != NULL) {
+ 		line = strdup(line);
+ 		TTYputs(NEWLINE);
+ 		TTYflush();
+ 	}
+ 	TTYset(1);
+ 	free(Screen);
+ 	free(Hist.lines[--Hist.size]);
+ 	return (char *)line;
+ }
+ 
+ void
+ add_history(char *line)
+ {
+ 	if (line == NULL || *line == '\0')
+ 		return;
+ 
+ 	if (Hist.pos && strcmp(line, Hist.lines[Hist.pos - 1]) == 0)
+ 		return;
+ 	hist_add(line);
+ }
+ 
+ static status
+ beg_line(void)
+ {
+ 	if (Point) {
+ 		Point = 0;
+ 		return CSmove;
+ 	}
+ 	return CSstay;
+ }
+ 
+ static status
+ del_char(void)
+ {
+ 	return delete_string(1);
+ }
+ 
+ static status
+ end_line(void)
+ {
+ 	if (Point != End) {
+ 		Point = End;
+ 		return CSmove;
+ 	}
+ 	return CSstay;
+ }
+ 
+ static status
+ accept_line()
+ {
+ 	Line[End] = '\0';
+ 	return CSdone;
+ }
+ 
+ static status
+ quote(void)
+ {
+ 	int	c;
+ 
+ 	return (c = TTYget()) == EOF ? CSeof : insert_char(c);
+ }
+ 
+ static status
+ move_to_char(void)
+ {
+ 	int c;
+ 	int i;
+ 	char *p;
+ 
+ 	if ((c = TTYget()) == EOF)
+ 		return CSeof;
+ 	for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
+ 		if (*p == c) {
+ 			Point = i;
+ 			return CSmove;
+ 		}
+ 	return CSstay;
+ }
+ 
+ static status
+ fd_word(void)
+ {
+ 	return do_forward(CSmove);
+ }
+ 
+ static status
+ fd_kill_word(void)
+ {
+ 	int i;
+ 
+ 	(void)do_forward(CSstay);
+ 	if (OldPoint != Point) {
+ 		i = Point - OldPoint;
+ 		Point = OldPoint;
+ 		return delete_string(i);
+ 	}
+ 	return CSstay;
+ }
+ 
+ static status
+ bk_word(void)
+ {
+ 	char *p;
+ 
+ 	for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
+ 		left(CSmove);
+ 
+ 	for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
+ 		left(CSmove);
+ 
+ 	return CSstay;
+ }
+ 
+ static status
+ bk_kill_word(void)
+ {
+ 	(void)bk_word();
+ 	if (OldPoint != Point)
+ 		return delete_string(OldPoint - Point);
+ 	return CSstay;
+ }
+ 
+ static keymap	Map[32] = {
+     {	CTL('@'),	ring_bell	},
+     {	CTL('A'),	beg_line	},
+     {	CTL('B'),	bk_char		},
+     {	CTL('B'),	bk_char		},
+     {	CTL('D'),	del_char	},
+     {	CTL('E'),	end_line	},
+     {	CTL('F'),	fd_char		},
+     {	CTL('G'),	ring_bell	},
+     {	CTL('H'),	bk_del_char	},
+     {	CTL('I'),	ring_bell	},
+     {	CTL('J'),	accept_line	},
+     {	CTL('K'),	kill_line	},
+     {	CTL('L'),	redisplay	},
+     {	CTL('M'),	accept_line	},
+     {	CTL('N'),	h_next		},
+     {	CTL('O'),	ring_bell	},
+     {	CTL('P'),	h_prev		},
+     {	CTL('Q'),	ring_bell	},
+     {	CTL('R'),	h_search	},
+     {	CTL('S'),	ring_bell	},
+     {	CTL('T'),	ring_bell	},
+     {	CTL('U'),	ring_bell	},
+     {	CTL('V'),	quote		},
+     {	CTL('W'),	ring_bell	},
+     {	CTL('X'),	ring_bell	},
+     {	CTL('Y'),	ring_bell	},
+     {	CTL('Z'),	ring_bell	},
+     {	CTL('['),	meta		},
+     {	CTL(']'),	move_to_char	},
+     {	CTL('^'),	ring_bell	},
+     {	CTL('_'),	ring_bell	},
+     {	0,		NULL		}
+ };
+ 
+ static keymap	MetaMap[8]= {
+     {	CTL('H'),	bk_kill_word	},
+     {	DEL,		bk_kill_word	},
+     {	'<',		h_first		},
+     {	'>',		h_last		},
+     {	'b',		bk_word		},
+     {	'd',		fd_kill_word	},
+     {	'f',		fd_word		},
+     {	0,		NULL		}
+ };
Index: 0.35/Modules/edline.h
*** 0.35/Modules/edline.h Tue, 16 Jan 2001 00:22:52 -0500 nas ()
--- 0.35(w)/Modules/edline.h Mon, 15 Jan 2001 23:46:07 -0500 nas (python/S/23_edline.h  644)
***************
*** 0 ****
--- 1,3 ----
+ 
+ extern char *readline(const char *prompt);
+ extern void add_history(char *p);
Index: 0.35/Modules/edlinemodule.c
*** 0.35/Modules/edlinemodule.c Tue, 16 Jan 2001 00:22:52 -0500 nas ()
--- 0.35(w)/Modules/edlinemodule.c Mon, 15 Jan 2001 23:54:09 -0500 nas (python/S/24_edlinemodu  644)
***************
*** 0 ****
--- 1,87 ----
+ /* This module makes the edline library to Python.  The edline library is
+  * a stripped down version of the editline library.  The editline library
+  * is a lighter version of GNU readline.  The module provides basic
+  * command line editing to the interactive interpreter.
+  *
+  * Placed in the public domain.
+  * Neil Schemenauer, January 15, 2001 
+  */
+ 
+ #include "Python.h"
+ 
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h> /* For isatty() */
+ #endif
+ 
+ #include "edline.h"
+ 
+ static char edline_doc[] = "\
+ Importing this module enables command line editing using the edline\n\
+ library.\n\
+ \n\
+ The edline library is based on code from the editline library which was\n\
+ released to the comp.sources.misc newsgroup with the following copyright:\n\
+ \n\
+   Copyright 1992 Simmule Turner and Rich Salz.  All rights reserved.\n\
+ \n\
+   This software is not subject to any license of the American Telephone\n\
+   and Telegraph Company or of the Regents of the University of California.\n\
+ \n\
+   Permission is granted to anyone to use this software for any purpose on\n\
+   any computer system, and to alter it and redistribute it freely, subject\n\
+   to the following restrictions:\n\
+   1. The authors are not responsible for the consequences of use of this\n\
+   software, no matter how awful, even if they arise from flaws in it.\n\
+   2. The origin of this software must not be misrepresented, either by\n\
+   explicit claim or by omission.  Since few users ever read sources,\n\
+   credits must appear in the documentation.\n\
+   3. Altered versions must be plainly marked as such, and must not be\n\
+   misrepresented as being the original software.  Since few users ever\n\
+   read sources, credits must appear in the documentation.\n\
+   4. This notice may not be removed or altered.\n\
+ ";
+ 
+ static char *
+ call_readline(char *prompt)
+ {
+ 	size_t n;
+ 	char *q, *p;
+ 
+ 	p = readline(prompt);
+ 	/* We must return a buffer allocated with PyMem_Malloc. */
+ 	if (p == NULL) {
+ 		p = PyMem_Malloc(1);
+ 		if (p != NULL)
+ 			*p = '\0';
+ 		return p;
+ 	}
+ 	n = strlen(p);
+ 	if (n > 0)
+ 		add_history(p);
+ 	/* Copy the malloc'ed buffer into a PyMem_Malloc'ed one and
+ 	   release the original. */
+ 	q = p;
+ 	p = PyMem_Malloc(n+2);
+ 	if (p != NULL) {
+ 		strncpy(p, q, n);
+ 		p[n] = '\n';
+ 		p[n+1] = '\0';
+ 	}
+ 	free(q);
+ 	return p;
+ }
+ 
+ static struct PyMethodDef edline_methods[] = {0, 0};
+ 
+ void
+ initreadline(void)
+ {
+ 	PyObject *m;
+ 
+ 	m = Py_InitModule4("readline", edline_methods, edline_doc,
+ 			   (PyObject *)NULL, PYTHON_API_VERSION);
+ 
+ 	if (isatty(fileno(stdin))) {
+ 		PyOS_ReadlineFunctionPointer = call_readline;
+ 	}
+ }
