#pragma prototyped
#include <ast.h>
#include <ctype.h>
#include "FEATURE/cmds"
#if KSHELL
# include "defs.h"
#endif
#include "io.h"
#include "history.h"
#include "edit.h"
#include "terminal.h"
#define ESH_NFIRST
#define ESH_KAPPEND
#define ESH_BETTER
#undef putchar
#define putchar(ed,c) ed_putchar(ed,c)
#define beep() ed_ringbell()
#if SHOPT_MULTIBYTE
# define gencpy(a,b) ed_gencpy(a,b)
# define genncpy(a,b,n) ed_genncpy(a,b,n)
# define genlen(str) ed_genlen(str)
static int print(int);
static int _isword(int);
# define isword(c) _isword(out[c])
#else
# define gencpy(a,b) strcpy((char*)(a),(char*)(b))
# define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
# define genlen(str) strlen(str)
# define print(c) isprint(c)
# define isword(c) (isalnum(out[c]) || (out[c]=='_'))
#endif
typedef struct _emacs_
{
genchar *screen;
genchar *cursor;
int mark;
int in_mult;
char cr_ok;
char CntrlO;
char overflow;
char scvalid;
int offset;
enum
{
CRT=0,
PAPER
} terminal;
Histloc_t _location;
int prevdirection;
Edit_t *ed;
} Emacs_t;
#define editb (*ep->ed)
#define eol editb.e_eol
#define cur editb.e_cur
#define hline editb.e_hline
#define hloff editb.e_hloff
#define hismin editb.e_hismin
#define usrkill editb.e_kill
#define usrlnext editb.e_lnext
#define usreof editb.e_eof
#define usrerase editb.e_erase
#define crallowed editb.e_crlf
#define Prompt editb.e_prompt
#define plen editb.e_plen
#define kstack editb.e_killbuf
#define lstring editb.e_search
#define lookahead editb.e_lookahead
#define env editb.e_env
#define raw editb.e_raw
#define histlines editb.e_hismax
#define w_size editb.e_wsize
#define drawbuff editb.e_inbuf
#define killing editb.e_mode
#define location ep->_location
#define LBUF 100
#define KILLCHAR UKILL
#define ERASECHAR UERASE
#define EOFCHAR UEOF
#define LNEXTCHAR ULNEXT
#define DELETE ('a'==97?0177:7)
typedef enum
{
FIRST,
REFRESH,
APPEND,
UPDATE,
FINAL
} Draw_t;
static void draw(Emacs_t*,Draw_t);
static int escape(Emacs_t*,genchar*, int);
static void putstring(Emacs_t*,char*);
static void search(Emacs_t*,genchar*,int);
static void setcursor(Emacs_t*,int, int);
static void show_info(Emacs_t*,const char*);
static void xcommands(Emacs_t*,int);
int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
{
Edit_t *ed = (Edit_t*)context;
register int c;
register int i;
register genchar *out;
register int count;
register Emacs_t *ep = ed->e_emacs;
int adjust,oadjust;
char backslash;
genchar *kptr;
char prompt[PRSIZE];
genchar Screen[MAXLINE];
if(!ep)
{
ep = ed->e_emacs = newof(0,Emacs_t,1,0);
ep->ed = ed;
ep->prevdirection = 1;
location.hist_command = -5;
}
Prompt = prompt;
ep->screen = Screen;
if(tty_raw(ERRIO,0) < 0)
{
return(reedit?reedit:ed_read(context, fd,buff,scend,0));
}
raw = 1;
ed_setup(ep->ed,fd,reedit);
out = (genchar*)buff;
#if SHOPT_MULTIBYTE
out = (genchar*)roundof((char*)out-(char*)0,sizeof(genchar));
ed_internal(buff,out);
#endif
if(!kstack)
{
kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
kstack[0] = '\0';
}
drawbuff = out;
#ifdef ESH_NFIRST
if (location.hist_command == -5)
{
kstack[0] = '\0';
location.hist_command = hline;
location.hist_line = hloff;
}
if (location.hist_command <= hismin)
{
location.hist_command = hismin + 1;
location.hist_line = 0;
}
ep->in_mult = hloff;
#endif
i = sigsetjmp(env,0);
if (i !=0)
{
tty_cooked(ERRIO);
if (i == UEOF)
{
return(0);
}
return(-1);
}
out[reedit] = 0;
if(scend+plen > (MAXLINE-2))
scend = (MAXLINE-2)-plen;
ep->mark = 0;
cur = eol;
draw(ep,reedit?REFRESH:FIRST);
adjust = -1;
backslash = 0;
if (ep->CntrlO)
{
#ifdef ESH_NFIRST
ed_ungetchar(ep->ed,cntl('N'));
#else
location = hist_locate(sh.hist_ptr,location.hist_command,location.hist_line,1);
if (location.hist_command < histlines)
{
hline = location.hist_command;
hloff = location.hist_line;
hist_copy((char*)kstack,MAXLINE, hline,hloff);
# if SHOPT_MULTIBYTE
ed_internal((char*)kstack,kstack);
# endif
ed_ungetchar(ep->ed,cntl('Y'));
}
#endif
}
ep->CntrlO = 0;
while ((c = ed_getchar(ep->ed,0)) != (-1))
{
if (backslash)
{
backslash = 0;
if (c==usrerase||c==usrkill||(!print(c) &&
(c!='\r'&&c!='\n')))
{
cur--;
out[cur++] = c;
out[eol] = '\0';
draw(ep,APPEND);
continue;
}
}
if (c == usrkill)
{
c = KILLCHAR ;
}
else if (c == usrerase)
{
c = ERASECHAR ;
}
else if (c == usrlnext)
{
c = LNEXTCHAR ;
}
else if ((c == usreof)&&(eol == 0))
{
c = EOFCHAR;
}
#ifdef ESH_KAPPEND
if (--killing <= 0)
killing = 0;
#endif
oadjust = count = adjust;
if(count<0)
count = 1;
adjust = -1;
i = cur;
switch(c)
{
case LNEXTCHAR:
c = ed_getchar(ep->ed,2);
goto do_default_processing;
case cntl('V'):
show_info(ep,fmtident(e_version));
continue;
case '\0':
ep->mark = i;
continue;
case cntl('X'):
xcommands(ep,count);
continue;
case EOFCHAR:
ed_flush(ep->ed);
tty_cooked(ERRIO);
return(0);
#ifdef u370
case cntl('S') :
case cntl('Q') :
continue;
#endif
case '\t':
if(cur>0 && ep->ed->sh->nextprompt)
{
if(ep->ed->e_tabcount==0)
{
ep->ed->e_tabcount=1;
ed_ungetchar(ep->ed,ESC);
goto do_escape;
}
else if(ep->ed->e_tabcount==1)
{
ed_ungetchar(ep->ed,'=');
goto do_escape;
}
ep->ed->e_tabcount = 0;
}
do_default_processing:
default:
if ((eol+1) >= (scend))
{
ed_ungetchar(ep->ed,c);
goto process;
}
for(i= ++eol; i>cur; i--)
out[i] = out[i-1];
backslash = (c == '\\');
out[cur++] = c;
draw(ep,APPEND);
continue;
case cntl('Y') :
{
c = genlen(kstack);
if ((c + eol) > scend)
{
beep();
continue;
}
ep->mark = i;
for(i=eol;i>=cur;i--)
out[c+i] = out[i];
kptr=kstack;
while (i = *kptr++)
out[cur++] = i;
draw(ep,UPDATE);
eol = genlen(out);
continue;
}
case '\n':
case '\r':
c = '\n';
goto process;
case DELETE:
case '\b':
case ERASECHAR :
if (count > i)
count = i;
#ifdef ESH_KAPPEND
kptr = &kstack[count];
if (killing)
{
c = genlen(kstack) + CHARSIZE;
while(c--)
kptr[c] = kstack[c];
}
else
*kptr = 0;
killing = 2;
i -= count;
eol -= count;
genncpy(kstack,out+i,cur-i);
#else
while ((count--)&&(i>0))
{
i--;
eol--;
}
genncpy(kstack,out+i,cur-i);
kstack[cur-i] = 0;
#endif
gencpy(out+i,out+cur);
ep->mark = i;
goto update;
case cntl('W') :
#ifdef ESH_KAPPEND
++killing;
#endif
if (ep->mark > eol )
ep->mark = eol;
if (ep->mark == i)
continue;
if (ep->mark > i)
{
adjust = ep->mark - i;
ed_ungetchar(ep->ed,cntl('D'));
continue;
}
adjust = i - ep->mark;
ed_ungetchar(ep->ed,usrerase);
continue;
case cntl('D') :
ep->mark = i;
#ifdef ESH_KAPPEND
if (killing)
kptr = &kstack[genlen(kstack)];
else
kptr = kstack;
killing = 2;
#else
kptr = kstack;
#endif
while ((count--)&&(eol>0)&&(i<eol))
{
*kptr++ = out[i];
eol--;
while(1)
{
if ((out[i] = out[(i+1)])==0)
break;
i++;
}
i = cur;
}
*kptr = '\0';
goto update;
case cntl('C') :
case cntl('F') :
{
int cntlC = (c==cntl('C'));
while (count-- && eol>i)
{
if (cntlC)
{
c = out[i];
#if SHOPT_MULTIBYTE
if((c&~STRIP)==0 && islower(c))
#else
if(islower(c))
#endif
{
c += 'A' - 'a';
out[i] = c;
}
}
i++;
}
goto update;
}
case cntl(']') :
c = ed_getchar(ep->ed,1);
if ((count == 0) || (count > eol))
{
beep();
continue;
}
if (out[i])
i++;
while (i < eol)
{
if (out[i] == c && --count==0)
goto update;
i++;
}
i = 0;
while (i < cur)
{
if (out[i] == c && --count==0)
break;
i++;
};
update:
cur = i;
draw(ep,UPDATE);
continue;
case cntl('B') :
if (count > i)
count = i;
i -= count;
goto update;
case cntl('T') :
if ((sh_isoption(SH_EMACS))&& (eol!=i))
i++;
if (i >= 2)
{
c = out[i - 1];
out[i-1] = out[i-2];
out[i-2] = c;
}
else
{
if(sh_isoption(SH_EMACS))
i--;
beep();
continue;
}
goto update;
case cntl('A') :
i = 0;
goto update;
case cntl('E') :
i = eol;
goto update;
case cntl('U') :
adjust = 4*count;
continue;
case KILLCHAR :
cur = 0;
oadjust = -1;
case cntl('K') :
if(oadjust >= 0)
{
#ifdef ESH_KAPPEND
killing = 2;
#endif
ep->mark = count;
ed_ungetchar(ep->ed,cntl('W'));
continue;
}
i = cur;
eol = i;
ep->mark = i;
#ifdef ESH_KAPPEND
if (killing)
gencpy(&kstack[genlen(kstack)], &out[i]);
else
gencpy(kstack,&out[i]);
killing = 2;
#else
gencpy(kstack,&out[i]);
#endif
out[i] = 0;
draw(ep,UPDATE);
if (c == KILLCHAR)
{
if (ep->terminal == PAPER)
{
putchar(ep->ed,'\n');
putstring(ep,Prompt);
}
c = ed_getchar(ep->ed,0);
if (c != usrkill)
{
ed_ungetchar(ep->ed,c);
continue;
}
if (ep->terminal == PAPER)
ep->terminal = CRT;
else
{
ep->terminal = PAPER;
putchar(ep->ed,'\n');
putstring(ep,Prompt);
}
}
continue;
case cntl('L'):
ed_crlf(ep->ed);
draw(ep,REFRESH);
continue;
case cntl('[') :
do_escape:
adjust = escape(ep,out,oadjust);
continue;
case cntl('R') :
search(ep,out,count);
goto drawline;
case cntl('P') :
if (count <= hloff)
hloff -= count;
else
{
hline -= count - hloff;
hloff = 0;
}
#ifdef ESH_NFIRST
if (hline <= hismin)
#else
if (hline < hismin)
#endif
{
hline = hismin+1;
beep();
#ifndef ESH_NFIRST
continue;
#endif
}
goto common;
case cntl('O') :
location.hist_command = hline;
location.hist_line = hloff;
ep->CntrlO = 1;
c = '\n';
goto process;
case cntl('N') :
#ifdef ESH_NFIRST
hline = location.hist_command;
hloff = location.hist_line;
#endif
location = hist_locate(sh.hist_ptr,hline,hloff,count);
if (location.hist_command > histlines)
{
beep();
#ifdef ESH_NFIRST
location.hist_command = histlines;
location.hist_line = ep->in_mult;
#else
continue;
#endif
}
hline = location.hist_command;
hloff = location.hist_line;
common:
#ifdef ESH_NFIRST
location.hist_command = hline;
location.hist_line = hloff;
#endif
hist_copy((char*)out,MAXLINE, hline,hloff);
#if SHOPT_MULTIBYTE
ed_internal((char*)(out),out);
#endif
drawline:
eol = genlen(out);
cur = eol;
draw(ep,UPDATE);
continue;
}
}
process:
if (c == (-1))
{
lookahead = 0;
beep();
*out = '\0';
}
draw(ep,FINAL);
tty_cooked(ERRIO);
if(ed->e_nlist)
{
ed->e_nlist = 0;
stakset(ed->e_stkptr,ed->e_stkoff);
}
if(c == '\n')
{
out[eol++] = '\n';
out[eol] = '\0';
ed_crlf(ep->ed);
}
#if SHOPT_MULTIBYTE
ed_external(out,buff);
#endif
i = strlen(buff);
if (i)
return(i);
return(-1);
}
static void show_info(Emacs_t *ep,const char *str)
{
register genchar *out = drawbuff;
register int c;
genchar string[LBUF];
int sav_cur = cur;
genncpy(string,out,sizeof(string)/sizeof(*string));
*out = 0;
cur = 0;
#if SHOPT_MULTIBYTE
ed_internal(str,out);
#else
gencpy(out,str);
#endif
draw(ep,UPDATE);
c = ed_getchar(ep->ed,0);
if(c!=' ')
ed_ungetchar(ep->ed,c);
cur = sav_cur;
genncpy(out,string,sizeof(string)/sizeof(*string));
draw(ep,UPDATE);
}
static void putstring(Emacs_t* ep,register char *sp)
{
register int c;
while (c= *sp++)
putchar(ep->ed,c);
}
static int escape(register Emacs_t* ep,register genchar *out,int count)
{
register int i,value;
int digit,ch;
digit = 0;
value = 0;
while ((i=ed_getchar(ep->ed,0)),isdigit(i))
{
value *= 10;
value += (i - '0');
digit = 1;
}
if (digit)
{
ed_ungetchar(ep->ed,i) ;
#ifdef ESH_KAPPEND
++killing;
#endif
return(value);
}
value = count;
if(value<0)
value = 1;
switch(ch=i)
{
case cntl('V'):
show_info(ep,fmtident(e_version));
return(-1);
case ' ':
ep->mark = cur;
return(-1);
#ifdef ESH_KAPPEND
case '+':
killing = 2;
return -1;
#endif
case 'p':
ed_ungetchar(ep->ed,cntl('Y'));
ed_ungetchar(ep->ed,cntl('W'));
#ifdef ESH_KAPPEND
killing = 0;
#endif
return(-1);
case 'l':
case 'd':
case 'c':
case 'f':
{
i = cur;
while(value-- && i<eol)
{
while ((out[i])&&(!isword(i)))
i++;
while ((out[i])&&(isword(i)))
i++;
}
if(ch=='l')
{
value = i-cur;
while (value-- > 0)
{
i = out[cur];
#if SHOPT_MULTIBYTE
if((i&~STRIP)==0 && isupper(i))
#else
if(isupper(i))
#endif
{
i += 'a' - 'A';
out[cur] = i;
}
cur++;
}
draw(ep,UPDATE);
return(-1);
}
else if(ch=='f')
goto update;
else if(ch=='c')
{
ed_ungetchar(ep->ed,cntl('C'));
return(i-cur);
}
else
{
if (i-cur)
{
ed_ungetchar(ep->ed,cntl('D'));
#ifdef ESH_KAPPEND
++killing;
#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
{
ed_ungetchar(ep->ed,usrerase);
#ifdef ESH_KAPPEND
++killing;
#endif
return(cur-i);
}
}
case '>':
ed_ungetchar(ep->ed,cntl('N'));
#ifdef ESH_NFIRST
if (ep->in_mult)
{
location.hist_command = histlines;
location.hist_line = ep->in_mult - 1;
}
else
{
location.hist_command = histlines - 1;
location.hist_line = 0;
}
#else
hline = histlines-1;
hloff = 0;
#endif
return(0);
case '<':
ed_ungetchar(ep->ed,cntl('P'));
hloff = 0;
#ifdef ESH_NFIRST
hline = hismin + 1;
return 0;
#else
return(hline-hismin);
#endif
case '#':
ed_ungetchar(ep->ed,'\n');
ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
ed_ungetchar(ep->ed,cntl('A'));
return(-1);
case '_' :
case '.' :
{
genchar name[MAXLINE];
char buf[MAXLINE];
char *ptr;
ptr = hist_word(buf,MAXLINE,(count?count:-1));
#if !KSHELL
if(ptr==0)
{
beep();
break;
}
#endif
if ((eol - cur) >= sizeof(name))
{
beep();
return(-1);
}
ep->mark = cur;
gencpy(name,&out[cur]);
while(*ptr)
{
out[cur++] = *ptr++;
eol++;
}
gencpy(&out[cur],name);
draw(ep,UPDATE);
return(-1);
}
#if KSHELL
case cntl('[') :
i = '\\';
case '*':
case '=':
ep->mark = cur;
if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
{
if(ep->ed->e_tabcount==1)
{
ep->ed->e_tabcount=2;
ed_ungetchar(ep->ed,cntl('\t'));
return(-1);
}
beep();
}
else if(i=='=')
{
draw(ep,REFRESH);
if(count>0)
ep->ed->e_tabcount=0;
else
{
i=ed_getchar(ep->ed,0);
ed_ungetchar(ep->ed,i);
if(isdigit(i))
ed_ungetchar(ep->ed,ESC);
}
}
else
{
if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
ep->ed->e_tabcount=0;
draw(ep,UPDATE);
}
return(-1);
case cntl(']'):
{
int c = ed_getchar(ep->ed,1);
if ((value == 0) || (value > eol))
{
beep();
return(-1);
}
i = cur;
if (i > 0)
i--;
while (i >= 0)
{
if (out[i] == c && --value==0)
goto update;
i--;
}
i = eol;
while (i > cur)
{
if (out[i] == c && --value==0)
break;
i--;
};
}
update:
cur = i;
draw(ep,UPDATE);
return(-1);
#ifdef _cmd_tput
case cntl('L'):
sh_trap("tput clear", 0);
draw(ep,REFRESH);
return(-1);
#endif
case '[':
switch(i=ed_getchar(ep->ed,1))
{
case 'A':
ed_ungetchar(ep->ed,cntl('P'));
return(-1);
case 'B':
ed_ungetchar(ep->ed,cntl('N'));
return(-1);
case 'C':
ed_ungetchar(ep->ed,cntl('F'));
return(-1);
case 'D':
ed_ungetchar(ep->ed,cntl('B'));
return(-1);
case 'H':
ed_ungetchar(ep->ed,cntl('A'));
return(-1);
case 'Y':
ed_ungetchar(ep->ed,cntl('E'));
return(-1);
default:
ed_ungetchar(ep->ed,i);
}
i = '_';
default:
if(ed_macro(ep->ed,i))
# ifdef ESH_BETTER
return(count);
# else
return(-1);
# endif
#else
update:
cur = i;
draw(ep,UPDATE);
return(-1);
default:
#endif
beep();
return(-1);
}
}
static void xcommands(register Emacs_t *ep,int count)
{
register int i = ed_getchar(ep->ed,0);
NOT_USED(count);
switch(i)
{
case cntl('X'):
if (ep->mark > eol)
ep->mark = eol;
i = ep->mark;
ep->mark = cur;
cur = i;
draw(ep,UPDATE);
return;
#if KSHELL
# ifdef ESH_BETTER
case cntl('E'):
if(ed_fulledit(ep->ed)==-1)
beep();
else
{
#if SHOPT_MULTIBYTE
ed_internal((char*)drawbuff,drawbuff);
#endif
ed_ungetchar(ep->ed,'\n');
}
return;
# define itos(i) fmtbase((long)(i),0,0)
case cntl('H'):
{
char hbuf[MAXLINE];
strcpy(hbuf, "Current command ");
strcat(hbuf, itos(hline));
if (hloff)
{
strcat(hbuf, " (line ");
strcat(hbuf, itos(hloff+1));
strcat(hbuf, ")");
}
if ((hline != location.hist_command) ||
(hloff != location.hist_line))
{
strcat(hbuf, "; Previous command ");
strcat(hbuf, itos(location.hist_command));
if (location.hist_line)
{
strcat(hbuf, " (line ");
strcat(hbuf, itos(location.hist_line+1));
strcat(hbuf, ")");
}
}
show_info(ep,hbuf);
return;
}
# if 0
case cntl('D'):
{
char debugbuf[MAXLINE];
strcpy(debugbuf, "count=");
strcat(debugbuf, itos(count));
strcat(debugbuf, " eol=");
strcat(debugbuf, itos(eol));
strcat(debugbuf, " cur=");
strcat(debugbuf, itos(cur));
strcat(debugbuf, " crallowed=");
strcat(debugbuf, itos(crallowed));
strcat(debugbuf, " plen=");
strcat(debugbuf, itos(plen));
strcat(debugbuf, " w_size=");
strcat(debugbuf, itos(w_size));
show_info(ep,debugbuf);
return;
}
# endif
# endif
#endif
default:
beep();
return;
}
}
static void search(Emacs_t* ep,genchar *out,int direction)
{
#ifndef ESH_NFIRST
Histloc_t location;
#endif
register int i,sl;
genchar str_buff[LBUF];
register genchar *string = drawbuff;
int sav_cur = cur;
genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
string[0] = '^';
string[1] = 'R';
string[2] = '\0';
sl = 2;
cur = sl;
draw(ep,UPDATE);
while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
{
if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
{
if (sl > 2)
{
string[--sl] = '\0';
cur = sl;
draw(ep,UPDATE);
}
else
beep();
continue;
}
if (i==usrkill)
{
beep();
goto restore;
}
if (i == '\\')
{
string[sl++] = '\\';
string[sl] = '\0';
cur = sl;
draw(ep,APPEND);
i = ed_getchar(ep->ed,1);
string[--sl] = '\0';
}
string[sl++] = i;
string[sl] = '\0';
cur = sl;
draw(ep,APPEND);
}
i = genlen(string);
if (direction < 1)
{
ep->prevdirection = -ep->prevdirection;
direction = 1;
}
else
direction = -1;
if (i != 2)
{
#if SHOPT_MULTIBYTE
ed_external(string,(char*)string);
#endif
strncpy(lstring,((char*)string)+2,SEARCHSIZE);
ep->prevdirection = direction;
}
else
direction = ep->prevdirection ;
location = hist_find(sh.hist_ptr,(char*)lstring,hline,1,direction);
i = location.hist_command;
if(i>0)
{
hline = i;
#ifdef ESH_NFIRST
hloff = location.hist_line = 0;
#else
hloff = location.hist_line;
#endif
hist_copy((char*)out,MAXLINE, hline,hloff);
#if SHOPT_MULTIBYTE
ed_internal((char*)out,out);
#endif
return;
}
if (i < 0)
{
beep();
#ifdef ESH_NFIRST
location.hist_command = hline;
location.hist_line = hloff;
#else
hloff = 0;
hline = histlines;
#endif
}
restore:
genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
cur = sav_cur;
return;
}
static void draw(register Emacs_t *ep,Draw_t option)
{
#define NORMAL ' '
#define LOWER '<'
#define BOTH '*'
#define UPPER '>'
register genchar *sptr;
genchar nscreen[2*MAXLINE];
genchar *ncursor;
register genchar *nptr;
char longline;
genchar *logcursor;
genchar *nscend;
register int i;
nptr = nscreen;
sptr = drawbuff;
logcursor = sptr + cur;
longline = NORMAL;
if (option == FIRST || option == REFRESH)
{
ep->overflow = NORMAL;
ep->cursor = ep->screen;
ep->offset = 0;
ep->cr_ok = crallowed;
if (option == FIRST)
{
ep->scvalid = 1;
return;
}
*ep->cursor = '\0';
putstring(ep,Prompt);
}
if ((lookahead)&&(option != FINAL))
{
ep->scvalid = 0;
return;
}
i = *(logcursor-1);
if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&&
print(i)&&((ep->cursor-ep->screen)<(w_size-1)))
{
putchar(ep->ed,i);
*ep->cursor++ = i;
*ep->cursor = '\0';
return;
}
ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0);
nptr += genlen(nptr);
sptr += genlen(sptr);
nscend = nptr - 1;
if(sptr == logcursor)
ncursor = nptr;
i = ncursor - nscreen;
if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
{
ep->offset = i - (w_size>>1);
if (--ep->offset < 0)
ep->offset = 0;
}
nptr = &nscreen[ep->offset];
sptr = ep->screen;
i = w_size;
while (i-- > 0)
{
if (*nptr == '\0')
{
*(nptr + 1) = '\0';
*nptr = ' ';
}
if (*sptr == '\0')
{
*(sptr + 1) = '\0';
*sptr = ' ';
}
if (*nptr == *sptr)
{
nptr++;
sptr++;
continue;
}
setcursor(ep,sptr-ep->screen,*nptr);
*sptr++ = *nptr++;
#if SHOPT_MULTIBYTE
while(*nptr==MARKER)
{
if(*sptr=='\0')
*(sptr + 1) = '\0';
*sptr++ = *nptr++;
i--;
ep->cursor++;
}
#endif
}
if (nscend >= &nscreen[ep->offset+w_size])
{
if (ep->offset > 0)
longline = BOTH;
else
longline = UPPER;
}
else
{
if (ep->offset > 0)
longline = LOWER;
}
if (longline != ep->overflow)
{
setcursor(ep,w_size,longline);
ep->overflow = longline;
}
i = (ncursor-nscreen) - ep->offset;
setcursor(ep,i,0);
if(option==FINAL && ep->ed->e_multiline)
setcursor(ep,nscend-nscreen,0);
ep->scvalid = 1;
return;
}
static void setcursor(register Emacs_t *ep,register int newp,int c)
{
register int oldp = ep->cursor - ep->screen;
newp = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0);
if(c)
{
putchar(ep->ed,c);
newp++;
}
ep->cursor = ep->screen+newp;
return;
}
#if SHOPT_MULTIBYTE
static int print(register int c)
{
return((c&~STRIP)==0 && isprint(c));
}
static int _isword(register int c)
{
return((c&~STRIP) || isalnum(c) || c=='_');
}
#endif