home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / util / vim-3.0.lha / Vim / src / ops.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  39KB  |  1,736 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * ops.c: implementation of various operators: doshift, dodelete, dotilde,
  11.  *          dochange, doyank, doput, dojoin
  12.  */
  13.  
  14. #include "vim.h"
  15. #include "globals.h"
  16. #include "proto.h"
  17. #include "param.h"
  18. #include "ops.h"
  19.  
  20. /*
  21.  * We have one yank buffer for normal yanks and puts, nine yank buffers for
  22.  * deletes and 26 yank buffers for use by name.
  23.  * Each yank buffer is an array of pointers to lines.
  24.  */
  25. static struct yankbuf
  26. {
  27.     char_u        **y_array;        /* pointer to array of line pointers */
  28.     linenr_t     y_size;         /* number of lines in y_array */
  29.     char_u        y_type;         /* MLINE, MCHAR or MBLOCK */
  30. } y_buf[36];                    /* 0..9 = number buffers, 10..35 = char buffers */
  31.  
  32. static struct    yankbuf *y_current;        /* ptr to current yank buffer */
  33. static int        yankappend;                /* TRUE when appending */
  34. static struct    yankbuf *y_previous = NULL; /* ptr to last written yank buffer */
  35.  
  36. static void        get_yank_buffer __ARGS((int));
  37. static int        stuff_yank __ARGS((int, char_u *));
  38. static void        free_yank __ARGS((long));
  39. static void        free_yank_all __ARGS((void));
  40. static void        block_prep __ARGS((linenr_t, int));
  41.  
  42. /* variables use by block_prep, dodelete and doyank */
  43. static int        startspaces;
  44. static int        endspaces;
  45. static int        textlen;
  46. static char_u        *textstart;
  47. static colnr_t    textcol;
  48.  
  49. /*
  50.  * doshift - handle a shift operation
  51.  */
  52.     void
  53. doshift(op, curs_top, amount)
  54.     int             op;
  55.     int                curs_top;
  56.     int                amount;
  57. {
  58.     register long    i;
  59.     int                first_char;
  60.  
  61.     if (!u_save((linenr_t)(curwin->w_cursor.lnum - 1), (linenr_t)(curwin->w_cursor.lnum + nlines)))
  62.         return;
  63.  
  64.     for (i = nlines; --i >= 0; )
  65.     {
  66.         first_char = *ml_get(curwin->w_cursor.lnum);
  67.         if (first_char == NUL)                            /* empty line */
  68.             curwin->w_cursor.col = 0;
  69.         /*
  70.          * Don't move the line right if it starts with # and p_si is set.
  71.          */
  72.         else if (!curbuf->b_p_si || first_char != '#')
  73.         {
  74.             /* if (Visual_block)
  75.                     shift the block, not the whole line
  76.             else */
  77.                 shift_line(op == LSHIFT, p_sr, amount);
  78.         }
  79.         ++curwin->w_cursor.lnum;
  80.     }
  81.  
  82.     if (curs_top)            /* put cursor on first line, for ">>" */
  83.         curwin->w_cursor.lnum -= nlines;
  84.     else
  85.         --curwin->w_cursor.lnum;        /* put cursor on last line, for ":>" */
  86.     updateScreen(CURSUPD);
  87.  
  88.     if (nlines > p_report)
  89.         smsg((char_u *)"%ld line%s %ced", nlines, plural(nlines),
  90.                                     (op == RSHIFT) ? '>' : '<');
  91. }
  92.  
  93. /*
  94.  * shift the current line one shiftwidth left (if left != 0) or right
  95.  * leaves cursor on first blank in the line
  96.  */
  97.     void
  98. shift_line(left, round, amount)
  99.     int left;
  100.     int    round;
  101.     int    amount;
  102. {
  103.     register int count;
  104.     register int i, j;
  105.     int p_sw = (int)curbuf->b_p_sw;
  106.  
  107.     count = get_indent();            /* get current indent */
  108.  
  109.     if (round)                        /* round off indent */
  110.     {
  111.         i = count / p_sw;            /* number of p_sw rounded down */
  112.         j = count % p_sw;            /* extra spaces */
  113.         if (j && left)                /* first remove extra spaces */
  114.             --amount;
  115.         if (left)
  116.         {
  117.             i -= amount;
  118.             if (i < 0)
  119.                 i = 0;
  120.         }
  121.         else
  122.             i += amount;
  123.         count = i * p_sw;
  124.     }
  125.     else                /* original vi indent */
  126.     {
  127.         if (left)
  128.         {
  129.             count -= p_sw * amount;
  130.             if (count < 0)
  131.                 count = 0;
  132.         }
  133.         else
  134.             count += p_sw * amount;
  135.     }
  136.     set_indent(count, TRUE);        /* set new indent */
  137. }
  138.  
  139. /*
  140.  * check if character is name of yank buffer
  141.  * Note: There is no check for 0 (default register), caller should do this
  142.  */
  143.      int
  144. is_yank_buffer(c, write)
  145.     int        c;
  146.     int        write;        /* if TRUE check for writable buffers */
  147. {
  148.     if (isalnum(c) || (!write && strchr(".%:", c) != NULL) || c == '"')
  149.         return TRUE;
  150.     return FALSE;
  151. }
  152.  
  153. /*
  154.  * Set y_current and yankappend, according to the value of yankbuffer.
  155.  *
  156.  * If yankbuffer is 0 and writing, use buffer 0
  157.  * If yankbuffer is 0 and reading, use previous buffer
  158.  */
  159.     static void
  160. get_yank_buffer(writing)
  161.     int        writing;
  162. {
  163.     register int i;
  164.  
  165.     yankappend = FALSE;
  166.     if (((yankbuffer == 0 && !writing) || yankbuffer == '"') && y_previous != NULL)
  167.     {
  168.         y_current = y_previous;
  169.         return;
  170.     }
  171.     i = yankbuffer;
  172.     if (isdigit(i))
  173.         i -= '0';
  174.     else if (islower(i))
  175.         i -= 'a' - 10;
  176.     else if (isupper(i))
  177.     {
  178.         i -= 'A' - 10;
  179.         yankappend = TRUE;
  180.     }
  181.     else            /* not 0-9, a-z or A-Z: use buffer 0 */
  182.         i = 0;
  183.     y_current = &(y_buf[i]);
  184.     if (writing)        /* remember the buffer we write into for doput() */
  185.         y_previous = y_current;
  186. }
  187.  
  188. /*
  189.  * start or stop recording into a yank buffer
  190.  *
  191.  * return FAIL for failure, OK otherwise
  192.  */
  193.     int
  194. dorecord(c)
  195.     int c;
  196. {
  197.     char_u        *p;
  198.     static int    bufname;
  199.     int            retval;
  200.  
  201.     if (Recording == FALSE)         /* start recording */
  202.     {
  203.         if (!isalnum(c) && c != '"')    /* registers 0-9, a-z and " are allowed */
  204.             retval = FAIL;
  205.         else
  206.         {
  207.             Recording = TRUE;
  208.             showmode();
  209.             bufname = c;
  210.             retval = OK;
  211.         }
  212.     }
  213.     else                            /* stop recording */
  214.     {
  215.         Recording = FALSE;
  216.         MSG("");
  217.             /* the trailing 'q' command will not have been put in the buffer */
  218.         p = get_recorded();
  219.         if (p == NULL)
  220.             retval = FAIL;
  221.         else
  222.             retval = (stuff_yank(bufname, p));
  223.     }
  224.     return retval;
  225. }
  226.  
  227. /*
  228.  * stuff string 'p' into yank buffer 'bufname' (append if uppercase)
  229.  * 'p' is assumed to be alloced.
  230.  *
  231.  * return FAIL for failure, OK otherwise
  232.  */
  233.     static int
  234. stuff_yank(bufname, p)
  235.     int bufname;
  236.     char_u *p;
  237. {
  238.     char_u *lp;
  239.     char_u **pp;
  240.  
  241.     yankbuffer = bufname;
  242.                                             /* check for read-only buffer */
  243.     if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
  244.         return FAIL;
  245.     get_yank_buffer(TRUE);
  246.     if (yankappend && y_current->y_array != NULL)
  247.     {
  248.         pp = &(y_current->y_array[y_current->y_size - 1]);
  249.         lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
  250.         if (lp == NULL)
  251.         {
  252.             free(p);
  253.             return FAIL;
  254.         }
  255.         STRCPY(lp, *pp);
  256.         STRCAT(lp, p);
  257.         free(p);
  258.         free(*pp);
  259.         *pp = lp;
  260.     }
  261.     else
  262.     {
  263.         free_yank_all();
  264.         if ((y_current->y_array = (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
  265.         {
  266.             free(p);
  267.             return FAIL;
  268.         }
  269.         y_current->y_array[0] = p;
  270.         y_current->y_size = 1;
  271.         y_current->y_type = MCHAR;    /* used to be MLINE, why? */
  272.     }
  273.     return OK;
  274. }
  275.  
  276. /*
  277.  * execute a yank buffer (register): copy it into the stuff buffer
  278.  *
  279.  * return FAIL for failure, OK otherwise
  280.  */
  281.     int
  282. doexecbuf(c)
  283.     int c;
  284. {
  285.     static int lastc = NUL;
  286.     long i;
  287.  
  288.     if (c == '@')                    /* repeat previous one */
  289.         c = lastc;
  290.     if (!is_yank_buffer(c, FALSE))    /* check for valid buffer */
  291.         return FAIL;
  292.     lastc = c;
  293.  
  294.     if (c == ':')                    /* use last command line */
  295.     {
  296.         if (last_cmdline == NULL)
  297.         {
  298.             EMSG(e_nolastcmd);
  299.             return FAIL;
  300.         }
  301.         free(new_last_cmdline);        /* don't keep the command line containing @: */
  302.         new_last_cmdline = NULL;
  303.         if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
  304.             return FAIL;
  305.         if (ins_typestr(last_cmdline, FALSE) == FAIL)
  306.             return FAIL;
  307.     }
  308.     else
  309.     {
  310.         yankbuffer = c;
  311.         get_yank_buffer(FALSE);
  312.         if (y_current->y_array == NULL)
  313.             return FAIL;
  314.  
  315.         for (i = y_current->y_size; --i >= 0; )
  316.         {
  317.         /* insert newline between lines and after last line if type is MLINE */
  318.             if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  319.             {
  320.                 if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
  321.                     return FAIL;
  322.             }
  323.             if (ins_typestr(y_current->y_array[i], FALSE) == FAIL)
  324.                 return FAIL;
  325.         }
  326.         Exec_reg = TRUE;        /* disable the 'q' command */
  327.     }
  328.     return OK;
  329. }
  330.  
  331. /*
  332.  * insert a yank buffer: copy it into the Read buffer
  333.  * used by CTRL-R command in insert mode
  334.  *
  335.  * return FAIL for failure, OK otherwise
  336.  */
  337.     int
  338. insertbuf(c)
  339.     int c;
  340. {
  341.     long i;
  342.  
  343.     /*
  344.      * It is possible to get into an endless loop by having CTRL-R a in
  345.      * register a and then, in insert mode, doing CTRL-R a.
  346.      * If you hit CTRL-C, the loop will be broken here.
  347.      */
  348.     breakcheck();
  349.     if (got_int)
  350.         return FAIL;
  351.  
  352.     if (!is_yank_buffer(c, FALSE))        /* check for valid buffer */
  353.         return FAIL;
  354.  
  355.     if (c == '.')                        /* insert last inserted text */
  356.     {
  357.         stuff_inserted(NUL, 1L, TRUE);
  358.         return OK;
  359.     }
  360.  
  361.     if (c == '%')                        /* insert file name */
  362.     {
  363.         if (check_fname() == FAIL)
  364.             return FAIL;
  365.         stuffReadbuff(curbuf->b_xfilename);
  366.         return OK;
  367.     }
  368.  
  369.     if (c == ':')                        /* insert last command line */
  370.     {
  371.         if (last_cmdline == NULL)
  372.         {
  373.             EMSG(e_nolastcmd);
  374.             return FAIL;
  375.         }
  376.         stuffReadbuff(last_cmdline);
  377.         return OK;
  378.     }
  379.  
  380.     yankbuffer = c;
  381.     get_yank_buff