1 /* $Header: /src/pub/tcsh/ed.refresh.c,v 3.30 2003/02/08 20:03:25 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. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 RCSID("$Id: ed.refresh.c,v 3.30 2003/02/08 20:03:25 christos Exp $")
38 /* #define DEBUG_UPDATE */
39 /* #define DEBUG_REFRESH */
40 /* #define DEBUG_LITERAL */
42 /* refresh.c -- refresh the current set of lines on the screen */
45 static int vcursor_h, vcursor_v;
46 static int rprompt_h, rprompt_v;
48 static void Draw __P((int));
49 static void Vdraw __P((int));
50 static void RefreshPromptpart __P((Char *));
51 static void update_line __P((Char *, Char *, int));
52 static void str_insert __P((Char *, int, int, Char *, int));
53 static void str_delete __P((Char *, int, int, int));
54 static void str_cp __P((Char *, Char *, int));
60 void PutPlusOne __P((int));
61 static void cpy_pad_spaces __P((Char *, Char *, int));
63 static Char *update_line_fix_mbyte_point __P((Char *, Char *, int));
65 #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
66 static void dprintf __P((char *, ...));
68 static void dprintstr __P((char *, Char *, Char *));
75 dprintf("%s:\"", str);
77 dprintf("%c", *f++ & ASCII);
80 #endif /* DEBUG_UPDATE */
83 * Print to $DEBUGTTY, so that we can test editing on one pty, and
84 * print debugging stuff on another. Don't interrupt the shell while
85 * debugging cause you'll mangle up the file descriptors!
89 dprintf(char *fmt, ...)
98 if ((dtty = getenv("DEBUGTTY"))) {
106 fmt = va_arg(va, char *);
107 #endif /* __STDC__ */
110 fd = open(dtty, O_RDWR);
120 #endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
123 Draw(c) /* draw c, expand tabs, ctl chars */
126 register Char ch = c & CHAR;
132 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
133 if (ch == '\n') { /* expand the newline */
135 * Don't force a newline if Vdraw does it (i.e. we're at end of line)
136 * - or we will get two newlines and possibly garbage in between
138 int oldv = vcursor_v;
140 Vdraw('\0'); /* assure end of line */
141 if (oldv == vcursor_v) {
142 vcursor_h = 0; /* reset cursor pos */
147 if (ch == '\t') { /* expand the tab */
150 if ((vcursor_h & 07) == 0)
151 break; /* go until tab stop */
154 else if (Iscntrl(ch)) {
157 if (ch == CTL_ESC('\177')) {
161 /* uncontrolify it; works only for iso8859-1 like sets */
164 if (ch == CTL_ESC('\177')) {
169 if (Isupper(_toebcdic[_toascii[c]|0100])
170 || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
173 Vdraw(_toebcdic[_toascii[c]|0100]);
178 Vdraw(((c >> 6) & 7) + '0');
179 Vdraw(((c >> 3) & 7) + '0');
180 Vdraw((c & 7) + '0');
190 !adrof(STRnokanji)) {
197 Vdraw(((c >> 6) & 7) + '0');
198 Vdraw(((c >> 3) & 7) + '0');
199 Vdraw((c & 7) + '0');
204 Vdraw(c) /* draw char c onto V lines */
208 # ifdef SHORT_STRINGS
209 dprintf("Vdrawing %6.6o '%c'\r\n", c, c & ASCII);
211 dprintf("Vdrawing %3.3o '%c'\r\n", c, c);
212 # endif /* SHORT_STRNGS */
213 #endif /* DEBUG_REFRESH */
215 Vdisplay[vcursor_v][vcursor_h] = (Char) c;
216 vcursor_h++; /* advance to next place */
217 if (vcursor_h >= TermH) {
218 Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */
219 vcursor_h = 0; /* reset it. */
222 if (vcursor_v >= TermV) { /* should NEVER happen. */
223 dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
227 #endif /* DEBUG_REFRESH */
232 * RefreshPromptpart()
233 * draws a prompt element, expanding literals (we know it's ASCIZ)
236 RefreshPromptpart(buf)
240 static unsigned int litnum = 0;
247 for (cp = buf; *cp; cp++) {
249 if (litnum < (sizeof(litptr) / sizeof(litptr[0]))) {
252 dprintf("litnum = %d, litptr = %x:\r\n",
253 litnum, litptr[litnum]);
254 #endif /* DEBUG_LITERAL */
256 while (*cp & LITERAL)
259 Vdraw((int) (litnum++ | LITERAL));
262 * XXX: This is a bug, we lose the last literal, if it is not
263 * followed by a normal character, but it is too hard to fix
275 * draws the new virtual screen image from the current input
276 * line, then goes line-by-line changing the real image to the new
277 * virtual image. The routine to re-draw a line can be replaced
278 * easily in hopes of a smarter one being placed there.
288 register int cur_line;
290 int cur_h, cur_v = 0, new_vcv;
295 dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
296 dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
297 #endif /* DEBUG_REFRESH */
298 oldgetting = GettingInput;
299 GettingInput = 0; /* avoid re-entrance via SIGWINCH */
301 /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
304 RefreshPromptpart(NULL);
305 RefreshPromptpart(RPromptBuf);
306 rprompt_h = vcursor_h;
307 rprompt_v = vcursor_v;
309 /* reset the Vdraw cursor, draw prompt */
312 RefreshPromptpart(NULL);
313 RefreshPromptpart(PromptBuf);
314 cur_h = -1; /* set flag in case I'm not set */
316 /* draw the current input buffer */
317 for (cp = InputBuf; (cp < LastChar); cp++) {
319 cur_h = vcursor_h; /* save for later */
325 if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */
330 rhdiff = TermH - vcursor_h - rprompt_h;
331 if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
333 * have a right-hand side prompt that will fit on
334 * the end of the first line with at least one
335 * character gap to the input buffer.
337 while (--rhdiff > 0) /* pad out with spaces */
339 RefreshPromptpart(RPromptBuf);
342 rprompt_h = 0; /* flag "not using rprompt" */
346 new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */
347 Vdraw('\0'); /* put NUL on end */
350 dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
351 TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
352 #endif /* DEBUG_REFRESH */
355 dprintf("updating %d lines.\r\n", new_vcv);
356 #endif /* DEBUG_UPDATE */
357 for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
358 /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
359 update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
362 #endif /* WINNT_NATIVE */
365 * Copy the new line to be the current one, and pad out with spaces
366 * to the full width of the terminal so that if we try moving the
367 * cursor by writing the character that is at the end of the
368 * screen line, it won't be a NUL or some old leftover stuff.
370 cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
372 (void) Strncpy(Display[cur_line], Vdisplay[cur_line], (size_t) TermH);
373 Display[cur_line][TermH] = '\0'; /* just in case */
377 dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
378 vcursor_v, OldvcV, cur_line);
379 #endif /* DEBUG_REFRESH */
380 if (OldvcV > new_vcv) {
381 for (; cur_line <= OldvcV; cur_line++) {
382 update_line(Display[cur_line], STRNULL, cur_line);
383 *Display[cur_line] = '\0';
386 OldvcV = new_vcv; /* set for next time */
388 dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
389 CursorH, CursorV, cur_h, cur_v);
390 #endif /* DEBUG_REFRESH */
393 #endif /* WINNT_NATIVE */
394 MoveToLine(cur_v); /* go to where the cursor is */
396 SetAttributes(0); /* Clear all attributes */
397 flush(); /* send the output... */
398 GettingInput = oldgetting; /* reset to old value */
403 { /* used to go to last used screen line */
411 { /* used to go to last used screen line */
420 /* insert num characters of s into d (in front of the character) at dat,
421 maximum length of d is dlen */
423 str_insert(d, dat, dlen, s, num)
425 register int dat, dlen;
429 register Char *a, *b;
433 if (num > dlen - dat)
437 dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
438 num, dat, dlen, short2str(d));
439 dprintf("s == \"%s\"n", short2str(s));
440 #endif /* DEBUG_REFRESH */
442 /* open up the space for num chars */
448 d[dlen] = '\0'; /* just in case */
451 dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
452 num, dat, dlen, short2str(d));
453 dprintf("s == \"%s\"n", short2str(s));
454 #endif /* DEBUG_REFRESH */
456 /* copy the characters */
457 for (a = d + dat; (a < d + dlen) && (num > 0); num--)
461 dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
462 num, dat, dlen, d, short2str(s));
463 dprintf("s == \"%s\"n", short2str(s));
464 #endif /* DEBUG_REFRESH */
467 /* delete num characters d at dat, maximum length of d is dlen */
469 str_delete(d, dat, dlen, num)
471 register int dat, dlen, num;
473 register Char *a, *b;
477 if (dat + num >= dlen) {
483 dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
484 num, dat, dlen, short2str(d));
485 #endif /* DEBUG_REFRESH */
487 /* open up the space for num chars */
493 d[dlen] = '\0'; /* just in case */
496 dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
497 num, dat, dlen, short2str(d));
498 #endif /* DEBUG_REFRESH */
503 register Char *a, *b;
511 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
513 update_line_fix_mbyte_point(start, target, d)
514 Char *start, *target;
517 if (_enable_mbdisp) {
523 if (Ismbyte1(*start) && Ismbyte2(*(start + 1)))
532 /* ****************************************************************
533 update_line() is based on finding the middle difference of each line
536 /old first difference
537 /beginning of line | /old last same /old EOL
539 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
540 new: eddie> Oh, my little buggy says to me, as lurgid as
542 \beginning of line | \new last same \new end of line
543 \new first difference
545 all are character pointers for the sake of speed. Special cases for
546 no differences, as well as for end of line additions must be handled.
547 **************************************************************** */
549 /* Minimum at which doing an insert it "worth it". This should be about
550 * half the "cost" of going into insert mode, inserting a character, and
551 * going back out. This should really be calculated from the termcap
552 * data... For the moment, a good number for ANSI terminals.
554 #define MIN_END_KEEP 4
556 static void /* could be changed to make it smarter */
557 update_line(old, new, cur_line)
558 register Char *old, *new;
561 register Char *o, *n, *p, c;
562 Char *ofd, *ols, *oe, *nfd, *nls, *ne;
563 Char *osb, *ose, *nsb, *nse;
569 for (o = old, n = new; *o && (*o == *n); o++, n++)
575 * Find the end of both old and new
580 * Remove any trailing blanks off of the end, being careful not to
581 * back up past the beginning.
594 /* remove blanks from end of new */
604 * if no diff, continue to next line of redraw
606 if (*ofd == '\0' && *nfd == '\0') {
608 dprintf("no difference.\r\n");
609 #endif /* DEBUG_UPDATE */
614 * find last same pointer
616 while ((o > ofd) && (n > nfd) && (*--o == *--n))
622 * find same begining and same end
630 * case 1: insert: scan from nfd to nls looking for *ofd
633 for (c = *ofd, n = nfd; n < nls; n++) {
635 for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
638 * if the new match is longer and it's worth keeping, then we
641 if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
652 * case 2: delete: scan from ofd to ols looking for *nfd
655 for (c = *nfd, o = ofd; o < ols; o++) {
657 for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
660 * if the new match is longer and it's worth keeping, then we
663 if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
674 * If `last same' is before `same end' re-adjust
683 * Pragmatics I: If old trailing whitespace or not enough characters to
684 * save to be worth it, then don't save the last same info.
686 if ((oe - ols) < MIN_END_KEEP) {
692 * Pragmatics II: if the terminal isn't smart enough, make the data dumber
693 * so the smart update doesn't try anything fancy
697 * fx is the number of characters we need to insert/delete: in the
698 * beginning to bring the two same begins together
700 fx = (int) ((nsb - nfd) - (osb - ofd));
702 * sx is the number of characters we need to insert/delete: in the end to
703 * bring the two same last parts together
705 sx = (int) ((nls - nse) - (ols - ose));
718 if ((ols - ofd) < (nls - nfd)) {
734 if ((ols - ofd) > (nls - nfd)) {
741 * Pragmatics III: make sure the middle shifted pointers are correct if
742 * they don't point to anything (we may have moved ols or nls).
744 /* if the change isn't worth it, don't bother */
745 /* was: if (osb == ose) */
746 if ((ose - osb) < MIN_END_KEEP) {
754 * Now that we are done with pragmatics we recompute fx, sx
756 fx = (int) ((nsb - nfd) - (osb - ofd));
757 sx = (int) ((nls - nse) - (ols - ose));
761 dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
762 ofd - old, osb - old, ose - old, ols - old, oe - old);
763 dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
764 nfd - new, nsb - new, nse - new, nls - new, ne - new);
765 dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
766 dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
767 dprintstr("old- oe", old, oe);
768 dprintstr("new- ne", new, ne);
769 dprintstr("old-ofd", old, ofd);
770 dprintstr("new-nfd", new, nfd);
771 dprintstr("ofd-osb", ofd, osb);
772 dprintstr("nfd-nsb", nfd, nsb);
773 dprintstr("osb-ose", osb, ose);
774 dprintstr("nsb-nse", nsb, nse);
775 dprintstr("ose-ols", ose, ols);
776 dprintstr("nse-nls", nse, nls);
777 dprintstr("ols- oe", ols, oe);
778 dprintstr("nls- ne", nls, ne);
779 #endif /* DEBUG_UPDATE */
782 * CursorV to this line cur_line MUST be in this routine so that if we
783 * don't have to change the line, we don't move to it. CursorH to first
786 MoveToLine(cur_line);
788 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
789 ofd = update_line_fix_mbyte_point(old, ofd, -1);
790 osb = update_line_fix_mbyte_point(old, osb, 1);
791 ose = update_line_fix_mbyte_point(old, ose, -1);
792 ols = update_line_fix_mbyte_point(old, ols, 1);
793 nfd = update_line_fix_mbyte_point(new, nfd, -1);
794 nsb = update_line_fix_mbyte_point(new, nsb, 1);
795 nse = update_line_fix_mbyte_point(new, nse, -1);
796 nls = update_line_fix_mbyte_point(new, nls, 1);
800 * at this point we have something like this:
802 * /old /ofd /osb /ose /ols /oe
803 * v.....................v v..................v v........v
804 * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
805 * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
806 * ^.....................^ ^..................^ ^........^
807 * \new \nfd \nsb \nse \nls \ne
809 * fx is the difference in length between the the chars between nfd and
810 * nsb, and the chars between ofd and osb, and is thus the number of
811 * characters to delete if < 0 (new is shorter than old, as above),
812 * or insert (new is longer than short).
814 * sx is the same for the second differences.
818 * if we have a net insert on the first difference, AND inserting the net
819 * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
820 * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
821 * (TermH - 1) else we do the deletes first so that we keep everything we
826 * if the last same is the same like the end, there is no last same part,
827 * otherwise we want to keep the last same part set p to the last useful
830 p = (ols != oe) ? oe : ose;
833 * if (There is a diffence in the beginning) && (we need to insert
834 * characters) && (the number of characters to insert is less than the term
835 * width) We need to do an insert! else if (we need to delete characters)
836 * We need to delete characters! else No insert or delete
838 if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
840 dprintf("first diff insert at %d...\r\n", nfd - new);
841 #endif /* DEBUG_UPDATE */
843 * Move to the first char to insert, where the first diff is.
845 MoveToChar(nfd - new);
847 * Check if we have stuff to keep at end
851 dprintf("with stuff to keep at end\r\n");
852 #endif /* DEBUG_UPDATE */
854 * insert fx chars of new starting at nfd
859 dprintf(" ERROR: cannot insert in early first diff\n");
860 #endif /* DEBUG_UPDATE */
861 Insert_write(nfd, fx);
862 str_insert(old, (int) (ofd - old), TermH, nfd, fx);
865 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
867 so_write(nfd + fx, (nsb - nfd) - fx);
868 str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
872 dprintf("without anything to save\r\n");
873 #endif /* DEBUG_UPDATE */
874 so_write(nfd, (nsb - nfd));
875 str_cp(ofd, nfd, (int) (nsb - nfd));
884 dprintf("first diff delete at %d...\r\n", ofd - old);
885 #endif /* DEBUG_UPDATE */
887 * move to the first char to delete where the first diff is
889 MoveToChar(ofd - old);
891 * Check if we have stuff to save
895 dprintf("with stuff to save at end\r\n");
896 #endif /* DEBUG_UPDATE */
898 * fx is less than zero *always* here but we check for code
904 dprintf(" ERROR: cannot delete in first diff\n");
905 #endif /* DEBUG_UPDATE */
907 str_delete(old, (int) (ofd - old), TermH, -fx);
910 * write (nsb-nfd) chars of new starting at nfd
912 so_write(nfd, (nsb - nfd));
913 str_cp(ofd, nfd, (int) (nsb - nfd));
918 dprintf("but with nothing left to save\r\n");
919 #endif /* DEBUG_UPDATE */
921 * write (nsb-nfd) chars of new starting at nfd
923 so_write(nfd, (nsb - nfd));
925 dprintf("cleareol %d\n", (oe - old) - (ne - new));
926 #endif /* DEBUG_UPDATE */
928 ClearEOL((oe - old) - (ne - new));
931 * The calculation above does not work too well on NT
933 ClearEOL(TermH - CursorH);
934 #endif /*WINNT_NATIVE*/
946 dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
947 #endif /* DEBUG_UPDATE */
949 * Check if we have stuff to delete
952 * fx is the number of characters inserted (+) or deleted (-)
955 MoveToChar((ose - old) + fx);
957 * Check if we have stuff to save
961 dprintf("with stuff to save at end\r\n");
962 #endif /* DEBUG_UPDATE */
964 * Again a duplicate test.
969 dprintf(" ERROR: cannot delete in second diff\n");
970 #endif /* DEBUG_UPDATE */
975 * write (nls-nse) chars of new starting at nse
977 so_write(nse, (nls - nse));
980 int olen = (int) (oe - old + fx);
984 dprintf("but with nothing left to save\r\n");
985 #endif /* DEBUG_UPDATE */
986 so_write(nse, (nls - nse));
988 dprintf("cleareol %d\n", olen - (ne - new));
989 #endif /* DEBUG_UPDATE */
991 ClearEOL(olen - (ne - new));
994 * The calculation above does not work too well on NT
996 ClearEOL(TermH - CursorH);
997 #endif /*WINNT_NATIVE*/
1002 * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
1004 if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1006 dprintf("late first diff insert at %d...\r\n", nfd - new);
1007 #endif /* DEBUG_UPDATE */
1009 MoveToChar(nfd - new);
1011 * Check if we have stuff to keep at the end
1015 dprintf("with stuff to keep at end\r\n");
1016 #endif /* DEBUG_UPDATE */
1018 * We have to recalculate fx here because we set it
1019 * to zero above as a flag saying that we hadn't done
1020 * an early first insert.
1022 fx = (int) ((nsb - nfd) - (osb - ofd));
1025 * insert fx chars of new starting at nfd
1029 dprintf(" ERROR: cannot insert in late first diff\n");
1030 #endif /* DEBUG_UPDATE */
1031 Insert_write(nfd, fx);
1032 str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1036 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1038 so_write(nfd + fx, (nsb - nfd) - fx);
1039 str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1043 dprintf("without anything to save\r\n");
1044 #endif /* DEBUG_UPDATE */
1045 so_write(nfd, (nsb - nfd));
1046 str_cp(ofd, nfd, (int) (nsb - nfd));
1051 * line is now NEW up to nse
1055 dprintf("second diff insert at %d...\r\n", nse - new);
1056 #endif /* DEBUG_UPDATE */
1057 MoveToChar(nse - new);
1060 dprintf("with stuff to keep at end\r\n");
1061 #endif /* DEBUG_UPDATE */
1063 /* insert sx chars of new starting at nse */
1066 dprintf(" ERROR: cannot insert in second diff\n");
1067 #endif /* DEBUG_UPDATE */
1068 Insert_write(nse, sx);
1072 * write (nls-nse) - sx chars of new starting at (nse + sx)
1074 so_write(nse + sx, (nls - nse) - sx);
1078 dprintf("without anything to save\r\n");
1079 #endif /* DEBUG_UPDATE */
1080 so_write(nse, (nls - nse));
1083 * No need to do a clear-to-end here because we were doing
1084 * a second insert, so we will have over written all of the
1090 dprintf("done.\r\n");
1091 #endif /* DEBUG_UPDATE */
1096 cpy_pad_spaces(dst, src, width)
1097 register Char *dst, *src;
1102 for (i = 0; i < width; i++) {
1103 if (*src == (Char) 0)
1117 { /* only move to new cursor pos */
1118 register Char *cp, c;
1119 register int h, th, v;
1121 /* first we must find where the cursor is... */
1124 th = TermH; /* optimize for speed */
1126 for (cp = PromptBuf; *cp; cp++) { /* do prompt */
1129 c = *cp & CHAR; /* extra speed plus strip the inverse */
1130 h++; /* all chars at least this long */
1132 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
1133 /* lets handle newline as part of the prompt */
1140 if (c == '\t') { /* if a tab, to next tab stop */
1145 else if (Iscntrl(c)) { /* if control char */
1147 if (h > th) { /* if overflow, compensate */
1152 else if (!Isprint(c)) {
1154 if (h > th) { /* if overflow, compensate */
1161 if (h >= th) { /* check, extra long tabs picked up here also */
1167 for (cp = InputBuf; cp < Cursor; cp++) { /* do input buffer to Cursor */
1168 c = *cp & CHAR; /* extra speed plus strip the inverse */
1169 h++; /* all chars at least this long */
1171 if (c == '\n') { /* handle newline in data part too */
1176 if (c == '\t') { /* if a tab, to next tab stop */
1181 else if (Iscntrl(c)) { /* if control char */
1183 if (h > th) { /* if overflow, compensate */
1188 else if (!Isprint(c)) {
1190 if (h > th) { /* if overflow, compensate */
1197 if (h >= th) { /* check, extra long tabs picked up here also */
1209 #ifndef WINTT_NATIVE
1215 Display[CursorV][CursorH++] = (Char) c;
1216 if (CursorH >= TermH) { /* if we must overflow */
1220 if (T_Margin & MARGIN_AUTO) {
1221 if (T_Margin & MARGIN_MAGIC) {
1223 (void) putraw('\b');
1227 (void) putraw('\r');
1228 (void) putraw('\n');
1236 { /* we added just one char, handle it fast.
1237 * assumes that screen cursor == real cursor */
1238 register Char c, mc;
1240 c = Cursor[-1] & CHAR; /* the char we just added */
1242 if (c == '\t' || Cursor != LastChar) {
1243 Refresh(); /* too hard to handle */
1247 if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1248 Refresh(); /* clear out rprompt if less than one char gap*/
1250 } /* else (only do at end of line, no TAB) */
1252 if (Iscntrl(c)) { /* if control char, do caret */
1254 mc = (c == '\177') ? '?' : (c | 0100);
1258 if (_toascii[c] == '\177' || Isupper(_toebcdic[_toascii[c]|0100])
1259 || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
1261 mc = (_toascii[c] == '\177') ? '?' : _toebcdic[_toascii[c]|0100];
1268 PutPlusOne(((c >> 6) & 7) + '0');
1269 PutPlusOne(((c >> 3) & 7) + '0');
1270 PutPlusOne((c & 7) + '0');
1274 else if (Isprint(c)) { /* normal char */
1282 !adrof(STRnokanji)) {
1288 PutPlusOne(((c >> 6) & 7) + '0');
1289 PutPlusOne(((c >> 3) & 7) + '0');
1290 PutPlusOne((c & 7) + '0');
1295 /* clear the screen buffers so that new new prompt starts fresh. */
1302 CursorV = 0; /* clear the display buffer */
1304 for (i = 0; i < TermV; i++)
1305 (void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
1311 { /* Make sure all lines are *really* blank */
1316 * Clear the lines from the bottom up so that if we try moving
1317 * the cursor down by writing the character that is at the end
1318 * of the screen line, we won't rewrite a character that shouldn't
1321 for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */
1328 MoveToLine(OldvcV); /* go to last line */
1329 (void) putraw('\r'); /* go to BOL */
1330 (void) putraw('\n'); /* go to new line */