Annotation of coherent/g/usr/bin/vi/redraw.c, revision 1.1

1.1     ! root        1: /* redraw.c */
        !             2: 
        !             3: /* Author:
        !             4:  *     Steve Kirkendall
        !             5:  *     14407 SW Teal Blvd. #C
        !             6:  *     Beaverton, OR 97005
        !             7:  *     [email protected]
        !             8:  */
        !             9: 
        !            10: 
        !            11: /* This file contains functions that draw text on the screen.  The major entry
        !            12:  * points are:
        !            13:  *     redrawrange()   - called from modify.c to give hints about what parts
        !            14:  *                       of the screen need to be redrawn.
        !            15:  *     redraw()        - redraws the screen (or part of it) and positions
        !            16:  *                       the cursor where it belongs.
        !            17:  *     idx2col()       - converts a markidx() value to a logical column number.
        !            18:  */
        !            19: 
        !            20: #include "config.h"
        !            21: #include "vi.h"
        !            22: #ifdef CRUNCH
        !            23: # define NEAR  LINES
        !            24: #else
        !            25: # define NEAR  (*o_nearscroll&0xff)
        !            26: #endif
        !            27: 
        !            28: /* This variable contains the line number that smartdrawtext() knows best */
        !            29: static long smartlno;
        !            30: 
        !            31: /* This function remembers where changes were made, so that the screen can be
        !            32:  * redraw in a more efficient manner.
        !            33:  */
        !            34: static long    redrawafter;    /* line# of first line that must be redrawn */
        !            35: static long    preredraw;      /* line# of last line changed, before change */
        !            36: static long    postredraw;     /* line# of last line changed, after change */
        !            37: static int     mustredraw;     /* boolean: anything forcing a screen update? */
        !            38: void redrawrange(after, pre, post)
        !            39:        long    after;  /* lower bound of redrawafter */
        !            40:        long    pre;    /* upper bound of preredraw */
        !            41:        long    post;   /* upper bound of postredraw */
        !            42: {
        !            43:        if (after == redrawafter)
        !            44:        {
        !            45:                /* multiple insertions/deletions at the same place -- combine
        !            46:                 * them
        !            47:                 */
        !            48:                preredraw -= (post - pre);
        !            49:                if (postredraw < post)
        !            50:                {
        !            51:                        preredraw += (post - postredraw);
        !            52:                        postredraw = post;
        !            53:                }
        !            54:                if (redrawafter > preredraw)
        !            55:                {
        !            56:                        redrawafter = preredraw;
        !            57:                }
        !            58:                if (redrawafter < 1L)
        !            59:                {
        !            60:                        redrawafter = 0L;
        !            61:                        preredraw = postredraw = INFINITY;
        !            62:                }
        !            63:        }
        !            64:        else if (postredraw > 0L)
        !            65:        {
        !            66:                /* multiple changes in different places -- redraw everything
        !            67:                 * after "after".
        !            68:                 */
        !            69:                postredraw = preredraw = INFINITY;
        !            70:                if (after < redrawafter)
        !            71:                        redrawafter = after;
        !            72:        }
        !            73:        else
        !            74:        {
        !            75:                /* first change */
        !            76:                redrawafter = after;
        !            77:                preredraw = pre;
        !            78:                postredraw = post;
        !            79:        }
        !            80:        mustredraw = TRUE;
        !            81: }
        !            82: 
        !            83: 
        !            84: #ifndef NO_CHARATTR
        !            85: /* see if a given line uses character attribute strings */
        !            86: static int hasattr(lno, text)
        !            87:        long            lno;    /* the line# of the cursor */
        !            88:        REG char        *text;  /* the text of the line, from fetchline */
        !            89: {
        !            90:        static long     plno;   /* previous line number */
        !            91:        static long     chgs;   /* previous value of changes counter */
        !            92:        static int      panswer;/* previous answer */
        !            93:        char            *scan;
        !            94: 
        !            95:        /* if charattr is off, then the answer is "no, it doesn't" */
        !            96:        if (!*o_charattr)
        !            97:        {
        !            98:                chgs = 0; /* <- forces us to check if charattr is later set */
        !            99:                return FALSE;
        !           100:        }
        !           101: 
        !           102:        /* if we already know the answer, return it... */
        !           103:        if (lno == plno && chgs == changes)
        !           104:        {
        !           105:                return panswer;
        !           106:        }
        !           107: 
        !           108:        /* get the line & look for "\fX" */
        !           109:        if (!text[0] || !text[1] || !text[2])
        !           110:        {
        !           111:                panswer = FALSE;
        !           112:        }
        !           113:        else
        !           114:        {
        !           115:                for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
        !           116:                {
        !           117:                }
        !           118:                panswer = (scan[2] != '\0');
        !           119:        }
        !           120: 
        !           121:        /* save the results */
        !           122:        plno = lno;
        !           123:        chgs = changes;
        !           124: 
        !           125:        /* return the results */
        !           126:        return panswer;
        !           127: }
        !           128: #endif
        !           129: 
        !           130: 
        !           131: #ifndef NO_VISIBLE
        !           132: /* This function checks to make sure that the correct lines are shown in
        !           133:  * reverse-video.  This is used to handle the "v" and "V" commands.
        !           134:  */
        !           135: static long    vizlow, vizhigh;        /* the starting and ending lines */
        !           136: static int     vizleft, vizright;      /* starting & ending indicies */
        !           137: static int     vizchange;              /* boolean: must use stupid drawtext? */
        !           138: static void setviz(curs)
        !           139:        MARK            curs;
        !           140: {
        !           141:        long            newlow, newhigh;
        !           142:        long            extra = 0L;
        !           143: 
        !           144:        /* for now, assume the worst... */
        !           145:        vizchange = TRUE;
        !           146: 
        !           147:        /* set newlow & newhigh according to V_from and cursor */
        !           148:        if (!V_from)
        !           149:        {
        !           150:                /* no lines should have reverse-video */
        !           151:                if (vizlow)
        !           152:                {
        !           153:                        redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
        !           154:                        vizlow = vizhigh = 0L;
        !           155:                }
        !           156:                else
        !           157:                {
        !           158:                        vizchange = FALSE;
        !           159:                }
        !           160:                return;
        !           161:        }
        !           162: 
        !           163:        /* figure out which lines *SHOULD* have hilites */
        !           164:        if (V_from < curs)
        !           165:        {
        !           166:                newlow = markline(V_from);
        !           167:                newhigh = markline(curs);
        !           168:                vizleft = markidx(V_from);
        !           169:                vizright = markidx(curs) + 1;
        !           170:        }
        !           171:        else
        !           172:        {
        !           173:                newlow = markline(curs);
        !           174:                newhigh = markline(V_from);
        !           175:                vizleft = markidx(curs);
        !           176:                vizright = markidx(V_from) + 1;
        !           177:        }
        !           178: 
        !           179:        /* adjust for line-mode hiliting */
        !           180:        if (V_linemd)
        !           181:        {
        !           182:                vizleft = 0;
        !           183:                vizright = BLKSIZE - 1;
        !           184:        }
        !           185:        else
        !           186:        {
        !           187:                extra = 1L;
        !           188:        }
        !           189: 
        !           190:        /* arrange for the necessary lines to be redrawn */
        !           191:        if (vizlow == 0L)
        !           192:        {
        !           193:                /* just starting to redraw */
        !           194:                redrawrange(newlow, newhigh, newhigh);
        !           195:        }
        !           196:        else
        !           197:        {
        !           198:                /* Were new lines added/removed at the front? */
        !           199:                if (newlow != vizlow)
        !           200:                {
        !           201:                        if (newlow < vizlow)
        !           202:                                redrawrange(newlow, vizlow + extra, vizlow + extra);
        !           203:                        else
        !           204:                                redrawrange(vizlow, newlow + extra, newlow + extra);
        !           205:                }
        !           206: 
        !           207:                /* Were new lines added/removed at the back? */
        !           208:                if (newhigh != vizhigh)
        !           209:                {
        !           210:                        if (newhigh < vizhigh)
        !           211:                                redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
        !           212:                        else
        !           213:                                redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
        !           214:                }
        !           215:        }
        !           216: 
        !           217:        /* remember which lines will contain hilighted text now */
        !           218:        vizlow = newlow;
        !           219:        vizhigh = newhigh;
        !           220: }
        !           221: #endif /* !NO_VISIBLE */
        !           222: 
        !           223: 
        !           224: /* This function converts a MARK to a column number.  It doesn't automatically
        !           225:  * adjust for leftcol; that must be done by the calling function
        !           226:  */
        !           227: int idx2col(curs, text, inputting)
        !           228:        MARK            curs;   /* the line# & index# of the cursor */
        !           229:        REG char        *text;  /* the text of the line, from fetchline */
        !           230:        int             inputting;      /* boolean: called from input() ? */
        !           231: {
        !           232:        static MARK     pcursor;/* previous cursor, for possible shortcut */
        !           233:        static MARK     pcol;   /* column number for pcol */
        !           234:        static long     chgs;   /* previous value of changes counter */
        !           235:        REG int         col;    /* used to count column numbers */
        !           236:        REG int         idx;    /* used to count down the index */
        !           237:        REG int         i;
        !           238: 
        !           239:        /* for now, assume we have to start counting at the left edge */
        !           240:        col = 0;
        !           241:        idx = markidx(curs);
        !           242: 
        !           243:        /* if the file hasn't changed & line number is the same & it has no
        !           244:         * embedded character attribute strings, can we do shortcuts?
        !           245:         */
        !           246:        if (chgs == changes
        !           247:         && !((curs ^ pcursor) & ~(BLKSIZE - 1))
        !           248: #ifndef NO_CHARATTR
        !           249:         && !hasattr(markline(curs), text)
        !           250: #endif
        !           251:        )
        !           252:        {
        !           253:                /* no movement? */
        !           254:                if (curs == pcursor)
        !           255:                {
        !           256:                        /* return the column of the char; for tabs, return its last column */
        !           257:                        if (text[idx] == '\t' && !inputting && !*o_list)
        !           258:                        {
        !           259:                                return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
        !           260:                        }
        !           261:                        else
        !           262:                        {
        !           263:                                return pcol;
        !           264:                        }
        !           265:                }
        !           266: 
        !           267:                /* movement to right? */
        !           268:                if (curs > pcursor)
        !           269:                {
        !           270:                        /* start counting from previous place */
        !           271:                        col = pcol;
        !           272:                        idx = markidx(curs) - markidx(pcursor);
        !           273:                        text += markidx(pcursor);
        !           274:                }
        !           275:        }
        !           276: 
        !           277:        /* count over to the char after the idx position */
        !           278:        while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
        !           279:        {
        !           280:                if (i == '\t' && !*o_list)
        !           281:                {
        !           282:                        col += *o_tabstop;
        !           283:                        col -= col % *o_tabstop;
        !           284:                }
        !           285:                else if (i >= '\0' && i < ' ' || i == '\177')
        !           286:                {
        !           287:                        col += 2;
        !           288:                }
        !           289: #ifndef NO_CHARATTR
        !           290:                else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
        !           291:                {
        !           292:                        text += 2; /* plus one more at bottom of loop */
        !           293:                        idx -= 2;
        !           294:                }                       
        !           295: #endif
        !           296:                else
        !           297:                {
        !           298:                        col++;
        !           299:                }
        !           300:                text++;
        !           301:                idx--;
        !           302:        }
        !           303: 
        !           304:        /* save stuff to speed next call */
        !           305:        pcursor = curs;
        !           306:        pcol = col;
        !           307:        chgs = changes;
        !           308: 
        !           309:        /* return the column of the char; for tabs, return its last column */
        !           310:        if (*text == '\t' && !inputting && !*o_list)
        !           311:        {
        !           312:                return col + *o_tabstop - (col % *o_tabstop) - 1;
        !           313:        }
        !           314:        else
        !           315:        {
        !           316:                return col;
        !           317:        }
        !           318: }
        !           319: 
        !           320: 
        !           321: /* This function is similar to idx2col except that it takes care of sideways
        !           322:  * scrolling - for the given line, at least.
        !           323:  */
        !           324: int mark2phys(m, text, inputting)
        !           325:        MARK    m;              /* a mark to convert */
        !           326:        char    *text;          /* the line that m refers to */
        !           327:        int     inputting;      /* boolean: caled from input() ? */
        !           328: {
        !           329:        int     i;
        !           330: 
        !           331:        i = idx2col(m, text, inputting);
        !           332:        while (i < leftcol)
        !           333:        {
        !           334:                leftcol -= *o_sidescroll;
        !           335:                mustredraw = TRUE;
        !           336:                redrawrange(1L, INFINITY, INFINITY);
        !           337:        }
        !           338:        while (i > rightcol)
        !           339:        {
        !           340:                leftcol += *o_sidescroll;
        !           341:                mustredraw = TRUE;
        !           342:                redrawrange(1L, INFINITY, INFINITY);
        !           343:        }
        !           344:        physrow = markline(m) - topline;
        !           345:        physcol = i - leftcol;
        !           346:        if (*o_number)
        !           347:                physcol += 8;
        !           348: 
        !           349:        return physcol;
        !           350: }
        !           351: 
        !           352: /* This function draws a single line of text on the screen.  The screen's
        !           353:  * cursor is assumed to be located at the leftmost column of the appropriate
        !           354:  * row.
        !           355:  */
        !           356: static void drawtext(text, lno, clr)
        !           357:        REG char        *text;  /* the text to draw */
        !           358:        long            lno;    /* the number of the line to draw */
        !           359:        int             clr;    /* boolean: do a clrtoeol? */
        !           360: {
        !           361:        REG int         col;    /* column number */
        !           362:        REG int         i;
        !           363:        REG int         tabstop;        /* *o_tabstop */
        !           364:        REG int         limitcol;       /* leftcol or leftcol + COLS */
        !           365:        int             abnormal;       /* boolean: charattr != A_NORMAL? */
        !           366: #ifndef NO_VISIBLE
        !           367:        int             rev;            /* boolean: standout mode, too? */
        !           368:        int             idx = 0;
        !           369: #endif
        !           370:        char            numstr[9];
        !           371: 
        !           372:        /* show the line number, if necessary */
        !           373:        if (*o_number)
        !           374:        {
        !           375:                sprintf(numstr, "%6ld  ", lno);
        !           376:                qaddstr(numstr);
        !           377:        }
        !           378: 
        !           379: #ifndef NO_SENTENCE
        !           380:        /* if we're hiding format lines, and this is one of them, then hide it */
        !           381:        if (*o_hideformat && *text == '.')
        !           382:        {
        !           383:                clrtoeol();
        !           384: #if OSK
        !           385:                qaddch('\l');
        !           386: #else
        !           387:                qaddch('\n');
        !           388: #endif
        !           389:                return;
        !           390:        }
        !           391: #endif
        !           392: 
        !           393:        /* move some things into registers... */
        !           394:        limitcol = leftcol;
        !           395:        tabstop = *o_tabstop;
        !           396:        abnormal = FALSE;
        !           397: 
        !           398: #ifndef CRUNCH
        !           399:        if (clr)
        !           400:                clrtoeol();
        !           401: #endif
        !           402: 
        !           403:        /* skip stuff that was scrolled off left edge */
        !           404:        for (col = 0;
        !           405:             (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
        !           406:             text++)
        !           407:        {
        !           408: #ifndef NO_VISIBLE
        !           409:                idx++;
        !           410: #endif
        !           411:                if (i == '\t' && !*o_list)
        !           412:                {
        !           413:                        col = col + tabstop - (col % tabstop);
        !           414:                }
        !           415:                else if (i >= 0 && i < ' ' || i == '\177')
        !           416:                {
        !           417:                        col += 2;
        !           418:                }
        !           419: #ifndef NO_CHARATTR
        !           420:                else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
        !           421:                {
        !           422:                        text += 2; /* plus one more as part of "for" loop */
        !           423: 
        !           424:                        /* since this attribute might carry over, we need it */
        !           425:                        switch (*text)
        !           426:                        {
        !           427:                          case 'R':
        !           428:                          case 'P':
        !           429:                                attrset(A_NORMAL);
        !           430:                                abnormal = FALSE;
        !           431:                                break;
        !           432: 
        !           433:                          case 'B':
        !           434:                                attrset(A_BOLD);
        !           435:                                abnormal = TRUE;
        !           436:                                break;
        !           437: 
        !           438:                          case 'U':
        !           439:                                attrset(A_UNDERLINE);
        !           440:                                abnormal = TRUE;
        !           441:                                break;
        !           442: 
        !           443:                          case 'I':
        !           444:                                attrset(A_ALTCHARSET);
        !           445:                                abnormal = TRUE;
        !           446:                                break;
        !           447:                        }
        !           448:                }
        !           449: #endif
        !           450:                else
        !           451:                {
        !           452:                        col++;
        !           453:                }
        !           454:        }
        !           455: 
        !           456: #ifndef NO_VISIBLE
        !           457:        /* Should we start hiliting at the first char of this line? */
        !           458:        if ((lno > vizlow && lno <= vizhigh
        !           459:            || lno == vizlow && vizleft < idx)
        !           460:           && !(lno == vizhigh && vizright < idx))
        !           461:        {
        !           462:                do_VISIBLE();
        !           463:                rev = TRUE;
        !           464:        }
        !           465: #endif
        !           466: 
        !           467:        /* adjust for control char that was partially visible */
        !           468:        while (col > limitcol)
        !           469:        {
        !           470:                qaddch(' ');
        !           471:                limitcol++;
        !           472:        }
        !           473: 
        !           474:        /* now for the visible characters */
        !           475:        limitcol = leftcol + COLS;
        !           476:        if (*o_number)
        !           477:                limitcol -= 8;
        !           478:        for (; (i = *text) && col < limitcol; text++)
        !           479:        {
        !           480: #ifndef NO_VISIBLE
        !           481:                /* maybe turn hilite on/off in the middle of the line */
        !           482:                if (lno == vizlow && vizleft == idx)
        !           483:                {
        !           484:                        do_VISIBLE();
        !           485:                        rev = TRUE;
        !           486:                }
        !           487:                if (lno == vizhigh && vizright == idx)
        !           488:                {
        !           489:                        do_SE();
        !           490:                        rev = FALSE;
        !           491:                }
        !           492:                idx++;
        !           493: 
        !           494:                /* if hiliting, never emit physical tabs */
        !           495:                if (rev && i == '\t' && !*o_list)
        !           496:                {
        !           497:                        i = col + tabstop - (col % tabstop);
        !           498:                        do
        !           499:                        {
        !           500:                                qaddch(' ');
        !           501:                                col++;
        !           502:                        } while (col < i && col < limitcol);
        !           503:                }
        !           504:                else
        !           505: #endif /* !NO_VISIBLE */
        !           506:                if (i == '\t' && !*o_list)
        !           507:                {
        !           508:                        i = col + tabstop - (col % tabstop);
        !           509:                        if (i < limitcol)
        !           510:                        {
        !           511: #ifdef CRUNCH
        !           512:                                if (!clr && has_PT && !((i - leftcol) & 7))
        !           513: #else
        !           514:                                if (has_PT && !((i - leftcol) & 7))
        !           515: #endif
        !           516:                                {
        !           517:                                        do
        !           518:                                        {
        !           519:                                                qaddch('\t');
        !           520:                                                col += 8; /* not exact! */
        !           521:                                        } while (col < i);
        !           522:                                        col = i; /* NOW it is exact */
        !           523:                                }
        !           524:                                else
        !           525:                                {
        !           526:                                        do
        !           527:                                        {
        !           528:                                                qaddch(' ');
        !           529:                                                col++;
        !           530:                                        } while (col < i && col < limitcol);
        !           531:                                }
        !           532:                        }
        !           533:                        else /* tab ending after screen? next line! */
        !           534:                        {
        !           535:                                col = limitcol;
        !           536:                                if (has_AM)
        !           537:                                {
        !           538:                                        addch('\n');    /* GB */
        !           539:                                }
        !           540:                        }
        !           541:                }
        !           542:                else if (i >= 0 && i < ' ' || i == '\177')
        !           543:                {
        !           544:                        col += 2;
        !           545:                        qaddch('^');
        !           546:                        if (col <= limitcol)
        !           547:                        {
        !           548:                                qaddch(i ^ '@');
        !           549:                        }
        !           550:                }
        !           551: #ifndef NO_CHARATTR
        !           552:                else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
        !           553:                {
        !           554:                        text += 2; /* plus one more as part of "for" loop */
        !           555:                        switch (*text)
        !           556:                        {
        !           557:                          case 'R':
        !           558:                          case 'P':
        !           559:                                attrset(A_NORMAL);
        !           560:                                abnormal = FALSE;
        !           561:                                break;
        !           562: 
        !           563:                          case 'B':
        !           564:                                attrset(A_BOLD);
        !           565:                                abnormal = TRUE;
        !           566:                                break;
        !           567: 
        !           568:                          case 'U':
        !           569:                                attrset(A_UNDERLINE);
        !           570:                                abnormal = TRUE;
        !           571:                                break;
        !           572: 
        !           573:                          case 'I':
        !           574:                                attrset(A_ALTCHARSET);
        !           575:                                abnormal = TRUE;
        !           576:                                break;
        !           577:                        }
        !           578:                }
        !           579: #endif
        !           580:                else
        !           581:                {
        !           582:                        col++;
        !           583:                        qaddch(i);
        !           584:                }
        !           585:        }
        !           586: 
        !           587:        /* get ready for the next line */
        !           588: #ifndef NO_CHARATTR
        !           589:        if (abnormal)
        !           590:        {
        !           591:                attrset(A_NORMAL);
        !           592:        }
        !           593: #endif
        !           594:        if (*o_list && col < limitcol)
        !           595:        {
        !           596:                qaddch('$');
        !           597:                col++;
        !           598:        }
        !           599: 
        !           600: #ifndef NO_VISIBLE
        !           601:        /* did we hilite this whole line?  If so, STOP! */
        !           602:        if (rev)
        !           603:        {
        !           604:                do_SE();
        !           605:        }
        !           606: #endif
        !           607: 
        !           608: #ifdef CRUNCH
        !           609:        if (clr && col < limitcol)
        !           610:        {
        !           611:                clrtoeol();
        !           612:        }
        !           613: #endif
        !           614:        if (!has_AM || col < limitcol)
        !           615:        {
        !           616:                addch('\n');
        !           617:        }
        !           618: 
        !           619:        wqrefresh();
        !           620: }
        !           621: 
        !           622: 
        !           623: #ifndef CRUNCH
        !           624: static void nudgecursor(same, scan, new, lno)
        !           625:        int     same;   /* number of chars to be skipped over */
        !           626:        char    *scan;  /* where the same chars end */
        !           627:        char    *new;   /* where the visible part of the line starts */
        !           628:        long    lno;    /* line number of this line */
        !           629: {
        !           630:        int     col;
        !           631: 
        !           632:        if (same > 0)
        !           633:        {
        !           634:                if (same < 5)
        !           635:                {
        !           636:                        /* move the cursor by overwriting */
        !           637:                        while (same > 0)
        !           638:                        {
        !           639:                                qaddch(scan[-same]);
        !           640:                                same--;
        !           641:                        }
        !           642:                }
        !           643:                else
        !           644:                {
        !           645:                        /* move the cursor by calling move() */
        !           646:                        col = (int)(scan - new);
        !           647:                        if (*o_number)
        !           648:                                col += 8;
        !           649:                        move((int)(lno - topline), col);
        !           650:                }
        !           651:        }
        !           652: }
        !           653: #endif /* not CRUNCH */
        !           654: 
        !           655: /* This function draws a single line of text on the screen, possibly with
        !           656:  * some cursor optimization.  The cursor is repositioned before drawing
        !           657:  * begins, so its position before doesn't really matter.
        !           658:  */
        !           659: static void smartdrawtext(text, lno, showit)
        !           660:        REG char        *text;  /* the text to draw */
        !           661:        long            lno;    /* line number of the text */
        !           662:        int             showit; /* boolean: output line? (else just remember it) */
        !           663: {
        !           664: #ifdef CRUNCH
        !           665:        move((int)(lno - topline), 0);
        !           666:        if (showit)
        !           667:        {
        !           668:                drawtext(text, lno, TRUE);
        !           669:        }
        !           670: #else /* not CRUNCH */
        !           671:        static char     old[256];       /* how the line looked last time */
        !           672:        char            new[256];       /* how it looks now */
        !           673:        char            *build;         /* used to put chars into new[] */
        !           674:        char            *scan;          /* used for moving thru new[] or old[] */
        !           675:        char            *end;           /* last non-blank changed char */
        !           676:        char            *shift;         /* used to insert/delete chars */
        !           677:        int             same;           /* length of a run of unchanged chars */
        !           678:        int             limitcol;
        !           679:        int             col;
        !           680:        int             i;
        !           681:        char            numstr[9];
        !           682: 
        !           683: # ifndef NO_CHARATTR
        !           684:        /* if this line has attributes, do it the dumb way instead */
        !           685:        if (hasattr(lno, text))
        !           686:        {
        !           687:                move((int)(lno - topline), 0);
        !           688:                drawtext(text, lno, TRUE);
        !           689:                return;
        !           690:        }
        !           691: # endif
        !           692: # ifndef NO_SENTENCE
        !           693:        /* if this line is a format line, & we're hiding format lines, then
        !           694:         * let the dumb drawtext() function handle it
        !           695:         */
        !           696:        if (*o_hideformat && *text == '.')
        !           697:        {
        !           698:                move((int)(lno - topline), 0);
        !           699:                drawtext(text, lno, TRUE);
        !           700:                return;
        !           701:        }
        !           702: # endif
        !           703: # ifndef NO_VISIBLE
        !           704:        if (vizchange)
        !           705:        {
        !           706:                move((int)(lno - topline), 0);
        !           707:                drawtext(text, lno, TRUE);
        !           708:                smartlno = 0L;
        !           709:                return;
        !           710:        }
        !           711: # endif
        !           712: 
        !           713:        /* skip stuff that was scrolled off left edge */
        !           714:        limitcol = leftcol;
        !           715:        for (col = 0;
        !           716:             (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
        !           717:             text++)
        !           718:        {
        !           719:                if (i == '\t' && !*o_list)
        !           720:                {
        !           721:                        col = col + *o_tabstop - (col % *o_tabstop);
        !           722:                }
        !           723:                else if (i >= 0 && i < ' ' || i == '\177')
        !           724:                {
        !           725:                        col += 2;
        !           726:                }
        !           727:                else
        !           728:                {
        !           729:                        col++;
        !           730:                }
        !           731:        }
        !           732: 
        !           733:        /* adjust for control char that was partially visible */
        !           734:        build = new;
        !           735:        while (col > limitcol)
        !           736:        {
        !           737:                *build++ = ' ';
        !           738:                limitcol++;
        !           739:        }
        !           740: 
        !           741:        /* now for the visible characters */
        !           742:        limitcol = leftcol + COLS;
        !           743:        if (*o_number)
        !           744:                limitcol -= 8;
        !           745:        for (; (i = *text) && col < limitcol; text++)
        !           746:        {
        !           747:                if (i == '\t' && !*o_list)
        !           748:                {
        !           749:                        i = col + *o_tabstop - (col % *o_tabstop);
        !           750:                        while (col < i && col < limitcol)
        !           751:                        {
        !           752:                                *build++ = ' ';
        !           753:                                col++;
        !           754:                        }
        !           755:                }
        !           756:                else if (i >= 0 && i < ' ' || i == '\177')
        !           757:                {
        !           758:                        col += 2;
        !           759:                        *build++ = '^';
        !           760:                        if (col <= limitcol)
        !           761:                        {
        !           762:                                *build++ = (i ^ '@');
        !           763:                        }
        !           764:                }
        !           765:                else
        !           766:                {
        !           767:                        col++;
        !           768:                        *build++ = i;
        !           769:                }
        !           770:        }
        !           771:        if (col < limitcol && *o_list)
        !           772:        {
        !           773:                *build++ = '$';
        !           774:                col++;
        !           775:        }
        !           776:        end = build;
        !           777:        while (col < limitcol)
        !           778:        {
        !           779:                *build++ = ' ';
        !           780:                col++;
        !           781:        }
        !           782: 
        !           783:        /* if we're just supposed to remember this line, then remember it */
        !           784:        if (!showit)
        !           785:        {
        !           786:                smartlno = lno;
        !           787:                strncpy(old, new, COLS);
        !           788:                return;
        !           789:        }
        !           790: 
        !           791:        /* locate the last non-blank character */
        !           792:        while (end > new && end[-1] == ' ')
        !           793:        {
        !           794:                end--;
        !           795:        }
        !           796: 
        !           797:        /* can we optimize the displaying of this line? */
        !           798:        if (lno != smartlno)
        !           799:        {
        !           800:                /* nope, can't optimize - different line */
        !           801:                move((int)(lno - topline), 0);
        !           802: 
        !           803:                /* show the line number, if necessary */
        !           804:                if (*o_number)
        !           805:                {
        !           806:                        sprintf(numstr, "%6ld  ", lno);
        !           807:                        qaddstr(numstr);
        !           808:                }
        !           809: 
        !           810:                /* show the new line */
        !           811:                for (scan = new, build = old; scan < end; )
        !           812:                {
        !           813:                        qaddch(*scan);
        !           814:                        *build++ = *scan++;
        !           815:                }
        !           816:                if (end < new + COLS - (*o_number ? 8 : 0))
        !           817:                {
        !           818:                        clrtoeol();
        !           819:                        while (build < old + COLS)
        !           820:                        {
        !           821:                                *build++ = ' ';
        !           822:                        }
        !           823:                }
        !           824:                smartlno = lno;
        !           825:                return;
        !           826:        }
        !           827: 
        !           828:        /* skip any initial unchanged characters */
        !           829:        for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
        !           830:        {
        !           831:        }
        !           832:        i = (scan - new);
        !           833:        if (*o_number)
        !           834:                i += 8;
        !           835:        move((int)(lno - topline), i);
        !           836: 
        !           837:        /* The in-between characters must be changed */
        !           838:        same = 0;
        !           839:        while (scan < end)
        !           840:        {
        !           841:                /* is this character a match? */
        !           842:                if (scan[0] == build[0])
        !           843:                {
        !           844:                        same++;
        !           845:                }
        !           846:                else /* do we want to insert? */
        !           847:                if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
        !           848:                {
        !           849:                        nudgecursor(same, scan, new, lno);
        !           850:                        same = 0;
        !           851: 
        !           852:                        insch(*scan);
        !           853:                        for (shift = old + COLS; --shift > build; )
        !           854:                        {
        !           855:                                shift[0] = shift[-1];
        !           856:                        }
        !           857:                        *build = *scan;
        !           858:                }
        !           859:                else /* do we want to delete? */
        !           860:                if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
        !           861:                {
        !           862:                        nudgecursor(same, scan, new, lno);
        !           863:                        same = 0;
        !           864: 
        !           865:                        delch();
        !           866:                        same++;
        !           867:                        for (shift = build; shift < old + COLS - 1; shift++)
        !           868:                        {
        !           869:                                shift[0] = shift[1];
        !           870:                        }
        !           871:                        if (*o_number)
        !           872:                                shift -= 8;
        !           873:                        *shift = ' ';
        !           874:                }
        !           875:                else /* we must overwrite */
        !           876:                {
        !           877:                        nudgecursor(same, scan, new, lno);
        !           878:                        same = 0;
        !           879: 
        !           880:                        addch(*scan);
        !           881:                        *build = *scan;
        !           882:                }
        !           883: 
        !           884:                build++;
        !           885:                scan++;
        !           886:        }
        !           887: 
        !           888:        /* maybe clear to EOL */
        !           889:        end = old + COLS - (*o_number ? 8 : 0);
        !           890:        while (build < end && *build == ' ')
        !           891:        {
        !           892:                build++;
        !           893:        }
        !           894:        if (build < end)
        !           895:        {
        !           896:                nudgecursor(same, scan, new, lno);
        !           897:                same = 0;
        !           898: 
        !           899:                clrtoeol();
        !           900:                while (build < old + COLS)
        !           901:                {
        !           902:                        *build++ = ' ';
        !           903:                }
        !           904:        }
        !           905: #endif /* not CRUNCH */
        !           906: }
        !           907: 
        !           908: 
        !           909: /* This function is used in visual mode for drawing the screen (or just parts
        !           910:  * of the screen, if that's all thats needed).  It also takes care of
        !           911:  * scrolling.
        !           912:  */
        !           913: void redraw(curs, inputting)
        !           914:        MARK    curs;           /* where to leave the screen's cursor */
        !           915:        int     inputting;      /* boolean: being called from input() ? */
        !           916: {
        !           917:        char            *text;          /* a line of text to display */
        !           918:        static long     chgs;           /* previous changes level */
        !           919:        long            l;
        !           920:        int             i;
        !           921: #ifndef CRUNCH
        !           922:        static long     showtop;        /* top line in window */
        !           923:        static long     showbottom;     /* bottom line in window */
        !           924: #endif
        !           925: 
        !           926:        /* if curs == MARK_UNSET, then we should reset internal vars */
        !           927:        if (curs == MARK_UNSET)
        !           928:        {
        !           929:                if (topline < 1 || topline > nlines)
        !           930:                {
        !           931:                        topline = 1L;
        !           932:                }
        !           933:                else
        !           934:                {
        !           935:                        move(LINES - 1, 0);
        !           936:                        clrtoeol();
        !           937:                }
        !           938:                leftcol = 0;
        !           939:                mustredraw = TRUE;
        !           940:                redrawafter = INFINITY;
        !           941:                preredraw = 0L;
        !           942:                postredraw = 0L;
        !           943:                chgs = 0;
        !           944:                smartlno = 0L;
        !           945: #ifndef NO_VISIBLE
        !           946:                vizlow = vizhigh = 0L;
        !           947:                vizchange = FALSE;
        !           948: #endif
        !           949: #ifndef CRUNCH
        !           950:                showtop = 0;
        !           951:                showbottom = INFINITY;
        !           952: #endif
        !           953:                return;
        !           954:        }
        !           955: 
        !           956: #ifndef NO_VISIBLE
        !           957:        /* adjustments to hilited area may force extra lines to be redrawn. */
        !           958:        setviz(curs);
        !           959: #endif
        !           960: 
        !           961:        /* figure out which column the cursor will be in */
        !           962:        l = markline(curs);
        !           963:        text = fetchline(l);
        !           964:        mark2phys(curs, text, inputting);
        !           965: 
        !           966: #ifndef NO_COLOR
        !           967:        fixcolor();
        !           968: #endif
        !           969: 
        !           970:        /* adjust topline, if necessary, to get the cursor on the screen */
        !           971:        if (l >= topline && l <= botline)
        !           972:        {
        !           973:                /* it is on the screen already */
        !           974: 
        !           975:                /* if the file was changed but !mustredraw, then redraw line */
        !           976:                if (!mustredraw && (chgs != changes
        !           977: #ifndef NO_VISIBLE
        !           978:                        || V_from
        !           979: #endif
        !           980: #ifndef CRUNCH
        !           981:                        || l < showtop || l > showbottom
        !           982: #endif
        !           983:                                                        ))
        !           984:                {
        !           985:                        smartdrawtext(text, l, (chgs != changes));
        !           986:                }
        !           987:        }
        !           988:        else if (l < topline && l >= topline - NEAR && (has_SR || has_AL))
        !           989:        {
        !           990:                /* near top - scroll down */
        !           991:                if (!mustredraw)
        !           992:                {
        !           993:                        move(0,0);
        !           994:                        while (l < topline)
        !           995:                        {
        !           996:                                topline--;
        !           997:                                if (has_SR)
        !           998:                                {
        !           999:                                        do_SR();
        !          1000:                                }
        !          1001:                                else
        !          1002:                                {
        !          1003:                                        insertln();
        !          1004:                                }
        !          1005:                                text = fetchline(topline);
        !          1006:                                drawtext(text, topline, FALSE);
        !          1007:                                do_UP();
        !          1008:                        }
        !          1009: 
        !          1010:                        /* blank out the last line */
        !          1011:                        move(LINES - 1, 0);
        !          1012:                        clrtoeol();
        !          1013:                }
        !          1014:                else
        !          1015:                {
        !          1016:                        topline = l;
        !          1017:                        redrawrange(0L, INFINITY, INFINITY);
        !          1018:                }
        !          1019:        }
        !          1020:        else if (l > topline && l <= botline + NEAR)
        !          1021:        {
        !          1022:                /* near bottom -- scroll up */
        !          1023:                if (!mustredraw)
        !          1024:                {
        !          1025:                        move(LINES - 1,0);
        !          1026:                        clrtoeol();
        !          1027:                        while (l > botline)
        !          1028:                        {
        !          1029:                                topline++; /* <-- also adjusts botline */
        !          1030:                                text = fetchline(botline);
        !          1031:                                drawtext(text, botline, FALSE);
        !          1032:                        }
        !          1033: #ifndef CRUNCH
        !          1034:                        showbottom = l;
        !          1035: #endif
        !          1036:                }
        !          1037:                else
        !          1038:                {
        !          1039:                        topline = l - (LINES - 2);
        !          1040:                        redrawrange(0L, INFINITY, INFINITY);
        !          1041:                }
        !          1042:        }
        !          1043:        else
        !          1044:        {
        !          1045:                /* distant line - center it & force a redraw */
        !          1046:                topline = l - (LINES / 2) - 1;
        !          1047:                if (topline < 1)
        !          1048:                {
        !          1049:                        topline = 1;
        !          1050:                }
        !          1051:                redrawrange(0L, INFINITY, INFINITY);
        !          1052:                smartlno = 0L;
        !          1053:                changes++;
        !          1054:        }
        !          1055: 
        !          1056: #ifndef CRUNCH
        !          1057:        /* make sure the current line is included in the "window" */
        !          1058:        if (l < showtop)
        !          1059:        {
        !          1060:                redrawrange(l, showtop, showtop);
        !          1061:                showtop = l;
        !          1062:        }
        !          1063:        if (l > showbottom)
        !          1064:        {
        !          1065:                redrawrange(showbottom, l, l);
        !          1066:                showbottom = l;
        !          1067:        }
        !          1068: #endif
        !          1069: 
        !          1070: 
        !          1071:        /* Now... do we really have to redraw? */
        !          1072:        if (mustredraw)
        !          1073:        {
        !          1074:                /* If redrawfter (and friends) aren't set, assume we should
        !          1075:                 * redraw everything.
        !          1076:                 */
        !          1077:                if (redrawafter == INFINITY)
        !          1078:                {
        !          1079:                        redrawafter = 0L;
        !          1080:                        preredraw = postredraw = INFINITY;
        !          1081:                }
        !          1082: 
        !          1083: #ifndef CRUNCH
        !          1084:                /* shrink the window, if possible */
        !          1085:                if (showtop < topline)
        !          1086:                {
        !          1087:                        showtop = topline;
        !          1088:                }
        !          1089:                if (showbottom > botline)
        !          1090:                {
        !          1091:                        showbottom = botline;
        !          1092:                }
        !          1093:                if (postredraw == INFINITY)
        !          1094:                {
        !          1095:                        /* these will be set to more reasonable values later */
        !          1096:                        showtop = INFINITY;
        !          1097:                        showbottom = 0L;
        !          1098:                }
        !          1099: #endif
        !          1100: 
        !          1101:                /* adjust smartlno to correspond with inserted/deleted lines */
        !          1102:                if (smartlno >= redrawafter)
        !          1103:                {
        !          1104:                        if (smartlno < preredraw && postredraw != preredraw) /*!!!*/
        !          1105:                        {
        !          1106:                                smartlno = 0L;
        !          1107:                        }
        !          1108:                        else
        !          1109:                        {
        !          1110:                                smartlno += (postredraw - preredraw);
        !          1111:                        }
        !          1112:                }
        !          1113: 
        !          1114:                /* should we insert some lines into the screen? */
        !          1115:                if (preredraw < postredraw && preredraw <= botline)
        !          1116:                {
        !          1117:                        /* lines were inserted into the file */
        !          1118: 
        !          1119:                        /* decide where insertion should start */
        !          1120:                        if (preredraw < topline)
        !          1121:                        {
        !          1122:                                l = topline;
        !          1123:                        }
        !          1124:                        else
        !          1125:                        {
        !          1126:                                l = preredraw;
        !          1127:                        }
        !          1128: 
        !          1129:                        /* insert the lines... maybe */
        !          1130:                        if (l + postredraw - preredraw > botline || !has_AL || *o_number)
        !          1131:                        {
        !          1132:                                /* Whoa!  a whole screen full - just redraw */
        !          1133:                                preredraw = postredraw = INFINITY;
        !          1134:                        }
        !          1135:                        else
        !          1136:                        {
        !          1137:                                /* really insert 'em */
        !          1138:                                move((int)(l - topline), 0);
        !          1139:                                for (i = postredraw - preredraw; i > 0; i--)
        !          1140:                                {
        !          1141:                                        insertln();
        !          1142:                                }
        !          1143: 
        !          1144:                                /* NOTE: the contents of those lines will be
        !          1145:                                 * drawn as part of the regular redraw loop.
        !          1146:                                 */
        !          1147: 
        !          1148:                                /* clear the last line */
        !          1149:                                move(LINES - 1, 0);
        !          1150:                                clrtoeol();
        !          1151:                        }
        !          1152:                }
        !          1153: 
        !          1154:                /* do we want to delete some lines from the screen? */
        !          1155:                if (preredraw > postredraw && postredraw <= botline)
        !          1156:                {
        !          1157:                        if (preredraw > botline || !has_DL || *o_number)
        !          1158:                        {
        !          1159:                                postredraw = preredraw = INFINITY;
        !          1160:                        }
        !          1161:                        else /* we'd best delete some lines from the screen */
        !          1162:                        {
        !          1163:                                /* clear the last line, so it doesn't look
        !          1164:                                 * ugly as it gets pulled up into the screen
        !          1165:                                 */
        !          1166:                                move(LINES - 1, 0);
        !          1167:                                clrtoeol();
        !          1168: 
        !          1169:                                /* delete the lines */
        !          1170:                                move((int)(postredraw - topline), 0);
        !          1171:                                for (l = postredraw;
        !          1172:                                     l < preredraw && l <= botline;
        !          1173:                                     l++)
        !          1174:                                {
        !          1175:                                        deleteln();
        !          1176:                                }
        !          1177: 
        !          1178:                                /* draw the lines that are now newly visible
        !          1179:                                 * at the bottom of the screen
        !          1180:                                 */
        !          1181:                                i = LINES - 1 + (postredraw - preredraw);
        !          1182:                                move(i, 0);
        !          1183:                                for (l = topline + i; l <= botline; l++)
        !          1184:                                {
        !          1185:                                        /* clear this line */
        !          1186:                                        clrtoeol();
        !          1187: 
        !          1188:                                        /* draw the line, or ~ for non-lines */
        !          1189:                                        if (l <= nlines)
        !          1190:                                        {
        !          1191:                                                text = fetchline(l);
        !          1192:                                                drawtext(text, l, FALSE);
        !          1193:                                        }
        !          1194:                                        else
        !          1195:                                        {
        !          1196:                                                addstr("~\n");
        !          1197:                                        }
        !          1198:                                }
        !          1199:                        }
        !          1200:                }
        !          1201: 
        !          1202:                /* redraw the current line */
        !          1203:                l = markline(curs);
        !          1204:                pfetch(l);
        !          1205:                smartdrawtext(ptext, l, TRUE);
        !          1206: 
        !          1207: #ifndef CRUNCH
        !          1208:                /* decide which lines must be in the "window" around the cursor */
        !          1209:                l = markline(curs);
        !          1210:                if ((*o_window & 0xff) + 1 == LINES)
        !          1211:                {
        !          1212:                        showtop = 1;
        !          1213:                        showbottom = INFINITY;
        !          1214:                }
        !          1215:                else if (l < showtop || l > showbottom)
        !          1216:                {
        !          1217:                        l -= (*o_window & 0xff) / 2;
        !          1218:                        if (l < topline)
        !          1219:                        {
        !          1220:                                l = topline;
        !          1221:                        }
        !          1222:                        if (l < showtop)
        !          1223:                        {
        !          1224:                                showtop = l;
        !          1225:                        }
        !          1226:                        l += (*o_window & 0xff) - 1;
        !          1227:                        if (l > botline)
        !          1228:                        {
        !          1229:                                showtop = showtop - l + botline;
        !          1230:                                l = botline;
        !          1231:                        }
        !          1232:                        if (l > showbottom)
        !          1233:                        {
        !          1234:                                showbottom = l;
        !          1235:                        }
        !          1236:                }
        !          1237: #endif
        !          1238: 
        !          1239:                /* decide where we should start redrawing from */
        !          1240:                if (redrawafter < topline)
        !          1241:                {
        !          1242:                        l = topline;
        !          1243:                }
        !          1244:                else
        !          1245:                {
        !          1246:                        l = redrawafter;
        !          1247:                }
        !          1248:                if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno))
        !          1249:                {
        !          1250:                        /* draw the other lines */
        !          1251:                        move((int)(l - topline), 0);
        !          1252:                        for (; l <= botline && l < postredraw; l++)
        !          1253:                        {
        !          1254:                                /* we already drew the current line, so skip it now */
        !          1255:                                if (l == smartlno)
        !          1256:                                {
        !          1257: #if OSK
        !          1258:                                        qaddch('\l');
        !          1259: #else
        !          1260:                                        qaddch('\n');
        !          1261: #endif
        !          1262:                                        continue;
        !          1263:                                }
        !          1264: 
        !          1265:                                /* draw the line, or ~ for non-lines */
        !          1266:                                if (l > nlines)
        !          1267:                                {
        !          1268:                                        qaddch('~');
        !          1269:                                        clrtoeol();
        !          1270:                                        addch('\n');
        !          1271:                                }
        !          1272: #ifndef CRUNCH
        !          1273:                                else if (l < showtop || l > showbottom)
        !          1274:                                {
        !          1275:                                        qaddch('@');
        !          1276:                                        clrtoeol();
        !          1277:                                        addch('\n');
        !          1278:                                }
        !          1279: #endif
        !          1280:                                else
        !          1281:                                {
        !          1282:                                        text = fetchline(l);
        !          1283:                                        drawtext(text, l, TRUE);
        !          1284:                                }
        !          1285:                        }
        !          1286:                }
        !          1287: 
        !          1288:                mustredraw = FALSE;
        !          1289:        }
        !          1290: 
        !          1291:        /* force total (non-partial) redraw next time if not set */
        !          1292:        redrawafter = INFINITY;
        !          1293:        preredraw = 0L;
        !          1294:        postredraw = 0L;
        !          1295: 
        !          1296:        /* move the cursor to where it belongs */
        !          1297:        move((int)(markline(curs) - topline), physcol);
        !          1298:        wqrefresh();
        !          1299: 
        !          1300:        chgs = changes;
        !          1301: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.