changeset 791:98a88a884610 v7.0230

updated for version 7.0230
author vimboss
date Mon, 20 Mar 2006 21:59:49 +0000
parents c8680debe1cc
children 860b73800cd7
files runtime/doc/quickfix.txt runtime/doc/todo.txt runtime/doc/version7.txt runtime/doc/vimball.txt runtime/plugin/vimball.vim src/eval.c src/ex_cmds.h src/gui_beval.c src/gui_gtk_x11.c src/menu.c src/ui.c
diffstat 11 files changed, 683 insertions(+), 144 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1,4 +1,4 @@
-*quickfix.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 19
+*quickfix.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 20
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -878,6 +878,7 @@ prefixes are:
 	%W		start of a multi-line warning message
 	%I		start of a multi-line informational message
 	%A		start of a multi-line message (unspecified type)
+	%>		for next line start with current pattern again |efm-%>|
 	%C		continuation of a multi-line message
 	%Z		end of a multi-line message
 These can be used with '+' and '-', see |efm-ignore| below.
@@ -929,6 +930,17 @@ starting with a space, followed by any c
 it also hides line 7 which would trigger a separate error message otherwise.
 Error format strings are always parsed pattern by pattern until the first
 match occurs.
+							*efm-%>*
+The %> item can be used to avoid trying patterns that appear earlier in
+'errorformat'.  This is useful for patterns that match just about anything.
+For example, if the error looks like this:
+
+	Error in line 123 of foo.c: ~
+	unknown variable "i" ~
+
+This can be found with: >
+	:set efm=xxx,%E%>Error in line %l of %f:,%Z%m
+Where "xxx" has a pattern that would also match the second line.
 
 Important: There is no memory of what part of the errorformat matched before;
 every line in the error file gets a complete new run through the error format
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 19
+*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 20
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,15 +30,23 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-'errorformat': Add a flag %? to check for a match with the next item first.
-Helps for continuation lines that may contain just about anything, e.g. an
-error message.
-    error 99 in file foo.c line 1234:
-	something is wrong here
+Links in docs to vimball docs.
+
+HTML indenting can be slow, find out why.
+Add a function to get the current time in usec.  reltime([start, [end]])
+    reltime().sec == seconds, reltime().usec = microseconds
+    reltime(start) current time relative to [start]
+	echo timestring(reltime(start), 3)  (3 is nr of digits after dot)
+    reltime(start, end) difference between start and end
 
-Gnome GUI: lots of error messages during startup.  These go away when not
-using the notebook for tab labels.  Still similar error messages when moving
-the toolbar to another location.
+Include GetLatestVimScripts script?
+
+Adjust src/main.aap for installing manpages like in Makefile.
+    And for generating Vim.app for the Mac.
+    Install spell files with src/main.aap.
+
+Gnome2: When moving the toolbar out of the dock, so that it becomes floating,
+it can no longer be moved.
 
 Win32: Describe how to do debugging. (George Reilly)
 
@@ -51,28 +59,8 @@ 8   Add patch from Muraoka Taro (Mar 16)
 - With 'nopaste' pasting is wrong, with 'paste' Command-V doesn't work.
   (Alan Schmitt)
 
-EMBEDDING: Make it possible to run Vim inside a window of another program.
-For GTK Neil Bird has a patch to use Vim like a widget.
-
-Ctags still hasn't included the patch.  Darren is looking for someone to do
-maintenance.  Is there another solution?
-
-HTML indenting can be slow, find out why.
-Add a function to get the current time in usec.  reltime([start, [end]])
-    reltime().sec == seconds, reltime().usec = microseconds
-    reltime(start) current time relative to [start]
-	echo timestring(reltime(start), 3)  (3 is nr of digits after dot)
-    reltime(start, end) difference between start and end
-Profiling:
-    - :profile pause
-    - :profile resume
-
-Adjust src/main.aap for installing manpages like in Makefile.
-    And for generating Vim.app for the Mac.
-    Install spell files with src/main.aap.
-
-Add ":smap", Select mode mapping?  Otherwise: ":sunmap", so that Visual mode
-mappings for normal keys can be removed from Select mode.
+Darren is including the patch in ctags.  Test it when it's ready.  Change
+"typename" to "typeref" in C complete code.
 
 Add more tests for all new functionality in Vim 7.  Especially new functions.
 
@@ -81,7 +69,6 @@ text of a previous change.
 
 
 Awaiting updated patches:
-7   Updated Ruby interface. (Ryan Paul)
 8   Add ":n" to fnamemodify(): normalize path, remove "../" when possible.
     Aric Blumer has a patch for this.
     He will update the patch for 6.3.
@@ -1446,7 +1433,6 @@ 7   Wild idea: Not only set highlighting
 7   CTRL-] checks the highlight group for finding out what the tag is.
 7   Add an explanation how a list of words can be used to highlight misspelled
     words.
-7   Command line completion for ":find" should search in 'path'.
 8   Add more command line completion for :syntax.
 8   Add more command line completion for :highlight.
 8   Add more command line completion for :sign.
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 18
+*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 20
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -36,6 +36,7 @@ Debugger support			|new-debug-support|
 Remote file explorer			|new-netrw-explore|
 Define an operator			|new-define-operator|
 Mapping to an expression		|new-map-expression|
+Visual and Select mode mappings		|new-map-select|
 Location list				|new-location-list|
 Various new items			|new-items-7|
 
@@ -143,6 +144,10 @@ difficult to locate errors.  Now the lin
 reported, relative to the function start.  This also means that line numbers
 for ":breakadd func" are different.
 
+When defining a user command with |:command| the special items could be
+abbreviated.  This caused unexpected behavior, such as <li> being recognized
+as <line1>.  The items can no longer be abbreviated.
+
 ==============================================================================
 NEW FEATURES						*new-7*
 
@@ -161,8 +166,8 @@ The |string()| function can be used to g
 variable.  Works for Numbers, Strings and composites of them.  Then |eval()|
 can be used to turn the string back into the variable value.
 
