1 /* $Header: /src/pub/tcsh/ed.refresh.c,v 3.28 2000/11/11 23:03:34 christos Exp $ */
3 * ed.refresh.c: Lower level screen refreshing functions
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 RCSID("$Id: ed.refresh.c,v 3.28 2000/11/11 23:03:34 christos Exp $")
42 /* #define DEBUG_UPDATE */
43 /* #define DEBUG_REFRESH */
44 /* #define DEBUG_LITERAL */
46 /* refresh.c -- refresh the current set of lines on the screen */
49 static int vcursor_h, vcursor_v;
50 static int rprompt_h, rprompt_v;
52 static void Draw __P((int));
53 static void Vdraw __P((int));
54 static void RefreshPromptpart __P((Char *));
55 static void update_line __P((Char *, Char *, int));
56 static void str_insert __P((Char *, int, int, Char *, int));
57 static void str_delete __P((Char *, int, int, int));
58 static void str_cp __P((Char *, Char *, int));
59 static void PutPlusOne __P((int));
60 static void cpy_pad_spaces __P((Char *, Char *, int));
62 static Char *update_line_fix_mbyte_point __P((Char *, Char *, int));
64 #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
65 static void dprintf __P((char *, ...));
67 static void dprintstr __P((char *, Char *, Char *));
74 dprintf("%s:\"", str);
76 dprintf("%c", *f++ & ASCII);
79 #endif /* DEBUG_UPDATE */
82 * Print to $DEBUGTTY, so that we can test editing on one pty, and
83 * print debugging stuff on another. Don't interrupt the shell while
84 * debugging cause you'll mangle up the file descriptors!
88 dprintf(char *fmt, ...)
97 if ((dtty = getenv("DEBUGTTY"))) {
105 fmt = va_arg(va, char *);
106 #endif /* __STDC__ */
109 fd = open(dtty, O_RDWR);
119 #endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
122 Draw(c) /* draw c, expand tabs, ctl chars */
125 register Char ch = c & CHAR;
131 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
132 if (ch == '\n') { /* expand the newline */
134 * Don't force a newline if Vdraw does it (i.e. we're at end of line)
135 * - or we will get two newlines and possibly garbage in between
137 int oldv = vcursor_v;
139 Vdraw('\0'); /* assure end of line */
140 if (oldv == vcursor_v) {
141 vcursor_h = 0; /* reset cursor pos */
146 if (ch == '\t') { /* expand the tab */
149 if ((vcursor_h & 07) == 0)
150 break; /* go until tab stop */
153 else if (Iscntrl(ch)) {
156 if (ch == CTL_ESC('\177')) {
160 /* uncontrolify it; works only for iso8859-1 like sets */
163 if (ch == CTL_ESC('\177')) {
168 if (Isupper(_toebcdic[_toascii[c]|0100])
169 || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
172 Vdraw(_toebcdic[_toascii[c]|0100]);
177 Vdraw(((c >> 6) & 7) + '0');
178 Vdraw(((c >> 3) & 7) + '0');
179 Vdraw((c & 7) + '0');
189 !adrof(STRnokanji)) {
196 Vdraw(((c >> 6) & 7) + '0');
197 Vdraw(((c >> 3) & 7) + '0');
198 Vdraw((c & 7) + '0');
203 Vdraw(c) /* draw char c onto V lines */
207 # ifdef SHORT_STRINGS
208 dprintf("Vdrawing %6.6o '%c'\r\n", c, c & ASCII);
210 dprintf("Vdrawing %3.3o '%c'\r\n", c, c);
211 # endif /* SHORT_STRNGS */
212 #endif /* DEBUG_REFRESH */
214 Vdisplay[vcursor_v][vcursor_h] = (Char) c;
215 vcursor_h++; /* advance to next place */
216 if (vcursor_h >= TermH) {
217 Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */
218 vcursor_h = 0; /* reset it. */
221 if (vcursor_v >= TermV) { /* should NEVER happen. */
222 dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
226 #endif /* DEBUG_REFRESH */
231 * RefreshPromptpart()
232 * draws a prompt element, expanding literals (we know it's ASCIZ)
235 RefreshPromptpart(buf)
239 static unsigned int litnum = 0;
246 for (cp = buf; *cp; cp++) {
248 if (litnum < (sizeof(litptr) / sizeof(litptr[0]))) {
251 dprintf("litnum = %d, litptr = %x:\r\n",
252 litnum, litptr[litnum]);
253 #endif /* DEBUG_LITERAL */
255 while (*cp & LITERAL)
258 Vdraw((int) (litnum++ | LITERAL));
261 * XXX: This is a bug, we lose the last literal, if it is not
262 * followed by a normal character, but it is too hard to fix
274 * draws the new virtual screen image from the current input
275 * line, then goes line-by-line changing the real image to the new
276 * virtual image. The routine to re-draw a line can be replaced
277 * easily in hopes of a smarter one being placed there.
279 static int OldvcV = 0;
283 register int cur_line;
285 int cur_h, cur_v = 0, new_vcv;
290 dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
291 dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
292 #endif /* DEBUG_REFRESH */
293 oldgetting = GettingInput;
294 GettingInput = 0; /* avoid re-entrance via SIGWINCH */
296 /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
299 RefreshPromptpart(NULL);
300 RefreshPromptpart(RPromptBuf);
301 rprompt_h = vcursor_h;
302 rprompt_v = vcursor_v;
304 /* reset the Vdraw cursor, draw prompt */
307 RefreshPromptpart(NULL);
308 RefreshPromptpart(PromptBuf);
309 cur_h = -1; /* set flag in case I'm not set */
311 /* draw the current input buffer */
312 for (cp = InputBuf; (cp < LastChar); cp++) {
314 cur_h = vcursor_h; /* save for later */
320 if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */
325 rhdiff = TermH - vcursor_h - rprompt_h;
326 if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
328 * have a right-hand side prompt that will fit on
329 * the end of the first line with at least one
330 * character gap to the input buffer.
332 while (--rhdiff > 0) /* pad out with spaces */
334 RefreshPromptpart(RPromptBuf);
337 rprompt_h = 0; /* flag "not using rprompt" */
341 new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */
342 Vdraw('\0'); /* put NUL on end */
345 dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
346 TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
347 #endif /* DEBUG_REFRESH */
350 dprintf("updating %d lines.\r\n", new_vcv);
351 #endif /* DEBUG_UPDATE */
352 for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
353 /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
354 update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
357 #endif /* WINNT_NATIVE */
360 * Copy the new line to be the current one, and pad out with spaces
361 * to the full width of the terminal so that if we try moving the
362 * cursor by writing the character that is at the end of the
363 * screen line, it won't be a NUL or some old leftover stuff.
365 cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
367 (void) Strncpy(Display[cur_line], Vdisplay[cur_line], (size_t) TermH);
368 Display[cur_line][TermH] = '\0'; /* just in case */
372 dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
373 vcursor_v, OldvcV, cur_line);
374 #endif /* DEBUG_REFRESH */
375 if (OldvcV > new_vcv) {
376 for (; cur_line <= OldvcV; cur_line++) {
377 update_line(Display[cur_line], STRNULL, cur_line);
378 *Display[cur_line] = '\0';
381 OldvcV = new_vcv; /* set for next time */
383 dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
384 CursorH, CursorV, cur_h, cur_v);
385 #endif /* DEBUG_REFRESH */
388 #endif /* WINNT_NATIVE */
389 MoveToLine(cur_v); /* go to where the cursor is */
391 SetAttributes(0); /* Clear all attributes */
392 flush(); /* send the output... */
393 GettingInput = oldgetting; /* reset to old value */
398 { /* used to go to last used screen line */
406 { /* used to go to last used screen line */
415 /* insert num characters of s into d (in front of the character) at dat,
416 maximum length of d is dlen */
418 str_insert(d, dat, dlen, s, num)
420 register int dat, dlen;
424 register Char *a, *b;
428 if (num > dlen - dat)
432 dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
433 num, dat, dlen, short2str(d));
434 dprintf("s == \"%s\"n", short2str(s));
435 #endif /* DEBUG_REFRESH */
437 /* open up the space for num chars */
443 d[dlen] = '\0'; /* just in case */
446 dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
447 num, dat, dlen, short2str(d));
448 dprintf("s == \"%s\"n", short2str(s));
449 #endif /* DEBUG_REFRESH */
451 /* copy the characters */
452 for (a = d + dat; (a < d + dlen) && (num > 0); num--)
456 dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
457 num, dat, dlen, d, short2str(s));
458 dprintf("s == \"%s\"n", short2str(s));
459 #endif /* DEBUG_REFRESH */
462 /* delete num characters d at dat, maximum length of d is dlen */
464 str_delete(d, dat, dlen, num)
466 register int dat, dlen, num;
468 register Char *a, *b;
472 if (dat + num >= dlen) {
478 dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
479 num, dat, dlen, short2str(d));
480 #endif /* DEBUG_REFRESH */
482 /* open up the space for num chars */
488 d[dlen] = '\0'; /* just in case */
491 dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
492 num, dat, dlen, short2str(d));
493 #endif /* DEBUG_REFRESH */
498 register Char *a, *b;
506 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
508 update_line_fix_mbyte_point(start, target, d)
509 Char *start, *target;
512 if (_enable_mbdisp) {
518 if (Ismbyte1(*start) && Ismbyte2(*(start + 1)))
527 /* ****************************************************************
528 update_line() is based on finding the middle difference of each line
531 /old first difference
532 /beginning of line | /old last same /old EOL
534 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
535 new: eddie> Oh, my little buggy says to me, as lurgid as
537 \beginning of line | \new last same \new end of line
538 \new first difference
540 all are character pointers for the sake of speed. Special cases for
541 no differences, as well as for end of line additions must be handled.
542 **************************************************************** */
544 /* Minimum at which doing an insert it "worth it". This should be about
545 * half the "cost" of going into insert mode, inserting a character, and
546 * going back out. This should really be calculated from the termcap
547 * data... For the moment, a good number for ANSI terminals.
549 #define MIN_END_KEEP 4
551 static void /* could be changed to make it smarter */
552 update_line(old, new, cur_line)
553 register Char *old, *new;
556 register Char *o, *n, *p, c;
557 Char *ofd, *ols, *oe, *nfd, *nls, *ne;
558 Char *osb, *ose, *nsb, *nse;
564 for (o = old, n = new; *o && (*o == *n); o++, n++)
570 * Find the end of both old and new
575 * Remove any trailing blanks off of the end, being careful not to
576 * back up past the beginning.
589 /* remove blanks from end of new */
599 * if no diff, continue to next line of redraw
601 if (*ofd == '\0' && *nfd == '\0') {
603 dprintf("no difference.\r\n");
604 #endif /* DEBUG_UPDATE */
609 * find last same pointer
611 while ((o > ofd) && (n > nfd) && (*--o == *--n))
617 * find same begining and same end
625 * case 1: insert: scan from nfd to nls looking for *ofd
628 for (c = *ofd, n = nfd; n < nls; n++) {
630 for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
633 * if the new match is longer and it's worth keeping, then we
636 if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
647 * case 2: delete: scan from ofd to ols looking for *nfd
650 for (c = *nfd, o = ofd; o < ols; o++) {
652 for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
655 * if the new match is longer and it's worth keeping, then we
658 if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
669 * If `last same' is before `same end' re-adjust
678 * Pragmatics I: If old trailing whitespace or not enough characters to
679 * save to be worth it, then don't save the last same info.
681 if ((oe - ols) < MIN_END_KEEP) {
687 * Pragmatics II: if the terminal isn't smart enough, make the data dumber
688 * so the smart update doesn't try anything fancy
692 * fx is the number of characters we need to insert/delete: in the
693 * beginning to bring the two same begins together
695 fx = (int) ((nsb - nfd) - (osb - ofd));
697 * sx is the number of characters we need to insert/delete: in the end to
698 * bring the two same last parts together
700 sx = (int) ((nls - nse) - (ols - ose));
713 if ((ols - ofd) < (nls - nfd)) {
729 if ((ols - ofd) > (nls - nfd)) {
736 * Pragmatics III: make sure the middle shifted pointers are correct if
737 * they don't point to anything (we may have moved ols or nls).
739 /* if the change isn't worth it, don't bother */
740 /* was: if (osb == ose) */
741 if ((ose - osb) < MIN_END_KEEP) {
749 * Now that we are done with pragmatics we recompute fx, sx
751 fx = (int) ((nsb - nfd) - (osb - ofd));
752 sx = (int) ((nls - nse) - (ols - ose));
756 dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
757 ofd - old, osb - old, ose - old, ols - old, oe - old);
758 dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
759 nfd - new, nsb - new, nse - new, nls - new, ne - new);
760 dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
761 dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
762 dprintstr("old- oe", old, oe);
763 dprintstr("new- ne", new, ne);
764 dprintstr("old-ofd", old, ofd);
765 dprintstr("new-nfd", new, nfd);
766 dprintstr("ofd-osb", ofd, osb);
767 dprintstr("nfd-nsb", nfd, nsb);
768 dprintstr("osb-ose", osb, ose);
769 dprintstr("nsb-nse", nsb, nse);
770 dprintstr("ose-ols", ose, ols);
771 dprintstr("nse-nls", nse, nls);
772 dprintstr("ols- oe", ols, oe);
773 dprintstr("nls- ne", nls, ne);
774 #endif /* DEBUG_UPDATE */
777 * CursorV to this line cur_line MUST be in this routine so that if we
778 * don't have to change the line, we don't move to it. CursorH to first
781 MoveToLine(cur_line);
783 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
784 ofd = update_line_fix_mbyte_point(old, ofd, -1);
785 osb = update_line_fix_mbyte_point(old, osb, 1);
786 ose = update_line_fix_mbyte_point(old, ose, -1);
787 ols = update_line_fix_mbyte_point(old, ols, 1);
788 nfd = update_line_fix_mbyte_point(new, nfd, -1);
789 nsb = update_line_fix_mbyte_point(new, nsb, 1);
790 nse = update_line_fix_mbyte_point(new, nse, -1);
791 nls = update_line_fix_mbyte_point(new, nls, 1);
795 * at this point we have something like this:
797 * /old /ofd /osb /ose /ols /oe
798 * v.....................v v..................v v........v
799 * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
800 * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
801 * ^.....................^ ^..................^ ^........^
802 * \new \nfd \nsb \nse \nls \ne
804 * fx is the difference in length between the the chars between nfd and
805 * nsb, and the chars between ofd and osb, and is thus the number of
806 * characters to delete if < 0 (new is shorter than old, as above),
807 * or insert (new is longer than short).
809 * sx is the same for the second differences.
813 * if we have a net insert on the first difference, AND inserting the net
814 * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
815 * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
816 * (TermH - 1) else we do the deletes first so that we keep everything we
821 * if the last same is the same like the end, there is no last same part,
822 * otherwise we want to keep the last same part set p to the last useful
825 p = (ols != oe) ? oe : ose;
828 * if (There is a diffence in the beginning) && (we need to insert
829 * characters) && (the number of characters to insert is less than the term
830 * width) We need to do an insert! else if (we need to delete characters)
831 * We need to delete characters! else No insert or delete
833 if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
835 dprintf("first diff insert at %d...\r\n", nfd - new);
836 #endif /* DEBUG_UPDATE */
838 * Move to the first char to insert, where the first diff is.
840 MoveToChar(nfd - new);
842 * Check if we have stuff to keep at end
846 dprintf("with stuff to keep at end\r\n");
847 #endif /* DEBUG_UPDATE */
849 * insert fx chars of new starting at nfd
854 dprintf(" ERROR: cannot insert in early first diff\n");
855 #endif /* DEBUG_UPDATE */
856 Insert_write(nfd, fx);
857 str_insert(old, (int) (ofd - old), TermH, nfd, fx);
860 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
862 so_write(nfd + fx, (nsb - nfd) - fx);
863 str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
867 dprintf("without anything to save\r\n");
868 #endif /* DEBUG_UPDATE */
869 so_write(nfd, (nsb - nfd));
870 str_cp(ofd, nfd, (int) (nsb - nfd));
879 dprintf("first diff delete at %d...\r\n", ofd - old);
880 #endif /* DEBUG_UPDATE */
882 * move to the first char to delete where the first diff is
884 MoveToChar(ofd - old);
886 * Check if we have stuff to save
890 dprintf("with stuff to save at end\r\n");
891 #endif /* DEBUG_UPDATE */
893 * fx is less than zero *always* here but we check for code
899 dprintf(" ERROR: cannot delete in first diff\n");
900 #endif /* DEBUG_UPDATE */
902 str_delete(old, (int) (ofd - old), TermH, -fx);
905 * write (nsb-nfd) chars of new starting at nfd
907 so_write(nfd, (nsb - nfd));
908 str_cp(ofd, nfd, (int) (nsb - nfd));
913 dprintf("but with nothing left to save\r\n");
914 #endif /* DEBUG_UPDATE */
916 * write (nsb-nfd) chars of new starting at nfd
918 so_write(nfd, (nsb - nfd));
920 dprintf("cleareol %d\n", (oe - old) - (ne - new));
921 #endif /* DEBUG_UPDATE */
923 ClearEOL((oe - old) - (ne - new));
926 * The calculation above does not work too well on NT
928 ClearEOL(TermH - CursorH);
929 #endif /*WINNT_NATIVE*/
941 dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
942 #endif /* DEBUG_UPDATE */
944 * Check if we have stuff to delete
947 * fx is the number of characters inserted (+) or deleted (-)
950 MoveToChar((ose - old) + fx);
952 * Check if we have stuff to save
956 dprintf("with stuff to save at end\r\n");
957 #endif /* DEBUG_UPDATE */
959 * Again a duplicate test.
964 dprintf(" ERROR: cannot delete in second diff\n");
965 #endif /* DEBUG_UPDATE */
970 * write (nls-nse) chars of new starting at nse
972 so_write(nse, (nls - nse));
975 int olen = (int) (oe - old + fx);
979 dprintf("but with nothing left to save\r\n");
980 #endif /* DEBUG_UPDATE */
981 so_write(nse, (nls - nse));
983 dprintf("cleareol %d\n", olen - (ne - new));
984 #endif /* DEBUG_UPDATE */
986 ClearEOL(olen - (ne - new));
989 * The calculation above does not work too well on NT
991 ClearEOL(TermH - CursorH);
992 #endif /*WINNT_NATIVE*/
997 * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
999 if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1001 dprintf("late first diff insert at %d...\r\n", nfd - new);
1002 #endif /* DEBUG_UPDATE */
1004 MoveToChar(nfd - new);
1006 * Check if we have stuff to keep at the end
1010 dprintf("with stuff to keep at end\r\n");
1011 #endif /* DEBUG_UPDATE */
1013 * We have to recalculate fx here because we set it
1014 * to zero above as a flag saying that we hadn't done
1015 * an early first insert.
1017 fx = (int) ((nsb - nfd) - (osb - ofd));
1020 * insert fx chars of new starting at nfd
1024 dprintf(" ERROR: cannot insert in late first diff\n");
1025 #endif /* DEBUG_UPDATE */
1026 Insert_write(nfd, fx);
1027 str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1031 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1033 so_write(nfd + fx, (nsb - nfd) - fx);
1034 str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1038 dprintf("without anything to save\r\n");
1039 #endif /* DEBUG_UPDATE */
1040 so_write(nfd, (nsb - nfd));
1041 str_cp(ofd, nfd, (int) (nsb - nfd));
1046 * line is now NEW up to nse
1050 dprintf("second diff insert at %d...\r\n", nse - new);
1051 #endif /* DEBUG_UPDATE */
1052 MoveToChar(nse - new);
1055 dprintf("with stuff to keep at end\r\n");
1056 #endif /* DEBUG_UPDATE */
1058 /* insert sx chars of new starting at nse */
1061 dprintf(" ERROR: cannot insert in second diff\n");
1062 #endif /* DEBUG_UPDATE */
1063 Insert_write(nse, sx);
1067 * write (nls-nse) - sx chars of new starting at (nse + sx)
1069 so_write(nse + sx, (nls - nse) - sx);
1073 dprintf("without anything to save\r\n");
1074 #endif /* DEBUG_UPDATE */
1075 so_write(nse, (nls - nse));
1078 * No need to do a clear-to-end here because we were doing
1079 * a second insert, so we will have over written all of the
1085 dprintf("done.\r\n");
1086 #endif /* DEBUG_UPDATE */
1091 cpy_pad_spaces(dst, src, width)
1092 register Char *dst, *src;
1097 for (i = 0; i < width; i++) {
1098 if (*src == (Char) 0)
1112 { /* only move to new cursor pos */
1113 register Char *cp, c;
1114 register int h, th, v;
1116 /* first we must find where the cursor is... */
1119 th = TermH; /* optimize for speed */
1121 for (cp = PromptBuf; *cp; cp++) { /* do prompt */
1124 c = *cp & CHAR; /* extra speed plus strip the inverse */
1125 h++; /* all chars at least this long */
1127 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
1128 /* lets handle newline as part of the prompt */
1135 if (c == '\t') { /* if a tab, to next tab stop */
1140 else if (Iscntrl(c)) { /* if control char */
1142 if (h > th) { /* if overflow, compensate */
1147 else if (!Isprint(c)) {
1149 if (h > th) { /* if overflow, compensate */
1156 if (h >= th) { /* check, extra long tabs picked up here also */
1162 for (cp = InputBuf; cp < Cursor; cp++) { /* do input buffer to Cursor */
1163 c = *cp & CHAR; /* extra speed plus strip the inverse */
1164 h++; /* all chars at least this long */
1166 if (c == '\n') { /* handle newline in data part too */
1171 if (c == '\t') { /* if a tab, to next tab stop */
1176 else if (Iscntrl(c)) { /* if control char */
1178 if (h > th) { /* if overflow, compensate */
1183 else if (!Isprint(c)) {
1185 if (h > th) { /* if overflow, compensate */
1192 if (h >= th) { /* check, extra long tabs picked up here also */
1209 Display[CursorV][CursorH++] = (Char) c;
1210 if (CursorH >= TermH) { /* if we must overflow */
1214 if (T_Margin & MARGIN_AUTO) {
1215 if (T_Margin & MARGIN_MAGIC) {
1217 (void) putraw('\b');
1221 (void) putraw('\r');
1222 (void) putraw('\n');
1229 { /* we added just one char, handle it fast.
1230 * assumes that screen cursor == real cursor */
1231 register Char c, mc;
1233 c = Cursor[-1] & CHAR; /* the char we just added */
1235 if (c == '\t' || Cursor != LastChar) {
1236 Refresh(); /* too hard to handle */
1240 if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1241 Refresh(); /* clear out rprompt if less than one char gap*/
1243 } /* else (only do at end of line, no TAB) */
1245 if (Iscntrl(c)) { /* if control char, do caret */
1247 mc = (c == '\177') ? '?' : (c | 0100);
1251 if (_toascii[c] == '\177' || Isupper(_toebcdic[_toascii[c]|0100])
1252 || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
1254 mc = (_toascii[c] == '\177') ? '?' : _toebcdic[_toascii[c]|0100];
1261 PutPlusOne(((c >> 6) & 7) + '0');
1262 PutPlusOne(((c >> 3) & 7) + '0');
1263 PutPlusOne((c & 7) + '0');
1267 else if (Isprint(c)) { /* normal char */
1275 !adrof(STRnokanji)) {
1281 PutPlusOne(((c >> 6) & 7) + '0');
1282 PutPlusOne(((c >> 3) & 7) + '0');
1283 PutPlusOne((c & 7) + '0');
1288 /* clear the screen buffers so that new new prompt starts fresh. */
1295 CursorV = 0; /* clear the display buffer */
1297 for (i = 0; i < TermV; i++)
1298 (void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
1304 { /* Make sure all lines are *really* blank */
1309 * Clear the lines from the bottom up so that if we try moving
1310 * the cursor down by writing the character that is at the end
1311 * of the screen line, we won't rewrite a character that shouldn't
1314 for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */
1321 MoveToLine(OldvcV); /* go to last line */
1322 (void) putraw('\r'); /* go to BOL */
1323 (void) putraw('\n'); /* go to new line */