aboutsummaryrefslogtreecommitdiff
path: root/src/ex_cmds.c
diff options
context:
space:
mode:
authorEliseo Martínez <eliseomarmol@gmail.com>2014-05-12 02:25:17 +0200
committerEliseo Martínez <eliseomarmol@gmail.com>2014-05-15 20:46:01 +0200
commitda51dc9cf202772f60bd2da975dbef257bd9237c (patch)
tree5c16b93238a153f55634e9323077f30c8133970c /src/ex_cmds.c
parentffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff)
downloadrneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/ex_cmds.c')
-rw-r--r--src/ex_cmds.c6374
1 files changed, 0 insertions, 6374 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
deleted file mode 100644
index 3613a02cb3..0000000000
--- a/src/ex_cmds.c
+++ /dev/null
@@ -1,6374 +0,0 @@
-/*
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- * See README.txt for an overview of the Vim source code.
- */
-
-/*
- * ex_cmds.c: some functions for command line commands
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "vim.h"
-#include "version_defs.h"
-#include "ex_cmds.h"
-#include "buffer.h"
-#include "charset.h"
-#include "diff.h"
-#include "digraph.h"
-#include "edit.h"
-#include "eval.h"
-#include "ex_cmds2.h"
-#include "ex_docmd.h"
-#include "ex_eval.h"
-#include "ex_getln.h"
-#include "farsi.h"
-#include "fileio.h"
-#include "fold.h"
-#include "getchar.h"
-#include "indent.h"
-#include "main.h"
-#include "mark.h"
-#include "mbyte.h"
-#include "memline.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "garray.h"
-#include "memory.h"
-#include "move.h"
-#include "normal.h"
-#include "ops.h"
-#include "option.h"
-#include "os_unix.h"
-#include "path.h"
-#include "quickfix.h"
-#include "regexp.h"
-#include "screen.h"
-#include "search.h"
-#include "spell.h"
-#include "syntax.h"
-#include "tag.h"
-#include "term.h"
-#include "ui.h"
-#include "undo.h"
-#include "window.h"
-#include "os/os.h"
-#include "os/shell.h"
-
-static int linelen(int *has_tab);
-static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap,
- char_u *cmd, int do_in,
- int do_out);
-static char_u *viminfo_filename(char_u *);
-static void do_viminfo(FILE *fp_in, FILE *fp_out, int flags);
-static int viminfo_encoding(vir_T *virp);
-static int read_viminfo_up_to_marks(vir_T *virp, int forceit,
- int writing);
-
-static int check_readonly(int *forceit, buf_T *buf);
-static void delbuf_msg(char_u *name);
-static int help_compare(const void *s1, const void *s2);
-
-/*
- * ":ascii" and "ga".
- */
-void do_ascii(exarg_T *eap)
-{
- int c;
- int cval;
- char buf1[20];
- char buf2[20];
- char_u buf3[7];
- int cc[MAX_MCO];
- int ci = 0;
- int len;
-
- if (enc_utf8)
- c = utfc_ptr2char(ml_get_cursor(), cc);
- else
- c = gchar_cursor();
- if (c == NUL) {
- MSG("NUL");
- return;
- }
-
- IObuff[0] = NUL;
- if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80) {
- if (c == NL) /* NUL is stored as NL */
- c = NUL;
- if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
- cval = NL; /* NL is stored as CR */
- else
- cval = c;
- if (vim_isprintc_strict(c) && (c < ' '
- || c > '~'
- )) {
- transchar_nonprint(buf3, c);
- vim_snprintf(buf1, sizeof(buf1), " <%s>", (char *)buf3);
- } else
- buf1[0] = NUL;
- if (c >= 0x80)
- vim_snprintf(buf2, sizeof(buf2), " <M-%s>",
- (char *)transchar(c & 0x7f));
- else
- buf2[0] = NUL;
- vim_snprintf((char *)IObuff, IOSIZE,
- _("<%s>%s%s %d, Hex %02x, Octal %03o"),
- transchar(c), buf1, buf2, cval, cval, cval);
- if (enc_utf8)
- c = cc[ci++];
- else
- c = 0;
- }
-
- /* Repeat for combining characters. */
- while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80))) {
- len = (int)STRLEN(IObuff);
- /* This assumes every multi-byte char is printable... */
- if (len > 0)
- IObuff[len++] = ' ';
- IObuff[len++] = '<';
- if (enc_utf8 && utf_iscomposing(c)
-# ifdef USE_GUI
- && !gui.in_use
-# endif
- )
- IObuff[len++] = ' '; /* draw composing char on top of a space */
- len += (*mb_char2bytes)(c, IObuff + len);
- vim_snprintf((char *)IObuff + len, IOSIZE - len,
- c < 0x10000 ? _("> %d, Hex %04x, Octal %o")
- : _("> %d, Hex %08x, Octal %o"), c, c, c);
- if (ci == MAX_MCO)
- break;
- if (enc_utf8)
- c = cc[ci++];
- else
- c = 0;
- }
-
- msg(IObuff);
-}
-
-/*
- * ":left", ":center" and ":right": align text.
- */
-void ex_align(exarg_T *eap)
-{
- pos_T save_curpos;
- int len;
- int indent = 0;
- int new_indent;
- int has_tab;
- int width;
-
- if (curwin->w_p_rl) {
- /* switch left and right aligning */
- if (eap->cmdidx == CMD_right)
- eap->cmdidx = CMD_left;
- else if (eap->cmdidx == CMD_left)
- eap->cmdidx = CMD_right;
- }
-
- width = atoi((char *)eap->arg);
- save_curpos = curwin->w_cursor;
- if (eap->cmdidx == CMD_left) { /* width is used for new indent */
- if (width >= 0)
- indent = width;
- } else {
- /*
- * if 'textwidth' set, use it
- * else if 'wrapmargin' set, use it
- * if invalid value, use 80
- */
- if (width <= 0)
- width = curbuf->b_p_tw;
- if (width == 0 && curbuf->b_p_wm > 0)
- width = W_WIDTH(curwin) - curbuf->b_p_wm;
- if (width <= 0)
- width = 80;
- }
-
- if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
- return;
-
- for (curwin->w_cursor.lnum = eap->line1;
- curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum) {
- if (eap->cmdidx == CMD_left) /* left align */
- new_indent = indent;
- else {
- has_tab = FALSE; /* avoid uninit warnings */
- len = linelen(eap->cmdidx == CMD_right ? &has_tab
- : NULL) - get_indent();
-
- if (len <= 0) /* skip blank lines */
- continue;
-
- if (eap->cmdidx == CMD_center)
- new_indent = (width - len) / 2;
- else {
- new_indent = width - len; /* right align */
-
- /*
- * Make sure that embedded TABs don't make the text go too far
- * to the right.
- */
- if (has_tab)
- while (new_indent > 0) {
- (void)set_indent(new_indent, 0);
- if (linelen(NULL) <= width) {
- /*
- * Now try to move the line as much as possible to
- * the right. Stop when it moves too far.
- */
- do
- (void)set_indent(++new_indent, 0);
- while (linelen(NULL) <= width);
- --new_indent;
- break;
- }
- --new_indent;
- }
- }
- }
- if (new_indent < 0)
- new_indent = 0;
- (void)set_indent(new_indent, 0); /* set indent */
- }
- changed_lines(eap->line1, 0, eap->line2 + 1, 0L);
- curwin->w_cursor = save_curpos;
- beginline(BL_WHITE | BL_FIX);
-}
-
-/*
- * Get the length of the current line, excluding trailing white space.
- */
-static int linelen(int *has_tab)
-{
- char_u *line;
- char_u *first;
- char_u *last;
- int save;
- int len;
-
- /* find the first non-blank character */
- line = ml_get_curline();
- first = skipwhite(line);
-
- /* find the character after the last non-blank character */
- for (last = first + STRLEN(first);
- last > first && vim_iswhite(last[-1]); --last)
- ;
- save = *last;
- *last = NUL;
- len = linetabsize(line); /* get line length */
- if (has_tab != NULL) /* check for embedded TAB */
- *has_tab = (vim_strrchr(first, TAB) != NULL);
- *last = save;
-
- return len;
-}
-
-/* Buffer for two lines used during sorting. They are allocated to
- * contain the longest line being sorted. */
-static char_u *sortbuf1;
-static char_u *sortbuf2;
-
-static int sort_ic; /* ignore case */
-static int sort_nr; /* sort on number */
-static int sort_rx; /* sort on regex instead of skipping it */
-
-static int sort_abort; /* flag to indicate if sorting has been interrupted */
-
-/* Struct to store info to be sorted. */
-typedef struct {
- linenr_T lnum; /* line number */
- long start_col_nr; /* starting column number or number */
- long end_col_nr; /* ending column number */
-} sorti_T;
-
-static int
-sort_compare(const void *s1, const void *s2);
-
-static int sort_compare(const void *s1, const void *s2)
-{
- sorti_T l1 = *(sorti_T *)s1;
- sorti_T l2 = *(sorti_T *)s2;
- int result = 0;
-
- /* If the user interrupts, there's no way to stop qsort() immediately, but
- * if we return 0 every time, qsort will assume it's done sorting and
- * exit. */
- if (sort_abort)
- return 0;
- fast_breakcheck();
- if (got_int)
- sort_abort = TRUE;
-
- /* When sorting numbers "start_col_nr" is the number, not the column
- * number. */
- if (sort_nr)
- result = l1.start_col_nr == l2.start_col_nr ? 0
- : l1.start_col_nr > l2.start_col_nr ? 1 : -1;
- else {
- /* We need to copy one line into "sortbuf1", because there is no
- * guarantee that the first pointer becomes invalid when obtaining the
- * second one. */
- STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.start_col_nr,
- l1.end_col_nr - l1.start_col_nr + 1);
- sortbuf1[l1.end_col_nr - l1.start_col_nr] = 0;
- STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.start_col_nr,
- l2.end_col_nr - l2.start_col_nr + 1);
- sortbuf2[l2.end_col_nr - l2.start_col_nr] = 0;
-
- result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
- : STRCMP(sortbuf1, sortbuf2);
- }
-
- /* If two lines have the same value, preserve the original line order. */
- if (result == 0)
- return (int)(l1.lnum - l2.lnum);
- return result;
-}
-
-/*
- * ":sort".
- */
-void ex_sort(exarg_T *eap)
-{
- regmatch_T regmatch;
- int len;
- linenr_T lnum;
- long maxlen = 0;
- size_t count = (size_t)(eap->line2 - eap->line1 + 1);
- size_t i;
- char_u *p;
- char_u *s;
- char_u *s2;
- char_u c; /* temporary character storage */
- int unique = FALSE;
- long deleted;
- colnr_T start_col;
- colnr_T end_col;
- int sort_oct; /* sort on octal number */
- int sort_hex; /* sort on hex number */
-
- /* Sorting one line is really quick! */
- if (count <= 1)
- return;
-
- if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
- return;
- sortbuf1 = NULL;
- sortbuf2 = NULL;
- regmatch.regprog = NULL;
- sorti_T *nrs = xmalloc(count * sizeof(sorti_T));
-
- sort_abort = sort_ic = sort_rx = sort_nr = sort_oct = sort_hex = 0;
-
- for (p = eap->arg; *p != NUL; ++p) {
- if (vim_iswhite(*p))
- ;
- else if (*p == 'i')
- sort_ic = TRUE;
- else if (*p == 'r')
- sort_rx = TRUE;
- else if (*p == 'n')
- sort_nr = 2;
- else if (*p == 'o')
- sort_oct = 2;
- else if (*p == 'x')
- sort_hex = 2;
- else if (*p == 'u')
- unique = TRUE;
- else if (*p == '"') /* comment start */
- break;
- else if (check_nextcmd(p) != NULL) {
- eap->nextcmd = check_nextcmd(p);
- break;
- } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = skip_regexp(p + 1, *p, TRUE, NULL);
- if (*s != *p) {
- EMSG(_(e_invalpat));
- goto sortend;
- }
- *s = NUL;
- /* Use last search pattern if sort pattern is empty. */
- if (s == p + 1) {
- if (last_search_pat() == NULL) {
- EMSG(_(e_noprevre));
- goto sortend;
- }
- regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
- } else
- regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
- if (regmatch.regprog == NULL)
- goto sortend;
- p = s; /* continue after the regexp */
- regmatch.rm_ic = p_ic;
- } else {
- EMSG2(_(e_invarg2), p);
- goto sortend;
- }
- }
-
- /* Can only have one of 'n', 'o' and 'x'. */
- if (sort_nr + sort_oct + sort_hex > 2) {
- EMSG(_(e_invarg));
- goto sortend;
- }
-
- /* From here on "sort_nr" is used as a flag for any number sorting. */
- sort_nr += sort_oct + sort_hex;
-
- /*
- * Make an array with all line numbers. This avoids having to copy all
- * the lines into allocated memory.
- * When sorting on strings "start_col_nr" is the offset in the line, for
- * numbers sorting it's the number to sort on. This means the pattern
- * matching and number conversion only has to be done once per line.
- * Also get the longest line length for allocating "sortbuf".
- */
- for (lnum = eap->line1; lnum <= eap->line2; ++lnum) {
- s = ml_get(lnum);
- len = (int)STRLEN(s);
- if (maxlen < len)
- maxlen = len;
-
- start_col = 0;
- end_col = len;
- if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0)) {
- if (sort_rx) {
- start_col = (colnr_T)(regmatch.startp[0] - s);
- end_col = (colnr_T)(regmatch.endp[0] - s);
- } else
- start_col = (colnr_T)(regmatch.endp[0] - s);
- } else if (regmatch.regprog != NULL)
- end_col = 0;
-
- if (sort_nr) {
- /* Make sure vim_str2nr doesn't read any digits past the end
- * of the match, by temporarily terminating the string there */
- s2 = s + end_col;
- c = *s2;
- *s2 = NUL;
- /* Sorting on number: Store the number itself. */
- p = s + start_col;
- if (sort_hex)
- s = skiptohex(p);
- else
- s = skiptodigit(p);
- if (s > p && s[-1] == '-')
- --s; /* include preceding negative sign */
- if (*s == NUL)
- /* empty line should sort before any number */
- nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
- else
- vim_str2nr(s, NULL, NULL, sort_oct, sort_hex,
- &nrs[lnum - eap->line1].start_col_nr, NULL);
- *s2 = c;
- } else {
- /* Store the column to sort at. */
- nrs[lnum - eap->line1].start_col_nr = start_col;
- nrs[lnum - eap->line1].end_col_nr = end_col;
- }
-
- nrs[lnum - eap->line1].lnum = lnum;
-
- if (regmatch.regprog != NULL)
- fast_breakcheck();
- if (got_int)
- goto sortend;
- }
-
- /* Allocate a buffer that can hold the longest line. */
- sortbuf1 = xmalloc(maxlen + 1);
- sortbuf2 = xmalloc(maxlen + 1);
-
- /* Sort the array of line numbers. Note: can't be interrupted! */
- qsort((void *)nrs, count, sizeof(sorti_T), sort_compare);
-
- if (sort_abort)
- goto sortend;
-
- /* Insert the lines in the sorted order below the last one. */
- lnum = eap->line2;
- for (i = 0; i < count; ++i) {
- s = ml_get(nrs[eap->forceit ? count - i - 1 : i].lnum);
- if (!unique || i == 0
- || (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0) {
- if (ml_append(lnum++, s, (colnr_T)0, FALSE) == FAIL)
- break;
- if (unique)
- STRCPY(sortbuf1, s);
- }
- fast_breakcheck();
- if (got_int)
- goto sortend;
- }
-
- /* delete the original lines if appending worked */
- if (i == count)
- for (i = 0; i < count; ++i)
- ml_delete(eap->line1, FALSE);
- else
- count = 0;
-
- /* Adjust marks for deleted (or added) lines and prepare for displaying. */
- deleted = (long)(count - (lnum - eap->line2));
- if (deleted > 0)
- mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted);
- else if (deleted < 0)
- mark_adjust(eap->line2, MAXLNUM, -deleted, 0L);
- changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
-
- curwin->w_cursor.lnum = eap->line1;
- beginline(BL_WHITE | BL_FIX);
-
-sortend:
- free(nrs);
- free(sortbuf1);
- free(sortbuf2);
- vim_regfree(regmatch.regprog);
- if (got_int)
- EMSG(_(e_interr));
-}
-
-/*
- * ":retab".
- */
-void ex_retab(exarg_T *eap)
-{
- linenr_T lnum;
- int got_tab = FALSE;
- long num_spaces = 0;
- long num_tabs;
- long len;
- long col;
- long vcol;
- long start_col = 0; /* For start of white-space string */
- long start_vcol = 0; /* For start of white-space string */
- int temp;
- long old_len;
- char_u *ptr;
- char_u *new_line = (char_u *)1; /* init to non-NULL */
- int did_undo; /* called u_save for current line */
- int new_ts;
- int save_list;
- linenr_T first_line = 0; /* first changed line */
- linenr_T last_line = 0; /* last changed line */
-
- save_list = curwin->w_p_list;
- curwin->w_p_list = 0; /* don't want list mode here */
-
- new_ts = getdigits(&(eap->arg));
- if (new_ts < 0) {
- EMSG(_(e_positive));
- return;
- }
- if (new_ts == 0)
- new_ts = curbuf->b_p_ts;
- for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum) {
- ptr = ml_get(lnum);
- col = 0;
- vcol = 0;
- did_undo = FALSE;
- for (;; ) {
- if (vim_iswhite(ptr[col])) {
- if (!got_tab && num_spaces == 0) {
- /* First consecutive white-space */
- start_vcol = vcol;
- start_col = col;
- }
- if (ptr[col] == ' ')
- num_spaces++;
- else
- got_tab = TRUE;
- } else {
- if (got_tab || (eap->forceit && num_spaces > 1)) {
- /* Retabulate this string of white-space */
-
- /* len is virtual length of white string */
- len = num_spaces = vcol - start_vcol;
- num_tabs = 0;
- if (!curbuf->b_p_et) {
- temp = new_ts - (start_vcol % new_ts);
- if (num_spaces >= temp) {
- num_spaces -= temp;
- num_tabs++;
- }
- num_tabs += num_spaces / new_ts;
- num_spaces -= (num_spaces / new_ts) * new_ts;
- }
- if (curbuf->b_p_et || got_tab ||
- (num_spaces + num_tabs < len)) {
- if (did_undo == FALSE) {
- did_undo = TRUE;
- if (u_save((linenr_T)(lnum - 1),
- (linenr_T)(lnum + 1)) == FAIL) {
- new_line = NULL; /* flag out-of-memory */
- break;
- }
- }
-
- /* len is actual number of white characters used */
- len = num_spaces + num_tabs;
- old_len = (long)STRLEN(ptr);
- new_line = xmalloc(old_len - col + start_col + len + 1);
-
- if (start_col > 0)
- memmove(new_line, ptr, (size_t)start_col);
- memmove(new_line + start_col + len,
- ptr + col, (size_t)(old_len - col + 1));
- ptr = new_line + start_col;
- for (col = 0; col < len; col++)
- ptr[col] = (col < num_tabs) ? '\t' : ' ';
- ml_replace(lnum, new_line, FALSE);
- if (first_line == 0)
- first_line = lnum;
- last_line = lnum;
- ptr = new_line;
- col = start_col + len;
- }
- }
- got_tab = FALSE;
- num_spaces = 0;
- }
- if (ptr[col] == NUL)
- break;
- vcol += chartabsize(ptr + col, (colnr_T)vcol);
- if (has_mbyte)
- col += (*mb_ptr2len)(ptr + col);
- else
- ++col;
- }
- if (new_line == NULL) /* out of memory */
- break;
- line_breakcheck();
- }
- if (got_int)
- EMSG(_(e_interr));
-
- if (curbuf->b_p_ts != new_ts)
- redraw_curbuf_later(NOT_VALID);
- if (first_line != 0)
- changed_lines(first_line, 0, last_line + 1, 0L);
-
- curwin->w_p_list = save_list; /* restore 'list' */
-
- curbuf->b_p_ts = new_ts;
- coladvance(curwin->w_curswant);
-
- u_clearline();
-}
-
-/*
- * :move command - move lines line1-line2 to line dest
- *
- * return FAIL for failure, OK otherwise
- */
-int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
-{
- char_u *str;
- linenr_T l;
- linenr_T extra; /* Num lines added before line1 */
- linenr_T num_lines; /* Num lines moved */
- linenr_T last_line; /* Last line in file after adding new text */
-
- if (dest >= line1 && dest < line2) {
- EMSG(_("E134: Move lines into themselves"));
- return FAIL;
- }
-
- num_lines = line2 - line1 + 1;
-
- /*
- * First we copy the old text to its new location -- webb
- * Also copy the flag that ":global" command uses.
- */
- if (u_save(dest, dest + 1) == FAIL)
- return FAIL;
- for (extra = 0, l = line1; l <= line2; l++) {
- str = vim_strsave(ml_get(l + extra));
- if (str != NULL) {
- ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
- free(str);
- if (dest < line1)
- extra++;
- }
- }
-
- /*
- * Now we must be careful adjusting our marks so that we don't overlap our
- * mark_adjust() calls.
- *
- * We adjust the marks within the old text so that they refer to the
- * last lines of the file (temporarily), because we know no other marks
- * will be set there since these line numbers did not exist until we added
- * our new lines.
- *
- * Then we adjust the marks on lines between the old and new text positions
- * (either forwards or backwards).
- *
- * And Finally we adjust the marks we put at the end of the file back to
- * their final destination at the new text position -- webb
- */
- last_line = curbuf->b_ml.ml_line_count;
- mark_adjust(line1, line2, last_line - line2, 0L);
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines);
- if (dest >= line2) {
- mark_adjust(line2 + 1, dest, -num_lines, 0L);
- curbuf->b_op_start.lnum = dest - num_lines + 1;
- curbuf->b_op_end.lnum = dest;
- } else {
- mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
- curbuf->b_op_start.lnum = dest + 1;
- curbuf->b_op_end.lnum = dest + num_lines;
- }
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
- mark_adjust(last_line - num_lines + 1, last_line,
- -(last_line - dest - extra), 0L);
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra);
-
- /*
- * Now we delete the original text -- webb
- */
- if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
- return FAIL;
-
- for (l = line1; l <= line2; l++)
- ml_delete(line1 + extra, TRUE);
-
- if (!global_busy && num_lines > p_report) {
- if (num_lines == 1)
- MSG(_("1 line moved"));
- else
- smsg((char_u *)_("%" PRId64 " lines moved"), (int64_t)num_lines);
- }
-
- /*
- * Leave the cursor on the last of the moved lines.
- */
- if (dest >= line1)
- curwin->w_cursor.lnum = dest;
- else
- curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
-
- if (line1 < dest) {
- dest += num_lines + 1;
- last_line = curbuf->b_ml.ml_line_count;
- if (dest > last_line + 1)
- dest = last_line + 1;
- changed_lines(line1, 0, dest, 0L);
- } else
- changed_lines(dest + 1, 0, line1 + num_lines, 0L);
-
- return OK;
-}
-
-/*
- * ":copy"
- */
-void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
-{
- linenr_T count;
- char_u *p;
-
- count = line2 - line1 + 1;
- curbuf->b_op_start.lnum = n + 1;
- curbuf->b_op_end.lnum = n + count;
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
-
- /*
- * there are three situations:
- * 1. destination is above line1
- * 2. destination is between line1 and line2
- * 3. destination is below line2
- *
- * n = destination (when starting)
- * curwin->w_cursor.lnum = destination (while copying)
- * line1 = start of source (while copying)
- * line2 = end of source (while copying)
- */
- if (u_save(n, n + 1) == FAIL)
- return;
-
- curwin->w_cursor.lnum = n;
- while (line1 <= line2) {
- /* need to use vim_strsave() because the line will be unlocked within
- * ml_append() */
- p = vim_strsave(ml_get(line1));
- if (p != NULL) {
- ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
- free(p);
- }
- /* situation 2: skip already copied lines */
- if (line1 == n)
- line1 = curwin->w_cursor.lnum;
- ++line1;
- if (curwin->w_cursor.lnum < line1)
- ++line1;
- if (curwin->w_cursor.lnum < line2)
- ++line2;
- ++curwin->w_cursor.lnum;
- }
-
- appended_lines_mark(n, count);
-
- msgmore((long)count);
-}
-
-static char_u *prevcmd = NULL; /* the previous command */
-
-#if defined(EXITFREE) || defined(PROTO)
-void free_prev_shellcmd(void)
-{
- free(prevcmd);
-}
-
-#endif
-
-/*
- * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
- * Bangs in the argument are replaced with the previously entered command.
- * Remember the argument.
- */
-void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
-{
- char_u *arg = eap->arg; /* command */
- linenr_T line1 = eap->line1; /* start of range */
- linenr_T line2 = eap->line2; /* end of range */
- char_u *newcmd = NULL; /* the new command */
- int free_newcmd = FALSE; /* need to free() newcmd */
- int ins_prevcmd;
- char_u *t;
- char_u *p;
- char_u *trailarg;
- int len;
- int scroll_save = msg_scroll;
-
- /*
- * Disallow shell commands for "rvim".
- * Disallow shell commands from .exrc and .vimrc in current directory for
- * security reasons.
- */
- if (check_restricted() || check_secure())
- return;
-
- if (addr_count == 0) { /* :! */
- msg_scroll = FALSE; /* don't scroll here */
- autowrite_all();
- msg_scroll = scroll_save;
- }
-
- /*
- * Try to find an embedded bang, like in :!<cmd> ! [args]
- * (:!! is indicated by the 'forceit' variable)
- */
- ins_prevcmd = forceit;
- trailarg = arg;
- do {
- len = (int)STRLEN(trailarg) + 1;
- if (newcmd != NULL)
- len += (int)STRLEN(newcmd);
- if (ins_prevcmd) {
- if (prevcmd == NULL) {
- EMSG(_(e_noprev));
- free(newcmd);
- return;
- }
- len += (int)STRLEN(prevcmd);
- }
- t = xmalloc(len);
- *t = NUL;
- if (newcmd != NULL)
- STRCAT(t, newcmd);
- if (ins_prevcmd)
- STRCAT(t, prevcmd);
- p = t + STRLEN(t);
- STRCAT(t, trailarg);
- free(newcmd);
- newcmd = t;
-
- /*
- * Scan the rest of the argument for '!', which is replaced by the
- * previous command. "\!" is replaced by "!" (this is vi compatible).
- */
- trailarg = NULL;
- while (*p) {
- if (*p == '!') {
- if (p > newcmd && p[-1] == '\\')
- STRMOVE(p - 1, p);
- else {
- trailarg = p;
- *trailarg++ = NUL;
- ins_prevcmd = TRUE;
- break;
- }
- }
- ++p;
- }
- } while (trailarg != NULL);
-
- free(prevcmd);
- prevcmd = newcmd;
-
- if (bangredo) { /* put cmd in redo buffer for ! command */
- /* If % or # appears in the command, it must have been escaped.
- * Reescape them, so that redoing them does not substitute them by the
- * buffername. */
- char_u *cmd = vim_strsave_escaped(prevcmd, (char_u *)"%#");
-
- AppendToRedobuffLit(cmd, -1);
- free(cmd);
- AppendToRedobuff((char_u *)"\n");
- bangredo = FALSE;
- }
- /*
- * Add quotes around the command, for shells that need them.
- */
- if (*p_shq != NUL) {
- newcmd = xmalloc(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1);
- STRCPY(newcmd, p_shq);
- STRCAT(newcmd, prevcmd);
- STRCAT(newcmd, p_shq);
- free_newcmd = TRUE;
- }
- if (addr_count == 0) { /* :! */
- /* echo the command */
- msg_start();
- msg_putchar(':');
- msg_putchar('!');
- msg_outtrans(newcmd);
- msg_clr_eos();
- windgoto(msg_row, msg_col);
-
- do_shell(newcmd, 0);
- } else { /* :range! */
- /* Careful: This may recursively call do_bang() again! (because of
- * autocommands) */
- do_filter(line1, line2, eap, newcmd, do_in, do_out);
- apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, FALSE, curbuf);
- }
- if (free_newcmd)
- free(newcmd);
-}
-
-/*
- * do_filter: filter lines through a command given by the user
- *
- * We mostly use temp files and the call_shell() routine here. This would
- * normally be done using pipes on a UNIX machine, but this is more portable
- * to non-unix machines. The call_shell() routine needs to be able
- * to deal with redirection somehow, and should handle things like looking
- * at the PATH env. variable, and adding reasonable extensions to the
- * command name given by the user. All reasonable versions of call_shell()
- * do this.
- * Alternatively, if on Unix and redirecting input or output, but not both,
- * and the 'shelltemp' option isn't set, use pipes.
- * We use input redirection if do_in is TRUE.
- * We use output redirection if do_out is TRUE.
- */
-static void
-do_filter (
- linenr_T line1,
- linenr_T line2,
- exarg_T *eap, /* for forced 'ff' and 'fenc' */
- char_u *cmd,
- int do_in,
- int do_out
-)
-{
- char_u *itmp = NULL;
- char_u *otmp = NULL;
- linenr_T linecount;
- linenr_T read_linecount;
- pos_T cursor_save;
- char_u *cmd_buf;
- buf_T *old_curbuf = curbuf;
- int shell_flags = 0;
-
- if (*cmd == NUL) /* no filter command */
- return;
-
-
- cursor_save = curwin->w_cursor;
- linecount = line2 - line1 + 1;
- curwin->w_cursor.lnum = line1;
- curwin->w_cursor.col = 0;
- changed_line_abv_curs();
- invalidate_botline();
-
- /*
- * When using temp files:
- * 1. * Form temp file names
- * 2. * Write the lines to a temp file
- * 3. Run the filter command on the temp file
- * 4. * Read the output of the command into the buffer
- * 5. * Delete the original lines to be filtered
- * 6. * Remove the temp files
- *
- * When writing the input with a pipe or when catching the output with a
- * pipe only need to do 3.
- */
-
- if (do_out)
- shell_flags |= kShellOptDoOut;
-
- if (!do_in && do_out && !p_stmp) {
- // Use a pipe to fetch stdout of the command, do not use a temp file.
- shell_flags |= kShellOptRead;
- curwin->w_cursor.lnum = line2;
- } else if (do_in && !do_out && !p_stmp) {
- // Use a pipe to write stdin of the command, do not use a temp file.
- shell_flags |= kShellOptWrite;
- curbuf->b_op_start.lnum = line1;
- curbuf->b_op_end.lnum = line2;
- } else if (do_in && do_out && !p_stmp) {
- // Use a pipe to write stdin and fetch stdout of the command, do not
- // use a temp file.
- shell_flags |= kShellOptRead | kShellOptWrite;
- curbuf->b_op_start.lnum = line1;
- curbuf->b_op_end.lnum = line2;
- curwin->w_cursor.lnum = line2;
- } else if ((do_in && (itmp = vim_tempname('i')) == NULL)
- || (do_out && (otmp = vim_tempname('o')) == NULL)) {
- EMSG(_(e_notmp));
- goto filterend;
- }
-
- /*
- * The writing and reading of temp files will not be shown.
- * Vi also doesn't do this and the messages are not very informative.
- */
- ++no_wait_return; /* don't call wait_return() while busy */
- if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap,
- FALSE, FALSE, FALSE, TRUE) == FAIL) {
- msg_putchar('\n'); /* keep message from buf_write() */
- --no_wait_return;
- if (!aborting())
- (void)EMSG2(_(e_notcreate), itmp); /* will call wait_return */
- goto filterend;
- }
- if (curbuf != old_curbuf)
- goto filterend;
-
- if (!do_out)
- msg_putchar('\n');
-
- /* Create the shell command in allocated memory. */
- cmd_buf = make_filter_cmd(cmd, itmp, otmp);
-
- windgoto((int)Rows - 1, 0);
- cursor_on();
-
- /*
- * When not redirecting the output the command can write anything to the
- * screen. If 'shellredir' is equal to ">", screen may be messed up by
- * stderr output of external command. Clear the screen later.
- * If do_in is FALSE, this could be something like ":r !cat", which may
- * also mess up the screen, clear it later.
- */
- if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
- redraw_later_clear();
-
- if (do_out) {
- if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL) {
- free(cmd_buf);
- goto error;
- }
- redraw_curbuf_later(VALID);
- }
- read_linecount = curbuf->b_ml.ml_line_count;
-
- /*
- * When call_shell() fails wait_return() is called to give the user a
- * chance to read the error messages. Otherwise errors are ignored, so you
- * can see the error messages from the command that appear on stdout; use
- * 'u' to fix the text
- * Switch to cooked mode when not redirecting stdin, avoids that something
- * like ":r !cat" hangs.
- * Pass on the kShellDoOut flag when the output is being redirected.
- */
- if (call_shell(