# 2.11BSD#431 - /usr/src/bin/tcsh/ed.refresh.c

##### Functions

    ClearDisp         X
    ClearLines        X
    GotoBottom        X
    PastBottom        X
    RefCursor         X
    RefPlusOne        X
    Refresh           X

##### Macros

    MIN_END_KEEP      X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.refresh.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
       2: /*
       3:  * ed.refresh.c: Lower level screen refreshing functions
       4:  */
       5: /*-
       6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
       7:  * All rights reserved.
       8:  *
       9:  * Redistribution and use in source and binary forms, with or without
      10:  * modification, are permitted provided that the following conditions
      11:  * are met:
      12:  * 1. Redistributions of source code must retain the above copyright
      13:  *    notice, this list of conditions and the following disclaimer.
      14:  * 2. Redistributions in binary form must reproduce the above copyright
      15:  *    notice, this list of conditions and the following disclaimer in the
      16:  *    documentation and/or other materials provided with the distribution.
      17:  * 3. All advertising materials mentioning features or use of this software
      18:  *    must display the following acknowledgement:
      19:  *	This product includes software developed by the University of
      20:  *	California, Berkeley and its contributors.
      21:  * 4. Neither the name of the University nor the names of its contributors
      22:  *    may be used to endorse or promote products derived from this software
      23:  *    without specific prior written permission.
      24:  *
      25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35:  * SUCH DAMAGE.
      36:  */
      37: #include "config.h"
      38: #if !defined(lint) && !defined(pdp11)
      39: static char *rcsid()
      40:     { return "$Id: ed.refresh.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44: #include "ed.h"
      45: /* #define DEBUG_UPDATE   */
      46: /* #define DEBUG_REFRESH */
      47: /* #define DEBUG_LITERAL */
      48:
      49: /* refresh.c -- refresh the current set of lines on the screen */
      50:
      51: Char   *litptr[256];
      52: static int vcur_h, vcur_v;
      53:
      54: static  void    Draw            __P((int));
      55: static  void    Vdraw           __P((int));
      56: static  void    Vnewline        __P((void));
      57: static  void    update_line         __P((Char *, Char *, int));
      58: static  int has_other_than_spaces   __P((Char *, int));
      59: static  void    str_insert      __P((Char *, int, int, Char *, int));
      60: static  void    str_delete      __P((Char *, int, int, int));
      61: static  void    str_cp          __P((Char *, Char *, int));
      62: static  void    PutPlusOne      __P((int));
      63:
      64: static void
      65: Draw(c)             /* draw c, expand tabs, ctl chars */
      66:     register int c;
      67: {
      68:     register Char ch = c & CHAR;
      69:
      70:     if (Isprint(ch)) {
      71:     Vdraw(c);
      72:     return;
      73:     }
      74:     /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
      75:     if (ch == '\n') {       /* expand the newline	 */
      76:     Vdraw('\0');    /* assure end of line	 */
      77:     vcur_h = 0;     /* reset cursor pos	 */
      78:     vcur_v++;
      79:     return;
      80:     }
      81:     if (ch == '\t') {       /* expand the tab 	 */
      82:     for (;;) {
      83:         Vdraw(' ');
      84:         if ((vcur_h & 07) == 0)
      85:         break;      /* go until tab stop	 */
      86:     }
      87:     }
      88:     else if (Iscntrl(ch)) {
      89:     Vdraw('^');
      90:     if (ch == '\177') {
      91:         Vdraw('?');
      92:     }
      93:     else {
      94:         /* uncontrolify it; works only for iso8859-1 like sets */
      95:         Vdraw((c | 0100));
      96:     }
      97:     }
      98:     else {
      99:     Vdraw('\\');
     100:     Vdraw(((c >> 6) & 7) + '0');
     101:     Vdraw(((c >> 3) & 7) + '0');
     102:     Vdraw((c & 7) + '0');
     103:     }
     104: }
     105:
     106: static void
     107: Vdraw(c)            /* draw char c onto V lines */
     108:     register int c;
     109: {
     110: #ifdef DEBUG_REFRESH
     111: # ifdef SHORT_STRINGS
     112:     xprintf("Vdrawing %6.6o '%c'\r\n", c, c & ASCII);
     113: # else
     114:     xprintf("Vdrawing %3.3o '%c'\r\n", c, c);
     115: # endif
     116: #endif
     117:
     118:     Vdisplay[vcur_v][vcur_h] = c;
     119:     vcur_h++;       /* advance to next place */
     120:     if (vcur_h >= TermH) {
     121:     Vdisplay[vcur_v][TermH] = '\0'; /* assure end of line */
     122:     vcur_h = 0;     /* reset it. */
     123:     vcur_v++;
     124:     if (vcur_v >= TermV) {  /* should NEVER happen. */
     125: #ifdef DEBUG_REFRESH
     126:         xprintf("\r\nVdraw: vcur_v overflow! Vcursor_v == %d > %d\r\n",
     127:             vcur_v, TermV);
     128:         abort();
     129: #endif				/* DEBUG_REFRESH */
     130:     }
     131:     }
     132: }
     133:
     134: static void
     135: Vnewline()
     136: {
     137:     /* needs work. */
     138: }
     139:
     140: /*
     141:  *  Refresh()
     142:  *	draws the new virtual screen image from the current input
     143:  *  	line, then goes line-by-line changing the real image to the new
     144:  *	virtual image. The routine to re-draw a line can be replaced
     145:  *	easily in hopes of a smarter one being placed there.
     146:  */
     147: static int OldvcV = 0;
     148: void
     149: Refresh()
     150: {
     151:     register int cur_line;
     152:     register Char *cp;
     153:     int     cur_h, cur_v = 0, new_vcv;
     154:     Char    oldgetting;
     155:     int     litnum = 0;
     156:
     157: #ifdef DEBUG_REFRESH
     158:     xprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
     159:     xprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
     160: #endif
     161:     oldgetting = GettingInput;
     162:     GettingInput = 0;       /* avoid re-entrance via SIGWINCH */
     163:
     164:     /* reset the Vdraw cursor */
     165:     vcur_h = 0;
     166:     vcur_v = 0;
     167:
     168:     /* draw prompt, we know it's ASCIZ */
     169:     for (cp = PromptBuf; *cp; cp++) {
     170:     if (*cp & LITERAL) {
     171:         if (litnum < (sizeof(litptr) / sizeof(litptr[0]))) {
     172:         litptr[litnum] = cp;
     173: #ifdef DEBUG_LITERAL
     174:         xprintf("litnum = %d, litptr = %x:\r\n",
     175:             litnum, litptr[litnum]);
     176: #endif
     177:         }
     178:         while (*cp & LITERAL)
     179:         cp++;
     180:         if (*cp)
     181:         Vdraw(litnum++ | LITERAL);
     182:         else {
     183:         /*
     184: 		 * XXX: This is a bug, we lose the last literal, if it is not
     185: 		 * followed by a normal character, but it is too hard to fix
     186: 		 */
     187:         break;
     188:         }
     189:     }
     190:     else
     191:         Draw(*cp);
     192:     }
     193:     cur_h = -1;         /* set flag in case I'm not set */
     194:
     195:     /* draw the current input buffer */
     196:     for (cp = InputBuf; (cp < LastChar); cp++) {
     197:     if (cp == Cursor) {
     198:         cur_h = vcur_h; /* save for later */
     199:         cur_v = vcur_v;
     200:     }
     201:     Draw(*cp);
     202:     }
     203:
     204:     /* to next line and draw the current search prompt if searching */
     205:     if (DoingSearch) {
     206:     Vnewline();
     207:     for (cp = SearchPrompt; *cp; cp++)
     208:         Draw(*cp);
     209:     for (cp = InputBuf; (cp < LastChar); cp++) {
     210:         if (cp == Cursor) {
     211:         cur_h = vcur_h; /* save for later */
     212:         cur_v = vcur_v;
     213:         }
     214:         Draw(*cp);
     215:     }
     216:     }
     217:
     218:     if (cur_h == -1) {      /* if I havn't been set yet, I'm at the end */
     219:     cur_h = vcur_h;
     220:     cur_v = vcur_v;
     221:     }
     222:     new_vcv = vcur_v;   /* must be done BEFORE the NUL is written */
     223:     Vdraw('\0');        /* put NUL on end */
     224:
     225: #ifdef DEBUG_REFRESH
     226:     xprintf(
     227:     "TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
     228:         TermH, vcur_h, vcur_v, short2str(Vdisplay[0]));
     229: #endif
     230:
     231:     for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
     232:     /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
     233:     update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
     234:     (void) Strncpy(Display[cur_line], Vdisplay[cur_line], TermH);
     235:     Display[cur_line][TermH] = '\0';    /* just in case */
     236:     }
     237: #ifdef DEBUG_REFRESH
     238:     xprintf("\r\nvcur_v = %d, OldvcV = %d, cur_line = %d\r\n",
     239:         vcur_v, OldvcV, cur_line);
     240: #endif
     241:     if (OldvcV > new_vcv) {
     242:     for (; cur_line <= OldvcV; cur_line++) {
     243:         MoveToLine(cur_line);
     244:         MoveToChar(0);
     245:         ClearEOL(Strlen(Display[cur_line]));
     246: #ifdef DEBUG_REFRESH
     247:         so_write(str2short("C\b"), 2);
     248: #endif
     249:         *Display[cur_line] = '\0';
     250:     }
     251:     }
     252:     OldvcV = new_vcv;       /* set for next time */
     253: #ifdef DEBUG_REFRESH
     254:     xprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
     255:         CursorH, CursorV, cur_h, cur_v);
     256: #endif
     257:     MoveToLine(cur_v);      /* go to where the cursor is */
     258:     MoveToChar(cur_h);
     259:     SetAttributes(0);       /* Clear all attributes */
     260:     flush();            /* send the output... */
     261:     GettingInput = oldgetting;  /* reset to old value */
     262: }
     263:
     264: #ifdef notdef
     265: GotoBottom()
     266: {               /* used to go to last used screen line */
     267:     MoveToLine(OldvcV);
     268: }
     269:
     270: #endif
     271:
     272: void
     273: PastBottom()
     274: {               /* used to go to last used screen line */
     275:     MoveToLine(OldvcV);
     276:     (void) putraw('\r');
     277:     (void) putraw('\n');
     278:     ClearDisp();
     279:     flush();
     280: }
     281:
     282: static int
     283: has_other_than_spaces(s, n)
     284:     register Char *s;
     285:     register int n;
     286: {
     287:     if (n <= 0)
     288:     return 0;
     289:
     290:     while (n-- > 0) {
     291:     if (*s != '\0' && *s != ' ')
     292:         return 1;
     293:     s++;
     294:     }
     295:     return 0;
     296: }
     297:
     298: /* insert num characters of s into d (in front of the character) at dat,
     299:    maximum length of d is dlen */
     300: static void
     301: str_insert(d, dat, dlen, s, num)
     302:     register Char *d;
     303:     register int dat, dlen;
     304:     register Char *s;
     305:     register int num;
     306: {
     307:     register Char *a, *b;
     308:
     309:     if (num <= 0)
     310:     return;
     311:     if (num > dlen - dat)
     312:     num = dlen - dat;
     313:
     314: #ifdef DEBUG_REFRESH
     315:     xprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
     316:         num, dat, dlen, short2str(d));
     317:     xprintf("s == \"%s\"n", short2str(s));
     318: #endif
     319:
     320:     /* open up the space for num chars */
     321:     if (num > 0) {
     322:     b = d + dlen - 1;
     323:     a = b - num;
     324:     while (a >= &d[dat])
     325:         *b-- = *a--;
     326:     d[dlen] = '\0';     /* just in case */
     327:     }
     328: #ifdef DEBUG_REFRESH
     329:     xprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
     330:         num, dat, dlen, short2str(d));
     331:     xprintf("s == \"%s\"n", short2str(s));
     332: #endif
     333:
     334:     /* copy the characters */
     335:     for (a = d + dat; (a < d + dlen) && (num > 0); num--)
     336:     *a++ = *s++;
     337:
     338: #ifdef DEBUG_REFRESH
     339:     xprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
     340:         num, dat, dlen, d, short2str(s));
     341:     xprintf("s == \"%s\"n", short2str(s));
     342: #endif
     343: }
     344:
     345: /* delete num characters d at dat, maximum length of d is dlen */
     346: static void
     347: str_delete(d, dat, dlen, num)
     348:     register Char *d;
     349:     register int dat, dlen, num;
     350: {
     351:     register Char *a, *b;
     352:
     353:     if (num <= 0)
     354:     return;
     355:     if (dat + num >= dlen) {
     356:     d[dat] = '\0';
     357:     return;
     358:     }
     359:
     360: #ifdef DEBUG_REFRESH
     361:     xprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
     362:         num, dat, dlen, short2str(d));
     363: #endif
     364:
     365:     /* open up the space for num chars */
     366:     if (num > 0) {
     367:     b = d + dat;
     368:     a = b + num;
     369:     while (a < &d[dlen])
     370:         *b++ = *a++;
     371:     d[dlen] = '\0';     /* just in case */
     372:     }
     373: #ifdef DEBUG_REFRESH
     374:     xprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
     375:         num, dat, dlen, short2str(d));
     376: #endif
     377: }
     378:
     379: static void
     380: str_cp(a, b, n)
     381:     register Char *a, *b;
     382:     register int n;
     383: {
     384:     while (n-- && *b)
     385:     *a++ = *b++;
     386: }
     387:
     388:
     389:
     390: /* ****************************************************************
     391:     update_line() is based on finding the middle difference of each line
     392:     on the screen; vis:
     393:
     394:
     395: 			     /old first difference
     396: 	/beginning of line   |              /old last same       /old EOL
     397: 	v		     v              v                    v
     398: old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
     399: new:	eddie> Oh, my little buggy says to me, as lurgid as
     400: 	^		     ^        ^			   ^
     401: 	\beginning of line   |        \new last same	   \new end of line
     402: 			     \new first difference
     403:
     404:     all are character pointers for the sake of speed.  Special cases for
     405:     no differences, as well as for end of line additions must be handled.
     406: **************************************************************** */
     407:
     408: /* Minimum at which doing an insert it "worth it".  This should be about
     409:  * half the "cost" of going into insert mode, inserting a character, and
     410:  * going back out.  This should really be calculated from the t_c_
     411:  * data...  For the moment, a good number for ANSI terminals.
     412:  */
     413: #define MIN_END_KEEP    4
     414:
     415: static void         /* could be changed to make it smarter */
     416: update_line(old, new, cur_line)
     417:     register Char *old, *new;
     418:     int     cur_line;
     419: {
     420:     register Char *o, *n, *p, c;
     421:     Char   *ofd, *ols, *oe, *nfd, *nls, *ne;
     422:     Char   *osb, *ose, *nsb, *nse;
     423:     int     fx, sx;
     424:
     425:     /*
     426:      * find first diff
     427:      */
     428:     for (o = old, n = new; *o && (*o == *n); o++, n++);
     429:     ofd = o;
     430:     nfd = n;
     431:
     432:     /*
     433:      * if no diff, continue to next line
     434:      */
     435:     if (*ofd == '\0' && *nfd == '\0') {
     436: #ifdef DEBUG_UPDATE
     437:     DEBUGPRINT("no difference.\r\n", 0);
     438: #endif				/* DEBUG_UPDATE */
     439:     return;
     440:     }
     441:
     442:     /*
     443:      * Find the end of both old and new
     444:      */
     445:     while (*o)
     446:     o++;
     447:     oe = o;
     448:
     449:     while (*n)
     450:     n++;
     451:     ne = n;
     452:
     453:     /*
     454:      * find last same *
     455:      */
     456:     for (; (o > ofd) && (n > nfd) && (o[-1] == n[-1]); o--, n--);
     457:     ols = o;
     458:     nls = n;
     459:
     460:     /*
     461:      * find same begining and same end
     462:      */
     463:     osb = ols;
     464:     nsb = nls;
     465:     ose = ols;
     466:     nse = nls;
     467:
     468:     /*
     469:      * case 1: insert: scan from nfd to nls looking for *ofd
     470:      */
     471:     if (*ofd) {
     472:     for (c = *ofd, n = nfd; n < nls; n++) {
     473:         if (c == *n) {
     474:         for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++);
     475:         /*
     476: 		 * if the new match is longer and it's worth keeping, then we
     477: 		 * take it
     478: 		 */
     479:         if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
     480:             nsb = n;
     481:             nse = p;
     482:             osb = ofd;
     483:             ose = o;
     484:         }
     485:         }
     486:     }
     487:     }
     488:
     489:     /*
     490:      * case 2: delete: scan from ofd to ols looking for *nfd
     491:      */
     492:     if (*nfd) {
     493:     for (c = *nfd, o = ofd; o < ols; o++) {
     494:         if (c == *o) {
     495:         for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++);
     496:         /*
     497: 		 * if the new match is longer and it's worth keeping, then we
     498: 		 * take it
     499: 		 */
     500:         if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
     501:             nsb = nfd;
     502:             nse = n;
     503:             osb = o;
     504:             ose = p;
     505:         }
     506:         }
     507:     }
     508:     }
     509:
     510:     /*
     511:      * Pragmatics I: If old trailing whitespace or not enough characters to
     512:      * save to be worth it, then don't save the last same info.
     513:      */
     514:     if ((oe - ols) < MIN_END_KEEP) {
     515:     ols = oe;
     516:     nls = ne;
     517:     }
     518:
     519:     /*
     520:      * Pragmatics II: if the terminal isn't smart enough, make the data dumber
     521:      * so the smart update doesn't try anything fancy
     522:      */
     523:
     524:     /*
     525:      * fx is the number of characters we need to insert/delete: in the
     526:      * beginning to bring the two same begins together
     527:      */
     528:     fx = (nsb - nfd) - (osb - ofd);
     529:     /*
     530:      * sx is the number of characters we need to insert/delete: in the end to
     531:      * bring the two same last parts together
     532:      */
     533:     sx = (nls - nse) - (ols - ose);
     534:
     535:     if (!T_CanIns) {
     536:     if (fx > 0) {
     537:         osb = ols;
     538:         ose = ols;
     539:         nsb = nls;
     540:         nse = nls;
     541:     }
     542:     if (sx > 0) {
     543:         ols = oe;
     544:         nls = ne;
     545:     }
     546:     if ((ols - ofd) < (nls - nfd)) {
     547:         ols = oe;
     548:         nls = ne;
     549:     }
     550:     }
     551:     if (!T_CanDel) {
     552:     if (fx < 0) {
     553:         osb = ols;
     554:         ose = ols;
     555:         nsb = nls;
     556:         nse = nls;
     557:     }
     558:     if (sx < 0) {
     559:         ols = oe;
     560:         nls = ne;
     561:     }
     562:     if ((ols - ofd) > (nls - nfd)) {
     563:         ols = oe;
     564:         nls = ne;
     565:     }
     566:     }
     567:
     568:     /*
     569:      * Pragmatics III: make sure the middle shifted pointers are correct if
     570:      * they don't point to anything (we may have moved ols or nls).
     571:      */
     572:     if (osb == ose) {
     573:     osb = ols;
     574:     ose = ols;
     575:     nsb = nls;
     576:     nse = nls;
     577:     }
     578:
     579:     /*
     580:      * Now that we are done with pragmatics we recompute fx, sx
     581:      */
     582:     fx = (nsb - nfd) - (osb - ofd);
     583:     sx = (nls - nse) - (ols - ose);
     584:
     585: #ifdef DEBUG_UPDATE
     586:     xprintf("\n");
     587:     xprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
     588:         ofd - old, osb - old, ose - old, ols - old, oe - old);
     589:     xprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
     590:         nfd - new, nsb - new, nse - new, nls - new, ne - new);
     591:     xprintf("old:\"%s\"\r\n", short2str(old));
     592:     xprintf("new:\"%s\"\r\n", short2str(new));
     593:     xprintf("ofd:\"%s\"\r\n", short2str(ofd));
     594:     xprintf("nfd:\"%s\"\r\n", short2str(nfd));
     595:     xprintf("ols:\"%s\"\r\n", short2str(ols));
     596:     xprintf("nls:\"%s\"\r\n", short2str(nls));
     597:     xprintf("*oe:%o,*ne:%o\r\n", *oe, *ne);
     598:     xprintf("osb:\"%s\"\r\n", short2str(osb));
     599:     xprintf("ose:\"%s\"\r\n", short2str(ose));
     600:     xprintf("nsb:\"%s\"\r\n", short2str(nsb));
     601:     xprintf("nse:\"%s\"\r\n", short2str(nse));
     602: #endif				/* DEBUG_UPDATE */
     603:
     604:     /*
     605:      * CursorV to this line cur_line MUST be in this routine so that if we
     606:      * don't have to change the line, we don't move to it. CursorH to first
     607:      * diff char
     608:      */
     609:     MoveToLine(cur_line);
     610:
     611:     /*
     612:      * at this point we have something like this:
     613:      *
     614:      * /old                  /ofd    /osb               /ose    /ols     /oe
     615:      * v.....................v       v..................v       v........v
     616:      * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
     617:      * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
     618:      * ^.....................^     ^..................^       ^........^
     619:      * \new                  \nfd  \nsb               \nse     \nls    \ne
     620:      *
     621:      */
     622:
     623:     /*
     624:      * if we have a net insert on the first difference, AND inserting the net
     625:      * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
     626:      * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
     627:      * (TermH) else we do the deletes first so that we keep everything we need
     628:      * to.
     629:      */
     630:
     631:     /*
     632:      * if the last same is the same like the end, there is no last same part,
     633:      * otherwise we want to keep the last same part set p to the last useful
     634:      * old character
     635:      */
     636:     p = (ols != oe) ? oe : ose;
     637:
     638:     /*
     639:      * if (There is a diffence in the beginning) && (we need to insert
     640:      * characters) && (the number of characters to insert is less than the term
     641:      * width) We need to do an insert! else if (we need to delete characters)
     642:      * We need to delete characters! else No insert or delete
     643:      */
     644:     if ((nsb != nfd) && fx > 0 && ((p - old) + fx <= TermH)) {
     645: #ifdef DEBUG_UPDATE
     646:     DEBUGPRINT("\nfirst diff insert at %d...\n", nfd - new);
     647: #endif				/* DEBUG_UPDATE */
     648:     /*
     649: 	 * Move to the first char to insert, where the first diff is.
     650: 	 */
     651:     MoveToChar(nfd - new);
     652:     /*
     653: 	 * Check if we have stuff to keep at end
     654: 	 */
     655:     if (nsb != ne) {
     656: #ifdef DEBUG_UPDATE
     657:         DEBUGPRINT("\nwith stuff to keep at end\n", 0);
     658: #endif				/* DEBUG_UPDATE */
     659:         /*
     660: 	     * insert fx chars of new starting at nfd
     661: 	     */
     662:         if (fx > 0) {
     663: #ifdef DEBUG_UPDATE
     664:         if (!T_CanIns)
     665:             xprintf("   ERROR: cannot insert in early first diff\n");
     666: #endif				/* DEBUG_UPDATE */
     667:         Insert_write(nfd, fx);
     668:         str_insert(old, ofd - old, TermH, nfd, fx);
     669:         }
     670:         /*
     671: 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
     672: 	     */
     673:         so_write(nfd + fx, (nsb - nfd) - fx);
     674:         str_cp(ofd + fx, nfd + fx, (nsb - nfd) - fx);
     675:     }
     676:     else {
     677: #ifdef DEBUG_UPDATE
     678:         DEBUGPRINT("\nwithout anything to save\n", 0);
     679: #endif				/* DEBUG_UPDATE */
     680:         so_write(nfd, (nsb - nfd));
     681:         str_cp(ofd, nfd, (nsb - nfd));
     682:         /*
     683: 	     * Done
     684: 	     */
     685:         return;
     686:     }
     687:     }
     688:     else if (fx < 0) {
     689: #ifdef DEBUG_UPDATE
     690:     DEBUGPRINT("\nfirst diff delete at %d...\n", ofd - old);
     691: #endif				/* DEBUG_UPDATE */
     692:     /*
     693: 	 * move to the first char to delete where the first diff is
     694: 	 */
     695:     MoveToChar(ofd - old);
     696:     /*
     697: 	 * Check if we have stuff to save
     698: 	 */
     699:     if (osb != oe) {
     700: #ifdef DEBUG_UPDATE
     701:         DEBUGPRINT("\nwith stuff to save at end\n", 0);
     702: #endif				/* DEBUG_UPDATE */
     703:         /*
     704: 	     * fx is less than zero *always* here but we check for code
     705: 	     * symmetry
     706: 	     */
     707:         if (fx < 0) {
     708:         if (!T_CanDel)
     709:             xprintf("   ERROR: cannot delete in first diff\n");
     710:         DeleteChars(-fx);
     711:         str_delete(old, ofd - old, TermH, -fx);
     712:         }
     713:         /*
     714: 	     * write (nsb-nfd) chars of new starting at nfd
     715: 	     */
     716:         so_write(nfd, (nsb - nfd));
     717:         str_cp(ofd, nfd, (nsb - nfd));
     718:
     719:     }
     720:     else {
     721: #ifdef DEBUG_UPDATE
     722:         DEBUGPRINT("\nbut with nothing left to save\n", 0);
     723: #endif				/* DEBUG_UPDATE */
     724:         /*
     725: 	     * write (nsb-nfd) chars of new starting at nfd
     726: 	     */
     727:         so_write(nfd, (nsb - nfd));
     728: #ifdef DEBUG_UPDATE
     729:         DEBUGPRINT("cleareol %d\n", (oe - old) - (ne - new));
     730: #endif				/* DEBUG_UPDATE */
     731:         ClearEOL((oe - old) - (ne - new));
     732:         /*
     733: 	     * Done
     734: 	     */
     735:         return;
     736:     }
     737:     }
     738:     else
     739:     fx = 0;
     740:
     741:     if (sx < 0) {
     742: #ifdef DEBUG_UPDATE
     743:     DEBUGPRINT("\nsecond diff delete at %d...\n", (ose - old) + fx);
     744: #endif				/* DEBUG_UPDATE */
     745:     /*
     746: 	 * Check if we have stuff to delete
     747: 	 */
     748:     /*
     749: 	 * fx is the number of characters inserted (+) or deleted (-)
     750: 	 */
     751:     MoveToChar((ose - old) + fx);
     752:     if (ols != oe) {
     753: #ifdef DEBUG_UPDATE
     754:         DEBUGPRINT("\nwith stuff to save at end\n", 0);
     755: #endif				/* DEBUG_UPDATE */
     756:         /*
     757: 	     * Again a duplicate test.
     758: 	     */
     759:         if (sx < 0) {
     760: #ifdef DEBUG_UPDATE
     761:         if (!T_CanDel)
     762:             xprintf("   ERROR: cannot delete in second diff\n");
     763: #endif				/* DEBUG_UPDATE */
     764:         DeleteChars(-sx);
     765:         }
     766:
     767:         /*
     768: 	     * write (nls-nse) chars of new starting at nse
     769: 	     */
     770:         so_write(nse, (nls - nse));
     771:     }
     772:     else {
     773: #ifdef DEBUG_UPDATE
     774:         DEBUGPRINT("\nbut with nothing left to save\n", 0);
     775: #endif				/* DEBUG_UPDATE */
     776:         so_write(nse, (nls - nse));
     777: #ifdef DEBUG_UPDATE
     778:         DEBUGPRINT("cleareol %d\n", (oe - old) - (ne - new));
     779: #endif				/* DEBUG_UPDATE */
     780:         ClearEOL((oe - old) - (ne - new));
     781:     }
     782:     }
     783:
     784:     /*
     785:      * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
     786:      */
     787:     if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
     788: #ifdef DEBUG_UPDATE
     789:     DEBUGPRINT("\nlate first diff insert at %d...\n", nfd - new);
     790: #endif				/* DEBUG_UPDATE */
     791:     MoveToChar(nfd - new);
     792:     /*
     793: 	 * Check if we have stuff to keep at the end
     794: 	 */
     795:     if (nsb != ne) {
     796: #ifdef DEBUG_UPDATE
     797:         DEBUGPRINT("\nwith stuff to keep at end\n", 0);
     798: #endif				/* DEBUG_UPDATE */
     799:         if (fx > 0) {
     800:         /*
     801: 		 * insert fx chars of new starting at nfd
     802: 		 */
     803: #ifdef DEBUG_UPDATE
     804:         if (!T_CanIns)
     805:             xprintf("   ERROR: cannot insert in late first diff\n");
     806: #endif				/* DEBUG_UPDATE */
     807:         Insert_write(nfd, fx);
     808:         str_insert(old, ofd - old, TermH, nfd, fx);
     809:         }
     810:
     811:         /*
     812: 	     * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
     813: 	     */
     814:         so_write(nfd + fx, (nsb - nfd) - fx);
     815:         str_cp(ofd + fx, nfd + fx, (nsb - nfd) - fx);
     816:     }
     817:     else {
     818: #ifdef DEBUG_UPDATE
     819:         DEBUGPRINT("\nwithout anything to save\n", 0);
     820: #endif				/* DEBUG_UPDATE */
     821:         so_write(nfd, (nsb - nfd));
     822:         str_cp(ofd, nfd, (nsb - nfd));
     823:     }
     824:     }
     825:
     826:     /*
     827:      * line is now NEW up to nse
     828:      */
     829:     if ((nls != nse) && has_other_than_spaces(nse, (nls - nse)) && sx >= 0) {
     830: #ifdef DEBUG_UPDATE
     831:     DEBUGPRINT("\nsecond diff insert at %d...\n", nse - new);
     832: #endif				/* DEBUG_UPDATE */
     833:     MoveToChar(nse - new);
     834:     if (nls != ne) {
     835: #ifdef DEBUG_UPDATE
     836:         DEBUGPRINT("\nwith stuff to keep at end\n", 0);
     837: #endif				/* DEBUG_UPDATE */
     838:         if (sx > 0) {
     839:         /* insert sx chars of new starting at nse */
     840: #ifdef DEBUG_UPDATE
     841:         if (!T_CanIns)
     842:             xprintf("   ERROR: cannot insert in second diff\n");
     843: #endif				/* DEBUG_UPDATE */
     844:         Insert_write(nse, sx);
     845:         }
     846:
     847:         /*
     848: 	     * write (nls-nse) - sx chars of new starting at (nse + sx)
     849: 	     */
     850:         so_write(nse + sx, (nls - nse) - sx);
     851:     }
     852:     else {
     853: #ifdef DEBUG_UPDATE
     854:         DEBUGPRINT("\nwithout anything to save\n", 0);
     855: #endif				/* DEBUG_UPDATE */
     856:         so_write(nse, (nls - nse));
     857:     }
     858:     }
     859: #ifdef DEBUG_UPDATE
     860:     DEBUGPRINT("\ndone.\n", 0);
     861: #endif				/* DEBUG_UPDATE */
     862: }
     863:
     864: void
     865: RefCursor()
     866: {               /* only move to new cursor pos */
     867:     register Char *cp, c;
     868:     register int h, th, v;
     869:
     870:     if (DoingSearch) {
     871:     Refresh();
     872:     return;
     873:     }
     874:
     875:     /* first we must find where the cursor is... */
     876:     h = 0;
     877:     v = 0;
     878:     th = TermH;         /* optimize for speed */
     879:
     880:     for (cp = PromptBuf; *cp; cp++) {   /* do prompt */
     881:     if (*cp & LITERAL)
     882:         continue;
     883:     c = *cp & CHAR;     /* extra speed plus strip the inverse */
     884:     h++;            /* all chars at least this long */
     885:
     886:     /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
     887:     /* lets handle newline as part of the prompt */
     888:
     889:     if (c == '\n') {
     890:         h = 0;
     891:         v++;
     892:     }
     893:     else {
     894:         if (c == '\t') {    /* if a tab, to next tab stop */
     895:         while (h & 07) {
     896:             h++;
     897:         }
     898:         }
     899:         else if (Iscntrl(c)) {  /* if control char */
     900:         h++;
     901:         if (h > th) {   /* if overflow, compensate */
     902:             h = 1;
     903:             v++;
     904:         }
     905:         }
     906:         else if (!Isprint(c)) {
     907:         h += 3;
     908:         if (h > th) {   /* if overflow, compensate */
     909:             h = h - th;
     910:             v++;
     911:         }
     912:         }
     913:     }
     914:
     915:     if (h >= th) {      /* check, extra long tabs picked up here also */
     916:         h = 0;
     917:         v++;
     918:     }
     919:     }
     920:
     921:     for (cp = InputBuf; cp < Cursor; cp++) {    /* do input buffer to Cursor */
     922:     c = *cp & CHAR;     /* extra speed plus strip the inverse */
     923:     h++;            /* all chars at least this long */
     924:
     925:     if (c == '\n') {    /* handle newline in data part too */
     926:         h = 0;
     927:         v++;
     928:     }
     929:     else {
     930:         if (c == '\t') {    /* if a tab, to next tab stop */
     931:         while (h & 07) {
     932:             h++;
     933:         }
     934:         }
     935:         else if (Iscntrl(c)) {  /* if control char */
     936:         h++;
     937:         if (h > th) {   /* if overflow, compensate */
     938:             h = 1;
     939:             v++;
     940:         }
     941:         }
     942:         else if (!Isprint(c)) {
     943:         h += 3;
     944:         if (h > th) {   /* if overflow, compensate */
     945:             h = h - th;
     946:             v++;
     947:         }
     948:         }
     949:     }
     950:
     951:     if (h >= th) {      /* check, extra long tabs picked up here also */
     952:         h = 0;
     953:         v++;
     954:     }
     955:     }
     956:
     957:     /* now go there */
     958:     MoveToLine(v);
     959:     MoveToChar(h);
     960:     flush();
     961: }
     962:
     963: static void
     964: PutPlusOne(c)
     965:     int    c;
     966: {
     967:     (void) putraw(c);
     968:     Display[CursorV][CursorH++] = c;
     969:     if (CursorH >= TermH) { /* if we must overflow */
     970:     CursorH = 0;
     971:     CursorV++;
     972:     OldvcV++;
     973:     (void) putraw('\r');
     974:     (void) putraw('\n');
     975:     }
     976: }
     977:
     978: void
     979: RefPlusOne()
     980: {               /* we added just one char, handle it fast *//* a
     981: 				 * ssumes that screen cursor == real cursor */
     982:     register Char c, mc;
     983:
     984:     c = Cursor[-1] & CHAR;  /* the char we just added */
     985:
     986:     if (c == '\t' || Cursor != LastChar) {
     987:     Refresh();      /* too hard to handle */
     988:     return;
     989:     }               /* else (only do at end of line, no TAB) */
     990:
     991:     if (DoingSearch) {
     992:     Refresh();
     993:     return;
     994:     }
     995:
     996:     if (Iscntrl(c)) {       /* if control char, do caret */
     997:     mc = (c == '\177') ? '?' : (c | 0100);
     998:     PutPlusOne('^');
     999:     PutPlusOne(mc);
    1000:     }
    1001:     else if (Isprint(c)) {  /* normal char */
    1002:     PutPlusOne(c);
    1003:     }
    1004:     else {
    1005:     PutPlusOne('\\');
    1006:     PutPlusOne(((c >> 6) & 7) + '0');
    1007:     PutPlusOne(((c >> 3) & 7) + '0');
    1008:     PutPlusOne((c & 7) + '0');
    1009:     }
    1010:     flush();
    1011: }
    1012:
    1013: /* clear the screen buffers so that new new prompt starts fresh. */
    1014:
    1015: void
    1016: ClearDisp()
    1017: {
    1018:     register int i;
    1019:
    1020:     CursorV = 0;        /* clear the display buffer */
    1021:     CursorH = 0;
    1022:     for (i = 0; i < TermV; i++)
    1023:     Display[i][0] = '\0';
    1024:     OldvcV = 0;
    1025: }
    1026:
    1027: void
    1028: ClearLines()
    1029: {               /* Make sure all lines are *really* blank */
    1030:     register int i;
    1031:
    1032:     if (T_CanCEOL) {
    1033:     MoveToChar(0);
    1034:     for (i = 0; i <= OldvcV; i++) { /* for each line on the screen */
    1035:         MoveToLine(i);
    1036:         ClearEOL(TermH);
    1037:     }
    1038:     MoveToLine(0);
    1039:     }
    1040:     else {
    1041:     MoveToLine(OldvcV); /* go to last line */
    1042:     (void) putraw('\r');    /* go to BOL */
    1043:     (void) putraw('\n');    /* go to new line */
    1044:     }
    1045: }