-The |:let| command can now use ":let var += expr" like using ":let var = var +
-expr".  "-=" and ".=" works in a similar way.
+The |:let| command can now use "+=".  ":let var += expr" works like
+":let var = var + expr".  "-=" and ".=" works in a similar way.
 
 With the |:profile| command you can find out where your function or script
 wastes its time.
@@ -493,6 +498,20 @@ Here the dot will be mapped to whatever 
 Also works for abbreviations.  See |:map-<expr>| for the details.
 
 
+Visual and Select mode mappings				*new-map-select*
+-------------------------------
+
+Previously Visual mode mappings applied both to Visual and Select mode.  With
+a trick to have the mappings work in Select mode like they would in Visual
+mode.
+
+Commands have been added to define mappings for Visual and Select mode
+separately: |:xmap| and |:smap|.  With the associated "noremap" and "unmap"
+commands.
+
+The same is done for menus: |:xmenu|, |:smenu|, etc.
+
+
 Location list						*new-location-list*
 -------------
 
@@ -1103,6 +1122,13 @@ getwinvar() now also works to obtain a b
 window.
 
 Added the "%s" item to 'errorformat'. (Yegappan Lakshmanan)
+Added the "%>" item to 'errorformat'.
+
+For 'errorformat' it was not possible to have a file name that contains the
+character that follows after "%f".  For example, in "%f:%l:%m" the file name
+could not contain ":".  Now include the first ":" where the rest of the
+pattern matches.  In the example a ":" not followed by a line number is
+included in the file name. (suggested by Emanuele Giaquinta)
 
 GTK GUI: use the GTK file dialog when it's available.  Mix from patches by
 Grahame Bowland and Evan Webb.
@@ -1133,12 +1159,6 @@ Lakshmanan)
 Win32: Balloons can have multiple lines if common controls supports it.
 (Sergey Khorev)
 
-For 'errorformat' it was not possible to have a file name that contains the
-character that follows after "%f".  For example, in "%f:%l:%m" the file name
-could not contain ":".  Now include the first ":" where the rest of the
-pattern matches.  In the example a ":" not followed by a line number is
-included in the file name. (suggested by Emanuele Giaquinta)
-
 For command-line completion the matches for various types of arguments are now
 sorted: user commands, variables, syntax names, etc.
 
@@ -1233,6 +1253,8 @@ Win32: In the batch files generated by t
 $VIM if it's set.  Example provided by Mathias Michaelis.
 Also create a vimtutor.bat batch file.
 
+The 'balloonexpr' option is now |global-local|.
+
 ==============================================================================
 COMPILE TIME CHANGES					*compile-changes-7*
 
@@ -1384,9 +1406,6 @@ just before it is invoked
 VMS: Occasionally CR characters were inserted in the file.  Expansion of
 environment variables was not correct. (Zoltan Arpadffy)
 
-VMS: Improved low level char input (affects just console mode). (Zoltan
-Arpadffy)
-
 UTF-8: When 'delcombine' is set "dw" only deleted the last combining character
 from the first character of the word.
 
@@ -1733,6 +1752,9 @@ change the window size ourselves, but th
 Peek for a character to get any window resize events and fix 'columns' and
 'lines' to undo this.
 
+When using the GTK plug mechanism, resizing and focus was not working
+properly. (Neil Bird)
+
 After deleting files from the argument list a session file generated with
 ":mksession" may contain invalid ":next" commands.
 
