(parse_charset_map): Remove an unused variable.
[bpt/emacs.git] / lisp / bookmark.el
index 511c237..53939f9 100644 (file)
@@ -1,6 +1,6 @@
-;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later.
+;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later
 
 
-;; Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 2001 Free Software Foundation
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Maintainer: Karl Fogel <kfogel@red-bean.com>
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Maintainer: Karl Fogel <kfogel@red-bean.com>
 
 ;; Enough with the credits already, get on to the good stuff:
 
 
 ;; Enough with the credits already, get on to the good stuff:
 
-;; FAVORITE CHINESE RESTAURANT: 
+;; FAVORITE CHINESE RESTAURANT:
 ;; Boy, that's a tough one.  Probably Hong Min, or maybe Emperor's
 ;; Choice (both in Chicago's Chinatown).  Well, both.  How about you?
 \f
 ;; Boy, that's a tough one.  Probably Hong Min, or maybe Emperor's
 ;; Choice (both in Chicago's Chinatown).  Well, both.  How about you?
 \f
-;;;; Code:
+;;; Code:
 
 (require 'pp)
 
 ;;; Misc comments:
 ;;
 ;; If variable bookmark-use-annotations is non-nil, an annotation is
 
 (require 'pp)
 
 ;;; Misc comments:
 ;;
 ;; If variable bookmark-use-annotations is non-nil, an annotation is
-;; queried for when setting a bookmark.  
+;; queried for when setting a bookmark.
 ;;
 ;; The bookmark list is sorted lexically by default, but you can turn
 ;; this off by setting bookmark-sort-flag to nil.  If it is nil, then
 ;;
 ;; The bookmark list is sorted lexically by default, but you can turn
 ;; this off by setting bookmark-sort-flag to nil.  If it is nil, then
@@ -121,7 +121,7 @@ behavior.\)
 
 To specify the file in which to save them, modify the variable
 `bookmark-default-file', which is `~/.emacs.bmk' by default."
 
 To specify the file in which to save them, modify the variable
 `bookmark-default-file', which is `~/.emacs.bmk' by default."
-  :type '(choice (const nil) (const t) integer)
+  :type '(choice (const nil) integer (other t))
   :group 'bookmark)
 
 
   :group 'bookmark)
 
 
@@ -149,7 +149,8 @@ It can have four values: t, nil, `never', and `nospecial'.
 The first three have the same meaning that they do for the
 variable `version-control', and the final value `nospecial' means just
 use the value of `version-control'."
 The first three have the same meaning that they do for the
 variable `version-control', and the final value `nospecial' means just
 use the value of `version-control'."
-  :type '(choice (const t) (const nil) (const never) (const nospecial))
+  :type '(choice (const nil) (const never) (const nospecial)
+                (other t))
   :group 'bookmark)
 
 
   :group 'bookmark)
 
 
@@ -168,7 +169,7 @@ recently set ones come first, oldest ones come last)."
 
 
 (defcustom bookmark-automatically-show-annotations t
 
 
 (defcustom bookmark-automatically-show-annotations t
-  "*Nil means don't show annotations when jumping to a bookmark."
+  "*nil means don't show annotations when jumping to a bookmark."
   :type 'boolean
   :group 'bookmark)
 
   :type 'boolean
   :group 'bookmark)
 
@@ -211,16 +212,9 @@ following in your `.emacs' file:
 
 ;; This variable is probably obsolete now...
 (or (boundp 'baud-rate)
 
 ;; This variable is probably obsolete now...
 (or (boundp 'baud-rate)
-    ;; some random value higher than 9600    
+    ;; some random value higher than 9600
     (setq baud-rate 19200))
 
     (setq baud-rate 19200))
 
-;; XEmacs apparently call this `buffer-substring-without-properties',
-;; sigh.
-(or (fboundp 'buffer-substring-no-properties)
-    (if (fboundp 'buffer-substring-without-properties)
-        (fset 'buffer-substring-no-properties
-              'buffer-substring-without-properties)
-      (fset 'buffer-substring-no-properties 'buffer-substring)))
 
 \f
 ;;; Keymap stuff:
 
 \f
 ;;; Keymap stuff:
@@ -306,19 +300,9 @@ So the cdr of each bookmark is an alist too.
 (defvar bookmarks-already-loaded nil)
 
 
 (defvar bookmarks-already-loaded nil)
 
 
-;; just add the hook to make sure that people don't lose bookmarks
-;; when they kill Emacs, unless they don't want to save them.
-;;;###autoload
-(add-hook 'kill-emacs-hook
-          (function
-           (lambda () (and (featurep 'bookmark)
-                           bookmark-alist
-                           (bookmark-time-to-save-p t)
-                           (bookmark-save)))))
-
 ;; more stuff added by db.
 
 ;; more stuff added by db.
 
-(defvar bookmark-current-bookmark nil 
+(defvar bookmark-current-bookmark nil
   "Name of bookmark most recently used in the current file.
 It is buffer local, used to make moving a bookmark forward
 through a file easier.")
   "Name of bookmark most recently used in the current file.
 It is buffer local, used to make moving a bookmark forward
 through a file easier.")
@@ -361,8 +345,13 @@ through a file easier.")
 
 
 (defun bookmark-get-bookmark (bookmark)
 
 
 (defun bookmark-get-bookmark (bookmark)
-  "Return the full entry for BOOKMARK in bookmark-alist."
-  (assoc bookmark bookmark-alist))
+  "Return the full entry for BOOKMARK in bookmark-alist.
+If BOOKMARK is not a string, return nil."
+  (when (stringp bookmark)
+    (apply (if bookmark-completion-ignore-case
+              #'assoc-ignore-case
+            #'assoc)
+          (list bookmark bookmark-alist))))
 
 
 (defun bookmark-get-bookmark-record (bookmark)
 
 
 (defun bookmark-get-bookmark-record (bookmark)
@@ -453,7 +442,7 @@ That is, all information but the name."
 (defun bookmark-get-info-node (bookmark)
   "Get the info node associated with BOOKMARK."
   (cdr (assq 'info-node (bookmark-get-bookmark-record bookmark))))
 (defun bookmark-get-info-node (bookmark)
   "Get the info node associated with BOOKMARK."
   (cdr (assq 'info-node (bookmark-get-bookmark-record bookmark))))
-  
+
 
 (defun bookmark-set-info-node (bookmark node)
   "Set the Info node of BOOKMARK to NODE."
 
 (defun bookmark-set-info-node (bookmark node)
   "Set the Info node of BOOKMARK to NODE."
@@ -467,7 +456,7 @@ That is, all information but the name."
   (message "%S" (assq 'info-node (bookmark-get-bookmark-record bookmark)))
   (sit-for 4)
   )
   (message "%S" (assq 'info-node (bookmark-get-bookmark-record bookmark)))
   (sit-for 4)
   )
-  
+
 
 (defvar bookmark-history nil
   "The history list for bookmark functions.")
 
 (defvar bookmark-history nil
   "The history list for bookmark functions.")
@@ -501,9 +490,9 @@ the empty string."
   "Put STRING into the bookmark prompt history, if caller non-interactive.
 We need this because sometimes bookmark functions are invoked from
 menus, so `completing-read' never gets a chance to set `bookmark-history'."
   "Put STRING into the bookmark prompt history, if caller non-interactive.
 We need this because sometimes bookmark functions are invoked from
 menus, so `completing-read' never gets a chance to set `bookmark-history'."
-  (` (or
-      (interactive-p)
-      (setq bookmark-history (cons (, string) bookmark-history)))))
+  `(or
+    (interactive-p)
+    (setq bookmark-history (cons ,string bookmark-history))))
 
 
 (defun bookmark-make (name &optional annotation overwrite info-node)
 
 
 (defun bookmark-make (name &optional annotation overwrite info-node)
@@ -524,17 +513,17 @@ INFO-NODE, so record this fact in the bookmark's entry."
         ;; no prefix arg means just overwrite old bookmark
         (setcdr (bookmark-get-bookmark stripped-name)
                 (list (bookmark-make-cell annotation info-node)))
         ;; no prefix arg means just overwrite old bookmark
         (setcdr (bookmark-get-bookmark stripped-name)
                 (list (bookmark-make-cell annotation info-node)))
-      
+
       ;; otherwise just cons it onto the front (either the bookmark
       ;; doesn't exist already, or there is no prefix arg.  In either
       ;; case, we want the new bookmark consed onto the alist...)
       ;; otherwise just cons it onto the front (either the bookmark
       ;; doesn't exist already, or there is no prefix arg.  In either
       ;; case, we want the new bookmark consed onto the alist...)
-      
+
       (setq bookmark-alist
             (cons
       (setq bookmark-alist
             (cons
-             (list stripped-name 
+             (list stripped-name
                    (bookmark-make-cell annotation info-node))
              bookmark-alist)))
                    (bookmark-make-cell annotation info-node))
              bookmark-alist)))
-    
+
     ;; Added by db
     (setq bookmark-current-bookmark stripped-name)
     (setq bookmark-alist-modification-count
     ;; Added by db
     (setq bookmark-current-bookmark stripped-name)
     (setq bookmark-alist-modification-count
@@ -550,21 +539,20 @@ being set.  This might change someday.
 Optional second arg INFO-NODE means this bookmark is at info node
 INFO-NODE, so record this fact in the bookmark's entry."
   (let ((the-record
 Optional second arg INFO-NODE means this bookmark is at info node
 INFO-NODE, so record this fact in the bookmark's entry."
   (let ((the-record
-         (` ((filename . (, (bookmark-buffer-file-name)))
-             (front-context-string
-              . (, (if (>= (- (point-max) (point)) bookmark-search-size)
-                       (buffer-substring-no-properties
-                        (point)
-                        (+ (point) bookmark-search-size))
-                     nil)))
-             (rear-context-string
-              . (, (if (>= (- (point) (point-min)) bookmark-search-size)
-                       (buffer-substring-no-properties
-                        (point)
-                        (- (point) bookmark-search-size))
-                     nil)))
-             (position . (, (point)))
-             ))))
+         `((filename . ,(bookmark-buffer-file-name))
+           (front-context-string
+            . ,(if (>= (- (point-max) (point)) bookmark-search-size)
+                   (buffer-substring-no-properties
+                    (point)
+                    (+ (point) bookmark-search-size))
+                   nil))
+           (rear-context-string
+            . ,(if (>= (- (point) (point-min)) bookmark-search-size)
+                   (buffer-substring-no-properties
+                    (point)
+                    (- (point) bookmark-search-size))
+                   nil))
+           (position . ,(point)))))
 
     ;; Now fill in the optional parts:
 
 
     ;; Now fill in the optional parts:
 
@@ -579,8 +567,8 @@ INFO-NODE, so record this fact in the bookmark's entry."
 
     ;; Finally, return the completed record.
     the-record))
 
     ;; Finally, return the completed record.
     the-record))
-    
-  
+
+
 \f
 ;;; File format stuff
 
 \f
 ;;; File format stuff
 
@@ -612,17 +600,17 @@ INFO-NODE, so record this fact in the bookmark's entry."
 ;; risk of interfering with existing ones.
 ;;
 ;; BOOKMARK-NAME is the string the user gives the bookmark and
 ;; risk of interfering with existing ones.
 ;;
 ;; BOOKMARK-NAME is the string the user gives the bookmark and
-;; accesses it by from then on.  
+;; accesses it by from then on.
 ;;
 ;; FILENAME is the location of the file in which the bookmark is set.
 ;;
 ;; STRING-IN-FRONT is a string of `bookmark-search-size' chars of
 ;; context in front of the point at which the bookmark is set.
 ;;
 ;;
 ;; FILENAME is the location of the file in which the bookmark is set.
 ;;
 ;; STRING-IN-FRONT is a string of `bookmark-search-size' chars of
 ;; context in front of the point at which the bookmark is set.
 ;;
-;; STRING-BEHIND is the same thing, but after the point.  
+;; STRING-BEHIND is the same thing, but after the point.
 ;;
 ;; The context strings exist so that modifications to a file don't
 ;;
 ;; The context strings exist so that modifications to a file don't
-;; necessarily cause a bookmark's position to be invalidated. 
+;; necessarily cause a bookmark's position to be invalidated.
 ;; bookmark-jump will search for STRING-BEHIND and STRING-IN-FRONT in
 ;; case the file has changed since the bookmark was set.  It will
 ;; attempt to place the user before the changes, if there were any.
 ;; bookmark-jump will search for STRING-BEHIND and STRING-IN-FRONT in
 ;; case the file has changed since the bookmark was set.  It will
 ;; attempt to place the user before the changes, if there were any.
@@ -672,11 +660,11 @@ affect point."
             (ann       (nth 4 record)))
        (list
         name
             (ann       (nth 4 record)))
        (list
         name
-        (` ((filename             .    (, filename))
-            (front-context-string .    (, (or front-str "")))
-            (rear-context-string  .    (, (or rear-str  "")))
-            (position             .    (, position))
-            (annotation           .    (, ann)))))))
+        `((filename             .    ,filename)
+          (front-context-string .    ,(or front-str ""))
+          (rear-context-string  .    ,(or rear-str  ""))
+          (position             .    ,position)
+          (annotation           .    ,ann)))))
    old-list))
 
 
    old-list))
 
 
@@ -788,7 +776,7 @@ the list of bookmarks.\)"
                  now-map))))
         (annotation nil))
     (and (string-equal str "") (setq str default))
                  now-map))))
         (annotation nil))
     (and (string-equal str "") (setq str default))
