(rmail-next-same-subject): Ignore leading and
[bpt/emacs.git] / lisp / info.el
index ec21f5b..a50b0c0 100644 (file)
@@ -58,6 +58,21 @@ The Lisp code is executed when the node is selected.")
   :type 'boolean
   :group 'info)
 
+(defface info-node
+  '((t (:bold t :italic t)))
+  "Face for Info node names."
+  :group 'info)
+
+(defface info-menu-5
+  '((t (:underline t)))
+  "Face for the fifth and tenth `*' in an Info menu."
+  :group 'info)
+
+(defface info-xref
+  '((t (:bold t)))
+  "Face for Info cross-references."
+  :group 'info)
+
 (defcustom Info-fontify-maximum-menu-size 30000
   "*Maximum size of menu to fontify if `Info-fontify' is non-nil."
   :type 'integer
@@ -146,10 +161,23 @@ Marker points nowhere if file has no tag table.")
   "Non-nil if Emacs was started solely as an Info browser.")
 
 (defvar Info-suffix-list
+  ;; The MS-DOS list should work both when long file names are
+  ;; supported (Windows 9X), and when only 8+3 file names are available.
   (if (eq system-type 'ms-dos)
       '( (".gz"      . "gunzip")
         (".z"       . "gunzip")
+        (".inz"     . "gunzip")
+        (".igz"     . "gunzip")
+        (".info.Z"  . "gunzip")
+        (".info.gz" . "gunzip")
+        ("-info.Z"  . "gunzip")
+        ("-info.gz" . "gunzip")
+        ("/index.gz". "gunzip")
+        ("/index.z" . "gunzip")
         (".inf"     . nil)
+        (".info"    . nil)
+        ("-info"    . nil)
+        ("/index"   . nil)
         (""         . nil))
     '( (".info.Z".    "uncompress")
        (".info.Y".    "unyabba")
@@ -232,12 +260,15 @@ Do the right thing if the file has been compressed or zipped."
             (jka-compr-installed-p)
             (jka-compr-get-compression-info fullname))
        (setq decoder nil))
-    (insert-file-contents fullname visit)
     (if decoder
-       (let ((buffer-read-only nil)
-             (default-directory (or (file-name-directory fullname)
-                                    default-directory)))
-         (call-process-region (point-min) (point-max) decoder t t)))))
+       (progn
+         (insert-file-contents-literally fullname visit)
+         (let ((buffer-read-only nil)
+               (coding-system-for-write 'no-conversion)
+               (default-directory (or (file-name-directory fullname)
+                                      default-directory)))
+           (call-process-region (point-min) (point-max) decoder t t)))
+      (insert-file-contents fullname visit))))
 
 ;;;###autoload (add-hook 'same-window-buffer-names "*info*")
 
@@ -255,11 +286,10 @@ The top-level Info directory is made by combining all the files named `dir'
 in all the directories in that path."
   (interactive (if current-prefix-arg
                   (list (read-file-name "Info file name: " nil nil t))))
+  (pop-to-buffer "*info*")
   (if file
       (Info-goto-node (concat "(" file ")"))
-    (if (get-buffer "*info*")
-       (pop-to-buffer "*info*")
-      (Info-directory))))
+    (Info-directory)))
 
 ;;;###autoload
 (defun info-standalone ()
@@ -500,7 +530,7 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
                    (save-excursion
                      (or buffers
                          (message "Composing main Info directory..."))
-                     (set-buffer (generate-new-buffer "info dir"))
+                     (set-buffer (generate-new-buffer " info dir"))
                      (insert-file-contents file)
                      (setq buffers (cons (current-buffer) buffers)
                            Info-dir-file-attributes
@@ -1487,6 +1517,7 @@ Give a blank topic name to go to the Index node itself."
   (interactive)
   (save-window-excursion
     (switch-to-buffer "*Help*")
+    (setq buffer-read-only nil)
     (erase-buffer)
     (insert (documentation 'Info-mode))
     (help-mode)
@@ -1748,9 +1779,12 @@ Selecting other nodes:
 \\[Info-index-next]    (comma) Move to the next match from a previous `i' command.
 
 Moving within a node:
-\\[Info-scroll-up]     Normally, scroll forward a full screen.  If the end of the buffer is
-already visible, try to go to the next menu entry, or up if there is none.
-\\[Info-scroll-down]  Normally, scroll backward.  If the beginning of the buffer is
+\\[Info-scroll-up]     Normally, scroll forward a full screen.
+Once you scroll far enough in a node that its menu appears on the screen
+but after point, the next scroll moves into its first subnode.
+When after all menu items (or if their is no menu), move up to
+the parent node.
+\\[Info-scroll-down]   Normally, scroll backward.  If the beginning of the buffer is
 already visible, try to go to the previous menu entry, or up if there is none.
 \\[beginning-of-buffer]        Go to beginning of node.  
 
