(Resizing Windows): Document the `preserve-before' argument of the
[bpt/emacs.git] / lisp / info.el
index 9f32c17..17905c6 100644 (file)
@@ -79,8 +79,8 @@ The Lisp code is executed when the node is selected.")
   :group 'info)
 
 (defface info-xref
-  '((((class color) (background light)) :foreground "blue")
-    (((class color) (background dark)) :foreground "cyan")
+  '((((class color) (background light)) :foreground "blue" :underline t)
+    (((class color) (background dark)) :foreground "cyan" :underline t)
     (t :underline t))
   "Face for Info cross-references."
   :group 'info)
@@ -188,7 +188,7 @@ file, so be prepared for a few surprises if you enable this feature."
   :type 'boolean
   :group 'info)
 
-(defcustom Info-search-whitespace-regexp "\\\\(?:\\\\s-+\\\\)"
+(defcustom Info-search-whitespace-regexp "\\(?:\\s-+\\)"
   "*If non-nil, regular expression to match a sequence of whitespace chars.
 This applies to Info search for regular expressions.
 You might want to use something like \"[ \\t\\r\\n]+\" instead.
@@ -455,6 +455,7 @@ Do the right thing if the file has been compressed or zipped."
 
 ;;;###autoload (add-hook 'same-window-regexps "\\*info\\*\\(\\|<[0-9]+>\\)")
 
+;;;###autoload (put 'info 'info-file "emacs")
 ;;;###autoload
 (defun info (&optional file buffer)
   "Enter Info, the documentation browser.
@@ -469,7 +470,8 @@ with the top-level Info directory.
 
 In interactive use, a non-numeric prefix argument directs
 this command to read a file name from the minibuffer.
-A numeric prefix argument appends the number to the buffer name.
+A numeric prefix argument selects an Info buffer with the prefix number
+appended to the Info buffer name.
 
 The search path for Info files is in the variable `Info-directory-list'.
 The top-level Info directory is made by combining all the files named `dir'
@@ -1061,8 +1063,8 @@ a case-insensitive match is tried."
          ;; into the menu in the like-named node in the main buffer.
          (apply 'insert-buffer-substring (cdr node))))
       (Info-dir-remove-duplicates)
-      ;; Kill all the buffers we just made.
-      (mapc 'kill-buffer buffers)
+      ;; Kill all the buffers we just made, including the special one excised.
+      (mapc 'kill-buffer (cons buffer buffers))
       (goto-char (point-min))
       (if problems
          (message "Composing main Info directory...problems encountered, see `*Messages*'")
@@ -1315,6 +1317,7 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
 ;; Go to an info node specified with a filename-and-nodename string
 ;; of the sort that is found in pointers in nodes.
 