-    ;; Ask for an annotation buffer for this bookmark 
+    ;; Ask for an annotation buffer for this bookmark
     (if bookmark-use-annotations
        (bookmark-read-annotation parg str)
       (bookmark-make str annotation parg (bookmark-info-current-node))
     (if bookmark-use-annotations
        (bookmark-read-annotation parg str)
       (bookmark-make str annotation parg (bookmark-info-current-node))
@@ -844,7 +832,7 @@ the bookmark (and file, and point) specified in buffer local variables."
     ;; Actually, bookmark-make-cell should probably be re-written,
     ;; to avoid this need.  Should I handle the error if a buffer is
     ;; killed between "C-x r m" and a "C-c C-c" in the annotation buffer?
     ;; Actually, bookmark-make-cell should probably be re-written,
     ;; to avoid this need.  Should I handle the error if a buffer is
     ;; killed between "C-x r m" and a "C-c C-c" in the annotation buffer?
-    (save-excursion 
+    (save-excursion
       (pop-to-buffer buf)
       (goto-char pt)
       (bookmark-make bookmark annotation parg (bookmark-info-current-node))
       (pop-to-buffer buf)
       (goto-char pt)
       (bookmark-make bookmark annotation parg (bookmark-info-current-node))
@@ -1042,7 +1030,7 @@ For example, if this is a Info buffer, return the Info file's name."
                          (expand-file-name bookmark-default-file)))
            ;; return t so the `and' will continue...
            t)
                          (expand-file-name bookmark-default-file)))
            ;; return t so the `and' will continue...
            t)
-       
+
        (file-readable-p (expand-file-name bookmark-default-file))
        (bookmark-load bookmark-default-file t t)
        (setq bookmarks-already-loaded t)))
        (file-readable-p (expand-file-name bookmark-default-file))
        (bookmark-load bookmark-default-file t t)
        (setq bookmarks-already-loaded t)))
