Annotation of researchv10dc/cmd/ex/ex_vops2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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