Annotation of coherent/g/usr/bin/vi/vcmd.c, revision 1.1

1.1     ! root        1: /* vcmd.c */
        !             2: 
        !             3: /* Author:
        !             4:  *     Steve Kirkendall
        !             5:  *     14407 SW Teal Blvd. #C
        !             6:  *     Beaverton, OR 97005
        !             7:  *     [email protected]
        !             8:  */
        !             9: 
        !            10: 
        !            11: /* This file contains the functions that handle VI commands */
        !            12: 
        !            13: 
        !            14: #include "config.h"
        !            15: #include "ctype.h"
        !            16: #include "vi.h"
        !            17: #if MSDOS
        !            18: # include <process.h>
        !            19: # include <string.h>
        !            20: #endif
        !            21: #if TOS
        !            22: # include <osbind.h>
        !            23: # include <string.h>
        !            24: #endif
        !            25: #if OSK
        !            26: # include <stdio.h>
        !            27: #endif
        !            28: 
        !            29: 
        !            30: /* This function puts the editor in EX mode */
        !            31: MARK v_quit()
        !            32: {
        !            33:        move(LINES - 1, 0);
        !            34:        mode = MODE_EX;
        !            35:        return cursor;
        !            36: }
        !            37: 
        !            38: /* This function causes the screen to be redrawn */
        !            39: MARK v_redraw()
        !            40: {
        !            41:        redraw(MARK_UNSET, FALSE);
        !            42:        return cursor;
        !            43: }
        !            44: 
        !            45: /* This function executes a string of EX commands, and waits for a user keystroke
        !            46:  * before returning to the VI screen.  If that keystroke is another ':', then
        !            47:  * another EX command is read and executed.
        !            48:  */
        !            49: /*ARGSUSED*/
        !            50: MARK v_1ex(m, text)
        !            51:        MARK    m;      /* the current line */
        !            52:        char    *text;  /* the first command to execute */
        !            53: {
        !            54:        /* run the command.  be careful about modes & output */
        !            55:        exwrote = (mode == MODE_COLON);
        !            56:        doexcmd(text);
        !            57:        exrefresh();
        !            58: 
        !            59:        /* if mode is no longer MODE_VI, then we should quit right away! */
        !            60:        if (mode != MODE_VI && mode != MODE_COLON)
        !            61:                return cursor;
        !            62: 
        !            63:        /* The command did some output.  Wait for a keystoke. */
        !            64:        if (exwrote)
        !            65:        {
        !            66:                mode = MODE_VI; 
        !            67:                msg("[Hit <RETURN> to continue]");
        !            68:                if (getkey(0) == ':')
        !            69:                {       mode = MODE_COLON;
        !            70:                        addch('\n');
        !            71:                }
        !            72:                else
        !            73:                        redraw(MARK_UNSET, FALSE);
        !            74:        }
        !            75: 
        !            76:        return cursor;
        !            77: }
        !            78: 
        !            79: /* This function undoes the last change */
        !            80: /*ARGSUSED*/
        !            81: MARK v_undo(m)
        !            82:        MARK    m;      /* (ignored) */
        !            83: {
        !            84:        if (undo())
        !            85:        {
        !            86:                redraw(MARK_UNSET, FALSE);
        !            87:        }
        !            88:        return cursor;
        !            89: }
        !            90: 
        !            91: /* This function deletes the character(s) that the cursor is on */
        !            92: MARK v_xchar(m, cnt, cmd)
        !            93:        MARK    m;      /* where to start deletions */
        !            94:        long    cnt;    /* number of chars to delete */
        !            95:        int     cmd;    /* either 'x' or 'X' */
        !            96: {
        !            97:        DEFAULT(1);
        !            98: 
        !            99:        /* for 'X', adjust so chars are deleted *BEFORE* cursor */
        !           100:        if (cmd == 'X')
        !           101:        {
        !           102:                if (markidx(m) < cnt)
        !           103:                        return MARK_UNSET;
        !           104:                m -= cnt;
        !           105:        }
        !           106: 
        !           107:        /* make sure we don't try to delete more thars than there are */
        !           108:        pfetch(markline(m));
        !           109:        if (markidx(m + cnt) > plen)
        !           110:        {
        !           111:                cnt = plen - markidx(m);
        !           112:        }
        !           113:        if (cnt == 0L)
        !           114:        {
        !           115:                return MARK_UNSET;
        !           116:        }
        !           117: 
        !           118:        /* do it */
        !           119:        ChangeText
        !           120:        {
        !           121:                cut(m, m + cnt);
        !           122:                delete(m, m + cnt);
        !           123:        }
        !           124:        return m;
        !           125: }
        !           126: 
        !           127: /* This function defines a mark */
        !           128: /*ARGSUSED*/
        !           129: MARK v_mark(m, count, key)
        !           130:        MARK    m;      /* where the mark will be */
        !           131:        long    count;  /* (ignored) */
        !           132:        int     key;    /* the ASCII label of the mark */
        !           133: {
        !           134:        if (key < 'a' || key > 'z')
        !           135:        {
        !           136:                msg("Marks must be from a to z");
        !           137:        }
        !           138:        else
        !           139:        {
        !           140:                mark[key - 'a'] = m;
        !           141:        }
        !           142:        return m;
        !           143: }
        !           144: 
        !           145: /* This function toggles upper & lower case letters */
        !           146: MARK v_ulcase(m, cnt)
        !           147:        MARK    m;      /* where to make the change */
        !           148:        long    cnt;    /* number of chars to flip */
        !           149: {
        !           150:        REG char        *pos;
        !           151:        REG int         j;
        !           152: 
        !           153:        DEFAULT(1);
        !           154: 
        !           155:        /* fetch the current version of the line */
        !           156:        pfetch(markline(m));
        !           157: 
        !           158:        /* for each position in the line */
        !           159:        for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++)
        !           160:        {
        !           161:                if (isupper(*pos))
        !           162:                {
        !           163:                        tmpblk.c[j] = tolower(*pos);
        !           164:                }
        !           165:                else
        !           166:                {
        !           167:                        tmpblk.c[j] = toupper(*pos);
        !           168:                }
        !           169:        }
        !           170: 
        !           171:        /* if the new text is different from the old, then change it */
        !           172:        if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
        !           173:        {
        !           174:                ChangeText
        !           175:                {
        !           176:                        tmpblk.c[j] = '\0';
        !           177:                        change(m, m + j, tmpblk.c);
        !           178:                }
        !           179:        }
        !           180: 
        !           181:        return m + j;
        !           182: }
        !           183: 
        !           184: 
        !           185: MARK v_replace(m, cnt, key)
        !           186:        MARK    m;      /* first char to be replaced */
        !           187:        long    cnt;    /* number of chars to replace */
        !           188:        int     key;    /* what to replace them with */
        !           189: {
        !           190:        REG char        *text;
        !           191:        REG int         i;
        !           192: 
        !           193:        DEFAULT(1);
        !           194: 
        !           195:        /* map ^M to '\n' */
        !           196:        if (key == '\r')
        !           197:        {
        !           198:                key = '\n';
        !           199:        }
        !           200: 
        !           201:        /* make sure the resulting line isn't too long */
        !           202:        if (cnt > BLKSIZE - 2 - markidx(m))
        !           203:        {
        !           204:                cnt = BLKSIZE - 2 - markidx(m);
        !           205:        }
        !           206: 
        !           207:        /* build a string of the desired character with the desired length */
        !           208:        for (text = tmpblk.c, i = cnt; i > 0; i--)
        !           209:        {
        !           210:                *text++ = key;
        !           211:        }
        !           212:        *text = '\0';
        !           213: 
        !           214:        /* make sure cnt doesn't extend past EOL */
        !           215:        pfetch(markline(m));
        !           216:        key = markidx(m);
        !           217:        if (key + cnt > plen)
        !           218:        {
        !           219:                cnt = plen - key;
        !           220:        }
        !           221: 
        !           222:        /* do the replacement */
        !           223:        ChangeText
        !           224:        {
        !           225:                change(m, m + cnt, tmpblk.c);
        !           226:        }
        !           227: 
        !           228:        if (*tmpblk.c == '\n')
        !           229:        {
        !           230:                return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
        !           231:        }
        !           232:        else
        !           233:        {
        !           234:                return m + cnt - 1;
        !           235:        }
        !           236: }
        !           237: 
        !           238: MARK v_overtype(m)
        !           239:        MARK            m;      /* where to start overtyping */
        !           240: {
        !           241:        MARK            end;    /* end of a substitution */
        !           242:        static long     width;  /* width of a single-line replace */
        !           243: 
        !           244:        /* the "doingdot" version of replace is really a substitution */
        !           245:        if (doingdot)
        !           246:        {
        !           247:                /* was the last one really repeatable? */
        !           248:                if (width < 0)
        !           249:                {
        !           250:                        msg("Can't repeat a multi-line overtype command");
        !           251:                        return MARK_UNSET;
        !           252:                }
        !           253: 
        !           254:                /* replacing nothing by nothing?  Don't bother */
        !           255:                if (width == 0)
        !           256:                {
        !           257:                        return m;
        !           258:                }
        !           259: 
        !           260:                /* replace some chars by repeated text */
        !           261:                return v_subst(m, width);
        !           262:        }
        !           263: 
        !           264:        /* Normally, we input starting here, in replace mode */
        !           265:        ChangeText
        !           266:        {
        !           267:                end = input(m, m, WHEN_VIREP, 0);
        !           268:        }
        !           269: 
        !           270:        /* if we ended on the same line we started on, then this
        !           271:         * overtype is repeatable via the dot key.
        !           272:         */
        !           273:        if (markline(end) == markline(m) && end >= m - 1L)
        !           274:        {
        !           275:                width = end - m + 1L;
        !           276:        }
        !           277:        else /* it isn't repeatable */
        !           278:        {
        !           279:                width = -1L;
        !           280:        }
        !           281: 
        !           282:        return end;
        !           283: }
        !           284: 
        !           285: 
        !           286: /* This function selects which cut buffer to use */
        !           287: /*ARGSUSED*/
        !           288: MARK v_selcut(m, cnt, key)
        !           289:        MARK    m;
        !           290:        long    cnt;
        !           291:        int     key;
        !           292: {
        !           293:        cutname(key);
        !           294:        return m;
        !           295: }
        !           296: 
        !           297: /* This function pastes text from a cut buffer */
        !           298: /*ARGSUSED*/
        !           299: MARK v_paste(m, cnt, cmd)
        !           300:        MARK    m;      /* where to paste the text */
        !           301:        long    cnt;    /* (ignored) */
        !           302:        int     cmd;    /* either 'p' or 'P' */
        !           303: {
        !           304:        MARK    dest;
        !           305: 
        !           306:        ChangeText
        !           307:        {
        !           308:                /* paste the text, and find out where it ends */
        !           309:                dest = paste(m, cmd == 'p', TRUE);
        !           310: 
        !           311:                /* was that a line-mode paste? */
        !           312:                if (dest && markline(dest) != markline(m))
        !           313:                {
        !           314:                        /* line-mode pastes leave the cursor at the front
        !           315:                         * of the first pasted line.
        !           316:                         */
        !           317:                        dest = m;
        !           318:                        if (cmd == 'p')
        !           319:                        {
        !           320:                                dest += BLKSIZE;
        !           321:                        }
        !           322:                        force_flags |= FRNT;
        !           323:                }
        !           324:        }
        !           325:        return dest;
        !           326: }
        !           327: 
        !           328: /* This function yanks text into a cut buffer */
        !           329: MARK v_yank(m, n)
        !           330:        MARK    m, n;   /* range of text to yank */
        !           331: {
        !           332:        cut(m, n);
        !           333:        return m;
        !           334: }
        !           335: 
        !           336: /* This function deletes a range of text */
        !           337: MARK v_delete(m, n)
        !           338:        MARK    m, n;   /* range of text to delete */
        !           339: {
        !           340:        /* illegal to try and delete nothing */
        !           341:        if (n <= m)
        !           342:        {
        !           343:                return MARK_UNSET;
        !           344:        }
        !           345: 
        !           346:        /* Do it */
        !           347:        ChangeText
        !           348:        {
        !           349:                cut(m, n);
        !           350:                delete(m, n);
        !           351:        }
        !           352:        return m;
        !           353: }
        !           354: 
        !           355: 
        !           356: /* This starts input mode without deleting anything */
        !           357: MARK v_insert(m, cnt, key)
        !           358:        MARK    m;      /* where to start (sort of) */
        !           359:        long    cnt;    /* repeat how many times? */
        !           360:        int     key;    /* what command is this for? {a,A,i,I,o,O} */
        !           361: {
        !           362:        int     wasdot;
        !           363:        long    reps;
        !           364:        int     delta = 0;/* 1 to take autoindent from line below, -1 for above */
        !           365: 
        !           366:        DEFAULT(1);
        !           367: 
        !           368:        ChangeText
        !           369:        {
        !           370:                /* tweak the insertion point, based on command key */
        !           371:                switch (key)
        !           372:                {
        !           373:                  case 'i':
        !           374:                        break;
        !           375: 
        !           376:                  case 'a':
        !           377:                        pfetch(markline(m));
        !           378:                        if (plen > 0)
        !           379:                        {
        !           380:                                m++;
        !           381:                        }
        !           382:                        break;
        !           383: 
        !           384:                  case 'I':
        !           385:                        m = m_front(m, 1L);
        !           386:                        break;
        !           387: 
        !           388:                  case 'A':
        !           389:                        pfetch(markline(m));
        !           390:                        m = (m & ~(BLKSIZE - 1)) + plen;
        !           391:                        break;
        !           392: 
        !           393:                  case 'O':
        !           394:                        m &= ~(BLKSIZE - 1);
        !           395:                        add(m, "\n");
        !           396:                        delta = 1;
        !           397:                        break;
        !           398: 
        !           399:                  case 'o':
        !           400:                        m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
        !           401:                        add(m, "\n");
        !           402:                        delta = -1;
        !           403:                        break;
        !           404:                }
        !           405: 
        !           406:                /* insert the same text once or more */
        !           407:                for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
        !           408:                {
        !           409:                        m = input(m, m, WHEN_VIINP, delta) + 1;
        !           410:                }
        !           411:                if (markidx(m) > 0)
        !           412:                {
        !           413:                        m--;
        !           414:                }
        !           415: 
        !           416:                doingdot = wasdot;
        !           417:        }
        !           418: 
        !           419: #ifndef CRUNCH
        !           420: # ifndef NO_EXTENSIONS
        !           421:        if (key == 'i' && *o_inputmode && mode == MODE_VI)
        !           422:        {
        !           423:                msg("Now in command mode!  To return to input mode, hit <i>");
        !           424:        }
        !           425: # endif
        !           426: #endif
        !           427: 
        !           428:        return m;
        !           429: }
        !           430: 
        !           431: /* This starts input mode with some text deleted */
        !           432: MARK v_change(m, n)
        !           433:        MARK    m, n;   /* the range of text to change */
        !           434: {
        !           435:        int     lnmode; /* is this a line-mode change? */
        !           436: 
        !           437:        /* swap them if they're in reverse order */
        !           438:        if (m > n)
        !           439:        {
        !           440:                MARK    tmp;
        !           441:                tmp = m;
        !           442:                m = n;
        !           443:                n = tmp;
        !           444:        }
        !           445: 
        !           446:        /* for line mode, retain the last newline char */
        !           447:        lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
        !           448:        if (lnmode)
        !           449:        {
        !           450:                n -= BLKSIZE;
        !           451:                pfetch(markline(n));
        !           452:                n = (n & ~(BLKSIZE - 1)) + plen;
        !           453:        }
        !           454: 
        !           455:        ChangeText
        !           456:        {
        !           457:                cut(m, n);
        !           458:                m = input(m, n, WHEN_VIINP, 0);
        !           459:        }
        !           460: 
        !           461:        return m;
        !           462: }
        !           463: 
        !           464: /* This function replaces a given number of characters with input */
        !           465: MARK v_subst(m, cnt)
        !           466:        MARK    m;      /* where substitutions start */
        !           467:        long    cnt;    /* number of chars to replace */
        !           468: {
        !           469:        DEFAULT(1);
        !           470: 
        !           471:        /* make sure we don't try replacing past EOL */
        !           472:        pfetch(markline(m));
        !           473:        if (markidx(m) + cnt > plen)
        !           474:        {
        !           475:                cnt = plen - markidx(m);
        !           476:        }
        !           477: 
        !           478:        /* Go for it! */
        !           479:        ChangeText
        !           480:        {
        !           481:                cut(m, m + cnt);
        !           482:                m = input(m, m + cnt, WHEN_VIINP, 0);
        !           483:        }
        !           484:        return m;
        !           485: }
        !           486: 
        !           487: /* This calls the ex "join" command to join some lines together */
        !           488: MARK v_join(m, cnt)
        !           489:        MARK    m;      /* the first line to be joined */
        !           490:        long    cnt;    /* number of other lines to join */
        !           491: {
        !           492:        MARK    joint;  /* where the lines were joined */
        !           493: 
        !           494:        DEFAULT(1);
        !           495: 
        !           496:        /* figure out where the joint will be */
        !           497:        pfetch(markline(m));
        !           498:        joint = (m & ~(BLKSIZE - 1)) + plen;
        !           499: 
        !           500:        /* join the lines */
        !           501:        cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
        !           502: 
        !           503:        /* the cursor should be left at the joint */
        !           504:        return joint;
        !           505: }
        !           506: 
        !           507: 
        !           508: /* This calls the ex "<" command to shift some lines left */
        !           509: MARK v_lshift(m, n)
        !           510:        MARK    m, n;   /* range of lines to shift */
        !           511: {
        !           512:        /* adjust for inclusive endmarks in ex */
        !           513:        n -= BLKSIZE;
        !           514: 
        !           515:        cmd_shift(m, n, CMD_SHIFTL, FALSE, (char *)0);
        !           516: 
        !           517:        return m;
        !           518: }
        !           519: 
        !           520: /* This calls the ex ">" command to shift some lines right */
        !           521: MARK v_rshift(m, n)
        !           522:        MARK    m, n;   /* range of lines to shift */
        !           523: {
        !           524:        /* adjust for inclusive endmarks in ex */
        !           525:        n -= BLKSIZE;
        !           526: 
        !           527:        cmd_shift(m, n, CMD_SHIFTR, FALSE, (char *)0);
        !           528: 
        !           529:        return m;
        !           530: }
        !           531: 
        !           532: /* This filters some lines through a preset program, to reformat them */
        !           533: MARK v_reformat(m, n)
        !           534:        MARK    m, n;   /* range of lines to shift */
        !           535: {
        !           536:        /* adjust for inclusive endmarks in ex */
        !           537:        n -= BLKSIZE;
        !           538: 
        !           539:        /* run the filter command */
        !           540:        filter(m, n, o_equalprg, TRUE);
        !           541: 
        !           542:        redraw(MARK_UNSET, FALSE);
        !           543:        return m;
        !           544: }
        !           545: 
        !           546: 
        !           547: /* This runs some lines through a filter program */
        !           548: MARK v_filter(m, n)
        !           549:        MARK    m, n;   /* range of lines to shift */
        !           550: {
        !           551:        char    cmdln[150];     /* a shell command line */
        !           552: 
        !           553:        /* adjust for inclusive endmarks in ex */
        !           554:        n -= BLKSIZE;
        !           555: 
        !           556:        if (vgets('!', cmdln, sizeof(cmdln)) > 0)
        !           557:        {
        !           558:                filter(m, n, cmdln, TRUE);
        !           559:        }
        !           560: 
        !           561:        redraw(MARK_UNSET, FALSE);
        !           562:        return m;
        !           563: }
        !           564: 
        !           565: 
        !           566: /* This function runs the ex "file" command to show the file's status */
        !           567: MARK v_status()
        !           568: {
        !           569:        cmd_file(cursor, cursor, CMD_FILE, 0, "");
        !           570:        return cursor;
        !           571: }
        !           572: 
        !           573: 
        !           574: /* This function runs the ":&" command to repeat the previous :s// */
        !           575: MARK v_again(m, n)
        !           576:        MARK    m, n;
        !           577: {
        !           578:        cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
        !           579:        return cursor;
        !           580: }
        !           581: 
        !           582: 
        !           583: 
        !           584: /* This function switches to the previous file, if possible */
        !           585: MARK v_switch()
        !           586: {
        !           587:        if (!*prevorig)
        !           588:                msg("No previous file");
        !           589:        else
        !           590:        {       strcpy(tmpblk.c, prevorig);
        !           591:                cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
        !           592:        }
        !           593:        return cursor;
        !           594: }
        !           595: 
        !           596: /* This function does a tag search on a keyword */
        !           597: /*ARGSUSED*/
        !           598: MARK v_tag(keyword, m, cnt)
        !           599:        char    *keyword;
        !           600:        MARK    m;
        !           601:        long    cnt;
        !           602: {
        !           603:        /* move the cursor to the start of the tag name, where m is */
        !           604:        cursor = m;
        !           605: 
        !           606:        /* perform the tag search */
        !           607:        cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
        !           608: 
        !           609:        return cursor;
        !           610: }
        !           611: 
        !           612: #ifndef NO_EXTENSIONS
        !           613: /* This function looks up a keyword by calling the helpprog program */
        !           614: /*ARGSUSED*/
        !           615: MARK v_keyword(keyword, m, cnt)
        !           616:        char    *keyword;
        !           617:        MARK    m;
        !           618:        long    cnt;
        !           619: {
        !           620:        int     waswarn;
        !           621:        char    cmdline[130];
        !           622: 
        !           623:        move(LINES - 1, 0);
        !           624:        addstr("---------------------------------------------------------\n");
        !           625:        clrtoeol();
        !           626:        refresh();
        !           627:        sprintf(cmdline, "%s %s", o_keywordprg, keyword);
        !           628:        waswarn = *o_warn;
        !           629:        *o_warn = FALSE;
        !           630:        suspend_curses();
        !           631:        if (system(cmdline))
        !           632:        {
        !           633:                addstr("<<< failed >>>\n");
        !           634:        }
        !           635:        resume_curses(FALSE);
        !           636:        mode = MODE_VI;
        !           637:        redraw(MARK_UNSET, FALSE);
        !           638:        *o_warn = waswarn;
        !           639: 
        !           640:        return m;
        !           641: }
        !           642: 
        !           643: 
        !           644: 
        !           645: MARK v_increment(keyword, m, cnt)
        !           646:        char    *keyword;
        !           647:        MARK    m;
        !           648:        long    cnt;
        !           649: {
        !           650:        static  sign;
        !           651:        char    newval[12];
        !           652:        long    atol();
        !           653: 
        !           654:        DEFAULT(1);
        !           655: 
        !           656:        /* get one more keystroke, unless doingdot */
        !           657:        if (!doingdot)
        !           658:        {
        !           659:                sign = getkey(0);
        !           660:        }
        !           661: 
        !           662:        /* adjust the number, based on that second keystroke */
        !           663:        switch (sign)
        !           664:        {
        !           665:          case '+':
        !           666:          case '#':
        !           667:                cnt = atol(keyword) + cnt;
        !           668:                break;
        !           669: 
        !           670:          case '-':
        !           671:                cnt = atol(keyword) - cnt;
        !           672:                break;
        !           673: 
        !           674:          case '=':
        !           675:                break;
        !           676: 
        !           677:          default:
        !           678:                return MARK_UNSET;
        !           679:        }
        !           680:        sprintf(newval, "%ld", cnt);
        !           681: 
        !           682:        ChangeText
        !           683:        {
        !           684:                change(m, m + strlen(keyword), newval);
        !           685:        }
        !           686: 
        !           687:        return m;
        !           688: }
        !           689: #endif
        !           690: 
        !           691: 
        !           692: /* This function acts like the EX command "xit" */
        !           693: /*ARGSUSED*/
        !           694: MARK v_xit(m, cnt, key)
        !           695:        MARK    m;      /* ignored */
        !           696:        long    cnt;    /* ignored */
        !           697:        int     key;    /* must be a second 'Z' */
        !           698: {
        !           699:        /* if second char wasn't 'Z', fail */
        !           700:        if (key != 'Z')
        !           701:        {
        !           702:                return MARK_UNSET;
        !           703:        }
        !           704: 
        !           705:        /* move the cursor to the bottom of the screen */
        !           706:        move(LINES - 1, 0);
        !           707:        clrtoeol();
        !           708: 
        !           709:        /* do the xit command */
        !           710:        cmd_xit(m, m, CMD_XIT, FALSE, "");
        !           711: 
        !           712:        /* return the cursor */
        !           713:        return m;
        !           714: }
        !           715: 
        !           716: 
        !           717: /* This function undoes changes to a single line, if possible */
        !           718: MARK v_undoline(m)
        !           719:        MARK    m;      /* where we hope to undo the change */
        !           720: {
        !           721:        /* make sure we have the right line in the buffer */
        !           722:        if (markline(m) != U_line)
        !           723:        {
        !           724:                return MARK_UNSET;
        !           725:        }
        !           726: 
        !           727:        /* fix it */
        !           728:        ChangeText
        !           729:        {
        !           730:                strcat(U_text, "\n");
        !           731:                change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
        !           732:        }
        !           733: 
        !           734:        /* nothing in the buffer anymore */
        !           735:        U_line = -1L;
        !           736: 
        !           737:        /* return, with the cursor at the front of the line */
        !           738:        return m & ~(BLKSIZE - 1);
        !           739: }
        !           740: 
        !           741: 
        !           742: #ifndef NO_ERRLIST
        !           743: MARK v_errlist(m)
        !           744:        MARK    m;
        !           745: {
        !           746:        cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
        !           747:        return cursor;
        !           748: }
        !           749: #endif
        !           750: 
        !           751: 
        !           752: #ifndef NO_AT
        !           753: /*ARGSUSED*/
        !           754: MARK v_at(m, cnt, key)
        !           755:        MARK    m;
        !           756:        long    cnt;
        !           757:        int     key;
        !           758: {
        !           759:        int     size;
        !           760: 
        !           761:        size = cb2str(key, tmpblk.c, BLKSIZE);
        !           762:        if (size <= 0 || size == BLKSIZE)
        !           763:        {
        !           764:                return MARK_UNSET;
        !           765:        }
        !           766: 
        !           767:        execmap(0, tmpblk.c, FALSE);
        !           768:        return cursor;
        !           769: }
        !           770: #endif
        !           771: 
        !           772: 
        !           773: #ifdef SIGTSTP
        !           774: MARK v_suspend()
        !           775: {
        !           776:        cmd_suspend(MARK_UNSET, MARK_UNSET, CMD_SUSPEND, FALSE, "");
        !           777:        return MARK_UNSET;
        !           778: }
        !           779: #endif
        !           780: 
        !           781: 
        !           782: #ifndef NO_VISIBLE
        !           783: /*ARGSUSED*/
        !           784: MARK v_start(m, cnt, cmd)
        !           785:        MARK    m;      /* starting point for a v or V command */
        !           786:        long    cnt;    /* ignored */
        !           787:        int     cmd;    /* either 'v' or 'V' */
        !           788: {
        !           789:        if (V_from)
        !           790:        {
        !           791:                V_from = MARK_UNSET;
        !           792:        }
        !           793:        else
        !           794:        {
        !           795:                V_from = m;
        !           796:                V_linemd = isupper(cmd);
        !           797:        }
        !           798:        return m;
        !           799: }
        !           800: #endif
        !           801: 
        !           802: #ifndef NO_POPUP
        !           803: # define MENU_HEIGHT 11
        !           804: # define MENU_WIDTH  23
        !           805: MARK v_popup(m, n)
        !           806:        MARK            m, n;   /* the range of text to change */
        !           807: {
        !           808:        int             i;
        !           809:        int             y, x;   /* position where the window will pop up at */
        !           810:        int             key;    /* keystroke from the user */
        !           811:        int             sel;    /* index of the selected operation */
        !           812:        static int      dfltsel;/* default value of sel */
        !           813:        static char     *labels[11] =
        !           814:        {
        !           815:                "ESC cancel!         ",
        !           816:                " d  delete (cut)    ",
        !           817:                " y  yank (copy)     ",
        !           818:                " p  paste after     ",
        !           819:                " P  paste before    ",
        !           820:                " >  more indented   ",
        !           821:                " <  less indented   ",
        !           822:                " =  reformat        ",
        !           823:                " !  external filter ",
        !           824:                " ZZ save & exit     ",
        !           825:                " u  undo previous   "
        !           826:        };
        !           827: 
        !           828:        /* try to position the menu near the cursor */
        !           829:        x = physcol - (MENU_WIDTH / 2);
        !           830:        if (x < 0)
        !           831:                x = 0;
        !           832:        else if (x + MENU_WIDTH + 2 > COLS)
        !           833:                x = COLS - MENU_WIDTH - 2;
        !           834:        if (markline(cursor) < topline || markline(cursor) > botline)
        !           835:                y = 0;
        !           836:        else if (markline(cursor) + 1L + MENU_HEIGHT > botline)
        !           837:                y = (int)(markline(cursor) - topline) - MENU_HEIGHT;
        !           838:        else
        !           839:                y = (int)(markline(cursor) - topline) + 1L;
        !           840: 
        !           841:        /* draw the menu */
        !           842:        for (sel = 0; sel < MENU_HEIGHT; sel++)
        !           843:        {
        !           844:                move(y + sel, x);
        !           845:                do_POPUP();
        !           846:                if (sel == dfltsel)
        !           847:                        qaddstr("-->");
        !           848:                else
        !           849:                        qaddstr("   ");
        !           850:                qaddstr(labels[sel]);
        !           851:                do_SE();
        !           852:        }
        !           853: 
        !           854:        /* get a selection */
        !           855:        move(y + dfltsel, x + 4);
        !           856:        for (sel = dfltsel; (key = getkey(WHEN_POPUP)) != '\\' && key != '\r'; )
        !           857:        {
        !           858:                /* erase the selection arrow */
        !           859:                move(y + sel, x);
        !           860:                do_POPUP();
        !           861:                qaddstr("   ");
        !           862:                qaddstr(labels[sel]);
        !           863:                do_SE();
        !           864: 
        !           865:                /* process the user's keystroke */
        !           866:                if (key == 'j' && sel < MENU_HEIGHT - 1)
        !           867:                {
        !           868:                        sel++;
        !           869:                }
        !           870:                else if (key == 'k' && sel > 0)
        !           871:                {
        !           872:                        sel--;
        !           873:                }
        !           874:                else if (key == '\033')
        !           875:                {
        !           876:                        sel = 0;
        !           877:                        break;
        !           878:                }
        !           879:                else
        !           880:                {
        !           881:                        for (i = 1; i < MENU_HEIGHT && labels[i][1] != key; i++)
        !           882:                        {
        !           883:                        }
        !           884:                        if (i < MENU_HEIGHT)
        !           885:                        {
        !           886:                                sel = i;
        !           887:                                break;
        !           888:                        }
        !           889:                }
        !           890: 
        !           891:                /* redraw the arrow, possibly in a new place */
        !           892:                move(y + sel, x);
        !           893:                do_POPUP();
        !           894:                qaddstr("-->");
        !           895:                qaddstr(labels[sel]);
        !           896:                do_SE();
        !           897:                move(y + sel, x + 4);
        !           898:        }
        !           899: 
        !           900:        /* in most cases, the default selection is "paste after" */
        !           901:        dfltsel = 3;
        !           902: 
        !           903:        /* perform the appropriate action */
        !           904:        switch (sel)
        !           905:        {
        !           906:          case 0:
        !           907:                m = cursor;
        !           908:                dfltsel = 0;
        !           909:                break;
        !           910: 
        !           911:          case 1: /* delete (cut) */
        !           912:                m = v_delete(m, n);
        !           913:                break;
        !           914: 
        !           915:          case 2: /* yank (copy) */
        !           916:                m = v_yank(m, n);
        !           917:                break;
        !           918: 
        !           919:          case 3: /* paste after */
        !           920:                m = v_paste(n, 1L, 'P');
        !           921:                break;
        !           922: 
        !           923:          case 4: /* paste before */
        !           924:                m = v_paste(m, 1L, 'P');
        !           925:                dfltsel = 4;
        !           926:                break;
        !           927: 
        !           928:          case 5: /* more indented */
        !           929:                m = v_rshift(m, n);
        !           930:                dfltsel = 5;
        !           931:                break;
        !           932: 
        !           933:          case 6: /* less indented */
        !           934:                m = v_lshift(m, n);
        !           935:                dfltsel = 6;
        !           936:                break;
        !           937: 
        !           938:          case 7: /* reformat */
        !           939:                m = v_reformat(m, n);
        !           940:                dfltsel = 7;
        !           941:                break;
        !           942: 
        !           943:          case 8: /* external filter */
        !           944:                m = v_filter(m, n);
        !           945:                dfltsel = 0;
        !           946:                break;
        !           947: 
        !           948:          case 9: /* save & exit */
        !           949:                /* get confirmation first */
        !           950:                do
        !           951:                {
        !           952:                        key = getkey(0);
        !           953:                } while (key != '\\' && key != 'Z' && key != '\r'    /* good */
        !           954:                      && key != '\033');                             /* bad  */
        !           955:                if (key != '\033')
        !           956:                {
        !           957:                        m = v_xit(m, 0L, 'Z');
        !           958:                }
        !           959:                break;
        !           960: 
        !           961:          case 10: /* undo previous */
        !           962:                m = v_undo(m);
        !           963:                dfltsel = 9;
        !           964:                break;
        !           965:        }
        !           966: 
        !           967:        /* arrange for the menu to be erased (except "save & exit" doesn't care)
        !           968:         */
        !           969:        if (sel != 9)
        !           970:                redraw(MARK_UNSET, FALSE);
        !           971: 
        !           972:        return m;
        !           973: }
        !           974: #endif /* undef NO_POPUP */

unix.superglobalmegacorp.com

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