1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * ed.refresh.c: Lower level screen refreshing functions
3c80476e4SDavid E. O'Brien */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien * All rights reserved.
7c80476e4SDavid E. O'Brien *
8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien * are met:
11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien * without specific prior written permission.
19c80476e4SDavid E. O'Brien *
20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien /* #define DEBUG_UPDATE */
35c80476e4SDavid E. O'Brien /* #define DEBUG_REFRESH */
36c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */
37c80476e4SDavid E. O'Brien
38c80476e4SDavid E. O'Brien /* refresh.c -- refresh the current set of lines on the screen */
39c80476e4SDavid E. O'Brien
4023338178SMark Peek Char *litptr;
41c80476e4SDavid E. O'Brien static int vcursor_h, vcursor_v;
42c80476e4SDavid E. O'Brien static int rprompt_h, rprompt_v;
43c80476e4SDavid E. O'Brien
4445e5710bSMark Peek static int MakeLiteral (Char *, int, Char);
45*19d2e3deSDmitry Chagin static int Draw (Char *, int, int);
4645e5710bSMark Peek static void Vdraw (Char, int);
4745e5710bSMark Peek static void RefreshPromptpart (Char *);
4845e5710bSMark Peek static void update_line (Char *, Char *, int);
4945e5710bSMark Peek static void str_insert (Char *, int, int, Char *, int);
5045e5710bSMark Peek static void str_delete (Char *, int, int, int);
5145e5710bSMark Peek static void str_cp (Char *, Char *, int);
52b2d5d167SMark Peek #ifndef WINNT_NATIVE
53b2d5d167SMark Peek static
54b2d5d167SMark Peek #else
55b2d5d167SMark Peek extern
56b2d5d167SMark Peek #endif
5745e5710bSMark Peek void PutPlusOne (Char, int);
5845e5710bSMark Peek static void cpy_pad_spaces (Char *, Char *, int);
59c80476e4SDavid E. O'Brien #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
609ccc37e3SMark Peek static void reprintf (char *, ...);
61c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6245e5710bSMark Peek static void dprintstr (char *, const Char *, const Char *);
63c80476e4SDavid E. O'Brien
64c80476e4SDavid E. O'Brien static void
dprintstr(char * str,const Char * f,const Char * t)6545e5710bSMark Peek dprintstr(char *str, const Char *f, const Char *t)
66c80476e4SDavid E. O'Brien {
679ccc37e3SMark Peek reprintf("%s:\"", str);
6823338178SMark Peek while (f < t) {
6945e5710bSMark Peek if (ASC(*f) & ~ASCII)
709ccc37e3SMark Peek reprintf("[%x]", *f++);
7123338178SMark Peek else
729ccc37e3SMark Peek reprintf("%c", CTL_ESC(ASCII & ASC(*f++)));
7323338178SMark Peek }
749ccc37e3SMark Peek reprintf("\"\r\n");
75c80476e4SDavid E. O'Brien }
76c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
77c80476e4SDavid E. O'Brien
789ccc37e3SMark Peek /* reprintf():
79c80476e4SDavid E. O'Brien * Print to $DEBUGTTY, so that we can test editing on one pty, and
80c80476e4SDavid E. O'Brien * print debugging stuff on another. Don't interrupt the shell while
81c80476e4SDavid E. O'Brien * debugging cause you'll mangle up the file descriptors!
82c80476e4SDavid E. O'Brien */
83c80476e4SDavid E. O'Brien static void
reprintf(char * fmt,...)849ccc37e3SMark Peek reprintf(char *fmt, ...)
85c80476e4SDavid E. O'Brien {
86c80476e4SDavid E. O'Brien static int fd = -1;
87c80476e4SDavid E. O'Brien char *dtty;
88c80476e4SDavid E. O'Brien
89c80476e4SDavid E. O'Brien if ((dtty = getenv("DEBUGTTY"))) {
90c80476e4SDavid E. O'Brien int o;
91c80476e4SDavid E. O'Brien va_list va;
92c80476e4SDavid E. O'Brien va_start(va, fmt);
93c80476e4SDavid E. O'Brien
94c80476e4SDavid E. O'Brien if (fd == -1)
9545e5710bSMark Peek fd = xopen(dtty, O_RDWR);
96c80476e4SDavid E. O'Brien o = SHOUT;
97c80476e4SDavid E. O'Brien flush();
98c80476e4SDavid E. O'Brien SHOUT = fd;
99c80476e4SDavid E. O'Brien xvprintf(fmt, va);
100c80476e4SDavid E. O'Brien va_end(va);
101c80476e4SDavid E. O'Brien flush();
102c80476e4SDavid E. O'Brien SHOUT = o;
103c80476e4SDavid E. O'Brien }
104c80476e4SDavid E. O'Brien }
105c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
106c80476e4SDavid E. O'Brien
10723338178SMark Peek static int litlen = 0, litalloc = 0;
10823338178SMark Peek
MakeLiteral(Char * str,int len,Char addlit)10945e5710bSMark Peek static int MakeLiteral(Char *str, int len, Char addlit)
110c80476e4SDavid E. O'Brien {
11123338178SMark Peek int i, addlitlen = 0;
11223338178SMark Peek Char *addlitptr = 0;
11323338178SMark Peek if (addlit) {
11423338178SMark Peek if ((addlit & LITERAL) != 0) {
11523338178SMark Peek addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
11623338178SMark Peek addlitlen = Strlen(addlitptr);
11723338178SMark Peek } else {
11823338178SMark Peek addlitptr = &addlit;
11923338178SMark Peek addlitlen = 1;
120c80476e4SDavid E. O'Brien }
12123338178SMark Peek for (i = 0; i < litlen; i += LIT_FACTOR)
12223338178SMark Peek if (!Strncmp(addlitptr, litptr + i, addlitlen) && !Strncmp(str, litptr + i + addlitlen, len) && litptr[i + addlitlen + len] == 0)
12323338178SMark Peek return (i / LIT_FACTOR) | LITERAL;
12423338178SMark Peek } else {
12523338178SMark Peek addlitlen = 0;
12623338178SMark Peek for (i = 0; i < litlen; i += LIT_FACTOR)
12723338178SMark Peek if (!Strncmp(str, litptr + i, len) && litptr[i + len] == 0)
12823338178SMark Peek return (i / LIT_FACTOR) | LITERAL;
12923338178SMark Peek }
13023338178SMark Peek if (litlen + addlitlen + len + 1 + (LIT_FACTOR - 1) > litalloc) {
13123338178SMark Peek Char *newlitptr;
13223338178SMark Peek int add = 256;
13323338178SMark Peek while (len + addlitlen + 1 + (LIT_FACTOR - 1) > add)
13423338178SMark Peek add *= 2;
13545e5710bSMark Peek newlitptr = xrealloc(litptr, (litalloc + add) * sizeof(Char));
13623338178SMark Peek if (!newlitptr)
13723338178SMark Peek return '?';
13823338178SMark Peek litptr = newlitptr;
13923338178SMark Peek litalloc += add;
14023338178SMark Peek if (addlitptr && addlitptr != &addlit)
14123338178SMark Peek addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
14223338178SMark Peek }
14323338178SMark Peek i = litlen / LIT_FACTOR;
14423338178SMark Peek if (i >= LITERAL || i == CHAR_DBWIDTH)
14523338178SMark Peek return '?';
14623338178SMark Peek if (addlitptr) {
14723338178SMark Peek Strncpy(litptr + litlen, addlitptr, addlitlen);
14823338178SMark Peek litlen += addlitlen;
14923338178SMark Peek }
15023338178SMark Peek Strncpy(litptr + litlen, str, len);
15123338178SMark Peek litlen += len;
15223338178SMark Peek do
15323338178SMark Peek litptr[litlen++] = 0;
15423338178SMark Peek while (litlen % LIT_FACTOR);
15523338178SMark Peek return i | LITERAL;
15623338178SMark Peek }
157c80476e4SDavid E. O'Brien
158*19d2e3deSDmitry Chagin /* draw char at cp, expand tabs, ctl chars */
15923338178SMark Peek static int
Draw(Char * cp,int nocomb,int drawPrompt)160*19d2e3deSDmitry Chagin Draw(Char *cp, int nocomb, int drawPrompt)
16123338178SMark Peek {
16245e5710bSMark Peek int w, i, lv, lh;
16345e5710bSMark Peek Char c, attr;
16423338178SMark Peek
165*19d2e3deSDmitry Chagin #ifdef WIDE_STRINGS
166*19d2e3deSDmitry Chagin if (!drawPrompt) { /* draw command-line */
167*19d2e3deSDmitry Chagin attr = 0;
168*19d2e3deSDmitry Chagin c = *cp;
169*19d2e3deSDmitry Chagin } else { /* draw prompt */
170*19d2e3deSDmitry Chagin /* prompt with attributes(UNDER,BOLD,STANDOUT) */
171*19d2e3deSDmitry Chagin if (*cp & (UNDER | BOLD | STANDOUT)) { /* *cp >= STANDOUT */
172*19d2e3deSDmitry Chagin
173*19d2e3deSDmitry Chagin /* example)
174*19d2e3deSDmitry Chagin * We can't distinguish whether (*cp=)0x02ffffff is
175*19d2e3deSDmitry Chagin * U+02FFFFFF or U+00FFFFFF|STANDOUT.
176*19d2e3deSDmitry Chagin * We handle as U+00FFFFFF|STANDOUT, only when drawing prompt. */
177*19d2e3deSDmitry Chagin attr = (*cp & ATTRIBUTES);
178*19d2e3deSDmitry Chagin /* ~(UNDER | BOLD | STANDOUT) = 0xf1ffffff */
179*19d2e3deSDmitry Chagin c = *cp & ~(UNDER | BOLD | STANDOUT);
180*19d2e3deSDmitry Chagin
181*19d2e3deSDmitry Chagin /* if c is ctrl code, we handle *cp as havnig no attributes */
182*19d2e3deSDmitry Chagin if ((c < 0x20 && c >= 0) || c == 0x7f) {
183*19d2e3deSDmitry Chagin attr = 0;
184*19d2e3deSDmitry Chagin c = *cp;
185*19d2e3deSDmitry Chagin }
186*19d2e3deSDmitry Chagin } else { /* prompt without attributes */
187*19d2e3deSDmitry Chagin attr = 0;
188*19d2e3deSDmitry Chagin c = *cp;
189*19d2e3deSDmitry Chagin }
190*19d2e3deSDmitry Chagin }
191*19d2e3deSDmitry Chagin #else
19223338178SMark Peek attr = *cp & ~CHAR;
19345e5710bSMark Peek c = *cp & CHAR;
194*19d2e3deSDmitry Chagin #endif
195*19d2e3deSDmitry Chagin w = NLSClassify(c, nocomb, drawPrompt);
19623338178SMark Peek switch (w) {
19723338178SMark Peek case NLSCLASS_NL:
19823338178SMark Peek Vdraw('\0', 0); /* assure end of line */
199c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset cursor pos */
200c80476e4SDavid E. O'Brien vcursor_v++;
20123338178SMark Peek break;
20223338178SMark Peek case NLSCLASS_TAB:
20323338178SMark Peek do {
20423338178SMark Peek Vdraw(' ', 1);
20523338178SMark Peek } while ((vcursor_h & 07) != 0);
20623338178SMark Peek break;
20723338178SMark Peek case NLSCLASS_CTRL:
20823338178SMark Peek Vdraw('^' | attr, 1);
20923338178SMark Peek if (c == CTL_ESC('\177')) {
21023338178SMark Peek Vdraw('?' | attr, 1);
21123338178SMark Peek } else {
2123b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
213c80476e4SDavid E. O'Brien /* uncontrolify it; works only for iso8859-1 like sets */
21423338178SMark Peek Vdraw(c | 0100 | attr, 1);
2153b6eaa7bSAndrey A. Chernov #else
21623338178SMark Peek Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1);
21723338178SMark Peek #endif
218c80476e4SDavid E. O'Brien }
21923338178SMark Peek break;
22023338178SMark Peek case NLSCLASS_ILLEGAL:
22123338178SMark Peek Vdraw('\\' | attr, 1);
22245e5710bSMark Peek Vdraw((((c >> 6) & 7) + '0') | attr, 1);
22345e5710bSMark Peek Vdraw((((c >> 3) & 7) + '0') | attr, 1);
22445e5710bSMark Peek Vdraw(((c & 7) + '0') | attr, 1);
22523338178SMark Peek break;
22623338178SMark Peek case NLSCLASS_ILLEGAL2:
22723338178SMark Peek case NLSCLASS_ILLEGAL3:
22823338178SMark Peek case NLSCLASS_ILLEGAL4:
229*19d2e3deSDmitry Chagin case NLSCLASS_ILLEGAL5:
230*19d2e3deSDmitry Chagin Vdraw('\\', 1);
231*19d2e3deSDmitry Chagin Vdraw('U', 1);
232*19d2e3deSDmitry Chagin Vdraw('+', 1);
233*19d2e3deSDmitry Chagin for (i = 16 + 4 * (-w-5); i >= 0; i -= 4)
23423338178SMark Peek Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1);
23523338178SMark Peek break;
23623338178SMark Peek case 0:
23723338178SMark Peek lv = vcursor_v;
23823338178SMark Peek lh = vcursor_h;
23923338178SMark Peek for (;;) {
24023338178SMark Peek lh--;
24123338178SMark Peek if (lh < 0) {
24223338178SMark Peek lv--;
24323338178SMark Peek if (lv < 0)
24423338178SMark Peek break;
24523338178SMark Peek lh = Strlen(Vdisplay[lv]) - 1;
246c80476e4SDavid E. O'Brien }
24723338178SMark Peek if (Vdisplay[lv][lh] != CHAR_DBWIDTH)
24823338178SMark Peek break;
24923338178SMark Peek }
25023338178SMark Peek if (lv < 0) {
25123338178SMark Peek Vdraw('\\' | attr, 1);
25245e5710bSMark Peek Vdraw((((c >> 6) & 7) + '0') | attr, 1);
25345e5710bSMark Peek Vdraw((((c >> 3) & 7) + '0') | attr, 1);
25445e5710bSMark Peek Vdraw(((c & 7) + '0') | attr, 1);
25545e5710bSMark Peek break;
25623338178SMark Peek }
25745e5710bSMark Peek Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]);
25823338178SMark Peek break;
25923338178SMark Peek default:
26023338178SMark Peek Vdraw(*cp, w);
26123338178SMark Peek break;
262c80476e4SDavid E. O'Brien }
26345e5710bSMark Peek return 1;
264c80476e4SDavid E. O'Brien }
265c80476e4SDavid E. O'Brien
266c80476e4SDavid E. O'Brien static void
Vdraw(Char c,int width)26745e5710bSMark Peek Vdraw(Char c, int width) /* draw char c onto V lines */
268c80476e4SDavid E. O'Brien {
269c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
270c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS
2719ccc37e3SMark Peek reprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width);
272c80476e4SDavid E. O'Brien # else
2739ccc37e3SMark Peek reprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width);
274c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */
275c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
276c80476e4SDavid E. O'Brien
27723338178SMark Peek /* Hopefully this is what all the terminals do with multi-column characters
27823338178SMark Peek that "span line breaks". */
27923338178SMark Peek while (vcursor_h + width > TermH)
28023338178SMark Peek Vdraw(' ', 1);
28145e5710bSMark Peek Vdisplay[vcursor_v][vcursor_h] = c;
28223338178SMark Peek if (width)
283c80476e4SDavid E. O'Brien vcursor_h++; /* advance to next place */
28423338178SMark Peek while (--width > 0)
28523338178SMark Peek Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH;
286c80476e4SDavid E. O'Brien if (vcursor_h >= TermH) {
287c80476e4SDavid E. O'Brien Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */
288c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset it. */
289c80476e4SDavid E. O'Brien vcursor_v++;
290c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
291c80476e4SDavid E. O'Brien if (vcursor_v >= TermV) { /* should NEVER happen. */
2929ccc37e3SMark Peek reprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
293c80476e4SDavid E. O'Brien vcursor_v, TermV);
294c80476e4SDavid E. O'Brien abort();
295c80476e4SDavid E. O'Brien }
296c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
297c80476e4SDavid E. O'Brien }
298c80476e4SDavid E. O'Brien }
299c80476e4SDavid E. O'Brien
300c80476e4SDavid E. O'Brien /*
301c80476e4SDavid E. O'Brien * RefreshPromptpart()
302c80476e4SDavid E. O'Brien * draws a prompt element, expanding literals (we know it's ASCIZ)
303c80476e4SDavid E. O'Brien */
304c80476e4SDavid E. O'Brien static void
RefreshPromptpart(Char * buf)30545e5710bSMark Peek RefreshPromptpart(Char *buf)
306c80476e4SDavid E. O'Brien {
30723338178SMark Peek Char *cp;
30845e5710bSMark Peek int w;
309c80476e4SDavid E. O'Brien
31045e5710bSMark Peek if (buf == NULL)
31145e5710bSMark Peek return;
31223338178SMark Peek for (cp = buf; *cp; ) {
313c80476e4SDavid E. O'Brien if (*cp & LITERAL) {
31423338178SMark Peek Char *litstart = cp;
315c80476e4SDavid E. O'Brien while (*cp & LITERAL)
316c80476e4SDavid E. O'Brien cp++;
31723338178SMark Peek if (*cp) {
31845e5710bSMark Peek w = NLSWidth(*cp & CHAR);
31945e5710bSMark Peek Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w);
32045e5710bSMark Peek cp++;
32123338178SMark Peek }
322c80476e4SDavid E. O'Brien else {
323c80476e4SDavid E. O'Brien /*
324c80476e4SDavid E. O'Brien * XXX: This is a bug, we lose the last literal, if it is not
325c80476e4SDavid E. O'Brien * followed by a normal character, but it is too hard to fix
326c80476e4SDavid E. O'Brien */
327c80476e4SDavid E. O'Brien break;
328c80476e4SDavid E. O'Brien }
329c80476e4SDavid E. O'Brien }
330c80476e4SDavid E. O'Brien else
331*19d2e3deSDmitry Chagin cp += Draw(cp, cp == buf, 1);
332c80476e4SDavid E. O'Brien }
333c80476e4SDavid E. O'Brien }
334c80476e4SDavid E. O'Brien
335c80476e4SDavid E. O'Brien /*
336c80476e4SDavid E. O'Brien * Refresh()
337c80476e4SDavid E. O'Brien * draws the new virtual screen image from the current input
338c80476e4SDavid E. O'Brien * line, then goes line-by-line changing the real image to the new
339c80476e4SDavid E. O'Brien * virtual image. The routine to re-draw a line can be replaced
340c80476e4SDavid E. O'Brien * easily in hopes of a smarter one being placed there.
341c80476e4SDavid E. O'Brien */
342b2d5d167SMark Peek #ifndef WINNT_NATIVE
343b2d5d167SMark Peek static
344b2d5d167SMark Peek #endif
345b2d5d167SMark Peek int OldvcV = 0;
346b2d5d167SMark Peek
347c80476e4SDavid E. O'Brien void
Refresh(void)34845e5710bSMark Peek Refresh(void)
349c80476e4SDavid E. O'Brien {
35023338178SMark Peek int cur_line;
35123338178SMark Peek Char *cp;
352c80476e4SDavid E. O'Brien int cur_h, cur_v = 0, new_vcv;
353c80476e4SDavid E. O'Brien int rhdiff;
354c80476e4SDavid E. O'Brien Char oldgetting;
355c80476e4SDavid E. O'Brien
356c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
3579ccc37e3SMark Peek reprintf("Prompt = :%s:\r\n", short2str(Prompt));
3589ccc37e3SMark Peek reprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
359c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
360c80476e4SDavid E. O'Brien oldgetting = GettingInput;
361c80476e4SDavid E. O'Brien GettingInput = 0; /* avoid re-entrance via SIGWINCH */
362c80476e4SDavid E. O'Brien
363c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
364c80476e4SDavid E. O'Brien vcursor_h = 0;
365c80476e4SDavid E. O'Brien vcursor_v = 0;
36645e5710bSMark Peek RefreshPromptpart(RPrompt);
367c80476e4SDavid E. O'Brien rprompt_h = vcursor_h;
368c80476e4SDavid E. O'Brien rprompt_v = vcursor_v;
369c80476e4SDavid E. O'Brien
370c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, draw prompt */
371c80476e4SDavid E. O'Brien vcursor_h = 0;
372c80476e4SDavid E. O'Brien vcursor_v = 0;
37345e5710bSMark Peek RefreshPromptpart(Prompt);
374c80476e4SDavid E. O'Brien cur_h = -1; /* set flag in case I'm not set */
375c80476e4SDavid E. O'Brien
376c80476e4SDavid E. O'Brien /* draw the current input buffer */
37723338178SMark Peek for (cp = InputBuf; (cp < LastChar); ) {
37823338178SMark Peek if (cp >= Cursor && cur_h == -1) {
379c80476e4SDavid E. O'Brien cur_h = vcursor_h; /* save for later */
380c80476e4SDavid E. O'Brien cur_v = vcursor_v;
38123338178SMark Peek Cursor = cp;
382c80476e4SDavid E. O'Brien }
383*19d2e3deSDmitry Chagin cp += Draw(cp, cp == InputBuf, 0);
384c80476e4SDavid E. O'Brien }
385c80476e4SDavid E. O'Brien
386c80476e4SDavid E. O'Brien if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */
387c80476e4SDavid E. O'Brien cur_h = vcursor_h;
388c80476e4SDavid E. O'Brien cur_v = vcursor_v;
389c80476e4SDavid E. O'Brien }
390c80476e4SDavid E. O'Brien
391c80476e4SDavid E. O'Brien rhdiff = TermH - vcursor_h - rprompt_h;
392c80476e4SDavid E. O'Brien if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
393c80476e4SDavid E. O'Brien /*
394c80476e4SDavid E. O'Brien * have a right-hand side prompt that will fit on
395c80476e4SDavid E. O'Brien * the end of the first line with at least one
396c80476e4SDavid E. O'Brien * character gap to the input buffer.
397c80476e4SDavid E. O'Brien */
398c80476e4SDavid E. O'Brien while (--rhdiff > 0) /* pad out with spaces */
39923338178SMark Peek Vdraw(' ', 1);
40045e5710bSMark Peek RefreshPromptpart(RPrompt);
401c80476e4SDavid E. O'Brien }
402c80476e4SDavid E. O'Brien else {
403c80476e4SDavid E. O'Brien rprompt_h = 0; /* flag "not using rprompt" */
404c80476e4SDavid E. O'Brien rprompt_v = 0;
405c80476e4SDavid E. O'Brien }
406c80476e4SDavid E. O'Brien
407c80476e4SDavid E. O'Brien new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */
40823338178SMark Peek Vdraw('\0', 1); /* put NUL on end */
409c80476e4SDavid E. O'Brien
41023338178SMark Peek #if defined (DEBUG_REFRESH)
4119ccc37e3SMark Peek reprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
412c80476e4SDavid E. O'Brien TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
413c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
414c80476e4SDavid E. O'Brien
415c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
4169ccc37e3SMark Peek reprintf("updating %d lines.\r\n", new_vcv);
417c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
418c80476e4SDavid E. O'Brien for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
419c80476e4SDavid E. O'Brien /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
420c80476e4SDavid E. O'Brien update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
4213b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
422c80476e4SDavid E. O'Brien flush();
4233b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
424c80476e4SDavid E. O'Brien
425c80476e4SDavid E. O'Brien /*
426c80476e4SDavid E. O'Brien * Copy the new line to be the current one, and pad out with spaces
427c80476e4SDavid E. O'Brien * to the full width of the terminal so that if we try moving the
428c80476e4SDavid E. O'Brien * cursor by writing the character that is at the end of the
429c80476e4SDavid E. O'Brien * screen line, it won't be a NUL or some old leftover stuff.
430c80476e4SDavid E. O'Brien */
431c80476e4SDavid E. O'Brien cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
432c80476e4SDavid E. O'Brien }
433c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4349ccc37e3SMark Peek reprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
435c80476e4SDavid E. O'Brien vcursor_v, OldvcV, cur_line);
436c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
437c80476e4SDavid E. O'Brien if (OldvcV > new_vcv) {
438c80476e4SDavid E. O'Brien for (; cur_line <= OldvcV; cur_line++) {
439c80476e4SDavid E. O'Brien update_line(Display[cur_line], STRNULL, cur_line);
440c80476e4SDavid E. O'Brien *Display[cur_line] = '\0';
441c80476e4SDavid E. O'Brien }
442c80476e4SDavid E. O'Brien }
443c80476e4SDavid E. O'Brien OldvcV = new_vcv; /* set for next time */
444c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4459ccc37e3SMark Peek reprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
446c80476e4SDavid E. O'Brien CursorH, CursorV, cur_h, cur_v);
447c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
4483b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
449c80476e4SDavid E. O'Brien flush();
4503b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
451c80476e4SDavid E. O'Brien MoveToLine(cur_v); /* go to where the cursor is */
452c80476e4SDavid E. O'Brien MoveToChar(cur_h);
453c80476e4SDavid E. O'Brien SetAttributes(0); /* Clear all attributes */
454c80476e4SDavid E. O'Brien flush(); /* send the output... */
455c80476e4SDavid E. O'Brien GettingInput = oldgetting; /* reset to old value */
456c80476e4SDavid E. O'Brien }
457c80476e4SDavid E. O'Brien
458c80476e4SDavid E. O'Brien #ifdef notdef
GotoBottom(void)45945e5710bSMark Peek GotoBottom(void)
460c80476e4SDavid E. O'Brien { /* used to go to last used screen line */
461c80476e4SDavid E. O'Brien MoveToLine(OldvcV);
462c80476e4SDavid E. O'Brien }
463c80476e4SDavid E. O'Brien
464c80476e4SDavid E. O'Brien #endif
465c80476e4SDavid E. O'Brien
466c80476e4SDavid E. O'Brien void
PastBottom(void)46745e5710bSMark Peek PastBottom(void)
468c80476e4SDavid E. O'Brien { /* used to go to last used screen line */
469c80476e4SDavid E. O'Brien MoveToLine(OldvcV);
470c80476e4SDavid E. O'Brien (void) putraw('\r');
471c80476e4SDavid E. O'Brien (void) putraw('\n');
472c80476e4SDavid E. O'Brien ClearDisp();
473c80476e4SDavid E. O'Brien flush();
474c80476e4SDavid E. O'Brien }
475c80476e4SDavid E. O'Brien
476c80476e4SDavid E. O'Brien
477c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat,
478c80476e4SDavid E. O'Brien maximum length of d is dlen */
479c80476e4SDavid E. O'Brien static void
str_insert(Char * d,int dat,int dlen,Char * s,int num)48045e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num)
481c80476e4SDavid E. O'Brien {
48223338178SMark Peek Char *a, *b;
483c80476e4SDavid E. O'Brien
484c80476e4SDavid E. O'Brien if (num <= 0)
485c80476e4SDavid E. O'Brien return;
486c80476e4SDavid E. O'Brien if (num > dlen - dat)
487c80476e4SDavid E. O'Brien num = dlen - dat;
488c80476e4SDavid E. O'Brien
489c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
4909ccc37e3SMark Peek reprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
491c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d));
4929ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s));
493c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
494c80476e4SDavid E. O'Brien
495c80476e4SDavid E. O'Brien /* open up the space for num chars */
496c80476e4SDavid E. O'Brien if (num > 0) {
497c80476e4SDavid E. O'Brien b = d + dlen - 1;
498c80476e4SDavid E. O'Brien a = b - num;
499c80476e4SDavid E. O'Brien while (a >= &d[dat])
500c80476e4SDavid E. O'Brien *b-- = *a--;
501c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */
502c80476e4SDavid E. O'Brien }
503c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5049ccc37e3SMark Peek reprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
505c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d));
5069ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s));
507c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
508c80476e4SDavid E. O'Brien
509c80476e4SDavid E. O'Brien /* copy the characters */
510c80476e4SDavid E. O'Brien for (a = d + dat; (a < d + dlen) && (num > 0); num--)
511c80476e4SDavid E. O'Brien *a++ = *s++;
512c80476e4SDavid E. O'Brien
513c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5149ccc37e3SMark Peek reprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
515c80476e4SDavid E. O'Brien num, dat, dlen, d, short2str(s));
5169ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s));
517c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
518c80476e4SDavid E. O'Brien }
519c80476e4SDavid E. O'Brien
520c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */
521c80476e4SDavid E. O'Brien static void
str_delete(Char * d,int dat,int dlen,int num)52245e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num)
523c80476e4SDavid E. O'Brien {
52423338178SMark Peek Char *a, *b;
525c80476e4SDavid E. O'Brien
526c80476e4SDavid E. O'Brien if (num <= 0)
527c80476e4SDavid E. O'Brien return;
528c80476e4SDavid E. O'Brien if (dat + num >= dlen) {
529c80476e4SDavid E. O'Brien d[dat] = '\0';
530c80476e4SDavid E. O'Brien return;
531c80476e4SDavid E. O'Brien }
532c80476e4SDavid E. O'Brien
533c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5349ccc37e3SMark Peek reprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
535c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d));
536c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
537c80476e4SDavid E. O'Brien
538c80476e4SDavid E. O'Brien /* open up the space for num chars */
539c80476e4SDavid E. O'Brien if (num > 0) {
540c80476e4SDavid E. O'Brien b = d + dat;
541c80476e4SDavid E. O'Brien a = b + num;
542c80476e4SDavid E. O'Brien while (a < &d[dlen])
543c80476e4SDavid E. O'Brien *b++ = *a++;
544c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */
545c80476e4SDavid E. O'Brien }
546c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
5479ccc37e3SMark Peek reprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
548c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d));
549c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */
550c80476e4SDavid E. O'Brien }
551c80476e4SDavid E. O'Brien
552c80476e4SDavid E. O'Brien static void
str_cp(Char * a,Char * b,int n)55345e5710bSMark Peek str_cp(Char *a, Char *b, int n)
554c80476e4SDavid E. O'Brien {
555c80476e4SDavid E. O'Brien while (n-- && *b)
556c80476e4SDavid E. O'Brien *a++ = *b++;
557c80476e4SDavid E. O'Brien }
558c80476e4SDavid E. O'Brien
559c80476e4SDavid E. O'Brien
560c80476e4SDavid E. O'Brien /* ****************************************************************
561c80476e4SDavid E. O'Brien update_line() is based on finding the middle difference of each line
562c80476e4SDavid E. O'Brien on the screen; vis:
563c80476e4SDavid E. O'Brien
564c80476e4SDavid E. O'Brien /old first difference
565c80476e4SDavid E. O'Brien /beginning of line | /old last same /old EOL
566c80476e4SDavid E. O'Brien v v v v
567c80476e4SDavid E. O'Brien old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
568c80476e4SDavid E. O'Brien new: eddie> Oh, my little buggy says to me, as lurgid as
569c80476e4SDavid E. O'Brien ^ ^ ^ ^
570c80476e4SDavid E. O'Brien \beginning of line | \new last same \new end of line
571c80476e4SDavid E. O'Brien \new first difference
572c80476e4SDavid E. O'Brien
573c80476e4SDavid E. O'Brien all are character pointers for the sake of speed. Special cases for
574c80476e4SDavid E. O'Brien no differences, as well as for end of line additions must be handled.
575c80476e4SDavid E. O'Brien **************************************************************** */
576c80476e4SDavid E. O'Brien
577c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it". This should be about
578c80476e4SDavid E. O'Brien * half the "cost" of going into insert mode, inserting a character, and
579c80476e4SDavid E. O'Brien * going back out. This should really be calculated from the termcap
580c80476e4SDavid E. O'Brien * data... For the moment, a good number for ANSI terminals.
581c80476e4SDavid E. O'Brien */
582c80476e4SDavid E. O'Brien #define MIN_END_KEEP 4
583c80476e4SDavid E. O'Brien
584c80476e4SDavid E. O'Brien static void /* could be changed to make it smarter */
update_line(Char * old,Char * new,int cur_line)58545e5710bSMark Peek update_line(Char *old, Char *new, int cur_line)
586c80476e4SDavid E. O'Brien {
58723338178SMark Peek Char *o, *n, *p, c;
588c80476e4SDavid E. O'Brien Char *ofd, *ols, *oe, *nfd, *nls, *ne;
589c80476e4SDavid E. O'Brien Char *osb, *ose, *nsb, *nse;
590c80476e4SDavid E. O'Brien int fx, sx;
591c80476e4SDavid E. O'Brien
592c80476e4SDavid E. O'Brien /*
59323338178SMark Peek * find first diff (won't be CHAR_DBWIDTH in either line)
594c80476e4SDavid E. O'Brien */
595c80476e4SDavid E. O'Brien for (o = old, n = new; *o && (*o == *n); o++, n++)
596c80476e4SDavid E. O'Brien continue;
597c80476e4SDavid E. O'Brien ofd = o;
598c80476e4SDavid E. O'Brien nfd = n;
599c80476e4SDavid E. O'Brien
600c80476e4SDavid E. O'Brien /*
601c80476e4SDavid E. O'Brien * Find the end of both old and new
602c80476e4SDavid E. O'Brien */
60345e5710bSMark Peek o = Strend(o);
60445e5710bSMark Peek
605c80476e4SDavid E. O'Brien /*
606c80476e4SDavid E. O'Brien * Remove any trailing blanks off of the end, being careful not to
607c80476e4SDavid E. O'Brien * back up past the beginning.
608c80476e4SDavid E. O'Brien */
60945e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) {
610c80476e4SDavid E. O'Brien while (ofd < o) {
611c80476e4SDavid E. O'Brien if (o[-1] != ' ')
612c80476e4SDavid E. O'Brien break;
613c80476e4SDavid E. O'Brien o--;
614c80476e4SDavid E. O'Brien }
61545e5710bSMark Peek }
616c80476e4SDavid E. O'Brien oe = o;
617c80476e4SDavid E. O'Brien *oe = (Char) 0;
618c80476e4SDavid E. O'Brien
61945e5710bSMark Peek n = Strend(n);
620c80476e4SDavid E. O'Brien
621c80476e4SDavid E. O'Brien /* remove blanks from end of new */
62245e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) {
623c80476e4SDavid E. O'Brien while (nfd < n) {
624c80476e4SDavid E. O'Brien if (n[-1] != ' ')
625c80476e4SDavid E. O'Brien break;
626c80476e4SDavid E. O'Brien n--;
627c80476e4SDavid E. O'Brien }
62845e5710bSMark Peek }
629c80476e4SDavid E. O'Brien ne = n;
630c80476e4SDavid E. O'Brien *ne = (Char) 0;
631c80476e4SDavid E. O'Brien
632c80476e4SDavid E. O'Brien /*
633c80476e4SDavid E. O'Brien * if no diff, continue to next line of redraw
634c80476e4SDavid E. O'Brien */
635c80476e4SDavid E. O'Brien if (*ofd == '\0' && *nfd == '\0') {
636c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
6379ccc37e3SMark Peek reprintf("no difference.\r\n");
638c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
639c80476e4SDavid E. O'Brien return;
640c80476e4SDavid E. O'Brien }
641c80476e4SDavid E. O'Brien
642c80476e4SDavid E. O'Brien /*
643c80476e4SDavid E. O'Brien * find last same pointer
644c80476e4SDavid E. O'Brien */
645c80476e4SDavid E. O'Brien while ((o > ofd) && (n > nfd) && (*--o == *--n))
646c80476e4SDavid E. O'Brien continue;
64723338178SMark Peek if (*o != *n) {
64823338178SMark Peek o++;
64923338178SMark Peek n++;
65023338178SMark Peek }
65123338178SMark Peek while (*o == CHAR_DBWIDTH) {
65223338178SMark Peek o++;
65323338178SMark Peek n++;
65423338178SMark Peek }
65523338178SMark Peek ols = o;
65623338178SMark Peek nls = n;
657c80476e4SDavid E. O'Brien
658c80476e4SDavid E. O'Brien /*
659c80476e4SDavid E. O'Brien * find same begining and same end
660c80476e4SDavid E. O'Brien */
661c80476e4SDavid E. O'Brien osb = ols;
662c80476e4SDavid E. O'Brien nsb = nls;
663c80476e4SDavid E. O'Brien ose = ols;
664c80476e4SDavid E. O'Brien nse = nls;
665c80476e4SDavid E. O'Brien
666c80476e4SDavid E. O'Brien /*
667c80476e4SDavid E. O'Brien * case 1: insert: scan from nfd to nls looking for *ofd
668c80476e4SDavid E. O'Brien */
669c80476e4SDavid E. O'Brien if (*ofd) {
670c80476e4SDavid E. O'Brien for (c = *ofd, n = nfd; n < nls; n++) {
671c80476e4SDavid E. O'Brien if (c == *n) {
672c80476e4SDavid E. O'Brien for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
673c80476e4SDavid E. O'Brien continue;
674c80476e4SDavid E. O'Brien /*
675c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we
676c80476e4SDavid E. O'Brien * take it
677c80476e4SDavid E. O'Brien */
678c80476e4SDavid E. O'Brien if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
679c80476e4SDavid E. O'Brien nsb = n;
680c80476e4SDavid E. O'Brien nse = p;
681c80476e4SDavid E. O'Brien osb = ofd;
682c80476e4SDavid E. O'Brien ose = o;
683c80476e4SDavid E. O'Brien }
684c80476e4SDavid E. O'Brien }
685c80476e4SDavid E. O'Brien }
686c80476e4SDavid E. O'Brien }
687c80476e4SDavid E. O'Brien
688c80476e4SDavid E. O'Brien /*
689c80476e4SDavid E. O'Brien * case 2: delete: scan from ofd to ols looking for *nfd
690c80476e4SDavid E. O'Brien */
691c80476e4SDavid E. O'Brien if (*nfd) {
692c80476e4SDavid E. O'Brien for (c = *nfd, o = ofd; o < ols; o++) {
693c80476e4SDavid E. O'Brien if (c == *o) {
694c80476e4SDavid E. O'Brien for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
695c80476e4SDavid E. O'Brien continue;
696c80476e4SDavid E. O'Brien /*
697c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we
698c80476e4SDavid E. O'Brien * take it
699c80476e4SDavid E. O'Brien */
700c80476e4SDavid E. O'Brien if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
701c80476e4SDavid E. O'Brien nsb = nfd;
702c80476e4SDavid E. O'Brien nse = n;
703c80476e4SDavid E. O'Brien osb = o;
704c80476e4SDavid E. O'Brien ose = p;
705c80476e4SDavid E. O'Brien }
706c80476e4SDavid E. O'Brien }
707c80476e4SDavid E. O'Brien }
708c80476e4SDavid E. O'Brien }
709c80476e4SDavid E. O'Brien #ifdef notdef
710c80476e4SDavid E. O'Brien /*
711c80476e4SDavid E. O'Brien * If `last same' is before `same end' re-adjust
712c80476e4SDavid E. O'Brien */
713c80476e4SDavid E. O'Brien if (ols < ose)
714c80476e4SDavid E. O'Brien ols = ose;
715c80476e4SDavid E. O'Brien if (nls < nse)
716c80476e4SDavid E. O'Brien nls = nse;
717c80476e4SDavid E. O'Brien #endif
718c80476e4SDavid E. O'Brien
719c80476e4SDavid E. O'Brien /*
720c80476e4SDavid E. O'Brien * Pragmatics I: If old trailing whitespace or not enough characters to
721c80476e4SDavid E. O'Brien * save to be worth it, then don't save the last same info.
722c80476e4SDavid E. O'Brien */
723c80476e4SDavid E. O'Brien if ((oe - ols) < MIN_END_KEEP) {
724c80476e4SDavid E. O'Brien ols = oe;
725c80476e4SDavid E. O'Brien nls = ne;
726c80476e4SDavid E. O'Brien }
727c80476e4SDavid E. O'Brien
728c80476e4SDavid E. O'Brien /*
729c80476e4SDavid E. O'Brien * Pragmatics II: if the terminal isn't smart enough, make the data dumber
730c80476e4SDavid E. O'Brien * so the smart update doesn't try anything fancy
731c80476e4SDavid E. O'Brien */
732c80476e4SDavid E. O'Brien
733c80476e4SDavid E. O'Brien /*
734c80476e4SDavid E. O'Brien * fx is the number of characters we need to insert/delete: in the
735c80476e4SDavid E. O'Brien * beginning to bring the two same begins together
736c80476e4SDavid E. O'Brien */
737c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd));
738c80476e4SDavid E. O'Brien /*
739c80476e4SDavid E. O'Brien * sx is the number of characters we need to insert/delete: in the end to
740c80476e4SDavid E. O'Brien * bring the two same last parts together
741c80476e4SDavid E. O'Brien */
742c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose));
743c80476e4SDavid E. O'Brien
744c80476e4SDavid E. O'Brien if (!T_CanIns) {
745c80476e4SDavid E. O'Brien if (fx > 0) {
746c80476e4SDavid E. O'Brien osb = ols;
747c80476e4SDavid E. O'Brien ose = ols;
748c80476e4SDavid E. O'Brien nsb = nls;
749c80476e4SDavid E. O'Brien nse = nls;
750c80476e4SDavid E. O'Brien }
751c80476e4SDavid E. O'Brien if (sx > 0) {
752c80476e4SDavid E. O'Brien ols = oe;
753c80476e4SDavid E. O'Brien nls = ne;
754c80476e4SDavid E. O'Brien }
755c80476e4SDavid E. O'Brien if ((ols - ofd) < (nls - nfd)) {
756c80476e4SDavid E. O'Brien ols = oe;
757c80476e4SDavid E. O'Brien nls = ne;
758c80476e4SDavid E. O'Brien }
759c80476e4SDavid E. O'Brien }
760c80476e4SDavid E. O'Brien if (!T_CanDel) {
761c80476e4SDavid E. O'Brien if (fx < 0) {
762c80476e4SDavid E. O'Brien osb = ols;
763c80476e4SDavid E. O'Brien ose = ols;
764c80476e4SDavid E. O'Brien nsb = nls;
765c80476e4SDavid E. O'Brien nse = nls;
766c80476e4SDavid E. O'Brien }
767c80476e4SDavid E. O'Brien if (sx < 0) {
768c80476e4SDavid E. O'Brien ols = oe;
769c80476e4SDavid E. O'Brien nls = ne;
770c80476e4SDavid E. O'Brien }
771c80476e4SDavid E. O'Brien if ((ols - ofd) > (nls - nfd)) {
772c80476e4SDavid E. O'Brien ols = oe;
773c80476e4SDavid E. O'Brien nls = ne;
774c80476e4SDavid E. O'Brien }
775c80476e4SDavid E. O'Brien }
776c80476e4SDavid E. O'Brien
777c80476e4SDavid E. O'Brien /*
778c80476e4SDavid E. O'Brien * Pragmatics III: make sure the middle shifted pointers are correct if
779c80476e4SDavid E. O'Brien * they don't point to anything (we may have moved ols or nls).
780c80476e4SDavid E. O'Brien */
781c80476e4SDavid E. O'Brien /* if the change isn't worth it, don't bother */
782c80476e4SDavid E. O'Brien /* was: if (osb == ose) */
783c80476e4SDavid E. O'Brien if ((ose - osb) < MIN_END_KEEP) {
784c80476e4SDavid E. O'Brien osb = ols;
785c80476e4SDavid E. O'Brien ose = ols;
786c80476e4SDavid E. O'Brien nsb = nls;
787c80476e4SDavid E. O'Brien nse = nls;
788c80476e4SDavid E. O'Brien }
789c80476e4SDavid E. O'Brien
790c80476e4SDavid E. O'Brien /*
791c80476e4SDavid E. O'Brien * Now that we are done with pragmatics we recompute fx, sx
792c80476e4SDavid E. O'Brien */
793c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd));
794c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose));
795c80476e4SDavid E. O'Brien
796c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
7979ccc37e3SMark Peek reprintf("\n");
7989ccc37e3SMark Peek reprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
799c80476e4SDavid E. O'Brien ofd - old, osb - old, ose - old, ols - old, oe - old);
8009ccc37e3SMark Peek reprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
801c80476e4SDavid E. O'Brien nfd - new, nsb - new, nse - new, nls - new, ne - new);
8029ccc37e3SMark Peek reprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
8039ccc37e3SMark Peek reprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
804c80476e4SDavid E. O'Brien dprintstr("old- oe", old, oe);
805c80476e4SDavid E. O'Brien dprintstr("new- ne", new, ne);
806c80476e4SDavid E. O'Brien dprintstr("old-ofd", old, ofd);
807c80476e4SDavid E. O'Brien dprintstr("new-nfd", new, nfd);
808c80476e4SDavid E. O'Brien dprintstr("ofd-osb", ofd, osb);
809c80476e4SDavid E. O'Brien dprintstr("nfd-nsb", nfd, nsb);
810c80476e4SDavid E. O'Brien dprintstr("osb-ose", osb, ose);
811c80476e4SDavid E. O'Brien dprintstr("nsb-nse", nsb, nse);
812c80476e4SDavid E. O'Brien dprintstr("ose-ols", ose, ols);
813c80476e4SDavid E. O'Brien dprintstr("nse-nls", nse, nls);
814c80476e4SDavid E. O'Brien dprintstr("ols- oe", ols, oe);
815c80476e4SDavid E. O'Brien dprintstr("nls- ne", nls, ne);
816c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
817c80476e4SDavid E. O'Brien
818c80476e4SDavid E. O'Brien /*
819c80476e4SDavid E. O'Brien * CursorV to this line cur_line MUST be in this routine so that if we
820c80476e4SDavid E. O'Brien * don't have to change the line, we don't move to it. CursorH to first
821c80476e4SDavid E. O'Brien * diff char
822c80476e4SDavid E. O'Brien */
823c80476e4SDavid E. O'Brien MoveToLine(cur_line);
824c80476e4SDavid E. O'Brien
825c80476e4SDavid E. O'Brien /*
826c80476e4SDavid E. O'Brien * at this point we have something like this:
827c80476e4SDavid E. O'Brien *
828c80476e4SDavid E. O'Brien * /old /ofd /osb /ose /ols /oe
829c80476e4SDavid E. O'Brien * v.....................v v..................v v........v
830c80476e4SDavid E. O'Brien * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
831c80476e4SDavid E. O'Brien * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
832c80476e4SDavid E. O'Brien * ^.....................^ ^..................^ ^........^
833c80476e4SDavid E. O'Brien * \new \nfd \nsb \nse \nls \ne
834c80476e4SDavid E. O'Brien *
835c80476e4SDavid E. O'Brien * fx is the difference in length between the the chars between nfd and
836c80476e4SDavid E. O'Brien * nsb, and the chars between ofd and osb, and is thus the number of
837c80476e4SDavid E. O'Brien * characters to delete if < 0 (new is shorter than old, as above),
838c80476e4SDavid E. O'Brien * or insert (new is longer than short).
839c80476e4SDavid E. O'Brien *
840c80476e4SDavid E. O'Brien * sx is the same for the second differences.
841c80476e4SDavid E. O'Brien */
842c80476e4SDavid E. O'Brien
843c80476e4SDavid E. O'Brien /*
844c80476e4SDavid E. O'Brien * if we have a net insert on the first difference, AND inserting the net
845c80476e4SDavid E. O'Brien * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
846c80476e4SDavid E. O'Brien * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
847c80476e4SDavid E. O'Brien * (TermH - 1) else we do the deletes first so that we keep everything we
848c80476e4SDavid E. O'Brien * need to.
849c80476e4SDavid E. O'Brien */
850c80476e4SDavid E. O'Brien
851c80476e4SDavid E. O'Brien /*
852c80476e4SDavid E. O'Brien * if the last same is the same like the end, there is no last same part,
853c80476e4SDavid E. O'Brien * otherwise we want to keep the last same part set p to the last useful
854c80476e4SDavid E. O'Brien * old character
855c80476e4SDavid E. O'Brien */
856c80476e4SDavid E. O'Brien p = (ols != oe) ? oe : ose;
857c80476e4SDavid E. O'Brien
858c80476e4SDavid E. O'Brien /*
859c80476e4SDavid E. O'Brien * if (There is a diffence in the beginning) && (we need to insert
860c80476e4SDavid E. O'Brien * characters) && (the number of characters to insert is less than the term
861c80476e4SDavid E. O'Brien * width) We need to do an insert! else if (we need to delete characters)
862c80476e4SDavid E. O'Brien * We need to delete characters! else No insert or delete
863c80476e4SDavid E. O'Brien */
864c80476e4SDavid E. O'Brien if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
865c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8669ccc37e3SMark Peek reprintf("first diff insert at %d...\r\n", nfd - new);
867c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
868c80476e4SDavid E. O'Brien /*
869c80476e4SDavid E. O'Brien * Move to the first char to insert, where the first diff is.
870c80476e4SDavid E. O'Brien */
871c80476e4SDavid E. O'Brien MoveToChar(nfd - new);
872c80476e4SDavid E. O'Brien /*
873c80476e4SDavid E. O'Brien * Check if we have stuff to keep at end
874c80476e4SDavid E. O'Brien */
875c80476e4SDavid E. O'Brien if (nsb != ne) {
876c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8779ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n");
878c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
879c80476e4SDavid E. O'Brien /*
880c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd
881c80476e4SDavid E. O'Brien */
882c80476e4SDavid E. O'Brien if (fx > 0) {
883c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
884c80476e4SDavid E. O'Brien if (!T_CanIns)
8859ccc37e3SMark Peek reprintf(" ERROR: cannot insert in early first diff\n");
886c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
887c80476e4SDavid E. O'Brien Insert_write(nfd, fx);
888c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx);
889c80476e4SDavid E. O'Brien }
890c80476e4SDavid E. O'Brien /*
891c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
892c80476e4SDavid E. O'Brien */
893c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx);
894c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
895c80476e4SDavid E. O'Brien }
896c80476e4SDavid E. O'Brien else {
897c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
8989ccc37e3SMark Peek reprintf("without anything to save\r\n");
899c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
900c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd));
901c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd));
902c80476e4SDavid E. O'Brien /*
903c80476e4SDavid E. O'Brien * Done
904c80476e4SDavid E. O'Brien */
905c80476e4SDavid E. O'Brien return;
906c80476e4SDavid E. O'Brien }
907c80476e4SDavid E. O'Brien }
908c80476e4SDavid E. O'Brien else if (fx < 0) {
909c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9109ccc37e3SMark Peek reprintf("first diff delete at %d...\r\n", ofd - old);
911c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
912c80476e4SDavid E. O'Brien /*
913c80476e4SDavid E. O'Brien * move to the first char to delete where the first diff is
914c80476e4SDavid E. O'Brien */
915c80476e4SDavid E. O'Brien MoveToChar(ofd - old);
916c80476e4SDavid E. O'Brien /*
917c80476e4SDavid E. O'Brien * Check if we have stuff to save
918c80476e4SDavid E. O'Brien */
919c80476e4SDavid E. O'Brien if (osb != oe) {
920c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9219ccc37e3SMark Peek reprintf("with stuff to save at end\r\n");
922c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
923c80476e4SDavid E. O'Brien /*
924c80476e4SDavid E. O'Brien * fx is less than zero *always* here but we check for code
925c80476e4SDavid E. O'Brien * symmetry
926c80476e4SDavid E. O'Brien */
927c80476e4SDavid E. O'Brien if (fx < 0) {
928c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
929c80476e4SDavid E. O'Brien if (!T_CanDel)
9309ccc37e3SMark Peek reprintf(" ERROR: cannot delete in first diff\n");
931c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
932c80476e4SDavid E. O'Brien DeleteChars(-fx);
933c80476e4SDavid E. O'Brien str_delete(old, (int) (ofd - old), TermH, -fx);
934c80476e4SDavid E. O'Brien }
935c80476e4SDavid E. O'Brien /*
936c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd
937c80476e4SDavid E. O'Brien */
938c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd));
939c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd));
940c80476e4SDavid E. O'Brien
941c80476e4SDavid E. O'Brien }
942c80476e4SDavid E. O'Brien else {
943c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9449ccc37e3SMark Peek reprintf("but with nothing left to save\r\n");
945c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
946c80476e4SDavid E. O'Brien /*
947c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd
948c80476e4SDavid E. O'Brien */
949c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd));
950c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
9519ccc37e3SMark Peek reprintf("cleareol %d\n", (oe - old) - (ne - new));
952c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
9533b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
954c80476e4SDavid E. O'Brien ClearEOL((oe - old) - (ne - new));
955c80476e4SDavid E. O'Brien #else
956c80476e4SDavid E. O'Brien /*
957c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT
958c80476e4SDavid E. O'Brien */
959c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH);
9603b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
961c80476e4SDavid E. O'Brien /*
962c80476e4SDavid E. O'Brien * Done
963c80476e4SDavid E. O'Brien */
964c80476e4SDavid E. O'Brien return;
965c80476e4SDavid E. O'Brien }
966c80476e4SDavid E. O'Brien }
967c80476e4SDavid E. O'Brien else
968c80476e4SDavid E. O'Brien fx = 0;
969c80476e4SDavid E. O'Brien
970c80476e4SDavid E. O'Brien if (sx < 0) {
971c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9729ccc37e3SMark Peek reprintf("second diff delete at %d...\r\n", (ose - old) + fx);
973c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
974c80476e4SDavid E. O'Brien /*
975c80476e4SDavid E. O'Brien * Check if we have stuff to delete
976c80476e4SDavid E. O'Brien */
977c80476e4SDavid E. O'Brien /*
978c80476e4SDavid E. O'Brien * fx is the number of characters inserted (+) or deleted (-)
979c80476e4SDavid E. O'Brien */
980c80476e4SDavid E. O'Brien
981c80476e4SDavid E. O'Brien MoveToChar((ose - old) + fx);
982c80476e4SDavid E. O'Brien /*
983c80476e4SDavid E. O'Brien * Check if we have stuff to save
984c80476e4SDavid E. O'Brien */
985c80476e4SDavid E. O'Brien if (ols != oe) {
986c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
9879ccc37e3SMark Peek reprintf("with stuff to save at end\r\n");
988c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
989c80476e4SDavid E. O'Brien /*
990c80476e4SDavid E. O'Brien * Again a duplicate test.
991c80476e4SDavid E. O'Brien */
992c80476e4SDavid E. O'Brien if (sx < 0) {
993c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
994c80476e4SDavid E. O'Brien if (!T_CanDel)
9959ccc37e3SMark Peek reprintf(" ERROR: cannot delete in second diff\n");
996c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
997c80476e4SDavid E. O'Brien DeleteChars(-sx);
998c80476e4SDavid E. O'Brien }
999c80476e4SDavid E. O'Brien
1000c80476e4SDavid E. O'Brien /*
1001c80476e4SDavid E. O'Brien * write (nls-nse) chars of new starting at nse
1002c80476e4SDavid E. O'Brien */
1003c80476e4SDavid E. O'Brien so_write(nse, (nls - nse));
1004c80476e4SDavid E. O'Brien }
1005c80476e4SDavid E. O'Brien else {
1006c80476e4SDavid E. O'Brien int olen = (int) (oe - old + fx);
1007c80476e4SDavid E. O'Brien if (olen > TermH)
1008c80476e4SDavid E. O'Brien olen = TermH;
1009c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10109ccc37e3SMark Peek reprintf("but with nothing left to save\r\n");
1011c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1012c80476e4SDavid E. O'Brien so_write(nse, (nls - nse));
1013c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH
10149ccc37e3SMark Peek reprintf("cleareol %d\n", olen - (ne - new));
1015c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
10163b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE
1017c80476e4SDavid E. O'Brien ClearEOL(olen - (ne - new));
1018c80476e4SDavid E. O'Brien #else
1019c80476e4SDavid E. O'Brien /*
1020c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT
1021c80476e4SDavid E. O'Brien */
1022c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH);
10233b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/
1024c80476e4SDavid E. O'Brien }
1025c80476e4SDavid E. O'Brien }
1026c80476e4SDavid E. O'Brien
1027c80476e4SDavid E. O'Brien /*
1028c80476e4SDavid E. O'Brien * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
1029c80476e4SDavid E. O'Brien */
1030c80476e4SDavid E. O'Brien if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
1031c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10329ccc37e3SMark Peek reprintf("late first diff insert at %d...\r\n", nfd - new);
1033c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1034c80476e4SDavid E. O'Brien
1035c80476e4SDavid E. O'Brien MoveToChar(nfd - new);
1036c80476e4SDavid E. O'Brien /*
1037c80476e4SDavid E. O'Brien * Check if we have stuff to keep at the end
1038c80476e4SDavid E. O'Brien */
1039c80476e4SDavid E. O'Brien if (nsb != ne) {
1040c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10419ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n");
1042c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1043c80476e4SDavid E. O'Brien /*
1044c80476e4SDavid E. O'Brien * We have to recalculate fx here because we set it
1045c80476e4SDavid E. O'Brien * to zero above as a flag saying that we hadn't done
1046c80476e4SDavid E. O'Brien * an early first insert.
1047c80476e4SDavid E. O'Brien */
1048c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd));
1049c80476e4SDavid E. O'Brien if (fx > 0) {
1050c80476e4SDavid E. O'Brien /*
1051c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd
1052c80476e4SDavid E. O'Brien */
1053c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1054c80476e4SDavid E. O'Brien if (!T_CanIns)
10559ccc37e3SMark Peek reprintf(" ERROR: cannot insert in late first diff\n");
1056c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1057c80476e4SDavid E. O'Brien Insert_write(nfd, fx);
1058c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx);
1059c80476e4SDavid E. O'Brien }
1060c80476e4SDavid E. O'Brien
1061c80476e4SDavid E. O'Brien /*
1062c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
1063c80476e4SDavid E. O'Brien */
1064c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx);
1065c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
1066c80476e4SDavid E. O'Brien }
1067c80476e4SDavid E. O'Brien else {
1068c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10699ccc37e3SMark Peek reprintf("without anything to save\r\n");
1070c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1071c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd));
1072c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd));
1073c80476e4SDavid E. O'Brien }
1074c80476e4SDavid E. O'Brien }
1075c80476e4SDavid E. O'Brien
1076c80476e4SDavid E. O'Brien /*
1077c80476e4SDavid E. O'Brien * line is now NEW up to nse
1078c80476e4SDavid E. O'Brien */
1079c80476e4SDavid E. O'Brien if (sx >= 0) {
1080c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10819ccc37e3SMark Peek reprintf("second diff insert at %d...\r\n", nse - new);
1082c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1083c80476e4SDavid E. O'Brien MoveToChar(nse - new);
1084c80476e4SDavid E. O'Brien if (ols != oe) {
1085c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
10869ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n");
1087c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1088c80476e4SDavid E. O'Brien if (sx > 0) {
1089c80476e4SDavid E. O'Brien /* insert sx chars of new starting at nse */
1090c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
1091c80476e4SDavid E. O'Brien if (!T_CanIns)
10929ccc37e3SMark Peek reprintf(" ERROR: cannot insert in second diff\n");
1093c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1094c80476e4SDavid E. O'Brien Insert_write(nse, sx);
1095c80476e4SDavid E. O'Brien }
1096c80476e4SDavid E. O'Brien
1097c80476e4SDavid E. O'Brien /*
1098c80476e4SDavid E. O'Brien * write (nls-nse) - sx chars of new starting at (nse + sx)
1099c80476e4SDavid E. O'Brien */
1100c80476e4SDavid E. O'Brien so_write(nse + sx, (nls - nse) - sx);
1101c80476e4SDavid E. O'Brien }
1102c80476e4SDavid E. O'Brien else {
1103c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11049ccc37e3SMark Peek reprintf("without anything to save\r\n");
1105c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1106c80476e4SDavid E. O'Brien so_write(nse, (nls - nse));
1107c80476e4SDavid E. O'Brien
1108c80476e4SDavid E. O'Brien /*
1109c80476e4SDavid E. O'Brien * No need to do a clear-to-end here because we were doing
1110c80476e4SDavid E. O'Brien * a second insert, so we will have over written all of the
1111c80476e4SDavid E. O'Brien * old string.
1112c80476e4SDavid E. O'Brien */
1113c80476e4SDavid E. O'Brien }
1114c80476e4SDavid E. O'Brien }
1115c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE
11169ccc37e3SMark Peek reprintf("done.\r\n");
1117c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */
1118c80476e4SDavid E. O'Brien }
1119c80476e4SDavid E. O'Brien
1120c80476e4SDavid E. O'Brien
1121c80476e4SDavid E. O'Brien static void
cpy_pad_spaces(Char * dst,Char * src,int width)112245e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width)
1123c80476e4SDavid E. O'Brien {
112423338178SMark Peek int i;
1125c80476e4SDavid E. O'Brien
1126c80476e4SDavid E. O'Brien for (i = 0; i < width; i++) {
1127c80476e4SDavid E. O'Brien if (*src == (Char) 0)
1128c80476e4SDavid E. O'Brien break;
1129c80476e4SDavid E. O'Brien *dst++ = *src++;
1130c80476e4SDavid E. O'Brien }
1131c80476e4SDavid E. O'Brien
1132c80476e4SDavid E. O'Brien while (i < width) {
1133c80476e4SDavid E. O'Brien *dst++ = ' ';
1134c80476e4SDavid E. O'Brien i++;
1135c80476e4SDavid E. O'Brien }
1136c80476e4SDavid E. O'Brien *dst = (Char) 0;
1137c80476e4SDavid E. O'Brien }
1138c80476e4SDavid E. O'Brien
1139c80476e4SDavid E. O'Brien void
RefCursor(void)114045e5710bSMark Peek RefCursor(void)
1141c80476e4SDavid E. O'Brien { /* only move to new cursor pos */
114223338178SMark Peek Char *cp;
114345e5710bSMark Peek int w, h, th, v;
1144c80476e4SDavid E. O'Brien
1145c80476e4SDavid E. O'Brien /* first we must find where the cursor is... */
1146c80476e4SDavid E. O'Brien h = 0;
1147c80476e4SDavid E. O'Brien v = 0;
1148c80476e4SDavid E. O'Brien th = TermH; /* optimize for speed */
1149c80476e4SDavid E. O'Brien
115045e5710bSMark Peek for (cp = Prompt; cp != NULL && *cp; ) { /* do prompt */
115123338178SMark Peek if (*cp & LITERAL) {
115223338178SMark Peek cp++;
1153c80476e4SDavid E. O'Brien continue;
115423338178SMark Peek }
1155*19d2e3deSDmitry Chagin w = NLSClassify(*cp & CHAR, cp == Prompt, 0);
115645e5710bSMark Peek cp++;
115723338178SMark Peek switch(w) {
115823338178SMark Peek case NLSCLASS_NL:
1159c80476e4SDavid E. O'Brien h = 0;
1160c80476e4SDavid E. O'Brien v++;
116123338178SMark Peek break;
116223338178SMark Peek case NLSCLASS_TAB:
116323338178SMark Peek while (++h & 07)
116423338178SMark Peek ;
116523338178SMark Peek break;
116623338178SMark Peek case NLSCLASS_CTRL:
116723338178SMark Peek h += 2;
116823338178SMark Peek break;
116923338178SMark Peek case NLSCLASS_ILLEGAL:
117023338178SMark Peek h += 4;
117123338178SMark Peek break;
117223338178SMark Peek case NLSCLASS_ILLEGAL2:
117323338178SMark Peek case NLSCLASS_ILLEGAL3:
117423338178SMark Peek case NLSCLASS_ILLEGAL4:
117523338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
117623338178SMark Peek break;
117723338178SMark Peek default:
117823338178SMark Peek h += w;
1179c80476e4SDavid E. O'Brien }
1180c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */
118123338178SMark Peek h -= th;
118223338178SMark Peek v++;
118323338178SMark Peek }
118423338178SMark Peek }
118523338178SMark Peek
118623338178SMark Peek for (cp = InputBuf; cp < Cursor;) { /* do input buffer to Cursor */
1187*19d2e3deSDmitry Chagin w = NLSClassify(*cp & CHAR, cp == InputBuf, 0);
118845e5710bSMark Peek cp++;
118923338178SMark Peek switch(w) {
119023338178SMark Peek case NLSCLASS_NL:
1191c80476e4SDavid E. O'Brien h = 0;
1192c80476e4SDavid E. O'Brien v++;
119323338178SMark Peek break;
119423338178SMark Peek case NLSCLASS_TAB:
119523338178SMark Peek while (++h & 07)
119623338178SMark Peek ;
119723338178SMark Peek break;
119823338178SMark Peek case NLSCLASS_CTRL:
119923338178SMark Peek h += 2;
120023338178SMark Peek break;
120123338178SMark Peek case NLSCLASS_ILLEGAL:
120223338178SMark Peek h += 4;
120323338178SMark Peek break;
120423338178SMark Peek case NLSCLASS_ILLEGAL2:
120523338178SMark Peek case NLSCLASS_ILLEGAL3:
120623338178SMark Peek case NLSCLASS_ILLEGAL4:
120723338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
120823338178SMark Peek break;
120923338178SMark Peek default:
121023338178SMark Peek h += w;
1211c80476e4SDavid E. O'Brien }
1212c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */
121323338178SMark Peek h -= th;
1214c80476e4SDavid E. O'Brien v++;
1215c80476e4SDavid E. O'Brien }
1216c80476e4SDavid E. O'Brien }
1217c80476e4SDavid E. O'Brien
1218c80476e4SDavid E. O'Brien /* now go there */
1219c80476e4SDavid E. O'Brien MoveToLine(v);
1220c80476e4SDavid E. O'Brien MoveToChar(h);
122145e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) {
122245e5710bSMark Peek ClearLines();
122345e5710bSMark Peek ClearDisp();
122445e5710bSMark Peek Refresh();
122545e5710bSMark Peek }
1226c80476e4SDavid E. O'Brien flush();
1227c80476e4SDavid E. O'Brien }
1228c80476e4SDavid E. O'Brien
1229b2d5d167SMark Peek #ifndef WINTT_NATIVE
1230c80476e4SDavid E. O'Brien static void
PutPlusOne(Char c,int width)123145e5710bSMark Peek PutPlusOne(Char c, int width)
1232c80476e4SDavid E. O'Brien {
123323338178SMark Peek while (width > 1 && CursorH + width > TermH)
123423338178SMark Peek PutPlusOne(' ', 1);
123523338178SMark Peek if ((c & LITERAL) != 0) {
123623338178SMark Peek Char *d;
123723338178SMark Peek for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
123823338178SMark Peek (void) putwraw(*d);
123923338178SMark Peek } else {
124023338178SMark Peek (void) putwraw(c);
124123338178SMark Peek }
1242c80476e4SDavid E. O'Brien Display[CursorV][CursorH++] = (Char) c;
124323338178SMark Peek while (--width > 0)
124423338178SMark Peek Display[CursorV][CursorH++] = CHAR_DBWIDTH;
1245c80476e4SDavid E. O'Brien if (CursorH >= TermH) { /* if we must overflow */
1246c80476e4SDavid E. O'Brien CursorH = 0;
1247c80476e4SDavid E. O'Brien CursorV++;
1248c80476e4SDavid E. O'Brien OldvcV++;
1249c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_AUTO) {
1250c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_MAGIC) {
1251c80476e4SDavid E. O'Brien (void) putraw(' ');
1252c80476e4SDavid E. O'Brien (void) putraw('\b');
1253c80476e4SDavid E. O'Brien }
1254c80476e4SDavid E. O'Brien }
1255c80476e4SDavid E. O'Brien else {
1256c80476e4SDavid E. O'Brien (void) putraw('\r');
1257c80476e4SDavid E. O'Brien (void) putraw('\n');
1258c80476e4SDavid E. O'Brien }
1259c80476e4SDavid E. O'Brien }
1260c80476e4SDavid E. O'Brien }
1261b2d5d167SMark Peek #endif
1262c80476e4SDavid E. O'Brien
1263c80476e4SDavid E. O'Brien void
RefPlusOne(int l)126423338178SMark Peek RefPlusOne(int l)
1265c80476e4SDavid E. O'Brien { /* we added just one char, handle it fast.
1266c80476e4SDavid E. O'Brien * assumes that screen cursor == real cursor */
126745e5710bSMark Peek Char *cp, c;
126823338178SMark Peek int w;
1269c80476e4SDavid E. O'Brien
127023338178SMark Peek if (Cursor != LastChar) {
1271c80476e4SDavid E. O'Brien Refresh(); /* too hard to handle */
1272c80476e4SDavid E. O'Brien return;
1273c80476e4SDavid E. O'Brien }
1274c80476e4SDavid E. O'Brien if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
1275c80476e4SDavid E. O'Brien Refresh(); /* clear out rprompt if less than one char gap*/
1276c80476e4SDavid E. O'Brien return;
127723338178SMark Peek }
127823338178SMark Peek cp = Cursor - l;
127945e5710bSMark Peek c = *cp & CHAR;
1280*19d2e3deSDmitry Chagin w = NLSClassify(c, cp == InputBuf, 0);
128123338178SMark Peek switch(w) {
128223338178SMark Peek case NLSCLASS_CTRL:
128323338178SMark Peek PutPlusOne('^', 1);
128423338178SMark Peek if (c == CTL_ESC('\177')) {
128523338178SMark Peek PutPlusOne('?', 1);
128623338178SMark Peek break;
128723338178SMark Peek }
12883b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
128923338178SMark Peek /* uncontrolify it; works only for iso8859-1 like sets */
129023338178SMark Peek PutPlusOne((c | 0100), 1);
12913b6eaa7bSAndrey A. Chernov #else
129223338178SMark Peek PutPlusOne(_toebcdic[_toascii[c]|0100], 1);
129323338178SMark Peek #endif
129423338178SMark Peek break;
129523338178SMark Peek case NLSCLASS_ILLEGAL:
129623338178SMark Peek PutPlusOne('\\', 1);
129723338178SMark Peek PutPlusOne(((c >> 6) & 7) + '0', 1);
129823338178SMark Peek PutPlusOne(((c >> 3) & 7) + '0', 1);
129923338178SMark Peek PutPlusOne((c & 7) + '0', 1);
130023338178SMark Peek break;
130123338178SMark Peek case 1:
130245e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet)
130345e5710bSMark Peek StartHighlight();
130423338178SMark Peek if (l > 1)
130523338178SMark Peek PutPlusOne(MakeLiteral(cp, l, 0), 1);
1306c80476e4SDavid E. O'Brien else
130723338178SMark Peek PutPlusOne(*cp, 1);
130845e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet)
130945e5710bSMark Peek StopHighlight();
131023338178SMark Peek break;
131123338178SMark Peek default:
131223338178SMark Peek Refresh(); /* too hard to handle */
131323338178SMark Peek return;
1314c80476e4SDavid E. O'Brien }
1315c80476e4SDavid E. O'Brien flush();
1316c80476e4SDavid E. O'Brien }
1317c80476e4SDavid E. O'Brien
1318c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */
1319c80476e4SDavid E. O'Brien
1320c80476e4SDavid E. O'Brien void
ClearDisp(void)132145e5710bSMark Peek ClearDisp(void)
1322c80476e4SDavid E. O'Brien {
132323338178SMark Peek int i;
1324c80476e4SDavid E. O'Brien
1325c80476e4SDavid E. O'Brien CursorV = 0; /* clear the display buffer */
1326c80476e4SDavid E. O'Brien CursorH = 0;
1327c80476e4SDavid E. O'Brien for (i = 0; i < TermV; i++)
1328*19d2e3deSDmitry Chagin (void) memset(Display[i], 0, (TermH + 1) * sizeof(Display[0][0]));
1329c80476e4SDavid E. O'Brien OldvcV = 0;
133023338178SMark Peek litlen = 0;
1331c80476e4SDavid E. O'Brien }
1332c80476e4SDavid E. O'Brien
1333c80476e4SDavid E. O'Brien void
ClearLines(void)133445e5710bSMark Peek ClearLines(void)
1335c80476e4SDavid E. O'Brien { /* Make sure all lines are *really* blank */
133623338178SMark Peek int i;
1337c80476e4SDavid E. O'Brien
1338c80476e4SDavid E. O'Brien if (T_CanCEOL) {
1339c80476e4SDavid E. O'Brien /*
1340c80476e4SDavid E. O'Brien * Clear the lines from the bottom up so that if we try moving
1341c80476e4SDavid E. O'Brien * the cursor down by writing the character that is at the end
1342c80476e4SDavid E. O'Brien * of the screen line, we won't rewrite a character that shouldn't
1343c80476e4SDavid E. O'Brien * be there.
1344c80476e4SDavid E. O'Brien */
1345c80476e4SDavid E. O'Brien for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */
1346c80476e4SDavid E. O'Brien MoveToLine(i);
1347c80476e4SDavid E. O'Brien MoveToChar(0);
1348c80476e4SDavid E. O'Brien ClearEOL(TermH);
1349c80476e4SDavid E. O'Brien }
1350c80476e4SDavid E. O'Brien }
1351c80476e4SDavid E. O'Brien else {
1352c80476e4SDavid E. O'Brien MoveToLine(OldvcV); /* go to last line */
1353c80476e4SDavid E. O'Brien (void) putraw('\r'); /* go to BOL */
1354c80476e4SDavid E. O'Brien (void) putraw('\n'); /* go to new line */
1355c80476e4SDavid E. O'Brien }
1356c80476e4SDavid E. O'Brien }
1357