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

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

unix.superglobalmegacorp.com

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