diff lisp/viper/viper.el @ 78:c7528f8e288d r20-0b34

Import from CVS: tag r20-0b34
author cvs
date Mon, 13 Aug 2007 09:05:42 +0200
parents 131b0175ea99
children 1ce6082ce73f
line wrap: on
line diff
--- a/lisp/viper/viper.el	Mon Aug 13 09:05:11 2007 +0200
+++ b/lisp/viper/viper.el	Mon Aug 13 09:05:42 2007 +0200
@@ -8,7 +8,7 @@
 
 ;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 
-(defconst viper-version "2.90 of June 19, 1996"
+(defconst viper-version "2.91 of August 5, 1996"
   "The current version of Viper")
 
 ;; This file is part of GNU Emacs.
@@ -24,8 +24,9 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
@@ -88,7 +89,7 @@
 ;;    The same macro name can have several different definitions:
 ;;    one global, several definitions for various major modes, and
 ;;    definitions for specific buffers.
-;;    Bffer-specific definitions override mode-specific
+;;    Buffer-specific definitions override mode-specific
 ;;    definitions, which, in turn, override global definitions.
 ;;
 ;;
@@ -100,8 +101,8 @@
 
 ;;; Acknowledgements:
 ;;  -----------------
-;;  Bug reports and ideas contributed by the following users
-;;  have helped improve Viper and the various versions of VIP.
+;;  Bug reports and ideas contributed by many users have helped
+;;  improve Viper and the various versions of VIP.
 ;;  See the on-line manual for a complete list of contributors. 
 ;;
 ;;
@@ -155,8 +156,8 @@
 ;;  For instance,  C-c will not have its standard Emacs binding
 ;;  and so many of the goodies of Emacs are not available.
 ;;
-;;  An skilled user, should set vip-expert-level to at least 3. This will
-;;  enable ;;  C-c and many Emacs facilities will become available.
+;;  A skilled user should set vip-expert-level to at least 3. This will
+;;  enable `C-c; and many Emacs facilities will become available.
 ;;  In this case, vip-vi-diehard-minor-mode is inactive.
 ;;
 ;;  Viper gurus should have at least
@@ -336,7 +337,12 @@
 
 ;;; Viper minor modes
 
-;; This is not local in Emacs, so we make it local.
+;; This must be local because although the stack of minor modes can be the same
+;; for all buffers, the associated *keymaps* can be different. In Viper,
+;; vip-vi-local-user-map, vip-insert-local-user-map, and others can have
+;; different keymaps for different buffers.
+;; Also, the keymaps associated with vip-vi/insert-state-modifier-minor-mode
+;; can be different.
 (make-variable-buffer-local 'minor-mode-map-alist)
 
 ;; Mode for vital things like \e, C-z.
@@ -473,26 +479,40 @@
 (defvar vip-replace-overlay-cursor-color "Red"
   "*Cursor color to use in Replace state")
 
-  
+(defvar vip-insert-state-cursor-color nil
+  "Cursor color for Viper insert state.")
+(put 'vip-insert-state-cursor-color 'permanent-local t)
+;; place to save cursor colow when switching to insert mode
+(vip-deflocalvar vip-saved-cursor-color nil "")
+
 (vip-deflocalvar vip-replace-overlay nil "")
 (put 'vip-replace-overlay 'permanent-local t)
 
-(if (vip-has-face-support-p)
-    (progn
-      (make-face 'vip-replace-overlay-face)
-      (vip-hide-face 'vip-replace-overlay-face)
-      (or (face-differs-from-default-p 'vip-replace-overlay-face)
-	  (progn
-	    (if (vip-can-use-colors "darkseagreen2" "Black")
-		(progn
-		  (set-face-background
-		   'vip-replace-overlay-face "darkseagreen2")
-		  (set-face-foreground 'vip-replace-overlay-face "Black")))
-	    (set-face-underline-p 'vip-replace-overlay-face t))
-	  )))
-	    
-(defvar vip-replace-overlay-face 'vip-replace-overlay-face
-  "*Face for highlighting replace regions on a window display.")
+(defvar vip-replace-overlay-pixmap "gray3"
+  "Pixmap to use for search face on non-color displays.")
+(defvar vip-search-face-pixmap "gray3"
+  "Pixmap to use for search face on non-color displays.")
+
+
+(defun vip-set-replace-overlay-face ()
+  (if (vip-has-face-support-p)
+      (defvar vip-replace-overlay-face
+	(progn
+	  (make-face 'vip-replace-overlay-face)
+	  (vip-hide-face 'vip-replace-overlay-face)
+	(or (face-differs-from-default-p 'vip-replace-overlay-face)
+	    (progn
+	      (if (vip-can-use-colors "darkseagreen2" "Black")
+		  (progn
+		    (set-face-background
+		     'vip-replace-overlay-face "darkseagreen2")
+		    (set-face-foreground 'vip-replace-overlay-face "Black")))
+	      (set-face-underline-p 'vip-replace-overlay-face t)
+	      (vip-set-face-pixmap
+	       'vip-replace-overlay-face vip-replace-overlay-pixmap)))
+	'vip-replace-overlay-face)
+	"*Face for highlighting replace regions on a window display.")
+    ))
   
 (defvar vip-replace-region-end-delimiter "$"
   "A string marking the end of replacement regions.
@@ -502,12 +522,10 @@
   "A string marking the beginning of replacement regions.
 It is used only with TTYs or if `vip-use-replace-region-delimiters'
 is non-nil.")
-(defvar vip-use-replace-region-delimiters 
-  (or (not (vip-has-face-support-p)) (not (vip-color-display-p)))
+(defvar vip-use-replace-region-delimiters (not (vip-has-face-support-p))
   "*If non-nil, Viper will always use `vip-replace-region-end-delimiter' and
 `vip-replace-region-start-delimiter' to delimit replacement regions, even on
-color displays. By default, the delimiters are used only on TTYs or
-monochrome displays.")
+color displays. By default, the delimiters are used only on TTYs.")
   
 ;; XEmacs requires glyphs
 (if vip-xemacs-p
@@ -562,21 +580,8 @@
 ;; Current mode.  One of: `emacs-state', `vi-state', `insert-state'
 (vip-deflocalvar vip-current-state 'emacs-state)
 
-
-(defvar vip-toggle-key "\C-z"
-  "The key used to change states from emacs to Vi and back.
-In insert mode, this key also functions as Meta. 
-Must be set in .vip file or prior to loading Viper.
-This setting cannot be changed interactively.")
-
-(defvar vip-ESC-key "\e" 
-  "Key used to ESC. 
-Must be set in .vip file or prior to loading Viper.
-This setting cannot be changed interactively.")
-
 (defvar vip-no-multiple-ESC  t
   "*If true, multiple ESC in Vi mode will cause bell to ring.
-\_ is then mapped to Meta.
 This is set to t on a windowing terminal and to 'twice on a dumb
 terminal (unless the user level is 1, 2, or 5). On a dumb terminal, this
 enables cursor keys and is generally more convenient, as terminals usually
@@ -697,10 +702,14 @@
 (defvar vip-s-forward nil)
 
 (defconst vip-case-fold-search nil
-  "*If t, search ignores cases.")
+  "*If not nil, search ignores case.")
 
 (defconst vip-re-search t
-  "*If t, search is reg-exp search, otherwise vanilla search.")
+  "*If not nil, search is reg-exp search, otherwise vanilla search.")
+
+(defvar vip-adjust-window-after-search t
+  "*If not nil, pull the window up or down, depending on the direction of the
+search, if search ends up near the bottom or near the top of the window.")
 
 (defconst vip-re-query-replace t
   "*If t then do regexp replace, if nil then do string replace.")
@@ -820,18 +829,7 @@
 (defvar vip-always t
   "t means, arrange that vi-state will be a default.")
 
-(defvar vip-ms-style-os-p (memq system-type '(ms-dos windows-nt windows-95))
-  "Tells is Emacs is running under an MS-style OS: ms-dos, window-nt, W95.")
-(defvar vip-vms-os-p (memq system-type '(vax-vms axp-vms))
-  "Tells if Emacs is running under VMS.")
-
-(defvar vip-custom-file-name (cond (vip-vms-os-p "sys$login:.vip")
-				   ((memq system-type '(emx ms-dos))
-				    "/_vip")
-				   ((memq system-type '(windows-nt windows-95))
-				    "~/_vip")
-				   (t ; Unix
-				    "~/.vip"))
+(defvar vip-custom-file-name (vip-convert-standard-file-name "~/.vip")
   "Viper customisation file.
 This variable must be set _before_ loading Viper.")
 
@@ -936,7 +934,7 @@
 				     "Movement commands")
 (vip-test-com-defun vip-movement-command)
 
-;; Commands that can be repeated by .(dotted)
+;; Commands that can be repeated by . (dotted)
 (defconst vip-dotable-commands '(?c ?d ?C ?D ?> ?<))
 (vip-test-com-defun vip-dotable-command)
 
@@ -948,7 +946,14 @@
 (defconst vip-regsuffix-commands '(?d ?y ?Y ?D ?p ?P ?x ?X))
 (vip-test-com-defun vip-regsuffix-command)
 
-
+(defconst vip-vi-commands (append vip-movement-commands
+				  vip-dotable-commands
+				  vip-charpair-commands
+				  vip-hash-cmds
+				  vip-prefix-commands
+				  vip-regsuffix-commands)
+  "The list of all commands in Vi-state.")
+(vip-test-com-defun vip-vi-command)
 
 ;;; Arrange the keymaps
 (require 'viper-keym)
@@ -985,6 +990,14 @@
 	   vip-insert-point
 	   (>= (point) vip-insert-point))
       (setq vip-last-posn-while-in-insert-state (point-marker)))
+  (if (eq vip-current-state 'insert-state)
+      (progn
+	(or (stringp vip-saved-cursor-color)
+	    (string= (vip-get-cursor-color) vip-insert-state-cursor-color)
+	    (setq vip-saved-cursor-color (vip-get-cursor-color)))
+	(if (stringp vip-saved-cursor-color)
+	    (vip-change-cursor-color vip-insert-state-cursor-color))
+	))
   (if (and (eq this-command 'dabbrev-expand)
 	   (integerp vip-pre-command-point)
 	   (> vip-insert-point vip-pre-command-point))
@@ -992,6 +1005,11 @@
   )
   
 (defsubst vip-insert-state-pre-command-sentinel ()
+  (or (memq this-command '(self-insert-command))
+      (memq (vip-event-key last-command-event)
+	    '(up down left right (meta f) (meta b)
+		 (control n) (control p) (control f) (control b)))
+      (vip-restore-cursor-color-after-insert))
   (if (and (eq this-command 'dabbrev-expand)
 	   (markerp vip-insert-point)
 	   (marker-position vip-insert-point))
@@ -1007,7 +1025,7 @@
   (if (and (<= (vip-replace-start) (point))
 	   (<=  (point) (vip-replace-end)))
       (vip-change-cursor-color vip-replace-overlay-cursor-color)
-    (vip-restore-cursor-color)
+    (vip-restore-cursor-color-after-replace)
     ))
 
 ;; to speed up, don't change cursor color before self-insert
@@ -1031,7 +1049,7 @@
   ;; cursor color or, if they terminate replace mode, the color will be changed
   ;; in vip-finish-change
   (or (memq this-command '(self-insert-command))
-      (vip-restore-cursor-color))
+      (vip-restore-cursor-color-after-replace))
   (cond 
    ((eq vip-current-state 'replace-state)
     ;; delete characters to compensate for inserted chars.
@@ -1150,18 +1168,18 @@
 		   
 	 (if vip-want-ctl-h-help
 	     (progn 
-	       (define-key vip-insert-basic-map "\C-h" 'help-command)
-	       (define-key vip-replace-map "\C-h" 'help-command))
+	       (define-key vip-insert-basic-map [(control h)] 'help-command)
+	       (define-key vip-replace-map [(control h)] 'help-command))
 	   (define-key vip-insert-basic-map 
-	     "\C-h" 'vip-del-backward-char-in-insert)
+	     [(control h)] 'vip-del-backward-char-in-insert)
 	   (define-key vip-replace-map
-	     "\C-h" 'vip-del-backward-char-in-replace)))
-		     
-	(t
+	     [(control h)] 'vip-del-backward-char-in-replace)))
+
+	(t ; Vi state
 	 (setq vip-vi-diehard-minor-mode (not vip-want-emacs-keys-in-vi))
 	 (if vip-want-ctl-h-help
-	     (define-key vip-vi-basic-map "\C-h" 'help-command)
-	   (define-key vip-vi-basic-map "\C-h" 'vip-backward-char)))
+	     (define-key vip-vi-basic-map [(control h)] 'help-command)
+	   (define-key vip-vi-basic-map [(control h)] 'vip-backward-char)))
 	))
 	     
     
@@ -1281,7 +1299,7 @@
    4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat
       undo. Another `u' changes direction.
    
-   6. Emacs Meta functions are invoked by typing `_' or `\\ ESC'.
+   6. Emacs Meta functions are invoked by typing `C-\\' or `\\ ESC'.
       On a window system, the best way is to use the Meta-key.
    7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
       something funny happens. This would abort the current editing command. 
@@ -1431,7 +1449,9 @@
     ;; keys `,',^ in Vi state, as they will do accents instead of Vi actions.
     (if (and (boundp 'iso-accents-mode) iso-accents-mode)
 	(iso-accents-mode -1))
-    
+
+    (vip-restore-cursor-color-after-insert)
+
     ;; Protection against user errors in hooks
     (condition-case conds
 	(run-hooks 'vip-vi-state-hook)
@@ -1445,6 +1465,14 @@
   (if (and vip-automatic-iso-accents (fboundp 'iso-accents-mode))
       (iso-accents-mode 1)) ; turn iso accents on
   
+  (or (stringp vip-saved-cursor-color)
+      (string= (vip-get-cursor-color) vip-insert-state-cursor-color)
+      (setq vip-saved-cursor-color (vip-get-cursor-color)))
+  ;; Commented out, because if vip-change-state-to-insert is executed
+  ;; non-interactively then the old cursor color may get lost. Same old Emacs
+  ;; bug related to local variables?
+;;;(if (stringp vip-saved-cursor-color)
+;;;      (vip-change-cursor-color vip-insert-state-cursor-color))
   ;; Protection against user errors in hooks
   (condition-case conds
       (run-hooks 'vip-insert-state-hook)
@@ -1496,20 +1524,24 @@
 ARG is used as the prefix value for the executed command.  If
 EVENTS is a list of events, which become the beginning of the command."
   (interactive "P")
+  (if (= last-command-char ?\\)
+      (message "Switched to EMACS state for the next command..."))
   (vip-escape-to-state arg events 'emacs-state))
   
 ;; escape to Vi mode termporarily
-(defun vip-escape-to-vi ()
+(defun vip-escape-to-vi (arg)
   "Escape from Emacs state to Vi state for one Vi 1-character command.
-This doesn't work with prefix arguments or most complex commands like
-cw, dw,  etc. But it does work with some 2-character commands,
-like dd or dr."
-  (interactive)
-  (vip-escape-to-state nil nil 'vi-state))  
-  
+If the Vi command that the user types has a prefix argument, e.g., `d2w', then
+Vi's prefix argument will be used. Otherwise, the prefix argument passed to
+`vip-escape-to-vi' is used."
+  (interactive "P")
+  (message "Switched to VI state for the next command...")
+  (vip-escape-to-state arg nil 'vi-state))
+
 ;; Escape to STATE mode for one Emacs command.
 (defun vip-escape-to-state (arg events state)
-  (let (com key prefix-arg)
+  ;;(let (com key prefix-arg)
+  (let (com key)
     ;; this temporarily turns off Viper's minor mode keymaps
     (vip-set-mode-vars-for state)
     (vip-normalize-minor-mode-map-alist)
@@ -1517,23 +1549,26 @@
     
     ;; protect against keyboard quit and other errors
     (condition-case nil
-	(progn
+	(let (vip-vi-kbd-minor-mode 
+	      vip-insert-kbd-minor-mode
+	      vip-emacs-kbd-minor-mode)
 	  (unwind-protect
 	      (progn
 		(setq com (key-binding (setq key 
 					     (if vip-xemacs-p
 						 (read-key-sequence nil)
 					       (read-key-sequence nil t)))))
-		;; In case of indirection--chase definitions.
+		;; In case of binding indirection--chase definitions.
 		;; Have to do it here because we execute this command under
 		;; different keymaps, so command-execute may not do the
 		;; right thing there
 		(while (vectorp com) (setq com (key-binding com))))
 	    nil)
-	  ;; exec command in the right Viper state
-	  ;; otherwise, if we switch buffers in the escaped command,
-	  ;; Viper's mode vars will remain those of `state'. When we return
-	  ;; to the orig buffer, the bindings will be screwed up.
+	  ;; Execute command com in the original Viper state, not in state
+	  ;; `state'. Otherwise, if we switch buffers while executing the
+	  ;; escaped to command, Viper's mode vars will remain those of
+	  ;; `state'. When we return to the orig buffer, the bindings will be
+	  ;; screwed up.
 	  (vip-set-mode-vars-for vip-current-state)
 	  
 	  ;; this-command, last-command-char, last-command-event
@@ -1547,13 +1582,27 @@
 	    
 	  (if (commandp com)
 	      (progn
-		(setq prefix-arg arg)
+		(setq prefix-arg (or prefix-arg arg))
 		(command-execute com)))
 	  )
       (quit (ding))
       (error (beep 1))))
