diff options
author | Bram Moolenaar <Bram@vim.org> | 2005-07-27 21:13:01 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2005-07-27 21:13:01 +0000 |
commit | 87e25fdf80c7b45deee9c59389b51503e906d93b (patch) | |
tree | e477f86746245499e324e1d1e9ccada6aed035e9 /src | |
parent | 231334e6efbf3a7f89183f8257e09492534a5f8c (diff) | |
download | vim-git-87e25fdf80c7b45deee9c59389b51503e906d93b.tar.gz |
updated for version 7.0117v7.0117
Diffstat (limited to 'src')
-rw-r--r-- | src/Make_ivc.mak | 4 | ||||
-rw-r--r-- | src/Makefile | 18 | ||||
-rw-r--r-- | src/buffer.c | 1 | ||||
-rw-r--r-- | src/eval.c | 80 | ||||
-rw-r--r-- | src/ex_cmds.h | 4 | ||||
-rw-r--r-- | src/ex_docmd.c | 1 | ||||
-rw-r--r-- | src/globals.h | 2 | ||||
-rw-r--r-- | src/gui.c | 1 | ||||
-rw-r--r-- | src/main.aap | 19 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/message.c | 843 | ||||
-rw-r--r-- | src/ops.c | 11 | ||||
-rw-r--r-- | src/proto/eval.pro | 2 | ||||
-rw-r--r-- | src/proto/message.pro | 1 | ||||
-rw-r--r-- | src/proto/quickfix.pro | 1 | ||||
-rw-r--r-- | src/proto/screen.pro | 1 | ||||
-rw-r--r-- | src/quickfix.c | 217 | ||||
-rw-r--r-- | src/screen.c | 3 | ||||
-rw-r--r-- | src/tag.c | 5 | ||||
-rw-r--r-- | src/version.h | 4 |
20 files changed, 845 insertions, 374 deletions
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak index 44f58fb94..2326c3086 100644 --- a/src/Make_ivc.mak +++ b/src/Make_ivc.mak @@ -88,8 +88,8 @@ LINK32=link.exe CPP_PROJ= /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c # ADD CPP /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c -LINK32_FLAGS= oldnames.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib -# ADD LINK32 oldnames.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib +LINK32_FLAGS= oldnames.lib kernel32.lib user32.lib gdi32.lib version.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib +# ADD LINK32 oldnames.lib kernel32.lib user32.lib gdi32.lib version.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib # SUBTRACT LINK32 /incremental:yes RSC_PROJ= /l 0x409 /d "FEAT_GUI_W32" diff --git a/src/Makefile b/src/Makefile index 83732a28a..2a74f4ed7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -879,6 +879,7 @@ HELPSUBDIR = /doc COLSUBDIR = /colors SYNSUBDIR = /syntax INDSUBDIR = /indent +AUTOSUBDIR = /autoload PLUGSUBDIR = /plugin FTPLUGSUBDIR = /ftplugin LANGSUBDIR = /lang @@ -899,6 +900,7 @@ PODIR = po ### COLSUBLOC location for colorscheme files ### SYNSUBLOC location for syntax files ### INDSUBLOC location for indent files +### AUTOSUBLOC location for standard autoload files ### PLUGSUBLOC location for standard plugin files ### FTPLUGSUBLOC location for ftplugin files ### LANGSUBLOC location for language files @@ -919,6 +921,7 @@ HELPSUBLOC = $(VIMRTLOC)$(HELPSUBDIR) COLSUBLOC = $(VIMRTLOC)$(COLSUBDIR) SYNSUBLOC = $(VIMRTLOC)$(SYNSUBDIR) INDSUBLOC = $(VIMRTLOC)$(INDSUBDIR) +AUTOSUBLOC = $(VIMRTLOC)$(AUTOSUBDIR) PLUGSUBLOC = $(VIMRTLOC)$(PLUGSUBDIR) FTPLUGSUBLOC = $(VIMRTLOC)$(FTPLUGSUBDIR) LANGSUBLOC = $(VIMRTLOC)$(LANGSUBDIR) @@ -1018,6 +1021,9 @@ SYNSOURCE = ../runtime/syntax INDSOURCE = ../runtime/indent # Where to copy the standard plugin files from +AUTOSOURCE = ../runtime/autoload + +# Where to copy the standard plugin files from PLUGSOURCE = ../runtime/plugin # Where to copy the ftplugin files from @@ -1290,6 +1296,7 @@ DEST_HELP = $(DESTDIR)$(HELPSUBLOC) DEST_COL = $(DESTDIR)$(COLSUBLOC) DEST_SYN = $(DESTDIR)$(SYNSUBLOC) DEST_IND = $(DESTDIR)$(INDSUBLOC) +DEST_AUTO = $(DESTDIR)$(AUTOSUBLOC) DEST_PLUG = $(DESTDIR)$(PLUGSUBLOC) DEST_FTP = $(DESTDIR)$(FTPLUGSUBLOC) DEST_LANG = $(DESTDIR)$(LANGSUBLOC) @@ -1739,7 +1746,8 @@ INSTALLMANARGS = $(VIMLOC) $(SCRIPTLOC) $(VIMRCLOC) $(HELPSOURCE) $(MANMOD) \ # install the help files; first adjust the contents for the final location installruntime: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(DEST_RT) \ $(DEST_HELP) $(DEST_PRINT) $(DEST_COL) $(DEST_SYN) $(DEST_IND) \ - $(DEST_FTP) $(DEST_PLUG) $(DEST_TUTOR) $(DEST_SPELL) $(DEST_COMP) + $(DEST_FTP) $(DEST_AUTO) $(DEST_PLUG) $(DEST_TUTOR) \ + $(DEST_SPELL) $(DEST_COMP) -$(SHELL) ./installman.sh install $(DEST_MAN) "" $(INSTALLMANARGS) @echo generating help tags # Generate the help tags with ":helptags" to handle all languages. @@ -1801,6 +1809,9 @@ installruntime: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(DEST_RT) \ # install the indent files cd $(INDSOURCE); $(INSTALL_DATA) *.vim README.txt $(DEST_IND) cd $(DEST_IND); chmod $(HELPMOD) *.vim README.txt +# install the standard autoload files + cd $(AUTOSOURCE); $(INSTALL_DATA) *.vim README.txt $(DEST_AUTO) + cd $(DEST_AUTO); chmod $(HELPMOD) *.vim README.txt # install the standard plugin files cd $(PLUGSOURCE); $(INSTALL_DATA) *.vim README.txt $(DEST_PLUG) cd $(DEST_PLUG); chmod $(HELPMOD) *.vim README.txt @@ -1965,7 +1976,7 @@ $(DESTDIR)$(exec_prefix) $(DEST_BIN) \ $(DEST_PRINT) $(DEST_COL) $(DEST_SYN) $(DEST_IND) $(DEST_FTP) \ $(DEST_LANG) $(DEST_KMAP) $(DEST_COMP) \ $(DEST_MACRO) $(DEST_TOOLS) $(DEST_TUTOR) $(DEST_SPELL) \ - $(DEST_PLUG): + $(DEST_AUTO) $(DEST_PLUG): -$(SHELL) ./mkinstalldirs $@ -chmod $(DIRMOD) $@ @@ -2103,8 +2114,9 @@ uninstall_runtime: -rm -f $(DEST_PRINT)/*.ps -rmdir $(DEST_HELP) $(DEST_PRINT) $(DEST_COL) $(DEST_SYN) $(DEST_IND) -rm -rf $(DEST_FTP)/*.vim $(DEST_FTP)/README.txt + -rm -f $(DEST_AUTO)/*.vim $(DEST_AUTO)/README.txt -rm -f $(DEST_PLUG)/*.vim $(DEST_PLUG)/README.txt - -rmdir $(DEST_FTP) $(DEST_PLUG) $(DEST_RT) + -rmdir $(DEST_FTP) $(DEST_AUTO) $(DEST_PLUG) $(DEST_RT) # This will fail when other Vim versions are installed, no worries. -rmdir $(DEST_VIM) diff --git a/src/buffer.c b/src/buffer.c index 07e9723a0..09ca27db8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -25,7 +25,6 @@ * The current implementation remembers all file names ever used. */ - #include "vim.h" #if defined(FEAT_CMDL_COMPL) || defined(FEAT_LISTCMDS) || defined(FEAT_EVAL) || defined(FEAT_PERL) diff --git a/src/eval.c b/src/eval.c index f18a3a95b..f2cc2a0b7 100644 --- a/src/eval.c +++ b/src/eval.c @@ -639,7 +639,6 @@ static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, static typval_T *alloc_tv __ARGS((void)); static typval_T *alloc_string_tv __ARGS((char_u *string)); static void free_tv __ARGS((typval_T *varp)); -static void clear_tv __ARGS((typval_T *varp)); static void init_tv __ARGS((typval_T *varp)); static long get_tv_number __ARGS((typval_T *varp)); static long get_tv_number_chk __ARGS((typval_T *varp, int *denote)); @@ -683,7 +682,7 @@ static int # endif prof_self_cmp __ARGS((const void *s1, const void *s2)); #endif -static int script_autoload __ARGS((char_u *name)); +static int script_autoload __ARGS((char_u *name, int reload)); static char_u *autoload_name __ARGS((char_u *name)); static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp)); static void func_free __ARGS((ufunc_T *fp)); @@ -1308,6 +1307,30 @@ get_spellword(list, pp) } #endif +/* + * Top level evaluation function, + */ + typval_T * +eval_expr(arg, nextcmd) + char_u *arg; + char_u **nextcmd; +{ + typval_T *tv; + + tv = (typval_T *)alloc(sizeof(typval_T)); + if (!tv) + return NULL; + + if (eval0(arg, tv, nextcmd, TRUE) == FAIL) + { + vim_free(tv); + return NULL; + } + + return tv; +} + + #if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) /* * Call some vimL function and return the result in "*rettv". @@ -7101,7 +7124,7 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline, } #endif /* Try loading a package. */ - if (fp == NULL && script_autoload(fname) && !aborting()) + if (fp == NULL && script_autoload(fname, TRUE) && !aborting()) { /* loaded a package, search for the function again */ fp = find_func(fname); @@ -15528,7 +15551,7 @@ free_tv(varp) /* * Free the memory for a variable value and set the value to NULL or 0. */ - static void + void clear_tv(varp) typval_T *varp; { @@ -15774,9 +15797,11 @@ find_var_in_ht(ht, varname, writing) if (HASHITEM_EMPTY(hi)) { /* For global variables we may try auto-loading the script. If it - * worked find the variable again. */ + * worked find the variable again. Don't auto-load a script if it was + * loaded already, otherwise it would be loaded every time when + * checking if a function name is a Funcref variable. */ if (ht == &globvarht && !writing - && script_autoload(varname) && !aborting()) + && script_autoload(varname, FALSE) && !aborting()) hi = hash_find(ht, varname); if (HASHITEM_EMPTY(hi)) return NULL; @@ -17566,29 +17591,52 @@ prof_self_cmp(s1, s2) #endif +/* The names of packages that once were loaded is remembered. */ +static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; + /* * If "name" has a package name try autoloading the script for it. * Return TRUE if a package was loaded. */ static int -script_autoload(name) - char_u *name; +script_autoload(name, reload) + char_u *name; + int reload; /* load script again when already loaded */ { char_u *p; - char_u *scriptname; + char_u *scriptname, *tofree; int ret = FALSE; + int i; - /* If there is no colon after name[1] there is no package name. */ + /* If there is no '#' after name[0] there is no package name. */ p = vim_strchr(name, AUTOLOAD_CHAR); - if (p == NULL || p <= name + 2) + if (p == NULL || p == name) return FALSE; - /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ - scriptname = autoload_name(name); - if (cmd_runtime(scriptname, FALSE) == OK) - ret = TRUE; + tofree = scriptname = autoload_name(name); + + /* Find the name in the list of previously loaded package names. Skip + * "autoload/", it's always the same. */ + for (i = 0; i < ga_loaded.ga_len; ++i) + if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) + break; + if (!reload && i < ga_loaded.ga_len) + ret = FALSE; /* was loaded already */ + else + { + /* Remember the name if it wasn't loaded already. */ + if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK) + { + ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname; + tofree = NULL; + } + + /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ + if (cmd_runtime(scriptname, FALSE) == OK) + ret = TRUE; + } - vim_free(scriptname); + vim_free(tofree); return ret; } diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 51053c9b2..c5adaeb1b 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -187,6 +187,8 @@ EX(CMD_cabbrev, "cabbrev", ex_abbreviate, EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN), EX(CMD_cabclear, "cabclear", ex_abclear, EXTRA|TRLBAR|CMDWIN), +EX(CMD_caddfile, "caddfile", ex_cfile, + TRLBAR|FILE1), EX(CMD_call, "call", ex_call, RANGE|NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN), EX(CMD_catch, "catch", ex_catch, @@ -201,6 +203,8 @@ EX(CMD_cd, "cd", ex_cd, BANG|FILE1|TRLBAR|CMDWIN), EX(CMD_center, "center", ex_align, TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY), +EX(CMD_cexpr, "cexpr", ex_cexpr, + NEEDARG|WORD1|NOTRLCOM|TRLBAR|BANG), EX(CMD_cfile, "cfile", ex_cfile, TRLBAR|FILE1|BANG), EX(CMD_cfirst, "cfirst", ex_cc, diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 5b07cf613..ab11dffd7 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -114,6 +114,7 @@ static int getargopt __ARGS((exarg_T *eap)); # define ex_cc ex_ni # define ex_cnext ex_ni # define ex_cfile ex_ni +# define ex_cexpr ex_ni # define qf_list ex_ni # define qf_age ex_ni # define ex_helpgrep ex_ni diff --git a/src/globals.h b/src/globals.h index 8460b49ba..fc1e61f0b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -166,8 +166,6 @@ EXTERN int need_maketitle INIT(= TRUE); /* call maketitle() soon */ #endif EXTERN int quit_more INIT(= FALSE); /* 'q' hit at "--more--" msg */ -EXTERN int more_back INIT(= 0); /* 'b' or 'u' at "--more--" msg */ -EXTERN int more_back_used INIT(= FALSE); /* using more_back */ #if defined(UNIX) || defined(__EMX__) || defined(VMS) || defined(MACOS_X) EXTERN int newline_on_exit INIT(= FALSE); /* did msg in altern. screen */ EXTERN int intr_char INIT(= 0); /* extra interrupt character */ @@ -455,6 +455,7 @@ gui_init() * where Vim was started. */ emsg_on_display = FALSE; msg_scrolled = 0; + clear_sb_text(); need_wait_return = FALSE; msg_didany = FALSE; diff --git a/src/main.aap b/src/main.aap index daa6e8b0b..83a9cd8ed 100644 --- a/src/main.aap +++ b/src/main.aap @@ -237,6 +237,7 @@ Source = fileio.c fold.c getchar.c + hardcopy.c hashtable.c if_cscope.c if_xcmdsrv.c @@ -440,6 +441,7 @@ HELPSUBDIR = /doc COLSUBDIR = /colors SYNSUBDIR = /syntax INDSUBDIR = /indent +AUTOSUBDIR = /autoload PLUGSUBDIR = /plugin FTPLUGSUBDIR = /ftplugin LANGSUBDIR = /lang @@ -459,6 +461,7 @@ PODIR = po ### COLSUBLOC location for colorscheme files ### SYNSUBLOC location for syntax files ### INDSUBLOC location for indent files +### AUTOSUBLOC location for standard autoload files ### PLUGSUBLOC location for standard plugin files ### FTPLUGSUBLOC location for ftplugin files ### LANGSUBLOC location for language files @@ -478,6 +481,7 @@ HELPSUBLOC = $VIMRTLOC$HELPSUBDIR COLSUBLOC = $VIMRTLOC$COLSUBDIR SYNSUBLOC = $VIMRTLOC$SYNSUBDIR INDSUBLOC = $VIMRTLOC$INDSUBDIR +AUTOSUBLOC = $VIMRTLOC$AUTOSUBDIR PLUGSUBLOC = $VIMRTLOC$PLUGSUBDIR FTPLUGSUBLOC = $VIMRTLOC$FTPLUGSUBDIR LANGSUBLOC = $VIMRTLOC$LANGSUBDIR @@ -566,6 +570,9 @@ SYNSOURCE = ../runtime/syntax INDSOURCE = ../runtime/indent # Where to copy the standard plugin files from +AUTOSOURCE = ../runtime/autoload + +# Where to copy the standard plugin files from PLUGSOURCE = ../runtime/plugin # Where to copy the ftplugin files from @@ -600,6 +607,7 @@ DEST_HELP = $DESTDIR$HELPSUBLOC DEST_COL = $DESTDIR$COLSUBLOC DEST_SYN = $DESTDIR$SYNSUBLOC DEST_IND = $DESTDIR$INDSUBLOC +DEST_AUTO = $DESTDIR$AUTOSUBLOC DEST_PLUG = $DESTDIR$PLUGSUBLOC DEST_FTP = $DESTDIR$FTPLUGSUBLOC DEST_LANG = $DESTDIR$LANGSUBLOC @@ -614,7 +622,7 @@ DEST_MAN = $DESTDIR$MANSUBDIR # These are directories, create them when needed. :attr {directory = $DIRMOD} $DEST_BIN $DEST_VIM $DEST_RT $DEST_HELP $DEST_COL - $DEST_SYN $DEST_IND $DEST_PLUG $DEST_FTP $DEST_LANG + $DEST_SYN $DEST_IND $DEST_AUTO $DEST_PLUG $DEST_FTP $DEST_LANG $DEST_COMP $DEST_KMAP $DEST_MACRO $DEST_TOOLS $DEST_TUTOR $DEST_SCRIPT $DEST_PRINT $DEST_MAN @@ -657,7 +665,8 @@ installvimbin {virtual}{force}: $Target $DEST_BIN # install the help files; first adjust the contents for the location installruntime {virtual}{force}: $HELPSOURCE/vim.1 $DEST_MAN $DEST_VIM $DEST_RT $DEST_HELP $DEST_COL $DEST_SYN $DEST_IND - $DEST_FTP $DEST_PLUG $DEST_TUTOR $DEST_COMP $DEST_PRINT + $DEST_FTP $DEST_AUTO $DEST_PLUG $DEST_TUTOR $DEST_COMP + $DEST_PRINT :print generating $DEST_MAN/$(VIMNAME).1 :cat $HELPSOURCE/vim.1 | :eval re.sub("/usr/local/lib/vim", _no.VIMLOC, stdin) | @@ -762,6 +771,9 @@ installruntime {virtual}{force}: $HELPSOURCE/vim.1 $DEST_MAN $DEST_VIM # install the indent files :copy $INDSOURCE/*.vim $INDSOURCE/README.txt $DEST_IND :chmod $HELPMOD $DEST_IND/*.vim +# install the standard autoload files + :copy $AUTOSOURCE/*.vim $AUTOSOURCE/README.txt $DEST_AUTO + :chmod $HELPMOD $DEST_AUTO/*.vim $DEST_AUTO/README.txt # install the standard plugin files :copy $PLUGSOURCE/*.vim $PLUGSOURCE/README.txt $DEST_PLUG :chmod $HELPMOD $DEST_PLUG/*.vim $DEST_PLUG/README.txt @@ -1041,8 +1053,9 @@ uninstall_runtime {virtual}{force}: :del {force}{recursive} $DEST_COMP :deldir {force} $DEST_HELP $DEST_COL $DEST_SYN $DEST_IND :del {force}{recursive} $DEST_FTP/*.vim $DEST_FTP/README.txt + :del {force} $DEST_AUTO/*.vim $DEST_AUTO/README.txt :del {force} $DEST_PLUG/*.vim $DEST_PLUG/README.txt - :deldir {force} $DEST_FTP $DEST_PLUG $DEST_PRINT $DEST_RT + :deldir {force} $DEST_FTP $DEST_AUTO $DEST_PLUG $DEST_PRINT $DEST_RT # This will fail when other Vim versions are installed, no worries. @try: :deldir $DEST_VIM diff --git a/src/main.c b/src/main.c index f6a31aa11..876289f67 100644 --- a/src/main.c +++ b/src/main.c @@ -1034,6 +1034,7 @@ main_loop(cmdwin, noexmode) emsg_on_display = FALSE; /* can delete error message now */ did_emsg = FALSE; msg_didany = FALSE; /* reset lines_left in msg_start() */ + clear_sb_text(); /* clear scroll-back text */ showruler(FALSE); setcursor(); diff --git a/src/message.c b/src/message.c index 94b885199..81c0a8e6e 100644 --- a/src/message.c +++ b/src/message.c @@ -29,7 +29,12 @@ static void msg_home_replace_attr __ARGS((char_u *fname, int attr)); static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr)); #endif static void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr)); -static void t_puts __ARGS((int t_col, char_u *t_s, char_u *s, int attr)); +static void msg_puts_display __ARGS((char_u *str, int maxlen, int attr, int recurse)); +static void msg_scroll_up __ARGS((void)); +static void store_sb_text __ARGS((char_u **sb_str, char_u *s, int attr, int *sb_col, int finish)); +static void t_puts __ARGS((int *t_col, char_u *t_s, char_u *s, int attr)); +static void msg_puts_printf __ARGS((char_u *str, int maxlen)); +static int do_more_prompt __ARGS((int typed_char)); static void msg_screen_putchar __ARGS((int c, int attr)); static int msg_check_screen __ARGS((void)); static void redir_write __ARGS((char_u *s, int maxlen)); @@ -924,6 +929,22 @@ wait_return(redraw) c = K_IGNORE; } #endif + if (p_more && !p_cp && (c == 'b' || c == 'k' || c == 'u')) + { + /* scroll back to show older messages */ + do_more_prompt(c); + if (quit_more) + { + c = CAR; /* just pretend CR was hit */ + quit_more = FALSE; + got_int = FALSE; + } + else + { + c = K_IGNORE; + hit_return_msg(); + } + } } while ((had_got_int && c == Ctrl_C) || c == K_IGNORE #ifdef FEAT_GUI @@ -1031,14 +1052,18 @@ wait_return(redraw) static void hit_return_msg() { - if (msg_didout) /* start on a new line */ + int save_p_more = p_more; + + p_more = FALSE; /* don't want see this message when scrolling back */ + if (msg_didout) /* start on a new line */ msg_putchar('\n'); if (got_int) MSG_PUTS(_("Interrupt: ")); - MSG_PUTS_ATTR(_("Hit ENTER or type command to continue"), hl_attr(HLF_R)); + MSG_PUTS_ATTR(_("Press ENTER or type command to continue"), hl_attr(HLF_R)); if (!msg_use_printf()) msg_clr_eos(); + p_more = save_p_more; } /* @@ -1515,7 +1540,7 @@ msg_prt_line(s, list) if (*s == NUL && !(list && lcs_eol != NUL)) msg_putchar(' '); - for (;;) + while (!got_int) { if (n_extra) { @@ -1711,22 +1736,10 @@ msg_puts_attr_len(str, maxlen, attr) int maxlen; int attr; { - int oldState; - char_u *s = str; - char_u *p; - char_u buf[4]; - char_u *t_s = str; /* string from "t_s" to "s" is still todo */ - int t_col = 0; /* screen cells todo, 0 when "t_s" not used */ -#ifdef FEAT_MBYTE - int l; - int cw; -#endif - int c; - /* * If redirection is on, also write to the redirection file. */ - redir_write(s, maxlen); + redir_write(str, maxlen); /* * Don't print anything when using ":silent cmd". @@ -1737,7 +1750,7 @@ msg_puts_attr_len(str, maxlen, attr) /* if MSG_HIST flag set, add message to history */ if ((attr & MSG_HIST) && maxlen < 0) { - add_msg_hist(s, -1, attr); + add_msg_hist(str, -1, attr); attr &= ~MSG_HIST; } @@ -1759,72 +1772,42 @@ msg_puts_attr_len(str, maxlen, attr) * cursor is. */ if (msg_use_printf()) - { -#ifdef WIN3264 - if (!(silent_mode && p_verbose == 0)) - mch_settmode(TMODE_COOK); /* handle '\r' and '\n' correctly */ -#endif - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) - { - if (!(silent_mode && p_verbose == 0)) - { - p = &buf[0]; - /* NL --> CR NL translation (for Unix, not for "--version") */ - /* NL --> CR translation (for Mac) */ - if (*s == '\n' && !info_message) - *p++ = '\r'; -#if defined(USE_CR) && !defined(MACOS_X_UNIX) - else -#endif - *p++ = *s; - *p = '\0'; - if (info_message) /* informative message, not an error */ - mch_msg((char *)buf); - else - mch_errmsg((char *)buf); - } - - /* primitive way to compute the current column */ -#ifdef FEAT_RIGHTLEFT - if (cmdmsg_rl) - { - if (*s == '\r' || *s == '\n') - msg_col = Columns - 1; - else - --msg_col; - } - else -#endif - { - if (*s == '\r' || *s == '\n') - msg_col = 0; - else - ++msg_col; - } - ++s; - } - msg_didout = TRUE; /* assume that line is not empty */ + msg_puts_printf(str, maxlen); + else + msg_puts_display(str, maxlen, attr, FALSE); +} -#ifdef WIN3264 - if (!(silent_mode && p_verbose == 0)) - mch_settmode(TMODE_RAW); +/* + * The display part of msg_puts_attr_len(). + * May be called recursively to display scroll-back text. + */ + static void +msg_puts_display(str, maxlen, attr, recurse) + char_u *str; + int maxlen; + int attr; + int recurse; +{ + char_u *s = str; + char_u *t_s = str; /* string from "t_s" to "s" is still todo */ + int t_col = 0; /* screen cells todo, 0 when "t_s" not used */ +#ifdef FEAT_MBYTE + int l; + int cw; #endif - return; - } + char_u *sb_str = str; + int sb_col = msg_col; + int wrap; did_wait_return = FALSE; while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { /* - * The screen is scrolled up when: - * - When outputting a newline in the last row - * - when outputting a character in the last column of the last row - * (some terminals scroll automatically, some don't. To avoid - * problems we scroll ourselves) + * We are at the end of the screen line when: + * - When outputting a newline. + * - When outputting a character in the last column. */ - if (msg_row >= Rows - 1 - && (*s == '\n' - || ( + if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || ( #ifdef FEAT_RIGHTLEFT cmdmsg_rl ? ( @@ -1844,47 +1827,55 @@ msg_puts_attr_len(str, maxlen, attr) # endif )))) { + /* + * The screen is scrolled up when at the last row (some terminals + * scroll automatically, some don't. To avoid problems we scroll + * ourselves). + */ if (t_col > 0) - { /* output postponed text */ - t_puts(t_col, t_s, s, attr); - t_col = 0; - } + t_puts(&t_col, t_s, s, attr); /* When no more prompt an no more room, truncate here */ if (msg_no_more && lines_left == 0) break; -#ifdef FEAT_GUI - /* Remove the cursor before scrolling, ScreenLines[] is going to - * become invalid. */ - if (gui.in_use) - gui_undraw_cursor(); -#endif - /* scrolling up always works */ - screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); - if (!can_clear((char_u *)" ")) - { - /* Scrolling up doesn't result in the right background. Set - * the background here. It's not efficient, but avoids that - * we have to do it all over the code. */ - screen_fill((int)Rows - 1, (int)Rows, 0, - (int)Columns, ' ', ' ', 0); - - /* Also clear the last char of the last but one line if it was - * not cleared before to avoid a scroll-up. */ - if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] - == (sattr_T)-1) - screen_fill((int)Rows - 2, (int)Rows - 1, - (int)Columns - 1, (int)Columns, ' ', ' ', 0); - } + /* Scroll the screen up one line. */ + msg_scroll_up(); msg_row = Rows - 2; if (msg_col >= Columns) /* can happen after screen resize */ msg_col = Columns - 1; + /* Display char in last column before showing more-prompt. */ + if (*s >= ' ' +#ifdef FEAT_RIGHTLEFT + && !cmdmsg_rl +#endif + ) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + { + if (enc_utf8 && maxlen >= 0) + /* avoid including composing chars after the end */ + l = utfc_ptr2len_check_len(s, + (int)((str + maxlen) - s)); + else + l = (*mb_ptr2len_check)(s); + s = screen_puts_mbyte(s, l, attr); + } + else +#endif + msg_screen_putchar(*s++, attr); + } + + if (p_more) + /* store text for scrolling back */ + store_sb_text(&sb_str, s, attr, &sb_col, TRUE); + ++msg_scrolled; - need_wait_return = TRUE; /* may need wait_return in main() */ + need_wait_return = TRUE; /* may need wait_return in main() */ if (must_redraw < VALID) must_redraw = VALID; redraw_cmdline = TRUE; @@ -1892,170 +1883,38 @@ msg_puts_attr_len(str, maxlen, attr) --cmdline_row; /* - * if screen is completely filled wait for a character + * If screen is completely filled and 'more' is set then wait + * for a character. */ if (p_more && --lines_left == 0 && State != HITRETURN && !msg_no_more && !exmode_active) { - oldState = State; - State = ASKMORE; -#ifdef FEAT_MOUSE - setmouse(); -#endif - msg_moremsg(FALSE); - for (;;) - { - /* - * Get a typed character directly from the user. - */ - c = get_keystroke(); - -#if defined(FEAT_MENU) && defined(FEAT_GUI) - if (c == K_MENU) - { - int idx = get_menu_index(current_menu, ASKMORE); - - /* Used a menu. If it starts with CTRL-Y, it must - * be a "Copy" for the clipboard. Otherwise - * assume that we end */ - if (idx == MENU_INDEX_INVALID) - continue; - c = *current_menu->strings[idx]; - if (c != NUL && current_menu->strings[idx][1] != NUL) - ins_typebuf(current_menu->strings[idx] + 1, - current_menu->noremap[idx], 0, TRUE, - current_menu->silent[idx]); - } -#endif - - switch (c) - { - case BS: - case 'k': - case K_UP: - if (!more_back_used) - { - msg_moremsg(TRUE); - continue; - } - more_back = 1; - lines_left = 1; - break; - case CAR: /* one extra line */ - case NL: - case 'j': - case K_DOWN: - lines_left = 1; - break; - case ':': /* start new command line */ -#ifdef FEAT_CON_DIALOG - if (!confirm_msg_used) -#endif - { - /* Since got_int is set all typeahead will be - * flushed, but we want to keep this ':', remember - * that in a special way. */ - typeahead_noflush(':'); - cmdline_row = Rows - 1; /* put ':' on this line */ - skip_redraw = TRUE; /* skip redraw once */ - need_wait_return = FALSE; /* don't wait in main() */ - } - /*FALLTHROUGH*/ - case 'q': /* quit */ - case Ctrl_C: - case ESC: #ifdef FEAT_CON_DIALOG - if (confirm_msg_used) - { - /* Jump to the choices of the dialog. */ - s = confirm_msg_tail; - lines_left = Rows - 1; - } - else -#endif - { - got_int = TRUE; - quit_more = TRUE; - } - break; - case 'u': /* Up half a page */ - case K_PAGEUP: - if (!more_back_used) - { - msg_moremsg(TRUE); - continue; - } - more_back = Rows / 2; - /*FALLTHROUGH*/ - case 'd': /* Down half a page */ - lines_left = Rows / 2; - break; - case 'b': /* one page back */ - if (!more_back_used) - { - msg_moremsg(TRUE); - continue; - } - more_back = Rows - 1; - /*FALLTHROUGH*/ - case ' ': /* one extra page */ - case K_PAGEDOWN: - case K_LEFTMOUSE: - lines_left = Rows - 1; - break; - -#ifdef FEAT_CLIPBOARD - case Ctrl_Y: - /* Strange way to allow copying (yanking) a modeless - * selection at the more prompt. Use CTRL-Y, - * because the same is used in Cmdline-mode and at the - * hit-enter prompt. However, scrolling one line up - * might be expected... */ - if (clip_star.state == SELECT_DONE) - clip_copy_modeless_selection(TRUE); - continue; -#endif - default: /* no valid response */ - msg_moremsg(TRUE); - continue; - } - break; - } - - /* clear the --more-- message */ - screen_fill((int)Rows - 1, (int)Rows, - 0, (int)Columns, ' ', ' ', 0); - State = oldState; -#ifdef FEAT_MOUSE - setmouse(); + if (do_more_prompt(NUL)) + s = confirm_msg_tail; +#else + (void)do_more_prompt(NUL); #endif if (quit_more) - { - msg_row = Rows - 1; - msg_col = 0; - return; /* the string is not displayed! */ - } -#ifdef FEAT_RIGHTLEFT - if (cmdmsg_rl) - msg_col = Columns - 1; -#endif + return; } } - if (t_col > 0 - && (vim_strchr((char_u *)"\n\r\b\t", *s) != NULL - || *s == BELL + wrap = *s == '\n' || msg_col + t_col >= Columns #ifdef FEAT_MBYTE || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col + t_col >= Columns - 1) #endif - )) - { + ; + if (t_col > 0 && (wrap || *s == '\r' || *s == '\b' + || *s == '\t' || *s == BELL)) /* output any postponed text */ - t_puts(t_col, t_s, s, attr); - t_col = 0; - } + t_puts(&t_col, t_s, s, attr); + + if (wrap && p_more && !recurse) + /* store text for scrolling back */ + store_sb_text(&sb_str, s, attr, &sb_col, TRUE); if (*s == '\n') /* go to next line */ { @@ -2073,7 +1932,7 @@ msg_puts_attr_len(str, maxlen, attr) if (msg_col) --msg_col; } - else if (*s == TAB) /* translate into spaces */ + else if (*s == TAB) /* translate Tab into spaces */ { do msg_screen_putchar(' ', attr); @@ -2141,17 +2000,172 @@ msg_puts_attr_len(str, maxlen, attr) /* output any postponed text */ if (t_col > 0) - t_puts(t_col, t_s, s, attr); + t_puts(&t_col, t_s, s, attr); + if (p_more && !recurse) + store_sb_text(&sb_str, s, attr, &sb_col, FALSE); msg_check(); } /* + * Scroll the screen up one line for displaying the next message line. + */ + static void +msg_scroll_up() +{ +#ifdef FEAT_GUI + /* Remove the cursor before scrolling, ScreenLines[] is going + * to become invalid. */ + if (gui.in_use) + gui_undraw_cursor(); +#endif + /* scrolling up always works */ + screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); + + if (!can_clear((char_u *)" ")) + { + /* Scrolling up doesn't result in the right background. Set the + * background here. It's not efficient, but avoids that we have to do + * it all over the code. */ + screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + + /* Also clear the last char of the last but one line if it was not + * cleared before to avoid a scroll-up. */ + if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1) + screen_fill((int)Rows - 2, (int)Rows - 1, + (int)Columns - 1, (int)Columns, ' ', ' ', 0); + } +} + +/* + * To be able to scroll back at the "more" and "hit-enter" prompts we need to + * store the displayed text and remember where screen lines start. + */ +typedef struct msgchunk_S msgchunk_T; +struct msgchunk_S +{ + msgchunk_T *sb_next; + msgchunk_T *sb_prev; + char sb_eol; /* TRUE when line ends after this text */ + int sb_msg_col; /* column in which text starts */ + int sb_attr; /* text attributes */ + char_u sb_text[1]; /* text to be displayed, actually longer */ +}; + +static msgchunk_T *last_msgchunk = NULL; /* last displayed text */ + +static msgchunk_T *msg_sb_start __ARGS((msgchunk_T *mps)); +static msgchunk_T *disp_sb_line __ARGS((int row, msgchunk_T *smp)); + +/* + * Store part of a printed message for displaying when scrolling back. + */ + static void +store_sb_text(sb_str, s, attr, sb_col, finish) + char_u **sb_str; /* start of string */ + char_u *s; /* just after string */ + int attr; + int *sb_col; + int finish; /* line ends */ +{ + msgchunk_T *mp; + + if (s > *sb_str) + { + mp = (msgchunk_T *)alloc((int)(sizeof(msgchunk_T) + (s - *sb_str))); + if (mp != NULL) + { + mp->sb_eol = finish; + mp->sb_msg_col = *sb_col; + mp->sb_attr = attr; + vim_strncpy(mp->sb_text, *sb_str, s - *sb_str); + + if (last_msgchunk == NULL) + { + last_msgchunk = mp; + mp->sb_prev = NULL; + } + else + { + mp->sb_prev = last_msgchunk; + last_msgchunk->sb_next = mp; + last_msgchunk = mp; + } + mp->sb_next = NULL; + } + } + else if (finish && last_msgchunk != NULL) + last_msgchunk->sb_eol = TRUE; + + *sb_str = s; + *sb_col = 0; +} + +/* + * Clear any text remembered for scrolling back. + * Called when redrawing the screen. + */ + void +clear_sb_text() +{ + msgchunk_T *mp; + + while (last_msgchunk != NULL) + { + mp = last_msgchunk->sb_prev; + vim_free(last_msgchunk); + last_msgchunk = mp; + } + last_msgchunk = NULL; +} + +/* + * Move to the start of screen line in already displayed text. + */ + static msgchunk_T * +msg_sb_start(mps) + msgchunk_T *mps; +{ + msgchunk_T *mp = mps; + + while (mp != NULL && mp->sb_prev != NULL && !mp->sb_prev->sb_eol) + mp = mp->sb_prev; + return mp; +} + +/* + * Display a screen line from previously displayed text at row "row". + * Returns a pointer to the text for the next line (can be NULL). + */ + static msgchunk_T * +disp_sb_line(row, smp) + int row; + msgchunk_T *smp; +{ + msgchunk_T *mp = smp; + char_u *p; + + for (;;) + { + msg_row = row; + msg_col = mp->sb_msg_col; + p = mp->sb_text; + if (*p == '\n') /* don't display the line break */ + ++p; + msg_puts_display(p, -1, mp->sb_attr, TRUE); + if (mp->sb_eol || mp->sb_next == NULL) + break; + mp = mp->sb_next; + } + return mp->sb_next; +} + +/* * Output any postponed text for msg_puts_attr_len(). */ static void t_puts(t_col, t_s, s, attr) - int t_col; + int *t_col; char_u *t_s; char_u *s; int attr; @@ -2159,7 +2173,8 @@ t_puts(t_col, t_s, s, attr) /* output postponed text */ msg_didout = TRUE; /* remember that line is not empty */ screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr); - msg_col += t_col; + msg_col += *t_col; + *t_col = 0; #ifdef FEAT_MBYTE /* If the string starts with a composing character don't increment the * column position for it. */ @@ -2173,7 +2188,6 @@ t_puts(t_col, t_s, s, attr) } } - /* * Returns TRUE when messages should be printed with mch_errmsg(). * This is used when there is no valid screen, so we can see error messages. @@ -2193,6 +2207,309 @@ msg_use_printf() ); } +/* + * Print a message when there is no valid screen. + */ + static void +msg_puts_printf(str, maxlen) + char_u *str; + int maxlen; +{ + char_u *s = str; + char_u buf[4]; + char_u *p; + +#ifdef WIN3264 + if (!(silent_mode && p_verbose == 0)) + mch_settmode(TMODE_COOK); /* handle '\r' and '\n' correctly */ +#endif + while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) + { + if (!(silent_mode && p_verbose == 0)) + { + /* NL --> CR NL translation (for Unix, not for "--version") */ + /* NL --> CR translation (for Mac) */ + p = &buf[0]; + if (*s == '\n' && !info_message) + *p++ = '\r'; +#if defined(USE_CR) && !defined(MACOS_X_UNIX) + else +#endif + *p++ = *s; + *p = '\0'; + if (info_message) /* informative message, not an error */ + mch_msg((char *)buf); + else + mch_errmsg((char *)buf); + } + + /* primitive way to compute the current column */ +#ifdef FEAT_RIGHTLEFT + if (cmdmsg_rl) + { + if (*s == '\r' || *s == '\n') + msg_col = Columns - 1; + else + --msg_col; + } + else +#endif + { + if (*s == '\r' || *s == '\n') + msg_col = 0; + else + ++msg_col; + } + ++s; + } + msg_didout = TRUE; /* assume that line is not empty */ + +#ifdef WIN3264 + if (!(silent_mode && p_verbose == 0)) + mch_settmode(TMODE_RAW); +#endif +} + +/* + * Show the more-prompt and handle the user response. + * This takes care of scrolling back and displaying previously displayed text. + * When at hit-enter prompt "typed_char" is the already typed character. + * Returns TRUE when jumping ahead to "confirm_msg_tail". + */ + static int +do_more_prompt(typed_char) + int typed_char; +{ + int used_typed_char = typed_char; + int oldState = State; + int c; +#ifdef FEAT_CON_DIALOG + int retval = FALSE; +#endif + int scroll; + msgchunk_T *mp_last = NULL; + msgchunk_T *mp; + int i; + + State = ASKMORE; +#ifdef FEAT_MOUSE + setmouse(); +#endif + msg_moremsg(FALSE); + for (;;) + { + /* + * Get a typed character directly from the user. + */ + if (used_typed_char != NUL) + { + c = used_typed_char; /* was typed at hit-enter prompt */ + used_typed_char = NUL; + } + else + c = get_keystroke(); + +#if defined(FEAT_MENU) && defined(FEAT_GUI) + if (c == K_MENU) + { + int idx = get_menu_index(current_menu, ASKMORE); + + /* Used a menu. If it starts with CTRL-Y, it must + * be a "Copy" for the clipboard. Otherwise + * assume that we end */ + if (idx == MENU_INDEX_INVALID) + continue; + c = *current_menu->strings[idx]; + if (c != NUL && current_menu->strings[idx][1] != NUL) + ins_typebuf(current_menu->strings[idx] + 1, + current_menu->noremap[idx], 0, TRUE, + current_menu->silent[idx]); + } +#endif + + scroll = 0; + switch (c) + { + case BS: /* scroll one line back */ + case K_BS: + case 'k': + case K_UP: + scroll = -1; + break; + + case CAR: /* one extra line */ + case NL: + case 'j': + case K_DOWN: + scroll = 1; + break; + + case 'u': /* Up half a page */ + case K_PAGEUP: + scroll = -(Rows / 2); + break; + + case 'd': /* Down half a page */ + scroll = Rows / 2; + break; + + case 'b': /* one page back */ + scroll = -(Rows - 1); + break; + + case ' ': /* one extra page */ + case K_PAGEDOWN: + case K_LEFTMOUSE: + scroll = Rows - 1; + break; + + case ':': /* start new command line */ +#ifdef FEAT_CON_DIALOG + if (!confirm_msg_used) +#endif + { + /* Since got_int is set all typeahead will be flushed, but we + * want to keep this ':', remember that in a special way. */ + typeahead_noflush(':'); + cmdline_row = Rows - 1; /* put ':' on this line */ + skip_redraw = TRUE; /* skip redraw once */ + need_wait_return = FALSE; /* don't wait in main() */ + } + /*FALLTHROUGH*/ + case 'q': /* quit */ + case Ctrl_C: + case ESC: +#ifdef FEAT_CON_DIALOG + if (confirm_msg_used) + { + /* Jump to the choices of the dialog. */ + retval = TRUE; + lines_left = Rows - 1; + } + else +#endif + { + got_int = TRUE; + quit_more = TRUE; + } + break; + +#ifdef FEAT_CLIPBOARD + case Ctrl_Y: + /* Strange way to allow copying (yanking) a modeless + * selection at the more prompt. Use CTRL-Y, + * because the same is used in Cmdline-mode and at the + * hit-enter prompt. However, scrolling one line up + * might be expected... */ + if (clip_star.state == SELECT_DONE) + clip_copy_modeless_selection(TRUE); + continue; +#endif + default: /* no valid response */ + msg_moremsg(TRUE); + continue; + } + + if (scroll != 0) + { + if (scroll < 0) + { + /* go to start of last line */ + if (mp_last == NULL) + mp = msg_sb_start(last_msgchunk); + else if (mp_last->sb_prev != NULL) + mp = msg_sb_start(mp_last->sb_prev); + else + mp = NULL; + + /* go to start of line at top of the screen */ + for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL; + ++i) + mp = msg_sb_start(mp->sb_prev); + + if (mp != NULL && mp->sb_prev != NULL) + { + /* Find line to be displayed at top. */ + for (i = 0; i > scroll; --i) + { + if (mp == NULL || mp->sb_prev == NULL) + break; + mp = msg_sb_start(mp->sb_prev); + if (mp_last == NULL) + mp_last = msg_sb_start(last_msgchunk); + else + mp_last = msg_sb_start(mp_last->sb_prev); + } + + if (scroll == -1 && screen_ins_lines(0, 0, 1, + (int)Rows, NULL) == OK) + { + /* clear last line, display line at top */ + screen_fill((int)Rows - 1, (int)Rows, 0, + (int)Columns, ' ', ' ', 0); + (void)disp_sb_line(0, mp); + } + else + { + /* redisplay */ + screenclear(); + for (i = 0; i < Rows - 1; ++i) + mp = disp_sb_line(i, mp); + } + scroll = 0; + } + } + else + { + /* First display any text that we scrolled back. */ + while (scroll > 0 && mp_last != NULL) + { + /* scroll up, display line at bottom */ + msg_scroll_up(); + screen_fill((int)Rows - 2, (int)Rows - 1, 0, + (int)Columns, ' ', ' ', 0); + mp_last = disp_sb_line((int)Rows - 2, mp_last); + --scroll; + } + } + + if (scroll <= 0) + { + /* displayed the requested text, more prompt again */ + msg_moremsg(FALSE); + continue; + } + + /* display more text, return to caller */ + lines_left = scroll; + } + + break; + } + + /* clear the --more-- message */ + screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + State = oldState; +#ifdef FEAT_MOUSE + setmouse(); +#endif + if (quit_more) + { + msg_row = Rows - 1; + msg_col = 0; + } +#ifdef FEAT_RIGHTLEFT + else if (cmdmsg_rl) + msg_col = Columns - 1; +#endif + +#ifdef FEAT_CON_DIALOG + return retval; +#else + return FALSE; +#endif +} + #if defined(USE_MCH_ERRMSG) || defined(PROTO) #ifdef mch_errmsg @@ -2344,15 +2661,15 @@ msg_screen_putchar(c, attr) msg_moremsg(full) int full; { - int attr; + int attr; + char_u *s = (char_u *)_("-- More --"); attr = hl_attr(HLF_M); - screen_puts((char_u *)_("-- More --"), (int)Rows - 1, 0, attr); + screen_puts(s, (int)Rows - 1, 0, attr); if (full) - screen_puts(more_back_used - ? (char_u *)_(" (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)") - : (char_u *)_(" (RET: line, SPACE: page, d: half page, q: quit)"), - (int)Rows - 1, 10, attr); + screen_puts((char_u *) + _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "), + (int)Rows - 1, vim_strsize(s), attr); } /* @@ -1580,9 +1580,15 @@ op_delete(oap) && *ml_get(oap->start.lnum) == NUL) { /* - * It's an error to operate on an empty region, when 'E' inclucded in + * It's an error to operate on an empty region, when 'E' included in * 'cpoptions' (Vi compatible). */ +#ifdef FEAT_VIRTUALEDIT + if (virtual_op) + /* Virtual editing: Nothing gets deleted, but we set the '[ and '] + * marks as if it happened. */ + goto setmarks; +#endif if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL) beep_flush(); return OK; @@ -1858,6 +1864,9 @@ op_delete(oap) msgmore(curbuf->b_ml.ml_line_count - old_lcount); +#ifdef FEAT_VIRTUALEDIT +setmarks: +#endif #ifdef FEAT_VISUAL if (oap->block_mode) { diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 6a2d44e7d..86ea3968f 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -22,6 +22,7 @@ char_u *eval_to_string_safe __ARGS((char_u *arg, char_u **nextcmd)); int eval_to_number __ARGS((char_u *expr)); list_T *eval_spell_expr __ARGS((char_u *badword, char_u *expr)); int get_spellword __ARGS((list_T *list, char_u **pp)); +typval_T *eval_expr __ARGS((char_u *arg, char_u **nextcmd)); void *call_func_retstr __ARGS((char_u *func, int argc, char_u **argv, int safe)); void *call_func_retlist __ARGS((char_u *func, int argc, char_u **argv, int safe)); void *save_funccal __ARGS((void)); @@ -59,6 +60,7 @@ void set_reg_var __ARGS((int c)); char_u *v_exception __ARGS((char_u *oldval)); char_u *v_throwpoint __ARGS((char_u *oldval)); char_u *set_cmdarg __ARGS((exarg_T *eap, char_u *oldarg)); +void clear_tv __ARGS((typval_T *varp)); char_u *get_var_value __ARGS((char_u *name)); void new_script_vars __ARGS((scid_T id)); void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var)); diff --git a/src/proto/message.pro b/src/proto/message.pro index db09d855c..faa03680c 100644 --- a/src/proto/message.pro +++ b/src/proto/message.pro @@ -39,6 +39,7 @@ void msg_puts_title __ARGS((char_u *s)); void msg_puts_long_attr __ARGS((char_u *longstr, int attr)); void msg_puts_long_len_attr __ARGS((char_u *longstr, int len, int attr)); void msg_puts_attr __ARGS((char_u *s, int attr)); +void clear_sb_text __ARGS((void)); int msg_use_printf __ARGS((void)); void mch_errmsg __ARGS((char *str)); void mch_msg __ARGS((char *str)); diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro index 7369a6441..6712cf151 100644 --- a/src/proto/quickfix.pro +++ b/src/proto/quickfix.pro @@ -24,5 +24,6 @@ char_u *skip_vimgrep_pat __ARGS((char_u *p, char_u **s, int *flags)); int get_errorlist __ARGS((list_T *list)); int set_errorlist __ARGS((list_T *list, int action)); void ex_cbuffer __ARGS((exarg_T *eap)); +void ex_cexpr __ARGS((exarg_T *eap)); void ex_helpgrep __ARGS((exarg_T *eap)); /* vim: set ft=c : */ diff --git a/src/proto/screen.pro b/src/proto/screen.pro index b5b6eec68..fd6a1fa92 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -37,6 +37,7 @@ void windgoto __ARGS((int row, int col)); void setcursor __ARGS((void)); int win_ins_lines __ARGS((win_T *wp, int row, int line_count, int invalid, int mayclear)); int win_del_lines __ARGS((win_T *wp, int row, int line_count, int invalid, int mayclear)); +int screen_ins_lines __ARGS((int off, int row, int line_count, int end, win_T *wp)); int screen_del_lines __ARGS((int off, int row, int line_count, int end, int force, win_T *wp)); int showmode __ARGS((void)); void unshowmode __ARGS((int force)); diff --git a/src/quickfix.c b/src/quickfix.c index d46578701..5847ae19d 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -88,7 +88,7 @@ struct eformat /* '-' do not include this line */ }; -static int qf_init_ext __ARGS((char_u *efile, buf_T *buf, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast)); +static int qf_init_ext __ARGS((char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast)); static void qf_new_list __ARGS((void)); static int qf_add_entry __ARGS((qfline_T **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid)); static void qf_msg __ARGS((void)); @@ -124,7 +124,7 @@ qf_init(efile, errorformat, newlist) { if (efile == NULL) return FAIL; - return qf_init_ext(efile, curbuf, errorformat, newlist, + return qf_init_ext(efile, curbuf, NULL, errorformat, newlist, (linenr_T)0, (linenr_T)0); } @@ -137,9 +137,10 @@ qf_init(efile, errorformat, newlist) * Return -1 for error, number of errors for success. */ static int -qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast) +qf_init_ext(efile, buf, tv, errorformat, newlist, lnumfirst, lnumlast) char_u *efile; buf_T *buf; + typval_T *tv; char_u *errorformat; int newlist; /* TRUE: start a new error list */ linenr_T lnumfirst; /* first line number to use */ @@ -176,6 +177,8 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast) char_u *directory = NULL; char_u *currfile = NULL; char_u *tail = NULL; + char_u *p_str = NULL; + listitem_T *p_li = NULL; struct dir_stack_T *file_stack = NULL; regmatch_T regmatch; static struct fmtpattern @@ -222,7 +225,7 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast) * regex prog. Only a few % characters are allowed. */ /* Use the local value of 'errorformat' if it's set. */ - if (errorformat == p_efm && *buf->b_p_efm != NUL) + if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) efm = buf->b_p_efm; else efm = errorformat; @@ -432,6 +435,14 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast) /* Always ignore case when looking for a matching error. */ regmatch.rm_ic = TRUE; + if (tv != NULL) + { + if (tv->v_type == VAR_STRING) + p_str = tv->vval.v_string; + else if (tv->v_type == VAR_LIST) + p_li = tv->vval.v_list->lv_first; + } + /* * Read the lines in the error file one by one. * Try to recognize one of the error formats in each line. @@ -441,10 +452,57 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast) /* Get the next line. */ if (fd == NULL) { - if (buflnum > lnumlast) - break; - vim_strncpy(IObuff, ml_get_buf(buf, buflnum++, FALSE), - CMDBUFFSIZE - 2); + if (tv != NULL) + { + int len; + + if (tv->v_type == VAR_STRING) + { + /* Get the next line from the supplied string */ + char_u *p; + + if (!*p_str) /* Reached the end of the string */ + break; + + p = vim_strchr(p_str, '\n'); + if (p) + len = p - p_str + 1; + else + len = STRLEN(p_str); + + if (len > CMDBUFFSIZE - 2) + vim_strncpy(IObuff, p_str, CMDBUFFSIZE - 2); + else + vim_strncpy(IObuff, p_str, len); + + p_str += len; + } + else if (tv->v_type == VAR_LIST) + { + /* Get the next line from the supplied list */ + while (p_li && p_li->li_tv.v_type != VAR_STRING) + p_li = p_li->li_next; /* Skip non-string items */ + + if (!p_li) /* End of the list */ + break; + + len = STRLEN(p_li->li_tv.vval.v_string); + if (len > CMDBUFFSIZE - 2) + len = CMDBUFFSIZE - 2; + + vim_strncpy(IObuff, p_li->li_tv.vval.v_string, len); + + p_li = p_li->li_next; /* next item */ + } + } + else + { + /* Get the next line from the supplied buffer */ + if (buflnum > lnumlast) + break; + vim_strncpy(IObuff, ml_get_buf(buf, buflnum++, FALSE), + CMDBUFFSIZE - 2); + } } else if (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) == NULL) break; @@ -1446,7 +1504,6 @@ qf_list(eap) int idx1 = 1; int idx2 = -1; int need_return = TRUE; - int last_printed = 1; char_u *arg = eap->arg; int all = eap->forceit; /* if not :cl!, only show recognised errors */ @@ -1467,7 +1524,6 @@ qf_list(eap) if (idx2 < 0) idx2 = (-idx2 > i) ? 0 : idx2 + i + 1; - more_back_used = TRUE; if (qf_lists[qf_curlist].qf_nonevalid) all = TRUE; qfp = qf_lists[qf_curlist].qf_start; @@ -1478,79 +1534,59 @@ qf_list(eap) if (need_return) { msg_putchar('\n'); + if (got_int) + break; need_return = FALSE; } - if (more_back == 0) - { - fname = NULL; - if (qfp->qf_fnum != 0 + + fname = NULL; + if (qfp->qf_fnum != 0 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) - { - fname = buf->b_fname; - if (qfp->qf_type == 1) /* :helpgrep */ - fname = gettail(fname); - } - if (fname == NULL) - sprintf((char *)IObuff, "%2d", i); - else - vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", + { + fname = buf->b_fname; + if (qfp->qf_type == 1) /* :helpgrep */ + fname = gettail(fname); + } + if (fname == NULL) + sprintf((char *)IObuff, "%2d", i); + else + vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char *)fname); - msg_outtrans_attr(IObuff, i == qf_lists[qf_curlist].qf_index - ? hl_attr(HLF_L) : hl_attr(HLF_D)); - if (qfp->qf_lnum == 0) - IObuff[0] = NUL; - else if (qfp->qf_col == 0) - sprintf((char *)IObuff, ":%ld", qfp->qf_lnum); - else - sprintf((char *)IObuff, ":%ld col %d", + msg_outtrans_attr(IObuff, i == qf_lists[qf_curlist].qf_index + ? hl_attr(HLF_L) : hl_attr(HLF_D)); + if (qfp->qf_lnum == 0) + IObuff[0] = NUL; + else if (qfp->qf_col == 0) + sprintf((char *)IObuff, ":%ld", qfp->qf_lnum); + else + sprintf((char *)IObuff, ":%ld col %d", qfp->qf_lnum, qfp->qf_col); - sprintf((char *)IObuff + STRLEN(IObuff), "%s:", + sprintf((char *)IObuff + STRLEN(IObuff), "%s:", (char *)qf_types(qfp->qf_type, qfp->qf_nr)); - msg_puts_attr(IObuff, hl_attr(HLF_N)); - if (qfp->qf_pattern != NULL) - { - qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); - STRCAT(IObuff, ":"); - msg_puts(IObuff); - } - msg_puts((char_u *)" "); + msg_puts_attr(IObuff, hl_attr(HLF_N)); + if (qfp->qf_pattern != NULL) + { + qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); + STRCAT(IObuff, ":"); + msg_puts(IObuff); + } + msg_puts((char_u *)" "); - /* Remove newlines and leading whitespace from the text. - * For an unrecognized line keep the indent, the compiler may - * mark a word with ^^^^. */ - qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) + /* Remove newlines and leading whitespace from the text. For an + * unrecognized line keep the indent, the compiler may mark a word + * with ^^^^. */ + qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff, IOSIZE); - msg_prt_line(IObuff, FALSE); - out_flush(); /* show one line at a time */ - need_return = TRUE; - last_printed = i; - } - } - if (more_back) - { - /* scrolling backwards from the more-prompt */ - /* TODO: compute the number of items from the screen lines */ - more_back = more_back * 2 - 1; - while (i > last_printed - more_back && i > idx1) - { - do - { - qfp = qfp->qf_prev; - --i; - } - while (i > idx1 && !qfp->qf_valid && !all); - } - more_back = 0; - } - else - { - qfp = qfp->qf_next; - ++i; + msg_prt_line(IObuff, FALSE); + out_flush(); /* show one line at a time */ + need_return = TRUE; } + + qfp = qfp->qf_next; + ++i; ui_breakcheck(); } - more_back_used = FALSE; } /* @@ -2330,7 +2366,7 @@ ex_cnext(eap) } /* - * ":cfile" command. + * ":cfile"/":cgetfile"/":caddfile" commands. */ void ex_cfile(eap) @@ -2338,7 +2374,19 @@ ex_cfile(eap) { if (*eap->arg != NUL) set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE); - if (qf_init(p_ef, p_efm, TRUE) > 0 && eap->cmdidx == CMD_cfile) + + /* + * This function is used by the :cfile, :cgetfile and :caddfile + * commands. + * :cfile always creates a new quickfix list and jumps to the + * first error. + * :cgetfile creates a new quickfix list but doesn't jump to the + * first error. + * :caddfile adds to an existing quickfix list. If there is no + * quickfix list then a new list is created. + */ + if (qf_init(p_ef, p_efm, eap->cmdidx != CMD_caddfile) > 0 + && eap->cmdidx == CMD_cfile) qf_jump(0, 0, eap->forceit); /* display first error */ } @@ -2917,11 +2965,32 @@ ex_cbuffer(eap) || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count) EMSG(_(e_invrange)); else - qf_init_ext(NULL, buf, p_efm, TRUE, eap->line1, eap->line2); + qf_init_ext(NULL, buf, NULL, p_efm, TRUE, eap->line1, eap->line2); } } /* + * ":cexpr {expr}" command. + */ + void +ex_cexpr(eap) + exarg_T *eap; +{ + typval_T *tv; + + tv = eval_expr(eap->arg, NULL); + if (!tv || (tv->v_type != VAR_STRING && tv->v_type != VAR_LIST) || + (tv->v_type == VAR_STRING && !tv->vval.v_string) || + (tv->v_type == VAR_LIST && !tv->vval.v_list)) + return; + + if (qf_init_ext(NULL, NULL, tv, p_efm, TRUE, (linenr_T)0, (linenr_T)0) > 0) + qf_jump(0, 0, eap->forceit); /* display first error */ + + clear_tv(tv); +} + +/* * ":helpgrep {pattern}" */ void diff --git a/src/screen.c b/src/screen.c index c07691e86..a3f3e0bd1 100644 --- a/src/screen.c +++ b/src/screen.c @@ -169,7 +169,6 @@ static void redraw_block __ARGS((int row, int end, win_T *wp)); #endif static int win_do_lines __ARGS((win_T *wp, int row, int line_count, int mayclear, int del)); static void win_rest_invalid __ARGS((win_T *wp)); -static int screen_ins_lines __ARGS((int, int, int, int, win_T *wp)); static void msg_pos_mode __ARGS((void)); #if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT) static int fillchar_status __ARGS((int *attr, int is_curwin)); @@ -7618,7 +7617,7 @@ win_rest_invalid(wp) * * return FAIL for failure, OK for success. */ - static int + int screen_ins_lines(off, row, line_count, end, wp) int off; int row; @@ -770,11 +770,6 @@ do_tag(tag, type, count, forceit, verbose) #endif break; } -#if 0 - /* avoid the need to hit <CR> when jumping to another file */ - msg_scrolled = 0; - redraw_all_later(NOT_VALID); -#endif cur_match = i - 1; } diff --git a/src/version.h b/src/version.h index a2074a2f8..03557c29a 100644 --- a/src/version.h +++ b/src/version.h @@ -36,5 +36,5 @@ #define VIM_VERSION_NODOT "vim70aa" #define VIM_VERSION_SHORT "7.0aa" #define VIM_VERSION_MEDIUM "7.0aa ALPHA" -#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Jul 25)" -#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Jul 25, compiled " +#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Jul 27)" +#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Jul 27, compiled " |