new file mode 100644
--- /dev/null
+++ b/runtime/doc/vimball.txt
@@ -0,0 +1,66 @@
+*vimball.txt*	Vimball Archiver				Mar 20, 2006
+Author:  Charles E. Campbell, Jr.  <NdrOchip@ScampbellPfamily.AbizM>
+	  (remove NOSPAM from Campbell's email first)
+Copyright: (c) 2004-2006 by Charles E. Campbell, Jr.	*Vimball-copyright*
+           The VIM LICENSE applies to Vimball.vim, and Vimball.txt
+           (see |copyright|) except use "Vimball" instead of "Vim".
+	   No warranty, express or implied.
+	   Use At-Your-Own-Risk!
+
+==============================================================================
+1. Contents					*vimball* *vimball-contents*
+
+	1. Contents......................................: |vimball-contents|
+	2. Vimball Manual................................: |vimball-manual|
+	3. Vimball History...............................: |vimball-history|
+
+
+==============================================================================
+2. Vimball Manual					*vimball-manual*
+
+							*:MkVimball*
+		:[range]MkVimball[!] filename
+
+	This command takes lines holding a path to files to be included in
+	your vimball; as an example: >
+		plugin/something.vim
+		doc/something.txt
+<	using MkVimball on this range will create a file called
+	"filename.vba" which can be used by Vimball.vim to re-create these
+	files.  If the "filename.vba" file already exists, then MkVimball
+	will issue a warning and not create the file.
+
+	However, if you use the exclamation point (!), then MkVimball will
+	create the "filename.vba" file, overwriting it if it already exists.
+	This behavior resembles that for |:w|.
+
+							*vimball-extract*
+		vim filename.vba
+
+	Simply editing a Vimball will cause Vimball.vim to tell the user to
+	source the file to extract its contents.
+
+	Extraction will only proceed if the first line of a putative vimball
+	file holds the "Vimball Archiver by Charles E.  Campbell, Jr., Ph.D."
+	line.
+
+		:VimballList				*vimball-vimballlist*
+	
+	This command will tell Vimball to list the files in the archive, along
+	with their lengths in lines.
+
+
+==============================================================================
+3. Vimball History					*vimball-history*
+
+	3  : Mar 20, 2006 * removed query, now requires sourcing to be
+	                    extracted (:so %).  Message to that effect
+			    included.
+			  * :VimballList  now shows files that would be
+			    extracted.
+	2  : Mar 20, 2006 * query, :UseVimball included
+	1  : Mar 20, 2006 * initial release
+
+
+==============================================================================
+vim:tw=78:ts=8:ft=help:fdm=marker
new file mode 100644
--- /dev/null
+++ b/runtime/plugin/vimball.vim
@@ -0,0 +1,256 @@
+" vimball : construct a file containing both paths and files
+" Author: Charles E. Campbell, Jr.
+" Date:   Mar 20, 2006
+" Version: 3
+" GetLatestVimScripts: 1502 1 :AutoInstall: vimball.vim
+" Copyright: (c) 2004-2006 by Charles E. Campbell, Jr.
+"            The VIM LICENSE applies to Vimball.vim, and Vimball.txt
+"            (see |copyright|) except use "Vimball" instead of "Vim".
+"            No warranty, express or implied.
+"  *** ***   Use At-Your-Own-Risk!   *** ***
+
+" ---------------------------------------------------------------------
+"  Load Once: {{{1
+if &cp || exists("g:loaded_vimball")
+ finish
+endif
+
+let s:keepcpo        = &cpo
+let g:loaded_vimball = "v3"
+set cpo&vim
+
+" ------------------------------------------------------------------------------
+" Public Interface: {{{1
+com! -ra -na=+ -bang MkVimball call s:MkVimball(<line1>,<line2>,<bang>0,<f-args>)
+com! -na=0 UseVimball  call s:Vimball(1)
+com! -na=0 VimballList call s:Vimball(0)
+au BufReadPost *.vba echohl WarningMsg | echo "Source this file to extract it! (:so %)" | echohl None
+
+" =====================================================================
+"  Functions: {{{1
+
+" ---------------------------------------------------------------------
+" MkVimball: creates a vimball given a list of paths to files {{{2
+" Vimball Format:
+"     path
+"     filesize
+"     [file]
+"     path
+"     filesize
+"     [file]
+fun! s:MkVimball(line1,line2,writelevel,vimballname) range
+"  call Dfunc("MkVimball(line1=".a:line1." line2=".a:line2." writelevel=".a:writelevel." vimballname<".a:vimballname.">")
+  let vbname= substitute(a:vimballname,'\.[^.]*$','','e').'.vba'
+  if !a:writelevel && filereadable(vbname)
+   echohl Error | echoerr "(MkVimball) file<".vbname."> exists; use ! to insist" | echohl None
+"   call Dret("MkVimball : file<".vbname."> already exists; use ! to insist")
+   return
+  endif
+
+  " user option bypass
+  let eikeep= &ei
+  set ei=all
+
+  let home   = substitute(&rtp,',.*$','','')
+  let curdir = getcwd()
+  exe "cd ".home
+
+  " record current tab, initialize while loop index
+  let curtabnr = tabpagenr()
+  let linenr   = a:line1
+"  call Decho("curtabnr=".curtabnr)
+
+  while linenr <= a:line2
+   let svfile  = getline(linenr)
+"   call Decho("svfile<".svfile.">")
+ 
+   if !filereadable(svfile)
+    echohl Error | echo "unable to read file<".svfile.">" | echohl None
+    let &ei= eikeep
+    exe "cd ".curdir
+"    call Dret("MkVimball")
+    return
+   endif
+ 
+   " create/switch to mkvimball tab
+   if !exists("vbtabnr")
+    tabnew
+    silent! file Vimball
+    let vbtabnr= tabpagenr()
+   else
+    exe "tabn ".vbtabnr
+   endif
+ 
+   let lastline= line("$") + 1
+   if lastline == 2 && getline("$") == ""
+	call setline(1,'" Vimball Archiver by Charles E. Campbell, Jr., Ph.D.')
+	call setline(2,'UseVimball')
+	call setline(3,'finish')
+	let lastline= 4
+   endif
+   call setline(lastline  ,svfile)
+   call setline(lastline+1,0)
+   exe "$r ".svfile
+   call setline(lastline+1,line("$") - lastline - 1)
+"   call Decho("lastline=".lastline." line$=".line("$"))
+
+  " restore to normal tab
+   exe "tabn ".curtabnr
+   let linenr= linenr + 1
+  endwhile
+
+  " write the vimball
+  exe "tabn ".vbtabnr
+  exe "cd ".curdir
+  if a:really
+   if a:writelevel
+    exe "w! ".vbname
+   else
+    exe "w ".vbname
+   endif
+  endif
+"  call Decho("Vimball<".vbname."> created")
+  echo "Vimball<".vbname."> created"
+
+  " remove the evidence
+  setlocal nomod bh=wipe
+  exe "tabn ".curtabnr
+  exe "tabc ".vbtabnr
+
+  " restore options
+  let &ei= eikeep
+
+"  call Dret("MkVimball")
+endfun
+
+" ---------------------------------------------------------------------
+" Vimball: {{{2
+fun! s:Vimball(really)
+"  call Dfunc("Vimball(really=".a:really.")")
+
+  if getline(1) !~ '^" Vimball Archiver by Charles E. Campbell, Jr., Ph.D.$'
+   echoerr "(Vimball) The current file does not appear to be a Vimball!"
+"   call Dret("Vimball")
+   return
+  endif
+
+  " initialize
+  let regakeep = @a
+  let eikeep   = &ei
+  let vekeep   = &ve
+  let makeep   = getpos("'a")
+  let curtabnr = tabpagenr()
+  set ei=all ve=all
+
+  " set up vimball tab
+  tabnew
+  silent! file Vimball
+  let vbtabnr= tabpagenr()
+  let didhelp= ""
+
+  " go to vim plugin home
+  let home   = substitute(&rtp,',.*$','','')
+  let curdir = getcwd()
+"  call Decho("exe cd ".home)
+  exe "cd ".home
+  let linenr  = 4
+  let filecnt = 0
+
+  " give title to listing of (extracted) files from Vimball Archive
+  if a:really
+   echohl Title | echomsg "Vimball Archive" | echohl None
+  else
+   echohl Title | echomsg "Vimball Archive Listing" | echohl None
+  endif
+
+  " apportion vimball contents to various files
+"  call Decho("exe tabn ".curtabnr)
+  exe "tabn ".curtabnr
+"  call Decho("linenr=".linenr." line$=".line("$"))
+  while 1 < linenr && linenr < line("$")
+   let fname   = getline(linenr)
+   let fsize   = getline(linenr+1)
+   let filecnt = filecnt + 1
+   if a:really
+    echomsg "extracted <".fname.">: ".fsize." lines"
+   else
+    echomsg "would extract <".fname.">: ".fsize." lines"
+   endif
+"   call Decho(linenr.": will extract file<".fname.">")
+"   call Decho((linenr+1).": fsize=".fsize)
+
+   " make directories if they don't exist yet
+   let fnamebuf= fname
+   while fnamebuf =~ '/'
+   	let dirname  = substitute(fnamebuf,'/.*$','','e')
+   	let fnamebuf = substitute(fnamebuf,'^.\{-}/\(.*\)$','\1','e')
+	if !isdirectory(dirname)
+"	 call Decho("making <".dirname.">")
+	 call mkdir(dirname)
+	endif
+	exe "cd ".dirname
+   endwhile
+   exe "cd ".home
+
+   " grab specified qty of lines and place into "a" buffer
+   exe linenr
+   norm! jjma
+   exe (linenr + fsize + 1)
+   silent norm! "ay'a
+"   call Decho("yanked ".fsize." lines into register-a")
+
+"   call Decho("didhelp<".didhelp."> fname<".fname.">")
+   if didhelp == "" && fname =~ 'doc/[^/]\+\.txt$'
+   	let didhelp= substitute(fname,'^\(.*\<doc\)[/\\][^.]*\.txt$','\1','e')
+"	call Decho("didhelp<".didhelp.">")
+   endif
+
+   " copy "a" buffer into tab
+"   call Decho('copy "a buffer into tab#'.vbtabnr)
+   exe "tabn ".vbtabnr
+   silent! %d
+   silent norm! "aPGdd1G
+"   call Decho("rega<".@a.">")
+
+   " write tab to file
+"   call Decho("exe w! ".fname)
+   exe "silent w! ".fname
+
+"   call Decho("exe tabn ".curtabnr)
+   exe "tabn ".curtabnr
+"   let oldlinenr = linenr " Decho
+   let linenr    = linenr + fsize + 2
+"   call Decho("update linenr= [linenr=".oldlinenr."] + [fsize=".fsize."] + 2 = ".linenr)
+  endwhile
+
+  " set up help
+"  call Decho("about to set up help: didhelp<".didhelp.">")
+  if didhelp != ""
+"   call Decho("exe helptags ".home."/".didhelp)
+   exe "helptags ".home."/".didhelp
+   echomsg "did helptags"
+  endif
+
+  " make sure a "Press ENTER..." prompt appears to keep the messages showing!
+  while filecnt < &ch
+   echomsg " "
+   let filecnt= filecnt + 1
+  endwhile
+
+  " restore events, delete tab and buffer
+  exe "tabn ".vbtabnr
+  setlocal nomod bh=wipe
+  exe "tabn ".curtabnr
+  exe "tabc ".vbtabnr
+  let &ei= eikeep
+  let @a = regakeep
+  if makeep[0] != 0
+   " restore mark a
+"   call Decho("restore mark-a: makeep=".string(makeep))
+   call setpos("'a",makeep)
+   ka
+  endif
+  exe "cd ".curdir
+
+"  call Dret("Vimball")
+endfun
--- a/src/eval.c
+++ b/src/eval.c
@@ -19382,7 +19382,7 @@ call_user_func(fp, argcount, argvars, re
 	}
     }
 #ifdef FEAT_PROFILE
-    if (do_profiling)
+    if (do_profiling == PROF_YES)
     {
 	if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
 	    func_do_profile(fp);
@@ -19417,7 +19417,8 @@ call_user_func(fp, argcount, argvars, re
     }
 
 #ifdef FEAT_PROFILE
-    if (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling))
+    if (do_profiling == PROF_YES && (fp->uf_profiling
+		    || (fc.caller != NULL && &fc.caller->func->uf_profiling)))
     {
 	profile_end(&fp->uf_tm_start);
 	profile_sub_wait(&wait_start, &fp->uf_tm_start);
@@ -19467,7 +19468,7 @@ call_user_func(fp, argcount, argvars, re
     sourcing_lnum = save_sourcing_lnum;
     current_SID = save_current_SID;
 #ifdef FEAT_PROFILE
-    if (do_profiling)
+    if (do_profiling == PROF_YES)
 	script_prof_restore(&wait_start);
 #endif
 
@@ -19710,7 +19711,7 @@ get_func_line(c, cookie, indent)
 	fcp->dbg_tick = debug_tick;
     }
 #ifdef FEAT_PROFILE
-    if (do_profiling)
+    if (do_profiling == PROF_YES)
 	func_line_end(cookie);
 #endif
 
@@ -19731,7 +19732,7 @@ get_func_line(c, cookie, indent)
 	    retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
 	    sourcing_lnum = fcp->linenr;
 #ifdef FEAT_PROFILE
-	    if (do_profiling)
+	    if (do_profiling == PROF_YES)
 		func_line_start(cookie);
 #endif
 	}
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -821,12 +821,22 @@ EX(CMD_slast,		"slast",	ex_last,
 			EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_smagic,		"smagic",	ex_submagic,
 			RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_smap,		"smap",		ex_map,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_smapclear,	"smapclear",	ex_mapclear,
+			EXTRA|TRLBAR|CMDWIN),
+EX(CMD_smenu,		"smenu",	ex_menu,
+			RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_snext,		"snext",	ex_next,
 			RANGE|NOTADR|BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_sniff,		"sniff",	ex_sniff,
 			EXTRA|TRLBAR),
 EX(CMD_snomagic,	"snomagic",	ex_submagic,
 			RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_snoremap,	"snoremap",	ex_map,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_snoremenu,	"snoremenu",	ex_menu,
+			RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_source,		"source",	ex_source,
 			BANG|FILE1|TRLBAR|SBOXOK|CMDWIN),
 EX(CMD_sort,		"sort",		ex_sort,
@@ -867,6 +877,10 @@ EX(CMD_stselect,	"stselect",	ex_stag,
 			BANG|TRLBAR|WORD1),
 EX(CMD_sunhide,		"sunhide",	ex_buffer_all,
 			RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sunmap,		"sunmap",	ex_unmap,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_sunmenu,		"sunmenu",	ex_menu,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_suspend,		"suspend",	ex_stop,
 			TRLBAR|BANG|CMDWIN),
 EX(CMD_sview,		"sview",	ex_splitview,
@@ -1035,6 +1049,20 @@ EX(CMD_xit,		"xit",		ex_exit,
 			RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN),
 EX(CMD_xall,		"xall",		do_wqall,
 			BANG|TRLBAR),
+EX(CMD_xmap,		"xmap",		ex_map,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_xmapclear,	"xmapclear",	ex_mapclear,
+			EXTRA|TRLBAR|CMDWIN),
+EX(CMD_xmenu,		"xmenu",	ex_menu,
+			RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_xnoremap,	"xnoremap",	ex_map,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_xnoremenu,	"xnoremenu",	ex_menu,
+			RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_xunmap,		"xunmap",	ex_unmap,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_xunmenu,		"xunmenu",	ex_menu,
+			EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
 EX(CMD_yank,		"yank",		ex_operators,
 			RANGE|WHOLEFOLD|REGSTR|COUNT|TRLBAR|CMDWIN),
 EX(CMD_z,		"z",		ex_z,
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -28,6 +28,8 @@ general_beval_cb(beval, state)
     char_u	*text;
     static char_u  *result = NULL;
     long	winnr = 0;
+    char_u	*bexpr;
+    buf_T	*save_curbuf;
 #ifdef FEAT_WINDOWS
     win_T	*cw;
 #endif
@@ -39,39 +41,51 @@ general_beval_cb(beval, state)
 	return;
 
 #ifdef FEAT_EVAL
-    if (*p_bexpr != NUL
-	    && get_beval_info(balloonEval, TRUE, &wp, &lnum, &text, &col) == OK)
+    if (get_beval_info(balloonEval, TRUE, &wp, &lnum, &text, &col) == OK)
     {
+	bexpr = (*wp->w_buffer->b_p_bexpr == NUL) ? p_bexpr
+						    : wp->w_buffer->b_p_bexpr;
+	if (*bexpr != NUL)
+	{
 # ifdef FEAT_WINDOWS
-	/* Convert window pointer to number. */
-	for (cw = firstwin; cw != wp; cw = cw->w_next)
-	    ++winnr;
+	    /* Convert window pointer to number. */
+	    for (cw = firstwin; cw != wp; cw = cw->w_next)
+		++winnr;
 # endif
 
-	set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum);
-	set_vim_var_nr(VV_BEVAL_WINNR, winnr);
-	set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum);
-	set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1));
-	set_vim_var_string(VV_BEVAL_TEXT, text, -1);
-	vim_free(text);
-
-	use_sandbox = was_set_insecurely((char_u *)"balloonexpr", 0);
-	if (use_sandbox)
-	    ++sandbox;
-	++textlock;
+	    set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum);
+	    set_vim_var_nr(VV_BEVAL_WINNR, winnr);
+	    set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum);
+	    set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1));
+	    set_vim_var_string(VV_BEVAL_TEXT, text, -1);
+	    vim_free(text);
 
