diff options
author | Bram Moolenaar <Bram@vim.org> | 2005-02-22 08:39:57 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2005-02-22 08:39:57 +0000 |
commit | df177f679e950a2ab2ad5fe7d45c1daface004d7 (patch) | |
tree | 21c0c50e9144ef873af675daf53b86beb26dd677 /src | |
parent | 6bdcfc08cb9c192972336e28a2a842b7abbb2811 (diff) | |
download | vim-git-df177f679e950a2ab2ad5fe7d45c1daface004d7.tar.gz |
updated for version 7.0051
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 6 | ||||
-rw-r--r-- | src/ex_docmd.c | 362 | ||||
-rw-r--r-- | src/fileio.c | 18 | ||||
-rw-r--r-- | src/globals.h | 11 | ||||
-rw-r--r-- | src/mbyte.c | 9 | ||||
-rw-r--r-- | src/message.c | 38 | ||||
-rw-r--r-- | src/netbeans.c | 14 | ||||
-rw-r--r-- | src/normal.c | 8 | ||||
-rw-r--r-- | src/os_unix.c | 335 | ||||
-rw-r--r-- | src/po/Make_ming.mak | 4 | ||||
-rw-r--r-- | src/po/Makefile | 4 | ||||
-rw-r--r-- | src/proto/ex_docmd.pro | 1 | ||||
-rw-r--r-- | src/proto/gui_mac.pro | 1 | ||||
-rw-r--r-- | src/proto/main.pro | 2 | ||||
-rw-r--r-- | src/proto/message.pro | 3 | ||||
-rw-r--r-- | src/quickfix.c | 13 | ||||
-rw-r--r-- | src/regexp.c | 407 | ||||
-rw-r--r-- | src/testdir/test11.in | 1 | ||||
-rw-r--r-- | src/vim.h | 9 |
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(®match, 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(®parse); + if (endc == 0) + { #ifdef FEAT_MBYTE - if (has_mbyte) - endc = mb_ptr2char_adv(®parse); - else + if (has_mbyte) + endc = mb_ptr2char_adv(®parse); + 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(®parse); + c_class = get_char_class(®parse); 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(®parse); + if (c_class != 0) + { + /* produce equivalence class */ + reg_equi_class(c_class); + } + else if ((c_class = + get_coll_element(®parse)) != 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, ®_startpos[no], ®_startp[no]); - if (regmatch(next)) + if (regmatch(next, startp)) return TRUE; restore_se(&save, ®_startpos[no], ®_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, ®_startzpos[no], ®_startzp[no]); - if (regmatch(next)) + if (regmatch(next, startp)) return TRUE; restore_se(&save, ®_startzpos[no], ®_startzp[no]); @@ -3883,7 +4082,7 @@ regmatch(scan) cleanup_subexpr(); save_se(&save, ®_endpos[no], ®_endp[no]); - if (regmatch(next)) + if (regmatch(next, startp)) return TRUE; restore_se(&save, ®_endpos[no], ®_endp[no]); @@ -3909,7 +4108,7 @@ regmatch(scan) cleanup_zsubexpr(); save_se(&save, ®_endzpos[no], ®_endzp[no]); - if (regmatch(next)) + if (regmatch(next, startp)) return TRUE; restore_se(&save, ®_endzpos[no], ®_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 @@ -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 */ |