2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: emacs.c /main/3 1995/11/01 16:35:06 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF *
29 * AT&T BELL LABORATORIES *
30 * AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN *
31 * ACCORDANCE WITH APPLICABLE AGREEMENTS *
33 * Copyright (c) 1995 AT&T Corp. *
34 * Unpublished & Not for Publication *
35 * All Rights Reserved *
37 * The copyright notice above does not evidence any *
38 * actual or intended publication of such source code *
40 * This software was created by the *
41 * Advanced Software Technology Department *
42 * AT&T Bell Laboratories *
44 * For further information contact *
45 * {research,attmail}!dgk *
47 ***************************************************************/
49 /* : : generated by proto : : */
51 #if !defined(__PROTO__)
52 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
53 #if defined(__cplusplus)
54 #define __MANGLE__ "C"
59 #define __PROTO__(x) x
61 #define __PARAM__(n,o) n
62 #if !defined(__STDC__) && !defined(__cplusplus)
63 #if !defined(c_plusplus)
74 #define __PROTO__(x) ()
75 #define __OTORP__(x) x
76 #define __PARAM__(n,o) o
84 #if defined(__cplusplus) || defined(c_plusplus)
85 #define __VARARG__ ...
89 #if defined(__STDARG__)
90 #define __VA_START__(p,a) va_start(p,a)
92 #define __VA_START__(p,a) va_start(p)
104 #include "terminal.h"
111 #define putchar(c) ed_putchar(c)
112 #define beep() ed_ringbell()
115 #ifdef SHOPT_MULTIBYTE
116 # define gencpy(a,b) ed_gencpy(a,b)
117 # define genncpy(a,b,n) ed_genncpy(a,b,n)
118 # define genlen(str) ed_genlen(str)
119 static int print __PROTO__((int));
120 static int isword __PROTO__((int));
123 # define gencpy(a,b) strcpy((char*)(a),(char*)(b))
124 # define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
125 # define genlen(str) strlen(str)
126 # define print(c) isprint(c)
127 # define isword(c) isalnum(out[c])
128 #endif /*SHOPT_MULTIBYTE */
130 #define eol editb.e_eol
131 #define cur editb.e_cur
132 #define mark editb.e_fchar
133 #define hline editb.e_hline
134 #define hloff editb.e_hloff
135 #define hismin editb.e_hismin
136 #define usrkill editb.e_kill
137 #define usreof editb.e_eof
138 #define usrerase editb.e_erase
139 #define crallowed editb.e_crlf
140 #define Prompt editb.e_prompt
141 #define plen editb.e_plen
142 #define kstack editb.e_killbuf
143 #define lstring editb.e_search
144 #define lookahead editb.e_index
145 #define env editb.e_env
146 #define raw editb.e_raw
147 #define histlines editb.e_hismax
148 #define w_size editb.e_wsize
149 #define drawbuff editb.e_inbuf
150 #define killing editb.e_mode
151 #define in_mult editb.e_saved
153 #define KILLCHAR UKILL
154 #define ERASECHAR UERASE
156 #define DELETE '\177'
158 /**********************
159 A large lookahead helps when the user is inserting
160 characters in the middle of the line.
161 ************************/
164 static genchar *screen; /* pointer to window buffer */
165 static genchar *cursor; /* Cursor in real screen */
168 CRT=0, /* Crt terminal */
169 PAPER /* Paper terminal */
174 FIRST, /* First time thru for logical line, prompt on screen */
175 REFRESH, /* Redraw entire screen */
176 APPEND, /* Append char before cursor to screen */
177 UPDATE, /* Update the screen as need be */
178 FINAL /* Update screen even if pending look ahead */
181 static void draw __PROTO__((Draw_t));
182 static int escape __PROTO__((genchar*, int));
183 static void putstring __PROTO__((char*));
184 static void search __PROTO__((genchar*,int));
185 static void setcursor __PROTO__((int, int));
186 static void show_info __PROTO__((const char*));
187 static void xcommands __PROTO__((int));
190 static Histloc_t location = { -5, 0 };
192 ed_emacsread __PARAM__((int fd,char *buff,int scend), (fd, buff, scend)) __OTORP__(int fd;char *buff;int scend;){
195 register genchar *out;
202 genchar Screen[MAXWINDOW];
203 #if KSHELL && (2*CHARSIZE*MAXLINE)<IOBSIZE
204 kstack = buff + MAXLINE*sizeof(genchar);
208 kstack = (genchar*)malloc(sizeof(genchar)*(MAXLINE));
214 drawbuff = out = (genchar*)buff;
215 if(tty_raw(ERRIO,0) < 0)
217 return(ed_read(fd,buff,scend));
220 /* This mess in case the read system call fails */
224 if (location.hist_command == -5) /* to be initialized */
226 kstack[0] = '\0'; /* also clear kstack... */
227 location.hist_command = hline;
228 location.hist_line = hloff;
230 if (location.hist_command <= hismin) /* don't start below minimum */
232 location.hist_command = hismin + 1;
233 location.hist_line = 0;
235 in_mult = hloff; /* save pos in last command */
236 #endif /* ESH_NFIRST */
237 i = sigsetjmp(env,0);
245 return(-1); /* some other error */
248 if(scend+plen > (MAXLINE-2))
249 scend = (MAXLINE-2)-plen;
250 mark = eol = cur = 0;
257 ed_ungetchar(cntl('N'));
259 location = hist_locate(sh.hist_ptr,location.hist_command,location.hist_line,1);
260 if (location.hist_command < histlines)
262 hline = location.hist_command;
263 hloff = location.hist_line;
264 hist_copy((char*)kstack,MAXLINE, hline,hloff);
265 # ifdef SHOPT_MULTIBYTE
266 ed_internal((char*)kstack,kstack);
267 # endif /* SHOPT_MULTIBYTE */
268 ed_ungetchar(cntl('Y'));
270 #endif /* ESH_NFIRST */
273 while ((c = ed_getchar(0)) != (-1))
278 if (c==usrerase||c==usrkill||(!print(c) &&
281 /* accept a backslashed character */
293 else if (c == usrerase)
297 else if ((c == usreof)&&(eol == 0))
302 if (--killing <= 0) /* reset killing flag */
305 oadjust = count = adjust;
313 show_info(&e_version[5]);
331 if ((eol+1) >= (scend)) /* will not fit on line */
333 ed_ungetchar(c); /* save character for next line */
336 for(i= ++eol; i>cur; i--)
338 backslash = (c == '\\');
345 if ((c + eol) > scend)
351 for(i=eol;i>=cur;i--)
365 case DELETE: /* delete char 0x7f */
366 case '\b': /* backspace, ^h */
371 kptr = &kstack[count]; /* move old contents here */
372 if (killing) /* prepend to killbuf */
374 c = genlen(kstack) + CHARSIZE; /* include '\0' */
375 while(c--) /* copy stuff */
379 *kptr = 0; /* this is end of data */
380 killing = 2; /* we are killing */
383 genncpy(kstack,out+i,cur-i);
385 while ((count--)&&(i>0))
390 genncpy(kstack,out+i,cur-i);
392 #endif /* ESH_KAPPEND */
393 gencpy(out+i,out+cur);
398 ++killing; /* keep killing flag */
407 ed_ungetchar(cntl('D'));
411 ed_ungetchar(usrerase);
417 kptr = &kstack[genlen(kstack)]; /* append here */
420 killing = 2; /* we are now killing */
423 #endif /* ESH_KAPPEND */
424 while ((count--)&&(eol>0)&&(i<eol))
430 if ((out[i] = out[(i+1)])==0)
441 int cntlC = (c==cntl('C'));
442 while (count-- && eol>i)
447 #ifdef SHOPT_MULTIBYTE
448 if((c&~STRIP)==0 && islower(c))
451 #endif /* SHOPT_MULTIBYTE */
463 if ((count == 0) || (count > eol))
472 if (out[i] == c && --count==0)
479 if (out[i] == c && --count==0)
495 if ((sh_isoption(SH_EMACS))&& (eol!=i))
505 if(sh_isoption(SH_EMACS))
527 killing = 2; /* set killing signal */
530 ed_ungetchar(cntl('W'));
537 if (killing) /* append to kill buffer */
538 gencpy(&kstack[genlen(kstack)], &out[i]);
540 gencpy(kstack,&out[i]);
541 killing = 2; /* set killing signal */
543 gencpy(kstack,&out[i]);
544 #endif /* ESH_KAPPEND */
549 if (terminal == PAPER)
560 if (terminal == PAPER)
575 adjust = escape(out,oadjust);
585 hline -= count - hloff;
592 #endif /* ESH_NFIRST */
603 location.hist_command = hline;
604 location.hist_line = hloff;
610 hline = location.hist_command; /* start at saved position */
611 hloff = location.hist_line;
612 #endif /* ESH_NFIRST */
613 location = hist_locate(sh.hist_ptr,hline,hloff,count);
614 if (location.hist_command > histlines)
618 location.hist_command = histlines;
619 location.hist_line = in_mult;
622 #endif /* ESH_NFIRST */
624 hline = location.hist_command;
625 hloff = location.hist_line;
628 location.hist_command = hline; /* save current position */
629 location.hist_line = hloff;
631 hist_copy((char*)out,MAXLINE, hline,hloff);
632 #ifdef SHOPT_MULTIBYTE
633 ed_internal((char*)(out),out);
634 #endif /* SHOPT_MULTIBYTE */
660 #ifdef SHOPT_MULTIBYTE
661 ed_external(out,buff);
662 #endif /* SHOPT_MULTIBYTE */
669 static void show_info __PARAM__((const char *str), (str)) __OTORP__(const char *str;){
670 register genchar *out = drawbuff;
672 genchar string[LBUF];
674 /* save current line */
675 genncpy(string,out,sizeof(string)/CHARSIZE-1);
678 #ifdef SHOPT_MULTIBYTE
679 ed_internal(str,out);
682 #endif /* SHOPT_MULTIBYTE */
689 genncpy(out,string,sizeof(string)/CHARSIZE-1);
693 static void putstring __PARAM__((register char *sp), (sp)) __OTORP__(register char *sp;){
700 static int escape __PARAM__((register genchar *out,int count), (out, count)) __OTORP__(register genchar *out;int count;){
701 register int i,value;
705 while ((i=ed_getchar(0)),isdigit(i))
715 ++killing; /* don't modify killing signal */
729 case '+': /* M-+ = append next kill */
731 return -1; /* no argument for next command */
734 case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
735 ed_ungetchar(cntl('Y'));
736 ed_ungetchar(cntl('W'));
738 killing = 0; /* start fresh */
742 case 'l': /* M-l == lower-case */
748 while(value-- && i<eol)
750 while ((out[i])&&(!isword(i)))
752 while ((out[i])&&(isword(i)))
761 #ifdef SHOPT_MULTIBYTE
762 if((i&~STRIP)==0 && isupper(i))
765 #endif /* SHOPT_MULTIBYTE */
780 ed_ungetchar(cntl('C'));
787 ed_ungetchar(cntl('D'));
789 ++killing; /* keep killing signal */
805 while(value-- && i>0)
808 while ((i>0)&&(!isword(i)))
810 while ((i>0)&&(isword(i-1)))
817 ed_ungetchar(usrerase);
826 ed_ungetchar(cntl('N'));
830 location.hist_command = histlines;
831 location.hist_line = in_mult - 1;
835 location.hist_command = histlines - 1;
836 location.hist_line = 0;
841 #endif /* ESH_NFIRST */
845 ed_ungetchar(cntl('P'));
851 return(hline-hismin);
852 #endif /* ESH_NFIRST */
857 ed_ungetchar((out[0]=='#')?cntl('D'):'#');
858 ed_ungetchar(cntl('A'));
863 genchar name[MAXLINE];
866 ptr = hist_word(buf,MAXLINE,(count?count:-1));
874 if ((eol - cur) >= sizeof(name))
880 gencpy(name,&out[cur]);
886 gencpy(&out[cur],name);
892 /* file name expansion */
893 case cntl('[') : /* filename completion */
895 case '*': /* filename expansion */
896 case '=': /* escape = - list all matching file names */
898 if(ed_expand((char*)out,&cur,&eol,i) < 0)
906 /* search back for character */
907 case cntl(']'): /* feature not in book */
909 int c = ed_getchar(1);
910 if ((value == 0) || (value > eol))
920 if (out[i] == c && --value==0)
927 if (out[i] == c && --value==0)
938 case '[': /* feature not in book */
942 /* look for user defined macro definitions */
945 return(count); /* pass argument to macro */
948 # endif /* ESH_BETTER */
964 * This routine process all commands starting with ^X
967 static void xcommands __PARAM__((int count), (count)) __OTORP__(int count;){
968 register int i = ed_getchar(0);
972 case cntl('X'): /* exchange dot and mark */
983 case cntl('E'): /* invoke emacs on current command */
984 if(ed_fulledit()==-1)
990 # define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */
992 case cntl('H'): /* ^X^H show history info */
996 strcpy(hbuf, "Current command ");
997 strcat(hbuf, itos(hline));
1000 strcat(hbuf, " (line ");
1001 strcat(hbuf, itos(hloff+1));
1004 if ((hline != location.hist_command) ||
1005 (hloff != location.hist_line))
1007 strcat(hbuf, "; Previous command ");
1008 strcat(hbuf, itos(location.hist_command));
1009 if (location.hist_line)
1011 strcat(hbuf, " (line ");
1012 strcat(hbuf, itos(location.hist_line+1));
1019 # if 0 /* debugging, modify as required */
1020 case cntl('D'): /* ^X^D show debugging info */
1022 char debugbuf[MAXLINE];
1024 strcpy(debugbuf, "count=");
1025 strcat(debugbuf, itos(count));
1026 strcat(debugbuf, " eol=");
1027 strcat(debugbuf, itos(eol));
1028 strcat(debugbuf, " cur=");
1029 strcat(debugbuf, itos(cur));
1030 strcat(debugbuf, " crallowed=");
1031 strcat(debugbuf, itos(crallowed));
1032 strcat(debugbuf, " plen=");
1033 strcat(debugbuf, itos(plen));
1034 strcat(debugbuf, " w_size=");
1035 strcat(debugbuf, itos(w_size));
1037 show_info(debugbuf);
1040 # endif /* debugging code */
1041 # endif /* ESH_BETTER */
1050 static void search __PARAM__((genchar *out,int direction), (out, direction)) __OTORP__(genchar *out;int direction;){
1051 static int prevdirection = 1 ;
1056 genchar str_buff[LBUF];
1057 register genchar *string = drawbuff;
1058 /* save current line */
1060 genncpy(str_buff,string,sizeof(str_buff)/CHARSIZE-1);
1067 while ((i = ed_getchar(1))&&(i != '\r')&&(i != '\n'))
1073 string[--sl] = '\0';
1088 string[sl++] = '\\';
1093 string[--sl] = '\0';
1104 prevdirection = -prevdirection;
1111 #ifdef SHOPT_MULTIBYTE
1112 ed_external(string,(char*)string);
1113 #endif /* SHOPT_MULTIBYTE */
1114 strncpy(lstring,((char*)string)+2,SEARCHSIZE);
1115 prevdirection = direction;
1118 direction = prevdirection ;
1119 location = hist_find(sh.hist_ptr,(char*)lstring,hline,1,direction);
1120 i = location.hist_command;
1125 hloff = location.hist_line = 0; /* display first line of multi line command */
1127 hloff = location.hist_line;
1128 #endif /* ESH_NFIRST */
1129 hist_copy((char*)out,MAXLINE, hline,hloff);
1130 #ifdef SHOPT_MULTIBYTE
1131 ed_internal((char*)out,out);
1132 #endif /* SHOPT_MULTIBYTE */
1139 location.hist_command = hline;
1140 location.hist_line = hloff;
1144 #endif /* ESH_NFIRST */
1147 genncpy(string,str_buff,sizeof(str_buff)/CHARSIZE-1);
1153 /* Adjust screen to agree with inputs: logical line and cursor */
1154 /* If 'first' assume screen is blank */
1155 /* Prompt is always kept on the screen */
1157 static void draw __PARAM__((Draw_t option), (option)) __OTORP__(Draw_t option;){
1163 static char overflow; /* Screen overflow flag set */
1164 register genchar *sptr; /* Pointer within screen */
1166 static int offset; /* Screen offset */
1167 static char scvalid; /* Screen is up to date */
1169 genchar nscreen[2*MAXLINE]; /* New entire screen */
1170 genchar *ncursor; /* New cursor */
1171 register genchar *nptr; /* Pointer to New screen */
1172 char longline; /* Line overflow */
1174 genchar *nscend; /* end of logical screen */
1179 logcursor = sptr + cur;
1182 if (option == FIRST || option == REFRESH)
1188 if (option == FIRST)
1194 putstring(Prompt); /* start with prompt */
1197 /*********************
1198 Do not update screen if pending characters
1199 **********************/
1201 if ((lookahead)&&(option != FINAL))
1204 scvalid = 0; /* Screen is out of date, APPEND will not work */
1209 /***************************************
1210 If in append mode, cursor at end of line, screen up to date,
1211 the previous character was a 'normal' character,
1212 and the window has room for another character.
1213 Then output the character and adjust the screen only.
1214 *****************************************/
1217 i = *(logcursor-1); /* last character inserted */
1219 if ((option == APPEND)&&(scvalid)&&(*logcursor == '\0')&&
1220 print(i)&&((cursor-screen)<(w_size-1)))
1229 ncursor = nptr + ed_virt_to_phys(sptr,nptr,cur,0,0);
1230 nptr += genlen(nptr);
1231 sptr += genlen(sptr);
1233 if(sptr == logcursor)
1236 /*********************
1237 Does ncursor appear on the screen?
1238 If not, adjust the screen offset so it does.
1239 **********************/
1241 i = ncursor - nscreen;
1243 if ((offset && i<=offset)||(i >= (offset+w_size)))
1245 /* Center the cursor on the screen */
1246 offset = i - (w_size>>1);
1251 /*********************
1252 Is the range of screen[0] thru screen[w_size] up-to-date
1253 with nscreen[offset] thru nscreen[offset+w_size] ?
1254 If not, update as need be.
1255 ***********************/
1257 nptr = &nscreen[offset];
1281 setcursor(sptr-screen,*nptr);
1283 #ifdef SHOPT_MULTIBYTE
1284 while(*nptr==MARKER)
1292 #endif /* SHOPT_MULTIBYTE */
1297 Screen overflow checks
1299 ********************/
1301 if (nscend >= &nscreen[offset+w_size])
1314 /* Update screen overflow indicator if need be */
1316 if (longline != overflow)
1318 setcursor(w_size,longline);
1319 overflow = longline;
1321 i = (ncursor-nscreen) - offset;
1328 * put the cursor to the <newp> position within screen buffer
1329 * if <c> is non-zero then output this character
1330 * cursor is set to reflect the change
1333 static void setcursor __PARAM__((register int newp,int c), (newp, c)) __OTORP__(register int newp;int c;){
1334 register int oldp = cursor - screen;
1337 if (!cr_ok || (2*(newp+plen)>(oldp+plen)))
1350 putchar(screen[oldp++]);
1357 cursor = screen+newp;
1361 #ifdef SHOPT_MULTIBYTE
1362 static int print __PARAM__((register int c), (c)) __OTORP__(register int c;){
1363 return((c&~STRIP)==0 && isprint(c));
1366 static int isword __PARAM__((register int i), (i)) __OTORP__(register int i;){
1367 register int c = drawbuff[i];
1368 return((c&~STRIP) || isalnum(c));
1370 #endif /* SHOPT_MULTIBYTE */