@@ -1060,7 +1048,7 @@ For example, if this is a Info buffer, return the Info file's name."
 
 ;;;###autoload
 (defun bookmark-jump (bookmark)
 
 ;;;###autoload
 (defun bookmark-jump (bookmark)
-  "Jump to bookmark BOOKMARK (a point in some file).  
+  "Jump to bookmark BOOKMARK (a point in some file).
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
@@ -1083,6 +1071,22 @@ of the old one in the permanent bookmark record."
              (bookmark-show-annotation bookmark)))))
 
 
              (bookmark-show-annotation bookmark)))))
 
 
+(defun bookmark-file-or-variation-thereof (file)
+  "Return FILE (a string) if it exists in any reasonable variation, else nil.
+Reasonable variations are FILE.gz, FILE.Z, FILE.info, FILE.info.gz, etc."
+  (cond
+   ((file-exists-p file)                       file)
+   ((file-exists-p (concat file ".Z"))         (concat file ".Z"))
+   ((file-exists-p (concat file ".gz"))        (concat file ".gz"))
+   ((file-exists-p (concat file ".z"))         (concat file ".z"))
+   ((file-exists-p (concat file ".info"))      (concat file ".info"))
+   ((file-exists-p (concat file ".info.gz"))   (concat file ".info.gz"))
+   ((file-exists-p (concat file ".info.Z"))    (concat file ".info.Z"))
+   ((file-exists-p (concat file ".info.z"))    (concat file ".info.z"))
+   ((vc-backend file)                          file) ; maybe VC has it?
+   (t                                          nil)))
+
+
 (defun bookmark-jump-noselect (str)
   ;; a leetle helper for bookmark-jump :-)
   ;; returns (BUFFER . POINT)
 (defun bookmark-jump-noselect (str)
   ;; a leetle helper for bookmark-jump :-)
   ;; returns (BUFFER . POINT)