+;;;###autoload
 (defun Info-goto-node (nodename &optional fork)
   "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
@@ -1440,8 +1443,9 @@ If FORK is a string, it is the name to use for the new buffer."
 (defvar Info-search-case-fold nil
   "The value of `case-fold-search' from previous `Info-search' command.")
 
-(defun Info-search (regexp)
-  "Search for REGEXP, starting from point, and select node it's found in."
+(defun Info-search (regexp &optional bound noerror count direction)
+  "Search for REGEXP, starting from point, and select node it's found in.
+If DIRECTION is `backward', search in the reverse direction."
   (interactive (list (read-string
                      (if Info-search-history
                          (format "Regexp search%s (default `%s'): "
@@ -1456,31 +1460,42 @@ If FORK is a string, it is the name to use for the new buffer."
     (setq regexp (car Info-search-history)))
   (when regexp
     (let (found beg-found give-up
+         (backward (eq direction 'backward))
          (onode Info-current-node)
          (ofile Info-current-file)
          (opoint (point))
+         (opoint-min (point-min))
+         (opoint-max (point-max))
          (ostart (window-start))
          (osubfile Info-current-subfile))
       (when Info-search-whitespace-regexp
-        (setq regexp (replace-regexp-in-string
-                      "[ \t\n]+" Info-search-whitespace-regexp regexp)))
+        (setq regexp
+              (mapconcat 'identity (split-string regexp "[ \t\n]+")
+                         Info-search-whitespace-regexp)))
       (setq Info-search-case-fold case-fold-search)
       (save-excursion
        (save-restriction
          (widen)
          (while (and (not give-up)
                      (or (null found)
-                         (isearch-range-invisible beg-found found)))
-           (if (re-search-forward regexp nil t)
-               (setq found (point) beg-found (match-beginning 0))
+                         (if backward
+                              (isearch-range-invisible found beg-found)
+                            (isearch-range-invisible beg-found found))))
+           (if (if backward
+                    (re-search-backward regexp bound t)
+                  (re-search-forward regexp bound t))
+               (setq found (point) beg-found (if backward (match-end 0)
+                                                (match-beginning 0)))
              (setq give-up t)))))
       ;; If no subfiles, give error now.
       (if give-up
          (if (null Info-current-subfile)
-             (re-search-forward regexp)
+             (if backward
+                  (re-search-backward regexp)
+                (re-search-forward regexp))
            (setq found nil)))
 
-      (unless found
+      (unless (or found bound)
        (unwind-protect
            ;; Try other subfiles.
            (let ((list ()))
@@ -1496,29 +1511,39 @@ If FORK is a string, it is the name to use for the new buffer."
                  ;; Find the subfile we just searched.
                  (search-forward (concat "\n" osubfile ": "))
                  ;; Skip that one.
-                 (forward-line 1)
+                 (forward-line (if backward 0 1))
                  ;; Make a list of all following subfiles.
                  ;; Each elt has the form (VIRT-POSITION . SUBFILENAME).
-                 (while (not (eobp))
-                   (re-search-forward "\\(^.*\\): [0-9]+$")
+                 (while (not (if backward (bobp) (eobp)))
+                   (if backward
+                       (re-search-backward "\\(^.*\\): [0-9]+$")
+                     (re-search-forward "\\(^.*\\): [0-9]+$"))
                    (goto-char (+ (match-end 1) 2))
                    (setq list (cons (cons (+ (point-min)
                                              (read (current-buffer)))
                                           (match-string-no-properties 1))
                                     list))
-                   (goto-char (1+ (match-end 0))))
+                   (goto-char (if backward
+                                   (1- (match-beginning 0))
+                                 (1+ (match-end 0)))))
                  ;; Put in forward order
                  (setq list (nreverse list))))
              (while list
                (message "Searching subfile %s..." (cdr (car list)))
                (Info-read-subfile (car (car list)))
+                (if backward (goto-char (point-max)))
                (setq list (cdr list))
                (setq give-up nil found nil)
                (while (and (not give-up)
                            (or (null found)
-                               (isearch-range-invisible beg-found found)))
-                 (if (re-search-forward regexp nil t)
-                     (setq found (point) beg-found (match-beginning 0))
+                               (if backward
+                                    (isearch-range-invisible found beg-found)
+                                  (isearch-range-invisible beg-found found))))
+                 (if (if backward
+                          (re-search-backward regexp nil t)
+                        (re-search-forward regexp nil t))
+                     (setq found (point) beg-found (if backward (match-end 0)
+                                                      (match-beginning 0)))
                    (setq give-up t)))
                (if give-up
                    (setq found nil))
@@ -1532,12 +1557,20 @@ If FORK is a string, it is the name to use for the new buffer."
                     (goto-char opoint)
                     (Info-select-node)
                     (set-window-start (selected-window) ostart)))))
-      (widen)
-      (goto-char found)
-      (Info-select-node)
+
+      (if (and (string= osubfile Info-current-subfile)
+               (> found opoint-min)
+               (< found opoint-max))
+          ;; Search landed in the same node
+          (goto-char found)
+        (widen)
+        (goto-char found)
+        (save-match-data (Info-select-node)))
+
       ;; 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))
          (setq Info-history (cons (list ofile onode opoint)
                                   Info-history))))))
 