-	vim_free(result);
-	result = eval_to_string(p_bexpr, NULL, TRUE);
+	    /*
+	     * Temporarily change the curbuf, so that we can determine whether
+	     * the buffer-local balloonexpr option was set insecurly.
+	     */
+	    save_curbuf = curbuf;
+	    curbuf = wp->w_buffer;
+	    use_sandbox = was_set_insecurely((char_u *)"balloonexpr",
+				 *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL);
+	    curbuf = save_curbuf;
+	    if (use_sandbox)
+		++sandbox;
+	    ++textlock;
 
-	if (use_sandbox)
-	    --sandbox;
-	--textlock;
+	    vim_free(result);
+	    result = eval_to_string(bexpr, NULL, TRUE);
+
+	    if (use_sandbox)
+		--sandbox;
+	    --textlock;
 
-	set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
-	if (result != NULL && result[0] != NUL)
-	{
-	    gui_mch_post_balloon(beval, result);
-	    return;
+	    set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
+	    if (result != NULL && result[0] != NUL)
+	    {
+		gui_mch_post_balloon(beval, result);
+		return;
+	    }
 	}
     }
 #endif
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -806,9 +806,9 @@ focus_in_event(GtkWidget *widget, GdkEve
     if (blink_state == BLINK_NONE)
 	gui_mch_start_blink();
 
-    /* make sure keyboard input goes there */
-    if (gtk_socket_id == 0)
-	gtk_widget_grab_focus(gui.drawarea);
+    /* make sure keyboard input goes to the draw area (if this is focus for a window) */
+    if (widget != gui.drawarea)
+        gtk_widget_grab_focus(gui.drawarea);
 
     return TRUE;
 }
