]> code.delx.au - gnu-emacs/blobdiff - lisp/emulation/viper.el
*** empty log message ***
[gnu-emacs] / lisp / emulation / viper.el
index 403bd25644be3c1d86c1c834f6fb1ee7dc15309c..6c940d9522c30d24686bc52e115d267a30397b39 100644 (file)
@@ -1,4 +1,4 @@
-;;; viper.el --- A full-featured Vi emulator.
+;;; viper.el --- A full-featured Vi emulator for GNU Emacs 19 and XEmacs 19,
 ;;              a VI Plan for Emacs Rescue,
 ;;              and a venomous VI PERil.
 ;;              Viper Is also a Package for Emacs Rebels.
@@ -6,10 +6,10 @@
 ;;  Keywords: emulations
 ;;  Author: Michael Kifer <kifer@cs.sunysb.edu>
 
-(defconst viper-version "2.82 of October 12, 1995"
-  "The current version of Viper")
+;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+(defconst viper-version "2.90 of June 19, 1996"
+  "The current version of Viper")
 
 ;; This file is part of GNU Emacs.
 
 ;;    much easier.
 ;;
 
+;; Code
 
 (require 'advice)
 (require 'cl)
 
 (require 'viper-util)
 
+;; Compiler pacifier
+(defvar vip-minibuffer-current-face)
+(defvar vip-minibuffer-insert-face)
+(defvar vip-minibuffer-vi-face)
+(defvar vip-minibuffer-emacs-face)
+(defvar iso-accents-mode)
+(defvar zmacs-region-stays)
+;; end pacifier
+
 \f
 ;;; Variables
              
@@ -467,9 +477,10 @@ it better fits your working style.")
 (vip-deflocalvar vip-replace-overlay nil "")
 (put 'vip-replace-overlay 'permanent-local t)
 
-(if (vip-window-display-p)
+(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")
@@ -492,7 +503,7 @@ is non-nil.")
 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-window-display-p)) (not (vip-color-display-p)))
+  (or (not (vip-has-face-support-p)) (not (vip-color-display-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
@@ -589,8 +600,11 @@ bound to delete-backward-char.")
 ;; Whether to preserve the indent, used by C-d in insert mode.
 (vip-deflocalvar vip-preserve-indent nil)
 
-(defconst vip-auto-indent nil
+(vip-deflocalvar vip-auto-indent nil
   "*Autoindent if t.")
+(vip-deflocalvar vip-electric-mode t
+  "*If t, enable electric behavior. 
+Currently only enables auto-indentation `according to mode'.")
 
 (defconst vip-shift-width 8
   "*The shiftwidth variable.")
@@ -806,10 +820,22 @@ These buffers can be cycled through via :R and :P commands.")
 (defvar vip-always t
   "t means, arrange that vi-state will be a default.")
 
-(defvar vip-custom-file-name "~/.vip"
+(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"))
   "Viper customisation file.
 This variable must be set _before_ loading Viper.")
 
+
 (defvar vip-spell-function 'ispell-region
   "Spell function used by #s<move> command to spell.")
 
@@ -928,7 +954,110 @@ Should be set in `~/.vip' file.")
 (require 'viper-keym)
 
 \f
-;;;; CODE
+;;; CODE
+
+;; sentinels
+
+;; Runs vip-after-change-functions inside after-change-functions
+(defun vip-after-change-sentinel (beg end len)
+  (let ((list vip-after-change-functions))
+    (while list
+      (funcall (car list) beg end len)
+      (setq list (cdr list)))))
+      
+;; Runs vip-before-change-functions inside before-change-functions
+(defun vip-before-change-sentinel (beg end)
+  (let ((list vip-before-change-functions))
+    (while list
+      (funcall (car list) beg end)
+      (setq list (cdr list)))))
+
+(defsubst vip-post-command-sentinel ()
+  (run-hooks 'vip-post-command-hooks))
+  
+(defsubst vip-pre-command-sentinel ()
+  (run-hooks 'vip-pre-command-hooks))
+  
+;; Needed so that Viper will be able to figure the last inserted
+;; chunk of text with reasonable accuracy.
+(defsubst vip-insert-state-post-command-sentinel ()
+  (if (and (memq vip-current-state '(insert-state replace-state))
+          vip-insert-point
+          (>= (point) vip-insert-point))
+      (setq vip-last-posn-while-in-insert-state (point-marker)))
+  (if (and (eq this-command 'dabbrev-expand)
+          (integerp vip-pre-command-point)
+          (> vip-insert-point vip-pre-command-point))
+      (move-marker vip-insert-point vip-pre-command-point))
+  )
+  
+(defsubst vip-insert-state-pre-command-sentinel ()
+  (if (and (eq this-command 'dabbrev-expand)
+          (markerp vip-insert-point)
+          (marker-position vip-insert-point))
+      (setq vip-pre-command-point (marker-position vip-insert-point))))
+       
+(defsubst vip-R-state-post-command-sentinel ()
+  ;; Restoring cursor color is needed despite
+  ;; vip-replace-state-pre-command-sentinel: When you jump to another buffer in
+  ;; another frame, the pre-command hook won't change cursor color to default
+  ;; in that other frame.  So, if the second frame cursor was red and we set
+  ;; the point outside the replacement region, then the cursor color will
+  ;; remain red. Restoring the default, below, prevents this.
+  (if (and (<= (vip-replace-start) (point))
+          (<=  (point) (vip-replace-end)))
+      (vip-change-cursor-color vip-replace-overlay-cursor-color)
+    (vip-restore-cursor-color)
+    ))
+
+;; to speed up, don't change cursor color before self-insert
+;; and common move commands
+(defsubst vip-replace-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)))
+  
+(defun vip-replace-state-post-command-sentinel ()
+  ;; Restoring cursor color is needed despite
+  ;; vip-replace-state-pre-command-sentinel: When one jumps to another buffer
+  ;; in another frame, the pre-command hook won't change cursor color to
+  ;; default in that other frame.  So, if the second frame cursor was red and
+  ;; we set the point outside the replacement region, then the cursor color
+  ;; will remain red. Restoring the default, below, fixes this problem.
+  ;;
+  ;; We optimize for self-insert-command's here, since they either don't change
+  ;; 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))
+  (cond 
+   ((eq vip-current-state 'replace-state)
+    ;; delete characters to compensate for inserted chars.
+    (let ((replace-boundary (vip-replace-end)))
+      (save-excursion
+       (goto-char vip-last-posn-in-replace-region)
+       (delete-char vip-replace-chars-to-delete)
+       (setq vip-replace-chars-to-delete 0
+             vip-replace-chars-deleted 0)
+       ;; terminate replace mode if reached replace limit
+       (if (= vip-last-posn-in-replace-region 
+              (vip-replace-end))
+           (vip-finish-change vip-last-posn-in-replace-region)))
+      
+      (if (and (<= (vip-replace-start) (point))
+              (<=  (point) replace-boundary))
+         (progn
+           ;; the state may have changed in vip-finish-change above
+           (if (eq vip-current-state 'replace-state)
+               (vip-change-cursor-color vip-replace-overlay-cursor-color))
+           (setq vip-last-posn-in-replace-region (point-marker))))
+      ))
+   
+   (t ;; terminate replace mode if changed Viper states.
+    (vip-finish-change vip-last-posn-in-replace-region))))
+
 
 ;; changing mode
 
@@ -936,16 +1065,17 @@ Should be set in `~/.vip' file.")
 (defun vip-change-state (new-state)
   ;; Keep vip-post/pre-command-hooks fresh.
   ;; We remove then add vip-post/pre-command-sentinel since it is very
-  ;; desirable that noone gets in-between
+  ;; desirable that vip-pre-command-sentinel is the last hook and
+  ;; vip-post-command-sentinel is the first hook.
   (remove-hook 'post-command-hook 'vip-post-command-sentinel)
   (add-hook 'post-command-hook 'vip-post-command-sentinel)
   (remove-hook 'pre-command-hook 'vip-pre-command-sentinel)
   (add-hook 'pre-command-hook 'vip-pre-command-sentinel t)
   ;; These hooks will be added back if switching to insert/replace mode
   (vip-remove-hook 'vip-post-command-hooks
-              'vip-insert-state-post-command-sentinel)
+                  'vip-insert-state-post-command-sentinel)
   (vip-remove-hook 'vip-pre-command-hooks
-              'vip-insert-state-pre-command-sentinel)
+                  'vip-insert-state-pre-command-sentinel)
   (cond ((eq new-state 'vi-state)
         (cond ((member vip-current-state '(insert-state replace-state))
                    
@@ -986,9 +1116,9 @@ Should be set in `~/.vip' file.")
             (vip-move-marker-locally 'vip-insert-point (point)))
         (vip-move-marker-locally 'vip-last-posn-while-in-insert-state (point))
         (vip-add-hook 'vip-post-command-hooks
-                  'vip-insert-state-post-command-sentinel t)
+                      'vip-insert-state-post-command-sentinel t)
         (vip-add-hook 'vip-pre-command-hooks
-                  'vip-insert-state-pre-command-sentinel t))
+                      'vip-insert-state-pre-command-sentinel t))
        ) ; outermost cond
   
   ;; Nothing needs to be done to switch to emacs mode! Just set some
@@ -1132,19 +1262,17 @@ Technically speaking, Viper is a Vi emulation package for GNU Emacs 19 and
 XEmacs 19.  It supports virtually all of Vi and Ex functionality, extending
 and improving upon much of it.
 
-   1. Viper supports Vi at several levels. Level 1 is the closest to
-      Vi, level 5 provides the most flexibility to depart from many Vi
-      conventions.
+   1. Viper supports Vi at several levels. Level 1 is the closest to Vi,
+      level 5 provides the most flexibility to depart from many Vi conventions.
       
       You will be asked to specify your user level in a following screen.
    
-      If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will
-      behave as in VI, to smooth transition to Viper for the beginners. 
-      However, to use Emacs productively, you are advised to reach user
-      level 3 or higher. 
+      If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will behave
+      as in VI, to smooth transition to Viper for the beginners. However, to
+      use Emacs productively, you are advised to reach user level 3 or higher. 
       
       If your user level is 2 or higher, ^X and ^C will invoke Emacs
-      functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and
+      functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and 
       ^G will be the usual Emacs's keyboard-quit (something like ^C in VI).
    
    2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
@@ -1155,9 +1283,8 @@ and improving upon much of it.
    
    6. Emacs Meta functions are invoked by typing `_' 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. 
+   7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
+      something funny happens. This would abort the current editing command. 
       
 You can get more information on Viper by:
 
@@ -1173,8 +1300,11 @@ This startup message appears whenever you load Viper, unless you type `y' now."
                         'vip-inhibit-startup-message
                         "Viper startup message inhibited"
                         vip-custom-file-name t))
-                   (kill-buffer (current-buffer))))
-             (message " ")
+                   ;;(kill-buffer (current-buffer))
+                   (message
+                    "The last message is in buffer `Viper Startup Message'")
+                   (sit-for 4)
+                   ))
              (vip-set-expert-level 'dont-change-unless)))
        (vip-change-state-to-vi))))
        
@@ -1264,7 +1394,7 @@ This startup message appears whenever you load Viper, unless you type `y' now."
        ))
        
   ;; minibuffer faces
-  (if (vip-window-display-p)
+  (if (vip-has-face-support-p)
       (setq vip-minibuffer-current-face
            (cond ((eq state 'emacs-state) vip-minibuffer-emacs-face)
                  ((eq state 'vi-state) vip-minibuffer-vi-face)
@@ -1462,7 +1592,7 @@ Suffixes such as .el or .elc should be stripped."
   (vip-eval-after-load
    load-file '(setq-default minor-mode-map-alist minor-mode-map-alist))
   )
-  
+
 
 (defun vip-ESC (arg)
   "Emulate ESC key in Emacs.
@@ -1633,13 +1763,41 @@ behaves as in Emacs, any number of multiple escapes is allowed."
 ;; represents the numeric value of the prefix argument and COM represents
 ;; command prefix such as "c", "d", "m" and "y".
 
+;; Get value part of prefix-argument ARG.
+(defsubst vip-p-val (arg)
+  (cond ((null arg) 1)
+       ((consp arg)
+        (if (or (null (car arg)) (equal (car arg) '(nil)))
+            1 (car arg)))
+       (t arg)))
+
+;; Get raw value part of prefix-argument ARG.
+(defsubst vip-P-val (arg)
+  (cond ((consp arg) (car arg))
+       (t arg)))
+
+;; Get com part of prefix-argument ARG.
+(defsubst vip-getcom (arg)
+  (cond ((null arg) nil)
+       ((consp arg) (cdr arg))
+       (t nil)))
+
+;; Get com part of prefix-argument ARG and modify it.
+(defun vip-getCom (arg)
+  (let ((com (vip-getcom arg)))
+    (cond ((equal com ?c) ?C)
+         ((equal com ?d) ?D)
+         ((equal com ?y) ?Y)
+         (t com))))
+
+
 ;; Compute numeric prefix arg value. 
 ;; Invoked by CHAR. COM is the command part obtained so far.
 (defun vip-prefix-arg-value (event com)
   (let (value)
     ;; read while number
-    (while (and (numberp event) (>= event ?0) (<= event ?9))
-      (setq value (+ (* (if (numberp value) value 0) 10) (- event ?0)))
+    (while (and (vip-characterp event) (>= event ?0) (<= event ?9))
+      (setq value (+ (* (if (vip-characterp value) value 0) 10) (- event ?0)))
       (setq event (vip-read-event-convert-to-char)))
     
     (setq prefix-arg value)
@@ -1689,7 +1847,9 @@ behaves as in Emacs, any number of multiple escapes is allowed."
   (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
+      ;; 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.
       (progn
        (setq prefix-arg (cons value com))
        (while (= char ?U)
@@ -1746,43 +1906,16 @@ behaves as in Emacs, any number of multiple escapes is allowed."
        last-command-char   
        (cond ((null arg) nil)
             ((consp arg) (car arg))
-            ((numberp arg) arg)
+            ((integerp arg) arg)
             (t (error vip-InvalidCommandArgument)))
        (cond ((null arg) nil)
             ((consp arg) (cdr arg))
-            ((numberp arg) nil)
+            ((integerp arg) nil)
             (t (error vip-InvalidCommandArgument))))
     (quit (setq vip-use-register nil)
          (signal 'quit nil)))
   (vip-deactivate-mark))
 
-;; Get value part of prefix-argument ARG.
-(defsubst vip-p-val (arg)
-  (cond ((null arg) 1)
-       ((consp arg)
-        (if (or (null (car arg)) (equal (car arg) '(nil)))
-            1 (car arg)))
-       (t arg)))
-
-;; Get raw value part of prefix-argument ARG.
-(defsubst vip-P-val (arg)
-  (cond ((consp arg) (car arg))
-       (t arg)))
-
-;; Get com part of prefix-argument ARG.
-(defsubst vip-getcom (arg)
-  (cond ((null arg) nil)
-       ((consp arg) (cdr arg))
-       (t nil)))
-
-;; Get com part of prefix-argument ARG and modify it.
-(defun vip-getCom (arg)
-  (let ((com (vip-getcom arg)))
-    (cond ((equal com ?c) ?C)
-         ((equal com ?d) ?D)
-         ((equal com ?y) ?Y)
-         (t com))))
-
 \f
 ;; repeat last destructive command
 
@@ -1792,10 +1925,31 @@ behaves as in Emacs, any number of multiple escapes is allowed."
   (set-register reg (concat (if (stringp (get-register reg))
                                (get-register reg) "")
                            (buffer-substring start end))))
+
+;; Saves last inserted text for possible use by vip-repeat command.
+(defun vip-save-last-insertion (beg end)
+  (setq vip-last-insertion (buffer-substring beg end))
+  (or (< (length vip-d-com) 5)
+      (setcar (nthcdr 4 vip-d-com) vip-last-insertion))
+  (or (null vip-command-ring)
+      (ring-empty-p vip-command-ring)
+      (progn
+       (setcar (nthcdr 4 (vip-current-ring-item vip-command-ring))
+               vip-last-insertion)
+       ;; del most recent elt, if identical to the second most-recent
+       (vip-cleanup-ring vip-command-ring)))
+  )
+    
+(defsubst vip-yank-last-insertion ()
+  "Inserts the text saved by the previous vip-save-last-insertion command."
+  (condition-case nil
+      (insert vip-last-insertion)
+    (error nil)))
+  
                            
 ;; define functions to be executed
 
-;; invoked by C command
+;; invoked by the `C' command
 (defun vip-exec-change (m-com com) 
   ;; handle C cmd at the eol and at eob.
   (if (or (and (eolp) (= vip-com-point (point)))
@@ -2065,10 +2219,11 @@ invokes the command before that, etc."
         (vip-d-com vip-d-com))
 
     (or (and (numberp num) (<= 0 num) (<= num 9))
-       (setq idx 0
-             num 0)
-       (message
-        "`vip-repeat-from-history' must be invoked as a Vi macro bound to `<key><digit>'"))
+       (progn
+         (setq idx 0
+               num 0)
+         (message
+          "`vip-repeat-from-history' must be invoked as a Vi macro bound to `<key><digit>'")))
     (while (< 0 num)
       (setq vip-d-com (vip-special-ring-rotate1 vip-command-ring -1))
       (setq num (1- num)))
@@ -2277,11 +2432,11 @@ Undo previous insertion and inserts new."
       (end-of-line)
       ;; make sure all lines end with newline, unless in the minibuffer or
       ;; when requested otherwise (require-final-newline is nil)
-      (if (and
-          (eobp)
-          (not (bolp))
-          require-final-newline
-          (not (vip-is-in-minibuffer)))
+      (if (and (eobp)
+              (not (bolp))
+              require-final-newline
+              (not (vip-is-in-minibuffer))
+              (not buffer-read-only))
          (insert "\n"))))
 
 (defun vip-yank-defun ()
@@ -2367,10 +2522,6 @@ Undo previous insertion and inserts new."
                  'vip-change-state-to-insert
                'vip-change-state-to-emacs)))
     (funcall hook)
-
-    ;; Make sure the minibufer overlay is kept up-to-date. In XEmacs also
-    ;; guards against the possibility of detaching this overlay.
-    (vip-add-hook 'vip-post-command-hooks 'vip-move-minibuffer-overlay)
     ))
   
 ;; Interpret last event in the local map
@@ -2384,30 +2535,31 @@ Undo previous insertion and inserts new."
   
 
 (defun vip-set-search-face ()
-  (if (not (vip-window-display-p))
-      ()
-    (defvar vip-search-face
-      (progn
-       (make-face 'vip-search-face)
-       (or (face-differs-from-default-p 'vip-search-face)
-           ;; face wasn't set in .vip or .Xdefaults
-           (if (vip-can-use-colors "Black" "khaki")
-               (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)))
-       'vip-search-face)
+  (if (vip-has-face-support-p)
+      (defvar vip-search-face
+       (progn
+         (make-face 'vip-search-face)
+         (vip-hide-face 'vip-search-face)
+         (or (face-differs-from-default-p 'vip-search-face)
+             ;; face wasn't set in .vip or .Xdefaults
+             (if (vip-can-use-colors "Black" "khaki")
+                 (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)))
+         'vip-search-face)
         "*Face used to flash out the search pattern.")
     ))
   
   
 (defun vip-set-minibuffer-faces ()
-  (if (not (vip-window-display-p))
+  (if (not (vip-has-face-support-p))
       ()
     (defvar vip-minibuffer-emacs-face
       (progn
        (make-face 'vip-minibuffer-emacs-face)
+       (vip-hide-face 'vip-minibuffer-emacs-face)
        (or (face-differs-from-default-p 'vip-minibuffer-emacs-face)
            ;; face wasn't set in .vip or .Xdefaults
            (if vip-vi-style-in-minibuffer
@@ -2418,7 +2570,7 @@ Undo previous insertion and inserts new."
                       'vip-minibuffer-emacs-face "darkseagreen2")
                      (set-face-foreground
                       'vip-minibuffer-emacs-face "Black"))
-                 (copy-face 'highlight 'vip-minibuffer-emacs-face))
+                 (copy-face 'modeline 'vip-minibuffer-emacs-face))
              ;; emacs state is the main state in the minibuffer
              (if (vip-can-use-colors "Black" "pink")
                  (progn
@@ -2433,6 +2585,7 @@ Undo previous insertion and inserts new."
     (defvar vip-minibuffer-insert-face
       (progn
        (make-face 'vip-minibuffer-insert-face)
+       (vip-hide-face 'vip-minibuffer-insert-face)
        (or (face-differs-from-default-p 'vip-minibuffer-insert-face)
            (if vip-vi-style-in-minibuffer
                (if (vip-can-use-colors "Black" "pink")
@@ -2448,7 +2601,7 @@ Undo previous insertion and inserts new."
                     'vip-minibuffer-insert-face "darkseagreen2")
                    (set-face-foreground
                     'vip-minibuffer-insert-face "Black"))
-               (copy-face 'highlight 'vip-minibuffer-insert-face))
+               (copy-face 'modeline 'vip-minibuffer-insert-face))
              (vip-italicize-face 'vip-minibuffer-insert-face)))
        'vip-minibuffer-insert-face)
       "Face used in the Minibuffer when it is in Insert state.")
@@ -2456,6 +2609,7 @@ Undo previous insertion and inserts new."
     (defvar vip-minibuffer-vi-face
       (progn
        (make-face 'vip-minibuffer-vi-face)
+       (vip-hide-face 'vip-minibuffer-vi-face)
        (or (face-differs-from-default-p 'vip-minibuffer-vi-face)
            (if vip-vi-style-in-minibuffer
                (if (vip-can-use-colors "Black" "grey")
@@ -2478,9 +2632,9 @@ Undo previous insertion and inserts new."
     
 (defun vip-read-string-with-history (prompt &optional initial 
                                            history-var default keymap)
-  ;; Reads string, prompting with PROMPT and inserting the INITIAL
+  ;; Read string, prompting with PROMPT and inserting the INITIAL
   ;; value. Uses HISTORY-VAR. DEFAULT is the default value to accept if the
-  ;; input is an empty string. Uses KEYMAP, if given, or the
+  ;; input is an empty string. Use KEYMAP, if given, or the
   ;; minibuffer-local-map.
   ;; Default value is displayed until the user types something in the
   ;; minibuffer. 
@@ -2518,13 +2672,17 @@ Undo previous insertion and inserts new."
     (if (or (string= (nth 0 (eval history-var)) (nth 1 (eval history-var)))
            (string= (nth 0 (eval history-var)) ""))
        (set history-var (cdr (eval history-var))))
-    ;; if the user enters nothing but the prev cmd wasn't vip-ex or
-    ;; vip-command-argument, this means that the user typed something then
-    ;; erased. Return "" in this case, not the default---default is too
-    ;; confusing in this case
+    ;; If the user enters nothing but the prev cmd wasn't vip-ex,
+    ;; vip-command-argument, or `! shell-command', this probably means 
+    ;; that the user typed something then erased. Return "" in this case, not
+    ;; the default---the default is too confusing in this case.
     (cond ((and (string= val "")
+               (not (string= prompt "!")) ; was a `! shell-command'
                (not (memq last-command
-                          (list 'vip-ex 'vip-command-argument t))))
+                          '(vip-ex
+                            vip-command-argument
+                            t)
+                          )))
           "")
          ((string= val "") (or default ""))
          (t val))
@@ -2609,11 +2767,22 @@ Undo previous insertion and inserts new."
                      (end-of-line)
                      (newline 1)
                      (if vip-auto-indent 
-                         (progn (setq vip-cted t) (indent-to col)))
+                         (progn
+                           (setq vip-cted t)
+                           (if vip-electric-mode
+                               (indent-according-to-mode)
+                             (indent-to col))
+                           ))
                      (vip-yank-last-insertion)))
        (end-of-line)
        (newline 1)
-       (if vip-auto-indent (progn (setq vip-cted t) (indent-to col)))
+       (if vip-auto-indent
+           (progn
+             (setq vip-cted t)
+             (if vip-electric-mode
+                 (indent-according-to-mode)
+               (indent-to col))
+             ))
        (vip-change-state-to-insert)
        ))))
 
@@ -2631,11 +2800,22 @@ Undo previous insertion and inserts new."
                      (beginning-of-line)
                      (open-line 1)
                      (if vip-auto-indent 
-                         (progn (setq vip-cted t) (indent-to col)))
+                         (progn
+                           (setq vip-cted t)
+                           (if vip-electric-mode
+                               (indent-according-to-mode)
+                             (indent-to col))
+                           ))
                      (vip-yank-last-insertion)))
        (beginning-of-line)
        (open-line 1)
-       (if vip-auto-indent (progn (setq vip-cted t) (indent-to col)))
+       (if vip-auto-indent
+           (progn
+             (setq vip-cted t)
+             (if vip-electric-mode
+                 (indent-according-to-mode)
+               (indent-to col))
+             ))
        (vip-change-state-to-insert)))))
 
 (defun vip-open-line-at-point (arg)
@@ -2692,106 +2872,6 @@ Undo previous insertion and inserts new."
    'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel t)
   )
   
-;; Runs vip-after-change-functions inside after-change-functions
-(defun vip-after-change-sentinel (beg end len)
-  (let ((list vip-after-change-functions))
-    (while list
-      (funcall (car list) beg end len)
-      (setq list (cdr list)))))
-      
-;; Runs vip-before-change-functions inside before-change-functions
-(defun vip-before-change-sentinel (beg end)
-  (let ((list vip-before-change-functions))
-    (while list
-      (funcall (car list) beg end)
-      (setq list (cdr list)))))
-
-(defsubst vip-post-command-sentinel ()
-  (run-hooks 'vip-post-command-hooks))
-  
-(defsubst vip-pre-command-sentinel ()
-  (run-hooks 'vip-pre-command-hooks))
-  
-;; Needed so that Viper will be able to figure the last inserted
-;; chunk of text with reasonable accuracy.
-(defsubst vip-insert-state-post-command-sentinel ()
-  (if (and (memq vip-current-state '(insert-state replace-state))
-          vip-insert-point
-          (>= (point) vip-insert-point))
-      (setq vip-last-posn-while-in-insert-state (point-marker)))
-  (if (and (eq this-command 'dabbrev-expand)
-          (integerp vip-pre-command-point)
-          (> vip-insert-point vip-pre-command-point))
-      (move-marker vip-insert-point vip-pre-command-point))
-  )
-  
-(defsubst vip-insert-state-pre-command-sentinel ()
-  (if (and (eq this-command 'dabbrev-expand)
-          (markerp vip-insert-point)
-          (marker-position vip-insert-point))
-      (setq vip-pre-command-point (marker-position vip-insert-point))))
-       
-(defsubst vip-R-state-post-command-sentinel ()
-  ;; Restoring cursor color is needed despite
-  ;; vip-replace-state-pre-command-sentinel: When you jump to another buffer in
-  ;; another frame, the pre-command hook won't change cursor color to default
-  ;; in that other frame.  So, if the second frame cursor was red and we set
-  ;; the point outside the replacement region, then the cursor color will
-  ;; remain red. Restoring the default, below, prevents this.
-  (if (and (<= (vip-replace-start) (point))
-          (<=  (point) (vip-replace-end)))
-      (vip-change-cursor-color vip-replace-overlay-cursor-color)
-    (vip-restore-cursor-color)
-    ))
-
-;; to speed up, don't change cursor color before self-insert
-;; and common move commands
-(defsubst vip-replace-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)))
-  
-(defun vip-replace-state-post-command-sentinel ()
-  ;; Restoring cursor color is needed despite
-  ;; vip-replace-state-pre-command-sentinel: When one jumps to another buffer
-  ;; in another frame, the pre-command hook won't change cursor color to
-  ;; default in that other frame.  So, if the second frame cursor was red and
-  ;; we set the point outside the replacement region, then the cursor color
-  ;; will remain red. Restoring the default, below, fixes this problem.
-  ;;
-  ;; We optimize for self-insert-command's here, since they either don't change
-  ;; 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))
-  (cond 
-   ((eq vip-current-state 'replace-state)
-    ;; delete characters to compensate for inserted chars.
-    (let ((replace-boundary (vip-replace-end)))
-      (save-excursion
-       (goto-char vip-last-posn-in-replace-region)
-       (delete-char vip-replace-chars-to-delete)
-       (setq vip-replace-chars-to-delete 0
-             vip-replace-chars-deleted 0)
-       ;; terminate replace mode if reached replace limit
-       (if (= vip-last-posn-in-replace-region 
-              (vip-replace-end))
-           (vip-finish-change vip-last-posn-in-replace-region)))
-      
-      (if (and (<= (vip-replace-start) (point))
-              (<=  (point) replace-boundary))
-         (progn
-           ;; the state may have changed in vip-finish-change above
-           (if (eq vip-current-state 'replace-state)
-               (vip-change-cursor-color vip-replace-overlay-cursor-color))
-           (setq vip-last-posn-in-replace-region (point-marker))))
-      ))
-   
-   (t ;; terminate replace mode if changed Viper states.
-    (vip-finish-change vip-last-posn-in-replace-region))))
-
 
 ;; checks how many chars were deleted by the last change
 (defun vip-replace-mode-spy-before (beg end)
@@ -2827,7 +2907,7 @@ Undo previous insertion and inserts new."
       ;;
       ;; The reason why new-dabbrev.el causes this are this:
       ;; if one dinamically completes a partial word that starts before the
-      ;; replacement region (but ends inside)then new-dabbrev.el first
+      ;; replacement region (but ends inside) then new-dabbrev.el first
       ;; moves cursor backwards, to the beginning of the word to be
       ;; completed (say, pt A). Then it inserts the 
       ;; completed word and then deletes the old, incomplete part.
@@ -2836,9 +2916,7 @@ Undo previous insertion and inserts new."
       ;; unless we check for the current command, which must be
       ;; dabbrev-expand.
       ;;
-      ;; We should be able deal with these problems in a better way
-      ;; when emacs will have overlays with sticky back ends.
-      ;; In fact, it would be also useful to add overlays for insert
+      ;; In fact, it might be also useful to have overlays for insert
       ;; regions as well, since this will let us capture the situation when
       ;; dabbrev-expand goes back past the insertion point to find the
       ;; beginning of the word to be expanded.
@@ -3486,15 +3564,16 @@ called from vip-repeat, the char last used is used.  This behaviour is
 controlled by the sign of prefix numeric value."
   (interactive "P")
   (let ((val (vip-p-val arg))
-       (com (vip-getcom arg)))
+       (com (vip-getcom arg))
+       (cmd-representation (nth 5 vip-d-com)))
     (if (> val 0)
        ;; this means that the function was called interactively
        (setq vip-f-char (read-char)
              vip-f-forward t
              vip-f-offset nil)
       ;; vip-repeat --- set vip-F-char from command-keys
-      (setq vip-F-char (if (stringp (nth 5 vip-d-com))
-                          (vip-seq-last-elt (nth 5 vip-d-com))
+      (setq vip-F-char (if (stringp cmd-representation)
+                          (vip-seq-last-elt cmd-representation)
                         vip-F-char)
            vip-f-char vip-F-char)
       (setq val (- val)))
@@ -3511,15 +3590,16 @@ controlled by the sign of prefix numeric value."
   "Go up to char ARG forward on line."
   (interactive "P")
   (let ((val (vip-p-val arg))
-       (com (vip-getcom arg)))
+       (com (vip-getcom arg))
+       (cmd-representation (nth 5 vip-d-com)))
     (if (> val 0)
        ;; this means that the function was called interactively
        (setq vip-f-char (read-char)
              vip-f-forward t
              vip-f-offset t)
       ;; vip-repeat --- set vip-F-char from command-keys
-      (setq vip-F-char (if (stringp (nth 5 vip-d-com))
-                          (vip-seq-last-elt (nth 5 vip-d-com))
+      (setq vip-F-char (if (stringp cmd-representation)
+                          (vip-seq-last-elt cmd-representation)
                         vip-F-char)
            vip-f-char vip-F-char)
       (setq val (- val)))
@@ -3536,15 +3616,16 @@ controlled by the sign of prefix numeric value."
   "Find char ARG on line backward."
   (interactive "P")
   (let ((val (vip-p-val arg))
-       (com (vip-getcom arg)))
+       (com (vip-getcom arg))
+       (cmd-representation (nth 5 vip-d-com)))
     (if (> val 0)
        ;; this means that the function was called interactively
        (setq vip-f-char (read-char)
              vip-f-forward nil
              vip-f-offset nil)
       ;; vip-repeat --- set vip-F-char from command-keys
-      (setq vip-F-char (if (stringp (nth 5 vip-d-com))
-                          (vip-seq-last-elt (nth 5 vip-d-com))
+      (setq vip-F-char (if (stringp cmd-representation)
+                          (vip-seq-last-elt cmd-representation)
                         vip-F-char)
            vip-f-char vip-F-char)
       (setq val (- val)))
@@ -3561,15 +3642,16 @@ controlled by the sign of prefix numeric value."
   "Go up to char ARG backward on line."
   (interactive "P")
   (let ((val (vip-p-val arg))
-       (com (vip-getcom arg)))
+       (com (vip-getcom arg))
+       (cmd-representation (nth 5 vip-d-com)))
     (if (> val 0)
        ;; this means that the function was called interactively
        (setq vip-f-char (read-char)
              vip-f-forward nil
              vip-f-offset t)
       ;; vip-repeat --- set vip-F-char from command-keys
-      (setq vip-F-char (if (stringp (nth 5 vip-d-com))
-                          (vip-seq-last-elt (nth 5 vip-d-com))
+      (setq vip-F-char (if (stringp cmd-representation)
+                          (vip-seq-last-elt cmd-representation)
                         vip-F-char)
            vip-f-char vip-F-char)
       (setq val (- val)))
@@ -3703,8 +3785,9 @@ controlled by the sign of prefix numeric value."
 (defun vip-paren-match (arg)
   "Go to the matching parenthesis."
   (interactive "P")
-  (let ((com (vip-getcom arg)))
-    (if (numberp arg)
+  (let ((com (vip-getcom arg))
+       anchor-point)
+    (if (integerp arg)
        (if (or (> arg 99) (< arg 1))
            (error "Prefix must be between 1 and 99")
          (goto-char
@@ -3712,20 +3795,33 @@ controlled by the sign of prefix numeric value."
               (* (/ (point-max) 100) arg)
             (/ (* (point-max) arg) 100)))
          (back-to-indentation))
-      (let (lim)
+      (let (beg-lim end-lim)
        (if (and (eolp) (not (bolp))) (forward-char -1))
+       (if (not (looking-at "[][(){}]"))
+           (setq anchor-point (point)))
        (save-excursion
+         (beginning-of-line)
+         (setq beg-lim (point))
          (end-of-line)
-         (setq lim (point)))
-       (if (re-search-forward "[][(){}]" lim t) 
-           (backward-char) 
-         (error "No matching character on line")))
+         (setq end-lim (point)))
+       (cond ((re-search-forward "[][(){}]" end-lim t) 
+              (backward-char) )
+             ((re-search-backward "[][(){}]" beg-lim t))
+             (t
+              (error "No matching character on line"))))
       (cond ((looking-at "[\(\[{]")
             (if com (vip-move-marker-locally 'vip-com-point (point)))
             (forward-sexp 1)
             (if com
                 (vip-execute-com 'vip-paren-match nil com)
               (backward-char)))
+           (anchor-point
+            (if com
+                (progn
+                  (vip-move-marker-locally 'vip-com-point anchor-point)
+                  (forward-char 1)
+                  (vip-execute-com 'vip-paren-match nil com)
+                  )))
            ((looking-at "[])}]")
             (forward-char)
             (if com (vip-move-marker-locally 'vip-com-point (point)))
@@ -3764,7 +3860,10 @@ controlled by the sign of prefix numeric value."
        (com (vip-getCom arg)))
     (if com (vip-move-marker-locally 'vip-com-point (point)))
     (forward-paragraph val)
-    (if com (vip-execute-com 'vip-forward-paragraph nil com))))
+    (if com
+       (progn
+         (backward-char 1)
+         (vip-execute-com 'vip-forward-paragraph nil com)))))
 
 (defun vip-backward-paragraph (arg)
   "Backward paragraph."
@@ -3774,7 +3873,11 @@ controlled by the sign of prefix numeric value."
        (com (vip-getCom arg)))
     (if com (vip-move-marker-locally 'vip-com-point (point)))
     (backward-paragraph val)
-    (if com (vip-execute-com 'vip-backward-paragraph nil com))))
+    (if com
+       (progn
+         (forward-char 1)
+         (vip-execute-com 'vip-backward-paragraph nil com)
+         (backward-char 1)))))
 
 ;; should be mode-specific etc.
 
@@ -4295,26 +4398,6 @@ To turn this feature off, set this variable to nil.")
       (copy-region-as-kill beg end)
     (error (copy-region-as-kill beg beg))))
     
-;; Saves last inserted text for possible use by vip-repeat command.
-(defun vip-save-last-insertion (beg end)
-  (setq vip-last-insertion (buffer-substring beg end))
-  (or (< (length vip-d-com) 5)
-      (setcar (nthcdr 4 vip-d-com) vip-last-insertion))
-  (or (null vip-command-ring)
-      (ring-empty-p vip-command-ring)
-      (progn
-       (setcar (nthcdr 4 (vip-current-ring-item vip-command-ring))
-               vip-last-insertion)
-       ;; del most recent elt, if identical to the second most-recent
-       (vip-cleanup-ring vip-command-ring)))
-  )
-    
-(defsubst vip-yank-last-insertion ()
-  "Inserts the text saved by the previous vip-save-last-insertion command."
-  (condition-case nil
-      (insert vip-last-insertion)
-    (error nil)))
-  
 
 (defun vip-delete-char (arg)
   "Delete character."
@@ -4471,7 +4554,7 @@ cursor move past the beginning of line."
            (vip-change-state-to-replace t))
        (kill-region (vip-replace-start)
                     (vip-replace-end))
-       (vip-restore-cursor-color)
+       (vip-hide-replace-overlay)
        (vip-change-state-to-insert))
     (error ;; make sure that the overlay doesn't stay.
            ;; go back to the original point
@@ -4644,7 +4727,7 @@ One can use `` and '' to temporarily jump 1 step back."
                (text-marker (get-register reg)))
           (if com (vip-move-marker-locally 'vip-com-point (point)))
           (if (not (vip-valid-marker text-marker))
-              (error (format vip-EmptyTextmarker char)))
+              (error vip-EmptyTextmarker char))
           (if (and (vip-same-line (point) vip-last-jump)
                    (= (point) vip-last-jump-ignore))
               (push-mark vip-last-jump t) 
@@ -4698,6 +4781,12 @@ One can use `` and '' to temporarily jump 1 step back."
 
 ;; Input Mode Indentation
 
+;; Returns t, if the string before point matches the regexp STR.
+(defsubst vip-looking-back (str)
+  (and (save-excursion (re-search-backward str nil t))
+       (= (point) (match-end 0))))
+
+
 (defun vip-forward-indent ()
   "Indent forward -- `C-t' in Vi."
   (interactive)
@@ -4711,7 +4800,8 @@ One can use `` and '' to temporarily jump 1 step back."
       (let ((p (point)) (c (current-column)) bol (indent t))
        (if (vip-looking-back "[0^]")
            (progn
-             (if (= ?^ (preceding-char)) (setq vip-preserve-indent t))
+             (if (eq ?^ (preceding-char))
+                 (setq vip-preserve-indent t))
              (delete-backward-char 1)
              (setq p (point))
              (setq indent nil)))
@@ -4729,9 +4819,9 @@ One can use `` and '' to temporarily jump 1 step back."
   "Auto Indentation, Vi-style."
   (interactive)
   (let ((col (current-indentation)))
-    (if (not vip-preserve-indent)
-       (setq vip-current-indent col)
-      (setq vip-preserve-indent nil))
+    (if vip-preserve-indent
+       (setq vip-preserve-indent nil)
+      (setq vip-current-indent col))
     ;; don't leave whitespace lines around
     (if (memq last-command
              '(vip-autoindent
@@ -4742,7 +4832,11 @@ One can use `` and '' to temporarily jump 1 step back."
     (if vip-auto-indent
        (progn
          (setq vip-cted t)
-         (indent-to vip-current-indent)))))
+         (if vip-electric-mode
+             (indent-according-to-mode)
+           (indent-to vip-current-indent))
+         ))
+    ))
 
           
 ;; Viewing registers
@@ -4778,8 +4872,7 @@ One can use `` and '' to temporarily jump 1 step back."
          ((vip-valid-register reg '(letter))
           (let* ((val (get-register (1+ (- reg ?a))))
                  (buf (if (not val) 
-                          (error 
-                           (format vip-EmptyTextmarker reg))
+                          (error vip-EmptyTextmarker reg)
                         (marker-buffer val)))
                  (pos (marker-position val))
                  line-no text (s pos) (e pos))
@@ -4846,7 +4939,7 @@ sensitive for VI-style look-and-feel."
   
   (interactive)
   
-  (if (not (numberp vip-expert-level)) (setq vip-expert-level 0))
+  (if (not (natnump vip-expert-level)) (setq vip-expert-level 0))
   
   (save-window-excursion
     (delete-other-windows)
@@ -4878,7 +4971,7 @@ sensitive for VI-style look-and-feel."
         (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))
-              
+
         (if (eq vip-expert-level 4) ; respect user's ex-style motions
                                     ; and vip-no-multiple-ESC
             (progn
@@ -5044,13 +5137,6 @@ Please, specify your level now: ")
   (interactive)
   (beep 1))
   
-
-;; Returns t, if the string before point matches the regexp STR.
-(defsubst vip-looking-back (str)
-  (and (save-excursion (re-search-backward str nil t))
-       (= (point) (match-end 0))))
-
-    
     
 ;; if ENFORCE-BUFFER is not nil, error if CHAR is a marker in another buffer
 (defun vip-register-to-point (char &optional enforce-buffer)
@@ -5102,13 +5188,13 @@ Please, specify your level now: ")
     (setq color-display-p (if (vip-window-display-p) 
                              (vip-color-display-p)
                            'non-x)
-         minibuffer-vi-face (if (vip-window-display-p)
+         minibuffer-vi-face (if (vip-has-face-support-p)
                                 (vip-get-face vip-minibuffer-vi-face)
                               'non-x)
-         minibuffer-insert-face (if (vip-window-display-p)
+         minibuffer-insert-face (if (vip-has-face-support-p)
                                     (vip-get-face vip-minibuffer-insert-face)
                                   'non-x)
-         minibuffer-emacs-face (if (vip-window-display-p)
+         minibuffer-emacs-face (if (vip-has-face-support-p)
                                    (vip-get-face vip-minibuffer-emacs-face)
                                  'non-x)
          frame-parameters (if (fboundp 'frame-parameters)
@@ -5247,7 +5333,7 @@ Mail anyway (y or n)? ")
     (setq
      unread-command-events
      (append
-      (cond ((numberp arg) (list (character-to-event arg)))
+      (cond ((vip-characterp arg) (list (character-to-event arg)))
            ((eventp arg)  (list arg))
            ((stringp arg) (mapcar 'character-to-event arg))
            ((vectorp arg) (append arg nil)) ; turn into list
@@ -5260,7 +5346,7 @@ Mail anyway (y or n)? ")
 (defun vip-eventify-list-xemacs (lis)
   (mapcar
    (function (lambda (elt)
-              (cond ((numberp elt) (character-to-event elt))
+              (cond ((vip-characterp elt) (character-to-event elt))
                     ((eventp elt)  elt)
                     (t (error
                         "vip-eventify-list-xemacs: can't convert to event, %S"
@@ -5314,40 +5400,54 @@ Mail anyway (y or n)? ")
     "Run `vip-change-state-to-vi' on entry."
     (vip-change-state-to-vi))
 
-  (defvar help-mode-hook nil)
+  (defvar makefile-mode-hook)
+  (add-hook 'makefile-mode-hook 'viper-mode)
+
+  (defvar help-mode-hook)
   (add-hook 'help-mode-hook 'viper-mode)
+
+  (defvar awk-mode-hook)
+  (add-hook 'awk-mode-hook 'viper-mode)
   
-  (defvar emacs-lisp-mode-hook nil)
-  (add-hook 'emacs-lisp-mode-hook 'viper-mode)
-  
-  (defvar html-mode-hook nil)
+  (defvar html-mode-hook)
   (add-hook 'html-mode-hook 'viper-mode)
+  (defvar html-helper-mode-hook)
+  (add-hook 'html-helper-mode-hook 'viper-mode)
+  
+  (defvar emacs-lisp-mode-hook)
+  (add-hook 'emacs-lisp-mode-hook 'viper-mode)
 
-  (defvar lisp-mode-hook nil)
+  (defvar lisp-mode-hook)
   (add-hook 'lisp-mode-hook 'viper-mode)
   
-  (defvar bibtex-mode-hook nil)                        
+  (defvar bibtex-mode-hook)
   (add-hook 'bibtex-mode-hook 'viper-mode)       
       
-  (defvar cc-mode-hook nil)
+  (defvar cc-mode-hook)
   (add-hook 'cc-mode-hook 'viper-mode)
       
-  (defvar c-mode-hook nil)
+  (defvar c-mode-hook)
   (add-hook 'c-mode-hook 'viper-mode)
       
-  (defvar c++-mode-hook nil)
+  (defvar c++-mode-hook)
   (add-hook 'c++-mode-hook 'viper-mode)
   
-  (defvar lisp-interaction-mode-hook nil)
+  (defvar lisp-interaction-mode-hook)
   (add-hook 'lisp-interaction-mode-hook 'viper-mode)
+
+  (defvar fortran-mode-hook)
+  (add-hook 'fortran-mode-hook 'vip-mode)
       
-  (defvar text-mode-hook nil)
+  (defvar text-mode-hook)
   (add-hook 'text-mode-hook 'viper-mode)
       
   (add-hook 'completion-list-mode-hook 'viper-mode)  
   (add-hook 'compilation-mode-hook     'viper-mode)  
+
+  (add-hook 'perl-mode-hook     'viper-mode)  
+  (add-hook 'tcl-mode-hook     'viper-mode)  
   
-  (defvar emerge-startup-hook nil)
+  (defvar emerge-startup-hook)
   (add-hook 'emerge-startup-hook 'vip-change-state-to-emacs)
   ;; Run vip-change-state-to-vi after quitting emerge.
   (vip-eval-after-load
@@ -5373,15 +5473,23 @@ Mail anyway (y or n)? ")
    '(defadvice read-passwd-1 (before vip-passwd-ad activate)
       "Switch to emacs state while reading password."
       (vip-change-state-to-emacs)))
+
+  (vip-eval-after-load
+   "prolog"
+   '(defadvice prolog-mode (after vip-prolog-ad activate)
+      "Switch to Vi state in Prolog mode."
+      (vip-change-state-to-vi)))
   
   ;; Emacs shell, ange-ftp, and comint-based modes
-  (defvar comint-mode-hook nil)
+  (defvar comint-mode-hook)
   (add-hook 'comint-mode-hook 'vip-change-state-to-insert)
   (add-hook 'comint-mode-hook 'vip-comint-mode-hook)
   
   ;; Shell scripts
-  (defvar sh-mode-hook nil)
+  (defvar sh-mode-hook)
   (add-hook 'sh-mode-hook 'viper-mode)
+  (defvar ksh-mode-hook)
+  (add-hook 'ksh-mode-hook 'viper-mode)
   
   ;; Dired
   ;; This is only necessary when the user uses vip-modify-major-mode
@@ -5389,22 +5497,18 @@ Mail anyway (y or n)? ")
 
   (if vip-emacs-p
       (progn
-       (defvar view-mode-hook nil
-         "View hook. Run after view mode.")
+       (defvar view-mode-hook)
        (add-hook 'view-mode-hook 'vip-change-state-to-emacs))
     (defadvice view-minor-mode (after vip-view-ad activate)
       "Switch to Emacs state in View mode."
       (vip-change-state-to-emacs))
-    (defvar view-hook nil
-      "View hook. Run after view mode.")
+    (defvar view-hook)
     (add-hook 'view-hook 'vip-change-state-to-emacs))
   
   ;; For VM users.
   ;; Put summary and other VM buffers in Emacs state.
-  (defvar vm-mode-hooks nil 
-    "This hook is run after vm is started.")
-  (defvar vm-summary-mode-hooks nil 
-    "This hook is run after vm switches to summary mode.")
+  (defvar vm-mode-hooks)
+  (defvar vm-summary-mode-hooks)
   (add-hook 'vm-mode-hooks   'vip-change-state-to-emacs)
   (add-hook 'vm-summary-mode-hooks   'vip-change-state-to-emacs)
   
@@ -5487,6 +5591,7 @@ Mail anyway (y or n)? ")
 (vip-harness-minor-mode "cyrillic")
 (vip-harness-minor-mode "russian")
 (vip-harness-minor-mode "view-less")
+(vip-harness-minor-mode "view")
 
 
 ;; Intercept maps could go in viper-keym.el