]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
Use __sparc__ rather than sparc.
[gnu-emacs] / lisp / info.el
index 96cbb218e96545361df03984ad727d7aae03f61d..56b7e3e7fd013b617a5f736bdb2feca5fffe9fcd 100644 (file)
@@ -1,7 +1,7 @@
 ;;; info.el --- info package for Emacs
 
 ;; Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 ;;; info.el --- info package for Emacs
 
 ;; Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;;   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: help
 
 ;; Maintainer: FSF
 ;; Keywords: help
@@ -10,7 +10,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -134,7 +134,7 @@ The Lisp code is executed when the node is selected.")
   :group 'info)
 
 (defface info-xref-visited
   :group 'info)
 
 (defface info-xref-visited
-  '((t :inherit link-visited))
+  '((t :inherit (link-visited info-xref)))
   "Face for visited Info cross-references."
   :version "22.1"
   :group 'info)
   "Face for visited Info cross-references."
   :version "22.1"
   :group 'info)
@@ -146,7 +146,8 @@ The Lisp code is executed when the node is selected.")
   :group 'info)
 
 (defcustom Info-fontify-maximum-menu-size 100000
   :group 'info)
 
 (defcustom Info-fontify-maximum-menu-size 100000
-  "*Maximum size of menu to fontify if `font-lock-mode' is non-nil."
+  "*Maximum size of menu to fontify if `font-lock-mode' is non-nil.
+Set to nil to disable node fontification."
   :type 'integer
   :group 'info)
 
   :type 'integer
   :group 'info)
 
@@ -287,7 +288,7 @@ It doesn't contain directory names or file name extensions added by Info.")
 
 (defvar Info-current-subfile nil
   "Info subfile that is actually in the *info* buffer now.
 
 (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.")
+It is 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.")
 
 (defvar Info-current-node nil
   "Name of node that Info is now looking at, or nil.")
@@ -463,12 +464,12 @@ Do the right thing if the file has been compressed or zipped."
                     (expand-file-name "info/" installation-directory)
                   (if invocation-directory
                       (let ((infodir (expand-file-name
                     (expand-file-name "info/" installation-directory)
                   (if invocation-directory
                       (let ((infodir (expand-file-name
-                                      "../info/"
+                                      "../share/info/"
                                       invocation-directory)))
                         (if (file-exists-p infodir)
                             infodir
                           (setq infodir (expand-file-name
                                       invocation-directory)))
                         (if (file-exists-p infodir)
                             infodir
                           (setq infodir (expand-file-name
-                                         "../../../info/"
+                                         "../../../share/info/"
                                          invocation-directory))
                           (and (file-exists-p infodir)
                                infodir))))))
                                          invocation-directory))
                           (and (file-exists-p infodir)
                                infodir))))))
@@ -622,12 +623,6 @@ just return nil (no error)."
        (cond
         ((string= (downcase filename) "dir")
          (setq found t))
        (cond
         ((string= (downcase filename) "dir")
          (setq found t))
-        ((string= filename "apropos")
-         (setq found 'apropos))
-        ((string= filename "history")
-         (setq found 'history))
-        ((string= filename "toc")
-         (setq found 'toc))
         (t
          (let ((dirs (if (string-match "^\\./" filename)
                           ;; If specified name starts with `./'
         (t
          (let ((dirs (if (string-match "^\\./" filename)
                           ;; If specified name starts with `./'
@@ -673,7 +668,8 @@ just return nil (no error)."
           (if noerror
               (setq filename nil)
             (error "Info file %s does not exist" filename)))
           (if noerror
               (setq filename nil)
             (error "Info file %s does not exist" filename)))
-        filename)))
+        filename)
+    (and (member filename '(apropos history toc)) filename)))
 
 (defun Info-find-node (filename nodename &optional no-going-back)
   "Go to an Info node specified as separate FILENAME and NODENAME.
 
 (defun Info-find-node (filename nodename &optional no-going-back)
   "Go to an Info node specified as separate FILENAME and NODENAME.
@@ -849,7 +845,7 @@ a case-insensitive match is tried."
                (goto-char (point-min))
                (condition-case ()
                    (if (and (re-search-forward
                (goto-char (point-min))
                (condition-case ()
                    (if (and (re-search-forward
-                             "makeinfo version \\([0-9]+.[0-9]+\\)"
+                             "makeinfo[ \n]version[ \n]\\([0-9]+.[0-9]+\\)"
                              (line-beginning-position 3) t)
                             (not (version< (match-string 1) "4.7")))
                        (setq found t))
                              (line-beginning-position 3) t)
                             (not (version< (match-string 1) "4.7")))
                        (setq found t))
@@ -891,9 +887,6 @@ a case-insensitive match is tried."
               (setq Info-current-file
                    (cond
                     ((eq filename t) "dir")
               (setq Info-current-file
                    (cond
                     ((eq filename t) "dir")
-                    ((eq filename 'apropos) "apropos")
-                    ((eq filename 'history) "history")
-                    ((eq filename 'toc) "toc")
                     (t filename)))
              ))
         ;; Use string-equal, not equal, to ignore text props.
                     (t filename)))
              ))
         ;; Use string-equal, not equal, to ignore text props.
@@ -1204,7 +1197,9 @@ a case-insensitive match is tried."
                  (point)
                  (if (re-search-forward "^[^* \n\t]" nil t)
                      (match-beginning 0)
                  (point)
                  (if (re-search-forward "^[^* \n\t]" nil t)
                      (match-beginning 0)
-                   (or limit (point-max)))) entries))))
+                   (or limit (point-max))))
+                entries)
+               (forward-line 0))))
          ;; Insert the entries just found.
          (while (= (line-beginning-position 0) (1- (point)))
            (backward-char))
          ;; Insert the entries just found.
          (while (= (line-beginning-position 0) (1- (point)))
            (backward-char))
@@ -1215,10 +1210,11 @@ a case-insensitive match is tried."
 
          ;; Now remove duplicate entries under the same heading.
          (let ((seen nil)
 
          ;; Now remove duplicate entries under the same heading.
          (let ((seen nil)
-               (limit (point)))
+               (limit (point-marker)))
            (goto-char start)
            (goto-char start)
-           (while (re-search-forward "^* \\([^:\n]+:\\(:\\|[^.\n]+\\).\\)"
-                                     limit 'move)
+           (while (and (> limit (point))
+                       (re-search-forward "^* \\([^:\n]+:\\(:\\|[^.\n]+\\).\\)"
+                                          limit 'move))
              ;; Fold case straight away; `member-ignore-case' here wasteful.
              (let ((x (downcase (match-string 1))))
                (if (member x seen)
              ;; Fold case straight away; `member-ignore-case' here wasteful.
              (let ((x (downcase (match-string 1))))
                (if (member x seen)
@@ -1319,16 +1315,25 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
              nil t)
        (let* ((start (match-beginning 1))
               (parameter-alist (Info-split-parameter-string (match-string 2)))
              nil t)
        (let* ((start (match-beginning 1))
               (parameter-alist (Info-split-parameter-string (match-string 2)))
-              (src (cdr (assoc-string "src" parameter-alist)))
-              (image-file (if src (if (file-name-absolute-p src) src
-                                    (concat default-directory src))
-                            ""))
-              (image (if (file-exists-p image-file)
-                         (create-image image-file)
-                       "[broken image]")))
-         (if (not (get-text-property start 'display))
-             (add-text-properties
-              start (point) `(display ,image rear-nonsticky (display)))))))
+               (src (cdr (assoc-string "src" parameter-alist))))
+          (if (display-images-p)
+              (let* ((image-file (if src (if (file-name-absolute-p src) src
+                                           (concat default-directory src))
+                                   ""))
+                     (image (if (file-exists-p image-file)
+                                (create-image image-file)
+                              "[broken image]")))
+                (if (not (get-text-property start 'display))
+                    (add-text-properties
+                     start (point) `(display ,image rear-nonsticky (display)))))
+            ;; text-only display, show alternative text if provided, or
+            ;; otherwise a clue that there's meant to be a picture
+            (delete-region start (point))
+            (insert (or (cdr (assoc-string "text" parameter-alist))
+                        (cdr (assoc-string "alt" parameter-alist))
+                        (and src
+                             (concat "[image:" src "]"))
+                        "[image]"))))))
     (set-buffer-modified-p nil)))
 
 ;; Texinfo 4.7 adds cookies of the form ^@^H[NAME CONTENTS ^@^H].
     (set-buffer-modified-p nil)))
 
 ;; Texinfo 4.7 adds cookies of the form ^@^H[NAME CONTENTS ^@^H].
@@ -1395,8 +1400,8 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
 
 (defvar Info-mode-line-node-keymap
   (let ((map (make-sparse-keymap)))
 
 (defvar Info-mode-line-node-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map [mode-line mouse-1] 'Info-scroll-up)
-    (define-key map [mode-line mouse-3] 'Info-scroll-down)
+    (define-key map [mode-line mouse-1] 'Info-mouse-scroll-up)
+    (define-key map [mode-line mouse-3] 'Info-mouse-scroll-down)
     map)
   "Keymap to put on the Info node name in the mode line.")
 
     map)
   "Keymap to put on the Info node name in the mode line.")
 
@@ -1407,11 +1412,13 @@ any double quotes or backslashes must be escaped (\\\",\\\\)."
                (concat
                 " ("
                 (if (stringp Info-current-file)
                (concat
                 " ("
                 (if (stringp Info-current-file)
-                    (file-name-nondirectory Info-current-file)
-                  "")
+                    (replace-regexp-in-string
+                     "%" "%%" (file-name-nondirectory Info-current-file))
+                  (format "*%S*" Info-current-file))
                 ") "
                 (if Info-current-node
                 ") "
                 (if Info-current-node
-                    (propertize Info-current-node
+                    (propertize (replace-regexp-in-string
+                                 "%" "%%" Info-current-node)
                                 'face 'mode-line-buffer-id
                                 'help-echo
                                 "mouse-1: scroll forward, mouse-3: scroll back"
                                 'face 'mode-line-buffer-id
                                 'help-echo
                                 "mouse-1: scroll forward, mouse-3: scroll back"
@@ -1554,6 +1561,8 @@ PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
            (node-regexp "Node: *\\([^,\n]*\\) *[,\n\t]"))
        (save-excursion
          (save-restriction
            (node-regexp "Node: *\\([^,\n]*\\) *[,\n\t]"))
        (save-excursion
          (save-restriction
+           (or Info-tag-table-marker
+               (error "No Info tags found"))
            (if (marker-buffer Info-tag-table-marker)
                (let ((marker Info-tag-table-marker))
                  (set-buffer (marker-buffer marker))
            (if (marker-buffer Info-tag-table-marker)
                (let ((marker Info-tag-table-marker))
                  (set-buffer (marker-buffer marker))
@@ -1646,8 +1655,11 @@ If DIRECTION is `backward', search in the reverse direction."
                            ;; Skip Tag Table node
                            (save-excursion
                              (and (search-backward "\^_" nil t)
                            ;; Skip Tag Table node
                            (save-excursion
                              (and (search-backward "\^_" nil t)
-                                  (looking-at "\^_\nTag Table"))))))
-           (let ((search-spaces-regexp Info-search-whitespace-regexp))
+                                  (looking-at
+                                   "\^_\n\\(Tag Table\\|Local Variables\\)"))))))
+           (let ((search-spaces-regexp
+                  (if (or (not isearch-mode) isearch-regexp)
+                      Info-search-whitespace-regexp)))
              (if (if backward
                      (re-search-backward regexp bound t)
                    (re-search-forward regexp bound t))
              (if (if backward
                      (re-search-backward regexp bound t)
                    (re-search-forward regexp bound t))
@@ -1665,7 +1677,9 @@ If DIRECTION is `backward', search in the reverse direction."
       ;; If no subfiles, give error now.
       (if give-up
          (if (null Info-current-subfile)
       ;; If no subfiles, give error now.
       (if give-up
          (if (null Info-current-subfile)
-             (let ((search-spaces-regexp Info-search-whitespace-regexp))
+             (let ((search-spaces-regexp
+                    (if (or (not isearch-mode) isearch-regexp)
+                        Info-search-whitespace-regexp)))
                (if backward
                    (re-search-backward regexp)
                  (re-search-forward regexp)))
                (if backward
                    (re-search-backward regexp)
                  (re-search-forward regexp)))
@@ -1734,8 +1748,11 @@ If DIRECTION is `backward', search in the reverse direction."
                                  ;; Skip Tag Table node
                                  (save-excursion
                                    (and (search-backward "\^_" nil t)
                                  ;; Skip Tag Table node
                                  (save-excursion
                                    (and (search-backward "\^_" nil t)
-                                        (looking-at "\^_\nTag Table"))))))
-                 (let ((search-spaces-regexp Info-search-whitespace-regexp))
+                                        (looking-at
+                                         "\^_\n\\(Tag Table\\|Local Variables\\)"))))))
+                 (let ((search-spaces-regexp
+                        (if (or (not isearch-mode) isearch-regexp)
+                            Info-search-whitespace-regexp)))
                    (if (if backward
                            (re-search-backward regexp nil t)
                          (re-search-forward regexp nil t))
                    (if (if backward
                            (re-search-backward regexp nil t)
                          (re-search-forward regexp nil t))
@@ -1812,8 +1829,8 @@ If DIRECTION is `backward', search in the reverse direction."
                         (unless isearch-forward 'backward))
          (Info-search (if isearch-regexp string (regexp-quote string))
                       bound noerror count
                         (unless isearch-forward 'backward))
          (Info-search (if isearch-regexp string (regexp-quote string))
                       bound noerror count
-                      (unless isearch-forward 'backward))
-         (point)))
+                      (unless isearch-forward 'backward)))
+       (point))
     (let ((isearch-search-fun-function nil))
       (isearch-search-fun))))
 
     (let ((isearch-search-fun-function nil))
       (isearch-search-fun))))
 
@@ -1829,11 +1846,11 @@ If DIRECTION is `backward', search in the reverse direction."
 
 (defun Info-isearch-push-state ()
   `(lambda (cmd)
 
 (defun Info-isearch-push-state ()
   `(lambda (cmd)
-     (Info-isearch-pop-state cmd ,Info-current-file ,Info-current-node)))
+     (Info-isearch-pop-state cmd ',Info-current-file ',Info-current-node)))
 
 (defun Info-isearch-pop-state (cmd file node)
 
 (defun Info-isearch-pop-state (cmd file node)
-  (or (and (string= Info-current-file file)
-           (string= Info-current-node node))
+  (or (and (equal Info-current-file file)
+           (equal Info-current-node node))
       (progn (Info-find-node file node) (sit-for 0))))
 
 (defun Info-isearch-start ()
       (progn (Info-find-node file node) (sit-for 0))))
 
 (defun Info-isearch-start ()
@@ -1851,7 +1868,7 @@ if ERRORNAME is nil, just return nil."
        (forward-line 1)
        (cond ((re-search-backward
                (concat name ":" (Info-following-node-name-re)) bound t)
        (forward-line 1)
        (cond ((re-search-backward
                (concat name ":" (Info-following-node-name-re)) bound t)
-              (match-string 1))
+              (match-string-no-properties 1))
              ((not (eq errorname t))
               (error "Node has no %s"
                      (capitalize (or errorname name)))))))))
              ((not (eq errorname t))
               (error "Node has no %s"
                      (capitalize (or errorname name)))))))))
@@ -1873,7 +1890,7 @@ End of submatch 0, 1, and 3 are the same, so you can safely concat."
 ;;; For compatibility; other files have used this name.
 (defun Info-following-node-name ()
   (and (looking-at (Info-following-node-name-re))
 ;;; For compatibility; other files have used this name.
 (defun Info-following-node-name ()
   (and (looking-at (Info-following-node-name-re))
-       (match-string 1)))
+       (match-string-no-properties 1)))
 
 (defun Info-next ()
   "Go to the next node of this node."
 
 (defun Info-next ()
   "Go to the next node of this node."
@@ -1907,7 +1924,8 @@ If SAME-FILE is non-nil, do not move to a different Info file."
       (Info-goto-node node)
       (setq p (point))
       (goto-char (point-min))
       (Info-goto-node node)
       (setq p (point))
       (goto-char (point-min))
-      (if (and (search-forward "\n* Menu:" nil t)
+      (if (and (stringp old-file)
+              (search-forward "\n* Menu:" nil t)
               (re-search-forward
                (if (string-equal old-node "Top")
                    (concat "\n\\*[^:]+: +(" (file-name-nondirectory old-file) ")")
               (re-search-forward
                (if (string-equal old-node "Top")
                    (concat "\n\\*[^:]+: +(" (file-name-nondirectory old-file) ")")
@@ -1975,51 +1993,53 @@ If SAME-FILE is non-nil, do not move to a different Info file."
           (while hl
             (let ((file (nth 0 (car hl)))
                   (node (nth 1 (car hl))))
           (while hl
             (let ((file (nth 0 (car hl)))
                   (node (nth 1 (car hl))))
-              (if (and (string-equal file curr-file)
-                       (string-equal node curr-node))
+              (if (and (equal file curr-file)
+                       (equal node curr-node))
                   (setq p (point)))
                   (setq p (point)))
-              (insert "* " node ": ("
-                     (propertize (or (file-name-directory file) "") 'invisible t)
-                     (file-name-nondirectory file)
-                      ")" node ".\n"))
+              (if (stringp file)
+                 (insert "* " node ": ("
+                         (propertize (or (file-name-directory file) "") 'invisible t)
+                         (file-name-nondirectory file)
+                         ")" node ".\n")))
             (setq hl (cdr hl))))))
             (setq hl (cdr hl))))))
-    (Info-find-node "history" "Top")
+    (Info-find-node 'history "Top")
     (goto-char (or p (point-min)))))
 
 (defun Info-toc ()
   "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)
     (goto-char (or p (point-min)))))
 
 (defun Info-toc ()
   "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 (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 "Table of Contents\n*****************\n\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")
-            (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))))
-    (Info-find-node "toc" "Top")
-    (goto-char (or p (point-min)))))
+  (if (stringp Info-current-file)
+      (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 "Table of Contents\n*****************\n\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")
+               (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))))
+       (Info-find-node 'toc "Top")
+       (goto-char (or p (point-min))))))
 
 (defun Info-insert-toc (nodes node-list level curr-file)
   "Insert table of contents with references to nodes."
 
 (defun Info-insert-toc (nodes node-list level curr-file)
   "Insert table of contents with references to nodes."
@@ -2219,16 +2239,18 @@ Because of ambiguities, this should be concatenated with something like
         (setq Info-point-loc
               (if (match-beginning 5)
                   (string-to-number (match-string 5))
         (setq Info-point-loc
               (if (match-beginning 5)
                   (string-to-number (match-string 5))
-                (buffer-substring (match-beginning 0) (1- (match-beginning 1)))))
+                (buffer-substring-no-properties
+                (match-beginning 0) (1- (match-beginning 1)))))
 ;;; Uncomment next line to use names of cross-references in non-index nodes:
 ;;;       (setq Info-point-loc
 ;;;             (buffer-substring (match-beginning 0) (1- (match-beginning 1))))
       )
     (replace-regexp-in-string
      "[ \n]+" " "
 ;;; Uncomment next line to use names of cross-references in non-index nodes:
 ;;;       (setq Info-point-loc
 ;;;             (buffer-substring (match-beginning 0) (1- (match-beginning 1))))
       )
     (replace-regexp-in-string
      "[ \n]+" " "
-     (or (match-string 2)
+     (or (match-string-no-properties 2)
         ;; If the node name is the menu entry name (using `entry::').
         ;; If the node name is the menu entry name (using `entry::').
-        (buffer-substring (match-beginning 0) (1- (match-beginning 1)))))))
+        (buffer-substring-no-properties
+         (match-beginning 0) (1- (match-beginning 1)))))))
 
 ;; No one calls this.
 ;;(defun Info-menu-item-sequence (list)
 
 ;; No one calls this.
 ;;(defun Info-menu-item-sequence (list)
@@ -2598,6 +2620,15 @@ in other ways.)"
         (t (Info-next-preorder)))
       (scroll-up))))
 
         (t (Info-next-preorder)))
       (scroll-up))))
 
+(defun Info-mouse-scroll-up (e)
+  "Scroll one screenful forward in Info, using the mouse.
+See `Info-scroll-up'."
+  (interactive "e")
+  (save-selected-window
+    (if (eventp e)
+       (select-window (posn-window (event-start e))))
+    (Info-scroll-up)))
+
 (defun Info-scroll-down ()
   "Scroll one screenful back in Info, considering all nodes as one sequence.
 If point is within the menu of a node, and `Info-scroll-prefer-subnodes'
 (defun Info-scroll-down ()
   "Scroll one screenful back in Info, considering all nodes as one sequence.
 If point is within the menu of a node, and `Info-scroll-prefer-subnodes'
@@ -2624,6 +2655,15 @@ parent node."
        (Info-last-preorder)
       (scroll-down))))
 
        (Info-last-preorder)
       (scroll-down))))
 
+(defun Info-mouse-scroll-down (e)
+  "Scroll one screenful backward in Info, using the mouse.
+See `Info-scroll-down'."
+  (interactive "e")
+  (save-selected-window
+    (if (eventp e)
+       (select-window (posn-window (event-start e))))
+    (Info-scroll-down)))
+
 (defun Info-next-reference (&optional recur)
   "Move cursor to the next cross-reference or menu item in the node."
   (interactive)
 (defun Info-next-reference (&optional recur)
   "Move cursor to the next cross-reference or menu item in the node."
   (interactive)
@@ -2682,7 +2722,7 @@ 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
   (or file (setq file Info-current-file))
   (or (assoc file Info-index-nodes)
       ;; Skip virtual Info files
-      (and (member file '("dir" "history" "toc" "apropos"))
+      (and (member file '("dir" apropos history toc))
            (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
       (not (stringp file))
       (if Info-file-supports-index-cookies
            (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
       (not (stringp file))
       (if Info-file-supports-index-cookies
@@ -2782,7 +2822,8 @@ Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches.
 Give an empty topic name to go to the Index node itself."
   (interactive
    (list
 Give an empty topic name to go to the Index node itself."
   (interactive
    (list
-    (let ((Info-complete-menu-buffer (clone-buffer))
+    (let ((completion-ignore-case t)
+         (Info-complete-menu-buffer (clone-buffer))
          (Info-complete-nodes (Info-index-nodes))
          (Info-history-list nil))
       (if (equal Info-current-file "dir")
          (Info-complete-nodes (Info-index-nodes))
          (Info-history-list nil))
       (if (equal Info-current-file "dir")
@@ -2794,6 +2835,11 @@ Give an empty topic name to go to the Index node itself."
        (kill-buffer Info-complete-menu-buffer)))))
   (if (equal Info-current-file "dir")
       (error "The Info directory node has no index; use m to select a manual"))
        (kill-buffer Info-complete-menu-buffer)))))
   (if (equal Info-current-file "dir")
       (error "The Info directory node has no index; use m to select a manual"))
+  ;; Strip leading colon in topic; index format does not allow them.
+  (if (and (stringp topic)
+          (> (length topic) 0)
+          (= (aref topic 0) ?:))
+      (setq topic (substring topic 1)))
   (let ((orignode Info-current-node)
        (pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
                         (regexp-quote topic)))
   (let ((orignode Info-current-node)
        (pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
                         (regexp-quote topic)))
@@ -2856,8 +2902,11 @@ Give an empty topic name to go to the Index node itself."
           (car (car Info-index-alternatives))
           (nth 2 (car Info-index-alternatives))
           (if (cdr Info-index-alternatives)
           (car (car Info-index-alternatives))
           (nth 2 (car Info-index-alternatives))
           (if (cdr Info-index-alternatives)
-              (format "(%s total; use `,' for next)"
-                      (length Info-index-alternatives))
+              (format "(%s total; use `%s' for next)"
+                      (length Info-index-alternatives)
+                      (key-description (where-is-internal
+                                        'Info-index-next overriding-local-map
+                                        t)))
             "(Only match)")))
 
 (defun Info-find-index-name (name)
             "(Only match)")))
 
 (defun Info-find-index-name (name)
@@ -2897,11 +2946,20 @@ Build a menu of the possible matches."
          manuals matches node nodes)
       (let ((Info-fontify-maximum-menu-size nil))
        (Info-directory)
          manuals matches node nodes)
       (let ((Info-fontify-maximum-menu-size nil))
        (Info-directory)
+       ;; current-node and current-file are nil when they invoke info-apropos
+       ;; as the first Info command, i.e. info-apropos loads info.el.  In that
+       ;; case, we use (DIR)Top instead, to avoid signalling an error after
+       ;; the search is complete.
+       (when (null current-node)
+         (setq current-file Info-current-file)
+         (setq current-node Info-current-node))
        (message "Searching indices...")
        (goto-char (point-min))
        (re-search-forward "\\* Menu: *\n" nil t)
        (while (re-search-forward "\\*.*: *(\\([^)]+\\))" nil t)
        (message "Searching indices...")
        (goto-char (point-min))
        (re-search-forward "\\* Menu: *\n" nil t)
        (while (re-search-forward "\\*.*: *(\\([^)]+\\))" nil t)
-         (setq manuals (cons (match-string 1) manuals)))
+         ;; add-to-list makes sure we don't have duplicates in `manuals',
+         ;; so that the following dolist loop runs faster.
+         (add-to-list 'manuals (match-string 1)))
        (dolist (manual (nreverse manuals))
          (message "Searching %s" manual)
          (condition-case err
        (dolist (manual (nreverse manuals))
          (message "Searching %s" manual)
          (condition-case err
@@ -2924,7 +2982,7 @@ Build a menu of the possible matches."
             (message "%s" (if (eq (car-safe err) 'error)
                               (nth 1 err) err))
             (sit-for 1 t)))))
             (message "%s" (if (eq (car-safe err) 'error)
                               (nth 1 err) err))
             (sit-for 1 t)))))
-      (Info-goto-node (concat "(" current-file ")" current-node))
+      (Info-find-node current-file current-node)
       (setq Info-history ohist
            Info-history-list ohist-list)
       (message "Searching indices...done")
       (setq Info-history ohist
            Info-history-list ohist-list)
       (message "Searching indices...done")
@@ -2943,7 +3001,7 @@ Build a menu of the possible matches."
                     (if (nth 3 entry)
                         (concat " (line " (nth 3 entry) ")")
                       "")))))
                     (if (nth 3 entry)
                         (concat " (line " (nth 3 entry) ")")
                       "")))))
-       (Info-find-node "apropos" "Index")
+       (Info-find-node 'apropos "Index")
        (setq Info-complete-cache nil)))))
 
 (defun Info-undefined ()
        (setq Info-complete-cache nil)))))
 
 (defun Info-undefined ()
@@ -3034,7 +3092,11 @@ At end of the node's text, moves to the next node, or up if none."
 (defun Info-follow-nearest-node (&optional fork)
   "Follow a node reference near point.
 If point is on a reference, follow that reference.  Otherwise,
 (defun Info-follow-nearest-node (&optional fork)
   "Follow a node reference near point.
 If point is on a reference, follow that reference.  Otherwise,
-if point is in a menu item description, follow that menu item."
+if point is in a menu item description, follow that menu item.
+
+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 new buffer."
   (interactive "P")
   (or (Info-try-follow-nearest-node fork)
       (when (save-excursion
   (interactive "P")
   (or (Info-try-follow-nearest-node fork)
       (when (save-excursion
@@ -3051,7 +3113,8 @@ if point is in a menu item description, follow that menu item."
 
 ;; Common subroutine.
 (defun Info-try-follow-nearest-node (&optional fork)
 
 ;; Common subroutine.
 (defun Info-try-follow-nearest-node (&optional fork)
-  "Follow a node reference near point.  Return non-nil if successful."
+  "Follow a node reference near point.  Return non-nil if successful.
+If FORK is non-nil, it i spassed to `Info-goto-node'."
   (let (node)
     (cond
      ((Info-get-token (point) "[hf]t?tp://" "[hf]t?tp://\\([^ \t\n\"`({<>})']+\\)")
   (let (node)
     (cond
      ((Info-get-token (point) "[hf]t?tp://" "[hf]t?tp://\\([^ \t\n\"`({<>})']+\\)")
@@ -3199,16 +3262,20 @@ if point is in a menu item description, follow that menu item."
 (defvar info-tool-bar-map
   (if (display-graphic-p)
       (let ((map (make-sparse-keymap)))
 (defvar info-tool-bar-map
   (if (display-graphic-p)
       (let ((map (make-sparse-keymap)))
-       (tool-bar-local-item-from-menu 'Info-exit "close" map Info-mode-map)
-       (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map)
-       (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map)
-       (tool-bar-local-item-from-menu 'Info-prev "prev-node" map Info-mode-map)
-       (tool-bar-local-item-from-menu 'Info-next "next-node" map Info-mode-map)
+       (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map
+                                      :rtl "right-arrow")
+       (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map
+                                      :rtl "left-arrow")
+       (tool-bar-local-item-from-menu 'Info-prev "prev-node" map Info-mode-map
+                                      :rtl "next-node")
+       (tool-bar-local-item-from-menu 'Info-next "next-node" map Info-mode-map
+                                      :rtl "prev-node")
        (tool-bar-local-item-from-menu 'Info-up "up-node" 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-goto-node "jump-to" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-search "search" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-up "up-node" 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-goto-node "jump-to" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map)
        (tool-bar-local-item-from-menu 'Info-search "search" map Info-mode-map)
+       (tool-bar-local-item-from-menu 'Info-exit "exit" map Info-mode-map)
        map)))
 
 (defvar Info-menu-last-node nil)
        map)))
 
 (defvar Info-menu-last-node nil)
@@ -3285,10 +3352,14 @@ 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"))
   (interactive "P")
   (unless Info-current-node
     (error "No current Info node"))
-  (let ((node (concat "(" (file-name-nondirectory Info-current-file) ")"
-                     Info-current-node)))
+  (let ((node (if (stringp Info-current-file)
+                 (concat "(" (file-name-nondirectory Info-current-file) ")"
+                         Info-current-node))))
     (if (zerop (prefix-numeric-value arg))
         (setq node (concat "(info \"" node "\")")))
     (if (zerop (prefix-numeric-value arg))
         (setq node (concat "(info \"" node "\")")))
+    (unless (stringp Info-current-file)
+      (setq node (format "(Info-find-node '%S '%S)"
+                        Info-current-file Info-current-node)))
     (kill-new node)
     (message "%s" node)))
 
     (kill-new node)
     (message "%s" node)))
 
@@ -3396,7 +3467,7 @@ Advanced commands:
   (setq widen-automatically nil)
   (setq desktop-save-buffer 'Info-desktop-buffer-misc-data)
   (add-hook 'kill-buffer-hook 'Info-kill-buffer nil t)
   (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 'clone-buffer-hook 'Info-clone-buffer 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)
   (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)
@@ -3417,7 +3488,8 @@ Advanced commands:
        Info-tag-table-buffer
        (kill-buffer Info-tag-table-buffer)))
 
        Info-tag-table-buffer
        (kill-buffer Info-tag-table-buffer)))
 
-(defun Info-clone-buffer-hook ()
+;; Placed on `clone-buffer-hook'.
+(defun Info-clone-buffer ()
   (when (bufferp Info-tag-table-buffer)
     (setq Info-tag-table-buffer
          (with-current-buffer Info-tag-table-buffer (clone-buffer))))
   (when (bufferp Info-tag-table-buffer)
     (setq Info-tag-table-buffer
          (with-current-buffer Info-tag-table-buffer (clone-buffer))))
@@ -3666,6 +3738,7 @@ the variable `Info-file-list-for-emacs'."
            (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
            (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
+                Info-fontify-maximum-menu-size
                  (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size)))
            rbeg rend)
 
                  (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size)))
            rbeg rend)
 
@@ -3774,6 +3847,8 @@ the variable `Info-file-list-for-emacs'."
                   (setq other-tag
                        (cond ((save-match-data (looking-back "\\<see"))
                               "")
                   (setq other-tag
                        (cond ((save-match-data (looking-back "\\<see"))
                               "")
+                             ((save-match-data (looking-back "\\<in"))
+                              "")
                              ((memq (char-before) '(nil ?\. ?! ??))
                                "See ")
                              ((save-match-data
                              ((memq (char-before) '(nil ?\. ?! ??))
                                "See ")
                              ((save-match-data
@@ -3815,29 +3890,30 @@ the variable `Info-file-list-for-emacs'."
                                         "^[ \t]+" ""
                                         (replace-regexp-in-string
                                          "[ \t\n]+" " "
                                         "^[ \t]+" ""
                                         (replace-regexp-in-string
                                          "[ \t\n]+" " "
-                                         (or (match-string 5)
+                                         (or (match-string-no-properties 5)
                                              (and (not (equal (match-string 4) ""))
                                              (and (not (equal (match-string 4) ""))
-                                                  (match-string 4))
-                                             (match-string 2)))))
+                                                  (match-string-no-properties 4))
+                                             (match-string-no-properties 2)))))
                                 (external-link-p
                                  (string-match "(\\([^)]+\\))\\([^)]*\\)" node))
                                  (file (if external-link-p
                                           (file-name-nondirectory
                                 (external-link-p
                                  (string-match "(\\([^)]+\\))\\([^)]*\\)" node))
                                  (file (if external-link-p
                                           (file-name-nondirectory
-                                           (match-string 1 node))
+                                           (match-string-no-properties 1 node))
                                         Info-current-file))
                                  (hl Info-history-list)
                                  res)
                             (if external-link-p
                                (setq node (if (equal (match-string 2 node) "")
                                                "Top"
                                         Info-current-file))
                                  (hl Info-history-list)
                                  res)
                             (if external-link-p
                                (setq node (if (equal (match-string 2 node) "")
                                                "Top"
-                                             (match-string 2 node))))
+                                             (match-string-no-properties 2 node))))
                            (while hl
                              (if (and (string-equal node (nth 1 (car hl)))
                            (while hl
                              (if (and (string-equal node (nth 1 (car hl)))
-                                      (string-equal
-                                       file (if external-link-p
-                                                (file-name-nondirectory
-                                                 (caar hl))
-                                              (caar hl))))
+                                      (equal file
+                                             (if (and external-link-p
+                                                      (stringp (caar hl)))
+                                                 (file-name-nondirectory
+                                                  (caar hl))
+                                               (caar hl))))
                                  (setq res (car hl) hl nil)
                                (setq hl (cdr hl))))
                             res))) 'info-xref-visited 'info-xref))
                                  (setq res (car hl) hl nil)
                                (setq hl (cdr hl))))
                             res))) 'info-xref-visited 'info-xref))
@@ -3897,8 +3973,8 @@ the variable `Info-file-list-for-emacs'."
       (goto-char (point-min))
       (when (and (or not-fontified-p fontify-visited-p)
                  (search-forward "\n* Menu:" nil t)
       (goto-char (point-min))
       (when (and (or not-fontified-p fontify-visited-p)
                  (search-forward "\n* Menu:" nil t)
-                 (not (Info-index-node))
                  ;; Don't take time to annotate huge menus
                  ;; Don't take time to annotate huge menus
+                Info-fontify-maximum-menu-size
                  (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
         (let ((n 0)
               cont)
                  (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
         (let ((n 0)
               cont)
@@ -3930,30 +4006,34 @@ the variable `Info-file-list-for-emacs'."
                  (if (and Info-fontify-visited-nodes
                           (save-match-data
                             (let* ((node (if (equal (match-string 3) "")
                  (if (and Info-fontify-visited-nodes
                           (save-match-data
                             (let* ((node (if (equal (match-string 3) "")
-                                            (match-string 1)
-                                          (match-string 3)))
+                                            (match-string-no-properties 1)
+                                          (match-string-no-properties 3)))
                                   (external-link-p
                                    (string-match "(\\([^)]+\\))\\([^)]*\\)" node))
                                   (file (if external-link-p
                                             (file-name-nondirectory
                                   (external-link-p
                                    (string-match "(\\([^)]+\\))\\([^)]*\\)" node))
                                   (file (if external-link-p
                                             (file-name-nondirectory
-                                             (match-string 1 node))
+                                             (match-string-no-properties 1 node))
                                           Info-current-file))
                                   (hl Info-history-list)
                                   res)
                               (if external-link-p
                                   (setq node (if (equal (match-string 2 node) "")
                                                  "Top"
                                           Info-current-file))
                                   (hl Info-history-list)
                                   res)
                               (if external-link-p
                                   (setq node (if (equal (match-string 2 node) "")
                                                  "Top"
-                                               (match-string 2 node))))
+                                               (match-string-no-properties 2 node))))
                              (while hl
                                (if (and (string-equal node (nth 1 (car hl)))
                              (while hl
                                (if (and (string-equal node (nth 1 (car hl)))
-                                        (string-equal
-                                         file (if external-link-p
-                                                  (file-name-nondirectory (caar hl))
-                                                (caar hl))))
+                                        (equal file
+                                               (if (and external-link-p
+                                                        (stringp (caar hl)))
+                                                   (file-name-nondirectory
+                                                    (caar hl))
+                                                 (caar hl))))
                                    (setq res (car hl) hl nil)
                                  (setq hl (cdr hl))))
                               res))) 'info-xref-visited 'info-xref)))
                                    (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)))
+             (when (and not-fontified-p
+                        (memq Info-hide-note-references '(t hide))
+                        (not (Info-index-node)))
                (put-text-property (match-beginning 2) (1- (match-end 6))
                                   'invisible t)
                ;; Unhide the file name in parens
                (put-text-property (match-beginning 2) (1- (match-end 6))
                                   'invisible t)
                ;; Unhide the file name in parens
@@ -3999,7 +4079,7 @@ the variable `Info-file-list-for-emacs'."
       ;; Fontify http and ftp references
       (goto-char (point-min))
       (when not-fontified-p
       ;; Fontify http and ftp references
       (goto-char (point-min))
       (when not-fontified-p
-        (while (re-search-forward "[hf]t?tp://[^ \t\n\"`({<>})']+" nil t)
+        (while (re-search-forward "\\(https?\\|ftp\\)://[^ \t\n\"`({<>})']+" nil t)
           (add-text-properties (match-beginning 0) (match-end 0)
                                '(font-lock-face info-xref
                                                 mouse-face highlight
           (add-text-properties (match-beginning 0) (match-end 0)
                                '(font-lock-face info-xref
                                                 mouse-face highlight
@@ -4208,8 +4288,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."
 
 (defun Info-desktop-buffer-misc-data (desktop-dirname)
   "Auxiliary information to be saved in desktop file."
-  (if (not (member Info-current-file '("apropos" "history" "toc")))
-      (list Info-current-file Info-current-node)))
+  (unless (member Info-current-file '(apropos history toc nil))
+    (list Info-current-file Info-current-node)))
 
 (defun Info-restore-desktop-buffer (desktop-buffer-file-name
                                     desktop-buffer-name
 
 (defun Info-restore-desktop-buffer (desktop-buffer-file-name
                                     desktop-buffer-name