@@ -2837,14 +2837,21 @@ get_item_dimensions(GtkWidget *widget, G
     if (using_gnome && widget != NULL)
     {
 # ifdef HAVE_GTK2
+        GtkWidget *parent;
 	BonoboDockItem *dockitem;
 
-	widget	 = gtk_widget_get_parent(widget);
-	dockitem = BONOBO_DOCK_ITEM(widget);
-
-	if (dockitem == NULL || dockitem->is_floating)
-	    return 0;
-	item_orientation = bonobo_dock_item_get_orientation(dockitem);
+	parent	 = gtk_widget_get_parent(widget);
+        if (G_TYPE_FROM_INSTANCE(parent) == BONOBO_TYPE_DOCK_ITEM)
+        {
+            /* Only menu & toolbar are dock items.  Could tabline be?
+             * Seem to be only the 2 defined in GNOME */
+            widget = parent;
+            dockitem = BONOBO_DOCK_ITEM(widget);
+
+            if (dockitem == NULL || dockitem->is_floating)
+                return 0;
+            item_orientation = bonobo_dock_item_get_orientation(dockitem);
+        }
 # else
 	GnomeDockItem *dockitem;
 
@@ -2911,16 +2918,39 @@ get_menu_tool_height(void)
     return height;
 }
 
+/* This controls whether we can set the real window hints at
+ * start-up when in a GtkPlug.
+ * 0 = normal processing (default)
+ * 1 = init. hints set, no-one's tried to reset since last check
+ * 2 = init. hints set, attempt made to change hints
+ */
+static int init_window_hints_state = 0;
+
     static void
-update_window_manager_hints(void)
+update_window_manager_hints(int force_width, int force_height)
 {
     static int old_width  = 0;
     static int old_height = 0;
+    static int old_min_width  = 0;
+    static int old_min_height = 0;
     static int old_char_width  = 0;
     static int old_char_height = 0;
 
     int width;
     int height;
+    int min_width;
+    int min_height;
+
+    /* At start-up, don't try to set the hints until the initial
+     * values have been used (those that dictate our initial size)
+     * Let forced (i.e., correct) values thruogh always.
+     */
+    if (!(force_width && force_height)  &&  init_window_hints_state > 0)
+    {
+        /* Don't do it! */
+        init_window_hints_state = 2;
+        return;
+    }
 
     /* This also needs to be done when the main window isn't there yet,
      * otherwise the hints don't work. */
@@ -2934,9 +2964,28 @@ update_window_manager_hints(void)
     height += get_menu_tool_height();
 # endif
 
+    /* GtkSockets use GtkPlug's [gui,mainwin] min-size hints to determine
+     * their actual widget size.  When we set our size ourselve (e.g.,
+     * 'set columns=' or init. -geom) we briefly set the min. to the size
+     * we wish to be instead of the legitimate minimum so that we actually
+     * resize correctly.
+     */
+    if (force_width && force_height)
+    {
+        min_width  = force_width;
+        min_height = force_height;
+    }
+    else
+    {
+        min_width  = width  + MIN_COLUMNS * gui.char_width;
+        min_height = height + MIN_LINES   * gui.char_height;
+    }
+
     /* Avoid an expose event when the size didn't change. */
     if (width != old_width
 	    || height != old_height
+            || min_width != old_min_width
+	    || min_height != old_min_height
 	    || gui.char_width != old_char_width
 	    || gui.char_height != old_char_height)
     {
@@ -2947,8 +2996,8 @@ update_window_manager_hints(void)
 	geometry.height_inc  = gui.char_height;
 	geometry.base_width  = width;
 	geometry.base_height = height;
-	geometry.min_width   = width  + MIN_COLUMNS * gui.char_width;
-	geometry.min_height  = height + MIN_LINES   * gui.char_height;
+        geometry.min_width   = min_width;
+        geometry.min_height  = min_height;
 	geometry_mask	     = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC
 			       |GDK_HINT_MIN_SIZE;
 # ifdef HAVE_GTK2
@@ -2961,10 +3010,12 @@ update_window_manager_hints(void)
 	gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
 				      &geometry, geometry_mask);
 # endif
-	old_width  = width;
-	old_height = height;
-	old_char_width	= gui.char_width;
-	old_char_height = gui.char_height;
+        old_width       = width;
+        old_height      = height;
+        old_min_width   = min_width;
+        old_min_height  = min_height;
+        old_char_width  = gui.char_width;
+        old_char_height = gui.char_height;
     }
 }
 