@@ -1094,47 +1098,33 @@ of the old one in the permanent bookmark record."
          (info-node              (bookmark-get-info-node str))
          (orig-file              file)
          )
          (info-node              (bookmark-get-info-node str))
          (orig-file              file)
          )
-    (if (or
-         (file-exists-p file)
-         ;; else try some common compression extensions
-         ;; and Emacs better handle it right!
-         ;; Sigh: I think it may *not* be handled at the moment.  What
-         ;; to do about this?
-         (setq file
-               (or
-                (let ((altname (concat file ".Z")))
-                  (and (file-exists-p altname)
-                       altname))
-                (let ((altname (concat file ".gz")))
-                  (and (file-exists-p altname)
-                       altname))
-                (let ((altname (concat file ".z")))
-                  (and (file-exists-p altname)
-                       altname)))))
+    (if (setq file (bookmark-file-or-variation-thereof file))
         (save-excursion
         (save-excursion
-          (if info-node
-              ;; Info nodes must be visited with care.
-              (progn
-                (require 'info)
-                (Info-find-node file info-node))
-            ;; Else no Info.  Can do an ordinary find-file:
-            (set-buffer (find-file-noselect file))
-            (goto-char place))
-
-          ;; Go searching forward first.  Then, if forward-str exists and
-          ;; was found in the file, we can search backward for behind-str.
-          ;; Rationale is that if text was inserted between the two in the
-          ;; file, it's better to be put before it so you can read it,
-          ;; rather than after and remain perhaps unaware of the changes.
-          (if forward-str
-              (if (search-forward forward-str (point-max) t)
-                  (goto-char (match-beginning 0))))
-          (if behind-str
-              (if (search-backward behind-str (point-min) t)
-                  (goto-char (match-end 0))))
-          ;; added by db
-          (setq bookmark-current-bookmark str)
-          (cons (current-buffer) (point)))
+          (save-window-excursion
+            (if info-node
+                ;; Info nodes must be visited with care.
+                (progn
+                  (require 'info)
+                  (Info-find-node file info-node))
+              ;; Else no Info.  Can do an ordinary find-file:
+              (set-buffer (find-file-noselect file))
+              (goto-char place))
+
+            ;; Go searching forward first.  Then, if forward-str exists and
+            ;; was found in the file, we can search backward for behind-str.
+            ;; Rationale is that if text was inserted between the two in the
+            ;; file, it's better to be put before it so you can read it,
+            ;; rather than after and remain perhaps unaware of the changes.
+            (if forward-str
+                (if (search-forward forward-str (point-max) t)
+                    (goto-char (match-beginning 0))))
+            (if behind-str
+                (if (search-backward behind-str (point-min) t)
+                    (goto-char (match-end 0))))
+            ;; added by db
+            (setq bookmark-current-bookmark str)
+            (cons (current-buffer) (point))))
+
       ;; Else unable to find the marked file, so ask if user wants to
       ;; relocate the bookmark, else remind them to consider deletion.
       (ding)
       ;; Else unable to find the marked file, so ask if user wants to
       ;; relocate the bookmark, else remind them to consider deletion.
       (ding)
@@ -1146,7 +1136,7 @@ of the old one in the permanent bookmark record."
             (bookmark-relocate str)
             ;; gasp!  It's a recursive function call in Emacs Lisp!
             (bookmark-jump-noselect str))
             (bookmark-relocate str)
             ;; gasp!  It's a recursive function call in Emacs Lisp!
             (bookmark-jump-noselect str))
-        (message 
+        (message
          "Bookmark not relocated; consider removing it \(%s\)." str)
         nil))))
 
          "Bookmark not relocated; consider removing it \(%s\)." str)
         nil))))
 
@@ -1179,12 +1169,13 @@ minibuffer history list `bookmark-history'."
   (let ((start (point)))
     (prog1
        (insert (bookmark-location bookmark)) ; *Return this line*
   (let ((start (point)))
     (prog1
        (insert (bookmark-location bookmark)) ; *Return this line*
-      (if window-system
-         (put-text-property start 
-                            (save-excursion (re-search-backward
-                                             "[^ \t]")
-                                            (1+ (point)))
-                            'mouse-face 'highlight)))))
+      (if (and (display-color-p) (display-mouse-p))
+         (add-text-properties start
+                              (save-excursion (re-search-backward
+                                               "[^ \t]")
+                                              (1+ (point)))
+                              '(mouse-face highlight
+                                help-echo "mouse-2: go to this bookmark"))))))
 
 ;;;###autoload
 (defalias 'bookmark-locate 'bookmark-insert-location)
 
 ;;;###autoload
 (defalias 'bookmark-locate 'bookmark-insert-location)
@@ -1236,7 +1227,7 @@ name."
 
 ;;;###autoload
 (defun bookmark-insert (bookmark)
 
 ;;;###autoload
 (defun bookmark-insert (bookmark)
-  "Insert the text of the file pointed to by bookmark BOOKMARK.  
+  "Insert the text of the file pointed to by bookmark BOOKMARK.
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
@@ -1256,7 +1247,7 @@ this."
 
 ;;;###autoload
 (defun bookmark-delete (bookmark &optional batch)
 
 ;;;###autoload
 (defun bookmark-delete (bookmark &optional batch)
-  "Delete BOOKMARK from the bookmark list.  
+  "Delete BOOKMARK from the bookmark list.
 Removes only the first instance of a bookmark with that name.  If
 there are one or more other bookmarks with the same name, they will
 not be deleted.  Defaults to the \"current\" bookmark \(that is, the
 Removes only the first instance of a bookmark with that name.  If
 there are one or more other bookmarks with the same name, they will
 not be deleted.  Defaults to the \"current\" bookmark \(that is, the
@@ -1290,7 +1281,7 @@ probably because we were called from there."
   ;; bookmark-alist-modification-count.  Returns t if they should be
   ;; saved, nil otherwise.  if last-time is non-nil, then this is
   ;; being called when emacs is killed.
   ;; bookmark-alist-modification-count.  Returns t if they should be
   ;; saved, nil otherwise.  if last-time is non-nil, then this is
   ;; being called when emacs is killed.
-  (cond (last-time 
+  (cond (last-time
         (and (> bookmark-alist-modification-count 0)
              bookmark-save-flag))
        ((numberp bookmark-save-flag)
         (and (> bookmark-alist-modification-count 0)
              bookmark-save-flag))
        ((numberp bookmark-save-flag)
@@ -1309,7 +1300,7 @@ Don't use this in Lisp programs; use `bookmark-save' instead."
 
 
 ;;;###autoload
 
 
 ;;;###autoload