-  (vip-set-mode-vars-for vip-current-state)) ; set state in new buffer
+  ;; set state in the new buffer
+  (vip-set-mode-vars-for vip-current-state))
       
+(defun vip-exec-form-in-vi  (form)
+  "Execute FORM in Vi state, regardless of the Ccurrent Vi state."
+  (let ((buff (current-buffer))
+	result)
+    (vip-set-mode-vars-for 'vi-state)
+    (setq result (eval form))
+    (if (not (equal buff (current-buffer))) ; cmd switched buffer
+	(save-excursion
+	  (set-buffer buff)
+	  (vip-set-mode-vars-for vip-current-state)))
+    (vip-set-mode-vars-for vip-current-state)
+    result))
+
 (defun vip-exec-form-in-emacs  (form)
   "Execute FORM in Emacs, temporarily disabling Viper's minor modes.
 Similar to vip-escape-to-emacs, but accepts forms rather than keystrokes."
@@ -1596,13 +1645,13 @@
 
 (defun vip-ESC (arg)
   "Emulate ESC key in Emacs.
-Prevents multiple escape keystrokes if vip-no-multiple-ESC is true. In that
-case \@ will be bound to ESC. If vip-no-multiple-ESC is 'twice double ESC
-would dings in vi-state. Other ESC sequences are emulated via the current
-Emacs's major mode keymap. This is more convenient on dumb terminals and in
-Emacs -nw, since this won't block functional keys such as up,down,
-etc. Meta key also will work. When vip-no-multiple-ESC is nil, ESC key
-behaves as in Emacs, any number of multiple escapes is allowed."
+Prevents multiple escape keystrokes if vip-no-multiple-ESC is true.
+If vip-no-multiple-ESC is 'twice double ESC would ding in vi-state.
+Other ESC sequences are emulated via the current Emacs's major mode
+keymap. This is more convenient on TTYs, since this won't block
+function keys such as up,down, etc. ESC will also will also work as
+a Meta key in this case. When vip-no-multiple-ESC is nil, ESC functions
+as a Meta key and any number of multiple escapes is allowed."
   (interactive "P")
   (let (char)
     (cond ((and (not vip-no-multiple-ESC) (eq vip-current-state 'vi-state))
@@ -1617,11 +1666,19 @@
 	  (t (ding)))
     ))
 
-(defun vip-alternate-ESC (arg)
-  "ESC key without checking for multiple keystrokes."
+(defun vip-alternate-Meta-key (arg)
+  "Simulate Emacs Meta key."
   (interactive "P")
   (vip-escape-to-emacs arg '(?\e)))
-  
+
+(defun vip-toggle-key-action ()
+  "Action bound to `vip-toggle-key'."
+  (interactive)
+  (if (and (< vip-expert-level 2) (equal vip-toggle-key "\C-z"))
+      (if (vip-window-display-p)
+	  (vip-iconify)
+	(suspend-emacs))
+    (vip-change-state-to-emacs)))
 
 ;; Intercept ESC sequences on dumb terminals.
 ;; Based on the idea contributed by Marcelino Veiga Tuimil <mveiga@dit.upm.es>
@@ -1792,9 +1849,9 @@
 
 
 ;; Compute numeric prefix arg value. 
-;; Invoked by CHAR. COM is the command part obtained so far.
+;; Invoked by EVENT. COM is the command part obtained so far.
 (defun vip-prefix-arg-value (event com)
-  (let (value)
+  (let (value func)
     ;; read while number
     (while (and (vip-characterp event) (>= event ?0) (<= event ?9))
       (setq value (+ (* (if (vip-characterp value) value 0) 10) (- event ?0)))
@@ -1805,11 +1862,39 @@
     (while (eq event ?U)
       (vip-describe-arg prefix-arg)
       (setq event (vip-read-event-convert-to-char)))
-    (vip-set-unread-command-events event)))
+
+    (if (or com (and (not (eq vip-current-state 'vi-state))
+		     ;; make sure it is a Vi command
+		     (vip-characterp event) (vip-vi-command-p event)
+		     ))
+	;; If appears to be one of the vi commands,
+	;; then execute it with funcall and clear prefix-arg in order to not
+	;; confuse subsequent commands
+	(progn
+	  ;; last-command-char is the char we want emacs to think was typed
+	  ;; last. If com is not nil, the vip-digit-argument command was called
+	  ;; from within vip-prefix-arg command, such as `d', `w', etc., i.e., 
+	  ;; the user typed, say, d2. In this case, `com' would be `d', `w',
+	  ;; etc.
+	  ;; If vip-digit-argument was invoked by vip-escape-to-vi (which is
+	  ;; indicated by the fact that the current state is not vi-state,
+	  ;; then `event' represents the vi command to be executed (e.g., `d',
+	  ;; `w', etc. Again, last-command-char must make emacs believe that
+	  ;; this is the command we typed.
+	  (setq last-command-char (or com event))
+	  (setq func (vip-exec-form-in-vi 
+		      (` (key-binding (char-to-string (, event))))))
+	  (funcall func prefix-arg)
+	  (setq prefix-arg nil))
+      ;; some other command -- let emacs do it in its own way
+      (vip-set-unread-command-events event))
+    ))
+
 
 ;; Vi operator as prefix argument."
 (defun vip-prefix-arg-com (char value com)
-  (let ((cont t))
+  (let ((cont t)
+	cmd-info mv-or-digit-cmd)
     (while (and cont
 		(memq char
 		      (list ?c ?d ?y ?! ?< ?> ?= ?# ?r ?R ?\"
@@ -1843,20 +1928,21 @@
 		 (setq char (read-char))))
 	      (t
 	       (setq com char)
-	       (setq char (vip-read-char-exclusive)))))))
+	       (setq char (vip-read-char-exclusive))))))
   (if (atom com)
-      ;; com is a single char, so we construct prefix-arg 
-      ;; and if char is ?, describe prefix arg, otherwise exit by
-      ;; pushing the char back into vip-set-unread-command-events
-      ;; Since char is a command, the command will execute with the prefix
-      ;; argument that we just constructed.
+      ;; `com' is a single char, so we construct the command argument
+      ;; and if `char' is `?', we describe the arg; otherwise 
+      ;; we prepare the command that will be executed at the end.
       (progn
-	(setq prefix-arg (cons value com))
+	(setq cmd-info (cons value com))
 	(while (= char ?U)
-	  (vip-describe-arg prefix-arg)
+	  (vip-describe-arg cmd-info)
 	  (setq char (read-char)))
-	(vip-set-unread-command-events char)
-	)
+	;; `char' is a movement command or a digit arg command---so we execute
+	;; it at the very end 
+	(setq mv-or-digit-cmd
+	      (vip-exec-form-in-vi 
+	       (` (key-binding (char-to-string (, char)))))))
     ;; as com is non-nil, this means that we have a command to execute
     (if (memq (car com) '(?r ?R))
 	;; execute apropriate region command.
@@ -1877,7 +1963,13 @@
 	    ((equal com '(?> . ?>)) (vip-line (cons value ?>)))
 	    ((equal com '(?! . ?!)) (vip-line (cons value ?!)))
 	    ((equal com '(?= . ?=)) (vip-line (cons value ?=)))
-	    (t (error ""))))))
+	    (t (error "")))))
+
+  (if mv-or-digit-cmd
+      (progn
+	(setq last-command-char char)
+	(funcall mv-or-digit-cmd cmd-info)))
+  ))
 
 (defun vip-describe-arg (arg)
   (let (val com)
@@ -1895,8 +1987,8 @@
   "Begin numeric argument for the next command."
   (interactive "P")
   (vip-leave-region-active)
-  (vip-prefix-arg-value last-command-char
-			(if (consp arg) (cdr arg) nil)))
+  (vip-prefix-arg-value
+   last-command-char (if (consp arg) (cdr arg) nil)))
 
 (defun vip-command-argument (arg)
   "Accept a motion command as an argument."
@@ -2480,22 +2572,25 @@
 ;;  Tells whether BEG is on the same line as END.
 ;;  If one of the args is nil, it'll return nil.
 (defun vip-same-line (beg end)
-   (let ((selective-display nil))
-     (cond ((and beg end)
-	    ;; This 'if' is needed because Emacs treats the next empty line
-	    ;; as part of the previous line.
-	    (if (or (> beg (point-max)) (> end (point-max))) ; out of range
-		()
-	      (if (and (> end beg) (= (vip-line-pos 'start) end))
-		  (setq end (min (1+ end) (point-max))))
-	      (if (and (> beg end) (= (vip-line-pos 'start) beg))
-		  (setq beg (min (1+ beg) (point-max))))
-	      (<= (count-lines beg end) 1) ))
-	   
-	   (t nil))
-	 ))
-	 
-	 
+   (let ((selective-display nil)
+	 (incr 0)
+	 temp)
+     (if (and beg end (> beg end))
+	 (setq temp beg
+	       beg end
+	       end temp))
+     (if (and beg end)
+	 (cond ((or (> beg (point-max)) (> end (point-max))) ; out of range
+		nil)
+	       (t
+		;; This 'if' is needed because Emacs treats the next empty line
+		;; as part of the previous line.
+		(if (= (vip-line-pos 'start) end)
+		    (setq incr 1))
+		(<= (+ incr (count-lines beg end)) 1))))
+     ))
+
+
 ;; Check if the string ends with a newline.
 (defun vip-end-with-a-newline-p (string)
   (or (string= string "")
@@ -2546,8 +2641,8 @@
 		  (progn
 		    (set-face-background 'vip-search-face "khaki")
 		    (set-face-foreground 'vip-search-face "Black"))
-		(copy-face 'italic 'vip-search-face)
-		(set-face-underline-p 'vip-search-face t)))
+		(set-face-underline-p 'vip-search-face t)
+		(vip-set-face-pixmap 'vip-search-face vip-search-face-pixmap)))
 	  'vip-search-face)
         "*Face used to flash out the search pattern.")
     ))
@@ -2781,10 +2876,8 @@
 	      (setq vip-cted t)
 	      (if vip-electric-mode
 		  (indent-according-to-mode)
-		(indent-to col))
-	      ))
-	(vip-change-state-to-insert)
-	))))
+		(indent-to col))))
+	(vip-change-state-to-insert)))))
 
 (defun vip-Open-line (arg)
   "Open line above."
@@ -2960,7 +3053,7 @@
 		   'vip-replace-state-post-command-sentinel) 
   (vip-remove-hook
    'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel) 
-  (vip-restore-cursor-color)
+  (vip-restore-cursor-color-after-replace)
   (setq vip-sitting-in-replace nil) ; just in case we'll need to know it
   (save-excursion
     (if (and 
@@ -3776,6 +3869,32 @@
   (interactive "p")
   (recenter (- (window-height) (1+ arg))))
 
+;; If vip-adjust-window-after-search is t, scroll up or down 1/4 of window
+;; height, depending on whether we are at the bottom or at the top of the
+;; window. This function is called by vip-search (which is called from
+;; vip-search-forward/backward/next)
+(defun vip-adjust-window ()
+  (let ((win-height (if vip-emacs-p
+			(1- (window-height)) ; adjust for modeline
+		      (window-displayed-height)))
+	(pt (point))
+	at-top-p at-bottom-p
+	min-scroll direction)
+    (save-excursion
+      (move-to-window-line 0) ; top
+      (setq at-top-p (<= (count-lines pt (point)) 2))
+      (move-to-window-line -1) ; bottom
+      (setq at-bottom-p (<= (count-lines pt (point)) 2))
+      )
+    (cond (at-top-p (setq min-scroll 1
+			  direction  1))
+	  (at-bottom-p (setq min-scroll 2
+			     direction -1)))
+    (if (and vip-adjust-window-after-search min-scroll)
+	(recenter
+	 (* (max min-scroll (/ win-height 7)) direction)))
+    ))
+
 
 ;; paren match
 ;; must correct this to only match ( to ) etc. On the other hand
@@ -3785,8 +3904,9 @@
 (defun vip-paren-match (arg)
   "Go to the matching parenthesis."
   (interactive "P")
+  (vip-leave-region-active)
   (let ((com (vip-getcom arg))
-	anchor-point)
+	parse-sexp-ignore-comments anchor-point)
     (if (integerp arg)
 	(if (or (> arg 99) (< arg 1))
 	    (error "Prefix must be between 1 and 99")
@@ -3914,21 +4034,30 @@
 
 (setq scroll-step 1)
 
-(defun vip-scroll (arg)
+(defun vip-scroll-screen (arg)
   "Scroll to next screen."
   (interactive "p")
-  (if (> arg 0)
-      (while (> arg 0)
-	(scroll-up)
-	(setq arg (1- arg)))
-    (while (> 0 arg)
-      (scroll-down)
-      (setq arg (1+ arg)))))
-
-(defun vip-scroll-back (arg)
+  (condition-case nil
+      (if (> arg 0)
+	  (while (> arg 0)
+	    (scroll-up)
+	    (setq arg (1- arg)))
+	(while (> 0 arg)
+	  (scroll-down)
+	  (setq arg (1+ arg))))
+    (error (beep 1)
+	   (if (> arg 0)
+	       (progn
+		 (message "End of buffer")
+		 (goto-char (point-max)))
+	     (message "Beginning of buffer")
+	     (goto-char (point-min))))
+    ))
+
+(defun vip-scroll-screen-back (arg)
   "Scroll to previous screen."
   (interactive "p")
-  (vip-scroll (- arg)))
+  (vip-scroll-screen (- arg)))
 
 (defun vip-scroll-down (arg)
   "Pull down half screen."
@@ -4017,6 +4146,62 @@
 	   (setq msg "Search style remains unchanged")))
     (prin1 msg t)))
 
+(defun vip-set-vi-search-style-macros (unset)
+  "Set the macros for toggling the search style in Viper's vi-state.
+The macro that toggles case sensitivity is bound to `//', and the one that
+toggles regexp search is bound to `///'.
+With a prefix argument, this function unsets the macros. "
+  (interactive "P")
+  (or noninteractive
+      (if (not unset)
+	  (progn
+	    ;; toggle case sensitivity in search
+	    (vip-record-kbd-macro
+	     "//" 'vi-state
+	     [1 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
+	     't)
+	    ;; toggle regexp/vanila search
+	    (vip-record-kbd-macro
+	     "///" 'vi-state
+	     [2 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
+	     't)
+	    (if (interactive-p)
+		(message
+		 "// and /// now toggle case-sensitivity and regexp search.")))
+	(vip-unrecord-kbd-macro "//" 'vi-state)
+	(sit-for 2)
+	(vip-unrecord-kbd-macro "///" 'vi-state))))
+
+(defun vip-set-emacs-search-style-macros (unset &optional arg-majormode)
+  "Set the macros for toggling the search style in Viper's emacs-state.
+The macro that toggles case sensitivity is bound to `//', and the one that
+toggles regexp search is bound to `///'.
+With a prefix argument, this function unsets the macros. 
+If the optional prefix argument is non-nil and specifies a valid major mode,
+this sets the macros only in the macros in that major mode. Otherwise,
+the macros are set in the current major mode.
+\(When unsetting the macros, the second argument has no effect.\)"
+  (interactive "P")
+  (or noninteractive
+      (if (not unset)
+	  (progn
+	    ;; toggle case sensitivity in search
+	    (vip-record-kbd-macro
+	     "//" 'emacs-state
+	     [1 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return] 
+	     (or arg-majormode major-mode))
+	    ;; toggle regexp/vanila search
+	    (vip-record-kbd-macro
+	     "///" 'emacs-state
+	     [2 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
+	     (or arg-majormode major-mode))
+	    (if (interactive-p)
+		(message
+		 "// and /// now toggle case-sensitivity and regexp search.")))
+	(vip-unrecord-kbd-macro "//" 'emacs-state)
+	(sit-for 2)
+	(vip-unrecord-kbd-macro "///" 'emacs-state))))
+
 
 (defun vip-search-forward (arg)
   "Search a string forward. 
@@ -4085,15 +4270,12 @@
 		      (re-search-backward string))
 		  (search-forward string nil nil val)
 		  (search-backward string))
-		;; don't wait and don't flash in macros
-		(or executing-kbd-macro
-		    (vip-flash-search-pattern))
 		(if (not (equal start-point (point)))
 		    (push-mark start-point t))) 
 	    (search-failed
 	     (if (and (not fail-if-not-found) vip-search-wrap-around-t)
 	         (progn
-		   (message "Search wrapped around end of buffer")
+		   (message "Search wrapped around BOTTOM of buffer")
 		   (goto-char (point-min))
 		   (vip-search string forward (cons 1 com) t start-point 'fail)
 		   ;; don't wait in macros
@@ -4112,15 +4294,12 @@
 	      (if vip-re-search
 		  (re-search-backward string nil nil val)
 	        (search-backward string nil nil val))
-	      ;; don't wait and don't flash in macros
-	      (or executing-kbd-macro
-		  (vip-flash-search-pattern))
 	      (if (not (equal start-point (point)))
 		  (push-mark start-point t))) 
 	  (search-failed
 	   (if (and (not fail-if-not-found) vip-search-wrap-around-t)
 	       (progn
-		 (message "Search wrapped around beginning of buffer")
+		 (message "Search wrapped around TOP of buffer")
 	         (goto-char (point-max))
 	         (vip-search string forward (cons 1 com) t start-point 'fail)
 		 ;; don't wait in macros
@@ -4132,7 +4311,14 @@
 	     (error "`%s': %s not found"
 		    string
 		    (if vip-re-search "Pattern" "String"))
-	     )))))))
+	     ))))
+      ;; pull up or down if at top/bottom of window
+      (vip-adjust-window)
+      ;; highlight the result of search
+      ;; don't wait and don't highlight in macros
+      (or executing-kbd-macro
+	  (vip-flash-search-pattern))
+      )))
 
 (defun vip-search-next (arg)
   "Repeat previous search."
@@ -4338,6 +4524,7 @@
     (setq vip-use-register nil)
     (if (vip-end-with-a-newline-p text)
 	(progn
+	  (end-of-line)
 	  (if (eobp)
 	      (insert "\n")
 	    (forward-line 1))
@@ -4752,6 +4939,7 @@
 	 (if (and (vip-same-line (point) vip-last-jump)
 		  (= (point) vip-last-jump-ignore))
 	     (goto-char vip-last-jump))
+	 (if (null (mark t)) (error "Mark is not set in this buffer"))
 	 (if (= (point) (mark t)) (pop-mark))
 	 (exchange-point-and-mark)
 	 (setq vip-last-jump (point-marker)
@@ -4828,7 +5016,9 @@
 		vip-open-line vip-Open-line
 		vip-replace-state-exit-cmd))
 	(indent-to-left-margin))
-    (newline 1)
+    ;; use \n instead of newline, or else <Return> will move the insert point
+    ;;(newline 1)
+    (insert "\n")
     (if vip-auto-indent
 	(progn
 	  (setq vip-cted t)
@@ -4952,13 +5142,10 @@
 	vip-ex-style-editing-in-insert  t
 	vip-want-ctl-h-help nil)
 
-  (cond
-	;; a novice or a beginner
-	((eq vip-expert-level 1)
-	 (global-set-key vip-toggle-key   ;; in emacs-state
-			 (if (vip-window-display-p)
-			     'vip-iconify
-			   'suspend-emacs))
+  (cond ((eq vip-expert-level 1) ; novice or beginner
+	 (global-set-key   ; in emacs-state 
+	  vip-toggle-key
+	  (if (vip-window-display-p) 'vip-iconify 'suspend-emacs))
 	 (setq vip-no-multiple-ESC	     t
 	       vip-re-search	    	     t
 	       vip-vi-style-in-minibuffer    t
@@ -4966,8 +5153,8 @@
 	       vip-want-emacs-keys-in-vi     nil
 	       vip-want-emacs-keys-in-insert nil))
 	
-	;; an intermediate to guru
 	((and (> vip-expert-level 1) (< vip-expert-level 5))
+	 ;; an intermediate to guru
 	 (setq vip-no-multiple-ESC     (if (vip-window-display-p) t 'twice)
 	       vip-want-emacs-keys-in-vi     t
 	       vip-want-emacs-keys-in-insert (> vip-expert-level 2))
@@ -4992,9 +5179,9 @@
 		     (cdr (assoc 'vip-no-multiple-ESC
 				 vip-saved-user-settings))))))
 	       
-	;; A wizard
+	;; A wizard!!
 	;; Ideally, if 5 is selected, a buffer should pop up to let the
-	;; user toggle variable values.
+	;; user toggle the values of variables.
 	(t (setq-default vip-ex-style-editing-in-insert
 			 (cdr (assoc 'vip-ex-style-editing-in-insert
 				     vip-saved-user-settings))
@@ -5374,17 +5561,11 @@
 
 ;; This hook designed to enable Vi-style editing in comint-based modes."
 (defun vip-comint-mode-hook ()
-  (setq require-final-newline nil)
-  (setq vip-ex-style-editing-in-insert nil
+  (setq require-final-newline nil
+	vip-ex-style-editing-in-insert nil
 	vip-ex-style-motion nil)
-  (vip-add-local-keys 'vi-state
-		      '(("\C-m" . comint-send-input) ; return
-			("\C-d" . comint-delchar-or-maybe-eof))) ; \C-d
-  (vip-add-local-keys 'insert-state
-		      '(("\C-m" . comint-send-input) ; return
-			("\C-d" . comint-delchar-or-maybe-eof))) ; \C-d
-  )
-  
+  (vip-change-state-to-insert))
+
 
 ;; This sets major mode hooks to make them come up in vi-state.
 (defun vip-set-hooks ()
@@ -5413,7 +5594,9 @@
   (add-hook 'html-mode-hook 'viper-mode)
   (defvar html-helper-mode-hook)
   (add-hook 'html-helper-mode-hook 'viper-mode)
-  
+  (defvar java-mode-hook)
+  (add-hook 'java-mode-hook 'viper-mode)
+
   (defvar emacs-lisp-mode-hook)
   (add-hook 'emacs-lisp-mode-hook 'viper-mode)
 
@@ -5438,6 +5621,11 @@
   (defvar fortran-mode-hook)
   (add-hook 'fortran-mode-hook 'vip-mode)
       
+  (defvar basic-mode-hook)
+  (add-hook 'basic-mode-hook 'vip-mode)
+  (defvar bat-mode-hook)
+  (add-hook 'bat-mode-hook 'vip-mode)
+
   (defvar text-mode-hook)
   (add-hook 'text-mode-hook 'viper-mode)
       
@@ -5449,7 +5637,18 @@
   
   (defvar emerge-startup-hook)
   (add-hook 'emerge-startup-hook 'vip-change-state-to-emacs)
-  ;; Run vip-change-state-to-vi after quitting emerge.
+
+  ;; Tell vc-diff to put *vc* in Vi mode
+  (if (featurep 'vc)
+      (defadvice vc-diff (after vip-vc-ad activate)
+	"Force Vi state in VC diff buffer."
+	(vip-change-state-to-vi))
+    (vip-eval-after-load
+     "vc"
+     '(defadvice vc-diff (after vip-vc-ad activate)
+	"Force Vi state in VC diff buffer."
+	(vip-change-state-to-vi))))
+
   (vip-eval-after-load
    "emerge"
    '(defadvice emerge-quit (after vip-emerge-advice activate)
@@ -5482,9 +5681,27 @@
   
   ;; Emacs shell, ange-ftp, and comint-based modes
   (defvar comint-mode-hook)
-  (add-hook 'comint-mode-hook 'vip-change-state-to-insert)
+  (vip-modify-major-mode 
+   'comint-mode 'insert-state vip-comint-mode-modifier-map)
+  (vip-modify-major-mode 
+   'comint-mode 'vi-state vip-comint-mode-modifier-map)
+  (vip-modify-major-mode 
+   'shell-mode 'insert-state vip-comint-mode-modifier-map)
+  (vip-modify-major-mode 
+   'shell-mode 'vi-state vip-comint-mode-modifier-map)
+  ;; ange-ftp in XEmacs
+  (vip-modify-major-mode 
+   'ange-ftp-shell-mode 'insert-state vip-comint-mode-modifier-map)
+  (vip-modify-major-mode 
+   'ange-ftp-shell-mode 'vi-state vip-comint-mode-modifier-map)
+  ;; ange-ftp in Emacs
+  (vip-modify-major-mode 
+   'internal-ange-ftp-mode 'insert-state vip-comint-mode-modifier-map)
+  (vip-modify-major-mode 
+   'internal-ange-ftp-mode 'vi-state vip-comint-mode-modifier-map)
+  ;; set hook
   (add-hook 'comint-mode-hook 'vip-comint-mode-hook)
-  
+
   ;; Shell scripts
   (defvar sh-mode-hook)
   (add-hook 'sh-mode-hook 'viper-mode)
@@ -5492,9 +5709,50 @@
   (add-hook 'ksh-mode-hook 'viper-mode)
   
   ;; Dired
-  ;; This is only necessary when the user uses vip-modify-major-mode
+  (vip-modify-major-mode 'dired-mode 'emacs-state vip-dired-modifier-map)
+  (vip-set-emacs-search-style-macros nil 'dired-mode)
   (add-hook 'dired-mode-hook 'vip-change-state-to-emacs)
 
+  ;; Tar
+  (vip-modify-major-mode 'tar-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'tar-mode)
+
+  ;; MH-E
+  (vip-modify-major-mode 'mh-folder-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'mh-folder-mode)
+  ;; changing state to emacs is needed so the preceding will take hold
+  (add-hook 'mh-folder-mode-hook 'vip-change-state-to-emacs)
+  (add-hook 'mh-show-mode-hook 'viper-mode)
+
+  ;; Gnus
+  (vip-modify-major-mode 'gnus-group-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'gnus-group-mode)
+  (vip-modify-major-mode 
+   'gnus-summary-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'gnus-summary-mode)
+  ;; changing state to emacs is needed so the preceding will take hold
+  (add-hook 'gnus-group-mode-hook 'vip-change-state-to-emacs)
+  (add-hook 'gnus-summary-mode-hook 'vip-change-state-to-emacs)
+  (add-hook 'gnus-article-mode-hook 'viper-mode)
+
+  ;; Info
+  (vip-modify-major-mode 'Info-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'Info-mode)
+  ;; Switching to emacs is needed  so the above will take hold
+  (defadvice Info-mode (after vip-Info-ad activate)
+    "Switch to emacs mode."
+    (vip-change-state-to-emacs))
+
+  ;; Buffer menu
+  (vip-modify-major-mode 
+   'Buffer-menu-mode 'emacs-state vip-slash-and-colon-map)
+  (vip-set-emacs-search-style-macros nil 'Buffer-menu-mode)
+  ;; Switching to emacs is needed  so the above will take hold
+  (defadvice Buffer-menu-mode (after vip-Buffer-menu-ad activate)
+    "Switch to emacs mode."
+    (vip-change-state-to-emacs))
+
+  ;; View mode
   (if vip-emacs-p
       (progn
 	(defvar view-mode-hook)
@@ -5537,15 +5795,9 @@
  (vector vip-repeat-from-history-key '\2) 'vi-state
  [(meta x) v i p - r e p e a t - f r o m - h i s t o r y return] 't)
  
-;; toggle case sensitivity in search
-(vip-record-kbd-macro
- "//" 'vi-state
- [1 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return] 't)
-;; toggle regexp/vanila search
-(vip-record-kbd-macro
- "///" 'vi-state
- [2 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return] 't)
- 
+;; set the toggle case sensitivity and regexp search macros
+(vip-set-vi-search-style-macros nil)
+
 
 ;; ~/.vip is loaded if it exists
 (if (and (file-exists-p vip-custom-file-name)
@@ -5575,6 +5827,7 @@
 (vip-set-minibuffer-style)
 (vip-set-minibuffer-faces)
 (vip-set-search-face)
+(vip-set-replace-overlay-face)
 (if vip-buffer-search-char
     (vip-buffer-search-enable))
 (vip-update-alphanumeric-class)
@@ -5603,15 +5856,10 @@
 ;; This is taken care of by vip-insert-global-user-map.
 ;;(define-key vip-replace-map vip-ESC-key 'vip-intercept-ESC-key)
 
-(define-key vip-insert-intercept-map vip-toggle-key 'vip-alternate-ESC)
+
 ;; The default vip-toggle-key is \C-z; for the novice, it suspends or
 ;; iconifies Emacs
-(define-key vip-vi-intercept-map vip-toggle-key
-  '(lambda () (interactive)
-     (if (and (< vip-expert-level 2) (equal vip-toggle-key "\C-z"))
-	 (if (vip-window-display-p) (vip-iconify) (suspend-emacs))
-       (vip-change-state-to-emacs))))
-
+(define-key vip-vi-intercept-map vip-toggle-key 'vip-toggle-key-action)
 (define-key vip-emacs-intercept-map vip-toggle-key 'vip-change-state-to-vi)