1 /*
2
3 * Copyright (c) 1984, 1985, 1986 AT&T
4 * All Rights Reserved
5
6 * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7 * CODE OF AT&T.
8 * The copyright notice above does not
9 * evidence any actual or intended
10 * publication of such source code.
11
12 */
13 /* @(#)emacs.c 1.1 */
14 /* Adapted for ksh by David Korn */
15 /* EMACS_MODES: c tabstop=4
16
17 One line screen editor for any program
18
19
20 Questions and comments should be
21 directed to
22
23 Michael T. Veach
24 IX 1C-341 X1614
25 ihuxl!veach
26
27 */
28 #ifdef DMERT /* 3bcc #undefs RT */
29 #define RT
30 #endif
31
32 #ifdef KSHELL
33 #include "defs.h"
34 #include "io.h"
35 #include "shtype.h"
36
37 #else
38 #include <setjmp.h>
39 #include <stdio.h>
40 #include <signal.h>
41 #include <ctype.h>
42 #endif /* KSHELL */
43
44 #include "history.h"
45 #include "edit.h"
46
47 #undef blank
48 #undef putchar
49 #define putchar(c) e_putchar(c)
50 #define beep() e_ringbell()
51
52
53 #ifdef KSHELL
54 extern void p_flush();
55 extern char *valup();
56
57 #else
58 static char version[] = "@(#)Editlib version 06/03/86";
59 extern unsigned char *_sobuf;
60 #define p_flush() fflush(stderr)
61 #define output stderr
62 #endif /* KSHELL */
63
64 #ifdef MULTIBYTE
65 #define gencpy(a,b) e_gencpy(a,b)
66 #define genncpy(a,b,n) e_genncpy(a,b,n)
67 #define genlen(str) e_genlen(str)
68 static int print();
69 static int isword();
70
71 #else
72 #define gencpy(a,b) strcpy((char*)(a),(char*)(b))
73 #define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
74 #define genlen(str) strlen(str)
75 #define print(c) isprint(c)
76 #define isword(c) isalnum(out[c])
77 #endif /*MULTIBYTE */
78
79 extern histloc hist_find();
80 extern histloc hist_locate();
81 extern char *hist_word();
82 extern char *itos();
83 extern char *strcpy();
84 extern char *strncpy();
85 extern void e_flush();
86 extern int e_getchar();
87 extern void e_putchar();
88 extern void ungetchar();
89
90 #define eol editb.e_eol
91 #define cur editb.e_cur
92 #define mark editb.e_fchar
93 #define hline editb.e_hline
94 #define hloff editb.e_hloff
95 #define hismin editb.e_hismin
96 #define usrkill editb.e_kill
97 #define usreof editb.e_eof
98 #define usrerase editb.e_erase
99 #define crallowed editb.e_crlf
100 #define llimit editb.e_llimit
101 #define Prompt editb.e_prompt
102 #define plen editb.e_plen
103 #define kstack editb.e_tmp
104 #define lstring editb.e_search
105 #define lookahead editb.e_index
106 #define env editb.e_env
107 #define raw editb.e_raw
108 #define histlines editb.e_hismax
109 #define w_size editb.e_wsize
110 #define drawbuff editb.e_inbuf
111 #define NO 0
112 #define YES 1
113 #define LBUF 100
114 #define KILLCHAR UKILL
115 #define ERASECHAR UERASE
116 #define EOFCHAR UEOF
117
118 /**********************
119 A large lookahead helps when the user is inserting
120 characters in the middle of the line.
121 ************************/
122
123
124 static genchar *screen; /* pointer to window buffer */
125 static genchar *cursor; /* Cursor in real screen */
126 static enum
127 {
128 CRT=0, /* Crt terminal */
129 PAPER /* Paper terminal */
130 } terminal ;
131
132 typedef enum
133 {
134 FIRST, /* First time thru for logical line, prompt on screen */
135 REFRESH, /* Redraw entire screen */
136 APPEND, /* Append char before cursor to screen */
137 UPDATE, /* Update the screen as need be */
138 FINAL /* Update screen even if pending look ahead */
139 } DRAWTYPE;
140
141 static void draw();
142 static int escape();
143 static void putstring();
144 static int search();
145 static void setcursor();
146
147 static int cr_ok;
148
hread(fd,buff,scend)149 hread(fd,buff,scend)
150 char *buff;
151 int fd,scend;
152 {
153 register int c;
154 register int i;
155 register genchar *out;
156 register int count;
157 int adjust,oadjust;
158 char backslash;
159 genchar *kptr;
160 static histloc location;
161 static int CntrlO;
162 char prompt[LBUF];
163 genchar stack[MAXLINE];
164 char string[LBUF*CHARSIZE];
165 genchar Screen[MAXWINDOW];
166 Prompt = prompt;
167 kstack = stack;
168 lstring = string;
169 screen = Screen;
170 drawbuff = out = (genchar*)buff;
171 kstack[0] = '\0';
172 if(setraw(fd) < 0)
173 {
174 p_flush();
175 return(read(fd,buff,scend));
176 }
177 raw = 1;
178 /* This mess in case the read system call fails */
179
180 e_setup(fd,LBUF);
181 if ((i=setjmp(env))!=0)
182 {
183 setcooked(fd);
184 if (i == UEOF)
185 {
186 return(0); /* EOF */
187 }
188 return(-1); /* some other error */
189 }
190 #ifdef MULTIBYTE
191 plen = e_internal(&Prompt[1],out); /* Skip the leading \r */
192 #else
193 gencpy(buff,&Prompt[1]); /* Skip the leading \r */
194 #endif /* MULTIBYTE */
195 scend -= plen;
196 llimit = scend;
197 mark = eol = cur = plen;
198 draw(FIRST);
199 adjust = -1;
200 backslash = 0;
201 if (CntrlO)
202 {
203 location = hist_locate(location.his_command,location.his_line,1);
204 if (location.his_command < histlines)
205 {
206 hline = location.his_command;
207 hloff = location.his_line;
208 hist_copy((char*)kstack,hline,hloff);
209 #ifdef MULTIBYTE
210 e_internal((char*)kstack,kstack);
211 #endif /* MULTIBYTE */
212 ungetchar(cntl(Y));
213 }
214 }
215 CntrlO = 0;
216 while ((c = e_getchar()) != (-1))
217 {
218 if (backslash)
219 {
220 backslash = 0;
221 if (c==usrerase||c==usrkill||(!print(c) &&
222 (c!='\r'&&c!='\n')))
223 {
224 /* accept a backslashed character */
225 cur--;
226 out[cur++] = c;
227 out[eol] = '\0';
228 draw(APPEND);
229 continue;
230 }
231 }
232 if (c == usrkill)
233 {
234 c = KILLCHAR ;
235 }
236 else if (c == usrerase)
237 {
238 c = ERASECHAR ;
239 }
240 else if ((c == usreof)&&(eol == plen))
241 {
242 c = EOFCHAR;
243 }
244 oadjust = count = adjust;
245 if(count<0)
246 count = 1;
247 adjust = -1;
248 i = cur;
249 switch(c)
250 {
251 case cntl(V):
252 {
253 genchar string[100];
254 /* save current line */
255 genncpy(string,out,sizeof(string)/CHARSIZE-1);
256 out[plen] = '\0';
257 cur = plen;
258 #ifdef MULTIBYTE
259 e_internal(&version[4],out+plen);
260 #else
261 gencpy(buff+plen,&version[4]);
262 #endif /* MULTIBYTE */
263 draw(UPDATE);
264 c = e_getchar();
265 ungetchar(c);
266 /* restore line */
267 cur = i;
268 genncpy(out,string,sizeof(string)/CHARSIZE-1);
269 draw(UPDATE);
270 }
271 continue;
272 case '\0':
273 mark = i;
274 continue;
275 case cntl(X):
276 i = e_getchar();
277 if (i != cntl(X))
278 {
279 beep();
280 continue;
281 }
282 if (mark > eol)
283 mark = eol;
284 i = mark;
285 mark = cur;
286 goto update;
287 case EOFCHAR:
288 e_flush();
289 setcooked(fd);
290 return(0);
291 #ifdef u370
292 case cntl(S) :
293 case cntl(Q) :
294 continue;
295 #endif /* u370 */
296 default:
297 i = ++eol;
298 if (i >= (scend)) /* will not fit on line */
299 {
300 eol--;
301 ungetchar(c); /* save character for next line */
302 draw(FINAL);
303 goto process;
304 }
305 for(i=eol;i>=cur;i--)
306 {
307 out[i] = out[i-1];
308 }
309 backslash = (c == '\\');
310 out[cur++] = c;
311 draw(APPEND);
312 continue;
313 case cntl(Y) :
314 {
315 c = genlen(kstack);
316 if ((c + eol) > scend)
317 {
318 beep();
319 continue;
320 }
321 mark = i;
322 for(i=eol;i>=cur;i--)
323 out[c+i] = out[i];
324 kptr=kstack;
325 while (i = *kptr++)
326 out[cur++] = i;
327 draw(UPDATE);
328 eol = genlen(out);
329 continue;
330 }
331 case '\n':
332 case '\r':
333 draw(FINAL);
334 out[eol++] = '\n';
335 out[eol] = '\0';
336 e_crlf();
337 goto process;
338 case ERASECHAR :
339 if (count > (i-plen))
340 count = i-plen;
341 while ((count--)&&(i>plen))
342 {
343 i--;
344 eol--;
345 }
346 genncpy(kstack,out+i,cur-i);
347 kstack[cur-i] = 0;
348 gencpy(out+i,out+cur);
349 mark = i;
350 goto update;
351 case cntl(W) :
352 if (mark > eol )
353 mark = eol;
354 if (mark == i)
355 continue;
356 if (mark > i)
357 {
358 adjust = mark - i;
359 ungetchar(cntl(D));
360 continue;
361 }
362 adjust = i - mark;
363 ungetchar('\b');
364 continue;
365 case cntl(D) :
366 mark = i;
367 kptr = kstack;
368 while ((count--)&&(eol>plen)&&(i<eol))
369 {
370 *kptr++ = out[i];
371 eol--;
372 while(1)
373 {
374 if ((out[i] = out[(i+1)])==0)
375 break;
376 i++;
377 }
378 i = cur;
379 }
380 *kptr = '\0';
381 goto update;
382 case cntl(C) :
383 case cntl(F) :
384 {
385 int cntlC = (c==cntl(C));
386 while (count-- && eol>i)
387 {
388 if (cntlC)
389 {
390 c = out[i];
391 #ifdef MULTIBYTE
392 if((c&~STRIP)==0 && islower(c))
393 #else
394 if(islower(c))
395 #endif /* MULTIBYTE */
396 {
397 c += 'A' - 'a';
398 out[i] = c;
399 }
400 }
401 i++;
402 }
403 goto update;
404 }
405 case cntl(]) :
406 c = e_getchar();
407 if (out[i])
408 i++;
409 while (i < eol)
410 {
411 if (out[i] == c)
412 goto update;
413 i++;
414 }
415 i = plen;
416 while (i < cur)
417 {
418 if (out[i] == c)
419 break;
420 i++;
421 };
422
423 update:
424 cur = i;
425 draw(UPDATE);
426 continue;
427
428 case cntl(B) :
429 if (count > (i-plen))
430 count = i - plen;
431 i -= count;
432 goto update;
433 case cntl(T) :
434 if ((is_option(GMACS))||(eol==i))
435 {
436 if (i >= plen + 2)
437 {
438 c = out[i - 1];
439 out[i-1] = out[i-2];
440 out[i-2] = c;
441 }
442 else
443 {
444 beep();
445 continue;
446 }
447 }
448 else
449 {
450 if (eol>(i+1))
451 {
452 c = out[i];
453 out[i] = out[i+1];
454 out[i+1] = c;
455 i++;
456 }
457 else
458 {
459 beep();
460 continue;
461 }
462 }
463 goto update;
464 case cntl(A) :
465 i = plen;
466 goto update;
467 case cntl(E) :
468 i = eol;
469 goto update;
470 case cntl(U) :
471 adjust = 4*count;
472 continue;
473 case KILLCHAR :
474 cur = plen;
475 oadjust = -1;
476 case cntl(K) :
477 if(oadjust >= 0)
478 {
479 mark = plen+count;
480 ungetchar(cntl(W));
481 continue;
482 }
483 i = cur;
484 eol = i;
485 mark = i;
486 gencpy(kstack,&out[i]);
487 out[i] = 0;
488 draw(UPDATE);
489 if (c == KILLCHAR)
490 {
491 if (terminal == PAPER)
492 putstring("\r\n");
493 c = e_getchar();
494 if (c != usrkill)
495 {
496 ungetchar(c);
497 continue;
498 }
499 if (terminal == PAPER)
500 terminal = CRT;
501 else
502 {
503 terminal = PAPER;
504 putstring("\r\n");
505 }
506 }
507 continue;
508 case cntl(L):
509 e_crlf();
510 draw(REFRESH);
511 continue;
512 case cntl([) :
513 adjust = escape(out,oadjust);
514 continue;
515 case cntl(R) :
516 search(out,count);
517 goto drawline;
518 case cntl(P) :
519 location = hist_locate(hline,hloff,-count);
520 hline = location.his_command;
521 if (hline < hismin)
522 {
523 hline = hismin;
524 beep();
525 }
526 goto common;
527
528 case cntl(O) :
529 location.his_command = hline;
530 location.his_line = hloff;
531 CntrlO = 1;
532 draw(FINAL);
533 out[eol++] = '\n';
534 out[eol] = '\0';
535 e_crlf();
536 goto process;
537 case cntl(N) :
538 location = hist_locate(hline,hloff,count);
539 if (location.his_command > histlines)
540 {
541 beep();
542 continue;
543 }
544 hline = location.his_command;
545 common:
546 hloff = location.his_line;
547 hist_copy(&out[plen],hline,hloff);
548 #ifdef MULTIBYTE
549 e_internal((char*)(&out[plen]),&out[plen]);
550 #endif /* MULTIBYTE */
551 drawline:
552 eol = genlen(out);
553 cur = eol;
554 draw(UPDATE);
555 continue;
556 }
557
558 }
559
560 process:
561
562 if (c == (-1))
563 {
564 lookahead = 0;
565 beep();
566 out[plen] = '\0';
567 }
568 gencpy(out,&out[plen]);
569 #ifdef MULTIBYTE
570 e_external(out,buff);
571 #endif /* MULTIBYTE */
572 #ifdef u370
573 putchar('\0');
574 #endif /* u370 */
575 e_flush();
576 setcooked(fd);
577 i = strlen(buff);
578 if (i)
579 return(i);
580 return(-1);
581 }
582
583
584 static void
585 putstring(s)
586 register char *s;
587 {
588 register int c;
589 while (c= *s++)
590 putchar(c);
591 }
592
593
594 static int
595 escape(out,count)
596 register genchar *out;
597 {
598 register int i,value;
599 int digit,ch;
600 digit = 0;
601 value = 0;
602 while ((i=e_getchar()),isdigit(i))
603 {
604 value *= 10;
605 value += (i - '0');
606 digit = 1;
607 }
608 if (digit)
609 {
610 ungetchar(i) ;
611 return(value);
612 }
613 value = count;
614 if(value<0)
615 value = 1;
616 switch(ch=i)
617 {
618 case ' ':
619 mark = cur;
620 return(-1);
621
622 case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
623 ungetchar(cntl(Y));
624 ungetchar(cntl(W));
625 return(-1);
626
627 case 'l': /* M-l == lower-case */
628 case 'd':
629 case 'c':
630 case 'f':
631 {
632 i = cur;
633 while(value-- && i<eol)
634 {
635 while (!isword(i))
636 i++;
637 while ((out[i])&&(isword(i)))
638 i++;
639 }
640 if(ch=='l')
641 {
642 value = i-cur;
643 while (value-- > 0)
644 {
645 i = out[cur];
646 #ifdef MULTIBYTE
647 if((i&~STRIP)==0 && isupper(i))
648 #else
649 if(isupper(i))
650 #endif /* MULTIBYTE */
651 {
652 i += 'a' - 'A';
653 out[cur] = i;
654 }
655 cur++;
656 }
657 draw(UPDATE);
658 return(-1);
659 }
660
661 else if(ch=='f')
662 {
663 cur = i;
664 draw(UPDATE);
665 return(-1);
666 }
667 else if(ch=='c')
668 {
669 ungetchar(cntl(C));
670 return(i-cur);
671 }
672 else
673 {
674 if (i-cur)
675 {
676 ungetchar(cntl(D));
677 return(i-cur);
678 }
679 beep();
680 return(-1);
681 }
682 }
683
684
685 case 'b':
686 case DELETE :
687 case '\b':
688 case 'h':
689 {
690 i = cur;
691 while(value-- && i>plen)
692 {
693 i--;
694 while ((i>plen)&&(!isword(i)))
695 i--;
696 while ((i>plen)&&(isword(i-1)))
697 i--;
698 }
699 if(ch=='b')
700 {
701 cur = i;
702 draw(UPDATE);
703 return(-1);
704 }
705 else
706 {
707 ungetchar(ERASECHAR);
708 return(cur-i);
709 }
710 }
711
712 case '>':
713 ungetchar(cntl(N));
714 return(histlines-(hline+1));
715
716 case '<':
717 ungetchar(cntl(P));
718 return(hline);
719
720
721 #ifdef KSHELL
722 case '_' :
723 case '.' :
724 {
725 genchar name[MAXLINE];
726 char buf[MAXLINE];
727 char *ptr;
728 ptr = hist_word(buf,(count?count:-1));
729 #ifndef KSHELL
730 if(ptr==NULL)
731 {
732 beep();
733 break;
734 }
735 #endif /* KSHELL */
736 if ((eol - cur) >= sizeof(name))
737 {
738 beep();
739 return(-1);
740 }
741 mark = cur;
742 gencpy(name,&out[cur]);
743 while(*ptr)
744 {
745 out[cur++] = *ptr++;
746 eol++;
747 }
748 gencpy(&out[cur],name);
749 draw(UPDATE);
750 return(-1);
751 }
752
753 /* file name expansion */
754 case cntl([) : /* easier to type */
755 i = '*';
756 case '*':
757 case '=': /* escape = - list all matching file names */
758 mark = cur;
759 if(q_expand(out,&cur,&eol,plen,i) < 0)
760 beep();
761 else if(i=='*')
762 draw(UPDATE);
763 else
764 draw(REFRESH);
765 return(-1);
766
767 default:
768 /* look for user defined macro definitions */
769 if(e_macro(i))
770 return(-1);
771 #else
772 default:
773 #endif /* KSHELL */
774 ungetchar(i);
775 ungetchar(cntl([));
776 ungetchar('\\');
777 return(-1);
778 }
779 }
780
781
782 static int
783 search(out,direction)
784 genchar out[];
785 {
786 static int prevdirection = 1 ;
787 histloc location;
788 register int i,sl;
789 genchar str_buff[100];
790 register genchar *string = drawbuff;
791 /* save current line */
792 char sav_cur = cur;
793 genncpy(str_buff,string,sizeof(str_buff)/CHARSIZE-1);
794 string[plen] = '^';
795 string[plen+1] = 'R';
796 string[plen+2] = '\0';
797 sl = 2+plen;
798 cur = sl;
799 draw(UPDATE);
800 while ((i = e_getchar())&&(i != '\r')&&(i != '\n'))
801 {
802 if (i==usrerase)
803 {
804 if (sl > 2+plen)
805 {
806 string[--sl] = '\0';
807 cur = sl;
808 draw(UPDATE);
809 }
810 else
811 beep();
812 continue;
813 }
814 if (i==usrkill)
815 {
816 beep();
817 goto restore;
818 }
819 if (i == '\\')
820 {
821 string[sl++] = '\\';
822 string[sl] = '\0';
823 cur = sl;
824 draw(APPEND);
825 i = e_getchar();
826 string[--sl] = '\0';
827 }
828 string[sl++] = i;
829 string[sl] = '\0';
830 cur = sl;
831 draw(APPEND);
832 }
833 i = genlen(string);
834
835 if (direction < 1)
836 {
837 prevdirection = -prevdirection;
838 direction = 1;
839 }
840 else
841 direction = -1;
842 if (i != 2+plen)
843 {
844 gencpy(lstring,&string[2+plen]);
845 #ifdef MULTIBYTE
846 e_external(lstring,(char*)lstring);
847 #endif /* MULTIBYTE */
848 prevdirection = direction;
849 }
850 else
851 direction = prevdirection ;
852 location = hist_find((char*)lstring,hline,1,direction);
853 i = location.his_command;
854 if(i>0)
855 {
856 hline = i;
857 hloff = location.his_line;
858 hist_copy((char*)&out[plen],hline,hloff);
859 #ifdef MULTIBYTE
860 e_internal((char*)&out[plen],&out[plen]);
861 #endif /* MULTIBYTE */
862 return;
863 }
864 if (i < 0)
865 {
866 beep();
867 hloff = (fc_fix?fc_fix->fixline:0);
868 hline = histlines;
869 }
870 restore:
871 genncpy(string,str_buff,sizeof(str_buff)/CHARSIZE-1);
872 cur = sav_cur;
873 return;
874 }
875
876
877 /* Adjust screen to agree with inputs: logical line and cursor */
878 /* If 'first' assume screen is blank */
879
880 static void
881 draw(option)
882 DRAWTYPE option;
883 {
884 #define NORMAL ' '
885 #define LOWER '<'
886 #define BOTH '*'
887 #define UPPER '>'
888 #define UNDEF 0
889
890 static char overflow; /* Screen overflow flag set */
891 register genchar *sptr; /* Pointer within screen */
892
893 static int offset; /* Screen offset */
894 static char scvalid; /* Screen is up to date */
895
896 genchar nscreen[2*MAXLINE]; /* New entire screen */
897 genchar *ncursor; /* New cursor */
898 register genchar *nptr; /* Pointer to New screen */
899 char longline; /* Line overflow */
900 genchar *logcursor;
901 genchar *nscend; /* end of logical screen */
902 register int i;
903
904 nptr = nscreen;
905 sptr = drawbuff;
906 logcursor = sptr + cur;
907 ncursor = nscreen;
908 longline = NORMAL;
909
910 if (option == FIRST || option == REFRESH)
911 {
912 overflow = NORMAL;
913 cursor = screen;
914 offset = 0;
915 cr_ok = crallowed;
916 if (option == FIRST)
917 {
918 scvalid = 1;
919 gencpy(cursor,sptr);
920 cursor += plen;
921 return;
922 }
923 *cursor = '\0';
924 }
925
926 /*********************
927 Do not update screen if pending characters
928 **********************/
929
930 if ((lookahead)&&(option != FINAL))
931 {
932
933 scvalid = 0; /* Screen is out of date, APPEND will not work */
934
935 return;
936 }
937
938 /***************************************
939 If in append mode, cursor at end of line, screen up to date,
940 the previous character was a 'normal' character,
941 and the window has room for another character.
942 Then output the character and adjust the screen only.
943 *****************************************/
944
945
946 i = *(logcursor-1);
947
948 if ((option == APPEND)&&(scvalid)&&(*logcursor == '\0')&&
949 print(i)&&((cursor-screen)<(w_size-1)))
950 {
951 putchar(i);
952 *cursor++ = i;
953 *cursor = '\0';
954 return;
955 }
956
957 /* copy the prompt */
958 i = plen;
959 while(--i >=0)
960 nptr[i] = sptr[i];
961 /* now the rest of the line */
962 ncursor = nptr + e_virt_to_phys(sptr,nptr,cur,plen,plen);
963 nptr += genlen(nptr);
964 sptr += genlen(sptr);
965 nscend = nptr - 1;
966 if(sptr == logcursor)
967 ncursor = nptr;
968
969 /*********************
970 Does ncursor appear on the screen?
971 If not, adjust the screen offset so it does.
972 **********************/
973
974 i = ncursor - nscreen;
975
976 if ((i <= offset)||(i >= (offset+w_size)))
977 {
978 offset = i - (w_size>>1);
979 if (offset < plen)
980 {
981 offset = (crallowed == YES) ? 0 : plen;
982 }
983 if ((offset >= plen)&&(cr_ok == NO))
984 {
985
986 /*********************************
987 Don't really know whats on the screen
988 because of strange characters in the prompt.
989
990 Mark entire screen as unknow.
991 ***********************************/
992
993 cursor = screen;
994 *cursor = '\0';
995 putchar('\r');
996 overflow = UNDEF;
997 cr_ok = YES;
998 }
999 }
1000 /*********************
1001 Is the range of screen[0] thru screen[w_size] up-to-date
1002 with nscreen[offset] thru nscreen[offset+w_size] ?
1003 If not, update as need be.
1004 ***********************/
1005
1006 nptr = &nscreen[offset];
1007 sptr = screen;
1008
1009 i = w_size;
1010
1011 while (i-- > 0)
1012 {
1013
1014 if (*nptr == '\0')
1015 {
1016 *(nptr + 1) = '\0';
1017 *nptr = ' ';
1018 }
1019 if (*sptr == '\0')
1020 {
1021 *(sptr + 1) = '\0';
1022 *sptr = ' ';
1023 }
1024 if (*nptr == *sptr)
1025 {
1026 nptr++;
1027 sptr++;
1028 continue;
1029 }
1030 setcursor(sptr-screen,*nptr);
1031 *sptr++ = *nptr++;
1032 #ifdef MULTIBYTE
1033 while(*nptr==MARKER)
1034 {
1035 *sptr++ = *nptr++;
1036 i--;
1037 cursor++;
1038 }
1039 #endif /* MULTIBYTE */
1040 }
1041
1042 /******************
1043
1044 Screen overflow checks
1045
1046 ********************/
1047
1048 if (nscend >= &nscreen[offset+w_size])
1049 {
1050 if (offset > plen)
1051 longline = BOTH;
1052 else
1053 longline = UPPER;
1054 }
1055 else
1056 {
1057 if (offset > plen)
1058 longline = LOWER;
1059 }
1060
1061 /* Update screen overflow indicator if need be */
1062
1063 if (longline != overflow)
1064 {
1065 setcursor(w_size,longline);
1066 overflow = longline;
1067 }
1068 i = (ncursor-nscreen) - offset;
1069 setcursor(i,0);
1070 scvalid = 1;
1071 return;
1072 }
1073
1074 /*
1075 * put the cursor to the <new> position within screen buffer
1076 * if <c> is non-zero then output this character
1077 * cursor is set to reflect the change
1078 */
1079
1080 static void
1081 setcursor(new,c)
1082 register int new,c;
1083 {
1084 register int old = cursor - screen;
1085 if (old > new)
1086 {
1087 if ((cr_ok == NO) || ((new*2)>old))
1088 {
1089 while (old > new)
1090 {
1091 putchar('\b');
1092 old--;
1093 }
1094 goto skip;
1095 }
1096 putchar('\r');
1097 old = 0;
1098 }
1099 while (new > old)
1100 putchar(screen[old++]);
1101 skip:
1102 if(c)
1103 {
1104 putchar(c);
1105 new++;
1106 }
1107 cursor = screen+new;
1108 return;
1109 }
1110
1111 #ifdef MULTIBYTE
1112 static int print(c)
1113 register int c;
1114 {
1115 return((c&~STRIP)==0 && isprint(c));
1116 }
1117
1118 static int isword(i)
1119 register int i;
1120 {
1121 register int c = drawbuff[i];
1122 return((c&~STRIP) || isalnum(c));
1123 }
1124 #endif /* MULTIBYTE */
1125