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

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

unix.superglobalmegacorp.com

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