Annotation of coherent/g/usr/bin/vi/vcmd.c, revision 1.1.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.