1 /* $Header: /src/pub/tcsh/ed.refresh.c,v 3.29 2002/03/08 17:36:45 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.29 2002/03/08 17:36:45 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));
55 static void PutPlusOne
__P((int));
56 static void cpy_pad_spaces
__P((Char
*, Char
*, int));
58 static Char
*update_line_fix_mbyte_point
__P((Char
*, Char
*, int));
60 #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
61 static void dprintf
__P((char *, ...));
63 static void dprintstr
__P((char *, Char
*, Char
*));
70 dprintf("%s:\"", str
);
72 dprintf("%c", *f
++ & ASCII
);
75 #endif /* DEBUG_UPDATE */
78 * Print to $DEBUGTTY, so that we can test editing on one pty, and
79 * print debugging stuff on another. Don't interrupt the shell while
80 * debugging cause you'll mangle up the file descriptors!
84 dprintf(char *fmt
, ...)
93 if ((dtty
= getenv("DEBUGTTY"))) {
101 fmt
= va_arg(va
, char *);
102 #endif /* __STDC__ */
105 fd
= open(dtty
, O_RDWR
);
115 #endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
118 Draw(c
) /* draw c, expand tabs, ctl chars */
121 register Char ch
= c
& CHAR
;
127 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
128 if (ch
== '\n') { /* expand the newline */
130 * Don't force a newline if Vdraw does it (i.e. we're at end of line)
131 * - or we will get two newlines and possibly garbage in between
133 int oldv
= vcursor_v
;
135 Vdraw('\0'); /* assure end of line */
136 if (oldv
== vcursor_v
) {
137 vcursor_h
= 0; /* reset cursor pos */
142 if (ch
== '\t') { /* expand the tab */
145 if ((vcursor_h
& 07) == 0)
146 break; /* go until tab stop */
149 else if (Iscntrl(ch
)) {
152 if (ch
== CTL_ESC('\177')) {
156 /* uncontrolify it; works only for iso8859-1 like sets */
159 if (ch
== CTL_ESC('\177')) {
164 if (Isupper(_toebcdic
[_toascii
[c
]|0100])
165 || strchr("@[\\]^_", _toebcdic
[_toascii
[c
]|0100]) != NULL
)
168 Vdraw(_toebcdic
[_toascii
[c
]|0100]);
173 Vdraw(((c
>> 6) & 7) + '0');
174 Vdraw(((c
>> 3) & 7) + '0');
175 Vdraw((c
& 7) + '0');
185 !adrof(STRnokanji
)) {
192 Vdraw(((c
>> 6) & 7) + '0');
193 Vdraw(((c
>> 3) & 7) + '0');
194 Vdraw((c
& 7) + '0');
199 Vdraw(c
) /* draw char c onto V lines */
203 # ifdef SHORT_STRINGS
204 dprintf("Vdrawing %6.6o '%c'\r\n", c
, c
& ASCII
);
206 dprintf("Vdrawing %3.3o '%c'\r\n", c
, c
);
207 # endif /* SHORT_STRNGS */
208 #endif /* DEBUG_REFRESH */
210 Vdisplay
[vcursor_v
][vcursor_h
] = (Char
) c
;
211 vcursor_h
++; /* advance to next place */
212 if (vcursor_h
>= TermH
) {
213 Vdisplay
[vcursor_v
][TermH
] = '\0'; /* assure end of line */
214 vcursor_h
= 0; /* reset it. */
217 if (vcursor_v
>= TermV
) { /* should NEVER happen. */
218 dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
222 #endif /* DEBUG_REFRESH */
227 * RefreshPromptpart()
228 * draws a prompt element, expanding literals (we know it's ASCIZ)
231 RefreshPromptpart(buf
)
235 static unsigned int litnum
= 0;
242 for (cp
= buf
; *cp
; cp
++) {
244 if (litnum
< (sizeof(litptr
) / sizeof(litptr
[0]))) {
247 dprintf("litnum = %d, litptr = %x:\r\n",
248 litnum
, litptr
[litnum
]);
249 #endif /* DEBUG_LITERAL */
251 while (*cp
& LITERAL
)
254 Vdraw((int) (litnum
++ | LITERAL
));
257 * XXX: This is a bug, we lose the last literal, if it is not
258 * followed by a normal character, but it is too hard to fix
270 * draws the new virtual screen image from the current input
271 * line, then goes line-by-line changing the real image to the new
272 * virtual image. The routine to re-draw a line can be replaced
273 * easily in hopes of a smarter one being placed there.
275 static int OldvcV
= 0;
279 register int cur_line
;
281 int cur_h
, cur_v
= 0, new_vcv
;
286 dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf
));
287 dprintf("InputBuf = :%s:\r\n", short2str(InputBuf
));
288 #endif /* DEBUG_REFRESH */
289 oldgetting
= GettingInput
;
290 GettingInput
= 0; /* avoid re-entrance via SIGWINCH */
292 /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
295 RefreshPromptpart(NULL
);
296 RefreshPromptpart(RPromptBuf
);
297 rprompt_h
= vcursor_h
;
298 rprompt_v
= vcursor_v
;
300 /* reset the Vdraw cursor, draw prompt */
303 RefreshPromptpart(NULL
);
304 RefreshPromptpart(PromptBuf
);
305 cur_h
= -1; /* set flag in case I'm not set */
307 /* draw the current input buffer */
308 for (cp
= InputBuf
; (cp
< LastChar
); cp
++) {
310 cur_h
= vcursor_h
; /* save for later */
316 if (cur_h
== -1) { /* if I haven't been set yet, I'm at the end */
321 rhdiff
= TermH
- vcursor_h
- rprompt_h
;
322 if (rprompt_h
!= 0 && rprompt_v
== 0 && vcursor_v
== 0 && rhdiff
> 1) {
324 * have a right-hand side prompt that will fit on
325 * the end of the first line with at least one
326 * character gap to the input buffer.
328 while (--rhdiff
> 0) /* pad out with spaces */
330 RefreshPromptpart(RPromptBuf
);
333 rprompt_h
= 0; /* flag "not using rprompt" */
337 new_vcv
= vcursor_v
; /* must be done BEFORE the NUL is written */
338 Vdraw('\0'); /* put NUL on end */
341 dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
342 TermH
, vcursor_h
, vcursor_v
, short2str(Vdisplay
[0]));
343 #endif /* DEBUG_REFRESH */
346 dprintf("updating %d lines.\r\n", new_vcv
);
347 #endif /* DEBUG_UPDATE */
348 for (cur_line
= 0; cur_line
<= new_vcv
; cur_line
++) {
349 /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
350 update_line(Display
[cur_line
], Vdisplay
[cur_line
], cur_line
);
353 #endif /* WINNT_NATIVE */
356 * Copy the new line to be the current one, and pad out with spaces
357 * to the full width of the terminal so that if we try moving the
358 * cursor by writing the character that is at the end of the
359 * screen line, it won't be a NUL or some old leftover stuff.
361 cpy_pad_spaces(Display
[cur_line
], Vdisplay
[cur_line
], TermH
);
363 (void) Strncpy(Display
[cur_line
], Vdisplay
[cur_line
], (size_t) TermH
);
364 Display
[cur_line
][TermH
] = '\0'; /* just in case */
368 dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
369 vcursor_v
, OldvcV
, cur_line
);
370 #endif /* DEBUG_REFRESH */
371 if (OldvcV
> new_vcv
) {
372 for (; cur_line
<= OldvcV
; cur_line
++) {
373 update_line(Display
[cur_line
], STRNULL
, cur_line
);
374 *Display
[cur_line
] = '\0';
377 OldvcV
= new_vcv
; /* set for next time */
379 dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
380 CursorH
, CursorV
, cur_h
, cur_v
);
381 #endif /* DEBUG_REFRESH */
384 #endif /* WINNT_NATIVE */
385 MoveToLine(cur_v
); /* go to where the cursor is */
387 SetAttributes(0); /* Clear all attributes */
388 flush(); /* send the output... */
389 GettingInput
= oldgetting
; /* reset to old value */
394 { /* used to go to last used screen line */
402 { /* used to go to last used screen line */
411 /* insert num characters of s into d (in front of the character) at dat,
412 maximum length of d is dlen */
414 str_insert(d
, dat
, dlen
, s
, num
)
416 register int dat
, dlen
;
420 register Char
*a
, *b
;
424 if (num
> dlen
- dat
)
428 dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
429 num
, dat
, dlen
, short2str(d
));
430 dprintf("s == \"%s\"n", short2str(s
));
431 #endif /* DEBUG_REFRESH */
433 /* open up the space for num chars */
439 d
[dlen
] = '\0'; /* just in case */
442 dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
443 num
, dat
, dlen
, short2str(d
));
444 dprintf("s == \"%s\"n", short2str(s
));
445 #endif /* DEBUG_REFRESH */
447 /* copy the characters */
448 for (a
= d
+ dat
; (a
< d
+ dlen
) && (num
> 0); num
--)
452 dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
453 num
, dat
, dlen
, d
, short2str(s
));
454 dprintf("s == \"%s\"n", short2str(s
));
455 #endif /* DEBUG_REFRESH */
458 /* delete num characters d at dat, maximum length of d is dlen */
460 str_delete(d
, dat
, dlen
, num
)
462 register int dat
, dlen
, num
;
464 register Char
*a
, *b
;
468 if (dat
+ num
>= dlen
) {
474 dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
475 num
, dat
, dlen
, short2str(d
));
476 #endif /* DEBUG_REFRESH */
478 /* open up the space for num chars */
484 d
[dlen
] = '\0'; /* just in case */
487 dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
488 num
, dat
, dlen
, short2str(d
));
489 #endif /* DEBUG_REFRESH */
494 register Char
*a
, *b
;
502 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
504 update_line_fix_mbyte_point(start
, target
, d
)
505 Char
*start
, *target
;
508 if (_enable_mbdisp
) {
514 if (Ismbyte1(*start
) && Ismbyte2(*(start
+ 1)))
523 /* ****************************************************************
524 update_line() is based on finding the middle difference of each line
527 /old first difference
528 /beginning of line | /old last same /old EOL
530 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
531 new: eddie> Oh, my little buggy says to me, as lurgid as
533 \beginning of line | \new last same \new end of line
534 \new first difference
536 all are character pointers for the sake of speed. Special cases for
537 no differences, as well as for end of line additions must be handled.
538 **************************************************************** */
540 /* Minimum at which doing an insert it "worth it". This should be about
541 * half the "cost" of going into insert mode, inserting a character, and
542 * going back out. This should really be calculated from the termcap
543 * data... For the moment, a good number for ANSI terminals.
545 #define MIN_END_KEEP 4
547 static void /* could be changed to make it smarter */
548 update_line(old
, new, cur_line
)
549 register Char
*old
, *new;
552 register Char
*o
, *n
, *p
, c
;
553 Char
*ofd
, *ols
, *oe
, *nfd
, *nls
, *ne
;
554 Char
*osb
, *ose
, *nsb
, *nse
;
560 for (o
= old
, n
= new; *o
&& (*o
== *n
); o
++, n
++)
566 * Find the end of both old and new
571 * Remove any trailing blanks off of the end, being careful not to
572 * back up past the beginning.
585 /* remove blanks from end of new */
595 * if no diff, continue to next line of redraw
597 if (*ofd
== '\0' && *nfd
== '\0') {
599 dprintf("no difference.\r\n");
600 #endif /* DEBUG_UPDATE */
605 * find last same pointer
607 while ((o
> ofd
) && (n
> nfd
) && (*--o
== *--n
))
613 * find same begining and same end
621 * case 1: insert: scan from nfd to nls looking for *ofd
624 for (c
= *ofd
, n
= nfd
; n
< nls
; n
++) {
626 for (o
= ofd
, p
= n
; p
< nls
&& o
< ols
&& *o
== *p
; o
++, p
++)
629 * if the new match is longer and it's worth keeping, then we
632 if (((nse
- nsb
) < (p
- n
)) && (2 * (p
- n
) > n
- nfd
)) {
643 * case 2: delete: scan from ofd to ols looking for *nfd
646 for (c
= *nfd
, o
= ofd
; o
< ols
; o
++) {
648 for (n
= nfd
, p
= o
; p
< ols
&& n
< nls
&& *p
== *n
; p
++, n
++)
651 * if the new match is longer and it's worth keeping, then we
654 if (((ose
- osb
) < (p
- o
)) && (2 * (p
- o
) > o
- ofd
)) {
665 * If `last same' is before `same end' re-adjust
674 * Pragmatics I: If old trailing whitespace or not enough characters to
675 * save to be worth it, then don't save the last same info.
677 if ((oe
- ols
) < MIN_END_KEEP
) {
683 * Pragmatics II: if the terminal isn't smart enough, make the data dumber
684 * so the smart update doesn't try anything fancy
688 * fx is the number of characters we need to insert/delete: in the
689 * beginning to bring the two same begins together
691 fx
= (int) ((nsb
- nfd
) - (osb
- ofd
));
693 * sx is the number of characters we need to insert/delete: in the end to
694 * bring the two same last parts together
696 sx
= (int) ((nls
- nse
) - (ols
- ose
));
709 if ((ols
- ofd
) < (nls
- nfd
)) {
725 if ((ols
- ofd
) > (nls
- nfd
)) {
732 * Pragmatics III: make sure the middle shifted pointers are correct if
733 * they don't point to anything (we may have moved ols or nls).
735 /* if the change isn't worth it, don't bother */
736 /* was: if (osb == ose) */
737 if ((ose
- osb
) < MIN_END_KEEP
) {
745 * Now that we are done with pragmatics we recompute fx, sx
747 fx
= (int) ((nsb
- nfd
) - (osb
- ofd
));
748 sx
= (int) ((nls
- nse
) - (ols
- ose
));
752 dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
753 ofd
- old
, osb
- old
, ose
- old
, ols
- old
, oe
- old
);
754 dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
755 nfd
- new, nsb
- new, nse
- new, nls
- new, ne
- new);
756 dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
757 dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
758 dprintstr("old- oe", old
, oe
);
759 dprintstr("new- ne", new, ne
);
760 dprintstr("old-ofd", old
, ofd
);
761 dprintstr("new-nfd", new, nfd
);
762 dprintstr("ofd-osb", ofd
, osb
);
763 dprintstr("nfd-nsb", nfd
, nsb
);
764 dprintstr("osb-ose", osb
, ose
);
765 dprintstr("nsb-nse", nsb
, nse
);
766 dprintstr("ose-ols", ose
, ols
);
767 dprintstr("nse-nls", nse
, nls
);
768 dprintstr("ols- oe", ols
, oe
);
769 dprintstr("nls- ne", nls
, ne
);
770 #endif /* DEBUG_UPDATE */
773 * CursorV to this line cur_line MUST be in this routine so that if we
774 * don't have to change the line, we don't move to it. CursorH to first
777 MoveToLine(cur_line
);
779 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
780 ofd
= update_line_fix_mbyte_point(old
, ofd
, -1);
781 osb
= update_line_fix_mbyte_point(old
, osb
, 1);
782 ose
= update_line_fix_mbyte_point(old
, ose
, -1);
783 ols
= update_line_fix_mbyte_point(old
, ols
, 1);
784 nfd
= update_line_fix_mbyte_point(new, nfd
, -1);
785 nsb
= update_line_fix_mbyte_point(new, nsb
, 1);
786 nse
= update_line_fix_mbyte_point(new, nse
, -1);
787 nls
= update_line_fix_mbyte_point(new, nls
, 1);
791 * at this point we have something like this:
793 * /old /ofd /osb /ose /ols /oe
794 * v.....................v v..................v v........v
795 * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
796 * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
797 * ^.....................^ ^..................^ ^........^
798 * \new \nfd \nsb \nse \nls \ne
800 * fx is the difference in length between the the chars between nfd and
801 * nsb, and the chars between ofd and osb, and is thus the number of
802 * characters to delete if < 0 (new is shorter than old, as above),
803 * or insert (new is longer than short).
805 * sx is the same for the second differences.
809 * if we have a net insert on the first difference, AND inserting the net
810 * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
811 * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
812 * (TermH - 1) else we do the deletes first so that we keep everything we
817 * if the last same is the same like the end, there is no last same part,
818 * otherwise we want to keep the last same part set p to the last useful
821 p
= (ols
!= oe
) ? oe
: ose
;
824 * if (There is a diffence in the beginning) && (we need to insert
825 * characters) && (the number of characters to insert is less than the term
826 * width) We need to do an insert! else if (we need to delete characters)
827 * We need to delete characters! else No insert or delete
829 if ((nsb
!= nfd
) && fx
> 0 && ((p
- old
) + fx
< TermH
)) {
831 dprintf("first diff insert at %d...\r\n", nfd
- new);
832 #endif /* DEBUG_UPDATE */
834 * Move to the first char to insert, where the first diff is.
836 MoveToChar(nfd
- new);
838 * Check if we have stuff to keep at end
842 dprintf("with stuff to keep at end\r\n");
843 #endif /* DEBUG_UPDATE */
845 * insert fx chars of new starting at nfd
850 dprintf(" ERROR: cannot insert in early first diff\n");
851 #endif /* DEBUG_UPDATE */
852 Insert_write(nfd
, fx
);
853 str_insert(old
, (int) (ofd
- old
), TermH
, nfd
, fx
);
856 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
858 so_write(nfd
+ fx
, (nsb
- nfd
) - fx
);
859 str_cp(ofd
+ fx
, nfd
+ fx
, (int) ((nsb
- nfd
) - fx
));
863 dprintf("without anything to save\r\n");
864 #endif /* DEBUG_UPDATE */
865 so_write(nfd
, (nsb
- nfd
));
866 str_cp(ofd
, nfd
, (int) (nsb
- nfd
));
875 dprintf("first diff delete at %d...\r\n", ofd
- old
);
876 #endif /* DEBUG_UPDATE */
878 * move to the first char to delete where the first diff is
880 MoveToChar(ofd
- old
);
882 * Check if we have stuff to save
886 dprintf("with stuff to save at end\r\n");
887 #endif /* DEBUG_UPDATE */
889 * fx is less than zero *always* here but we check for code
895 dprintf(" ERROR: cannot delete in first diff\n");
896 #endif /* DEBUG_UPDATE */
898 str_delete(old
, (int) (ofd
- old
), TermH
, -fx
);
901 * write (nsb-nfd) chars of new starting at nfd
903 so_write(nfd
, (nsb
- nfd
));
904 str_cp(ofd
, nfd
, (int) (nsb
- nfd
));
909 dprintf("but with nothing left to save\r\n");
910 #endif /* DEBUG_UPDATE */
912 * write (nsb-nfd) chars of new starting at nfd
914 so_write(nfd
, (nsb
- nfd
));
916 dprintf("cleareol %d\n", (oe
- old
) - (ne
- new));
917 #endif /* DEBUG_UPDATE */
919 ClearEOL((oe
- old
) - (ne
- new));
922 * The calculation above does not work too well on NT
924 ClearEOL(TermH
- CursorH
);
925 #endif /*WINNT_NATIVE*/
937 dprintf("second diff delete at %d...\r\n", (ose
- old
) + fx
);
938 #endif /* DEBUG_UPDATE */
940 * Check if we have stuff to delete
943 * fx is the number of characters inserted (+) or deleted (-)
946 MoveToChar((ose
- old
) + fx
);
948 * Check if we have stuff to save
952 dprintf("with stuff to save at end\r\n");
953 #endif /* DEBUG_UPDATE */
955 * Again a duplicate test.
960 dprintf(" ERROR: cannot delete in second diff\n");
961 #endif /* DEBUG_UPDATE */
966 * write (nls-nse) chars of new starting at nse
968 so_write(nse
, (nls
- nse
));
971 int olen
= (int) (oe
- old
+ fx
);
975 dprintf("but with nothing left to save\r\n");
976 #endif /* DEBUG_UPDATE */
977 so_write(nse
, (nls
- nse
));
979 dprintf("cleareol %d\n", olen
- (ne
- new));
980 #endif /* DEBUG_UPDATE */
982 ClearEOL(olen
- (ne
- new));
985 * The calculation above does not work too well on NT
987 ClearEOL(TermH
- CursorH
);
988 #endif /*WINNT_NATIVE*/
993 * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
995 if ((nsb
!= nfd
) && (osb
- ofd
) <= (nsb
- nfd
) && (fx
== 0)) {
997 dprintf("late first diff insert at %d...\r\n", nfd
- new);
998 #endif /* DEBUG_UPDATE */
1000 MoveToChar(nfd
- new);
1002 * Check if we have stuff to keep at the end
1006 dprintf("with stuff to keep at end\r\n");
1007 #endif /* DEBUG_UPDATE */
1009 * We have to recalculate fx here because we set it
1010 * to zero above as a flag saying that we hadn't done
1011 * an early first insert.
1013 fx
= (int) ((nsb
- nfd
) - (osb
- ofd
));
1016 * insert fx chars of new starting at nfd
1020 dprintf(" ERROR: cannot insert in late first diff\n");
1021 #endif /* DEBUG_UPDATE */
1022 Insert_write(nfd
, fx
);
1023 str_insert(old
, (int) (ofd
- old
), TermH
, nfd
, fx
);
1027 * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1029 so_write(nfd
+ fx
, (nsb
- nfd
) - fx
);
1030 str_cp(ofd
+ fx
, nfd
+ fx
, (int) ((nsb
- nfd
) - fx
));
1034 dprintf("without anything to save\r\n");
1035 #endif /* DEBUG_UPDATE */
1036 so_write(nfd
, (nsb
- nfd
));
1037 str_cp(ofd
, nfd
, (int) (nsb
- nfd
));
1042 * line is now NEW up to nse
1046 dprintf("second diff insert at %d...\r\n", nse
- new);
1047 #endif /* DEBUG_UPDATE */
1048 MoveToChar(nse
- new);
1051 dprintf("with stuff to keep at end\r\n");
1052 #endif /* DEBUG_UPDATE */
1054 /* insert sx chars of new starting at nse */
1057 dprintf(" ERROR: cannot insert in second diff\n");
1058 #endif /* DEBUG_UPDATE */
1059 Insert_write(nse
, sx
);
1063 * write (nls-nse) - sx chars of new starting at (nse + sx)
1065 so_write(nse
+ sx
, (nls
- nse
) - sx
);
1069 dprintf("without anything to save\r\n");
1070 #endif /* DEBUG_UPDATE */
1071 so_write(nse
, (nls
- nse
));
1074 * No need to do a clear-to-end here because we were doing
1075 * a second insert, so we will have over written all of the
1081 dprintf("done.\r\n");
1082 #endif /* DEBUG_UPDATE */
1087 cpy_pad_spaces(dst
, src
, width
)
1088 register Char
*dst
, *src
;
1093 for (i
= 0; i
< width
; i
++) {
1094 if (*src
== (Char
) 0)
1108 { /* only move to new cursor pos */
1109 register Char
*cp
, c
;
1110 register int h
, th
, v
;
1112 /* first we must find where the cursor is... */
1115 th
= TermH
; /* optimize for speed */
1117 for (cp
= PromptBuf
; *cp
; cp
++) { /* do prompt */
1120 c
= *cp
& CHAR
; /* extra speed plus strip the inverse */
1121 h
++; /* all chars at least this long */
1123 /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
1124 /* lets handle newline as part of the prompt */
1131 if (c
== '\t') { /* if a tab, to next tab stop */
1136 else if (Iscntrl(c
)) { /* if control char */
1138 if (h
> th
) { /* if overflow, compensate */
1143 else if (!Isprint(c
)) {
1145 if (h
> th
) { /* if overflow, compensate */
1152 if (h
>= th
) { /* check, extra long tabs picked up here also */
1158 for (cp
= InputBuf
; cp
< Cursor
; cp
++) { /* do input buffer to Cursor */
1159 c
= *cp
& CHAR
; /* extra speed plus strip the inverse */
1160 h
++; /* all chars at least this long */
1162 if (c
== '\n') { /* handle newline in data part too */
1167 if (c
== '\t') { /* if a tab, to next tab stop */
1172 else if (Iscntrl(c
)) { /* if control char */
1174 if (h
> th
) { /* if overflow, compensate */
1179 else if (!Isprint(c
)) {
1181 if (h
> th
) { /* if overflow, compensate */
1188 if (h
>= th
) { /* check, extra long tabs picked up here also */
1205 Display
[CursorV
][CursorH
++] = (Char
) c
;
1206 if (CursorH
>= TermH
) { /* if we must overflow */
1210 if (T_Margin
& MARGIN_AUTO
) {
1211 if (T_Margin
& MARGIN_MAGIC
) {
1213 (void) putraw('\b');
1217 (void) putraw('\r');
1218 (void) putraw('\n');
1225 { /* we added just one char, handle it fast.
1226 * assumes that screen cursor == real cursor */
1227 register Char c
, mc
;
1229 c
= Cursor
[-1] & CHAR
; /* the char we just added */
1231 if (c
== '\t' || Cursor
!= LastChar
) {
1232 Refresh(); /* too hard to handle */
1236 if (rprompt_h
!= 0 && (TermH
- CursorH
- rprompt_h
< 3)) {
1237 Refresh(); /* clear out rprompt if less than one char gap*/
1239 } /* else (only do at end of line, no TAB) */
1241 if (Iscntrl(c
)) { /* if control char, do caret */
1243 mc
= (c
== '\177') ? '?' : (c
| 0100);
1247 if (_toascii
[c
] == '\177' || Isupper(_toebcdic
[_toascii
[c
]|0100])
1248 || strchr("@[\\]^_", _toebcdic
[_toascii
[c
]|0100]) != NULL
)
1250 mc
= (_toascii
[c
] == '\177') ? '?' : _toebcdic
[_toascii
[c
]|0100];
1257 PutPlusOne(((c
>> 6) & 7) + '0');
1258 PutPlusOne(((c
>> 3) & 7) + '0');
1259 PutPlusOne((c
& 7) + '0');
1263 else if (Isprint(c
)) { /* normal char */
1271 !adrof(STRnokanji
)) {
1277 PutPlusOne(((c
>> 6) & 7) + '0');
1278 PutPlusOne(((c
>> 3) & 7) + '0');
1279 PutPlusOne((c
& 7) + '0');
1284 /* clear the screen buffers so that new new prompt starts fresh. */
1291 CursorV
= 0; /* clear the display buffer */
1293 for (i
= 0; i
< TermV
; i
++)
1294 (void) memset(Display
[i
], 0, TermH
* sizeof(Display
[0][0]));
1300 { /* Make sure all lines are *really* blank */
1305 * Clear the lines from the bottom up so that if we try moving
1306 * the cursor down by writing the character that is at the end
1307 * of the screen line, we won't rewrite a character that shouldn't
1310 for (i
= OldvcV
; i
>= 0; i
--) { /* for each line on the screen */
1317 MoveToLine(OldvcV
); /* go to last line */
1318 (void) putraw('\r'); /* go to BOL */
1319 (void) putraw('\n'); /* go to new line */