Add icicle
authorJoerg Jaspert <joerg@debian.org>
Sun, 3 Mar 2013 13:32:31 +0000 (14:32 +0100)
committerJoerg Jaspert <joerg@debian.org>
Sun, 3 Mar 2013 13:32:31 +0000 (14:32 +0100)
40 files changed:
elisp/icicle/apropos-fn+var.el [new file with mode: 0644]
elisp/icicle/bookmark+-1.el [new file with mode: 0644]
elisp/icicle/bookmark+-bmu.el [new file with mode: 0644]
elisp/icicle/bookmark+-chg.el [new file with mode: 0644]
elisp/icicle/bookmark+-doc.el [new file with mode: 0644]
elisp/icicle/bookmark+-key.el [new file with mode: 0644]
elisp/icicle/bookmark+-lit.el [new file with mode: 0644]
elisp/icicle/bookmark+-mac.el [new file with mode: 0644]
elisp/icicle/bookmark+.el [new file with mode: 0644]
elisp/icicle/col-highlight.el [new file with mode: 0644]
elisp/icicle/crosshairs.el [new file with mode: 0644]
elisp/icicle/dired+.el [new file with mode: 0644]
elisp/icicle/doremi-frm.el [new file with mode: 0644]
elisp/icicle/doremi.el [new file with mode: 0644]
elisp/icicle/fit-frame.el [new file with mode: 0644]
elisp/icicle/fuzzy-match.el [new file with mode: 0644]
elisp/icicle/hexrgb.el [new file with mode: 0644]
elisp/icicle/hl-line+.el [new file with mode: 0644]
elisp/icicle/icicles-chg.el [new file with mode: 0644]
elisp/icicle/icicles-cmd1.el [new file with mode: 0644]
elisp/icicle/icicles-cmd2.el [new file with mode: 0644]
elisp/icicle/icicles-doc1.el [new file with mode: 0644]
elisp/icicle/icicles-doc2.el [new file with mode: 0644]
elisp/icicle/icicles-face.el [new file with mode: 0644]
elisp/icicle/icicles-fn.el [new file with mode: 0644]
elisp/icicle/icicles-install.el [new file with mode: 0644]
elisp/icicle/icicles-mac.el [new file with mode: 0644]
elisp/icicle/icicles-mcmd.el [new file with mode: 0644]
elisp/icicle/icicles-mode.el [new file with mode: 0644]
elisp/icicle/icicles-opt.el [new file with mode: 0644]
elisp/icicle/icicles-var.el [new file with mode: 0644]
elisp/icicle/icicles.el [new file with mode: 0644]
elisp/icicle/icomplete+.el [new file with mode: 0644]
elisp/icicle/info+.el [new file with mode: 0644]
elisp/icicle/lacarte.el [new file with mode: 0644]
elisp/icicle/menu-bar+.el [new file with mode: 0644]
elisp/icicle/misc-cmds.el [new file with mode: 0644]
elisp/icicle/ring+.el [new file with mode: 0644]
elisp/icicle/synonyms.el [new file with mode: 0644]
elisp/icicle/vline.el [new file with mode: 0644]

diff --git a/elisp/icicle/apropos-fn+var.el b/elisp/icicle/apropos-fn+var.el
new file mode 100644 (file)
index 0000000..d92c4f1
--- /dev/null
@@ -0,0 +1,638 @@
+;;; apropos-fn+var.el --- Apropos for functions and variables
+;; 
+;; Filename: apropos-fn.el
+;; Description: Apropos for functions and variables
+;; Author: Drew Adams
+;; Maintainer: Drew Adams
+;; Copyright (C) 1996-2012, Drew Adams, all rights reserved.
+;; Created: Mon Nov 28 15:41:09 2005
+;; Version: 
+;; Last-Updated: Fri May 11 16:27:59 2012 (-0700)
+;;           By: dradams
+;;     Update #: 177
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/apropos-fn+var.el
+;; Keywords: apropos
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x
+;; 
+;; Features that might be required by this library:
+;;
+;;   `apropos', `naked'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 
+;;; Commentary: 
+;;
+;;  Standard `apropos' commands `apropos-variable' and
+;;  `apropos-command' do not distinguish, by command name, between the
+;;  different types of target object (but you can do that via `C-u').
+;;  This library provides individual `apropos' commands for user
+;;  options, variables in general (not just options), and functions in
+;;  general (not just commands).  These commands are defined here:
+;;
+;;    `apropos-option'   - Apropos a user option
+;;    `apropos-variable' - Apropos any variable, not just user option
+;;    `apropos-function' - Apropos any function, not just command
+;;
+;;
+;;  ***** NOTE: The following functions defined in `apropos.el' have
+;;              been REDEFINED HERE:
+;;
+;;  `apropos-variable' - See above (the standard command does what
+;;                       `apropos-option' does here).
+;;  `apropos-print'    - Identifies user options with label `Option'.
+;;
+;; 
+;;  Slightly different versions of `apropos-function' and
+;;  `apropos-variable' were posted by Kevin Rodgers to bug-gnu-emacs,
+;;  Tue, 06 Sep 2005 14:34:54 -0600.  Kevin didn't actually redefine
+;;  `apropos-variable' (he would never do that ;-)), but he provided
+;;  the new definition.  I redefined `apropos-print' and added button
+;;  type `apropos-option'.
+;; 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 
+;;; Change Log:
+;;
+;; 2012/05/11 dadams
+;;     apropos-print: Updated for Emacs 24.
+;; 2012/03/31 dadams
+;;     Button apropos-option: Added properties face and apropos-short-label (same as var).
+;; 2011/10/07 dadams
+;;     Added soft require of naked.el.
+;;     apropos-print: Use naked-key-description if available.
+;; 2011/03/31 dadams
+;;     apropos-print: Added Emacs 24+ version.
+;; 2006/03/03 dadams
+;;     Updated to latest Emacs 22 CVS version:
+;;       apropos-orig-regexp was renamed to apropos-pattern.
+;;       apropos-print now has an additional optional arg.
+;; 2006/02/25 dadams
+;;     apropos-variable: Added ignored optional arg, for compatibility.
+;; 2005/11/29 dadams
+;;     Added redefinition of apropos-print and button type apropos-option.
+;;     Made arg to apropos-function and apropos-variable mandatory.
+;; 2005/11/28 dadams
+;;     Redefined apropos-variable. Defined apropos-option as old version.
+;; 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;; 
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;; 
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;; 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 
+;;; Code:
+
+(require 'apropos)
+
+(require 'naked nil t) ;; (no error if not found): naked-key-description
+
+;; Quiet byte compiler
+(defvar apropos-compact-layout)
+(defvar apropos-multi-type)
+(defvar apropos-pattern)
+(defvar apropos-sort-by-scores)
+
+;;;;;;;;;;;;;;;;;;;;;;;;
+
+(if (< emacs-major-version 22)
+    (defun apropos-function (pattern)
+      "Show functions that match PATTERN (a regular expression).
+This includes functions that are not commands."
+      (interactive "i")                 ; Ignored when interactive
+      (if (interactive-p)
+          (let ((apropos-do-all t))
+            (call-interactively 'apropos-command))
+        (apropos-command pattern t)))
+  (defun apropos-function (pattern)
+    "Show functions that match PATTERN.
+This includes functions that are not commands.
+PATTERN can be a word, a list of words (separated by spaces),
+or a regexp (using some regexp special characters).  If it is a word,
+search for matches for that word as a substring.  If it is a list of words,
+search for matches for any two (or more) of those words.
+
+When called from a Lisp program, a string PATTERN is used as a regexp,
+while a list of strings is used as a word list."
+    (interactive "i")                   ; Ignored when interactive
+    (if (interactive-p)
+        (let ((apropos-do-all t))
+          (call-interactively 'apropos-command))
+      (apropos-command pattern t))))
+
+
+;;; REPLACE ORIGINAL defined in `apropos.el'.
+;;; Allow for non user-option variables too.
+;;; Rename original command as `apropos-option'.
+;;; 
+(or (fboundp 'apropos-option)
+(fset 'apropos-option (symbol-function 'apropos-variable)))
+
+(if (< emacs-major-version 22)
+    (defun apropos-variable (pattern &optional ignore)
+      "Show variables that match PATTERN (a regular expression).
+This includes variables that are not user options."
+      (interactive "i")                 ; Ignored when interactive
+      (if (interactive-p)
+          (let ((apropos-do-all t))
+            (call-interactively 'apropos-option))
+        (apropos-option pattern t)))
+  (defun apropos-variable (pattern &optional ignore)
+    "Show variables that match PATTERN.
+This includes variables that are not user options.
+PATTERN can be a word, a list of words (separated by spaces),
+or a regexp (using some regexp special characters).  If it is a word,
+search for matches for that word as a substring.  If it is a list of
+words, search for matches for any two (or more) of those words."
+    (interactive "i")                   ; Ignored when interactive
+    (if (interactive-p)
+        (let ((apropos-do-all t))
+          (call-interactively 'apropos-option))
+      (apropos-option pattern t))))
+
+
+;;; REPLACE ORIGINAL defined in `apropos.el'.
+;;; Use label "Option" for user options.
+;;; 
+(cond ((< emacs-major-version 22)       ; Emacs 20 and 21.
+       (defun apropos-print (do-keys spacing)
+         "Output result of apropos searching into buffer `*Apropos*'.
+The value of `apropos-accumulator' is the list of items to output.
+Each element should have the format (SYMBOL FN-DOC VAR-DOC [PLIST-DOC]).
+The return value is the list that was in `apropos-accumulator', sorted
+alphabetically by symbol name; but this function also sets
+`apropos-accumulator' to nil before returning."
+         (if (null apropos-accumulator)
+             (message "No apropos matches for `%s'" apropos-regexp)
+           (setq apropos-accumulator
+                 (sort apropos-accumulator (lambda (a b)
+                                             (string-lessp (car a) (car b)))))
+           (and apropos-label-face
+                (symbolp apropos-label-face)
+                (setq apropos-label-face `(face ,apropos-label-face
+                                           mouse-face highlight)))
+           (with-output-to-temp-buffer "*Apropos*"
+             (let ((p apropos-accumulator)
+                   (old-buffer (current-buffer))
+                   symbol item point1 point2)
+               (set-buffer standard-output)
+               (apropos-mode)
+               (if window-system
+                   (insert "If you move the mouse over text that changes color,\n"
+                           (substitute-command-keys
+                            "you can click \\[apropos-mouse-follow] to get more information.\n")))
+               (insert (substitute-command-keys
+                        "In this buffer, type \\[apropos-follow] to get full documentation.\n\n"))
+               (while (consp p)
+                 (or (not spacing) (bobp) (terpri))
+                 (setq apropos-item (car p)
+                       symbol (car apropos-item)
+                       p (cdr p)
+                       point1 (point))
+                 (princ symbol)         ; print symbol name
+                 (setq point2 (point))
+                 ;; Calculate key-bindings if we want them.
+                 (and do-keys
+                      (commandp symbol)
+                      (indent-to 30 1)
+                      (if (let ((keys
+                                 (save-excursion
+                                   (set-buffer old-buffer)
+                                   (where-is-internal symbol)))
+                                filtered)
+                            ;; Copy over the list of key sequences,
+                            ;; omitting any that contain a buffer or a frame.
+                            (while keys
+                              (let ((key (car keys))
+                                    (i 0)
+                                    loser)
+                                (while (< i (length key))
+                                  (if (or (framep (aref key i))
+                                          (bufferp (aref key i)))
+                                      (setq loser t))
+                                  (setq i (1+ i)))
+                                (or loser
+                                    (setq filtered (cons key filtered))))
+                              (setq keys (cdr keys)))
+                            (setq item filtered))
+                          ;; Convert the remaining keys to a string and insert.
+                          (insert
+                           (mapconcat
+                            (lambda (key)
+                              (setq key (condition-case ()
+                                            (if (fboundp 'naked-key-description)
+                                                (naked-key-description key)
+                                              (key-description key))
+                                          (error)))
+                              (if apropos-keybinding-face
+                                  (put-text-property 0 (length key)
+                                                     'face apropos-keybinding-face
+                                                     key))
+                              key)
+                            item ", "))
+                        (insert "M-x")
+                        (put-text-property (- (point) 3) (point)
+                                           'face apropos-keybinding-face)
+                        (insert " " (symbol-name symbol) " ")
+                        (insert "RET")
+                        (put-text-property (- (point) 3) (point)
+                                           'face apropos-keybinding-face)))
+                 (terpri)
+                 ;; only now so we don't propagate text attributes all over
+                 (put-text-property point1 point2 'item
+                                    (if (eval `(or ,@(cdr apropos-item)))
+                                        (car apropos-item)
+                                      apropos-item))
+                 (if apropos-symbol-face
+                     (put-text-property point1 point2 'face apropos-symbol-face))
+                 (apropos-print-doc 'describe-function 1 (if (commandp symbol)
+                                                             "Command"
+                                                           (if (apropos-macrop symbol)
+                                                               "Macro"
+                                                             "Function"))
+                                    t)
+                 ;; We used to use customize-variable-other-window instead
+                 ;; for a customizable variable, but that is slow.
+                 ;; It is better to show an ordinary help buffer
+                 ;; and let the user click on the customization button
+                 ;; in that buffer, if he wants to.
+                 ;; Likewise for `customize-face-other-window'.
+                 (apropos-print-doc 'describe-variable 2 (if (user-variable-p symbol)
+                                                             "Option"
+                                                           "Variable")
+                                    t)
+                 (apropos-print-doc 'customize-group-other-window 6 "Group" t)
+                 (apropos-print-doc 'describe-face 5 "Face" t)
+                 (apropos-print-doc 'widget-browse-other-window 4 "Widget" t)
+                 (apropos-print-doc 'apropos-describe-plist 3 "Plist" nil))
+               (setq buffer-read-only t))))
+         (prog1 apropos-accumulator
+           (setq apropos-accumulator ()))))
+      ((< emacs-major-version 24)       ; Emacs 22 and 23.
+       (defun apropos-print (do-keys spacing &optional text nosubst)
+         "Output result of apropos searching into buffer `*Apropos*'.
+The value of `apropos-accumulator' is the list of items to output.
+Each element should have the format
+ (SYMBOL SCORE FN-DOC VAR-DOC [PLIST-DOC WIDGET-DOC FACE-DOC GROUP-DOC]).
+The return value is the list that was in `apropos-accumulator', sorted
+alphabetically by symbol name; but this function also sets
+`apropos-accumulator' to nil before returning.
+
+If SPACING is non-nil, it should be a string; separate items with that string.
+If non-nil TEXT is a string that will be printed as a heading."
+         (if (null apropos-accumulator)
+             (message "No apropos matches for `%s'" apropos-pattern)
+           (setq apropos-accumulator
+                 (sort apropos-accumulator
+                       (lambda (a b)
+                         ;; Don't sort by score if user can't see the score.
+                         ;; It would be confusing.  -- rms.
+                         (if (and (boundp 'apropos-sort-by-scores)
+                                  apropos-sort-by-scores)
+                             (or (> (cadr a) (cadr b))
+                                 (and (= (cadr a) (cadr b))
+                                      (string-lessp (car a) (car b))))
+                           (string-lessp (car a) (car b))))))
+           (with-output-to-temp-buffer "*Apropos*"
+             (let ((p apropos-accumulator)
+                   (old-buffer (current-buffer))
+                   symbol item)
+               (set-buffer standard-output)
+               (apropos-mode)
+               (if (display-mouse-p)
+                   (insert
+                    "If moving the mouse over text changes the text's color, "
+                    "you can click\n"
+                    "mouse-2 (second button from right) on that text to "
+                    "get more information.\n"))
+               (insert "In this buffer, go to the name of the command, function, or variable,\n"
+                       (substitute-command-keys
+                        "and type \\[apropos-follow] to get full documentation.\n\n"))
+               (if text (insert text "\n\n"))
+               (while (consp p)
+                 (when (and spacing (not (bobp)))
+                   (princ spacing))
+                 (setq apropos-item (car p)
+                       symbol (car apropos-item)
+                       p (cdr p))
+                 ;; Insert dummy score element for backwards compatibility with 21.x
+                 ;; apropos-item format.
+                 (if (not (numberp (cadr apropos-item)))
+                     (setq apropos-item
+                           (cons (car apropos-item)
+                                 (cons nil (cdr apropos-item)))))
+                 (insert-text-button (symbol-name symbol)
+                                     'type 'apropos-symbol
+                                     ;; Can't use default, since user may have
+                                     ;; changed the variable!
+                                     ;; Just say `no' to variables containing faces!
+                                     'face apropos-symbol-face)
+                 (if (and (eq apropos-sort-by-scores 'verbose)
+                          (cadr apropos-item))
+                     (insert " (" (number-to-string (cadr apropos-item)) ") "))
+                 ;; Calculate key-bindings if we want them.
+                 (and do-keys
+                      (commandp symbol)
+                      (indent-to 30 1)
+                      (if (let ((keys
+                                 (save-excursion
+                                   (set-buffer old-buffer)
+                                   (where-is-internal symbol)))
+                                filtered)
+                            ;; Copy over the list of key sequences,
+                            ;; omitting any that contain a buffer or a frame.
+                            (while keys
+                              (let ((key (car keys))
+                                    (i 0)
+                                    loser)
+                                (while (< i (length key))
+                                  (if (or (framep (aref key i))
+                                          (bufferp (aref key i)))
+                                      (setq loser t))
+                                  (setq i (1+ i)))
+                                (or loser
+                                    (setq filtered (cons key filtered))))
+                              (setq keys (cdr keys)))
+                            (setq item filtered))
+                          ;; Convert the remaining keys to a string and insert.
+                          (insert
+                           (mapconcat
+                            (lambda (key)
+                              (setq key (condition-case ()
+                                            (if (fboundp 'naked-key-description)
+                                                (naked-key-description key)
+                                              (key-description key))
+                                          (error)))
+                              (if apropos-keybinding-face
+                                  (put-text-property 0 (length key)
+                                                     'face apropos-keybinding-face
+                                                     key))
+                              key)
+                            item ", "))
+                        (insert "M-x ... RET")
+                        (when apropos-keybinding-face
+                          (put-text-property (- (point) 11) (- (point) 8)
+                                             'face apropos-keybinding-face)
+                          (put-text-property (- (point) 3) (point)
+                                             'face apropos-keybinding-face))))
+                 (terpri)
+                 (apropos-print-doc 2 (if (commandp symbol)
+                                          'apropos-command
+                                        (if (apropos-macrop symbol)
+                                            'apropos-macro
+                                          'apropos-function))
+                                    (not nosubst))
+                 (apropos-print-doc 3 (if (user-variable-p symbol)
+                                          'apropos-option
+                                        'apropos-variable)
+                                    (not nosubst))
+                 (apropos-print-doc 7 'apropos-group t)
+                 (apropos-print-doc 6 'apropos-face t)
+                 (apropos-print-doc 5 'apropos-widget t)
+                 (apropos-print-doc 4 'apropos-plist nil))
+               (setq buffer-read-only t))))
+         (prog1 apropos-accumulator
+           (setq apropos-accumulator ())))) ; permit gc
+      (t                                ; Emacs 24+.
+       (defun apropos-print (do-keys spacing &optional text nosubst)
+         "Output result of apropos searching into buffer `*Apropos*'.
+The value of `apropos-accumulator' is the list of items to output.
+Each element should have the format
+ (SYMBOL SCORE FN-DOC VAR-DOC [PLIST-DOC WIDGET-DOC FACE-DOC GROUP-DOC]).
+The return value is the list that was in `apropos-accumulator', sorted
+alphabetically by symbol name; but this function also sets
+`apropos-accumulator' to nil before returning.
+
+If SPACING is non-nil, it should be a string; separate items with that string.
+If non-nil TEXT is a string that will be printed as a heading."
+         (if (null apropos-accumulator)
+             (message "No apropos matches for `%s'" apropos-pattern)
+           (setq apropos-accumulator
+                 (sort apropos-accumulator
+                       (lambda (a b)
+                         ;; Don't sort by score if user can't see the score.
+                         ;; It would be confusing.  -- rms.
+                         (if apropos-sort-by-scores
+                             (or (> (cadr a) (cadr b))
+                                 (and (= (cadr a) (cadr b))
+                                      (string-lessp (car a) (car b))))
+                           (string-lessp (car a) (car b))))))
+           (with-output-to-temp-buffer "*Apropos*"
+             (let ((p apropos-accumulator)
+                   (old-buffer (current-buffer))
+                   (inhibit-read-only t)
+                   symbol item)
+               (set-buffer standard-output)
+               (apropos-mode)
+               (insert (substitute-command-keys "Type \\[apropos-follow] on ")
+                       (if apropos-multi-type "a type label" "an entry")
+                       " to view its full documentation.\n\n")
+               (if text (insert text "\n\n"))
+               (dolist (apropos-item p)
+                 (when (and spacing (not (bobp)))
+                   (princ spacing))
+                 (setq symbol (car apropos-item))
+                 ;; Insert dummy score element for backwards compatibility with 21.x
+                 ;; apropos-item format.
+                 (if (not (numberp (cadr apropos-item)))
+                     (setq apropos-item
+                           (cons (car apropos-item)
+                                 (cons nil (cdr apropos-item)))))
+                 (insert-text-button (symbol-name symbol)
+                                     'type 'apropos-symbol
+                                     'skip apropos-multi-type
+                                     'face (if (boundp 'apropos-symbol-face)
+                                               apropos-symbol-face
+                                             'apropos-symbol))
+                 (if (and (eq apropos-sort-by-scores 'verbose)
+                          (cadr apropos-item))
+                     (insert " (" (number-to-string (cadr apropos-item)) ") "))
+                 ;; Calculate key-bindings if we want them.
+                 (unless apropos-compact-layout
+                   (and do-keys
+                        (commandp symbol)
+                        (not (eq symbol 'self-insert-command))
+                        (indent-to 30 1)
+                        (if (let ((keys
+                                   (with-current-buffer old-buffer
+                                     (where-is-internal symbol)))
+                                  filtered)
+                              ;; Copy over the list of key sequences,
+                              ;; omitting any that contain a buffer or a frame.
+                              ;; FIXME: Why omit keys that contain buffers and
+                              ;; frames?  This looks like a bad workaround rather
+                              ;; than a proper fix.  Does anybody know what problem
+                              ;; this is trying to address?  --Stef
+                              (dolist (key keys)
+                                (let ((i 0)
+                                      loser)
+                                  (while (< i (length key))
+                                    (if (or (framep (aref key i))
+                                            (bufferp (aref key i)))
+                                        (setq loser t))
+                                    (setq i (1+ i)))
+                                  (or loser
+                                      (push key filtered))))
+                              (setq item filtered))
+                            ;; Convert the remaining keys to a string and insert.
+                            (insert
+                             (mapconcat
+                              (lambda (key)
+                                (setq key (condition-case ()
+                                              (if (fboundp 'naked-key-description)
+                                                  (naked-key-description key)
+                                                (key-description key))
+                                            (error)))
+                                (put-text-property 0 (length key)
+                                                   'face (if (boundp 'apropos-keybinding-face)
+                                                             apropos-keybinding-face
+                                                           'apropos-keybinding)
+                                                   key)
+                                key)
+                              item ", "))
+                          (insert "M-x ... RET")
+                          (put-text-property (- (point) 11) (- (point) 8)
+                                             'face (if (boundp 'apropos-keybinding-face)
+                                                       apropos-keybinding-face
+                                                     'apropos-keybinding))
+                          (put-text-property (- (point) 3) (point)
+                                             'face (if (boundp 'apropos-keybinding-face)
+                                                       apropos-keybinding-face
+                                                     'apropos-keybinding))))
+                   (terpri))
+                 (apropos-print-doc 2 (if (commandp symbol)
+                                          'apropos-command
+                                        (if (apropos-macrop symbol)
+                                            'apropos-macro
+                                          'apropos-function))
+                                    (not nosubst))
+                 (apropos-print-doc 3 (if (user-variable-p symbol)
+                                          'apropos-option
+                                        'apropos-variable)
+                                    (not nosubst))
+                 (apropos-print-doc 7 'apropos-group t)
+                 (apropos-print-doc 6 'apropos-face t)
+                 (apropos-print-doc 5 'apropos-widget t)
+                 (apropos-print-doc 4 'apropos-plist nil))
+               (set (make-local-variable 'truncate-partial-width-windows) t)
+               (set (make-local-variable 'truncate-lines) t))))
+         (prog1 apropos-accumulator
+           (setq apropos-accumulator ()))))) ; permit gc
+
+(when (>= emacs-major-version 22)
+  (defface apropos-option '((t (:inherit font-lock-variable-name-face)))
+    "Face used for option names in Apropos buffers."
+    :group 'apropos)
+
+  (define-button-type 'apropos-option
+      'apropos-label "Option"
+      'apropos-short-label "v"          ; Same as variable
+      'face '(apropos-option button)
+      'help-echo "mouse-2, RET: Display more help on this user option (variable)"
+      'follow-link t
+      'action (lambda (button)
+                (describe-variable (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-function
+;;;       'apropos-label "Function"
+;;;       'apropos-short-label "f"
+;;;       'face '(font-lock-function-name-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this function"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (describe-function (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-macro
+;;;       'apropos-label "Macro"
+;;;       'apropos-short-label "m"
+;;;       'face '(font-lock-function-name-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this macro"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (describe-function (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-command
+;;;       'apropos-label "Command"
+;;;       'apropos-short-label "c"
+;;;       'face '(font-lock-function-name-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this command"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (describe-function (button-get button 'apropos-symbol))))
+
+;;;   ;; We used to use `customize-variable-other-window' instead for a
+;;;   ;; customizable variable, but that is slow.  It is better to show an
+;;;   ;; ordinary help buffer and let the user click on the customization
+;;;   ;; button in that buffer, if he wants to.
+;;;   ;; Likewise for `customize-face-other-window'.
+;;;   (define-button-type 'apropos-variable
+;;;       'apropos-label "Variable"
+;;;       'apropos-short-label "v"
+;;;       'face '(font-lock-variable-name-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this variable"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (describe-variable (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-face
+;;;       'apropos-label "Face"
+;;;       'apropos-short-label "F"
+;;;       'face '(font-lock-variable-name-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this face"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (describe-face (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-group
+;;;       'apropos-label "Group"
+;;;       'apropos-short-label "g"
+;;;       'face '(font-lock-builtin-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this group"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (customize-group-other-window
+;;;                  (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-widget
+;;;       'apropos-label "Widget"
+;;;       'apropos-short-label "w"
+;;;       'face '(font-lock-builtin-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this widget"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (widget-browse-other-window (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-plist
+;;;       'apropos-label "Properties"
+;;;       'apropos-short-label "p"
+;;;       'face '(font-lock-keyword-face button)
+;;;       'help-echo "mouse-2, RET: Display more help on this plist"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (apropos-describe-plist (button-get button 'apropos-symbol))))
+
+;;;   (define-button-type 'apropos-library
+;;;       'help-echo "mouse-2, RET: Display more help on this library"
+;;;       'follow-link t
+;;;       'action (lambda (button)
+;;;                 (apropos-library (button-get button 'apropos-symbol))))
+  )
+
+;;;;;;;;;;;;;;;;;;;;
+
+(provide 'apropos-fn+var)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; apropos-fn.el ends here
diff --git a/elisp/icicle/bookmark+-1.el b/elisp/icicle/bookmark+-1.el
new file mode 100644 (file)
index 0000000..989319c
--- /dev/null
@@ -0,0 +1,10332 @@
+;;; bookmark+-1.el - First part of package Bookmark+.
+;;
+;; Filename: bookmark+-1.el
+;; Description: First part of package Bookmark+.
+;; Author: Drew Adams, Thierry Volpiatto
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2012, Drew Adams, all rights reserved.
+;; Copyright (C) 2009, Thierry Volpiatto, all rights reserved.
+;; Created: Mon Jul 12 13:43:55 2010 (-0700)
+;; Last-Updated: Wed May 16 08:20:58 2012 (-0700)
+;;           By: dradams
+;;     Update #: 5559
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/bookmark+-1.el
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x
+;;
+;; Features that might be required by this library:
+;;
+;;   `bookmark', `bookmark+-1', `bookmark+-mac', `cl', `dired',
+;;   `dired-aux', `dired-x', `ffap', `pp', `thingatpt', `thingatpt+'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;    The Bookmark+ libraries are these:
+;;
+;;    `bookmark+.el'     - main (driver) library
+;;    `bookmark+-mac.el' - Lisp macros
+;;    `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;;    `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;;    `bookmark+-1.el'   - other (non-bmenu) required code (this file)
+;;    `bookmark+-key.el' - key and menu bindings
+;;
+;;    `bookmark+-doc.el' - documentation (comment-only file)
+;;    `bookmark+-chg.el' - change log (comment-only file)
+;;
+;;    The documentation (in `bookmark+-doc.el') includes how to
+;;    byte-compile and install Bookmark+.  The documentation is also
+;;    available in these ways:
+;;
+;;    1. From the bookmark list (`C-x r l'):
+;;       Use `?' to show the current bookmark-list status and general
+;;       help, then click link `Doc in Commentary' or link `Doc on the
+;;       Web'.
+;;
+;;    2. From the Emacs-Wiki Web site:
+;;       http://www.emacswiki.org/cgi-bin/wiki/BookmarkPlus.
+;;
+;;    3. From the Bookmark+ group customization buffer:
+;;       `M-x customize-group bookmark-plus', then click link
+;;       `Commentary'.
+;;
+;;    (The commentary links in #1 and #3 work only if you have library
+;;    `bookmark+-doc.el' in your `load-path'.)
+;;(@> "Index")
+;;
+;;  Index
+;;  -----
+;;
+;;  If you have library `linkd.el' and Emacs 22 or later, load
+;;  `linkd.el' and turn on `linkd-mode' now.  It lets you easily
+;;  navigate around the sections of this doc.  Linkd mode will
+;;  highlight this Index, as well as the cross-references and section
+;;  headings throughout this file.  You can get `linkd.el' here:
+;;  http://dto.freeshell.org/notebook/Linkd.html.
+;;
+;;  (@> "Things Defined Here")
+;;  (@> "User Options (Customizable)")
+;;  (@> "Internal Variables")
+;;  (@> "Compatibility Code for Older Emacs Versions")
+;;  (@> "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
+;;  (@> "Bookmark+ Functions (`bmkp-*')")
+;;    (@> "Search-and-Replace Locations of Marked Bookmarks")
+;;    (@> "Tags")
+;;    (@> "Bookmark Predicates")
+;;    (@> "Filter Functions")
+;;    (@> "General Utility Functions")
+;;    (@> "Bookmark Entry Access Functions")
+;;    (@> "Sorting - General Functions")
+;;    (@> "Sorting - Commands")
+;;    (@> "Sorting - General Predicates")
+;;    (@> "Sorting - File-Name Predicates")
+;;    (@> "Indirect Bookmarking Functions")
+;;    (@> "Other Bookmark+ Functions (`bmkp-*')")
+;;  (@> "Keymaps")
+;;(@* "Things Defined Here")
+;;
+;;  Things Defined Here
+;;  -------------------
+;;
+;;  Commands defined here:
+;;
+;;    `bmkp-add-tags', `bmkp-all-tags-jump',
+;;    `bmkp-all-tags-jump-other-window', `bmkp-all-tags-regexp-jump',
+;;    `bmkp-all-tags-regexp-jump-other-window',
+;;    `bmkp-autofile-add-tags', `bmkp-autofile-all-tags-jump',
+;;    `bmkp-autofile-all-tags-jump-other-window',
+;;    `bmkp-autofile-all-tags-regexp-jump',
+;;    `bmkp-autofile-all-tags-regexp-jump-other-window',
+;;    `bmkp-autofile-jump', `bmkp-autofile-jump-other-window',
+;;    `bmkp-autofile-remove-tags', `bmkp-autofile-set',
+;;    `bmkp-autofile-some-tags-jump',
+;;    `bmkp-autofile-some-tags-jump-other-window',
+;;    `bmkp-autofile-some-tags-regexp-jump',
+;;    `bmkp-autofile-some-tags-regexp-jump-other-window',
+;;    `bmkp-auto-idle-bookmark-mode', `bmkp-autonamed-jump',
+;;    `bmkp-autonamed-jump-other-window',
+;;    `bmkp-autonamed-this-buffer-jump',
+;;    `bmkp-autonamed-this-buffer-jump-other-window',
+;;    `bmkp-bookmark-a-file' `bmkp-bookmark-file-jump',
+;;    `bmkp-bookmark-list-jump',
+;;    `bmkp-choose-navlist-from-bookmark-list',
+;;    `bmkp-choose-navlist-of-type', `bmkp-compilation-target-set',
+;;    `bmkp-compilation-target-set-all', `bmkp-copy-tags',
+;;    `bmkp-crosshairs-highlight', `bmkp-cycle',
+;;    `bmkp-cycle-autonamed', `bmkp-cycle-autonamed-other-window',
+;;    `bmkp-cycle-bookmark-list',
+;;    `bmkp-cycle-bookmark-list-other-window', `bmkp-cycle-desktop',
+;;    `bmkp-cycle-dired', `bmkp-cycle-dired-other-window',
+;;    `bmkp-cycle-file', `bmkp-cycle-file-other-window',
+;;    `bmkp-cycle-gnus', `bmkp-cycle-gnus-other-window',
+;;    `bmkp-cycle-info', `bmkp-cycle-info-other-window',
+;;    `bmkp-cycle-lighted', `bmkp-cycle-lighted-other-window',
+;;    `bmkp-cycle-local-file', `bmkp-cycle-local-file-other-window',
+;;    `bmkp-cycle-man', `bmkp-cycle-man-other-window',
+;;    `bmkp-cycle-non-file', `bmkp-cycle-non-file-other-window',
+;;    `bmkp-cycle-other-window', `bmkp-cycle-remote-file',
+;;    `bmkp-cycle-remote-file-other-window',
+;;    `bmkp-cycle-specific-buffers',
+;;    `bmkp-cycle-specific-buffers-other-window',
+;;    `bmkp-cycle-specific-files',
+;;    `bmkp-cycle-specific-files-other-window',
+;;    `bmkp-cycle-this-buffer', `bmkp-cycle-this-buffer-other-window',
+;;    `bmkp-cycle-this-file', `bmkp-cycle-this-file/buffer',
+;;    `bmkp-cycle-this-file/buffer-other-window',
+;;    `bmkp-cycle-this-file-other-window', `bmkp-cycle-variable-list',
+;;    `bmkp-cycle-url', `bmkp-cycle-url-other-window',
+;;    `bmkp-delete-all-autonamed-for-this-buffer',
+;;    `bmkp-delete-all-temporary-bookmarks', `bmkp-delete-bookmarks',
+;;    `bmkp-describe-bookmark', `bmkp-describe-bookmark-internals',
+;;    `bmkp-desktop-change-dir', `bmkp-desktop-delete',
+;;    `bmkp-desktop-jump', `bmkp-desktop-read', `bmkp-dired-jump',
+;;    `bmkp-dired-jump-other-window', `bmkp-dired-this-dir-jump',
+;;    `bmkp-dired-this-dir-jump-other-window',
+;;    `bmkp-edit-bookmark-name-and-file', `bmkp-edit-bookmark-record',
+;;    `bmkp-edit-bookmark-record-send',
+;;    `bmkp-edit-bookmark-records-send', `bmkp-edit-tags',
+;;    `bmkp-edit-tags-send', `bmkp-empty-file',
+;;    `bmkp-file-target-set', `bmkp-file-all-tags-jump',
+;;    `bmkp-file-all-tags-jump-other-window',
+;;    `bmkp-file-all-tags-regexp-jump',
+;;    `bmkp-file-all-tags-regexp-jump-other-window', `bmkp-file-jump',
+;;    `bmkp-file-jump-other-window', `bmkp-file-some-tags-jump',
+;;    `bmkp-file-some-tags-jump-other-window',
+;;    `bmkp-file-some-tags-regexp-jump',
+;;    `bmkp-file-some-tags-regexp-jump-other-window',
+;;    `bmkp-file-this-dir-all-tags-jump',
+;;    `bmkp-file-this-dir-all-tags-jump-other-window',
+;;    `bmkp-file-this-dir-all-tags-regexp-jump',
+;;    `bmkp-file-this-dir-all-tags-regexp-jump-other-window',
+;;    `bmkp-file-this-dir-jump',
+;;    `bmkp-file-this-dir-jump-other-window',
+;;    `bmkp-file-this-dir-some-tags-jump',
+;;    `bmkp-file-this-dir-some-tags-jump-other-window',
+;;    `bmkp-file-this-dir-some-tags-regexp-jump',
+;;    `bmkp-file-this-dir-some-tags-regexp-jump-other-window',
+;;    `bmkp-find-file', `bmkp-find-file-other-window',
+;;    `bmkp-find-file-all-tags',
+;;    `bmkp-find-file-all-tags-other-window',
+;;    `bmkp-find-file-all-tags-regexp',
+;;    `bmkp-find-file-all-tags-regexp-other-window',
+;;    `bmkp-find-file-some-tags',
+;;    `bmkp-find-file-some-tags-other-window',
+;;    `bmkp-find-file-some-tags-regexp',
+;;    `bmkp-find-file-some-tags-regexp-other-window',
+;;    `bmkp-global-auto-idle-bookmark-mode' (Emacs 21+),
+;;    `bmkp-gnus-jump', `bmkp-gnus-jump-other-window',
+;;    `bmkp-image-jump', `bmkp-image-jump-other-window',
+;;    `bmkp-info-jump', `bmkp-info-jump-other-window',
+;;    `bmkp-jump-in-navlist', `bmkp-jump-in-navlist-other-window',
+;;    `bmkp-jump-to-type', `bmkp-jump-to-type-other-window',
+;;    `bmkp-list-all-tags', `bmkp-list-defuns-in-commands-file',
+;;    `bmkp-local-file-jump', `bmkp-local-file-jump-other-window',
+;;    `bmkp-make-bookmark-savable', `bmkp-make-bookmark-temporary',
+;;    `bmkp-make-function-bookmark', `bmkp-man-jump',
+;;    `bmkp-man-jump-other-window', `bmkp-menu-jump-other-window'
+;;    (Emacs 20, 21), `bmkp-navlist-bmenu-list',
+;;    `bmkp-next-autonamed-bookmark',
+;;    `bmkp-next-autonamed-bookmark-repeat', `bmkp-next-bookmark',
+;;    `bmkp-next-bookmark-list-bookmark',
+;;    `bmkp-next-bookmark-list-bookmark-repeat',
+;;    `bmkp-next-bookmark-repeat', `bmkp-next-bookmark-this-buffer',
+;;    `bmkp-next-bookmark-this-buffer-repeat',
+;;    `bmkp-next-bookmark-this-file',
+;;    `bmkp-next-bookmark-this-file/buffer',
+;;    `bmkp-next-bookmark-this-file/buffer-repeat',
+;;    `bmkp-next-bookmark-this-file-repeat', `bmkp-next-bookmark-w32',
+;;    `bmkp-next-bookmark-w32-repeat', `bmkp-next-desktop-bookmark',
+;;    `bmkp-next-desktop-bookmark-repeat', `bmkp-next-dired-bookmark',
+;;    `bmkp-next-dired-bookmark-repeat', `bmkp-next-file-bookmark',
+;;    `bmkp-next-file-bookmark-repeat', `bmkp-next-gnus-bookmark',
+;;    `bmkp-next-gnus-bookmark-repeat', `bmkp-next-info-bookmark',
+;;    `bmkp-next-info-bookmark-repeat', `bmkp-next-lighted-bookmark',
+;;    `bmkp-next-lighted-bookmark-repeat',
+;;    `bmkp-next-local-file-bookmark',
+;;    `bmkp-next-local-file-bookmark-repeat',
+;;    `bmkp-next-man-bookmark', `bmkp-next-man-bookmark-repeat',
+;;    `bmkp-next-non-file-bookmark',
+;;    `bmkp-next-non-file-bookmark-repeat',
+;;    `bmkp-next-remote-file-bookmark',
+;;    `bmkp-next-remote-file-bookmark-repeat',
+;;    `bmkp-next-specific-buffers-bookmark',
+;;    `bmkp-next-specific-buffers-bookmark-repeat',
+;;    `bmkp-next-specific-files-bookmark',
+;;    `bmkp-next-specific-files-bookmark-repeat',
+;;    `bmkp-next-variable-list-bookmark',
+;;    `bmkp-next-variable-list-bookmark-repeat',
+;;    `bmkp-next-url-bookmark', `bmkp-next-url-bookmark-repeat',
+;;    `bmkp-non-file-jump', `bmkp-non-file-jump-other-window',
+;;    `bmkp-occur-create-autonamed-bookmarks',
+;;    `bmkp-occur-target-set', `bmkp-occur-target-set-all',
+;;    `bmkp-paste-add-tags', `bmkp-paste-replace-tags',
+;;    `bmkp-previous-bookmark', `bmkp-previous-bookmark-repeat',
+;;    `bmkp-previous-bookmark-this-buffer',
+;;    `bmkp-previous-bookmark-this-buffer-repeat',
+;;    `bmkp-previous-bookmark-this-file',
+;;    `bmkp-previous-bookmark-this-file/buffer',
+;;    `bmkp-previous-bookmark-this-file/buffer-repeat',
+;;    `bmkp-previous-bookmark-this-file-repeat',
+;;    `bmkp-previous-bookmark-w32',
+;;    `bmkp-previous-bookmark-w32-repeat',
+;;    `bmkp-purge-notags-autofiles', `bmkp-read-bookmark-for-type',
+;;    `bmkp-region-jump', `bmkp-region-jump-other-window',
+;;    `bmkp-remote-file-jump', `bmkp-remote-file-jump-other-window',
+;;    `bmkp-remove-all-tags', `bmkp-remove-tags',
+;;    `bmkp-remove-tags-from-all', `bmkp-rename-tag',
+;;    `bmkp-revert-bookmark-file', `bmkp-save-menu-list-state',
+;;    `bmkp-send-bug-report', `bmkp-set-autonamed-bookmark',
+;;    `bmkp-set-autonamed-bookmark-at-line',
+;;    `bmkp-set-autonamed-regexp-buffer',
+;;    `bmkp-set-autonamed-regexp-region',
+;;    `bmkp-set-bookmark-file-bookmark', `bmkp-set-desktop-bookmark',
+;;    `bmkp-set-restrictions-bookmark', `bmkp-set-tag-value',
+;;    `bmkp-set-tag-value-for-navlist',
+;;    `bmkp-set-variable-list-bookmark', `bmkp-some-tags-jump',
+;;    `bmkp-some-tags-jump-other-window',
+;;    `bmkp-some-tags-regexp-jump',
+;;    `bmkp-some-tags-regexp-jump-other-window',
+;;    `bmkp-specific-buffers-jump',
+;;    `bmkp-specific-buffers-jump-other-window',
+;;    `bmkp-specific-files-jump',
+;;    `bmkp-specific-files-jump-other-window',
+;;    `bmkp-switch-bookmark-file', `bmkp-switch-bookmark-file-create',
+;;    `bmkp-switch-to-last-bookmark-file', `bmkp-tag-a-file',
+;;    `bmkp-temporary-bookmarking-mode', `bmkp-temporary-jump',
+;;    `bmkp-temporary-jump-other-window',
+;;    `bmkp-this-buffer-bmenu-list', `bmkp-this-buffer-jump',
+;;    `bmkp-this-buffer-jump-other-window',
+;;    `bmkp-this-file-bmenu-list', `bmkp-this-file/buffer-bmenu-list',
+;;    `bmkp-toggle-autonamed-bookmark-set/delete',
+;;    `bmkp-toggle-autotemp-on-set',
+;;    `bmkp-toggle-bookmark-set-refreshes',
+;;    `bmkp-toggle-saving-bookmark-file',
+;;    `bmkp-toggle-saving-menu-list-state',
+;;    `bmkp-toggle-temporary-bookmark',
+;;    `bmkp-turn-on-auto-idle-bookmark-mode' (Emacs 21+),
+;;    `bmkp-unomit-all', `bmkp-untag-a-file', `bmkp-url-target-set',
+;;    `bmkp-url-jump', `bmkp-url-jump-other-window',
+;;    `bmkp-variable-list-jump', `bmkp-version',
+;;    `bmkp-w32-browser-jump', `bmkp-w3m-jump',
+;;    `bmkp-w3m-jump-other-window', `old-bookmark-insert'.
+;;
+;;  User options defined here:
+;;
+;;    `bmkp-auto-idle-bookmark-min-distance',
+;;    `bmkp-auto-idle-bookmark-mode-delay',
+;;    `bmkp-auto-idle-bookmark-mode-lighter',
+;;    `bmkp-auto-idle-bookmark-mode-set-function',
+;;    `bmkp-autoname-bookmark-function', `bmkp-autoname-format',
+;;    `bmkp-autotemp-bookmark-predicates',
+;;    `bmkp-bookmark-name-length-max',
+;;    `bmkp-count-multi-mods-as-one-flag', `bmkp-crosshairs-flag',
+;;    `bmkp-default-bookmark-name',
+;;    `bmkp-default-handlers-for-file-types',
+;;    `bmkp-desktop-no-save-vars',
+;;    `bmkp-guess-default-handler-for-file-flag',
+;;    `bmkp-handle-region-function', `bmkp-incremental-filter-delay',
+;;    `bmkp-last-as-first-bookmark-file',
+;;    `bmkp-menu-popup-max-length', `bmkp-other-window-pop-to-flag',
+;;    `bmkp-prompt-for-tags-flag', `bmkp-region-search-size',
+;;    `bmkp-save-new-location-flag',
+;;    `bmkp-sequence-jump-display-function',
+;;    `bmkp-show-end-of-region', `bmkp-sort-comparer',
+;;    `bmkp-su-or-sudo-regexp', `bmkp-tags-for-completion',
+;;    `bmkp-temporary-bookmarking-mode',
+;;    `bmkp-temporary-bookmarking-mode-hook',
+;;    `bmkp-temporary-bookmarking-mode-lighter',
+;;    `bmkp-this-file/buffer-cycle-sort-comparer', `bmkp-use-region',
+;;    `bmkp-w3m-allow-multi-tabs'.
+;;
+;;  Non-interactive functions defined here:
+;;
+;;    `bmkext-jump-gnus', `bmkext-jump-man', `bmkext-jump-w3m',
+;;    `bmkext-jump-woman', `bmkp-all-exif-data',
+;;    `bmkp-all-tags-alist-only', `bmkp-all-tags-regexp-alist-only',
+;;    `bmkp-alpha-cp', `bmkp-alpha-p', `bmkp-annotated-alist-only',
+;;    `bmkp-autofile-alist-only', `bmkp-autofile-all-tags-alist-only',
+;;    `bmkp-autofile-all-tags-regexp-alist-only',
+;;    `bmkp-autofile-bookmark-p',
+;;    `bmkp-autofile-some-tags-alist-only',
+;;    `bmkp-autofile-some-tags-regexp-alist-only',
+;;    `bmkp-autoname-bookmark-function-default',
+;;    `bmkp-autonamed-alist-only',
+;;    `bmkp-autonamed-bookmark-for-buffer-p',
+;;    `bmkp-autonamed-bookmark-p',
+;;    `bmkp-autonamed-this-buffer-alist-only',
+;;    `bmkp-autonamed-this-buffer-bookmark-p',
+;;    `bmkp-bookmark-creation-cp', `bmkp-bookmark-data-from-record',
+;;    `bmkp-bookmark-description', `bmkp-bookmark-last-access-cp',
+;;    `bmkp-bookmark-file-alist-only',
+;;    `bmkp-bookmark-list-alist-only',
+;;    `bmkp-bookmark-file-bookmark-p',
+;;    `bmkp-bookmark-list-bookmark-p', `bmkp-bookmark-name-member',
+;;    `bmkp-bookmark-record-from-name', `bmkp-bookmark-type',
+;;    `bmkp-buffer-last-access-cp', `bmkp-buffer-names',
+;;    `bmkp-compilation-file+line-at', `bmkp-completing-read-1',
+;;    `bmkp-completing-read-buffer-name',
+;;    `bmkp-completing-read-file-name', `bmkp-completing-read-lax',
+;;    `bmkp-cp-not', `bmkp-create-variable-list-bookmark',
+;;    `bmkp-current-bookmark-list-state', `bmkp-current-sort-order',
+;;    `bmkp-cycle-1', `bmkp-default-bookmark-file',
+;;    `bmkp-default-bookmark-name', `bmkp-default-handler-for-file',
+;;    `bmkp-default-handler-user', `bmkp-delete-autonamed-no-confirm',
+;;    `bmkp-delete-autonamed-this-buffer-no-confirm',
+;;    `bmkp-delete-bookmark-name-from-list',
+;;    `bmkp-delete-temporary-no-confirm', `bmkp-desktop-alist-only',
+;;    `bmkp-desktop-bookmark-p', `bmkp-desktop-kill',
+;;    `bmkp-dired-alist-only', `bmkp-dired-bookmark-p',
+;;    `bmkp-dired-subdirs', `bmkp-dired-this-dir-alist-only',
+;;    `bmkp-dired-this-dir-bookmark-p',
+;;    `bmkp-dired-wildcards-bookmark-p',
+;;    `bmkp-edit-bookmark-record-mode',
+;;    `bmkp-edit-bookmark-records-mode', `bmkp-edit-tags-mode',
+;;    `bmkp-end-position-post-context',
+;;    `bmkp-end-position-pre-context', `bmkp-every',
+;;    `bmkp-file-alist-only', `bmkp-file-all-tags-alist-only',
+;;    `bmkp-file-all-tags-regexp-alist-only', `bmkp-file-alpha-cp',
+;;    `bmkp-file-attribute-0-cp', `bmkp-file-attribute-1-cp',
+;;    `bmkp-file-attribute-2-cp', `bmkp-file-attribute-3-cp',
+;;    `bmkp-file-attribute-4-cp', `bmkp-file-attribute-5-cp',
+;;    `bmkp-file-attribute-6-cp', `bmkp-file-attribute-7-cp',
+;;    `bmkp-file-attribute-8-cp', `bmkp-file-attribute-9-cp',
+;;    `bmkp-file-attribute-10-cp', `bmkp-file-attribute-11-cp',
+;;    `bmkp-file-bookmark-p', `bmkp-file-names', `bmkp-file-remote-p',
+;;    `bmkp-file-some-tags-alist-only',
+;;    `bmkp-file-some-tags-regexp-alist-only',
+;;    `bmkp-file-this-dir-alist-only',
+;;    `bmkp-file-this-dir-all-tags-alist-only',
+;;    `bmkp-file-this-dir-all-tags-regexp-alist-only',
+;;    `bmkp-file-this-dir-bookmark-p',
+;;    `bmkp-file-this-dir-some-tags-alist-only',
+;;    `bmkp-file-this-dir-some-tags-regexp-alist-only',
+;;    `bmkp-flagged-bookmark-p', `bmkp-flagged-cp', `bmkp-float-time',
+;;    `bmkp-full-tag', `bmkp-function-bookmark-p',
+;;    `bmkp-get-autofile-bookmark', `bmkp-get-bookmark-in-alist',
+;;    `bmkp-get-buffer-name', `bmkp-get-end-position',
+;;    `bmkp-get-tag-value', `bmkp-get-tags', `bmkp-get-visit-time',
+;;    `bmkp-get-visits-count', `bmkp-gnus-alist-only',
+;;    `bmkp-gnus-bookmark-p', `bmkp-gnus-cp', `bmkp-goto-position',
+;;    `bmkp-handle-region-default', `bmkp-handler-cp',
+;;    `bmkp-handler-pred', `bmkp-has-tag-p', `bmkp-image-alist-only',
+;;    `bmkp-image-bookmark-p', `bmkp-info-alist-only',
+;;    `bmkp-info-bookmark-p', `bmkp-info-cp', `bmkp-isearch-bookmarks'
+;;    (Emacs 23+), `bmkp-isearch-bookmarks-regexp' (Emacs 23+),
+;;    `bmkp-isearch-next-bookmark-buffer' (Emacs 23+), `bmkp-jump-1',
+;;    `bmkp-jump-bookmark-file', `bmkp-jump-bookmark-list',
+;;    `bmkp-jump-desktop', `bmkp-jump-dired', `bmkp-jump-function',
+;;    `bmkp-jump-gnus', `bmkp-jump-man', `bmkp-jump-sequence',
+;;    `bmkp-jump-url-browse', `bmkp-jump-variable-list',
+;;    `bmkp-jump-w3m', `bmkp-jump-w3m-new-session',
+;;    `bmkp-jump-w3m-only-one-tab', `bmkp-jump-woman',
+;;    `bmkp-last-specific-buffer-alist-only',
+;;    `bmkp-last-specific-buffer-p',
+;;    `bmkp-last-specific-file-alist-only',
+;;    `bmkp-last-specific-file-p', `bmkp-line-number-at-pos',
+;;    `bmkp-list-position', `bmkp-local-directory-bookmark-p',
+;;    `bmkp-local-file-accessed-more-recently-cp',
+;;    `bmkp-local-file-alist-only', `bmkp-local-file-bookmark-p',
+;;    `bmkp-local-file-size-cp', `bmkp-local-file-type-cp',
+;;    `bmkp-local-file-updated-more-recently-cp',
+;;    `bmkp-make-bookmark-file-record',
+;;    `bmkp-make-bookmark-list-record', `bmkp-make-desktop-record',
+;;    `bmkp-make-dired-record', `bmkp-make-gnus-record',
+;;    `bmkp-make-man-record', `bmkp-make-plain-predicate',
+;;    `bmkp-make-record-for-target-file',
+;;    `bmkp-make-url-browse-record', `bmkp-make-variable-list-record',
+;;    `bmkp-make-w3m-record', `bmkp-make-woman-record' (Emacs 21+),
+;;    `bmkp-man-alist-only', `bmkp-man-bookmark-p',
+;;    `bmkp-marked-bookmark-p', `bmkp-marked-bookmarks-only',
+;;    `bmkp-marked-cp', `bmkp-maybe-save-bookmarks',
+;;    `bmkp-modified-bookmark-p', `bmkp-modified-cp',
+;;    `bmkp-msg-about-sort-order', `bmkp-multi-sort',
+;;    `bmkp-names-same-bookmark-p', `bmkp-non-autonamed-alist-only',
+;;    `bmkp-non-file-alist-only', `bmkp-non-file-bookmark-p',
+;;    `bmkp-not-near-other-auto-idle-bmks', `bmkp-omitted-alist-only',
+;;    `bmkp-orphaned-file-alist-only',
+;;    `bmkp-orphaned-file-bookmark-p',
+;;    `bmkp-orphaned-local-file-alist-only',
+;;    `bmkp-orphaned-local-file-bookmark-p',
+;;    `bmkp-orphaned-remote-file-alist-only',
+;;    `bmkp-orphaned-remote-file-bookmark-p',
+;;    `bmkp-position-after-whitespace',
+;;    `bmkp-position-before-whitespace', `bmkp-position-cp',
+;;    `bmkp-position-post-context',
+;;    `bmkp-position-post-context-region',
+;;    `bmkp-position-pre-context', `bmkp-position-pre-context-region',
+;;    `bmkp-printable-p', `bmkp-printable-vars+vals',
+;;    `bmkp-read-bookmark-file-name', `bmkp-read-tag-completing',
+;;    `bmkp-read-tags', `bmkp-read-tags-completing',
+;;    `bmkp-read-variable', `bmkp-read-variables-completing',
+;;    `bmkp-record-visit', `bmkp-refresh-latest-bookmark-list',
+;;    `bmkp-refresh-menu-list', `bmkp-refresh/rebuild-menu-list.',
+;;    `bmkp-regexp-filtered-annotation-alist-only',
+;;    `bmkp-regexp-filtered-bookmark-name-alist-only',
+;;    `bmkp-regexp-filtered-file-name-alist-only',
+;;    `bmkp-regexp-filtered-tags-alist-only',
+;;    `bmkp-region-alist-only', `bmkp-region-bookmark-p',
+;;    `bmkp-remote-file-alist-only', `bmkp-remote-file-bookmark-p',
+;;    `bmkp-remove-dups', `bmkp-remove-if', `bmkp-remove-if-not',
+;;    `bmkp-remove-omitted',
+;;    `bmkp-rename-for-marked-and-omitted-lists',
+;;    `bmkp-repeat-command', `bmkp-replace-existing-bookmark',
+;;    `bmkp-root-or-sudo-logged-p', `bmkp-same-creation-time-p',
+;;    `bmkp-same-file-p', `bmkp-save-new-region-location',
+;;    `bmkp-select-buffer-other-window', `bmkp-sequence-bookmark-p',
+;;    `bmkp-set-tag-value-for-bookmarks', `bmkp-set-union',
+;;    `bmkp-some', `bmkp-some-marked-p', `bmkp-some-tags-alist-only',
+;;    `bmkp-some-tags-regexp-alist-only', `bmkp-some-unmarked-p'
+;;    `bmkp-sort-omit', `bmkp-sound-jump',
+;;    `bmkp-specific-buffers-alist-only',
+;;    `bmkp-specific-files-alist-only',
+;;    `bmkp-string-less-case-fold-p', `bmkp-tagged-bookmark-p',
+;;    `bmkp-tagged-cp', `bmkp-tag-name', `bmkp-tags-in-bookmark-file',
+;;    `bmkp-tags-list', `bmkp-temporary-alist-only',
+;;    `bmkp-temporary-bookmark-p', `bmkp-this-buffer-alist-only',
+;;    `bmkp-this-buffer-p', `bmkp-this-file-alist-only',
+;;    `bmkp-this-file/buffer-alist-only', `bmkp-this-file-p',
+;;    `bmkp-unmarked-bookmarks-only', `bmkp-upcase',
+;;    `bmkp-update-autonamed-bookmark', `bmkp-url-alist-only',
+;;    `bmkp-url-bookmark-p', `bmkp-url-browse-alist-only',
+;;    `bmkp-url-browse-bookmark-p', `bmkp-url-cp',
+;;    `bmkp-variable-list-alist-only',
+;;    `bmkp-variable-list-bookmark-p', `bmkp-visited-more-cp',
+;;    `bmkp-w3m-alist-only', `bmkp-w3m-bookmark-p', `bmkp-w3m-cp',
+;;    `bmkp-w3m-set-new-buffer-name'.
+;;
+;;  Internal variables defined here:
+;;
+;;    `bmkp-after-set-hook', `bmkp-autofile-history',
+;;    `bmkp-auto-idle-bookmark-mode-timer',
+;;    `bmkp-auto-idle-bookmarks', `bmkp-autonamed-history',
+;;    `bmkp-autotemp-all-when-set-p', `bmkp-bookmark-file-history',
+;;    `bmkp-bookmark-list-history', `bmkp-current-bookmark-file',
+;;    `bmkp-current-nav-bookmark', `bmkp-desktop-history',
+;;    `bmkp-dired-history', `bmkp-edit-bookmark-record-mode-map',
+;;    `bmkp-edit-bookmark-records-mode-map',
+;;    `bmkp-edit-bookmark-records-number', `bmkp-edit-tags-mode-map',
+;;    `bmkp-file-bookmark-handlers', `bmkp-file-history',
+;;    `bmkp-gnus-history', `bmkp-image-history', `bmkp-info-history',
+;;    `bmkp-isearch-bookmarks' (Emacs 23+),
+;;    `bmkp-jump-display-function', `bmkp-jump-other-window-map',
+;;    `bmkp-last-bmenu-state-file', `bmkp-last-bookmark-file',
+;;    `bmkp-last-save-flag-value', `bmkp-last-specific-buffer',
+;;    `bmkp-last-specific-file', `bmkp-latest-bookmark-alist',
+;;    `bmkp-local-file-history', `bmkp-man-history',
+;;    `bmkp-modified-bookmarks', `bmkp-nav-alist',
+;;    `bmkp-non-file-filename', `bmkp-non-file-history',
+;;    `bmkp-region-history', `bmkp-remote-file-history',
+;;    `bmkp-return-buffer', `bmkp-reverse-multi-sort-p',
+;;    `bmkp-reverse-sort-p', `bmkp-sorted-alist',
+;;    `bmkp-specific-buffers-history', `bmkp-specific-files-history',
+;;    `bmkp-tag-history', `bmkp-tags-alist', `bmkp-temporary-history',
+;;    `bmkp-types-alist', `bmkp-url-history',
+;;    `bmkp-use-w32-browser-p', `bmkp-variable-list-history',
+;;    `bmkp-version-number', `bmkp-w3m-history'.
+;;
+;;
+;;  ***** NOTE: The following commands defined in `bookmark.el'
+;;              have been REDEFINED HERE:
+;;
+;;    `bookmark-delete', `bookmark-edit-annotation',
+;;    `bookmark-edit-annotation-mode', `bookmark-insert',
+;;    `bookmark-insert-location', `bookmark-jump',
+;;    `bookmark-jump-other-window', `bookmark-load',
+;;    `bookmark-relocate', `bookmark-rename', `bookmark-save',
+;;    `bookmark-send-edited-annotation', `bookmark-set',
+;;    `bookmark-set-name', `bookmark-yank-word'.
+;;
+;;
+;;  ***** NOTE: The following non-interactive functions defined in
+;;              `bookmark.el' have been REDEFINED HERE:
+;;
+;;    `bookmark--jump-via', `bookmark-alist-from-buffer',
+;;    `bookmark-all-names', `bookmark-completing-read',
+;;    `bookmark-default-handler', `bookmark-exit-hook-internal',
+;;    `bookmark-get-bookmark', `bookmark-get-bookmark-record' (Emacs
+;;    20-22), `bookmark-get-handler' (Emacs 20-22),
+;;    `bookmark-handle-bookmark', `bookmark-jump-noselect' (Emacs
+;;    20-22), `bookmark-location', `bookmark-make-record',
+;;    `bookmark-make-record-default',
+;;    `bookmark-maybe-load-default-file', `bookmark-prop-get' (Emacs
+;;    20-22), `bookmark-prop-set', `bookmark-show-annotation',
+;;    `bookmark-show-all-annotations', `bookmark-store' (Emacs 20-22),
+;;    `bookmark-write-file'.
+;;
+;;
+;;  ***** NOTE: The following variables defined in `bookmark.el'
+;;              have been REDEFINED HERE:
+;;
+;;    `bookmark-alist' (doc string only),
+;;    `bookmark-make-record-function' (Emacs 20-22),
+;;    `bookmarks-already-loaded' (doc string only).
+;;
+;;
+;;  ***** NOTE: The following functions defined in `info.el'
+;;              have been REDEFINED HERE:
+;;
+;;    `Info-bookmark-jump' (Emacs 20-22), `Info-bookmark-make-record'
+;;    (Emacs 20-22).
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(unless (fboundp 'file-remote-p) (require 'ffap)) ;; ffap-file-remote-p
+(eval-when-compile (require 'gnus)) ;; mail-header-id (really in `nnheader.el')
+(eval-when-compile (require 'gnus-sum)) ;; gnus-summary-article-header
+(eval-when-compile (require 'cl)) ;; case, multiple-value-bind, typecase (plus, for Emacs 20: dolist)
+
+(require 'thingatpt+ nil t) ;; (no error if not found):
+;; region-or-non-nil-symbol-name-nearest-point, symbol-nearest-point
+
+(require 'bookmark)
+;; bookmark-alist, bookmark-alist-modification-count, bookmark-annotation-name,
+;; bookmark-automatically-show-annotations, bookmark-bmenu-bookmark,
+;; bookmark-bmenu-surreptitiously-rebuild-list, bookmark-buffer-file-name, bookmark-buffer-name,
+;; bookmark-completion-ignore-case, bookmark-current-bookmark, bookmark-default-file,
+;; bookmark-edit-annotation, bookmark-get-annotation, bookmark-get-bookmark-record, bookmark-get-filename,
+;; bookmark-get-front-context-string, bookmark-get-handler, bookmark-get-position,
+;; bookmark-get-rear-context-string, bookmark-import-new-list, bookmark-insert-file-format-version-stamp,
+;; bookmark-kill-line, bookmark-make-record, bookmark-maybe-historicize-string,
+;; bookmark-maybe-upgrade-file-format, bookmark-menu-popup-paned-menu, bookmark-name-from-full-record,
+;; bookmark-name-from-record, bookmark-popup-menu-and-apply-function, bookmark-prop-get, bookmark-save-flag,
+;; bookmark-search-size, bookmark-set-annotation, bookmark-set-filename, bookmark-set-position,
+;; bookmark-time-to-save-p, bookmark-use-annotations, bookmark-version-control, bookmark-yank-point
+
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+       (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+      ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+       (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;;    The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+
+(require 'bookmark+-mac)
+;; bmkp-define-cycle-command, bmkp-define-file-sort-predicate, bmkp-menu-bar-make-toggle,
+;; bmkp-replace-regexp-in-string, bmkp-with-output-to-plain-temp-buffer
+
+(put 'bmkp-with-output-to-plain-temp-buffer 'common-lisp-indent-function '(4 &body))
+
+(eval-when-compile (require 'bookmark+-bmu))
+;; bmkp-bmenu-before-hide-marked-alist,
+;; bmkp-bmenu-before-hide-unmarked-alist, bmkp-bmenu-commands-file,
+;; bmkp-bmenu-filter-function, bmkp-bmenu-filter-pattern,
+;; bmkp-bmenu-first-time-p, bmkp-flagged-bookmarks, bmkp-bmenu-goto-bookmark-named,
+;; bmkp-bmenu-marked-bookmarks, bmkp-bmenu-omitted-bookmarks,
+;; bmkp-bmenu-refresh-menu-list, bmkp-bmenu-show-all,
+;; bmkp-bmenu-state-file, bmkp-bmenu-title,
+;; bmkp-maybe-unpropertize-bookmark-names, bmkp-sort-orders-alist,
+;; bookmark-bmenu-toggle-filenames
+
+
+;; (eval-when-compile (require 'bookmark+-lit nil t))
+;; bmkp-light-bookmark, bmkp-light-bookmarks, bmkp-light-this-buffer
+
+
+;; For the redefinition of `bookmark-get-bookmark'.
+(provide 'bookmark+-1)                  ; Ensure this library is loaded before we compile it.
+(require 'bookmark+-1)                  ; So be sure to put this library in your `load-path' before
+                                        ; trying to byte-compile it.
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Quiet the byte-compiler
+
+(defvar bmkp-auto-light-when-set)       ; Defined in `bookmark+-lit.el'.
+(defvar bmkp-auto-light-when-jump)      ; Defined in `bookmark+-lit.el'.
+(defvar bmkp-light-priorities)          ; Defined in `bookmark+-lit.el'.
+(defvar bmkp-temporary-bookmarking-mode)
+(defvar bmkp-global-auto-idle-bookmark-mode)
+(defvar bookmark-current-point)         ; Defined in `bookmark.el', but not in Emacs 23+.
+(defvar bookmark-edit-annotation-text-func) ; Defined in `bookmark.el'.
+(defvar bookmark-read-annotation-text-func) ; Defined in `bookmark.el', but not in Emacs 23+.
+(defvar bookmark-make-record-function)  ; Defined in `bookmark.el'.
+(defvar desktop-basefilename)           ; Defined in `desktop.el' (Emacs < 22).
+(defvar desktop-base-file-name)         ; Defined in `desktop.el'.
+(defvar desktop-buffer-args-list)       ; Defined in `desktop.el'.
+(defvar desktop-delay-hook)             ; Defined in `desktop.el'.
+(defvar desktop-dirname)                ; Defined in `desktop.el'.
+(defvar desktop-file-modtime)           ; Defined in `desktop.el'.
+(defvar desktop-globals-to-save)        ; Defined in `desktop.el'.
+(defvar desktop-save-mode)              ; Defined in `desktop.el'.
+(defvar desktop-save)                   ; Defined in `desktop.el'.
+(defvar dired-actual-switches)          ; Defined in `dired.el'.
+(defvar dired-buffers)                  ; Defined in `dired.el'.
+(defvar dired-directory)                ; Defined in `dired.el'.
+(defvar dired-guess-shell-case-fold-search) ; Defined in `dired-x.el'.
+(defvar dired-subdir-alist)             ; Defined in `dired.el'.
+(defvar gnus-article-current)           ; Defined in `gnus-sum.el'.
+(defvar Info-current-node)              ; Defined in `info.el'.
+(defvar Info-current-file)              ; Defined in `info.el'.
+(defvar Man-arguments)                  ; Defined in `man.el'.
+(defvar read-file-name-completion-ignore-case) ; Emacs 23+.
+(defvar last-repeatable-command)        ; Defined in `repeat.el'.
+(defvar w3m-current-title)              ; Defined in `w3m.el'.
+(defvar w3m-current-url)                ; Defined in `w3m.el'.
+(defvar w3m-mode-map)                   ; Defined in `w3m.el'.
+(defvar wide-n-restrictions)            ; Defined in `wide-n.el'.
+(defvar woman-last-file-name)           ; Defined in `woman.el'.
+;;(@* "User Options (Customizable)")
+;;; User Options (Customizable) --------------------------------------
+
+;;;###autoload
+(defcustom bmkp-auto-idle-bookmark-min-distance 1000
+  "*Minimum number of chars between automatic bookmark positions."
+  :type '(choice
+          (const   :tag "No minumum distance" nil)
+          (integer :tag "At least this many chars" :value 1000))
+  :group 'bookmark-plus)
+
+;; Emacs 20 only.
+;;;###autoload
+(unless (fboundp 'define-minor-mode)
+  (defcustom bmkp-auto-idle-bookmark-mode nil
+    "*Non-nil means that bookmarks are created periodically automatically.
+Setting this variable directly does not take effect;
+use either \\[customize] or command `bmkp-auto-idle-bookmark-mode'."
+    :set        (lambda (symbol value) (bmkp-auto-idle-bookmark-mode (if value 1 -1)))
+    :initialize 'custom-initialize-default
+    :type 'boolean :group 'bookmark-plus :require 'bookmark+))
+
+;;;###autoload
+(defcustom bmkp-auto-idle-bookmark-mode-delay 60
+  "*Number of seconds delay before automatically setting a bookmark.
+Such automatic bookmarking is controlled by
+`bmkp-temporary-bookmarking-mode'."
+  :type 'integer :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-auto-idle-bookmark-mode-lighter " Auto-Bmk"
+  "*Lighter for `bmkp-auto-idle-bookmark-mode'.
+This string shows in the mode line when `bmkp-auto-idle-bookmark-mode'
+is enabled.  Set this to nil or \"\" if you do not want any lighter."
+  :type 'string :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-auto-idle-bookmark-mode-set-function #'bmkp-set-autonamed-bookmark-at-line
+  "*Function used to set an automatic bookmark.
+Used by `bmkp-temporary-bookmarking-mode'.
+The default value, `bmkp-set-autonamed-bookmark-at-line', sets an
+autonamed bookmark at the start of the current line.  To bookmark the
+current position, so you can have more than one automatic bookmark per
+line, use `bmkp-set-autonamed-bookmark' instead."
+  :type 'function :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-autoname-bookmark-function 'bmkp-autoname-bookmark-function-default
+  "*Function to automatically name a bookmark at point (cursor position).
+It should accept a buffer position as its (first) argument.
+The name returned should match the application of
+`bmkp-autoname-format' to the buffer name."
+  :type 'function :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-autoname-format (if (> emacs-major-version 21) "^[0-9]\\{9\\} %s" "^[0-9]+ %s")
+  "*Format string to match an autonamed bookmark name.
+It must have a single `%s' to accept the buffer name."
+  :type 'string :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-autotemp-bookmark-predicates '(bmkp-autonamed-bookmark-p
+                                               bmkp-autonamed-this-buffer-bookmark-p)
+  "*Predicates for bookmarks to be set (created) as temporary bookmarks.
+Each is typically a type predicate, but it can be any function that
+accepts as its (first) argument a bookmark or bookmark name.
+These are the predefined type predicates:
+ `bmkp-autofile-bookmark-p', `bmkp-autonamed-bookmark-for-buffer-p',
+ `bmkp-autonamed-bookmark-p', `bmkp-autonamed-this-buffer-bookmark-p',
+ `bmkp-bookmark-file-bookmark-p', `bmkp-bookmark-list-bookmark-p',
+ `bmkp-desktop-bookmark-p', `bmkp-dired-bookmark-p',
+ `bmkp-dired-this-dir-bookmark-p', `bmkp-file-bookmark-p',
+ `bmkp-file-remote-p', `bmkp-file-this-dir-bookmark-p',
+ `bmkp-function-bookmark-p', `bmkp-gnus-bookmark-p',
+ `bmkp-image-bookmark-p', `bmkp-info-bookmark-p',
+ `bmkp-last-specific-buffer-p', `bmkp-last-specific-file-p',
+ `bmkp-local-directory-bookmark-p', `bmkp-local-file-bookmark-p',
+ `bmkp-man-bookmark-p', `bmkp-non-file-bookmark-p',
+ `bmkp-region-bookmark-p', `bmkp-remote-file-bookmark-p',
+ `bmkp-sequence-bookmark-p', `bmkp-this-buffer-p', `bmkp-this-file-p',
+ `bmkp-url-bookmark-p', `bmkp-url-browse-bookmark-p',
+ `bmkp-variable-list-bookmark-p', `bmkp-w3m-bookmark-p'"
+  :type '(repeat symbol) :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-bookmark-name-length-max 70
+  "*Max number of chars for default name for a bookmark with a region."
+  :type 'integer :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-count-multi-mods-as-one-flag t
+  "*Non-nil means count multiple modifications as one.
+
+This is for `bookmark-alist-modification-count'.  Non-nil means that
+when you invoke a command that acts on multiple bookmarks or acts in
+multiple ways on one bookmark, all of changes together count as only
+one moficication.  That can prevent automatic saving of your bookmark
+file during the sequence of modifications, so that when the command is
+done you can choose not to save (i.e., to quit) if you like."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-crosshairs-flag (> emacs-major-version 21)
+  "*Non-nil means highlight with crosshairs when you visit a bookmark.
+The highlighting is temporary - until your next action.
+You need library `crosshairs.el' for this feature, and you need Emacs
+22 or later.
+
+NOTE: Crosshairs highlighting is shown in the buffer that is current
+after jumping.  If the bookmarked jumped to does not really have an
+associated buffer, for example a bookmark with a handler such as
+`w32-browser' that just invokes a separate, non-Emacs program, then
+the current buffer after jumping will be the buffer before jumping.
+
+If you use this option in Lisp code, you will want to add/remove
+`bmkp-crosshairs-highlight' to/from `bookmark-after-jump-hook'."
+  :set (lambda (sym new-val)
+         (custom-set-default sym new-val)
+         (if (and bmkp-crosshairs-flag (> emacs-major-version 21)
+                  (condition-case nil (require 'crosshairs nil t) (error nil)))
+             (add-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)
+           (remove-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)))
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-default-bookmark-name 'highlighted
+  "*Default bookmark name preference.
+In `*Bookmark List*' use the name of the current line's bookmark.
+Otherwise, if `bookmark+-lit.el' is not loaded then use the name of
+ the last-used bookmark in the current file.
+
+Otherwise, use this option to determine the default, by preferring one
+of the following, if available:
+
+* a highlighted bookmark at point
+* the last-used bookmark in the current file"
+  :type '(choice
+          (const :tag "Highlighted bookmark at point"    highlighted)
+          (const :tag "Last used bookmark in same file"  last-used))
+  :group 'bookmark-plus)
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias)            ; Emacs 22+
+  (defvaralias 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types)
+  (make-obsolete-variable 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types
+                          "2012-02-27"))
+
+;;;###autoload
+(defcustom bmkp-default-handlers-for-file-types
+  (and (require 'dired-x)               ; It in turn requires `dired-aux.el'
+       (eval-when-compile (when (< emacs-major-version 21) (require 'cl))) ;; `dolist', for Emacs 20
+       (let ((assns  ()))
+         (dolist (shell-assn  dired-guess-shell-alist-user)
+           (push (cons (car shell-assn)
+                       `(lambda (bmk)
+                         (dired-run-shell-command
+                          (dired-shell-stuff-it ,(cadr shell-assn) (list (bookmark-get-filename bmk))
+                           nil nil))))
+                 assns))
+         assns))
+  "*File associations for bookmark handlers used for indirect bookmarks.
+Each element of the alist is (REGEXP . COMMAND).
+REGEXP matches a file name.
+COMMAND is a sexp that evaluates to either a shell command (a string)
+ or an Emacs function (a symbol or a lambda form).  The shell command
+ or Lisp function must accept a file-name argument.
+
+Example value:
+
+ ((\"\\\\.pdf$\"   . \"AcroRd32.exe\") ; Adobe Acrobat Reader
+  (\"\\\\.ps$\"    . \"gsview32.exe\") ; Ghostview (PostScript viewer)
+  (\"\\\\.html?$\" . browse-url)       ; Use Lisp function `browse-url'
+  (\"\\\\.doc$\"   . w32-browser))     ; Use Lisp function `w32-browser'
+
+When you change this option using Customize, if you want to use a
+literal string as COMMAND then you must double-quote the text:
+\"...\".  (But do not use double-quotes for the REGEXP.)  If you want
+to use a symbol as COMMAND, just type the symbol name (no quotes).
+
+This option is used by `bmkp-default-handler-for-file' to determine
+the default `file-handler' property for a given file bookmark.  If a
+given file name does not match this option, and if
+`bmkp-guess-default-handler-for-file-flag' is non-nil, then
+`bmkp-default-handler-for-file' tries to guess a shell command to use
+in the default handler.  For that it uses `dired-guess-default' and
+\(Emacs 23+ only) mailcap entries, in that order."
+  :type '(alist :key-type
+          regexp :value-type
+          (sexp :tag "Shell command (string) or Emacs function (symbol or lambda form)"))
+  :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-desktop-no-save-vars '(search-ring regexp-search-ring kill-ring)
+  "*List of variables not to save when creating a desktop bookmark.
+They are removed from `desktop-globals-to-save' for the duration of
+the save (only)."
+  :type '(repeat (variable :tag "Variable")) :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-handle-region-function 'bmkp-handle-region-default
+  "*Function to handle a bookmarked region."
+  :type 'function :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-incremental-filter-delay (if (boundp 'bookmark-search-delay)
+                                             bookmark-search-delay
+                                           0.2)
+  "*Seconds to wait before updating display when filtering bookmarks."
+  :type 'number :group 'bookmark-plus)
+
+;; Remove autoload cookie to avoid (void-variable bookmark-default-file) ;;;###autoload
+(defcustom bmkp-last-as-first-bookmark-file bookmark-default-file
+  "*Whether to use the last-used bookmark file as the first used.
+If nil then Emacs always uses the value of `bookmark-default-file' as
+the initial bookmark file, in any given session.
+
+If non-nil, Emacs uses the last bookmark file you used, in the last
+Emacs session.  If none was recorded then it uses
+`bookmark-default-file'.  The particular non-nil value must be a an
+absolute file name \(possibly containing `~') - it is not expanded).
+
+NOTE: A non-nil option value is overwritten by Bookmark+, so that it
+becomes the last-used bookmark file.  A nil value is never
+overwritten."
+  :type '(choice
+          (const :tag "Use `bookmark-default-file' as initial bookmark file" nil)
+          (file  :tag "Use last-used bookmark file as initial bookmark file"
+           :value "~/.emacs.bmk"))
+  :group 'bookmark)
+
+;;;###autoload
+(defcustom bmkp-menu-popup-max-length 20
+  "*Max number of bookmarks for `bookmark-completing-read' to use a menu.
+When choosing a bookmark from a list of bookmarks using
+`bookmark-completing-read', this controls whether to use a menu or
+minibuffer input with completion.
+If t, then always use a menu.
+If nil, then never use a menu.
+If an integer, then use a menu only if there are fewer bookmark
+ choices than the value."
+  :type '(choice
+          (integer :tag "Use a menu if there are fewer bookmark choices than this" 20)
+          (const   :tag "Always use a menu to choose a bookmark" t)
+          (const   :tag "Never use a menu to choose a bookmark" nil))
+  :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-new-bookmark-default-names
+  (let ((fns  '((lambda () (let ((ff  (function-called-at-point)))
+                             (and ff  (symbolp ff)  (symbol-name ff)))))))
+    (when (fboundp 'region-or-non-nil-symbol-name-nearest-point) ; Defined in `thingatpt+.el'.
+      (push 'region-or-non-nil-symbol-name-nearest-point fns)))
+  "Functions to produce the default name for a new bookmark.
+\(The default name for an *existing* bookmark is obtained using
+`bmkp-default-bookmark-name'.)
+
+The option value is a list of functions that do not require an
+argument and return a string (or nil).  They are invoked in order to
+produce the default names.
+
+The following names are also provided, after the names described
+above: The value of variable `bookmark-current-bookmark' and the
+return value of function `bookmark-buffer-name', in that order.
+
+These latter names are the defaults provided by vanilla Emacs
+`bookmark.el', so if you want the vanilla behavior then set the option
+value to nil.
+
+For non-interactive use of a default bookmark name, and for Emacs
+prior to Emacs 23 even for interactive use, only the first default
+name is used.
+
+Some functions you might want to use in the option value:
+
+ * `region-or-non-nil-symbol-name-nearest-point'
+ * (lambda () (let ((ff  (function-called-at-point)))
+      (and (symbolp ff) (symbol-name ff))))
+ * (lambda () (let ((vv  (variable-at-point))) ; `variable-at-point'
+      (and (symbolp vv) (symbol-name vv))))    ;  returns 0 if no var
+ * `word-at-point'
+ * (lambda () (let ((ss  (symbol-at-point)))
+     (and ss (symbol-name ss))))
+
+The first of these is defined in library `thingatpt+.el'.  It returns
+the text in the region, if it is active and not empty.  Otherwise it
+returns the name of the (non-`nil') symbol nearest point, within
+maximum search distances `near-point-x-distance' (left and right) and
+`near-point-y-distance' (up and down)."
+  :type '(repeat function) :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-other-window-pop-to-flag t
+  "*Non-nil means other-window bookmark jumping uses `pop-to-buffer'.
+Use nil if you want the vanilla Emacs behavior, which uses
+`switch-to-buffer-other-window'.  That creates a new window even if
+there is already another window showing the buffer."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-prompt-for-tags-flag nil
+  "*Non-nil means `bookmark-set' prompts for tags (when called interactively)."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-region-search-size 40
+  "*Same as `bookmark-search-size', but specialized for bookmark regions."
+  :type 'integer :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-save-new-location-flag t
+  "*Non-nil means save automatically relocated bookmarks.
+If nil, then the new bookmark location is visited, but it is not saved
+as part of the bookmark definition."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-sequence-jump-display-function 'pop-to-buffer
+  "*Function used to display the bookmarks in a bookmark sequence."
+  :type 'function :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-show-end-of-region t
+  "*Show end of region with `exchange-point-and-mark' when activating a region.
+If nil show only beginning of region."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-sort-comparer '((bmkp-info-cp bmkp-gnus-cp bmkp-url-cp bmkp-local-file-type-cp)
+                                bmkp-alpha-p) ; This corresponds to `s k'.
+  ;; $$$$$$ An alternative default value: `bmkp-alpha-p', which corresponds to `s n'.
+  "*Predicate or predicates for sorting (comparing) bookmarks.
+This defines the default sort for bookmarks in the bookmark list.
+
+Various sorting commands, such as \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-sort-by-bookmark-visit-frequency]', change the value of this
+option dynamically (but they do not save the changed value).
+
+The value must be one of the following:
+
+* nil, meaning do not sort
+
+* a predicate that takes two bookmarks as args
+
+* a list of the form ((PRED...) FINAL-PRED), where each PRED and
+  FINAL-PRED are predicates that take two bookmarks as args
+
+If the value is a list of predicates, then each PRED is tried in turn
+until one returns a non-nil value.  In that case, the result is the
+car of that value.  If no non-nil value is returned by any PRED, then
+FINAL-PRED is used and its value is the result.
+
+Each PRED should return `(t)' for true, `(nil)' for false, or nil for
+undecided.  A nil value means that the next PRED decides (or
+FINAL-PRED, if there is no next PRED).
+
+Thus, a PRED is a special kind of predicate that indicates either a
+boolean value (as a singleton list) or \"I cannot decide - let the
+next guy else decide\".  (Essentially, each PRED is a hook function
+that is run using `run-hook-with-args-until-success'.)
+
+Examples:
+
+ nil           - No sorting.
+
+ string-lessp  - Single predicate that returns nil or non-nil.
+
+ ((p1 p2))     - Two predicates `p1' and `p2', which each return
+                 (t) for true, (nil) for false, or nil for undecided.
+
+ ((p1 p2) string-lessp)
+               - Same as previous, except if both `p1' and `p2' return
+                 nil, then the return value of `string-lessp' is used.
+
+Note that these two values are generally equivalent, in terms of their
+effect (*):
+
+ ((p1 p2))
+ ((p1) p2-plain) where p2-plain is (bmkp-make-plain-predicate p2)
+
+Likewise, these three values generally act equivalently (*):
+
+ ((p1))
+ (() p1-plain)
+ p1-plain        where p1-plain is (bmkp-make-plain-predicate p1)
+
+The PRED form lets you easily combine predicates: use `p1' unless it
+cannot decide, in which case try `p2', and so on.  The value ((p2 p1))
+tries the predicates in the opposite order: first `p2', then `p1' if
+`p2' returns nil.
+
+Using a single predicate or FINAL-PRED makes it easy to reuse an
+existing predicate that returns nil or non-nil.
+
+You can also convert a PRED-type predicate (which returns (t), (nil),
+or nil) into an ordinary predicate, by using function
+`bmkp-make-plain-predicate'.  That lets you reuse elsewhere, as
+ordinary predicates, any PRED-type predicates you define.
+
+For example, this defines a plain predicate to compare by URL:
+ (defalias 'bmkp-url-p (bmkp-make-plain-predicate 'bmkp-url-cp))
+
+Note: As a convention, predefined Bookmark+ PRED-type predicate names
+have the suffix `-cp' (for \"component predicate\") instead of `-p'.
+
+--
+* If you use `\\[bmkp-reverse-multi-sort-order]', then there is a difference in \
+behavior between
+
+   (a) using a plain predicate as FINAL-PRED and
+   (b) using the analogous PRED-type predicate (and no FINAL-PRED).
+
+  In the latter case, `\\[bmkp-reverse-multi-sort-order]' affects when the predicate \
+is tried and
+  its return value.  See `bmkp-reverse-multi-sort-order'."
+  :type '(choice
+          (const    :tag "None (do not sort)" nil)
+          (function :tag "Sorting Predicate")
+          (list     :tag "Sorting Multi-Predicate"
+           (repeat (function :tag "Component Predicate"))
+           (choice
+            (const    :tag "None" nil)
+            (function :tag "Final Predicate"))))
+  :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-su-or-sudo-regexp "\\(/su:\\|/sudo:\\)"
+  "*Regexp to recognize `su' or `sudo' Tramp bookmarks."
+  :type 'regexp :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-tags-for-completion 'current
+  "*List of strings used as tags for completion (not an alist).
+The tags can be specified here individually or taken from (a) the
+current bookmark list or (b) one or more bookmark files or both.
+
+\(In Emacs 20 and 21, you cannot choose (b) when customizing, but if
+\(b) was chosen using a later Emacs version then the option value can
+still be used in Emacs 20 and 21.)
+
+If a relative file name is specified for a bookmark file then the
+current value of `default-directory' is used to find the file."
+  :type (if (> emacs-major-version 21)
+            '(choice
+              (const :tag "From current bookmarks only" current)
+              (list :tag "From current bookmarks and other sources"
+               (const  :tag "" current)
+               (repeat :inline t :tag "Additional sources or specific tags"
+                (choice
+                 (string :tag "Specific tag")
+                 (cons   :tag "All tags from a bookmark file"
+                  (const :tag "" bmkfile) (file :must-match t)))))
+              (repeat :tag "Choose sources or specific tags"
+               (choice
+                (string :tag "Specific tag")
+                (cons   :tag "All tags from a bookmark file"
+                 (const :tag "" bmkfile) (file :must-match t)))))
+          ;; A bug in Emacs 20-21 means we must sacrifice the user choice of current plus other sources.
+          '(choice
+            (const :tag "From current bookmarks only" current)
+            (repeat :tag "Choose sources or specific tags" ; A 2nd Emacs 20-21 bug ignores `:tag' for menu.
+             (choice
+              (string :tag "Specific tag")
+              (cons   :tag "All tags from a bookmark file"
+               (const :tag "" bmkfile) (file :must-match t))))))
+  :group 'bookmark-plus)
+
+;; Emacs 20 only.
+(unless (fboundp 'define-minor-mode)
+  (defcustom bmkp-temporary-bookmarking-mode nil
+    "*Non-nil means that bookmarks are temporary (not recorded on disk).
+Setting this variable directly does not take effect;
+use either \\[customize] or command `bmkp-temporary-bookmarking-mode'."
+    :set (lambda (symbol value) (bmkp-temporary-bookmarking-mode (if value 1 -1)))
+    :initialize 'custom-initialize-default
+    :type 'boolean :group 'bookmark-plus :require 'bookmark+))
+
+;;;###autoload
+(defcustom bmkp-temporary-bookmarking-mode-hook ()
+  "*Functions run after entering and exiting temporary-bookmarking mode."
+  :type 'hook :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-this-file/buffer-cycle-sort-comparer '((bmkp-position-cp))
+  "*`bmkp-sort-comparer' value for cycling this-file/buffer bookmarks.
+Use bookmarks for the currently visited file or (non-file) buffer.
+Some values you might want to use: ((bmkp-position-cp)),
+ ((bmkp-bookmark-creation-cp)), ((bmkp-visited-more-cp)).
+See `bmkp-sort-comparer'."
+  :type '(choice
+          (const    :tag "None (do not sort)" nil)
+          (function :tag "Sorting Predicate")
+          (list     :tag "Sorting Multi-Predicate"
+           (repeat (function :tag "Component Predicate"))
+           (choice
+            (const    :tag "None" nil)
+            (function :tag "Final Predicate"))))
+  :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-guess-default-handler-for-file-flag nil
+  "*Non-nil means guess the default handler when creating a file bookmark.
+This is ignored if a handler can be found using option
+`bmkp-default-handlers-for-file-types'.  Otherwise, this is used by
+function `bmkp-default-handler-for-file' to determine the default
+handler for a given file."
+  :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-temporary-bookmarking-mode-lighter " Temp-Bmk"
+  "*Lighter for `bmkp-temporary-bookmarking-mode'.
+This string shows in the mode line when `bmkp-temporary-bookmarking-mode'
+is enabled.  Set this to nil or \"\" if you do not want any lighter."
+  :type 'string :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-use-region t
+  "*Non-nil means visiting a bookmark activates its recorded region."
+  :type '(choice
+          (const :tag "Activate bookmark region (except during cycling)"  t)
+          (const :tag "Do not activate bookmark region"                   nil)
+          (const :tag "Activate bookmark region even during cycling"      cycling-too))
+  :group 'bookmark-plus)
+
+;;;###autoload
+(defcustom bmkp-w3m-allow-multi-tabs t
+  "*Non-nil means jump to W3M bookmarks in a new session."
+  :type 'boolean :group 'bookmark-plus)
+;;(@* "Internal Variables")
+;;; Internal Variables -----------------------------------------------
+
+(defconst bmkp-non-file-filename "   - no file -"
+  "Name to use for `filename' entry, for non-file bookmarks.")
+
+(defconst bmkp-types-alist '(("autofile"         . bmkp-autofile-history)
+                             ("autonamed"        . bmkp-autonamed-history)
+                             ("bookmark-file"    . bmkp-bookmark-file-history)
+                             ("bookmark-list"    . bmkp-bookmark-list-history)
+                             ("desktop"          . bmkp-desktop-history)
+                             ("dired"            . bmkp-dired-history)
+                             ("dired-this-dir"   . bmkp-dired-history)
+                             ("file"             . bmkp-file-history)
+                             ("file-this-dir"    . bmkp-file-history)
+                             ("gnus"             . bmkp-gnus-history)
+                             ("image"            . bmkp-image-history)
+                             ("info"             . bmkp-info-history)
+                             ("local-file"       . bmkp-local-file-history)
+                             ("man"              . bmkp-man-history)
+                             ("non-file"         . bmkp-non-file-history)
+                             ("region"           . bmkp-region-history)
+                             ("remote-file"      . bmkp-remote-file-history)
+                             ("specific-buffers" . bmkp-specific-buffers-history)
+                             ("specific-files"   . bmkp-specific-files-history)
+                             ("temporary"        . bmkp-temporary-history)
+                             ("url"              . bmkp-url-history)
+                             ("variable-list"    . bmkp-variable-list-history))
+  "Alist of bookmark types used by `bmkp-jump-to-type'.
+Keys are bookmark type names.  Values are corresponding history variables.")
+
+(defvar bmkp-autofile-history ()         "History for autofile bookmarks.")
+(defvar bmkp-autonamed-history ()        "History for autonamed bookmarks.")
+(defvar bmkp-bookmark-file-history ()    "History for bookmark-file bookmarks.")
+(defvar bmkp-bookmark-list-history ()    "History for bookmark-list bookmarks.")
+(defvar bmkp-desktop-history ()          "History for desktop bookmarks.")
+(defvar bmkp-dired-history ()            "History for Dired bookmarks.")
+(defvar bmkp-file-history ()             "History for file bookmarks.")
+(defvar bmkp-gnus-history ()             "History for Gnus bookmarks.")
+(defvar bmkp-image-history ()            "History for image-file bookmarks.")
+(defvar bmkp-info-history ()             "History for Info bookmarks.")
+(defvar bmkp-last-bmenu-state-file nil   "Last value of option `bmkp-bmenu-state-file'.")
+(defvar bmkp-local-file-history ()       "History for local-file bookmarks.")
+(defvar bmkp-man-history ()              "History for `man'-page bookmarks.")
+(defvar bmkp-non-file-history ()         "History for buffer (non-file) bookmarks.")
+(defvar bmkp-region-history ()           "History for bookmarks that activate the region.")
+(defvar bmkp-remote-file-history ()      "History for remote-file bookmarks.")
+(defvar bmkp-specific-buffers-history () "History for specific-buffers bookmarks.")
+(defvar bmkp-specific-files-history ()   "History for specific-files bookmarks.")
+(defvar bmkp-temporary-history ()        "History for temporary bookmarks.")
+(defvar bmkp-url-history ()              "History for URL bookmarks.")
+(defvar bmkp-variable-list-history ()    "History for variable-list bookmarks.")
+(defvar bmkp-w3m-history ()              "History for W3M bookmarks.")
+
+(defvar bmkp-after-set-hook nil "Hook run after `bookmark-set' sets a bookmark.")
+
+(defvar bmkp-auto-idle-bookmarks ()
+  "Alist of bookmarks that were created automatically during this session.")
+
+(defvar bmkp-auto-idle-bookmark-mode-timer nil
+  "Timer for `bmkp-auto-idle-bookmark-mode'.
+This variable is buffer-local, which means that there is a separate
+timer for each buffer where automatic bookmarking is enabled.
+
+NOTE: For Emacs 20, the variable is not buffer-local, by default.  To
+make it so, do this:
+
+  (make-variable-buffer-local 'bmkp-auto-idle-bookmark-mode-timer)")
+
+(unless (< emacs-major-version 21) (make-variable-buffer-local 'bmkp-auto-idle-bookmark-mode-timer))
+
+
+(defvar bmkp-autotemp-all-when-set-p nil "Non-nil means make any bookmark temporary whenever it is set.")
+
+;;; $$$$$$ No - don't bother.
+;;; (defconst bmkp-bookmark-modifier-functions  '(bookmark-prop-set bmkp-replace-existing-bookmark
+;;;                                               bookmark-set-name bookmark-store)
+;;;   "List of functions that modify bookmarks.
+;;; Used to mark modified, unsaved bookmarks, in `*Bookmark List*'.
+;;; Should not include any function that calls another in the list.")
+
+(defvar bmkp-copied-tags ()
+  "List of tags copied from a bookmark, for pasting to other bookmarks.")
+
+(defvar bmkp-current-bookmark-file bookmark-default-file
+  "Current bookmark file.
+When you start Emacs, this is initialized according to
+`bmkp-last-as-first-bookmark-file'.
+
+When you load bookmarks using `\\[bmkp-switch-bookmark-file-create]', this is set to the file you
+load.  When you save bookmarks using `bookmark-save' with no prefix
+arg, they are saved to this file.
+
+Loading a bookmark file does not change the value of
+`bookmark-default-file', but it might change the value of
+`bmkp-last-as-first-bookmark-file' (which see).  The value of
+`bookmark-default-file' is never changed, except by your
+customizations.")
+
+(defvar bmkp-edit-bookmark-orig-record nil
+  "Record of bookmark being edited.")
+
+(defvar bmkp-file-bookmark-handlers '(bmkp-jump-dired image-bookmark-jump)
+  "List of functions that handle file or directory bookmarks.
+This is used to determine `bmkp-file-bookmark-p'.")
+
+(defvar bmkp-last-bookmark-file bookmark-default-file
+  "Last bookmark file used in this session (or default bookmark file).
+This is a backup for `bmkp-current-bookmark-file'.")
+
+(defvar bmkp-current-nav-bookmark nil "Current bookmark for navigation.")
+
+(defvar bmkp-jump-display-function nil "Function used currently to display a bookmark.")
+
+(defvar bmkp-last-specific-buffer ""
+  "Name of buffer used by `bmkp-last-specific-buffer-p'.")
+
+(defvar bmkp-last-specific-file ""
+  "(Absolute) file name used by `bmkp-last-specific-file-p'.")
+
+(defvar bmkp-modified-bookmarks ()
+  "Alist of bookmarks that have been modified and not saved.")
+
+(defvar bmkp-nav-alist () "Current bookmark alist used for navigation.")
+
+(defvar bmkp-return-buffer nil "Name of buffer to return to.")
+
+(defvar bmkp-reverse-sort-p nil "Non-nil means the sort direction is reversed.")
+
+(defvar bmkp-reverse-multi-sort-p nil
+  "Non-nil means the truth values returned by predicates are complemented.
+This changes the order of the sorting groups, but it does not in
+general reverse that order.  The order within each group is unchanged
+\(not reversed).")
+
+(defvar bmkp-use-w32-browser-p nil
+  "Non-nil means use `w32-browser' in the default bookmark handler.
+That is, use the default Windows application for the bookmarked file.
+This has no effect if function `w32-browser' is not defined.")
+
+(defvar bmkp-latest-bookmark-alist () "Copy of `bookmark-alist' as last filtered.")
+
+(defvar bmkp-last-save-flag-value nil "Last value of option `bookmark-save-flag'.")
+
+(defvar bmkp-sorted-alist ()
+  "Copy of current bookmark alist, as sorted for buffer `*Bookmark List*'.
+Has the same structure as `bookmark-alist'.")
+
+(defvar bmkp-tag-history () "History of tags read from the user.")
+
+(defvar bmkp-tags-alist ()
+  "Alist of all bookmark tags, per option `bmkp-tags-for-completion'.
+Each entry is a full tag: a cons whose car is a tag name, a string.
+This is set by function `bmkp-tags-list'.
+Use that function to update the value.")
+
+
+;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
+;;
+;; Doc string does not say that the file that was loaded is `bookmark-default-file'.
+;;
+(defvar bookmarks-already-loaded nil
+  "Non-nil means some bookmarks have been loaded during this Emacs session.")
+
+
+;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
+;;
+;; Doc string reflects `Bookmark+' enhancements.
+;;
+(put 'bookmark-alist 'variable-documentation
+     "Association list of bookmarks and their records.
+Bookmark functions update the value automatically.
+You probably do not want to change the value yourself.
+
+The value is an alist with entries of the form
+ (BOOKMARK-NAME . PARAM-ALIST)
+or the deprecated form (BOOKMARK-NAME PARAM-ALIST).
+
+ BOOKMARK-NAME is the name you gave to the bookmark when creating it.
+ PARAM-ALIST is an alist of bookmark information.  The order of the
+  entries in PARAM-ALIST is not important.  The possible entries are
+  described below.  An entry with a key but null value means the entry
+  is not used.
+
+Bookmarks created using vanilla Emacs (`bookmark.el'):
+
+ (filename . FILENAME)
+ (location . LOCATION)
+ (position . POS)
+ (front-context-string . STR-AFTER-POS)
+ (rear-context-string  . STR-BEFORE-POS)
+ (handler . HANDLER)
+ (annotation . ANNOTATION)
+
+ FILENAME names the bookmarked file.
+ LOCATION names the bookmarked file, URL, or other place (Emacs 23+).
+  FILENAME or LOCATION is what is shown in the bookmark list
+  (`C-x r l') when you use `M-t'.
+ POS is the bookmarked buffer position (position in the file).
+ STR-AFTER-POS is buffer text that immediately follows POS.
+ STR-BEFORE-POS is buffer text that immediately precedes POS.
+ ANNOTATION is a string that you can provide to identify the bookmark.
+  See options `bookmark-use-annotations' and
+  `bookmark-automatically-show-annotations'.
+ HANDLER is a function that provides the bookmark-jump behavior
+  for a specific kind of bookmark.  This is the case for Info
+  bookmarks, for instance (starting with Emacs 23).
+
+Bookmarks created using Bookmark+ are the same as for vanilla Emacs,
+except for the following differences.
+
+1. Visit information is recorded, using entries `visits' and `time':
+
+ (visits . NUMBER-OF-VISITS)
+ (time . TIME-LAST-VISITED)
+
+ NUMBER-OF-VISITS is a whole-number counter.
+
+ TIME-LAST-VISITED is an Emacs time representation, such as is
+ returned by function `current-time'.
+
+2. The buffer name is recorded, using entry `buffer-name'.  It need
+not be associated with a file.
+
+3. If no file is associated with the bookmark, then FILENAME is
+   `   - no file -'.
+
+4. Bookmarks can be tagged by users.  The tag information is recorded
+using entry `tags':
+
+ (tags . TAGS-ALIST)
+
+ TAGS-ALIST is an alist with string keys.
+
+5. A bookmark can be simply a wrapper for a file, in which case it has
+entry `file-handler' instead of `handler'.  When you \"jump\" to such
+a bookmark, the `file-handler' function or shell-command is applied to
+the `filename' entry.  Any `handler' entry present is ignored, as are
+entries such as `position'.  It is only the target file that is
+important.
+
+6. Bookmarks can have individual highlighting, provided by users.
+This overrides any default highlighting.
+
+ (lighting . HIGHLIGHTING)
+
+ HIGHLIGHTING is a property list that contain any of these keyword
+ pairs:
+
+   `:style' - Highlighting style.  Cdrs of `bmkp-light-styles-alist'
+              entries are the possible values.
+   `:face'  - Highlighting face, a symbol.
+   `:when'  - A sexp to be evaluated.  Return value of `:no-light'
+              means do not highlight.
+
+7. The following additional entries are used to record region
+information.  When a region is bookmarked, POS represents the region
+start position.
+
+ (end-position . END-POS)
+ (front-context-region-string . STR-BEFORE-END-POS)
+ (rear-context-region-string . STR-AFTER-END-POS))
+
+ END-POS is the region end position.
+ STR-BEFORE-END-POS is buffer text that precedes END-POS.
+ STR-AFTER-END-POS is buffer text that follows END-POS.
+
+The two context region strings are non-nil only when a region is
+bookmarked.
+
+ NOTE: The relative locations of `front-context-region-string' and
+ `rear-context-region-string' are reversed from those of
+ `front-context-string' and `rear-context-string'.  For example,
+ `front-context-string' is the text that *follows* `position', but
+ `front-context-region-string' *precedes* `end-position'.
+
+8. The following additional entries are used for a Dired bookmark.
+
+ (dired-marked . MARKED-FILES)
+ (dired-switches . SWITCHES)
+
+ MARKED-FILES is the list of files that were marked.
+ SWITCHES is the string of `dired-listing-switches'.
+
+9. The following additional entries are used for a Gnus bookmark.
+
+ (group . GNUS-GROUP-NAME)
+ (article . GNUS-ARTICLE-NUMBER)
+ (message-id . GNUS-MESSAGE-ID)
+
+ GNUS-GROUP-NAME is the name of a Gnus group.
+ GNUS-ARTICLE-NUMBER is the number of a Gnus article.
+ GNUS-MESSAGE-ID is the identifier of a Gnus message.
+
+10. For a URL bookmark, FILENAME or LOCATION is a URL.
+
+11. A sequence bookmark has this additional entry:
+
+ (sequence . COMPONENT-BOOKMARKS)
+
+ COMPONENT-BOOKMARKS is the list of component bookmark names.
+
+12. A function bookmark has this additional entry, which records the
+FUNCTION:
+
+ (function . FUNCTION)
+
+13. A bookmark-list bookmark has this additional entry, which records
+the state of buffer `*Bookmark List*' at the time it is created:
+
+ (bookmark-list . STATE)
+
+ STATE records the sort order, filter function, omit list, and title.")
+;;(@* "Compatibility Code for Older Emacs Versions")
+;;; Compatibility Code for Older Emacs Versions ----------------------
+
+(when (< emacs-major-version 23)
+
+  ;; These definitions are for Emacs versions prior to Emacs 23.
+  ;; They are the same as the vanilla Emacs 23+ definitions, except as noted.
+  ;; They let older versions of Emacs handle bookmarks created with Emacs 23.
+  ;; (Emacs < 23 also needs a compatible `bookmark-make-record' version,
+  ;; but I redefine it for all versions, in any case.)
+
+  (defun Info-bookmark-make-record ()
+    "Create an Info bookmark record."
+    `(,Info-current-node
+      ,@(bookmark-make-record-default 'no-file)
+      (filename . ,Info-current-file)
+      (info-node . ,Info-current-node)
+      (handler . Info-bookmark-jump)))
+
+  ;; Requires `info.el' explicitly (not autoloaded for `Info-find-node'.
+  (defun Info-bookmark-jump (bookmark)
+    "Jump to Info bookmark BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+    (require 'info)
+    ;; Implements the `handler' for the record type returned by `Info-bookmark-make-record'.
+    (let* ((file       (bookmark-prop-get bookmark 'filename))
+           (info-node  (bookmark-prop-get bookmark 'info-node))
+           (buf        (save-window-excursion ; VANILLA EMACS FIXME: doesn't work with frames!
+                         (Info-find-node file info-node) (current-buffer))))
+      ;; Use `bookmark-default-handler' to move to appropriate location within Info node.
+      (bookmark-default-handler
+       `("" (buffer . ,buf) . ,(bmkp-bookmark-data-from-record bookmark)))))
+
+  (add-hook 'Info-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+                                            'Info-bookmark-make-record)))
+
+  (defvar bookmark-make-record-function 'bookmark-make-record-default
+    "Function called with no arguments, to create a bookmark record.
+It should return the new record, which should be a cons cell of the
+form (NAME . ALIST) or just ALIST, where ALIST is as described in
+`bookmark-alist'.  If it cannot construct the record, then it should
+raise an error.
+
+NAME is a string that names the new bookmark.  NAME can be nil, in
+which case a default name is used.
+
+ALIST can contain an entry (handler . FUNCTION) which sets the handler
+to FUNCTION, which is then used instead of `bookmark-default-handler'.
+FUNCTION must accept the same arguments as `bookmark-default-handler'.
+
+You can set this variable buffer-locally to enable bookmarking of
+locations that should be treated specially, such as Info nodes, news
+posts, images, pdf documents, etc.")
+
+  (defun bookmark-prop-get (bookmark prop)
+    "Return property PROP of BOOKMARK, or nil if no such property.
+BOOKMARK is a bookmark name or a bookmark record."
+    (cdr (assq prop (bmkp-bookmark-data-from-record bookmark))))
+
+  (defun bookmark-get-handler (bookmark)
+    "Return the `handler' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+    (bookmark-prop-get bookmark 'handler))
+
+  (defun bookmark-jump-noselect (bookmark)
+    "Return the location recorded for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+The return value has the form (BUFFER . POINT), where BUFFER is a
+buffer and POINT is the location within BUFFER."
+    (save-excursion (bookmark-handle-bookmark bookmark) (cons (current-buffer) (point)))))
+
+(when (< emacs-major-version 22)
+
+  ;; These definitions are for Emacs versions prior to Emacs 22.
+  ;; They are the same as the vanilla Emacs 22+ definitions, except as noted.
+
+;;;   ;; Bookmark+ doesn't use this, but `bookmark.el' still does.  Who has a slow `baud-rate' now?
+;;;   (defun bookmark-maybe-message (fmt &rest args)
+;;;     "Apply `message' to FMT and ARGS, but only if the display is fast enough."
+;;;     (when (>= baud-rate 9600) (apply 'message fmt args)))
+
+  ;; Emacs 22+ just uses `bookmark-jump-other-window' for the menu also.
+  (defun bmkp-menu-jump-other-window (event)
+    "Jump to BOOKMARK (a point in some file) in another window.
+See `bookmark-jump-other-window'."
+    (interactive "e")
+    (bookmark-popup-menu-and-apply-function 'bookmark-jump-other-window
+                                            "Jump to Bookmark (Other Window)" event)))
+;;(@* "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
+;;; Core Replacements (`bookmark-*' except `bookmark-bmenu-*') -------
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Doc string does not mention `bookmark-alist': does NOT test whether BOOKMARK is in `bookmark-alist'.
+;;
+(defun bookmark-get-bookmark-record (bookmark)
+  "Return the data part of BOOKMARK, that is, all but the name.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a bookmark name then it is looked up in `bookmark-alist'.
+If it is a record then it is NOT looked up (need not belong)."
+  (let ((data  (cdr (bookmark-get-bookmark bookmark))))
+    ;; A bookmark record is either (NAME ALIST) or (NAME . ALIST).
+    (if (and (null (cdr data)) (consp (caar data)))
+        (car data)
+      data)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. If BOOKMARK is a bookmark-name string that has non-nil property `bmkp-full-record'
+;;    then look up the bookmark that is the value of that property in `bookmark-alist', and
+;;    if found return it.
+;; 2. Handle the should-not-happen case of non-string, non-cons.
+;; 3. Document NOERROR in doc string.
+;;
+(defun bookmark-get-bookmark (bookmark &optional noerror)
+  "Return the full bookmark (record) that corresponds to BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil optional arg NOERROR means return nil if BOOKMARK is not a
+valid bookmark.  If NOERROR is nil then raise an error in this case.
+
+If BOOKMARK is a bookmark name instead of a full bookmark then return
+what `bmkp-bookmark-record-from-name' (with no MEMP check) returns.
+
+This function is like `bmkp-get-bookmark-in-alist', except that
+`bmkp-get-bookmark-in-alist' always tests whether BOOKMARK is in
+`bookmark-alist', whether BOOKMARK is a string (a bookmark name) or a
+full bookmark.  `bmkp-get-bookmark-in-alist' is thus a real test for
+bookmark existence.  Use `bookmark-get-bookmark' only when you do NOT
+want to look up the bookmark in `bookmark-alist'."
+  (cond ((consp bookmark) bookmark)     ; No test of alist membership.
+        ((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror)) ; No MEMP check.
+        (t (and (not noerror) (error "Invalid bookmark: `%s'" bookmark)))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Use option `bmkp-new-bookmark-default-names' to obtain the default name.
+;;
+(defun bookmark-make-record ()
+  "Return a new bookmark record (NAME . ALIST) for the current location.
+Start with `bookmark-make-record-function'.  If it does not provide a
+bookmark name, then use option `bmkp-new-bookmark-default-names' to
+provide it.  If that does not provide it then use
+`bookmark-current-bookmark' or `bookmark-buffer-name', in that order."
+  (let ((record  (funcall bookmark-make-record-function))
+        defname)
+    (if (stringp (car record))
+        record
+      (when (car record) (push nil record))
+      (setq defname  (catch 'bookmark-make-record
+                       (dolist (fn  bmkp-new-bookmark-default-names)
+                         (when (functionp fn) ; Be sure it is defined and is a function.
+                           (let ((val  (funcall fn)))
+                             (when (and (stringp val) (not (string= "" val)))
+                               (throw 'bookmark-make-record val)))))
+                       (or bookmark-current-bookmark (bookmark-buffer-name))))
+      (when (and defname  (not (stringp defname)))  (setq defname  (format "%s" defname))) ; Just in case.
+      (setcar record  defname)
+      record)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Update the bookmark name also, not just the data, for an existing bookmark.
+;; 2. Use `bmkp-get-bookmark-in-alist' to test whether the bookmark already exists.
+;; 3. Put full bookmark record on bookmark name (inside record) as property `bmkp-full-record'.
+;; 4. Use `bmkp-maybe-save-bookmarks'.
+;; 5. Add the bookmark to `bmkp-modified-bookmarks', and to `bmkp-auto-idle-bookmarks' if appropriate.
+;; 6. Return the bookmark.
+;;
+(defun bookmark-store (bookmark-name data no-overwrite &optional no-msg-p)
+  "Store the bookmark named BOOKMARK-NAME, giving it DATA.
+Return the new bookmark.
+
+DATA is the bookmark record without its name, i.e., what
+`bmkp-bookmark-data-from-record' returns.
+
+If NO-OVERWRITE is non-nil and bookmark BOOKMARK-NAME already exists
+in the current bookmark list (`bookmark-alist') then record the new
+bookmark but do not discard the old one.
+
+The check for existence uses `bmkp-get-bookmark-in-alist'.
+
+Note: In spite of the function name, like all functions that define or
+change bookmarks, this function does not necessarily save your
+bookmark file.  Saving the file depends on `bookmark-save-flag'.
+
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+  (bookmark-maybe-load-default-file)
+  (let ((bname  (copy-sequence bookmark-name))
+        bmk)
+    (unless (featurep 'xemacs)
+      ;; XEmacs's `set-text-properties' does not work on free-standing strings, apparently.
+      (set-text-properties 0 (length bname) () bname))
+    (if (or no-overwrite  (not (setq bmk  (bmkp-get-bookmark-in-alist bname 'NOERROR))))
+        (push (setq bmk  (cons bname data)) bookmark-alist) ; Add new bookmark.
+      (bookmark-set-name bmk bname)     ; Overwrite existing bookmark.
+      (setcdr bmk data))
+    ;; Put the full bookmark on its name as property `bmkp-full-record'.
+    ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+    ;; If it needs to be stripped, that will be done when saving.
+    (put-text-property 0 (length bname) 'bmkp-full-record bmk bname)
+    (bmkp-maybe-save-bookmarks)
+    ;; These two are the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+    (unless (memq bmk bmkp-modified-bookmarks)
+      (setq bmkp-modified-bookmarks  (cons bmk bmkp-modified-bookmarks)))
+    (when (and (boundp 'bmkp-setting-auto-idle-bmk-p)
+               (not (memq bmk bmkp-auto-idle-bookmarks)))
+      (setq bmkp-auto-idle-bookmarks  (cons bmk bmkp-auto-idle-bookmarks)))
+    (setq bookmark-current-bookmark  bname)
+    (bmkp-refresh/rebuild-menu-list bmk no-msg-p)
+    bmk))                               ; Return the bookmark.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; BUG fix: Need bookmark arg in `interactive' spec.
+;;
+;;;###autoload
+(defun bookmark-edit-annotation-mode (bookmark)
+  "Mode for editing the annotation of bookmark BOOKMARK.
+When you have finished composing, type \\[bookmark-send-annotation].
+BOOKMARK is a bookmark name or a bookmark record.
+
+\\{bookmark-edit-annotation-mode-map}"
+  (interactive (list (bookmark-completing-read "Edit annotation of bookmark"
+                                               (bmkp-default-bookmark-name)
+                                               (bmkp-annotated-alist-only))))
+  (kill-all-local-variables)
+  (make-local-variable 'bookmark-annotation-name)
+  (setq bookmark-annotation-name  bookmark)
+  (use-local-map bookmark-edit-annotation-mode-map)
+  (setq major-mode  'bookmark-edit-annotation-mode
+        mode-name  "Edit Bookmark Annotation")
+  (insert (funcall (if (boundp 'bookmark-edit-annotation-text-func)
+                       bookmark-edit-annotation-text-func
+                     bookmark-read-annotation-text-func)
+                   bookmark))
+  (let ((annotation  (bookmark-get-annotation bookmark)))
+    (if (and annotation (not (string-equal annotation "")))
+       (insert annotation)))
+  (if (fboundp 'run-mode-hooks)
+      (run-mode-hooks 'text-mode-hook)
+    (run-hooks 'text-mode-hook)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. BUG fix: Put point back where it was (on the bookmark just annotated).
+;; 2. Refresh menu list, to pick up the `a' marker.
+;; 3. Make sure it's the annotation buffer that gets killed.
+;; 4. Delete window also, if `misc-cmds.el' loaded.
+;;
+;;;###autoload
+(defun bookmark-send-edited-annotation ()
+  "Use buffer contents as annotation for a bookmark.
+Lines beginning with `#' are ignored."
+  (interactive)
+  (unless (eq major-mode 'bookmark-edit-annotation-mode)
+    (error "Not in bookmark-edit-annotation-mode"))
+  (goto-char (point-min))
+  (while (< (point) (point-max))
+    (if (looking-at "^#")
+        (bookmark-kill-line t)
+      (forward-line 1)))
+  (let ((annotation      (buffer-substring-no-properties (point-min) (point-max)))
+       (bookmark        bookmark-annotation-name)
+        (annotation-buf  (current-buffer)))
+    (bookmark-set-annotation bookmark annotation)
+    (setq bookmark-alist-modification-count  (1+ bookmark-alist-modification-count))
+    (bmkp-refresh/rebuild-menu-list bookmark) ; So display `a' and `*' markers (updated).
+    (if (fboundp 'kill-buffer-and-its-windows)
+        (kill-buffer-and-its-windows annotation-buf) ; Defined in `misc-cmds.el'.
+      (kill-buffer annotation-buf))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Added `interactive' spec.
+;;
+;;;###autoload
+(defun bookmark-edit-annotation (bookmark)
+  "Pop up a buffer for editing bookmark BOOKMARK's annotation.
+BOOKMARK is a bookmark name or a bookmark record."
+  (interactive (list (bookmark-completing-read "Edit annotation of bookmark"
+                                               (bmkp-default-bookmark-name)
+                                               (bmkp-annotated-alist-only))))
+  (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
+  (bookmark-edit-annotation-mode bookmark))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Added optional arg ALIST.
+;;
+(defun bookmark-all-names (&optional alist)
+  "Return a list of all bookmark names.
+The names are those of the bookmarks in ALIST or, if nil,
+`bookmark-alist'."
+  (bookmark-maybe-load-default-file)
+  (mapcar (lambda (bmk) (bmkp-bookmark-name-from-record bmk)) (or alist bookmark-alist)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional args ALIST, PRED, and HIST.
+;; 2. Define using helper function `bmkp-completing-read-1',
+;;    which binds `icicle-delete-candidate-object' to (essentially) `bookmark-delete'.
+;;
+(defun bookmark-completing-read (prompt &optional default alist pred hist)
+  "Read a bookmark name, prompting with PROMPT.
+PROMPT is automatically suffixed with \": \", so do not include that.
+
+Optional arg DEFAULT is a string to return if the user enters the
+ empty string.
+The alist argument used for completion is ALIST or, if nil,
+ `bookmark-alist'.
+Optional arg PRED is a predicate used for completion.
+Optional arg HIST is a history variable for completion.  Default is
+ `bookmark-history'.
+
+If you access this function from a menu, then, depending on the value
+of option `bmkp-menu-popup-max-length' and the number of
+bookmarks in ALIST, you choose the bookmark using a menu or using
+completion.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+  (bmkp-completing-read-1 prompt default alist pred hist nil))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Handles also regions and non-file buffers.
+;; 2. Do not use NO-CONTEXT or POSN if < Emacs 24.
+;;
+(defun bookmark-make-record-default (&optional no-file no-context position visits)
+  "Return the record describing the location of a new bookmark.
+Point must be where the bookmark is to be set.
+
+Non-nil NO-FILE means return only the subset of the record that
+ pertains to the location within the buffer (not also the file name).
+
+Non-nil NO-CONTEXT means do not include the front and rear context
+strings in the record enough.
+
+Non-nil POSITION means record it, not point, as the `position' entry.
+
+Non-nil VISITS means record it as the `visits' entry."
+  (let* ((dired-p  (and (boundp 'dired-buffers) (car (rassq (current-buffer) dired-buffers))))
+         (buf      (buffer-name))
+         (ctime    (current-time))
+
+         ;; Begin `let*' dependencies.
+         (regionp  (and transient-mark-mode mark-active (not (eq (mark) (point)))))
+         (beg      (if regionp (region-beginning) (or position (point))))
+         (end      (if regionp (region-end) (point)))
+         (fcs      (if regionp
+                       (bmkp-position-post-context-region beg end)
+                     (bmkp-position-post-context beg)))
+         (rcs      (if regionp
+                       (bmkp-position-pre-context-region beg)
+                     (bmkp-position-pre-context beg)))
+         (fcrs     (when regionp (bmkp-end-position-pre-context beg end)))
+         (ecrs     (when regionp (bmkp-end-position-post-context end))))
+    `(,@(unless no-file
+                `((filename . ,(cond ((buffer-file-name) (bookmark-buffer-file-name))
+                                     (dired-p            nil)
+                                     (t                  bmkp-non-file-filename)))))
+      (buffer-name . ,buf)
+      ,@(unless (and no-context (> emacs-major-version 23))
+                `((front-context-string . ,fcs)))
+      ,@(unless (and no-context (> emacs-major-version 23))
+                `((rear-context-string . ,rcs)))
+      ,@(unless (and no-context (> emacs-major-version 23))
+                `((front-context-region-string . ,fcrs)))
+      ,@(unless (and no-context (> emacs-major-version 23))
+                `((rear-context-region-string  . ,ecrs)))
+      (visits       . ,(or visits 0))
+      (time         . ,ctime)
+      (created      . ,ctime)
+      (position     . ,beg)
+      (end-position . ,end))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Put full bookmark record on bookmark name (inside record), as property `bmkp-full-record'.
+;;
+(defun bookmark-alist-from-buffer ()
+  "Read and return a bookmark list (in any format) from the current buffer.
+Put the full bookmark record on the bookmark name (in the record), as
+a text property.  Point is irrelevant and unaffected."
+  (let ((bmks  (save-excursion
+                 (goto-char (point-min))
+                 (if (search-forward bookmark-end-of-version-stamp-marker nil t)
+                     (read (current-buffer))
+                   ;; Else we're dealing with format version 0
+                   (if (search-forward "(" nil t)
+                       (progn (forward-char -1) (read (current-buffer)))
+                     ;; Else no hope of getting information here.
+                     (error "Buffer is not in bookmark-list format"))))))
+    ;; Put full bookmark on bookmark names as property `bmkp-full-record'.
+    ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+    ;; If property needs to be stripped, that will be done when saving.
+    (dolist (bmk  bmks)
+      (put-text-property 0 (length (car bmk)) 'bmkp-full-record bmk (car bmk)))
+    bmks))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `bookmark-make-record'.
+;; 2. Use special default prompts for active region, W3M, and Gnus.
+;; 3. Use function `bmkp-new-bookmark-default-names', in addition to the name that
+;;    `bookmark-make-record' comes up with, as the list of default values.
+;; 4. Use `bmkp-completing-read-lax', choosing from current buffer's bookmarks.
+;; 5. Numeric prefix arg (diff from plain): all bookmarks as completion candidates.
+;; 6. Prompt for tags if `bmkp-prompt-for-tags-flag' is non-nil.
+;; 7. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-set'.
+;; 8. Make bookmark temporary, if `bmkp-autotemp-bookmark-predicates' says to.
+;; 9. Run `bmkp-after-set-hook'.
+;;
+;;;###autoload
+(defun bookmark-set (&optional name parg interactivep) ; `C-x r m', `C-x p c m'
+  "Set a bookmark named NAME, then run `bmkp-after-set-hook'.
+If the region is active (`transient-mark-mode') and nonempty, then
+record the region limits in the bookmark.
+
+If NAME is nil, then prompt for the bookmark name.  The default names
+for prompting are as follows (in order of priority):
+
+ * If in W3M mode, then the current W3M title.
+
+ * If in a Gnus mode, then the Gnus summary article header.
+
+ * If on a `man' page, then the page name (command and section).
+
+ * If the region is active and nonempty, then the buffer name followed
+   by \": \" and the region prefix (up to
+   `bmkp-bookmark-name-length-max' chars).
+
+ * The names defined by option `bmkp-new-bookmark-default-names'.
+
+ * The value of variable `bookmark-current-bookmark', the name of the
+   last-used bookmark for the current file.
+
+ * The value returned by function `bookmark-buffer-name'.
+
+For Emacs 23+, all of the names described above are available as
+default values, by repeating `M-n'.  For older Emacs versions, the
+first name provided is the only default value.
+
+While entering a bookmark name at the prompt:
+
+ * You can use (lax) completion against bookmarks in the same buffer.
+   If there are no bookmarks in the current buffer, then all bookmarks
+   are completion candidates.  (See also below, about a numeric prefix
+   argument.)
+
+ * You can use `C-M-w' to yank words from the buffer to the
+   minibuffer.  Repeating `C-M-w' yanks successive words (newlines
+   between yanked words are stripped out).
+
+ * You can use `C-M-u' to insert the name of the last bookmark used in
+   the buffer.  This can be useful as an aid to track your progress
+   through a large file.  (If no bookmark has yet been used, then
+   `C-M-u' inserts the name of the visited file.)
+
+A prefix argument changes the behavior as follows:
+
+ * Numeric prefix arg: Use all bookmarks as completion candidates,
+   instead of just the bookmarks for the current buffer.
+
+ * Plain prefix arg (`C-u'): Do not overwrite a bookmark that has the
+   same name as NAME, if such a bookmark already exists.  Instead,
+   push the new bookmark onto the bookmark alist.
+
+   The most recently set bookmark named NAME is thus the one in effect
+   at any given time, but any others named NAME are still available,
+   should you decide to delete the most recent one.
+
+Use `\\[bookmark-delete]' to remove bookmarks (you give it a name, and it removes
+only the first instance of a bookmark with that name from the list of
+bookmarks)."
+  (interactive (list nil current-prefix-arg t))
+  (unwind-protect
+       (progn
+         (bookmark-maybe-load-default-file)
+         (setq bookmark-current-point   (point)) ; `bookmark-current-point' is a free var here.
+         ;; Do not set these if they are already set in some other buffer (e.g gnus-art).
+         (unless (and bookmark-yank-point  bookmark-current-buffer)
+           (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point  (point)))
+           (setq bookmark-current-buffer  (current-buffer)))
+         (let* ((record   (bookmark-make-record))
+                (defname  (cond ((eq major-mode 'w3m-mode) w3m-current-title)
+                                ((eq major-mode 'gnus-summary-mode) (elt (gnus-summary-article-header) 1))
+                                ((memq major-mode '(Man-mode woman-mode))
+                                 (buffer-substring (point-min) (save-excursion (goto-char (point-min))
+                                                                               (skip-syntax-forward "^ ")
+                                                                               (point))))
+                                (t nil)))
+                (defname  (and defname  (bmkp-replace-regexp-in-string "\n" " " defname)))
+                (bname    (or name  (bmkp-completing-read-lax
+                                     "Set bookmark "
+                                     (bmkp-new-bookmark-default-names defname)
+                                     (and (or (not parg) (consp parg)) ; No numeric PARG: all bookmarks.
+                                          (bmkp-specific-buffers-alist-only))
+                                     nil 'bookmark-history))))
+           (when (string-equal bname "") (setq bname  defname))
+           (bookmark-store bname (cdr record) (consp parg) (not interactivep))
+           (when (and interactivep bmkp-prompt-for-tags-flag)
+             (bmkp-add-tags bname (bmkp-read-tags-completing) 'NO-UPDATE-P)) ; Do not refresh tags. (?)
+           (case (and (boundp 'bmkp-auto-light-when-set) bmkp-auto-light-when-set)
+             (autonamed-bookmark       (when (bmkp-autonamed-bookmark-p bname)
+                                         (bmkp-light-bookmark bname)))
+             (non-autonamed-bookmark   (unless (bmkp-autonamed-bookmark-p bname)
+                                         (bmkp-light-bookmark bname)))
+             (any-bookmark             (bmkp-light-bookmark bname))
+             (autonamed-in-buffer      (bmkp-light-bookmarks
+                                        (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p
+                                                            (bmkp-this-buffer-alist-only))
+                                        nil interactivep))
+             (non-autonamed-in-buffer  (bmkp-light-bookmarks
+                                        (bmkp-remove-if #'bmkp-autonamed-bookmark-p
+                                                        (bmkp-this-buffer-alist-only))
+                                        nil interactivep))
+             (all-in-buffer            (bmkp-light-this-buffer nil interactivep)))
+           ;; Maybe make bookmark temporary.
+           (if bmkp-autotemp-all-when-set-p
+               (bmkp-make-bookmark-temporary bname)
+             (catch 'bookmark-set
+               (dolist (pred  bmkp-autotemp-bookmark-predicates)
+                 (when (and (functionp pred)  (funcall pred bname))
+                   (bmkp-make-bookmark-temporary bname)
+                   (throw 'bookmark-set t)))))
+           (run-hooks 'bmkp-after-set-hook)
+           (if bookmark-use-annotations
+               (bookmark-edit-annotation bname)
+             (goto-char bookmark-current-point)))) ; `bookmark-current-point' is a free var here.
+    (setq bookmark-yank-point     nil
+          bookmark-current-buffer nil)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Put full bookmark record on the name as property `bmkp-full-record'.
+;; Add BOOKMARK to `bmkp-modified-bookmarks'.
+;;
+(defun bookmark-set-name (bookmark newname)
+  "Set name of BOOKMARK to NEWNAME.
+BOOKMARK is a bookmark name or a bookmark record."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (setcar bookmark newname)
+  ;; Put the full bookmark on its name as property `bmkp-full-record'.
+  ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+  ;; If it needs to be stripped, that will be done when saving.
+  (put-text-property 0 (length newname) 'bmkp-full-record bookmark newname)
+  ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+  (unless (memq bookmark bmkp-modified-bookmarks)
+    (setq bmkp-modified-bookmarks  (cons bookmark bmkp-modified-bookmarks))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Prevent adding a newline in a bookmark name when yanking.
+;;
+;;;###autoload
+(defun bookmark-yank-word ()            ; Bound to `C-M-w' in minibuffer when setting bookmark.
+  "Yank the word at point in `bookmark-current-buffer'.
+Repeat to yank consecutive words from the current buffer, appending
+them to the minibuffer.  However, newline characters between yanked
+words are stripped out."
+  (interactive)
+  (let ((string  (with-current-buffer bookmark-current-buffer
+                   (goto-char bookmark-yank-point)
+                   (buffer-substring-no-properties (point)
+                                                   (progn (forward-word 1)
+                                                          (setq bookmark-yank-point  (point)))))))
+    (setq string  (bmkp-replace-regexp-in-string "\n" "" string))
+    (insert string)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Separate renaming of obsolete default bookmark name (do it even if not loading the default file).
+;; 2. Load `bmkp-last-as-first-bookmark-file' if it is non-nil.
+;;
+(defun bookmark-maybe-load-default-file ()
+  "If bookmarks have not yet been loaded, load them.
+If `bmkp-last-as-first-bookmark-file' is non-nil, load it.
+Otherwise, load `bookmark-default-file'."
+  ;; If there is no file at `bookmark-default-file' but there is a file with the obsolete default
+  ;; name, then rename that file to the value of `bookmark-default-file'.
+  ;; Do this regardless of whether it is `bookmark-default-file' that we load here.
+  (when (and (file-exists-p bookmark-old-default-file)  (not (file-exists-p bookmark-default-file)))
+    (rename-file bookmark-old-default-file bookmark-default-file))
+  (let ((file-to-load  (bmkp-default-bookmark-file)))
+    (and (not bookmarks-already-loaded)
+         (null bookmark-alist)
+         (file-readable-p file-to-load)
+         (bookmark-load file-to-load t 'nosave)
+         (setq bookmarks-already-loaded  t))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Save DISPLAY-FUNCTION to `bmkp-jump-display-function' before calling
+;;    `bookmark-handle-bookmark'.
+;; 2. Update the name and position of an autonamed bookmark, in case it moved.
+;; 3. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-jump'.
+;; 4. Added `catch', so a handler can throw to skip the rest of the processing if it wants.
+;;
+(defun bookmark--jump-via (bookmark display-function)
+  "Display BOOKMARK using DISPLAY-FUNCTION.
+Then run `bookmark-after-jump-hook' and show annotations for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  (bmkp-record-visit bookmark 'BATCHP)
+  (setq bmkp-jump-display-function  display-function)
+  (catch 'bookmark--jump-via
+    (bookmark-handle-bookmark bookmark)
+    (let ((win  (get-buffer-window (current-buffer) 0)))
+      (when win (set-window-point win (point))))
+    ;; If this is an autonamed bookmark, update its name and position, in case it moved.
+    ;; But don't do this if we're using w32, since we might not have moved to the bookmark position.
+    (when (and (bmkp-autonamed-bookmark-for-buffer-p bookmark (buffer-name))
+               (not bmkp-use-w32-browser-p))
+      (setq bookmark  (bmkp-update-autonamed-bookmark bookmark)))
+    (case (and (boundp 'bmkp-auto-light-when-jump) bmkp-auto-light-when-jump)
+      (autonamed-bookmark       (when (bmkp-autonamed-bookmark-p bookmark)
+                                  (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
+      (non-autonamed-bookmark   (unless (bmkp-autonamed-bookmark-p bookmark)
+                                  (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
+      (any-bookmark             (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT))
+      (autonamed-in-buffer      (bmkp-light-bookmarks
+                                 (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p
+                                                     (bmkp-this-buffer-alist-only))
+                                 nil 'MSG))
+      (non-autonamed-in-buffer  (bmkp-light-bookmarks
+                                 (bmkp-remove-if #'bmkp-autonamed-bookmark-p (bmkp-this-buffer-alist-only))
+                                 nil 'MSG))
+      (all-in-buffer            (bmkp-light-this-buffer nil 'MSG)))
+    (let ((orig-buff  (current-buffer))) ; Used by `crosshairs-highlight'.
+      (run-hooks 'bookmark-after-jump-hook))
+    (let ((jump-fn  (bmkp-get-tag-value bookmark "bmkp-jump")))
+      (when jump-fn (funcall jump-fn)))
+    (when bookmark-automatically-show-annotations (bookmark-show-annotation bookmark))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Add to beginning, not end, of bookmark record.
+;; 2. Do not use `nconc'.
+;; 3. Respect both old and newer bookmark formats.
+;; 4. Add BOOKMARK to `bmkp-modified-bookmarks'.
+;;
+(defun bookmark-prop-set (bookmark prop val)
+  "Set the property PROP of BOOKMARK to VAL.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let* ((bmk   (bookmark-get-bookmark bookmark))
+         (cell  (assq prop (bmkp-bookmark-data-from-record bmk))))
+    (if cell
+        (setcdr cell val)
+      (if (consp (car (cadr bmk)))      ; Old format: ("name" ((filename . "f")...))
+          (setcdr bmk (list (cons (cons prop val) (cadr bmk))))
+        (setcdr bmk (cons (cons prop val) (cdr bmk))))) ; New: ("name" (filename . "f")...)
+    ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+    (unless (memq bmk bmkp-modified-bookmarks)
+      (setq bmkp-modified-bookmarks  (cons bmk bmkp-modified-bookmarks)))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg USE-REGION-P.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-jump-1'.
+;; 4. Added note about Icicles `S-delete' to doc string.
+;;
+;;;###autoload
+(defun bookmark-jump (bookmark          ; Bound to `C-x j j', `C-x r b', `C-x p g'
+                      &optional display-function use-region-p)
+  "Jump to 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 function `bookmark-load' for more about this.
+
+If the file pointed to by BOOKMARK no longer exists, you are asked if
+you wish to give the bookmark a new location.  If so, `bookmark-jump'
+jumps to the new location and saves it.
+
+If the bookmark defines a region, then the region is activated if
+`bmkp-use-region' is not-nil or it is nil and you use a prefix
+argument.  A prefix arg temporarily flips the value of
+`bmkp-use-region'.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate.
+
+In Lisp code:
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil DISPLAY-FUNCTION is a function to display the bookmark.  By
+ default, `switch-to-buffer' is used.
+Non-nil USE-REGION-P flips the value of `bmkp-use-region'."
+  (interactive (list (bookmark-completing-read "Jump to bookmark" (bmkp-default-bookmark-name))
+                     nil
+                     current-prefix-arg))
+  (bmkp-jump-1 bookmark (or display-function 'switch-to-buffer) use-region-p))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg USE-REGION-P.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-jump-1'.
+;;
+;;;###autoload
+(defun bookmark-jump-other-window (bookmark &optional use-region-p)
+                                        ; Bound to `C-x 4 j j', `C-x p j', `C-x p o', `C-x p q'
+  "Jump to bookmark BOOKMARK in another window.
+See `bookmark-jump', in particular for info about using a prefix arg."
+  (interactive (list (bookmark-completing-read "Jump to bookmark (in another window)"
+                                               (bmkp-default-bookmark-name))
+                     current-prefix-arg))
+  (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window use-region-p))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Privilege property `file-handler' over `handler'.  If the former is available, apply it to the file.
+;;
+;; 2. If BOOKMARK has its own handler but that is not a defined function, then use the default handler.
+;;    This lets Emacs 22, for instance, handle Emacs 23+ image bookmarks.
+;;
+;; 3. Different relocation message for non-file bookmark.
+;;
+(defun bookmark-handle-bookmark (bookmark)
+  "Call BOOKMARK's handler, or `bookmark-default-handler' if it has none.
+Return nil or raise an error.
+
+BOOKMARK is a bookmark name or a bookmark record.
+
+More precisely:
+
+  If BOOKMARK has both `file-handler' and `filename' entries then
+  apply the former to the latter.
+
+  Else, if BOOKMARK has a `handler' property that is a defined
+  function then apply it to BOOKMARK.
+
+  Else, apply the default bookmark handler,
+  `bookmark-default-handler', to BOOKMARK.
+
+The default handler changes the current buffer and point.
+
+If the default handler is used and a file error is raised, the error
+is handled as follows:
+ If BOOKMARK has no `filename' entry, do nothing.
+ Else prompt to relocate the file.
+   If relocated, then try again to handle.  Else raise a file error."
+  (cond ((functionp (bookmark-prop-get bookmark 'file-handler))
+         (funcall (bookmark-prop-get bookmark 'file-handler) (bookmark-get-filename bookmark)))
+        ((functionp (bookmark-get-handler bookmark))
+         (funcall (bookmark-get-handler bookmark) (bookmark-get-bookmark bookmark)))
+        (t
+         (condition-case err
+             (funcall 'bookmark-default-handler (bookmark-get-bookmark bookmark))
+           (bookmark-error-no-filename  ; `file-error'
+            ;; BOOKMARK can be either a bookmark name or a bookmark record.
+            ;; If a record, do nothing - assume it is a bookmark used internally by some other package.
+            (when (stringp bookmark)
+              (let ((file             (bookmark-get-filename bookmark))
+                    (use-dialog-box   nil)
+                    (use-file-dialog  nil))
+                (when file
+                  ;; Ask user whether to relocate the file.  If no, signal the file error.
+                  (unless (string= file bmkp-non-file-filename) (setq file  (expand-file-name file)))
+                  (ding)
+                  (cond ((y-or-n-p (if (and (string= file bmkp-non-file-filename)
+                                            (bmkp-get-buffer-name bookmark))
+                                       "Bookmark's buffer does not exist.  Re-create it? "
+                                     (concat (file-name-nondirectory file) " nonexistent.  Relocate \""
+                                             bookmark "\"? ")))
+                         (if (string= file bmkp-non-file-filename)
+                             ;; This is probably not the right way to get the correct buffer, but it's
+                             ;; better than nothing, and it gives the user a chance to DTRT.
+                             (pop-to-buffer (bmkp-get-buffer-name bookmark)) ; Create buffer.
+                           (bookmark-relocate bookmark)) ; Relocate to file.
+                         (funcall (or (bookmark-get-handler bookmark) 'bookmark-default-handler)
+                                  (bookmark-get-bookmark bookmark))) ; Try again
+                        (t
+                         (message "Bookmark not relocated: `%s'" bookmark)
+                         (signal (car err) (cdr err)))))))))))
+  (when (stringp bookmark) (setq bookmark-current-bookmark  bookmark))
+  ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
+  ;; to use the return value.  Perhaps we should return the bookmark instead?
+  nil)                                  ; Return nil if no error.
+
+(put 'bookmark-error-no-filename 'error-conditions
+     '(error bookmark-errors bookmark-error-no-filename))
+(put 'bookmark-error-no-filename 'error-message "Bookmark has no associated file (or directory)")
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Support regions, buffer names, and property `file-handler'.
+;; 2. Handle MS Windows `Open' command if `bmkp-use-w32-browser-p' and if `w32-browser' is defined.
+;;
+(defun bookmark-default-handler (bookmark)
+  "Default handler to jump to the location of BOOKMARK.
+Return nil (or raise an error).
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+If `bmkp-use-w32-browser-p' is non-nil and function `w32-browser' is
+defined, then call `w32-browser'.  That is, use the default MS Windows
+application for the bookmarked file.
+
+If BOOKMARK has properties `file-handler' and `filename', then apply
+the value of the former to the latter.
+
+If BOOKMARK is an old-style Info bookmark, then go to the Info node.
+
+If BOOKMARK records a nonempty region and `bmkp-use-region' is
+ non-nil then activate the region.
+
+Otherwise, call `bmkp-goto-position' to go to the recorded position."
+  (let* ((bmk            (bookmark-get-bookmark bookmark))
+         (file           (bookmark-get-filename bmk))
+         (buf            (bookmark-prop-get bmk 'buffer))
+         (bufname        (bmkp-get-buffer-name bmk))
+         (pos            (bookmark-get-position bmk))
+         (end-pos        (bmkp-get-end-position bmk))
+         (old-info-node  (and (not (bookmark-get-handler bookmark))  (bookmark-prop-get bmk 'info-node))))
+
+    (cond ((and bmkp-use-w32-browser-p (fboundp 'w32-browser) file)  (w32-browser file))
+          ((and (bookmark-prop-get bookmark 'file-handler) file)
+           (funcall (bookmark-prop-get bookmark 'file-handler) file))
+          (old-info-node                ; Emacs 20-21 Info bookmarks - no handler entry.
+           (progn (require 'info) (Info-find-node file old-info-node) (goto-char pos)))
+          ((not (and bmkp-use-region end-pos (/= pos end-pos)))
+           ;; Single-position bookmark (no region).  Go to it.
+           (bmkp-goto-position bmk file buf bufname pos
+                               (bookmark-get-front-context-string bmk)
+                               (bookmark-get-rear-context-string bmk)))
+          (t
+           ;; Bookmark with a region.  Go to it and activate the region.
+           (if (and file (file-readable-p file) (not (buffer-live-p buf)))
+               (with-current-buffer (find-file-noselect file) (setq buf  (buffer-name)))
+             ;; No file found.  If no buffer either, then signal that file doesn't exist.
+             (unless (or (and buf (get-buffer buf))
+                         (and bufname (get-buffer bufname) (not (string= buf bufname))))
+               (signal 'bookmark-error-no-filename (list 'stringp file))))
+           (set-buffer (or buf bufname))
+           (when bmkp-jump-display-function
+             (save-current-buffer (funcall bmkp-jump-display-function (current-buffer)))
+             (raise-frame))
+           (goto-char (min pos (point-max)))
+           (when (> pos (point-max)) (error "Bookmark position is beyond buffer end"))
+           ;; Activate region.  Relocate it if it moved.  Save relocated bookmark if confirm.
+           (funcall bmkp-handle-region-function bmk)))
+    ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
+    ;; to use the return value.  Perhaps we should return the bookmark instead?
+    nil))                               ; Return nil if no file error.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added bookmark default for interactive use.
+;; 2. Added optional arg NO-UPDATE-P.
+;; 3. Added note about `S-delete' to doc string.
+;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;; 5. Update Dired location too, for Dired bookmark.
+;; 6. Refresh menu list, to show new location.
+;;
+;;;###autoload
+(defun bookmark-relocate (bookmark-name &optional no-update-p) ; Not bound
+  "Relocate the bookmark named BOOKMARK-NAME to another file.
+You are prompted for the new file name.
+
+Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and do not
+refresh/rebuild the bookmark-list display.
+
+Changes the file associated with the bookmark.
+Useful when a file has been renamed after a bookmark was set in it.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+  (interactive (list (bookmark-completing-read "Bookmark to relocate" (bmkp-default-bookmark-name))))
+  (bookmark-maybe-historicize-string bookmark-name)
+  (bookmark-maybe-load-default-file)
+  (let* ((icicle-unpropertize-completion-result-flag  t) ; For `read-file-name'.
+         (bookmark-filename                           (bookmark-get-filename bookmark-name))
+         (new-filename                                (abbreviate-file-name
+                                                       (expand-file-name
+                                                        (read-file-name
+                                                         (format "Relocate %s to: " bookmark-name)
+                                                         (file-name-directory bookmark-filename))))))
+    (bookmark-set-filename bookmark-name new-filename)
+    ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
+    (let ((dired-dir  (bookmark-prop-get bookmark-name 'dired-directory)))
+      (when (and dired-dir (equal dired-dir bookmark-filename))
+        (bookmark-prop-set bookmark-name 'dired-directory new-filename))))
+  (bmkp-maybe-save-bookmarks)
+  (when (and bookmark-bmenu-toggle-filenames (get-buffer "*Bookmark List*")
+             (get-buffer-window (get-buffer "*Bookmark List*") 0)
+             (not no-update-p))
+    (with-current-buffer (get-buffer "*Bookmark List*") ; Do NOT just use `bmkp-refresh/rebuild-menu-list'.
+      (bmkp-refresh-menu-list bookmark-name)))) ; So display new location and `*' marker.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added bookmark default for interactive use.
+;; 2. Do not add any text properties here.  That's done in `bmkp-bmenu-propertize-item'.
+;; 3. Added note about `S-delete' to doc string.
+;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;;
+;;;###autoload
+(defun bookmark-insert-location (bookmark-name &optional no-history) ; `C-x p I' (original: `C-x p f')
+  "Insert file or buffer name for the bookmark named BOOKMARK-NAME.
+If a file is bookmarked, insert the recorded file name.
+If a non-file buffer is bookmarked, insert the recorded buffer name.
+
+Optional second arg NO-HISTORY means do not record this in the
+minibuffer history list `bookmark-history'.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+  (interactive
+   (let ((bmk  (bookmark-completing-read "Insert bookmark location" (bmkp-default-bookmark-name))))
+     (if (> emacs-major-version 21) (list bmk) bmk)))
+  (or no-history (bookmark-maybe-historicize-string bookmark-name))
+  (insert (bookmark-location bookmark-name))) ; Return the line inserted.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Pass full bookmark to the various "get" functions.
+;; 2. Location returned can be a buffer name, instead of a file name.
+;;
+(defun bookmark-location (bookmark)
+  "Return the name of the file or buffer associated with BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+Return \"-- Unknown location --\" if no location name can be found."
+  (bookmark-maybe-load-default-file)
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (or (bookmark-prop-get bookmark 'location)
+      (bookmark-get-filename bookmark)
+      (bmkp-get-buffer-name bookmark)
+      (bookmark-prop-get bookmark 'buffer)
+      "-- Unknown location --"))
+      ;; $$$$$$$$$ ""))
+      ;; $$$$ (error "Bookmark has no file or buffer name: %S" bookmark)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added BATCHP arg.  Return OLD if BATCHP is non-nil and NEW is nil.
+;; 2. Rename also in marked and omitted lists.
+;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
+;; 4. Use `bmkp-completing-read-lax', not `read-from-minibuffer'.
+;; 5. Put `bmkp-full-record' property on new name.
+;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
+;; 4. Added note about `S-delete' to doc string.
+;; 6. Refresh menu list, to show new name.
+;;
+;;;###autoload
+(defun bookmark-rename (old &optional new batchp) ; Not bound in Bookmark+
+  "Change bookmark's name from OLD to NEW.
+Interactively:
+ If called from the keyboard, then prompt for OLD.
+ If called from the menubar, select OLD from a menu.
+If NEW is nil, then prompt for its string value (unless BATCH).
+
+When entering the NEW name you can use completion against existing
+bookmark names.  This completion is lax, so you can easily edit an
+existing name.  See `bookmark-set' for particular keys available
+during this input.
+
+If BATCHP is non-nil, then do not rebuild the bookmark list.  (NEW
+should be non-nil if BATCH is non-nil.)
+
+If you use Icicles then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+  (interactive (list (bookmark-completing-read "Old bookmark name" (bmkp-default-bookmark-name))))
+  (bookmark-maybe-historicize-string old)
+  (bookmark-maybe-load-default-file)
+  (setq bookmark-current-point  (point)) ; `bookmark-current-point' is a free var here.
+  (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point  (point)))
+  (setq bookmark-current-buffer  (current-buffer))
+  (let ((newname  (or new  (and (not batchp)  (bmkp-completing-read-lax "New name: " old)))))
+;;; $$$$$$  (read-from-minibuffer "New name: " nil
+;;;           (let ((now-map  (copy-keymap minibuffer-local-map)))
+;;;             (define-key now-map  "\C-w" 'bookmark-yank-word)
+;;;             now-map)
+;;;           nil 'bookmark-history))))
+
+    (when newname
+      (bookmark-set-name old newname)
+      ;; Put the bookmark on the name as property `bmkp-full-record'.
+      ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+      ;; If it needs to be stripped, that will be done when saving.
+      (put-text-property 0 (length newname) 'bmkp-full-record (bmkp-bookmark-record-from-name newname)
+                         newname)
+      (bmkp-rename-for-marked-and-omitted-lists old newname) ; Rename in marked & omitted lists, if present.
+      (setq bookmark-current-bookmark  newname)
+      (unless batchp
+        (if (and (get-buffer "*Bookmark List*") (get-buffer-window (get-buffer "*Bookmark List*") 0))
+            (with-current-buffer (get-buffer "*Bookmark List*")
+              (bmkp-refresh-menu-list newname)) ; So the new name is displayed.
+          (bookmark-bmenu-surreptitiously-rebuild-list)))
+      (bmkp-maybe-save-bookmarks))
+    (or newname old)))                  ; NEWNAME is nil only if BATCHP is non-nil and NEW was nil.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added bookmark default for interactive use.
+;; 2. Added note about `S-delete' to doc string.
+;; 3. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;;
+(or (fboundp 'old-bookmark-insert)
+(fset 'old-bookmark-insert (symbol-function 'bookmark-insert)))
+
+;;;###autoload
+(defun bookmark-insert (bookmark-name)  ; Bound to `C-x p i'
+  "Insert the text of a bookmarked file.
+BOOKMARK-NAME is the name of the 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 function `bookmark-load' for more about this.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+  (interactive (list (bookmark-completing-read "Insert bookmark contents" (bmkp-default-bookmark-name))))
+  (old-bookmark-insert bookmark-name))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Accept a bookmark or a bookmark name as arg.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-get-bookmark-in-alist', not `bookmark-get-bookmark'.
+;; 4. Remove highlighting for the bookmark.
+;; 5. Doc string includes note about `S-delete' for Icicles.
+;; 6. Update `bmkp-latest-bookmark-alist', `bmkp-bmenu-omitted-bookmarks', and `bmkp-auto-idle-bookmarks'.
+;; 7. Increment `bookmark-alist-modification-count' even when BATCHP is non-nil.
+;;
+;;;###autoload
+(defun bookmark-delete (bookmark &optional batchp) ; Bound to `C-x p d'
+  "Delete the BOOKMARK from the bookmark list.
+BOOKMARK is a bookmark name or a bookmark record.
+Interactively, default to the \"current\" bookmark (that is, the one
+most recently used in this file), if it exists.
+
+If BOOKMARK is a name and it has property `bmkp-full-record' then use
+that property along with the name to find the bookmark to delete.
+If it is a name without property `bmkp-full-record' then delete (only)
+the first bookmark in `bookmark-alist' with that name.
+
+Optional arg BATCHP means do not update buffer `*Bookmark List*'.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate.  In this way, you can delete multiple bookmarks."
+  (interactive (list (bookmark-completing-read "Delete bookmark" (bmkp-default-bookmark-name))))
+
+  ;; $$$$$$ Instead of loading unconditionally, maybe we should just try to delete conditionally?
+  ;; IOW, why not (when bookmarks-already-loaded BODY) instead of `bookmark-maybe-load-default-file'?
+  ;; If it gets called on a hook that gets run before ever loading, then should probably do nothing.
+  ;; Leaving it as is for now (2011-04-06).
+  (bookmark-maybe-load-default-file)
+
+  (let* ((bmk    (bookmark-get-bookmark bookmark 'NOERROR))
+         (bname  (bmkp-bookmark-name-from-record bmk))) ; BOOKMARK might have been a bookmark.
+    (when bname                         ; Do nothing if BOOKMARK does not represent a bookmark.
+      (bookmark-maybe-historicize-string bname)
+      (when (fboundp 'bmkp-unlight-bookmark) (bmkp-unlight-bookmark bmk 'NOERROR))
+      (setq bookmark-alist                (delq bmk bookmark-alist)
+            bmkp-latest-bookmark-alist    (delq bmk bmkp-latest-bookmark-alist)
+            bmkp-auto-idle-bookmarks      (delq bmk bmkp-auto-idle-bookmarks)
+            bmkp-bmenu-omitted-bookmarks  (bmkp-delete-bookmark-name-from-list
+                                           bname bmkp-bmenu-omitted-bookmarks))
+      (unless (bmkp-get-bookmark-in-alist bookmark-current-bookmark 'NOERROR)
+        (setq bookmark-current-bookmark  nil)) ; Make this nil if last occurrence of BMK was deleted.
+       ;; Do NOT refresh/rebuild if BATCHP.  Caller must do that if batching deletions.
+      (unless batchp (bmkp-refresh/rebuild-menu-list nil batchp))
+      (bmkp-maybe-save-bookmarks))))    ; Increments `bookmark-alist-modification-count'.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `bmkp-current-bookmark-file', not `bookmark-default-file'.
+;; 2. Update `bmkp-last-as-first-bookmark-file' if it is non-nil.
+;; 3. Reset `bmkp-modified-bookmarks' to ().
+;; 4. Call `bmkp-refresh/rebuild-menu-list'.
+;;
+;;;###autoload
+(defun bookmark-save (&optional parg file) ; Bound to `C-x p s'
+  "Save currently defined bookmarks.
+Save by default in the file named by variable
+`bmkp-current-bookmark-file'.  With a prefix arg, you are prompted for
+the file to save to.
+
+If `bmkp-last-as-first-bookmark-file' is non-nil, update its value to
+the file being saved.
+
+To load bookmarks from a specific file, use `\\[bookmark-load]'
+\(`bookmark-load').
+
+If called from Lisp:
+ With nil PARG, use file `bmkp-current-bookmark-file'.
+ With non-nil PARG and non-nil FILE, use file FILE.
+ With non-nil PARG and nil FILE, prompt the user for the file to use."
+  (interactive "P")
+  (bookmark-maybe-load-default-file)
+  (let ((file-to-save
+         (cond ((and (not parg) (not file)) bmkp-current-bookmark-file)
+               ((and (not parg) file) file)
+               ((and parg (not file)) (bmkp-read-bookmark-file-name "File to save bookmarks in: ")))))
+    (when (and bmkp-last-as-first-bookmark-file
+               bookmark-save-flag)      ; nil if temporary bookmarking mode.
+      (customize-save-variable 'bmkp-last-as-first-bookmark-file file-to-save))
+    (bookmark-write-file file-to-save))
+  ;; Indicate by the count that we have synced the current bookmark file.
+  ;; If an error has already occurred somewhere, the count will not be set, which is what we want.
+  (setq bookmark-alist-modification-count  0
+        bmkp-modified-bookmarks            ())
+  (bmkp-refresh/rebuild-menu-list))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Do not save temporary bookmarks (`bmkp-temporary-bookmark-p').
+;; 2. Added optional arg ALT-MSG.
+;; 3. Insert code piecewise, to improve performance when saving `bookmark-alist'.
+;;    (Do not let `pp' parse all of `bookmark-alist' at once.)
+;; 4. Unless `bmkp-propertize-bookmark-names-flag', remove text properties from bookmark name and file name.
+;; 5. Bind `print-circle' to t around pp, to record bookmark name with `bmkp-full-record' property.
+;; 6. Use `case', not `cond'.
+;;
+(defun bookmark-write-file (file &optional alt-msg)
+  "Write `bookmark-alist' to FILE.
+Bookmarks that have a non-nil `bmkp-temp' property are not saved.
+They are removed from the bookmark file, but not from the current
+bookmark list.
+
+Non-nil ALT-MSG is a message format string to use in place of the
+default, \"Saving bookmarks to file `%s'...\".  The string must
+contain a `%s' construct, so that it can be passed along with FILE to
+`format'.  At the end, \"done\" is appended to the message."
+  (let ((msg  (or alt-msg "Saving bookmarks to file `%s'..." file)))
+    (message (or alt-msg "Saving bookmarks to file `%s'...") file)
+    (with-current-buffer (get-buffer-create " *Bookmarks*")
+      (goto-char (point-min))
+      (delete-region (point-min) (point-max))
+      (let ((print-length  nil)
+            (print-level   nil)
+            bname fname last-fname)
+        (bookmark-insert-file-format-version-stamp)
+        (insert "(")
+        (dolist (bmk  bookmark-alist)
+          (unless (bmkp-temporary-bookmark-p bmk)
+            (setq bname  (car bmk)
+                  fname  (bookmark-get-filename bmk))
+            (when (or (not (> emacs-major-version 20)) ; Emacs 20 can't do (not (boundp 'print-circle)).
+                      (not bmkp-propertize-bookmark-names-flag))
+              (set-text-properties 0 (length bname) () bname)
+              (when fname (set-text-properties 0 (length fname) () fname)))
+            (setcar bmk bname)
+            (when (setq last-fname  (assq 'filename bmk)) (setcdr last-fname fname))
+            (let ((print-circle  t)) (pp bmk (current-buffer)))))
+        (insert ")")
+        (let ((version-control  (case bookmark-version-control
+                                  ((nil)      nil)
+                                  (never      'never)
+                                  (nospecial  version-control)
+                                  (t          t)))
+              (errorp           nil))
+          (condition-case nil
+              (write-region (point-min) (point-max) file)
+            (file-error (setq errorp  t) (message "CANNOT WRITE FILE `%s'" file) (sit-for 4)))
+          (kill-buffer (current-buffer))
+          (unless errorp (message (concat msg "done") file)))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg means OVERWRITE.
+;; 2. Use `bmkp-read-bookmark-file-name', not `read-file-name', and use different default.
+;; 3. If OVERWRITE is non-nil:
+;;    * Update `bmkp-last-bookmark-file' to `bmkp-current-bookmark-file'.
+;;    * Update `bmkp-current-bookmark-file' to FILE .
+;;    * If `bmkp-last-as-first-bookmark-file', then update it to FILE and save it to disk.
+;; 4. If the bookmark-file buffer already existed, do not kill it after loading.
+;; 5.  Set `bookmarks-already-loaded' regardless of FILE (not just `bookmark-default-file').
+;; 6. Update `bmkp-sorted-alist' (it's a cache).
+;; 7. Final msg says whether overwritten.
+;; 8. Call `bmkp-bmenu-refresh-menu-list' at end.
+;;
+;;;###autoload
+(defun bookmark-load (file &optional overwrite batchp) ; Bound to `C-x p l'
+  "Load bookmarks from FILE (which must be in the standard format).
+Without a prefix argument (argument OVERWRITE is nil), add the newly
+loaded bookmarks to those already current.  They will be saved to the
+current bookmark file when bookmarks are saved.
+
+If you do not use a prefix argument, then no existing bookmarks are
+overwritten.  If you load some bookmarks that have the same names as
+bookmarks already defined in your Emacs session, numeric suffixes
+\"<2>\", \"<3>\",... are appended as needed to the names of those new
+bookmarks to distinguish them.
+
+With a prefix argument, switch the bookmark file currently used,
+*replacing* all currently existing bookmarks with the newly loaded
+bookmarks.  In this case, the value of `bmkp-current-bookmark-file'is
+backed up to `bmkp-last-bookmark-file' and then changed to FILE, so
+bookmarks will subsequently be saved to FILE.  If
+`bmkp-last-as-first-bookmark-file' is non-nil then its value is also
+changed to FILE and it is saved persistently, so that the next Emacs
+session will start with it as the bookmark file.  (The value of
+`bookmark-default-file' is unaffected.)
+
+Interactively, if any bookmarks have been modified since last saved
+then you are asked whether you want to first save them before loading
+FILE.  If you hit `C-g' then both saving and loading are canceled.
+
+When called from Lisp, non-nil optional arg BATCHP means this is not
+an interactive call.  In this case, do not interact with the user: do
+not ask whether to save the current (unsaved) bookmark list before
+loading; do not display any load progress messages; and do not
+update/refresh buffer `*Bookmark List*'.
+
+If BATCHP is `save' and bookmarks have been modified since the
+bookmark list was last saved, then save the bookmark list before
+loading.
+
+If BATCHP is any other non-nil value besides `save', do not save the
+bookmark list.
+
+Your initial bookmark file, either `bmkp-last-as-first-bookmark-file'
+or `bookmark-default-file', is loaded automatically by Emacs the first
+time you use bookmarks in a session - you do not need to load it
+manually.  Use `bookmark-load' only to load extra bookmarks (with no
+prefix arg) or an alternative set of bookmarks (with a prefix arg).
+
+If you use `bookmark-load' to load a file that does not contain a
+proper bookmark alist, then when bookmarks are saved the current
+bookmark file will likely become corrupted.  You should load only
+bookmark files that were created using the bookmark functions."
+  (interactive
+   (list (let ((default  (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+                             (bmkp-default-bookmark-file)
+                           bmkp-last-bookmark-file)))
+           (bmkp-read-bookmark-file-name
+            (if current-prefix-arg "Switch to bookmark file: " "Add bookmarks from file: ")
+            (or (file-name-directory default) "~/")
+            default
+            t))
+         current-prefix-arg))
+  ;; Maybe save first.
+  (when (or (eq batchp 'save)
+            (and (not batchp)  (> bookmark-alist-modification-count 0)
+                 (condition-case err
+                     (yes-or-no-p "Save current bookmarks before loading? (`C-g': cancel load) ")
+                   (quit  (error "OK, canceled"))
+                   (error (error (error-message-string err))))))
+    (bookmark-save))
+  ;; Load.
+  (setq file  (abbreviate-file-name (expand-file-name file)))
+  (unless (file-readable-p file) (error "Cannot read bookmark file `%s'" file))
+  (unless batchp (message "Loading bookmarks from `%s'..." file))
+  (let ((existing-buf  (get-file-buffer file)))
+    (with-current-buffer (let ((enable-local-variables nil)) (find-file-noselect file))
+      (goto-char (point-min))
+      (bookmark-maybe-upgrade-file-format)
+      (let ((blist  (bookmark-alist-from-buffer)))
+        (unless (listp blist) (error "Invalid bookmark list in `%s'" file))
+        (cond (overwrite
+               (setq bmkp-last-bookmark-file            bmkp-current-bookmark-file
+                     bmkp-current-bookmark-file         file
+                     bookmark-alist                     blist
+                     bookmark-alist-modification-count  0)
+               (when bmkp-last-as-first-bookmark-file
+                 (customize-save-variable 'bmkp-last-as-first-bookmark-file file)))
+              (t
+               (bookmark-import-new-list blist)
+               (setq bookmark-alist-modification-count  (1+ bookmark-alist-modification-count))))
+        (setq bookmarks-already-loaded  t ; Systematically, whenever any file is loaded.
+              bmkp-sorted-alist         (bmkp-sort-omit bookmark-alist)))
+      (unless (eq existing-buf (current-buffer)) (kill-buffer (current-buffer)))))
+  (unless batchp                        ; If appropriate, *CALLER* MUST refresh/rebuild, if BATCHP.
+    (bmkp-refresh/rebuild-menu-list)
+    (message "%s bookmarks in `%s'" (if overwrite "Switched to" "Added") file)))
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg MSG-P.  Show message if no annotation.
+;; 2. Name buffer after the bookmark.
+;; 3. MSG-P means message if no annotation.
+;; 4. Use `view-mode'.  `q' uses `quit-window'.
+;; 5. Fit frame to buffer if `one-windowp'.
+;; 6. Restore frame selection.
+;;
+(defun bookmark-show-annotation (bookmark &optional msg-p)
+  "Display the annotation for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+If no annotation and MSG-P is non-nil, show a no-annotation message."
+  (let* ((bmk       (bookmark-get-bookmark bookmark 'NOERROR))
+         (bmk-name  (bmkp-bookmark-name-from-record bmk))
+         (ann       (and bmk  (bookmark-get-annotation bmk))))
+    (if (not (and ann (not (string-equal ann ""))))
+        (when msg-p (message "Bookmark has no annotation"))
+      (let ((oframe  (selected-frame)))
+        (save-selected-window
+          (pop-to-buffer (get-buffer-create (format "*`%s' Annotation*" bmk-name)))
+          (let ((buffer-read-only  nil)) ; Because buffer might already exist, in view mode.
+            (delete-region (point-min) (point-max))
+            (insert (concat "Annotation for bookmark '" bmk-name "':\n\n"))
+            (put-text-property (line-beginning-position -1) (line-end-position 1)
+                               'face 'bmkp-heading)
+            (insert ann))
+          (goto-char (point-min))
+          (view-mode-enter (cons (selected-window) (cons nil 'quit-window)))
+          (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window)))
+        (select-frame-set-input-focus oframe)))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use name `*Bookmark Annotations*', not `*Bookmark Annotation*'.
+;; 2. Don't list bookmarks that have no annotation.
+;; 3. Highlight bookmark names.  Don't indent annotations.  Add a blank line after each annotation.
+;; 4. Use `view-mode'.  `q' uses `quit-window'.
+;; 5. Fit frame to buffer if `one-windowp'.
+;; 6. Restore frame selection.
+;;
+(defun bookmark-show-all-annotations ()
+  "Display the annotations for all bookmarks."
+  (let ((oframe  (selected-frame)))
+    (save-selected-window
+      (pop-to-buffer (get-buffer-create "*Bookmark Annotations*"))
+      (let ((buffer-read-only  nil))    ; Because buffer might already exist, in view mode.
+        (delete-region (point-min) (point-max))
+        (dolist (full-record  bookmark-alist) ; (Could use `bmkp-annotated-alist-only' here instead.)
+          (let ((ann  (bookmark-get-annotation full-record)))
+            (when (and ann (not (string-equal ann "")))
+              (insert (concat (bmkp-bookmark-name-from-record full-record) ":\n"))
+              (put-text-property (line-beginning-position 0) (line-end-position 0) 'face 'bmkp-heading)
+              (insert ann) (unless (bolp) (insert "\n\n")))))
+        (goto-char (point-min))
+        (view-mode-enter (cons (selected-window) (cons nil 'quit-window)))
+        (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))))
+    (select-frame-set-input-focus oframe)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Save menu-list state to `bmkp-bmenu-state-file'.
+;;
+(defun bookmark-exit-hook-internal ()   ; This goes on `kill-emacs-hook'.
+  "Save currently defined bookmarks and perhaps bookmark menu-list state.
+Run `bookmark-exit-hook', then save bookmarks if they were updated.
+Then save menu-list state to file `bmkp-bmenu-state-file', but only if
+that option is non-nil."
+  (run-hooks 'bookmark-exit-hook)
+  (when (and bookmark-alist (bookmark-time-to-save-p t)) (bookmark-save))
+  (bmkp-save-menu-list-state))
+;;(@* "Bookmark+ Functions (`bmkp-*')")
+;;; Bookmark+ Functions (`bmkp-*') -----------------------------------
+
+(defun bmkp-new-bookmark-default-names (&optional first-def)
+  "Return a list of default names (strings) for a new bookmark.
+A non-nil optional arg FIRST-DEF is prepended to the list of names
+described below.
+
+If the region is active and non-empty, then the first default name
+\(other than FIRST-DEF) is the current buffer name followed by \": \"
+and the region prefix (up to `bmkp-bookmark-name-length-max' chars).
+The other names are as described below.
+
+Uses option `bmkp-new-bookmark-default-names' to come up with the
+other names.  To these names, `bookmark-current-bookmark' and
+`bookmark-buffer-name' are appened, if available (non-nil).
+
+NOTE: For Emacs versions prior to Emacs 23, return only a single
+default name, not a list of names.  The name is the first in the list
+of names described above for Emacs 23+."
+  (let ((defs  (and first-def  (list first-def)))
+        val)
+    (unless (and (< emacs-major-version 23)  defs) ; Just use FIRST-DEF for Emacs < 23.
+      ;; If region is active, first default is its text, with buffer name prepended.
+      (when (and transient-mark-mode mark-active  (not (eq (mark) (point))))
+        (let* ((regname  (concat (buffer-name) ": " (buffer-substring (region-beginning) (region-end))))
+               (defname  (bmkp-replace-regexp-in-string
+                          "\n" " "
+                          (progn (save-excursion (goto-char (region-beginning))
+                                                 (skip-chars-forward " ")
+                                                 (setq bookmark-yank-point  (point)))
+                                 (substring regname 0 (min bmkp-bookmark-name-length-max
+                                                           (length regname)))))))
+          (if (< emacs-major-version 23)
+              (setq defs  defname)
+            (add-to-list 'defs defname))))
+      ;; Names provided by option `bmkp-new-bookmark-default-names',
+      ;; plus `bookmark-current-bookmark' and `bookmark-buffer-name'.
+      (unless (and (< emacs-major-version 23)  defs)
+        (catch 'bmkp-new-bookmark-default-names
+          (dolist (fn  bmkp-new-bookmark-default-names)
+            (when (functionp fn)        ; Be sure it is defined and is a function.
+              (setq val  (funcall fn))
+              (when (and (stringp val) (not (string= "" val)))
+                (setq val  (bmkp-replace-regexp-in-string "\n" " " val))
+                (if (> emacs-major-version 22)
+                    (add-to-list 'defs val)
+                  (throw 'bmkp-new-bookmark-default-names (setq defs  val)))))))
+        (when (and (< emacs-major-version 23)  (null defs))
+          (setq defs  (or bookmark-current-bookmark  (bookmark-buffer-name))))
+        (when (consp defs)
+          (when bookmark-current-bookmark (push bookmark-current-bookmark defs))
+          (let ((buf  (bookmark-buffer-name))) (when buf (push buf defs)))
+          (setq defs  (nreverse defs)))))
+    defs))
+
+(defun bmkp-bookmark-record-from-name (bookmark-name &optional noerror memp alist)
+  "Return the full bookmark (record) that corresponds to BOOKMARK-NAME.
+BOOKMARK-NAME must be a string.  If it has non-nil text property
+`bmkp-full-record' then use that.  Otherwise, look for the first
+bookmark in ALIST that has the given name.
+
+Non-nil optional arg NOERROR means return nil if BOOKMARK-NAME does
+not name a valid bookmark or is valid but is not in ALIST.  If NOERROR
+is nil then raise an error in this case.
+
+Non-nil optional arg MEMP means that if property `bmkp-full-record' is
+available then look up its value (the full bookmark) in ALIST, testing
+with `eq'.  If that record is not in ALIST, return nil.
+
+Optional arg ALIST defaults to `bookmark-alist'."
+  (unless alist (setq alist  bookmark-alist))
+  (let ((full  (get-text-property 0 'bmkp-full-record bookmark-name)))
+    (or (and full
+             (or (not memp)  (memq full alist))
+             full)
+        ;; Punt: return first matching bookmark in ALIST.
+        (if (fboundp 'assoc-string)     ; Emacs 22+.  Use `assoc-string' for its CASE-FOLD arg.
+            (assoc-string bookmark-name alist bookmark-completion-ignore-case)
+          (assoc bookmark-name alist))
+        (and (not noerror) (error "No such bookmark in bookmark list: `%s'" bookmark-name)))))
+
+(defun bmkp-rename-for-marked-and-omitted-lists (old new)
+  "Replace OLD bookmark name with NEW in marked and omitted lists."
+  (when (bmkp-marked-bookmark-p old)
+    (setq bmkp-bmenu-marked-bookmarks  (bmkp-delete-bookmark-name-from-list old
+                                                                            bmkp-bmenu-marked-bookmarks))
+    (push new bmkp-bmenu-marked-bookmarks))
+  (when (bmkp-omitted-bookmark-p old)
+    (setq bmkp-bmenu-omitted-bookmarks  (bmkp-delete-bookmark-name-from-list old
+                                                                             bmkp-bmenu-omitted-bookmarks))
+    (push new bmkp-bmenu-omitted-bookmarks)))
+
+(defun bmkp-get-bookmark-in-alist (bookmark &optional noerror alist)
+  "Return the full bookmark in ALIST that corresponds to BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+
+Non-nil optional arg NOERROR means return nil if BOOKMARK does not
+represent a valid bookmark or is valid but is not in ALIST.  If
+NOERROR is nil then raise an error in this case.
+
+Optional arg ALIST defaults to `bookmark-alist'.
+
+Bookmark membership in ALIST is tested using `eq'.
+
+If BOOKMARK is a bookmark name instead of a full bookmark then return
+what `bmkp-bookmark-record-from-name' with non-nil arg MEMP returns.
+
+This function is like `bookmark-get-bookmark', except that
+`bookmark-get-bookmark' tests whether BOOKMARK is in `bookmark-alist'
+only when it is a string (a bookmark name, not a full bookmark).  When
+BOOKMARK is a full bookmark `bookmark-get-bookmark' is thus not a test
+for its existence, as is `bmkp-get-bookmark-in-alist'."
+  (cond ((consp bookmark) (and (memq bookmark bookmark-alist)  bookmark))
+        ((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror 'MEMP))
+        (t (and (not noerror) (error "Invalid bookmark: `%s'" bookmark)))))
+
+(defun bmkp-default-bookmark-file ()
+  "`bmkp-last-as-first-bookmark-file', or `bookmark-default-file' if nil."
+  (or bmkp-last-as-first-bookmark-file bookmark-default-file))
+
+(defun bmkp-completing-read-lax (prompt &optional default alist pred hist)
+  "Read a bookmark name, prompting with PROMPT.
+Like `bookmark-completing-read', but completion is lax: your input
+need not match any existing bookmark name.
+
+In addition:
+ * You can use `SPC' and `?' freely when typing the name.
+ * You can use `C-M-w' repeatedly to yank consecutive words from the
+   current buffer (see `bookmark-yank-word')."
+  (let ((orig-C-M-w  (lookup-key minibuffer-local-completion-map (kbd "C-M-w")))
+        (orig-C-M-u  (lookup-key minibuffer-local-completion-map (kbd "C-M-u")))
+        (orig-SPC    (lookup-key minibuffer-local-completion-map (kbd "SPC")))
+        (orig-qmark  (lookup-key minibuffer-local-completion-map (kbd "?"))))
+    (unwind-protect
+         (progn (define-key minibuffer-local-completion-map (kbd "C-M-w") 'bookmark-yank-word)
+                (define-key minibuffer-local-completion-map (kbd "C-M-u") 'bookmark-insert-current-bookmark)
+                (unless (and (boundp 'icicle-mode)  icicle-mode
+                             (eq orig-SPC 'icicle-self-insert))
+                  (define-key minibuffer-local-completion-map (kbd "SPC") 'self-insert-command))
+                (unless (and (boundp 'icicle-mode)  icicle-mode
+                             (eq orig-qmark 'icicle-self-insert))
+                  (define-key minibuffer-local-completion-map   (kbd "?") 'self-insert-command))
+                (bmkp-completing-read-1 prompt default alist pred hist t))
+      (define-key minibuffer-local-completion-map (kbd "C-M-w") orig-C-M-w)
+      (define-key minibuffer-local-completion-map (kbd "C-M-u") orig-C-M-u)
+      (define-key minibuffer-local-completion-map (kbd "SPC")   orig-SPC)
+      (define-key minibuffer-local-completion-map (kbd "?")     orig-qmark))))
+
+(defun bmkp-completing-read-1 (prompt default alist pred hist laxp)
+  "Helper for `bookmark-completing-read(-lax)'.
+LAXP non-nil means use lax completion."
+  (bookmark-maybe-load-default-file)
+  (setq alist  (or alist bookmark-alist))
+  (if (and (not laxp)
+           (listp last-nonmenu-event)
+           (or (eq t bmkp-menu-popup-max-length)
+               (and (integerp bmkp-menu-popup-max-length)
+                    (< (length alist) bmkp-menu-popup-max-length))))
+      (bookmark-menu-popup-paned-menu
+       t prompt
+       (if bmkp-sort-comparer           ; Test whether to sort, but always use `string-lessp'.
+           (sort (bookmark-all-names alist) 'string-lessp)
+         (bookmark-all-names alist)))
+    (let* ((icicle-delete-candidate-object  (lambda (cand) ; For `S-delete' in Icicles.
+                                              (bookmark-delete
+                                               (icicle-transform-multi-completion cand))))
+           (completion-ignore-case          bookmark-completion-ignore-case)
+           (default                         default)
+           (prompt                          (if default
+                                                (concat prompt
+                                                        (format " (%s): "
+                                                                (if (consp default) (car default) default)
+                                                                default))
+                                              (concat prompt ": ")))
+           (str                             (completing-read prompt alist pred (not laxp) nil
+                                                             (or hist 'bookmark-history) default)))
+      (when (consp default) (setq default  (car default))) ; Emacs 23+
+      (if (and (string-equal "" str) default) default str))))
+
+(defun bmkp-jump-1 (bookmark display-function use-region-p)
+  "Helper function for `bookmark-jump' commands.
+BOOKMARK is a bookmark name or a bookmark record.
+DISPLAY-FUNCTION is passed to `bookmark--jump-via'.
+Non-nil USE-REGION-P means activate the region, if recorded."
+  (setq bookmark  (bookmark-get-bookmark bookmark 'NOERROR))
+  (unless bookmark (error "No bookmark specified"))
+  (bookmark-maybe-historicize-string (bmkp-bookmark-name-from-record bookmark))
+  (let ((bmkp-use-region  (if use-region-p (not bmkp-use-region) bmkp-use-region)))
+    (bookmark--jump-via bookmark display-function)))
+
+(defun bmkp-select-buffer-other-window (buffer)
+  "Select BUFFER in another window.
+If `bmkp-other-window-pop-to-flag' is non-nil, then use
+`pop-to-buffer'.  Otherwise, use `switch-to-buffer-other-window'."
+  (if bmkp-other-window-pop-to-flag
+      (pop-to-buffer buffer t)
+    (switch-to-buffer-other-window buffer)))
+
+(defun bmkp-maybe-save-bookmarks (&optional same-count-p)
+  "Increment save counter and maybe save `bookmark-alist'.
+Non-nil optional arg SAME-COUNT-P means do not increment
+`bookmark-alist-modification-count'."
+  (unless same-count-p (setq bookmark-alist-modification-count  (1+ bookmark-alist-modification-count)))
+  (when (bookmark-time-to-save-p) (bookmark-save)))
+
+;;;###autoload
+(defun bmkp-edit-bookmark-name-and-file (bookmark &optional edit-record-p)
+                                        ; Bound to `C-x p r' (`r' in bookmark list)
+  "Edit BOOKMARK's name and file name, and maybe save them.
+Return a list of the new bookmark name and new file name.
+BOOKMARK is a bookmark name or a bookmark record.
+
+Without a prefix arg, you are prompted for the new bookmark name and
+ the new file name.  When entering the new name you can use completion
+ against existing names.  This completion is lax, so you can easily
+ edit an existing name.  See `bookmark-set' for particular keys
+available during this input.
+
+With a prefix arg, edit the complete bookmark record (the
+ internal, Lisp form)."
+  (interactive
+   (list (bookmark-completing-read
+          (concat "Edit " (and current-prefix-arg "internal record for ") "bookmark")
+          (bmkp-default-bookmark-name))
+         current-prefix-arg))
+  (setq bookmark  (bmkp-get-bookmark-in-alist bookmark))
+  (if edit-record-p
+      (bmkp-edit-bookmark-record bookmark)
+    (let* ((bookmark-name                               (bmkp-bookmark-name-from-record bookmark))
+           (bookmark-filename                           (bookmark-get-filename bookmark-name))
+           (new-bmk-name                                (bmkp-completing-read-lax
+                                                         "New bookmark name: " bookmark-name))
+           (icicle-unpropertize-completion-result-flag  t) ; For `read-file-name'.
+           (new-filename                                (read-file-name
+                                                         "New file name (location): "
+                                                         (and bookmark-filename
+                                                              (file-name-directory bookmark-filename))
+                                                         bookmark-filename))
+           (changed-bmk-name-p                          (and (not (equal new-bmk-name ""))
+                                                             (not (equal new-bmk-name bookmark-name))))
+           (changed-filename-p                          (and (not (equal new-filename ""))
+                                                             (not (equal new-filename bookmark-filename)))))
+
+           
+      (when (or changed-bmk-name-p  changed-filename-p)
+        (when changed-bmk-name-p (bookmark-rename bookmark-name new-bmk-name 'BATCHP))
+        (when changed-filename-p (bookmark-set-filename new-bmk-name new-filename))
+        ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
+        (let ((dired-dir  (bookmark-prop-get new-bmk-name 'dired-directory)))
+          (when (and dired-dir (equal dired-dir bookmark-filename))
+            (bookmark-prop-set new-bmk-name 'dired-directory new-filename)))
+        (bmkp-maybe-save-bookmarks)     ; Maybe save automatically.
+        (when (and bookmark-alist-modification-count ; Did not save automatically.  Ask user.
+                   (y-or-n-p "Save changes? "))
+          (bookmark-save))
+        (list new-bmk-name new-filename)))))
+
+(define-derived-mode bmkp-edit-bookmark-records-mode emacs-lisp-mode
+    "Edit Bookmark Records"
+  "Mode for editing a list of bookmark records, as in `bookmark-alist'.
+When you have finished editing, use `\\[bmkp-edit-bookmark-record-send]'."
+  :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-records-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-records-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-bookmark-records-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-records-send)
+
+(defvar bmkp-edit-bookmark-records-number 0
+  "NUmber of bookmard records being edited.")
+
+;;;###autoload
+(defun bmkp-edit-bookmark-records-send (&optional msg-p) ; Bound to `C-c C-c' in records-editing buffer.
+  "Update `bookmark-alist' with buffer contents: a bookmark alist.
+Lines beginning with `;;' are ignored.
+Non-interactively, optional arg MSG-P means display progress messages.
+
+This assumes that the bookmarks in the buffer are the marked bookmarks
+in `*Bookmark List*'.  That is, it assumes that the buffer was created
+by `bmkp-bmenu-edit-marked' (`\\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-edit-marked]' in `*Bookmark List*')."
+  (interactive "p")
+  (unless (eq major-mode 'bmkp-edit-bookmark-records-mode)
+    (error "Not in `bmkp-edit-bookmark-records-mode'"))
+  (when msg-p (message "Reading edited bookmarks..."))
+  (let ((editbuf     (current-buffer))
+        (read-error-msg
+         (catch 'bmkp-edit-bookmark-records-send
+           (let ((edited-bookmarks    (condition-case err
+                                          (save-excursion (goto-char (point-min))  (read (current-buffer)))
+                                        (error (throw 'bmkp-edit-bookmark-records-send
+                                                 (error-message-string err)))))
+                 (orig-bmks           (bmkp-marked-bookmarks-only))
+                 (bookmark-save-flag  (and (not bmkp-count-multi-mods-as-one-flag)
+                                           bookmark-save-flag))) ; Save only after `dolist'.
+             (cond ((not (listp edited-bookmarks))
+                    (throw 'bmkp-edit-bookmark-records-send "Not a list of bookmarks"))
+                   ((not (= (length edited-bookmarks) bmkp-edit-bookmark-records-number))
+                    (throw 'bmkp-edit-bookmark-records-send
+                      (format "Need %d bookmarks, but there seem to be %d"
+                              bmkp-edit-bookmark-records-number (length edited-bookmarks)))))
+             (dolist (edited-bmk  edited-bookmarks)
+               (unless (and (consp edited-bmk) (stringp (car edited-bmk))) ; Sanity check.
+                 (throw 'bmkp-edit-bookmark-records-send (format "Invalid bookmark: `%s'" edited-bmk)))
+               (let ((bname  (bmkp-bookmark-name-from-record edited-bmk))
+                     (data   (bmkp-bookmark-data-from-record edited-bmk)))
+                 ;; Put the full bookmark on its name as property `bmkp-full-record'.
+                 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+                 ;; If it needs to be stripped, that will be done when saving.
+                 (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
+                 ;; Update the original bookmark (same cons cell) with what's in the edited version.
+                 (setcar (car orig-bmks) bname)
+                 (setcdr (car orig-bmks) data)
+                 ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+                 (unless (memq (car orig-bmks) bmkp-modified-bookmarks)
+                   (setq bmkp-modified-bookmarks  (cons (car orig-bmks) bmkp-modified-bookmarks)))
+                 (setq orig-bmks  (cdr orig-bmks))))
+             ;; Update using modified ORIG-BMKS.
+             (setq bmkp-bmenu-marked-bookmarks        (mapcar #'bmkp-bookmark-name-from-record
+                                                              bmkp-modified-bookmarks)
+                   bmkp-sorted-alist                  (bmkp-sort-omit bookmark-alist)
+                   bookmark-alist-modification-count  (1+ bookmark-alist-modification-count)))
+           nil)))
+    (if (stringp read-error-msg)
+        (if msg-p  (message "%s  --> edit and try again" read-error-msg)  (error read-error-msg))
+      (when (get-buffer editbuf) (kill-buffer editbuf))
+      (bmkp-refresh/rebuild-menu-list nil (not msg-p)))))
+
+(define-derived-mode bmkp-edit-bookmark-record-mode emacs-lisp-mode
+    "Edit Bookmark Record"
+  "Mode for editing an internal bookmark record.
+When you have finished editing, use `\\[bmkp-edit-bookmark-record-send]'."
+  :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-record-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-record-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-bookmark-record-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-record-send)
+
+;;;###autoload
+(defun bmkp-edit-bookmark-record (bookmark) ; Bound to `C-x p e'.
+  "Edit the full record (the Lisp sexp) for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+When you finish editing, use `\\[bmkp-edit-bookmark-record-send]'.
+The current bookmark list is then updated to reflect your edits."
+  (interactive (list (bookmark-completing-read "Edit Lisp record for bookmark:"
+                                               (bmkp-default-bookmark-name))))
+  (bookmark-maybe-load-default-file)
+  (setq bmkp-edit-bookmark-orig-record  (bmkp-get-bookmark-in-alist bookmark))
+  (let* ((bmk-copy  (copy-sequence bmkp-edit-bookmark-orig-record)) ; Shallow copy
+         (bname     (bmkp-bookmark-name-from-record bmk-copy))
+         (bufname   (format "*Edit Record for Bookmark `%s'*" bname)))
+    (set-text-properties 0 (length bname) nil bname) ; Strip properties from (copied) name string.
+    (bookmark-maybe-historicize-string bname)
+    (bmkp-with-output-to-plain-temp-buffer bufname
+      (princ
+       (substitute-command-keys
+        (concat ";; Edit the Lisp record for bookmark\n;;\n"
+                ";; `" bname "'\n;;\n"
+                ";; Type \\<bmkp-edit-bookmark-record-mode-map>\
+`\\[bmkp-edit-bookmark-record-send]' when done.\n;;\n")))
+      ;; (let ((print-circle  t)) (pp bmk)) ; $$$$$$ Binding should not really be needed now.
+      (pp bmk-copy)
+      (goto-char (point-min)))
+    (pop-to-buffer bufname)
+    (buffer-enable-undo)
+    (with-current-buffer (get-buffer bufname) (bmkp-edit-bookmark-record-mode))))
+
+;;;###autoload
+(defun bmkp-edit-bookmark-record-send (&optional msg-p) ; Bound to `C-c C-c' in record-editing buffer.
+  "Update `bookmark-alist' with buffer contents: a bookmark record.
+Lines beginning with `;;' are ignored.
+Non-interactively, optional arg MSG-P means display progress messages."
+  (interactive "p")
+  (unless (eq major-mode 'bmkp-edit-bookmark-record-mode)
+    (error "Not in `bmkp-edit-bookmark-record-mode'"))
+  (when msg-p (message "Reading edited bookmark..."))
+  (let* ((editbuf     (current-buffer))
+         (bmk-name    nil)
+         (read-error-msg
+          (catch 'bmkp-edit-bookmark-record-send
+            (let ((edited-bmk
+                   (condition-case err
+                       (save-excursion (goto-char (point-min))  (read (current-buffer)))
+                     (error (throw 'bmkp-edit-bookmark-record-send (error-message-string err))))))
+              (unless (and (consp edited-bmk) (stringp (car edited-bmk)))
+                (throw 'bmkp-edit-bookmark-record-send (format "Invalid bookmark: `%s'" edited-bmk)))
+              (let ((bname  (bmkp-bookmark-name-from-record edited-bmk))
+                    (data   (bmkp-bookmark-data-from-record edited-bmk)))
+                ;; Put the full bookmark on its name as property `bmkp-full-record'.
+                ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+                ;; If it needs to be stripped, that will be done when saving.
+                (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
+                ;; Update the original bookmark with what's in the edited version.
+                (setcar bmkp-edit-bookmark-orig-record bname)
+                (setcdr bmkp-edit-bookmark-orig-record data)
+                ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+                (unless (memq bmkp-edit-bookmark-orig-record bmkp-modified-bookmarks)
+                  (setq bmkp-modified-bookmarks  (cons bmkp-edit-bookmark-orig-record
+                                                       bmkp-modified-bookmarks)))
+                (setq bmk-name  bname)) ; Save for bookmark-list display, below.
+              (setq bmkp-sorted-alist                  (bmkp-sort-omit bookmark-alist)
+                    bookmark-alist-modification-count  (1+ bookmark-alist-modification-count)))
+            nil)))
+    (if (stringp read-error-msg)
+        (if msg-p
+            (message "%s  --> edit and try again" read-error-msg)
+          (error read-error-msg))
+      (when (get-buffer editbuf) (kill-buffer editbuf))
+      (bmkp-refresh/rebuild-menu-list bmk-name (not msg-p))))
+  (setq bmkp-edit-bookmark-orig-record  nil)) ; Reset it.
+
+(define-derived-mode bmkp-edit-tags-mode emacs-lisp-mode
+    "Edit Bookmark Tags"
+  "Mode for editing bookmark tags.
+When you have finished composing, type \\[bmkp-edit-tags-send]."
+  :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-tags-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-tags-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-tags-mode-map "\C-c\C-c" 'bmkp-edit-tags-send)
+
+;;;###autoload
+(defun bmkp-edit-tags (bookmark)        ; Bound to `C-x p t e'
+  "Edit BOOKMARK's tags, and maybe save the result.
+The edited value must be a list each of whose elements is either a
+ string or a cons whose key is a string.
+BOOKMARK is a bookmark name or a bookmark record."
+  (interactive (list (bookmark-completing-read "Edit tags for bookmark" (bmkp-default-bookmark-name))))
+  (setq bookmark  (bmkp-get-bookmark-in-alist bookmark))
+  (let* ((btags    (bmkp-get-tags bookmark))
+         (bmkname  (bmkp-bookmark-name-from-record bookmark))
+         (edbuf    (format "*Edit Tags for Bookmark `%s'*" bmkname)))
+    (setq bmkp-return-buffer  (current-buffer))
+    (bmkp-with-output-to-plain-temp-buffer edbuf
+      (princ
+       (substitute-command-keys
+        (concat ";; Edit tags for bookmark\n;;\n;; \"" bmkname "\"\n;;\n"
+                ";; The edited value must be a list each of whose elements is\n"
+                ";; either a string or a cons whose key is a string.\n;;\n"
+                ";; DO NOT MODIFY THESE COMMENTS.\n;;\n"
+                ";; Type \\<bmkp-edit-tags-mode-map>`\\[bmkp-edit-tags-send]' when done.\n\n")))
+      (let ((print-circle  t)) (pp btags))
+      (goto-char (point-min)))
+    (pop-to-buffer edbuf)
+    (buffer-enable-undo)
+    (with-current-buffer (get-buffer edbuf) (bmkp-edit-tags-mode))))
+
+;;;###autoload
+(defun bmkp-edit-tags-send (&optional batchp)
+  "Use buffer contents as the internal form of a bookmark's tags.
+DO NOT MODIFY the header comment lines, which begin with `;;'."
+  (interactive)
+  (unless (eq major-mode 'bmkp-edit-tags-mode) (error "Not in `bmkp-edit-tags-mode'"))
+  (let (bname)
+    (unwind-protect
+         (let (tags bmk)
+           (goto-char (point-min))
+           (unless (search-forward ";; Edit tags for bookmark\n;;\n;; ")
+             (error "Missing header in edit buffer"))
+           (unless (stringp (setq bname  (read (current-buffer))))
+             (error "Bad bookmark name in edit-buffer header"))
+           (unless (setq bmk  (bmkp-get-bookmark-in-alist bname 'NOERROR))
+             (error "No such bookmark: `%s'" bname))
+           (unless (bmkp-bookmark-type bmk) (error "Invalid bookmark"))
+           (goto-char (point-min))
+           (setq tags  (read (current-buffer)))
+           (unless (listp tags) (error "Tags sexp is not a list of strings or an alist with string keys"))
+           (bookmark-prop-set bmk 'tags tags)
+           (setq bname  (bmkp-bookmark-name-from-record bmk))
+           (bmkp-record-visit bmk batchp)
+           (bmkp-refresh/rebuild-menu-list bname batchp)
+           (bmkp-maybe-save-bookmarks)
+           (unless batchp (message "Updated bookmark file with edited tags")))
+      (kill-buffer (current-buffer)))
+    (when bmkp-return-buffer
+      (pop-to-buffer bmkp-return-buffer)
+      (when (equal (buffer-name (current-buffer)) "*Bookmark List*")
+        (bmkp-bmenu-goto-bookmark-named bname)))))
+
+(defun bmkp-bookmark-type (bookmark)
+  "Return the type of BOOKMARK or nil if no type is recognized.
+Return nil if the bookmark record is not recognized (invalid).
+See the code for the possible non-nil return values.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (condition-case nil
+      (progn
+        ;; If BOOKMARK is already a bookmark record, not a bookmark name, then we must use it.
+        ;; If we used the name instead, then tests such as `bookmark-get-filename' would fail,
+        ;; because they call `bookmark-get-bookmark', which, for a string, checks whether the
+        ;; bookmark exists in `bookmark-alist'.  But we want to be able to use `bmkp-bookmark-type'
+        ;; to get the type of any bookmark record, not necessarily one that is in `bookmark-alist'.
+        (when (stringp bookmark) (setq bookmark  (bookmark-get-bookmark bookmark)))
+        (let ((filep  (bookmark-get-filename bookmark)))
+          (cond ((bmkp-sequence-bookmark-p bookmark)             'bmkp-sequence-bookmark-p)
+                ((bmkp-function-bookmark-p bookmark)             'bmkp-function-bookmark-p)
+                ((bmkp-variable-list-bookmark-p bookmark)        'bmkp-variable-list-bookmark-p)
+                ((bmkp-url-bookmark-p bookmark)                  'bmkp-url-bookmark-p)
+                ((bmkp-gnus-bookmark-p bookmark)                 'bmkp-gnus-bookmark-p)
+                ((bmkp-desktop-bookmark-p bookmark)              'bmkp-desktop-bookmark-p)
+                ((bmkp-bookmark-file-bookmark-p bookmark)        'bmkp-bookmark-file-bookmark-p)
+                ((bmkp-bookmark-list-bookmark-p bookmark)        'bmkp-bookmark-list-bookmark-p)
+                ((bmkp-man-bookmark-p bookmark)                  'bmkp-man-bookmark-p)
+                ((bmkp-info-bookmark-p bookmark)                 'bmkp-info-bookmark-p)
+                ((bookmark-get-handler bookmark)                 'bookmark-get-handler)
+                ((bmkp-region-bookmark-p bookmark)               'bmkp-region-bookmark-p)
+                ;; Make sure we test for remoteness before any other tests of the file itself
+                ;; (e.g. `file-exists-p'). We do not want to prompt for a password etc.
+                ((and filep (bmkp-file-remote-p filep))          'remote-file)
+                ((and filep (file-directory-p filep))            'local-directory)
+                (filep                                           'local-file)
+                ((and (bmkp-get-buffer-name bookmark)
+                      (or (not filep)
+                          (equal filep bmkp-non-file-filename))) 'buffer)
+                (t                                               nil))))
+    (error nil)))
+
+(defun bmkp-record-visit (bookmark &optional batchp)
+  "Update the data recording a visit to BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+This increments the `visits' entry and sets the `time' entry to the
+current time.  If either an entry is not present, it is added (with 0
+value for `visits').
+With non-nil optional arg BATCHP, do not rebuild the menu list.
+
+Although this function modifies BOOKMARK, it does not increment
+`bookmark-alist-modification-count', and it does not add BOOKMARK to
+`bmkp-modified-bookmarks'.  This is so that simply recording the visit
+does not count toward needing to save or showing BOOKMARK as modified."
+  (let ((vis                      (bookmark-prop-get bookmark 'visits))
+        (bmkp-modified-bookmarks  bmkp-modified-bookmarks))
+    (if vis  (bookmark-prop-set bookmark 'visits (1+ vis))  (bookmark-prop-set bookmark 'visits 0))
+    (bookmark-prop-set bookmark 'time (current-time))
+    (unless batchp (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
+    (let ((bookmark-save-flag  nil))  (bmkp-maybe-save-bookmarks 'SAME-COUNT-P))))
+
+(defun bmkp-default-bookmark-name (&optional alist)
+  "Default bookmark name.  See option `bmkp-default-bookmark-name'.
+Non-nil ALIST means return nil unless the default names a bookmark in
+ALIST."
+  (let ((bname  (if (equal (buffer-name (current-buffer)) "*Bookmark List*")
+                    (bookmark-bmenu-bookmark)
+                  (if (fboundp 'bmkp-default-lighted)
+                      (if (eq 'highlighted bmkp-default-bookmark-name)
+                          (or (bmkp-default-lighted) bookmark-current-bookmark)
+                        (or bookmark-current-bookmark (bmkp-default-lighted)))
+                    bookmark-current-bookmark))))
+    (when (and bname alist)
+      (setq bname  (bmkp-bookmark-name-from-record (bmkp-bookmark-record-from-name
+                                                    bname 'NOERROR 'MEMP alist))))
+    bname))
+
+(defun bmkp-buffer-names ()
+  "Buffer names used by existing bookmarks that really have buffers.
+This excludes buffers for bookmarks such as desktops that are not
+really associated with a buffer."
+  (let ((bufs  ())
+        buf)
+    (dolist (bmk  bookmark-alist)
+      (when (and (not (bmkp-desktop-bookmark-p        bmk))
+                 (not (bmkp-bookmark-file-bookmark-p  bmk))
+                 (not (bmkp-sequence-bookmark-p       bmk))
+                 (not (bmkp-function-bookmark-p       bmk))
+                 (not (bmkp-variable-list-bookmark-p  bmk))
+                 (setq buf  (bmkp-get-buffer-name     bmk)))
+        (add-to-list 'bufs buf)))
+    bufs))
+
+(defun bmkp-file-names ()
+  "The absolute file names used by the existing bookmarks.
+This excludes the pseudo file name `bmkp-non-file-filename'."
+  (let ((files  ())
+        file)
+    (dolist (bmk  bookmark-alist)
+      (when (and (setq file  (bookmark-get-filename bmk))  (not (equal file bmkp-non-file-filename)))
+        (add-to-list 'files file)))
+    files))
+
+;;;###autoload
+(defun bmkp-send-bug-report ()          ; Not bound
+  "Send a bug report about a Bookmark+ problem."
+  (interactive)
+  (browse-url (format (concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark+ bug: \
+&body=Describe bug below, using a precise recipe that starts with `emacs -Q' or `emacs -q'.  \
+Be sure to mention the `Update #' from header of the particular Bookmark+ file header.\
+%%0A%%0AEmacs version: %s")
+                      (emacs-version))))
+
+;;;###autoload
+(defun bmkp-toggle-bookmark-set-refreshes () ; Not bound
+  "Toggle `bookmark-set' refreshing `bmkp-latest-bookmark-alist'.
+Add/remove `bmkp-refresh-latest-bookmark-list' to/from
+`bmkp-after-set-hook'."
+  (interactive)
+  (if (member 'bmkp-refresh-latest-bookmark-list bmkp-after-set-hook)
+      (remove-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)
+    (add-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)))
+
+(defun bmkp-refresh-latest-bookmark-list ()
+  "Refresh `bmkp-latest-bookmark-alist' to reflect `bookmark-alist'."
+  (setq bmkp-latest-bookmark-alist  (if bmkp-bmenu-filter-function
+                                        (funcall bmkp-bmenu-filter-function)
+                                      bookmark-alist)))
+
+;;;###autoload
+(defun bmkp-toggle-saving-menu-list-state () ; Bound to `C-M-~' in bookmark list
+  "Toggle the value of option `bmkp-bmenu-state-file'.
+Tip: You can use this before quitting Emacs, to not save the state.
+If the initial value of `bmkp-bmenu-state-file' is nil, then this
+command has no effect."
+  (interactive)
+  (unless (or bmkp-last-bmenu-state-file bmkp-bmenu-state-file)
+    (error "Cannot toggle: initial value of `bmkp-bmenu-state-file' is nil"))
+  (setq bmkp-last-bmenu-state-file  (prog1 bmkp-bmenu-state-file
+                                      (setq bmkp-bmenu-state-file  bmkp-last-bmenu-state-file)))
+  (message (if bmkp-bmenu-state-file
+               "Autosaving of bookmark list state is now ON"
+             "Autosaving of bookmark list state is now OFF")))
+
+;;;###autoload
+(defun bmkp-save-menu-list-state (&optional msg-p) ; Used in `bookmark-exit-hook-internal'.
+  "Save menu-list state, unless not saving or list has not yet been shown.
+The state is saved to the value of `bmkp-bmenu-state-file'.
+Non-interactively, optional arg MSG-P means display progress messages."
+  (interactive "p")
+  (when (and (not bmkp-bmenu-first-time-p)  bmkp-bmenu-state-file)
+    (when msg-p (message "Saving bookmark-list display state..."))
+    (let ((config-list
+           `((last-sort-comparer                    . ,bmkp-sort-comparer)
+             (last-reverse-sort-p                   . ,bmkp-reverse-sort-p)
+             (last-reverse-multi-sort-p             . ,bmkp-reverse-multi-sort-p)
+             (last-latest-bookmark-alist            . ,(bmkp-maybe-unpropertize-bookmark-names
+                                                        bmkp-latest-bookmark-alist))
+             (last-bmenu-omitted-bookmarks          . ,(bmkp-maybe-unpropertize-bookmark-names
+                                                        bmkp-bmenu-omitted-bookmarks))
+             (last-bmenu-marked-bookmarks           . ,(bmkp-maybe-unpropertize-bookmark-names
+                                                        bmkp-bmenu-marked-bookmarks))
+             (last-bmenu-filter-function            . ,bmkp-bmenu-filter-function)
+             (last-bmenu-filter-pattern             . ,bmkp-bmenu-filter-pattern)
+             (last-bmenu-title                      . ,bmkp-bmenu-title)
+             (last-bmenu-bookmark                   . ,(and (get-buffer "*Bookmark List*")
+                                                            (with-current-buffer
+                                                                (get-buffer "*Bookmark List*")
+                                                              (bookmark-bmenu-bookmark))))
+             (last-specific-buffer                  . ,bmkp-last-specific-buffer)
+             (last-specific-file                    . ,bmkp-last-specific-file)
+             (last-bmenu-toggle-filenames           . ,bookmark-bmenu-toggle-filenames)
+             (last-bmenu-before-hide-marked-alist   . ,(bmkp-maybe-unpropertize-bookmark-names
+                                                        bmkp-bmenu-before-hide-marked-alist))
+             (last-bmenu-before-hide-unmarked-alist . ,(bmkp-maybe-unpropertize-bookmark-names
+                                                        bmkp-bmenu-before-hide-unmarked-alist))
+             (last-bookmark-file                    . ,(convert-standard-filename
+                                                        (expand-file-name
+                                                         bmkp-current-bookmark-file))))))
+      (with-current-buffer (get-buffer-create " *Menu-List State*")
+        (goto-char (point-min))
+        (delete-region (point-min) (point-max))
+        (let ((print-length  nil)
+              (print-level   nil)
+              (print-circle  t))
+          (pp config-list (current-buffer)))
+        (condition-case nil
+            (write-region (point-min) (point-max) bmkp-bmenu-state-file)
+          (file-error (message "Cannot write `%s'" bmkp-bmenu-state-file)))
+        (kill-buffer (current-buffer)))
+      (when msg-p (message "Saving bookmark-list display state...done")))))
+
+;;;###autoload
+(defun bmkp-toggle-saving-bookmark-file (&optional msg-p) ; Bound to `M-~' in bookmark list
+  "Toggle the value of option `bookmark-save-flag'.
+If the initial value of `bookmark-save-flag' is nil, then this
+command has no effect.
+Non-interactively, non-nil MSG-P means display a status message."
+  (interactive "p")
+  (unless (or bmkp-last-save-flag-value bookmark-save-flag)
+    (error "Cannot toggle: initial value of `bookmark-save-flag' is nil"))
+  (setq bmkp-last-save-flag-value  (prog1 bookmark-save-flag
+                                     (setq bookmark-save-flag  bmkp-last-save-flag-value)))
+  (when msg-p (message (if bookmark-save-flag
+                           "Autosaving of current bookmark file is now ON"
+                         "Autosaving of current bookmark file is now OFF"))))
+
+;;;###autoload
+(defun bmkp-make-function-bookmark (bookmark-name function &optional msg-p) ; Not bound
+  "Create a bookmark that invokes FUNCTION when \"jumped\" to.
+You are prompted for the bookmark name and the name of the function.
+Interactively, you are prompted for the bookmark and the function.
+Returns the new bookmark (internal record).
+
+Non-interactively, non-nil optional arg MSG-P means display a status
+message."
+  (interactive
+   (let ((icicle-unpropertize-completion-result-flag  t))
+     (list (read-string "Bookmark: ")
+           (completing-read "Function: " obarray 'functionp)
+           t)))
+  (bookmark-store bookmark-name `((filename . ,bmkp-non-file-filename)
+                                  (position . 0)
+                                  (function . ,(read function))
+                                  (handler  . bmkp-jump-function))
+                  nil (not msg-p))
+  (let ((new  (bmkp-bookmark-record-from-name bookmark-name 'NOERROR)))
+    (unless (memq new bmkp-latest-bookmark-alist)
+      (setq bmkp-latest-bookmark-alist  (cons new bmkp-latest-bookmark-alist)))
+    (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+    new))
+
+;;;###autoload
+(defun bmkp-revert-bookmark-file (&optional msg-p) ; Same as `C-u g' in bookmark list (but not bound).
+  "Revert to the bookmarks in the current bookmark file.
+This discards all modifications to bookmarks and the bookmark list
+\(e.g. added/deleted bookmarks).
+This has the same effect as using `C-u \\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-refresh-menu-list]' in \
+buffer `*Bookmark List*'.
+Non-interactively, non-nil MSG-P means display a status message."
+  (interactive "p")
+  (if (and msg-p (not (yes-or-no-p (format "Revert to bookmarks saved in file `%s'? "
+                                           bmkp-current-bookmark-file))))
+      (error "OK - canceled")
+    (bookmark-load bmkp-current-bookmark-file 'OVERWRITE msg-p) ; Do not let `bookmark-load' ask to save.
+    (bmkp-refresh/rebuild-menu-list nil (not msg-p))))
+
+;;;###autoload
+(defun bmkp-switch-bookmark-file (file &optional batchp) ; Not bound and not used in the code now.
+  "Switch to a different bookmark file, FILE.
+Return FILE.  Interactively, you are prompted for FILE.
+Replace all bookmarks in the current bookmark list with those from the
+newly loaded FILE.  Bookmarks are subsequently saved to FILE.
+
+Optional arg BATCHP is passed to `bookmark-load'."
+  (interactive
+   (list  (let* ((std-default  (bmkp-default-bookmark-file))
+                 (default      (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+                                   (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+                                       bookmark-default-file
+                                     std-default)
+                                 bmkp-last-bookmark-file)))
+            (bmkp-read-bookmark-file-name "Switch to bookmark file: "
+                                          (or (file-name-directory default)  "~/")
+                                          default t)))) ; Require that the file exist.
+  (bookmark-load file t batchp))        ; Treat it interactively, if this command is called interactively.
+
+;;;###autoload
+(defun bmkp-switch-to-last-bookmark-file (&optional batchp) ; Not bound to any key, by default
+  "Switch back to the last-used bookmark file.
+Replace all currently existing bookmarks with those newly loaded from
+the last-used file.  Swap the values of `bmkp-last-bookmark-file' and
+`bmkp-current-bookmark-file'.
+
+Optional arg BATCHP is passed to `bookmark-load'."
+  (interactive)
+  (bookmark-load (or bmkp-last-bookmark-file  (bmkp-default-bookmark-file))
+                 t batchp))             ; Treat it interactively, if this command is called interactively.
+
+;;;###autoload
+(defun bmkp-switch-bookmark-file-create (file &optional batchp)
+                                        ; Bound to `C-x p L', (`L' in bookmark list)
+  "Switch to bookmark file FILE, creating it as empty if it does not exist.
+Return FILE.  Interactively, you are prompted for FILE.
+Replace all bookmarks in the current bookmark list with those from the
+newly loaded FILE.  Bookmarks are subsequently saved to FILE.
+
+If there is no file with the name you provide (FILE), then create a
+new, empty bookmark file with that name and use that from now on.
+This empties the bookmark list.  Interactively, you are required to
+confirm this.
+
+Non-nil BATCHP is passed to `bookmark-load'."
+  (interactive
+   (list (let* ((std-default  (bmkp-default-bookmark-file))
+                (default      (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+                                  (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+                                      bookmark-default-file
+                                    std-default)
+                                bmkp-last-bookmark-file)))
+           (bmkp-read-bookmark-file-name "Switch to bookmark file: "
+                                         (or (file-name-directory default)  "~/")
+                                         default))))
+  (let ((empty-p  nil))
+    (if (file-readable-p file)
+;;;     (if (or batchp  (y-or-n-p (format "CONFIRM: `%s' as the current bookmark file? " file)))
+;;;         (bookmark-load file t batchp)
+;;;       (error "OK, canceled"))
+        (bookmark-load file t batchp)   ; Treat it interactively, if this command is called interactively.
+      (setq empty-p  t)
+      (if (and (not batchp)
+               (not (y-or-n-p (format "Create and use NEW, EMPTY bookmark file `%s'? " file))))
+          (error "OK - canceled")
+        (bmkp-empty-file file)
+        (bookmark-load file t batchp))) ; Treat it interactively, if this command is called interactively.
+    (unless batchp (message "Bookmark file is now %s`%s'" (if empty-p "EMPTY file " "") file)))
+  file)
+
+(defun bmkp-read-bookmark-file-name (&optional prompt dir default-filename require-match)
+  "Read and return an (absolute) bookmark file name.
+PROMPT is the prompt to use (default: \"Use bookmark file: \").
+
+DEFAULT-FILENAME is as for `read-file-name', except if nil then the
+default is `.emacs.bmk' in the current directory.  Regardless what
+DEFAULT-FILENAME is, you can enter any file name.
+
+The other args are the same as for `read-file-name'."
+  (let ((insert-default-directory                    t)
+        (icicle-unpropertize-completion-result-flag  t)) ; For `read-file-name'.
+    (expand-file-name
+     (read-file-name (or prompt "Use bookmark file: ") dir (or default-filename
+                                                               (if (> emacs-major-version 22)
+                                                                   (list ".emacs.bmk" bookmark-default-file)
+                                                                 ".emacs.bmk"))
+                     require-match))))
+
+;;;###autoload
+(defun bmkp-empty-file (file &optional confirmp) ; Bound to `C-x p 0'
+  "Empty the bookmark file FILE, or create FILE (empty) if it does not exist.
+In either case, FILE will become an empty bookmark file.  Return FILE.
+
+NOTE: If FILE already exists and you confirm emptying it, no check is
+      made that it is in fact a bookmark file before emptying it.
+      It is simply replaced by an empty bookmark file and saved.
+
+This does NOT also make FILE the current bookmark file.  To do that,
+use `\\[bmkp-switch-bookmark-file-create]' (`bmkp-switch-bookmark-file-create')."
+  (interactive (list (let ((icicle-unpropertize-completion-result-flag  t))
+                       (read-file-name "Create empty bookmark file: " "~/"))
+                     t))
+  (setq file  (expand-file-name file))
+  (bookmark-maybe-load-default-file)
+  (when (and confirmp  (file-exists-p file)
+             (not (y-or-n-p (format "CONFIRM: Empty the existing file `%s'? " file))))
+    (error "OK - canceled"))
+  (let ((bookmark-alist  ()))
+    (bookmark-write-file file (if (file-exists-p file)
+                                  "Emptying bookmark file `%s'..."
+                                "Creating new, empty bookmark file `%s'...")))
+  file)
+
+;;;###autoload
+(defun bmkp-crosshairs-highlight ()     ; Not bound
+  "Call `crosshairs-highlight', unless the region is active.
+You can add this to hook `bookmark-after-jump-hook'.
+You need library `crosshairs.el' to use this command."
+  (interactive)
+  (when (> emacs-major-version 21)      ; No-op for Emacs 20-21.
+    (unless (condition-case nil (require 'crosshairs nil t) (error nil))
+      (error "You need library `crosshairs.el' to use this command"))
+    (unless mark-active
+      (let ((crosshairs-overlay-priority  (and (boundp 'bmkp-light-priorities)
+                                               (1+ (apply #'max
+                                                          (mapcar #'cdr bmkp-light-priorities))))))
+        (crosshairs-highlight)))))
+
+;;;###autoload
+(defun bmkp-choose-navlist-from-bookmark-list (bookmark-name &optional alist) ; Bound to `C-x p B'
+  "Choose a bookmark-list bookmark and set the bookmark navigation list.
+The navigation-list variable, `bmkp-nav-alist', is set to the list of
+bookmarks that would be displayed by `bookmark-bmenu-list' (`C-x r l')
+for the chosen bookmark-list bookmark, sorted and filtered as
+appropriate.
+
+Instead of choosing a bookmark-list bookmark, you can choose the
+pseudo-bookmark `CURRENT *Bookmark List*'.  The bookmarks used for the
+navigation list are those that would be currently shown in the
+`*Bookmark List*' (even if the list is not currently displayed)."
+  (interactive
+   (let ((bookmark-alist  (cons (bmkp-current-bookmark-list-state) (bmkp-bookmark-list-alist-only))))
+     (list (bmkp-read-bookmark-for-type "bookmark-list" bookmark-alist nil nil
+                                        'bmkp-bookmark-list-history "Choose ")
+           bookmark-alist)))
+  (let ((state  (let ((bookmark-alist  (or alist (cons (bmkp-current-bookmark-list-state)
+                                                       (bmkp-bookmark-list-alist-only)))))
+                  (bookmark-prop-get bookmark-name 'bookmark-list))))
+    (let ((bmkp-sort-comparer               (cdr (assq 'last-sort-comparer              state)))
+          (bmkp-reverse-sort-p              (cdr (assq 'last-reverse-sort-p             state)))
+          (bmkp-reverse-multi-sort-p        (cdr (assq 'last-reverse-multi-sort-p       state)))
+          (bmkp-bmenu-omitted-bookmarks     (cdr (assq 'last-bmenu-omitted-bookmarks    state)))
+          (bmkp-bmenu-filter-function       (cdr (assq 'last-bmenu-filter-function      state)))
+          (bmkp-bmenu-filter-pattern        (or (cdr (assq 'last-bmenu-filter-pattern   state)) ""))
+          (bmkp-bmenu-title                 (cdr (assq 'last-bmenu-title                state)))
+          (bookmark-bmenu-toggle-filenames  (cdr (assq 'last-bmenu-toggle-filenames     state))))
+      (setq bmkp-nav-alist             (bmkp-sort-omit
+                                        (if bmkp-bmenu-filter-function
+                                            (funcall bmkp-bmenu-filter-function)
+                                          (if (string= "CURRENT *Bookmark List*" bookmark-name)
+                                              (or bmkp-latest-bookmark-alist bookmark-alist)
+                                            bookmark-alist))
+                                        (and (not (eq bmkp-bmenu-filter-function
+                                                      'bmkp-omitted-alist-only))
+                                             bmkp-bmenu-omitted-bookmarks))
+            bmkp-current-nav-bookmark  (car bmkp-nav-alist))))
+  (message "Bookmark navigation list is now %s"
+           (if (and (string= "CURRENT *Bookmark List*" bookmark-name)
+                    (not (get-buffer "*Bookmark List*")))
+               "the global bookmark list"
+             (format "`%s'" bookmark-name))))
+
+(defun bmkp-current-bookmark-list-state ()
+  "Pseudo-bookmark for the current `*Bookmark List*' state."
+  (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+  (cons "CURRENT *Bookmark List*" (bmkp-make-bookmark-list-record)))
+
+;;;###autoload
+(defun bmkp-choose-navlist-of-type (type) ; Bound to `C-x p :'
+  "Set the bookmark navigation list to the bookmarks of a type you choose.
+The pseudo-type `any' sets the navigation list to all bookmarks.
+This sets variable `bmkp-nav-alist'."
+  (interactive
+   (let* ((completion-ignore-case                      t)
+          (icicle-unpropertize-completion-result-flag  t)
+          (type                                        (completing-read "Type: "
+                                                                        (cons '("any" . bookmark-history)
+                                                                              bmkp-types-alist)
+                                                                        nil t nil nil "any")))
+     (list type)))
+  (setq bmkp-nav-alist  (if (equal "any" type)
+                            bookmark-alist
+                          (funcall (intern (format "bmkp-%s-alist-only" type)))))
+  (unless bmkp-nav-alist (error "No bookmarks"))
+  (setq bmkp-current-nav-bookmark  (car bmkp-nav-alist))
+  (message "Bookmark navigation list is now %s"
+           (if (equal "any" type) "all bookmarks" (format "for type `%s'" type))))
+
+(defun bmkp-autonamed-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an autonamed bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+  (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+  (string-match (format bmkp-autoname-format ".*") bookmark))
+
+(defun bmkp-autonamed-this-buffer-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an autonamed bookmark for this buffer."
+  (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+  (and (bmkp-autonamed-bookmark-p bookmark)  (bmkp-this-buffer-p bookmark)))
+
+(defun bmkp-autonamed-bookmark-for-buffer-p (bookmark buffer-name)
+  "Return non-nil if BOOKMARK is an autonamed bookmark for BUFFER.
+BOOKMARK is a bookmark name or a bookmark record.
+BUFFER-NAME is a string matching the buffer-name part of an autoname.
+This does not check the `buffer-name' entry of BOOKMARK.  It checks
+only the buffer indicated by the bookmark name."
+  (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+  (string-match (format bmkp-autoname-format (regexp-quote buffer-name)) bookmark))
+
+(defun bmkp-update-autonamed-bookmark (bookmark)
+  "Update the name and position of the autonamed BOOKMARK at point.
+Return the updated BOOKMARK: If input was a bookmark name, then return
+ then new name, else the new (full) bookmark.
+It is a good idea to set BOOKMARK to the result of this call.
+BOOKMARK is a bookmark name or a bookmark record."
+  (let ((namep  (stringp bookmark)))
+    (setq bookmark  (bookmark-get-bookmark bookmark))
+    (bookmark-set-position bookmark (point))
+    ;; Autonamed bookmarks do not have regions.  Update `end-position' to be the same as `position'.
+    (when (bmkp-get-end-position bookmark)
+      (bookmark-prop-set bookmark 'end-position (point)))
+    (let ((newname  (funcall bmkp-autoname-bookmark-function (point))))
+      (bookmark-rename (bmkp-bookmark-name-from-record bookmark) newname 'BATCHP)
+      (bmkp-refresh/rebuild-menu-list (bmkp-bookmark-name-from-record bookmark)) ; So display new name.
+      (bmkp-maybe-save-bookmarks))
+    (if namep (bmkp-bookmark-name-from-record bookmark) bookmark))) ; Return updated bookmark or name.
+
+;;;###autoload
+(defun bmkp-this-file/buffer-bmenu-list () ; Bound to `C-x p ,'
+  "Show the bookmark list just for bookmarks for the current file/buffer.
+If visiting a file, this is `bmkp-this-file-bmenu-list'.  Otherwise,
+this is `bmkp-this-buffer-bmenu-list'."
+  (interactive)
+  (if (buffer-file-name) (bmkp-this-file-bmenu-list) (bmkp-this-buffer-bmenu-list)))
+
+;;;###autoload
+(defun bmkp-this-file-bmenu-list ()
+  "Show the bookmark list just for bookmarks for the current file.
+Set `bmkp-last-specific-file' to the current file name.
+If the current buffer is not visiting a file, prompt for the file name."
+  (interactive)
+  (setq bmkp-last-specific-file     (or (buffer-file-name)
+                                        (let ((icicle-unpropertize-completion-result-flag  t))
+                                          (read-file-name "File: ")))
+        bmkp-bmenu-filter-function  'bmkp-last-specific-file-alist-only
+        bmkp-bmenu-title            (format "File `%s' Bookmarks" bmkp-last-specific-file))
+  (let ((bookmark-alist         (funcall bmkp-bmenu-filter-function))
+        (bmkp-bmenu-state-file  nil))   ; Prevent restoring saved state.
+    (unless bookmark-alist (error "No bookmarks for file `%s'" bmkp-last-specific-file))
+    (setq bmkp-latest-bookmark-alist  bookmark-alist)
+    (pop-to-buffer (get-buffer-create "*Bookmark List*"))
+    (bookmark-bmenu-list 'filteredp))
+  (when (interactive-p)
+    (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+                               (format "Only bookmarks for file `%s' are shown"
+                                       bmkp-last-specific-file)))
+  (raise-frame))
+
+;;;###autoload
+(defun bmkp-this-buffer-bmenu-list ()
+  "Show the bookmark list just for bookmarks for the current buffer.
+Set `bmkp-last-specific-buffer' to the current buffer name."
+  (interactive)
+  (setq bmkp-last-specific-buffer   (buffer-name)
+        bmkp-bmenu-filter-function  'bmkp-last-specific-buffer-alist-only
+        bmkp-bmenu-title            (format "Buffer `%s' Bookmarks" bmkp-last-specific-buffer))
+  (let ((bookmark-alist         (funcall bmkp-bmenu-filter-function))
+        (bmkp-bmenu-state-file  nil))   ; Prevent restoring saved state.
+    (unless bookmark-alist (error "No bookmarks for buffer `%s'" bmkp-last-specific-buffer))
+    (setq bmkp-latest-bookmark-alist  bookmark-alist)
+    (pop-to-buffer (get-buffer-create "*Bookmark List*"))
+    (bookmark-bmenu-list 'filteredp))
+  (when (interactive-p)
+    (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+                               (format "Only bookmarks for buffer `%s' are shown"
+                                       bmkp-last-specific-buffer)))
+  (raise-frame))
+
+;;;###autoload
+(defun bmkp-navlist-bmenu-list ()       ; Bound to `C-x p N'
+  "Show the bookmark list just for bookmarks from the navigation list."
+  (interactive)
+  (unless bmkp-nav-alist
+    (bookmark-maybe-load-default-file)
+    (setq bmkp-nav-alist  bookmark-alist)
+    (unless bmkp-nav-alist (error "No bookmarks"))
+    (setq bmkp-current-nav-bookmark  (car bmkp-nav-alist))
+    (message "Bookmark navigation list is now the global bookmark list") (sit-for 2))
+  (setq bmkp-bmenu-title  "Current Navlist Bookmarks")
+  (let ((bookmark-alist         bmkp-nav-alist)
+        (bmkp-bmenu-state-file  nil))   ; Prevent restoring saved state.
+    (unless bookmark-alist (error "No bookmarks"))
+    (setq bmkp-latest-bookmark-alist  bookmark-alist)
+    (pop-to-buffer (get-buffer-create "*Bookmark List*"))
+    (bookmark-bmenu-list 'filteredp))
+  (when (interactive-p)
+    (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+                               "Only bookmarks for the navigation list are shown"))
+  (raise-frame))
+
+(defun bmkp-completing-read-buffer-name (&optional no-default-p)
+  "Read the name of a buffer associated with a bookmark.
+The candidates are the buffers in `bmkp-buffer-names'.
+Non-nil NO-DEFAULT-P means provide no default value.  Used when
+ called in a loop, to let the user exit using empty input.
+If NO-DEFAULT-P is nil, then the default is the current buffer's name,
+ or the value of `bmkp-last-specific-buffer' if the current buffer has
+ no bookmarks."
+  (bookmark-maybe-load-default-file)
+  (let ((icicle-unpropertize-completion-result-flag  t))
+    (completing-read "Buffer: " (mapcar #'list (bmkp-buffer-names)) nil t nil 'buffer-name-history
+                     (and (not no-default-p)
+                          (if (member (buffer-name) (bmkp-buffer-names))
+                              (buffer-name)
+                            bmkp-last-specific-buffer)))))
+
+(defun bmkp-completing-read-file-name (&optional no-default-p)
+  "Read the name of a file associated with a bookmark.
+The candidates are the absolute file names in `bmkp-file-names'.
+Non-nil NO-DEFAULT-P means provide no default value.  Used when
+ called in a loop, to let the user exit using empty input.
+If NO-DEFAULT-P is nil, then the default is the current buffer's file
+ name, if any, or the value of `bmkp-last-specific-file' if the
+ current buffer has no associated file or the file has no bookmarks."
+  (bookmark-maybe-load-default-file)
+  (let ((completion-ignore-case                      (if (boundp 'read-file-name-completion-ignore-case)
+                                                         read-file-name-completion-ignore-case
+                                                       (memq system-type
+                                                             '(ms-dos windows-nt darwin cygwin))))
+        (icicle-unpropertize-completion-result-flag  t))
+    (completing-read "File: " (mapcar #'list (bmkp-file-names)) nil t nil 'file-name-history
+                     (and (not no-default-p)
+                          (let ((file  (buffer-file-name)))
+                            (if (and file (member file (bmkp-file-names)))
+                                file
+                              bmkp-last-specific-file))))))
+
+(defun bmkp-refresh/rebuild-menu-list (&optional bookmark no-msg-p)
+  "Refresh or rebuild buffer `*Bookmark List*'.
+If the buffer is already displayed, call `bmkp-refresh-menu-list'.
+Otherwise, call `bookmark-bmenu-surreptitiously-rebuild-list'.
+Args are the same as for `bmkp-refresh-menu-list'."
+  (let ((bmklistbuf  (get-buffer "*Bookmark List*")))
+    (if (and bmklistbuf  (get-buffer-window bmklistbuf 0))
+        (with-current-buffer bmklistbuf (bmkp-refresh-menu-list bookmark no-msg-p))
+      (bookmark-bmenu-surreptitiously-rebuild-list no-msg-p))))
+
+(defun bmkp-refresh-menu-list (&optional bookmark no-msg-p)
+  "Refresh (revert) the bookmark list (\"menu list\").
+This brings the displayed list up to date.  It does not change the
+current filtering or sorting of the displayed list.
+Non-nil optional arg BOOKMARK means move cursor to BOOKMARK's line.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+  (let ((bookmark-alist  (if bmkp-bmenu-filter-function
+                             (funcall bmkp-bmenu-filter-function)
+                           bookmark-alist)))
+    (setq bmkp-latest-bookmark-alist  bookmark-alist)
+    (unless no-msg-p  (message "Updating bookmark list..."))
+    (bookmark-bmenu-list bmkp-bmenu-filter-function) ; No filter function means start anew.
+    (when bookmark
+      (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+      (with-current-buffer (get-buffer "*Bookmark List*")
+        (bmkp-bmenu-goto-bookmark-named bookmark)
+        (let ((bmenu-win  (get-buffer-window (current-buffer) 0)))
+          (when bmenu-win (set-window-point bmenu-win (point))))))
+    (unless no-msg-p  (message "Updating bookmark list...done"))))
+
+;;;###autoload
+(defun bmkp-unomit-all (&optional msg-p) ; Bound to `O U' in bookmark list
+  "Remove all bookmarks from the list of omitted bookmarks.
+After this, all bookmarks are available for display.
+Non-interactively, non-nil optional arg MSG-P means display a status
+message."
+  (interactive "p")
+  (unless bmkp-bmenu-omitted-bookmarks (error "No omitted bookmarks to UN-omit"))
+  (when msg-p (message "UN-omitting ALL omitted bookmarks..."))
+  (let ((count  0))
+    (dolist (bmk-name  bmkp-bmenu-omitted-bookmarks)
+      (setq bmkp-bmenu-omitted-bookmarks  (bmkp-delete-bookmark-name-from-list
+                                           bmk-name bmkp-bmenu-omitted-bookmarks)
+            count                         (1+ count)))
+    (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+    (when msg-p (message "UN-omitted %d bookmarks" count)))
+  (when (equal (buffer-name (current-buffer)) "*Bookmark List*") (bmkp-bmenu-show-all))
+  (when (and (fboundp 'fit-frame-if-one-window)
+             (equal (buffer-name (current-buffer)) "*Bookmark List*"))
+    (fit-frame-if-one-window)))
+
+(defun bmkp-omitted-alist-only ()
+  "`bookmark-alist', filtered to retain only the omitted bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-omitted-bookmark-p bookmark-alist))
+
+(defun bmkp-omitted-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an omitted bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+  (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+  (bmkp-bookmark-name-member bookmark bmkp-bmenu-omitted-bookmarks))
+
+
+;;(@* "Search-and-Replace Locations of Marked Bookmarks")
+;;  *** Search-and-Replace Locations of Marked Bookmarks ***
+
+(when (> emacs-major-version 22)
+  (defvar bmkp-isearch-bookmarks nil
+    "Bookmarks whose locations are to be incrementally searched.")
+
+  (defun bmkp-isearch-next-bookmark-buffer (&optional bookmark wrap)
+    "Return the next buffer in a series of bookmark buffers.
+Used as a value for `multi-isearch-next-buffer-function', for Isearch
+of multiple bookmarks.
+
+Variable `bmkp-isearch-bookmarks' is a list of bookmarks.  Each
+bookmark in the list is visited by `bookmark--jump-via', and the
+corresponding bookmark buffer is returned."
+    (let ((bookmarks  (if isearch-forward bmkp-isearch-bookmarks (reverse bmkp-isearch-bookmarks))))
+      (bookmark--jump-via
+       (if wrap
+           (car bookmarks)
+         (let ((this-bmk  (catch 'bmkp-isearch-next-bookmark-buffer
+                            (dolist (bmk  bookmarks)
+                              (when (if (bmkp-get-buffer-name bmk)
+                                        (equal (bmkp-get-buffer-name bmk) (buffer-name))
+                                      (equal (bookmark-get-filename bmk) (buffer-file-name)))
+                                (throw 'bmkp-isearch-next-bookmark-buffer bmk)))
+                            (car bookmarks))))
+           (cadr (member this-bmk bookmarks))))
+       'ignore)
+      (current-buffer)))
+
+  (defun bmkp-isearch-bookmarks (bookmarks)
+    "Start multi-bookmark Isearch on BOOKMARKS."
+    (let ((multi-isearch-next-buffer-function  'bmkp-isearch-next-bookmark-buffer)
+          (bmkp-isearch-bookmarks              bookmarks))
+      (bookmark-jump (car bookmarks))
+      (goto-char (if isearch-forward (point-min) (point-max)))
+      (isearch-forward)))
+
+  (defun bmkp-isearch-bookmarks-regexp (bookmarks)
+    "Start multi-bookmark regexp Isearch on BOOKMARKS."
+    (let ((multi-isearch-next-buffer-function  'bmkp-isearch-next-bookmark-buffer)
+          (bmkp-isearch-bookmarks              bookmarks))
+      (bookmark-jump (car bookmarks))
+      (goto-char (if isearch-forward (point-min) (point-max)))
+      (isearch-forward-regexp))))
+
+
+;;(@* "Tags")
+;;  *** Tags ***
+
+(defun bmkp-get-tags (bookmark)
+  "Return the `tags' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  (bookmark-prop-get bookmark 'tags))
+
+(defalias 'bmkp-tagged-bookmark-p 'bmkp-get-tags)
+
+(defun bmkp-get-tag-value (bookmark tag)
+  "Return value of BOOKMARK's tag TAG.
+BOOKMARK is a bookmark name or a bookmark record.
+TAG is a string.
+Return nil if BOOKMARK has no such TAG or if TAG has no value."
+  (assoc-default tag (bmkp-get-tags bookmark)))
+
+(defun bmkp-has-tag-p (bookmark tag)
+  "Return non-nil if BOOKMARK is tagged with TAG.
+BOOKMARK is a bookmark name or a bookmark record.
+TAG is a string."
+  (assoc-default tag (bmkp-get-tags bookmark) nil t))
+
+;; NOT USED currently - we use `bmkp-read-tags-completing' instead.
+(defun bmkp-read-tags ()
+  "Read tags one by one, and return them as a list."
+  (let ((tag    (read-string "Tag (RET for each, empty input to finish): "))
+        (btags  ()))
+    (while (not (string= "" tag))
+      (push tag btags)
+      (setq tag  (read-string "Tag: ")))
+    btags))
+
+(defun bmkp-read-tag-completing (&optional prompt candidate-tags require-match update-tags-alist-p)
+  "Read a tag with completion, and return it as a string.
+The candidate tags available are determined by option
+`bmkp-tags-for-completion'.
+
+PROMPT is the prompt string.  If nil, then use \"Tag: \".
+CANDIDATE-TAGS is an alist of tags to use for completion.
+ If nil, then all tags from all bookmarks are used for completion.
+ The set of all tags is taken from variable `bmkp-tags-alist'.
+REQUIRE-MATCH is passed to `completing-read'.
+Non-nil UPDATE-TAGS-ALIST-P means update var `bmkp-tags-alist'."
+  (bookmark-maybe-load-default-file)
+  (let ((cand-tags                                   (copy-sequence
+                                                      (or candidate-tags
+                                                          (and (not update-tags-alist-p)
+                                                               bmkp-tags-alist) ; Use cached list.
+                                                          (bmkp-tags-list)))) ; Update the cache.
+        (icicle-unpropertize-completion-result-flag  t))
+    (completing-read (or prompt "Tag: ") cand-tags nil require-match nil 'bmkp-tag-history)))
+
+(defun bmkp-read-tags-completing (&optional candidate-tags require-match update-tags-alist-p)
+  "Read tags with completion, and return them as a list of strings.
+Read tags one by one, until you hit `RET' twice consecutively.
+
+CANDIDATE-TAGS is an alist of tags to use for completion.
+ If nil then the candidate tags are taken from variable
+ `bmkp-tags-alist'.
+REQUIRE-MATCH is passed to `completing-read'.
+Non-nil UPDATE-TAGS-ALIST-P means update var `bmkp-tags-alist',
+determining the tags to use per option `bmkp-tags-for-completion'."
+  (bookmark-maybe-load-default-file)
+  (let ((cands                                       ())
+        (btags                                       ())
+        (prompt1                                     "Tag (RET for each, empty input to finish): ")
+        (prompt2                                     "Tag: ")
+        (icicle-unpropertize-completion-result-flag  t)
+        tag old-tag)
+    ;; Make a new candidates alist, with just one entry per tag name.  The original cdr is discarded.
+    (dolist (full-tag  (or candidate-tags
+                           (and (not update-tags-alist-p) bmkp-tags-alist) ; Use cached list.
+                           (bmkp-tags-list)))
+      (add-to-list 'cands (list (if (consp full-tag) (car full-tag) full-tag))))
+    (setq tag    (completing-read prompt1 cands nil require-match nil 'bmkp-tag-history)
+          cands  (delete (assoc tag cands) cands)) ; Tag read is no longer a candidate.
+    (while (not (string= "" tag))
+      (if (member tag btags)            ; User can enter it more than once, if not REQUIRE-MATCH.
+          (message "Tag `%s' already included" tag)
+        (push tag btags))               ; But we only add it once.
+      (setq tag    (completing-read prompt2 cands nil require-match nil 'bmkp-tag-history)
+            cands  (delete (assoc tag cands) cands)))
+    (nreverse btags)))
+
+;;;###autoload
+(defun bmkp-list-all-tags (fullp current-only-p &optional msg-p)
+                                        ; Bound to `C-x p t l', (`T l' in bookmark list)
+  "List bookmark tags.
+Show the list in the minibuffer or, if not enough space, in buffer
+`*All Tags*'.  The tags are listed alphabetically, respecting option
+`case-fold-search'.
+
+With no prefix arg or with a plain prefix arg (`C-u'), the tags listed
+are those defined by option `bmkp-tags-for-completion'.  Otherwise
+\(i.e., with a numeric prefix arg), the tags listed are those from the
+current list of bookmarks only.
+
+With no prefix arg or with a negative prefix arg (e.g. `C--'), list
+only the tag names.  With a non-negative prefix arg (e.g. `C-1' or
+plain `C-u'), list the full alist of tags.
+
+Note that when the full tags alist is shown, the same tag name appears
+once for each of its different values.
+
+Non-interactively, non-nil MSG-P means display a status message."
+  (interactive (list (and current-prefix-arg (> (prefix-numeric-value current-prefix-arg) 0))
+                     (and current-prefix-arg (not (consp current-prefix-arg)))
+                     t))
+  (require 'pp)
+  (when msg-p (message "Gathering tags..."))
+  (pp-display-expression  (sort (bmkp-tags-list (not fullp) current-only-p)
+                                (if fullp
+                                    (lambda (t1 t2) (bmkp-string-less-case-fold-p (car t1) (car t2)))
+                                  'bmkp-string-less-case-fold-p))
+                          "*All Tags"))
+
+(defun bmkp-tags-list (&optional names-only-p current-only-p)
+  "List of all bookmark tags, per option `bmkp-tags-for-completion'.
+Non-nil NAMES-ONLY-P means return a list of only the tag names.
+Otherwise, return an alist of the full tags and set variable
+`bmkp-tags-alist' to that alist, as a cache.
+
+Non-nil CURRENT-ONLY-P means ignore option `bmkp-tags-for-completion'
+and return only the tags for the currently loaded bookmarks."
+  (let ((tags      ())
+        (opt-tags  bmkp-tags-for-completion)
+        bmk-tags)
+    (when (or (eq opt-tags 'current)  current-only-p)  (setq opt-tags '(current)))
+    (dolist (entry  opt-tags)
+      (typecase entry
+        (cons                           ; A bookmark file
+         (when (eq 'bmkfile (car entry))
+           (setq entry  (cdr entry)
+                 tags   (append tags (bmkp-tags-in-bookmark-file entry names-only-p)))))
+        (string (add-to-list 'tags (if names-only-p entry (list entry))))
+        (symbol (when (eq entry 'current)
+                  (bookmark-maybe-load-default-file)
+                  (dolist (bmk  bookmark-alist)
+                    (setq bmk-tags  (bmkp-get-tags bmk))
+                    (dolist (tag  bmk-tags)
+                      (add-to-list 'tags (if names-only-p (bmkp-tag-name tag) (bmkp-full-tag tag)))))))))
+    (unless names-only-p (setq bmkp-tags-alist  tags))
+    tags))
+
+(defun bmkp-tags-in-bookmark-file (file &optional names-only-p)
+  "Return the list of tags from all bookmarks in bookmark-file FILE.
+If FILE is a relative file name, it is expanded in `default-directory.
+If FILE does not name a valid, bookmark file then nil is returned.
+Non-nil NAMES-ONLY-P means return a list of only the tag names.
+Otherwise, return an alist of the full tags.
+"
+  (setq file  (expand-file-name file))
+  (let ((bookmark-save-flag  nil)       ; Just to play safe.
+        (bmk-alist           ())
+        (tags                ())
+        bmk-tags)
+    (if (not (file-readable-p file))
+        (message "Cannot read bookmark file `%s'" file)
+      (with-current-buffer (let ((enable-local-variables  ())) (find-file-noselect file))
+        (goto-char (point-min))
+        (condition-case nil             ; Check whether it's a valid bookmark file.
+            (progn (bookmark-maybe-upgrade-file-format)
+                   (unless (listp (setq bmk-alist  (bookmark-alist-from-buffer))) (error "")))
+          (error (message "Not a valid bookmark file: `%s'" file))))
+      (dolist (bmk  bmk-alist)
+        (setq bmk-tags  (bmkp-get-tags bmk))
+        (dolist (tag  bmk-tags)
+          (add-to-list 'tags (if names-only-p (bmkp-tag-name tag) (bmkp-full-tag tag))))))
+    tags))
+
+(defun bmkp-tag-name (tag)
+  "Name of TAG.  If TAG is an atom, then TAG, else (car TAG)."
+  (if (atom tag) tag (car tag)))
+
+(defun bmkp-full-tag (tag)
+  "Full cons entry for TAG.  If TAG is a cons, then TAG, else (list TAG)."
+  (if (consp tag) tag (list tag)))
+
+;;;###autoload
+(defun bmkp-remove-all-tags (bookmark &optional no-update-p msg-p)
+                                        ; Bound to `C-x p t 0', (`T 0' in bookmark list)
+  "Remove all tags from BOOKMARK.
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+   do not refresh/rebuild the bookmark-list display.
+ - Non-nil optional arg MSG-P means show a message about the removal."
+  (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'msg))
+  (when (and msg-p (null (bmkp-get-tags bookmark))) (error "Bookmark has no tags to remove"))
+  (let ((nb-removed  (and (interactive-p) (length (bmkp-get-tags bookmark)))))
+    (bookmark-prop-set bookmark 'tags ())
+    (unless no-update-p (bmkp-tags-list)) ; Update the tags cache.
+    (bmkp-maybe-save-bookmarks)
+    (when (and msg-p  nb-removed) (message "%d tags removed" nb-removed)))
+  (unless no-update-p
+    (bmkp-refresh/rebuild-menu-list bookmark (not msg-p)))) ; So remove `t' marker and add `*' for BOOKMARK.
+
+;;;###autoload
+(defun bmkp-add-tags (bookmark tags &optional no-update-p msg-p)
+                                        ; `C-x p t + b' (`b' for bookmark), (`T +' in bookmark list)
+  "Add TAGS to BOOKMARK.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+Completion for the bookmark name is strict.
+Completion for tags is lax: you are not limited to existing tags.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time.  Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+* TAGS is a list of strings.
+* Non-nil MSG-P means display a message about the addition.
+* Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+  do not refresh/rebuild the bookmark-list display.
+
+The absolute value of the return value is the number of tags added.
+If BOOKMARK was untagged before the operation, then the return value
+is negative."
+  (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name))
+                     (bmkp-read-tags-completing nil nil current-prefix-arg)
+                     'msg))
+  (let* ((newtags  (copy-alist (bmkp-get-tags bookmark)))
+         (olen     (length newtags)))
+    (dolist (tag  tags)  (unless (or (assoc tag newtags) (member tag newtags))  (push tag newtags)))
+    (bookmark-prop-set bookmark 'tags newtags)
+    (unless no-update-p (bmkp-tags-list)) ; Update the tags cache.
+    (bmkp-maybe-save-bookmarks)
+    (unless no-update-p
+      (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So display `t' and `*' markers for BOOKMARK.
+    (let ((nb-added  (- (length newtags) olen)))
+      (when msg-p (message "%d tags added. Now: %S" nb-added ; Echo just the tag names.
+                           (let ((tgs  (mapcar #'bmkp-tag-name newtags)))
+                             (setq tgs (sort tgs #'string<)))))
+      (when (and (zerop olen)  (> (length newtags) 0))
+        (setq nb-added  (- nb-added)))
+      nb-added)))
+
+;; $$$$$$ Not yet used
+;;;###autoload
+(defun bmkp-set-tag-value-for-navlist (tag value) ; Bound to `C-x p t V'
+  "Set the value of TAG to VALUE, for each bookmark in the navlist.
+If any of the bookmarks has no tag named TAG, then add one with VALUE."
+  (interactive (list (bmkp-read-tag-completing) (read (read-string "Value: ")) 'msg))
+  (bmkp-set-tag-value-for-bookmarks bmkp-nav-alist tag value))
+
+;; $$$$$$ Not yet used
+(defun bmkp-set-tag-value-for-bookmarks (bookmarks tag value) ; Not bound
+  "Set the value of TAG to VALUE, for each of the BOOKMARKS.
+If any of the BOOKMARKS has no tag named TAG, then add one with VALUE."
+  (let ((bookmark-save-flag  (and (not bmkp-count-multi-mods-as-one-flag)
+                                  bookmark-save-flag))) ; Save only after `dolist'.
+    (dolist (bmk  bookmarks) (bmkp-set-tag-value bmk tag value 'NO-UPDATE-P))))
+
+;;;###autoload
+(defun bmkp-set-tag-value (bookmark tag value &optional no-update-p msg-p) ; Bound to `C-x p t v'
+  "For BOOKMARK's TAG, set the value to VALUE.
+If BOOKMARK has no tag named TAG, then add one with value VALUE.
+Non-interactively:
+* Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+* do not refresh/rebuild the bookmark-list display.
+* Non-nil MSG-P means display a message about the updated value."
+  (interactive
+   (let* ((bmk  (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)))
+          (tag  (bmkp-read-tag-completing "Tag: " (mapcar 'bmkp-full-tag (bmkp-get-tags bmk)))))
+     (list bmk tag (read (read-string "Value: ")) 'msg)))
+  (unless (bmkp-has-tag-p bookmark tag) (bmkp-add-tags bookmark (list tag) no-update-p))
+  (let* ((newtags     (copy-alist (bmkp-get-tags bookmark)))
+         (assoc-tag   (assoc tag newtags))
+         (member-tag  (and (not assoc-tag) (member tag newtags))))
+    (if assoc-tag (setcdr assoc-tag value) (setcar member-tag (cons (car member-tag) value)))
+    (bookmark-prop-set bookmark 'tags newtags))
+  (when msg-p "Tag value set"))
+
+;;;###autoload
+(defun bmkp-remove-tags (bookmark tags &optional no-update-p msg-p)
+                                        ; `C-x p t - b' (`b' for bookmark), (`T -' in bookmark list)
+  "Remove TAGS from BOOKMARK.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time.  Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+* TAGS is a list of strings.  The corresponding tags are removed.
+* Non-nil MSG-P means display status messages.
+* Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+  do not refresh/rebuild the bookmark-list display.
+
+The absolute value of the return value is the number of tags removed.
+If BOOKMARK is untagged after the operation, then the return value
+is negative."
+  (interactive (let ((bmk  (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name))))
+                 (list bmk
+                       (bmkp-read-tags-completing (mapcar 'bmkp-full-tag (bmkp-get-tags bmk))
+                                                  t current-prefix-arg)
+                       'msg)))
+  (let* ((remtags  (copy-alist (bmkp-get-tags bookmark)))
+         (olen     (length remtags)))
+    (if (null remtags)
+        (when msg-p (message "Bookmark has no tags to remove")) ; Do nothing if bookmark has no tags.
+      (setq remtags  (bmkp-remove-if (lexical-let ((tgs  tags))
+                                       #'(lambda (tag)
+                                           (if (atom tag) (member tag tgs) (member (car tag) tgs))))
+                                     remtags))
+      (bookmark-prop-set bookmark 'tags remtags)
+      (unless no-update-p (bmkp-tags-list)) ; Update the tags cache.
+      (bmkp-maybe-save-bookmarks)
+      (unless no-update-p
+        (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So remove `t' marker if no tags.
+      (let ((nb-removed  (- olen (length remtags))))
+        (when msg-p (message "%d tags removed. Now: %S" nb-removed ; Echo just the tag names.
+                             (let ((tgs  (mapcar #'bmkp-tag-name remtags)))
+                               (setq tgs (sort tgs #'string<)))))
+        (when (and (zerop (length remtags))  (> olen 0))
+          (setq nb-removed  (- nb-removed)))
+        nb-removed))))
+
+;;;###autoload
+(defun bmkp-remove-tags-from-all (tags &optional msg-p) ; Bound to `C-x p t d', (`T d' in bookmark list)
+  "Remove TAGS from all bookmarks.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter each tag.
+This affects all bookmarks, even those not showing in bookmark list.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time.  Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+* TAGS is a list of strings.  The corresponding tags are removed.
+* Non-nil optional arg MSG-P means show a message about the deletion."
+  (interactive
+   (if (not (y-or-n-p "Delete the tags you specify from ALL bookmarks? "))
+       (error "OK - deletion canceled")
+     (list (bmkp-read-tags-completing nil t current-prefix-arg)
+           'MSG)))
+  (let ((bookmark-save-flag  (and (not bmkp-count-multi-mods-as-one-flag)
+                                  bookmark-save-flag))) ; Save only after `dolist'.
+    (dolist (bmk  (bookmark-all-names)) (bmkp-remove-tags bmk tags 'NO-UPDATE-P)))
+  (bmkp-tags-list)                      ; Update the tags cache (only once, at end).
+  (when msg-p (message "Tags removed from all bookmarks: %S" tags)))
+
+;;;###autoload
+(defun bmkp-rename-tag (tag newname &optional msg-p) ; Bound to `C-x p t r', (`T r' in bookmark list)
+  "Rename TAG to NEWNAME in all bookmarks, even those not showing.
+Non-interactively, non-nil MSG-P means display a message about the
+deletion."
+  (interactive (list (bmkp-read-tag-completing "Tag (old name): ")
+                     (bmkp-read-tag-completing "New name: ")
+                     'MSG))
+  (let ((tag-exists-p        nil)
+        (bookmark-save-flag  (and (not bmkp-count-multi-mods-as-one-flag)
+                                  bookmark-save-flag))) ; Save only after `dolist'.
+    (dolist (bmk  (bookmark-all-names))
+      (let ((newtags  (copy-alist (bmkp-get-tags bmk))))
+        (when newtags
+          (let* ((assoc-tag   (assoc tag newtags))
+                 (member-tag  (and (not assoc-tag) (member tag newtags))))
+            (cond (assoc-tag  (setcar assoc-tag newname))
+                  (member-tag (setcar member-tag newname)))
+            (when (or assoc-tag member-tag)
+              (setq tag-exists-p  t)
+              (bookmark-prop-set bmk 'tags newtags))))))
+    (if tag-exists-p
+        (bmkp-tags-list)                ; Update the tags cache now, after iterate.
+      (error "No such tag: `%s'" tag))
+    (when msg-p (message "Renamed"))))
+
+;;;###autoload
+(defun bmkp-copy-tags (bookmark &optional msg-p) ; Bound to `C-x p t c', `C-x p t M-w'
+  "Copy tags from BOOKMARK, so you can paste them to another bookmark.
+Note that you can copy from a BOOKMARK that has no tags or has an
+empty tags list.  In that case, the copied-tags list is empty, so if
+you paste it as a replacement then the recipient bookmark will end up
+with no tags.
+
+Non-interactively, non-nil MSG-P means display a message about the
+number of tags copied."
+  (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'msg))
+  (let ((btags  (bmkp-get-tags bookmark)))
+    (setq bmkp-copied-tags  (copy-alist btags))
+    (when msg-p (message "%d tags now available for pasting" (length btags)))))
+
+;;;###autoload
+(defun bmkp-paste-add-tags (bookmark &optional no-update-p msg-p) ; Bound to `C-x p t p', `C-x p t C-y'
+  "Add tags to BOOKMARK that were previously copied from another bookmark.
+Return the number of tags added.
+The tags are copied from `bmkp-copied-tags'.
+Non-interactively:
+* Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+  do not refresh/rebuild the bookmark-list display.
+* Non-nil MSG-P means display a message about the addition."
+  (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'msg))
+  (unless (listp bmkp-copied-tags)
+    (error "`bmkp-paste-add-tags': `bmkp-copied-tags' is not a list"))
+  (bmkp-add-tags bookmark bmkp-copied-tags no-update-p msg-p))
+
+;;;###autoload
+(defun bmkp-paste-replace-tags (bookmark &optional no-update-p msg-p) ; Bound to `C-x p t q'
+  "Replace tags for BOOKMARK with those copied from another bookmark.
+Return the number of tags for BOOKMARK.
+The tags are copied from `bmkp-copied-tags'.
+Any previously existing tags for BOOKMARK are lost.
+Non-interactively:
+* Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+  do not refresh/rebuild the bookmark-list display.
+* Non-nil MSG-P means display a message about the addition."
+  (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'msg))
+  (unless (listp bmkp-copied-tags)
+    (error "`bmkp-paste-replace-tags': `bmkp-copied-tags' is not a list"))
+  (let ((has-tags-p  (bmkp-get-tags bookmark)))
+    (when (and msg-p  has-tags-p
+               (not (y-or-n-p "Existing tags will be LOST - really replace them? ")))
+      (error "OK - paste-replace tags canceled"))
+    (when has-tags-p (bmkp-remove-all-tags bookmark no-update-p msg-p)))
+  (bmkp-add-tags bookmark bmkp-copied-tags no-update-p msg-p))
+
+
+;;(@* "Bookmark Predicates")
+;;  *** Bookmark Predicates ***
+
+(defun bmkp-autofile-bookmark-p (bookmark &optional prefix)
+  "Return non-nil if BOOKMARK is an autofile bookmark.
+That means that it is `bmkp-file-bookmark-p' and also its
+non-directory file name is the same as the bookmark name.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+Non-interactively, non-nil optional arg PREFIX means that the bookmark
+name is actually expected to be the file name prefixed by PREFIX (a
+string)."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (and (bmkp-file-bookmark-p bookmark)
+       (let ((fname  (file-name-nondirectory (bookmark-get-filename bookmark))))
+         (string= (if prefix (concat prefix fname) fname)
+                  (bmkp-bookmark-name-from-record bookmark)))))
+
+(defun bmkp-bookmark-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a bookmark-file bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-bookmark-file))
+
+(defun bmkp-bookmark-list-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a bookmark-list bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-bookmark-list))
+
+(defun bmkp-desktop-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a desktop bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-desktop))
+
+;; Note: To avoid remote access, if bookmark does not have the Dired handler, then we insist
+;; that it be for a local directory.  IOW, we do not include remote directories that were not
+;; bookmarked by Bookmark+ (and so do not have the Dired handler).
+(defun bmkp-dired-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a Dired bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (or (eq (bookmark-get-handler bookmark) 'bmkp-jump-dired)
+      (bmkp-local-directory-bookmark-p bookmark)))
+
+(defun bmkp-dired-this-dir-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a Dired bookmark for the `default-directory'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (and (bmkp-dired-bookmark-p bookmark)
+       (let ((dir  (file-name-directory (bookmark-get-filename bookmark))))
+         (bmkp-same-file-p dir default-directory))))
+
+(defun bmkp-dired-wildcards-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks a Dired buffer with wildcards.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (and (bmkp-dired-bookmark-p bookmark)
+       (let ((file  (bookmark-get-filename bookmark)))
+         (and (stringp file) (if (fboundp 'string-match-p)
+                                 (string-match-p (regexp-quote "*") file)
+                               (save-match-data (string-match (regexp-quote "*") file)))))))
+
+(defun bmkp-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks a file or directory.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let* ((filename   (bookmark-get-filename bookmark))
+         (nonfile-p  (equal filename bmkp-non-file-filename))
+         (handler    (bookmark-get-handler bookmark)))
+    (and filename (not nonfile-p)
+         (or (not handler)
+             (memq handler bmkp-file-bookmark-handlers)
+             (equal handler (bmkp-default-handler-for-file filename)))
+         (not (and (bookmark-prop-get bookmark 'info-node)))))) ; Emacs 20-21 Info: no handler.
+
+(defun bmkp-file-this-dir-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks file/subdir in `default-directory'.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (and (bmkp-file-bookmark-p bookmark)
+       (equal (file-name-directory (bookmark-get-filename bookmark)) default-directory)))
+
+(defun bmkp-flagged-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is flagged for deletion in `*Bookmark List*'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (memq bookmark bmkp-flagged-bookmarks))
+
+(defun bmkp-function-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a function bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-function))
+
+(defun bmkp-gnus-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a Gnus bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (memq (bookmark-get-handler bookmark)
+        '(gnus-summary-bookmark-jump bmkp-jump-gnus bmkext-jump-gnus)))
+
+(defun bmkp-image-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an image-file bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (or (eq (bookmark-get-handler bookmark) 'image-bookmark-jump)
+      (and (fboundp 'image-file-name-regexp) ; In `image-file.el' (Emacs 22+).
+           (bmkp-file-bookmark-p bookmark)
+           (not (bmkp-dired-bookmark-p bookmark))
+           (if (fboundp 'string-match-p)
+               (string-match-p (image-file-name-regexp) (bookmark-get-filename bookmark))
+             (save-match-data
+               (string-match (image-file-name-regexp) (bookmark-get-filename bookmark)))))))
+
+(defun bmkp-info-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an Info bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (or (eq (bookmark-get-handler bookmark) 'Info-bookmark-jump)
+      (and (not (bookmark-get-handler bookmark))
+           (or (string= "*info*" (bmkp-get-buffer-name bookmark))
+               (bookmark-prop-get bookmark 'info-node))))) ; Emacs 20-21 - no `buffer-name' entry.
+
+(defun bmkp-local-directory-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks a local directory.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let ((file  (bookmark-get-filename bookmark)))
+    (and (bmkp-local-file-bookmark-p bookmark) (file-directory-p file))))
+
+(defun bmkp-local-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks a local file or directory.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (and (bmkp-file-bookmark-p bookmark) (not (bmkp-remote-file-bookmark-p bookmark))))
+
+(defun bmkp-man-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a `man' page bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (memq (bookmark-get-handler bookmark) '(bmkp-jump-man bmkp-jump-woman
+                                          bmkext-jump-man bmkext-jump-woman)))
+
+(defun bmkp-marked-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a marked bookmark in `*Bookmark List*'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (unless (stringp bookmark) (setq bookmark  (bmkp-bookmark-name-from-record bookmark)))
+  (bmkp-bookmark-name-member bookmark bmkp-bmenu-marked-bookmarks))
+
+(defun bmkp-modified-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a modified bookmark'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (memq bookmark bmkp-modified-bookmarks))
+
+(defun bmkp-non-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a non-file bookmark (e.g *scratch*).
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+It includes bookmarks to existing buffers, as well as bookmarks
+defined for buffers that do not currently exist.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let* ((filename   (bookmark-get-filename bookmark))
+         (nonfile-p  (equal filename bmkp-non-file-filename)))
+    (and (bmkp-get-buffer-name bookmark)
+         (or (not filename) nonfile-p
+             ;; Ensure not remote before calling `file-exists-p'.  (Do not prompt for password.)
+             (and (not (bmkp-file-remote-p filename)) (not (file-exists-p filename))))
+         (not (bookmark-get-handler bookmark)))))
+
+(defun bmkp-orphaned-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an orphaned file or directory bookmark.
+This means that the file recorded for BOOKMARK does not exist or is
+not readable.  But a Dired bookmark with wildcards in the file name is
+assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (and (bmkp-file-bookmark-p bookmark)
+       (if (bmkp-dired-bookmark-p bookmark)
+           (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+                (not (file-readable-p (bookmark-get-filename bookmark))))
+         (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-orphaned-local-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an orphaned local-file bookmark.
+This means that the file name recorded for BOOKMARK is not remote, and
+the file does not exist or is not readable.  But a Dired bookmark with
+wildcards in the file name is assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (and (bmkp-local-file-bookmark-p bookmark)
+       (if (bmkp-dired-bookmark-p bookmark)
+           (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+                (not (file-readable-p (bookmark-get-filename bookmark))))
+         (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-orphaned-remote-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is an orphaned remote-file bookmark.
+This means that the file name recorded for BOOKMARK is remote, and the
+file does not exist or is not readable.  But a Dired bookmark with
+wildcards in the file name is assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark))
+  (and (bmkp-remote-file-bookmark-p bookmark)
+       (if (bmkp-dired-bookmark-p bookmark)
+           (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+                (not (file-readable-p (bookmark-get-filename bookmark))))
+         (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-region-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK has region information.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (and (bmkp-get-end-position bookmark)
+       (/= (bookmark-get-position bookmark) (bmkp-get-end-position bookmark))))
+
+(defun bmkp-remote-file-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK bookmarks a remote file or directory.
+This includes remote Dired bookmarks, but otherwise excludes bookmarks
+with handlers (e.g. Info, Gnus).
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let* ((handler   (bookmark-get-handler bookmark))
+         (file      (bookmark-get-filename bookmark))
+         (rem-file  (and file  (bmkp-file-remote-p file))))
+    (and rem-file  (or (not handler) (eq handler 'bmkp-jump-dired)))))
+
+(defun bmkp-temporary-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is temporary.
+This means that it has a non-nil `bmkp-temp' property.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (setq bookmark  (bookmark-get-bookmark bookmark 'NOERROR))
+  (if (not bookmark) nil (bookmark-prop-get bookmark 'bmkp-temp)))
+
+(defun bmkp-this-buffer-p (bookmark)
+  "Return non-nil if BOOKMARK's buffer is the current buffer.
+But return nil if BOOKMARK has an associated file, but it is not the
+ buffer's file.
+And return nil for bookmarks, such as desktops, that are not really
+ associated with a buffer, even if they have a `buffer-name' entry.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (and (let ((this-file  (condition-case nil (bookmark-buffer-file-name) (error nil)))
+             (bmk-file   (and (bmkp-file-bookmark-p bookmark)  (bookmark-get-filename bookmark))))
+         ;; Two possibilities:
+         ;; * Neither buffer nor bookmark has a file, and the buffer names are the same.
+         ;; * Both have files, and they are the same file.
+         (or (and (not this-file) (not bmk-file)  (equal (bmkp-get-buffer-name bookmark) (buffer-name)))
+             (and this-file bmk-file  (bmkp-same-file-p this-file bmk-file))))
+       (not (bmkp-desktop-bookmark-p        bookmark))
+       (not (bmkp-bookmark-file-bookmark-p  bookmark))
+       (not (bmkp-sequence-bookmark-p       bookmark))
+       (not (bmkp-function-bookmark-p       bookmark))
+       (not (bmkp-variable-list-bookmark-p  bookmark))))
+
+(defun bmkp-this-file-p (bookmark)
+  "Return non-nil if BOOKMARK's file is the visited file.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let ((bmk-file   (and (bmkp-file-bookmark-p bookmark)  (bookmark-get-filename bookmark)))
+        (this-file  (or (and (buffer-file-name) (bookmark-buffer-file-name))
+                        (and (eq major-mode 'dired-mode)  (if (consp dired-directory)
+                                                              (car dired-directory)
+                                                            dired-directory)))))
+    (and bmk-file (bmkp-same-file-p this-file bmk-file))))
+
+(defun bmkp-last-specific-buffer-p (bookmark)
+  "Return t if BOOKMARK's `buffer-name' is `bmkp-last-specific-buffer'.
+But return nil for bookmarks, such as desktops, that are not really
+associated with a buffer, even if they have a `buffer-name' entry.
+It does not matter whether the buffer exists.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let ((buf  (bmkp-get-buffer-name bookmark)))
+    (and buf (string= buf bmkp-last-specific-buffer)
+         (not (bmkp-desktop-bookmark-p        bookmark))
+         (not (bmkp-bookmark-file-bookmark-p  bookmark))
+         (not (bmkp-sequence-bookmark-p       bookmark))
+         (not (bmkp-function-bookmark-p       bookmark))
+         (not (bmkp-variable-list-bookmark-p  bookmark)))))
+
+(defun bmkp-last-specific-file-p (bookmark)
+  "Return t if BOOKMARK's `filename' is `bmkp-last-specific-file'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (let ((file  (bookmark-get-filename bookmark)))
+    (and file (string= file bmkp-last-specific-file))))
+
+(defun bmkp-sequence-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a sequence bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-sequence))
+
+(defun bmkp-url-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a URL bookmark.
+This means that it satifies either `bmkp-url-browse-bookmark-p' or
+`bmkp-w3m-bookmark-p'.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (or (bmkp-url-browse-bookmark-p bookmark) (bmkp-w3m-bookmark-p bookmark)))
+
+(defun bmkp-url-browse-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a `browse-url' bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-url-browse))
+
+(defun bmkp-variable-list-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a variable-list bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (eq (bookmark-get-handler bookmark) 'bmkp-jump-variable-list))
+
+(defun bmkp-w3m-bookmark-p (bookmark)
+  "Return non-nil if BOOKMARK is a W3M bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+  (memq (bookmark-get-handler bookmark) '(bmkp-jump-w3m bmkext-jump-w3m)))
+
+
+;;(@* "Filter Functions")
+;;  *** Filter Functions ***
+
+(defun bmkp-all-tags-alist-only (tags)
+  "`bookmark-alist', but with only bookmarks having all their tags in TAGS.
+Does not include bookmarks that have no tags.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   #'(lambda (bmk)
+       (lexical-let* ((tgs       tags)
+                      (bmk-tags  (bmkp-get-tags bmk)))
+         (and bmk-tags  (bmkp-every #'(lambda (tag) (member (bmkp-tag-name tag) tgs)) bmk-tags))))
+   bookmark-alist))
+
+(defun bmkp-all-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', but with only bookmarks having all tags match REGEXP.
+Does not include bookmarks that have no tags.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk)
+         (let ((bmk-tags  (bmkp-get-tags bmk)))
+           (and bmk-tags  (bmkp-every #'(lambda (tag) (string-match rg (bmkp-tag-name tag))) bmk-tags)))))
+   bookmark-alist))
+
+(defun bmkp-annotated-alist-only ()
+  "`bookmark-alist', but only for bookmarks with non-empty annotations.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (lambda (bmk)
+                        (let ((annotation  (bookmark-get-annotation bmk)))
+                          (and annotation (not (string-equal annotation "")))))
+                      bookmark-alist))
+
+(defun bmkp-autofile-alist-only (&optional prefix)
+  "`bookmark-alist', filtered to retain only autofile bookmarks.
+With non-nil arg PREFIX, the bookmark names must all have that PREFIX."
+  (bookmark-maybe-load-default-file)
+  (if (not prefix)
+      (bmkp-remove-if-not #'bmkp-autofile-bookmark-p bookmark-alist)
+    (bmkp-remove-if-not (lexical-let ((pref  prefix)) #'(lambda (bmk) (bmkp-autofile-bookmark-p bmk pref)))
+                        bookmark-alist)))
+
+(defun bmkp-autofile-all-tags-alist-only (tags)
+  "`bookmark-alist', with only autofiles having all tags in TAGS.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk)
+         (and (bmkp-autofile-bookmark-p bmk)  (bmkp-get-tags bmk)
+              (bmkp-every (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+   bookmark-alist))
+
+(defun bmkp-autofile-all-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', with only autofiles having all tags match REGEXP.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk)
+         (and (bmkp-autofile-bookmark-p bmk)
+              (let ((bmk-tags  (bmkp-get-tags bmk)))
+                (and bmk-tags  (bmkp-every #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                           bmk-tags))))))
+   bookmark-alist))
+
+(defun bmkp-autofile-some-tags-alist-only (tags)
+  "`bookmark-alist', with only autofiles having some tags in TAGS.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   #'(lambda (bmk) (and (bmkp-autofile-bookmark-p bmk)
+                        (bmkp-some (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag)))
+                                   tags)))
+   bookmark-alist))
+
+(defun bmkp-autofile-some-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', with only autofiles having some tags match REGEXP.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk) (and (bmkp-autofile-bookmark-p bmk)
+                          (bmkp-some #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                     (bmkp-get-tags bmk)))))
+   bookmark-alist))
+(defun bmkp-autonamed-alist-only ()
+  "`bookmark-alist', with only autonamed bookmarks (from any buffers).
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p bookmark-alist))
+
+(defun bmkp-autonamed-this-buffer-alist-only ()
+  "`bookmark-alist', with only autonamed bookmarks for the current buffer.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (lambda (bmk) (bmkp-this-buffer-p bmk)) bookmark-alist))
+
+(defun bmkp-bookmark-file-alist-only ()
+  "`bookmark-alist', filtered to retain only bookmark-file bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-bookmark-file-bookmark-p bookmark-alist))
+
+(defun bmkp-bookmark-list-alist-only ()
+  "`bookmark-alist', filtered to retain only bookmark-list bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-bookmark-list-bookmark-p bookmark-alist))
+
+(defun bmkp-desktop-alist-only ()
+  "`bookmark-alist', filtered to retain only desktop bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-desktop-bookmark-p bookmark-alist))
+
+(defun bmkp-dired-alist-only ()
+  "`bookmark-alist', filtered to retain only Dired bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-dired-bookmark-p bookmark-alist))
+
+(defun bmkp-dired-this-dir-alist-only ()
+  "`bookmark-alist', with only Dired bookmarks for the current directory.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-dired-this-dir-bookmark-p bookmark-alist))
+
+(defun bmkp-file-alist-only ()
+  "`bookmark-alist', filtered to retain only file and directory bookmarks.
+This excludes bookmarks that might contain file information but are
+particular in some way - for example, Info bookmarks or Gnus bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-file-bookmark-p bookmark-alist))
+
+(defun bmkp-file-all-tags-alist-only (tags)
+  "`bookmark-alist', with only file bookmarks having all tags in TAGS.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk)
+         (and (bmkp-file-bookmark-p bmk)  (bmkp-get-tags bmk)
+              (bmkp-every (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+   bookmark-alist))
+
+(defun bmkp-file-all-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', with only file bookmarks having all tags match REGEXP.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk)
+         (and (bmkp-file-bookmark-p bmk)
+              (let ((bmk-tags  (bmkp-get-tags bmk)))
+                (and bmk-tags  (bmkp-every #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                           bmk-tags))))))
+   bookmark-alist))
+
+(defun bmkp-file-some-tags-alist-only (tags)
+  "`bookmark-alist', with only file bookmarks having some tags in TAGS.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk) (and (bmkp-file-bookmark-p bmk)
+                          (bmkp-some (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag)))
+                                     tgs))))
+   bookmark-alist))
+
+(defun bmkp-file-some-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', with only file bookmarks having some tags match REGEXP.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk) (and (bmkp-file-bookmark-p bmk)
+                          (bmkp-some #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                     (bmkp-get-tags bmk)))))
+   bookmark-alist))
+
+(defun bmkp-file-this-dir-alist-only ()
+  "`bookmark-alist', filtered with `bmkp-file-this-dir-bookmark-p'.
+Include only files and subdir that are in `default-directory'.
+This excludes bookmarks that might contain file information but are
+particular in some way - for example, Info bookmarks or Gnus bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-file-this-dir-bookmark-p bookmark-alist))
+
+(defun bmkp-file-this-dir-all-tags-alist-only (tags)
+  "`bookmark-alist', for files in this dir having all tags in TAGS.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk)
+         (and (bmkp-file-this-dir-bookmark-p bmk)  (bmkp-get-tags bmk)
+              (bmkp-every (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+   bookmark-alist))
+
+(defun bmkp-file-this-dir-all-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', for files in this dir having all tags match REGEXP.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk)
+         (and (bmkp-file-this-dir-bookmark-p bmk)
+              (let ((bmk-tags  (bmkp-get-tags bmk)))
+                (and bmk-tags
+                     (bmkp-every #'(lambda (tag) (string-match rg (bmkp-tag-name tag))) bmk-tags))))))
+   bookmark-alist))
+
+(defun bmkp-file-this-dir-some-tags-alist-only (tags)
+  "`bookmark-alist', for files in this dir having some tags in TAGS.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk) (and (bmkp-file-this-dir-bookmark-p bmk)
+                          (bmkp-some (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag)))
+                                     tgs))))
+   bookmark-alist))
+
+(defun bmkp-file-this-dir-some-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', for files in this dir having some tags match REGEXP.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((rg  regexp))
+     #'(lambda (bmk) (and (bmkp-file-this-dir-bookmark-p bmk)
+                          (bmkp-some #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                     (bmkp-get-tags bmk)))))
+   bookmark-alist))
+
+(defun bmkp-gnus-alist-only ()
+  "`bookmark-alist', filtered to retain only Gnus bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-gnus-bookmark-p bookmark-alist))
+
+(defun bmkp-image-alist-only ()
+  "`bookmark-alist', filtered to retain only image-file bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-image-bookmark-p bookmark-alist))
+
+(defun bmkp-info-alist-only ()
+  "`bookmark-alist', filtered to retain only Info bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-info-bookmark-p bookmark-alist))
+
+(defun bmkp-last-specific-buffer-alist-only ()
+  "`bookmark-alist', but only for `bmkp-last-specific-buffer'.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-last-specific-buffer-p bookmark-alist))
+
+(defun bmkp-last-specific-file-alist-only ()
+  "`bookmark-alist', but only for `bmkp-last-specific-file'.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-last-specific-file-p bookmark-alist))
+
+(defun bmkp-man-alist-only ()
+  "`bookmark-alist', filtered to retain only `man' page bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-man-bookmark-p bookmark-alist))
+
+(defun bmkp-local-file-alist-only ()
+  "`bookmark-alist', filtered to retain only local-file bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-local-file-bookmark-p bookmark-alist))
+
+(defun bmkp-non-autonamed-alist-only ()
+  "`bookmark-alist', with only non-autonamed bookmarks (from any buffers).
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (lambda (bmk) (not (bmkp-autonamed-bookmark-p bmk))) bookmark-alist))
+
+(defun bmkp-non-file-alist-only ()
+  "`bookmark-alist', filtered to retain only non-file bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-non-file-bookmark-p bookmark-alist))
+
+(defun bmkp-orphaned-file-alist-only ()
+  "`bookmark-alist', filtered to retain only orphaned file bookmarks."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-orphaned-file-bookmark-p bookmark-alist))
+
+(defun bmkp-orphaned-local-file-alist-only ()
+  "`bookmark-alist', but retaining only orphaned local-file bookmarks."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-orphaned-local-file-bookmark-p bookmark-alist))
+
+(defun bmkp-orphaned-remote-file-alist-only ()
+  "`bookmark-alist', but retaining only orphaned remote-file bookmarks."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-orphaned-remote-file-bookmark-p bookmark-alist))
+
+(defun bmkp-regexp-filtered-annotation-alist-only ()
+  "`bookmark-alist' for annotations matching `bmkp-bmenu-filter-pattern'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not
+   #'(lambda (bmk)
+       (let ((annot  (bookmark-get-annotation bmk)))
+         (and (stringp annot) (not (string= "" annot))
+              (string-match bmkp-bmenu-filter-pattern annot))))
+   bookmark-alist))                     ; (Could use `bmkp-annotated-alist-only' here instead.)
+
+(defun bmkp-regexp-filtered-bookmark-name-alist-only ()
+  "`bookmark-alist' for bookmarks matching `bmkp-bmenu-filter-pattern'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not
+   #'(lambda (bmk) (string-match bmkp-bmenu-filter-pattern (car bmk))) bookmark-alist))
+
+(defun bmkp-regexp-filtered-file-name-alist-only ()
+  "`bookmark-alist' for files matching `bmkp-bmenu-filter-pattern'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'(lambda (bmk) (let ((fname  (bookmark-get-filename bmk)))
+                                        (and fname  (string-match bmkp-bmenu-filter-pattern fname))))
+                      bookmark-alist))
+
+(defun bmkp-regexp-filtered-tags-alist-only ()
+  "`bookmark-alist' for tags matching `bmkp-bmenu-filter-pattern'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'(lambda (bmk)
+                          (let ((bmk-tags  (bmkp-get-tags bmk)))
+                            (and bmk-tags (bmkp-some #'(lambda (tag) (string-match bmkp-bmenu-filter-pattern
+                                                                                   (bmkp-tag-name tag)))
+                                                     bmk-tags))))
+                      bookmark-alist))
+
+(defun bmkp-region-alist-only ()
+  "`bookmark-alist', filtered to retain only bookmarks that have regions.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-region-bookmark-p bookmark-alist))
+
+(defun bmkp-remote-file-alist-only ()
+  "`bookmark-alist', filtered to retain only remote-file bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-remote-file-bookmark-p bookmark-alist))
+
+(defun bmkp-some-tags-alist-only (tags)
+  "`bookmark-alist', but with only bookmarks having some tags in TAGS.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not
+   (lexical-let ((tgs  tags))
+     #'(lambda (bmk) (bmkp-some (lexical-let ((bk  bmk)) #'(lambda (tag) (bmkp-has-tag-p bk tag))) tgs)))
+   bookmark-alist))
+
+(defun bmkp-some-tags-regexp-alist-only (regexp)
+  "`bookmark-alist', but with only bookmarks having some tags match REGEXP.
+A new list is returned (no side effects)."
+  (bmkp-remove-if-not (lexical-let ((rg  regexp))
+                        #'(lambda (bmk) (bmkp-some #'(lambda (tag) (string-match rg (bmkp-tag-name tag)))
+                                                   (bmkp-get-tags bmk))))
+                      bookmark-alist))
+
+(defun bmkp-specific-buffers-alist-only (&optional buffers)
+  "`bookmark-alist', filtered to retain only bookmarks to buffers BUFFERS.
+BUFFERS is a list of buffer names.
+It defaults to a singleton list with the current buffer's name.
+A new list is returned (no side effects).
+
+Note: Bookmarks created by vanilla Emacs do not record the buffer
+name.  They are therefore excluded from the returned alist."
+  (unless buffers  (setq buffers  (list (buffer-name))))
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (lexical-let ((bufs  buffers))
+                        #'(lambda (bmk)
+                            (and (not (bmkp-desktop-bookmark-p       bmk)) ; Exclude these
+                                 (not (bmkp-bookmark-file-bookmark-p bmk))
+                                 (not (bmkp-sequence-bookmark-p      bmk))
+                                 (not (bmkp-function-bookmark-p      bmk))
+                                 (not (bmkp-variable-list-bookmark-p bmk))
+                                 (member (bmkp-get-buffer-name bmk) bufs))))
+                      bookmark-alist))
+
+(defun bmkp-specific-files-alist-only (&optional files)
+  "`bookmark-alist', filtered to retain only bookmarks to files FILES.
+FILES is a list of absolute file names.
+It defaults to a singleton list with the current buffer's file name.
+A new list is returned (no side effects)."
+  (unless files  (setq files  (list (buffer-file-name))))
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (lexical-let ((ff  files)) #'(lambda (bmk) (member (bookmark-get-filename bmk) ff)))
+                      bookmark-alist))
+
+(defun bmkp-temporary-alist-only ()
+  "`bookmark-alist', filtered to retain only temporary bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-temporary-bookmark-p bookmark-alist))
+
+(defun bmkp-this-file/buffer-alist-only ()
+  "`bookmark-alist', with only bookmarks for the current file/buffer.
+A new list is returned (no side effects).
+If visiting a file, this is `bmkp-this-file-alist-only'.
+Otherwise, this is `bmkp-this-buffer-alist-only'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not (if (buffer-file-name) #'bmkp-this-file-p #'bmkp-this-buffer-p) bookmark-alist))
+
+(defun bmkp-this-buffer-alist-only ()
+  "`bookmark-alist', with only bookmarks for the current buffer.
+A new list is returned (no side effects).
+See `bmkp-this-buffer-p'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-this-buffer-p bookmark-alist))
+
+(defun bmkp-this-file-alist-only ()
+  "`bookmark-alist', with only bookmarks for the current file.
+A new list is returned (no side effects).
+See `bmkp-this-file-p'."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-this-file-p bookmark-alist))
+
+(defun bmkp-url-alist-only ()
+  "`bookmark-alist', filtered to retain only URL bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-url-bookmark-p bookmark-alist))
+
+(defun bmkp-url-browse-alist-only ()
+  "`bookmark-alist', filtered to retain only non-W3M URL bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-url-browse-bookmark-p bookmark-alist))
+
+(defun bmkp-variable-list-alist-only ()
+  "`bookmark-alist', filtered to retain only variable-list bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-variable-list-bookmark-p bookmark-alist))
+
+(defun bmkp-w3m-alist-only ()
+  "`bookmark-alist', filtered to retain only W3M bookmarks.
+A new list is returned (no side effects)."
+  (bookmark-maybe-load-default-file)
+  (bmkp-remove-if-not #'bmkp-w3m-bookmark-p bookmark-alist))
+
+
+;;; Marked bookmarks
+
+(defun bmkp-marked-bookmarks-only ()
+  "Return the list of marked bookmarks."
+  (bmkp-remove-if-not #'bmkp-marked-bookmark-p bookmark-alist))
+
+(defun bmkp-unmarked-bookmarks-only ()
+  "Return the list of unmarked bookmarks."
+  (bmkp-remove-if #'bmkp-marked-bookmark-p bookmark-alist))
+
+(defun bmkp-some-marked-p (alist)
+  "Return non-nil if ALIST is nonempty and includes a marked bookmark."
+  (catch 'break (dolist (i  alist)  (and (bmkp-marked-bookmark-p i)  (throw 'break t)))))
+
+(defun bmkp-some-unmarked-p (alist)
+  "Return non-nil if ALIST is nonempty and includes an unmarked bookmark."
+  (catch 'break (dolist (i  alist)  (and (not (bmkp-marked-bookmark-p i))  (throw 'break t)))))
+
+
+;;(@* "General Utility Functions")
+;;  *** General Utility Functions ***
+
+(when (and (fboundp 'cl-puthash) (not (fboundp 'puthash))) ; Emacs 20 with `cl-extra.el' loaded.
+  (defalias 'puthash 'cl-puthash))
+
+(if (fboundp 'puthash)                  ; Emacs 21+, or Emacs 20 with `cl-extra.el' loaded.
+    (defun bmkp-remove-dups (sequence &optional test)
+      "Copy of SEQUENCE with duplicate elements removed.
+Optional arg TEST is the test function.  If nil, test with `equal'.
+See `make-hash-table' for possible values of TEST."
+      (setq test  (or test #'equal))
+      (let ((htable  (make-hash-table :test test)))
+        (loop for elt in sequence
+              unless (gethash elt htable)
+              do     (puthash elt elt htable)
+              finally return (loop for i being the hash-values in htable collect i))))
+
+  (defun bmkp-remove-dups (list &optional use-eq)
+    "Copy of LIST with duplicate elements removed.
+Test using `equal' by default, or `eq' if optional USE-EQ is non-nil."
+    (let ((tail  list)
+          new)
+      (while tail
+        (unless (if use-eq (memq (car tail) new) (member (car tail) new))
+          (push (car tail) new))
+        (pop tail))
+      (nreverse new))))
+
+;; For a name propertized with `bmkp-full-record', this is similar to `bmkp-assoc-delete-all'.
+(defun bmkp-delete-bookmark-name-from-list (delname bnames)
+  "Delete names that represent the same bookmark as DELNAME from BNAMES.
+This means that they are `string=' and they either have no property
+`bmkp-full-record' or that property has the same value.
+Return the modified list BNAMES."
+  ;; $$$$$$ Can we change `equal' to `eq' everywhere here?
+  (let ((delprop  (get-text-property 0 'bmkp-full-record delname))
+        bmkprop)
+    (if (not delprop)
+        (setq bnames  (delete delname bnames)) ; Unpropertized - just use `delete'.
+      ;; Propertized.  Delete names that are `string=' and have the same property value or none.
+      (while (and bnames  (string= delname (car bnames)) ; Delete those at list beginning.
+                  (or (not (setq bmkprop  (get-text-property 0 'bmkp-full-record (car bnames))))
+                      (equal delprop bmkprop)))
+        (setq bnames  (cdr bnames)))
+      (let ((tail  bnames)              ; Delete those not at list beginning.
+            tail-cdr)
+        (while (setq tail-cdr  (cdr tail))
+          (if (and (car tail-cdr)
+                   (string= delname (car tail-cdr))
+                   (or (not (setq bmkprop  (get-text-property 0 'bmkp-full-record (car tail-cdr))))
+                       (equal delprop bmkprop)))
+              (setcdr tail  (cdr tail-cdr))
+            (setq tail  tail-cdr))))
+      bnames)))
+
+(defun bmkp-bookmark-name-member (name names)
+  "Like `member', but tests also bookmark NAME's `bmkp-full-record' property.
+Return the tail of NAMES whose car is NAME with the property match.
+If NAME has no `bmkp-full-record' property then this is just `member'.
+If NAME has property `bmkp-full-record', then test whether both:
+ a. NAME is a member of NAMES and
+ b. NAME has the same `bmkp-full-record' value as an element of NAMES."
+  ;; $$$$$$ Can we change `equal' to `eq' here?
+  (let ((prop  (get-text-property 0 'bmkp-full-record name)))
+    (if (not prop)
+        (member name names)             ; Unpropertized - just use `member'.
+      (while (and names  (not (and (string= name (car names)) ; = `bmkp-names-same-bookmark-p'.
+                                   ;; If unpropertized in NAMES, then assume it's the one.
+                                   (or (not (get-text-property 0 'bmkp-full-record (car names)))
+                                       (equal prop (get-text-property 0 'bmkp-full-record (car names)))))))
+        (setq names  (cdr names)))
+      names)))
+
+(defun bmkp-names-same-bookmark-p (name1 name2)
+  "Return non-nil if the two strings name the same bookmark.
+The strings are `string=' and their `bmkp-full-record' property values
+for the first character are `equal'."
+
+  ;; $$$$$$ Can we change `equal' to `eq' here?
+  (and (string= name1 name2)
+       (equal (get-text-property 0 'bmkp-full-record name1)
+              (get-text-property 0 'bmkp-full-record name2))))
+
+(defun bmkp-remove-if (pred xs)
+  "A copy of list XS with no elements that satisfy predicate PRED."
+  (let ((result  ()))
+    (dolist (x  xs)  (unless (funcall pred x) (push x result)))
+    (nreverse result)))
+
+(defun bmkp-remove-if-not (pred xs)
+  "A copy of list XS with only elements that satisfy predicate PRED."
+  (let ((result  ()))
+    (dolist (x  xs)  (when (funcall pred x) (push x result)))
+    (nreverse result)))
+
+;; Similar to `every' in `cl-extra.el', without non-list sequences and multiple sequences.
+(defun bmkp-every (predicate list)
+  "Return t if PREDICATE is true for all elements of LIST; else nil."
+  (while (and list (funcall predicate (car list))) (setq list  (cdr list)))
+  (null list))
+
+;; Similar to `some' in `cl-extra.el', without non-list sequences and multiple sequences.
+(defun bmkp-some (predicate list)
+  "Return non-nil if PREDICATE is true for some element of LIST; else nil.
+Return the first non-nil value returned by PREDICATE."
+  (let ((res  nil))
+    (while (and list (not (setq res  (funcall predicate (pop list))))))
+    res))
+
+;; From `cl-seq.el', function `union', without keyword treatment.
+;; (Same as `icicle-set-union' in `icicles-fn.el'.)
+(defun bmkp-set-union (list1 list2)
+  "Combine LIST1 and LIST2 using a set-union operation.
+The result list contains all items that appear in either LIST1 or
+LIST2.  Comparison is done using `equal'.  This is a non-destructive
+function; it copies the data if necessary."
+  (cond ((null list1)         list2)
+        ((null list2)         list1)
+        ((equal list1 list2)  list1)
+        (t
+         (unless (>= (length list1) (length list2))
+           (setq list1  (prog1 list2 (setq list2  list1)))) ; Swap them.
+         (while list2
+           (unless (member (car list2) list1)  (setq list1  (cons (car list2) list1)))
+           (setq list2  (cdr list2)))
+         list1)))
+
+(defun bmkp-upcase (string)
+  "`upcase', but in case of error, return original STRING.
+This works around an Emacs 20 problem that occurs if STRING contains
+binary data (weird chars)."
+  (condition-case nil (upcase string) (error string)))
+
+;; Thx to Michael Heerdegen and Michael Albinus for help with this one.
+(defun bmkp-same-file-p (file1 file2)
+  "Return non-nil if FILE1 and FILE2 name the same file.
+If either name is not absolute, then it is expanded relative to
+`default-directory' for the test."
+  (let* ((remote1        (bmkp-file-remote-p file1))
+         (remote2        (bmkp-file-remote-p file2))
+         (ignore-case-p  (and (not remote1) (not remote2) ; Assume case-sensitive if remote.
+                              (if (boundp 'read-file-name-completion-ignore-case)
+                                  (eval (car (get 'read-file-name-completion-ignore-case
+                                                  'standard-value)))
+                                ;; From the Emacs 24 definition of `read-file-name-completion-ignore-case'.
+                                (memq system-type '(ms-dos windows-nt darwin cygwin))))))
+    (and (equal remote1 remote2)
+         (if (fboundp 'file-equal-p)
+             (file-equal-p file1 file2)
+           (let ((ft1  (file-truename (expand-file-name file1)))
+                 (ft2  (file-truename (expand-file-name file2))))
+             (eq t (compare-strings ft1 0 (length ft1) ft2 0 (length ft2) ignore-case-p)))))))
+
+;;; $$$$$$
+;;; (defun bmkp-same-file-p (file1 file2)
+;;;   "Return non-nil if FILE1 and FILE2 name the same file.
+;;; If either name is not absolute, then it is expanded relative to
+;;; `default-directory' for the test."
+;;;   (and (equal (bmkp-file-remote-p file1) (bmkp-file-remote-p file2))
+;;;        (string= (file-truename (expand-file-name file1))
+;;;                 (file-truename (expand-file-name file2)))))
+
+;;; $$$$$$
+;;; (defun bmkp-file-remote-p (file-name)
+;;;   "Returns non-nil if string FILE-NAME is likely to name a remote file."
+;;;   (if (fboundp 'file-remote-p)
+;;;       (file-remote-p file-name)
+;;;     (and (fboundp 'ffap-file-remote-p) (ffap-file-remote-p file-name))))
+
+(defun bmkp-file-remote-p (file)
+  "Test whether FILE specifies a location on a remote system.
+Return nil or a string identifying the remote connection (ideally a
+prefix of FILE).
+
+A file is considered remote if accessing it is likely to be slower or
+less reliable than accessing local files.
+
+This is `file-remote-p', if that function is available.  If not, use a
+simple match against rough remote file syntax: `/...:'.
+
+Unless `file-remote-p' is available and FILE has a `file-remote-p'
+handler that opens a remote connection, `bmkp-file-remote-p' does not
+open a remote connection."
+  (if (fboundp 'file-remote-p)
+      (file-remote-p file)
+    (and (stringp file) (string-match "\\`/[^/]+:" file)
+         (match-string 0 file))))
+
+(defun bmkp-float-time (&optional specified-time)
+  "Same as `float-time'.  (Needed for Emacs 20.)"
+  (if (fboundp 'float-time)
+      (float-time specified-time)
+    (unless specified-time (setq specified-time  (current-time)))
+    (+ (* (float (nth 0 specified-time)) (expt 2 16))  (nth 1 specified-time))))
+
+(defun bmkp-string-less-case-fold-p (s1 s2)
+  "Like `string-lessp', but respect `case-fold-search'."
+  (when case-fold-search (setq s1  (bmkp-upcase s1)
+                               s2  (bmkp-upcase s2)))
+  (string-lessp s1 s2))
+
+(defun bmkp-make-plain-predicate (pred &optional final-pred)
+  "Return a plain predicate that corresponds to component-predicate PRED.
+PRED and FINAL-PRED correspond to their namesakes in
+`bmkp-sort-comparer' (which see).
+
+PRED should return `(t)', `(nil)', or nil.
+
+Optional arg FINAL-PRED is the final predicate to use if PRED cannot
+decide (returns nil).  If FINAL-PRED is nil, then `bmkp-alpha-p', the
+plain-predicate equivalent of `bmkp-alpha-cp' is used as the final
+predicate."
+  `(lambda (b1 b2) (let ((res  (funcall ',pred b1 b2)))
+                     (if res (car res) (funcall ',(or final-pred 'bmkp-alpha-p) b1 b2)))))
+
+(defun bmkp-repeat-command (command)
+  "Repeat COMMAND."
+  (let ((repeat-message-function  'ignore))
+    (setq last-repeatable-command  command)
+    (repeat nil)))
+
+
+;;; If you need this for some reason, uncomment it.
+;;; (defun bmkp-fix-bookmark-alist-and-save ()
+;;;   "Update format of `bookmark-default-file' created in summer of 2009.
+;;; You DO NOT NEED THIS, unless you happen to have used `bookmark+.el' in
+;;; the summer of 2009 to create non-file bookmarks.  If you did that,
+;;; then some of those bookmarks might cause vanilla Emacs (emacs -Q) to
+;;; raise an error.  You can use this command to fix that problem: it
+;;; modifies your existing `bookmark-default-file' (`.emacs.bmk'), after
+;;; backing up that file (suffixing the name with \"_saveNUMBER\")."
+;;;   (interactive)
+;;;   (require 'cl)                         ; For `gensym'
+;;;   (if (not (yes-or-no-p
+;;;              "This will modify your bookmark file, after backing it up.  OK? "))
+;;;       (message "OK, nothing done")
+;;;     (bookmark-maybe-load-default-file)
+;;;     (let ((bkup-file  (concat bookmark-default-file "_" (symbol-name (gensym "save")))))
+;;;       (when (condition-case err
+;;;                 (progn
+;;;                   (with-current-buffer (find-file-noselect bookmark-default-file)
+;;;                     (write-file bkup-file))
+;;;                   (dolist (bmk  bookmark-alist)
+;;;                     (let ((fn-tail  (member '(filename) bmk))
+;;;                           (hdlr     (bookmark-get-handler (car bmk))))
+;;;                       (cond (fn-tail
+;;;                              (setcar fn-tail (cons 'filename bmkp-non-file-filename)))
+;;;                             ((and (eq hdlr 'bmkp-jump-gnus)
+;;;                                   (not (assoc 'filename bmk)))
+;;;                              (setcdr bmk (cons (cons 'filename bmkp-non-file-filename)
+;;;                                                (cdr bmk)))))))
+;;;                   t)                    ; Be sure `dolist' exit with t to allow saving.
+;;;               (error (error "No changes made. %s" (error-message-string err))))
+;;;         (bookmark-save)
+;;;         (message "Bookmarks file fixed.  Old version is `%s'" bkup-file)))))
+
+
+;;(@* "Bookmark Entry Access Functions")
+;;  *** Bookmark Entry Access Functions ***
+
+(defun bmkp-get-buffer-name (bookmark)
+  "Return the `buffer-name' value for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  (bookmark-prop-get bookmark 'buffer-name))
+
+(defun bmkp-get-end-position (bookmark)
+  "Return the `end-position' value for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  (bookmark-prop-get bookmark 'end-position))
+
+(defun bmkp-get-visits-count (bookmark)
+  "Return the `visits' count for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  (bookmark-prop-get bookmark 'visits))
+
+(defun bmkp-get-visit-time (bookmark)
+  "Return the `time' value for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+  ;; Should just be a prop-get, but when first implemented, we used a float
+  ;; instead of a time cons, so we need to convert any such obsolete recorded times.
+  (let ((vt  (bookmark-prop-get bookmark 'time)))
+    (when (numberp vt)                  ; Convert mid-2009 time values (floats) to cons form.
+      (setq vt  (if (boundp 'seconds-to-time)
+                    (seconds-to-time vt)
+                  (list (floor vt 65536) ; Inlined `seconds-to-time', for Emacs 20-21.
+                        (floor (mod vt 65536))
+                        (floor (* (- vt (ffloor vt)) 1000000))))))
+    vt))
+
+
+;;(@* "Sorting - General Functions")
+;;  *** Sorting - General Functions ***
+
+(defun bmkp-sort-omit (alist &optional omit)
+  "Sort a copy of ALIST, omitting any elements whose keys are in OMIT.
+Return the copy.
+Do not sort if `bmkp-sort-comparer' is nil.
+This is a non-destructive operation: ALIST is not modified.
+
+Sorting is done using using `bmkp-sort-comparer'.
+If `bmkp-reverse-sort-p' is non-nil, then reverse the sort order.
+Keys are compared for sorting using `equal'.
+
+If optional arg OMIT is non-nil, then it is a list of keys.  Omit from
+the return value any elements with keys in the list."
+  (lexical-let ((new-alist  (bmkp-remove-omitted alist omit))
+                (sort-fn    (and bmkp-sort-comparer  (if (and (not (functionp bmkp-sort-comparer))
+                                                              (consp bmkp-sort-comparer))
+                                                         'bmkp-multi-sort
+                                                       bmkp-sort-comparer))))
+    (when sort-fn
+      (setq new-alist  (sort new-alist (if bmkp-reverse-sort-p
+                                           #'(lambda (a b) (not (funcall sort-fn a b)))
+                                         sort-fn))))
+    new-alist))
+
+(defun bmkp-remove-omitted (alist &optional omit)
+  "Copy of bookmark ALIST without bookmarks whose names are in list OMIT.
+Name comparison is done using `bmkp-bookmark-name-member'.
+If optional arg OMIT is non-nil, then omit from the return value any
+elements with keys in list OMIT."
+  (let ((new  ()))
+    (dolist (ii  alist)  (unless (bmkp-bookmark-name-member (car ii) omit)  (push ii new)))
+    (nreverse new)))
+
+;;; $$$$$$ No longer used.
+;;; (defun bmkp-sort-and-remove-dups (alist &optional omit)
+;;;   "Remove duplicates from a copy of ALIST, then sort it and return it.
+;;; Do not sort if `bmkp-sort-comparer' is nil.
+;;; Always remove duplicates.  Keep only the first element with a given
+;;; key.  This is a non-destructive operation: ALIST is not modified.
+
+;;; Sorting is done using using `bmkp-sort-comparer'.
+;;; If `bmkp-reverse-sort-p' is non-nil, then reverse the sort order.
+;;; Keys are compared for sorting using `equal'.
+;;; If optional arg OMIT is non-nil, then omit from the return value any
+;;; elements with keys in list OMIT."
+;;;   (lexical-let ((new-alist  (bmkp-remove-assoc-dups alist omit))
+;;;                (sort-fn  (and bmkp-sort-comparer  (if (and (not (functionp bmkp-sort-comparer))
+;;;                                                     (consp bmkp-sort-comparer))
+;;;                                                            'bmkp-multi-sort
+;;;                                                    bmkp-sort-comparer))))
+;;;     (when sort-fn
+;;;       (setq new-alist  (sort new-alist (if bmkp-reverse-sort-p
+;;;                                            #'(lambda (a b) (not (funcall sort-fn a b)))
+;;;                                          sort-fn))))
+;;;     new-alist))
+
+;;; KEEP this simpler version also.  This uses `run-hook-with-args-until-success', but it
+;;; does not respect `bmkp-reverse-multi-sort-p'.
+;;; (defun bmkp-multi-sort (b1 b2)
+;;;   "Try predicates in `bmkp-sort-comparer', in order, until one decides.
+;;; See the description of `bmkp-sort-comparer'."
+;;;   (let* ((preds   (append (car bmkp-sort-comparer) (cdr bmkp-sort-comparer)))
+;;;          (result  (run-hook-with-args-until-success 'preds b1 b2)))
+;;;     (if (consp result)
+;;;         (car result)
+;;;       result)))
+
+;;; $$$$$$ No longer used.
+;;; (defun bmkp-remove-assoc-dups (alist &optional omit)
+;;;   "Shallow copy of ALIST without elements that have duplicate keys.
+;;; Only the first element of those with the same key is kept.
+;;; Keys are compared using `equal'.
+;;; If optional arg OMIT is non-nil, then omit from the return value any
+;;; elements with keys in list OMIT."
+;;;   (let ((new  ()))
+;;;     (dolist (ii  alist)  (unless (or (assoc (car ii) new) (member (car ii) omit))  (push ii new)))
+;;;     (nreverse new)))
+
+
+;; This Lisp definition respects `bmkp-reverse-multi-sort-p', and can be extended.
+(defun bmkp-multi-sort (b1 b2)
+  "Try predicates in `bmkp-sort-comparer', in order, until one decides.
+See the description of `bmkp-sort-comparer'.
+If `bmkp-reverse-multi-sort-p' is non-nil, then reverse the order for
+using multi-sorting predicates."
+  (let ((preds       (car bmkp-sort-comparer))
+        (final-pred  (cadr bmkp-sort-comparer))
+        (result      nil))
+    (when bmkp-reverse-multi-sort-p (setq preds  (reverse preds)))
+    (catch 'bmkp-multi-sort
+      (dolist (pred  preds)
+        (setq result  (funcall pred b1 b2))
+        (when (consp result)
+          (when bmkp-reverse-multi-sort-p (setq result  (list (not (car result)))))
+          (throw 'bmkp-multi-sort (car result))))
+      (and final-pred  (if bmkp-reverse-multi-sort-p
+                           (not (funcall final-pred b1 b2))
+                         (funcall final-pred b1 b2))))))
+
+;; The message is only approximate.  The effect of `bmkp-reverse-multi-sort-p' is not
+;; always intuitive, but it can often be useful.  What's not always intuitive is the placement
+;; (the order) of bookmarks that are not sorted by the PREDs.
+;;
+(defun bmkp-msg-about-sort-order (order &optional prefix-msg suffix-msg)
+  "Display a message mentioning the current sort ORDER and direction.
+Optional arg PREFIX-MSG is prepended to the constructed message, and
+terminated with a period.
+Similarly, SUFFIX-MSG is appended, after appending \".  \"."
+  (let ((msg  (if (not bmkp-sort-comparer)
+                  "Bookmarks NOT sorted"
+                (format "%s%s" (concat "Sorted " order)
+                        (if (not (and (consp bmkp-sort-comparer) ; Ordinary single predicate.
+                                      (consp (car bmkp-sort-comparer))))
+                            (if bmkp-reverse-sort-p "; REVERSED" "")
+                          (if (not (cadr (car bmkp-sort-comparer)))
+                              ;; Single PRED.
+                              (if (or (and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+                                      (and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p)))
+                                  "; REVERSED"
+                                "")
+
+                            ;; In case we want to distinguish:
+                            ;; (if (and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+                            ;;     "; reversed"
+                            ;;   (if (and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p))
+                            ;;       "; reversed +"
+                            ;;     ""))
+
+                            ;; At least two PREDs.
+                            (cond ((and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+                                   "; REVERSED")
+                                  ((and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p))
+                                   "; each predicate group reversed")
+                                  ((and bmkp-reverse-multi-sort-p bmkp-reverse-sort-p)
+                                   "; order of predicate groups reversed")
+                                  (t ""))))))))
+    (when prefix-msg (setq msg  (concat prefix-msg ".  " msg)))
+    (when suffix-msg (setq msg  (concat msg ".  " suffix-msg)))
+    (message msg)))
+
+
+;;(@* "Sorting - Commands")
+;;  *** Sorting - Commands ***
+
+(defun bmkp-current-sort-order ()
+  "Current sort order or sort function, as a string suitable in a message."
+  (or (car (rassoc bmkp-sort-comparer bmkp-sort-orders-alist))  (format "%s" bmkp-sort-comparer)))
+
+
+;;(@* "Sorting - General Predicates")
+;;  *** Sorting - General Predicates ***
+
+(defun bmkp-flagged-cp (b1 b2)
+  "True if bookmark B1 is flagged for deletion and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((m1  (bmkp-flagged-bookmark-p b1))
+        (m2  (bmkp-flagged-bookmark-p b2)))
+    (cond ((and m1 m2)  nil)
+          (m1           '(t))
+          (m2           '(nil))
+          (t            nil))))
+
+(defun bmkp-marked-cp (b1 b2)
+  "True if bookmark B1 is marked and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((m1  (bmkp-marked-bookmark-p b1))
+        (m2  (bmkp-marked-bookmark-p b2)))
+    (cond ((and m1 m2)  nil)
+          (m1           '(t))
+          (m2           '(nil))
+          (t            nil))))
+
+(defun bmkp-modified-cp (b1 b2)
+  "True if bookmark B1 is modified and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((m1  (bmkp-modified-bookmark-p b1))
+        (m2  (bmkp-modified-bookmark-p b2)))
+    (cond ((and m1 m2)  nil)
+          (m1           '(t))
+          (m2           '(nil))
+          (t            nil))))
+
+(defun bmkp-tagged-cp (b1 b2)
+  "True if bookmark B1 is tagged and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((m1  (bmkp-tagged-bookmark-p b1))
+        (m2  (bmkp-tagged-bookmark-p b2)))
+    (cond ((and m1 m2)  nil)
+          (m1           '(t))
+          (m2           '(nil))
+          (t            nil))))
+
+(defun bmkp-visited-more-cp (b1 b2)
+  "True if bookmark B1 was visited more often than B2.
+Return nil if incomparable as described.
+
+True also if B1 was visited but B2 was not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((v1  (bmkp-get-visits-count b1))
+        (v2  (bmkp-get-visits-count b2)))
+    (cond ((and v1 v2)
+           (cond ((> v1 v2)  '(t))
+                 ((> v2 v1)  '(nil))
+                 (t          nil)))
+          (v1                '(t))
+          (v2                '(nil))
+          (t                 nil))))
+
+(defun bmkp-bookmark-creation-cp (b1 b2)
+  "True if bookmark B1 was created more recently than B2.
+Return nil if incomparable as described.
+
+True also if B1 has a `created' entry but B2 has none.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((t1  (bookmark-prop-get b1 'created))
+        (t2  (bookmark-prop-get b2 'created)))
+    (cond ((and t1 t2)
+           (setq t1  (bmkp-float-time t1)
+                 t2  (bmkp-float-time t2))
+           (cond ((> t1 t2)  '(t))
+                 ((> t2 t1)  '(nil))
+                 (t          nil)))
+          (t1                '(t))
+          (t2                '(nil))
+          (t                 nil))))
+
+;; Not used currently.
+(defun bmkp-same-creation-time-p (b1 b2)
+  "Return non-nil if `B1 and B2 have same `created' entry.
+If neither has a `created' entry (vanilla bookmarks), then return
+non-nil if the full bookmarks are `equal'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (let ((time1  (bookmark-prop-get b1 'created))
+        (time2  (bookmark-prop-get b2 'created)))
+    (if (or time1 time2)
+        (equal time1 time2)
+      (equal b1 b2))))
+
+(defun bmkp-bookmark-last-access-cp (b1 b2)
+  "True if bookmark B1 was visited more recently than B2.
+Return nil if incomparable as described.
+
+True also if B1 was visited but B2 was not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((t1  (bmkp-get-visit-time b1))
+        (t2  (bmkp-get-visit-time b2)))
+    (cond ((and t1 t2)
+           (setq t1  (bmkp-float-time t1)
+                 t2  (bmkp-float-time t2))
+           (cond ((> t1 t2)  '(t))
+                 ((> t2 t1)  '(nil))
+                 (t          nil)))
+          (t1                '(t))
+          (t2                '(nil))
+          (t                 nil))))
+
+(defun bmkp-buffer-last-access-cp (b1 b2)
+  "True if bookmark B1's buffer or file was visited more recently than B2's.
+Return nil if incomparable as described.
+
+A bookmark to an existing buffer sorts before a file bookmark, even if
+the buffer has not been visited during this session.
+
+True also if B1 has a buffer but B2 does not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((buf1  (bmkp-get-buffer-name b1))
+        (buf2  (bmkp-get-buffer-name b2))
+        f1 f2 t1 t2)
+    (setq buf1  (and buf1 (get-buffer buf1))
+          buf2  (and buf2 (get-buffer buf2)))
+    (cond ((and buf1 buf2)              ; Both buffers exist.   See whether they were accessed.
+           (when buf1 (setq buf1  (member buf1 (buffer-list))
+                            buf1  (length buf1)))
+           (when buf2 (setq buf2  (member buf2 (buffer-list))
+                            buf2  (length buf2)))
+           (cond ((and buf1 buf2)       ; Both were accessed.  Priority to most recent access.
+                  (cond ((< buf1 buf2)  '(t))
+                        ((< buf2 buf1)  '(nil))
+                        (t              nil)))
+                 (buf1                  '(t)) ; Only buf1 was accessed.
+                 (buf2                  '(nil)) ; Only buf2 was accessed.
+                 (t                     nil))) ; Neither was accessed.
+
+          (buf1                         '(t)) ; Only buf1 exists.
+          (buf2                         '(nil)) ; Only buf2 exists.
+          (t                            nil)))) ; Neither buffer exists
+
+(defun bmkp-handler-cp (b1 b2)
+  "True if bookmark B1's handler name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+Two bookmarks with handlers are compared alphabetically, by their
+handler-function names, respecting `case-fold-search'.
+True also if B1 has a handler but B2 has not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((h1  (bookmark-get-handler b1))
+        (h2  (bookmark-get-handler b2)))
+    (cond ((and h1 h2 (symbolp h1) (symbolp h2))
+           ;; Pretend woman bookmarks are man bookmarks, to keep them together.
+           (when (eq h1 'bmkp-jump-woman) (setq h1  'bmkp-jump-man))
+           (when (eq h2 'bmkp-jump-woman) (setq h2  'bmkp-jump-man))
+           (setq h1  (symbol-name h1)
+                 h2  (symbol-name h2))
+           (when case-fold-search (setq h1  (bmkp-upcase h1)
+                                        h2  (bmkp-upcase h2)))
+           (cond ((string-lessp h1 h2)  '(t))
+                 ((string-lessp h2 h1)  '(nil))
+                 (t                     nil)))
+          (h1                           '(t))
+          (h2                           '(nil))
+          (t                            nil))))
+
+(defun bmkp-info-cp (b1 b2)
+  "True if bookmark B1 sorts as an Info bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two Info bookmarks are compared first by file name (corresponding to
+the manual), then by node name, then by position.
+True also if B1 is an Info bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((i1  (bmkp-info-bookmark-p b1))
+        (i2  (bmkp-info-bookmark-p b2)))
+    (cond ((and i1 i2)
+           (setq i1  (abbreviate-file-name (bookmark-get-filename b1))
+                 i2  (abbreviate-file-name (bookmark-get-filename b2)))
+           (when case-fold-search (setq i1  (bmkp-upcase i1)
+                                        i2  (bmkp-upcase i2)))
+           (cond ((string-lessp i1 i2)                  '(t)) ; Compare manuals (file names).
+                 ((string-lessp i2 i1)                  '(nil))
+                 (t                     ; Compare node names.
+                  (setq i1  (bookmark-prop-get b1 'info-node)
+                        i2  (bookmark-prop-get b2 'info-node))
+                  (cond ((string-lessp i1 i2)           '(t))
+                        ((string-lessp i2 i1)           '(nil))
+                        (t
+                         (setq i1  (bookmark-get-position b1)
+                               i2  (bookmark-get-position b2))
+                         (cond ((or (not i1) (not i2))  '(t)) ; Fallback if no `position' entry.
+                               ((<= i1 i2)              '(t))
+                               ((< i2 i1)               '(nil))))))))
+          (i1                                           '(t))
+          (i2                                           '(nil))
+          (t                                            nil))))
+
+(defun bmkp-gnus-cp (b1 b2)
+  "True if bookmark B1 sorts as a Gnus bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two Gnus bookmarks are compared first by Gnus group name, then by
+article number, then by message ID.
+True also if B1 is a Gnus bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((g1  (bmkp-gnus-bookmark-p b1))
+        (g2  (bmkp-gnus-bookmark-p b2)))
+    (cond ((and g1 g2)
+           (setq g1  (bookmark-prop-get b1 'group)
+                 g2  (bookmark-prop-get b2 'group))
+           (cond ((string-lessp g1 g2)                '(t)) ; Compare groups.
+                 ((string-lessp g2 g1)                '(nil))
+                 (t                     ; Compare article numbers.
+                  (setq g1  (bookmark-prop-get b1 'article)
+                        g2  (bookmark-prop-get b2 'article))
+                  (cond ((< g1 g2)                    '(t))
+                        ((< g2 g1)                    '(nil))
+                        (t
+                         (setq g1  (bookmark-prop-get b1 'message-id)
+                               g2  (bookmark-prop-get b2 'message-id))
+                         (cond ((string-lessp g1 g2)  '(t)) ; Compare message IDs.
+                               ((string-lessp g2 g1)  '(nil))
+                               (t                     nil)))))))
+          (g1                                         '(t))
+          (g2                                         '(nil))
+          (t                                          nil))))
+
+(defun bmkp-url-cp (b1 b2)
+  "True if bookmark B1 sorts as a URL bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two URL bookmarks are compared alphabetically, by their URLs.
+True also if B1 is a URL bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((u1  (bmkp-url-bookmark-p b1))
+        (u2  (bmkp-url-bookmark-p b2)))
+    (cond ((and u1 u2)
+           (setq u1  (or (bookmark-prop-get b1 'location) (bookmark-get-filename b1))
+                 u2  (or (bookmark-prop-get b2 'location) (bookmark-get-filename b2)))
+           (cond ((string-lessp u1 u2)  '(t))
+                 ((string-lessp u2 u1)  '(nil))
+                 (t                     nil)))
+          (u1                           '(t))
+          (u2                           '(nil))
+          (t                            nil))))
+
+;; Not used now.
+(defun bmkp-w3m-cp (b1 b2)
+  "True if bookmark B1 sorts as a W3M URL bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two W3M URL bookmarks are compared alphabetically, by their URLs.
+True also if B1 is a W3M bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((w1  (bmkp-w3m-bookmark-p b1))
+        (w2  (bmkp-w3m-bookmark-p b2)))
+    (cond ((and w1 w2)
+           (setq w1  (bookmark-get-filename b1)
+                 w2  (bookmark-get-filename b2))
+           (cond ((string-lessp w1 w2)  '(t))
+                 ((string-lessp w2 w1)  '(nil))
+                 (t                     nil)))
+          (w1                           '(t))
+          (w2                           '(nil))
+          (t                            nil))))
+
+(defun bmkp-position-cp (b1 b2)
+  "True if the `position' of B1 is not greater than that of B2.
+Return nil if B1 and B2 do not bookmark the same buffer or they have
+the same `position' value.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((buf1  (bmkp-get-buffer-name b1))
+        (buf2  (bmkp-get-buffer-name b2)))
+    (and buf1 buf2 (equal buf1 buf2)
+         (let ((i1  (bookmark-get-position b1))
+               (i2  (bookmark-get-position b2)))
+           (cond ((or (not i1) (not i2))  '(t)) ; Fallback if no `position' entry.
+                 ((<= i1 i2)              '(t))
+                 ((< i2 i1)               '(nil)))))))
+
+(defun bmkp-alpha-cp (b1 b2)
+  "True if bookmark B1's name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+The bookmark names are compared, respecting `case-fold-search'.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((s1  (car b1))
+        (s2  (car b2)))
+    (when case-fold-search (setq s1  (bmkp-upcase s1)
+                                 s2  (bmkp-upcase s2)))
+    (cond ((string-lessp s1 s2)  '(t))
+          ((string-lessp s2 s1)  '(nil))
+          (t                     nil))))
+
+;; Do not use `bmkp-make-plain-predicate', because it falls back on `bookmark-alpha-p'.
+;; Return nil if `bookmark-alpha-cp' cannot decide.
+(defun bmkp-alpha-p (b1 b2)
+  "True if bookmark B1's name sorts alphabetically before B2's.
+The bookmark names are compared, respecting `case-fold-search'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (car (bmkp-alpha-cp b1 b2)))
+
+
+;;(@* "Sorting - File-Name Predicates")
+;;  *** Sorting - File-Name Predicates ***
+
+(defun bmkp-file-alpha-cp (b1 b2)
+  "True if bookmark B1's file name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+The file names are shortened using `abbreviate-file-name', then they
+are compared respecting `case-fold-search'.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (let ((f1  (bmkp-file-bookmark-p b1))
+        (f2  (bmkp-file-bookmark-p b2)))
+    (cond ((and f1 f2)
+           ;; Call `abbreviate-file-name' mainly to get letter case right per platform.
+           (setq f1  (abbreviate-file-name (bookmark-get-filename b1))
+                 f2  (abbreviate-file-name (bookmark-get-filename b2)))
+           (when case-fold-search (setq f1  (bmkp-upcase f1)
+                                        f2  (bmkp-upcase f2)))
+           (cond ((string-lessp f1 f2)  '(t))
+                 ((string-lessp f2 f1)  '(nil))
+                 (t                     nil)))
+          (f1                           '(t))
+          (f2                           '(nil))
+          (t                            nil))))
+
+;; We define all file-attribute predicates, in case you want to use them.
+;;
+;; `bmkp-file-attribute-0-cp'  - type
+;; `bmkp-file-attribute-1-cp'  - links
+;; `bmkp-file-attribute-2-cp'  - uid
+;; `bmkp-file-attribute-3-cp'  - gid
+;; `bmkp-file-attribute-4-cp'  - last access time
+;; `bmkp-file-attribute-5-cp'  - last update time
+;; `bmkp-file-attribute-6-cp'  - last status change
+;; `bmkp-file-attribute-7-cp'  - size
+;; `bmkp-file-attribute-8-cp'  - modes
+;; `bmkp-file-attribute-9-cp'  - gid change
+;; `bmkp-file-attribute-10-cp' - inode
+;; `bmkp-file-attribute-11-cp' - device
+;;
+(bmkp-define-file-sort-predicate 0) ; Type: file, symlink, dir
+(bmkp-define-file-sort-predicate 1) ; Links
+(bmkp-define-file-sort-predicate 2) ; Uid
+(bmkp-define-file-sort-predicate 3) ; Gid
+(bmkp-define-file-sort-predicate 4) ; Last access time
+(bmkp-define-file-sort-predicate 5) ; Last modification time
+(bmkp-define-file-sort-predicate 6) ; Last status-change time
+(bmkp-define-file-sort-predicate 7) ; Size
+(bmkp-define-file-sort-predicate 8) ; Modes
+(bmkp-define-file-sort-predicate 9) ; Gid would change if re-created
+(bmkp-define-file-sort-predicate 10) ; Inode
+(bmkp-define-file-sort-predicate 11) ; Device
+
+(defun bmkp-local-file-accessed-more-recently-cp (b1 b2)
+  "True if bookmark B1's local file was accessed more recently than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks.  Two remote files are considered incomparable - their
+access times are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+         (bmkp-cp-not (bmkp-file-attribute-4-cp b1 b2)))
+        ((bmkp-local-file-bookmark-p b1)         '(t))
+        ((bmkp-local-file-bookmark-p b2)         '(nil))
+        ((and (bmkp-remote-file-bookmark-p b1)
+              (bmkp-remote-file-bookmark-p b2))  nil)
+        ((bmkp-remote-file-bookmark-p b1)        '(t))
+        ((bmkp-remote-file-bookmark-p b2)        '(nil))
+        (t                                       nil)))
+
+(defun bmkp-local-file-updated-more-recently-cp (b1 b2)
+  "True if bookmark B1's local file was updated more recently than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks.  Two remote files are considered incomparable - their
+update times are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+         (bmkp-cp-not (bmkp-file-attribute-5-cp b1 b2)))
+        ((bmkp-local-file-bookmark-p b1)         '(t))
+        ((bmkp-local-file-bookmark-p b2)         '(nil))
+        ((and (bmkp-remote-file-bookmark-p b1)
+              (bmkp-remote-file-bookmark-p b2))  nil)
+        ((bmkp-remote-file-bookmark-p b1)        '(t))
+        ((bmkp-remote-file-bookmark-p b2)        '(nil))
+        (t                                       nil)))
+
+(defun bmkp-local-file-size-cp (b1 b2)
+  "True if bookmark B1's local file is larger than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks.  Two remote files are considered incomparable - their
+sizes are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+         (bmkp-cp-not (bmkp-file-attribute-7-cp b1 b2)))
+        ((bmkp-local-file-bookmark-p b1)         '(t))
+        ((bmkp-local-file-bookmark-p b2)         '(nil))
+        ((and (bmkp-remote-file-bookmark-p b1)
+              (bmkp-remote-file-bookmark-p b2))  nil)
+        ((bmkp-remote-file-bookmark-p b1)        '(t))
+        ((bmkp-remote-file-bookmark-p b2)        '(nil))
+        (t                                       nil)))
+
+(defun bmkp-local-file-type-cp (b1 b2)
+  "True if bookmark B1 sorts by local file type before B2.
+Return nil if neither sorts before the other.
+
+For two local files, a file sorts before a symlink, which sorts before
+a directory.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks.  Two remote files are considered incomparable - their file
+types are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+  (setq b1  (bookmark-get-bookmark b1)
+        b2  (bookmark-get-bookmark b2))
+  (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+         (bmkp-file-attribute-0-cp b1 b2))
+        ((bmkp-local-file-bookmark-p b1)         '(t))
+        ((bmkp-local-file-bookmark-p b2)         '(nil))
+        ((and (bmkp-remote-file-bookmark-p b1)
+              (bmkp-remote-file-bookmark-p b2))  nil)
+        ((bmkp-remote-file-bookmark-p b1)        '(t))
+        ((bmkp-remote-file-bookmark-p b2)        '(nil))
+        (t                                       nil)))
+
+(defun bmkp-cp-not (truth)
+  "Return the negation of boolean value TRUTH.
+If TRUTH is (t), return (nil), and vice versa.
+If TRUTH is nil, return nil."
+  (and truth (if (car truth) '(nil) '(t))))
+
+
+;;(@* "Indirect Bookmarking Functions")
+;;  *** Indirect Bookmarking Functions ***
+
+;;;###autoload
+(defun bmkp-url-target-set (url &optional prefix-only-p name/prefix msg-p) ; `C-x p c u'
+  "Set a bookmark for a URL.  Return the bookmark.
+Interactively you are prompted for the URL.  Completion is available.
+Use `M-n' to pick up the url at point as the default.
+
+You are also prompted for the bookmark name.  But with a prefix arg,
+you are prompted only for a bookmark-name prefix.  In that case, the
+bookmark name is the prefix followed by the URL.
+
+When entering a bookmark name you can use completion against existing
+names.  This completion is lax, so you can easily edit an existing
+name.  See `bookmark-set' for particular keys available during this
+input.
+
+Non-interactively:
+* Non-nil PREFIX-ONLY-P means NAME/PREFIX is a bookmark-name prefix.
+* NAME/PREFIX is the bookmark name or its prefix (the suffix = URL).
+* Non-nil MSG-P means display a status message."
+  (interactive
+   (list (if (require 'ffap nil t)
+             (ffap-read-file-or-url "URL: " (or (thing-at-point 'url)  (and (fboundp 'url-get-url-at-point)
+                                                                            (url-get-url-at-point))))
+           (let ((icicle-unpropertize-completion-result-flag  t))
+             (read-file-name "URL: " nil (or (thing-at-point 'url)  (and (fboundp 'url-get-url-at-point)
+                                                                         (url-get-url-at-point))))))
+         current-prefix-arg
+         (if current-prefix-arg
+             (read-string "Prefix for bookmark name: ")
+           (bmkp-completing-read-lax "Bookmark name"))))
+  (unless name/prefix (setq name/prefix  ""))
+  (lexical-let* ((ul                             url)
+                 (bookmark-make-record-function  (if (eq major-mode 'w3m-mode)
+                                                     'bmkp-make-w3m-record
+                                                   #'(lambda () (bmkp-make-url-browse-record ul))))
+                 bmk failure)
+    (condition-case err
+        (setq bmk  (bookmark-store (if prefix-only-p (concat name/prefix url) name/prefix)
+                                   (cdr (bookmark-make-record)) nil (not msg-p)))
+      (error (setq failure  err)))
+    (if (not failure)
+        bmk                             ; Return the bookmark.
+      (error "Failed to create bookmark for `%s':\n%s\n" url failure))))
+
+;;;###autoload
+(defun bmkp-file-target-set (file &optional prefix-only-p name/prefix no-overwrite no-update-p msg-p)
+                                        ; Bound to `C-x p c f'
+  "Set a bookmark for FILE.  Return the bookmark.
+The bookmarked position is the beginning of the file.
+Interactively you are prompted for FILE.  Completion is available.
+You can use `M-n' to pick up the file name at point, or if none then
+the visited file.
+
+You are also prompted for the bookmark name.  But with a prefix arg,
+you are prompted only for a bookmark-name prefix.  In that case, the
+bookmark name is the prefix followed by the non-directory part of
+FILE.
+
+When entering a bookmark name you can use completion against existing
+names.  This completion is lax, so you can easily edit an existing
+name.  See `bookmark-set' for particular keys available during this
+input.
+
+Non-interactively:
+ - Non-nil optional arg PREFIX-ONLY-P means prompt for a name prefix.
+ - Optional arg NAME/PREFIX is the name or name prefix string.
+ - Optional arg NO-OVERWRITE is passed to `bookmark-store': non-nil
+   means do not overwrite an existing bookmark that has the same name.
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+   do not refresh/rebuild the bookmark-list display.
+ - Non-nil optional arg MSG-P means show a warning message if file
+   does not exist."
+  (interactive
+   (list (let ((icicle-unpropertize-completion-result-flag  t))
+           (read-file-name "File: " nil
+                           (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+                                   (run-hook-with-args-until-success 'file-name-at-point-functions)
+                                 (ffap-guesser))
+                               (thing-at-point 'filename)
+                               (buffer-file-name))))
+         current-prefix-arg
+         (if current-prefix-arg
+             (read-string "Prefix for bookmark name: ")
+           (bmkp-completing-read-lax "Bookmark name"))
+         'MSG))
+  (unless name/prefix (setq name/prefix  ""))
+  (let ((bookmark-make-record-function  (bmkp-make-record-for-target-file file))
+        bmk failure)
+    (condition-case err
+        (setq bmk  (bookmark-store (if prefix-only-p
+                                       (concat name/prefix (file-name-nondirectory file))
+                                     name/prefix)
+                                   (cdr (bookmark-make-record))
+                                   no-overwrite
+                                   (not msg-p)))
+      (error (setq failure  (error-message-string err))))
+    (if (not failure)
+        (prog1 bmk                      ; Return the bookmark.
+          (unless no-update-p (bmkp-refresh/rebuild-menu-list bmk (not msg-p)))
+          (when (and msg-p  (not (file-exists-p file)))
+            (message "File name is now bookmarked, but no such file yet: `%s'" (expand-file-name file))))
+      (error "Failed to create bookmark for `%s':\n%s\n" file failure))))
+
+(defun bmkp-make-record-for-target-file (file)
+  "Return a function that creates a bookmark record for FILE.
+The bookmarked position will be the beginning of the file."
+  ;; $$$$$$ Maybe need a way to bypass default handler, at least for autofiles.
+  ;;        Doesn't seem to make much sense to use a handler such as a shell cmd in this context. (?)
+  (let ((default-handler  (condition-case nil (bmkp-default-handler-for-file file) (error nil))))
+    (cond (default-handler              ; User default handler
+              `(lambda () '((filename . ,file) (position . 0) (file-handler . ,default-handler))))
+          ;; Non-user defaults.
+          ((and (require 'image nil t) (require 'image-mode nil t) ; Image
+                (condition-case nil (image-type file) (error nil)))
+           ;; Last two lines of function are from `image-bookmark-make-record'.
+           ;; But don't use that directly, because it uses
+           ;; `bookmark-make-record-default', which gets nil for `filename'.
+
+           ;; NEED to keep this code sync'd with `diredp-bookmark'.
+           (lambda ()
+             `((filename   . ,file)
+               (position   . 0)
+               (image-type . ,(image-type file))
+               (handler    . image-bookmark-jump))))
+          ((let ((case-fold-search  t))  (string-match "\\([.]au$\\|[.]wav$\\)" file)) ; Sound
+           ;; Obsolete: `(lambda () '((filename . ,file) (handler . bmkp-sound-jump))))
+           `(lambda () '((filename . ,file) (file-handler . play-sound-file))))
+          (t
+           `(lambda () '((filename . ,file) (position . 0)))))))
+
+;;;###autoload
+(defalias 'bmkp-bookmark-a-file 'bmkp-autofile-set)
+;;;###autoload
+(defun bmkp-autofile-set (file &optional dir prefix no-update-p msg-p) ; Bound to `C-x p c a'
+  "Set a bookmark for FILE, autonaming the bookmark for the file.
+Return the bookmark.
+Interactively, you are prompted for FILE.  You can use `M-n' to pick
+up the file name at point or the visited file.
+
+The bookmark name is the non-directory part of FILE, but with a prefix
+arg you are also prompted for a PREFIX string to prepend to the
+bookmark name.  The bookmarked position is the beginning of the file.
+
+Note that if you provide PREFIX then the bookmark will not satisfy
+`bmkp-autofile-bookmark-p' unless you provide the same PREFIX to that
+predicate.
+
+The bookmark's file name is FILE if absolute.  If relative then it is
+FILE expanded in DIR, if non-nil, or in the current directory
+\(`default-directory').
+
+If a bookmark with the same name already exists for the same file name
+then do nothing.
+
+Otherwise, create a new bookmark for the file, even if a bookmark with
+the same name already exists.  This means that you can have more than
+one autofile bookmark with the same bookmark name and the same
+relative file name (non-directory part), but with different absolute
+file names.
+
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and
+   do not refresh/rebuild the bookmark-list display.
+ - Non-nil optional arg MSG-P means display status messages."
+  (interactive
+   (list (let ((icicle-unpropertize-completion-result-flag  t))
+           (read-file-name "File: " nil
+                           (if (or (> emacs-major-version 23)
+                                   (and (= emacs-major-version 23) (> emacs-minor-version 1)))
+                               (let ((deflts  ())
+                                     def)
+                                 (when (setq def  (buffer-file-name)) (push def deflts))
+                                 (when (setq def  (thing-at-point 'filename)) (push def deflts))
+                                 (when (setq def  (ffap-guesser)) (push def deflts))
+                                 (when (and (boundp 'file-name-at-point-functions)
+                                            (setq def  (run-hook-with-args-until-success
+                                                        'file-name-at-point-functions)))
+                                   (push def deflts))
+                                 deflts)
+                             (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+                                     (run-hook-with-args-until-success 'file-name-at-point-functions)
+                                   (ffap-guesser))
+                                 (thing-at-point 'filename)
+                                 (buffer-file-name)))))
+         nil
+         (and current-prefix-arg (read-string "Prefix for bookmark name: "))
+         'MSG))
+  (let* ((dir-to-use  (if (file-name-absolute-p file)
+                          (file-name-directory file)
+                        (or dir default-directory)))
+         ;; Look for existing bookmark with same name, same file, in `dir-to-use'.
+         (bmk         (bmkp-get-autofile-bookmark file dir-to-use prefix)))
+    ;; If BMK was found, then instead of doing nothing we could replace the existing BMK with a new
+    ;; one, as follows:
+    ;; (let ((bookmark-make-record-function (bmkp-make-record-for-target-file file)))
+    ;;   (bmkp-replace-existing-bookmark bmk)) ; Update the existing bookmark.
+    (if (not bmk)
+        ;; Create a new bookmark, and return it.
+        (bmkp-file-target-set (expand-file-name file dir-to-use) t prefix 'NO-OVERWRITE no-update-p msg-p)
+      (when msg-p (message "Autofile bookmark set for `%s'" file))
+      bmk)))                            ; Return the bookmark.
+
+(defun bmkp-get-autofile-bookmark (file &optional dir prefix)
+  "Return an existing autofile bookmark for FILE, or nil if there is none.
+The bookmark name is the non-directory part of FILE, but if PREFIX is
+non-nil then it is PREFIX prepended to the non-directory part of FILE.
+
+The directory part of property `filename' is the directory part of
+FILE, if FILE is absolute.  Otherwise, it is DIR, if non-nil, or
+`default-directory' otherwise.
+
+FILE and the `filename' property of the bookmark returned are the
+same, except possibly for their directory parts (see previous)."
+  (let* ((fname       (file-name-nondirectory file))
+         (bname       (if prefix (concat prefix fname) fname))
+         (dir-to-use  (if (file-name-absolute-p file)
+                          (file-name-directory file)
+                        (or dir default-directory))))
+    ;; Look for existing bookmark with same name, same file, in `dir-to-use'.
+    (catch 'bmkp-get-autofile-bookmark
+      (dolist (bmk  bookmark-alist)
+        (when (string= bname (bmkp-bookmark-name-from-record bmk))
+          (let* ((bfil  (bookmark-get-filename bmk))
+                 (bdir  (and bfil (file-name-directory bfil))))
+            (when (and bfil
+                       (bmkp-same-file-p fname (file-name-nondirectory bfil))
+                       (bmkp-same-file-p bdir dir-to-use))
+              (throw 'bmkp-get-autofile-bookmark bmk))))) ; Return the bookmark.
+      nil)))
+
+;;;###autoload
+(defalias 'bmkp-tag-a-file 'bmkp-autofile-add-tags) ; Bound to `C-x p t + a'
+;;;###autoload
+(defun bmkp-autofile-add-tags (file tags &optional dir prefix no-update-p msg-p)
+  "Add TAGS to the autofile bookmark for FILE.
+Return the number of tags added.
+
+If there is no autofile bookmark for FILE, create one.
+Interactively, you are prompted for FILE and then TAGS.
+When prompted for FILE you can use `M-n' to pick up the file name at
+point, or if none then the visited file.
+
+With a non-negative prefix argument, you are prompted for a file-name
+prefix, as in `bmkp-autofile-set'.
+
+When prompted for tags, hit `RET' to enter each tag, then hit `RET'
+again after the last tag.  You can use completion to enter each tag.
+Completion is lax: you are not limited to existing tags.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time.  Use a non-positive prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings.
+ - DIR, PREFIX, and NO-UPDATE-P are as for `bmkp-autofile-set'.
+ - Non-nil MSG-P means display a message about the addition."
+  (interactive
+   (list (let ((icicle-unpropertize-completion-result-flag  t))
+           (read-file-name "File: " nil
+                           (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+                                   (run-hook-with-args-until-success 'file-name-at-point-functions)
+                                 (ffap-guesser))
+                               (thing-at-point 'filename)
+                               (buffer-file-name))))
+         (bmkp-read-tags-completing nil nil (and current-prefix-arg
+                                                 (< (prefix-numeric-value current-prefix-arg) 1)))
+         nil
+         (and current-prefix-arg (wholenump (prefix-numeric-value current-prefix-arg))
+              (read-string "Prefix for bookmark name: "))
+         'msg))
+  (bmkp-add-tags (bmkp-autofile-set file dir prefix no-update-p) tags no-update-p msg-p))
+
+;;;###autoload
+(defalias 'bmkp-untag-a-file 'bmkp-autofile-remove-tags) ; Bound to `C-x p t - a'
+;;;###autoload
+(defun bmkp-autofile-remove-tags (file tags &optional dir prefix no-update-p msg-p)
+  "Remove TAGS from autofile bookmark for FILE.
+Return the number of tags removed.
+
+Interactively, you are prompted for TAGS and then FILE.
+With Emacs 22 and later, only files with at least one of the given
+tags are candidates.
+
+When prompted for FILE you can use `M-n' to pick up the file name at
+point, or if none then the visited file.
+
+With a non-negative prefix argument, you are prompted for a file-name
+prefix, as in `bmkp-autofile-set'.
+
+
+When prompted for tags, hit `RET' to enter each tag to be removed,
+then hit `RET' again after the last tag.  You can use completion to
+enter each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time.  Use a non-positive prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings.
+ - DIR, PREFIX, and NO-UPDATE-P are as for `bmkp-autofile-set'.
+ - Non-nil MSG-P means display a message about the removal."
+  (interactive
+   (lexical-let* ((pref
+                   (and current-prefix-arg  (wholenump (prefix-numeric-value current-prefix-arg))
+                        (read-string "Prefix for bookmark name: ")))
+                  (tgs
+                   (bmkp-read-tags-completing nil nil (and current-prefix-arg  (< (prefix-numeric-value
+                                                                                   current-prefix-arg) 1))))
+                  (icicle-unpropertize-completion-result-flag  t) ; For `read-file-name'.
+                  (fil   (condition-case nil
+                             (read-file-name
+                              "File: " nil
+                              (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+                                      (run-hook-with-args-until-success 'file-name-at-point-functions)
+                                    (ffap-guesser))
+                                  (thing-at-point 'filename)
+                                  (buffer-file-name))
+                              t nil #'(lambda (ff) ; PREDICATE - only for Emacs 22+.
+                                        (let* ((bmk   (bmkp-get-autofile-bookmark ff nil pref))
+                                               (btgs  (and bmk  (bmkp-get-tags bmk))))
+                                          (and btgs  (catch 'bmkp-autofile-remove-tags-pred
+                                                       (dolist (tag  tgs)
+                                                         (when (not (member tag btgs))
+                                                           (throw 'bmkp-autofile-remove-tags-pred nil)))
+                                                       t)))))
+                           (error (read-file-name "File: " nil (or (ffap-guesser)
+                                                                   (thing-at-point 'filename)
+                                                                   (buffer-file-name)))))))
+     (list fil tgs nil pref 'MSG)))
+  (bmkp-remove-tags (bmkp-autofile-set file dir prefix no-update-p) tags no-update-p msg-p))
+
+;;;###autoload
+(defun bmkp-purge-notags-autofiles (&optional prefix msg-p) ; Not bound
+  "Delete all autofile bookmarks that have no tags.
+With a prefix arg, you are prompted for a PREFIX for the bookmark name.
+Non-interactively, non-nil MSG-P means display a status message."
+  (interactive (if (not (y-or-n-p "Delete all autofile bookmarks that do not have tags? "))
+                   (error "OK - deletion canceled")
+                 (list (and current-prefix-arg (read-string "Prefix for bookmark name: "))
+                       'MSG-P)))
+  (let ((bmks                (bmkp-autofile-alist-only prefix))
+        (bookmark-save-flag  (and (not bmkp-count-multi-mods-as-one-flag)
+                                  bookmark-save-flag)) ; Save only after `dolist'.
+        record tags)
+    ;; Needs Bookmark+ version of `bookmark-delete', which accepts a bookmark, not just its name.
+    (dolist (bmk  bmks)
+      (when (and (setq tags  (assq 'tags (bmkp-bookmark-data-from-record bmk)))
+                 (or (not tags) (null (cdr tags))))
+        (bookmark-delete bmk 'BATCHP)))) ; Do not refresh list here - do it after iterate.
+  (bmkp-tags-list)                      ; Update the tags cache now, after iterate.
+  (bmkp-refresh/rebuild-menu-list nil (not msg-p))) ; Refresh now, after iterate.
+
+
+;; $$$$$$ Not used currently.
+(defun bmkp-replace-existing-bookmark (bookmark)
+  "Replace existing BOOKMARK with a new one of the same name.
+Return the new bookmark.
+BOOKMARK is a full bookmark record, not a bookmark name.
+
+This replaces the existing bookmark data with the data for a new
+bookmark, based on `bookmark-make-record-function'.  It also updates
+the `bmkp-full-record' on the bookmark name (without otherwise
+changing the name)."
+  (let (failure)
+    (condition-case err
+        (progn                          ; Code similar to `bookmark-store'.
+          (setcdr bookmark (cdr (bookmark-make-record)))
+          (bmkp-maybe-save-bookmarks)
+          ;; Put the full bookmark on its name as property `bmkp-full-record'.
+          ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+          ;; If it needs to be stripped, that will be done when saving.
+          (let ((bname  (bmkp-bookmark-name-from-record bookmark)))
+            (put-text-property 0 (length bname) 'bmkp-full-record bookmark bname)
+            ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+            (unless (memq bookmark bmkp-modified-bookmarks)
+              (setq bmkp-modified-bookmarks  (cons bookmark bmkp-modified-bookmarks)))
+            (setq bookmark-current-bookmark  bname))
+          (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
+      (error (setq failure  (error-message-string err))))
+    (if (not failure)
+        bookmark                        ; Return the bookmark.
+      (error "Failed to update bookmark `%s':\n%s\n"
+             (bmkp-bookmark-name-from-record bookmark) failure))))
+
+(defun bmkp-default-handler-for-file (filename)
+  "Return a default bookmark handler for FILENAME, or nil.
+If non-nil, it is a Lisp function, determined as follows:
+
+1. Match FILENAME against `bmkp-default-handlers-for-file-types'.  If
+it matches a Lisp function, return that function.  If it matches a
+shell command, return a Lisp function that invokes that shell command.
+
+2. If no match is found and `bmkp-guess-default-handler-for-file-flag'
+is non-nil, then try to find an appropriate shell command using, in
+order, `dired-guess-default' and (Emacs 23+ only)
+`mailcap-file-default-commands'.  If a match is found then return a
+Lisp function that invokes that shell command."
+  (lexical-let* ((ff         (list filename))
+                 (bmkp-user  (bmkp-default-handler-user filename))
+                 (shell-cmd  (if (stringp bmkp-user)
+                                 bmkp-user
+                               (and (not bmkp-user)
+                                    bmkp-guess-default-handler-for-file-flag
+                                    (or (and (require 'dired-x nil t)
+                                             (let* ((case-fold-search
+                                                     (or (and (boundp 'dired-guess-shell-case-fold-search)
+                                                              dired-guess-shell-case-fold-search)
+                                                         case-fold-search))
+                                                    (default  (dired-guess-default (list filename))))
+                                               (if (consp default) (car default) default)))
+                                        (and (require 'mailcap nil t) ; Emacs 23+
+                                             (car (mailcap-file-default-commands (list filename)))))))))
+