+ (Info-prev-reference t))
+ (if (looking-at "^\\* ")
+ (forward-char 2)))))
+\f
+(defvar Info-index-nodes nil
+ "Alist of cached index node names of visited Info files.
+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 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
+ (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))
+ 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 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)
+ ;; 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."
+ (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)))))