/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1984-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* Pat Sullivan *
* *
***********************************************************************/
/* Adapted for ksh by David Korn */
/* EMACS_MODES: c tabstop=4
One line screen editor for any program
Questions and comments should be
directed to
Michael T. Veach
IX 1C-341 X1614
ihuxl!veach
*/
/* The following is provided by:
*
* Matthijs N. Melchior
* AT&T Network Systems International
* APT Nederland
* HV BZ335 x2962
* hvlpb!mmelchio
*
*
* If symbol ESHPLUS is defined, the following features is present:
*
* ESH_NFIRST
* - A ^N as first history related command after the prompt will move
* to the next command relative to the last known history position.
* It will not start at the position where the last command was entered
* as is done by the ^P command. Every history related command will
* set both the current and last position. Executing a command will
* only set the current position.
*
* ESH_KAPPEND
* - Successive kill and delete commands will accumulate their data
* in the kill buffer, by appending or prepending as appropriate.
* This mode will be reset by any command not adding something to the
* kill buffer.
*
* ESH_BETTER
* - Some enhancements:
* - argument for a macro is passed to its replacement
* - ^X^H command to find out about history position (debugging)
* - ^X^D command to show any debugging info
*
* I do not pretend these for changes are completely independent,
* but you can use them to seperate features.
*/
#ifdef DMERT /* 3bcc #undefs RT */
# define RT
#endif
#ifdef KSHELL
# include "defs.h"
#else
# include "io.h"
#endif /* KSHELL */
#include "history.h"
#include "edit.h"
#include "terminal.h"
#ifdef ESHPLUS
# define ESH_NFIRST
# define ESH_KAPPEND
# define ESH_BETTER
#endif /*ESHPLUS */
#ifdef MULTIBYTE
static int print();
static int isword();
#else
#endif /*MULTIBYTE */
#ifdef ESHPLUS
#endif
#define NO 0
/**********************
A large lookahead helps when the user is inserting
characters in the middle of the line.
************************/
static enum
{
} terminal ;
typedef enum
{
} DRAWTYPE;
static void draw();
static int escape();
static void putstring();
static void search();
static void setcursor();
static void show_info();
static void xcommands();
static int cr_ok;
char *buff;
int fd;
unsigned scend;
{
register int c;
register int i;
register int count;
char backslash;
static int CntrlO;
#else
if(kstack==0)
{
kstack[0] = '\0';
}
#endif
{
p_flush();
}
raw = 1;
/* This mess in case the read system call fails */
#ifdef ESH_NFIRST
if (hist_ptr) /* hloff cleared by ed_setup, recalculate... */
{
}
{
}
#endif /* ESH_NFIRST */
if (i)
{
if (i == UEOF)
{
return(0); /* EOF */
}
return(-1); /* some other error */
}
*out = 0;
adjust = -1;
backslash = 0;
if (CntrlO)
{
#ifdef ESH_NFIRST
#else
{
# ifdef MULTIBYTE
# endif /* MULTIBYTE */
}
#endif /* ESH_NFIRST */
}
CntrlO = 0;
while ((c = ed_getchar()) != (-1))
{
if (backslash)
{
backslash = 0;
(c!='\r'&&c!='\n')))
{
/* accept a backslashed character */
cur--;
continue;
}
}
if (c == usrkill)
{
c = KILLCHAR ;
}
else if (c == usrerase)
{
c = ERASECHAR ;
}
{
c = EOFCHAR;
}
#ifdef ESH_KAPPEND
if (--killing <= 0) /* reset killing flag */
killing = 0;
#endif
if(count<0)
count = 1;
adjust = -1;
i = cur;
switch(c)
{
case cntl('V'):
continue;
case '\0':
mark = i;
continue;
case cntl('X'):
continue;
case EOFCHAR:
ed_flush();
return(0);
#ifdef u370
case cntl('S') :
case cntl('Q') :
continue;
#endif /* u370 */
default:
i = ++eol;
if (i >= (scend)) /* will not fit on line */
{
eol--;
ed_ungetchar(c); /* save character for next line */
goto process;
}
{
}
backslash = (c == '\\');
continue;
case cntl('Y') :
{
{
beep();
continue;
}
mark = i;
while (i = *kptr++)
continue;
}
case '\n':
case '\r':
c = '\n';
goto process;
case DELETE: /* delete char 0x7f */
case '\b': /* backspace, ^h */
case ERASECHAR :
if (count > i)
count = i;
#ifdef ESH_KAPPEND
if (killing) /* prepend to killbuf */
{
while(c--) /* copy stuff */
}
else
*kptr = 0; /* this is end of data */
i -= count;
#else
while ((count--)&&(i>0))
{
i--;
eol--;
}
#endif /* ESH_KAPPEND */
mark = i;
goto update;
case cntl('W') :
#ifdef ESH_KAPPEND
++killing; /* keep killing flag */
#endif
if (mark == i)
continue;
if (mark > i)
{
continue;
}
continue;
case cntl('D') :
mark = i;
#ifdef ESH_KAPPEND
if (killing)
else
#else
#endif /* ESH_KAPPEND */
{
eol--;
while(1)
{
break;
i++;
}
i = cur;
}
*kptr = '\0';
goto update;
case cntl('C') :
case cntl('F') :
{
{
if (cntlC)
{
c = out[i];
#ifdef MULTIBYTE
#else
if(islower(c))
#endif /* MULTIBYTE */
{
c += 'A' - 'a';
out[i] = c;
}
}
i++;
}
goto update;
}
case cntl(']') :
c = ed_getchar();
{
beep();
continue;
}
if (out[i])
i++;
while (i < eol)
{
goto update;
i++;
}
i = 0;
while (i < cur)
{
break;
i++;
};
cur = i;
continue;
case cntl('B') :
if (count > i)
count = i;
i -= count;
goto update;
case cntl('T') :
{
if (i >= 2)
{
c = out[i - 1];
out[i-2] = c;
}
else
{
beep();
continue;
}
}
else
{
if (eol>(i+1))
{
c = out[i];
out[i+1] = c;
i++;
}
else
{
beep();
continue;
}
}
goto update;
case cntl('A') :
i = 0;
goto update;
case cntl('E') :
i = eol;
goto update;
case cntl('U') :
continue;
case KILLCHAR :
cur = 0;
oadjust = -1;
case cntl('K') :
if(oadjust >= 0)
{
#ifdef ESH_KAPPEND
#endif
continue;
}
i = cur;
eol = i;
mark = i;
#ifdef ESH_KAPPEND
if (killing) /* append to kill buffer */
else
#else
#endif /* ESH_KAPPEND */
out[i] = 0;
if (c == KILLCHAR)
{
{
putchar('\n');
}
c = ed_getchar();
if (c != usrkill)
{
ed_ungetchar(c);
continue;
}
else
{
putchar('\n');
}
}
continue;
case cntl('L'):
ed_crlf();
continue;
case cntl('[') :
continue;
case cntl('R') :
goto drawline;
case cntl('P') :
else
{
hloff = 0;
}
#ifdef ESH_NFIRST
#else
#endif /* ESH_NFIRST */
{
beep();
#ifndef ESH_NFIRST
continue;
#endif
}
goto common;
case cntl('O') :
CntrlO = 1;
c = '\n';
goto process;
case cntl('N') :
#ifdef ESH_NFIRST
#endif /* ESH_NFIRST */
{
beep();
#ifdef ESH_NFIRST
#else
continue;
#endif /* ESH_NFIRST */
}
#ifdef ESH_NFIRST
#endif
#ifdef MULTIBYTE
#endif /* MULTIBYTE */
continue;
}
}
if (c == (-1))
{
lookahead = 0;
beep();
*out = '\0';
}
if(c == '\n')
{
ed_crlf();
}
else
p_flush();
#ifdef MULTIBYTE
#endif /* MULTIBYTE */
if (i)
return(i);
return(-1);
}
char *str;
{
register int c;
/* save current line */
*out = 0;
cur = 0;
#ifdef MULTIBYTE
#else
#endif /* MULTIBYTE */
c = ed_getchar();
if(c!=' ')
ed_ungetchar(c);
/* restore line */
}
static void
putstring(s)
register char *s;
{
register int c;
while (c= *s++)
putchar(c);
}
static int
int count;
{
register int i,value;
digit = 0;
value = 0;
while ((i=ed_getchar()),isdigit(i))
{
value *= 10;
value += (i - '0');
digit = 1;
}
if (digit)
{
ed_ungetchar(i) ;
#ifdef ESH_KAPPEND
++killing; /* don't modify killing signal */
#endif
return(value);
}
if(value<0)
value = 1;
switch(ch=i)
{
case ' ':
return(-1);
#ifdef ESH_KAPPEND
case '+': /* M-+ = append next kill */
killing = 2;
return -1; /* no argument for next command */
#endif
case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
#ifdef ESH_KAPPEND
killing = 0; /* start fresh */
#endif
return(-1);
case 'l': /* M-l == lower-case */
case 'd':
case 'c':
case 'f':
{
i = cur;
{
i++;
i++;
}
if(ch=='l')
{
while (value-- > 0)
{
#ifdef MULTIBYTE
#else
if(isupper(i))
#endif /* MULTIBYTE */
{
i += 'a' - 'A';
}
cur++;
}
return(-1);
}
else if(ch=='f')
goto update;
else if(ch=='c')
{
return(i-cur);
}
else
{
if (i-cur)
{
#ifdef ESH_KAPPEND
++killing; /* keep killing signal */
#endif
return(i-cur);
}
beep();
return(-1);
}
}
case 'b':
case DELETE :
case '\b':
case 'h':
{
i = cur;
while(value-- && i>0)
{
i--;
while ((i>0)&&(!isword(i)))
i--;
while ((i>0)&&(isword(i-1)))
i--;
}
if(ch=='b')
goto update;
else
{
#ifdef ESH_KAPPEND
++killing;
#endif
return(cur-i);
}
}
case '>':
#ifdef ESH_NFIRST
if (in_mult)
{
}
else
{
}
#else
hloff = 0;
#endif /* ESH_NFIRST */
return(0);
case '<':
hloff = 0;
#ifdef ESH_NFIRST
return 0;
#else
#endif /* ESH_NFIRST */
case '#':
ed_ungetchar('\n');
ed_ungetchar('#');
return(-1);
case '_' :
case '.' :
{
char *ptr;
#ifndef KSHELL
if(ptr==0)
{
beep();
break;
}
#endif /* KSHELL */
{
beep();
return(-1);
}
while(*ptr)
{
eol++;
}
return(-1);
}
#ifdef KSHELL
/* file name expansion */
i = '\\';
case '*': /* filename expansion */
case '=': /* escape = - list all matching file names */
beep();
else if(i=='=')
else
return(-1);
/* search back for character */
{
int c = ed_getchar();
{
beep();
return(-1);
}
i = cur;
if (i > 0)
i--;
while (i >= 0)
{
goto update;
i--;
}
i = eol;
while (i > cur)
{
break;
i--;
};
cur = i;
return(-1);
case '[': /* feature not in book */
i = '_';
}
default:
/* look for user defined macro definitions */
if(ed_macro(i))
# ifdef ESH_BETTER
return(count); /* pass argument to macro */
# else
return(-1);
# endif /* ESH_BETTER */
#else
cur = i;
return(-1);
default:
#endif /* KSHELL */
beep();
return(-1);
}
beep();
return(-1);
}
/*
* This routine process all commands starting with ^X
*/
static void
int count;
{
register int i = ed_getchar();
switch(i)
{
i = mark;
cur = i;
return;
#ifdef KSHELL
# ifdef ESH_BETTER
if(ed_fulledit()==-1)
beep();
else
ed_ungetchar('\n');
return;
{
if (hloff)
{
}
{
{
}
}
return;
}
# if 0 /* debugging, modify as required */
{
return;
}
# endif /* debugging code */
# endif /* ESH_BETTER */
#endif /* KSHELL */
default:
beep();
return;
}
}
static void
int direction;
{
#ifndef ESH_NFIRST
#endif
register int i,sl;
/* save current line */
string[0] = '^';
sl = 2;
{
if (i==usrerase)
{
if (sl > 2)
{
}
else
beep();
continue;
}
if (i==usrkill)
{
beep();
goto restore;
}
if (i == '\\')
{
i = ed_getchar();
}
}
if (direction < 1)
{
direction = 1;
}
else
direction = -1;
if (i != 2)
{
#ifdef MULTIBYTE
#endif /* MULTIBYTE */
}
else
i = location.his_command;
if(i>0)
{
hline = i;
#ifdef ESH_NFIRST
#else
#endif /* ESH_NFIRST */
#ifdef MULTIBYTE
#endif /* MULTIBYTE */
return;
}
if (i < 0)
{
beep();
#ifdef ESH_NFIRST
#else
hloff = 0;
#endif /* ESH_NFIRST */
}
return;
}
/* Adjust screen to agree with inputs: logical line and cursor */
/* If 'first' assume screen is blank */
/* Prompt is always kept on the screen */
static void
{
#define UNDEF 0
register int i;
{
offset = 0;
{
scvalid = 1;
return;
}
*cursor = '\0';
}
/*********************
Do not update screen if pending characters
**********************/
{
scvalid = 0; /* Screen is out of date, APPEND will not work */
return;
}
/***************************************
If in append mode, cursor at end of line, screen up to date,
the previous character was a 'normal' character,
and the window has room for another character.
Then output the character and adjust the screen only.
*****************************************/
{
putchar(i);
*cursor++ = i;
*cursor = '\0';
return;
}
/* copy the line */
/*********************
Does ncursor appear on the screen?
If not, adjust the screen offset so it does.
**********************/
{
/* Center the cursor on the screen */
if (--offset < 0)
offset = 0;
}
/*********************
Is the range of screen[0] thru screen[w_size] up-to-date
with nscreen[offset] thru nscreen[offset+w_size] ?
If not, update as need be.
***********************/
i = w_size;
while (i-- > 0)
{
if (*nptr == '\0')
{
*nptr = ' ';
}
if (*sptr == '\0')
{
*sptr = ' ';
}
{
nptr++;
sptr++;
continue;
}
#ifdef MULTIBYTE
{
i--;
cursor++;
}
#endif /* MULTIBYTE */
}
/******************
Screen overflow checks
********************/
{
if (offset > 0)
else
}
else
{
if (offset > 0)
}
/* Update screen overflow indicator if need be */
{
}
setcursor(i,0);
scvalid = 1;
return;
}
/*
* put the cursor to the <new> position within screen buffer
* if <c> is non-zero then output this character
* cursor is set to reflect the change
*/
static void
register int new,c;
{
{
{
{
putchar('\b');
old--;
}
goto skip;
}
old = 0;
}
skip:
if(c)
{
putchar(c);
new++;
}
return;
}
#ifdef MULTIBYTE
static int print(c)
register int c;
{
}
static int isword(i)
register int i;
{
register int c = drawbuff[i];
}
#endif /* MULTIBYTE */