comparison lisp/info.el @ 367:a4f53d9b3154 r21-1-13

Import from CVS: tag r21-1-13
author cvs
date Mon, 13 Aug 2007 11:01:07 +0200
parents 8e84bee8ddd0
children cc15677e0335
comparison
equal deleted inserted replaced
366:83d76f480a59 367:a4f53d9b3154
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 ;; General Public License for more details. 22 ;; General Public License for more details.
23 23
24 ;; You should have received a copy of the GNU General Public License 24 ;; You should have received a copy of the GNU General Public License
25 ;; along with XEmacs; see the file COPYING. If not, write to the 25 ;; along with XEmacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA. 27 ;; Boston, MA 02111-1307, USA.
28 28
29 ;;; Synched up with: Not synched with FSF. 29 ;;; Synched up with: Not synched with FSF.
30 30
394 use any existing `dir' or `localdir' file and ignore info 394 use any existing `dir' or `localdir' file and ignore info
395 directories containing none 395 directories containing none
396 `always' auto-generate a directory listing ignoring existing 396 `always' auto-generate a directory listing ignoring existing
397 `dir' and `localdir' files 397 `dir' and `localdir' files
398 `if-missing', the default, auto-generates a directory listing 398 `if-missing', the default, auto-generates a directory listing
399 if no `dir' or `localdir' file is present. Otherwise the 399 if no `dir' or `localdir' file is present. Otherwise the
400 contents of any of these files is used instead. 400 contents of any of these files is used instead.
401 `if-outdated' auto-generates a directory listing if the `dir' 401 `if-outdated' auto-generates a directory listing if the `dir'
402 and `localdir' are either inexistent or outdated (touched 402 and `localdir' are either inexistent or outdated (touched
403 less recently than an info file in the same directory)." 403 less recently than an info file in the same directory)."
404 :type '(choice (const :tag "never" never) 404 :type '(choice (const :tag "never" never)
405 (const :tag "always" always) 405 (const :tag "always" always)
406 (const :tag "if-missing" if-missing) 406 (const :tag "if-missing" if-missing)
407 (const :tag "if-outdated" if-outdated)) 407 (const :tag "if-outdated" if-outdated))
408 :group 'info) 408 :group 'info)
409 409
410 (defcustom Info-save-auto-generated-dir nil 410 (defcustom Info-save-auto-generated-dir nil
411 "*Whether an auto-generated info directory listing should be saved. 411 "*Whether an auto-generated info directory listing should be saved.
412 Possible values are: 412 Possible values are:
413 nil or `never', the default, auto-generated info directory 413 nil or `never', the default, auto-generated info directory
414 information will never be saved. 414 information will never be saved.
415 `always', auto-generated info directory information will be saved to 415 `always', auto-generated info directory information will be saved to
416 a `dir' file in the same directory overwriting it if it exists 416 a `dir' file in the same directory overwriting it if it exists
417 `conservative', auto-generated info directory information will be saved 417 `conservative', auto-generated info directory information will be saved
418 to a `dir' file in the same directory but the user is asked before 418 to a `dir' file in the same directory but the user is asked before
419 overwriting any existing file." 419 overwriting any existing file."
420 :type '(choice (const :tag "never" never) 420 :type '(choice (const :tag "never" never)
421 (const :tag "always" always) 421 (const :tag "always" always)
422 (const :tag "conservative" conservative)) 422 (const :tag "conservative" conservative))
423 :group 'info) 423 :group 'info)
424 424
425 (defvar Info-emacs-info-file-name "xemacs.info" 425 (defconst Info-emacs-info-file-name "xemacs.info"
426 "The filename of the XEmacs info for 426 "The filename of the XEmacs info for `Info-goto-emacs-command-node'
427 `Info-goto-emacs-command-node' (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") 427 (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')")
428 428
429 ;;;###autoload 429 ;;;###autoload
430 (defvar Info-directory-list nil 430 (defvar Info-directory-list nil
431 "List of directories to search for Info documentation files. 431 "List of directories to search for Info documentation files.
432 432
439 search path, make the needed modifications on the variable's value 439 search path, make the needed modifications on the variable's value
440 from .emacs. For instance: 440 from .emacs. For instance:
441 441
442 (setq Info-directory-list (cons \"~/info\" Info-directory-list))") 442 (setq Info-directory-list (cons \"~/info\" Info-directory-list))")
443 443
444 (defcustom Info-localdir-heading-regexp 444 ;; This could as well be hard-coded since ${srcdir}/info/dir is in CVS --dv
445 "^Locally installed XEmacs Packages:?" 445 (defconst Info-localdir-heading-regexp "^Local Packages:$"
446 "The menu part of localdir files will be inserted below this topic 446 "The menu part of localdir files will be inserted below this topic
447 heading." 447 heading.")
448 :type 'regexp
449 :group 'info)
450 448
451 (defface info-node '((t (:bold t :italic t))) 449 (defface info-node '((t (:bold t :italic t)))
452 "Face used for node links in info." 450 "Face used for node links in info."
453 :group 'info-faces) 451 :group 'info-faces)
454 452
455 (defface info-xref '((t (:bold t))) 453 (defface info-xref '((t (:bold t)))
456 "Face used for cross-references in info." 454 "Face used for cross-references in info."
457 :group 'info-faces) 455 :group 'info-faces)
458 456
459 ;; Is this right for NT? .zip, with -c for to stdout, right? 457 ;; This list is based on Karl Berry-s advice about extensions `info' itself
460 (defvar Info-suffix-list '( ("" . nil) 458 ;; might encounter. --dv
461 (".info" . nil) 459 (defcustom Info-suffix-list '(("" . nil)
462 (".info.gz" . "gzip -dc %s") 460 (".info" . nil)
463 (".info-z" . "gzip -dc %s") 461 (".gz" . "gzip -dc %s")
464 (".info.Z" . "uncompress -c %s") 462 (".info.gz" . "gzip -dc %s")
465 (".gz" . "gzip -dc %s") 463 (".z" . "gzip -dc %s")
466 (".Z" . "uncompress -c %s") 464 (".info.z" . "gzip -dc %s")
467 (".zip" . "unzip -c %s") ) 465 (".bz2" . "bzip2 -dc %s")
468 "List of file name suffixes and associated decoding commands. 466 (".info.bz2" . "bzip2 -dc %s")
467 (".Z" . "uncompress -c %s")
468 (".info.Z" . "uncompress -c %s")
469 (".zip" . "unzip -c %s")
470 (".info.zip" . "unzip -c %s")
471 (".y" . "cat %s | unyabba")
472 ("info.y" . "cat %s | unyabba")
473 ;; These ones are for MS-DOS filenames.
474 (".inf" . nil)
475 (".igz" . "gzip -dc %s")
476 (".inz" . "gzip -c %s"))
477 "*List of file name suffixes and associated decoding commands.
469 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is 478 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is
470 changed to name of the file to decode, otherwise the file is given to 479 changed to name of the file to decode, otherwise the file is given to
471 the command as standard input. If STRING is nil, no decoding is done.") 480 the command as standard input. If STRING is nil, no decoding is done."
472 481 :type '(repeat (cons (string :tag "suffix")
473 (defvar Info-footnote-tag "Note" 482 (choice :tag "command"
483 (const :tag "none" :value nil)
484 (string :tag ""))))
485 :group 'info)
486
487 (defcustom Info-footnote-tag "Note"
474 "*Symbol that identifies a footnote or cross-reference. 488 "*Symbol that identifies a footnote or cross-reference.
475 All \"*Note\" references will be changed to use this word instead.") 489 All \"*Note\" references will be changed to use this word instead."
490 :type 'string
491 :group 'info)
476 492
477 (defvar Info-current-file nil 493 (defvar Info-current-file nil
478 "Info file that Info is now looking at, or nil. 494 "Info file that Info is now looking at, or nil.
479 This is the name that was specified in Info, not the actual file name. 495 This is the name that was specified in Info, not the actual file name.
480 It doesn't contain directory names or file name extensions added by Info.") 496 It doesn't contain directory names or file name extensions added by Info.")
496 (defvar Info-current-annotation-completions nil 512 (defvar Info-current-annotation-completions nil
497 "Cached completion list for current annotation files.") 513 "Cached completion list for current annotation files.")
498 514
499 (defvar Info-index-alternatives nil 515 (defvar Info-index-alternatives nil
500 "List of possible matches for last Info-index command.") 516 "List of possible matches for last Info-index command.")
517
501 (defvar Info-index-first-alternative nil) 518 (defvar Info-index-first-alternative nil)
502 519
503 (defcustom Info-annotations-path '("~/.xemacs/info.notes" 520 (defcustom Info-annotations-path '("~/.xemacs/info.notes"
504 "~/.infonotes" 521 "~/.infonotes"
505 "/usr/lib/info.notes") 522 "/usr/lib/info.notes")
524 This is the file .../info/dir, which contains the topmost node of the 541 This is the file .../info/dir, which contains the topmost node of the
525 Info hierarchy. The first time you invoke Info you start off 542 Info hierarchy. The first time you invoke Info you start off
526 looking at that node, which is (dir)Top. 543 looking at that node, which is (dir)Top.
527  544 
528 File: dir Node: Top This is the top of the INFO tree 545 File: dir Node: Top This is the top of the INFO tree
529 This (the Directory node) gives a menu of major topics. 546 This (the Directory node) gives a menu of major topics.
530 547
531 * Menu: The list of major topics begins on the next line. 548 * Menu: The list of major topics begins on the next line.
532 549
533 ") 550 ")
534 551
535 (defvar Info-no-description-string "[No description available]" 552 (defcustom Info-no-description-string "[No description available]"
536 "Description string for info files that have none") 553 "*Description string for info files that have none"
554 :type 'string
555 :group 'info)
537 556
538 ;;;###autoload 557 ;;;###autoload
539 (defun info (&optional file) 558 (defun info (&optional file)
540 "Enter Info, the documentation browser. 559 "Enter Info, the documentation browser.
541 Optional argument FILE specifies the file to examine; 560 Optional argument FILE specifies the file to examine;
594 ;; empty filename is simple case 613 ;; empty filename is simple case
595 ((null filename) 614 ((null filename)
596 (Info-find-file-node nil nodename no-going-back tryfile line)) 615 (Info-find-file-node nil nodename no-going-back tryfile line))
597 ;; Convert filename to lower case if not found as specified. 616 ;; Convert filename to lower case if not found as specified.
598 ;; Expand it, look harder... 617 ;; Expand it, look harder...
599 ((let (temp temp-downcase found 618 ((let ((fname (substitute-in-file-name filename))
600 (fname (substitute-in-file-name filename))) 619 temp found)
601 (let ((dirs (cond 620 (let ((dirs (cond
602 ((string-match "^\\./" fname) ; If specified name starts with `./' 621 ;; If specified name starts with `./', then just try
603 (list default-directory)) ; then just try current directory. 622 ;; current directory. No point in searching for an absolute
623 ;; file name
624 ((string-match "^\\./" fname)
625 (list default-directory))
604 ((file-name-absolute-p fname) 626 ((file-name-absolute-p fname)
605 '(nil)) ; No point in searching for an absolute file name 627 '(nil))
606 (Info-additional-search-directory-list 628 (Info-additional-search-directory-list
607 (append Info-directory-list 629 (append Info-directory-list
608 Info-additional-search-directory-list)) 630 Info-additional-search-directory-list))
609 (t Info-directory-list)))) 631 (t Info-directory-list))))
610 ;; Search the directory list for file FNAME. 632 ;; Search the directory list for file FNAME.
611 (while (and dirs (not found)) 633 (while (and dirs (not found))
612 (setq temp (expand-file-name fname (car dirs))) 634 (setq temp (expand-file-name fname (car dirs)))
613 (setq temp-downcase 635 (setq found (Info-suffixed-file temp))
614 (expand-file-name (downcase fname) (car dirs)))
615 (if (equal temp-downcase temp) (setq temp-downcase nil))
616 ;; Try several variants of specified name.
617 ;; Try downcasing, appending a suffix, or both.
618 (setq found (Info-suffixed-file temp temp-downcase))
619 (setq dirs (cdr dirs))) 636 (setq dirs (cdr dirs)))
620 (if found 637 (if found
621 (progn (setq filename (expand-file-name found)) 638 (progn (setq filename (expand-file-name found))
622 t)))) 639 t))))
623 (Info-find-file-node filename nodename no-going-back tryfile line)) 640 (Info-find-file-node filename nodename no-going-back tryfile line))
624 ;; Look for a URL. This pattern is stolen from w3.el to prevent 641 ;; Look for a URL. This pattern is stolen from w3.el to prevent
625 ;; loading it if we won't need it. 642 ;; loading it if we won't need it.
796 ;; constructed Info-dir-contents. 813 ;; constructed Info-dir-contents.
797 (defvar Info-dir-file-attributes nil) 814 (defvar Info-dir-file-attributes nil)
798 815
799 (defun Info-insert-dir () 816 (defun Info-insert-dir ()
800 "Construct the Info directory node by merging the files named 817 "Construct the Info directory node by merging the files named
801 \"dir\" or \"localdir\" from the directories in `Info-directory-list' 818 \"dir\" or \"localdir\" from the directories in `Info-directory-list'.
802 The \"dir\" files will take precedence in cases where both exist. It 819 The \"dir\" files will take precedence in cases where both exist. It
803 sets the *info* buffer's `default-directory' to the first directory we 820 sets the *info* buffer's `default-directory' to the first directory we
804 actually get any text from." 821 actually get any text from."
805 (if (and Info-dir-contents Info-dir-file-attributes 822 (if (and Info-dir-contents Info-dir-file-attributes
806 ;; Verify that none of the files we used has changed 823 ;; Verify that none of the files we used has changed
822 ;; Search the directory list for the directory file. 839 ;; Search the directory list for the directory file.
823 (while dirs 840 (while dirs
824 (let ((truename (file-truename (expand-file-name (car dirs))))) 841 (let ((truename (file-truename (expand-file-name (car dirs)))))
825 (or (member truename dirs-done) 842 (or (member truename dirs-done)
826 (member (directory-file-name truename) dirs-done) 843 (member (directory-file-name truename) dirs-done)
827 ;; Try several variants of specified name. 844 ;; Karl Berry recently added the ability all possibilities for
828 ;; Try upcasing, appending `.info', or both. 845 ;; extension as for normal info files. This code however is
829 (let* (buf 846 ;; still unsatisfactory: if one day, we find a compressed dir
830 file 847 ;; file (which looks possible), we should be able to handle it
831 (attrs 848 ;; (which means decompress and read it, update it, save and
832 (or 849 ;; recompress it). --dv
833 (progn (setq file (expand-file-name "dir" truename)) 850 (let ((trials '("dir" "DIR"
834 (file-attributes file)) 851 "dir.info" "DIR.INFO"
835 (progn (setq file (expand-file-name "DIR" truename)) 852 "dir.inf" "DIR.INF"
836 (file-attributes file)) 853 "localdir" "LOCALDIR"
837 (progn (setq file (expand-file-name "dir.info" truename)) 854 "localdir.info" "LOCALDIR.INFO"
838 (file-attributes file)) 855 "localdir.inf" "LOCALDIR.INF"))
839 (progn (setq file (expand-file-name "DIR.INFO" truename)) 856 buf file attrs)
840 (file-attributes file)) 857 (catch 'found
841 (progn (setq file (expand-file-name "localdir" truename)) 858 (while (setq file (pop trials))
842 (file-attributes file)) 859 (setq file (expand-file-name file truename))
843 (progn (setq file (expand-file-name "dir" truename)) 860 (and (setq attrs (file-attributes file))
844 nil) 861 (throw 'found t))))
845 ))) 862 (unless file
863 (setq file (expand-file-name "dir" truename)))
846 (setq dirs-done 864 (setq dirs-done
847 (cons truename 865 (cons truename
848 (cons (directory-file-name truename) 866 (cons (directory-file-name truename)
849 dirs-done))) 867 dirs-done)))
850 (Info-maybe-update-dir file) 868 (Info-maybe-update-dir file)
857 (set-buffer (or buf 875 (set-buffer (or buf
858 (generate-new-buffer 876 (generate-new-buffer
859 (if (string-match "localdir" file) 877 (if (string-match "localdir" file)
860 "localdir" 878 "localdir"
861 "info dir")))) 879 "info dir"))))
862 (if (not buf) 880 (if (not buf)
863 (insert-file-contents file)) 881 (insert-file-contents file))
864 (if (string-match "localdir" (buffer-name)) 882 (if (string-match "localdir" (buffer-name))
865 (setq lbuffers (cons (current-buffer) lbuffers)) 883 (setq lbuffers (cons (current-buffer) lbuffers))
866 (setq buffers (cons (current-buffer) buffers))) 884 (setq buffers (cons (current-buffer) buffers)))
867 (if attrs 885 (if attrs
868 (setq Info-dir-file-attributes 886 (setq Info-dir-file-attributes
869 (cons (cons file attrs) 887 (cons (cons file attrs)
870 Info-dir-file-attributes))))))) 888 Info-dir-file-attributes)))))))
871 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs))) 889 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs)))
872 (setq dirs (cdr dirs)))) 890 (setq dirs (cdr dirs))))
873 891
874 ;; ensure that the localdir files are inserted last, and reverse 892 ;; ensure that the localdir files are inserted last, and reverse
875 ;; the list of them so that when they get pushed in, they appear 893 ;; the list of them so that when they get pushed in, they appear
876 ;; in the same order they got specified in the path, from top to 894 ;; in the same order they got specified in the path, from top to
877 ;; bottom. 895 ;; bottom.
878 (nconc buffers (reverse lbuffers)) 896 (nconc buffers (reverse lbuffers))
879 897
880 (or buffers 898 (or buffers
881 (error "Can't find the Info directory node")) 899 (error "Can't find the Info directory node"))
882 ;; Distinguish the dir file that comes with Emacs from all the 900 ;; Distinguish the dir file that comes with Emacs from all the
883 ;; others. Yes, that is really what this is supposed to do. 901 ;; others. Yes, that is really what this is supposed to do.
884 ;; If it doesn't work, fix it. 902 ;; If it doesn't work, fix it.
943 (search-forward "\n\^_" nil 'move) 961 (search-forward "\n\^_" nil 'move)
944 (beginning-of-line) 962 (beginning-of-line)
945 (setq end (point)) 963 (setq end (point))
946 (setq nodes (cons (list nodename other beg end) nodes)))))) 964 (setq nodes (cons (list nodename other beg end) nodes))))))
947 (setq others (cdr others)))) 965 (setq others (cdr others))))
948 966
949 ;; Add to the main menu a menu item for each other node. 967 ;; Add to the main menu a menu item for each other node.
950 (re-search-forward "^\\* Menu:" nil t) 968 (re-search-forward "^\\* Menu:" nil t)
951 (forward-line 1) 969 (forward-line 1)
952 (let ((menu-items '("top")) 970 (let ((menu-items '("top"))
953 (nodes nodes) 971 (nodes nodes)
996 (message "Composing main Info directory...done")) 1014 (message "Composing main Info directory...done"))
997 (setq Info-dir-contents (buffer-string))) 1015 (setq Info-dir-contents (buffer-string)))
998 (setq default-directory Info-dir-contents-directory) 1016 (setq default-directory Info-dir-contents-directory)
999 (setq buffer-file-name (caar Info-dir-file-attributes))) 1017 (setq buffer-file-name (caar Info-dir-file-attributes)))
1000 1018
1019 (defmacro Info-directory-files (dir-file &optional all full nosort files-only)
1020 "Return a list of Info files living in the same directory as DIR-FILE.
1021 This list actually contains the files living in this directory, except for
1022 the dir file itself and the secondary info files (foo-1 foo-2 etc).
1023
1024 If the optional argument ALL is non nil, the secondary info files are also
1025 included in the list.
1026
1027 Please refer to the function `directory-files' for the meaning of the other
1028 optional arguments."
1029 `(let* ((dir (file-name-directory ,dir-file))
1030 (all-files (remove ,dir-file (directory-files dir ',full nil ',nosort
1031 ',files-only))))
1032 (setq all-files
1033 (if ,full
1034 (remove (concat dir ".")
1035 (remove (concat dir "..") all-files))
1036 (remove "."
1037 (remove ".." all-files))))
1038 (if ,all
1039 all-files
1040 (let ((suff-match
1041 (concat "-[0-9]+\\("
1042 ;; Extract all known compression suffixes from
1043 ;; Info-suffix-list. These suffixes can typically be
1044 ;; found in entries of the form `.info.something'.
1045 (let ((suff-list Info-suffix-list)
1046 suff regexp)
1047 (while (setq suff (pop suff-list))
1048 (and (string-match "^\\.info" (car suff))
1049 (setq regexp (concat regexp
1050 (regexp-quote
1051 (substring
1052 (car suff) 5))
1053 (and suff-list "\\|")))))
1054 regexp)
1055 "\\)?$"))
1056 info-files file)
1057 (while (setq file (pop all-files))
1058 (or (string-match suff-match file)
1059 (push file info-files)))
1060 (reverse info-files)
1061 ))
1062 ))
1063
1001 (defun Info-maybe-update-dir (file) 1064 (defun Info-maybe-update-dir (file)
1002 "Rebuild dir or localdir according to `Info-auto-generate-directory'." 1065 "Rebuild dir or localdir according to `Info-auto-generate-directory'."
1003 (unless (or (not (file-exists-p (file-name-directory file))) 1066 (unless (or (not (file-exists-p (file-name-directory file)))
1004 (null (directory-files (file-name-directory file) nil "\\.info"))) 1067 (null (Info-directory-files file 'all)))
1005 (if (not (find-buffer-visiting file)) 1068 (if (not (find-buffer-visiting file))
1006 (if (not (file-exists-p file)) 1069 (if (not (file-exists-p file))
1007 (if (or (eq Info-auto-generate-directory 'always) 1070 (if (or (eq Info-auto-generate-directory 'always)
1008 (eq Info-auto-generate-directory 'if-missing)) 1071 (eq Info-auto-generate-directory 'if-missing))
1009 (Info-build-dir-anew (file-name-directory file))) 1072 (Info-build-dir-anew (file-name-directory file)))
1010 (if (or (eq Info-auto-generate-directory 'always) 1073 (if (or (eq Info-auto-generate-directory 'always)
1011 (and (eq Info-auto-generate-directory 'if-outdated) 1074 (and (eq Info-auto-generate-directory 'if-outdated)
1012 (Info-dir-outdated-p file))) 1075 (Info-dir-outdated-p file)))
1013 (Info-rebuild-dir file)))))) 1076 (Info-rebuild-dir file))))))
1018 (defun Info-dir-outdated-p (file) 1081 (defun Info-dir-outdated-p (file)
1019 "Return non-nil if dir or localdir is outdated. 1082 "Return non-nil if dir or localdir is outdated.
1020 dir or localdir are outdated when an info file in the same 1083 dir or localdir are outdated when an info file in the same
1021 directory has been modified more recently." 1084 directory has been modified more recently."
1022 (let ((dir-mod-time (nth 5 (file-attributes file))) 1085 (let ((dir-mod-time (nth 5 (file-attributes file)))
1023 f-mod-time 1086 f-mod-time newer)
1024 newer)
1025 (setq Info-dir-newer-info-files nil) 1087 (setq Info-dir-newer-info-files nil)
1026 (mapcar 1088 (mapcar
1027 '(lambda (f) 1089 '(lambda (f)
1028 (prog2 1090 (prog2
1029 (setq f-mod-time (nth 5 (file-attributes f))) 1091 (setq f-mod-time (nth 5 (file-attributes f)))
1030 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) 1092 (setq newer (or (> (car f-mod-time) (car dir-mod-time))
1031 (and (= (car f-mod-time) (car dir-mod-time)) 1093 (and (= (car f-mod-time) (car dir-mod-time))
1032 (> (car (cdr f-mod-time)) (car (cdr dir-mod-time)))))) 1094 (> (car (cdr f-mod-time))
1033 (if (and (file-readable-p f) 1095 (car (cdr dir-mod-time))))))
1034 newer) 1096 (if (and (file-readable-p f) newer)
1035 (setq Info-dir-newer-info-files 1097 (setq Info-dir-newer-info-files
1036 (cons f Info-dir-newer-info-files))))) 1098 (cons f Info-dir-newer-info-files)))))
1037 (directory-files (file-name-directory file) 1099 (Info-directory-files file nil 'fullname 'nosort t))
1038 'fullname
1039 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$"
1040 'nosort
1041 t))
1042 Info-dir-newer-info-files)) 1100 Info-dir-newer-info-files))
1043 1101
1044 (defun Info-extract-dir-entry-from (file) 1102 (defun Info-extract-dir-entry-from (file)
1045 "Extract the dir entry from the info FILE. 1103 "Extract the dir entry from the info FILE.
1046 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY' 1104 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY'
1064 (let (entry entries) 1122 (let (entry entries)
1065 (save-excursion 1123 (save-excursion
1066 (save-restriction 1124 (save-restriction
1067 (narrow-to-region beg end) 1125 (narrow-to-region beg end)
1068 (goto-char beg) 1126 (goto-char beg)
1069 (while (re-search-forward "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t) 1127 (while (re-search-forward
1128 "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t)
1070 (setq entry (list (match-string 2) 1129 (setq entry (list (match-string 2)
1071 (match-string 1) 1130 (match-string 1)
1072 (downcase (or (match-string 3) 1131 (downcase (or (match-string 3)
1073 (match-string 1))))) 1132 (match-string 1)))))
1074 (setq entry 1133 (setq entry
1075 (cons (nreverse 1134 (cons (nreverse
1076 (cdr 1135 (cdr
1077 (nreverse 1136 (nreverse
1078 (split-string 1137 (split-string
1079 (buffer-substring 1138 (buffer-substring
1080 (re-search-forward "[ \t]*" nil t) 1139 (re-search-forward "[ \t]*" nil t)
1081 (or (and (re-search-forward "^[^ \t]" nil t) 1140 (or (and (re-search-forward "^[^ \t]" nil t)
1082 (goto-char (match-beginning 0))) 1141 (goto-char (match-beginning 0)))
1083 (point-max))) 1142 (point-max)))
1084 "[ \t]*\n[ \t]*")))) 1143 "[ \t]*\n[ \t]*"))))
1095 (setq len (length (concat (car e) 1154 (setq len (length (concat (car e)
1096 (car (cdr e))))) 1155 (car (cdr e)))))
1097 (if (> len description-col) 1156 (if (> len description-col)
1098 (setq description-col len))) 1157 (setq description-col len)))
1099 entries) 1158 entries)
1100 (setq description-col (+ 5 description-col)) 1159 (setq description-col (+ 5 description-col))
1101 (mapcar '(lambda (e) 1160 (mapcar '(lambda (e)
1102 (setq e (cdr e)) ; Drop filename 1161 (setq e (cdr e)) ; Drop filename
1103 (insert "* " (car e) ":" (car (cdr e))) 1162 (insert "* " (car e) ":" (car (cdr e)))
1104 (setq e (car (cdr (cdr e)))) 1163 (setq e (car (cdr (cdr e))))
1105 (while e 1164 (while e
1110 (insert "\n"))) 1169 (insert "\n")))
1111 1170
1112 1171
1113 (defun Info-build-dir-anew (directory) 1172 (defun Info-build-dir-anew (directory)
1114 "Build info directory information for DIRECTORY. 1173 "Build info directory information for DIRECTORY.
1115 The generated directory listing may be saved to a `dir' according 1174 The generated directory listing may be saved to a `dir' according
1116 to the value of `Info-save-auto-generated-dir'" 1175 to the value of `Info-save-auto-generated-dir'"
1117 (save-excursion 1176 (save-excursion
1118 (let* ((dirfile (expand-file-name "dir" directory)) 1177 (let* ((dirfile (expand-file-name "dir" directory))
1119 (to-temp (or (null Info-save-auto-generated-dir) 1178 (to-temp (or (null Info-save-auto-generated-dir)
1120 (eq Info-save-auto-generated-dir 'never) 1179 (eq Info-save-auto-generated-dir 'never)
1121 (and (not (file-writable-p dirfile)) 1180 (and (not (file-writable-p dirfile))
1122 (message "File not writable %s. Using temporary." dirfile)))) 1181 (message "File not writable %s. Using temporary."
1123 (info-files 1182 dirfile))))
1124 (directory-files directory 1183 (info-files (Info-directory-files dirfile nil 'fullname nil t)))
1125 'fullname
1126 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$"
1127 nil
1128 t)))
1129 (if to-temp 1184 (if to-temp
1130 (message "Creating temporary dir in %s..." directory) 1185 (message "Creating temporary dir in %s..." directory)
1131 (message "Creating %s..." dirfile)) 1186 (message "Creating %s..." dirfile))
1132 (set-buffer (find-file-noselect dirfile t)) 1187 (set-buffer (find-file-noselect dirfile t))
1133 (setq buffer-read-only nil) 1188 (setq buffer-read-only nil)
1134 (erase-buffer) 1189 (erase-buffer)
1135 (insert Info-dir-prologue 1190 (insert Info-dir-prologue "Info files in " directory ":\n\n")
1136 "Info files in " directory ":\n\n") 1191 (Info-dump-dir-entries
1137 (Info-dump-dir-entries 1192 (mapcar
1138 (mapcar
1139 '(lambda (f) 1193 '(lambda (f)
1140 (or (Info-extract-dir-entry-from f) 1194 (or (Info-extract-dir-entry-from f)
1141 (list 'dummy 1195 (list 'dummy
1142 (progn 1196 (progn (string-match "\\([^.]*\\)\\(\\..*\\)?$"
1143 (string-match "\\(.*\\)\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" 1197 (file-name-nondirectory f))
1144 (file-name-nondirectory f)) 1198 (capitalize
1145 (capitalize (match-string 1 (file-name-nondirectory f)))) 1199 (match-string 1 (file-name-nondirectory f))))
1146 ":" 1200 ":"
1147 (list Info-no-description-string)))) 1201 (list Info-no-description-string))))
1148 info-files)) 1202 info-files))
1149 (if to-temp 1203 (if to-temp
1150 (set-buffer-modified-p nil) 1204 (set-buffer-modified-p nil)
1154 (message "Creating %s...done" dirfile))))) 1208 (message "Creating %s...done" dirfile)))))
1155 1209
1156 1210
1157 (defun Info-rebuild-dir (file) 1211 (defun Info-rebuild-dir (file)
1158 "Build info directory information in the directory of dir FILE. 1212 "Build info directory information in the directory of dir FILE.
1159 Description of info files are merged from the info files in the 1213 Description of info files are merged from the info files in the
1160 directory and the contents of FILE with the description in info files 1214 directory and the contents of FILE with the description in info files
1161 taking precedence over descriptions in FILE. 1215 taking precedence over descriptions in FILE.
1162 The generated directory listing may be saved to a `dir' according to 1216 The generated directory listing may be saved to a `dir' according to
1163 the value of `Info-save-auto-generated-dir' " 1217 the value of `Info-save-auto-generated-dir' "
1164 (save-excursion 1218 (save-excursion
1165 (save-restriction 1219 (save-restriction
1166 (let (dir-section-contents dir-full-contents 1220 (let (dir-section-contents dir-full-contents
1167 dir-entry 1221 dir-entry
1168 file-dir-entry 1222 file-dir-entry
1169 mark next-section 1223 mark next-section
1170 not-first-section 1224 not-first-section
1171 (to-temp 1225 (to-temp
1172 (or (null Info-save-auto-generated-dir) 1226 (or (null Info-save-auto-generated-dir)
1173 (eq Info-save-auto-generated-dir 'never) 1227 (eq Info-save-auto-generated-dir 'never)
1174 (and (eq Info-save-auto-generated-dir 'always) 1228 (and (eq Info-save-auto-generated-dir 'always)
1175 (not (file-writable-p file)) 1229 (not (file-writable-p file))
1176 (message "File not writable %s. Using temporary." file)) 1230 (message "File not writable %s. Using temporary." file))
1177 (and (eq Info-save-auto-generated-dir 'conservative) 1231 (and (eq Info-save-auto-generated-dir 'conservative)
1178 (or (and (not (file-writable-p file)) 1232 (or (and (not (file-writable-p file))
1179 (message "File not writable %s. Using temporary." file)) 1233 (message
1180 (not (y-or-n-p 1234 "File not writable %s. Using temporary." file))
1181 (message "%s is outdated. Overwrite ? " 1235 (not (y-or-n-p
1236 (message "%s is outdated. Overwrite ? "
1182 file)))))))) 1237 file))))))))
1183 (set-buffer (find-file-noselect file t)) 1238 (set-buffer (find-file-noselect file t))
1184 (setq buffer-read-only nil) 1239 (setq buffer-read-only nil)
1185 (if to-temp 1240 (if to-temp
1186 (message "Rebuilding temporary %s..." file) 1241 (message "Rebuilding temporary %s..." file)
1192 (re-search-forward "^\\* Menu:.*$" nil t) 1247 (re-search-forward "^\\* Menu:.*$" nil t)
1193 (setq mark (and (re-search-forward "^\\* " nil t) 1248 (setq mark (and (re-search-forward "^\\* " nil t)
1194 (match-beginning 0)))) 1249 (match-beginning 0))))
1195 (throw 'done nil)) 1250 (throw 'done nil))
1196 (setq dir-full-contents (Info-parse-dir-entries mark (point-max))) 1251 (setq dir-full-contents (Info-parse-dir-entries mark (point-max)))
1197 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) 1252 (setq next-section (or (and (re-search-forward
1253 "^[^* \t].*:[ \t]*$" nil t)
1198 (match-beginning 0)) 1254 (match-beginning 0))
1199 (point-max))) 1255 (point-max)))
1200 (while next-section 1256 (while next-section
1201 (narrow-to-region mark next-section) 1257 (narrow-to-region mark next-section)
1202 (setq dir-section-contents (nreverse (Info-parse-dir-entries (point-min) 1258 (setq dir-section-contents (nreverse (Info-parse-dir-entries
1203 (point-max)))) 1259 (point-min) (point-max))))
1204 (mapcar '(lambda (file) 1260 (mapcar
1205 (setq dir-entry (assoc (downcase 1261 '(lambda (file)
1206 (file-name-sans-extension 1262 (setq dir-entry (assoc (downcase
1207 (file-name-nondirectory file))) 1263 (file-name-sans-extension
1208 dir-section-contents) 1264 (file-name-nondirectory file)))
1209 file-dir-entry (Info-extract-dir-entry-from file)) 1265 dir-section-contents)
1210 (if dir-entry 1266 file-dir-entry (Info-extract-dir-entry-from file))
1211 (if file-dir-entry 1267 (if dir-entry
1212 ;; A dir entry in the info file takes precedence over an 1268 (if file-dir-entry
1213 ;; existing entry in the dir file 1269 ;; A dir entry in the info file takes precedence over
1214 (setcdr dir-entry (cdr file-dir-entry))) 1270 ;; an existing entry in the dir file
1215 (unless (or not-first-section 1271 (setcdr dir-entry (cdr file-dir-entry)))
1216 (assoc (downcase 1272 (unless (or not-first-section
1217 (file-name-sans-extension 1273 (assoc (downcase
1218 (file-name-nondirectory file))) 1274 (file-name-sans-extension
1219 dir-full-contents)) 1275 (file-name-nondirectory file)))
1220 (if file-dir-entry 1276 dir-full-contents))
1221 (setq dir-section-contents (cons file-dir-entry 1277 (if file-dir-entry
1222 dir-section-contents)) 1278 (setq dir-section-contents
1223 (setq dir-section-contents 1279 (cons file-dir-entry dir-section-contents))
1224 (cons (list 'dummy 1280 (setq dir-section-contents
1225 (capitalize (file-name-sans-extension 1281 (cons (list 'dummy
1226 (file-name-nondirectory file))) 1282 (capitalize (file-name-sans-extension
1227 ":" 1283 (file-name-nondirectory
1228 (list Info-no-description-string)) 1284 file)))
1229 dir-section-contents)))))) 1285 ":"
1230 Info-dir-newer-info-files) 1286 (list Info-no-description-string))
1287 dir-section-contents))))))
1288 Info-dir-newer-info-files)
1231 (delete-region (point-min) (point-max)) 1289 (delete-region (point-min) (point-max))
1232 (Info-dump-dir-entries (nreverse dir-section-contents)) 1290 (Info-dump-dir-entries (nreverse dir-section-contents))
1233 (widen) 1291 (widen)
1234 (if (= next-section (point-max)) 1292 (if (= next-section (point-max))
1235 (setq next-section nil) 1293 (setq next-section nil)
1236 (or (setq mark (and (re-search-forward "^\\* " nil t) 1294 (or (setq mark (and (re-search-forward "^\\* " nil t)
1237 (match-beginning 0))) 1295 (match-beginning 0)))
1238 (throw 'done nil)) 1296 (throw 'done nil))
1239 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) 1297 (setq next-section (or (and (re-search-forward
1298 "^[^* \t].*:[ \t]*$" nil t)
1240 (match-beginning 0)) 1299 (match-beginning 0))
1241 (point-max)))) 1300 (point-max))))
1242 (setq not-first-section t))) 1301 (setq not-first-section t)))
1243 (if to-temp 1302 (if to-temp
1244 (progn 1303 (progn
1245 (set-buffer-modified-p nil) 1304 (set-buffer-modified-p nil)
1246 (message "Rebuilding temporary %s...done" file)) 1305 (message "Rebuilding temporary %s...done" file))
1247 (save-buffer) 1306 (save-buffer)
1248 (message "Rebuilding %s...done" file)))))) 1307 (message "Rebuilding %s...done" file))))))
1249 1308
1250 ;;;###autoload 1309 ;;;###autoload
1251 (defun Info-batch-rebuild-dir () 1310 (defun Info-batch-rebuild-dir ()
1252 "(Re)build info `dir' files in the directories remaining on the command line. 1311 "(Re)build `dir' files in the directories remaining on the command line.
1253 Use this from the command line, with `-batch'; 1312 Use this from the command line, with `-batch', it won't work in an
1254 it won't work in an interactive Emacs. 1313 interactive XEmacs.
1255 Each file is processed even if an error occurred previously. 1314
1256 For example, invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\"" 1315 Each file is processed even if an error occurred previously. For example,
1316 invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\""
1257 ;; command-line-args-left is what is left of the command line (from 1317 ;; command-line-args-left is what is left of the command line (from
1258 ;; startup.el) 1318 ;; startup.el)
1259 (defvar command-line-args-left) ; Avoid 'free variable' warning 1319 (defvar command-line-args-left) ; Avoid 'free variable' warning
1260 (if (not noninteractive) 1320 (if (not noninteractive)
1261 (error "`Info-batch-rebuild-dir' is to be used only with -batch")) 1321 (error "`Info-batch-rebuild-dir' is to be used only with -batch"))
1264 (while command-line-args-left 1324 (while command-line-args-left
1265 (if (not (file-directory-p (car command-line-args-left))) 1325 (if (not (file-directory-p (car command-line-args-left)))
1266 (message "Warning: Skipped %s. Not a directory." 1326 (message "Warning: Skipped %s. Not a directory."
1267 (car command-line-args-left)) 1327 (car command-line-args-left))
1268 (setq dir (expand-file-name "dir" (car command-line-args-left))) 1328 (setq dir (expand-file-name "dir" (car command-line-args-left)))
1269 (setq localdir (expand-file-name "localdir" (car command-line-args-left))) 1329 (setq localdir (expand-file-name "localdir"
1270 (cond 1330 (car command-line-args-left)))
1331 (cond
1271 ((file-exists-p dir) 1332 ((file-exists-p dir)
1272 (Info-rebuild-dir dir)) 1333 (Info-rebuild-dir dir))
1273 ((file-exists-p localdir) 1334 ((file-exists-p localdir)
1274 (Info-rebuild-dir localdir)) 1335 (Info-rebuild-dir localdir))
1275 (t 1336 (t
1328 (widen) 1389 (widen)
1329 (erase-buffer) 1390 (erase-buffer)
1330 (Info-insert-file-contents (Info-suffixed-file 1391 (Info-insert-file-contents (Info-suffixed-file
1331 (expand-file-name lastfilename 1392 (expand-file-name lastfilename
1332 (file-name-directory 1393 (file-name-directory
1333 Info-current-file))) 1394 Info-current-file))
1395 'exact)
1334 t) 1396 t)
1335 (set-buffer-modified-p nil) 1397 (set-buffer-modified-p nil)
1336 (setq Info-current-subfile lastfilename))) 1398 (setq Info-current-subfile lastfilename)))
1337 (goto-char (point-min)) 1399 (goto-char (point-min))
1338 (search-forward "\n\^_") 1400 (search-forward "\n\^_")
1339 (+ (- nodepos lastfilepos) (point)))) 1401 (+ (- nodepos lastfilepos) (point))))
1340 1402
1341 (defun Info-suffixed-file (name &optional name2) 1403 (defun Info-all-case-regexp (str)
1342 "Look for NAME with each of the `Info-suffix-list' extensions in 1404 (let ((regexp "")
1343 turn. Optional NAME2 is the name of a fallback info file to check 1405 (len (length str))
1344 for; usually a downcased version of NAME." 1406 (i 0)
1345 (let ((suff Info-suffix-list) 1407 c)
1346 (found nil) 1408 (while (< i len)
1347 file file2) 1409 (setq c (aref str i))
1348 (while (and suff (not found)) 1410 (cond ((or (and (>= c ?A) (<= c ?Z))
1349 (setq file (concat name (caar suff)) 1411 (and (>= c ?a) (<= c ?z)))
1350 file2 (and name2 (concat name2 (caar suff)))) 1412 (setq regexp (concat regexp
1351 (cond 1413 "["
1352 ((file-regular-p file) 1414 (char-to-string (downcase c))
1353 (setq found file)) 1415 "\\|"
1354 ((and file2 (file-regular-p file2)) 1416 (char-to-string (upcase c))
1355 (setq found file2)) 1417 "]")))
1356 (t 1418 (t
1357 (setq suff (cdr suff))))) 1419 (setq regexp (concat regexp (char-to-string c)))))
1358 (or found 1420 (setq i (1+ i)))
1359 (and name (when (file-regular-p name) 1421 regexp))
1360 name)) 1422
1361 (and name2 (when (file-regular-p name2) 1423 (defun Info-suffixed-file (name &optional exact)
1362 name2))))) 1424 "Look for an info file named NAME. This function tries to be smart in
1425 finding the file corresponding to NAME: if it doesn't exist, several
1426 variants are looked for, notably by appending suffixes from
1427 `Info-suffix-list' and by trying to change the characters case in NAME.
1428
1429 The optional argument EXACT prevents this function from trying different case
1430 versions of NAME. Only the suffixes are tried."
1431 (catch 'found
1432 ;; First, try NAME alone:
1433 (and (file-regular-p name) (throw 'found name))
1434 ;; Then, try different variants
1435 (let ((suff-match (concat "\\("
1436 (let ((suff-list Info-suffix-list)
1437 suff regexp)
1438 (while (setq suff (pop suff-list))
1439 (setq regexp
1440 (concat regexp
1441 (regexp-quote (car suff))
1442 (and suff-list "\\|"))))
1443 regexp)
1444 "\\)?$"))
1445 (dir (file-name-directory name))
1446 file files)
1447 (setq name (file-name-nondirectory name))
1448 (setq files
1449 (condition-case data ;; protect against invalid directory
1450 ;; First, try NAME[.<suffix>]
1451 (append
1452 (directory-files dir 'fullname
1453 (concat "^" (regexp-quote name) suff-match)
1454 nil t)
1455 (if exact
1456 nil
1457 ;; Then, try to match the name independantly of the
1458 ;; characters case.
1459 (directory-files dir 'fullname
1460 (Info-all-case-regexp
1461 (concat "^"
1462 (regexp-quote name)
1463 suff-match))
1464 nil t)))
1465 (t
1466 (display-warning 'info
1467 (format "directory `%s' error: %s" dir data))
1468 nil)))
1469 (while (setq file (pop files))
1470 (and (file-regular-p file)
1471 (throw 'found file)))
1472 )))
1363 1473
1364 (defun Info-insert-file-contents (file &optional visit) 1474 (defun Info-insert-file-contents (file &optional visit)
1365 (setq file (expand-file-name file default-directory)) 1475 (setq file (expand-file-name file default-directory))
1366 (let ((suff Info-suffix-list)) 1476 (let ((suff Info-suffix-list)
1367 (while (and suff (or (<= (length file) (length (car (car suff)))) 1477 len)
1368 (not (equal (substring file 1478 (while (and suff
1369 (- (length (car (car suff))))) 1479 (setq len (length (car (car suff))))
1370 (car (car suff)))))) 1480 (or (<= (length file) len)
1481 (not (or
1482 (equal (substring file (- len))
1483 (car (car suff)))
1484 (equal (substring file (- len))
1485 (upcase (car (car suff)))))
1486 )))
1371 (setq suff (cdr suff))) 1487 (setq suff (cdr suff)))
1372 (if (stringp (cdr (car suff))) 1488 (if (stringp (cdr (car suff)))
1373 (let ((command (if (string-match "%s" (cdr (car suff))) 1489 (let ((command (if (string-match "%s" (cdr (car suff)))
1374 (format (cdr (car suff)) file) 1490 (format (cdr (car suff)) file)
1375 (concat (cdr (car suff)) " < " file)))) 1491 (concat (cdr (car suff)) " < " file))))
1435 (list (cons modeline-buffer-id-left-extent "Info: ") 1551 (list (cons modeline-buffer-id-left-extent "Info: ")
1436 (cons modeline-buffer-id-right-extent 1552 (cons modeline-buffer-id-right-extent
1437 (concat 1553 (concat
1438 "(" 1554 "("
1439 (if Info-current-file 1555 (if Info-current-file
1440 (let ((name (file-name-nondirectory Info-current-file))) 1556 (let ((name (file-name-nondirectory
1441 (if (string-match "\\.info$" name) 1557 Info-current-file)))
1442 (substring name 0 -5) 1558 (if (string-match "^\\([^.]*\\)\\..*$" name)
1559 (match-string 1 name)
1443 name)) 1560 name))
1444 "") 1561 "")
1445 ")" 1562 ")"
1446 (or Info-current-node "")))))) 1563 (or Info-current-node ""))))))
1447 1564
1558 (forward-line 1) 1675 (forward-line 1)
1559 (let ((beg (point))) 1676 (let ((beg (point)))
1560 (forward-line 1) 1677 (forward-line 1)
1561 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]" 1678 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]"
1562 beg t) 1679 beg t)
1563 (setq compl 1680 (setq compl
1564 (cons (list (buffer-substring (match-beginning 1) 1681 (cons (list (buffer-substring (match-beginning 1)
1565 (match-end 1))) 1682 (match-end 1)))
1566 compl)))))))) 1683 compl))))))))
1567 (setq Info-current-file-completions compl)))) 1684 (setq Info-current-file-completions compl))))
1568 1685
1589 (if (null Info-current-subfile) 1706 (if (null Info-current-subfile)
1590 (progn (re-search-forward regexp) (setq found (point))) 1707 (progn (re-search-forward regexp) (setq found (point)))
1591 (condition-case nil 1708 (condition-case nil
1592 (progn (re-search-forward regexp) (setq found (point))) 1709 (progn (re-search-forward regexp) (setq found (point)))
1593 (search-failed nil))))) 1710 (search-failed nil)))))
1594 (if (not found) ;can only happen in subfile case -- else would have erred 1711 (if (not found)
1712 ;; can only happen in subfile case -- else would have erred
1595 (unwind-protect 1713 (unwind-protect
1596 (let ((list ())) 1714 (let ((list ()))
1597 (set-buffer (marker-buffer Info-tag-table-marker)) 1715 (set-buffer (marker-buffer Info-tag-table-marker))
1598 (goto-char (point-min)) 1716 (goto-char (point-min))
1599 (search-forward "\n\^_\nIndirect:") 1717 (search-forward "\n\^_\nIndirect:")
1606 (beginning-of-line) 1724 (beginning-of-line)
1607 (while (not (eobp)) 1725 (while (not (eobp))
1608 (re-search-forward "\\(^.*\\): [0-9]+$") 1726 (re-search-forward "\\(^.*\\): [0-9]+$")
1609 (goto-char (+ (match-end 1) 2)) 1727 (goto-char (+ (match-end 1) 2))
1610 (setq list (cons (cons (read (current-buffer)) 1728 (setq list (cons (cons (read (current-buffer))
1611 (buffer-substring (match-beginning 1) 1729 (buffer-substring
1612 (match-end 1))) 1730 (match-beginning 1)
1731 (match-end 1)))
1613 list)) 1732 list))
1614 (goto-char (1+ (match-end 0)))) 1733 (goto-char (1+ (match-end 0))))
1615 (setq list (nreverse list) 1734 (setq list (nreverse list)
1616 list (cdr list))) 1735 list (cdr list)))
1617 (while list 1736 (while list
1634 (or (and (equal onode Info-current-node) 1753 (or (and (equal onode Info-current-node)
1635 (equal ofile Info-current-file)) 1754 (equal ofile Info-current-file))
1636 (Info-history-add ofile onode opoint))))) 1755 (Info-history-add ofile onode opoint)))))
1637 1756
1638 ;; Extract the value of the node-pointer named NAME. 1757 ;; Extract the value of the node-pointer named NAME.
1639 ;; If there is none, use ERRORNAME in the error message; 1758 ;; If there is none, use ERRORNAME in the error message;
1640 ;; if ERRORNAME is nil, just return nil. 1759 ;; if ERRORNAME is nil, just return nil.
1641 (defun Info-extract-pointer (name &optional errorname) 1760 (defun Info-extract-pointer (name &optional errorname)
1642 (save-excursion 1761 (save-excursion
1643 (goto-char (point-min)) 1762 (goto-char (point-min))
1644 (forward-line 4) 1763 (forward-line 4)
1896 (setq item nil)))) 2015 (setq item nil))))
1897 (list item)))) 2016 (list item))))
1898 ;; there is a problem here in that if several menu items have the same 2017 ;; there is a problem here in that if several menu items have the same
1899 ;; name you can only go to the node of the first with this command. 2018 ;; name you can only go to the node of the first with this command.
1900 (Info-goto-node (Info-extract-menu-item menu-item) nil t)) 2019 (Info-goto-node (Info-extract-menu-item menu-item) nil t))
1901 2020
1902 (defun Info-extract-menu-item (menu-item &optional noerror) 2021 (defun Info-extract-menu-item (menu-item &optional noerror)
1903 (save-excursion 2022 (save-excursion
1904 (goto-char (point-min)) 2023 (goto-char (point-min))
1905 (if (let ((case-fold-search t)) 2024 (if (let ((case-fold-search t))
1906 (search-forward "\n* menu:" nil t)) 2025 (search-forward "\n* menu:" nil t))
2245 ;;;###autoload 2364 ;;;###autoload
2246 (defun Info-elisp-ref (func) 2365 (defun Info-elisp-ref (func)
2247 "Look up an Emacs Lisp function in the Elisp manual in the Info system. 2366 "Look up an Emacs Lisp function in the Elisp manual in the Info system.
2248 This command is designed to be used whether you are already in Info or not." 2367 This command is designed to be used whether you are already in Info or not."
2249 (interactive (let ((fn (function-at-point)) 2368 (interactive (let ((fn (function-at-point))
2250 (enable-recursive-minibuffers t) 2369 (enable-recursive-minibuffers t)
2251 val) 2370 val)
2252 (setq val (completing-read 2371 (setq val (completing-read
2253 (format "Look up Emacs Lisp function%s: " 2372 (format "Look up Emacs Lisp function%s: "
2254 (if fn 2373 (if fn
2255 (format " (default %s)" fn) 2374 (format " (default %s)" fn)
2318 (setq bufs (cdr bufs)))) 2437 (setq bufs (cdr bufs))))
2319 (goto-char savept))))) 2438 (goto-char savept)))))
2320 2439
2321 (defvar Info-annotate-map nil 2440 (defvar Info-annotate-map nil
2322 "Local keymap used within `a' command of Info.") 2441 "Local keymap used within `a' command of Info.")
2442
2323 (if Info-annotate-map 2443 (if Info-annotate-map
2324 nil 2444 nil
2325 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map)) 2445 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map))
2326 (setq Info-annotate-map (copy-keymap text-mode-map)) 2446 (setq Info-annotate-map (copy-keymap text-mode-map))
2327 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate)) 2447 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate))
2633 ((>= x (- w bx)) (Info-next) t) 2753 ((>= x (- w bx)) (Info-next) t)
2634 (t nil))))) 2754 (t nil)))))
2635 2755
2636 (defvar Info-mode-map nil 2756 (defvar Info-mode-map nil
2637 "Keymap containing Info commands.") 2757 "Keymap containing Info commands.")
2758
2638 (if Info-mode-map 2759 (if Info-mode-map
2639 nil 2760 nil
2640 (setq Info-mode-map (make-sparse-keymap)) 2761 (setq Info-mode-map (make-sparse-keymap))
2641 (suppress-keymap Info-mode-map) 2762 (suppress-keymap Info-mode-map)
2642 (define-key Info-mode-map "." 'beginning-of-buffer) 2763 (define-key Info-mode-map "." 'beginning-of-buffer)
2791 (run-hooks 'Info-mode-hook) 2912 (run-hooks 'Info-mode-hook)
2792 (Info-set-mode-line)) 2913 (Info-set-mode-line))
2793 2914
2794 (defvar Info-edit-map nil 2915 (defvar Info-edit-map nil
2795 "Local keymap used within `e' command of Info.") 2916 "Local keymap used within `e' command of Info.")
2917
2796 (if Info-edit-map 2918 (if Info-edit-map
2797 nil 2919 nil
2798 ;; XEmacs: remove FSF stuff 2920 ;; XEmacs: remove FSF stuff
2799 (setq Info-edit-map (make-sparse-keymap)) 2921 (setq Info-edit-map (make-sparse-keymap))
2800 (set-keymap-name Info-edit-map 'Info-edit-map) 2922 (set-keymap-name Info-edit-map 'Info-edit-map)
2930 (progn 3052 (progn
2931 (goto-char (match-end 0)) 3053 (goto-char (match-end 0))
2932 (while 3054 (while
2933 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?") 3055 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?")
2934 (goto-char (match-end 0)) 3056 (goto-char (match-end 0))
2935 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref)))) 3057 (Info-highlight-region (match-beginning 1) (match-end 1)
3058 'info-xref))))
2936 ;; Now get the xrefs in the body 3059 ;; Now get the xrefs in the body
2937 (goto-char (point-min)) 3060 (goto-char (point-min))
2938 (while (re-search-forward xref-regexp nil t) 3061 (while (re-search-forward xref-regexp nil t)
2939 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack 3062 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack
2940 nil 3063 nil
2941 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref))) 3064 (Info-highlight-region (match-beginning 1) (match-end 1)
3065 'info-xref)))
2942 ;; then highlight the nodes in the menu. 3066 ;; then highlight the nodes in the menu.
2943 (goto-char (point-min)) 3067 (goto-char (point-min))
2944 (if (and (search-forward "\n* menu:" nil t)) 3068 (if (and (search-forward "\n* menu:" nil t))
2945 (while (re-search-forward 3069 (while (re-search-forward
2946 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t) 3070 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t)
2947 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-node))) 3071 (Info-highlight-region (match-beginning 1) (match-end 1)
3072 'info-node)))
2948 (set-buffer-modified-p nil)))) 3073 (set-buffer-modified-p nil))))
2949 3074
2950 (defun Info-construct-menu (&optional event) 3075 (defun Info-construct-menu (&optional event)
2951 "Construct a menu of Info commands. 3076 "Construct a menu of Info commands.
2952 Adds an entry for the node at EVENT, or under point if EVENT is omitted. 3077 Adds an entry for the node at EVENT, or under point if EVENT is omitted.
2953 Used to construct the menubar submenu and popup menu." 3078 Used to construct the menubar submenu and popup menu."
2954 (or event (setq event (point))) 3079 (or event (setq event (point)))
2955 (let ((case-fold-search t) 3080 (let ((case-fold-search t)
2956 (xref-regexp (concat "\\*" 3081 (xref-regexp (concat "\\*"
2957 (regexp-quote Info-footnote-tag) 3082 (regexp-quote Info-footnote-tag)
2958 "[ \n\t]*\\([^:]*\\):")) 3083 "[ \n\t]*\\([^:]*\\):"))
2959 up-p prev-p next-p menu xrefs subnodes in) 3084 up-p prev-p next-p menu xrefs subnodes in)
2960 (save-excursion 3085 (save-excursion
2961 ;; `one-space' fixes "Notes:" xrefs that are split across lines. 3086 ;; `one-space' fixes "Notes:" xrefs that are split across lines.