]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
Version 3.15
[gnu-emacs] / lisp / info.el
index 5e8e6ed8340a7a1c267a5c02fe54eaf8b2a5d73b..4c40e187c03d7c265dfd020f5dd54026970f1b1f 100644 (file)
@@ -1,7 +1,7 @@
 ;;; info.el --- info package for Emacs
 
-;; Copyright (C) 1985,86,92,93,94,95,96,97,98,99,2000,01,02,03,2004
-;;  Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+;;   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: help
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
-;; Note that nowadays we expect info files to be made using makeinfo.
+;; Note that nowadays we expect Info files to be made using makeinfo.
 ;; In particular we make these assumptions:
 ;;  - a menu item MAY contain colons but not colon-space ": "
 ;;  - a menu item ending with ": " (but not ":: ") is an index entry
 (eval-when-compile (require 'jka-compr))
 
 (defgroup info nil
-  "Info subsystem"
+  "Info subsystem."
   :group 'help
   :group 'docs)
 
 
 (defvar Info-history nil
-  "Stack of info nodes user has visited.
-Each element of list is a list (FILENAME NODENAME BUFFERPOS).")
+  "Stack of Info nodes user has visited.
+Each element of the stack is a list (FILENAME NODENAME BUFFERPOS).")
+
+(defvar Info-history-forward nil
+  "Stack of Info nodes user has visited with `Info-history-back' command.
+Each element of the stack is a list (FILENAME NODENAME BUFFERPOS).")
 
 (defvar Info-history-list nil
-  "List of all info nodes user has visited.
-Each element of list is a list (FILENAME NODENAME).")
+  "List of all Info nodes user has visited.
+Each element of the list is a list (FILENAME NODENAME).")
 
 (defcustom Info-enable-edit nil
   "*Non-nil means the \\<Info-mode-map>\\[Info-edit] command in Info can edit the current node.
-This is convenient if you want to write info files by hand.
+This is convenient if you want to write Info files by hand.
 However, we recommend that you not do this.
 It is better to write a Texinfo file and generate the Info file from that,
 because that gives you a printed manual as well."
@@ -72,14 +76,64 @@ The Lisp code is executed when the node is selected.")
   "Face for Info node names."
   :group 'info)
 
-(defface info-menu-5
+(defface info-title-1
+  '((((type tty pc) (class color) (background light))
+     :foreground "green" :weight bold)
+    (((type tty pc) (class color) (background dark))
+     :foreground "yellow" :weight bold)
+    (t :height 1.2 :inherit info-title-2))
+  "Face for info titles at level 1."
+  :group 'info)
+;; backward-compatibility alias
+(put 'Info-title-1-face 'face-alias 'info-title-1)
+
+(defface info-title-2
+  '((((type tty pc) (class color)) :foreground "lightblue" :weight bold)
+    (t :height 1.2 :inherit info-title-3))
+  "Face for info titles at level 2."
+  :group 'info)
+;; backward-compatibility alias
+(put 'Info-title-2-face 'face-alias 'info-title-2)
+
+(defface info-title-3
+  '((((type tty pc) (class color)) :weight bold)
+    (t :height 1.2 :inherit info-title-4))
+  "Face for info titles at level 3."
+  :group 'info)
+;; backward-compatibility alias
+(put 'Info-title-3-face 'face-alias 'info-title-3)
+
+(defface info-title-4
+  '((((type tty pc) (class color)) :weight bold)
+    (t :weight bold :inherit variable-pitch))
+  "Face for info titles at level 4."
+  :group 'info)
+;; backward-compatibility alias
+(put 'Info-title-4-face 'face-alias 'info-title-4)
+
+(defface info-menu-header
+  '((((type tty pc))
+     :underline t
+     :weight bold)
+    (t
+     :inherit variable-pitch
+     :weight bold))
+  "Face for headers in Info menus."
+  :group 'info)
+
+(defface info-menu-star
   '((((class color)) :foreground "red1")
     (t :underline t))
   "Face for every third `*' in an Info menu."
   :group 'info)
+(put 'info-menu-5 'face-alias 'info-menu-star)
 
 (defface info-xref
-  '((((class color) (background light)) :foreground "blue" :underline t)
+  '((((min-colors 88)
+      (class color) (background light)) :foreground "blue1" :underline t)
+    (((class color) (background light)) :foreground "blue" :underline t)
+    (((min-colors 88)
+      (class color) (background dark)) :foreground "cyan1" :underline t)
     (((class color) (background dark)) :foreground "cyan" :underline t)
     (t :underline t))
   "Face for Info cross-references."
@@ -88,13 +142,13 @@ The Lisp code is executed when the node is selected.")
 (defface info-xref-visited
   '((default :inherit info-xref)
     (((class color) (background light)) :foreground "magenta4")
-    (((class color) (background dark)) :foreground "magenta3")) ;"violet"?
+    (((class color) (background dark)) :foreground "violet"))
   "Face for visited Info cross-references."
   :group 'info)
 
 (defcustom Info-fontify-visited-nodes t
-  "*Non-nil means to fontify visited nodes in a different face."
-  :version "21.4"
+  "*Non-nil to fontify references to visited nodes in `info-xref-visited' face."
+  :version "22.1"
   :type 'boolean
   :group 'info)
 
@@ -157,6 +211,7 @@ These directories are searched after those in `Info-directory-list'."
 
 (defcustom Info-scroll-prefer-subnodes nil
   "*If non-nil, \\<Info-mode-map>\\[Info-scroll-up] in a menu visits subnodes.
+
 If this is non-nil, and you scroll far enough in a node that its menu
 appears on the screen, the next \\<Info-mode-map>\\[Info-scroll-up]
 moves to a subnode indicated by the following menu item.  This means
@@ -165,15 +220,16 @@ that you visit a subnode before getting to the end of the menu.
 Setting this option to nil results in behavior similar to the stand-alone
 Info reader program, which visits the first subnode from the menu only
 when you hit the end of the current node."
-  :version "21.4"
+  :version "22.1"
   :type 'boolean
   :group 'info)
 
 (defcustom Info-hide-note-references t
   "*If non-nil, hide the tag and section reference in *note and * menu items.
 If value is non-nil but not `hide', also replaces the \"*note\" with \"see\".
-If value is non-nil but not t or `hide', the reference section is still shown."
-  :version "21.4"
+If value is non-nil but not t or `hide', the reference section is still shown.
+`nil' completely disables this feature."
+  :version "22.1"
   :type '(choice (const :tag "No hiding" nil)
                 (const :tag "Replace tag and hide reference" t)
                 (const :tag "Hide tag and reference" hide)
@@ -182,9 +238,9 @@ If value is non-nil but not t or `hide', the reference section is still shown."
 
 (defcustom Info-refill-paragraphs nil
   "*If non-nil, attempt to refill paragraphs with hidden references.
-This refilling may accidentally remove explicit line breaks in the info
+This refilling may accidentally remove explicit line breaks in the Info
 file, so be prepared for a few surprises if you enable this feature."
-  :version "21.4"
+  :version "22.1"
   :type 'boolean
   :group 'info)
 
@@ -197,6 +253,24 @@ a tab, a carriage return (control-M), a newline, and `]+'."
   :type 'regexp
   :group 'info)
 
+(defcustom Info-isearch-search t
+  "*If non-nil, isearch in Info searches through multiple nodes.
+Before leaving the initial Info node, where isearch was started,
+it fails once with the error message [initial node], and with
+subsequent C-s/C-r continues through other nodes without failing
+with this error message in other nodes.  When isearch fails for
+the rest of the manual, it wraps aroung the whole manual and
+restarts the search from the top/final node depending on
+search direction.
+
+Setting this option to nil restores the default isearch behavior
+with wrapping around the current Info node."
+  :version "22.1"
+  :type 'boolean
+  :group 'info)
+
+(defvar Info-isearch-initial-node nil)
+
 (defcustom Info-mode-hook
   ;; Try to obey obsolete Info-fontify settings.
   (unless (and (boundp 'Info-fontify) (null Info-fontify))
@@ -221,7 +295,7 @@ Can also be t when using `Info-on-current-buffer'.")
 
 (defvar Info-current-subfile nil
   "Info subfile that is actually in the *info* buffer now.
-nil if current info file is not split into subfiles.")
+nil if current Info file is not split into subfiles.")
 
 (defvar Info-current-node nil
   "Name of node that Info is now looking at, or nil.")
@@ -331,7 +405,7 @@ be last in the list.")
        (not (file-directory-p filename))))
 
 (defun info-insert-file-contents (filename &optional visit)
-  "Insert the contents of an info file in the current buffer.
+  "Insert the contents of an Info file in the current buffer.
 Do the right thing if the file has been compressed or zipped."
   (let* ((tail Info-suffix-list)
         (lfn (if (fboundp 'msdos-long-file-names)
@@ -489,9 +563,10 @@ in all the directories in that path."
       ;; since the argument will then be parsed improperly.  This also
       ;; has the added benefit of allowing node names to be included
       ;; following the parenthesized filename.
-      (if (and (stringp file) (string-match "(.*)" file))
-         (Info-goto-node file)
-       (Info-goto-node (concat "(" file ")")))
+      (Info-goto-node
+       (if (and (stringp file) (string-match "(.*)" file))
+           file
+         (concat "(" file ")")))
     (if (zerop (buffer-size))
         (Info-directory))))
 
@@ -605,22 +680,22 @@ just return nil (no error)."
         filename)))
 
 (defun Info-find-node (filename nodename &optional no-going-back)
-  "Go to an info node specified as separate FILENAME and NODENAME.
+  "Go to an Info node specified as separate FILENAME and NODENAME.
 NO-GOING-BACK is non-nil if recovering from an error in this function;
 it says do not attempt further (recursive) error recovery."
   (info-initialize)
   (setq filename (Info-find-file filename))
+  ;; Go into Info buffer.
+  (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*"))
   ;; Record the node we are leaving.
   (if (and Info-current-file (not no-going-back))
       (setq Info-history
             (cons (list Info-current-file Info-current-node (point))
                   Info-history)))
-  ;; Go into info buffer.
-  (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*"))
   (Info-find-node-2 filename nodename no-going-back))
 
 (defun Info-on-current-buffer (&optional nodename)
-  "Use the `Info-mode' to browse the current info buffer.
+  "Use the `Info-mode' to browse the current Info buffer.
 If a prefix arg is provided, it queries for the NODENAME which
 else defaults to \"Top\"."
   (interactive
@@ -638,7 +713,7 @@ else defaults to \"Top\"."
 ;; makeinfo-buffer) out of the way of normal operations.
 ;;
 (defun Info-revert-find-node (filename nodename)
-  "Go to an info node FILENAME and NODENAME, re-reading disk contents.
+  "Go to an Info node FILENAME and NODENAME, re-reading disk contents.
 When *info* is already displaying FILENAME and NODENAME, the window position
 is preserved, if possible."
   (pop-to-buffer "*info*")
@@ -1001,7 +1076,7 @@ a case-insensitive match is tried."
       ;; Insert the entire original dir file as a start; note that we've
       ;; already saved its default directory to use as the default
       ;; directory for the whole concatenation.
-      (insert-buffer buffer)
+      (save-excursion (insert-buffer-substring buffer))
 
       ;; Look at each of the other buffers one by one.
       (dolist (other others)
@@ -1130,8 +1205,9 @@ a case-insensitive match is tried."
            (goto-char start)
            (while (re-search-forward "^* \\([^:\n]+:\\(:\\|[^.\n]+\\).\\)"
                                      limit 'move)
-             (let ((x (match-string 1)))
-               (if (member-ignore-case x seen)
+             ;; Fold case straight away; `member-ignore-case' here wasteful.
+             (let ((x (downcase (match-string 1))))
+               (if (member x seen)
                    (delete-region (match-beginning 0)
                                   (progn (re-search-forward "^[^ \t]" nil t)
                                          (match-beginning 0)))
@@ -1245,7 +1321,7 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
 ;; Hide any construct of the general form ^@[^@-^_][ ...  ^@[^@-^_]],
 ;; including one optional trailing newline.
 (defun Info-hide-cookies-node ()
-  "Hide unrecognised cookies in current node."
+  "Hide unrecognized cookies in current node."
   (save-excursion
     (let ((inhibit-read-only t)
          (case-fold-search t))
@@ -1259,7 +1335,7 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
     (set-buffer-modified-p nil)))
 
 (defun Info-select-node ()
-  "Select the info node that point is in."
+  "Select the Info node that point is in."
   ;; Bind this in case the user sets it to nil.
   (let ((case-fold-search t))
     (save-excursion
@@ -1295,7 +1371,8 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
        ;; Add a new unique history item to full history list
        (let ((new-history (list Info-current-file Info-current-node)))
          (setq Info-history-list
-               (cons new-history (delete new-history Info-history-list))))
+               (cons new-history (delete new-history Info-history-list)))
+         (setq Info-history-forward nil))
        (if (not (eq Info-fontify-maximum-menu-size nil))
             (Info-fontify-node))
        (Info-display-images-node)
@@ -1314,18 +1391,20 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
                        ") "
                        (or Info-current-node ""))))))
 \f
-;; Go to an info node specified with a filename-and-nodename string
+;; Go to an Info node specified with a filename-and-nodename string
 ;; of the sort that is found in pointers in nodes.
 
-;;;###autoload
+;; Don't autoload this function: the correct entry point for other packages
+;; to use is `info'.  --Stef
+;; ;;;###autoload
 (defun Info-goto-node (nodename &optional fork)
-  "Go to info node named NODENAME.  Give just NODENAME or (FILENAME)NODENAME.
+  "Go to Info node named NODENAME.  Give just NODENAME or (FILENAME)NODENAME.
 If NODENAME is of the form (FILENAME)NODENAME, the node is in the Info file
 FILENAME; otherwise, NODENAME should be in the current Info file (or one of
 its sub-files).
 Completion is available, but only for node names in the current Info file.
 If FORK is non-nil (interactively with a prefix arg), show the node in
-a new info buffer.
+a new Info buffer.
 If FORK is a string, it is the name to use for the new buffer."
   (interactive (list (Info-read-node-name "Go to node: ") current-prefix-arg))
   (info-initialize)
@@ -1349,6 +1428,43 @@ If FORK is a string, it is the name to use for the new buffer."
 
 (defvar Info-read-node-completion-table)
 
+(defun Info-read-node-name-2 (string path-and-suffixes action)
+  "Virtual completion table for file names input in Info node names.
+PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
+  (let* ((names nil)
+        (suffixes (remove "" (cdr path-and-suffixes)))
+        (suffix (concat (regexp-opt suffixes t) "\\'"))
+        (string-dir (file-name-directory string))
+        (dirs
+         (if (file-name-absolute-p string)
+             (list (file-name-directory string))
+           (car path-and-suffixes))))
+    (dolist (dir dirs)
+      (unless dir
+       (setq dir default-directory))
+      (if string-dir (setq dir (expand-file-name string-dir dir)))
+      (when (file-directory-p dir)
+       (dolist (file (file-name-all-completions
+                      (file-name-nondirectory string) dir))
+         ;; If the file name has no suffix or a standard suffix,
+         ;; include it.
+         (and (or (null (file-name-extension file))
+                  (string-match suffix file))
+              ;; But exclude subfiles of split Info files.
+              (not (string-match "-[0-9]+\\'" file))
+              ;; And exclude backup files.
+              (not (string-match "~\\'" file))
+              (push (if string-dir (concat string-dir file) file) names))
+         ;; If the file name ends in a standard suffix,
+         ;; add the unsuffixed name as a completion option.
+         (when (string-match suffix file)
+           (setq file (substring file 0 (match-beginning 0)))
+           (push (if string-dir (concat string-dir file) file) names)))))
+    (cond
+     ((eq action t) (all-completions string names))
+     ((null action) (try-completion string names))
+     (t (test-completion string names)))))
+
 ;; This function is used as the "completion table" while reading a node name.
 ;; It does completion using the alist in Info-read-node-completion-table
 ;; unless STRING starts with an open-paren.
@@ -1359,15 +1475,16 @@ If FORK is a string, it is the name to use for the new buffer."
     (let ((file (substring string 1)))
       (cond
        ((eq code nil)
-       (let ((comp (try-completion file 'locate-file-completion
+       (let ((comp (try-completion file 'Info-read-node-name-2
                                    (cons Info-directory-list
                                          (mapcar 'car Info-suffix-list)))))
          (cond
           ((eq comp t) (concat string ")"))
           (comp (concat "(" comp)))))
-       ((eq code t) (all-completions file 'locate-file-completion
-                                    (cons Info-directory-list
-                                          (mapcar 'car Info-suffix-list))))
+       ((eq code t)
+       (all-completions file 'Info-read-node-name-2
+                        (cons Info-directory-list
+                              (mapcar 'car Info-suffix-list))))
        (t nil))))
    ;; If a file name was given, then any node is fair game.
    ((string-match "\\`(" string)
@@ -1383,6 +1500,10 @@ If FORK is a string, it is the name to use for the new buffer."
    (t
     (test-completion string Info-read-node-completion-table predicate))))
 
+;; Arrange to highlight the proper letters in the completion list buffer.
+(put 'Info-read-node-name-1 'completion-base-size-function
+     (lambda () 1))
+
 (defun Info-read-node-name (prompt &optional default)
   (let* ((completion-ignore-case t)
         (Info-read-node-completion-table (Info-build-node-completions))
@@ -1488,7 +1609,7 @@ If DIRECTION is `backward', search in the reverse direction."
                            ;; Skip node header line
                            (and (save-excursion (forward-line -1)
                                                 (looking-at "\^_"))
-                                (forward-line 1))
+                                (forward-line (if backward -1 1)))
                            ;; Skip Tag Table node
                            (save-excursion
                              (and (search-backward "\^_" nil t)
@@ -1500,6 +1621,14 @@ If DIRECTION is `backward', search in the reverse direction."
                  (setq found (point) beg-found (if backward (match-end 0)
                                                  (match-beginning 0)))
                (setq give-up t))))))
+
+      (when (and isearch-mode Info-isearch-search
+                (not Info-isearch-initial-node)
+                (not bound)
+                (or give-up (and found (not (and (> found opoint-min)
+                                                 (< found opoint-max))))))
+       (signal 'search-failed (list regexp "initial node")))
+
       ;; If no subfiles, give error now.
       (if give-up
          (if (null Info-current-subfile)
@@ -1509,6 +1638,9 @@ If DIRECTION is `backward', search in the reverse direction."
                  (re-search-forward regexp)))
            (setq found nil)))
 
+      (if (and bound (not found))
+         (signal 'search-failed (list regexp)))
+
       (unless (or found bound)
        (unwind-protect
            ;; Try other subfiles.
@@ -1526,6 +1658,7 @@ If DIRECTION is `backward', search in the reverse direction."
                  (search-forward (concat "\n" osubfile ": "))
                  ;; Skip that one.
                  (forward-line (if backward 0 1))
+                 (if backward (forward-char -1))
                  ;; Make a list of all following subfiles.
                  ;; Each elt has the form (VIRT-POSITION . SUBFILENAME).
                  (while (not (if backward (bobp) (eobp)))
@@ -1564,7 +1697,7 @@ If DIRECTION is `backward', search in the reverse direction."
                                  ;; Skip node header line
                                  (and (save-excursion (forward-line -1)
                                                       (looking-at "\^_"))
-                                      (forward-line 1))
+                                      (forward-line (if backward -1 1)))
                                  ;; Skip Tag Table node
                                  (save-excursion
                                    (and (search-backward "\^_" nil t)
@@ -1601,7 +1734,8 @@ If DIRECTION is `backward', search in the reverse direction."
       ;; Use string-equal, not equal, to ignore text props.
       (or (and (string-equal onode Info-current-node)
               (equal ofile Info-current-file))
-          (and isearch-mode isearch-wrapped (eq opoint opoint-min))
+          (and isearch-mode isearch-wrapped
+              (eq opoint (if isearch-forward opoint-min opoint-max)))
          (setq Info-history (cons (list ofile onode opoint)
                                   Info-history))))))
 
@@ -1632,23 +1766,32 @@ If DIRECTION is `backward', search in the reverse direction."
   (Info-search regexp bound noerror count 'backward))
 
 (defun Info-isearch-search ()
-  (cond
-   (isearch-word
-    (if isearch-forward 'word-search-forward 'word-search-backward))
-   (isearch-regexp
-    (lambda (regexp bound noerror)
-      (condition-case nil
-          (progn
-            (Info-search regexp bound noerror nil
-                         (unless isearch-forward 'backward))
-            (point))
-        (error nil))))
-   (t
-    (if isearch-forward 'search-forward 'search-backward))))
+  (if Info-isearch-search
+      (lambda (string &optional bound noerror count)
+       (if isearch-word
+           (Info-search (concat "\\b" (replace-regexp-in-string
+                                       "\\W+" "\\W+"
+                                       (replace-regexp-in-string
+                                        "^\\W+\\|\\W+$" "" string)
+                                       nil t)
+                                "\\b")
+                        bound noerror count
+                        (unless isearch-forward 'backward))
+         (Info-search (if isearch-regexp string (regexp-quote string))
+                      bound noerror count
+                      (unless isearch-forward 'backward))
+         (point)))
+    (let ((isearch-search-fun-function nil))
+      (isearch-search-fun))))
 
 (defun Info-isearch-wrap ()
-  (if isearch-regexp
-      (if isearch-forward (Info-top-node) (Info-final-node))
+  (if Info-isearch-search
+      (if Info-isearch-initial-node
+         (progn
+           (if isearch-forward (Info-top-node) (Info-final-node))
+           (goto-char (if isearch-forward (point-min) (point-max))))
+       (setq Info-isearch-initial-node Info-current-node)
+       (setq isearch-wrapped nil))
     (goto-char (if isearch-forward (point-min) (point-max)))))
 
 (defun Info-isearch-push-state ()
@@ -1660,6 +1803,8 @@ If DIRECTION is `backward', search in the reverse direction."
            (string= Info-current-node node))
       (progn (Info-find-node file node) (sit-for 0))))
 
+(defun Info-isearch-start ()
+  (setq Info-isearch-initial-node nil))
 \f
 (defun Info-extract-pointer (name &optional errorname)
   "Extract the value of the node-pointer named NAME.
@@ -1727,22 +1872,42 @@ If SAME-FILE is non-nil, do not move to a different Info file."
                 (concat "\n\\* +\\(" (regexp-quote old-node)
                         ":\\|[^:]+: +" (regexp-quote old-node) "\\)"))
               nil t))
-        (beginning-of-line)
+        (progn (beginning-of-line) (if (looking-at "^\\* ") (forward-char 2)))
       (goto-char p)
       (Info-restore-point Info-history))))
 
-(defun Info-last ()
-  "Go back to the last node visited."
+(defun Info-history-back ()
+  "Go back in the history to the last node visited."
   (interactive)
   (or Info-history
       (error "This is the first Info node you looked at"))
-  (let (filename nodename opoint)
+  (let ((history-forward
+        (cons (list Info-current-file Info-current-node (point))
+              Info-history-forward))
+       filename nodename opoint)
     (setq filename (car (car Info-history)))
     (setq nodename (car (cdr (car Info-history))))
     (setq opoint (car (cdr (cdr (car Info-history)))))
     (setq Info-history (cdr Info-history))
     (Info-find-node filename nodename)
     (setq Info-history (cdr Info-history))
+    (setq Info-history-forward history-forward)
+    (goto-char opoint)))
+
+(defalias 'Info-last 'Info-history-back)
+
+(defun Info-history-forward ()
+  "Go forward in the history of visited nodes."
+  (interactive)
+  (or Info-history-forward
+      (error "This is the last Info node you looked at"))
+  (let ((history-forward (cdr Info-history-forward))
+       filename nodename opoint)
+    (setq filename (car (car Info-history-forward)))
+    (setq nodename (car (cdr (car Info-history-forward))))
+    (setq opoint (car (cdr (cdr (car Info-history-forward)))))
+    (Info-find-node filename nodename)
+    (setq Info-history-forward history-forward)
     (goto-char opoint)))
 
 ;;;###autoload
@@ -1896,7 +2061,7 @@ Table of contents is created from the tree structure of menus."
   "Follow cross reference named FOOTNOTENAME to the node it refers to.
 FOOTNOTENAME may be an abbreviation of the reference name.
 If FORK is non-nil (interactively with a prefix arg), show the node in
-a new info buffer.  If FORK is a string, it is the name to use for the
+a new Info buffer.  If FORK is a string, it is the name to use for the
 new buffer."
   (interactive
    (let ((completion-ignore-case t)
@@ -2107,7 +2272,7 @@ Because of ambiguities, this should be concatenated with something like
 The menu item should one of those listed in the current node's menu.
 Completion is allowed, and the default menu item is the one point is on.
 If FORK is non-nil (interactively with a prefix arg), show the node in
-a new info buffer.  If FORK is a string, it is the name to use for the
+a new Info buffer.  If FORK is a string, it is the name to use for the
 new buffer."
   (interactive
    (let ((completions '())
@@ -2432,7 +2597,9 @@ parent node."
     (if (looking-at "\\* Menu:")
        (if recur
            (error "No cross references in this node")
-         (Info-next-reference t)))))
+         (Info-next-reference t))
+      (if (looking-at "^\\* ")
+         (forward-char 2)))))
 
 (defun Info-prev-reference (&optional recur)
   "Move cursor to the previous cross-reference or menu item in the node."
@@ -2451,7 +2618,9 @@ parent node."
     (if (looking-at "\\* Menu:")
        (if recur
            (error "No cross references in this node")
-         (Info-prev-reference t)))))
+         (Info-prev-reference t))
+      (if (looking-at "^\\* ")
+         (forward-char 2)))))
 \f
 (defvar Info-index-nodes nil
   "Alist of cached index node names of visited Info files.
@@ -2685,25 +2854,29 @@ Build a menu of the possible matches."
        (goto-char (point-min))
        (re-search-forward "\\* Menu: *\n" nil t)
        (while (re-search-forward "\\*.*: *(\\([^)]+\\))" nil t)
-         (add-to-list 'manuals (match-string 1)))
-       (dolist (manual manuals)
+         (setq manuals (cons (match-string 1) manuals)))
+       (dolist (manual (nreverse manuals))
          (message "Searching %s" manual)
-         (if (setq nodes (Info-index-nodes (Info-find-file manual)))
-              (condition-case nil
+         (condition-case err
+             (if (setq nodes (Info-index-nodes (Info-find-file manual)))
                   (save-excursion
                     (Info-find-node manual (car nodes))
                     (while
                         (progn
                           (goto-char (point-min))
                           (while (re-search-forward pattern nil t)
-                            (add-to-list 'matches
-                                         (list manual
-                                               (match-string-no-properties 1)
-                                               (match-string-no-properties 2)
-                                               (match-string-no-properties 3))))
+                           (setq matches
+                                 (cons (list manual
+                                             (match-string-no-properties 1)
+                                             (match-string-no-properties 2)
+                                             (match-string-no-properties 3))
+                                       matches)))
                           (setq nodes (cdr nodes) node (car nodes)))
-                      (Info-goto-node node)))
-                (error nil)))))
+                      (Info-goto-node node))))
+           (error
+            (message "%s" (if (eq (car-safe err) 'error)
+                              (nth 1 err) err))
+            (sit-for 1 t)))))
       (Info-goto-node (concat "(" current-file ")" current-node))
       (setq Info-history ohist
            Info-history-list ohist-list)
@@ -2713,8 +2886,8 @@ Build a menu of the possible matches."
        (with-current-buffer (get-buffer-create " *info-apropos*")
          (erase-buffer)
          (insert "\n\^_\nFile: apropos, Node: Index, Up: (dir)\n")
-         (insert "* Menu: \nNodes whose indices contain \"" string "\"\n\n")
-         (dolist (entry matches)
+         (insert "* Menu: \nNodes whose indices contain `" string "':\n\n")
+         (dolist (entry (nreverse matches))
            (insert
             (format "* %-38s (%s)%s.%s\n"
                     (concat (nth 1 entry) " [" (nth 0 entry) "]:")
@@ -2754,7 +2927,7 @@ Build a menu of the possible matches."
       (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
                    (message (if flag "Type Space to see more"
                               "Type Space to return to Info"))
-                   (if (not (eq ?\  (setq ch (read-event))))
+                   (if (not (eq ?\s (setq ch (read-event))))
                        (progn (setq unread-command-events (list ch)) nil)
                      flag))
        (scroll-up)))
@@ -2887,19 +3060,19 @@ if point is in a menu item description, follow that menu item."
   (define-key Info-mode-map "<" 'Info-top-node)
   (define-key Info-mode-map ">" 'Info-final-node)
   (define-key Info-mode-map "b" 'beginning-of-buffer)
-  (define-key Info-mode-map "c" 'Info-copy-current-node-name)
   (define-key Info-mode-map "d" 'Info-directory)
   (define-key Info-mode-map "e" 'Info-edit)
   (define-key Info-mode-map "f" 'Info-follow-reference)
   (define-key Info-mode-map "g" 'Info-goto-node)
   (define-key Info-mode-map "h" 'Info-help)
   (define-key Info-mode-map "i" 'Info-index)
-  (define-key Info-mode-map "l" 'Info-last)
+  (define-key Info-mode-map "l" 'Info-history-back)
   (define-key Info-mode-map "L" 'Info-history)
   (define-key Info-mode-map "m" 'Info-menu)
   (define-key Info-mode-map "n" 'Info-next)
   (define-key Info-mode-map "p" 'Info-prev)
   (define-key Info-mode-map "q" 'Info-exit)
+  (define-key Info-mode-map "r" 'Info-history-forward)
   (define-key Info-mode-map "s" 'Info-search)
   (define-key Info-mode-map "S" 'Info-search-case-sensitively)
   ;; For consistency with Rmail.
@@ -2908,8 +3081,11 @@ if point is in a menu item description, follow that menu item."
   (define-key Info-mode-map "t" 'Info-top-node)
   (define-key Info-mode-map "T" 'Info-toc)
   (define-key Info-mode-map "u" 'Info-up)
-  ;; For consistency with dired-copy-filename-as-kill.
+  ;; `w' for consistency with `dired-copy-filename-as-kill'.
   (define-key Info-mode-map "w" 'Info-copy-current-node-name)
+  (define-key Info-mode-map "c" 'Info-copy-current-node-name)
+  ;; `^' for consistency with `dired-up-directory'.
+  (define-key Info-mode-map "^" 'Info-up)
   (define-key Info-mode-map "," 'Info-index-next)
   (define-key Info-mode-map "\177" 'Info-scroll-down)
   (define-key Info-mode-map [mouse-2] 'Info-mouse-follow-nearest-node)
@@ -2924,7 +3100,7 @@ if point is in a menu item description, follow that menu item."
 
 (easy-menu-define
  Info-mode-menu Info-mode-map
- "Menu for info files."
+ "Menu for Info files."
  '("Info"
    ["Up" Info-up :active (Info-check-pointer "up")
     :help "Go up in the Info tree"]
@@ -2946,24 +3122,24 @@ if point is in a menu item description, follow that menu item."
    ("Reference" ["You should never see this" report-emacs-bug t])
    ["Search..." Info-search
     :help "Search for regular expression in this Info file"]
-   ["Search Case-Sensitively..." Info-search-case-sensitively
-    :help "Search for regular expression case sensitively"]
    ["Search Next" Info-search-next
     :help "Search for another occurrence of regular expression"]
    ["Go to Node..." Info-goto-node
     :help "Go to a named node"]
-   ["Last" Info-last :active Info-history
-    :help "Go to the last node you were at"]
+   ["Back in history" Info-history-back :active Info-history
+    :help "Go back in history to the last node you were at"]
+   ["Forward in history" Info-history-forward :active Info-history-forward
+    :help "Go forward in history"]
    ["History" Info-history :active Info-history-list
     :help "Go to menu of visited nodes"]
    ["Table of Contents" Info-toc
     :help "Go to table of contents"]
-   ("Index..."
-    ["Lookup a String" Info-index
+   ("Index"
+    ["Lookup a String..." Info-index
      :help "Look for a string in the index items"]
-    ["Next Matching Item" Info-index-next
+    ["Next Matching Item" Info-index-next :active Info-index-alternatives
      :help "Look for another occurrence of previous item"]
-    ["Lookup a string in all indices" info-apropos
+    ["Lookup a string in all indices..." info-apropos
      :help "Look for a string in the indices of all manuals"])
    ["Edit" Info-edit :help "Edit contents of this node"
     :active Info-enable-edit]
@@ -2981,7 +3157,8 @@ if point is in a menu item description, follow that menu item."
        (tool-bar-local-item-from-menu 'Info-prev "left_arrow" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-next "right_arrow" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-up "up_arrow" map Info-mode-map)
-       (tool-bar-local-item-from-menu 'Info-last "undo" map Info-mode-map)
+       (tool-bar-local-item-from-menu 'Info-history-back "back_arrow" map Info-mode-map)
+       (tool-bar-local-item-from-menu 'Info-history-forward "fwd_arrow" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-top-node "home" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-goto-node "jump_to" map Info-mode-map)
@@ -3056,12 +3233,12 @@ if point is in a menu item description, follow that menu item."
 
 \f
 (defun Info-copy-current-node-name (&optional arg)
-  "Put the name of the current info node into the kill ring.
-The name of the info file is prepended to the node name in parentheses.
+  "Put the name of the current Info node into the kill ring.
+The name of the Info file is prepended to the node name in parentheses.
 With a zero prefix arg, put the name inside a function call to `info'."
   (interactive "P")
   (unless Info-current-node
-    (error "No current info node"))
+    (error "No current Info node"))
   (let ((node (concat "(" (file-name-nondirectory
                            (or (and (stringp Info-current-file)
                                     Info-current-file)
@@ -3078,6 +3255,10 @@ With a zero prefix arg, put the name inside a function call to `info'."
 (put 'Info-mode 'mode-class 'special)
 (put 'Info-mode 'no-clone-indirect t)
 
+(defvar tool-bar-map)
+
+;; Autoload cookie needed by desktop.el
+;;;###autoload
 (defun Info-mode ()
   "Info mode provides commands for browsing through the Info documentation tree.
 Documentation in Info is divided into \"nodes\", each of which discusses
@@ -3101,7 +3282,8 @@ Selecting other nodes:
          Picking a menu item causes another node to be selected.
 \\[Info-directory]     Go to the Info directory node.
 \\[Info-follow-reference]      Follow a cross reference.  Reads name of reference.
-\\[Info-last]  Move to the last node you were at.
+\\[Info-history-back]  Move back in history to the last node you were at.
+\\[Info-history-forward]       Move forward in history to the node you returned from after using \\[Info-history-back].
 \\[Info-history]       Go to menu of visited nodes.
 \\[Info-toc]   Go to table of contents of the current Info file.
 \\[Info-top-node]      Go to the Top node of this file.
@@ -3124,7 +3306,7 @@ Moving within a node:
 \\[beginning-of-buffer]        Go to beginning of node.
 
 Advanced commands:
-\\[Info-copy-current-node-name]        Put name of current info node in the kill ring.
+\\[Info-copy-current-node-name]        Put name of current Info node in the kill ring.
 \\[clone-buffer]       Select a new cloned Info buffer in another window.
 \\[Info-edit]  Edit contents of selected node.
 1 .. 9 Pick first ... ninth item in node's menu.
@@ -3158,6 +3340,7 @@ Advanced commands:
   (make-local-variable 'Info-tag-table-buffer)
   (setq Info-tag-table-buffer nil)
   (make-local-variable 'Info-history)
+  (make-local-variable 'Info-history-forward)
   (make-local-variable 'Info-index-alternatives)
   (setq header-line-format
        (if Info-use-header-line
@@ -3168,9 +3351,13 @@ Advanced commands:
   (make-local-variable 'line-move-ignore-invisible)
   (setq line-move-ignore-invisible t)
   (make-local-variable 'desktop-save-buffer)
+  (make-local-variable 'widen-automatically)
+  (setq widen-automatically nil)
   (setq desktop-save-buffer 'Info-desktop-buffer-misc-data)
+  (add-hook 'kill-buffer-hook 'Info-kill-buffer nil t)
   (add-hook 'clone-buffer-hook 'Info-clone-buffer-hook nil t)
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
+  (add-hook 'isearch-mode-hook 'Info-isearch-start nil t)
   (set (make-local-variable 'isearch-search-fun-function)
        'Info-isearch-search)
   (set (make-local-variable 'isearch-wrap-function)
@@ -3180,7 +3367,14 @@ Advanced commands:
   (set (make-local-variable 'search-whitespace-regexp)
        Info-search-whitespace-regexp)
   (Info-set-mode-line)
-  (run-hooks 'Info-mode-hook))
+  (run-mode-hooks 'Info-mode-hook))
+
+;; When an Info buffer is killed, make sure the associated tags buffer
+;; is killed too.
+(defun Info-kill-buffer ()
+  (and (eq major-mode 'Info-mode)
+       Info-tag-table-buffer
+       (kill-buffer Info-tag-table-buffer)))
 
 (defun Info-clone-buffer-hook ()
   (when (bufferp Info-tag-table-buffer)
@@ -3215,14 +3409,14 @@ which returns to Info mode for browsing.
   (setq buffer-read-only nil)
   (force-mode-line-update)
   (buffer-enable-undo (current-buffer))
-  (run-hooks 'Info-edit-mode-hook))
+  (run-mode-hooks 'Info-edit-mode-hook))
 
 (defun Info-edit ()
   "Edit the contents of this Info node.
 Allowed only if variable `Info-enable-edit' is non-nil."
   (interactive)
   (or Info-enable-edit
-      (error "Editing info nodes is not enabled"))
+      (error "Editing Info nodes is not enabled"))
   (Info-edit-mode)
   (message "%s" (substitute-command-keys
                 "Editing: Type \\<Info-edit-map>\\[Info-cease-edit] to return to info")))
@@ -3284,7 +3478,7 @@ in the first element of the returned list (which is treated specially in
                          "\\( <[0-9]+>\\)?:\\s *\\(.*\\)\\."
                          "\\(?:[ \t\n]+(line +\\([0-9]+\\))\\)?"))
        (info-file "emacs"))            ;default
-    ;; Determine which info file this command is documented in.
+    ;; Determine which Info file this command is documented in.
     (if (get command 'info-file)
        (setq info-file (get command 'info-file))
       ;; If it doesn't say explicitly, test its name against
@@ -3369,7 +3563,7 @@ COMMAND must be a symbol or string."
                (message "Found %d other entr%s.  Use %s to see %s."
                         (1- num-matches)
                         (if (> num-matches 2) "ies" "y")
-                        (substitute-command-keys "\\[Info-last]")
+                        (substitute-command-keys "\\[Info-history-back]")
                         (if (> num-matches 2) "them" "it")))))
       (error "Couldn't find documentation for %s" command))))
 
@@ -3393,61 +3587,6 @@ the variable `Info-file-list-for-emacs'."
          (t
           (Info-goto-emacs-command-node command)))))
 \f
-(defface Info-title-1-face
-  '((((type tty pc) (class color)) :foreground "yellow" :weight bold)
-    (t :height 1.2 :inherit Info-title-2-face))
-  "Face for Info titles at level 1."
-  :group 'info)
-
-(defface Info-title-2-face
-  '((((type tty pc) (class color)) :foreground "lightblue" :weight bold)
-    (t :height 1.2 :inherit Info-title-3-face))
-  "Face for Info titles at level 2."
-  :group 'info)
-
-(defface Info-title-3-face
-  '((((type tty pc) (class color)) :weight bold)
-    (t :height 1.2 :inherit Info-title-4-face))
-  "Face for Info titles at level 3."
-  :group 'info)
-
-(defface Info-title-4-face
-  '((((type tty pc) (class color)) :weight bold)
-    (t :weight bold :inherit variable-pitch))
-  "Face for Info titles at level 4."
-  :group 'info)
-
-(defface info-menu-header
-  '((((type tty pc))
-     :underline t
-     :weight bold)
-    (t
-     :inherit variable-pitch
-     :weight bold))
-  "Face for headers in Info menus."
-  :group 'info)
-
-(defun Info-escape-percent (string)
-  "Double all occurrences of `%' in STRING.
-
-Return a new string with all `%' characters replaced by `%%'.
-Preserve text properties."
-  (let ((start 0)
-       (end (length string))
-       mb me m matches)
-    (save-match-data
-      (while (and (< start end) (string-match "%" string start))
-       (setq mb (match-beginning 0)
-             me (1+ mb)
-             m (substring string mb me)
-             matches (cons m
-                           (cons m
-                                 (cons (substring string start mb)
-                                       matches)))
-             start me))
-      (push (substring string start end) matches)
-      (apply #'concat (nreverse matches)))))
-
 (defvar Info-next-link-keymap
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap [header-line mouse-1] 'Info-next)
@@ -3468,7 +3607,6 @@ Preserve text properties."
     keymap)
   "Keymap to put on the Prev link in the text or the header line.")
 
-
 (defvar Info-up-link-keymap
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap [header-line mouse-1] 'Info-up)
@@ -3540,7 +3678,11 @@ Preserve text properties."
                                 (buffer-substring (point) header-end)))
                 (setq header (buffer-substring (point) header-end))))
             (put-text-property (point-min) (1+ (point-min))
-                               'header-line (Info-escape-percent header))
+                               'header-line
+                              (replace-regexp-in-string
+                               "%"
+                               ;; Preserve text properties on duplicated `%'.
+                               (lambda (s) (concat s s)) header))
             ;; Hide the part of the first line
             ;; that is in the header, if it is just part.
             (unless (bobp)
@@ -3551,14 +3693,14 @@ Preserve text properties."
       ;; Fontify titles
       (goto-char (point-min))
       (when not-fontified-p
-        (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\|\\.+\\)$"
+        (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*\\*+\\|==+\\|--+\\|\\.\\.+\\)$"
                                   nil t)
           (let* ((c (preceding-char))
                  (face
-                  (cond ((= c ?*) 'Info-title-1-face)
-                        ((= c ?=) 'Info-title-2-face)
-                        ((= c ?-) 'Info-title-3-face)
-                        (t        'Info-title-4-face))))
+                  (cond ((= c ?*) 'info-title-1)
+                        ((= c ?=) 'info-title-2)
+                        ((= c ?-) 'info-title-3)
+                        (t        'info-title-4))))
             (put-text-property (match-beginning 1) (match-end 1)
                                'font-lock-face face))
           ;; This is a serious problem for trying to handle multiple
@@ -3715,76 +3857,78 @@ Preserve text properties."
         (let ((n 0)
               cont)
           (while (re-search-forward
-                  (concat "^\\* +\\(" Info-menu-entry-name-re "\\)\\(:"
-                          Info-node-spec-re "\\([ \t]*\\)\\)")
+                  (concat "^\\* Menu:\\|\\(?:^\\* +\\(" Info-menu-entry-name-re "\\)\\(:"
+                          Info-node-spec-re "\\([ \t]*\\)\\)\\)")
                   nil t)
-            (when not-fontified-p
-              (setq n (1+ n))
-              (if (and (<= n 9) (zerop (% n 3))) ; visual aids to help with 1-9 keys
-                  (put-text-property (match-beginning 0)
-                                     (1+ (match-beginning 0))
-                                     'font-lock-face 'info-menu-5)))
-            (when not-fontified-p
-              (add-text-properties
-               (match-beginning 1) (match-end 1)
-               (list
-                'help-echo (if (match-end 3)
-                               (concat "mouse-2: go to " (match-string 3))
-                             "mouse-2: go to this node")
-                'mouse-face 'highlight)))
-            (when (or not-fontified-p fontify-visited-p)
-              (add-text-properties
-               (match-beginning 1) (match-end 1)
-               (list
-                'font-lock-face
-                ;; Display visited menu items in a different face
-                (if (and Info-fontify-visited-nodes
-                         (save-match-data
-                           (let ((node (if (equal (match-string 3) "")
-                                           (match-string 1)
-                                         (match-string 3)))
-                                 (file (file-name-nondirectory Info-current-file))
-                                 (hl Info-history-list)
-                                 res)
-                             (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node)
-                                 (setq file (file-name-nondirectory
-                                             (match-string 1 node))
-                                       node (if (equal (match-string 2 node) "")
-                                                "Top"
-                                              (match-string 2 node))))
-                             (while hl
-                               (if (and (string-equal node (nth 1 (car hl)))
-                                        (string-equal file
-                                                      (file-name-nondirectory
-                                                       (nth 0 (car hl)))))
-                                   (setq res (car hl) hl nil)
-                                 (setq hl (cdr hl))))
-                             res))) 'info-xref-visited 'info-xref))))
-            (when (and not-fontified-p (memq Info-hide-note-references '(t hide)))
-              (put-text-property (match-beginning 2) (1- (match-end 6))
-                                 'invisible t)
-              ;; Unhide the file name in parens
-              (if (and (match-end 4) (not (eq (char-after (match-end 4)) ?.)))
-                  (remove-text-properties (match-beginning 4) (match-end 4)
-                                          '(invisible t)))
-              ;; We need a stretchable space like :align-to but with
-              ;; a minimum value.
-              (put-text-property (1- (match-end 6)) (match-end 6) 'display
-                                 (if (>= 22 (- (match-end 1)
-                                               (match-beginning 0)))
-                                     '(space :align-to 24)
-                                   '(space :width 2)))
-              (setq cont (looking-at "."))
-              (while (and (= (forward-line 1) 0)
-                          (looking-at "\\([ \t]+\\)[^*\n]"))
-                (put-text-property (match-beginning 1) (1- (match-end 1))
-                                   'invisible t)
-                (put-text-property (1- (match-end 1)) (match-end 1)
-                                   'display
-                                   (if cont
-                                       '(space :align-to 26)
-                                     '(space :align-to 24)))
-                (setq cont t))))))
+           (when (match-beginning 1)
+             (when not-fontified-p
+               (setq n (1+ n))
+               (if (and (<= n 9) (zerop (% n 3))) ; visual aids to help with 1-9 keys
+                   (put-text-property (match-beginning 0)
+                                      (1+ (match-beginning 0))
+                                      'font-lock-face 'info-menu-star)))
+             (when not-fontified-p
+               (add-text-properties
+                (match-beginning 1) (match-end 1)
+                (list
+                 'help-echo (if (and (match-end 3)
+                                     (not (equal (match-string 3) "")))
+                                (concat "mouse-2: go to " (match-string 3))
+                              "mouse-2: go to this node")
+                 'mouse-face 'highlight)))
+             (when (or not-fontified-p fontify-visited-p)
+               (add-text-properties
+                (match-beginning 1) (match-end 1)
+                (list
+                 'font-lock-face
+                 ;; Display visited menu items in a different face
+                 (if (and Info-fontify-visited-nodes
+                          (save-match-data
+                            (let ((node (if (equal (match-string 3) "")
+                                            (match-string 1)
+                                          (match-string 3)))
+                                  (file (file-name-nondirectory Info-current-file))
+                                  (hl Info-history-list)
+                                  res)
+                              (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node)
+                                  (setq file (file-name-nondirectory
+                                              (match-string 1 node))
+                                        node (if (equal (match-string 2 node) "")
+                                                 "Top"
+                                               (match-string 2 node))))
+                              (while hl
+                                (if (and (string-equal node (nth 1 (car hl)))
+                                         (string-equal file
+                                                       (file-name-nondirectory
+                                                        (nth 0 (car hl)))))
+                                    (setq res (car hl) hl nil)
+                                  (setq hl (cdr hl))))
+                              res))) 'info-xref-visited 'info-xref))))
+             (when (and not-fontified-p (memq Info-hide-note-references '(t hide)))
+               (put-text-property (match-beginning 2) (1- (match-end 6))
+                                  'invisible t)
+               ;; Unhide the file name in parens
+               (if (and (match-end 4) (not (eq (char-after (match-end 4)) ?.)))
+                   (remove-text-properties (match-beginning 4) (match-end 4)
+                                           '(invisible t)))
+               ;; We need a stretchable space like :align-to but with
+               ;; a minimum value.
+               (put-text-property (1- (match-end 6)) (match-end 6) 'display
+                                  (if (>= 22 (- (match-end 1)
+                                                (match-beginning 0)))
+                                      '(space :align-to 24)
+                                    '(space :width 2)))
+               (setq cont (looking-at "."))
+               (while (and (= (forward-line 1) 0)
+                           (looking-at "\\([ \t]+\\)[^*\n]"))
+                 (put-text-property (match-beginning 1) (1- (match-end 1))
+                                    'invisible t)
+                 (put-text-property (1- (match-end 1)) (match-end 1)
+                                    'display
+                                    (if cont
+                                        '(space :align-to 26)
+                                      '(space :align-to 24)))
+                 (setq cont t)))))))
 
       ;; Fontify menu headers
       ;; Add the face `info-menu-header' to any header before a menu entry
@@ -3814,19 +3958,9 @@ Preserve text properties."
 
       (set-buffer-modified-p nil))))
 \f
-
-;; When an Info buffer is killed, make sure the associated tags buffer
-;; is killed too.
-(defun Info-kill-buffer ()
-  (and (eq major-mode 'Info-mode)
-       Info-tag-table-buffer
-       (kill-buffer Info-tag-table-buffer)))
-
-(add-hook 'kill-buffer-hook 'Info-kill-buffer)
-
 ;;; Speedbar support:
 ;; These functions permit speedbar to display the "tags" in the
-;; current info node.
+;; current Info node.
 (eval-when-compile (require 'speedbar))
 
 (defvar Info-speedbar-key-map nil
@@ -3868,7 +4002,7 @@ Preserve text properties."
 ;;; Info hierarchy display method
 ;;;###autoload
 (defun Info-speedbar-browser ()
-  "Initialize speedbar to display an info node browser.
+  "Initialize speedbar to display an Info node browser.
 This will add a speedbar major display mode."
   (interactive)
   (require 'speedbar)
@@ -3961,8 +4095,7 @@ INDENT is the current indentation depth."
 
 (defun Info-speedbar-fetch-file-nodes (nodespec)
   "Fetch the subnodes from the info NODESPEC.
-NODESPEC is a string of the form: (file)node.
-Optional THISFILE represends the filename of"
+NODESPEC is a string of the form: (file)node."
   (save-excursion
     ;; Set up a buffer we can use to fake-out Info.
     (set-buffer (get-buffer-create "*info-browse-tmp*"))
@@ -4006,12 +4139,24 @@ BUFFER is the buffer speedbar is requesting buttons for."
   (Info-speedbar-hierarchy-buttons nil 0)
   )
 
-(dolist (mess '("^Node has no Previous$"
+(dolist (mess '("^First node in file$"
+               "^No `.*' in index$"
+               "^No cross-reference named"
+               "^No cross.references in this node$"
+               "^No current Info node$"
                "^No menu in this node$"
-               "^Node has no Next$"
-                "^No cross-references in this node^"
-                search-failed
-               "^No \".*\" in index$"))
+               "^No more items in menu$"
+               "^No more nodes$"
+               "^No pointer \\(?:forward\\|backward\\) from this node$"
+               "^No previous `i' command$"
+               "^No previous items in menu$"
+               "^No previous nodes$"
+               "^No such item in menu$"
+               "^No such node or anchor"
+               "^Node has no"
+               "^Point neither on reference nor in menu item description$"
+               "^This is the \\(?:first\\|last\\) Info node you looked at$"
+               search-failed))
   (add-to-list 'debug-ignored-errors mess))
 
 ;;;;  Desktop support
@@ -4021,11 +4166,10 @@ BUFFER is the buffer speedbar is requesting buttons for."
   (if (not (member Info-current-file '("apropos" "history" "toc")))
       (list Info-current-file Info-current-node)))
 
-;;;###autoload
 (defun Info-restore-desktop-buffer (desktop-buffer-file-name
                                     desktop-buffer-name
                                     desktop-buffer-misc)
-  "Restore an info buffer specified in a desktop file."
+  "Restore an Info buffer specified in a desktop file."
   (let ((first (nth 0 desktop-buffer-misc))
         (second (nth 1 desktop-buffer-misc)))
   (when (and first second)
@@ -4035,7 +4179,10 @@ BUFFER is the buffer speedbar is requesting buttons for."
     (Info-find-node first second)
     (current-buffer))))
 
+(add-to-list 'desktop-buffer-mode-handlers
+            '(Info-mode . Info-restore-desktop-buffer))
+
 (provide 'info)
 
-;;; arch-tag: f2480fe2-2139-40c1-a49b-6314991164ac
+;; arch-tag: f2480fe2-2139-40c1-a49b-6314991164ac
 ;;; info.el ends here