Annotation of 43BSD/ucb/ex/ex_vops2.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)ex_vops2.c  6.8 (Berkeley) 6/7/85";
                      9: #endif not lint
                     10: 
                     11: #include "ex.h"
                     12: #include "ex_tty.h"
                     13: #include "ex_vis.h"
                     14: 
                     15: /*
                     16:  * Low level routines for operations sequences,
                     17:  * and mostly, insert mode (and a subroutine
                     18:  * to read an input line, including in the echo area.)
                     19:  */
                     20: extern char    *vUA1, *vUA2;           /* mjm: extern; also in ex_vops.c */
                     21: extern char    *vUD1, *vUD2;           /* mjm: extern; also in ex_vops.c */
                     22: 
                     23: /*
                     24:  * Obleeperate characters in hardcopy
                     25:  * open with \'s.
                     26:  */
                     27: bleep(i, cp)
                     28:        register int i;
                     29:        char *cp;
                     30: {
                     31: 
                     32:        i -= column(cp);
                     33:        do
                     34:                putchar('\\' | QUOTE);
                     35:        while (--i >= 0);
                     36:        rubble = 1;
                     37: }
                     38: 
                     39: /*
                     40:  * Common code for middle part of delete
                     41:  * and change operating on parts of lines.
                     42:  */
                     43: vdcMID()
                     44: {
                     45:        register char *cp;
                     46: 
                     47:        squish();
                     48:        setLAST();
                     49:        if (FIXUNDO)
                     50:                vundkind = VCHNG, CP(vutmp, linebuf);
                     51:        if (wcursor < cursor)
                     52:                cp = wcursor, wcursor = cursor, cursor = cp;
                     53:        vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
                     54:        return (column(wcursor - 1));
                     55: }
                     56: 
                     57: /*
                     58:  * Take text from linebuf and stick it
                     59:  * in the VBSIZE buffer BUF.  Used to save
                     60:  * deleted text of part of line.
                     61:  */
                     62: takeout(BUF)
                     63:        char *BUF;
                     64: {
                     65:        register char *cp;
                     66: 
                     67:        if (wcursor < linebuf)
                     68:                wcursor = linebuf;
                     69:        if (cursor == wcursor) {
                     70:                beep();
                     71:                return;
                     72:        }
                     73:        if (wcursor < cursor) {
                     74:                cp = wcursor;
                     75:                wcursor = cursor;
                     76:                cursor = cp;
                     77:        }
                     78:        setBUF(BUF);
                     79:        if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
                     80:                beep();
                     81: }
                     82: 
                     83: /*
                     84:  * Are we at the end of the printed representation of the
                     85:  * line?  Used internally in hardcopy open.
                     86:  */
                     87: ateopr()
                     88: {
                     89:        register int i, c;
                     90:        register char *cp = vtube[destline] + destcol;
                     91: 
                     92:        for (i = WCOLS - destcol; i > 0; i--) {
                     93:                c = *cp++;
                     94:                if (c == 0)
                     95:                        return (1);
                     96:                if (c != ' ' && (c & QUOTE) == 0)
                     97:                        return (0);
                     98:        }
                     99:        return (1);
                    100: }
                    101: 
                    102: /*
                    103:  * Append.
                    104:  *
                    105:  * This routine handles the top level append, doing work
                    106:  * as each new line comes in, and arranging repeatability.
                    107:  * It also handles append with repeat counts, and calculation
                    108:  * of autoindents for new lines.
                    109:  */
                    110: bool   vaifirst;
                    111: bool   gobbled;
                    112: char   *ogcursor;
                    113: 
                    114: vappend(ch, cnt, indent)
                    115:        int ch;         /* mjm: char --> int */
                    116:        int cnt, indent;
                    117: {
                    118:        register int i;
                    119:        register char *gcursor;
                    120:        bool escape;
                    121:        int repcnt, savedoomed;
                    122:        short oldhold = hold;
                    123:        int oldmask;
                    124: 
                    125:        /*
                    126:         * Before a move in hardopen when the line is dirty
                    127:         * or we are in the middle of the printed representation,
                    128:         * we retype the line to the left of the cursor so the
                    129:         * insert looks clean.
                    130:         */
                    131:        if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
                    132:                rubble = 1;
                    133:                gcursor = cursor;
                    134:                i = *gcursor;
                    135:                *gcursor = ' ';
                    136:                wcursor = gcursor;
                    137:                vmove();
                    138:                *gcursor = i;
                    139:        }
                    140:        vaifirst = indent == 0;
                    141: 
                    142:        /*
                    143:         * Handle replace character by (eventually)
                    144:         * limiting the number of input characters allowed
                    145:         * in the vgetline routine.
                    146:         */
                    147:        if (ch == 'r')
                    148:                repcnt = 2;
                    149:        else
                    150:                repcnt = 0;
                    151: 
                    152:        /*
                    153:         * If an autoindent is specified, then
                    154:         * generate a mixture of blanks to tabs to implement
                    155:         * it and place the cursor after the indent.
                    156:         * Text read by the vgetline routine will be placed in genbuf,
                    157:         * so the indent is generated there.
                    158:         */
                    159:        if (value(AUTOINDENT) && indent != 0) {
                    160:                gcursor = genindent(indent);
                    161:                *gcursor = 0;
                    162:                vgotoCL(qcolumn(cursor - 1, genbuf));
                    163:        } else {
                    164:                gcursor = genbuf;
                    165:                *gcursor = 0;
                    166:                if (ch == 'o')
                    167:                        vfixcurs();
                    168:        }
                    169: 
                    170:        /*
                    171:         * Prepare for undo.  Pointers delimit inserted portion of line.
                    172:         */
                    173:        vUA1 = vUA2 = cursor;
                    174: 
                    175:        /*
                    176:         * If we are not in a repeated command and a ^@ comes in
                    177:         * then this means the previous inserted text.
                    178:         * If there is none or it was too long to be saved,
                    179:         * then beep() and also arrange to undo any damage done
                    180:         * so far (e.g. if we are a change.)
                    181:         */
                    182:        if ((vglobp && *vglobp == 0) || peekbr()) {
                    183:                if ((INS[0] & (QUOTE|TRIM)) == OVERBUF) {
                    184:                        beep();
                    185:                        if (!splitw)
                    186:                                ungetkey('u');
                    187:                        doomed = 0;
                    188:                        hold = oldhold;
                    189:                        return;
                    190:                }
                    191:                /*
                    192:                 * Unread input from INS.
                    193:                 * An escape will be generated at end of string.
                    194:                 * Hold off n^^2 type update on dumb terminals.
                    195:                 */
                    196:                vglobp = INS;
                    197:                hold |= HOLDQIK;
                    198:        } else if (vglobp == 0)
                    199:                /*
                    200:                 * Not a repeated command, get
                    201:                 * a new inserted text for repeat.
                    202:                 */
                    203:                INS[0] = 0;
                    204: 
                    205:        /*
                    206:         * For wrapmargin to hack away second space after a '.'
                    207:         * when the first space caused a line break we keep
                    208:         * track that this happened in gobblebl, which says
                    209:         * to gobble up a blank silently.
                    210:         */
                    211:        gobblebl = 0;
                    212: 
                    213:        oldmask = sigblock(sigmask(SIGWINCH));
                    214:        /*
                    215:         * Text gathering loop.
                    216:         * New text goes into genbuf starting at gcursor.
                    217:         * cursor preserves place in linebuf where text will eventually go.
                    218:         */
                    219:        if (*cursor == 0 || state == CRTOPEN)
                    220:                hold |= HOLDROL;
                    221:        for (;;) {
                    222:                if (ch == 'r' && repcnt == 0)
                    223:                        escape = 0;
                    224:                else {
                    225:                        gcursor = vgetline(repcnt, gcursor, &escape, ch);
                    226: 
                    227:                        /*
                    228:                         * After an append, stick information
                    229:                         * about the ^D's and ^^D's and 0^D's in
                    230:                         * the repeated text buffer so repeated
                    231:                         * inserts of stuff indented with ^D as backtab's
                    232:                         * can work.
                    233:                         */
                    234:                        if (HADUP)
                    235:                                addtext("^");
                    236:                        else if (HADZERO)
                    237:                                addtext("0");
                    238:                        while (CDCNT > 0)
                    239:                                addtext("\204"), CDCNT--;
                    240:                        if (gobbled)
                    241:                                addtext(" ");
                    242:                        addtext(ogcursor);
                    243:                }
                    244:                repcnt = 0;
                    245: 
                    246:                /*
                    247:                 * Smash the generated and preexisting indents together
                    248:                 * and generate one cleanly made out of tabs and spaces
                    249:                 * if we are using autoindent.
                    250:                 */
                    251:                if (!vaifirst && value(AUTOINDENT)) {
                    252:                        i = fixindent(indent);
                    253:                        if (!HADUP)
                    254:                                indent = i;
                    255:                        gcursor = strend(genbuf);
                    256:                }
                    257: 
                    258:                /*
                    259:                 * Limit the repetition count based on maximum
                    260:                 * possible line length; do output implied
                    261:                 * by further count (> 1) and cons up the new line
                    262:                 * in linebuf.
                    263:                 */
                    264:                cnt = vmaxrep(ch, cnt);
                    265:                CP(gcursor + 1, cursor);
                    266:                do {
                    267:                        CP(cursor, genbuf);
                    268:                        if (cnt > 1) {
                    269:                                int oldhold = hold;
                    270: 
                    271:                                Outchar = vinschar;
                    272:                                hold |= HOLDQIK;
                    273:                                printf("%s", genbuf);
                    274:                                hold = oldhold;
                    275:                                Outchar = vputchar;
                    276:                        }
                    277:                        cursor += gcursor - genbuf;
                    278:                } while (--cnt > 0);
                    279:                endim();
                    280:                vUA2 = cursor;
                    281:                if (escape != '\n')
                    282:                        CP(cursor, gcursor + 1);
                    283: 
                    284:                /*
                    285:                 * If doomed characters remain, clobber them,
                    286:                 * and reopen the line to get the display exact.
                    287:                 */
                    288:                if (state != HARDOPEN) {
                    289:                        DEPTH(vcline) = 0;
                    290:                        savedoomed = doomed;
                    291:                        if (doomed > 0) {
                    292:                                register int cind = cindent();
                    293: 
                    294:                                physdc(cind, cind + doomed);
                    295:                                doomed = 0;
                    296:                        }
                    297:                        i = vreopen(LINE(vcline), lineDOT(), vcline);
                    298: #ifdef TRACE
                    299:                        if (trace)
                    300:                                fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
                    301: #endif
                    302:                        if (ch == 'R')
                    303:                                doomed = savedoomed;
                    304:                }
                    305: 
                    306:                /*
                    307:                 * All done unless we are continuing on to another line.
                    308:                 */
                    309:                if (escape != '\n')
                    310:                        break;
                    311: 
                    312:                /*
                    313:                 * Set up for the new line.
                    314:                 * First save the current line, then construct a new
                    315:                 * first image for the continuation line consisting
                    316:                 * of any new autoindent plus the pushed ahead text.
                    317:                 */
                    318:                killU();
                    319:                addtext(gobblebl ? " " : "\n");
                    320:                vsave();
                    321:                cnt = 1;
                    322:                if (value(AUTOINDENT)) {
                    323: #ifdef LISPCODE
                    324:                        if (value(LISP))
                    325:                                indent = lindent(dot + 1);
                    326:                        else
                    327: #endif
                    328:                             if (!HADUP && vaifirst)
                    329:                                indent = whitecnt(linebuf);
                    330:                        vaifirst = 0;
                    331:                        strcLIN(vpastwh(gcursor + 1));
                    332:                        gcursor = genindent(indent);
                    333:                        *gcursor = 0;
                    334:                        if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
                    335:                                gcursor = genbuf;
                    336:                        CP(gcursor, linebuf);
                    337:                } else {
                    338:                        CP(genbuf, gcursor + 1);
                    339:                        gcursor = genbuf;
                    340:                }
                    341: 
                    342:                /*
                    343:                 * If we started out as a single line operation and are now
                    344:                 * turning into a multi-line change, then we had better yank
                    345:                 * out dot before it changes so that undo will work
                    346:                 * correctly later.
                    347:                 */
                    348:                if (FIXUNDO && vundkind == VCHNG) {
                    349:                        vremote(1, yank, 0);
                    350:                        undap1--;
                    351:                }
                    352: 
                    353:                /*
                    354:                 * Now do the append of the new line in the buffer,
                    355:                 * and update the display.  If slowopen
                    356:                 * we don't do very much.
                    357:                 */
                    358:                vdoappend(genbuf);
                    359:                vundkind = VMANYINS;
                    360:                vcline++;
                    361:                if (state != VISUAL)
                    362:                        vshow(dot, NOLINE);
                    363:                else {
                    364:                        i += LINE(vcline - 1);
                    365:                        vopen(dot, i);
                    366:                        if (value(SLOWOPEN))
                    367:                                vscrap();
                    368:                        else
                    369:                                vsync1(LINE(vcline));
                    370:                }
                    371:                strcLIN(gcursor);
                    372:                *gcursor = 0;
                    373:                cursor = linebuf;
                    374:                vgotoCL(qcolumn(cursor - 1, genbuf));
                    375:        }
                    376: 
                    377:        /*
                    378:         * All done with insertion, position the cursor
                    379:         * and sync the screen.
                    380:         */
                    381:        hold = oldhold;
                    382:        if (cursor > linebuf)
                    383:                cursor--;
                    384:        if (state != HARDOPEN)
                    385:                vsyncCL();
                    386:        else if (cursor > linebuf)
                    387:                back1();
                    388:        doomed = 0;
                    389:        wcursor = cursor;
                    390:        vmove();
                    391:        (void)sigsetmask(oldmask);
                    392: }
                    393: 
                    394: /*
                    395:  * Subroutine for vgetline to back up a single character position,
                    396:  * backwards around end of lines (vgoto can't hack columns which are
                    397:  * less than 0 in general).
                    398:  */
                    399: back1()
                    400: {
                    401: 
                    402:        vgoto(destline - 1, WCOLS + destcol - 1);
                    403: }
                    404: 
                    405: /*
                    406:  * Get a line into genbuf after gcursor.
                    407:  * Cnt limits the number of input characters
                    408:  * accepted and is used for handling the replace
                    409:  * single character command.  Aescaped is the location
                    410:  * where we stick a termination indicator (whether we
                    411:  * ended with an ESCAPE or a newline/return.
                    412:  *
                    413:  * We do erase-kill type processing here and also
                    414:  * are careful about the way we do this so that it is
                    415:  * repeatable.  (I.e. so that your kill doesn't happen,
                    416:  * when you repeat an insert if it was escaped with \ the
                    417:  * first time you did it.  commch is the command character
                    418:  * involved, including the prompt for readline.
                    419:  */
                    420: char *
                    421: vgetline(cnt, gcursor, aescaped, commch)
                    422:        int cnt;
                    423:        register char *gcursor;
                    424:        bool *aescaped;
                    425:        char commch;
                    426: {
                    427:        register int c, ch;
                    428:        register char *cp;
                    429:        int x, y, iwhite, backsl=0;
                    430:        char *iglobp;
                    431:        char cstr[2];
                    432:        int (*OO)() = Outchar;
                    433: 
                    434:        /*
                    435:         * Clear the output state and counters
                    436:         * for autoindent backwards motion (counts of ^D, etc.)
                    437:         * Remember how much white space at beginning of line so
                    438:         * as not to allow backspace over autoindent.
                    439:         */
                    440:        *aescaped = 0;
                    441:        ogcursor = gcursor;
                    442:        flusho();
                    443:        CDCNT = 0;
                    444:        HADUP = 0;
                    445:        HADZERO = 0;
                    446:        gobbled = 0;
                    447:        iwhite = whitecnt(genbuf);
                    448:        iglobp = vglobp;
                    449: 
                    450:        /*
                    451:         * Carefully avoid using vinschar in the echo area.
                    452:         */
                    453:        if (splitw)
                    454:                Outchar = vputchar;
                    455:        else {
                    456:                Outchar = vinschar;
                    457:                vprepins();
                    458:        }
                    459:        for (;;) {
                    460:                backsl = 0;
                    461:                if (gobblebl)
                    462:                        gobblebl--;
                    463:                if (cnt != 0) {
                    464:                        cnt--;
                    465:                        if (cnt == 0)
                    466:                                goto vadone;
                    467:                }
                    468:                c = getkey();
                    469:                if (c != ATTN)
                    470:                        c &= (QUOTE|TRIM);
                    471:                ch = c;
                    472:                maphopcnt = 0;
                    473:                if (vglobp == 0 && Peekkey == 0 && commch != 'r')
                    474:                        while ((ch = map(c, immacs)) != c) {
                    475:                                c = ch;
                    476:                                if (!value(REMAP))
                    477:                                        break;
                    478:                                if (++maphopcnt > 256)
                    479:                                        error("Infinite macro loop");
                    480:                        }
                    481:                if (!iglobp) {
                    482: 
                    483:                        /*
                    484:                         * Erase-kill type processing.
                    485:                         * Only happens if we were not reading
                    486:                         * from untyped input when we started.
                    487:                         * Map users erase to ^H, kill to -1 for switch.
                    488:                         */
                    489: #ifndef USG3TTY
                    490:                        if (c == tty.sg_erase)
                    491:                                c = CTRL(h);
                    492:                        else if (c == tty.sg_kill)
                    493:                                c = -1;
                    494: #else
                    495:                        if (c == tty.c_cc[VERASE])
                    496:                                c = CTRL(h);
                    497:                        else if (c == tty.c_cc[VKILL])
                    498:                                c = -1;
                    499: #endif
                    500:                        switch (c) {
                    501: 
                    502:                        /*
                    503:                         * ^?           Interrupt drops you back to visual
                    504:                         *              command mode with an unread interrupt
                    505:                         *              still in the input buffer.
                    506:                         *
                    507:                         * ^\           Quit does the same as interrupt.
                    508:                         *              If you are a ex command rather than
                    509:                         *              a vi command this will drop you
                    510:                         *              back to command mode for sure.
                    511:                         */
                    512:                        case ATTN:
                    513:                        case QUIT:
                    514:                                ungetkey(c);
                    515:                                goto vadone;
                    516: 
                    517:                        /*
                    518:                         * ^H           Backs up a character in the input.
                    519:                         *
                    520:                         * BUG:         Can't back around line boundaries.
                    521:                         *              This is hard because stuff has
                    522:                         *              already been saved for repeat.
                    523:                         */
                    524:                        case CTRL(h):
                    525: bakchar:
                    526:                                cp = gcursor - 1;
                    527:                                if (cp < ogcursor) {
                    528:                                        if (splitw) {
                    529:                                                /*
                    530:                                                 * Backspacing over readecho
                    531:                                                 * prompt. Pretend delete but
                    532:                                                 * don't beep.
                    533:                                                 */
                    534:                                                ungetkey(c);
                    535:                                                goto vadone;
                    536:                                        }
                    537:                                        beep();
                    538:                                        continue;
                    539:                                }
                    540:                                goto vbackup;
                    541: 
                    542:                        /*
                    543:                         * ^W           Back up a white/non-white word.
                    544:                         */
                    545:                        case CTRL(w):
                    546:                                wdkind = 1;
                    547:                                for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
                    548:                                        continue;
                    549:                                for (c = wordch(cp - 1);
                    550:                                    cp > ogcursor && wordof(c, cp - 1); cp--)
                    551:                                        continue;
                    552:                                goto vbackup;
                    553: 
                    554:                        /*
                    555:                         * users kill   Kill input on this line, back to
                    556:                         *              the autoindent.
                    557:                         */
                    558:                        case -1:
                    559:                                cp = ogcursor;
                    560: vbackup:
                    561:                                if (cp == gcursor) {
                    562:                                        beep();
                    563:                                        continue;
                    564:                                }
                    565:                                endim();
                    566:                                *cp = 0;
                    567:                                c = cindent();
                    568:                                vgotoCL(qcolumn(cursor - 1, genbuf));
                    569:                                if (doomed >= 0)
                    570:                                        doomed += c - cindent();
                    571:                                gcursor = cp;
                    572:                                continue;
                    573: 
                    574:                        /*
                    575:                         * \            Followed by erase or kill
                    576:                         *              maps to just the erase or kill.
                    577:                         */
                    578:                        case '\\':
                    579:                                x = destcol, y = destline;
                    580:                                putchar('\\');
                    581:                                vcsync();
                    582:                                c = getkey();
                    583: #ifndef USG3TTY
                    584:                                if (c == tty.sg_erase || c == tty.sg_kill)
                    585: #else
                    586:                                if (c == tty.c_cc[VERASE]
                    587:                                    || c == tty.c_cc[VKILL])
                    588: #endif
                    589:                                {
                    590:                                        vgoto(y, x);
                    591:                                        if (doomed >= 0)
                    592:                                                doomed++;
                    593:                                        goto def;
                    594:                                }
                    595:                                ungetkey(c), c = '\\';
                    596:                                backsl = 1;
                    597:                                break;
                    598: 
                    599:                        /*
                    600:                         * ^Q           Super quote following character
                    601:                         *              Only ^@ is verboten (trapped at
                    602:                         *              a lower level) and \n forces a line
                    603:                         *              split so doesn't really go in.
                    604:                         *
                    605:                         * ^V           Synonym for ^Q
                    606:                         */
                    607:                        case CTRL(q):
                    608:                        case CTRL(v):
                    609:                                x = destcol, y = destline;
                    610:                                putchar('^');
                    611:                                vgoto(y, x);
                    612:                                c = getkey();
                    613: #ifdef TIOCSETC
                    614:                                if (c == ATTN)
                    615:                                        c = nttyc.t_intrc;
                    616: #endif
                    617:                                if (c != NL) {
                    618:                                        if (doomed >= 0)
                    619:                                                doomed++;
                    620:                                        goto def;
                    621:                                }
                    622:                                break;
                    623:                        }
                    624:                }
                    625: 
                    626:                /*
                    627:                 * If we get a blank not in the echo area
                    628:                 * consider splitting the window in the wrapmargin.
                    629:                 */
                    630:                if (c != NL && !splitw) {
                    631:                        if (c == ' ' && gobblebl) {
                    632:                                gobbled = 1;
                    633:                                continue;
                    634:                        }
                    635:                        if (value(WRAPMARGIN) &&
                    636:                                (outcol >= OCOLUMNS - value(WRAPMARGIN) ||
                    637:                                 backsl && outcol==0) &&
                    638:                                commch != 'r') {
                    639:                                /*
                    640:                                 * At end of word and hit wrapmargin.
                    641:                                 * Move the word to next line and keep going.
                    642:                                 */
                    643:                                wdkind = 1;
                    644:                                *gcursor++ = c;
                    645:                                if (backsl)
                    646:                                        *gcursor++ = getkey();
                    647:                                *gcursor = 0;
                    648:                                /*
                    649:                                 * Find end of previous word if we are past it.
                    650:                                 */
                    651:                                for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--)
                    652:                                        ;
                    653:                                if (outcol+(backsl?OCOLUMNS:0) - (gcursor-cp) >= OCOLUMNS - value(WRAPMARGIN)) {
                    654:                                        /*
                    655:                                         * Find beginning of previous word.
                    656:                                         */
                    657:                                        for (; cp>ogcursor && !isspace(cp[-1]); cp--)
                    658:                                                ;
                    659:                                        if (cp <= ogcursor) {
                    660:                                                /*
                    661:                                                 * There is a single word that
                    662:                                                 * is too long to fit.  Just
                    663:                                                 * let it pass, but beep for
                    664:                                                 * each new letter to warn
                    665:                                                 * the luser.
                    666:                                                 */
                    667:                                                c = *--gcursor;
                    668:                                                *gcursor = 0;
                    669:                                                beep();
                    670:                                                goto dontbreak;
                    671:                                        }
                    672:                                        /*
                    673:                                         * Save it for next line.
                    674:                                         */
                    675:                                        macpush(cp, 0);
                    676:                                        cp--;
                    677:                                }
                    678:                                macpush("\n", 0);
                    679:                                /*
                    680:                                 * Erase white space before the word.
                    681:                                 */
                    682:                                while (cp > ogcursor && isspace(cp[-1]))
                    683:                                        cp--;   /* skip blank */
                    684:                                gobblebl = 3;
                    685:                                goto vbackup;
                    686:                        }
                    687:                dontbreak:;
                    688:                }
                    689: 
                    690:                /*
                    691:                 * Word abbreviation mode.
                    692:                 */
                    693:                cstr[0] = c;
                    694:                if (anyabbrs && gcursor > ogcursor && !wordch(cstr) && wordch(gcursor-1)) {
                    695:                                int wdtype, abno;
                    696: 
                    697:                                cstr[1] = 0;
                    698:                                wdkind = 1;
                    699:                                cp = gcursor - 1;
                    700:                                for (wdtype = wordch(cp - 1);
                    701:                                    cp > ogcursor && wordof(wdtype, cp - 1); cp--)
                    702:                                        ;
                    703:                                *gcursor = 0;
                    704:                                for (abno=0; abbrevs[abno].mapto; abno++) {
                    705:                                        if (eq(cp, abbrevs[abno].cap)) {
                    706:                                                macpush(cstr, 0);
                    707:                                                macpush(abbrevs[abno].mapto);
                    708:                                                goto vbackup;
                    709:                                        }
                    710:                                }
                    711:                }
                    712: 
                    713:                switch (c) {
                    714: 
                    715:                /*
                    716:                 * ^M           Except in repeat maps to \n.
                    717:                 */
                    718:                case CR:
                    719:                        if (vglobp)
                    720:                                goto def;
                    721:                        c = '\n';
                    722:                        /* presto chango ... */
                    723: 
                    724:                /*
                    725:                 * \n           Start new line.
                    726:                 */
                    727:                case NL:
                    728:                        *aescaped = c;
                    729:                        goto vadone;
                    730: 
                    731:                /*
                    732:                 * escape       End insert unless repeat and more to repeat.
                    733:                 */
                    734:                case ESCAPE:
                    735:                        if (lastvgk)
                    736:                                goto def;
                    737:                        goto vadone;
                    738: 
                    739:                /*
                    740:                 * ^D           Backtab.
                    741:                 * ^T           Software forward tab.
                    742:                 *
                    743:                 *              Unless in repeat where this means these
                    744:                 *              were superquoted in.
                    745:                 */
                    746:                case CTRL(d):
                    747:                case CTRL(t):
                    748:                        if (vglobp)
                    749:                                goto def;
                    750:                        /* fall into ... */
                    751: 
                    752:                /*
                    753:                 * ^D|QUOTE     Is a backtab (in a repeated command).
                    754:                 */
                    755:                case CTRL(d) | QUOTE:
                    756:                        *gcursor = 0;
                    757:                        cp = vpastwh(genbuf);
                    758:                        c = whitecnt(genbuf);
                    759:                        if (ch == CTRL(t)) {
                    760:                                /*
                    761:                                 * ^t just generates new indent replacing
                    762:                                 * current white space rounded up to soft
                    763:                                 * tab stop increment.
                    764:                                 */
                    765:                                if (cp != gcursor)
                    766:                                        /*
                    767:                                         * BUG:         Don't hack ^T except
                    768:                                         *              right after initial
                    769:                                         *              white space.
                    770:                                         */
                    771:                                        continue;
                    772:                                cp = genindent(iwhite = backtab(c + value(SHIFTWIDTH) + 1));
                    773:                                ogcursor = cp;
                    774:                                goto vbackup;
                    775:                        }
                    776:                        /*
                    777:                         * ^D works only if we are at the (end of) the
                    778:                         * generated autoindent.  We count the ^D for repeat
                    779:                         * purposes.
                    780:                         */
                    781:                        if (c == iwhite && c != 0)
                    782:                                if (cp == gcursor) {
                    783:                                        iwhite = backtab(c);
                    784:                                        CDCNT++;
                    785:                                        ogcursor = cp = genindent(iwhite);
                    786:                                        goto vbackup;
                    787:                                } else if (&cp[1] == gcursor &&
                    788:                                    (*cp == '^' || *cp == '0')) {
                    789:                                        /*
                    790:                                         * ^^D moves to margin, then back
                    791:                                         * to current indent on next line.
                    792:                                         *
                    793:                                         * 0^D moves to margin and then
                    794:                                         * stays there.
                    795:                                         */
                    796:                                        HADZERO = *cp == '0';
                    797:                                        ogcursor = cp = genbuf;
                    798:                                        HADUP = 1 - HADZERO;
                    799:                                        CDCNT = 1;
                    800:                                        endim();
                    801:                                        back1();
                    802:                                        vputchar(' ');
                    803:                                        goto vbackup;
                    804:                                }
                    805:                        if (vglobp && vglobp - iglobp >= 2 &&
                    806:                            (vglobp[-2] == '^' || vglobp[-2] == '0')
                    807:                            && gcursor == ogcursor + 1)
                    808:                                goto bakchar;
                    809:                        continue;
                    810: 
                    811:                default:
                    812:                        /*
                    813:                         * Possibly discard control inputs.
                    814:                         */
                    815:                        if (!vglobp && junk(c)) {
                    816:                                beep();
                    817:                                continue;
                    818:                        }
                    819: def:
                    820:                        if (!backsl) {
                    821:                                int cnt;
                    822:                                putchar(c);
                    823:                                flush();
                    824:                        }
                    825:                        if (gcursor > &genbuf[LBSIZE - 2])
                    826:                                error("Line too long");
                    827:                        *gcursor++ = c & TRIM;
                    828:                        vcsync();
                    829:                        if (value(SHOWMATCH) && !iglobp)
                    830:                                if (c == ')' || c == '}')
                    831:                                        lsmatch(gcursor);
                    832:                        continue;
                    833:                }
                    834:        }
                    835: vadone:
                    836:        *gcursor = 0;
                    837:        if (Outchar != termchar)
                    838:                Outchar = OO;
                    839:        endim();
                    840:        return (gcursor);
                    841: }
                    842: 
                    843: int    vgetsplit();
                    844: char   *vsplitpt;
                    845: 
                    846: /*
                    847:  * Append the line in buffer at lp
                    848:  * to the buffer after dot.
                    849:  */
                    850: vdoappend(lp)
                    851:        char *lp;
                    852: {
                    853:        register int oing = inglobal;
                    854: 
                    855:        vsplitpt = lp;
                    856:        inglobal = 1;
                    857:        ignore(append(vgetsplit, dot));
                    858:        inglobal = oing;
                    859: }
                    860: 
                    861: /*
                    862:  * Subroutine for vdoappend to pass to append.
                    863:  */
                    864: vgetsplit()
                    865: {
                    866: 
                    867:        if (vsplitpt == 0)
                    868:                return (EOF);
                    869:        strcLIN(vsplitpt);
                    870:        vsplitpt = 0;
                    871:        return (0);
                    872: }
                    873: 
                    874: /*
                    875:  * Vmaxrep determines the maximum repetitition factor
                    876:  * allowed that will yield total line length less than
                    877:  * LBSIZE characters and also does hacks for the R command.
                    878:  */
                    879: vmaxrep(ch, cnt)
                    880:        char ch;
                    881:        register int cnt;
                    882: {
                    883:        register int len, replen;
                    884: 
                    885:        if (cnt > LBSIZE - 2)
                    886:                cnt = LBSIZE - 2;
                    887:        replen = strlen(genbuf);
                    888:        if (ch == 'R') {
                    889:                len = strlen(cursor);
                    890:                if (replen < len)
                    891:                        len = replen;
                    892:                CP(cursor, cursor + len);
                    893:                vUD2 += len;
                    894:        }
                    895:        len = strlen(linebuf);
                    896:        if (len + cnt * replen <= LBSIZE - 2)
                    897:                return (cnt);
                    898:        cnt = (LBSIZE - 2 - len) / replen;
                    899:        if (cnt == 0) {
                    900:                vsave();
                    901:                error("Line too long");
                    902:        }
                    903:        return (cnt);
                    904: }

unix.superglobalmegacorp.com

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