summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/edit/emacs.c
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2020-12-27 17:47:37 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-01-30 17:13:33 +0000
commitb30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch)
tree6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libshell/common/edit/emacs.c
parentdf36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff)
downloadillumos-gate-b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f.tar.gz
13405 ksh93 update to 2012-08-01
13434 sh: mishandles backslash as last character of a block of input 11750 ksh mkdir builtin doesn't honor special file permissions 9199 ksh93 builtin *grep -v mishandles blank lines, blows up libgcrypt-config 6756 sh (and ksh) have issues with ${1+"$@"} 6520 ksh: sleep could wait forever 4860 ksh93: core in printf 3791 /bin/sh's builtin 'rm' busted: 'rm -f' without arguments returns error 1047 ksh overwrites child core files 880 ksh93 coredumps on 'unset' 499 "interrupted system call" when using "tee" builtin in ksh Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Dominik Hassler <hadfl@omnios.org> Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libshell/common/edit/emacs.c')
-rw-r--r--usr/src/lib/libshell/common/edit/emacs.c1487
1 files changed, 0 insertions, 1487 deletions
diff --git a/usr/src/lib/libshell/common/edit/emacs.c b/usr/src/lib/libshell/common/edit/emacs.c
deleted file mode 100644
index be96eb1af4..0000000000
--- a/usr/src/lib/libshell/common/edit/emacs.c
+++ /dev/null
@@ -1,1487 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1982-2010 AT&T Intellectual Property *
-* and is licensed under the *
-* Common Public License, Version 1.0 *
-* by AT&T Intellectual Property *
-* *
-* A copy of the License is available at *
-* http://www.opensource.org/licenses/cpl1.0.txt *
-* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
-* *
-* Information and Software Systems Research *
-* AT&T Research *
-* Florham Park NJ *
-* *
-* David Korn <dgk@research.att.com> *
-* *
-***********************************************************************/
-#pragma prototyped
-/* Original version by Michael T. Veach
- * Adapted for ksh by David Korn */
-/* EMACS_MODES: c tabstop=4
-
-One line screen editor for any program
-
-*/
-
-
-/* The following is provided by:
- *
- * Matthijs N. Melchior
- * AT&T Network Systems International
- * APT Nederland
- * HV BZ335 x2962
- * hvlpb!mmelchio
- *
- * These are now on by default
- *
- * 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.
- */
-
-#include <ast.h>
-#include "FEATURE/cmds"
-#if KSHELL
-# include "defs.h"
-#else
-# include <ctype.h>
-#endif /* KSHELL */
-#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 /*SHOPT_MULTIBYTE */
-
-typedef struct _emacs_
-{
- genchar *screen; /* pointer to window buffer */
- genchar *cursor; /* Cursor in real screen */
- int mark;
- int in_mult;
- char cr_ok;
- char CntrlO;
- char overflow; /* Screen overflow flag set */
- char scvalid; /* Screen is up to date */
- char lastdraw; /* last update type */
- int offset; /* Screen offset */
- enum
- {
- CRT=0, /* Crt terminal */
- PAPER /* Paper terminal */
- } terminal;
- Histloc_t _location;
- int prevdirection;
- Edit_t *ed; /* pointer to edit data */
-} 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)
-
-/**********************
-A large lookahead helps when the user is inserting
-characters in the middle of the line.
-************************/
-
-
-typedef enum
-{
- FIRST, /* First time thru for logical line, prompt on screen */
- REFRESH, /* Redraw entire screen */
- APPEND, /* Append char before cursor to screen */
- UPDATE, /* Update the screen as need be */
- FINAL /* Update screen even if pending look ahead */
-} 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;
- ep->lastdraw = FINAL;
- if(tty_raw(ERRIO,0) < 0)
- {
- return(reedit?reedit:ed_read(context, fd,buff,scend,0));
- }
- raw = 1;
- /* This mess in case the read system call fails */
-
- ed_setup(ep->ed,fd,reedit);
- out = (genchar*)buff;
-#if SHOPT_MULTIBYTE
- out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
- if(reedit)
- ed_internal(buff,out);
-#endif /* SHOPT_MULTIBYTE */
- if(!kstack)
- {
- kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
- kstack[0] = '\0';
- }
- drawbuff = out;
-#ifdef ESH_NFIRST
- if (location.hist_command == -5) /* to be initialized */
- {
- kstack[0] = '\0'; /* also clear kstack... */
- location.hist_command = hline;
- location.hist_line = hloff;
- }
- if (location.hist_command <= hismin) /* don't start below minimum */
- {
- location.hist_command = hismin + 1;
- location.hist_line = 0;
- }
- ep->in_mult = hloff; /* save pos in last command */
-#endif /* ESH_NFIRST */
- i = sigsetjmp(env,0);
- if (i !=0)
- {
- if(ep->ed->e_multiline)
- {
- cur = eol;
- draw(ep,FINAL);
- ed_flush(ep->ed);
- }
- tty_cooked(ERRIO);
- if (i == UEOF)
- {
- return(0); /* EOF */
- }
- return(-1); /* some other error */
- }
- 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 /* SHOPT_MULTIBYTE */
- ed_ungetchar(ep->ed,cntl('Y'));
- }
-#endif /* ESH_NFIRST */
- }
- 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')))
- {
- /* accept a backslashed character */
- 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) /* reset killing flag */
- 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 /* u370 */
- 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;
- }
- /* FALLTHROUGH */
- do_default_processing:
- default:
-
- if ((eol+1) >= (scend)) /* will not fit on line */
- {
- ed_ungetchar(ep->ed,c); /* save character for next line */
- 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: /* delete char 0x7f */
- case '\b': /* backspace, ^h */
- case ERASECHAR :
- if (count > i)
- count = i;
-#ifdef ESH_KAPPEND
- kptr = &kstack[count]; /* move old contents here */
- if (killing) /* prepend to killbuf */
- {
- c = genlen(kstack) + CHARSIZE; /* include '\0' */
- while(c--) /* copy stuff */
- kptr[c] = kstack[c];
- }
- else
- *kptr = 0; /* this is end of data */
- killing = 2; /* we are killing */
- 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 /* ESH_KAPPEND */
- gencpy(out+i,out+cur);
- ep->mark = i;
- goto update;
- case cntl('W') :
-#ifdef ESH_KAPPEND
- ++killing; /* keep killing flag */
-#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)]; /* append here */
- else
- kptr = kstack;
- killing = 2; /* we are now killing */
-#else
- kptr = kstack;
-#endif /* ESH_KAPPEND */
- 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 /* SHOPT_MULTIBYTE */
- {
- 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;
- /* FALLTHROUGH */
- case cntl('K') :
- if(oadjust >= 0)
- {
-#ifdef ESH_KAPPEND
- killing = 2; /* set killing signal */
-#endif
- ep->mark = count;
- ed_ungetchar(ep->ed,cntl('W'));
- continue;
- }
- i = cur;
- eol = i;
- ep->mark = i;
-#ifdef ESH_KAPPEND
- if (killing) /* append to kill buffer */
- gencpy(&kstack[genlen(kstack)], &out[i]);
- else
- gencpy(kstack,&out[i]);
- killing = 2; /* set killing signal */
-#else
- gencpy(kstack,&out[i]);
-#endif /* ESH_KAPPEND */
- 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'):
- if(!ep->ed->e_nocrnl)
- ed_crlf(ep->ed);
- draw(ep,REFRESH);
- ep->ed->e_nocrnl = 0;
- 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 /* ESH_NFIRST */
- {
- 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; /* start at saved position */
- hloff = location.hist_line;
-#endif /* ESH_NFIRST */
- 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 /* ESH_NFIRST */
- }
- hline = location.hist_command;
- hloff = location.hist_line;
- common:
-#ifdef ESH_NFIRST
- location.hist_command = hline; /* save current position */
- location.hist_line = hloff;
-#endif
- cur = 0;
- draw(ep,UPDATE);
- hist_copy((char*)out,MAXLINE, hline,hloff);
-#if SHOPT_MULTIBYTE
- ed_internal((char*)(out),out);
-#endif /* SHOPT_MULTIBYTE */
- 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 /* SHOPT_MULTIBYTE */
- 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;
- /* save current line */
- genncpy(string,out,sizeof(string)/sizeof(*string));
- *out = 0;
- cur = 0;
-#if SHOPT_MULTIBYTE
- ed_internal(str,out);
-#else
- gencpy(out,str);
-#endif /* SHOPT_MULTIBYTE */
- draw(ep,UPDATE);
- c = ed_getchar(ep->ed,0);
- if(c!=' ')
- ed_ungetchar(ep->ed,c);
- /* restore line */
- 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; /* don't modify killing signal */
-#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 '+': /* M-+ = append next kill */
- killing = 2;
- return -1; /* no argument for next command */
-#endif
-
- case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
- ed_ungetchar(ep->ed,cntl('Y'));
- ed_ungetchar(ep->ed,cntl('W'));
-#ifdef ESH_KAPPEND
- killing = 0; /* start fresh */
-#endif
- return(-1);
-
- case 'l': /* M-l == lower-case */
- 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 /* SHOPT_MULTIBYTE */
- {
- 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; /* 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
- {
- 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 /* ESH_NFIRST */
- return(0);
-
- case '<':
- ed_ungetchar(ep->ed,cntl('P'));
- hloff = 0;
-#ifdef ESH_NFIRST
- hline = hismin + 1;
- return 0;
-#else
- return(hline-hismin);
-#endif /* ESH_NFIRST */
-
-
- 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(ptr==0)
- {
- beep();
- break;
- }
- 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
-
- /* file name expansion */
- case cntl('[') : /* filename completion */
- i = '\\';
- /* FALLTHROUGH */
- case '*': /* filename expansion */
- case '=': /* escape = - list all matching file names */
- 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);
-
- /* search back for character */
- case cntl(']'): /* feature not in book */
- {
- 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'): /* clear screen */
- sh_trap("tput clear", 0);
- draw(ep,REFRESH);
- return(-1);
-#endif
- case '[': /* feature not in book */
- switch(i=ed_getchar(ep->ed,1))
- {
- case 'A':
- if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
- {
- if(ep->lastdraw==APPEND && ep->prevdirection != -2)
- {
- out[cur] = 0;
- gencpy(&((genchar*)lstring)[1],out);
-#if SHOPT_MULTIBYTE
- ed_external(&((genchar*)lstring)[1],lstring+1);
-#endif /* SHOPT_MULTIBYTE */
- *lstring = '^';
- ep->prevdirection = -2;
- }
- if(*lstring)
- {
- ed_ungetchar(ep->ed,'\r');
- ed_ungetchar(ep->ed,cntl('R'));
- return(-1);
- }
- }
- *lstring = 0;
- 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 = '_';
- /* FALLTHROUGH */
-
- default:
- /* look for user defined macro definitions */
- if(ed_macro(ep->ed,i))
-# ifdef ESH_BETTER
- return(count); /* pass argument to macro */
-# else
- return(-1);
-# endif /* ESH_BETTER */
-#else
- update:
- cur = i;
- draw(ep,UPDATE);
- return(-1);
-
- default:
-#endif /* KSHELL */
- beep();
- return(-1);
- }
- return(-1);
-}
-
-
-/*
- * This routine process all commands starting with ^X
- */
-
-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'): /* exchange dot and mark */
- 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'): /* invoke emacs on current command */
- if(ed_fulledit(ep->ed)==-1)
- beep();
- else
- {
-#if SHOPT_MULTIBYTE
- ed_internal((char*)drawbuff,drawbuff);
-#endif /* SHOPT_MULTIBYTE */
- ed_ungetchar(ep->ed,'\n');
- }
- return;
-
-# define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */
-
- case cntl('H'): /* ^X^H show history info */
- {
- 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 /* debugging, modify as required */
- case cntl('D'): /* ^X^D show debugging info */
- {
- 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 /* debugging code */
-# endif /* ESH_BETTER */
-#endif /* KSHELL */
-
- 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;
- /* save current line */
- 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(ep->prevdirection == -2 && i!=2 || direction!=1)
- ep->prevdirection = -1;
- if (direction < 1)
- {
- ep->prevdirection = -ep->prevdirection;
- direction = 1;
- }
- else
- direction = -1;
- if (i != 2)
- {
-#if SHOPT_MULTIBYTE
- ed_external(string,(char*)string);
-#endif /* SHOPT_MULTIBYTE */
- 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; /* display first line of multi line command */
-#else
- hloff = location.hist_line;
-#endif /* ESH_NFIRST */
- hist_copy((char*)out,MAXLINE, hline,hloff);
-#if SHOPT_MULTIBYTE
- ed_internal((char*)out,out);
-#endif /* SHOPT_MULTIBYTE */
- return;
- }
- if (i < 0)
- {
- beep();
-#ifdef ESH_NFIRST
- location.hist_command = hline;
- location.hist_line = hloff;
-#else
- hloff = 0;
- hline = histlines;
-#endif /* ESH_NFIRST */
- }
-restore:
- genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
- cur = sav_cur;
- 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 draw(register Emacs_t *ep,Draw_t option)
-{
-#define NORMAL ' '
-#define LOWER '<'
-#define BOTH '*'
-#define UPPER '>'
-
- register genchar *sptr; /* Pointer within screen */
- genchar nscreen[2*MAXLINE]; /* New entire screen */
- genchar *ncursor; /* New cursor */
- register genchar *nptr; /* Pointer to New screen */
- char longline; /* Line overflow */
- genchar *logcursor;
- genchar *nscend; /* end of logical screen */
- register int i;
-
- nptr = nscreen;
- sptr = drawbuff;
- logcursor = sptr + cur;
- longline = NORMAL;
- ep->lastdraw = option;
-
- 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); /* start with prompt */
- }
-
- /*********************
- Do not update screen if pending characters
- **********************/
-
- if ((lookahead)&&(option != FINAL))
- {
-
- ep->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.
- *****************************************/
-
-
- i = *(logcursor-1); /* last character inserted */
-
- 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;
- }
-
- /* copy the line */
- 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;
-
- /*********************
- Does ncursor appear on the screen?
- If not, adjust the screen offset so it does.
- **********************/
-
- i = ncursor - nscreen;
-
- if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
- {
- /* Center the cursor on the screen */
- ep->offset = i - (w_size>>1);
- if (--ep->offset < 0)
- ep->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.
- ***********************/
-
- 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 /* SHOPT_MULTIBYTE */
- }
- if(ep->ed->e_multiline && option == REFRESH && ep->ed->e_nocrnl==0)
- ed_setcursor(ep->ed, ep->screen, ep->cursor-ep->screen, ep->ed->e_peol, -1);
-
-
- /******************
-
- Screen overflow checks
-
- ********************/
-
- if (nscend >= &nscreen[ep->offset+w_size])
- {
- if (ep->offset > 0)
- longline = BOTH;
- else
- longline = UPPER;
- }
- else
- {
- if (ep->offset > 0)
- longline = LOWER;
- }
-
- /* Update screen overflow indicator if need be */
-
- 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+1-nscreen,0);
- ep->scvalid = 1;
- return;
-}
-
-/*
- * put the cursor to the <newp> position within screen buffer
- * if <c> is non-zero then output this character
- * cursor is set to reflect the change
- */
-
-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 /* SHOPT_MULTIBYTE */