#### Defined functions

ClearDisp defined in line 1015; used 13 times

- in line 278
- in /usr/src/bin/tcsh/ed.init.c line 168
- in /usr/src/bin/tcsh/ed.inputl.c line 83, 233, 246, 305, 334, 348, 371
- in /usr/src/bin/tcsh/ed.refresh.c line 278
- in /usr/src/bin/tcsh/ed.screen.c line 1419
- in /usr/src/bin/tcsh/sh.proc.c line 429
- in /usr/src/bin/tcsh/tc.sched.c line 260

ClearLines defined in line 1027; used 8 times

- in /usr/src/bin/tcsh/ed.init.c line 167
- in /usr/src/bin/tcsh/ed.inputl.c line 232, 245, 304, 333, 347
- in /usr/src/bin/tcsh/sh.proc.c line 428
- in /usr/src/bin/tcsh/tc.sched.c line 259

Draw defined in line 64; used 4 times

- in line 191, 201, 208, 214

GotoBottom defined in line 265; never used
PastBottom defined in line 272; used 2 times

- in /usr/src/bin/tcsh/ed.inputl.c line 297, 303

PutPlusOne defined in line 963; used 7 times

- in line 998-1008(7)

RefCursor defined in line 864; never used
RefPlusOne defined in line 978; never used
Refresh defined in line 148; used 21 times