@@ -1554,6 +1587,48 @@ If FORK is a string, it is the name to use for the new buffer."
     (if Info-search-history
         (Info-search (car Info-search-history))
       (call-interactively 'Info-search))))
+
+(defun Info-search-backward (regexp &optional bound noerror count)
+  "Search for REGEXP in the reverse direction."
+  (interactive (list (read-string
+                     (if Info-search-history
+                         (format "Regexp search%s backward (default `%s'): "
+                                  (if case-fold-search "" " case-sensitively")
+                                 (car Info-search-history))
+                       (format "Regexp search%s backward: "
+                                (if case-fold-search "" " case-sensitively")))
+                     nil 'Info-search-history)))
+  (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))))
+
+(defun Info-isearch-wrap ()
+  (if isearch-regexp
+      (if isearch-forward (Info-top-node) (Info-final-node))
+    (goto-char (if isearch-forward (point-min) (point-max)))))
+
+(defun Info-isearch-push-state ()
+  `(lambda (cmd)
+     (Info-isearch-pop-state cmd ,Info-current-file ,Info-current-node)))
+
+(defun Info-isearch-pop-state (cmd file node)
+  (or (and (string= Info-current-file file)
+           (string= Info-current-node node))
+      (progn (Info-find-node file node) (sit-for 0))))
+
 \f
 (defun Info-extract-pointer (name &optional errorname)
   "Extract the value of the node-pointer named NAME.
@@ -1655,7 +1730,7 @@ If SAME-FILE is non-nil, do not move to a different Info file."
       (let ((inhibit-read-only t))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\^_\nFile: history Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: history,  Node: Top,  Up: (dir)\n\n")
         (insert "Recently Visited Nodes\n**********************\n\n")
         (insert "* Menu:\n\n")
         (let ((hl (delete '("history" "Top") Info-history-list)))
@@ -1672,27 +1747,34 @@ If SAME-FILE is non-nil, do not move to a different Info file."
     (goto-char (or p (point-min)))))
 
 (defun Info-toc ()
-  "Go to a node with table of contents of the current Info file."
+  "Go to a node with table of contents of the current Info file.
+Table of contents is created from the tree structure of menus."
   (interactive)
-  (let ((curr-file Info-current-file)
-        (curr-node Info-current-node)
+  (let ((curr-file (substring-no-properties Info-current-file))
+        (curr-node (substring-no-properties Info-current-node))
         p)
     (with-current-buffer (get-buffer-create " *info-toc*")
       (let ((inhibit-read-only t)
             (node-list (Info-build-toc curr-file)))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\^_\nFile: toc Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: toc,  Node: Top,  Up: (dir)\n\n")
         (insert "Table of Contents\n*****************\n\n")
-        (insert "*Note Top::\n")
+        (insert "*Note Top: (" curr-file ")Top.\n")
         (Info-insert-toc
          (nth 2 (assoc "Top" node-list)) ; get Top nodes
          node-list 0 curr-file))
       (if (not (bobp))
           (let ((Info-hide-note-references 'hide)
                 (Info-fontify-visited-nodes nil))
+            (Info-mode)
             (setq Info-current-file "toc" Info-current-node "Top")
-            (Info-fontify-node)))
+            (goto-char (point-min))
+            (narrow-to-region (or (re-search-forward "\n[\^_\f]\n" nil t)
+                                  (point-min))
+                              (point-max))
+            (Info-fontify-node)
+            (widen)))
       (goto-char (point-min))
       (if (setq p (search-forward (concat "*Note " curr-node ":") nil t))
           (setq p (- p (length curr-node) 2))))
@@ -1713,14 +1795,12 @@ If SAME-FILE is non-nil, do not move to a different Info file."
 
 (defun Info-build-toc (file)
   "Build table of contents from menus of Info FILE and its subfiles."
-  (if (equal file "dir")
-      (error "Table of contents for Info directory is not supported yet"))
   (with-temp-buffer
-    (let* ((default-directory (or (and (stringp file)
-                                       (file-name-directory
-                                        (setq file (Info-find-file file))))
+    (let* ((file (and (stringp file) (Info-find-file file)))
+           (default-directory (or (and (stringp file)
+                                       (file-name-directory file))
                                   default-directory))
-           (main-file file)
+           (main-file (and (stringp file) file))
            (sections '(("Top" "Top")))
            nodes subfiles)
       (while (or main-file subfiles)
@@ -2349,78 +2429,97 @@ Each element has the form (INFO-FILE INDEX-NODE-NAMES-LIST).")
 (defun Info-index-nodes (&optional file)
   "Return a list of names of all index nodes in Info FILE.
 If FILE is omitted, it defaults to the current Info file.
-First look in a list of cached index node names.  Then scan Info file
-and its subfiles for nodes with index cookie.  Then try index nodes
-starting from the first node in the top level menu whose name
-contains the word \"Index\", plus any immediately following nodes
-whose names also contain the word \"Index\"."
+First look in a list of cached index node names.  Then scan Info
+file and its subfiles for nodes with the index cookie.  Then try
+to find index nodes starting from the first node in the top level
+menu whose name contains the word \"Index\", plus any immediately
+following nodes whose names also contain the word \"Index\"."
   (or file (setq file Info-current-file))
   (or (assoc file Info-index-nodes)
       ;; Skip virtual Info files
-      (member file '("dir" "history" "toc" "apropos"))
+      (and (member file '("dir" "history" "toc" "apropos"))
+           (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
+      (not (stringp file))
       ;; Find nodes with index cookie
       (let* ((default-directory (or (and (stringp file)
                                          (file-name-directory
                                           (setq file (Info-find-file file))))
                                     default-directory))
-             (main-file file)
-             (Info-fontify-maximum-menu-size nil)
-             subfiles nodes node Info-history Info-history-list)
-        (with-temp-buffer
-          (while (or main-file subfiles)
-            (erase-buffer)
-            (info-insert-file-contents (or main-file (car subfiles)))
-            (goto-char (point-min))
-            (while (search-forward "\0\10[index\0\10]" nil 'move)
-              (save-excursion
-                (re-search-backward "^\^_")
-                (search-forward "Node: ")
-                (setq nodes (cons (Info-following-node-name) nodes))))
-            (if main-file
-                (save-excursion
-                  (goto-char (point-min))
-                  (if (search-forward "\n\^_\nIndirect:" nil t)
-                      (let ((bound (save-excursion (search-forward "\n\^_" nil t))))
-                        (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t)
-                          (setq subfiles (cons (match-string-no-properties 1)
-                                               subfiles)))))
-                  (setq subfiles (nreverse subfiles)
-                        main-file nil))
-              (setq subfiles (cdr subfiles)))))
+             Info-history Info-history-list Info-fontify-maximum-menu-size
+             (main-file file) subfiles nodes node)
+        (condition-case nil
+            (with-temp-buffer
+              (while (or main-file subfiles)
+                (erase-buffer)
+                (info-insert-file-contents (or main-file (car subfiles)))
+                (goto-char (point-min))
+                (while (search-forward "\0\b[index\0\b]" nil 'move)
+                  (save-excursion
+                    (re-search-backward "^\^_")
+                    (search-forward "Node: ")
+                    (setq nodes (cons (Info-following-node-name) nodes))))
+                (if main-file
+                    (save-excursion
+                      (goto-char (point-min))
+                      (if (search-forward "\n\^_\nIndirect:" nil t)
+                          (let ((bound (save-excursion (search-forward "\n\^_" nil t))))
+                            (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t)
+                              (setq subfiles (cons (match-string-no-properties 1)
+                                                   subfiles)))))
+                      (setq subfiles (nreverse subfiles)
+                            main-file nil))
+                  (setq subfiles (cdr subfiles)))))
+          (error nil))
         (if nodes
             (setq nodes (nreverse nodes)
                   Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
         nodes)
-      ;; Find nodes with string "Index" in node names
-      (let ((Info-fontify-maximum-menu-size nil)
-            (case-fold-search t)
-            nodes node Info-history Info-history-list)
-        (with-temp-buffer
-          (Info-mode)
-          (Info-find-node file "Top")
-          (when (and (search-forward "\n* menu:" nil t)
-                     (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t))
-            (goto-char (match-beginning 1))
-            (setq nodes (list (Info-extract-menu-node-name)))
-            (Info-goto-node (car nodes))
-            (while (and (setq node (Info-extract-pointer "next" t))
-                        (string-match "\\<Index\\>" node))
-              (setq nodes (cons node nodes))
-              (Info-goto-node node))))
+      ;; Find nodes with the word "Index" in the node name
+      (let ((case-fold-search t)
+            Info-history Info-history-list Info-fontify-maximum-menu-size
+            nodes node)
+        (condition-case nil
+            (with-temp-buffer
+              (Info-mode)
+              (Info-find-node file "Top")
+              (when (and (search-forward "\n* menu:" nil t)
+                         (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t))
+                (goto-char (match-beginning 1))
+                (setq nodes (list (Info-extract-menu-node-name)))
+                (Info-goto-node (car nodes))
+                (while (and (setq node (Info-extract-pointer "next" t))
+                            (string-match "\\<Index\\>" node))
+                  (setq nodes (cons node nodes))
+                  (Info-goto-node node))))
+          (error nil))
         (if nodes
             (setq nodes (nreverse nodes)
                   Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
         nodes)
-      ;; Info file has no index nodes
-      (setq Info-index-nodes (cons (cons file nil)
-                                   Info-index-nodes)))
+      ;; If file has no index nodes, still add it to the cache
+      (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
   (cdr (assoc file Info-index-nodes)))
 
 (defun Info-index-node (&optional node file)
   "Return non-nil value if NODE is an index node.
 If NODE is nil, check the current Info node.
 If FILE is nil, check the current Info file."
-  (member (or node Info-current-node) (Info-index-nodes file)))
+  (if (or (and node (not (equal node Info-current-node)))
+          (assoc (or file Info-current-file) Info-index-nodes))
+      (member (or node Info-current-node) (Info-index-nodes file))
+    ;; Don't search all index nodes if request is only for the current node
+    ;; and file is not in the cache of index nodes
+    (or
+     (save-match-data
+       (string-match "\\<Index\\>" (or node Info-current-node "")))
+     (save-excursion
+       (goto-char (+ (or (save-excursion
+                           (search-backward "\n\^_" nil t))
+                         (point-min)) 2))
+       (search-forward "\0\b[index\0\b]"
+                       (or (save-excursion
+                             (search-forward "\n\^_" nil t))
+                           (point-max)) t)))))
 
 (defun Info-goto-index ()
   "Go to the first index node."
@@ -2766,16 +2865,21 @@ if point is in a menu item description, follow that menu item."
   (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)
   (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 "s" 'Info-search)
+  (define-key Info-mode-map "S" 'Info-search-case-sensitively)
   ;; For consistency with Rmail.
   (define-key Info-mode-map "\M-s" 'Info-search)
   (define-key Info-mode-map "\M-n" 'clone-buffer)
   (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.
+  (define-key Info-mode-map "w" 'Info-copy-current-node-name)
   (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)
@@ -2820,9 +2924,9 @@ if point is in a menu item description, follow that menu item."
    ["Last" Info-last :active Info-history
     :help "Go to the last node you were at"]
    ["History" Info-history :active Info-history-list
-    :help "Go to the history buffer"]
+    :help "Go to menu of visited nodes"]
    ["Table of Contents" Info-toc
-    :help "Go to the buffer with a table of contents"]
+    :help "Go to table of contents"]
    ("Index..."
     ["Lookup a String" Info-index
      :help "Look for a string in the index items"]
@@ -2920,20 +3024,23 @@ if point is in a menu item description, follow that menu item."
     (error (ding))))
 
 \f
-(defun Info-copy-current-node-name ()
+(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."
-  (interactive)
+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"))
-  (kill-new
-   (concat "("
-          (file-name-nondirectory
-           (if (stringp Info-current-file)
-               Info-current-file
-             (or buffer-file-name "")))
-          ")"
-          Info-current-node)))
+  (let ((node (concat "(" (file-name-nondirectory
+                           (or (and (stringp Info-current-file)
+                                    Info-current-file)
+                               buffer-file-name
+                               ""))
+                      ")" Info-current-node)))
+    (if (zerop (prefix-numeric-value arg))
+        (setq node (concat "(info \"" node "\")")))
+    (kill-new node)
+    (message "%s" node)))
 
 \f
 ;; Info mode is suitable only for specially formatted data.
@@ -2964,15 +3071,15 @@ Selecting other nodes:
 \\[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]       Go to the history buffer.
-\\[Info-toc]   Go to the buffer with a table of contents.
-\\[Info-index] Look up a topic in this file's Index and move to that node.
-\\[Info-index-next]    (comma) Move to the next match from a previous \\<Info-mode-map>\\[Info-index] command.
-\\[info-apropos]       Look for a string in the indices of all manuals.
+\\[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.
 \\[Info-final-node]    Go to the final node in this file.
 \\[Info-backward-node] Go backward one node, considering all nodes as forming one sequence.
 \\[Info-forward-node]  Go forward one node, considering all nodes as forming one sequence.
+\\[Info-index] Look up a topic in this file's Index and move to that node.
+\\[Info-index-next]    (comma) Move to the next match from a previous \\<Info-mode-map>\\[Info-index] command.
+\\[info-apropos]       Look for a string in the indices of all manuals.
 
 Moving within a node:
 \\[Info-scroll-up]     Normally, scroll forward a full screen.
@@ -2989,15 +3096,15 @@ Advanced commands:
 \\[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      Pick first item in node's menu.
-2, 3, 4, 5   Pick second ... fifth item in node's menu.
+1 .. 9 Pick first ... ninth item in node's menu.
+         Every third `*' is highlighted to help pick the right number.
 \\[Info-goto-node]     Move to node specified by name.
          You may include a filename as well, as (FILENAME)NODENAME.
 \\[universal-argument] \\[info]        Move to new Info file with completion.
+\\[universal-argument] N \\[info]      Select Info buffer with prefix number in the name *info*<N>.
 \\[Info-search]        Search through this Info file for specified regexp,
          and select the node in which the next occurrence is found.
-\\[Info-search-case-sensitively]       Search through this Info file
-         for specified regexp case-sensitively.
+\\[Info-search-case-sensitively]       Search through this Info file for specified regexp case-sensitively.
 \\[Info-search-next]   Search for another occurrence of regexp
          from a previous \\<Info-mode-map>\\[Info-search] command.
 \\[Info-next-reference]        Move cursor to next cross-reference or menu item.
@@ -3033,6 +3140,14 @@ Advanced commands:
   (setq desktop-save-buffer 'Info-desktop-buffer-misc-data)
   (add-hook 'clone-buffer-hook 'Info-clone-buffer-hook nil t)
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
+  (set (make-local-variable 'isearch-search-fun-function)
+       'Info-isearch-search)
+  (set (make-local-variable 'isearch-wrap-function)
+       'Info-isearch-wrap)
+  (set (make-local-variable 'isearch-push-state-function)
+       'Info-isearch-push-state)
+  (set (make-local-variable 'search-whitespace-regexp)
+       Info-search-whitespace-regexp)
   (Info-set-mode-line)
   (run-hooks 'Info-mode-hook))
 
@@ -3147,6 +3262,7 @@ The locations are of the format used in `Info-history', i.e.
                           (car elt)
                         elt))
                 (file (if (consp elt) (cdr elt) elt))
+                (case-fold-search nil)
                 (regexp (concat "\\`" (regexp-quote name)
                                 "\\(\\'\\|-\\)")))
            (if (string-match regexp (symbol-name command))
@@ -3329,7 +3445,8 @@ Preserve text properties."
            (fontify-visited-p ; visited nodes need to be re-fontified
             (and Info-fontify-visited-nodes
                  ;; Don't take time to refontify visited nodes in huge nodes
-                 (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size))))
+                 (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size)))
+           rbeg rend)
 
       ;; Fontify header line
       (goto-char (point-min))
@@ -3414,23 +3531,24 @@ Preserve text properties."
                 other-tag)
             (when not-fontified-p
               (when Info-hide-note-references
-                ;; *Note is often used where *note should have been
-                (goto-char start)
-                (skip-syntax-backward " ")
-                (setq other-tag
-                      (cond ((memq (char-before) '(nil ?\. ?! ??))
-                             "See ")
-                            ((memq (char-before) '(?\, ?\; ?\: ?-))
-                             "see ")
-                            ((memq (char-before) '(?\( ?\[ ?\{))
-                             ;; Check whether the paren is preceded by
-                             ;; an end of sentence
-                             (skip-syntax-backward " (")
-                             (if (memq (char-before) '(nil ?\. ?! ??))
-                                 "See "
-                               "see "))
-                            ((save-match-data (looking-at "\n\n"))
-                             "See ")))
+                (when (not (eq Info-hide-note-references 'hide))
+                  ;; *Note is often used where *note should have been
+                  (goto-char start)
+                  (skip-syntax-backward " ")
+                  (setq other-tag
+                        (cond ((memq (char-before) '(nil ?\. ?! ??))
+                               "See ")
+                              ((memq (char-before) '(?\, ?\; ?\: ?-))
+                               "see ")
+                              ((memq (char-before) '(?\( ?\[ ?\{))
+                               ;; Check whether the paren is preceded by
+                               ;; an end of sentence
+                               (skip-syntax-backward " (")
+                               (if (memq (char-before) '(nil ?\. ?! ??))
+                                   "See "
+                                 "see "))
+                              ((save-match-data (looking-at "\n\n"))
+                               "See "))))
                 (goto-char next)
                 (add-text-properties
                  (match-beginning 1)
@@ -3440,7 +3558,7 @@ Preserve text properties."
                          (if (string-match "\n" (match-string 1))
                              (+ start1 (match-beginning 0)))))
                      (match-end 1))
-                 (if (and other-tag (not (eq Info-hide-note-references 'hide)))
+                 (if other-tag
                      `(display ,other-tag front-sticky nil rear-nonsticky t)
                    '(invisible t front-sticky nil rear-nonsticky t))))
               (add-text-properties
@@ -3453,39 +3571,48 @@ Preserve text properties."
                              "mouse-2: go to this node")
                 'mouse-face 'highlight)))
             (when (or not-fontified-p fontify-visited-p)
-              (add-text-properties
-               (match-beginning 2) (match-end 2)
-               (list
-                'font-lock-face
-                ;; Display visited nodes in a different face
-                (if (and Info-fontify-visited-nodes
-                         (save-match-data
-                           (let* ((node (replace-regexp-in-string
-                                         "^[ \t]+" ""
-                                         (replace-regexp-in-string
-                                          "[ \t\n]+" " "
-                                          (or (match-string 5)
-                                              (and (not (equal (match-string 4) ""))
-                                                   (match-string 4))
-                                              (match-string 2)))))
-                                  (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))))
+              (setq rbeg (match-beginning 2)
+                    rend (match-end 2))
+              (put-text-property
+               rbeg rend
+               'font-lock-face
+               ;; Display visited nodes in a different face
+               (if (and Info-fontify-visited-nodes
+                        (save-match-data
+                          (let* ((node (replace-regexp-in-string
+                                        "^[ \t]+" ""
+                                        (replace-regexp-in-string
+                                         "[ \t\n]+" " "
+                                         (or (match-string 5)
+                                             (and (not (equal (match-string 4) ""))
+                                                  (match-string 4))
+                                             (match-string 2)))))
+                                 (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))
+              ;; For multiline ref, unfontify newline and surrounding whitespace
+              (save-excursion
+                (goto-char rbeg)
+                (save-match-data
+                  (while (re-search-forward "\\s-*\n\\s-*" rend t nil)
+                    (remove-text-properties (match-beginning 0)
+                                            (match-end 0)
+                                            '(font-lock-face t))))))
             (when not-fontified-p
               (when (memq Info-hide-note-references '(t hide))
                 (add-text-properties (match-beginning 3) (match-end 3)
@@ -3845,7 +3972,8 @@ BUFFER is the buffer speedbar is requesting buttons for."
 
 (defun Info-desktop-buffer-misc-data (desktop-dirname)
   "Auxiliary information to be saved in desktop file."
-  (list Info-current-file Info-current-node))
+  (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
@@ -3855,6 +3983,9 @@ BUFFER is the buffer speedbar is requesting buttons for."
   (let ((first (nth 0 desktop-buffer-misc))
         (second (nth 1 desktop-buffer-misc)))
   (when (and first second)
+    (when desktop-buffer-name
+      (set-buffer (get-buffer-create desktop-buffer-name))
+      (Info-mode))
     (Info-find-node first second)
     (current-buffer))))