@@ -3211,7 +3262,7 @@ gui_mch_show_tabline(int showit)
     {
 	/* Note: this may cause a resize event */
 	gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), showit);
-	update_window_manager_hints();
+	update_window_manager_hints(0, 0);
 #ifndef HAVE_GTK2
 	showing_tabline = showit;
 #endif
@@ -3583,35 +3634,31 @@ gui_mch_init(void)
     /*
      * Use a Notebook for the tab pages labels.  The labels are hidden by
      * default.
-     * TODO: currently doesn't work for Gnome.
      */
-    if (!using_gnome)
-    {
-	gui.tabline = gtk_notebook_new();
-	gtk_widget_show(gui.tabline);
-	gtk_box_pack_start(GTK_BOX(vbox), gui.tabline, FALSE, FALSE, 0);
-	gtk_notebook_set_show_border(GTK_NOTEBOOK(gui.tabline), FALSE);
-	gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), FALSE);
-
-	{
-	    GtkWidget *page, *label;
-
-	    /* Add the first tab. */
-	    page = gtk_vbox_new(FALSE, 0);
-	    gtk_widget_show(page);
-	    gtk_container_add(GTK_CONTAINER(gui.tabline), page);
-	    label = gtk_label_new("-Empty-");
-	    gtk_widget_show(label);
-	    gtk_notebook_set_tab_label(GTK_NOTEBOOK(gui.tabline), page, label);
-	}
-	gtk_signal_connect(GTK_OBJECT(gui.tabline), "switch_page",
-			   GTK_SIGNAL_FUNC(on_select_tab), NULL);
-
-	/* Create a popup menu for the tab line and connect it. */
-	tabline_menu = create_tabline_menu();
-	gtk_signal_connect_object(GTK_OBJECT(gui.tabline), "button_press_event",
-		  GTK_SIGNAL_FUNC(on_tabline_menu), GTK_OBJECT(tabline_menu));
-    }
+    gui.tabline = gtk_notebook_new();
+    gtk_widget_show(gui.tabline);
+    gtk_box_pack_start(GTK_BOX(vbox), gui.tabline, FALSE, FALSE, 0);
+    gtk_notebook_set_show_border(GTK_NOTEBOOK(gui.tabline), FALSE);
+    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), FALSE);
+
+    {
+        GtkWidget *page, *label;
+
+        /* Add the first tab. */
+        page = gtk_vbox_new(FALSE, 0);
+        gtk_widget_show(page);
+        gtk_container_add(GTK_CONTAINER(gui.tabline), page);
+        label = gtk_label_new("-Empty-");
+        gtk_widget_show(label);
+        gtk_notebook_set_tab_label(GTK_NOTEBOOK(gui.tabline), page, label);
+    }
+    gtk_signal_connect(GTK_OBJECT(gui.tabline), "switch_page",
+                       GTK_SIGNAL_FUNC(on_select_tab), NULL);
+
+    /* Create a popup menu for the tab line and connect it. */
+    tabline_menu = create_tabline_menu();
+    gtk_signal_connect_object(GTK_OBJECT(gui.tabline), "button_press_event",
+              GTK_SIGNAL_FUNC(on_tabline_menu), GTK_OBJECT(tabline_menu));
 #endif
 
     gui.formwin = gtk_form_new();
