home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / elvis / Source / c / vcmd < prev    next >
Encoding:
Text File  |  1990-03-26  |  10.3 KB  |  593 lines

  1. /* vcmd.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    16820 SW Tallac Way
  6.  *    Beaverton, OR 97006
  7.  *    kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
  8.  */
  9.  
  10.  
  11. /* This file contains the functions that handle VI commands */
  12.  
  13.  
  14. #include "vi.h"
  15.  
  16.  
  17. /* This function puts the editor in EX mode */
  18. MARK v_quit()
  19. {
  20.     mode = MODE_EX;
  21.     return cursor;
  22. }
  23.  
  24. /* This function causes the screen to be redrawn */
  25. MARK v_redraw()
  26. {
  27.     redraw(MARK_UNSET, FALSE);
  28.     return cursor;
  29. }
  30.  
  31. /* This function executes a single EX command, and waits for a user keystroke
  32.  * before returning to the VI screen.  If that keystroke is another ':', then
  33.  * another EX command is read and executed.
  34.  */
  35. MARK v_1ex(m, text)
  36.     MARK    m;    /* the current line */
  37.     char    *text;    /* the first command to execute */
  38. {
  39.     /* scroll up, so we don't overwrite the command */
  40.     addch('\n');
  41.     refresh();
  42.  
  43.     /* run the command.  be careful about modes & output */
  44.     exwrote = FALSE;
  45.     mode = MODE_COLON;
  46.     doexcmd(text);
  47.     exrefresh();
  48.     if (mode == MODE_COLON)
  49.         mode = MODE_VI;
  50.  
  51.     /* if mode is no longer MODE_VI, then we should quit right away! */
  52.     if (mode != MODE_VI)
  53.         return cursor;
  54.  
  55.     /* The command did some output.  Wait for a keystoke. */
  56.     if (exwrote)
  57.     {
  58.         msg("[Hit any key to continue]");
  59.         if (getkey(0) == ':')
  60.         {
  61.             ungetkey(':');
  62.         }
  63.     }
  64.  
  65.     redraw(MARK_UNSET, FALSE);
  66.     return cursor;
  67. }
  68.  
  69. /* This function undoes the last change */
  70. MARK v_undo(m)
  71.     MARK    m;    /* (ignored) */
  72. {
  73.     undo();
  74.     redraw(MARK_UNSET, FALSE);
  75.     return cursor;
  76. }
  77.  
  78. /* This function deletes the character(s) that the cursor is on */
  79. MARK v_xchar(m, cnt)
  80.     MARK    m;    /* where to start deletions */
  81.     long    cnt;    /* number of chars to delete */
  82. {
  83.     DEFAULT(1);
  84.  
  85.     pfetch(markline(m));
  86.     if (markidx(m + cnt) > plen)
  87.     {
  88.         cnt = plen - markidx(m);
  89.     }
  90.     if (cnt == 0L)
  91.     {
  92.         return MARK_UNSET;
  93.     }
  94.     ChangeText
  95.     {
  96.         cut(m, m + cnt);
  97.         delete(m, m + cnt);
  98.     }
  99.     return m;
  100. }
  101.  
  102. /* This function deletes character to the left of the cursor */
  103. MARK v_Xchar(m, cnt)
  104.     MARK    m;    /* where deletions end */
  105.     long    cnt;    /* number of chars to delete */
  106. {
  107.     DEFAULT(1);
  108.  
  109.     /* if we're at the first char of the line, error! */
  110.     if (markidx(m) == 0)
  111.     {
  112.         return MARK_UNSET;
  113.     }
  114.  
  115.     /* make sure we don't try to delete more chars than there are */
  116.     if (cnt > markidx(m))
  117.     {
  118.         cnt = markidx(m);
  119.     }
  120.  
  121.     /* delete 'em */
  122.     ChangeText
  123.     {
  124.         cut(m - cnt, m);
  125.         delete(m - cnt, m);
  126.     }
  127.  
  128.     return m - cnt;
  129. }
  130.  
  131. /* This function defines a mark */
  132. MARK v_mark(m, count, key)
  133.     MARK    m;    /* where the mark will be */
  134.     long    count;    /* (ignored) */
  135.     int    key;    /* the ASCII label of the mark */
  136. {
  137.     if (key < 'a' || key > 'z')
  138.     {
  139.         msg("Marks must be from a to z");
  140.     }
  141.     else
  142.     {
  143.         mark[key - 'a'] = m;
  144.     }
  145.     return m;
  146. }
  147.  
  148. /* This function toggles upper & lower case letters */
  149. MARK v_ulcase(m)
  150.     MARK    m;    /* where to make the change */
  151. {
  152.     char    new[2];
  153.  
  154.     /* extract the char that's there now */
  155.     pfetch(markline(m));
  156.     new[0] = ptext[markidx(m)];
  157.     new[1] = '\0';
  158.  
  159.     /* change it if necessary */
  160.     if (new[0] >= 'a' && new[0] <= 'z' || new[0] >= 'A' && new[0] <= 'Z')
  161.     {
  162.         new[0] ^= ('A' ^ 'a');
  163.         ChangeText
  164.         {
  165.             change(m, m + 1, new);
  166.         }
  167.     }
  168.     if (new[0] && ptext[markidx(m) + 1])
  169.     {
  170.         m++;
  171.     }
  172.     return m;
  173. }
  174.  
  175.  
  176. MARK v_replace(m, cnt, key)
  177.     MARK    m;    /* first char to be replaced */
  178.     long    cnt;    /* number of chars to replace */
  179.     int    key;    /* what to replace them with */
  180. {
  181.     register char    *text;
  182.     register int    i;
  183.  
  184.     DEFAULT(1);
  185.  
  186.     /* map ^M to '\n' */
  187.     if (key == '\r')
  188.     {
  189.         key = '\n';
  190.     }
  191.     else if (!doingdot && key == ctrl('V'))
  192.     {
  193.         key = getkey(0);
  194.     }
  195.  
  196.     /* make sure the resulting line isn't too long */
  197.     if (cnt > BLKSIZE - 2 - markidx(m))
  198.     {
  199.         cnt = BLKSIZE - 2 - markidx(m);
  200.     }
  201.  
  202.     /* build a string of the desired character with the desired length */
  203.     for (text = tmpblk.c, i = cnt; i > 0; i--)
  204.     {
  205.         *text++ = key;
  206.     }
  207.     *text = '\0';
  208.  
  209.     /* make sure cnt doesn't extend past EOL */
  210.     pfetch(markline(m));
  211.     key = markidx(m);
  212.     if (key + cnt > plen)
  213.     {
  214.         cnt = plen - key;
  215.     }
  216.  
  217.     /* do the replacement */
  218.     ChangeText
  219.     {
  220.         change(m, m + cnt, tmpblk.c);
  221.     }
  222.  
  223.     if (*tmpblk.c == '\n')
  224.     {
  225.         return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
  226.     }
  227.     else
  228.     {
  229.         return m + cnt - 1;
  230.     }
  231. }
  232.  
  233. MARK v_overtype(m)
  234.     MARK    m;    /* where to start overtyping */
  235. {
  236.     MARK    end;    /* end of a substitution */
  237.  
  238.     /* input starting here, in replace mode */
  239.     ChangeText
  240.     {
  241.         m = input(m, m, WHEN_VIREP);
  242.     }
  243.     return m;
  244. }
  245.  
  246.  
  247. /* This function selects which cut buffer to use */
  248. MARK v_selcut(m, cnt, key)
  249.     MARK    m;
  250.     long    cnt;
  251.     int    key;
  252. {
  253.     cutname(key);
  254.     return m;
  255. }
  256.  
  257. /* This function pastes text from a cut buffer */
  258. MARK v_paste(m, cnt, cmd)
  259.     MARK    m;    /* where to paste the text */
  260.     long    cnt;    /* (ignored) */
  261.     int    cmd;    /* either 'p' or 'P' */
  262. {
  263.     ChangeText
  264.     {
  265.         m = paste(m, cmd == 'p', FALSE);
  266.     }
  267.     return m;
  268. }
  269.  
  270. /* This function yanks text into a cut buffer */
  271. MARK v_yank(m, n)
  272.     MARK    m, n;    /* range of text to yank */
  273. {
  274.     cut(m, n);
  275.     return m;
  276. }
  277.  
  278. /* This function deletes a range of text */
  279. MARK v_delete(m, n)
  280.     MARK    m, n;    /* range of text to delete */
  281. {
  282.     ChangeText
  283.     {
  284.         cut(m, n);
  285.         delete(m, n);
  286.     }
  287.     return m;
  288. }
  289.  
  290.  
  291. /* This starts input mode without deleting anything */
  292. MARK v_insert(m, cnt, key)
  293.     MARK    m;    /* where to start (sort of) */
  294.     long    cnt;    /* repeat how many times? */
  295.     int    key;    /* what command is this for? {a,A,i,I,o,O} */
  296. {
  297.     int    wasdot;
  298.     long    reps;
  299.  
  300.     DEFAULT(1);
  301.  
  302.     ChangeText
  303.     {
  304.         /* tweak the insertion point, based on command key */
  305.         switch (key)
  306.         {
  307.           case 'i':
  308.             break;
  309.  
  310.           case 'a':
  311.             pfetch(markline(m));
  312.             if (plen > 0)
  313.             {
  314.                 m++;
  315.             }
  316.             break;
  317.  
  318.           case 'I':
  319.             m = movefront(m, 1L);
  320.             break;
  321.  
  322.           case 'A':
  323.             pfetch(markline(m));
  324.             m = (m & ~(BLKSIZE - 1)) + plen;
  325.             break;
  326.  
  327.           case 'O':
  328.             m &= ~(BLKSIZE - 1);
  329.             add(m, "\n");
  330.             break;
  331.  
  332.           case 'o':
  333.             m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
  334.             add(m, "\n");
  335.             break;
  336.         }
  337.  
  338.         /* insert the same text once or more */
  339.         for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
  340.         {
  341.             m = input(m, m, WHEN_VIINP);
  342.         }
  343.  
  344.         /* compensate for inaccurate redraw clues from input() */
  345.         if (key == 'O' | key == 'o' && wasdot)
  346.         {
  347.             redrawpost++;
  348.         }
  349.  
  350.         doingdot = FALSE;
  351.     }
  352.  
  353.     return m;
  354. }
  355.  
  356. /* This starts input mode with some text deleted */
  357. MARK v_change(m, n)
  358.     MARK    m, n;    /* the range of text to change */
  359. {
  360.     int    lnmode;    /* is this a line-mode change? */
  361.  
  362.     /* swap them if they're in reverse order */
  363.     if (m > n)
  364.     {
  365.         MARK    tmp;
  366.         tmp = m;
  367.         m = n;
  368.         n = tmp;
  369.     }
  370.  
  371.     /* for line mode, retain the last newline char */
  372.     lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
  373.     if (lnmode)
  374.     {
  375.         n -= BLKSIZE;
  376.         pfetch(markline(n));
  377.         n = (n & ~(BLKSIZE - 1)) + plen;
  378.     }
  379.  
  380.     ChangeText
  381.     {
  382.         cut(m, n);
  383.         m = input(m, n, WHEN_VIINP);
  384.     }
  385.  
  386.     /* compensate for inaccurate redraw clues from paste() */
  387.     if (doingdot)
  388.     {
  389.         redrawpre = markline(n);
  390.         if (lnmode)
  391.         {
  392.             redrawpre++;
  393.             redrawpost++;
  394.         }
  395.     }
  396.  
  397.     return m;
  398. }
  399.  
  400. /* This function replaces a given number of characters with input */
  401. MARK v_subst(m, cnt)
  402.     MARK    m;    /* where substitutions start */
  403.     long    cnt;    /* number of chars to replace */
  404. {
  405.     DEFAULT(1);
  406.  
  407.     /* make sure we don't try replacing past EOL */
  408.     pfetch(markline(m));
  409.     if (markidx(m) + cnt > plen)
  410.     {
  411.         cnt = plen - markidx(m);
  412.     }
  413.  
  414.     /* Go for it! */
  415.     ChangeText
  416.     {
  417.         cut(m, m + cnt);
  418.         m = input(m, m + cnt, WHEN_VIINP);
  419.     }
  420.     return m;
  421. }
  422.  
  423. /* This calls the ex "join" command to join some lines together */
  424. MARK v_join(m, cnt)
  425.     MARK    m;    /* the first line to be joined */
  426.     long    cnt;    /* number of other lines to join */
  427. {
  428.     MARK    joint;    /* where the lines were joined */
  429.  
  430.     DEFAULT(1);
  431.  
  432.     /* figure out where the joint will be */
  433.     pfetch(markline(m));
  434.     joint = (m & ~(BLKSIZE - 1)) + plen;
  435.  
  436.     /* join the lines */
  437.     cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
  438.     mustredraw = TRUE;
  439.  
  440.     /* the cursor should be left at the joint */
  441.     return joint;
  442. }
  443.  
  444. /* This calls the ex shifter command to shift some lines */
  445. static MARK shift_help(m, n, excmd)
  446.     MARK    m, n;    /* range of lines to shift */
  447.     CMD    excmd;    /* which way do we shift? */
  448. {
  449.     /* make sure our endpoints aren't in reverse order */
  450.     if (m > n)
  451.     {
  452.         MARK tmp;
  453.  
  454.         tmp = n;
  455.         n = m;
  456.         m = tmp;
  457.     }
  458.  
  459.     /* linemode? adjust for inclusive endmarks in ex */
  460.     if (markidx(m) == 0 && markidx(n) == 0)
  461.     {
  462.         n -= BLKSIZE;
  463.     }
  464.  
  465.     cmd_shift(m, n, excmd, 0, "");
  466.     return m;
  467. }
  468.  
  469. /* This calls the ex "<" command to shift some lines left */
  470. MARK v_shiftl(m, n)
  471.     MARK    m, n;    /* range of lines to shift */
  472. {
  473.     return shift_help(m, n, CMD_SHIFTL);
  474. }
  475.  
  476. /* This calls the ex ">" command to shift some lines right */
  477. MARK v_shiftr(m, n)
  478.     MARK    m, n;    /* range of lines to shift */
  479. {
  480.     return shift_help(m, n, CMD_SHIFTR);
  481. }
  482.  
  483. /* This runs some lines through a filter program */
  484. MARK v_filter(m, n)
  485.     MARK    m, n;    /* range of lines to shift */
  486. {
  487.     char    cmdln[100];    /* a shell command line */
  488.  
  489.     /* linemode? adjust for inclusive endmarks in ex */
  490.     if (markidx(m) == 0 && markidx(n) == 0)
  491.     {
  492.         n -= BLKSIZE;
  493.     }
  494.  
  495.     if (vgets('!', cmdln, sizeof(cmdln)) > 0)
  496.     {
  497.         filter(m, n, cmdln);
  498.     }
  499.  
  500.     redraw(MARK_UNSET, FALSE);
  501.     return m;
  502. }
  503.  
  504.  
  505. /* This function runs the ex "file" command to show the file's status */
  506. MARK v_status()
  507. {
  508.     cmd_file(cursor, cursor, CMD_FILE, 0, "");
  509.     return cursor;
  510. }
  511.  
  512.  
  513. /* This function does a tag search on a keyword */
  514. MARK v_tag(keyword)
  515.     char    *keyword;
  516. {
  517.     cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
  518.     redraw(MARK_UNSET, FALSE);
  519.     return cursor;
  520. }
  521.  
  522. /* This function looks up a keyword by calling the helpprog program */
  523. MARK v_keyword(keyword)
  524.     char    *keyword;
  525. {
  526.     int    status;
  527.  
  528.     move(LINES - 1, 0);
  529.     addstr("---------------------------------------------------------\n");
  530.     clrtoeol();
  531.     refresh();
  532.     suspend_curses();
  533.  
  534. #ifdef ARC
  535.  
  536.     ARC_keyword(keyword);
  537.  
  538. #else
  539.  
  540.     switch (fork())
  541.     {
  542.       case -1:                        /* error */
  543.         break;
  544.  
  545.       case 0:                        /* child */
  546.         execl(o_keywordprg, o_keywordprg, keyword, (char *)0);
  547.         exit(2); /* if we get here, the exec failed */
  548.  
  549.       default:                        /* parent */
  550.         wait(&status);
  551.         if (status > 0)
  552.         {
  553.             write(2, "<<< failed >>>\n", 15);
  554.         }
  555.     }
  556. #endif
  557.  
  558.     resume_curses(FALSE); /* "resume, but not quietly" */
  559.     redraw(MARK_UNSET, FALSE);
  560.     return cursor;
  561. }
  562.  
  563.  
  564.  
  565. /* This function acts like the EX command "xit" */
  566. MARK v_xit(m, cnt, key)
  567.     MARK    m;    /* ignored */
  568.     long    cnt;    /* ignored */
  569.     int    key;    /* must be a second 'Z' */
  570. {
  571.     /* if second char wasn't 'Z', fail */
  572.     if (key != 'Z')
  573.     {
  574.         return MARK_UNSET;
  575.     }
  576.  
  577.     /* move the physical cursor to the end of the screen */
  578.     move(LINES - 1, 0);
  579.     clrtoeol();
  580.     refresh();
  581.  
  582.     /* do the xit command */
  583.     mode = MODE_COLON;
  584.     cmd_xit(m, m, CMD_XIT, FALSE, "");
  585.     if (mode == MODE_COLON)
  586.     {
  587.         mode = MODE_VI;
  588.     }
  589.  
  590.     /* regardless of whether we succeeded or failed, return the cursor */
  591.     return m;
  592. }
  593.