(menu-bar-file-menu) <dired>: Change help-echo string.
[bpt/emacs.git] / lisp / tooltip.el
CommitLineData
b670783a 1;;; tooltip.el --- show tooltip windows
7840ced1 2
0d30b337
TTN
3;; Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004,
4;; 2005 Free Software Foundation, Inc.
7840ced1
GM
5
6;; Author: Gerd Moellmann <gerd@acm.org>
7;; Keywords: help c mouse tools
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
7840ced1
GM
25
26;;; Commentary:
27
7840ced1
GM
28;;; Code:
29
5673b222
JB
30(defvar comint-prompt-regexp)
31
7840ced1
GM
32;;; Customizable settings
33
34(defgroup tooltip nil
35 "Customization group for the `tooltip' package."
36 :group 'help
3e6ed970 37 :group 'gud
7840ced1
GM
38 :group 'mouse
39 :group 'tools
01b23b99 40 :version "21.1"
7840ced1
GM
41 :tag "Tool Tips")
42
88751b11 43(defcustom tooltip-delay 0.7
7840ced1
GM
44 "Seconds to wait before displaying a tooltip the first time."
45 :tag "Delay"
46 :type 'number
47 :group 'tooltip)
48
7840ced1
GM
49(defcustom tooltip-short-delay 0.1
50 "Seconds to wait between subsequent tooltips on different items."
51 :tag "Short delay"
52 :type 'number
53 :group 'tooltip)
54
7840ced1 55(defcustom tooltip-recent-seconds 1
01b23b99
DL
56 "Display tooltips if changing tip items within this many seconds.
57Do so after `tooltip-short-delay'."
7840ced1
GM
58 :tag "Recent seconds"
59 :type 'number
60 :group 'tooltip)
61
88751b11 62(defcustom tooltip-hide-delay 10
a93c8ba8
GM
63 "Hide tooltips automatically after this many seconds."
64 :tag "Hide delay"
65 :type 'number
66 :group 'tooltip)
67
e4df9b40 68(defcustom tooltip-x-offset nil
37a29d46 69 "X offset, in pixels, for the display of tooltips.
e4df9b40
GM
70The offset is relative to the position of the mouse. It must
71be chosen so that the tooltip window doesn't contain the mouse
7142670a
EZ
72when it pops up. If the value is nil, the default offset is 5
73pixels.
74
75If `tooltip-frame-parameters' includes the `left' parameter,
76the value of `tooltip-x-offset' is ignored."
e4df9b40
GM
77 :tag "X offset"
78 :type '(choice (const :tag "Default" nil)
79 (integer :tag "Offset" :value 1))
80 :group 'tooltip)
81
e4df9b40 82(defcustom tooltip-y-offset nil
37a29d46 83 "Y offset, in pixels, for the display of tooltips.
e4df9b40
GM
84The offset is relative to the position of the mouse. It must
85be chosen so that the tooltip window doesn't contain the mouse
7142670a
EZ
86when it pops up. If the value is nil, the default offset is -10
87pixels.
88
89If `tooltip-frame-parameters' includes the `top' parameter,
90the value of `tooltip-y-offset' is ignored."
e4df9b40
GM
91 :tag "Y offset"
92 :type '(choice (const :tag "Default" nil)
93 (integer :tag "Offset" :value 1))
94 :group 'tooltip)
95
7840ced1
GM
96(defcustom tooltip-frame-parameters
97 '((name . "tooltip")
7840ced1 98 (internal-border-width . 5)
7840ced1 99 (border-width . 1))
7142670a
EZ
100 "Frame parameters used for tooltips.
101
102If `left' or `top' parameters are included, they specify the absolute
103position to pop up the tooltip."
7840ced1
GM
104 :type 'sexp
105 :tag "Frame Parameters"
106 :group 'tooltip)
107
2621f5a9
GM
108(defface tooltip
109 '((((class color))
39440204
JPW
110 :background "lightyellow"
111 :foreground "black"
112 :inherit variable-pitch)
113 (t
114 :inherit variable-pitch))
2621f5a9 115 "Face for tooltips."
daf96a41
JL
116 :group 'tooltip
117 :group 'basic-faces)
2621f5a9 118
90aff7c6
NR
119(defcustom tooltip-use-echo-area nil
120 "Use the echo area instead of tooltip frames for help and GUD tooltips."
121 :type 'boolean
122 :tag "Use echo area"
123 :group 'tooltip)
124
7840ced1
GM
125\f
126;;; Variables that are not customizable.
127
128(defvar tooltip-hook nil
129 "Functions to call to display tooltips.
130Each function is called with one argument EVENT which is a copy of
131the last mouse movement event that occurred.")
132
7840ced1
GM
133(defvar tooltip-timeout-id nil
134 "The id of the timeout started when Emacs becomes idle.")
135
7840ced1
GM
136(defvar tooltip-last-mouse-motion-event nil
137 "A copy of the last mouse motion event seen.")
138
7840ced1
GM
139(defvar tooltip-hide-time nil
140 "Time when the last tooltip was hidden.")
141
1af98f07
RS
142(defvar gud-tooltip-mode) ;; Prevent warning.
143
7840ced1
GM
144;;; Event accessors
145
146(defun tooltip-event-buffer (event)
147 "Return the buffer over which event EVENT occurred.
148This might return nil if the event did not occur over a buffer."
149 (let ((window (posn-window (event-end event))))
150 (and window (window-buffer window))))
151
7840ced1
GM
152;;; Switching tooltips on/off
153
154;; We don't set track-mouse globally because this is a big redisplay
155;; problem in buffers having a pre-command-hook or such installed,
156;; which does a set-buffer, like the summary buffer of Gnus. Calling
157;; set-buffer prevents redisplay optimizations, so every mouse motion
158;; would be accompanied by a full redisplay.
159
8bc973e9
NR
160(define-minor-mode tooltip-mode
161 "Toggle Tooltip display.
7840ced1 162With ARG, turn tooltip mode on if and only if ARG is positive."
8bc973e9 163 :global t
d5e2843d 164 :init-value (not (or noninteractive
5eca5ecd 165 emacs-basic-display
5fc54662 166 (not (display-graphic-p))
d5e2843d 167 (not (fboundp 'x-show-tip))))
5fc54662 168 :initialize 'custom-initialize-safe-default
8bc973e9 169 :group 'tooltip
ef75a647 170 (unless (or (null tooltip-mode) (fboundp 'x-show-tip))
c6da4eb4 171 (error "Sorry, tooltips are not yet available on this system"))
a93d8344
NR
172 (if tooltip-mode
173 (progn
174 (add-hook 'pre-command-hook 'tooltip-hide)
175 (add-hook 'tooltip-hook 'tooltip-help-tips))
176 (unless (and (boundp 'gud-tooltip-mode) gud-tooltip-mode)
177 (remove-hook 'pre-command-hook 'tooltip-hide))
178 (remove-hook 'tooltip-hook 'tooltip-help-tips))
179 (setq show-help-function
90aff7c6 180 (if tooltip-mode 'tooltip-show-help nil)))
dea87733 181
7840ced1
GM
182\f
183;;; Timeout for tooltip display
184
7840ced1
GM
185(defun tooltip-delay ()
186 "Return the delay in seconds for the next tooltip."
187 (let ((delay tooltip-delay)
a1f84f6d 188 (now (float-time)))
7840ced1
GM
189 (when (and tooltip-hide-time
190 (< (- now tooltip-hide-time) tooltip-recent-seconds))
191 (setq delay tooltip-short-delay))
192 delay))
193
06f76f9f 194(defun tooltip-cancel-delayed-tip ()
7840ced1
GM
195 "Disable the tooltip timeout."
196 (when tooltip-timeout-id
197 (disable-timeout tooltip-timeout-id)
198 (setq tooltip-timeout-id nil)))
199
06f76f9f 200(defun tooltip-start-delayed-tip ()
04cedb11 201 "Add a one-shot timeout to call function `tooltip-timeout'."
7840ced1
GM
202 (setq tooltip-timeout-id
203 (add-timeout (tooltip-delay) 'tooltip-timeout nil)))
204
7840ced1 205(defun tooltip-timeout (object)
04cedb11 206 "Function called when timer with id `tooltip-timeout-id' fires."
7840ced1
GM
207 (run-hook-with-args-until-success 'tooltip-hook
208 tooltip-last-mouse-motion-event))
209
7840ced1 210\f
7840ced1
GM
211;;; Displaying tips
212
2621f5a9 213(defun tooltip-set-param (alist key value)
4b2bb9be 214 "Change the value of KEY in alist ALIST to VALUE.
f1180544 215If there's no association for KEY in ALIST, add one, otherwise
2621f5a9
GM
216change the existing association. Value is the resulting alist."
217 (let ((param (assq key alist)))
218 (if (consp param)
219 (setcdr param value)
220 (push (cons key value) alist))
221 alist))
222
cae07240 223(defun tooltip-show (text &optional use-echo-area)
7142670a
EZ
224 "Show a tooltip window displaying TEXT.
225
1d6197fb 226Text larger than `x-max-tooltip-size' is clipped.
7142670a
EZ
227
228If the alist in `tooltip-frame-parameters' includes `left' and `top'
229parameters, they determine the x and y position where the tooltip
230is displayed. Otherwise, the tooltip pops at offsets specified by
231`tooltip-x-offset' and `tooltip-y-offset' from the current mouse
1d6197fb
NR
232position.
233
cae07240
KS
234Optional second arg USE-ECHO-AREA non-nil means to show tooltip
235in echo area."
236 (if use-echo-area
72200f89 237 (message "%s" text)
e5603149 238 (condition-case error
2621f5a9
GM
239 (let ((params (copy-sequence tooltip-frame-parameters))
240 (fg (face-attribute 'tooltip :foreground))
241 (bg (face-attribute 'tooltip :background)))
06f76f9f
GM
242 (when (stringp fg)
243 (setq params (tooltip-set-param params 'foreground-color fg))
244 (setq params (tooltip-set-param params 'border-color fg)))
245 (when (stringp bg)
246 (setq params (tooltip-set-param params 'background-color bg)))
2621f5a9
GM
247 (x-show-tip (propertize text 'face 'tooltip)
248 (selected-frame)
f3b05e99 249 params
a93c8ba8 250 tooltip-hide-delay
2621f5a9
GM
251 tooltip-x-offset
252 tooltip-y-offset))
f1180544 253 (error
e5603149
GM
254 (message "Error while displaying tooltip: %s" error)
255 (sit-for 1)
256 (message "%s" text)))))
257
7840ced1
GM
258(defun tooltip-hide (&optional ignored-arg)
259 "Hide a tooltip, if one is displayed.
260Value is non-nil if tooltip was open."
06f76f9f 261 (tooltip-cancel-delayed-tip)
7840ced1 262 (when (x-hide-tip)
a1f84f6d 263 (setq tooltip-hide-time (float-time))))
7840ced1 264
7840ced1
GM
265\f
266;;; Debugger-related functions
267
268(defun tooltip-identifier-from-point (point)
269 "Extract the identifier at POINT, if any.
270Value is nil if no identifier exists at point. Identifier extraction
271is based on the current syntax table."
272 (save-excursion
273 (goto-char point)
274 (let ((start (progn (skip-syntax-backward "w_") (point))))
275 (unless (looking-at "[0-9]")
276 (skip-syntax-forward "w_")
277 (when (> (point) start)
278 (buffer-substring start (point)))))))
279
7840ced1
GM
280(defmacro tooltip-region-active-p ()
281 "Value is non-nil if the region is currently active."
282 (if (string-match "^GNU" (emacs-version))
283 `(and transient-mark-mode mark-active)
284 `(region-active-p)))
285
7840ced1
GM
286(defun tooltip-expr-to-print (event)
287 "Return an expression that should be printed for EVENT.
288If a region is active and the mouse is inside the region, print
289the region. Otherwise, figure out the identifier around the point
290where the mouse is."
291 (save-excursion
292 (set-buffer (tooltip-event-buffer event))
293 (let ((point (posn-point (event-end event))))
294 (if (tooltip-region-active-p)
295 (when (and (<= (region-beginning) point) (<= point (region-end)))
296 (buffer-substring (region-beginning) (region-end)))
297 (tooltip-identifier-from-point point)))))
298
7840ced1
GM
299(defun tooltip-process-prompt-regexp (process)
300 "Return regexp matching the prompt of PROCESS at the end of a string.
04cedb11
JB
301The prompt is taken from the value of `comint-prompt-regexp' in
302the buffer of PROCESS."
7840ced1
GM
303 (let ((prompt-regexp (save-excursion
304 (set-buffer (process-buffer process))
305 comint-prompt-regexp)))
306 ;; Most start with `^' but the one for `sdb' cannot be easily
307 ;; stripped. Code the prompt for `sdb' fixed here.
308 (if (= (aref prompt-regexp 0) ?^)
309 (setq prompt-regexp (substring prompt-regexp 1))
310 (setq prompt-regexp "\\*"))
311 (concat "\n*" prompt-regexp "$")))
312
7840ced1
GM
313(defun tooltip-strip-prompt (process output)
314 "Return OUTPUT with any prompt of PROCESS stripped from its end."
315 (let ((prompt-regexp (tooltip-process-prompt-regexp process)))
316 (save-match-data
317 (when (string-match prompt-regexp output)
318 (setq output (substring output 0 (match-beginning 0)))))
319 output))
320
7840ced1 321\f
7840ced1
GM
322;;; Tooltip help.
323
324(defvar tooltip-help-message nil
90aff7c6 325 "The last help message received via `tooltip-show-help'.")
7840ced1 326
90aff7c6 327(defun tooltip-show-help (msg)
7840ced1
GM
328 "Function installed as `show-help-function'.
329MSG is either a help string to display, or nil to cancel the display."
86f0d417 330 (let ((previous-help tooltip-help-message))
7840ced1
GM
331 (setq tooltip-help-message msg)
332 (cond ((null msg)
06f76f9f
GM
333 ;; Cancel display. This also cancels a delayed tip, if
334 ;; there is one.
7840ced1 335 (tooltip-hide))
06f76f9f
GM
336 ((equal previous-help msg)
337 ;; Same help as before (but possibly the mouse has moved).
338 ;; Keep what we have.
339 )
7840ced1 340 (t
f1180544 341 ;; A different help. Remove a previous tooltip, and
06f76f9f
GM
342 ;; display a new one, with some delay.
343 (tooltip-hide)
344 (tooltip-start-delayed-tip)))))
7840ced1 345
7840ced1
GM
346(defun tooltip-help-tips (event)
347 "Hook function to display a help tooltip.
06f76f9f 348This is installed on the hook `tooltip-hook', which is run when
04cedb11 349the timer with id `tooltip-timeout-id' fires.
7840ced1
GM
350Value is non-nil if this function handled the tip."
351 (when (stringp tooltip-help-message)
90aff7c6 352 (tooltip-show tooltip-help-message tooltip-use-echo-area)
7840ced1
GM
353 t))
354
5ce0fb91 355(provide 'tooltip)
7840ced1 356
18385083 357;; arch-tag: 3d61135e-4618-4a78-af28-183f6df5636f
7840ced1 358;;; tooltip.el ends here