@@ -3705,10 +3752,30 @@ gui_mch_init(void)
 			   GTK_SIGNAL_FUNC(enter_notify_event), NULL);
     }
 
-    gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
-			   GTK_SIGNAL_FUNC(focus_out_event), NULL);
-    gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
-			   GTK_SIGNAL_FUNC(focus_in_event), NULL);
+    /* Real windows can get focus ... GtkPlug, being a mere container can't,
+     * only its widgets.  Arguably, this could be common code and we not use
+     * the window focus at all, but let's be safe.
+     */
+    if (gtk_socket_id == 0)
+    {
+        gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
+                               GTK_SIGNAL_FUNC(focus_out_event), NULL);
+        gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
+                               GTK_SIGNAL_FUNC(focus_in_event), NULL);
+    }
+    else
+    {
+        gtk_signal_connect(GTK_OBJECT(gui.drawarea), "focus_out_event",
+                               GTK_SIGNAL_FUNC(focus_out_event), NULL);
+        gtk_signal_connect(GTK_OBJECT(gui.drawarea), "focus_in_event",
+                               GTK_SIGNAL_FUNC(focus_in_event), NULL);
+#ifdef FEAT_GUI_TABLINE
+        gtk_signal_connect(GTK_OBJECT(gui.tabline), "focus_out_event",
+                               GTK_SIGNAL_FUNC(focus_out_event), NULL);
+        gtk_signal_connect(GTK_OBJECT(gui.tabline), "focus_in_event",
+                               GTK_SIGNAL_FUNC(focus_in_event), NULL);
+#endif /* FEAT_GUI_TABLINE */
+    }
 
     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "motion_notify_event",
 		       GTK_SIGNAL_FUNC(motion_notify_event), NULL);
@@ -3793,8 +3860,17 @@ gui_mch_new_colors(void)
 form_configure_event(GtkWidget *widget, GdkEventConfigure *event,
 		     gpointer data)
 {
+    int usable_height = event->height;
+
+    /* When in a GtkPlug, we can't guarantee valid heights (as a round
+     * no. of char-heights), so we have to manually sanitise them.
+     * Widths seem to sort themselves out, don't ask me why.
+     */
+    if (gtk_socket_id != 0)
+        usable_height -= (gui.char_height - (gui.char_height/2)); /* sic. */
+
     gtk_form_freeze(GTK_FORM(gui.formwin));
-    gui_resize_shell(event->width, event->height);
+    gui_resize_shell(event->width, usable_height);
     gtk_form_thaw(GTK_FORM(gui.formwin));
 
     return TRUE;
@@ -3824,6 +3900,37 @@ mainwin_destroy_cb(GtkObject *object, gp
     }
 }
 
+
+/*
+ * Bit of a hack to ensure we start GtkPlug windows with the correct window
+ * hints (and thus the required size from -geom), but that after that we
+ * put the hints back to normal (the actual minimum size) so we may
+ * subsequently be resized smaller.  GtkSocket (the parent end) uses the
+ * plug's window 'min hints to set *it's* minum size, but that's also the
+ * only way we have of making ourselves bigger (by set lines/columns).
+ * Thus set hints at start-up to ensure correct init. size, then a
+ * second after the final attempt to reset the real minimum hinst (done by
+ * scrollbar init.), actually do the sttandard hinst and stop the timer.
+ * We'll not let the default hints be set while this timer's active.
+ */
+/*ARGSUSED*/
+    static gboolean
+check_startup_plug_hints(gpointer data)
+{
+    if (init_window_hints_state == 1)
+    {
+        /* Safe to use normal hints now */
+        init_window_hints_state = 0;
+        update_window_manager_hints(0, 0);
+        return FALSE;   /* stop timer */
+    }
+
+    /* Keep on trying */
+    init_window_hints_state = 1;
+    return TRUE;
+}
+
+
 /*
  * Open the GUI window which was created by a call to gui_mch_init().
  */
@@ -3887,12 +3994,32 @@ gui_mch_open(void)
 #endif
 	vim_free(gui.geom);
 	gui.geom = NULL;
+
+        /* From now until everyone's stopped trying to set the window hints
+         * to their correct minimum values, stop them being set as we need
+         * them to remain at our required size for the parent GtkSocket to
+         * give us the right initial size.
+         */
+	if (gtk_socket_id != 0  &&  (mask & WidthValue || mask & HeightValue))
+        {
+            guint pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width);
+            guint pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height);
+
+#ifdef HAVE_GTK2
+            pixel_width  += get_menu_tool_width();
+            pixel_height += get_menu_tool_height();
+#endif
+
+            update_window_manager_hints(pixel_width, pixel_height);
+            init_window_hints_state = 1;
+            g_timeout_add(1000, check_startup_plug_hints, NULL);
+        }
     }
 
     gtk_form_set_size(GTK_FORM(gui.formwin),
 	    (guint)(gui_get_base_width() + Columns * gui.char_width),
 	    (guint)(gui_get_base_height() + Rows * gui.char_height));
-    update_window_manager_hints();
+    update_window_manager_hints(0, 0);
 
     if (foreground_argument != NULL)
 	fg_pixel = gui_get_color((char_u *)foreground_argument);
@@ -4125,17 +4252,25 @@ gui_mch_set_shellsize(int width, int hei
     /* give GTK+ a chance to put all widget's into place */
     gui_mch_update();
 
+#ifndef HAVE_GTK2
     /* this will cause the proper resizement to happen too */
-    update_window_manager_hints();
-
-#ifdef HAVE_GTK2
+    update_window_manager_hints(0, 0);
+
+#else  /* HAVE_GTK2 */
+    /* this will cause the proper resizement to happen too */
+    if (gtk_socket_id == 0)
+        update_window_manager_hints(0, 0);
+
     /* With GTK+ 2, changing the size of the form widget doesn't resize
-     * the window.  So lets do it the other way around and resize the
+     * the window.  So let's do it the other way around and resize the
      * main window instead. */
     width  += get_menu_tool_width();
     height += get_menu_tool_height();
 
-    gtk_window_resize(GTK_WINDOW(gui.mainwin), width, height);
+    if (gtk_socket_id == 0)
+        gtk_window_resize(GTK_WINDOW(gui.mainwin), width, height);
+    else
+        update_window_manager_hints(width, height);
 
 #if 0
     if (!resize_idle_installed)
@@ -4231,7 +4366,7 @@ gui_mch_enable_menu(int showit)
 	else
 	    gtk_widget_hide(widget);
 
-	update_window_manager_hints();
+	update_window_manager_hints(0, 0);
     }
 }
 #endif /* FEAT_MENU */
