Annotation of 3BSD/cmd/ex/ex_vops2.c, revision 1.1

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

unix.superglobalmegacorp.com

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