home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BURKS 2
/
BURKS_AUG97.ISO
/
SLAKWARE
/
D10
/
TOOLS.TGZ
/
TOOLS.tar
/
usr
/
doc
/
tools-2.17
/
example
/
editline.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-05
|
23KB
|
1,383 lines
/* $Revision: 1.4 $
**
** Main editing routines for editline library.
*/
#include "editline.h"
#include <ctype.h>
extern const char version_string[];
const char * string = version_string+2;
/*
** Manifest constants.
*/
#define SCREEN_WIDTH 80
#define SCREEN_ROWS 24
#define NO_ARG (-1)
#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)
#if !defined(HIST_SIZE)
#define HIST_SIZE 20
#endif /* !defined(HIST_SIZE) */
/*
** Command status codes.
*/
typedef enum _STATUS {
CSdone, CSeof, CSmove, CSdispatch, CSstay
} STATUS;
/*
** The type of case-changing to perform.
*/
typedef enum _CASE {
TOupper, TOlower
} CASE;
/*
** 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.
*/
int rl_eof;
int rl_erase;
int rl_intr;
int rl_kill;
STATIC CHAR NIL[] = "";
STATIC CONST CHAR *Input = NIL;
STATIC CHAR *Line;
STATIC CONST char *Prompt;
STATIC CHAR *Yanked;
STATIC char *Screen;
STATIC char NEWLINE[]= CRLF;
STATIC HISTORY H;
int rl_quit;
STATIC int Repeat;
STATIC int End;
STATIC int Mark;
STATIC int OldPoint;
STATIC int Point;
STATIC int PushBack;
STATIC int Pushed;
FORWARD KEYMAP Map[33];
FORWARD KEYMAP MetaMap[16];
STATIC SIZE_T Length;
STATIC SIZE_T ScreenCount;
STATIC SIZE_T ScreenSize;
STATIC char *backspace;
STATIC int TTYwidth;
STATIC int TTYrows;
/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
int rl_meta_chars = 1;
/*
** Declarations.
*/
STATIC CHAR *editinput();
extern int read();
extern int write();
#if defined(USE_TERMCAP)
extern char *getenv();
extern char *tgetstr();
extern int tgetent();
#endif /* defined(USE_TERMCAP) */
/*
** TTY input/output functions.
*/
STATIC void
TTYflush()
{
if (ScreenCount) {
(void)write(1, Screen, ScreenCount);
ScreenCount = 0;
}
}
STATIC void
TTYput(c)
CHAR c;
{
Screen[ScreenCount] = c;
if (++ScreenCount >= ScreenSize - 1) {
ScreenSize += SCREEN_INC;
RENEW(Screen, char, ScreenSize);
}
}
STATIC void
TTYputs(p)
CHAR *p;
{
while (*p)
TTYput(*p++);
}
STATIC void
TTYshow(c)
CHAR c;
{
if (c == DEL) {
TTYput('^');
TTYput('?');
}
else if (ISCTL(c)) {
TTYput('^');
TTYput(UNCTL(c));
}
else if (rl_meta_chars && ISMETA(c)) {
TTYput('M');
TTYput('-');
TTYput(UNMETA(c));
}
else
TTYput(c);
}
STATIC void
TTYstring(p)
CHAR *p;
{
while (*p)
TTYshow(*p++);
}
STATIC unsigned int
TTYget()
{
CHAR c;
TTYflush();
if (Pushed) {
Pushed = 0;
return PushBack;
}
if (*Input)
return *Input++;
return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
}
#define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
STATIC void
TTYbackn(n)
int n;
{
while (--n >= 0)
TTYback();
}
STATIC void
TTYinfo()
{
static int init;
#if defined(USE_TERMCAP)
char *term;
char buff[2048];
char *bp;
#endif /* defined(USE_TERMCAP) */
#if defined(TIOCGWINSZ)
struct winsize W;
#endif /* defined(TIOCGWINSZ) */
if (init) {
#if defined(TIOCGWINSZ)
/* 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;
}
#endif /* defined(TIOCGWINSZ) */
return;
}
init++;
TTYwidth = TTYrows = 0;
#if defined(USE_TERMCAP)
bp = &buff[0];
if ((term = getenv("TERM")) == NULL)
term = "dumb";
if (tgetent(buff, term) < 0) {
TTYwidth = SCREEN_WIDTH;
TTYrows = SCREEN_ROWS;
return;
}
backspace = tgetstr("le", &bp);
TTYwidth = tgetnum("co");
TTYrows = tgetnum("li");
#endif /* defined(USE_TERMCAP) */
#if defined(TIOCGWINSZ)
if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
TTYwidth = (int)W.ws_col;
TTYrows = (int)W.ws_row;
}
#endif /* defined(TIOCGWINSZ) */
if (TTYwidth <= 0 || TTYrows <= 0) {
TTYwidth = SCREEN_WIDTH;
TTYrows = SCREEN_ROWS;
}
}
/*
** Print an array of words in columns.
*/
STATIC void
columns(ac, av)
int ac;
CHAR **av;
{
CHAR *p;
int i;
int j;
int k;
int len;
int skip;
int longest;
int cols;
/* Find longest name, determine column count from that. */
for (longest = 0, i = 0; i < ac; i++)
if ((j = strlen((char *)av[i])) > longest)
longest = j;
cols = TTYwidth / (longest + 3);
TTYputs((CHAR *)NEWLINE);
for (skip = ac / cols + 1, i = 0; i < skip; i++) {
for (j = i; j < ac; j += skip) {
for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
TTYput(*p);
if (j + skip < ac)
while (++len < longest + 3)
TTYput(' ');
}
TTYputs((CHAR *)NEWLINE);
}
}
STATIC void
reposition()
{
int i;
CHAR *p;
TTYput('\r');
TTYputs((CHAR *)Prompt);
for (i = Point, p = Line; --i >= 0; p++)
TTYshow(*p);
}
STATIC void
left(Change)
STATUS Change;
{
TTYback();
if (Point) {
if (ISCTL(Line[Point - 1]))
TTYback();
else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
TTYback();
TTYback();
}
}
if (Change == CSmove)
Point--;
}
STATIC void
right(Change)
STATUS Change;
{
TTYshow(Line[Point]);
if (Change == CSmove)
Point++;
}
STATIC STATUS
ring_bell()
{
TTYput('\07');
TTYflush();
return CSstay;
}
STATIC STATUS
do_macro(c)
unsigned int c;
{
CHAR name[4];
name[0] = '_';
name[1] = c;
name[2] = '_';
name[3] = '\0';
if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
Input = NIL;
return ring_bell();
}
return CSstay;
}
STATIC STATUS
do_forward(move)
STATUS move;
{
int i;
CHAR *p;
i = 0;
do {
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);
if (Point == End)
break;
} while (++i < Repeat);
return CSstay;
}
STATIC STATUS
do_case(type)
CASE type;
{
int i;
int end;
int count;
CHAR *p;
(void)do_forward(CSstay);
if (OldPoint != Point) {
if ((count = Point - OldPoint) < 0)
count = -count;
Point = OldPoint;
if ((end = Point + count) > End)
end = End;
for (i = Point, p = &Line[i]; i < end; i++, p++) {
if (type == TOupper) {
if (islower(*p))
*p = toupper(*p);
}
else if (isupper(*p))
*p = tolower(*p);
right(CSmove);
}
}
return CSstay;
}
STATIC STATUS
case_down_word()
{
return do_case(TOlower);
}
STATIC STATUS
case_up_word()
{
return do_case(TOupper);
}
STATIC void
ceol()
{
int extras;
int i;
CHAR *p;
for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
TTYput(' ');
if (ISCTL(*p)) {
TTYput(' ');
extras++;
}
else if (rl_meta_chars && ISMETA(*p)) {
TTYput(' ');
TTYput(' ');
extras += 2;
}
}
for (i += extras; i > Point; i--)
TTYback();
}
STATIC void
clear_line()
{
Point = -strlen(Prompt);
TTYput('\r');
ceol();
Point = 0;
End = 0;
Line[0] = '\0';
}
STATIC STATUS
insert_string(p)
CHAR *p;
{
SIZE_T len;
int i;
CHAR *new;
CHAR *q;
len = strlen((char *)p);
if (End + len >= Length) {
if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
return CSstay;
if (Length) {
COPYFROMTO(new, Line, Length);
DISPOSE(Line);
}
Line = new;
Length += len + MEM_INC;
}
for (q = &Line[Point], i = End - Point; --i >= 0; )
q[len + i] = q[i];
COPYFROMTO(&Line[Point], p, len);
End += len;
Line[End] = '\0';
TTYstring(&Line[Point]);
Point += len;
return Point == End ? CSstay : CSmove;
}
STATIC CHAR *
next_hist()
{
return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
}
STATIC CHAR *
prev_hist()
{
return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
}
STATIC STATUS
do_insert_hist(p)
CHAR *