@@ -4262,7 +4397,7 @@ gui_mch_show_toolbar(int showit)
 	else
 	    gtk_widget_hide(widget);
 
-	update_window_manager_hints();
+	update_window_manager_hints(0, 0);
     }
 }
 #endif /* FEAT_TOOLBAR */
@@ -4960,7 +5095,7 @@ gui_mch_init_font(char_u *font_name, int
 #endif /* !HAVE_GTK2 */
 
     /* Preserve the logical dimensions of the screen. */
-    update_window_manager_hints();
+    update_window_manager_hints(0, 0);
 
     return OK;
 }
@@ -6577,7 +6712,7 @@ gui_mch_enable_scrollbar(scrollbar_T *sb
     else
 	gtk_widget_hide(sb->id);
 
-    update_window_manager_hints();
+    update_window_manager_hints(0, 0);
 }
 
 
--- a/src/menu.c
+++ b/src/menu.c
@@ -739,6 +739,7 @@ add_menu_path(menu_path, menuarg, pri_ta
 		    switch (1 << i)
 		    {
 			case MENU_VISUAL_MODE:
+			case MENU_SELECT_MODE:
 			case MENU_OP_PENDING_MODE:
 			case MENU_CMDLINE_MODE:
 			    c = Ctrl_C;
@@ -1464,8 +1465,14 @@ get_menu_cmd_modes(cmd, forceit, noremap
     switch (*cmd++)
     {
 	case 'v':			/* vmenu, vunmenu, vnoremenu */
+	    modes = MENU_VISUAL_MODE | MENU_SELECT_MODE;
+	    break;
+	case 'x':			/* xmenu, xunmenu, xnoremenu */
 	    modes = MENU_VISUAL_MODE;
 	    break;
+	case 's':			/* smenu, sunmenu, snoremenu */
+	    modes = MENU_SELECT_MODE;
+	    break;
 	case 'o':			/* omenu */
 	    modes = MENU_OP_PENDING_MODE;
 	    break;
@@ -1480,7 +1487,8 @@ get_menu_cmd_modes(cmd, forceit, noremap
 	    break;
 	case 'a':			/* amenu */
 	    modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE | MENU_NORMAL_MODE
-				    | MENU_VISUAL_MODE | MENU_OP_PENDING_MODE;
+				    | MENU_VISUAL_MODE | MENU_SELECT_MODE
+                                    | MENU_OP_PENDING_MODE;
 	    break;
 	case 'n':
 	    if (*cmd != 'o')		/* nmenu, not noremenu */
@@ -1494,7 +1502,7 @@ get_menu_cmd_modes(cmd, forceit, noremap
 	    if (forceit)		/* menu!! */
 		modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE;
 	    else			/* menu */
-		modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE
+		modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE | MENU_SELECT_MODE
 						       | MENU_OP_PENDING_MODE;
     }
 
@@ -1545,7 +1553,12 @@ get_menu_index(menu, state)
 	idx = MENU_INDEX_CMDLINE;
 #ifdef FEAT_VISUAL
     else if (VIsual_active)
-	idx = MENU_INDEX_VISUAL;
+    {
+        if (VIsual_select)
+            idx = MENU_INDEX_SELECT;
+        else
+            idx = MENU_INDEX_VISUAL;
+    }
 #endif
     else if (state == HITRETURN || state == ASKMORE)
 	idx = MENU_INDEX_CMDLINE;
@@ -1712,7 +1725,11 @@ get_menu_mode()
 {
 #ifdef FEAT_VISUAL
     if (VIsual_active)
+    {
+        if (VIsual_select)
+            return MENU_INDEX_SELECT;
 	return MENU_INDEX_VISUAL;
+    }
 #endif
     if (State & INSERT)
 	return MENU_INDEX_INSERT;
--- a/src/ui.c
+++ b/src/ui.c
@@ -139,7 +139,7 @@ ui_inchar(buf, maxlen, wtime, tb_change_
 #endif
 
 #ifdef FEAT_PROFILE
-    if (do_profiling && wtime != 0)
+    if (do_profiling == PROF_YES && wtime != 0)
 	prof_inchar_enter();
 #endif
 
@@ -199,7 +199,7 @@ ui_inchar(buf, maxlen, wtime, tb_change_
 theend:
 #endif
 #ifdef FEAT_PROFILE
-    if (do_profiling && wtime != 0)
+    if (do_profiling == PROF_YES && wtime != 0)
 	prof_inchar_exit();
 #endif
     return retval;
@@ -473,7 +473,8 @@ clip_own_selection(cbd)
 	     * selected area.  There is no specific redraw command for this,
 	     * just redraw all windows on the current buffer. */
 	    if (cbd->owned
-		    && get_real_state() == VISUAL
+		    && (get_real_state() == VISUAL
+					    || get_real_state() == SELECTMODE)
 		    && clip_isautosel()
 		    && hl_attr(HLF_V) != hl_attr(HLF_VNC))
 		redraw_curbuf_later(INVERTED_ALL);
@@ -503,7 +504,8 @@ clip_lose_selection(cbd)
 	 * area.  There is no specific redraw command for this, just redraw all
 	 * windows on the current buffer. */
 	if (was_owned
-		&& get_real_state() == VISUAL
+		&& (get_real_state() == VISUAL
+					    || get_real_state() == SELECTMODE)
 		&& clip_isautosel()
 		&& hl_attr(HLF_V) != hl_attr(HLF_VNC))
 	{