Annotation of coherent/g/usr/bin/vi/redraw.c, revision 1.1.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.