summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-02-22 08:39:57 +0000
committerBram Moolenaar <Bram@vim.org>2005-02-22 08:39:57 +0000
commitdf177f679e950a2ab2ad5fe7d45c1daface004d7 (patch)
tree21c0c50e9144ef873af675daf53b86beb26dd677 /src
parent6bdcfc08cb9c192972336e28a2a842b7abbb2811 (diff)
downloadvim-git-df177f679e950a2ab2ad5fe7d45c1daface004d7.tar.gz
updated for version 7.0051
Diffstat (limited to 'src')
-rw-r--r--src/Makefile6
-rw-r--r--src/ex_docmd.c362
-rw-r--r--src/fileio.c18
-rw-r--r--src/globals.h11
-rw-r--r--src/mbyte.c9
-rw-r--r--src/message.c38
-rw-r--r--src/netbeans.c14
-rw-r--r--src/normal.c8
-rw-r--r--src/os_unix.c335
-rw-r--r--src/po/Make_ming.mak4
-rw-r--r--src/po/Makefile4
-rw-r--r--src/proto/ex_docmd.pro1
-rw-r--r--src/proto/gui_mac.pro1
-rw-r--r--src/proto/main.pro2
-rw-r--r--src/proto/message.pro3
-rw-r--r--src/quickfix.c13
-rw-r--r--src/regexp.c407
-rw-r--r--src/testdir/test11.in1
-rw-r--r--src/vim.h9
19 files changed, 965 insertions, 281 deletions
diff --git a/src/Makefile b/src/Makefile
index b2dc0153f..0ea38f70b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -505,6 +505,7 @@ CClink = $(CC)
# Often used for GCC: mixed optimizing, lot of optimizing, debugging
#CFLAGS = -g -O2 -fno-strength-reduce -Wall -Wshadow -Wmissing-prototypes
#CFLAGS = -g -O2 -fno-strength-reduce -Wall -Wmissing-prototypes
+#CFLAGS = -g -Wall -Wmissing-prototypes
#CFLAGS = -O6 -fno-strength-reduce -Wall -Wshadow -Wmissing-prototypes
#CFLAGS = -g -DDEBUG -Wall -Wshadow -Wmissing-prototypes
#CFLAGS = -g -O2 '-DSTARTUPTIME="vimstartup"' -fno-strength-reduce -Wall -Wmissing-prototypes
@@ -2410,6 +2411,11 @@ $(APPDIR): bundle-dir bundle-executable bundle-info bundle-resource \
bundle-dir: $(APPDIR)/Contents $(VIMTARGET)
-@srcdir=`pwd`; cd $(HELPSOURCE); $(MAKE) VIMEXE=$$srcdir/$(VIMTARGET) vimtags
cp -R ../runtime $(APPDIR)
+# When using CVS some CVS directories might have been copied.
+ cvs=`find $(APPDIR) \( -name CVS -o -name AAPDIR \) -print`; \
+ if test -n "$$cvs"; then \
+ rm -rf $$cvs; \
+ fi
bundle-executable: $(VIMTARGET)
cp $(VIMTARGET) $(APPDIR)/Contents/MacOS/$(VIMTARGET)
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index d2e933af4..2bb5aeb2f 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -128,6 +128,7 @@ static int getargopt __ARGS((exarg_T *eap));
static int check_more __ARGS((int, int));
static linenr_T get_address __ARGS((char_u **, int skip, int to_other_file));
+static void get_flags __ARGS((exarg_T *eap));
#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
|| !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME)
static void ex_script_ni __ARGS((exarg_T *eap));
@@ -185,6 +186,7 @@ static void ex_recover __ARGS((exarg_T *eap));
static void ex_mode __ARGS((exarg_T *eap));
static void ex_wrongmodifier __ARGS((exarg_T *eap));
static void ex_find __ARGS((exarg_T *eap));
+static void ex_open __ARGS((exarg_T *eap));
static void ex_edit __ARGS((exarg_T *eap));
#if !defined(FEAT_GUI) && !defined(FEAT_CLIENTSERVER)
# define ex_drop ex_ni
@@ -271,6 +273,7 @@ static void ex_winpos __ARGS((exarg_T *eap));
static void ex_operators __ARGS((exarg_T *eap));
static void ex_put __ARGS((exarg_T *eap));
static void ex_copymove __ARGS((exarg_T *eap));
+static void ex_may_print __ARGS((exarg_T *eap));
static void ex_submagic __ARGS((exarg_T *eap));
static void ex_join __ARGS((exarg_T *eap));
static void ex_at __ARGS((exarg_T *eap));
@@ -570,19 +573,22 @@ do_exmode(improved)
int save_msg_scroll;
int prev_msg_row;
linenr_T prev_line;
+ int changedtick;
- save_msg_scroll = msg_scroll;
- ++RedrawingDisabled; /* don't redisplay the window */
- ++no_wait_return; /* don't wait for return */
if (improved)
exmode_active = EXMODE_VIM;
else
- {
- settmode(TMODE_COOK);
exmode_active = EXMODE_NORMAL;
- }
-
State = NORMAL;
+
+ /* When using ":global /pat/ visual" and then "Q" we return to continue
+ * the :global command. */
+ if (global_busy)
+ return;
+
+ save_msg_scroll = msg_scroll;
+ ++RedrawingDisabled; /* don't redisplay the window */
+ ++no_wait_return; /* don't wait for return */
#ifdef FEAT_GUI
/* Ignore scrollbar and mouse events in Ex mode */
++hold_gui_events;
@@ -606,6 +612,7 @@ do_exmode(improved)
need_wait_return = FALSE;
ex_pressedreturn = FALSE;
ex_no_reprint = FALSE;
+ changedtick = curbuf->b_changedtick;
prev_msg_row = msg_row;
prev_line = curwin->w_cursor.lnum;
#ifdef FEAT_SNIFF
@@ -620,29 +627,38 @@ do_exmode(improved)
do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
lines_left = Rows - 1;
- if (prev_line != curwin->w_cursor.lnum && !ex_no_reprint)
+ if ((prev_line != curwin->w_cursor.lnum
+ || changedtick != curbuf->b_changedtick) && !ex_no_reprint)
{
- if (ex_pressedreturn)
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ EMSG(_(e_emptybuf));
+ else
{
- /* go up one line, to overwrite the ":<CR>" line, so the
- * output doensn't contain empty lines. */
- msg_row = prev_msg_row;
- if (prev_msg_row == Rows - 1)
- msg_row--;
+ if (ex_pressedreturn)
+ {
+ /* go up one line, to overwrite the ":<CR>" line, so the
+ * output doensn't contain empty lines. */
+ msg_row = prev_msg_row;
+ if (prev_msg_row == Rows - 1)
+ msg_row--;
+ }
+ msg_col = 0;
+ print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE);
+ msg_clr_eos();
}
- msg_col = 0;
- print_line_no_prefix(curwin->w_cursor.lnum, FALSE);
- msg_clr_eos();
}
- else if (ex_pressedreturn) /* must be at EOF */
- EMSG(_("E501: At end-of-file"));
+ else if (ex_pressedreturn && !ex_no_reprint) /* must be at EOF */
+ {
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ EMSG(_(e_emptybuf));
+ else
+ EMSG(_("E501: At end-of-file"));
+ }
}
#ifdef FEAT_GUI
--hold_gui_events;
#endif
- if (!improved)
- settmode(TMODE_RAW);
--RedrawingDisabled;
--no_wait_return;
update_screen(CLEAR);
@@ -1663,7 +1679,8 @@ do_one_cmd(cmdlinep, sourcing,
/* in ex mode, an empty line works like :+ */
if (*ea.cmd == NUL && exmode_active
&& (getline_equal(getline, cookie, getexmodeline)
- || getline_equal(getline, cookie, getexline)))
+ || getline_equal(getline, cookie, getexline))
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
{
ea.cmd = (char_u *)"+";
ex_pressedreturn = TRUE;
@@ -1671,7 +1688,10 @@ do_one_cmd(cmdlinep, sourcing,
/* ignore comment and empty lines */
if (*ea.cmd == '"' || *ea.cmd == NUL)
+ {
+ ex_pressedreturn = TRUE;
goto doend;
+ }
/*
* 2. handle command modifiers.
@@ -1936,7 +1956,7 @@ do_one_cmd(cmdlinep, sourcing,
*/
if (ea.skip) /* skip this if inside :if */
goto doend;
- if (*ea.cmd == '|')
+ if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2))
{
ea.cmdidx = CMD_print;
ea.argt = RANGE+COUNT+TRLBAR;
@@ -1948,14 +1968,12 @@ do_one_cmd(cmdlinep, sourcing,
}
else if (ea.addr_count != 0)
{
- if (ea.line2 < 0)
- errormsg = invalid_range(&ea);
+ if (ea.line2 < 0 || ea.line2 > curbuf->b_ml.ml_line_count)
+ errormsg = (char_u *)_(e_invrange);
else
{
if (ea.line2 == 0)
curwin->w_cursor.lnum = 1;
- else if (ea.line2 > curbuf->b_ml.ml_line_count)
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
else
curwin->w_cursor.lnum = ea.line2;
beginline(BL_SOL | BL_FIX);
@@ -2090,7 +2108,7 @@ do_one_cmd(cmdlinep, sourcing,
*/
if (!global_busy && ea.line1 > ea.line2)
{
- if (sourcing)
+ if (sourcing || exmode_active)
{
errormsg = (char_u *)_("E493: Backwards range given");
goto doend;
@@ -2280,9 +2298,13 @@ do_one_cmd(cmdlinep, sourcing,
/*
* Check for <newline> to end a shell command.
- * Also do this for ":read !cmd" and ":write !cmd".
+ * Also do this for ":read !cmd", ":write !cmd" and ":global".
+ * Any others?
*/
- else if (ea.cmdidx == CMD_bang || ea.usefilter)
+ else if (ea.cmdidx == CMD_bang
+ || ea.cmdidx == CMD_global
+ || ea.cmdidx == CMD_vglobal
+ || ea.usefilter)
{
for (p = ea.arg; *p; ++p)
{
@@ -2367,6 +2389,12 @@ do_one_cmd(cmdlinep, sourcing,
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
+
+ /*
+ * Check for flags: 'l', 'p' and '#'.
+ */
+ if (ea.argt & EXFLAGS)
+ get_flags(&ea);
/* no arguments allowed */
if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL
&& vim_strchr((char_u *)"|\"", *ea.arg) == NULL)
@@ -2661,6 +2689,7 @@ find_command(eap, full)
{
int len;
char_u *p;
+ int i;
/*
* Isolate the command and search for it in the command table.
@@ -2669,6 +2698,7 @@ find_command(eap, full)
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
* but :sre[wind] is another command, as are :scrip[tnames],
* :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
+ * - the "d" command can directly be followed by 'l' or 'p' flag.
*/
p = eap->cmd;
if (*p == 'k')
@@ -2694,6 +2724,22 @@ find_command(eap, full)
if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
++p;
len = (int)(p - eap->cmd);
+ if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
+ {
+ /* Check for ":dl", ":dell", etc. to ":deletel": that's
+ * :delete with the 'l' flag. Same for 'p'. */
+ for (i = 0; i < len; ++i)
+ if (eap->cmd[i] != "delete"[i])
+ break;
+ if (i == len - 1)
+ {
+ --len;
+ if (p[-1] == 'l')
+ eap->flags |= EXFLAG_LIST;
+ else
+ eap->flags |= EXFLAG_PRINT;
+ }
+ }
if (ASCII_ISLOWER(*eap->cmd))
eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)];
@@ -2928,8 +2974,6 @@ set_one_cmd_context(xp, buff)
/*
* 4. parse command
*/
-
- cmd = skipwhite(cmd);
xp->xp_pattern = cmd;
if (*cmd == NUL)
return NULL;
@@ -3281,6 +3325,7 @@ set_one_cmd_context(xp, buff)
case CMD_botright:
case CMD_browse:
case CMD_confirm:
+ case CMD_debug:
case CMD_folddoclosed:
case CMD_folddoopen:
case CMD_hide:
@@ -3633,6 +3678,7 @@ set_one_cmd_context(xp, buff)
* Backslashed delimiters after / or ? will be skipped, and commands will
* not be expanded between /'s and ?'s or after "'".
*
+ * Also skip white space and ":" characters.
* Returns the "cmd" pointer advanced to beyond the range.
*/
char_u *
@@ -3642,8 +3688,7 @@ skip_range(cmd, ctx)
{
int delim;
- while (*cmd != NUL && (vim_isspace(*cmd) || VIM_ISDIGIT(*cmd) ||
- vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL))
+ while (vim_strchr((char_u *)" \t0123456789.$%'/?-+,;", *cmd) != NULL)
{
if (*cmd == '\'')
{
@@ -3662,6 +3707,11 @@ skip_range(cmd, ctx)
if (*cmd != NUL)
++cmd;
}
+
+ /* Skip ":" and white space. */
+ while (*cmd == ':')
+ cmd = skipwhite(cmd + 1);
+
return cmd;
}
@@ -3856,6 +3906,25 @@ error:
}
/*
+ * Get flags from an Ex command argument.
+ */
+ static void
+get_flags(eap)
+ exarg_T *eap;
+{
+ while (vim_strchr((char_u *)"lp#", *eap->arg) != NULL)
+ {
+ if (*eap->arg == 'l')
+ eap->flags |= EXFLAG_LIST;
+ else if (*eap->arg == 'p')
+ eap->flags |= EXFLAG_PRINT;
+ else
+ eap->flags |= EXFLAG_NR;
+ eap->arg = skipwhite(eap->arg + 1);
+ }
+}
+
+/*
* Function called for command which is Not Implemented. NI!
*/
void
@@ -4280,7 +4349,7 @@ separate_nextcmd(eap)
#ifdef FEAT_EVAL
/* Skip over `=expr` when wildcards are expanded. */
- else if (p[0] == '`' && p[1] == '=')
+ else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE))
{
p += 2;
(void)skip_expr(&p);
@@ -6116,31 +6185,27 @@ ex_exit(eap)
ex_print(eap)
exarg_T *eap;
{
- int save_list = 0; /* init for GCC */
-
- if (eap->cmdidx == CMD_list)
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ EMSG(_(e_emptybuf));
+ else
{
- save_list = curwin->w_p_list;
- curwin->w_p_list = 1;
+ for ( ;!got_int; ui_breakcheck())
+ {
+ print_line(eap->line1,
+ (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound
+ || (eap->flags & EXFLAG_NR)),
+ eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST));
+ if (++eap->line1 > eap->line2)
+ break;
+ out_flush(); /* show one line at a time */
+ }
+ setpcmark();
+ /* put cursor at last line */
+ curwin->w_cursor.lnum = eap->line2;
+ beginline(BL_SOL | BL_FIX);
}
- for ( ;!got_int; ui_breakcheck())
- {
- print_line(eap->line1,
- (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
- if (++eap->line1 > eap->line2)
- break;
- out_flush(); /* show one line at a time */
- }
- setpcmark();
- /* put cursor at last line */
- curwin->w_cursor.lnum = eap->line2;
- beginline(BL_SOL | BL_FIX);
-
ex_no_reprint = TRUE;
-
- if (eap->cmdidx == CMD_list)
- curwin->w_p_list = save_list;
}
#ifdef FEAT_BYTEOFF
@@ -6689,7 +6754,45 @@ ex_find(eap)
}
/*
- * ":edit", ":badd".
+ * ":open" simulation: for now just work like ":visual".
+ */
+ static void
+ex_open(eap)
+ exarg_T *eap;
+{
+ regmatch_T regmatch;
+ char_u *p;
+
+ curwin->w_cursor.lnum = eap->line2;
+ beginline(BL_SOL | BL_FIX);
+ if (*eap->arg == '/')
+ {
+ /* ":open /pattern/": put cursor in column found with pattern */
+ ++eap->arg;
+ p = skip_regexp(eap->arg, '/', p_magic, NULL);
+ *p = NUL;
+ regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0);
+ if (regmatch.regprog != NULL)
+ {
+ regmatch.rm_ic = p_ic;
+ p = ml_get_curline();
+ if (vim_regexec(&regmatch, p, (colnr_T)0))
+ curwin->w_cursor.col = regmatch.startp[0] - p;
+ else
+ EMSG(_(e_nomatch));
+ vim_free(regmatch.regprog);
+ }
+ /* Move to the NUL, ignore any other arguments. */
+ eap->arg += STRLEN(eap->arg);
+ }
+ check_cursor();
+
+ eap->cmdidx = CMD_visual;
+ do_exedit(eap, NULL);
+}
+
+/*
+ * ":edit", ":badd", ":visual".
*/
static void
ex_edit(eap)
@@ -6711,6 +6814,7 @@ do_exedit(eap, old_curwin)
#ifdef FEAT_WINDOWS
int need_hide;
#endif
+ int exmode_was = exmode_active;
/*
* ":vi" command ends Ex mode.
@@ -6720,7 +6824,45 @@ do_exedit(eap, old_curwin)
{
exmode_active = FALSE;
if (*eap->arg == NUL)
+ {
+ /* Special case: ":global/pat/visual\NLvi-commands" */
+ if (global_busy)
+ {
+ int rd = RedrawingDisabled;
+ int nwr = no_wait_return;
+ int ms = msg_scroll;
+#ifdef FEAT_GUI
+ int he = hold_gui_events;
+#endif
+
+ if (eap->nextcmd != NULL)
+ {
+ stuffReadbuff(eap->nextcmd);
+ eap->nextcmd = NULL;
+ }
+
+ if (exmode_was != EXMODE_VIM)
+ settmode(TMODE_RAW);
+ RedrawingDisabled = 0;
+ no_wait_return = 0;
+ need_wait_return = FALSE;
+ msg_scroll = 0;
+#ifdef FEAT_GUI
+ hold_gui_events = 0;
+#endif
+ must_redraw = CLEAR;
+
+ main_loop(FALSE, TRUE);
+
+ RedrawingDisabled = rd;
+ no_wait_return = nwr;
+ msg_scroll = ms;
+#ifdef FEAT_GUI
+ hold_gui_events = he;
+#endif
+ }
return;
+ }
}
if ((eap->cmdidx == CMD_new
@@ -6961,7 +7103,9 @@ ex_syncbind(eap)
ex_read(eap)
exarg_T *eap;
{
- int i;
+ int i;
+ int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+ linenr_T lnum;
if (eap->usefilter) /* :r!cmd */
do_bang(1, eap, FALSE, FALSE, TRUE);
@@ -7011,7 +7155,25 @@ ex_read(eap)
EMSG2(_(e_notopen), eap->arg);
}
else
+ {
+ if (empty && exmode_active)
+ {
+ /* Delete the empty line that remains. Historically ex does
+ * this but vi doesn't. */
+ if (eap->line2 == 0)
+ lnum = curbuf->b_ml.ml_line_count;
+ else
+ lnum = 1;
+ if (*ml_get(lnum) == NUL)
+ {
+ ml_delete(lnum, FALSE);
+ deleted_lines_mark(lnum, 1L);
+ if (curwin->w_cursor.lnum >= lnum)
+ --curwin->w_cursor.lnum;
+ }
+ }
redraw_curbuf_later(VALID);
+ }
}
}
@@ -7034,6 +7196,13 @@ ex_cd(eap)
else
#endif
{
+ if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged()
+ && !eap->forceit)
+ {
+ EMSG(_("E747: Cannot change directory, buffer is modifed (add ! to override)"));
+ return;
+ }
+
/* ":cd -": Change to previous directory */
if (STRCMP(new_dir, "-") == 0)
{
@@ -7132,6 +7301,7 @@ ex_equal(eap)
exarg_T *eap;
{
smsg((char_u *)"%ld", (long)eap->line2);
+ ex_may_print(eap);
}
static void
@@ -7361,6 +7531,7 @@ ex_operators(eap)
#ifdef FEAT_VIRTUALEDIT
virtual_op = MAYBE;
#endif
+ ex_may_print(eap);
}
/*
@@ -7377,7 +7548,8 @@ ex_put(eap)
eap->forceit = TRUE;
}
curwin->w_cursor.lnum = eap->line2;
- do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, PUT_LINE);
+ do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
+ PUT_LINE|PUT_CURSLINE);
}
/*
@@ -7395,6 +7567,7 @@ ex_copymove(eap)
eap->nextcmd = NULL;
return;
}
+ get_flags(eap);
/*
* move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
@@ -7414,6 +7587,22 @@ ex_copymove(eap)
ex_copy(eap->line1, eap->line2, n);
u_clearline();
beginline(BL_SOL | BL_FIX);
+ ex_may_print(eap);
+}
+
+/*
+ * Print the current line if flags were given to the Ex command.
+ */
+ static void
+ex_may_print(eap)
+ exarg_T *eap;
+{
+ if (eap->flags != 0)
+ {
+ print_line(curwin->w_cursor.lnum, (eap->flags & EXFLAG_NR),
+ (eap->flags & EXFLAG_LIST));
+ ex_no_reprint = TRUE;
+ }
}
/*
@@ -7451,6 +7640,7 @@ ex_join(eap)
}
do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit);
beginline(BL_WHITE | BL_FIX);
+ ex_may_print(eap);
}
/*
@@ -7474,7 +7664,9 @@ ex_at(eap)
c = '@';
/* put the register in mapbuf */
if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
+ {
beep_flush();
+ }
else
{
int save_efr = exec_from_reg;
@@ -7602,18 +7794,36 @@ ex_redir(eap)
/* make register empty */
write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
}
- if (*arg != NUL)
- EMSG2(_(e_invarg2), eap->arg);
}
- else
+ if (*arg != NUL)
+ {
EMSG2(_(e_invarg2), eap->arg);
+ redir_reg = 0;
+ }
+ }
+ else if (*arg == '=' && arg[1] == '>')
+ {
+ int append;
+
+ /* redirect to a variable */
+ close_redir();
+ arg += 2;
+
+ if (*arg == '>')
+ {
+ ++arg;
+ append = TRUE;
+ }
+ else
+ append = FALSE;
+
+ if (var_redir_start(skipwhite(arg), append) == OK)
+ redir_vname = 1;
}
#endif
/* TODO: redirect to a buffer */
- /* TODO: redirect to an internal variable */
-
else
EMSG2(_(e_invarg2), eap->arg);
}
@@ -7690,6 +7900,11 @@ close_redir()
}
#ifdef FEAT_EVAL
redir_reg = 0;
+ if (redir_vname)
+ {
+ var_redir_stop();
+ redir_vname = 0;
+ }
#endif
}
@@ -7774,8 +7989,7 @@ ex_mkrc(eap)
#if defined(FEAT_SESSION) && defined(vim_mkdir)
/* When using 'viewdir' may have to create the directory. */
if (using_vdir && !mch_isdir(p_vdir))
- if (vim_mkdir(p_vdir, 0755) != 0)
- EMSG2(_("E739: Cannot create directory: %s"), p_vdir);
+ vim_mkdir_emsg(p_vdir, 0755);
#endif
fd = open_exfile(fname, eap->forceit, WRITEBIN);
@@ -7893,6 +8107,22 @@ theend:
#endif
}
+#if ((defined(FEAT_SESSION) || defined(FEAT_EVAL)) && defined(vim_mkdir)) \
+ || defined(PROTO)
+ int
+vim_mkdir_emsg(name, prot)
+ char_u *name;
+ int prot;
+{
+ if (vim_mkdir(name, prot) != 0)
+ {
+ EMSG2(_("E739: Cannot create directory: %s"), name);
+ return FAIL;
+ }
+ return OK;
+}
+#endif
+
/*
* Open a file for writing for an Ex command, with some checks.
* Return file descriptor, or NULL on failure.
diff --git a/src/fileio.c b/src/fileio.c
index 9dd1d4975..064468870 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -140,10 +140,6 @@ static int get_mac_fio_flags __ARGS((char_u *ptr));
#endif
static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
-static linenr_T write_no_eol_lnum = 0; /* non-zero lnum when last line of
- next binary write should not have
- an end-of-line */
-
void
filemess(buf, name, s, attr)
buf_T *buf;
@@ -288,9 +284,7 @@ readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
int conv_restlen = 0; /* nr of bytes in conv_rest[] */
#endif
-#ifdef FEAT_AUTOCMD
write_no_eol_lnum = 0; /* in case it was set by the previous read */
-#endif
/*
* If there is no file name yet, use the one for the read file.
@@ -308,6 +302,10 @@ readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
curbuf->b_flags |= BF_NOTEDITED;
}
+ /* After reading a file the cursor line changes but we don't want to
+ * display the line. */
+ ex_no_reprint = TRUE;
+
/*
* For Unix: Use the short file name whenever possible.
* Avoids problems with networks and when directory names are changed.
@@ -2230,7 +2228,6 @@ failed:
check_marks_read();
#endif
-#ifdef FEAT_AUTOCMD
/*
* Trick: We remember if the last line of the read didn't have
* an eol for when writing it again. This is required for
@@ -2238,6 +2235,7 @@ failed:
*/
write_no_eol_lnum = read_no_eol_lnum;
+#ifdef FEAT_AUTOCMD
if (!read_stdin && !read_buffer)
{
int m = msg_scroll;
@@ -2628,6 +2626,10 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit,
# endif
#endif
+ /* After writing a file changedtick changes but we don't want to display
+ * the line. */
+ ex_no_reprint = TRUE;
+
/*
* If there is no file name yet, use the one for the written file.
* BF_NOTEDITED is set to reflect this (in case the write fails).
@@ -6267,7 +6269,7 @@ buf_store_time(buf, st, fname)
write_lnum_adjust(offset)
linenr_T offset;
{
- if (write_no_eol_lnum) /* only if there is a missing eol */
+ if (write_no_eol_lnum != 0) /* only if there is a missing eol */
write_no_eol_lnum += offset;
}
diff --git a/src/globals.h b/src/globals.h
index 1df8b87fe..2c1c53a3d 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -155,6 +155,7 @@ EXTERN int did_endif INIT(= FALSE); /* just had ":endif" */
EXTERN int did_emsg; /* set by emsg() when the message
is displayed or thrown */
EXTERN int called_emsg; /* always set by emsg() */
+EXTERN int ex_exitval INIT(= 0); /* exit value for ex mode */
EXTERN int emsg_on_display INIT(= FALSE); /* there is an error message */
EXTERN int rc_did_emsg INIT(= FALSE); /* vim_regcomp() called emsg() */
@@ -181,6 +182,7 @@ EXTERN int x_force_connect INIT(= FALSE); /* Do connect to X server.
"exclude" in 'clipboard'. */
# endif
#endif
+EXTERN int ex_keep_indent INIT(= FALSE); /* getexmodeline(): keep indent */
EXTERN int vgetc_busy INIT(= FALSE); /* inside vgetc() now */
EXTERN int didset_vim INIT(= FALSE); /* did set $VIM ourselves */
@@ -927,6 +929,10 @@ EXTERN int autocmd_bufnr INIT(= 0); /* fnum for <abuf> on cmdline */
EXTERN char_u *autocmd_match INIT(= NULL); /* name for <amatch> on cmdline */
#endif
+EXTERN linenr_T write_no_eol_lnum INIT(= 0); /* non-zero lnum when last line
+ of next binary write should
+ not have an end-of-line */
+
#ifdef FEAT_WINDOWS
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */
@@ -957,6 +963,7 @@ EXTERN int redir_off INIT(= FALSE); /* no redirection for a moment */
EXTERN FILE *redir_fd INIT(= NULL); /* message redirection file */
#ifdef FEAT_EVAL
EXTERN int redir_reg INIT(= 0); /* message redirection register */
+EXTERN int redir_vname INIT(= 0); /* message redirection variable */
#endif
#ifdef FEAT_LANGMAP
@@ -1399,14 +1406,12 @@ EXTERN char_u e_invexprmsg[] INIT(=N_("E449: Invalid expression received"));
EXTERN char_u e_guarded[] INIT(=N_("E463: Region is guarded, cannot modify"));
EXTERN char_u e_nbreadonly[] INIT(=N_("E744: NetBeans does not allow changes in read-only files"));
#endif
-#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
EXTERN char_u e_intern2[] INIT(=N_("E685: Internal error: %s"));
-#endif
#if defined(HAVE_SETJMP_H) || defined(HAVE_TRY_EXCEPT)
EXTERN char_u e_complex[] INIT(=N_("E361: Crash intercepted; regexp too complex?"));
#endif
EXTERN char_u e_outofstack[] INIT(=N_("E363: pattern caused out-of-stack error"));
-
+EXTERN char_u e_emptybuf[] INIT(=N_("E749: empty buffer"));
#ifdef MACOS_X_UNIX
EXTERN short disallow_gui INIT(= FALSE);
diff --git a/src/mbyte.c b/src/mbyte.c
index f3092556d..89b53c2e5 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -2871,12 +2871,16 @@ enc_locale()
# ifdef HAVE_NL_LANGINFO_CODESET
if ((s = nl_langinfo(CODESET)) == NULL || *s == NUL)
# endif
-# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+# ifdef MACOS
+ s = "utf-8";
+# else
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
if ((s = setlocale(LC_CTYPE, NULL)) == NULL || *s == NUL)
-# endif
+# endif
if ((s = getenv("LC_ALL")) == NULL || *s == NUL)
if ((s = getenv("LC_CTYPE")) == NULL || *s == NUL)
s = getenv("LANG");
+# endif
if (s == NULL || *s == NUL)
return FAIL;
@@ -5578,6 +5582,7 @@ convert_setup(vcp, from, to)
# endif
if (vcp->vc_type == CONV_NONE)
return FAIL;
+
return OK;
}
diff --git a/src/message.c b/src/message.c
index 6f2e7c155..f6494847f 100644
--- a/src/message.c
+++ b/src/message.c
@@ -518,6 +518,7 @@ emsg(s)
#endif
called_emsg = TRUE;
+ ex_exitval = 1;
/*
* If "emsg_severe" is TRUE: When an error exception is to be thrown,
@@ -533,7 +534,7 @@ emsg(s)
* If 'debug' is set: do error message anyway, but without side effects.
* If "emsg_skip" is set: never do error messages.
*/
- if ((emsg_off > 0 && *p_debug == NUL)
+ if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL)
#ifdef FEAT_EVAL
|| emsg_skip > 0
#endif
@@ -638,7 +639,7 @@ emsg2(s, a1)
emsg3(s, a1, a2)
char_u *s, *a1, *a2;
{
- if ((emsg_off > 0 && *p_debug == NUL)
+ if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL)
#ifdef FEAT_EVAL
|| emsg_skip > 0
#endif
@@ -667,7 +668,7 @@ emsgn(s, n)
char_u *s;
long n;
{
- if ((emsg_off > 0 && *p_debug == NUL)
+ if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL)
#ifdef FEAT_EVAL
|| emsg_skip > 0
#endif
@@ -677,6 +678,13 @@ emsgn(s, n)
return emsg(IObuff);
}
+ void
+emsg_invreg(name)
+ int name;
+{
+ EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
+}
+
/*
* Like msg(), but truncate to a single line if p_shm contains 't', or when
* "force" is TRUE. This truncates in another way as for normal messages.
@@ -1481,8 +1489,9 @@ str2specialbuf(sp, buf, len)
* print line for :print or :list command
*/
void
-msg_prt_line(s)
+msg_prt_line(s, list)
char_u *s;
+ int list;
{
int c;
int col = 0;
@@ -1497,8 +1506,11 @@ msg_prt_line(s)
char_u buf[MB_MAXBYTES + 1];
#endif
+ if (curwin->w_p_list)
+ list = TRUE;
+
/* find start of trailing whitespace */
- if (curwin->w_p_list && lcs_trail)
+ if (list && lcs_trail)
{
trail = s + STRLEN(s);
while (trail > s && vim_iswhite(trail[-1]))
@@ -1507,7 +1519,7 @@ msg_prt_line(s)
/* output a space for an empty line, otherwise the line will be
* overwritten */
- if (*s == NUL && !(curwin->w_p_list && lcs_eol != NUL))
+ if (*s == NUL && !(list && lcs_eol != NUL))
msg_putchar(' ');
for (;;)
@@ -1535,11 +1547,11 @@ msg_prt_line(s)
{
attr = 0;
c = *s++;
- if (c == TAB && (!curwin->w_p_list || lcs_tab1))
+ if (c == TAB && (!list || lcs_tab1))
{
/* tab amount depends on current column */
n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
- if (!curwin->w_p_list)
+ if (!list)
{
c = ' ';
c_extra = ' ';
@@ -1551,7 +1563,7 @@ msg_prt_line(s)
attr = hl_attr(HLF_8);
}
}
- else if (c == NUL && curwin->w_p_list && lcs_eol != NUL)
+ else if (c == NUL && list && lcs_eol != NUL)
{
p_extra = (char_u *)"";
c_extra = NUL;
@@ -2521,7 +2533,7 @@ redir_write(str, maxlen)
if ((redir_fd != NULL
#ifdef FEAT_EVAL
- || redir_reg
+ || redir_reg || redir_vname
#endif
) && !redir_off)
{
@@ -2533,6 +2545,8 @@ redir_write(str, maxlen)
#ifdef FEAT_EVAL
if (redir_reg)
write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
+ else if (redir_vname)
+ var_redir_str((char_u *)" ", -1);
else if (redir_fd)
#endif
fputs(" ", redir_fd);
@@ -2543,13 +2557,15 @@ redir_write(str, maxlen)
#ifdef FEAT_EVAL
if (redir_reg)
write_reg_contents(redir_reg, s, maxlen, TRUE);
+ if (redir_vname)
+ var_redir_str(s, maxlen);
#endif
/* Adjust the current column */
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
{
#ifdef FEAT_EVAL
- if (!redir_reg && redir_fd != NULL)
+ if (!redir_reg && !redir_vname && redir_fd != NULL)
#endif
putc(*s, redir_fd);
if (*s == '\r' || *s == '\n')
diff --git a/src/netbeans.c b/src/netbeans.c
index ed75470c5..3eeeb0703 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -114,14 +114,12 @@ BalloonEval *balloonEval = NULL;
#ifdef FEAT_GUI_MOTIF
static void netbeans_Xt_connect __ARGS((void *context));
-#else
-# ifdef FEAT_GUI_GTK
+#endif
+#ifdef FEAT_GUI_GTK
static void netbeans_gtk_connect __ARGS((void));
-# else
-# ifdef FEAT_GUI_W32
+#endif
+#ifdef FEAT_GUI_W32
static void netbeans_w32_connect __ARGS((void));
-# endif
-# endif
#endif
static int dosetvisible = FALSE;
@@ -2559,6 +2557,10 @@ netbeans_startup_done(void)
#else
# ifdef FEAT_GUI_GTK
netbeans_gtk_connect();
+# else
+# ifdef FEAT_GUI_W32
+ netbeans_w32_connect();
+# endif
# endif
#endif
diff --git a/src/normal.c b/src/normal.c
index f13b45eec..2ba3f74b7 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -232,7 +232,11 @@ static const struct nv_cmd
{Ctrl_N, nv_down, NV_STS, FALSE},
{Ctrl_O, nv_ctrlo, 0, 0},
{Ctrl_P, nv_up, NV_STS, FALSE},
+#ifdef FEAT_VISUAL
+ {Ctrl_Q, nv_visual, 0, FALSE},
+#else
{Ctrl_Q, nv_ignore, 0, 0},
+#endif
{Ctrl_R, nv_redo, 0, 0},
{Ctrl_S, nv_ignore, 0, 0},
{Ctrl_T, nv_tagpop, NV_NCW, 0},
@@ -6852,11 +6856,15 @@ nv_regname(cap)
* Handle "v", "V" and "CTRL-V" commands.
* Also for "gh", "gH" and "g^H" commands: Always start Select mode, cap->arg
* is TRUE.
+ * Handle CTRL-Q just like CTRL-V.
*/
static void
nv_visual(cap)
cmdarg_T *cap;
{
+ if (cap->cmdchar == Ctrl_Q)
+ cap->cmdchar = Ctrl_V;
+
/* 'v', 'V' and CTRL-V can be used while an operator is pending to make it
* characterwise, linewise, or blockwise. */
if (cap->oap->op_type != OP_NOP)
diff --git a/src/os_unix.c b/src/os_unix.c
index d89636d3a..945092f15 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -165,6 +165,7 @@ static int sig_alarm_called;
#endif
static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
+static void catch_int_signal __ARGS((void));
static void set_signals __ARGS((void));
static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
#ifndef __EMX__
@@ -175,6 +176,14 @@ static int have_dollars __ARGS((int, char_u **));
#ifndef NO_EXPANDPATH
static int pstrcmp __ARGS((const void *, const void *));
static int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags));
+# if defined(MACOS_X) && defined(FEAT_MBYTE)
+extern char_u *mac_precompose_path __ARGS((char_u *decompPath, size_t decompLen, size_t *precompLen));
+# endif
+#endif
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+extern void mac_conv_init __ARGS((void));
+extern void mac_conv_cleanup __ARGS((void));
#endif
#ifndef __EMX__
@@ -1083,6 +1092,10 @@ mch_init()
out_flush();
set_signals();
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+ mac_conv_init();
+#endif
}
static void
@@ -1113,11 +1126,8 @@ set_signals()
signal(SIGPIPE, SIG_IGN);
#endif
- /*
- * We want to catch CTRL-C (only works while in Cooked mode).
- */
#ifdef SIGINT
- signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+ catch_int_signal();
#endif
/*
@@ -1149,6 +1159,17 @@ set_signals()
#endif
}
+#if defined(SIGINT) || defined(PROTO)
+/*
+ * Catch CTRL-C (only works while in Cooked mode).
+ */
+ static void
+catch_int_signal()
+{
+ signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+}
+#endif
+
void
reset_signals()
{
@@ -2694,6 +2715,8 @@ static void exit_scroll __ARGS((void));
static void
exit_scroll()
{
+ if (silent_mode)
+ return;
if (newline_on_exit || msg_didout)
{
if (msg_use_printf())
@@ -2764,6 +2787,11 @@ mch_exit(r)
if (gui.in_use)
gui_exit(r);
#endif
+
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+ mac_conv_cleanup();
+#endif
+
#ifdef __QNX__
/* A core dump won't be created if the signal handler
* doesn't return, so we can't call exit() */
@@ -3282,6 +3310,27 @@ mch_new_shellsize()
/* Nothing to do. */
}
+#ifndef USE_SYSTEM
+static void append_ga_line __ARGS((garray_T *gap));
+
+/*
+ * Append the text in "gap" below the cursor line and clear "gap".
+ */
+ static void
+append_ga_line(gap)
+ garray_T *gap;
+{
+ /* Remove trailing CR. */
+ if (gap->ga_len > 0
+ && !curbuf->b_p_bin
+ && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
+ --gap->ga_len;
+ ga_append(gap, NUL);
+ ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
+ gap->ga_len = 0;
+}
+#endif
+
int
mch_call_shell(cmd, options)
char_u *cmd;
@@ -3398,11 +3447,12 @@ mch_call_shell(cmd, options)
#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
-#define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
- 127, some shell use that already */
+# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
+ 127, some shells use that already */
char_u *newcmd = NULL;
pid_t pid;
+ pid_t wpid = 0;
pid_t wait_pid = 0;
# ifdef HAVE_UNION_WAIT
union wait status;
@@ -3415,19 +3465,19 @@ mch_call_shell(cmd, options)
int i;
char_u *p;
int inquote;
-# ifdef FEAT_GUI
int pty_master_fd = -1; /* for pty's */
+# ifdef FEAT_GUI
int pty_slave_fd = -1;
char *tty_name;
+# endif
int fd_toshell[2]; /* for pipes */
int fd_fromshell[2];
int pipe_error = FALSE;
-# ifdef HAVE_SETENV
+# ifdef HAVE_SETENV
char envbuf[50];
-# else
+# else
static char envbuf_Rows[20];
static char envbuf_Columns[20];
-# endif
# endif
int did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
@@ -3480,19 +3530,24 @@ mch_call_shell(cmd, options)
}
argv[argc] = NULL;
-# ifdef FEAT_GUI
/*
- * For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
- * executed command into the Vim window. Or use a pipe.
+ * For the GUI, when writing the output into the buffer and when reading
+ * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
+ * of the executed command into the Vim window. Or use a pipe.
*/
- if (gui.in_use && show_shell_mess)
+ if ((options & (SHELL_READ|SHELL_WRITE))
+# ifdef FEAT_GUI
+ || (gui.in_use && show_shell_mess)
+# endif
+ )
{
+# ifdef FEAT_GUI
/*
* Try to open a master pty.
* If this works, open the slave pty.
* If the slave can't be opened, close the master pty.
*/
- if (p_guipty)
+ if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
{
pty_master_fd = OpenPTY(&tty_name); /* open pty */
if (pty_master_fd >= 0 && ((pty_slave_fd =
@@ -3506,6 +3561,7 @@ mch_call_shell(cmd, options)
* If not opening a pty or it didn't work, try using pipes.
*/
if (pty_master_fd < 0)
+# endif
{
pipe_error = (pipe(fd_toshell) < 0);
if (!pipe_error) /* pipe create OK */
@@ -3526,8 +3582,6 @@ mch_call_shell(cmd, options)
}
if (!pipe_error) /* pty or pipe opened or not used */
-# endif
-
{
# ifdef __BEOS__
beos_cleanup_read_thread();
@@ -3535,15 +3589,20 @@ mch_call_shell(cmd, options)
if ((pid = fork()) == -1) /* maybe we should use vfork() */
{
MSG_PUTS(_("\nCannot fork\n"));
+ if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
- if (gui.in_use && show_shell_mess)
+ || (gui.in_use && show_shell_mess)
+# endif
+ )
{
+# ifdef FEAT_GUI
if (pty_master_fd >= 0) /* close the pseudo tty */
{
close(pty_master_fd);
close(pty_slave_fd);
}
else /* close the pipes */
+# endif
{
close(fd_toshell[0]);
close(fd_toshell[1]);
@@ -3551,7 +3610,6 @@ mch_call_shell(cmd, options)
close(fd_fromshell[1]);
}
}
-# endif
}
else if (pid == 0) /* child */
{
@@ -3593,13 +3651,17 @@ mch_call_shell(cmd, options)
close(fd);
}
}
+ else if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
- else if (gui.in_use)
+ || gui.in_use
+# endif
+ )
{
-# ifdef HAVE_SETSID
+# ifdef HAVE_SETSID
(void)setsid();
-# endif
+# endif
+# ifdef FEAT_GUI
/* push stream discipline modules */
if (options & SHELL_COOKED)
SetupSlavePTY(pty_slave_fd);
@@ -3608,8 +3670,9 @@ mch_call_shell(cmd, options)
* unless run by root) */
ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
# endif
+# endif
/* Simulate to have a dumb terminal (for now) */
-# ifdef HAVE_SETENV
+# ifdef HAVE_SETENV
setenv("TERM", "dumb", 1);
sprintf((char *)envbuf, "%ld", Rows);
setenv("ROWS", (char *)envbuf, 1);
@@ -3617,7 +3680,7 @@ mch_call_shell(cmd, options)
setenv("LINES", (char *)envbuf, 1);
sprintf((char *)envbuf, "%ld", Columns);
setenv("COLUMNS", (char *)envbuf, 1);
-# else
+# else
/*
* Putenv does not copy the string, it has to remain valid.
* Use a static array to avoid loosing allocated memory.
@@ -3629,8 +3692,9 @@ mch_call_shell(cmd, options)
putenv(envbuf_Rows);
sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
putenv(envbuf_Columns);
-# endif
+# endif
+# ifdef FEAT_GUI
if (pty_master_fd >= 0)
{
close(pty_master_fd); /* close master side of pty */
@@ -3646,6 +3710,7 @@ mch_call_shell(cmd, options)
close(pty_slave_fd); /* has been dupped, close it now */
}
else
+# endif
{
/* set up stdin for the child */
close(fd_toshell[1]);
@@ -3664,7 +3729,7 @@ mch_call_shell(cmd, options)
dup(1);
}
}
-# endif /* FEAT_GUI */
+
/*
* There is no type cast for the argv, because the type may be
* different on different machines. This may cause a warning
@@ -3679,21 +3744,27 @@ mch_call_shell(cmd, options)
{
/*
* While child is running, ignore terminating signals.
+ * Do catch CTRL-C, so that "got_int" is set.
*/
catch_signals(SIG_IGN, SIG_ERR);
-
-# ifdef FEAT_GUI
+ catch_int_signal();
/*
* For the GUI we redirect stdin, stdout and stderr to our window.
+ * This is also used to pipe stdin/stdout to/from the external
+ * command.
*/
- if (gui.in_use && show_shell_mess)
+ if ((options & (SHELL_READ|SHELL_WRITE))
+# ifdef FEAT_GUI
+ || (gui.in_use && show_shell_mess)
+# endif
+ )
{
-# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
+# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
char_u buffer[BUFLEN + 1];
-# ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
int buffer_off = 0; /* valid bytes in buffer[] */
-# endif
+# endif
char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
int ta_len = 0; /* valid bytes in ta_buf[] */
int len;
@@ -3702,7 +3773,10 @@ mch_call_shell(cmd, options)
int c;
int toshell_fd;
int fromshell_fd;
+ garray_T ga;
+ int noread_cnt;
+# ifdef FEAT_GUI
if (pty_master_fd >= 0)
{
close(pty_slave_fd); /* close slave side of pty */
@@ -3710,6 +3784,7 @@ mch_call_shell(cmd, options)
toshell_fd = dup(pty_master_fd);
}
else
+# endif
{
close(fd_toshell[0]);
close(fd_fromshell[1]);
@@ -3738,6 +3813,76 @@ mch_call_shell(cmd, options)
old_State = State;
State = EXTERNCMD; /* don't redraw at window resize */
+ if (options & SHELL_WRITE && toshell_fd >= 0)
+ {
+ /* Fork a process that will write the lines to the
+ * external program. */
+ if ((wpid = fork()) == -1)
+ {
+ MSG_PUTS(_("\nCannot fork\n"));
+ }
+ else if (wpid == 0)
+ {
+ linenr_T lnum = curbuf->b_op_start.lnum;
+ int written = 0;
+ char_u *p = ml_get(lnum);
+ char_u *s;
+ size_t l;
+
+ /* child */
+ for (;;)
+ {
+ l = STRLEN(p + written);
+ if (l == 0)
+ len = 0;
+ else if (p[written] == NL)
+ /* NL -> NUL translation */
+ len = write(toshell_fd, "", (size_t)1);
+ else
+ {
+ s = vim_strchr(p + written, NL);
+ len = write(toshell_fd, (char *)p + written,
+ s == NULL ? l : s - (p + written));
+ }
+ if (len == l)
+ {
+ /* Finished a line, add a NL, unless this line
+ * should not have one. */
+ if (lnum != curbuf->b_op_end.lnum
+ || !curbuf->b_p_bin
+ || (lnum != write_no_eol_lnum
+ && (lnum !=
+ curbuf->b_ml.ml_line_count
+ || curbuf->b_p_eol)))
+ write(toshell_fd, "\n", (size_t)1);
+ ++lnum;
+ if (lnum > curbuf->b_op_end.lnum)
+ {
+ /* finished all the lines, close pipe */
+ close(toshell_fd);
+ toshell_fd = -1;
+ break;
+ }
+ p = ml_get(lnum);
+ written = 0;
+ }
+ else if (len > 0)
+ written += len;
+ }
+ _exit(0);
+ }
+ else
+ {
+ close(toshell_fd);
+ toshell_fd = -1;
+ }
+ }
+
+ if (options & SHELL_READ)
+ ga_init2(&ga, 1, BUFLEN);
+
+ noread_cnt = 0;
+
for (;;)
{
/*
@@ -3745,12 +3890,15 @@ mch_call_shell(cmd, options)
* if there are any. Don't do this if we are expanding
* wild cards (would eat typeahead). Don't get extra
* characters when we already have one.
+ * Don't read characters unless we didn't get output for a
+ * while, avoids that ":r !ls" eats typeahead.
*/
len = 0;
if (!(options & SHELL_EXPAND)
&& (ta_len > 0
- || (len = ui_inchar(ta_buf, BUFLEN, 10L,
- 0)) > 0))
+ || (noread_cnt > 4
+ && (len = ui_inchar(ta_buf,
+ BUFLEN, 10L, 0)) > 0)))
{
/*
* For pipes:
@@ -3759,19 +3907,23 @@ mch_call_shell(cmd, options)
*/
if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
{
-# ifdef SIGINT
+# ifdef SIGINT
/*
* Send SIGINT to the child's group or all
* processes in our group.
*/
if (ta_buf[ta_len] == Ctrl_C
|| ta_buf[ta_len] == intr_char)
-# ifdef HAVE_SETSID
+ {
+# ifdef HAVE_SETSID
kill(-pid, SIGINT);
-# else
+# else
kill(0, SIGINT);
-# endif
# endif
+ if (wpid > 0)
+ kill(wpid, SIGINT);
+ }
+# endif
if (pty_master_fd < 0 && toshell_fd >= 0
&& ta_buf[ta_len] == Ctrl_D)
{
@@ -3799,10 +3951,10 @@ mch_call_shell(cmd, options)
}
else if (ta_buf[i] == '\r')
ta_buf[i] = '\n';
-# ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
if (has_mbyte)
i += (*mb_ptr2len_check)(ta_buf + i) - 1;
-# endif
+# endif
}
/*
@@ -3815,7 +3967,7 @@ mch_call_shell(cmd, options)
{
if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
msg_putchar(ta_buf[i]);
-# ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
else if (has_mbyte)
{
int l = (*mb_ptr2len_check)(ta_buf + i);
@@ -3823,7 +3975,7 @@ mch_call_shell(cmd, options)
msg_outtrans_len(ta_buf + i, l);
i += l - 1;
}
-# endif
+# endif
else
msg_outtrans_len(ta_buf + i, 1);
}
@@ -3837,18 +3989,37 @@ mch_call_shell(cmd, options)
* Write the characters to the child, unless EOF has
* been typed for pipes. Write one character at a
* time, to avoid loosing too much typeahead.
+ * When writing buffer lines, drop the typed
+ * characters (only check for CTRL-C).
*/
- if (toshell_fd >= 0)
+ if (options & SHELL_WRITE)
+ ta_len = 0;
+ else if (toshell_fd >= 0)
{
len = write(toshell_fd, (char *)ta_buf, (size_t)1);
if (len > 0)
{
ta_len -= len;
mch_memmove(ta_buf, ta_buf + len, ta_len);
+ noread_cnt = 0;
}
}
}
+ if (got_int)
+ {
+ /* CTRL-C sends a signal to the child, we ignore it
+ * ourselves */
+# ifdef HAVE_SETSID
+ kill(-pid, SIGINT);
+# else
+ kill(0, SIGINT);
+# endif
+ if (wpid > 0)
+ kill(wpid, SIGINT);
+ got_int = FALSE;
+ }
+
/*
* Check if the child has any characters to be printed.
* Read them and write them to our window. Repeat this as
@@ -3858,24 +4029,42 @@ mch_call_shell(cmd, options)
* TODO: This should handle escape sequences, compatible
* to some terminal (vt52?).
*/
+ ++noread_cnt;
while (RealWaitForChar(fromshell_fd, 10L, NULL))
{
len = read(fromshell_fd, (char *)buffer
-# ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
+ buffer_off, (size_t)(BUFLEN - buffer_off)
-# else
+# else
, (size_t)BUFLEN
-# endif
+# endif
);
if (len <= 0) /* end of file or error */
goto finished;
-# ifdef FEAT_MBYTE
- len += buffer_off;
- buffer[len] = NUL;
- if (has_mbyte)
+
+ noread_cnt = 0;
+ if (options & SHELL_READ)
+ {
+ /* Do NUL -> NL translation, append NL separated
+ * lines to the current buffer. */
+ for (i = 0; i < len; ++i)
+ {
+ if (buffer[i] == NL)
+ append_ga_line(&ga);
+ else if (buffer[i] == NUL)
+ ga_append(&ga, NL);
+ else
+ ga_append(&ga, buffer[i]);
+ }
+ }
+# ifdef FEAT_MBYTE
+ else if (has_mbyte)
{
int l;
+ len += buffer_off;
+ buffer[len] = NUL;
+
/* Check if the last character in buffer[] is
* incomplete, keep these bytes for the next
* round. */
@@ -3913,8 +4102,8 @@ mch_call_shell(cmd, options)
}
buffer_off = 0;
}
+# endif /* FEAT_MBYTE */
else
-# endif /* FEAT_MBYTE */
{
buffer[len] = NUL;
msg_puts(buffer);
@@ -3931,11 +4120,11 @@ mch_call_shell(cmd, options)
* Check if the child still exists, before checking for
* typed characters (otherwise we would loose typeahead).
*/
-# ifdef __NeXT__
+# ifdef __NeXT__
wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
-# else
+# else
wait_pid = waitpid(pid, &status, WNOHANG);
-# endif
+# endif
if ((wait_pid == (pid_t)-1 && errno == ECHILD)
|| (wait_pid == pid && WIFEXITED(status)))
{
@@ -3946,20 +4135,29 @@ mch_call_shell(cmd, options)
}
finished:
p_more = p_more_save;
+ if (options & SHELL_READ)
+ {
+ if (ga.ga_len > 0)
+ {
+ append_ga_line(&ga);
+ /* remember that the NL was missing */
+ write_no_eol_lnum = curwin->w_cursor.lnum;
+ }
+ else
+ write_no_eol_lnum = 0;
+ ga_clear(&ga);
+ }
-# ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
/*
* Give all typeahead that wasn't used back to ui_inchar().
*/
if (ta_len)
ui_inchar_undo(ta_buf, ta_len);
-# endif
State = old_State;
if (toshell_fd >= 0)
close(toshell_fd);
close(fromshell_fd);
}
-# endif /* FEAT_GUI */
/*
* Wait until our child has exited.
@@ -3970,7 +4168,7 @@ finished:
*/
while (wait_pid != pid)
{
-#ifdef _THREAD_SAFE
+# ifdef _THREAD_SAFE
/* Ugly hack: when compiled with Python threads are probably
* used, in which case wait() sometimes hangs for no obvious
* reason. Use waitpid() instead and loop (like the GUI). */
@@ -3985,9 +4183,9 @@ finished:
mch_delay(10L, TRUE);
continue;
}
-#else
+# else
wait_pid = wait(&status);
-#endif
+# endif
if (wait_pid <= 0
# ifdef ECHILD
&& errno == ECHILD
@@ -3996,6 +4194,11 @@ finished:
break;
}
+ /* Make sure the child that writes to the external program is
+ * dead. */
+ if (wpid > 0)
+ kill(wpid, SIGKILL);
+
/*
* Set to raw mode right now, otherwise a CTRL-C after
* catch_signals() will kill Vim.
@@ -4656,7 +4859,19 @@ unix_expandpath(gap, path, wildoff, flags)
if (*path_end != NUL)
backslash_halve(buf + len + 1);
if (mch_getperm(buf) >= 0) /* add existing file */
+ {
+#if defined(MACOS_X) && defined(FEAT_MBYTE)
+ size_t precomp_len = STRLEN(buf)+1;
+ char_u *precomp_buf =
+ mac_precompose_path(buf, precomp_len, &precomp_len);
+ if (precomp_buf)
+ {
+ mch_memmove(buf, precomp_buf, precomp_len);
+ vim_free(precomp_buf);
+ }
+#endif
addfile(gap, buf, flags);
+ }
}
}
}
diff --git a/src/po/Make_ming.mak b/src/po/Make_ming.mak
index 810efb036..db42720b2 100644
--- a/src/po/Make_ming.mak
+++ b/src/po/Make_ming.mak
@@ -10,9 +10,9 @@
# language (xx) and add it to the next three lines.
#
-LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+LANGUAGES = af ca cs de en_GB es fr ga it ja ko no pl ru sk sv uk zh_TW \
zh_TW.UTF-8 zh_CN zh_CN.UTF-8
-MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo ga.mo it.mo ja.mo \
ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
diff --git a/src/po/Makefile b/src/po/Makefile
index c71df8dad..dc94efd7a 100644
--- a/src/po/Makefile
+++ b/src/po/Makefile
@@ -4,9 +4,9 @@
# Note: ja.sjis, *.cp1250 and zh_CN.cp936 are only for MS-Windows, they are
# not installed on Unix
-LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+LANGUAGES = af ca cs de en_GB es fr ga it ja ko no pl ru sk sv uk zh_TW \
zh_TW.UTF-8 zh_CN zh_CN.UTF-8
-MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo ga.mo it.mo ja.mo \
ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index 0a8b5d368..9a0fd2b3c 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -33,6 +33,7 @@ void alist_slash_adjust __ARGS((void));
void ex_splitview __ARGS((exarg_T *eap));
void do_exedit __ARGS((exarg_T *eap, win_T *old_curwin));
void do_sleep __ARGS((long msec));
+int vim_mkdir_emsg __ARGS((char_u *name, int prot));
FILE *open_exfile __ARGS((char_u *fname, int forceit, char *mode));
void update_topline_cursor __ARGS((void));
void exec_normal_cmd __ARGS((char_u *cmd, int remap, int silent));
diff --git a/src/proto/gui_mac.pro b/src/proto/gui_mac.pro
index b5a4638d1..9a296fd19 100644
--- a/src/proto/gui_mac.pro
+++ b/src/proto/gui_mac.pro
@@ -39,6 +39,7 @@ void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
int gui_mch_adjust_charsize __ARGS((void));
int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+char_u *gui_mch_get_fontname __ARGS((GuiFont font, char_u *name));
GuiFont gui_mac_find_font __ARGS((char_u *font_name));
void gui_mch_set_font __ARGS((GuiFont font));
int gui_mch_same_font __ARGS((GuiFont f1, GuiFont f2));
diff --git a/src/proto/main.pro b/src/proto/main.pro
index bd75174ef..2ecce7955 100644
--- a/src/proto/main.pro
+++ b/src/proto/main.pro
@@ -1,5 +1,5 @@
/* main.c */
-void main_loop __ARGS((int cmdwin));
+void main_loop __ARGS((int cmdwin, int noexmode));
void getout_preserve_modified __ARGS((int exitval));
void getout __ARGS((int exitval));
int process_env __ARGS((char_u *env, int is_viminit));
diff --git a/src/proto/message.pro b/src/proto/message.pro
index 9957b75d8..647c8d107 100644
--- a/src/proto/message.pro
+++ b/src/proto/message.pro
@@ -9,6 +9,7 @@ int emsg __ARGS((char_u *s));
int emsg2 __ARGS((char_u *s, char_u *a1));
int emsg3 __ARGS((char_u *s, char_u *a1, char_u *a2));
int emsgn __ARGS((char_u *s, long n));
+void emsg_invreg __ARGS((int name));
char_u *msg_trunc_attr __ARGS((char_u *s, int force, int attr));
char_u *msg_may_trunc __ARGS((int force, char_u *s));
void ex_messages __ARGS((exarg_T *eap));
@@ -31,7 +32,7 @@ void msg_make __ARGS((char_u *arg));
int msg_outtrans_special __ARGS((char_u *strstart, int from));
char_u *str2special __ARGS((char_u **sp, int from));
void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len));
-void msg_prt_line __ARGS((char_u *s));
+void msg_prt_line __ARGS((char_u *s, int list));
void msg_puts __ARGS((char_u *s));
void msg_puts_title __ARGS((char_u *s));
void msg_puts_long __ARGS((char_u *longstr));
diff --git a/src/quickfix.c b/src/quickfix.c
index a8544b34e..079e6c981 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1456,7 +1456,7 @@ qf_list(eap)
qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
? skipwhite(qfp->qf_text) : qfp->qf_text,
IObuff, IOSIZE);
- msg_prt_line(IObuff);
+ msg_prt_line(IObuff, FALSE);
out_flush(); /* show one line at a time */
need_return = TRUE;
last_printed = i;
@@ -2279,7 +2279,6 @@ ex_vimgrep(eap)
exarg_T *eap;
{
regmmatch_T regmatch;
- char_u *save_cpo;
int fcount;
char_u **fnames;
char_u *s;
@@ -2317,10 +2316,6 @@ ex_vimgrep(eap)
}
#endif
- /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
- save_cpo = p_cpo;
- p_cpo = empty_option;
-
/* Get the search pattern: either white-separated or enclosed in // */
regmatch.regprog = NULL;
p = skip_vimgrep_pat(eap->arg, &s);
@@ -2545,12 +2540,6 @@ jumpend:
theend:
vim_free(regmatch.regprog);
-
- /* Only resture 'cpo' when it wasn't set in the mean time. */
- if (p_cpo == empty_option)
- p_cpo = save_cpo;
- else
- free_string_option(save_cpo);
}
/*
diff --git a/src/regexp.c b/src/regexp.c
index a9915a3b1..c4f892078 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -74,11 +74,12 @@
* (Here we have one of the subtle syntax dependencies: an individual BRANCH
* (as opposed to a collection of them) is never concatenated with anything
* because of operator precedence). The "next" pointer of a BRACES_COMPLEX
- * node points to the node after the stuff to be repeated. The operand of some
- * types of node is a literal string; for others, it is a node leading into a
- * sub-FSM. In particular, the operand of a BRANCH node is the first node of
- * the branch. (NB this is *not* a tree structure: the tail of the branch
- * connects to the thing following the set of BRANCHes.)
+ * node points to the node after the stuff to be repeated.
+ * The operand of some types of node is a literal string; for others, it is a
+ * node leading into a sub-FSM. In particular, the operand of a BRANCH node
+ * is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects to the
+ * thing following the set of BRANCHes.)
*
* pattern is coded like:
*
@@ -97,6 +98,14 @@
* +---------------------------------------------+
*
*
+ * +----------------------+
+ * V |
+ * <aa>\+ BRANCH <aa> --> BRANCH --> BACK BRANCH --> NOTHING --> END
+ * | | ^ ^
+ * | +----------+ |
+ * +-------------------------------------------------+
+ *
+ *
* +-------------------------+
* V |
* <aa>\{} BRANCH BRACE_LIMITS --> BRACE_COMPLEX <aa> --> BACK END
@@ -386,7 +395,10 @@ static char_u REGEXP_INRANGE[] = "]^-n\\";
static char_u REGEXP_ABBR[] = "nrtebdoxuU";
static int backslash_trans __ARGS((int c));
-static int skip_class_name __ARGS((char_u **pp));
+static int get_char_class __ARGS((char_u **pp));
+static int get_equi_class __ARGS((char_u **pp));
+static void reg_equi_class __ARGS((int c));
+static int get_coll_element __ARGS((char_u **pp));
static char_u *skip_anyof __ARGS((char_u *p));
static void init_class_tab __ARGS((void));
@@ -408,12 +420,12 @@ backslash_trans(c)
}
/*
- * Check for a character class name. "pp" points to the '['.
+ * Check for a character class name "[:name:]". "pp" points to the '['.
* Returns one of the CLASS_ items. CLASS_NONE means that no item was
* recognized. Otherwise "pp" is advanced to after the item.
*/
static int
-skip_class_name(pp)
+get_char_class(pp)
char_u **pp;
{
static const char *(class_names[]) =
@@ -467,55 +479,6 @@ skip_class_name(pp)
}
/*
- * Skip over a "[]" range.
- * "p" must point to the character after the '['.
- * The returned pointer is on the matching ']', or the terminating NUL.
- */
- static char_u *
-skip_anyof(p)
- char_u *p;
-{
- int cpo_lit; /* 'cpoptions' contains 'l' flag */
-#ifdef FEAT_MBYTE
- int l;
-#endif
-
- cpo_lit = (!reg_syn && vim_strchr(p_cpo, CPO_LITERAL) != NULL);
-
- if (*p == '^') /* Complement of range. */
- ++p;
- if (*p == ']' || *p == '-')
- ++p;
- while (*p != NUL && *p != ']')
- {
-#ifdef FEAT_MBYTE
- if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
- p += l;
- else
-#endif
- if (*p == '-')
- {
- ++p;
- if (*p != ']' && *p != NUL)
- mb_ptr_adv(p);
- }
- else if (*p == '\\'
- && (vim_strchr(REGEXP_INRANGE, p[1]) != NULL
- || (!cpo_lit && vim_strchr(REGEXP_ABBR, p[1]) != NULL)))
- p += 2;
- else if (*p == '[')
- {
- if (skip_class_name(&p) == CLASS_NONE)
- ++p; /* It was not a class name */
- }
- else
- ++p;
- }
-
- return p;
-}
-
-/*
* Specific version of character class functions.
* Using a table to keep this fast.
*/
@@ -695,6 +658,8 @@ static char_u *regnext __ARGS((char_u *));
static void regc __ARGS((int b));
#ifdef FEAT_MBYTE
static void regmbc __ARGS((int c));
+#else
+# define regmbc(c) regc(c)
#endif
static void reginsert __ARGS((int, char_u *));
static void reginsert_limits __ARGS((int, long, long, char_u *));
@@ -725,6 +690,210 @@ re_lookbehind(prog)
}
/*
+ * Check for an equivalence class name "[=a=]". "pp" points to the '['.
+ * Returns a character representing the class. Zero means that no item was
+ * recognized. Otherwise "pp" is advanced to after the item.
+ */
+ static int
+get_equi_class(pp)
+ char_u **pp;
+{
+ int c;
+ int l = 1;
+ char_u *p = *pp;
+
+ if (p[1] == '=')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ l = mb_ptr2len_check(p + 2);
+#endif
+ if (p[l + 2] == '=' && p[l + 3] == ']')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = mb_ptr2char(p + 2);
+ else
+#endif
+ c = p[2];
+ *pp += l + 4;
+ return c;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Produce the bytes for equivalence class "c".
+ * Currently only handles latin1, latin9 and utf-8.
+ */
+ static void
+reg_equi_class(c)
+ int c;
+{
+#ifdef FEAT_MBYTE
+ if (enc_utf8 || STRCMP(p_enc, "latin1") == 0
+ || STRCMP(p_enc, "latin9") == 0)
+#endif
+ {
+ switch (c)
+ {
+ case 'A': case 'À': case 'Á': case 'Â':
+ case 'Ã': case 'Ä': case 'Å':
+ regmbc('A'); regmbc('À'); regmbc('Á'); regmbc('Â');
+ regmbc('Ã'); regmbc('Ä'); regmbc('Å');
+ return;
+ case 'C': case 'Ç':
+ regmbc('C'); regmbc('Ç');
+ return;
+ case 'E': case 'È': case 'É': case 'Ê': case 'Ë':
+ regmbc('E'); regmbc('È'); regmbc('É'); regmbc('Ê');
+ regmbc('Ë');
+ return;
+ case 'I': case 'Ì': case 'Í': case 'Î': case 'Ï':
+ regmbc('I'); regmbc('Ì'); regmbc('Í'); regmbc('Î');
+ regmbc('Ï');
+ return;
+ case 'N': case 'Ñ':
+ regmbc('N'); regmbc('Ñ');
+ return;
+ case 'O': case 'Ò': case 'Ó': case 'Ô': case 'Õ': case 'Ö':
+ regmbc('O'); regmbc('Ò'); regmbc('Ó'); regmbc('Ô');
+ regmbc('Õ'); regmbc('Ö');
+ return;
+ case 'U': case 'Ù': case 'Ú': case 'Û': case 'Ü':
+ regmbc('U'); regmbc('Ù'); regmbc('Ú'); regmbc('Û');
+ regmbc('Ü');
+ return;
+ case 'Y': case 'Ý':
+ regmbc('Y'); regmbc('Ý');
+ return;
+ case 'a': case 'à': case 'á': case 'â':
+ case 'ã': case 'ä': case 'å':
+ regmbc('a'); regmbc('à'); regmbc('á'); regmbc('â');
+ regmbc('ã'); regmbc('ä'); regmbc('å');
+ return;
+ case 'c': case 'ç':
+ regmbc('c'); regmbc('ç');
+ return;
+ case 'e': case 'è': case 'é': case 'ê': case 'ë':
+ regmbc('e'); regmbc('è'); regmbc('é'); regmbc('ê');
+ regmbc('ë');
+ return;
+ case 'i': case 'ì': case 'í': case 'î': case 'ï':
+ regmbc('i'); regmbc('ì'); regmbc('í'); regmbc('î');
+ regmbc('ï');
+ return;
+ case 'n': case 'ñ':
+ regmbc('n'); regmbc('ñ');
+ return;
+ case 'o': case 'ò': case 'ó': case 'ô': case 'õ': case 'ö':
+ regmbc('o'); regmbc('ò'); regmbc('ó'); regmbc('ô');
+ regmbc('õ'); regmbc('ö');
+ return;
+ case 'u': case 'ù': case 'ú': case 'û': case 'ü':
+ regmbc('u'); regmbc('ù'); regmbc('ú'); regmbc('û');
+ regmbc('ü');
+ return;
+ case 'y': case 'ý': case 'ÿ':
+ regmbc('y'); regmbc('ý'); regmbc('ÿ');
+ return;
+ }
+ }
+ regmbc(c);
+}
+
+/*
+ * Check for a collating element "[.a.]". "pp" points to the '['.
+ * Returns a character. Zero means that no item was recognized. Otherwise
+ * "pp" is advanced to after the item.
+ * Currently only single characters are recognized!
+ */
+ static int
+get_coll_element(pp)
+ char_u **pp;
+{
+ int c;
+ int l = 1;
+ char_u *p = *pp;
+
+ if (p[1] == '.')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ l = mb_ptr2len_check(p + 2);
+#endif
+ if (p[l + 2] == '.' && p[l + 3] == ']')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = mb_ptr2char(p + 2);
+ else
+#endif
+ c = p[2];
+ *pp += l + 4;
+ return c;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Skip over a "[]" range.
+ * "p" must point to the character after the '['.
+ * The returned pointer is on the matching ']', or the terminating NUL.
+ */
+ static char_u *
+skip_anyof(p)
+ char_u *p;
+{
+ int cpo_lit; /* 'cpoptions' contains 'l' flag */
+ int cpo_bsl; /* 'cpoptions' contains '\' flag */
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ cpo_lit = (!reg_syn && vim_strchr(p_cpo, CPO_LITERAL) != NULL);
+ cpo_bsl = (!reg_syn && vim_strchr(p_cpo, CPO_BACKSL) != NULL);
+
+ if (*p == '^') /* Complement of range. */
+ ++p;
+ if (*p == ']' || *p == '-')
+ ++p;
+ while (*p != NUL && *p != ']')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ p += l;
+ else
+#endif
+ if (*p == '-')
+ {
+ ++p;
+ if (*p != ']' && *p != NUL)
+ mb_ptr_adv(p);
+ }
+ else if (*p == '\\'
+ && !cpo_bsl
+ && (vim_strchr(REGEXP_INRANGE, p[1]) != NULL
+ || (!cpo_lit && vim_strchr(REGEXP_ABBR, p[1]) != NULL)))
+ p += 2;
+ else if (*p == '[')
+ {
+ if (get_char_class(&p) == CLASS_NONE
+ && get_equi_class(&p) == 0
+ && get_coll_element(&p) == 0)
+ ++p; /* It was not a class name */
+ }
+ else
+ ++p;
+ }
+
+ return p;
+}
+
+/*
* Skip past regular expression.
* Stop at end of "startp" or where "dirc" is found ('/', '?', etc).
* Take care of characters with a backslash in front of it.
@@ -1251,16 +1420,6 @@ regpiece(flagp)
*flagp = flags;
return ret;
}
- if (!(flags & HASWIDTH) && re_multi_type(op) == MULTI_MULT)
- {
- if (op == Magic('*'))
- EMSG_M_RET_NULL(_("E56: %s* operand could be empty"),
- reg_magic >= MAGIC_ON);
- if (op == Magic('+'))
- EMSG_M_RET_NULL(_("E57: %s+ operand could be empty"),
- reg_magic == MAGIC_ALL);
- /* "\{}" is checked below, it's allowed when there is an upper limit */
- }
/* default flags */
*flagp = (WORST | SPSTART | (flags & (HASNL | HASLOOKBH)));
@@ -1338,10 +1497,6 @@ regpiece(flagp)
case Magic('{'):
if (!read_limits(&minval, &maxval))
return NULL;
- if (!(flags & HASWIDTH) && (maxval > minval
- ? maxval >= MAX_LIMIT : minval >= MAX_LIMIT))
- EMSG_M_RET_NULL(_("E58: %s{ operand could be empty"),
- reg_magic == MAGIC_ALL);
if (flags & SIMPLE)
{
reginsert(BRACE_SIMPLE, ret);
@@ -1391,6 +1546,7 @@ regatom(flagp)
char_u *ret;
int flags;
int cpo_lit; /* 'cpoptions' contains 'l' flag */
+ int cpo_bsl; /* 'cpoptions' contains '\' flag */
int c;
static char_u *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
static int classcodes[] = {ANY, IDENT, SIDENT, KWORD, SKWORD,
@@ -1406,6 +1562,7 @@ regatom(flagp)
*flagp = WORST; /* Tentatively. */
cpo_lit = (!reg_syn && vim_strchr(p_cpo, CPO_LITERAL) != NULL);
+ cpo_bsl = (!reg_syn && vim_strchr(p_cpo, CPO_BACKSL) != NULL);
c = getchr();
switch (c)
@@ -1827,7 +1984,10 @@ collection:
/* At the start ']' and '-' mean the literal character. */
if (*regparse == ']' || *regparse == '-')
+ {
+ startc = *regparse;
regc(*regparse++);
+ }
while (*regparse != NUL && *regparse != ']')
{
@@ -1845,15 +2005,22 @@ collection:
}
else
{
+ /* Also accept "a-[.z.]" */
+ endc = 0;
+ if (*regparse == '[')
+ endc = get_coll_element(&regparse);
+ if (endc == 0)
+ {
#ifdef FEAT_MBYTE
- if (has_mbyte)
- endc = mb_ptr2char_adv(&regparse);
- else
+ if (has_mbyte)
+ endc = mb_ptr2char_adv(&regparse);
+ else
#endif
- endc = *regparse++;
+ endc = *regparse++;
+ }
/* Handle \o40, \x20 and \u20AC style sequences */
- if (endc == '\\' && !cpo_lit)
+ if (endc == '\\' && !cpo_lit && !cpo_bsl)
endc = coll_get_char();
if (startc > endc)
@@ -1892,8 +2059,10 @@ collection:
* Only "\]", "\^", "\]" and "\\" are special in Vi. Vim
* accepts "\t", "\e", etc., but only when the 'l' flag in
* 'cpoptions' is not included.
+ * Posix doesn't recognize backslash at all.
*/
else if (*regparse == '\\'
+ && !cpo_bsl
&& (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
|| (!cpo_lit
&& vim_strchr(REGEXP_ABBR,
@@ -1942,15 +2111,30 @@ collection:
int c_class;
int cu;
- c_class = skip_class_name(&regparse);
+ c_class = get_char_class(&regparse);
startc = -1;
/* Characters assumed to be 8 bits! */
switch (c_class)
{
case CLASS_NONE:
- /* literal '[', allow [[-x] as a range */
- startc = *regparse++;
- regc(startc);
+ c_class = get_equi_class(&regparse);
+ if (c_class != 0)
+ {
+ /* produce equivalence class */
+ reg_equi_class(c_class);
+ }
+ else if ((c_class =
+ get_coll_element(&regparse)) != 0)
+ {
+ /* produce a collating element */
+ regmbc(c_class);
+ }
+ else
+ {
+ /* literal '[', allow [[-x] as a range */
+ startc = *regparse++;
+ regc(startc);
+ }
break;
case CLASS_ALNUM:
for (cu = 1; cu <= 255; cu++)
@@ -2354,6 +2538,8 @@ initchr(str)
static int
peekchr()
{
+ static int after_slash = FALSE;
+
if (curchr == -1)
{
switch (curchr = regparse[0])
@@ -2392,10 +2578,16 @@ peekchr()
curchr = Magic(curchr);
break;
case '*':
- /* * is not magic as the very first character, eg "?*ptr" and when
- * after '^', eg "/^*ptr" */
- if (reg_magic >= MAGIC_ON && !at_start
- && !(prev_at_start && prevchr == Magic('^')))
+ /* * is not magic as the very first character, eg "?*ptr", when
+ * after '^', eg "/^*ptr" and when after "\(", "\|", "\&". But
+ * "\(\*" is not magic, thus must be magic if "after_slash" */
+ if (reg_magic >= MAGIC_ON
+ && !at_start
+ && !(prev_at_start && prevchr == Magic('^'))
+ && (after_slash
+ || (prevchr != Magic('(')
+ && prevchr != Magic('&')
+ && prevchr != Magic('|'))))
curchr = Magic('*');
break;
case '^':
@@ -2460,8 +2652,10 @@ peekchr()
prev_at_start = at_start;
at_start = FALSE; /* be able to say "/\*ptr" */
++regparse;
+ ++after_slash;
peekchr();
--regparse;
+ --after_slash;
curchr = toggle_Magic(curchr);
}
else if (vim_strchr(REGEXP_ABBR, c))
@@ -2723,7 +2917,7 @@ read_limits(minval, maxval)
*maxval = MAX_LIMIT; /* It was \{} or \{-} */
if (*regparse == '\\')
regparse++; /* Allow either \{...} or \{...\} */
- if (*regparse != '}' || (*maxval == 0 && *minval == 0))
+ if (*regparse != '}')
{
sprintf((char *)IObuff, _("E554: Syntax error in %s{...}"),
reg_magic == MAGIC_ALL ? "" : "\\");
@@ -2815,7 +3009,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
*(pp) = (savep)->se_u.ptr; }
static int re_num_cmp __ARGS((long_u val, char_u *scan));
-static int regmatch __ARGS((char_u *prog));
+static int regmatch __ARGS((char_u *prog, regsave_T *startp));
static int regrepeat __ARGS((char_u *p, long maxcount));
#ifdef DEBUG
@@ -3273,7 +3467,7 @@ regtry(prog, col)
need_clear_zsubexpr = TRUE;
#endif
- if (regmatch(prog->program + 1))
+ if (regmatch(prog->program + 1, NULL))
{
cleanup_subexpr();
if (REG_MULTI)
@@ -3379,8 +3573,9 @@ static long bl_maxval;
* undefined state!
*/
static int
-regmatch(scan)
+regmatch(scan, startp)
char_u *scan; /* Current node. */
+ regsave_T *startp; /* start position for BACK */
{
char_u *next; /* Next node. */
int op;
@@ -3803,6 +3998,10 @@ regmatch(scan)
break;
case BACK:
+ /* When we run into BACK without matching something non-empty, we
+ * fail. */
+ if (startp != NULL && reg_save_equal(startp))
+ return FALSE;
break;
case MOPEN + 0: /* Match start: \zs */
@@ -3823,7 +4022,7 @@ regmatch(scan)
cleanup_subexpr();
save_se(&save, &reg_startpos[no], &reg_startp[no]);
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
restore_se(&save, &reg_startpos[no], &reg_startp[no]);
@@ -3833,7 +4032,7 @@ regmatch(scan)
case NOPEN: /* \%( */
case NCLOSE: /* \) after \%( */
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
return FALSE;
/* break; Not Reached */
@@ -3856,7 +4055,7 @@ regmatch(scan)
cleanup_zsubexpr();
save_se(&save, &reg_startzpos[no], &reg_startzp[no]);
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
restore_se(&save, &reg_startzpos[no], &reg_startzp[no]);
@@ -3883,7 +4082,7 @@ regmatch(scan)
cleanup_subexpr();
save_se(&save, &reg_endpos[no], &reg_endp[no]);
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
restore_se(&save, &reg_endpos[no], &reg_endp[no]);
@@ -3909,7 +4108,7 @@ regmatch(scan)
cleanup_zsubexpr();
save_se(&save, &reg_endzpos[no], &reg_endzp[no]);
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
restore_se(&save, &reg_endzpos[no], &reg_endzp[no]);
@@ -4076,7 +4275,7 @@ regmatch(scan)
do
{
reg_save(&save);
- if (regmatch(OPERAND(scan)))
+ if (regmatch(OPERAND(scan), &save))
return TRUE;
reg_restore(&save);
scan = regnext(scan);
@@ -4134,7 +4333,7 @@ regmatch(scan)
? brace_min[no] : brace_max[no]))
{
reg_save(&save);
- if (regmatch(OPERAND(scan)))
+ if (regmatch(OPERAND(scan), &save))
return TRUE;
reg_restore(&save);
--brace_count[no]; /* failed, decrement match count */
@@ -4148,11 +4347,11 @@ regmatch(scan)
if (brace_count[no] <= brace_max[no])
{
reg_save(&save);
- if (regmatch(OPERAND(scan)))
+ if (regmatch(OPERAND(scan), &save))
return TRUE; /* matched some more times */
reg_restore(&save);
--brace_count[no]; /* matched just enough times */
- /* continue with the items after \{} */
+ /* { continue with the items after \{} */
}
}
else
@@ -4161,7 +4360,7 @@ regmatch(scan)
if (brace_count[no] <= brace_min[no])
{
reg_save(&save);
- if (regmatch(next))
+ if (regmatch(next, &save))
return TRUE;
reg_restore(&save);
next = OPERAND(scan);
@@ -4234,7 +4433,7 @@ regmatch(scan)
|| *reginput == nextb_ic)
{
reg_save(&save);
- if (regmatch(next))
+ if (regmatch(next, startp))
return TRUE;
reg_restore(&save);
}
@@ -4271,7 +4470,7 @@ regmatch(scan)
|| *reginput == nextb_ic)
{
reg_save(&save);
- if (regmatch(next))
+ if (regmatch(next, &save))
return TRUE;
reg_restore(&save);
}
@@ -4295,7 +4494,7 @@ regmatch(scan)
/* If the operand matches, we fail. Otherwise backup and
* continue with the next item. */
reg_save(&save);
- if (regmatch(OPERAND(scan)))
+ if (regmatch(OPERAND(scan), startp))
return FALSE;
reg_restore(&save);
}
@@ -4309,7 +4508,7 @@ regmatch(scan)
/* If the operand doesn't match, we fail. Otherwise backup
* and continue with the next item. */
reg_save(&save);
- if (!regmatch(OPERAND(scan)))
+ if (!regmatch(OPERAND(scan), startp))
return FALSE;
if (op == MATCH) /* zero-width */
reg_restore(&save);
@@ -4331,7 +4530,7 @@ regmatch(scan)
* faster.
*/
reg_save(&save_start);
- if (regmatch(next))
+ if (regmatch(next, startp))
{
/* save the position after the found match for next */
reg_save(&save_after);
@@ -4347,7 +4546,7 @@ regmatch(scan)
for (;;)
{
reg_restore(&save_start);
- if (regmatch(OPERAND(scan))
+ if (regmatch(OPERAND(scan), startp)
&& reg_save_equal(&behind_pos))
{
behind_pos = save_behind_pos;
diff --git a/src/testdir/test11.in b/src/testdir/test11.in
index 0e721b754..063aeb260 100644
--- a/src/testdir/test11.in
+++ b/src/testdir/test11.in
@@ -38,6 +38,7 @@ STARTTEST
:au BufReadPost *.gz !gzip <afile>:r
:e! Xtestfile.gz " Edit compressed file
:w>>test.out " Append it to the output file
+:set shelltemp " need temp files here
:au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>").".t")
:au FilterReadPre *.out !sed s/e/E/ <afile>.t ><afile>
:au FilterReadPre *.out !rm <afile>.t
diff --git a/src/vim.h b/src/vim.h
index 6d2b24957..fa554b026 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -782,6 +782,8 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
#define SHELL_COOKED 4 /* set term to cooked mode */
#define SHELL_DOOUT 8 /* redirecting output */
#define SHELL_SILENT 16 /* don't print error returned by command */
+#define SHELL_READ 32 /* read lines and insert into buffer */
+#define SHELL_WRITE 64 /* write lines from buffer */
/* Values returned by mch_nodetype() */
#define NODE_NORMAL 0 /* file or directory, check with mch_isdir()*/
@@ -885,9 +887,10 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
/* flags for do_put() */
#define PUT_FIXINDENT 1 /* make indent look nice */
#define PUT_CURSEND 2 /* leave cursor after end of new text */
-#define PUT_LINE 4 /* put register as lines */
-#define PUT_LINE_SPLIT 8 /* split line for linewise register */
-#define PUT_LINE_FORWARD 16 /* put linewise register below Visual sel. */
+#define PUT_CURSLINE 4 /* leave cursor on last line of new text */
+#define PUT_LINE 8 /* put register as lines */
+#define PUT_LINE_SPLIT 16 /* split line for linewise register */
+#define PUT_LINE_FORWARD 32 /* put linewise register below Visual sel. */
/* flags for set_indent() */
#define SIN_CHANGED 1 /* call changed_bytes() when line changed */