145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/ed.refresh.c,v 3.46 2006/08/23 15:03:14 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 3545e5710bSMark Peek RCSID("$tcsh: ed.refresh.c,v 3.46 2006/08/23 15:03:14 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); 4945e5710bSMark Peek static int Draw (Char *, 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) 6445e5710bSMark Peek static void dprintf (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 { 71c80476e4SDavid E. O'Brien dprintf("%s:\"", str); 7223338178SMark Peek while (f < t) { 7345e5710bSMark Peek if (ASC(*f) & ~ASCII) 7423338178SMark Peek dprintf("[%x]", *f++); 7523338178SMark Peek else 7645e5710bSMark Peek dprintf("%c", CTL_ESC(ASCII & ASC(*f++))); 7723338178SMark Peek } 78c80476e4SDavid E. O'Brien dprintf("\"\r\n"); 79c80476e4SDavid E. O'Brien } 80c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 81c80476e4SDavid E. O'Brien 82c80476e4SDavid E. O'Brien /* dprintf(): 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 88c80476e4SDavid E. O'Brien dprintf(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 16223338178SMark Peek static int 16345e5710bSMark Peek Draw(Char *cp, int nocomb) /* draw char at cp, expand tabs, ctl chars */ 16423338178SMark Peek { 16545e5710bSMark Peek int w, i, lv, lh; 16645e5710bSMark Peek Char c, attr; 16723338178SMark Peek 16823338178SMark Peek attr = *cp & ~CHAR; 16945e5710bSMark Peek c = *cp & CHAR; 17023338178SMark Peek w = NLSClassify(c, nocomb); 17123338178SMark Peek switch (w) { 17223338178SMark Peek case NLSCLASS_NL: 17323338178SMark Peek Vdraw('\0', 0); /* assure end of line */ 174c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset cursor pos */ 175c80476e4SDavid E. O'Brien vcursor_v++; 17623338178SMark Peek break; 17723338178SMark Peek case NLSCLASS_TAB: 17823338178SMark Peek do { 17923338178SMark Peek Vdraw(' ', 1); 18023338178SMark Peek } while ((vcursor_h & 07) != 0); 18123338178SMark Peek break; 18223338178SMark Peek case NLSCLASS_CTRL: 18323338178SMark Peek Vdraw('^' | attr, 1); 18423338178SMark Peek if (c == CTL_ESC('\177')) { 18523338178SMark Peek Vdraw('?' | attr, 1); 18623338178SMark Peek } else { 1873b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 188c80476e4SDavid E. O'Brien /* uncontrolify it; works only for iso8859-1 like sets */ 18923338178SMark Peek Vdraw(c | 0100 | attr, 1); 1903b6eaa7bSAndrey A. Chernov #else 19123338178SMark Peek Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1); 19223338178SMark Peek #endif 193c80476e4SDavid E. O'Brien } 19423338178SMark Peek break; 19523338178SMark Peek case NLSCLASS_ILLEGAL: 19623338178SMark Peek Vdraw('\\' | attr, 1); 19745e5710bSMark Peek Vdraw((((c >> 6) & 7) + '0') | attr, 1); 19845e5710bSMark Peek Vdraw((((c >> 3) & 7) + '0') | attr, 1); 19945e5710bSMark Peek Vdraw(((c & 7) + '0') | attr, 1); 20023338178SMark Peek break; 20123338178SMark Peek case NLSCLASS_ILLEGAL2: 20223338178SMark Peek case NLSCLASS_ILLEGAL3: 20323338178SMark Peek case NLSCLASS_ILLEGAL4: 20423338178SMark Peek Vdraw('\\' | attr, 1); 20523338178SMark Peek Vdraw('U' | attr, 1); 20623338178SMark Peek Vdraw('+' | attr, 1); 20723338178SMark Peek for (i = 8 * NLSCLASS_ILLEGAL_SIZE(w) - 4; i >= 0; i -= 4) 20823338178SMark Peek Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1); 20923338178SMark Peek break; 21023338178SMark Peek case 0: 21123338178SMark Peek lv = vcursor_v; 21223338178SMark Peek lh = vcursor_h; 21323338178SMark Peek for (;;) { 21423338178SMark Peek lh--; 21523338178SMark Peek if (lh < 0) { 21623338178SMark Peek lv--; 21723338178SMark Peek if (lv < 0) 21823338178SMark Peek break; 21923338178SMark Peek lh = Strlen(Vdisplay[lv]) - 1; 220c80476e4SDavid E. O'Brien } 22123338178SMark Peek if (Vdisplay[lv][lh] != CHAR_DBWIDTH) 22223338178SMark Peek break; 22323338178SMark Peek } 22423338178SMark Peek if (lv < 0) { 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); 22945e5710bSMark Peek break; 23023338178SMark Peek } 23145e5710bSMark Peek Vdisplay[lv][lh] = MakeLiteral(cp, 1, Vdisplay[lv][lh]); 23223338178SMark Peek break; 23323338178SMark Peek default: 23423338178SMark Peek Vdraw(*cp, w); 23523338178SMark Peek break; 236c80476e4SDavid E. O'Brien } 23745e5710bSMark Peek return 1; 238c80476e4SDavid E. O'Brien } 239c80476e4SDavid E. O'Brien 240c80476e4SDavid E. O'Brien static void 24145e5710bSMark Peek Vdraw(Char c, int width) /* draw char c onto V lines */ 242c80476e4SDavid E. O'Brien { 243c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 244c80476e4SDavid E. O'Brien # ifdef SHORT_STRINGS 24523338178SMark Peek dprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width); 246c80476e4SDavid E. O'Brien # else 24723338178SMark Peek dprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width); 248c80476e4SDavid E. O'Brien # endif /* SHORT_STRNGS */ 249c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 250c80476e4SDavid E. O'Brien 25123338178SMark Peek /* Hopefully this is what all the terminals do with multi-column characters 25223338178SMark Peek that "span line breaks". */ 25323338178SMark Peek while (vcursor_h + width > TermH) 25423338178SMark Peek Vdraw(' ', 1); 25545e5710bSMark Peek Vdisplay[vcursor_v][vcursor_h] = c; 25623338178SMark Peek if (width) 257c80476e4SDavid E. O'Brien vcursor_h++; /* advance to next place */ 25823338178SMark Peek while (--width > 0) 25923338178SMark Peek Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH; 260c80476e4SDavid E. O'Brien if (vcursor_h >= TermH) { 261c80476e4SDavid E. O'Brien Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */ 262c80476e4SDavid E. O'Brien vcursor_h = 0; /* reset it. */ 263c80476e4SDavid E. O'Brien vcursor_v++; 264c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 265c80476e4SDavid E. O'Brien if (vcursor_v >= TermV) { /* should NEVER happen. */ 266c80476e4SDavid E. O'Brien dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n", 267c80476e4SDavid E. O'Brien vcursor_v, TermV); 268c80476e4SDavid E. O'Brien abort(); 269c80476e4SDavid E. O'Brien } 270c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 271c80476e4SDavid E. O'Brien } 272c80476e4SDavid E. O'Brien } 273c80476e4SDavid E. O'Brien 274c80476e4SDavid E. O'Brien /* 275c80476e4SDavid E. O'Brien * RefreshPromptpart() 276c80476e4SDavid E. O'Brien * draws a prompt element, expanding literals (we know it's ASCIZ) 277c80476e4SDavid E. O'Brien */ 278c80476e4SDavid E. O'Brien static void 27945e5710bSMark Peek RefreshPromptpart(Char *buf) 280c80476e4SDavid E. O'Brien { 28123338178SMark Peek Char *cp; 28245e5710bSMark Peek int w; 283c80476e4SDavid E. O'Brien 28445e5710bSMark Peek if (buf == NULL) 28545e5710bSMark Peek return; 28623338178SMark Peek for (cp = buf; *cp; ) { 287c80476e4SDavid E. O'Brien if (*cp & LITERAL) { 28823338178SMark Peek Char *litstart = cp; 289c80476e4SDavid E. O'Brien while (*cp & LITERAL) 290c80476e4SDavid E. O'Brien cp++; 29123338178SMark Peek if (*cp) { 29245e5710bSMark Peek w = NLSWidth(*cp & CHAR); 29345e5710bSMark Peek Vdraw(MakeLiteral(litstart, cp + 1 - litstart, 0), w); 29445e5710bSMark Peek cp++; 29523338178SMark Peek } 296c80476e4SDavid E. O'Brien else { 297c80476e4SDavid E. O'Brien /* 298c80476e4SDavid E. O'Brien * XXX: This is a bug, we lose the last literal, if it is not 299c80476e4SDavid E. O'Brien * followed by a normal character, but it is too hard to fix 300c80476e4SDavid E. O'Brien */ 301c80476e4SDavid E. O'Brien break; 302c80476e4SDavid E. O'Brien } 303c80476e4SDavid E. O'Brien } 304c80476e4SDavid E. O'Brien else 30523338178SMark Peek cp += Draw(cp, cp == buf); 306c80476e4SDavid E. O'Brien } 307c80476e4SDavid E. O'Brien } 308c80476e4SDavid E. O'Brien 309c80476e4SDavid E. O'Brien /* 310c80476e4SDavid E. O'Brien * Refresh() 311c80476e4SDavid E. O'Brien * draws the new virtual screen image from the current input 312c80476e4SDavid E. O'Brien * line, then goes line-by-line changing the real image to the new 313c80476e4SDavid E. O'Brien * virtual image. The routine to re-draw a line can be replaced 314c80476e4SDavid E. O'Brien * easily in hopes of a smarter one being placed there. 315c80476e4SDavid E. O'Brien */ 316b2d5d167SMark Peek #ifndef WINNT_NATIVE 317b2d5d167SMark Peek static 318b2d5d167SMark Peek #endif 319b2d5d167SMark Peek int OldvcV = 0; 320b2d5d167SMark Peek 321c80476e4SDavid E. O'Brien void 32245e5710bSMark Peek Refresh(void) 323c80476e4SDavid E. O'Brien { 32423338178SMark Peek int cur_line; 32523338178SMark Peek Char *cp; 326c80476e4SDavid E. O'Brien int cur_h, cur_v = 0, new_vcv; 327c80476e4SDavid E. O'Brien int rhdiff; 328c80476e4SDavid E. O'Brien Char oldgetting; 329c80476e4SDavid E. O'Brien 330c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 33145e5710bSMark Peek dprintf("Prompt = :%s:\r\n", short2str(Prompt)); 332c80476e4SDavid E. O'Brien dprintf("InputBuf = :%s:\r\n", short2str(InputBuf)); 333c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 334c80476e4SDavid E. O'Brien oldgetting = GettingInput; 335c80476e4SDavid E. O'Brien GettingInput = 0; /* avoid re-entrance via SIGWINCH */ 336c80476e4SDavid E. O'Brien 337c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */ 338c80476e4SDavid E. O'Brien vcursor_h = 0; 339c80476e4SDavid E. O'Brien vcursor_v = 0; 34045e5710bSMark Peek RefreshPromptpart(RPrompt); 341c80476e4SDavid E. O'Brien rprompt_h = vcursor_h; 342c80476e4SDavid E. O'Brien rprompt_v = vcursor_v; 343c80476e4SDavid E. O'Brien 344c80476e4SDavid E. O'Brien /* reset the Vdraw cursor, draw prompt */ 345c80476e4SDavid E. O'Brien vcursor_h = 0; 346c80476e4SDavid E. O'Brien vcursor_v = 0; 34745e5710bSMark Peek RefreshPromptpart(Prompt); 348c80476e4SDavid E. O'Brien cur_h = -1; /* set flag in case I'm not set */ 349c80476e4SDavid E. O'Brien 350c80476e4SDavid E. O'Brien /* draw the current input buffer */ 35123338178SMark Peek for (cp = InputBuf; (cp < LastChar); ) { 35223338178SMark Peek if (cp >= Cursor && cur_h == -1) { 353c80476e4SDavid E. O'Brien cur_h = vcursor_h; /* save for later */ 354c80476e4SDavid E. O'Brien cur_v = vcursor_v; 35523338178SMark Peek Cursor = cp; 356c80476e4SDavid E. O'Brien } 35723338178SMark Peek cp += Draw(cp, cp == InputBuf); 358c80476e4SDavid E. O'Brien } 359c80476e4SDavid E. O'Brien 360c80476e4SDavid E. O'Brien if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */ 361c80476e4SDavid E. O'Brien cur_h = vcursor_h; 362c80476e4SDavid E. O'Brien cur_v = vcursor_v; 363c80476e4SDavid E. O'Brien } 364c80476e4SDavid E. O'Brien 365c80476e4SDavid E. O'Brien rhdiff = TermH - vcursor_h - rprompt_h; 366c80476e4SDavid E. O'Brien if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) { 367c80476e4SDavid E. O'Brien /* 368c80476e4SDavid E. O'Brien * have a right-hand side prompt that will fit on 369c80476e4SDavid E. O'Brien * the end of the first line with at least one 370c80476e4SDavid E. O'Brien * character gap to the input buffer. 371c80476e4SDavid E. O'Brien */ 372c80476e4SDavid E. O'Brien while (--rhdiff > 0) /* pad out with spaces */ 37323338178SMark Peek Vdraw(' ', 1); 37445e5710bSMark Peek RefreshPromptpart(RPrompt); 375c80476e4SDavid E. O'Brien } 376c80476e4SDavid E. O'Brien else { 377c80476e4SDavid E. O'Brien rprompt_h = 0; /* flag "not using rprompt" */ 378c80476e4SDavid E. O'Brien rprompt_v = 0; 379c80476e4SDavid E. O'Brien } 380c80476e4SDavid E. O'Brien 381c80476e4SDavid E. O'Brien new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */ 38223338178SMark Peek Vdraw('\0', 1); /* put NUL on end */ 383c80476e4SDavid E. O'Brien 38423338178SMark Peek #if defined (DEBUG_REFRESH) 385c80476e4SDavid E. O'Brien dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n", 386c80476e4SDavid E. O'Brien TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0])); 387c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 388c80476e4SDavid E. O'Brien 389c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 390c80476e4SDavid E. O'Brien dprintf("updating %d lines.\r\n", new_vcv); 391c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 392c80476e4SDavid E. O'Brien for (cur_line = 0; cur_line <= new_vcv; cur_line++) { 393c80476e4SDavid E. O'Brien /* NOTE THAT update_line MAY CHANGE Display[cur_line] */ 394c80476e4SDavid E. O'Brien update_line(Display[cur_line], Vdisplay[cur_line], cur_line); 3953b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 396c80476e4SDavid E. O'Brien flush(); 3973b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 398c80476e4SDavid E. O'Brien 399c80476e4SDavid E. O'Brien /* 400c80476e4SDavid E. O'Brien * Copy the new line to be the current one, and pad out with spaces 401c80476e4SDavid E. O'Brien * to the full width of the terminal so that if we try moving the 402c80476e4SDavid E. O'Brien * cursor by writing the character that is at the end of the 403c80476e4SDavid E. O'Brien * screen line, it won't be a NUL or some old leftover stuff. 404c80476e4SDavid E. O'Brien */ 405c80476e4SDavid E. O'Brien cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH); 406c80476e4SDavid E. O'Brien } 407c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 408c80476e4SDavid E. O'Brien dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n", 409c80476e4SDavid E. O'Brien vcursor_v, OldvcV, cur_line); 410c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 411c80476e4SDavid E. O'Brien if (OldvcV > new_vcv) { 412c80476e4SDavid E. O'Brien for (; cur_line <= OldvcV; cur_line++) { 413c80476e4SDavid E. O'Brien update_line(Display[cur_line], STRNULL, cur_line); 414c80476e4SDavid E. O'Brien *Display[cur_line] = '\0'; 415c80476e4SDavid E. O'Brien } 416c80476e4SDavid E. O'Brien } 417c80476e4SDavid E. O'Brien OldvcV = new_vcv; /* set for next time */ 418c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 419c80476e4SDavid E. O'Brien dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n", 420c80476e4SDavid E. O'Brien CursorH, CursorV, cur_h, cur_v); 421c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 4223b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 423c80476e4SDavid E. O'Brien flush(); 4243b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 425c80476e4SDavid E. O'Brien MoveToLine(cur_v); /* go to where the cursor is */ 426c80476e4SDavid E. O'Brien MoveToChar(cur_h); 427c80476e4SDavid E. O'Brien SetAttributes(0); /* Clear all attributes */ 428c80476e4SDavid E. O'Brien flush(); /* send the output... */ 429c80476e4SDavid E. O'Brien GettingInput = oldgetting; /* reset to old value */ 430c80476e4SDavid E. O'Brien } 431c80476e4SDavid E. O'Brien 432c80476e4SDavid E. O'Brien #ifdef notdef 43345e5710bSMark Peek GotoBottom(void) 434c80476e4SDavid E. O'Brien { /* used to go to last used screen line */ 435c80476e4SDavid E. O'Brien MoveToLine(OldvcV); 436c80476e4SDavid E. O'Brien } 437c80476e4SDavid E. O'Brien 438c80476e4SDavid E. O'Brien #endif 439c80476e4SDavid E. O'Brien 440c80476e4SDavid E. O'Brien void 44145e5710bSMark Peek PastBottom(void) 442c80476e4SDavid E. O'Brien { /* used to go to last used screen line */ 443c80476e4SDavid E. O'Brien MoveToLine(OldvcV); 444c80476e4SDavid E. O'Brien (void) putraw('\r'); 445c80476e4SDavid E. O'Brien (void) putraw('\n'); 446c80476e4SDavid E. O'Brien ClearDisp(); 447c80476e4SDavid E. O'Brien flush(); 448c80476e4SDavid E. O'Brien } 449c80476e4SDavid E. O'Brien 450c80476e4SDavid E. O'Brien 451c80476e4SDavid E. O'Brien /* insert num characters of s into d (in front of the character) at dat, 452c80476e4SDavid E. O'Brien maximum length of d is dlen */ 453c80476e4SDavid E. O'Brien static void 45445e5710bSMark Peek str_insert(Char *d, int dat, int dlen, Char *s, int num) 455c80476e4SDavid E. O'Brien { 45623338178SMark Peek Char *a, *b; 457c80476e4SDavid E. O'Brien 458c80476e4SDavid E. O'Brien if (num <= 0) 459c80476e4SDavid E. O'Brien return; 460c80476e4SDavid E. O'Brien if (num > dlen - dat) 461c80476e4SDavid E. O'Brien num = dlen - dat; 462c80476e4SDavid E. O'Brien 463c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 464c80476e4SDavid E. O'Brien dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n", 465c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 466c80476e4SDavid E. O'Brien dprintf("s == \"%s\"n", short2str(s)); 467c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien /* open up the space for num chars */ 470c80476e4SDavid E. O'Brien if (num > 0) { 471c80476e4SDavid E. O'Brien b = d + dlen - 1; 472c80476e4SDavid E. O'Brien a = b - num; 473c80476e4SDavid E. O'Brien while (a >= &d[dat]) 474c80476e4SDavid E. O'Brien *b-- = *a--; 475c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */ 476c80476e4SDavid E. O'Brien } 477c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 478c80476e4SDavid E. O'Brien dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n", 479c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 480c80476e4SDavid E. O'Brien dprintf("s == \"%s\"n", short2str(s)); 481c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 482c80476e4SDavid E. O'Brien 483c80476e4SDavid E. O'Brien /* copy the characters */ 484c80476e4SDavid E. O'Brien for (a = d + dat; (a < d + dlen) && (num > 0); num--) 485c80476e4SDavid E. O'Brien *a++ = *s++; 486c80476e4SDavid E. O'Brien 487c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 488c80476e4SDavid E. O'Brien dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n", 489c80476e4SDavid E. O'Brien num, dat, dlen, d, short2str(s)); 490c80476e4SDavid E. O'Brien dprintf("s == \"%s\"n", short2str(s)); 491c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 492c80476e4SDavid E. O'Brien } 493c80476e4SDavid E. O'Brien 494c80476e4SDavid E. O'Brien /* delete num characters d at dat, maximum length of d is dlen */ 495c80476e4SDavid E. O'Brien static void 49645e5710bSMark Peek str_delete(Char *d, int dat, int dlen, int num) 497c80476e4SDavid E. O'Brien { 49823338178SMark Peek Char *a, *b; 499c80476e4SDavid E. O'Brien 500c80476e4SDavid E. O'Brien if (num <= 0) 501c80476e4SDavid E. O'Brien return; 502c80476e4SDavid E. O'Brien if (dat + num >= dlen) { 503c80476e4SDavid E. O'Brien d[dat] = '\0'; 504c80476e4SDavid E. O'Brien return; 505c80476e4SDavid E. O'Brien } 506c80476e4SDavid E. O'Brien 507c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 508c80476e4SDavid E. O'Brien dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n", 509c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 510c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 511c80476e4SDavid E. O'Brien 512c80476e4SDavid E. O'Brien /* open up the space for num chars */ 513c80476e4SDavid E. O'Brien if (num > 0) { 514c80476e4SDavid E. O'Brien b = d + dat; 515c80476e4SDavid E. O'Brien a = b + num; 516c80476e4SDavid E. O'Brien while (a < &d[dlen]) 517c80476e4SDavid E. O'Brien *b++ = *a++; 518c80476e4SDavid E. O'Brien d[dlen] = '\0'; /* just in case */ 519c80476e4SDavid E. O'Brien } 520c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 521c80476e4SDavid E. O'Brien dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n", 522c80476e4SDavid E. O'Brien num, dat, dlen, short2str(d)); 523c80476e4SDavid E. O'Brien #endif /* DEBUG_REFRESH */ 524c80476e4SDavid E. O'Brien } 525c80476e4SDavid E. O'Brien 526c80476e4SDavid E. O'Brien static void 52745e5710bSMark Peek str_cp(Char *a, Char *b, int n) 528c80476e4SDavid E. O'Brien { 529c80476e4SDavid E. O'Brien while (n-- && *b) 530c80476e4SDavid E. O'Brien *a++ = *b++; 531c80476e4SDavid E. O'Brien } 532c80476e4SDavid E. O'Brien 533c80476e4SDavid E. O'Brien 534c80476e4SDavid E. O'Brien /* **************************************************************** 535c80476e4SDavid E. O'Brien update_line() is based on finding the middle difference of each line 536c80476e4SDavid E. O'Brien on the screen; vis: 537c80476e4SDavid E. O'Brien 538c80476e4SDavid E. O'Brien /old first difference 539c80476e4SDavid E. O'Brien /beginning of line | /old last same /old EOL 540c80476e4SDavid E. O'Brien v v v v 541c80476e4SDavid E. O'Brien old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 542c80476e4SDavid E. O'Brien new: eddie> Oh, my little buggy says to me, as lurgid as 543c80476e4SDavid E. O'Brien ^ ^ ^ ^ 544c80476e4SDavid E. O'Brien \beginning of line | \new last same \new end of line 545c80476e4SDavid E. O'Brien \new first difference 546c80476e4SDavid E. O'Brien 547c80476e4SDavid E. O'Brien all are character pointers for the sake of speed. Special cases for 548c80476e4SDavid E. O'Brien no differences, as well as for end of line additions must be handled. 549c80476e4SDavid E. O'Brien **************************************************************** */ 550c80476e4SDavid E. O'Brien 551c80476e4SDavid E. O'Brien /* Minimum at which doing an insert it "worth it". This should be about 552c80476e4SDavid E. O'Brien * half the "cost" of going into insert mode, inserting a character, and 553c80476e4SDavid E. O'Brien * going back out. This should really be calculated from the termcap 554c80476e4SDavid E. O'Brien * data... For the moment, a good number for ANSI terminals. 555c80476e4SDavid E. O'Brien */ 556c80476e4SDavid E. O'Brien #define MIN_END_KEEP 4 557c80476e4SDavid E. O'Brien 558c80476e4SDavid E. O'Brien static void /* could be changed to make it smarter */ 55945e5710bSMark Peek update_line(Char *old, Char *new, int cur_line) 560c80476e4SDavid E. O'Brien { 56123338178SMark Peek Char *o, *n, *p, c; 562c80476e4SDavid E. O'Brien Char *ofd, *ols, *oe, *nfd, *nls, *ne; 563c80476e4SDavid E. O'Brien Char *osb, *ose, *nsb, *nse; 564c80476e4SDavid E. O'Brien int fx, sx; 565c80476e4SDavid E. O'Brien 566c80476e4SDavid E. O'Brien /* 56723338178SMark Peek * find first diff (won't be CHAR_DBWIDTH in either line) 568c80476e4SDavid E. O'Brien */ 569c80476e4SDavid E. O'Brien for (o = old, n = new; *o && (*o == *n); o++, n++) 570c80476e4SDavid E. O'Brien continue; 571c80476e4SDavid E. O'Brien ofd = o; 572c80476e4SDavid E. O'Brien nfd = n; 573c80476e4SDavid E. O'Brien 574c80476e4SDavid E. O'Brien /* 575c80476e4SDavid E. O'Brien * Find the end of both old and new 576c80476e4SDavid E. O'Brien */ 57745e5710bSMark Peek o = Strend(o); 57845e5710bSMark Peek 579c80476e4SDavid E. O'Brien /* 580c80476e4SDavid E. O'Brien * Remove any trailing blanks off of the end, being careful not to 581c80476e4SDavid E. O'Brien * back up past the beginning. 582c80476e4SDavid E. O'Brien */ 58345e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) { 584c80476e4SDavid E. O'Brien while (ofd < o) { 585c80476e4SDavid E. O'Brien if (o[-1] != ' ') 586c80476e4SDavid E. O'Brien break; 587c80476e4SDavid E. O'Brien o--; 588c80476e4SDavid E. O'Brien } 58945e5710bSMark Peek } 590c80476e4SDavid E. O'Brien oe = o; 591c80476e4SDavid E. O'Brien *oe = (Char) 0; 592c80476e4SDavid E. O'Brien 59345e5710bSMark Peek n = Strend(n); 594c80476e4SDavid E. O'Brien 595c80476e4SDavid E. O'Brien /* remove blanks from end of new */ 59645e5710bSMark Peek if (!(adrof(STRhighlight) && MarkIsSet)) { 597c80476e4SDavid E. O'Brien while (nfd < n) { 598c80476e4SDavid E. O'Brien if (n[-1] != ' ') 599c80476e4SDavid E. O'Brien break; 600c80476e4SDavid E. O'Brien n--; 601c80476e4SDavid E. O'Brien } 60245e5710bSMark Peek } 603c80476e4SDavid E. O'Brien ne = n; 604c80476e4SDavid E. O'Brien *ne = (Char) 0; 605c80476e4SDavid E. O'Brien 606c80476e4SDavid E. O'Brien /* 607c80476e4SDavid E. O'Brien * if no diff, continue to next line of redraw 608c80476e4SDavid E. O'Brien */ 609c80476e4SDavid E. O'Brien if (*ofd == '\0' && *nfd == '\0') { 610c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 611c80476e4SDavid E. O'Brien dprintf("no difference.\r\n"); 612c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 613c80476e4SDavid E. O'Brien return; 614c80476e4SDavid E. O'Brien } 615c80476e4SDavid E. O'Brien 616c80476e4SDavid E. O'Brien /* 617c80476e4SDavid E. O'Brien * find last same pointer 618c80476e4SDavid E. O'Brien */ 619c80476e4SDavid E. O'Brien while ((o > ofd) && (n > nfd) && (*--o == *--n)) 620c80476e4SDavid E. O'Brien continue; 62123338178SMark Peek if (*o != *n) { 62223338178SMark Peek o++; 62323338178SMark Peek n++; 62423338178SMark Peek } 62523338178SMark Peek while (*o == CHAR_DBWIDTH) { 62623338178SMark Peek o++; 62723338178SMark Peek n++; 62823338178SMark Peek } 62923338178SMark Peek ols = o; 63023338178SMark Peek nls = n; 631c80476e4SDavid E. O'Brien 632c80476e4SDavid E. O'Brien /* 633c80476e4SDavid E. O'Brien * find same begining and same end 634c80476e4SDavid E. O'Brien */ 635c80476e4SDavid E. O'Brien osb = ols; 636c80476e4SDavid E. O'Brien nsb = nls; 637c80476e4SDavid E. O'Brien ose = ols; 638c80476e4SDavid E. O'Brien nse = nls; 639c80476e4SDavid E. O'Brien 640c80476e4SDavid E. O'Brien /* 641c80476e4SDavid E. O'Brien * case 1: insert: scan from nfd to nls looking for *ofd 642c80476e4SDavid E. O'Brien */ 643c80476e4SDavid E. O'Brien if (*ofd) { 644c80476e4SDavid E. O'Brien for (c = *ofd, n = nfd; n < nls; n++) { 645c80476e4SDavid E. O'Brien if (c == *n) { 646c80476e4SDavid E. O'Brien for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++) 647c80476e4SDavid E. O'Brien continue; 648c80476e4SDavid E. O'Brien /* 649c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we 650c80476e4SDavid E. O'Brien * take it 651c80476e4SDavid E. O'Brien */ 652c80476e4SDavid E. O'Brien if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) { 653c80476e4SDavid E. O'Brien nsb = n; 654c80476e4SDavid E. O'Brien nse = p; 655c80476e4SDavid E. O'Brien osb = ofd; 656c80476e4SDavid E. O'Brien ose = o; 657c80476e4SDavid E. O'Brien } 658c80476e4SDavid E. O'Brien } 659c80476e4SDavid E. O'Brien } 660c80476e4SDavid E. O'Brien } 661c80476e4SDavid E. O'Brien 662c80476e4SDavid E. O'Brien /* 663c80476e4SDavid E. O'Brien * case 2: delete: scan from ofd to ols looking for *nfd 664c80476e4SDavid E. O'Brien */ 665c80476e4SDavid E. O'Brien if (*nfd) { 666c80476e4SDavid E. O'Brien for (c = *nfd, o = ofd; o < ols; o++) { 667c80476e4SDavid E. O'Brien if (c == *o) { 668c80476e4SDavid E. O'Brien for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++) 669c80476e4SDavid E. O'Brien continue; 670c80476e4SDavid E. O'Brien /* 671c80476e4SDavid E. O'Brien * if the new match is longer and it's worth keeping, then we 672c80476e4SDavid E. O'Brien * take it 673c80476e4SDavid E. O'Brien */ 674c80476e4SDavid E. O'Brien if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) { 675c80476e4SDavid E. O'Brien nsb = nfd; 676c80476e4SDavid E. O'Brien nse = n; 677c80476e4SDavid E. O'Brien osb = o; 678c80476e4SDavid E. O'Brien ose = p; 679c80476e4SDavid E. O'Brien } 680c80476e4SDavid E. O'Brien } 681c80476e4SDavid E. O'Brien } 682c80476e4SDavid E. O'Brien } 683c80476e4SDavid E. O'Brien #ifdef notdef 684c80476e4SDavid E. O'Brien /* 685c80476e4SDavid E. O'Brien * If `last same' is before `same end' re-adjust 686c80476e4SDavid E. O'Brien */ 687c80476e4SDavid E. O'Brien if (ols < ose) 688c80476e4SDavid E. O'Brien ols = ose; 689c80476e4SDavid E. O'Brien if (nls < nse) 690c80476e4SDavid E. O'Brien nls = nse; 691c80476e4SDavid E. O'Brien #endif 692c80476e4SDavid E. O'Brien 693c80476e4SDavid E. O'Brien /* 694c80476e4SDavid E. O'Brien * Pragmatics I: If old trailing whitespace or not enough characters to 695c80476e4SDavid E. O'Brien * save to be worth it, then don't save the last same info. 696c80476e4SDavid E. O'Brien */ 697c80476e4SDavid E. O'Brien if ((oe - ols) < MIN_END_KEEP) { 698c80476e4SDavid E. O'Brien ols = oe; 699c80476e4SDavid E. O'Brien nls = ne; 700c80476e4SDavid E. O'Brien } 701c80476e4SDavid E. O'Brien 702c80476e4SDavid E. O'Brien /* 703c80476e4SDavid E. O'Brien * Pragmatics II: if the terminal isn't smart enough, make the data dumber 704c80476e4SDavid E. O'Brien * so the smart update doesn't try anything fancy 705c80476e4SDavid E. O'Brien */ 706c80476e4SDavid E. O'Brien 707c80476e4SDavid E. O'Brien /* 708c80476e4SDavid E. O'Brien * fx is the number of characters we need to insert/delete: in the 709c80476e4SDavid E. O'Brien * beginning to bring the two same begins together 710c80476e4SDavid E. O'Brien */ 711c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 712c80476e4SDavid E. O'Brien /* 713c80476e4SDavid E. O'Brien * sx is the number of characters we need to insert/delete: in the end to 714c80476e4SDavid E. O'Brien * bring the two same last parts together 715c80476e4SDavid E. O'Brien */ 716c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose)); 717c80476e4SDavid E. O'Brien 718c80476e4SDavid E. O'Brien if (!T_CanIns) { 719c80476e4SDavid E. O'Brien if (fx > 0) { 720c80476e4SDavid E. O'Brien osb = ols; 721c80476e4SDavid E. O'Brien ose = ols; 722c80476e4SDavid E. O'Brien nsb = nls; 723c80476e4SDavid E. O'Brien nse = nls; 724c80476e4SDavid E. O'Brien } 725c80476e4SDavid E. O'Brien if (sx > 0) { 726c80476e4SDavid E. O'Brien ols = oe; 727c80476e4SDavid E. O'Brien nls = ne; 728c80476e4SDavid E. O'Brien } 729c80476e4SDavid E. O'Brien if ((ols - ofd) < (nls - nfd)) { 730c80476e4SDavid E. O'Brien ols = oe; 731c80476e4SDavid E. O'Brien nls = ne; 732c80476e4SDavid E. O'Brien } 733c80476e4SDavid E. O'Brien } 734c80476e4SDavid E. O'Brien if (!T_CanDel) { 735c80476e4SDavid E. O'Brien if (fx < 0) { 736c80476e4SDavid E. O'Brien osb = ols; 737c80476e4SDavid E. O'Brien ose = ols; 738c80476e4SDavid E. O'Brien nsb = nls; 739c80476e4SDavid E. O'Brien nse = nls; 740c80476e4SDavid E. O'Brien } 741c80476e4SDavid E. O'Brien if (sx < 0) { 742c80476e4SDavid E. O'Brien ols = oe; 743c80476e4SDavid E. O'Brien nls = ne; 744c80476e4SDavid E. O'Brien } 745c80476e4SDavid E. O'Brien if ((ols - ofd) > (nls - nfd)) { 746c80476e4SDavid E. O'Brien ols = oe; 747c80476e4SDavid E. O'Brien nls = ne; 748c80476e4SDavid E. O'Brien } 749c80476e4SDavid E. O'Brien } 750c80476e4SDavid E. O'Brien 751c80476e4SDavid E. O'Brien /* 752c80476e4SDavid E. O'Brien * Pragmatics III: make sure the middle shifted pointers are correct if 753c80476e4SDavid E. O'Brien * they don't point to anything (we may have moved ols or nls). 754c80476e4SDavid E. O'Brien */ 755c80476e4SDavid E. O'Brien /* if the change isn't worth it, don't bother */ 756c80476e4SDavid E. O'Brien /* was: if (osb == ose) */ 757c80476e4SDavid E. O'Brien if ((ose - osb) < MIN_END_KEEP) { 758c80476e4SDavid E. O'Brien osb = ols; 759c80476e4SDavid E. O'Brien ose = ols; 760c80476e4SDavid E. O'Brien nsb = nls; 761c80476e4SDavid E. O'Brien nse = nls; 762c80476e4SDavid E. O'Brien } 763c80476e4SDavid E. O'Brien 764c80476e4SDavid E. O'Brien /* 765c80476e4SDavid E. O'Brien * Now that we are done with pragmatics we recompute fx, sx 766c80476e4SDavid E. O'Brien */ 767c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 768c80476e4SDavid E. O'Brien sx = (int) ((nls - nse) - (ols - ose)); 769c80476e4SDavid E. O'Brien 770c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 771c80476e4SDavid E. O'Brien dprintf("\n"); 772c80476e4SDavid E. O'Brien dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n", 773c80476e4SDavid E. O'Brien ofd - old, osb - old, ose - old, ols - old, oe - old); 774c80476e4SDavid E. O'Brien dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n", 775c80476e4SDavid E. O'Brien nfd - new, nsb - new, nse - new, nls - new, ne - new); 776c80476e4SDavid E. O'Brien dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"); 777c80476e4SDavid E. O'Brien dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"); 778c80476e4SDavid E. O'Brien dprintstr("old- oe", old, oe); 779c80476e4SDavid E. O'Brien dprintstr("new- ne", new, ne); 780c80476e4SDavid E. O'Brien dprintstr("old-ofd", old, ofd); 781c80476e4SDavid E. O'Brien dprintstr("new-nfd", new, nfd); 782c80476e4SDavid E. O'Brien dprintstr("ofd-osb", ofd, osb); 783c80476e4SDavid E. O'Brien dprintstr("nfd-nsb", nfd, nsb); 784c80476e4SDavid E. O'Brien dprintstr("osb-ose", osb, ose); 785c80476e4SDavid E. O'Brien dprintstr("nsb-nse", nsb, nse); 786c80476e4SDavid E. O'Brien dprintstr("ose-ols", ose, ols); 787c80476e4SDavid E. O'Brien dprintstr("nse-nls", nse, nls); 788c80476e4SDavid E. O'Brien dprintstr("ols- oe", ols, oe); 789c80476e4SDavid E. O'Brien dprintstr("nls- ne", nls, ne); 790c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 791c80476e4SDavid E. O'Brien 792c80476e4SDavid E. O'Brien /* 793c80476e4SDavid E. O'Brien * CursorV to this line cur_line MUST be in this routine so that if we 794c80476e4SDavid E. O'Brien * don't have to change the line, we don't move to it. CursorH to first 795c80476e4SDavid E. O'Brien * diff char 796c80476e4SDavid E. O'Brien */ 797c80476e4SDavid E. O'Brien MoveToLine(cur_line); 798c80476e4SDavid E. O'Brien 799c80476e4SDavid E. O'Brien /* 800c80476e4SDavid E. O'Brien * at this point we have something like this: 801c80476e4SDavid E. O'Brien * 802c80476e4SDavid E. O'Brien * /old /ofd /osb /ose /ols /oe 803c80476e4SDavid E. O'Brien * v.....................v v..................v v........v 804c80476e4SDavid E. O'Brien * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as 805c80476e4SDavid E. O'Brien * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as 806c80476e4SDavid E. O'Brien * ^.....................^ ^..................^ ^........^ 807c80476e4SDavid E. O'Brien * \new \nfd \nsb \nse \nls \ne 808c80476e4SDavid E. O'Brien * 809c80476e4SDavid E. O'Brien * fx is the difference in length between the the chars between nfd and 810c80476e4SDavid E. O'Brien * nsb, and the chars between ofd and osb, and is thus the number of 811c80476e4SDavid E. O'Brien * characters to delete if < 0 (new is shorter than old, as above), 812c80476e4SDavid E. O'Brien * or insert (new is longer than short). 813c80476e4SDavid E. O'Brien * 814c80476e4SDavid E. O'Brien * sx is the same for the second differences. 815c80476e4SDavid E. O'Brien */ 816c80476e4SDavid E. O'Brien 817c80476e4SDavid E. O'Brien /* 818c80476e4SDavid E. O'Brien * if we have a net insert on the first difference, AND inserting the net 819c80476e4SDavid E. O'Brien * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character 820c80476e4SDavid E. O'Brien * (which is ne if nls != ne, otherwise is nse) off the edge of the screen 821c80476e4SDavid E. O'Brien * (TermH - 1) else we do the deletes first so that we keep everything we 822c80476e4SDavid E. O'Brien * need to. 823c80476e4SDavid E. O'Brien */ 824c80476e4SDavid E. O'Brien 825c80476e4SDavid E. O'Brien /* 826c80476e4SDavid E. O'Brien * if the last same is the same like the end, there is no last same part, 827c80476e4SDavid E. O'Brien * otherwise we want to keep the last same part set p to the last useful 828c80476e4SDavid E. O'Brien * old character 829c80476e4SDavid E. O'Brien */ 830c80476e4SDavid E. O'Brien p = (ols != oe) ? oe : ose; 831c80476e4SDavid E. O'Brien 832c80476e4SDavid E. O'Brien /* 833c80476e4SDavid E. O'Brien * if (There is a diffence in the beginning) && (we need to insert 834c80476e4SDavid E. O'Brien * characters) && (the number of characters to insert is less than the term 835c80476e4SDavid E. O'Brien * width) We need to do an insert! else if (we need to delete characters) 836c80476e4SDavid E. O'Brien * We need to delete characters! else No insert or delete 837c80476e4SDavid E. O'Brien */ 838c80476e4SDavid E. O'Brien if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) { 839c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 840c80476e4SDavid E. O'Brien dprintf("first diff insert at %d...\r\n", nfd - new); 841c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 842c80476e4SDavid E. O'Brien /* 843c80476e4SDavid E. O'Brien * Move to the first char to insert, where the first diff is. 844c80476e4SDavid E. O'Brien */ 845c80476e4SDavid E. O'Brien MoveToChar(nfd - new); 846c80476e4SDavid E. O'Brien /* 847c80476e4SDavid E. O'Brien * Check if we have stuff to keep at end 848c80476e4SDavid E. O'Brien */ 849c80476e4SDavid E. O'Brien if (nsb != ne) { 850c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 851c80476e4SDavid E. O'Brien dprintf("with stuff to keep at end\r\n"); 852c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 853c80476e4SDavid E. O'Brien /* 854c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd 855c80476e4SDavid E. O'Brien */ 856c80476e4SDavid E. O'Brien if (fx > 0) { 857c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 858c80476e4SDavid E. O'Brien if (!T_CanIns) 859c80476e4SDavid E. O'Brien dprintf(" ERROR: cannot insert in early first diff\n"); 860c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 861c80476e4SDavid E. O'Brien Insert_write(nfd, fx); 862c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx); 863c80476e4SDavid E. O'Brien } 864c80476e4SDavid E. O'Brien /* 865c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx) 866c80476e4SDavid E. O'Brien */ 867c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx); 868c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx)); 869c80476e4SDavid E. O'Brien } 870c80476e4SDavid E. O'Brien else { 871c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 872c80476e4SDavid E. O'Brien dprintf("without anything to save\r\n"); 873c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 874c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 875c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 876c80476e4SDavid E. O'Brien /* 877c80476e4SDavid E. O'Brien * Done 878c80476e4SDavid E. O'Brien */ 879c80476e4SDavid E. O'Brien return; 880c80476e4SDavid E. O'Brien } 881c80476e4SDavid E. O'Brien } 882c80476e4SDavid E. O'Brien else if (fx < 0) { 883c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 884c80476e4SDavid E. O'Brien dprintf("first diff delete at %d...\r\n", ofd - old); 885c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 886c80476e4SDavid E. O'Brien /* 887c80476e4SDavid E. O'Brien * move to the first char to delete where the first diff is 888c80476e4SDavid E. O'Brien */ 889c80476e4SDavid E. O'Brien MoveToChar(ofd - old); 890c80476e4SDavid E. O'Brien /* 891c80476e4SDavid E. O'Brien * Check if we have stuff to save 892c80476e4SDavid E. O'Brien */ 893c80476e4SDavid E. O'Brien if (osb != oe) { 894c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 895c80476e4SDavid E. O'Brien dprintf("with stuff to save at end\r\n"); 896c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 897c80476e4SDavid E. O'Brien /* 898c80476e4SDavid E. O'Brien * fx is less than zero *always* here but we check for code 899c80476e4SDavid E. O'Brien * symmetry 900c80476e4SDavid E. O'Brien */ 901c80476e4SDavid E. O'Brien if (fx < 0) { 902c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 903c80476e4SDavid E. O'Brien if (!T_CanDel) 904c80476e4SDavid E. O'Brien dprintf(" ERROR: cannot delete in first diff\n"); 905c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 906c80476e4SDavid E. O'Brien DeleteChars(-fx); 907c80476e4SDavid E. O'Brien str_delete(old, (int) (ofd - old), TermH, -fx); 908c80476e4SDavid E. O'Brien } 909c80476e4SDavid E. O'Brien /* 910c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd 911c80476e4SDavid E. O'Brien */ 912c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 913c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 914c80476e4SDavid E. O'Brien 915c80476e4SDavid E. O'Brien } 916c80476e4SDavid E. O'Brien else { 917c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 918c80476e4SDavid E. O'Brien dprintf("but with nothing left to save\r\n"); 919c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 920c80476e4SDavid E. O'Brien /* 921c80476e4SDavid E. O'Brien * write (nsb-nfd) chars of new starting at nfd 922c80476e4SDavid E. O'Brien */ 923c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 924c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 925c80476e4SDavid E. O'Brien dprintf("cleareol %d\n", (oe - old) - (ne - new)); 926c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 9273b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE 928c80476e4SDavid E. O'Brien ClearEOL((oe - old) - (ne - new)); 929c80476e4SDavid E. O'Brien #else 930c80476e4SDavid E. O'Brien /* 931c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT 932c80476e4SDavid E. O'Brien */ 933c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH); 9343b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/ 935c80476e4SDavid E. O'Brien /* 936c80476e4SDavid E. O'Brien * Done 937c80476e4SDavid E. O'Brien */ 938c80476e4SDavid E. O'Brien return; 939c80476e4SDavid E. O'Brien } 940c80476e4SDavid E. O'Brien } 941c80476e4SDavid E. O'Brien else 942c80476e4SDavid E. O'Brien fx = 0; 943c80476e4SDavid E. O'Brien 944c80476e4SDavid E. O'Brien if (sx < 0) { 945c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 946c80476e4SDavid E. O'Brien dprintf("second diff delete at %d...\r\n", (ose - old) + fx); 947c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 948c80476e4SDavid E. O'Brien /* 949c80476e4SDavid E. O'Brien * Check if we have stuff to delete 950c80476e4SDavid E. O'Brien */ 951c80476e4SDavid E. O'Brien /* 952c80476e4SDavid E. O'Brien * fx is the number of characters inserted (+) or deleted (-) 953c80476e4SDavid E. O'Brien */ 954c80476e4SDavid E. O'Brien 955c80476e4SDavid E. O'Brien MoveToChar((ose - old) + fx); 956c80476e4SDavid E. O'Brien /* 957c80476e4SDavid E. O'Brien * Check if we have stuff to save 958c80476e4SDavid E. O'Brien */ 959c80476e4SDavid E. O'Brien if (ols != oe) { 960c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 961c80476e4SDavid E. O'Brien dprintf("with stuff to save at end\r\n"); 962c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 963c80476e4SDavid E. O'Brien /* 964c80476e4SDavid E. O'Brien * Again a duplicate test. 965c80476e4SDavid E. O'Brien */ 966c80476e4SDavid E. O'Brien if (sx < 0) { 967c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 968c80476e4SDavid E. O'Brien if (!T_CanDel) 969c80476e4SDavid E. O'Brien dprintf(" ERROR: cannot delete in second diff\n"); 970c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 971c80476e4SDavid E. O'Brien DeleteChars(-sx); 972c80476e4SDavid E. O'Brien } 973c80476e4SDavid E. O'Brien 974c80476e4SDavid E. O'Brien /* 975c80476e4SDavid E. O'Brien * write (nls-nse) chars of new starting at nse 976c80476e4SDavid E. O'Brien */ 977c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 978c80476e4SDavid E. O'Brien } 979c80476e4SDavid E. O'Brien else { 980c80476e4SDavid E. O'Brien int olen = (int) (oe - old + fx); 981c80476e4SDavid E. O'Brien if (olen > TermH) 982c80476e4SDavid E. O'Brien olen = TermH; 983c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 984c80476e4SDavid E. O'Brien dprintf("but with nothing left to save\r\n"); 985c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 986c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 987c80476e4SDavid E. O'Brien #ifdef DEBUG_REFRESH 988c80476e4SDavid E. O'Brien dprintf("cleareol %d\n", olen - (ne - new)); 989c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 9903b6eaa7bSAndrey A. Chernov #ifndef WINNT_NATIVE 991c80476e4SDavid E. O'Brien ClearEOL(olen - (ne - new)); 992c80476e4SDavid E. O'Brien #else 993c80476e4SDavid E. O'Brien /* 994c80476e4SDavid E. O'Brien * The calculation above does not work too well on NT 995c80476e4SDavid E. O'Brien */ 996c80476e4SDavid E. O'Brien ClearEOL(TermH - CursorH); 9973b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/ 998c80476e4SDavid E. O'Brien } 999c80476e4SDavid E. O'Brien } 1000c80476e4SDavid E. O'Brien 1001c80476e4SDavid E. O'Brien /* 1002c80476e4SDavid E. O'Brien * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... 1003c80476e4SDavid E. O'Brien */ 1004c80476e4SDavid E. O'Brien if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { 1005c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1006c80476e4SDavid E. O'Brien dprintf("late first diff insert at %d...\r\n", nfd - new); 1007c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1008c80476e4SDavid E. O'Brien 1009c80476e4SDavid E. O'Brien MoveToChar(nfd - new); 1010c80476e4SDavid E. O'Brien /* 1011c80476e4SDavid E. O'Brien * Check if we have stuff to keep at the end 1012c80476e4SDavid E. O'Brien */ 1013c80476e4SDavid E. O'Brien if (nsb != ne) { 1014c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1015c80476e4SDavid E. O'Brien dprintf("with stuff to keep at end\r\n"); 1016c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1017c80476e4SDavid E. O'Brien /* 1018c80476e4SDavid E. O'Brien * We have to recalculate fx here because we set it 1019c80476e4SDavid E. O'Brien * to zero above as a flag saying that we hadn't done 1020c80476e4SDavid E. O'Brien * an early first insert. 1021c80476e4SDavid E. O'Brien */ 1022c80476e4SDavid E. O'Brien fx = (int) ((nsb - nfd) - (osb - ofd)); 1023c80476e4SDavid E. O'Brien if (fx > 0) { 1024c80476e4SDavid E. O'Brien /* 1025c80476e4SDavid E. O'Brien * insert fx chars of new starting at nfd 1026c80476e4SDavid E. O'Brien */ 1027c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1028c80476e4SDavid E. O'Brien if (!T_CanIns) 1029c80476e4SDavid E. O'Brien dprintf(" ERROR: cannot insert in late first diff\n"); 1030c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1031c80476e4SDavid E. O'Brien Insert_write(nfd, fx); 1032c80476e4SDavid E. O'Brien str_insert(old, (int) (ofd - old), TermH, nfd, fx); 1033c80476e4SDavid E. O'Brien } 1034c80476e4SDavid E. O'Brien 1035c80476e4SDavid E. O'Brien /* 1036c80476e4SDavid E. O'Brien * write (nsb-nfd) - fx chars of new starting at (nfd + fx) 1037c80476e4SDavid E. O'Brien */ 1038c80476e4SDavid E. O'Brien so_write(nfd + fx, (nsb - nfd) - fx); 1039c80476e4SDavid E. O'Brien str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx)); 1040c80476e4SDavid E. O'Brien } 1041c80476e4SDavid E. O'Brien else { 1042c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1043c80476e4SDavid E. O'Brien dprintf("without anything to save\r\n"); 1044c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1045c80476e4SDavid E. O'Brien so_write(nfd, (nsb - nfd)); 1046c80476e4SDavid E. O'Brien str_cp(ofd, nfd, (int) (nsb - nfd)); 1047c80476e4SDavid E. O'Brien } 1048c80476e4SDavid E. O'Brien } 1049c80476e4SDavid E. O'Brien 1050c80476e4SDavid E. O'Brien /* 1051c80476e4SDavid E. O'Brien * line is now NEW up to nse 1052c80476e4SDavid E. O'Brien */ 1053c80476e4SDavid E. O'Brien if (sx >= 0) { 1054c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1055c80476e4SDavid E. O'Brien dprintf("second diff insert at %d...\r\n", nse - new); 1056c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1057c80476e4SDavid E. O'Brien MoveToChar(nse - new); 1058c80476e4SDavid E. O'Brien if (ols != oe) { 1059c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1060c80476e4SDavid E. O'Brien dprintf("with stuff to keep at end\r\n"); 1061c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1062c80476e4SDavid E. O'Brien if (sx > 0) { 1063c80476e4SDavid E. O'Brien /* insert sx chars of new starting at nse */ 1064c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1065c80476e4SDavid E. O'Brien if (!T_CanIns) 1066c80476e4SDavid E. O'Brien dprintf(" ERROR: cannot insert in second diff\n"); 1067c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1068c80476e4SDavid E. O'Brien Insert_write(nse, sx); 1069c80476e4SDavid E. O'Brien } 1070c80476e4SDavid E. O'Brien 1071c80476e4SDavid E. O'Brien /* 1072c80476e4SDavid E. O'Brien * write (nls-nse) - sx chars of new starting at (nse + sx) 1073c80476e4SDavid E. O'Brien */ 1074c80476e4SDavid E. O'Brien so_write(nse + sx, (nls - nse) - sx); 1075c80476e4SDavid E. O'Brien } 1076c80476e4SDavid E. O'Brien else { 1077c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1078c80476e4SDavid E. O'Brien dprintf("without anything to save\r\n"); 1079c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1080c80476e4SDavid E. O'Brien so_write(nse, (nls - nse)); 1081c80476e4SDavid E. O'Brien 1082c80476e4SDavid E. O'Brien /* 1083c80476e4SDavid E. O'Brien * No need to do a clear-to-end here because we were doing 1084c80476e4SDavid E. O'Brien * a second insert, so we will have over written all of the 1085c80476e4SDavid E. O'Brien * old string. 1086c80476e4SDavid E. O'Brien */ 1087c80476e4SDavid E. O'Brien } 1088c80476e4SDavid E. O'Brien } 1089c80476e4SDavid E. O'Brien #ifdef DEBUG_UPDATE 1090c80476e4SDavid E. O'Brien dprintf("done.\r\n"); 1091c80476e4SDavid E. O'Brien #endif /* DEBUG_UPDATE */ 1092c80476e4SDavid E. O'Brien } 1093c80476e4SDavid E. O'Brien 1094c80476e4SDavid E. O'Brien 1095c80476e4SDavid E. O'Brien static void 109645e5710bSMark Peek cpy_pad_spaces(Char *dst, Char *src, int width) 1097c80476e4SDavid E. O'Brien { 109823338178SMark Peek int i; 1099c80476e4SDavid E. O'Brien 1100c80476e4SDavid E. O'Brien for (i = 0; i < width; i++) { 1101c80476e4SDavid E. O'Brien if (*src == (Char) 0) 1102c80476e4SDavid E. O'Brien break; 1103c80476e4SDavid E. O'Brien *dst++ = *src++; 1104c80476e4SDavid E. O'Brien } 1105c80476e4SDavid E. O'Brien 1106c80476e4SDavid E. O'Brien while (i < width) { 1107c80476e4SDavid E. O'Brien *dst++ = ' '; 1108c80476e4SDavid E. O'Brien i++; 1109c80476e4SDavid E. O'Brien } 1110c80476e4SDavid E. O'Brien *dst = (Char) 0; 1111c80476e4SDavid E. O'Brien } 1112c80476e4SDavid E. O'Brien 1113c80476e4SDavid E. O'Brien void 111445e5710bSMark Peek RefCursor(void) 1115c80476e4SDavid E. O'Brien { /* only move to new cursor pos */ 111623338178SMark Peek Char *cp; 111745e5710bSMark Peek int w, h, th, v; 1118c80476e4SDavid E. O'Brien 1119c80476e4SDavid E. O'Brien /* first we must find where the cursor is... */ 1120c80476e4SDavid E. O'Brien h = 0; 1121c80476e4SDavid E. O'Brien v = 0; 1122c80476e4SDavid E. O'Brien th = TermH; /* optimize for speed */ 1123c80476e4SDavid E. O'Brien 112445e5710bSMark Peek for (cp = Prompt; cp != NULL && *cp; ) { /* do prompt */ 112523338178SMark Peek if (*cp & LITERAL) { 112623338178SMark Peek cp++; 1127c80476e4SDavid E. O'Brien continue; 112823338178SMark Peek } 112945e5710bSMark Peek w = NLSClassify(*cp & CHAR, cp == Prompt); 113045e5710bSMark Peek cp++; 113123338178SMark Peek switch(w) { 113223338178SMark Peek case NLSCLASS_NL: 1133c80476e4SDavid E. O'Brien h = 0; 1134c80476e4SDavid E. O'Brien v++; 113523338178SMark Peek break; 113623338178SMark Peek case NLSCLASS_TAB: 113723338178SMark Peek while (++h & 07) 113823338178SMark Peek ; 113923338178SMark Peek break; 114023338178SMark Peek case NLSCLASS_CTRL: 114123338178SMark Peek h += 2; 114223338178SMark Peek break; 114323338178SMark Peek case NLSCLASS_ILLEGAL: 114423338178SMark Peek h += 4; 114523338178SMark Peek break; 114623338178SMark Peek case NLSCLASS_ILLEGAL2: 114723338178SMark Peek case NLSCLASS_ILLEGAL3: 114823338178SMark Peek case NLSCLASS_ILLEGAL4: 114923338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w); 115023338178SMark Peek break; 115123338178SMark Peek default: 115223338178SMark Peek h += w; 1153c80476e4SDavid E. O'Brien } 1154c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */ 115523338178SMark Peek h -= th; 115623338178SMark Peek v++; 115723338178SMark Peek } 115823338178SMark Peek } 115923338178SMark Peek 116023338178SMark Peek for (cp = InputBuf; cp < Cursor;) { /* do input buffer to Cursor */ 116145e5710bSMark Peek w = NLSClassify(*cp & CHAR, cp == InputBuf); 116245e5710bSMark Peek cp++; 116323338178SMark Peek switch(w) { 116423338178SMark Peek case NLSCLASS_NL: 1165c80476e4SDavid E. O'Brien h = 0; 1166c80476e4SDavid E. O'Brien v++; 116723338178SMark Peek break; 116823338178SMark Peek case NLSCLASS_TAB: 116923338178SMark Peek while (++h & 07) 117023338178SMark Peek ; 117123338178SMark Peek break; 117223338178SMark Peek case NLSCLASS_CTRL: 117323338178SMark Peek h += 2; 117423338178SMark Peek break; 117523338178SMark Peek case NLSCLASS_ILLEGAL: 117623338178SMark Peek h += 4; 117723338178SMark Peek break; 117823338178SMark Peek case NLSCLASS_ILLEGAL2: 117923338178SMark Peek case NLSCLASS_ILLEGAL3: 118023338178SMark Peek case NLSCLASS_ILLEGAL4: 118123338178SMark Peek h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w); 118223338178SMark Peek break; 118323338178SMark Peek default: 118423338178SMark Peek h += w; 1185c80476e4SDavid E. O'Brien } 1186c80476e4SDavid E. O'Brien if (h >= th) { /* check, extra long tabs picked up here also */ 118723338178SMark Peek h -= th; 1188c80476e4SDavid E. O'Brien v++; 1189c80476e4SDavid E. O'Brien } 1190c80476e4SDavid E. O'Brien } 1191c80476e4SDavid E. O'Brien 1192c80476e4SDavid E. O'Brien /* now go there */ 1193c80476e4SDavid E. O'Brien MoveToLine(v); 1194c80476e4SDavid E. O'Brien MoveToChar(h); 119545e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) { 119645e5710bSMark Peek ClearLines(); 119745e5710bSMark Peek ClearDisp(); 119845e5710bSMark Peek Refresh(); 119945e5710bSMark Peek } 1200c80476e4SDavid E. O'Brien flush(); 1201c80476e4SDavid E. O'Brien } 1202c80476e4SDavid E. O'Brien 1203b2d5d167SMark Peek #ifndef WINTT_NATIVE 1204c80476e4SDavid E. O'Brien static void 120545e5710bSMark Peek PutPlusOne(Char c, int width) 1206c80476e4SDavid E. O'Brien { 120723338178SMark Peek while (width > 1 && CursorH + width > TermH) 120823338178SMark Peek PutPlusOne(' ', 1); 120923338178SMark Peek if ((c & LITERAL) != 0) { 121023338178SMark Peek Char *d; 121123338178SMark Peek for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++) 121223338178SMark Peek (void) putwraw(*d); 121323338178SMark Peek } else { 121423338178SMark Peek (void) putwraw(c); 121523338178SMark Peek } 1216c80476e4SDavid E. O'Brien Display[CursorV][CursorH++] = (Char) c; 121723338178SMark Peek while (--width > 0) 121823338178SMark Peek Display[CursorV][CursorH++] = CHAR_DBWIDTH; 1219c80476e4SDavid E. O'Brien if (CursorH >= TermH) { /* if we must overflow */ 1220c80476e4SDavid E. O'Brien CursorH = 0; 1221c80476e4SDavid E. O'Brien CursorV++; 1222c80476e4SDavid E. O'Brien OldvcV++; 1223c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_AUTO) { 1224c80476e4SDavid E. O'Brien if (T_Margin & MARGIN_MAGIC) { 1225c80476e4SDavid E. O'Brien (void) putraw(' '); 1226c80476e4SDavid E. O'Brien (void) putraw('\b'); 1227c80476e4SDavid E. O'Brien } 1228c80476e4SDavid E. O'Brien } 1229c80476e4SDavid E. O'Brien else { 1230c80476e4SDavid E. O'Brien (void) putraw('\r'); 1231c80476e4SDavid E. O'Brien (void) putraw('\n'); 1232c80476e4SDavid E. O'Brien } 1233c80476e4SDavid E. O'Brien } 1234c80476e4SDavid E. O'Brien } 1235b2d5d167SMark Peek #endif 1236c80476e4SDavid E. O'Brien 1237c80476e4SDavid E. O'Brien void 123823338178SMark Peek RefPlusOne(int l) 1239c80476e4SDavid E. O'Brien { /* we added just one char, handle it fast. 1240c80476e4SDavid E. O'Brien * assumes that screen cursor == real cursor */ 124145e5710bSMark Peek Char *cp, c; 124223338178SMark Peek int w; 1243c80476e4SDavid E. O'Brien 124423338178SMark Peek if (Cursor != LastChar) { 1245c80476e4SDavid E. O'Brien Refresh(); /* too hard to handle */ 1246c80476e4SDavid E. O'Brien return; 1247c80476e4SDavid E. O'Brien } 1248c80476e4SDavid E. O'Brien if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) { 1249c80476e4SDavid E. O'Brien Refresh(); /* clear out rprompt if less than one char gap*/ 1250c80476e4SDavid E. O'Brien return; 125123338178SMark Peek } 125223338178SMark Peek cp = Cursor - l; 125345e5710bSMark Peek c = *cp & CHAR; 125423338178SMark Peek w = NLSClassify(c, cp == InputBuf); 125523338178SMark Peek switch(w) { 125623338178SMark Peek case NLSCLASS_CTRL: 125723338178SMark Peek PutPlusOne('^', 1); 125823338178SMark Peek if (c == CTL_ESC('\177')) { 125923338178SMark Peek PutPlusOne('?', 1); 126023338178SMark Peek break; 126123338178SMark Peek } 12623b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 126323338178SMark Peek /* uncontrolify it; works only for iso8859-1 like sets */ 126423338178SMark Peek PutPlusOne((c | 0100), 1); 12653b6eaa7bSAndrey A. Chernov #else 126623338178SMark Peek PutPlusOne(_toebcdic[_toascii[c]|0100], 1); 126723338178SMark Peek #endif 126823338178SMark Peek break; 126923338178SMark Peek case NLSCLASS_ILLEGAL: 127023338178SMark Peek PutPlusOne('\\', 1); 127123338178SMark Peek PutPlusOne(((c >> 6) & 7) + '0', 1); 127223338178SMark Peek PutPlusOne(((c >> 3) & 7) + '0', 1); 127323338178SMark Peek PutPlusOne((c & 7) + '0', 1); 127423338178SMark Peek break; 127523338178SMark Peek case 1: 127645e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) 127745e5710bSMark Peek StartHighlight(); 127823338178SMark Peek if (l > 1) 127923338178SMark Peek PutPlusOne(MakeLiteral(cp, l, 0), 1); 1280c80476e4SDavid E. O'Brien else 128123338178SMark Peek PutPlusOne(*cp, 1); 128245e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) 128345e5710bSMark Peek StopHighlight(); 128423338178SMark Peek break; 128523338178SMark Peek default: 128623338178SMark Peek Refresh(); /* too hard to handle */ 128723338178SMark Peek return; 1288c80476e4SDavid E. O'Brien } 1289c80476e4SDavid E. O'Brien flush(); 1290c80476e4SDavid E. O'Brien } 1291c80476e4SDavid E. O'Brien 1292c80476e4SDavid E. O'Brien /* clear the screen buffers so that new new prompt starts fresh. */ 1293c80476e4SDavid E. O'Brien 1294c80476e4SDavid E. O'Brien void 129545e5710bSMark Peek ClearDisp(void) 1296c80476e4SDavid E. O'Brien { 129723338178SMark Peek int i; 1298c80476e4SDavid E. O'Brien 1299c80476e4SDavid E. O'Brien CursorV = 0; /* clear the display buffer */ 1300c80476e4SDavid E. O'Brien CursorH = 0; 1301c80476e4SDavid E. O'Brien for (i = 0; i < TermV; i++) 1302c80476e4SDavid E. O'Brien (void) memset(Display[i], 0, TermH * sizeof(Display[0][0])); 1303c80476e4SDavid E. O'Brien OldvcV = 0; 130423338178SMark Peek litlen = 0; 1305c80476e4SDavid E. O'Brien } 1306c80476e4SDavid E. O'Brien 1307c80476e4SDavid E. O'Brien void 130845e5710bSMark Peek ClearLines(void) 1309c80476e4SDavid E. O'Brien { /* Make sure all lines are *really* blank */ 131023338178SMark Peek int i; 1311c80476e4SDavid E. O'Brien 1312c80476e4SDavid E. O'Brien if (T_CanCEOL) { 1313c80476e4SDavid E. O'Brien /* 1314c80476e4SDavid E. O'Brien * Clear the lines from the bottom up so that if we try moving 1315c80476e4SDavid E. O'Brien * the cursor down by writing the character that is at the end 1316c80476e4SDavid E. O'Brien * of the screen line, we won't rewrite a character that shouldn't 1317c80476e4SDavid E. O'Brien * be there. 1318c80476e4SDavid E. O'Brien */ 1319c80476e4SDavid E. O'Brien for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */ 1320c80476e4SDavid E. O'Brien MoveToLine(i); 1321c80476e4SDavid E. O'Brien MoveToChar(0); 1322c80476e4SDavid E. O'Brien ClearEOL(TermH); 1323c80476e4SDavid E. O'Brien } 1324c80476e4SDavid E. O'Brien } 1325c80476e4SDavid E. O'Brien else { 1326c80476e4SDavid E. O'Brien MoveToLine(OldvcV); /* go to last line */ 1327c80476e4SDavid E. O'Brien (void) putraw('\r'); /* go to BOL */ 1328c80476e4SDavid E. O'Brien (void) putraw('\n'); /* go to new line */ 1329c80476e4SDavid E. O'Brien } 1330c80476e4SDavid E. O'Brien } 1331