-(defun bookmark-save (&optional parg file) 
+(defun bookmark-save (&optional parg file)
   "Save currently defined bookmarks.
 Saves by default in the file defined by the variable
 `bookmark-default-file'.  With a prefix arg, save it in file FILE
   "Save currently defined bookmarks.
 Saves by default in the file defined by the variable
 `bookmark-default-file'.  With a prefix arg, save it in file FILE
@@ -1355,21 +1346,22 @@ for a file, defaulting to the file defined by variable
       (set-buffer (let ((enable-local-variables nil))
                     (find-file-noselect file)))
       (goto-char (point-min))
       (set-buffer (let ((enable-local-variables nil))
                     (find-file-noselect file)))
       (goto-char (point-min))
-      (delete-region (point-min) (point-max))
-      (bookmark-insert-file-format-version-stamp)
-      (pp bookmark-alist (current-buffer))
-      (let ((version-control
-             (cond
-              ((null bookmark-version-control) nil)
-              ((eq 'never bookmark-version-control) 'never)
-              ((eq 'nospecial bookmark-version-control) version-control)
-              (t
-               t))))
-        (write-file file)
-        (kill-buffer (current-buffer))
-        (if (>= baud-rate 9600)
-            (message "Saving bookmarks to file %s...done" file))
-        ))))
+      (let ((print-length nil)
+           (print-level nil))
+       (delete-region (point-min) (point-max))
+       (bookmark-insert-file-format-version-stamp)
+       (pp bookmark-alist (current-buffer))
+       (let ((version-control
+              (cond
+               ((null bookmark-version-control) nil)
+               ((eq 'never bookmark-version-control) 'never)
+               ((eq 'nospecial bookmark-version-control) version-control)
+               (t
+                t))))
+         (write-file file)
+         (kill-buffer (current-buffer))
+         (if (>= baud-rate 9600)
+             (message "Saving bookmarks to file %s...done" file)))))))
 
 
 (defun bookmark-import-new-list (new-list)
 
 
 (defun bookmark-import-new-list (new-list)
@@ -1426,7 +1418,7 @@ method buffers use to resolve name collisions."
   (interactive
    (list (read-file-name
           (format "Load bookmarks from: (%s) "
   (interactive
    (list (read-file-name
           (format "Load bookmarks from: (%s) "
-                  bookmark-default-file)        
+                  bookmark-default-file)
           ;;Default might not be used often,
           ;;but there's no better default, and
           ;;I guess it's better than none at all.
           ;;Default might not be used often,
           ;;but there's no better default, and
           ;;I guess it's better than none at all.
@@ -1456,7 +1448,7 @@ method buffers use to resolve name collisions."
                        (expand-file-name bookmark-default-file)
                        file)
                       (setq bookmarks-already-loaded t))
                        (expand-file-name bookmark-default-file)
                        file)
                       (setq bookmarks-already-loaded t))
-                  (bookmark-bmenu-surreptitiously-rebuild-list)) 
+                  (bookmark-bmenu-surreptitiously-rebuild-list))
               (error "Invalid bookmark list in %s" file)))
           (kill-buffer (current-buffer)))
        (if (and (null no-msg) (>= baud-rate 9600))
               (error "Invalid bookmark list in %s" file)))
           (kill-buffer (current-buffer)))
        (if (and (null no-msg) (>= baud-rate 9600))
@@ -1482,7 +1474,7 @@ method buffers use to resolve name collisions."
     nil
   (setq bookmark-bmenu-mode-map (make-keymap))
   (suppress-keymap bookmark-bmenu-mode-map t)
     nil
   (setq bookmark-bmenu-mode-map (make-keymap))
   (suppress-keymap bookmark-bmenu-mode-map t)
-  (define-key bookmark-bmenu-mode-map "q" 'bookmark-bmenu-quit)
+  (define-key bookmark-bmenu-mode-map "q" 'quit-window)
   (define-key bookmark-bmenu-mode-map "v" 'bookmark-bmenu-select)
   (define-key bookmark-bmenu-mode-map "w" 'bookmark-bmenu-locate)
   (define-key bookmark-bmenu-mode-map "2" 'bookmark-bmenu-2-window)
   (define-key bookmark-bmenu-mode-map "v" 'bookmark-bmenu-select)
   (define-key bookmark-bmenu-mode-map "w" 'bookmark-bmenu-locate)
   (define-key bookmark-bmenu-mode-map "2" 'bookmark-bmenu-2-window)
@@ -1490,6 +1482,7 @@ method buffers use to resolve name collisions."
   (define-key bookmark-bmenu-mode-map "j" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "\C-c\C-c" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "f" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "j" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "\C-c\C-c" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "f" 'bookmark-bmenu-this-window)
+  (define-key bookmark-bmenu-mode-map "\C-m" 'bookmark-bmenu-this-window)
   (define-key bookmark-bmenu-mode-map "o" 'bookmark-bmenu-other-window)
   (define-key bookmark-bmenu-mode-map "\C-o"
     'bookmark-bmenu-switch-other-window)
   (define-key bookmark-bmenu-mode-map "o" 'bookmark-bmenu-other-window)
   (define-key bookmark-bmenu-mode-map "\C-o"
     'bookmark-bmenu-switch-other-window)
@@ -1505,7 +1498,7 @@ method buffers use to resolve name collisions."
   (define-key bookmark-bmenu-mode-map "?" 'describe-mode)
   (define-key bookmark-bmenu-mode-map "u" 'bookmark-bmenu-unmark)
   (define-key bookmark-bmenu-mode-map "m" 'bookmark-bmenu-mark)
   (define-key bookmark-bmenu-mode-map "?" 'describe-mode)
   (define-key bookmark-bmenu-mode-map "u" 'bookmark-bmenu-unmark)
   (define-key bookmark-bmenu-mode-map "m" 'bookmark-bmenu-mark)
-  (define-key bookmark-bmenu-mode-map "l" 'bookmark-bmenu-load) 
+  (define-key bookmark-bmenu-mode-map "l" 'bookmark-bmenu-load)
   (define-key bookmark-bmenu-mode-map "r" 'bookmark-bmenu-rename)
   (define-key bookmark-bmenu-mode-map "t" 'bookmark-bmenu-toggle-filenames)
   (define-key bookmark-bmenu-mode-map "a" 'bookmark-bmenu-show-annotation)
   (define-key bookmark-bmenu-mode-map "r" 'bookmark-bmenu-rename)
   (define-key bookmark-bmenu-mode-map "t" 'bookmark-bmenu-toggle-filenames)
   (define-key bookmark-bmenu-mode-map "a" 'bookmark-bmenu-show-annotation)
@@ -1514,7 +1507,7 @@ method buffers use to resolve name collisions."
   (define-key bookmark-bmenu-mode-map [mouse-2]
     'bookmark-bmenu-other-window-with-mouse))
 
   (define-key bookmark-bmenu-mode-map [mouse-2]
     'bookmark-bmenu-other-window-with-mouse))
 
-  
+
 
 ;; Bookmark Buffer Menu mode is suitable only for specially formatted
 ;; data.
 
 ;; Bookmark Buffer Menu mode is suitable only for specially formatted
 ;; data.
@@ -1522,7 +1515,7 @@ method buffers use to resolve name collisions."
 
 
 ;; todo: need to display whether or not bookmark exists as a buffer in
 
 
 ;; todo: need to display whether or not bookmark exists as a buffer in
-;; flag column. 
+;; flag column.
 
 ;; Format:
 ;; FLAGS  BOOKMARK [ LOCATION ]
 
 ;; Format:
 ;; FLAGS  BOOKMARK [ LOCATION ]
@@ -1533,7 +1526,7 @@ method buffers use to resolve name collisions."
 Don't affect the buffer ring order."
   (if (get-buffer "*Bookmark List*")
       (save-excursion
 Don't affect the buffer ring order."
   (if (get-buffer "*Bookmark List*")
       (save-excursion
-        (save-window-excursion 
+        (save-window-excursion
           (bookmark-bmenu-list)))))
 
 
           (bookmark-bmenu-list)))))
 
 
@@ -1564,12 +1557,13 @@ deletion, or > if it is flagged for displaying."
            (insert "  "))
         (let ((start (point)))
           (insert (bookmark-name-from-full-record full-record))
            (insert "  "))
         (let ((start (point)))
           (insert (bookmark-name-from-full-record full-record))
-          (if window-system
-              (put-text-property start 
-                                 (save-excursion (re-search-backward
-                                                  "[^ \t]")
-                                                 (1+ (point)))
-                                 'mouse-face 'highlight))
+          (if (and (display-color-p) (display-mouse-p))
+              (add-text-properties start
+                                   (save-excursion (re-search-backward
+                                                    "[^ \t]")
+                                                   (1+ (point)))
+                                   '(mouse-face highlight
+                                     help-echo "mouse-2: go to this bookmark")))
           (insert "\n")
           )))
      bookmark-alist))
           (insert "\n")
           )))
      bookmark-alist))
@@ -1604,9 +1598,9 @@ Bookmark names preceded by a \"*\" have annotations.
 \\[bookmark-bmenu-other-window] -- select this bookmark in another window,
   so the bookmark menu bookmark remains visible in its window.
 \\[bookmark-bmenu-switch-other-window] -- switch the other window to this bookmark.
 \\[bookmark-bmenu-other-window] -- select this bookmark in another window,
   so the bookmark menu bookmark remains visible in its window.
 \\[bookmark-bmenu-switch-other-window] -- switch the other window to this bookmark.
-\\[bookmark-bmenu-rename] -- rename this bookmark \(prompts for new name\).   
+\\[bookmark-bmenu-rename] -- rename this bookmark \(prompts for new name\).
 \\[bookmark-bmenu-delete] -- mark this bookmark to be deleted, and move down.
 \\[bookmark-bmenu-delete] -- mark this bookmark to be deleted, and move down.
-\\[bookmark-bmenu-delete-backwards] -- mark this bookmark to be deleted, and move up. 
+\\[bookmark-bmenu-delete-backwards] -- mark this bookmark to be deleted, and move up.
 \\[bookmark-bmenu-execute-deletions] -- delete bookmarks marked with `\\[bookmark-bmenu-delete]'.
 \\[bookmark-bmenu-save] -- save the current bookmark list in the default file.
   With a prefix arg, prompts for a file to save in.
 \\[bookmark-bmenu-execute-deletions] -- delete bookmarks marked with `\\[bookmark-bmenu-delete]'.
 \\[bookmark-bmenu-save] -- save the current bookmark list in the default file.
   With a prefix arg, prompts for a file to save in.
@@ -1660,9 +1654,9 @@ Optional argument SHOW means show them unconditionally."
              (let ((start (save-excursion (end-of-line) (point))))
                (move-to-column bookmark-bmenu-file-column t)
                ;; Strip off `mouse-face' from the white spaces region.
              (let ((start (save-excursion (end-of-line) (point))))
                (move-to-column bookmark-bmenu-file-column t)
                ;; Strip off `mouse-face' from the white spaces region.
-               (if window-system
+               (if (and (display-color-p) (display-mouse-p))
                    (remove-text-properties start (point)
                    (remove-text-properties start (point)
-                                           '(mouse-face))))
+                                           '(mouse-face nil help-echo nil))))
              (delete-region (point) (progn (end-of-line) (point)))
               (insert "  ")
               ;; Pass the NO-HISTORY arg:
              (delete-region (point) (progn (end-of-line) (point)))
               (insert "  ")
               ;; Pass the NO-HISTORY arg:
@@ -1691,12 +1685,14 @@ Optional argument SHOW means show them unconditionally."
                 (bookmark-kill-line)
                (let ((start (point)))
                  (insert (car bookmark-bmenu-hidden-bookmarks))
                 (bookmark-kill-line)
                (let ((start (point)))
                  (insert (car bookmark-bmenu-hidden-bookmarks))
-                 (if window-system
-                     (put-text-property start 
-                                        (save-excursion (re-search-backward
-                                                         "[^ \t]")
-                                                        (1+ (point)))
-                                        'mouse-face 'highlight)))
+                 (if (and (display-color-p) (display-mouse-p))
+                     (add-text-properties start
+                                          (save-excursion (re-search-backward
+                                                           "[^ \t]")
+                                                          (1+ (point)))
+                                          '(mouse-face highlight
+                                            help-echo
+                                            "mouse-2: go to this bookmark"))))
                 (setq bookmark-bmenu-hidden-bookmarks
                       (cdr bookmark-bmenu-hidden-bookmarks))
                 (forward-line 1))))))))
                 (setq bookmark-bmenu-hidden-bookmarks
                       (cdr bookmark-bmenu-hidden-bookmarks))
                 (forward-line 1))))))))
@@ -1733,8 +1729,8 @@ Optional argument SHOW means show them unconditionally."
       (beginning-of-line)
       (forward-char bookmark-bmenu-bookmark-column)
       (prog1
       (beginning-of-line)
       (forward-char bookmark-bmenu-bookmark-column)
       (prog1
-          (buffer-substring-no-properties (point) 
-                            (progn 
+          (buffer-substring-no-properties (point)
+                            (progn
                               (end-of-line)
                               (point)))
         ;; well, this is certainly crystal-clear:
                               (end-of-line)
                               (point)))
         ;; well, this is certainly crystal-clear:
@@ -1799,7 +1795,7 @@ You can mark bookmarks with the \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mar
   (interactive)
   (if (bookmark-bmenu-check-position)
       (let ((bmrk (bookmark-bmenu-bookmark))
   (interactive)
   (if (bookmark-bmenu-check-position)
       (let ((bmrk (bookmark-bmenu-bookmark))
-            (menu (current-buffer))          
+            (menu (current-buffer))
             (others ())
             tem)
         (goto-char (point-min))
             (others ())
             tem)
         (goto-char (point-min))
@@ -1808,8 +1804,8 @@ You can mark bookmarks with the \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mar
           (let ((buffer-read-only nil))
             (delete-char -1)
             (insert ?\ ))
           (let ((buffer-read-only nil))
             (delete-char -1)
             (insert ?\ ))
-          (or (string-equal tem bmrk) 
-              (member tem others) 
+          (or (string-equal tem bmrk)
+              (member tem others)
               (setq others (cons tem others))))
         (setq others (nreverse others)
               tem (/ (1- (frame-height)) (1+ (length others))))
               (setq others (cons tem others))))
         (setq others (nreverse others)
               tem (/ (1- (frame-height)) (1+ (length others))))
@@ -1896,7 +1892,10 @@ With a prefix arg, prompts for a file to save them in."
   "Make the other window select this line's bookmark.
 The current window remains selected."
   (interactive)
   "Make the other window select this line's bookmark.
 The current window remains selected."
   (interactive)
-  (let ((bookmark (bookmark-bmenu-bookmark)))
+  (let ((bookmark (bookmark-bmenu-bookmark))
+        (pop-up-windows t)
+        same-window-buffer-names
+        same-window-regexps)
     (if (bookmark-bmenu-check-position)
        (let* ((pair (bookmark-jump-noselect bookmark))
                (buff (car pair))
     (if (bookmark-bmenu-check-position)
        (let* ((pair (bookmark-jump-noselect bookmark))
                (buff (car pair))
@@ -1942,14 +1941,6 @@ The current window remains selected."
        (bookmark-edit-annotation bookmark))))
 
 
        (bookmark-edit-annotation bookmark))))
 
 
-(defun bookmark-bmenu-quit ()
-  "Quit the bookmark menu."
-  (interactive)
-  (let ((buffer (current-buffer)))
-    (switch-to-buffer (other-buffer))
-    (bury-buffer buffer)))
-
-
 (defun bookmark-bmenu-unmark (&optional backup)
   "Cancel all requested operations on bookmark on this line and move down.
 Optional BACKUP means move up."
 (defun bookmark-bmenu-unmark (&optional backup)
   "Cancel all requested operations on bookmark on this line and move down.
 Optional BACKUP means move up."
@@ -2128,7 +2119,7 @@ The number of panes depends on the number of bookmarks."
 
 ;;;###autoload
 (defun bookmark-menu-insert (event)
 
 ;;;###autoload
 (defun bookmark-menu-insert (event)
-  "Insert the text of the file pointed to by bookmark BOOKMARK.  
+  "Insert the text of the file pointed to by bookmark BOOKMARK.
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
@@ -2144,7 +2135,7 @@ corresponding bookmark function from Lisp \(the one without the
 
 ;;;###autoload
 (defun bookmark-menu-jump (event)
 
 ;;;###autoload
 (defun bookmark-menu-jump (event)
-  "Jump to bookmark BOOKMARK (a point in some file).  
+  "Jump to bookmark BOOKMARK (a point in some file).
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
 You may have a problem using this function if the value of variable
 `bookmark-alist' is nil.  If that happens, you need to load in some
 bookmarks.  See help on function `bookmark-load' for more about
@@ -2160,7 +2151,7 @@ corresponding bookmark function from Lisp \(the one without the
 
 ;;;###autoload
 (defun bookmark-menu-locate (event)
 
 ;;;###autoload
 (defun bookmark-menu-locate (event)
-  "Insert the name of the file associated with BOOKMARK. 
+  "Insert the name of the file associated with BOOKMARK.
 \(This is not the same as the contents of that file\).
 
 Warning: this function only takes an EVENT as argument.  Use the
 \(This is not the same as the contents of that file\).
 
 Warning: this function only takes an EVENT as argument.  Use the
@@ -2173,10 +2164,10 @@ corresponding bookmark function from Lisp \(the one without the
 
 ;;;###autoload
 (defun bookmark-menu-rename (event)
 
 ;;;###autoload
 (defun bookmark-menu-rename (event)
-  "Change the name of OLD-BOOKMARK to NEWNAME.  
+  "Change the name of OLD-BOOKMARK to NEWNAME.
 If called from keyboard, prompts for OLD-BOOKMARK and NEWNAME.
 If called from menubar, OLD-BOOKMARK is selected from a menu, and
 If called from keyboard, prompts for OLD-BOOKMARK and NEWNAME.
 If called from menubar, OLD-BOOKMARK is selected from a menu, and
-prompts for NEWNAME. 
+prompts for NEWNAME.
 If called from Lisp, prompts for NEWNAME if only OLD-BOOKMARK was
 passed as an argument.  If called with two strings, then no prompting
 is done.  You must pass at least OLD-BOOKMARK when calling from Lisp.
 If called from Lisp, prompts for NEWNAME if only OLD-BOOKMARK was
 passed as an argument.  If called with two strings, then no prompting
 is done.  You must pass at least OLD-BOOKMARK when calling from Lisp.
@@ -2195,7 +2186,7 @@ corresponding bookmark function from Lisp \(the one without the
 
 ;;;###autoload
 (defun bookmark-menu-delete (event)
 
 ;;;###autoload
 (defun bookmark-menu-delete (event)
-  "Delete the bookmark named NAME from the bookmark list.  
+  "Delete the bookmark named NAME from the bookmark list.
 Removes only the first instance of a bookmark with that name.  If
 there are one or more other bookmarks with the same name, they will
 not be deleted.  Defaults to the \"current\" bookmark \(that is, the
 Removes only the first instance of a bookmark with that name.  If
 there are one or more other bookmarks with the same name, they will
 not be deleted.  Defaults to the \"current\" bookmark \(that is, the
@@ -2225,7 +2216,7 @@ corresponding bookmark function from Lisp \(the one without the
 
 ;; make bookmarks appear toward the right side of the menu.
 (if (boundp 'menu-bar-final-items)
 
 ;; make bookmarks appear toward the right side of the menu.
 (if (boundp 'menu-bar-final-items)
-    (if menu-bar-final-items 
+    (if menu-bar-final-items
         (setq menu-bar-final-items
               (cons 'bookmark menu-bar-final-items)))
   (setq menu-bar-final-items '(bookmark)))
         (setq menu-bar-final-items
               (cons 'bookmark menu-bar-final-items)))
   (setq menu-bar-final-items '(bookmark)))
@@ -2267,7 +2258,7 @@ corresponding bookmark function from Lisp \(the one without the
   '("Set Bookmark" . bookmark-set))
 
 ;;;###autoload
   '("Set Bookmark" . bookmark-set))
 
 ;;;###autoload
-(define-key menu-bar-bookmark-map [jump] 
+(define-key menu-bar-bookmark-map [jump]
   '("Jump to Bookmark" . bookmark-menu-jump))
 
 ;;;; end bookmark menu stuff ;;;;
   '("Jump to Bookmark" . bookmark-menu-jump))
 
 ;;;; end bookmark menu stuff ;;;;
@@ -2277,8 +2268,24 @@ corresponding bookmark function from Lisp \(the one without the
 (defvar bookmark-load-hook nil
   "Hook to run at the end of loading bookmark.")
 
 (defvar bookmark-load-hook nil
   "Hook to run at the end of loading bookmark.")
 
+;;; Exit Hook, called from kill-emacs-hook
+(defvar bookmark-exit-hook nil
+  "Hook to run when emacs exits")
+
+(defun bookmark-exit-hook-internal ()
+  "Save bookmark state, if necessary, at Emacs exit time.
+This also runs `bookmark-exit-hooks'."
+  (and
+   (progn (run-hooks 'bookmark-exit-hooks) t)
+   bookmark-alist
+   (bookmark-time-to-save-p t)
+   (bookmark-save)))
+
+(add-hook 'kill-emacs-hook 'bookmark-exit-hook-internal)
+
+
 (run-hooks 'bookmark-load-hook)
 
 (provide 'bookmark)
 (run-hooks 'bookmark-load-hook)
 
 (provide 'bookmark)
-      
+
 ;;; bookmark.el ends here
 ;;; bookmark.el ends here