1*19d2e3deSDmitry Chagin /* $Header: /p/tcsh/cvsroot/tcsh/ed.refresh.c,v 3.51 2015/06/06 21:19:07 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * ed.refresh.c: Lower level screen refreshing functions 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1729301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 18c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 19c80476e4SDavid E. O'Brien * without specific prior written permission. 20c80476e4SDavid E. O'Brien * 21c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c80476e4SDavid E. O'Brien * SUCH DAMAGE. 32c80476e4SDavid E. O'Brien */ 33c80476e4SDavid E. O'Brien #include "sh.h" 34c80476e4SDavid E. O'Brien 35*19d2e3deSDmitry Chagin RCSID("$tcsh: ed.refresh.c,v 3.51 2015/06/06 21:19:07 christos Exp $") 36c80476e4SDavid E. O'Brien 37c80476e4SDavid E. O'Brien #include "ed.h" 38c80476e4SDavid E. O'Brien /* #define DEBUG_UPDATE */ 39c80476e4SDavid E. O'Brien /* #define DEBUG_REFRESH */ 40c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */ 41c80476e4SDavid E. O'Brien 42c80476e4SDavid E. O'Brien /* refresh.c -- refresh the current set of lines on the screen */ 43c80476e4SDavid E. O'Brien 4423338178SMark Peek Char *litptr; 45c80476e4SDavid E. O'Brien static int vcursor_h, vcursor_v; 46c80476e4SDavid E. O'Brien static int rprompt_h, rprompt_v; 47c80476e4SDavid E. O'Brien 4845e5710bSMark Peek static int MakeLiteral (Char *, int, Char); 49*19d2e3deSDmitry Chagin static int Draw (Char *, int, int); 5045e5710bSMark Peek static void Vdraw (Char, int); 5145e5710bSMark Peek static void RefreshPromptpart (Char *); 5245e5710bSMark Peek static void update_line (Char *, Char *, int); 5345e5710bSMark Peek static void str_insert (Char *, int, int, Char *, int); 5445e5710bSMark Peek static void str_delete (Char *, int, int, int); 5545e5710bSMark Peek static void str_cp (Char *, Char *, int); 56b2d5d167SMark Peek #ifndef WINNT_NATIVE 57b2d5d167SMark Peek static 58b2d5d167SMark Peek #else 59b2d5d167SMark Peek extern 60b2d5d167SMark Peek #endif 6145e5710bSMark Peek void PutPlusOne (Char, int); 6245e5710bSMark Peek static void cpy_pad_spaces (Char *, Char *, int); 63c80476e4SDavid E. O'Brien #if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL) 649ccc37e3SMark Peek static void reprintf (char *, ...); 65c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 6645e5710bSMark Peek static void dprintstr (char *, const Char *, const Char *); 67c80476e4SDavid E. O'Brien 68c80476e4SDavid E. O'Brien static void 6945e5710bSMark Peek dprintstr(char *str, const Char *f, const Char *t) 70c80476e4SDavid E. O'Brien { 719ccc37e3SMark Peek reprintf("%s:\"", str); 7223338178SMark Peek while (f < t) { 7345e5710bSMark Peek if (ASC(*f) & ~ASCII) 749ccc37e3SMark Peek reprintf("[%x]", *f++); 7523338178SMark Peek else 769ccc37e3SMark Peek reprintf("%c", CTL_ESC(ASCII & ASC(*f++))); 7723338178SMark Peek } 789ccc37e3SMark Peek reprintf("\"\r\n"); 79c80476e4SDavid E. O'Brien } 80c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 81c80476e4SDavid E. O'Brien 829ccc37e3SMark Peek /* reprintf(): 83c80476e4SDavid E. O'Brien * Print to $DEBUGTTY, so that we can test editing on one pty, and 84c80476e4SDavid E. O'Brien * print debugging stuff on another. Don't interrupt the shell while 85c80476e4SDavid E. O'Brien * debugging cause you'll mangle up the file descriptors! 86c80476e4SDavid E. O'Brien */ 87c80476e4SDavid E. O'Brien static void 889ccc37e3SMark Peek reprintf(char *fmt, ...) 89c80476e4SDavid E. O'Brien { 90c80476e4SDavid E. O'Brien static int fd = -1; 91c80476e4SDavid E. O'Brien char *dtty; 92c80476e4SDavid E. O'Brien 93c80476e4SDavid E. O'Brien if ((dtty = getenv("DEBUGTTY"))) { 94c80476e4SDavid E. O'Brien int o; 95c80476e4SDavid E. O'Brien va_list va; 96c80476e4SDavid E. O'Brien va_start(va, fmt); 97c80476e4SDavid E. O'Brien 98c80476e4SDavid E. O'Brien if (fd == -1) 9945e5710bSMark Peek fd = xopen(dtty, O_RDWR); 100c80476e4SDavid E. O'Brien o = SHOUT; 101c80476e4SDavid E. O'Brien flush(); 102c80476e4SDavid E. O'Brien SHOUT = fd; 103c80476e4SDavid E. O'Brien xvprintf(fmt, va); 104c80476e4SDavid E. O'Brien va_end(va); 105c80476e4SDavid E. O'Brien flush(); 106c80476e4SDavid E. O'Brien SHOUT = o; 107c80476e4SDavid E. O'Brien } 108c80476e4SDavid E. O'Brien } 109c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */ 110c80476e4SDavid E. O'Brien 11123338178SMark Peek static int litlen = 0, litalloc = 0; 11223338178SMark Peek 11345e5710bSMark Peek static int MakeLiteral(Char *str, int len, Char addlit) 114c80476e4SDavid E. O'Brien { 11523338178SMark Peek int i, addlitlen = 0; 11623338178SMark Peek Char *addlitptr = 0; 11723338178SMark Peek if (addlit) { 11823338178SMark Peek if ((addlit & LITERAL) != 0) { 11923338178SMark Peek addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR; 12023338178SMark Peek addlitlen = Strlen(addlitptr); 12123338178SMark Peek } else { 12223338178SMark Peek addlitptr = &addlit; 12323338178SMark Peek addlitlen = 1; 124c80476e4SDavid E. O'Brien } 12523338178SMark Peek for (i = 0; i < litlen; i += LIT_FACTOR) 12623338178SMark Peek if (!Strncmp(addlitptr, litptr + i, addlitlen) && !Strncmp(str, litptr + i + addlitlen, len) && litptr[i + addlitlen + len] == 0) 12723338178SMark Peek return (i / LIT_FACTOR) | LITERAL; 12823338178SMark Peek } else { 12923338178SMark Peek addlitlen = 0; 13023338178SMark Peek for (i = 0; i < litlen; i += LIT_FACTOR) 13123338178SMark Peek if (!Strncmp(str, litptr + i, len) && litptr[i + len] == 0) 13223338178SMark Peek return (i / LIT_FACTOR) | LITERAL; 13323338178SMark Peek } 13423338178SMark Peek if (litlen + addlitlen + len + 1 + (LIT_FACTOR - 1) > litalloc) { 13523338178SMark Peek Char *newlitptr; 13623338178SMark Peek int add = 256; 13723338178SMark Peek while (len + addlitlen + 1 + (LIT_FACTOR - 1) > add) 13823338178SMark Peek add *= 2; 13945e5710bSMark Peek newlitptr = xrealloc(litptr, (litalloc + add) * sizeof(Char)); 14023338178SMark Peek if (!newlitptr) 14123338178SMark Peek return '?'; 14223338178SMark Peek litptr = newlitptr; 14323338178SMark Peek litalloc += add; 14423338178SMark Peek if (addlitptr && addlitptr != &addlit) 14523338178SMark Peek addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR; 14623338178SMark Peek } 14723338178SMark Peek i = litlen / LIT_FACTOR; 14823338178SMark Peek if (i >= LITERAL || i == CHAR_DBWIDTH) 14923338178SMark Peek return '?'; 15023338178SMark Peek if (addlitptr) { 15123338178SMark Peek Strncpy(litptr + litlen, addlitptr, addlitlen); 15223338178SMark Peek litlen += addlitlen; 15323338178SMark Peek } 15423338178SMark Peek Strncpy(litptr + litlen, str, len); 15523338178SMark Peek litlen += len; 15623338178SMark Peek do 15723338178SMark Peek litptr[litlen++] = 0; 15823338178SMark Peek while (litlen % LIT_FACTOR); 15923338178SMark Peek return i | LITERAL; 16023338178SMark Peek } 161c80476e4SDavid E. O'Brien 162*19d2e3deSDmitry Chagin /* draw char at cp, expand tabs, ctl chars */ 16323338178SMark Peek static int 164*19d2e3deSDmitry Chagin Draw(Char *cp, int nocomb, int drawPrompt) 16523338178SMark Peek { 16645e5710bSMark Peek int w, i, lv, lh; 16745e5710bSMark Peek Char c, attr; 16823338178SMark Peek 169*19d2e3deSDmitry Chagin #ifdef WIDE_STRINGS 170*19d2e3deSDmitry Chagin if (!drawPrompt) { /* draw command-line */ 171*19d2e3deSDmitry Chagin attr = 0; 172*19d2e3deSDmitry Chagin c = *cp; 173*19d2e3deSDmitry Chagin } else { /* draw prompt */ 174*19d2e3deSDmitry Chagin /* prompt with attributes(UNDER,BOLD,STANDOUT) */ 175*19d2e3deSDmitry Chagin if (*cp & (UNDER | BOLD | STANDOUT)) { /* *cp >= STANDOUT */ 176*19d2e3deSDmitry Chagin 177*19d2e3deSDmitry Chagin /* example) 178*19d2e3deSDmitry Chagin * We can't distinguish whether (*cp=)0x02ffffff is 179*19d2e3deSDmitry Chagin * U+02FFFFFF or U+00FFFFFF|STANDOUT. 180*19d2e3deSDmitry Chagin * We handle as U+00FFFFFF|STANDOUT, only when drawing prompt. */ 181*19d2e3deSDmitry Chagin attr = (*cp & ATTRIBUTES); 182*19d2e3deSDmitry Chagin /* ~(UNDER | BOLD | STANDOUT) = 0xf1ffffff */ 183*19d2e3deSDmitry Chagin c = *cp & ~(UNDER | BOLD | STANDOUT); 184*19d2e3deSDmitry Chagin 185*19d2e3deSDmitry Chagin /* if c is ctrl code, we handle *cp as havnig no attributes */ 186*19d2e3deSDmitry Chagin if ((c < 0x20 && c >= 0) || c == 0x7f) { 187*19d2e3deSDmitry Chagin attr = 0; 188*19d2e3deSDmitry Chagin c = *cp; 189*19d2e3deSDmitry Chagin } 190*19d2e3deSDmitry Chagin } else { /* prompt without attributes */ 191*19d2e3deSDmitry Chagin attr = 0; 192*19d2e3deSDmitry Chagin c = *cp; 193*19d2e3deSDmitry Chagin } 194*19d2e3deSDmitry Chagin } 195*19d2e3deSDmitry Chagin #else 19623338178SMark Peek attr = *cp & ~CHAR; 19745e5710bSMark Peek c = *cp & CHAR; 198*19d2e3deSDmitry Chagin #endif 199*19d2e3deSDmitry Chagin w = NLSClassify(c, nocomb, drawPrompt); 20023338178SMark Peek switch (w) { 20123338178SMark Peek case NLSCLASS_NL: 20223338178SMark Peek Vdraw('\0', 0); /* assure end of line */ 203c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset cursor pos */ 204c80476e4SDavid E. O'Brien vcursor_v++; 20523338178SMark Peek break; 20623338178SMark Peek case NLSCLASS_TAB: 20723338178SMark Peek do { 20823338178SMark Peek Vdraw(' ', 1); 20923338178SMark Peek } while ((vcursor_h & 07) != 0); 21023338178SMark Peek break; 21123338178SMark Peek case NLSCLASS_CTRL: 21223338178SMark Peek Vdraw('^' | attr, 1); 21323338178SMark Peek if (c == CTL_ESC('\177')) { 21423338178SMark Peek Vdraw('?' | attr, 1); 21523338178SMark Peek } else { 2163b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 217c80476e4SDavid E. O'Brien /* uncontrolify it; works only for iso8859-1 like sets */ 21823338178SMark Peek Vdraw(c | 0100 | attr, 1); 2193b6eaa7bSAndrey A. Chernov #else 22023338178SMark Peek Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1); 22123338178SMark Peek #endif 222c80476e4SDavid E. O'Brien } 22323338178SMark Peek break; 22423338178SMark Peek case NLSCLASS_ILLEGAL: 22523338178SMark Peek Vdraw('\\' | attr, 1); 22645e5710bSMark Peek Vdraw((((c >> 6) & 7) + '0') | attr, 1); 22745e5710bSMark Peek Vdraw((((c >> 3) & 7) + '0') | attr, 1); 22845e5710bSMark Peek Vdraw(((c & 7) + '0') | attr, 1); 22923338178SMark Peek break; 23023338178SMark Peek case NLSCLASS_ILLEGAL2: 23123338178SMark Peek case NLSCLASS_ILLEGAL3: 23223338178SMark Peek case NLSCLASS_ILLEGAL4: 233*19d2e3deSDmitry Chagin case NLSCLASS_ILLEGAL5: 234*19d2e3deSDmitry Chagin Vdraw('\\', 1); 235*19d2e3deSDmitry Chagin Vdraw('U', 1); 236*19d2e3deSDmitry Chagin Vdraw('+', 1); 237*19d2e3deSDmitry Chagin for (i = 16 + 4 * (-w-5); i >= 0; i -= 4) 23823338178SMark Peek Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1); 23923338178SMark Peek break; 24023338178SMark Peek case 0: 24123338178SMark Peek lv = vcursor_v; 24223338178SMark Peek lh = vcursor_h; 24323338178SMark Peek for (;;) { 24423338178SMark Peek lh--; 24523338178SMark Peek if (lh < 0) { 24623338178SMark Peek lv--; 24723338178SMark Peek if (lv < 0) 24823338178SMark Peek break; 24923338178SMark Peek lh = Strlen(Vdisplay[lv]) - 1; 250c80476e4SDavid E. O'Brien } 25123338178SMark Peek if (Vdisplay[lv][lh] != CHAR_DBWIDTH) 25223338178SMark Peek break; 25323338178SMark Peek } 25423338178SMark Peek if (lv < 0) { 25523338178SMark Peek Vdraw('\\' | attr, 1); 25645e5710bSMark Peek Vdraw((((c >> 6) & 7) + '0') | attr, 1); 25745e5710bSMark Peek Vdraw((((c >> 3) & 7) + '0') | attr, 1); 25845e5710bSMark Peek Vdraw(((c & 7) + '0') | attr, 1); 25945e5710bSMark Peek break; 26023338178SMark Peek } 26145e5710bSMark Peek Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]); 26223338178SMark Peek break; 26323338178SMark Peek default: 26423338178SMark Peek Vdraw(*cp, w); 26523338178SMark Peek break; 266c80476e4SDavid E. O'Brien } 26745e5710bSMark Peek return 1; 268c80476e4SDavid E. O'Brien } 269c80476e4SDavid E. O'Brien 270c80476e4SDavid E. O'Brien static void 27145e5710bSMark Peek Vdraw(Char c, int width) /* draw char c onto V lines */ 272c80476e4SDavid E. O'Brien { 273c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 274c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS 2759ccc37e3SMark Peek reprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width); 276c80476e4SDavid E. O'Brien # else 2779ccc37e3SMark Peek reprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width); 278c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */ 279c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 280c80476e4SDavid E. O'Brien 28123338178SMark Peek /* Hopefully this is what all the terminals do with multi-column characters 28223338178SMark Peek that "span line breaks". */ 28323338178SMark Peek while (vcursor_h + width > TermH) 28423338178SMark Peek Vdraw(' ', 1); 28545e5710bSMark Peek Vdisplay[vcursor_v][vcursor_h] = c; 28623338178SMark Peek if (width) 287c80476e4SDavid E. O'Brien vcursor_h++; /* advance to next place */ 28823338178SMark Peek while (--width > 0) 28923338178SMark Peek Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH; 290c80476e4SDavid E. O'Brien if (vcursor_h >= TermH) { 291c80476e4SDavid E. O'Brien Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */ 292c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset it. */ 293c80476e4SDavid E. O'Brien vcursor_v++; 294c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 295c80476e4SDavid E. O'Brien if (vcursor_v >= TermV) { /* should NEVER happen. */ 2969ccc37e3SMark Peek reprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n", 297c80476e4SDavid E. O'Brien vcursor_v, TermV); 298c80476e4SDavid E. O'Brien abort(); 299c80476e4SDavid E. O'Brien } 300c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 301c80476e4SDavid E. O'Brien } 302c80476e4SDavid E. O'Brien } 303c80476e4SDavid E. O'Brien 304c80476e4SDavid E. O'Brien /* 305c80476e4SDavid E. O'Brien * RefreshPromptpart() 306c80476e4SDavid E. O'Brien * draws a prompt element, expanding literals (we know it's ASCIZ) 307c80476e4SDavid E. O'Brien */ 308c80476e4SDavid E. O'Brien static void 30945e5710bSMark Peek RefreshPromptpart(Char *buf) 310c80476e4SDavid E. O'Brien { 31123338178SMark Peek Char *cp; 31245e5710bSMark Peek int w; 313c80476e4SDavid E. O'Brien 31445e5710bSMark Peek if (buf == NULL) 31545e5710bSMark Peek return; 31623338178SMark Peek for (cp = buf; *cp; ) { 317c80476e4SDavid E. O'Brien if (*cp & LITERAL) { 31823338178SMark Peek Char *litstart = cp; 319c80476e4SDavid E. O'Brien while (*cp & LITERAL) 320c80476e4SDavid E. O'Brien cp++; 32123338178SMark Peek if (*cp) { 32245e5710bSMark Peek w = NLSWidth(*cp & CHAR); 32345e5710bSMark Peek Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w); 32445e5710bSMark Peek cp++; 32523338178SMark Peek } 326c80476e4SDavid E. O'Brien else { 327c80476e4SDavid E. O'Brien /* 328c80476e4SDavid E. O'Brien * XXX: This is a bug, we lose the last literal, if it is not 329c80476e4SDavid E. O'Brien * followed by a normal character, but it is too hard to fix 330c80476e4SDavid E. O'Brien */ 331c80476e4SDavid E. O'Brien break; 332c80476e4SDavid E. O'Brien } 333c80476e4SDavid E. O'Brien } 334c80476e4SDavid E. O'Brien else 335*19d2e3deSDmitry Chagin cp += Draw(cp, cp == buf, 1); 336c80476e4SDavid E. O'Brien } 337c80476e4SDavid E. O'Brien } 338c80476e4SDavid E. O'Brien 339c80476e4SDavid E. O'Brien /* 340c80476e4SDavid E. O'Brien * Refresh() 341c80476e4SDavid E. O'Brien * draws the new virtual screen image from the current input 342c80476e4SDavid E. O'Brien * line, then goes line-by-line changing the real image to the new 343c80476e4SDavid E. O'Brien * virtual image. The routine to re-draw a line can be replaced 344c80476e4SDavid E. O'Brien * easily in hopes of a smarter one being placed there. 345c80476e4SDavid E. O'Brien */ 346b2d5d167SMark Peek #ifndef WINNT_NATIVE 347b2d5d167SMark Peek static 348b2d5d167SMark Peek #endif 349b2d5d167SMark Peek int OldvcV = 0; 350b2d5d167SMark Peek 351c80476e4SDavid E. O'Brien void 35245e5710bSMark Peek Refresh(void) 353c80476e4SDavid E. O'Brien { 35423338178SMark Peek int cur_line; 35523338178SMark Peek Char *cp; 356c80476e4SDavid E. O'Brien int cur_h, cur_v = 0, new_vcv; 357c80476e4SDavid E. O'Brien int rhdiff; 358c80476e4SDavid E. O'Brien Char oldgetting; 359c80476e4SDavid E. O'Brien 360c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 3619ccc37e3SMark Peek reprintf("Prompt = :%s:\r\n", short2str(Prompt)); 3629ccc37e3SMark Peek reprintf("InputBuf = :%s:\r\n", short2str(InputBuf)); 363c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 364c80476e4SDavid E. O'Brien oldgetting = GettingInput; 365c80476e4SDavid E. O'Brien GettingInput = 0; /* avoid re-entrance via SIGWINCH */ 366c80476e4SDavid E. O'Brien 367c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */ 368c80476e4SDavid E. O'Brien vcursor_h = 0; 369c80476e4SDavid E. O'Brien vcursor_v = 0; 37045e5710bSMark Peek RefreshPromptpart(RPrompt); 371c80476e4SDavid E. O'Brien rprompt_h = vcursor_h; 372c80476e4SDavid E. O'Brien rprompt_v = vcursor_v; 373c80476e4SDavid E. O'Brien 374c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, draw prompt */ 375c80476e4SDavid E. O'Brien vcursor_h = 0; 376c80476e4SDavid E. O'Brien vcursor_v = 0; 37745e5710bSMark Peek RefreshPromptpart(Prompt); 378c80476e4SDavid E. O'Brien cur_h = -1; /* set flag in case I'm not set */ 379c80476e4SDavid E. O'Brien 380c80476e4SDavid E. O'Brien /* draw the current input buffer */ 38123338178SMark Peek for (cp = InputBuf; (cp < LastChar); ) { 38223338178SMark Peek if (cp >= Cursor && cur_h == -1) { 383c80476e4SDavid E. O'Brien cur_h = vcursor_h; /* save for later */ 384c80476e4SDavid E. O'Brien cur_v = vcursor_v; 38523338178SMark Peek Cursor = cp; 386c80476e4SDavid E. O'Brien } 387*19d2e3deSDmitry Chagin cp += Draw(cp, cp == InputBuf, 0); 388c80476e4SDavid E. O'Brien } 389c80476e4SDavid E. O'Brien 390c80476e4SDavid E. O'Brien if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */ 391c80476e4SDavid E. O'Brien cur_h = vcursor_h; 392c80476e4SDavid E. O'Brien cur_v = vcursor_v; 393c80476e4SDavid E. O'Brien } 394c80476e4SDavid E. O'Brien 395c80476e4SDavid E. O'Brien rhdiff = TermH - vcursor_h - rprompt_h; 396c80476e4SDavid E. O'Brien if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) { 397c80476e4SDavid E. O'Brien /* 398c80476e4SDavid E. O'Brien * have a right-hand side prompt that will fit on 399c80476e4SDavid E. O'Brien * the end of the first line with at least one 400c80476e4SDavid E. O'Brien * character gap to the input buffer. 401c80476e4SDavid E. O'Brien */ 402c80476e4SDavid E. O'Brien while (--rhdiff > 0) /* pad out with spaces */ 40323338178SMark Peek Vdraw(' ', 1); 40445e5710bSMark Peek RefreshPromptpart(RPrompt); 405c80476e4SDavid E. O'Brien } 406c80476e4SDavid E. O'Brien else { 407c80476e4SDavid E. O'Brien rprompt_h = 0; /* flag "not using rprompt" */ 408c80476e4SDavid E. O'Brien rprompt_v = 0; 409c80476e4SDavid E. O'Brien } 410c80476e4SDavid E. O'Brien 411c80476e4SDavid E. O'Brien new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */ 41223338178SMark Peek Vdraw('\0', 1); /* put NUL on end */ 413c80476e4SDavid E. O'Brien 41423338178SMark Peek #if defined (DEBUG_REFRESH) 4159ccc37e3SMark Peek reprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n", 416c80476e4SDavid E. O'Brien TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0])); 417c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 418c80476e4SDavid E. O'Brien 419c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 4209ccc37e3SMark Peek reprintf("updating %d lines.\r\n", new_vcv); 421c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 422c80476e4SDavid E. O'Brien for (cur_line = 0; cur_line <= new_vcv; cur_line++) { 423c80476e4SDavid E. O'Brien /* NOTE THAT update_line MAY CHANGE Display[cur_line] */ 424c80476e4SDavid E. O'Brien update_line(Display[cur_line], Vdisplay[cur_line], cur_line); 4253b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 426c80476e4SDavid E. O'Brien flush(); 4273b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 428c80476e4SDavid E. O'Brien 429c80476e4SDavid E. O'Brien /* 430c80476e4SDavid E. O'Brien * Copy the new line to be the current one, and pad out with spaces 431c80476e4SDavid E. O'Brien * to the full width of the terminal so that if we try moving the 432c80476e4SDavid E. O'Brien * cursor by writing the character that is at the end of the 433c80476e4SDavid E. O'Brien * screen line, it won't be a NUL or some old leftover stuff. 434c80476e4SDavid E. O'Brien */ 435c80476e4SDavid E. O'Brien cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH); 436c80476e4SDavid E. O'Brien } 437c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 4389ccc37e3SMark Peek reprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n", 439c80476e4SDavid E. O'Brien vcursor_v, OldvcV, cur_line); 440c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 441c80476e4SDavid E. O'Brien if (OldvcV > new_vcv) { 442c80476e4SDavid E. O'Brien for (; cur_line <= OldvcV; cur_line++) { 443c80476e4SDavid E. O'Brien update_line(Display[cur_line], STRNULL, cur_line); 444c80476e4SDavid E. O'Brien *Display[cur_line] = '\0'; 445c80476e4SDavid E. O'Brien } 446c80476e4SDavid E. O'Brien } 447c80476e4SDavid E. O'Brien OldvcV = new_vcv; /* set for next time */ 448c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 4499ccc37e3SMark Peek reprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n", 450c80476e4SDavid E. O'Brien CursorH, CursorV, cur_h, cur_v); 451c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 4523b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 453c80476e4SDavid E. O'Brien flush(); 4543b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 455c80476e4SDavid E. O'Brien MoveToLine(cur_v); /* go to where the cursor is */ 456c80476e4SDavid E. O'Brien MoveToChar(cur_h); 457c80476e4SDavid E. O'Brien SetAttributes(0); /* Clear all attributes */ 458c80476e4SDavid E. O'Brien flush(); /* send the output... */ 459c80476e4SDavid E. O'Brien GettingInput = oldgetting; /* reset to old value */ 460c80476e4SDavid E. O'Brien } 461c80476e4SDavid E. O'Brien 462c80476e4SDavid E. O'Brien #ifdef notdef 46345e5710bSMark Peek GotoBottom(void) 464c80476e4SDavid E. O'Brien { /* used to go to last used screen line */ 465c80476e4SDavid E. O'Brien MoveToLine(OldvcV); 466c80476e4SDavid E. O'Brien } 467c80476e4SDavid E. O'Brien 468c80476e4SDavid E. O'Brien #endif 469c80476e4SDavid E. O'Brien 470c80476e4SDavid E. O'Brien void 47145e5710bSMark Peek PastBottom(void) 472c80476e4SDavid E. O'Brien { /* used to go to last used screen line */ 473c80476e4SDavid E. O'Brien MoveToLine(OldvcV); 474c80476e4SDavid E. O'Brien (void) putraw('\r'); 475c80476e4SDavid E. O'Brien (void) putraw('\n'); 476c80476e4SDavid E. O'Brien ClearDisp(); 477c80476e4SDavid E. O'Brien flush(); 478c80476e4SDavid E. O'Brien } 479c80476e4SDavid E. O'Brien 480c80476e4SDavid E. O'Brien 481c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat, 482c80476e4SDavid E. O'Brien maximum length of d is dlen */ 483c80476e4SDavid E. O'Brien static void 48445e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num) 485c80476e4SDavid E. O'Brien { 48623338178SMark Peek Char *a, *b; 487c80476e4SDavid E. O'Brien 488c80476e4SDavid E. O'Brien if (num <= 0) 489c80476e4SDavid E. O'Brien return; 490c80476e4SDavid E. O'Brien if (num > dlen - dat) 491c80476e4SDavid E. O'Brien num = dlen - dat; 492c80476e4SDavid E. O'Brien 493c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 4949ccc37e3SMark Peek reprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n", 495c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 4969ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s)); 497c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 498c80476e4SDavid E. O'Brien 499c80476e4SDavid E. O'Brien /* open up the space for num chars */ 500c80476e4SDavid E. O'Brien if (num > 0) { 501c80476e4SDavid E. O'Brien b = d + dlen - 1; 502c80476e4SDavid E. O'Brien a = b - num; 503c80476e4SDavid E. O'Brien while (a >= &d[dat]) 504c80476e4SDavid E. O'Brien *b-- = *a--; 505c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */ 506c80476e4SDavid E. O'Brien } 507c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 5089ccc37e3SMark Peek reprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n", 509c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 5109ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s)); 511c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 512c80476e4SDavid E. O'Brien 513c80476e4SDavid E. O'Brien /* copy the characters */ 514c80476e4SDavid E. O'Brien for (a = d + dat; (a < d + dlen) && (num > 0); num--) 515c80476e4SDavid E. O'Brien *a++ = *s++; 516c80476e4SDavid E. O'Brien 517c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 5189ccc37e3SMark Peek reprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n", 519c80476e4SDavid E. O'Brien num, dat, dlen, d, short2str(s)); 5209ccc37e3SMark Peek reprintf("s == \"%s\"n", short2str(s)); 521c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 522c80476e4SDavid E. O'Brien } 523c80476e4SDavid E. O'Brien 524c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */ 525c80476e4SDavid E. O'Brien static void 52645e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num) 527c80476e4SDavid E. O'Brien { 52823338178SMark Peek Char *a, *b; 529c80476e4SDavid E. O'Brien 530c80476e4SDavid E. O'Brien if (num <= 0) 531c80476e4SDavid E. O'Brien return; 532c80476e4SDavid E. O'Brien if (dat + num >= dlen) { 533c80476e4SDavid E. O'Brien d[dat] = '\0'; 534c80476e4SDavid E. O'Brien return; 535c80476e4SDavid E. O'Brien } 536c80476e4SDavid E. O'Brien 537c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 5389ccc37e3SMark Peek reprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n", 539c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 540c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 541c80476e4SDavid E. O'Brien 542c80476e4SDavid E. O'Brien /* open up the space for num chars */ 543c80476e4SDavid E. O'Brien if (num > 0) { 544c80476e4SDavid E. O'Brien b = d + dat; 545c80476e4SDavid E. O'Brien a = b + num; 546c80476e4SDavid E. O'Brien while (a < &d[dlen]) 547c80476e4SDavid E. O'Brien *b++ = *a++; 548c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */ 549c80476e4SDavid E. O'Brien } 550c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 5519ccc37e3SMark Peek reprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n", 552c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 553c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 554c80476e4SDavid E. O'Brien } 555c80476e4SDavid E. O'Brien 556c80476e4SDavid E. O'Brien static void 55745e5710bSMark Peek str_cp(Char *a, Char *b, int n) 558c80476e4SDavid E. O'Brien { 559c80476e4SDavid E. O'Brien while (n-- && *b) 560c80476e4SDavid E. O'Brien *a++ = *b++; 561c80476e4SDavid E. O'Brien } 562c80476e4SDavid E. O'Brien 563c80476e4SDavid E. O'Brien 564c80476e4SDavid E. O'Brien /* **************************************************************** 565c80476e4SDavid E. O'Brien update_line() is based on finding the middle difference of each line 566c80476e4SDavid E. O'Brien on the screen; vis: 567c80476e4SDavid E. O'Brien 568c80476e4SDavid E. O'Brien /old first difference 569c80476e4SDavid E. O'Brien /beginning of line | /old last same /old EOL 570c80476e4SDavid E. O'Brien v v v v 571c80476e4SDavid E. O'Brien old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 572c80476e4SDavid E. O'Brien new: eddie> Oh, my little buggy says to me, as lurgid as 573c80476e4SDavid E. O'Brien ^ ^ ^ ^ 574c80476e4SDavid E. O'Brien \beginning of line | \new last same \new end of line 575c80476e4SDavid E. O'Brien \new first difference 576c80476e4SDavid E. O'Brien 577c80476e4SDavid E. O'Brien all are character pointers for the sake of speed. Special cases for 578c80476e4SDavid E. O'Brien no differences, as well as for end of line additions must be handled. 579c80476e4SDavid E. O'Brien **************************************************************** */ 580c80476e4SDavid E. O'Brien 581c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it". This should be about 582c80476e4SDavid E. O'Brien * half the "cost" of going into insert mode, inserting a character, and 583c80476e4SDavid E. O'Brien * going back out. This should really be calculated from the termcap 584c80476e4SDavid E. O'Brien * data... For the moment, a good number for ANSI terminals. 585c80476e4SDavid E. O'Brien */ 586c80476e4SDavid E. O'Brien #define MIN_END_KEEP 4 587c80476e4SDavid E. O'Brien 588c80476e4SDavid E. O'Brien static void /* could be changed to make it smarter */ 58945e5710bSMark Peek update_line(Char *old, Char *new, int cur_line) 590c80476e4SDavid E. O'Brien { 59123338178SMark Peek Char *o, *n, *p, c; 592c80476e4SDavid E. O'Brien Char *ofd, *ols, *oe, *nfd, *nls, *ne; 593c80476e4SDavid E. O'Brien Char *osb, *ose, *nsb, *nse; 594c80476e4SDavid E. O'Brien int fx, sx; 595c80476e4SDavid E. O'Brien 596c80476e4SDavid E. O'Brien /* 59723338178SMark Peek * find first diff (won't be CHAR_DBWIDTH in either line) 598c80476e4SDavid E. O'Brien */ 599c80476e4SDavid E. O'Brien for (o = old, n = new; *o && (*o == *n); o++, n++) 600c80476e4SDavid E. O'Brien continue; 601c80476e4SDavid E. O'Brien ofd = o; 602c80476e4SDavid E. O'Brien nfd = n; 603c80476e4SDavid E. O'Brien 604c80476e4SDavid E. O'Brien /* 605c80476e4SDavid E. O'Brien * Find the end of both old and new 606c80476e4SDavid E. O'Brien */ 60745e5710bSMark Peek o = Strend(o); 60845e5710bSMark Peek 609c80476e4SDavid E. O'Brien /* 610c80476e4SDavid E. O'Brien * Remove any trailing blanks off of the end, being careful not to 611c80476e4SDavid E. O'Brien * back up past the beginning. 612c80476e4SDavid E. O'Brien */ 61345e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) { 614c80476e4SDavid E. O'Brien while (ofd < o) { 615c80476e4SDavid E. O'Brien if (o[-1] != ' ') 616c80476e4SDavid E. O'Brien break; 617c80476e4SDavid E. O'Brien o--; 618c80476e4SDavid E. O'Brien } 61945e5710bSMark Peek } 620c80476e4SDavid E. O'Brien oe = o; 621c80476e4SDavid E. O'Brien *oe = (Char) 0; 622c80476e4SDavid E. O'Brien 62345e5710bSMark Peek n = Strend(n); 624c80476e4SDavid E. O'Brien 625c80476e4SDavid E. O'Brien /* remove blanks from end of new */ 62645e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) { 627c80476e4SDavid E. O'Brien while (nfd < n) { 628c80476e4SDavid E. O'Brien if (n[-1] != ' ') 629c80476e4SDavid E. O'Brien break; 630c80476e4SDavid E. O'Brien n--; 631c80476e4SDavid E. O'Brien } 63245e5710bSMark Peek } 633c80476e4SDavid E. O'Brien ne = n; 634c80476e4SDavid E. O'Brien *ne = (Char) 0; 635c80476e4SDavid E. O'Brien 636c80476e4SDavid E. O'Brien /* 637c80476e4SDavid E. O'Brien * if no diff, continue to next line of redraw 638c80476e4SDavid E. O'Brien */ 639c80476e4SDavid E. O'Brien if (*ofd == '\0' && *nfd == '\0') { 640c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 6419ccc37e3SMark Peek reprintf("no difference.\r\n"); 642c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 643c80476e4SDavid E. O'Brien return; 644c80476e4SDavid E. O'Brien } 645c80476e4SDavid E. O'Brien 646c80476e4SDavid E. O'Brien /* 647c80476e4SDavid E. O'Brien * find last same pointer 648c80476e4SDavid E. O'Brien */ 649c80476e4SDavid E. O'Brien while ((o > ofd) && (n > nfd) && (*--o == *--n)) 650c80476e4SDavid E. O'Brien continue; 65123338178SMark Peek if (*o != *n) { 65223338178SMark Peek o++; 65323338178SMark Peek n++; 65423338178SMark Peek } 65523338178SMark Peek while (*o == CHAR_DBWIDTH) { 65623338178SMark Peek o++; 65723338178SMark Peek n++; 65823338178SMark Peek } 65923338178SMark Peek ols = o; 66023338178SMark Peek nls = n; 661c80476e4SDavid E. O'Brien 662c80476e4SDavid E. O'Brien /* 663c80476e4SDavid E. O'Brien * find same begining and same end 664c80476e4SDavid E. O'Brien */ 665c80476e4SDavid E. O'Brien osb = ols; 666c80476e4SDavid E. O'Brien nsb = nls; 667c80476e4SDavid E. O'Brien ose = ols; 668c80476e4SDavid E. O'Brien nse = nls; 669c80476e4SDavid E. O'Brien 670c80476e4SDavid E. O'Brien /* 671c80476e4SDavid E. O'Brien * case 1: insert: scan from nfd to nls looking for *ofd 672c80476e4SDavid E. O'Brien */ 673c80476e4SDavid E. O'Brien if (*ofd) { 674c80476e4SDavid E. O'Brien for (c = *ofd, n = nfd; n < nls; n++) { 675c80476e4SDavid E. O'Brien if (c == *n) { 676c80476e4SDavid E. O'Brien for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++) 677c80476e4SDavid E. O'Brien continue; 678c80476e4SDavid E. O'Brien /* 679c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we 680c80476e4SDavid E. O'Brien * take it 681c80476e4SDavid E. O'Brien */ 682c80476e4SDavid E. O'Brien if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) { 683c80476e4SDavid E. O'Brien nsb = n; 684c80476e4SDavid E. O'Brien nse = p; 685c80476e4SDavid E. O'Brien osb = ofd; 686c80476e4SDavid E. O'Brien ose = o; 687c80476e4SDavid E. O'Brien } 688c80476e4SDavid E. O'Brien } 689c80476e4SDavid E. O'Brien } 690c80476e4SDavid E. O'Brien } 691c80476e4SDavid E. O'Brien 692c80476e4SDavid E. O'Brien /* 693c80476e4SDavid E. O'Brien * case 2: delete: scan from ofd to ols looking for *nfd 694c80476e4SDavid E. O'Brien */ 695c80476e4SDavid E. O'Brien if (*nfd) { 696c80476e4SDavid E. O'Brien for (c = *nfd, o = ofd; o < ols; o++) { 697c80476e4SDavid E. O'Brien if (c == *o) { 698c80476e4SDavid E. O'Brien for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++) 699c80476e4SDavid E. O'Brien continue; 700c80476e4SDavid E. O'Brien /* 701c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we 702c80476e4SDavid E. O'Brien * take it 703c80476e4SDavid E. O'Brien */ 704c80476e4SDavid E. O'Brien if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) { 705c80476e4SDavid E. O'Brien nsb = nfd; 706c80476e4SDavid E. O'Brien nse = n; 707c80476e4SDavid E. O'Brien osb = o; 708c80476e4SDavid E. O'Brien ose = p; 709c80476e4SDavid E. O'Brien } 710c80476e4SDavid E. O'Brien } 711c80476e4SDavid E. O'Brien } 712c80476e4SDavid E. O'Brien } 713c80476e4SDavid E. O'Brien #ifdef notdef 714c80476e4SDavid E. O'Brien /* 715c80476e4SDavid E. O'Brien * If `last same' is before `same end' re-adjust 716c80476e4SDavid E. O'Brien */ 717c80476e4SDavid E. O'Brien if (ols < ose) 718c80476e4SDavid E. O'Brien ols = ose; 719c80476e4SDavid E. O'Brien if (nls < nse) 720c80476e4SDavid E. O'Brien nls = nse; 721c80476e4SDavid E. O'Brien #endif 722c80476e4SDavid E. O'Brien 723c80476e4SDavid E. O'Brien /* 724c80476e4SDavid E. O'Brien * Pragmatics I: If old trailing whitespace or not enough characters to 725c80476e4SDavid E. O'Brien * save to be worth it, then don't save the last same info. 726c80476e4SDavid E. O'Brien */ 727c80476e4SDavid E. O'Brien if ((oe - ols) < MIN_END_KEEP) { 728c80476e4SDavid E. O'Brien ols = oe; 729c80476e4SDavid E. O'Brien nls = ne; 730c80476e4SDavid E. O'Brien } 731c80476e4SDavid E. O'Brien 732c80476e4SDavid E. O'Brien /* 733c80476e4SDavid E. O'Brien * Pragmatics II: if the terminal isn't smart enough, make the data dumber 734c80476e4SDavid E. O'Brien * so the smart update doesn't try anything fancy 735c80476e4SDavid E. O'Brien */ 736c80476e4SDavid E. O'Brien 737c80476e4SDavid E. O'Brien /* 738c80476e4SDavid E. O'Brien * fx is the number of characters we need to insert/delete: in the 739c80476e4SDavid E. O'Brien * beginning to bring the two same begins together 740c80476e4SDavid E. O'Brien */ 741c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 742c80476e4SDavid E. O'Brien /* 743c80476e4SDavid E. O'Brien * sx is the number of characters we need to insert/delete: in the end to 744c80476e4SDavid E. O'Brien * bring the two same last parts together 745c80476e4SDavid E. O'Brien */ 746c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose)); 747c80476e4SDavid E. O'Brien 748c80476e4SDavid E. O'Brien if (!T_CanIns) { 749c80476e4SDavid E. O'Brien if (fx > 0) { 750c80476e4SDavid E. O'Brien osb = ols; 751c80476e4SDavid E. O'Brien ose = ols; 752c80476e4SDavid E. O'Brien nsb = nls; 753c80476e4SDavid E. O'Brien nse = nls; 754c80476e4SDavid E. O'Brien } 755c80476e4SDavid E. O'Brien if (sx > 0) { 756c80476e4SDavid E. O'Brien ols = oe; 757c80476e4SDavid E. O'Brien nls = ne; 758c80476e4SDavid E. O'Brien } 759c80476e4SDavid E. O'Brien if ((ols - ofd) < (nls - nfd)) { 760c80476e4SDavid E. O'Brien ols = oe; 761c80476e4SDavid E. O'Brien nls = ne; 762c80476e4SDavid E. O'Brien } 763c80476e4SDavid E. O'Brien } 764c80476e4SDavid E. O'Brien if (!T_CanDel) { 765c80476e4SDavid E. O'Brien if (fx < 0) { 766c80476e4SDavid E. O'Brien osb = ols; 767c80476e4SDavid E. O'Brien ose = ols; 768c80476e4SDavid E. O'Brien nsb = nls; 769c80476e4SDavid E. O'Brien nse = nls; 770c80476e4SDavid E. O'Brien } 771c80476e4SDavid E. O'Brien if (sx < 0) { 772c80476e4SDavid E. O'Brien ols = oe; 773c80476e4SDavid E. O'Brien nls = ne; 774c80476e4SDavid E. O'Brien } 775c80476e4SDavid E. O'Brien if ((ols - ofd) > (nls - nfd)) { 776c80476e4SDavid E. O'Brien ols = oe; 777c80476e4SDavid E. O'Brien nls = ne; 778c80476e4SDavid E. O'Brien } 779c80476e4SDavid E. O'Brien } 780c80476e4SDavid E. O'Brien 781c80476e4SDavid E. O'Brien /* 782c80476e4SDavid E. O'Brien * Pragmatics III: make sure the middle shifted pointers are correct if 783c80476e4SDavid E. O'Brien * they don't point to anything (we may have moved ols or nls). 784c80476e4SDavid E. O'Brien */ 785c80476e4SDavid E. O'Brien /* if the change isn't worth it, don't bother */ 786c80476e4SDavid E. O'Brien /* was: if (osb == ose) */ 787c80476e4SDavid E. O'Brien if ((ose - osb) < MIN_END_KEEP) { 788c80476e4SDavid E. O'Brien osb = ols; 789c80476e4SDavid E. O'Brien ose = ols; 790c80476e4SDavid E. O'Brien nsb = nls; 791c80476e4SDavid E. O'Brien nse = nls; 792c80476e4SDavid E. O'Brien } 793c80476e4SDavid E. O'Brien 794c80476e4SDavid E. O'Brien /* 795c80476e4SDavid E. O'Brien * Now that we are done with pragmatics we recompute fx, sx 796c80476e4SDavid E. O'Brien */ 797c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 798c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose)); 799c80476e4SDavid E. O'Brien 800c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 8019ccc37e3SMark Peek reprintf("\n"); 8029ccc37e3SMark Peek reprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n", 803c80476e4SDavid E. O'Brien ofd - old, osb - old, ose - old, ols - old, oe - old); 8049ccc37e3SMark Peek reprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n", 805c80476e4SDavid E. O'Brien nfd - new, nsb - new, nse - new, nls - new, ne - new); 8069ccc37e3SMark Peek reprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"); 8079ccc37e3SMark Peek reprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"); 808c80476e4SDavid E. O'Brien dprintstr("old- oe", old, oe); 809c80476e4SDavid E. O'Brien dprintstr("new- ne", new, ne); 810c80476e4SDavid E. O'Brien dprintstr("old-ofd", old, ofd); 811c80476e4SDavid E. O'Brien dprintstr("new-nfd", new, nfd); 812c80476e4SDavid E. O'Brien dprintstr("ofd-osb", ofd, osb); 813c80476e4SDavid E. O'Brien dprintstr("nfd-nsb", nfd, nsb); 814c80476e4SDavid E. O'Brien dprintstr("osb-ose", osb, ose); 815c80476e4SDavid E. O'Brien dprintstr("nsb-nse", nsb, nse); 816c80476e4SDavid E. O'Brien dprintstr("ose-ols", ose, ols); 817c80476e4SDavid E. O'Brien dprintstr("nse-nls", nse, nls); 818c80476e4SDavid E. O'Brien dprintstr("ols- oe", ols, oe); 819c80476e4SDavid E. O'Brien dprintstr("nls- ne", nls, ne); 820c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 821c80476e4SDavid E. O'Brien 822c80476e4SDavid E. O'Brien /* 823c80476e4SDavid E. O'Brien * CursorV to this line cur_line MUST be in this routine so that if we 824c80476e4SDavid E. O'Brien * don't have to change the line, we don't move to it. CursorH to first 825c80476e4SDavid E. O'Brien * diff char 826c80476e4SDavid E. O'Brien */ 827c80476e4SDavid E. O'Brien MoveToLine(cur_line); 828c80476e4SDavid E. O'Brien 829c80476e4SDavid E. O'Brien /* 830c80476e4SDavid E. O'Brien * at this point we have something like this: 831c80476e4SDavid E. O'Brien * 832c80476e4SDavid E. O'Brien * /old /ofd /osb /ose /ols /oe 833c80476e4SDavid E. O'Brien * v.....................v v..................v v........v 834c80476e4SDavid E. O'Brien * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as 835c80476e4SDavid E. O'Brien * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as 836c80476e4SDavid E. O'Brien * ^.....................^ ^..................^ ^........^ 837c80476e4SDavid E. O'Brien * \new \nfd \nsb \nse \nls \ne 838c80476e4SDavid E. O'Brien * 839c80476e4SDavid E. O'Brien * fx is the difference in length between the the chars between nfd and 840c80476e4SDavid E. O'Brien * nsb, and the chars between ofd and osb, and is thus the number of 841c80476e4SDavid E. O'Brien * characters to delete if < 0 (new is shorter than old, as above), 842c80476e4SDavid E. O'Brien * or insert (new is longer than short). 843c80476e4SDavid E. O'Brien * 844c80476e4SDavid E. O'Brien * sx is the same for the second differences. 845c80476e4SDavid E. O'Brien */ 846c80476e4SDavid E. O'Brien 847c80476e4SDavid E. O'Brien /* 848c80476e4SDavid E. O'Brien * if we have a net insert on the first difference, AND inserting the net 849c80476e4SDavid E. O'Brien * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character 850c80476e4SDavid E. O'Brien * (which is ne if nls != ne, otherwise is nse) off the edge of the screen 851c80476e4SDavid E. O'Brien * (TermH - 1) else we do the deletes first so that we keep everything we 852c80476e4SDavid E. O'Brien * need to. 853c80476e4SDavid E. O'Brien */ 854c80476e4SDavid E. O'Brien 855c80476e4SDavid E. O'Brien /* 856c80476e4SDavid E. O'Brien * if the last same is the same like the end, there is no last same part, 857c80476e4SDavid E. O'Brien * otherwise we want to keep the last same part set p to the last useful 858c80476e4SDavid E. O'Brien * old character 859c80476e4SDavid E. O'Brien */ 860c80476e4SDavid E. O'Brien p = (ols != oe) ? oe : ose; 861c80476e4SDavid E. O'Brien 862c80476e4SDavid E. O'Brien /* 863c80476e4SDavid E. O'Brien * if (There is a diffence in the beginning) && (we need to insert 864c80476e4SDavid E. O'Brien * characters) && (the number of characters to insert is less than the term 865c80476e4SDavid E. O'Brien * width) We need to do an insert! else if (we need to delete characters) 866c80476e4SDavid E. O'Brien * We need to delete characters! else No insert or delete 867c80476e4SDavid E. O'Brien */ 868c80476e4SDavid E. O'Brien if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) { 869c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 8709ccc37e3SMark Peek reprintf("first diff insert at %d...\r\n", nfd - new); 871c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 872c80476e4SDavid E. O'Brien /* 873c80476e4SDavid E. O'Brien * Move to the first char to insert, where the first diff is. 874c80476e4SDavid E. O'Brien */ 875c80476e4SDavid E. O'Brien MoveToChar(nfd - new); 876c80476e4SDavid E. O'Brien /* 877c80476e4SDavid E. O'Brien * Check if we have stuff to keep at end 878c80476e4SDavid E. O'Brien */ 879c80476e4SDavid E. O'Brien if (nsb != ne) { 880c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 8819ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n"); 882c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 883c80476e4SDavid E. O'Brien /* 884c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd 885c80476e4SDavid E. O'Brien */ 886c80476e4SDavid E. O'Brien if (fx > 0) { 887c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 888c80476e4SDavid E. O'Brien if (!T_CanIns) 8899ccc37e3SMark Peek reprintf(" ERROR: cannot insert in early first diff\n"); 890c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 891c80476e4SDavid E. O'Brien Insert_write(nfd, fx); 892c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx); 893c80476e4SDavid E. O'Brien } 894c80476e4SDavid E. O'Brien /* 895c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx) 896c80476e4SDavid E. O'Brien */ 897c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx); 898c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx)); 899c80476e4SDavid E. O'Brien } 900c80476e4SDavid E. O'Brien else { 901c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9029ccc37e3SMark Peek reprintf("without anything to save\r\n"); 903c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 904c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 905c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 906c80476e4SDavid E. O'Brien /* 907c80476e4SDavid E. O'Brien * Done 908c80476e4SDavid E. O'Brien */ 909c80476e4SDavid E. O'Brien return; 910c80476e4SDavid E. O'Brien } 911c80476e4SDavid E. O'Brien } 912c80476e4SDavid E. O'Brien else if (fx < 0) { 913c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9149ccc37e3SMark Peek reprintf("first diff delete at %d...\r\n", ofd - old); 915c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 916c80476e4SDavid E. O'Brien /* 917c80476e4SDavid E. O'Brien * move to the first char to delete where the first diff is 918c80476e4SDavid E. O'Brien */ 919c80476e4SDavid E. O'Brien MoveToChar(ofd - old); 920c80476e4SDavid E. O'Brien /* 921c80476e4SDavid E. O'Brien * Check if we have stuff to save 922c80476e4SDavid E. O'Brien */ 923c80476e4SDavid E. O'Brien if (osb != oe) { 924c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9259ccc37e3SMark Peek reprintf("with stuff to save at end\r\n"); 926c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 927c80476e4SDavid E. O'Brien /* 928c80476e4SDavid E. O'Brien * fx is less than zero *always* here but we check for code 929c80476e4SDavid E. O'Brien * symmetry 930c80476e4SDavid E. O'Brien */ 931c80476e4SDavid E. O'Brien if (fx < 0) { 932c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 933c80476e4SDavid E. O'Brien if (!T_CanDel) 9349ccc37e3SMark Peek reprintf(" ERROR: cannot delete in first diff\n"); 935c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 936c80476e4SDavid E. O'Brien DeleteChars(-fx); 937c80476e4SDavid E. O'Brien str_delete(old, (int) (ofd - old), TermH, -fx); 938c80476e4SDavid E. O'Brien } 939c80476e4SDavid E. O'Brien /* 940c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd 941c80476e4SDavid E. O'Brien */ 942c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 943c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 944c80476e4SDavid E. O'Brien 945c80476e4SDavid E. O'Brien } 946c80476e4SDavid E. O'Brien else { 947c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9489ccc37e3SMark Peek reprintf("but with nothing left to save\r\n"); 949c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 950c80476e4SDavid E. O'Brien /* 951c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd 952c80476e4SDavid E. O'Brien */ 953c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 954c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 9559ccc37e3SMark Peek reprintf("cleareol %d\n", (oe - old) - (ne - new)); 956c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 9573b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE 958c80476e4SDavid E. O'Brien ClearEOL((oe - old) - (ne - new)); 959c80476e4SDavid E. O'Brien #else 960c80476e4SDavid E. O'Brien /* 961c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT 962c80476e4SDavid E. O'Brien */ 963c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH); 9643b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/ 965c80476e4SDavid E. O'Brien /* 966c80476e4SDavid E. O'Brien * Done 967c80476e4SDavid E. O'Brien */ 968c80476e4SDavid E. O'Brien return; 969c80476e4SDavid E. O'Brien } 970c80476e4SDavid E. O'Brien } 971c80476e4SDavid E. O'Brien else 972c80476e4SDavid E. O'Brien fx = 0; 973c80476e4SDavid E. O'Brien 974c80476e4SDavid E. O'Brien if (sx < 0) { 975c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9769ccc37e3SMark Peek reprintf("second diff delete at %d...\r\n", (ose - old) + fx); 977c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 978c80476e4SDavid E. O'Brien /* 979c80476e4SDavid E. O'Brien * Check if we have stuff to delete 980c80476e4SDavid E. O'Brien */ 981c80476e4SDavid E. O'Brien /* 982c80476e4SDavid E. O'Brien * fx is the number of characters inserted (+) or deleted (-) 983c80476e4SDavid E. O'Brien */ 984c80476e4SDavid E. O'Brien 985c80476e4SDavid E. O'Brien MoveToChar((ose - old) + fx); 986c80476e4SDavid E. O'Brien /* 987c80476e4SDavid E. O'Brien * Check if we have stuff to save 988c80476e4SDavid E. O'Brien */ 989c80476e4SDavid E. O'Brien if (ols != oe) { 990c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 9919ccc37e3SMark Peek reprintf("with stuff to save at end\r\n"); 992c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 993c80476e4SDavid E. O'Brien /* 994c80476e4SDavid E. O'Brien * Again a duplicate test. 995c80476e4SDavid E. O'Brien */ 996c80476e4SDavid E. O'Brien if (sx < 0) { 997c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 998c80476e4SDavid E. O'Brien if (!T_CanDel) 9999ccc37e3SMark Peek reprintf(" ERROR: cannot delete in second diff\n"); 1000c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1001c80476e4SDavid E. O'Brien DeleteChars(-sx); 1002c80476e4SDavid E. O'Brien } 1003c80476e4SDavid E. O'Brien 1004c80476e4SDavid E. O'Brien /* 1005c80476e4SDavid E. O'Brien * write (nls-nse) chars of new starting at nse 1006c80476e4SDavid E. O'Brien */ 1007c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 1008c80476e4SDavid E. O'Brien } 1009c80476e4SDavid E. O'Brien else { 1010c80476e4SDavid E. O'Brien int olen = (int) (oe - old + fx); 1011c80476e4SDavid E. O'Brien if (olen > TermH) 1012c80476e4SDavid E. O'Brien olen = TermH; 1013c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10149ccc37e3SMark Peek reprintf("but with nothing left to save\r\n"); 1015c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1016c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 1017c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 10189ccc37e3SMark Peek reprintf("cleareol %d\n", olen - (ne - new)); 1019c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 10203b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE 1021c80476e4SDavid E. O'Brien ClearEOL(olen - (ne - new)); 1022c80476e4SDavid E. O'Brien #else 1023c80476e4SDavid E. O'Brien /* 1024c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT 1025c80476e4SDavid E. O'Brien */ 1026c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH); 10273b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/ 1028c80476e4SDavid E. O'Brien } 1029c80476e4SDavid E. O'Brien } 1030c80476e4SDavid E. O'Brien 1031c80476e4SDavid E. O'Brien /* 1032c80476e4SDavid E. O'Brien * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... 1033c80476e4SDavid E. O'Brien */ 1034c80476e4SDavid E. O'Brien if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { 1035c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10369ccc37e3SMark Peek reprintf("late first diff insert at %d...\r\n", nfd - new); 1037c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1038c80476e4SDavid E. O'Brien 1039c80476e4SDavid E. O'Brien MoveToChar(nfd - new); 1040c80476e4SDavid E. O'Brien /* 1041c80476e4SDavid E. O'Brien * Check if we have stuff to keep at the end 1042c80476e4SDavid E. O'Brien */ 1043c80476e4SDavid E. O'Brien if (nsb != ne) { 1044c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10459ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n"); 1046c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1047c80476e4SDavid E. O'Brien /* 1048c80476e4SDavid E. O'Brien * We have to recalculate fx here because we set it 1049c80476e4SDavid E. O'Brien * to zero above as a flag saying that we hadn't done 1050c80476e4SDavid E. O'Brien * an early first insert. 1051c80476e4SDavid E. O'Brien */ 1052c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 1053c80476e4SDavid E. O'Brien if (fx > 0) { 1054c80476e4SDavid E. O'Brien /* 1055c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd 1056c80476e4SDavid E. O'Brien */ 1057c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1058c80476e4SDavid E. O'Brien if (!T_CanIns) 10599ccc37e3SMark Peek reprintf(" ERROR: cannot insert in late first diff\n"); 1060c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1061c80476e4SDavid E. O'Brien Insert_write(nfd, fx); 1062c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx); 1063c80476e4SDavid E. O'Brien } 1064c80476e4SDavid E. O'Brien 1065c80476e4SDavid E. O'Brien /* 1066c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx) 1067c80476e4SDavid E. O'Brien */ 1068c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx); 1069c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx)); 1070c80476e4SDavid E. O'Brien } 1071c80476e4SDavid E. O'Brien else { 1072c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10739ccc37e3SMark Peek reprintf("without anything to save\r\n"); 1074c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1075c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 1076c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 1077c80476e4SDavid E. O'Brien } 1078c80476e4SDavid E. O'Brien } 1079c80476e4SDavid E. O'Brien 1080c80476e4SDavid E. O'Brien /* 1081c80476e4SDavid E. O'Brien * line is now NEW up to nse 1082c80476e4SDavid E. O'Brien */ 1083c80476e4SDavid E. O'Brien if (sx >= 0) { 1084c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10859ccc37e3SMark Peek reprintf("second diff insert at %d...\r\n", nse - new); 1086c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1087c80476e4SDavid E. O'Brien MoveToChar(nse - new); 1088c80476e4SDavid E. O'Brien if (ols != oe) { 1089c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 10909ccc37e3SMark Peek reprintf("with stuff to keep at end\r\n"); 1091c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1092c80476e4SDavid E. O'Brien if (sx > 0) { 1093c80476e4SDavid E. O'Brien /* insert sx chars of new starting at nse */ 1094c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1095c80476e4SDavid E. O'Brien if (!T_CanIns) 10969ccc37e3SMark Peek reprintf(" ERROR: cannot insert in second diff\n"); 1097c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1098c80476e4SDavid E. O'Brien Insert_write(nse, sx); 1099c80476e4SDavid E. O'Brien } 1100c80476e4SDavid E. O'Brien 1101c80476e4SDavid E. O'Brien /* 1102c80476e4SDavid E. O'Brien * write (nls-nse) - sx chars of new starting at (nse + sx) 1103c80476e4SDavid E. O'Brien */ 1104c80476e4SDavid E. O'Brien so_write(nse + sx, (nls - nse) - sx); 1105c80476e4SDavid E. O'Brien } 1106c80476e4SDavid E. O'Brien else { 1107c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 11089ccc37e3SMark Peek reprintf("without anything to save\r\n"); 1109c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1110c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 1111c80476e4SDavid E. O'Brien 1112c80476e4SDavid E. O'Brien /* 1113c80476e4SDavid E. O'Brien * No need to do a clear-to-end here because we were doing 1114c80476e4SDavid E. O'Brien * a second insert, so we will have over written all of the 1115c80476e4SDavid E. O'Brien * old string. 1116c80476e4SDavid E. O'Brien */ 1117c80476e4SDavid E. O'Brien } 1118c80476e4SDavid E. O'Brien } 1119c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 11209ccc37e3SMark Peek reprintf("done.\r\n"); 1121c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1122c80476e4SDavid E. O'Brien } 1123c80476e4SDavid E. O'Brien 1124c80476e4SDavid E. O'Brien 1125c80476e4SDavid E. O'Brien static void 112645e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width) 1127c80476e4SDavid E. O'Brien { 112823338178SMark Peek int i; 1129c80476e4SDavid E. O'Brien 1130c80476e4SDavid E. O'Brien for (i = 0; i < width; i++) { 1131c80476e4SDavid E. O'Brien if (*src == (Char) 0) 1132c80476e4SDavid E. O'Brien break; 1133c80476e4SDavid E. O'Brien *dst++ = *src++; 1134c80476e4SDavid E. O'Brien } 1135c80476e4SDavid E. O'Brien 1136c80476e4SDavid E. O'Brien while (i < width) { 1137c80476e4SDavid E. O'Brien *dst++ = ' '; 1138c80476e4SDavid E. O'Brien i++; 1139c80476e4SDavid E. O'Brien } 1140c80476e4SDavid E. O'Brien *dst = (Char) 0; 1141c80476e4SDavid E. O'Brien } 1142c80476e4SDavid E. O'Brien 1143c80476e4SDavid E. O'Brien void 114445e5710bSMark Peek RefCursor(void) 1145c80476e4SDavid E. O'Brien { /* only move to new cursor pos */ 114623338178SMark Peek Char *cp; 114745e5710bSMark Peek int w, h, th, v; 1148c80476e4SDavid E. O'Brien 1149c80476e4SDavid E. O'Brien /* first we must find where the cursor is... */ 1150c80476e4SDavid E. O'Brien h = 0; 1151c80476e4SDavid E. O'Brien v = 0; 1152c80476e4SDavid E. O'Brien th = TermH; /* optimize for speed */ 1153c80476e4SDavid E. O'Brien 115445e5710bSMark Peek for (cp = Prompt; cp != NULL && *cp; ) { /* do prompt */ 115523338178SMark Peek if (*cp & LITERAL) { 115623338178SMark Peek cp++; 1157c80476e4SDavid E. O'Brien continue; 115823338178SMark Peek } 1159*19d2e3deSDmitry Chagin w = NLSClassify(*cp & CHAR, cp == Prompt, 0); 116045e5710bSMark Peek cp++; 116123338178SMark Peek switch(w) { 116223338178SMark Peek case NLSCLASS_NL: 1163c80476e4SDavid E. O'Brien h = 0; 1164c80476e4SDavid E. O'Brien v++; 116523338178SMark Peek break; 116623338178SMark Peek case NLSCLASS_TAB: 116723338178SMark Peek while (++h & 07) 116823338178SMark Peek ; 116923338178SMark Peek break; 117023338178SMark Peek case NLSCLASS_CTRL: 117123338178SMark Peek h += 2; 117223338178SMark Peek break; 117323338178SMark Peek case NLSCLASS_ILLEGAL: 117423338178SMark Peek h += 4; 117523338178SMark Peek break; 117623338178SMark Peek case NLSCLASS_ILLEGAL2: 117723338178SMark Peek case NLSCLASS_ILLEGAL3: 117823338178SMark Peek case NLSCLASS_ILLEGAL4: 117923338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w); 118023338178SMark Peek break; 118123338178SMark Peek default: 118223338178SMark Peek h += w; 1183c80476e4SDavid E. O'Brien } 1184c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */ 118523338178SMark Peek h -= th; 118623338178SMark Peek v++; 118723338178SMark Peek } 118823338178SMark Peek } 118923338178SMark Peek 119023338178SMark Peek for (cp = InputBuf; cp < Cursor;) { /* do input buffer to Cursor */ 1191*19d2e3deSDmitry Chagin w = NLSClassify(*cp & CHAR, cp == InputBuf, 0); 119245e5710bSMark Peek cp++; 119323338178SMark Peek switch(w) { 119423338178SMark Peek case NLSCLASS_NL: 1195c80476e4SDavid E. O'Brien h = 0; 1196c80476e4SDavid E. O'Brien v++; 119723338178SMark Peek break; 119823338178SMark Peek case NLSCLASS_TAB: 119923338178SMark Peek while (++h & 07) 120023338178SMark Peek ; 120123338178SMark Peek break; 120223338178SMark Peek case NLSCLASS_CTRL: 120323338178SMark Peek h += 2; 120423338178SMark Peek break; 120523338178SMark Peek case NLSCLASS_ILLEGAL: 120623338178SMark Peek h += 4; 120723338178SMark Peek break; 120823338178SMark Peek case NLSCLASS_ILLEGAL2: 120923338178SMark Peek case NLSCLASS_ILLEGAL3: 121023338178SMark Peek case NLSCLASS_ILLEGAL4: 121123338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w); 121223338178SMark Peek break; 121323338178SMark Peek default: 121423338178SMark Peek h += w; 1215c80476e4SDavid E. O'Brien } 1216c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */ 121723338178SMark Peek h -= th; 1218c80476e4SDavid E. O'Brien v++; 1219c80476e4SDavid E. O'Brien } 1220c80476e4SDavid E. O'Brien } 1221c80476e4SDavid E. O'Brien 1222c80476e4SDavid E. O'Brien /* now go there */ 1223c80476e4SDavid E. O'Brien MoveToLine(v); 1224c80476e4SDavid E. O'Brien MoveToChar(h); 122545e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) { 122645e5710bSMark Peek ClearLines(); 122745e5710bSMark Peek ClearDisp(); 122845e5710bSMark Peek Refresh(); 122945e5710bSMark Peek } 1230c80476e4SDavid E. O'Brien flush(); 1231c80476e4SDavid E. O'Brien } 1232c80476e4SDavid E. O'Brien 1233b2d5d167SMark Peek #ifndef WINTT_NATIVE 1234c80476e4SDavid E. O'Brien static void 123545e5710bSMark Peek PutPlusOne(Char c, int width) 1236c80476e4SDavid E. O'Brien { 123723338178SMark Peek while (width > 1 && CursorH + width > TermH) 123823338178SMark Peek PutPlusOne(' ', 1); 123923338178SMark Peek if ((c & LITERAL) != 0) { 124023338178SMark Peek Char *d; 124123338178SMark Peek for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++) 124223338178SMark Peek (void) putwraw(*d); 124323338178SMark Peek } else { 124423338178SMark Peek (void) putwraw(c); 124523338178SMark Peek } 1246c80476e4SDavid E. O'Brien Display[CursorV][CursorH++] = (Char) c; 124723338178SMark Peek while (--width > 0) 124823338178SMark Peek Display[CursorV][CursorH++] = CHAR_DBWIDTH; 1249c80476e4SDavid E. O'Brien if (CursorH >= TermH) { /* if we must overflow */ 1250c80476e4SDavid E. O'Brien CursorH = 0; 1251c80476e4SDavid E. O'Brien CursorV++; 1252c80476e4SDavid E. O'Brien OldvcV++; 1253c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_AUTO) { 1254c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_MAGIC) { 1255c80476e4SDavid E. O'Brien (void) putraw(' '); 1256c80476e4SDavid E. O'Brien (void) putraw('\b'); 1257c80476e4SDavid E. O'Brien } 1258c80476e4SDavid E. O'Brien } 1259c80476e4SDavid E. O'Brien else { 1260c80476e4SDavid E. O'Brien (void) putraw('\r'); 1261c80476e4SDavid E. O'Brien (void) putraw('\n'); 1262c80476e4SDavid E. O'Brien } 1263c80476e4SDavid E. O'Brien } 1264c80476e4SDavid E. O'Brien } 1265b2d5d167SMark Peek #endif 1266c80476e4SDavid E. O'Brien 1267c80476e4SDavid E. O'Brien void 126823338178SMark Peek RefPlusOne(int l) 1269c80476e4SDavid E. O'Brien { /* we added just one char, handle it fast. 1270c80476e4SDavid E. O'Brien * assumes that screen cursor == real cursor */ 127145e5710bSMark Peek Char *cp, c; 127223338178SMark Peek int w; 1273c80476e4SDavid E. O'Brien 127423338178SMark Peek if (Cursor != LastChar) { 1275c80476e4SDavid E. O'Brien Refresh(); /* too hard to handle */ 1276c80476e4SDavid E. O'Brien return; 1277c80476e4SDavid E. O'Brien } 1278c80476e4SDavid E. O'Brien if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) { 1279c80476e4SDavid E. O'Brien Refresh(); /* clear out rprompt if less than one char gap*/ 1280c80476e4SDavid E. O'Brien return; 128123338178SMark Peek } 128223338178SMark Peek cp = Cursor - l; 128345e5710bSMark Peek c = *cp & CHAR; 1284*19d2e3deSDmitry Chagin w = NLSClassify(c, cp == InputBuf, 0); 128523338178SMark Peek switch(w) { 128623338178SMark Peek case NLSCLASS_CTRL: 128723338178SMark Peek PutPlusOne('^', 1); 128823338178SMark Peek if (c == CTL_ESC('\177')) { 128923338178SMark Peek PutPlusOne('?', 1); 129023338178SMark Peek break; 129123338178SMark Peek } 12923b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 129323338178SMark Peek /* uncontrolify it; works only for iso8859-1 like sets */ 129423338178SMark Peek PutPlusOne((c | 0100), 1); 12953b6eaa7bSAndrey A. Chernov #else 129623338178SMark Peek PutPlusOne(_toebcdic[_toascii[c]|0100], 1); 129723338178SMark Peek #endif 129823338178SMark Peek break; 129923338178SMark Peek case NLSCLASS_ILLEGAL: 130023338178SMark Peek PutPlusOne('\\', 1); 130123338178SMark Peek PutPlusOne(((c >> 6) & 7) + '0', 1); 130223338178SMark Peek PutPlusOne(((c >> 3) & 7) + '0', 1); 130323338178SMark Peek PutPlusOne((c & 7) + '0', 1); 130423338178SMark Peek break; 130523338178SMark Peek case 1: 130645e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) 130745e5710bSMark Peek StartHighlight(); 130823338178SMark Peek if (l > 1) 130923338178SMark Peek PutPlusOne(MakeLiteral(cp, l, 0), 1); 1310c80476e4SDavid E. O'Brien else 131123338178SMark Peek PutPlusOne(*cp, 1); 131245e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) 131345e5710bSMark Peek StopHighlight(); 131423338178SMark Peek break; 131523338178SMark Peek default: 131623338178SMark Peek Refresh(); /* too hard to handle */ 131723338178SMark Peek return; 1318c80476e4SDavid E. O'Brien } 1319c80476e4SDavid E. O'Brien flush(); 1320c80476e4SDavid E. O'Brien } 1321c80476e4SDavid E. O'Brien 1322c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */ 1323c80476e4SDavid E. O'Brien 1324c80476e4SDavid E. O'Brien void 132545e5710bSMark Peek ClearDisp(void) 1326c80476e4SDavid E. O'Brien { 132723338178SMark Peek int i; 1328c80476e4SDavid E. O'Brien 1329c80476e4SDavid E. O'Brien CursorV = 0; /* clear the display buffer */ 1330c80476e4SDavid E. O'Brien CursorH = 0; 1331c80476e4SDavid E. O'Brien for (i = 0; i < TermV; i++) 1332*19d2e3deSDmitry Chagin (void) memset(Display[i], 0, (TermH + 1) * sizeof(Display[0][0])); 1333c80476e4SDavid E. O'Brien OldvcV = 0; 133423338178SMark Peek litlen = 0; 1335c80476e4SDavid E. O'Brien } 1336c80476e4SDavid E. O'Brien 1337c80476e4SDavid E. O'Brien void 133845e5710bSMark Peek ClearLines(void) 1339c80476e4SDavid E. O'Brien { /* Make sure all lines are *really* blank */ 134023338178SMark Peek int i; 1341c80476e4SDavid E. O'Brien 1342c80476e4SDavid E. O'Brien if (T_CanCEOL) { 1343c80476e4SDavid E. O'Brien /* 1344c80476e4SDavid E. O'Brien * Clear the lines from the bottom up so that if we try moving 1345c80476e4SDavid E. O'Brien * the cursor down by writing the character that is at the end 1346c80476e4SDavid E. O'Brien * of the screen line, we won't rewrite a character that shouldn't 1347c80476e4SDavid E. O'Brien * be there. 1348c80476e4SDavid E. O'Brien */ 1349c80476e4SDavid E. O'Brien for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */ 1350c80476e4SDavid E. O'Brien MoveToLine(i); 1351c80476e4SDavid E. O'Brien MoveToChar(0); 1352c80476e4SDavid E. O'Brien ClearEOL(TermH); 1353c80476e4SDavid E. O'Brien } 1354c80476e4SDavid E. O'Brien } 1355c80476e4SDavid E. O'Brien else { 1356c80476e4SDavid E. O'Brien MoveToLine(OldvcV); /* go to last line */ 1357c80476e4SDavid E. O'Brien (void) putraw('\r'); /* go to BOL */ 1358c80476e4SDavid E. O'Brien (void) putraw('\n'); /* go to new line */ 1359c80476e4SDavid E. O'Brien } 1360c80476e4SDavid E. O'Brien } 1361