Annotation of 41BSD/cmd/ex/ex_vwind.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1980 Regents of the University of California */
                      2: static char *sccsid = "@(#)ex_vwind.c  6.1 10/18/80";
                      3: #include "ex.h"
                      4: #include "ex_tty.h"
                      5: #include "ex_vis.h"
                      6: 
                      7: /*
                      8:  * Routines to adjust the window, showing specified lines
                      9:  * in certain positions on the screen, and scrolling in both
                     10:  * directions.  Code here is very dependent on mode (open versus visual).
                     11:  */
                     12: 
                     13: /*
                     14:  * Move in a nonlocal way to line addr.
                     15:  * If it isn't on screen put it in specified context.
                     16:  * New position for cursor is curs.
                     17:  * Like most routines here, we vsave().
                     18:  */
                     19: vmoveto(addr, curs, context)
                     20:        register line *addr;
                     21:        char *curs;
                     22:        char context;
                     23: {
                     24: 
                     25:        markit(addr);
                     26:        vsave();
                     27:        vjumpto(addr, curs, context);
                     28: }
                     29: 
                     30: /*
                     31:  * Vjumpto is like vmoveto, but doesn't mark previous
                     32:  * context or save linebuf as current line.
                     33:  */
                     34: vjumpto(addr, curs, context)
                     35:        register line *addr;
                     36:        char *curs;
                     37:        char context;
                     38: {
                     39: 
                     40:        noteit(0);
                     41:        if (context != 0)
                     42:                vcontext(addr, context);
                     43:        else
                     44:                vshow(addr, NOLINE);
                     45:        noteit(1);
                     46:        vnline(curs);
                     47: }
                     48: 
                     49: /*
                     50:  * Go up or down cnt (negative is up) to new position curs.
                     51:  */
                     52: vupdown(cnt, curs)
                     53:        register int cnt;
                     54:        char *curs;
                     55: {
                     56: 
                     57:        if (cnt > 0)
                     58:                vdown(cnt, 0, 0);
                     59:        else if (cnt < 0)
                     60:                vup(-cnt, 0, 0);
                     61:        if (vcnt == 0)
                     62:                vrepaint(curs);
                     63:        else
                     64:                vnline(curs);
                     65: }
                     66: 
                     67: /*
                     68:  * Go up cnt lines, afterwards preferring to be ind
                     69:  * logical lines from the top of the screen.
                     70:  * If scroll, then we MUST use a scroll.
                     71:  * Otherwise clear and redraw if motion is far.
                     72:  */
                     73: vup(cnt, ind, scroll)
                     74:        register int cnt, ind;
                     75:        bool scroll;
                     76: {
                     77:        register int i, tot;
                     78: 
                     79:        if (dot == one) {
                     80:                beep();
                     81:                return;
                     82:        }
                     83:        vsave();
                     84:        i = lineDOT() - 1;
                     85:        if (cnt > i) {
                     86:                ind -= cnt - i;
                     87:                if (ind < 0)
                     88:                        ind = 0;
                     89:                cnt = i;
                     90:        }
                     91:        if (!scroll && cnt <= vcline) {
                     92:                vshow(dot - cnt, NOLINE);
                     93:                return;
                     94:        }
                     95:        cnt -= vcline, dot -= vcline, vcline = 0;
                     96:        if (hold & HOLDWIG)
                     97:                goto contxt;
                     98:        if (state == VISUAL && !AL && !SR &&
                     99:            cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
                    100:                goto okr;
                    101:        tot = WECHO - ZERO;
                    102:        if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
                    103:                if (ind > basWLINES / 2)
                    104:                        ind = basWLINES / 3;
                    105: contxt:
                    106:                vcontext(dot + ind - cnt, '.');
                    107:                return;
                    108:        }
                    109: okr:
                    110:        vrollR(cnt);
                    111:        if (scroll) {
                    112:                vcline += ind, dot += ind;
                    113:                if (vcline >= vcnt)
                    114:                        dot -= vcline - vcnt + 1, vcline = vcnt - 1;
                    115:                getDOT();
                    116:        }
                    117: }
                    118: 
                    119: /*
                    120:  * Like vup, but scrolling down.
                    121:  */
                    122: vdown(cnt, ind, scroll)
                    123:        register int cnt, ind;
                    124:        bool scroll;
                    125: {
                    126:        register int i, tot;
                    127: 
                    128:        if (dot == dol) {
                    129:                beep();
                    130:                return;
                    131:        }
                    132:        vsave();
                    133:        i = dol - dot;
                    134:        if (cnt > i) {
                    135:                ind -= cnt - i;
                    136:                if (ind < 0)
                    137:                        ind = 0;
                    138:                cnt = i;
                    139:        }
                    140:        i = vcnt - vcline - 1;
                    141:        if (!scroll && cnt <= i) {
                    142:                vshow(dot + cnt, NOLINE);
                    143:                return;
                    144:        }
                    145:        cnt -= i, dot += i, vcline += i;
                    146:        if (hold & HOLDWIG)
                    147:                goto dcontxt;
                    148:        if (!scroll) {
                    149:                tot = WECHO - ZERO;
                    150:                if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
                    151: dcontxt:
                    152:                        vcontext(dot + cnt, '.');
                    153:                        return;
                    154:                }
                    155:        }
                    156:        if (cnt > 0)
                    157:                vroll(cnt);
                    158:        if (state == VISUAL && scroll) {
                    159:                vcline -= ind, dot -= ind;
                    160:                if (vcline < 0)
                    161:                        dot -= vcline, vcline = 0;
                    162:                getDOT();
                    163:        }
                    164: }
                    165: 
                    166: /*
                    167:  * Show line addr in context where on the screen.
                    168:  * Work here is in determining new top line implied by
                    169:  * this placement of line addr, since we always draw from the top.
                    170:  */
                    171: vcontext(addr, where)
                    172:        register line *addr;
                    173:        char where;
                    174: {
                    175:        register line *top;
                    176: 
                    177:        getline(*addr);
                    178:        if (state != VISUAL)
                    179:                top = addr;
                    180:        else switch (where) {
                    181: 
                    182:        case '^':
                    183:                addr = vback(addr, basWLINES - vdepth());
                    184:                getline(*addr);
                    185:                /* fall into ... */
                    186: 
                    187:        case '-':
                    188:                top = vback(addr, basWLINES - vdepth());
                    189:                getline(*addr);
                    190:                break;
                    191: 
                    192:        case '.':
                    193:                top = vback(addr, basWLINES / 2 - vdepth());
                    194:                getline(*addr);
                    195:                break;
                    196: 
                    197:        default:
                    198:                top = addr;
                    199:                break;
                    200:        }
                    201:        if (state == ONEOPEN && LINE(0) == WBOT)
                    202:                vup1();
                    203:        vcnt = vcline = 0;
                    204:        vclean();
                    205:        if (state == CRTOPEN)
                    206:                vup1();
                    207:        vshow(addr, top);
                    208: }
                    209: 
                    210: /*
                    211:  * Get a clean line.  If we are in a hard open
                    212:  * we may be able to reuse the line we are on
                    213:  * if it is blank.  This is a real win.
                    214:  */
                    215: vclean()
                    216: {
                    217: 
                    218:        if (state != VISUAL && state != CRTOPEN) {
                    219:                destcol = 0;
                    220:                if (!ateopr())
                    221:                        vup1();
                    222:                vcnt = 0;
                    223:        }
                    224: }
                    225: 
                    226: /*
                    227:  * Show line addr with the specified top line on the screen.
                    228:  * Top may be 0; in this case have vcontext compute the top
                    229:  * (and call us recursively).  Eventually, we clear the screen
                    230:  * (or its open mode equivalent) and redraw.
                    231:  */
                    232: vshow(addr, top)
                    233:        line *addr, *top;
                    234: {
                    235: #ifndef CBREAK
                    236:        register bool fried = 0;
                    237: #endif
                    238:        register int cnt = addr - dot;
                    239:        register int i = vcline + cnt;
                    240:        short oldhold = hold;
                    241: 
                    242:        if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
                    243:                dot = addr;
                    244:                getDOT();
                    245:                vcline = i;
                    246:                return;
                    247:        }
                    248:        if (state != VISUAL) {
                    249:                dot = addr;
                    250:                vopen(dot, WBOT);
                    251:                return;
                    252:        }
                    253:        if (top == 0) {
                    254:                vcontext(addr, '.');
                    255:                return;
                    256:        }
                    257:        dot = top;
                    258: #ifndef CBREAK
                    259:        if (vcookit(2))
                    260:                fried++, vcook();
                    261: #endif
                    262:        oldhold = hold;
                    263:        hold |= HOLDAT;
                    264:        vclear();
                    265:        vreset(0);
                    266:        vredraw(WTOP);
                    267:        /* error if vcline >= vcnt ! */
                    268:        vcline = addr - top;
                    269:        dot = addr;
                    270:        getDOT();
                    271:        hold = oldhold;
                    272:        vsync(LASTLINE);
                    273: #ifndef CBREAK
                    274:        if (fried)
                    275:                flusho(), vraw();
                    276: #endif
                    277: }
                    278: 
                    279: /*
                    280:  * reset the state.
                    281:  * If inecho then leave us at the beginning of the echo
                    282:  * area;  we are called this way in the middle of a :e escape
                    283:  * from visual, e.g.
                    284:  */
                    285: vreset(inecho)
                    286:        bool inecho;
                    287: {
                    288: 
                    289:        vcnt = vcline = 0;
                    290:        WTOP = basWTOP;
                    291:        WLINES = basWLINES;
                    292:        if (inecho)
                    293:                splitw = 1, vgoto(WECHO, 0);
                    294: }
                    295: 
                    296: /*
                    297:  * Starting from which line preceding tp uses almost (but not more
                    298:  * than) cnt physical lines?
                    299:  */
                    300: line *
                    301: vback(tp, cnt)
                    302:        register int cnt;
                    303:        register line *tp;
                    304: {
                    305:        register int d;
                    306: 
                    307:        if (cnt > 0)
                    308:                for (; tp > one; tp--) {
                    309:                        getline(tp[-1]);
                    310:                        d = vdepth();
                    311:                        if (d > cnt)
                    312:                                break;
                    313:                        cnt -= d;
                    314:                }
                    315:        return (tp);
                    316: }
                    317: 
                    318: /*
                    319:  * How much scrolling will it take to roll cnt lines starting at tp?
                    320:  */
                    321: vfit(tp, cnt)
                    322:        register line *tp;
                    323:        int cnt;
                    324: {
                    325:        register int j;
                    326: 
                    327:        j = 0;
                    328:        while (cnt > 0) {
                    329:                cnt--;
                    330:                getline(tp[cnt]);
                    331:                j += vdepth();
                    332:        }
                    333:        if (tp > dot)
                    334:                j -= WBOT - LASTLINE;
                    335:        return (j);
                    336: }
                    337: 
                    338: /*
                    339:  * Roll cnt lines onto the screen.
                    340:  */
                    341: vroll(cnt)
                    342:        register int cnt;
                    343: {
                    344: #ifndef CBREAK
                    345:        register bool fried = 0;
                    346: #endif
                    347:        short oldhold = hold;
                    348: 
                    349: #ifdef ADEBUG
                    350:        if (trace)
                    351:                tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
                    352: #endif
                    353:        if (state != VISUAL)
                    354:                hold |= HOLDAT|HOLDROL;
                    355:        if (WBOT == WECHO) {
                    356:                vcnt = 0;
                    357:                if (state == ONEOPEN)
                    358:                        vup1();
                    359:        }
                    360: #ifndef CBREAK
                    361:        if (vcookit(cnt))
                    362:                fried++, vcook();
                    363: #endif
                    364:        for (; cnt > 0 && Peekkey != ATTN; cnt--) {
                    365:                dot++, vcline++;
                    366:                vopen(dot, LASTLINE);
                    367:                vscrap();
                    368:        }
                    369:        hold = oldhold;
                    370:        if (state == HARDOPEN)
                    371:                sethard();
                    372:        vsyncCL();
                    373: #ifndef CBREAK
                    374:        if (fried)
                    375:                flusho(), vraw();
                    376: #endif
                    377: }
                    378: 
                    379: /*
                    380:  * Roll backwards (scroll up).
                    381:  */
                    382: vrollR(cnt)
                    383:        register int cnt;
                    384: {
                    385:        register bool fried = 0;
                    386:        short oldhold = hold;
                    387: 
                    388: #ifdef ADEBUG
                    389:        if (trace)
                    390:                tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
                    391: #endif
                    392: #ifndef CBREAK
                    393:        if (vcookit(cnt))
                    394:                fried++, vcook();
                    395: #endif
                    396:        if (WBOT == WECHO)
                    397:                vcnt = 0;
                    398:        heldech = 0;
                    399:        hold |= HOLDAT|HOLDECH;
                    400:        for (; cnt > 0 && Peekkey != ATTN; cnt--) {
                    401:                dot--;
                    402:                vopen(dot, WTOP);
                    403:                vscrap();
                    404:        }
                    405:        hold = oldhold;
                    406:        if (heldech)
                    407:                vclrech(0);
                    408:        vsync(LINE(vcnt-1));
                    409: #ifndef CBREAK
                    410:        if (fried)
                    411:                flusho(), vraw();
                    412: #endif
                    413: }
                    414: 
                    415: /*
                    416:  * Go into cooked mode (allow interrupts) during
                    417:  * a scroll if we are at less than 1200 baud and not
                    418:  * a 'vi' command, of if we are in a 'vi' command and the
                    419:  * scroll is more than 2 full screens.
                    420:  *
                    421:  * BUG:                An interrupt during a scroll in this way
                    422:  *             dumps to command mode.
                    423:  */
                    424: vcookit(cnt)
                    425:        register int cnt;
                    426: {
                    427: 
                    428:        return (cnt > 1 && (ospeed < B1200 && !initev || cnt > LINES * 2));
                    429: }
                    430: 
                    431: /*
                    432:  * Determine displayed depth of current line.
                    433:  */
                    434: vdepth()
                    435: {
                    436:        register int d;
                    437: 
                    438:        d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + IN) / WCOLS;
                    439: #ifdef ADEBUG
                    440:        if (trace)
                    441:                tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
                    442: #endif
                    443:        return (d == 0 ? 1 : d);
                    444: }
                    445: 
                    446: /*
                    447:  * Move onto a new line, with cursor at position curs.
                    448:  */
                    449: vnline(curs)
                    450:        char *curs;
                    451: {
                    452: 
                    453:        if (curs)
                    454:                wcursor = curs;
                    455:        else if (vmoving)
                    456:                wcursor = vfindcol(vmovcol);
                    457:        else
                    458:                wcursor = vskipwh(linebuf);
                    459:        cursor = linebuf;
                    460:        vmove();
                    461: }

unix.superglobalmegacorp.com

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