@@ -1786,20 +1820,9 @@ Advanced commands:
   (setq Info-tag-table-buffer nil)
   (make-local-variable 'Info-history)
   (make-local-variable 'Info-index-alternatives)
-  (if (memq (framep (selected-frame)) '(x pc w32))
-      (progn
-       (make-face 'info-node)
-       (make-face 'info-menu-5)
-       (make-face 'info-xref)
-       (or (face-differs-from-default-p 'info-node)
-           (if (face-differs-from-default-p 'bold-italic)
-               (copy-face 'bold-italic 'info-node)
-             (copy-face 'bold 'info-node)))
-       (or (face-differs-from-default-p 'info-menu-5)
-           (set-face-underline-p 'info-menu-5 t))
-       (or (face-differs-from-default-p 'info-xref)
-           (copy-face 'bold 'info-xref)))
-    (setq Info-fontify nil))
+  ;; This is for the sake of the invisible text we use handling titles.
+  (make-local-variable 'line-move-ignore-invisible)
+  (setq line-move-ignore-invisible t)
   (Info-set-mode-line)
   (run-hooks 'Info-mode-hook))
 
@@ -1988,8 +2011,12 @@ The alist key is the character the title is underlined with (?*, ?= or ?-)."
        (put-text-property (match-beginning 1) (match-end 1)
                           'face
                           (cdr (assq (preceding-char) Info-title-face-alist)))
-       (put-text-property (match-end 1) (match-end 2)
-                          'invisible t))
+       ;; This is a serious problem for trying to handle multiple
+       ;; frame types at once.  We want this text to be invisible
+       ;; on frames that can display the font above.
+       (if (memq (framep (selected-frame)) '(x pc w32))
+           (put-text-property (match-end 1) (match-end 2)
+                              'invisible t)))
       (goto-char (point-min))
       (while (re-search-forward "\\*Note[ \n\t]+\\([^:]*\\):" nil t)
        (if (= (char-after (1- (match-beginning 0))) ?\") ; hack
@@ -2025,7 +2052,83 @@ The alist key is the character the title is underlined with (?*, ?= or ?-)."
        (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.
+
+(eval-when-compile (require 'speedbspec))
+
+(defvar Info-last-speedbar-node nil
+  "Last node viewed with speedbar in the form '(NODE FILE).")
+
+(defvar Info-speedbar-menu-items
+  '(["Browse Item On Line" speedbar-edit-line t])
+  "Additional menu-items to add to speedbar frame.")
+
+(defun Info-speedbar-buttons (buffer)
+  "Create a speedbar display to help navigation in an Info file.
+BUFFER is the buffer speedbar is requesting buttons for."
+  (goto-char (point-min))
+  (if (and (looking-at "<Directory>")
+          (save-excursion
+            (set-buffer buffer)
+            (and (equal (car Info-last-speedbar-node) Info-current-node)
+                 (equal (cdr Info-last-speedbar-node) Info-current-file))))
+      nil
+    (erase-buffer)
+    (speedbar-insert-button "<Directory>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-directory)
+    (speedbar-insert-button "<Top>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-top-node)
+    (speedbar-insert-button "<Last>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-last)
+    (speedbar-insert-button "<Up>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-up)
+    (speedbar-insert-button "<Next>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-next)
+    (speedbar-insert-button "<Prev>" 'info-xref 'highlight
+                           'Info-speedbar-button
+                           'Info-prev)
+    (let ((completions nil))
+      (save-excursion
+       (set-buffer buffer)
+       (setq Info-last-speedbar-node
+             (cons Info-current-node Info-current-file))
+       (goto-char (point-min))
+       ;; Always skip the first one...
+       (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
+       (while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
+         (setq completions (cons (buffer-substring (match-beginning 1)
+                                                   (match-end 1))
+                                 completions))))
+      (setq completions (nreverse completions))
+      (while completions
+       (speedbar-make-tag-line nil nil nil nil
+                               (car completions) 'Info-speedbar-menu
+                               nil 'info-node 0)
+       (setq completions (cdr completions))))))
+
+(defun Info-speedbar-button (text token indent)
+  "Called when user clicks <Directory> from speedbar.
+TEXT, TOKEN, and INDENT are unused."
+  (speedbar-with-attached-buffer
+   (funcall token)
+   (setq Info-last-speedbar-node nil)
+   (speedbar-update-contents)))
+
+(defun Info-speedbar-menu (text token indent)
+  "Goto the menu node specified in TEXT.
+TOKEN and INDENT are not used."
+  (speedbar-with-attached-buffer
+   (Info-menu text)
+   (setq Info-last-speedbar-node nil)
+   (speedbar-update-contents)))
 
 (provide 'info)