home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elvis_1.4.tar.Z / elvis_1.4.tar / vcmd.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  13KB  |  765 lines

  1. /* vcmd.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the functions that handle VI commands */
  12.  
  13.  
  14. #include "config.h"
  15. #include "vi.h"
  16. #if MSDOS
  17. #include <process.h>
  18. #include <string.h>
  19. #endif
  20. #if TOS
  21. #include <osbind.h>
  22. #include <string.h>
  23. #endif
  24. #if OSK
  25. # include <stdio.h>
  26. #endif
  27.  
  28.  
  29. /* This function puts the editor in EX mode */
  30. MARK v_quit()
  31. {
  32.     move(LINES - 1, 0);
  33.     mode = MODE_EX;
  34.     return cursor;
  35. }
  36.  
  37. /* This function causes the screen to be redrawn */
  38. MARK v_redraw()
  39. {
  40.     redraw(MARK_UNSET, FALSE);
  41.     return cursor;
  42. }
  43.  
  44. /* This function executes a single EX command, and waits for a user keystroke
  45.  * before returning to the VI screen.  If that keystroke is another ':', then
  46.  * another EX command is read and executed.
  47.  */
  48. /*ARGSUSED*/
  49. MARK v_1ex(m, text)
  50.     MARK    m;    /* the current line */
  51.     char    *text;    /* the first command to execute */
  52. {
  53.     /* run the command.  be careful about modes & output */
  54.     exwrote = (mode == MODE_COLON);
  55.     doexcmd(text);
  56.     exrefresh();
  57.  
  58.     /* if mode is no longer MODE_VI, then we should quit right away! */
  59.     if (mode != MODE_VI && mode != MODE_COLON)
  60.         return cursor;
  61.  
  62.     /* The command did some output.  Wait for a keystoke. */
  63.     if (exwrote)
  64.     {
  65.         mode = MODE_VI;    
  66.         msg("[Hit <RETURN> to continue]");
  67.         if (getkey(0) == ':')
  68.         {    mode = MODE_COLON;
  69.             addch('\n');
  70.         }
  71.         else
  72.             redraw(MARK_UNSET, FALSE);
  73.     }
  74.  
  75.     return cursor;
  76. }
  77.  
  78. /* This function undoes the last change */
  79. /*ARGSUSED*/
  80. MARK v_undo(m)
  81.     MARK    m;    /* (ignored) */
  82. {
  83.     if (undo())
  84.     {
  85.         redraw(MARK_UNSET, FALSE);
  86.     }
  87.     return cursor;
  88. }
  89.  
  90. /* This function deletes the character(s) that the cursor is on */
  91. MARK v_xchar(m, cnt, cmd)
  92.     MARK    m;    /* where to start deletions */
  93.     long    cnt;    /* number of chars to delete */
  94.     int    cmd;    /* either 'x' or 'X' */
  95. {
  96.     DEFAULT(1);
  97.  
  98.     /* for 'X', adjust so chars are deleted *BEFORE* cursor */
  99.     if (cmd == 'X')
  100.     {
  101.         if (markidx(m) < cnt)
  102.             return MARK_UNSET;
  103.         m -= cnt;
  104.     }
  105.  
  106.     /* make sure we don't try to delete more thars than there are */
  107.     pfetch(markline(m));
  108.     if (markidx(m + cnt) > plen)
  109.     {
  110.         cnt = plen - markidx(m);
  111.     }
  112.     if (cnt == 0L)
  113.     {
  114.         return MARK_UNSET;
  115.     }
  116.  
  117.     /* do it */
  118.     ChangeText
  119.     {
  120.         cut(m, m + cnt);
  121.         delete(m, m + cnt);
  122.     }
  123.     return m;
  124. }
  125.  
  126. /* This function defines a mark */
  127. /*ARGSUSED*/
  128. MARK v_mark(m, count, key)
  129.     MARK    m;    /* where the mark will be */
  130.     long    count;    /* (ignored) */
  131.     int    key;    /* the ASCII label of the mark */
  132. {
  133.     if (key < 'a' || key > 'z')
  134.     {
  135.         msg("Marks must be from a to z");
  136.     }
  137.     else
  138.     {
  139.         mark[key - 'a'] = m;
  140.     }
  141.     return m;
  142. }
  143.  
  144. /* This function toggles upper & lower case letters */
  145. MARK v_ulcase(m, cnt)
  146.     MARK    m;    /* where to make the change */
  147.     long    cnt;    /* number of chars to flip */
  148. {
  149.     REG char     *pos;
  150.     REG int        i, j;
  151.     static char    flip[] =
  152.         "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ[](){}<>";
  153.  
  154.     DEFAULT(1);
  155.  
  156.     /* fetch the current version of the line */
  157.     pfetch(markline(m));
  158.  
  159.     /* for each position in the line */
  160.     for (j = 0, i = markidx(m); j < cnt && ptext[i]; j++, i++)
  161.     {
  162.         tmpblk.c[j] = 0;
  163.  
  164.         /* one of the standard chars? */
  165.         for (pos = flip; *pos && *pos != ptext[i]; pos++)
  166.         {
  167.         }
  168.         if (*pos)
  169.         {
  170.             tmpblk.c[j] = flip[(int)(pos - flip) ^ 1];
  171.         }
  172. #ifndef NO_DIGRAPH
  173.         else /* one of the non-standard chars? */
  174.         {
  175.             for (pos = o_flipcase; *pos && *pos != ptext[i]; pos++)
  176.             {
  177.             }
  178.             if (*pos)
  179.             {
  180.                 tmpblk.c[j] = o_flipcase[(int)(pos - o_flipcase) ^ 1];
  181.             }
  182.         }
  183. #endif
  184.  
  185.         /* if nothing special, then don't change it */
  186.         if (tmpblk.c[j] == 0)
  187.         {
  188.             tmpblk.c[j] = ptext[i];
  189.         }
  190.     }
  191.  
  192.     /* if the new text is different from the old, then change it */
  193.     if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
  194.     {
  195.         ChangeText
  196.         {
  197.             tmpblk.c[j] = '\0';
  198.             change(m, m + j, tmpblk.c);
  199.         }
  200.     }
  201.  
  202.     return m + j;
  203. }
  204.  
  205.  
  206. MARK v_replace(m, cnt, key)
  207.     MARK    m;    /* first char to be replaced */
  208.     long    cnt;    /* number of chars to replace */
  209.     int    key;    /* what to replace them with */
  210. {
  211.     REG char    *text;
  212.     REG int        i;
  213.  
  214.     DEFAULT(1);
  215.  
  216.     /* map ^M to '\n' */
  217.     if (key == '\r')
  218.     {
  219.         key = '\n';
  220.     }
  221.  
  222.     /* make sure the resulting line isn't too long */
  223.     if (cnt > BLKSIZE - 2 - markidx(m))
  224.     {
  225.         cnt = BLKSIZE - 2 - markidx(m);
  226.     }
  227.  
  228.     /* build a string of the desired character with the desired length */
  229.     for (text = tmpblk.c, i = cnt; i > 0; i--)
  230.     {
  231.         *text++ = key;
  232.     }
  233.     *text = '\0';
  234.  
  235.     /* make sure cnt doesn't extend past EOL */
  236.     pfetch(markline(m));
  237.     key = markidx(m);
  238.     if (key + cnt > plen)
  239.     {
  240.         cnt = plen - key;
  241.     }
  242.  
  243.     /* do the replacement */
  244.     ChangeText
  245.     {
  246.         change(m, m + cnt, tmpblk.c);
  247.     }
  248.  
  249.     if (*tmpblk.c == '\n')
  250.     {
  251.         return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
  252.     }
  253.     else
  254.     {
  255.         return m + cnt - 1;
  256.     }
  257. }
  258.  
  259. MARK v_overtype(m)
  260.     MARK        m;    /* where to start overtyping */
  261. {
  262.     MARK        end;    /* end of a substitution */
  263.     static long    width;    /* width of a single-line replace */
  264.  
  265.     /* the "doingdot" version of replace is really a substitution */
  266.     if (doingdot)
  267.     {
  268.         /* was the last one really repeatable? */
  269.         if (width < 0)
  270.         {
  271.             msg("Can't repeat a multi-line overtype command");
  272.             return MARK_UNSET;
  273.         }
  274.  
  275.         /* replacing nothing by nothing?  Don't bother */
  276.         if (width == 0)
  277.         {
  278.             return m;
  279.         }
  280.  
  281.         /* replace some chars by repeated text */
  282.         return v_subst(m, width);
  283.     }
  284.  
  285.     /* Normally, we input starting here, in replace mode */
  286.     ChangeText
  287.     {
  288.         end = input(m, m, WHEN_VIREP);
  289.     }
  290.  
  291.     /* if we ended on the same line we started on, then this
  292.      * overtype is repeatable via the dot key.
  293.      */
  294.     if (markline(end) == markline(m) && end >= m - 1L)
  295.     {
  296.         width = end - m + 1L;
  297.     }
  298.     else /* it isn't repeatable */
  299.     {
  300.         width = -1L;
  301.     }
  302.  
  303.     return end;
  304. }
  305.  
  306.  
  307. /* This function selects which cut buffer to use */
  308. /*ARGSUSED*/
  309. MARK v_selcut(m, cnt, key)
  310.     MARK    m;
  311.     long    cnt;
  312.     int    key;
  313. {
  314.     cutname(key);
  315.     return m;
  316. }
  317.  
  318. /* This function pastes text from a cut buffer */
  319. /*ARGSUSED*/
  320. MARK v_paste(m, cnt, cmd)
  321.     MARK    m;    /* where to paste the text */
  322.     long    cnt;    /* (ignored) */
  323.     int    cmd;    /* either 'p' or 'P' */
  324. {
  325.     ChangeText
  326.     {
  327.         m = paste(m, cmd == 'p', FALSE);
  328.     }
  329.     return m;
  330. }
  331.  
  332. /* This function yanks text into a cut buffer */
  333. MARK v_yank(m, n)
  334.     MARK    m, n;    /* range of text to yank */
  335. {
  336.     cut(m, n);
  337.     return m;
  338. }
  339.  
  340. /* This function deletes a range of text */
  341. MARK v_delete(m, n)
  342.     MARK    m, n;    /* range of text to delete */
  343. {
  344.     /* illegal to try and delete nothing */
  345.     if (n <= m)
  346.     {
  347.         return MARK_UNSET;
  348.     }
  349.  
  350.     /* Do it */
  351.     ChangeText
  352.     {
  353.         cut(m, n);
  354.         delete(m, n);
  355.     }
  356.     return m;
  357. }
  358.  
  359.  
  360. /* This starts input mode without deleting anything */
  361. MARK v_insert(m, cnt, key)
  362.     MARK    m;    /* where to start (sort of) */
  363.     long    cnt;    /* repeat how many times? */
  364.     int    key;    /* what command is this for? {a,A,i,I,o,O} */
  365. {
  366.     int    wasdot;
  367.     long    reps;
  368.     int    after;    /* are we appending or inserting? */
  369.  
  370.     DEFAULT(1);
  371.  
  372.     ChangeText
  373.     {
  374.         /* tweak the insertion point, based on command key */
  375.         switch (key)
  376.         {
  377.           case 'i':
  378.             after = FALSE;
  379.             break;
  380.  
  381.           case 'a':
  382.             pfetch(markline(m));
  383.             if (plen > 0)
  384.             {
  385.                 m++;
  386.             }
  387.             after = TRUE;
  388.             break;
  389.  
  390.           case 'I':
  391.             m = m_front(m, 1L);
  392.             after = FALSE;
  393.             break;
  394.  
  395.           case 'A':
  396.             pfetch(markline(m));
  397.             m = (m & ~(BLKSIZE - 1)) + plen;
  398.             after = TRUE;
  399.             break;
  400.  
  401.           case 'O':
  402.             m &= ~(BLKSIZE - 1);
  403.             add(m, "\n");
  404.             after = FALSE;
  405.             break;
  406.  
  407.           case 'o':
  408.             m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
  409.             add(m, "\n");
  410.             after = FALSE;
  411.             break;
  412.         }
  413.  
  414.         /* insert the same text once or more */
  415.         for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
  416.         {
  417.             m = input(m, m, WHEN_VIINP);
  418.             if (after)
  419.             {
  420.                 m++;
  421.             }
  422.         }
  423.         if (after)
  424.         {
  425.             m--;
  426.         }
  427.  
  428.         doingdot = wasdot;
  429.     }
  430.  
  431. #ifndef CRUNCH
  432. # ifndef NO_EXTENSIONS
  433.     if (key == 'i' && *o_inputmode && mode == MODE_VI)
  434.     {
  435.         msg("Now in visual command mode!  To return to input mode, hit <i>.");
  436.     }
  437. # endif
  438. #endif
  439.  
  440.     return m;
  441. }
  442.  
  443. /* This starts input mode with some text deleted */
  444. MARK v_change(m, n)
  445.     MARK    m, n;    /* the range of text to change */
  446. {
  447.     int    lnmode;    /* is this a line-mode change? */
  448.  
  449.     /* swap them if they're in reverse order */
  450.     if (m > n)
  451.     {
  452.         MARK    tmp;
  453.         tmp = m;
  454.         m = n;
  455.         n = tmp;
  456.     }
  457.  
  458.     /* for line mode, retain the last newline char */
  459.     lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
  460.     if (lnmode)
  461.     {
  462.         n -= BLKSIZE;
  463.         pfetch(markline(n));
  464.         n = (n & ~(BLKSIZE - 1)) + plen;
  465.     }
  466.  
  467.     ChangeText
  468.     {
  469.         cut(m, n);
  470.         m = input(m, n, WHEN_VIINP);
  471.     }
  472.  
  473.     return m;
  474. }
  475.  
  476. /* This function replaces a given number of characters with input */
  477. MARK v_subst(m, cnt)
  478.     MARK    m;    /* where substitutions start */
  479.     long    cnt;    /* number of chars to replace */
  480. {
  481.     DEFAULT(1);
  482.  
  483.     /* make sure we don't try replacing past EOL */
  484.     pfetch(markline(m));
  485.     if (markidx(m) + cnt > plen)
  486.     {
  487.         cnt = plen - markidx(m);
  488.     }
  489.  
  490.     /* Go for it! */
  491.     ChangeText
  492.     {
  493.         cut(m, m + cnt);
  494.         m = input(m, m + cnt, WHEN_VIINP);
  495.     }
  496.     return m;
  497. }
  498.  
  499. /* This calls the ex "join" command to join some lines together */
  500. MARK v_join(m, cnt)
  501.     MARK    m;    /* the first line to be joined */
  502.     long    cnt;    /* number of other lines to join */
  503. {
  504.     MARK    joint;    /* where the lines were joined */
  505.  
  506.     DEFAULT(1);
  507.  
  508.     /* figure out where the joint will be */
  509.     pfetch(markline(m));
  510.     joint = (m & ~(BLKSIZE - 1)) + plen;
  511.  
  512.     /* join the lines */
  513.     cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
  514.     mustredraw = TRUE;
  515.  
  516.     /* the cursor should be left at the joint */
  517.     return joint;
  518. }
  519.  
  520. /* This calls the ex shifter command to shift some lines */
  521. static MARK shift_help(m, n, excmd)
  522.     MARK    m, n;    /* range of lines to shift */
  523.     CMD    excmd;    /* which way do we shift? */
  524. {
  525.     /* adjust for inclusive endmarks in ex */
  526.     n -= BLKSIZE;
  527.  
  528.     cmd_shift(m, n, excmd, 0, "");
  529.     return m;
  530. }
  531.  
  532. /* This calls the ex "<" command to shift some lines left */
  533. MARK v_lshift(m, n)
  534.     MARK    m, n;    /* range of lines to shift */
  535. {
  536.     return shift_help(m, n, CMD_SHIFTL);
  537. }
  538.  
  539. /* This calls the ex ">" command to shift some lines right */
  540. MARK v_rshift(m, n)
  541.     MARK    m, n;    /* range of lines to shift */
  542. {
  543.     return shift_help(m, n, CMD_SHIFTR);
  544. }
  545.  
  546. /* This runs some lines through a filter program */
  547. MARK v_filter(m, n)
  548.     MARK    m, n;    /* range of lines to shift */
  549. {
  550.     char    cmdln[100];    /* a shell command line */
  551.  
  552.     /* adjust for inclusive endmarks in ex */
  553.     n -= BLKSIZE;
  554.  
  555.     if (vgets('!', cmdln, sizeof(cmdln)) > 0)
  556.     {
  557.         filter(m, n, cmdln);
  558.     }
  559.  
  560.     redraw(MARK_UNSET, FALSE);
  561.     return m;
  562. }
  563.  
  564.  
  565. /* This function runs the ex "file" command to show the file's status */
  566. MARK v_status()
  567. {
  568.     cmd_file(cursor, cursor, CMD_FILE, 0, "");
  569.     return cursor;
  570. }
  571.  
  572.  
  573. /* This function runs the ":&" command to repeat the previous :s// */
  574. MARK v_again(m, n)
  575.     MARK    m, n;
  576. {
  577.     cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
  578.     return cursor;
  579. }
  580.  
  581.  
  582.  
  583. /* This function switches to the previous file, if possible */
  584. MARK v_switch()
  585. {
  586.     if (!*prevorig)
  587.         msg("No previous file");
  588.     else
  589.     {    strcpy(tmpblk.c, prevorig);
  590.         cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
  591.     }
  592.     return cursor;
  593. }
  594.  
  595. /* This function does a tag search on a keyword */
  596. /*ARGSUSED*/
  597. MARK v_tag(keyword, m, cnt)
  598.     char    *keyword;
  599.     MARK    m;
  600.     long    cnt;
  601. {
  602.     /* move the cursor to the start of the tag name, where m is */
  603.     cursor = m;
  604.  
  605.     /* perform the tag search */
  606.     cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
  607.  
  608.     return cursor;
  609. }
  610.  
  611. #ifndef NO_EXTENSIONS
  612. /* This function looks up a keyword by calling the helpprog program */
  613. /*ARGSUSED*/
  614. MARK v_keyword(keyword, m, cnt)
  615.     char    *keyword;
  616.     MARK    m;
  617.     long    cnt;
  618. {
  619.     int    waswarn;
  620.     char    cmdline[130];
  621.  
  622.     move(LINES - 1, 0);
  623.     addstr("---------------------------------------------------------\n");
  624.     clrtoeol();
  625.     refresh();
  626.     sprintf(cmdline, "%s %s", o_keywordprg, keyword);
  627.     waswarn = *o_warn;
  628.     *o_warn = FALSE;
  629.     suspend_curses();
  630.     if (system(cmdline))
  631.     {
  632.         addstr("<<< failed >>>\n");
  633.     }
  634.     resume_curses(FALSE);
  635.     mode = MODE_VI;
  636.     redraw(MARK_UNSET, FALSE);
  637.     *o_warn = waswarn;
  638.  
  639.     return m;
  640. }
  641.  
  642.  
  643.  
  644. MARK v_increment(keyword, m, cnt)
  645.     char    *keyword;
  646.     MARK    m;
  647.     long    cnt;
  648. {
  649.     static    sign;
  650.     char    newval[12];
  651.     long    atol();
  652.  
  653.     DEFAULT(1);
  654.  
  655.     /* get one more keystroke, unless doingdot */
  656.     if (!doingdot)
  657.     {
  658.         sign = getkey(0);
  659.     }
  660.  
  661.     /* adjust the number, based on that second keystroke */
  662.     switch (sign)
  663.     {
  664.       case '+':
  665.       case '#':
  666.         cnt = atol(keyword) + cnt;
  667.         break;
  668.  
  669.       case '-':
  670.         cnt = atol(keyword) - cnt;
  671.         break;
  672.  
  673.       case '=':
  674.         break;
  675.  
  676.       default:
  677.         return MARK_UNSET;
  678.     }
  679.     sprintf(newval, "%ld", cnt);
  680.  
  681.     ChangeText
  682.     {
  683.         change(m, m + strlen(keyword), newval);
  684.     }
  685.  
  686.     return m;
  687. }
  688. #endif
  689.  
  690.  
  691. /* This function acts like the EX command "xit" */
  692. /*ARGSUSED*/
  693. MARK v_xit(m, cnt, key)
  694.     MARK    m;    /* ignored */
  695.     long    cnt;    /* ignored */
  696.     int    key;    /* must be a second 'Z' */
  697. {
  698.     /* if second char wasn't 'Z', fail */
  699.     if (key != 'Z')
  700.     {
  701.         return MARK_UNSET;
  702.     }
  703.  
  704.     /* move the cursor to the bottom of the screen */
  705.     move(LINES - 1, 0);
  706.     clrtoeol();
  707.  
  708.     /* do the xit command */
  709.     cmd_xit(m, m, CMD_XIT, FALSE, "");
  710.  
  711.     /* return the cursor */
  712.     return m;
  713. }
  714.  
  715.  
  716. /* This function undoes changes to a single line, if possible */
  717. MARK v_undoline(m)
  718.     MARK    m;    /* where we hope to undo the change */
  719. {
  720.     /* make sure we have the right line in the buffer */
  721.     if (markline(m) != U_line)
  722.     {
  723.         return MARK_UNSET;
  724.     }
  725.  
  726.     /* fix it */
  727.     ChangeText
  728.     {
  729.         strcat(U_text, "\n");
  730.         change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
  731.     }
  732.  
  733.     /* nothing in the buffer anymore */
  734.     U_line = -1L;
  735.  
  736.     /* return, with the cursor at the front of the line */
  737.     return m & ~(BLKSIZE - 1);
  738. }
  739.  
  740.  
  741. #ifndef NO_ERRLIST
  742. MARK v_errlist(m)
  743.     MARK    m;
  744. {
  745.     cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
  746.     return cursor;
  747. }
  748. #endif
  749.  
  750.  
  751. #ifndef NO_AT
  752. /*ARGSUSED*/
  753. MARK v_at(m, cnt, key)
  754.     MARK    m;
  755.     long    cnt;
  756.     int    key;
  757. {
  758.     if (!fromcutbuf(key))
  759.     {
  760.         return MARK_UNSET;
  761.     }
  762.     return cursor;
  763. }
  764. #endif
  765.