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

unix.superglobalmegacorp.com

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