(U+663C): Use `->subsumptive' for M-07705, M-13886 and C3-2C37.
[chise/xemacs-chise.git.1] / lisp / apropos.el
1 ;;; apropos.el --- apropos commands for users and programmers.
2
3 ;; Copyright (C) 1989, 1994, 1995 Free Software Foundation, Inc.
4
5 ;; Author: Joe Wells <jbw@bigbird.bu.edu>
6 ;; Rewritten: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
7 ;; Maintainer: SL Baur <steve@xemacs.org>
8 ;; Keywords: help
9
10 ;; This file is part of XEmacs.
11
12 ;; XEmacs is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; XEmacs is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Synched up with: Last synched with FSF 19.34, diverged since.
28
29 ;;; Commentary:
30
31 ;; The ideas for this package were derived from the C code in
32 ;; src/keymap.c and elsewhere.  The functions in this file should
33 ;; always be byte-compiled for speed.  Someone should rewrite this in
34 ;; C (as part of src/keymap.c) for speed.
35
36 ;; The idea for super-apropos is based on the original implementation
37 ;; by Lynn Slater <lrs@esl.com>.
38
39 ;;; ChangeLog:
40
41 ;; Fixed bug, current-local-map can return nil.
42 ;; Change, doesn't calculate key-bindings unless needed.
43 ;; Added super-apropos capability, changed print functions.
44 ;;; Made fast-apropos and super-apropos share code.
45 ;;; Sped up fast-apropos again.
46 ;; Added apropos-do-all option.
47 ;;; Added fast-command-apropos.
48 ;; Changed doc strings to comments for helping functions.
49 ;;; Made doc file buffer read-only, buried it.
50 ;; Only call substitute-command-keys if do-all set.
51
52 ;; Optionally use configurable faces to make the output more legible.
53 ;; Differentiate between command, function and macro.
54 ;; Apropos-command (ex command-apropos) does cmd and optionally user var.
55 ;; Apropos shows all 3 aspects of symbols (fn, var and plist)
56 ;; Apropos-documentation (ex super-apropos) now finds all it should.
57 ;; New apropos-value snoops through all values and optionally plists.
58 ;; Reading DOC file doesn't load nroff.
59 ;; Added hypertext following of documentation, mouse-2 on variable gives value
60 ;;   from buffer in active window.
61
62 ;;; Code:
63
64 ;; I see a degradation of maybe 10-20% only.
65 ;; [sb -- FSF protects the face declarations with `if window-system'
66 ;;  I see no reason why we should do so]
67 (defvar apropos-do-all nil
68   "*Whether the apropos commands should do more.
69 Slows them down more or less.  Set this non-nil if you have a fast machine.")
70
71 ;; XEmacs addition
72 (defvar apropos-symbol-face (if (boundp 'font-lock-keyword-face)
73                                 font-lock-keyword-face
74                               'bold)
75   "*Face for symbol name in apropos output or `nil'.
76 This looks good, but slows down the commands several times.")
77
78 ;; XEmacs addition
79 (defvar apropos-keybinding-face (if (boundp 'font-lock-string-face)
80                                     font-lock-string-face
81                                   'underline)
82   "*Face for keybinding display in apropos output or `nil'.
83 This looks good, but slows down the commands several times.")
84
85 ;; XEmacs addition
86 (defvar apropos-label-face (if (boundp 'font-lock-comment-face)
87                                font-lock-comment-face
88                              'italic)
89   "*Face for label (Command, Variable ...) in apropos output or `nil'.
90 If this is `nil' no mouse highlighting occurs.
91 This looks good, but slows down the commands several times.
92 When this is a face name, as it is initially, it gets transformed to a
93 text-property list for efficiency.")
94
95 ;; XEmacs addition
96 (defvar apropos-property-face (if (boundp 'font-lock-variable-name-face)
97                                   font-lock-variable-name-face
98                                 'bold-italic)
99   "*Face for property name in apropos output or `nil'.
100 This looks good, but slows down the commands several times.")
101
102 (defvar apropos-match-face 'secondary-selection
103   "*Face for matching part in apropos-documentation/value output or `nil'.
104 This looks good, but slows down the commands several times.")
105
106
107 (defvar apropos-mode-map
108   (let ((map (make-sparse-keymap)))
109     (define-key map [(control m)] 'apropos-follow)
110     (define-key map [return] 'apropos-follow)
111     (define-key map [(button2up)] 'apropos-mouse-follow)
112     (define-key map [(button2)] 'undefined)
113     map)
114   "Keymap used in Apropos mode.")
115
116
117 (defvar apropos-regexp nil
118   "Regexp used in current apropos run.")
119
120 (defvar apropos-files-scanned ()
121   "List of elc files already scanned in current run of `apropos-documentation'.")
122
123 (defvar apropos-accumulator ()
124   "Alist of symbols already found in current apropos run.")
125
126 (defvar apropos-item ()
127   "Current item in or for apropos-accumulator.")
128 \f
129 (defvar apropos-mode-hook nil) ; XEmacs
130
131 (defun apropos-mode ()
132   "Major mode for following hyperlinks in output of apropos commands.
133
134 \\{apropos-mode-map}"
135   (interactive)
136   (kill-all-local-variables)
137   (use-local-map apropos-mode-map)
138   (setq major-mode 'apropos-mode
139         mode-name "Apropos")
140   (run-hooks 'apropos-mode-hook)) ; XEmacs
141
142
143 ;; For auld lang syne:
144 ;;;###autoload
145 (fset 'command-apropos 'apropos-command)
146
147 ;;;###autoload
148 (defun apropos-command (apropos-regexp &optional do-all)
149   "Shows commands (interactively callable functions) that match REGEXP.
150 With optional prefix ARG or if `apropos-do-all' is non-nil, also show
151 variables."
152   ;; XEmacs: All code related to special treatment of buffer has been removed
153   (interactive (list (read-string (concat "Apropos command "
154                                           (if (or current-prefix-arg
155                                                   apropos-do-all)
156                                               "or variable ")
157                                           "(regexp): "))
158                      current-prefix-arg))
159   (or do-all (setq do-all apropos-do-all))
160   (setq apropos-accumulator
161         (apropos-internal apropos-regexp
162                           (if do-all
163                               (lambda (symbol) (or (commandp symbol)
164                                                    (user-variable-p symbol)))
165                             'commandp)))
166   (apropos-print
167    t
168    (lambda (p)
169      (let (doc symbol)
170        (while p
171          (setcar p (list
172                     (setq symbol (car p))
173                     (if (commandp symbol)
174                         (if (setq doc
175                                   ;; XEmacs change: if obsolete,
176                                   ;; only mention that.
177                                   (or (function-obsoleteness-doc symbol)
178                                       (documentation symbol t)))
179                             (substring doc 0 (string-match "\n" doc))
180                           "(not documented)"))
181                     (and do-all
182                          (user-variable-p symbol)
183                          (if (setq doc
184                                    (or
185                                     ;; XEmacs change: if obsolete,
186                                     ;; only mention that.
187                                     (variable-obsoleteness-doc symbol)
188                                     (documentation-property
189                                      symbol 'variable-documentation t)))
190                              (substring doc 0
191                                             (string-match "\n" doc))))))
192          (setq p (cdr p)))))
193    nil))
194
195
196 ;;;###autoload
197 (defun apropos (apropos-regexp &optional do-all)
198   "Show all bound symbols whose names match REGEXP.
199 With optional prefix ARG or if `apropos-do-all' is non-nil, also show unbound
200 symbols and key bindings, which is a little more time-consuming.
201 Returns list of symbols and documentation found."
202   (interactive "sApropos symbol (regexp): \nP")
203   ;; XEmacs change: hitting ENTER by mistake is a common mess-up and
204   ;; shouldn't make Emacs hang for a long time trying to list all symbols.
205   (or (> (length apropos-regexp) 0)
206       (error "Must pass non-empty regexp to `apropos'"))
207   (setq apropos-accumulator
208         (apropos-internal apropos-regexp
209                           (and (not do-all)
210                                (not apropos-do-all)
211                                (lambda (symbol)
212                                  (or (fboundp symbol)
213                                      (boundp symbol)
214                                      (find-face symbol)
215                                      (symbol-plist symbol))))))
216   (apropos-print
217    (or do-all apropos-do-all)
218    (lambda (p)
219      (let (symbol doc)
220        (while p
221          (setcar p (list
222                     (setq symbol (car p))
223                     (if (fboundp symbol)
224                         (if (setq doc
225                                   ;; XEmacs change: if obsolete,
226                                   ;; only mention that.
227                                   (or (function-obsoleteness-doc symbol)
228                                       (documentation symbol t)))
229                             (substring doc 0 (string-match "\n" doc))
230                           "(not documented)"))
231                     (if (boundp symbol)
232                         (if (setq doc
233                                   (or
234                                    ;; XEmacs change: if obsolete,
235                                    ;; only mention that.
236                                    (variable-obsoleteness-doc symbol)
237                                    (documentation-property
238                                     symbol 'variable-documentation t)))
239                             (substring doc 0
240                                        (string-match "\n" doc))
241                           "(not documented)"))
242                     (if (setq doc (symbol-plist symbol))
243                         (if (eq (/ (length doc) 2) 1)
244                             (format "1 property (%s)" (car doc))
245                           (format "%d properties" (/ (length doc) 2))))
246                     (if (get symbol 'widget-type)
247                         (if (setq doc (documentation-property
248                                        symbol 'widget-documentation t))
249                             (substring doc 0
250                                        (string-match "\n" doc))
251                           "(not documented)"))
252                     (if (find-face symbol)
253                         (if (setq doc (face-doc-string symbol))
254                             (substring doc 0
255                                        (string-match "\n" doc))
256                           "(not documented)"))
257                     (when (get symbol 'custom-group)
258                       (if (setq doc (documentation-property
259                                      symbol 'group-documentation t))
260                           (substring doc 0
261                                      (string-match "\n" doc))
262                         "(not documented)"))))
263          (setq p (cdr p)))))
264    nil))
265
266
267 ;;;###autoload
268 (defun apropos-value (apropos-regexp &optional do-all)
269   "Show all symbols whose value's printed image matches REGEXP.
270 With optional prefix ARG or if `apropos-do-all' is non-nil, also looks
271 at the function and at the names and values of properties.
272 Returns list of symbols and values found."
273   (interactive "sApropos value (regexp): \nP")
274   (or do-all (setq do-all apropos-do-all))
275   (setq apropos-accumulator ())
276    (let (f v p)
277      (mapatoms
278       (lambda (symbol)
279         (setq f nil v nil p nil)
280         (or (memq symbol '(apropos-regexp do-all apropos-accumulator
281                                           symbol f v p))
282             (setq v (apropos-value-internal 'boundp symbol 'symbol-value)))
283         (if do-all
284             (setq f (apropos-value-internal 'fboundp symbol 'symbol-function)
285                   p (apropos-format-plist symbol "\n    " t)))
286         (if (or f v p)
287             (setq apropos-accumulator (cons (list symbol f v p)
288                                             apropos-accumulator))))))
289   (apropos-print nil nil t))
290
291
292 ;;;###autoload
293 (defun apropos-documentation (apropos-regexp &optional do-all)
294   "Show symbols whose documentation contain matches for REGEXP.
295 With optional prefix ARG or if `apropos-do-all' is non-nil, also use
296 documentation that is not stored in the documentation file and show key
297 bindings.
298 Returns list of symbols and documentation found."
299   (interactive "sApropos documentation (regexp): \nP")
300   (or do-all (setq do-all apropos-do-all))
301   (setq apropos-accumulator () apropos-files-scanned ())
302   (let ((standard-input (get-buffer-create " apropos-temp"))
303         f v)
304     (unwind-protect
305         (save-excursion
306           (set-buffer standard-input)
307           (apropos-documentation-check-doc-file)
308           (if do-all
309               (mapatoms
310                (lambda (symbol)
311                  (setq f (apropos-safe-documentation symbol)
312                        v (get symbol 'variable-documentation))
313                  (when (integerp v) (setq v nil))
314                  (setq f (apropos-documentation-internal f)
315                        v (apropos-documentation-internal v))
316                  (if (or f v)
317                      (if (setq apropos-item
318                                (cdr (assq symbol apropos-accumulator)))
319                          (progn
320                            (if f
321                                (setcar apropos-item f))
322                            (if v
323                                (setcar (cdr apropos-item) v)))
324                        (setq apropos-accumulator
325                              (cons (list symbol f v)
326                                    apropos-accumulator)))))))
327           (apropos-print nil nil t))
328       (kill-buffer standard-input))))
329
330 \f
331 (defun apropos-value-internal (predicate symbol function)
332   (if (funcall predicate symbol)
333       (progn
334         (setq symbol (prin1-to-string (funcall function symbol)))
335         (if (string-match apropos-regexp symbol)
336             (progn
337               (if apropos-match-face
338                   (put-text-property (match-beginning 0) (match-end 0)
339                                      'face apropos-match-face
340                                      symbol))
341               symbol)))))
342
343 (defun apropos-documentation-internal (doc)
344   (if (consp doc)
345       (apropos-documentation-check-elc-file (car doc))
346     (and doc
347          (string-match apropos-regexp doc)
348          (progn
349            (if apropos-match-face
350                (put-text-property (match-beginning 0)
351                                   (match-end 0)
352                                   'face apropos-match-face
353                                   (setq doc (copy-sequence doc))))
354            doc))))
355
356 (defun apropos-format-plist (pl sep &optional compare)
357   (setq pl (symbol-plist pl))
358   (let (p p-out)
359     (while pl
360       (setq p (format "%s %S" (car pl) (nth 1 pl)))
361       (if (or (not compare) (string-match apropos-regexp p))
362           (if apropos-property-face
363               (put-text-property 0 (length (symbol-name (car pl)))
364                                  'face apropos-property-face p))
365         (setq p nil))
366       (if p
367           (progn
368             (and compare apropos-match-face
369                  (put-text-property (match-beginning 0) (match-end 0)
370                                     'face apropos-match-face
371                                     p))
372             (setq p-out (concat p-out (if p-out sep) p))))
373       (setq pl (nthcdr 2 pl)))
374     p-out))
375
376
377 ;; Finds all documentation related to APROPOS-REGEXP in internal-doc-file-name.
378
379 (defun apropos-documentation-check-doc-file ()
380   (let (type symbol (sepa 2) sepb start end doc)
381     (insert ?\^_)
382     (backward-char)
383     (insert-file-contents (concat doc-directory internal-doc-file-name))
384     (forward-char)
385     (while (save-excursion
386              (setq sepb (search-forward "\^_"))
387              (not (eobp)))
388       (beginning-of-line 2)
389       (if (save-restriction
390             (narrow-to-region (point) (1- sepb))
391             (re-search-forward apropos-regexp nil t))
392           (progn
393             (setq start (match-beginning 0)
394                   end (point))
395             (goto-char (1+ sepa))
396             (or (setq type (if (eq ?F (preceding-char))
397                                1        ; function documentation
398                              2)         ; variable documentation
399                       symbol (read)
400                       start (- start (point) 1)
401                       end (- end (point) 1)
402                       doc (buffer-substring (1+ (point)) (1- sepb))
403                       apropos-item (assq symbol apropos-accumulator))
404                 (setq apropos-item (list symbol nil nil)
405                       apropos-accumulator (cons apropos-item
406                                                 apropos-accumulator)))
407             (if apropos-match-face
408                 (put-text-property start end 'face apropos-match-face doc))
409             (setcar (nthcdr type apropos-item) doc)))
410       (setq sepa (goto-char sepb)))))
411
412 (defun apropos-documentation-check-elc-file (file)
413   (if (member file apropos-files-scanned)
414       nil
415     (let (symbol doc start end this-is-a-variable)
416       (setq apropos-files-scanned (cons file apropos-files-scanned))
417       (erase-buffer)
418       (insert-file-contents file)
419       (while (search-forward "\n#@" nil t)
420         ;; Read the comment length, and advance over it.
421         (setq end (read)
422               start (1+ (point))
423               end (+ (point) end -1))
424         (forward-char)
425         (if (save-restriction
426               ;; match ^ and $ relative to doc string
427               (narrow-to-region start end)
428               (re-search-forward apropos-regexp nil t))
429             (progn
430               (goto-char (+ end 2))
431               (setq doc (buffer-substring start end)
432                     end (- (match-end 0) start)
433                     start (- (match-beginning 0) start)
434                     this-is-a-variable (looking-at "(def\\(var\\|const\\) ")
435                     symbol (progn
436                              (skip-chars-forward "(a-z")
437                              (forward-char)
438                              (read))
439                     symbol (if (consp symbol)
440                                (nth 1 symbol)
441                              symbol))
442               (if (if this-is-a-variable
443                       (get symbol 'variable-documentation)
444                     (and (fboundp symbol) (apropos-safe-documentation symbol)))
445                   (progn
446                     (or (setq apropos-item (assq symbol apropos-accumulator))
447                         (setq apropos-item (list symbol nil nil)
448                               apropos-accumulator (cons apropos-item
449                                                         apropos-accumulator)))
450                     (if apropos-match-face
451                         (put-text-property start end 'face apropos-match-face
452                                            doc))
453                     (setcar (nthcdr (if this-is-a-variable 2 1)
454                                     apropos-item)
455                             doc)))))))))
456
457
458
459 (defun apropos-safe-documentation (function)
460   "Like documentation, except it avoids calling `get_doc_string'.
461 Will return nil instead."
462   (while (and function (symbolp function))
463     (setq function (if (fboundp function)
464                        (symbol-function function))))
465   (if (eq (car-safe function) 'macro)
466       (setq function (cdr function)))
467   ;; XEmacs change from: (setq function (if (byte-code-function-p function)
468   (setq function (if (compiled-function-p function)
469                      (if (fboundp 'compiled-function-doc-string)
470                          (compiled-function-doc-string function)
471                        (if (> (length function) 4)
472                            (aref function 4)))
473                    (if (eq (car-safe function) 'autoload)
474                        (nth 2 function)
475                      (if (eq (car-safe function) 'lambda)
476                          (if (stringp (nth 2 function))
477                              (nth 2 function)
478                            (if (stringp (nth 3 function))
479                                (nth 3 function)))))))
480   (if (integerp function)
481       nil
482     function))
483
484
485
486 (defun apropos-print (do-keys doc-fn spacing)
487   "Output result of various apropos commands with `apropos-regexp'.
488 APROPOS-ACCUMULATOR is a list.  Optional DOC-FN is called for each element
489 of apropos-accumulator and may modify it resulting in (symbol fn-doc
490 var-doc [plist-doc]).  Returns sorted list of symbols and documentation
491 found."
492   (if (null apropos-accumulator)
493       (message "No apropos matches for `%s'" apropos-regexp)
494     (if doc-fn
495         (funcall doc-fn apropos-accumulator))
496     (setq apropos-accumulator
497           (sort apropos-accumulator (lambda (a b)
498                                       (string-lessp (car a) (car b)))))
499     (and apropos-label-face
500          (or (symbolp apropos-label-face)
501              (facep apropos-label-face)) ; XEmacs
502          (setq apropos-label-face `(face ,apropos-label-face
503                                          mouse-face highlight)))
504     (let ((help-buffer-prefix-string "Apropos"))
505       (with-displaying-help-buffer
506        (lambda ()
507          (with-current-buffer standard-output
508            (run-hooks 'apropos-mode-hook)
509            (let ((p apropos-accumulator)
510                  (old-buffer (current-buffer))
511                  symbol item point1 point2)
512              ;; Mostly useless but to provide better keymap
513              ;; explanation. help-mode-map will be used instead.
514              (use-local-map apropos-mode-map)
515              ;; XEmacs change from (if window-system
516              (if (device-on-window-system-p)
517                  (progn
518                    (princ "If you move the mouse over text that changes color,\n")
519                    (princ (substitute-command-keys
520                            "you can click \\[apropos-mouse-follow] to get more information.\n"))))
521              (princ (substitute-command-keys
522                      "Type \\[apropos-follow] in this buffer to get full documentation.\n\n"))
523              (while (consp p)
524                (or (not spacing) (bobp) (terpri))
525                (setq apropos-item (car p)
526                      symbol (car apropos-item)
527                      p (cdr p)
528                      point1 (point))
529                (princ symbol)           ; print symbol name
530                (setq point2 (point))
531                ;; Calculate key-bindings if we want them.
532                (and do-keys
533                     (commandp symbol)
534                     (indent-to 30 1)
535                     (if (let ((keys
536                                (save-excursion
537                                  (set-buffer old-buffer)
538                                  (where-is-internal symbol)))
539                               filtered)
540                           ;; Copy over the list of key sequences,
541                           ;; omitting any that contain a buffer or a frame.
542                           (while keys
543                             (let ((key (car keys))
544                                   (i 0)
545                                   loser)
546                               (while (< i (length key))
547                                 (if (or (framep (aref key i))
548                                         (bufferp (aref key i)))
549                                     (setq loser t))
550                                 (setq i (1+ i)))
551                               (or loser
552                                   (setq filtered (cons key filtered))))
553                             (setq keys (cdr keys)))
554                           (setq item filtered))
555                         ;; Convert the remaining keys to a string and insert.
556                         (princ
557                          (mapconcat
558                           (lambda (key)
559                             (setq key (key-description key))
560                             (if apropos-keybinding-face
561                                 (put-text-property 0 (length key)
562                                                    'face apropos-keybinding-face
563                                                    key))
564                             key)
565                           item ", "))
566                       (princ "Type ")
567                       (princ "M-x")
568                       (put-text-property (- (point) 3) (point)
569                                          'face apropos-keybinding-face)
570                       (princ (format " %s " (symbol-name symbol)))
571                       (princ "RET")
572                       (put-text-property (- (point) 3) (point)
573                                          'face apropos-keybinding-face)))
574                (terpri)
575                ;; only now so we don't propagate text attributes all over
576                (put-text-property point1 point2 'item
577                                   (if (eval `(or ,@(cdr apropos-item)))
578                                       (car apropos-item)
579                                     apropos-item))
580                (if apropos-symbol-face
581                    (put-text-property point1 point2 'face apropos-symbol-face))
582                ;; Add text-property on symbol, too.
583                (put-text-property point1 point2 'keymap apropos-mode-map)
584                (apropos-print-doc 'describe-function 1
585                                   (if (commandp symbol)
586                                       "Command"
587                                     (if (apropos-macrop symbol)
588                                         "Macro"
589                                       "Function"))
590                                   do-keys)
591                (if (get symbol 'custom-type)
592                    (apropos-print-doc 'customize-variable-other-window 2
593                                       "User Option" do-keys)
594                  (apropos-print-doc 'describe-variable 2
595                                     "Variable" do-keys))
596                (apropos-print-doc 'customize-other-window 6 "Group" do-keys)
597                (apropos-print-doc 'customize-face-other-window 5 "Face" do-keys)
598                (apropos-print-doc 'widget-browse-other-window 4 "Widget" do-keys)
599                (apropos-print-doc 'apropos-describe-plist 3
600                                   "Plist" nil)))))
601        apropos-regexp))
602     (prog1 apropos-accumulator
603       (setq apropos-accumulator ()))))  ; permit gc
604
605
606 (defun apropos-macrop (symbol)
607   "Return t if SYMBOL is a Lisp macro."
608   (and (fboundp symbol)
609        (consp (setq symbol
610                     (symbol-function symbol)))
611        (or (eq (car symbol) 'macro)
612            (if (eq (car symbol) 'autoload)
613                (memq (nth 4 symbol)
614                      '(macro t))))))
615
616
617 (defun apropos-print-doc (action i str do-keys)
618   (with-current-buffer standard-output
619     (if (stringp (setq i (nth i apropos-item)))
620         (progn
621           (insert "  ")
622           (put-text-property (- (point) 2) (1- (point))
623                              'action action)
624           (insert str ": ")
625           (if apropos-label-face
626               (add-text-properties (- (point) (length str) 2)
627                                    (1- (point))
628                                    apropos-label-face))
629           (add-text-properties (- (point) (length str) 2)
630                                (1- (point))
631                                (list 'keymap apropos-mode-map))
632           (insert (if do-keys (substitute-command-keys i) i))
633           (or (bolp) (terpri))))))
634
635 (defun apropos-mouse-follow (event)
636   (interactive "e")
637   ;; XEmacs change:  We're using the standard help buffer code now, don't
638   ;; do special tricks about trying to preserve current-buffer about mouse
639   ;; clicks.
640
641   (save-excursion
642     ;; XEmacs change from:
643     ;; (set-buffer (window-buffer (posn-window (event-start event))))
644     ;; (goto-char (posn-point (event-start event)))
645     (set-buffer (event-buffer event))
646     (goto-char (event-closest-point event))
647     ;; XEmacs change: following code seems useless
648     ;;(or (and (not (eobp)) (get-text-property (point) 'mouse-face))
649     ;;    (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
650     ;;    (error "There is nothing to follow here"))
651     (apropos-follow)))
652
653
654 (defun apropos-follow (&optional other)
655   (interactive)
656   (let* (;; Properties are always found at the beginning of the line.
657          (bol (save-excursion (beginning-of-line) (point)))
658          ;; If there is no `item' property here, look behind us.
659          (item (get-text-property bol 'item))
660          (item-at (if item nil (previous-single-property-change bol 'item)))
661          ;; Likewise, if there is no `action' property here, look in front.
662          (action (get-text-property bol 'action))
663          (action-at (if action nil (next-single-property-change bol 'action))))
664     (and (null item) item-at
665          (setq item (get-text-property (1- item-at) 'item)))
666     (and (null action) action-at
667          (setq action (get-text-property action-at 'action)))
668     (if (not (and item action))
669         (error "There is nothing to follow here"))
670     (if (consp item) (error "There is nothing to follow in `%s'" (car item)))
671     (if other (set-buffer other))
672     (funcall action item)))
673
674
675
676 (defun apropos-describe-plist (symbol)
677   "Display a pretty listing of SYMBOL's plist."
678   (let ((help-buffer-prefix-string "Apropos-plist"))
679     (with-displaying-help-buffer
680      (lambda ()
681        (run-hooks 'apropos-mode-hook)
682        (princ "Symbol ")
683        (prin1 symbol)
684        (princ "'s plist is\n (")
685        (with-current-buffer standard-output
686          (if apropos-symbol-face
687              (put-text-property 8 (- (point) 14) 'face apropos-symbol-face)))
688        (princ (apropos-format-plist symbol "\n  "))
689        (princ ")")
690        (terpri)
691        (print-help-return-message))
692      (symbol-name symbol))))
693
694 (provide 'apropos) ; XEmacs
695
696 ;;; apropos.el ends here