- in line 871, 987-992(2)
- in /usr/src/bin/tcsh/ed.init.c line 172
- in /usr/src/bin/tcsh/ed.inputl.c line 114, 156, 199, 236, 249, 308, 316, 323, 337, 351, 361, 373
- in /usr/src/bin/tcsh/ed.refresh.c line 871, 987-992(2)
- in /usr/src/bin/tcsh/sh.proc.c line 430
- in /usr/src/bin/tcsh/tc.sched.c line 261

Vdraw defined in line 106; used 12 times

- in line 71-76(2), 83, 89-102(7), 181, 223

Vnewline defined in line 134; used 1 times

- in line 206

has_other_than_spaces defined in line 282; used 1 times

- in line 829

rcsid defined in line 39; never used
str_cp defined in line 379; used 5 times

- in line 674, 681, 717, 815, 822

str_delete defined in line 346; used 1 times

- in line 711

str_insert defined in line 300; used 2 times

- in line 668, 808

update_line defined in line 415; used 1 times

- in line 233

#### Defined variables

OldvcV defined in line 147; used 10 times

- in line 239-242(3), 252, 267, 275, 972, 1024, 1034, 1041

litptr defined in line 51; used 4 times

- in line 171-175(4)

vcur_h defined in line 52; used 11 times

- in line 77, 84, 118-122(4), 165, 198, 211, 219, 228

vcur_v defined in line 52; used 13 times

- in line 78, 118-127(5), 166, 199, 212, 220-222(2), 228, 239

#### Defined macros

MIN_END_KEEP defined in line 413; used 1 times

- in line 514

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2178 |