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

unix.superglobalmegacorp.com

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