comparison lisp/custom/wid-edit.el @ 195:a2f645c6b9f8 r20-3b24

Import from CVS: tag r20-3b24
author cvs
date Mon, 13 Aug 2007 09:59:05 +0200
parents f53b5ca2e663
children acd284d43ca1
comparison
equal deleted inserted replaced
194:2947057885e5 195:a2f645c6b9f8
1 ;;; wid-edit.el --- Functions for creating and using widgets. 1 ;;; wid-edit.el --- Functions for creating and using widgets.
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Maintainer: Hrvoje Niksic <hniksic@srce.hr>
6 ;; Keywords: extensions 7 ;; Keywords: extensions
7 ;; Version: 1.9960 8 ;; Version: 1.9960-x
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 9 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 10
10 ;; This file is part of GNU Emacs. 11 ;; This file is part of XEmacs.
11 12
12 ;; GNU Emacs is free software; you can redistribute it and/or modify 13 ;; XEmacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by 14 ;; it 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 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version. 16 ;; any later version.
16 17
17 ;; GNU Emacs is distributed in the hope that it will be useful, 18 ;; XEmacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details. 21 ;; GNU General Public License for more details.
21 22
22 ;; You should have received a copy of the GNU General Public License 23 ;; 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 ;; along with XEmacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA. 26 ;; Boston, MA 02111-1307, USA.
26 27
27 ;;; Commentary: 28 ;;; Commentary:
28 ;; 29 ;;
29 ;; See `widget.el'. 30 ;; See `widget.el'.
30 31
32
31 ;;; Code: 33 ;;; Code:
32 34
33 (require 'widget) 35 (require 'widget)
34 (eval-when-compile (require 'cl)) 36
35 37 (autoload 'pp-to-string "pp")
36 ;;; Compatibility. 38 (autoload 'finder-commentary "finder" nil t)
37 39
38 (eval-and-compile 40 (defun widget-event-point (event)
39 (autoload 'pp-to-string "pp") 41 "Character position of the end of event if that exists, or nil."
40 (autoload 'Info-goto-node "info") 42 (if (mouse-event-p event)
41 (autoload 'finder-commentary "finder" nil t) 43 (event-point event)
42 44 nil))
43 (when (string-match "XEmacs" emacs-version)
44 (condition-case nil
45 (require 'overlay)
46 (error (load-library "x-overlay"))))
47
48 (if (string-match "XEmacs" emacs-version)
49 (defun widget-event-point (event)
50 "Character position of the end of event if that exists, or nil."
51 (if (mouse-event-p event)
52 (event-point event)
53 nil))
54 (defun widget-event-point (event)
55 "Character position of the end of event if that exists, or nil."
56 (posn-point (event-end event))))
57
58 (defalias 'widget-read-event (if (string-match "XEmacs" emacs-version)
59 'next-event
60 'read-event))
61
62 ;; The following should go away when bundled with Emacs.
63 (condition-case ()
64 (require 'custom)
65 (error nil))
66
67 (unless (and (featurep 'custom) (fboundp 'custom-declare-variable))
68 ;; We have the old custom-library, hack around it!
69 (defmacro defgroup (&rest args) nil)
70 (defmacro defcustom (var value doc &rest args)
71 (` (defvar (, var) (, value) (, doc))))
72 (defmacro defface (&rest args) nil)
73 (define-widget-keywords :prefix :tag :load :link :options :type :group)
74 (when (fboundp 'copy-face)
75 (copy-face 'default 'widget-documentation-face)
76 (copy-face 'bold 'widget-button-face)
77 (copy-face 'italic 'widget-field-face)))
78
79 (unless (fboundp 'button-release-event-p)
80 ;; XEmacs function missing from Emacs.
81 (defun button-release-event-p (event)
82 "Non-nil if EVENT is a mouse-button-release event object."
83 (and (eventp event)
84 (memq (event-basic-type event) '(mouse-1 mouse-2 mouse-3))
85 (or (memq 'click (event-modifiers event))
86 (memq 'drag (event-modifiers event))))))
87
88 (unless (fboundp 'functionp)
89 ;; Missing from Emacs 19.34 and earlier.
90 (defun functionp (object)
91 "Non-nil of OBJECT is a type of object that can be called as a function."
92 (or (subrp object) (byte-code-function-p object)
93 (eq (car-safe object) 'lambda)
94 (and (symbolp object) (fboundp object)))))
95
96 (unless (fboundp 'error-message-string)
97 ;; Emacs function missing in XEmacs.
98 (defun error-message-string (obj)
99 "Convert an error value to an error message."
100 (let ((buf (get-buffer-create " *error-message*")))
101 (erase-buffer buf)
102 (display-error obj buf)
103 (buffer-string buf)))))
104 45
105 ;;; Customization. 46 ;;; Customization.
106 47
107 (defgroup widgets nil 48 (defgroup widgets nil
108 "Customization support for the Widget Library." 49 "Customization support for the Widget Library."
160 (t 101 (t
161 (:italic t))) 102 (:italic t)))
162 "Face used for editable fields." 103 "Face used for editable fields."
163 :group 'widget-faces) 104 :group 'widget-faces)
164 105
165 (defface widget-single-line-field-face '((((class grayscale color) 106 ;; Currently unused
166 (background light)) 107 ;(defface widget-single-line-field-face '((((class grayscale color)
167 (:background "gray85")) 108 ; (background light))
168 (((class grayscale color) 109 ; (:background "gray85"))
169 (background dark)) 110 ; (((class grayscale color)
170 (:background "dim gray")) 111 ; (background dark))
171 (t 112 ; (:background "dim gray"))
172 (:italic t))) 113 ; (t
173 "Face used for editable fields spanning only a single line." 114 ; (:italic t)))
174 :group 'widget-faces) 115 ; "Face used for editable fields spanning only a single line."
175 116 ; :group 'widget-faces)
176 (defvar widget-single-line-display-table 117 ;
177 (let ((table (make-display-table))) 118 ;(defvar widget-single-line-display-table
178 (aset table 9 "^I") 119 ; (let ((table (make-display-table)))
179 (aset table 10 "^J") 120 ; (aset table 9 "^I")
180 table) 121 ; (aset table 10 "^J")
181 "Display table used for single-line editable fields.") 122 ; table)
182 123 ; "Display table used for single-line editable fields.")
183 (when (fboundp 'set-face-display-table) 124 ;
184 (set-face-display-table 'widget-single-line-field-face 125 ;(set-face-display-table 'widget-single-line-field-face
185 widget-single-line-display-table)) 126 ; widget-single-line-display-table)
186 127
128
129 ;; Some functions from this file have been ported to C for speed.
130 ;; Setting this to t (*before* loading wid-edit.el) will make them
131 ;; shadow the subrs. It should be used only for debugging purposes.
132 (defvar widget-shadow-subrs nil)
133
134
187 ;;; Utility functions. 135 ;;; Utility functions.
188 ;; 136 ;;
189 ;; These are not really widget specific. 137 ;; These are not really widget specific.
190 138
191 (defsubst widget-plist-member (plist prop) 139 (when (or (not (fboundp 'widget-plist-member))
192 ;; Return non-nil if PLIST has the property PROP. 140 widget-shadow-subrs)
193 ;; PLIST is a property list, which is a list of the form 141 ;; Recoded in C, for efficiency. It used to be a defsubst, but old
194 ;; (PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol. 142 ;; compiled code won't fail -- it will just be slower.
195 ;; Unlike `plist-get', this allows you to distinguish between a missing 143 (defun widget-plist-member (plist prop)
196 ;; property and a property with the value nil. 144 ;; Return non-nil if PLIST has the property PROP.
197 ;; The value is actually the tail of PLIST whose car is PROP. 145 ;; PLIST is a property list, which is a list of the form
198 (while (and plist (not (eq (car plist) prop))) 146 ;; (PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol.
199 (setq plist (cdr (cdr plist)))) 147 ;; Unlike `plist-get', this allows you to distinguish between a missing
200 plist) 148 ;; property and a property with the value nil.
149 ;; The value is actually the tail of PLIST whose car is PROP.
150 (while (and plist (not (eq (car plist) prop)))
151 (setq plist (cddr plist)))
152 plist))
201 153
202 (defun widget-princ-to-string (object) 154 (defun widget-princ-to-string (object)
203 ;; Return string representation of OBJECT, any Lisp object. 155 ;; Return string representation of OBJECT, any Lisp object.
204 ;; No quoting characters are used; no delimiters are printed around 156 ;; No quoting characters are used; no delimiters are printed around
205 ;; the contents of strings. 157 ;; the contents of strings.
206 (save-excursion 158 (with-current-buffer (get-buffer-create " *widget-tmp*")
207 (set-buffer (get-buffer-create " *widget-tmp*"))
208 (erase-buffer) 159 (erase-buffer)
209 (let ((standard-output (current-buffer))) 160 (princ object (current-buffer))
210 (princ object))
211 (buffer-string))) 161 (buffer-string)))
212 162
213 (defun widget-clear-undo () 163 (defun widget-clear-undo ()
214 "Clear all undo information." 164 "Clear all undo information."
215 (buffer-disable-undo (current-buffer)) 165 (buffer-disable-undo)
216 (buffer-enable-undo)) 166 (buffer-enable-undo))
217 167
218 (defcustom widget-menu-max-size 40 168 (defcustom widget-menu-max-size 40
219 "Largest number of items allowed in a popup-menu. 169 "Largest number of items allowed in a popup-menu.
220 Larger menus are read through the minibuffer." 170 Larger menus are read through the minibuffer."
221 :group 'widgets 171 :group 'widgets
222 :type 'integer) 172 :type 'integer)
223 173
224 (defcustom widget-menu-minibuffer-flag (string-match "XEmacs" emacs-version) 174 (defcustom widget-menu-minibuffer-flag nil
225 "*Control how to ask for a choice from the keyboard. 175 "*Control how to ask for a choice from the keyboard.
226 Non-nil means use the minibuffer; 176 Non-nil means use the minibuffer;
227 nil means read a single character." 177 nil means read a single character."
228 :group 'widgets 178 :group 'widgets
229 :type 'boolean) 179 :type 'boolean)
240 The user is asked to choose between each NAME from the items alist, 190 The user is asked to choose between each NAME from the items alist,
241 and the VALUE of the chosen element will be returned. If EVENT is a 191 and the VALUE of the chosen element will be returned. If EVENT is a
242 mouse event, and the number of elements in items is less than 192 mouse event, and the number of elements in items is less than
243 `widget-menu-max-size', a popup menu will be used, otherwise the 193 `widget-menu-max-size', a popup menu will be used, otherwise the
244 minibuffer." 194 minibuffer."
245 (cond ((and (< (length items) widget-menu-max-size) 195 (cond ((and (< (length items) widget-menu-max-size)
246 event (fboundp 'x-popup-menu) window-system) 196 event
247 ;; We are in Emacs-19, pressed by the mouse 197 (console-on-window-system-p))
248 (x-popup-menu event 198 ;; Pressed by the mouse.
249 (list title (cons "" items))))
250 ((and (< (length items) widget-menu-max-size)
251 event (fboundp 'popup-menu) window-system)
252 ;; We are in XEmacs, pressed by the mouse
253 (let ((val (get-popup-menu-response 199 (let ((val (get-popup-menu-response
254 (cons title 200 (cons title
255 (mapcar 201 (mapcar (lambda (x)
256 (function 202 (if (stringp x)
257 (lambda (x) 203 (vector x nil nil)
258 (if (stringp x) 204 (vector (car x) (list (car x)) t)))
259 (vector x nil nil) 205 items)))))
260 (vector (car x) (list (car x)) t))))
261 items)))))
262 (setq val (and val 206 (setq val (and val
263 (listp (event-object val)) 207 (listp (event-object val))
264 (stringp (car-safe (event-object val))) 208 (stringp (car-safe (event-object val)))
265 (car (event-object val)))) 209 (car (event-object val))))
266 (cdr (assoc val items)))) 210 (cdr (assoc val items))))
267 (widget-menu-minibuffer-flag 211 ((and (not widget-menu-minibuffer-flag)
268 ;; Read the choice of name from the minibuffer. 212 ;; Can't handle more than 10 items (as many digits)
269 (setq items (widget-remove-if 'stringp items)) 213 (<= (length items) 10))
270 (let ((val (completing-read (concat title ": ") items nil t)))
271 (if (stringp val)
272 (let ((try (try-completion val items)))
273 (when (stringp try)
274 (setq val try))
275 (cdr (assoc val items)))
276 nil)))
277 (t
278 ;; Construct a menu of the choices 214 ;; Construct a menu of the choices
279 ;; and then use it for prompting for a single character. 215 ;; and then use it for prompting for a single character.
280 (let* ((overriding-terminal-local-map 216 (let* ((overriding-terminal-local-map (make-sparse-keymap))
281 (make-sparse-keymap)) 217 (map (make-sparse-keymap title))
282 map choice (next-digit ?0) 218 (next-digit ?0)
283 some-choice-enabled 219 some-choice-enabled value)
284 value)
285 ;; Define SPC as a prefix char to get to this menu. 220 ;; Define SPC as a prefix char to get to this menu.
286 (define-key overriding-terminal-local-map " " 221 (define-key overriding-terminal-local-map " " map)
287 (setq map (make-sparse-keymap title))) 222 (with-current-buffer (get-buffer-create " widget-choose")
288 (save-excursion
289 (set-buffer (get-buffer-create " widget-choose"))
290 (erase-buffer) 223 (erase-buffer)
291 (insert "Available choices:\n\n") 224 (insert "Available choices:\n\n")
292 (while items 225 (dolist (choice items)
293 (setq choice (car items) items (cdr items)) 226 (when (consp choice)
294 (if (consp choice) 227 (let* ((name (car choice))
295 (let* ((name (car choice)) 228 (function (cdr choice)))
296 (function (cdr choice))) 229 (insert (format "%c = %s\n" next-digit name))
297 (insert (format "%c = %s\n" next-digit name)) 230 (define-key map (vector next-digit) function)
298 (define-key map (vector next-digit) function) 231 (setq some-choice-enabled t)))
299 (setq some-choice-enabled t)))
300 ;; Allocate digits to disabled alternatives 232 ;; Allocate digits to disabled alternatives
301 ;; so that the digit of a given alternative never varies. 233 ;; so that the digit of a given alternative never varies.
302 (setq next-digit (1+ next-digit))) 234 (incf next-digit))
303 (insert "\nC-g = Quit")) 235 (insert "\nC-g = Quit"))
304 (or some-choice-enabled 236 (or some-choice-enabled
305 (error "None of the choices is currently meaningful")) 237 (error "None of the choices is currently meaningful"))
306 (define-key map [?\C-g] 'keyboard-quit) 238 (define-key map [?\C-g] 'keyboard-quit)
307 (define-key map [t] 'keyboard-quit) 239 (define-key map [t] 'keyboard-quit)
308 (setcdr map (nreverse (cdr map))) 240 ;(setcdr map (nreverse (cdr map)))
309 ;; Unread a SPC to lead to our new menu. 241 ;; Unread a SPC to lead to our new menu.
310 (setq unread-command-events (cons ?\ unread-command-events)) 242 (push (character-to-event ?\ ) unread-command-events)
311 ;; Read a char with the menu, and return the result 243 ;; Read a char with the menu, and return the result
312 ;; that corresponds to it. 244 ;; that corresponds to it.
313 (save-window-excursion 245 (save-window-excursion
314 (display-buffer (get-buffer " widget-choose")) 246 (display-buffer (get-buffer " widget-choose"))
315 (let ((cursor-in-echo-area t)) 247 (let ((cursor-in-echo-area t))
316 (setq value 248 (setq value
317 (lookup-key overriding-terminal-local-map 249 (lookup-key overriding-terminal-local-map
318 (read-key-sequence title) t)))) 250 (read-key-sequence (concat title ": ") t)))))
251 (message "")
319 (when (eq value 'keyboard-quit) 252 (when (eq value 'keyboard-quit)
320 (error "Canceled")) 253 (error "Canceled"))
321 value)))) 254 value))
322 255 (t
323 (defun widget-remove-if (predictate list) 256 ;; Read the choice of name from the minibuffer.
324 (let (result (tail list)) 257 (setq items (remove-if 'stringp items))
325 (while tail 258 (let ((val (completing-read (concat title ": ") items nil t)))
326 (or (funcall predictate (car tail)) 259 (if (stringp val)
327 (setq result (cons (car tail) result))) 260 (let ((try (try-completion val items)))
328 (setq tail (cdr tail))) 261 (when (stringp try)
329 (nreverse result))) 262 (setq val try))
330 263 (cdr (assoc val items)))
264 nil)))))
265
266
331 ;;; Widget text specifications. 267 ;;; Widget text specifications.
332 ;; 268 ;;
333 ;; These functions are for specifying text properties. 269 ;; These functions are for specifying text properties.
334 270
335 (defcustom widget-field-add-space 271 (defcustom widget-field-add-space t
336 (or t 272 ;; Setting this to nil might be available, once some problems are resolved.
337 ;; It shouldn't be necessary in 20.3, but I need to debug it first.
338 (< emacs-major-version 20)
339 (and (eq emacs-major-version 20)
340 (< emacs-minor-version 3))
341 (not (string-match "XEmacs" emacs-version)))
342 "Non-nil means add extra space at the end of editable text fields. 273 "Non-nil means add extra space at the end of editable text fields.
343 274
344 This is needed on all versions of Emacs, and on XEmacs before 20.3. 275 This is needed on all versions of Emacs. If you don't add the space,
345 If you don't add the space, it will become impossible to edit a zero 276 it will become impossible to edit a zero size field."
346 size field."
347 :type 'boolean 277 :type 'boolean
348 :group 'widgets) 278 :group 'widgets)
349 279
350 (defcustom widget-field-use-before-change 280 (defcustom widget-field-use-before-change
351 (and (or (> emacs-minor-version 34) 281 (and (or (> emacs-minor-version 34)
364 (goto-char to) 294 (goto-char to)
365 (cond ((null (widget-get widget :size)) 295 (cond ((null (widget-get widget :size))
366 (forward-char 1)) 296 (forward-char 1))
367 ;; Terminating space is not part of the field, but necessary in 297 ;; Terminating space is not part of the field, but necessary in
368 ;; order for local-map to work. Remove next sexp if local-map works 298 ;; order for local-map to work. Remove next sexp if local-map works
369 ;; at the end of the overlay. 299 ;; at the end of the extent.
370 (widget-field-add-space 300 (widget-field-add-space
371 (insert-and-inherit " "))) 301 (insert-and-inherit " ")))
372 (setq to (point))) 302 (setq to (point)))
373 (let ((map (widget-get widget :keymap)) 303 (let ((map (widget-get widget :keymap))
374 (face (or (widget-get widget :value-face) 'widget-field-face)) 304 (face (or (widget-get widget :value-face) 'widget-field-face))
375 (help-echo (widget-get widget :help-echo)) 305 (help-echo (widget-get widget :help-echo))
376 (overlay (make-overlay from to nil 306 (extent (make-extent from to)))
377 nil (or (not widget-field-add-space)
378 (widget-get widget :size)))))
379 (unless (or (stringp help-echo) (null help-echo)) 307 (unless (or (stringp help-echo) (null help-echo))
380 (setq help-echo 'widget-mouse-help)) 308 (setq help-echo 'widget-mouse-help))
381 (widget-put widget :field-overlay overlay) 309 (widget-put widget :field-extent extent)
382 (overlay-put overlay 'detachable nil) 310 (and (or (not widget-field-add-space)
383 (overlay-put overlay 'field widget) 311 (widget-get widget :size))
384 (overlay-put overlay 'local-map map) 312 (set-extent-property extent 'end-closed t))
385 (overlay-put overlay 'keymap map) 313 (set-extent-property extent 'detachable nil)
386 (overlay-put overlay 'face face) 314 (set-extent-property extent 'field widget)
387 (overlay-put overlay 'balloon-help help-echo) 315 (set-extent-property extent 'keymap map)
388 (overlay-put overlay 'help-echo help-echo))) 316 (set-extent-property extent 'face face)
317 (set-extent-property extent 'balloon-help help-echo)
318 (set-extent-property extent 'help-echo help-echo)))
389 319
390 (defun widget-specify-button (widget from to) 320 (defun widget-specify-button (widget from to)
391 "Specify button for WIDGET between FROM and TO." 321 "Specify button for WIDGET between FROM and TO."
392 (let ((face (widget-apply widget :button-face-get)) 322 (let ((face (widget-apply widget :button-face-get))
393 (help-echo (widget-get widget :help-echo)) 323 (help-echo (widget-get widget :help-echo))
394 (overlay (make-overlay from to nil t nil))) 324 (extent (make-extent from to)))
395 (widget-put widget :button-overlay overlay) 325 (widget-put widget :button-extent extent)
396 (unless (or (null help-echo) (stringp help-echo)) 326 (unless (or (null help-echo) (stringp help-echo))
397 (setq help-echo 'widget-mouse-help)) 327 (setq help-echo 'widget-mouse-help))
398 (overlay-put overlay 'button widget) 328 (set-extent-property extent 'start-open t)
399 (overlay-put overlay 'mouse-face widget-mouse-face) 329 (set-extent-property extent 'button widget)
400 (overlay-put overlay 'balloon-help help-echo) 330 (set-extent-property extent 'mouse-face widget-mouse-face)
401 (overlay-put overlay 'help-echo help-echo) 331 (set-extent-property extent 'balloon-help help-echo)
402 (overlay-put overlay 'face face))) 332 (set-extent-property extent 'help-echo help-echo)
333 (set-extent-property extent 'face face)))
403 334
404 (defun widget-mouse-help (extent) 335 (defun widget-mouse-help (extent)
405 "Find mouse help string for button in extent." 336 "Find mouse help string for button in extent."
406 (let* ((widget (widget-at (extent-start-position extent))) 337 (let* ((widget (widget-at (extent-start-position extent)))
407 (help-echo (and widget (widget-get widget :help-echo)))) 338 (help-echo (and widget (widget-get widget :help-echo))))
408 (cond ((stringp help-echo) 339 (cond ((stringp help-echo)
409 help-echo) 340 help-echo)
410 ((and (symbolp help-echo) (fboundp help-echo) 341 ((and (functionp help-echo)
411 (stringp (setq help-echo (funcall help-echo widget)))) 342 (stringp (setq help-echo (funcall help-echo widget))))
412 help-echo) 343 help-echo)
413 (t 344 (t
414 (format "(widget %S :help-echo %S)" widget help-echo))))) 345 (format "(widget %S :help-echo %S)" widget help-echo)))))
415 346
416 (defun widget-specify-sample (widget from to) 347 (defun widget-specify-sample (widget from to)
417 ;; Specify sample for WIDGET between FROM and TO. 348 ;; Specify sample for WIDGET between FROM and TO.
418 (let ((face (widget-apply widget :sample-face-get)) 349 (let ((face (widget-apply widget :sample-face-get))
419 (overlay (make-overlay from to nil t nil))) 350 (extent (make-extent from to nil)))
420 (overlay-put overlay 'face face) 351 (set-extent-property extent 'start-open t)
421 (widget-put widget :sample-overlay overlay))) 352 (set-extent-property extent 'face face)
353 (widget-put widget :sample-extent extent)))
422 354
423 (defun widget-specify-doc (widget from to) 355 (defun widget-specify-doc (widget from to)
424 ;; Specify documentation for WIDGET between FROM and TO. 356 ;; Specify documentation for WIDGET between FROM and TO.
425 (let ((overlay (make-overlay from to nil t nil))) 357 (let ((extent (make-extent from to)))
426 (overlay-put overlay 'widget-doc widget) 358 (set-extent-property extent 'start-open t)
427 (overlay-put overlay 'face widget-documentation-face) 359 (set-extent-property extent 'widget-doc widget)
428 (widget-put widget :doc-overlay overlay))) 360 (set-extent-property extent 'face widget-documentation-face)
361 (widget-put widget :doc-extent extent)))
429 362
430 (defmacro widget-specify-insert (&rest form) 363 (defmacro widget-specify-insert (&rest form)
431 ;; Execute FORM without inheriting any text properties. 364 ;; Execute FORM without inheriting any text properties.
432 (` 365 `(save-restriction
433 (save-restriction
434 (let ((inhibit-read-only t) 366 (let ((inhibit-read-only t)
435 result
436 before-change-functions 367 before-change-functions
437 after-change-functions) 368 after-change-functions)
438 (insert "<>") 369 (insert "<>")
439 (narrow-to-region (- (point) 2) (point)) 370 (narrow-to-region (- (point) 2) (point))
440 (goto-char (1+ (point-min))) 371 (goto-char (1+ (point-min)))
441 (setq result (progn (,@ form))) 372 ;; We use `prog1' instead of a `result' variable, as the latter
442 (delete-region (point-min) (1+ (point-min))) 373 ;; confuses the byte-compiler in some cases (a warning).
443 (delete-region (1- (point-max)) (point-max)) 374 (prog1 (progn ,@form)
444 (goto-char (point-max)) 375 (delete-region (point-min) (1+ (point-min)))
445 result)))) 376 (delete-region (1- (point-max)) (point-max))
377 (goto-char (point-max))))))
446 378
447 (defface widget-inactive-face '((((class grayscale color) 379 (defface widget-inactive-face '((((class grayscale color)
448 (background dark)) 380 (background dark))
449 (:foreground "light gray")) 381 (:foreground "light gray"))
450 (((class grayscale color) 382 (((class grayscale color)
456 :group 'widget-faces) 388 :group 'widget-faces)
457 389
458 (defun widget-specify-inactive (widget from to) 390 (defun widget-specify-inactive (widget from to)
459 "Make WIDGET inactive for user modifications." 391 "Make WIDGET inactive for user modifications."
460 (unless (widget-get widget :inactive) 392 (unless (widget-get widget :inactive)
461 (let ((overlay (make-overlay from to nil t nil))) 393 (let ((extent (make-extent from to)))
462 (overlay-put overlay 'face 'widget-inactive-face) 394 (set-extent-property extent 'start-open t)
395 (set-extent-property extent 'face 'widget-inactive-face)
463 ;; This is disabled, as it makes the mouse cursor change shape. 396 ;; This is disabled, as it makes the mouse cursor change shape.
464 ;; (overlay-put overlay 'mouse-face 'widget-inactive-face) 397 ;(set-extent-property extent 'mouse-face 'widget-inactive-face)
465 (overlay-put overlay 'evaporate t) 398 ;; ...actually, in XEmacs, we can easily choose our own pointer
466 (overlay-put overlay 'priority 100) 399 ;; shapes. However, the mouse-face of the "inner" extent will
467 (overlay-put overlay (if (string-match "XEmacs" emacs-version) 400 ;; still be drawn.
468 'read-only 401 (set-extent-property extent 'detachable t)
469 'modification-hooks) '(widget-overlay-inactive)) 402 (set-extent-property extent 'priority 100)
470 (widget-put widget :inactive overlay)))) 403 (set-extent-property extent 'read-only 't)
471 404 (widget-put widget :inactive extent))))
472 (defun widget-overlay-inactive (&rest junk) 405
473 "Ignoring the arguments, signal an error." 406 ;; We don't have modification functions, so this is unused.
474 (unless inhibit-read-only 407 ;(defun widget-overlay-inactive (&rest junk)
475 (error "Attempt to modify inactive widget"))) 408 ; "Ignoring the arguments, signal an error."
409 ; (unless inhibit-read-only
410 ; (error "Attempt to modify inactive widget")))
476 411
477 412
478 (defun widget-specify-active (widget) 413 (defun widget-specify-active (widget)
479 "Make WIDGET active for user modifications." 414 "Make WIDGET active for user modifications."
480 (let ((inactive (widget-get widget :inactive))) 415 (let ((inactive (widget-get widget :inactive)))
481 (when inactive 416 (when inactive
482 (delete-overlay inactive) 417 (delete-extent inactive)
483 (widget-put widget :inactive nil)))) 418 (widget-put widget :inactive nil))))
484 419
420
485 ;;; Widget Properties. 421 ;;; Widget Properties.
486 422
487 (defsubst widget-type (widget) 423 (defun widget-type (widget)
488 "Return the type of WIDGET, a symbol." 424 "Return the type of WIDGET, a symbol."
489 (car widget)) 425 (car widget))
490 426
491 (defun widget-put (widget property value) 427 (when (or (not (fboundp 'widget-put))
492 "In WIDGET set PROPERTY to VALUE. 428 widget-shadow-subrs)
429 (defun widget-put (widget property value)
430 "In WIDGET set PROPERTY to VALUE.
493 The value can later be retrived with `widget-get'." 431 The value can later be retrived with `widget-get'."
494 (setcdr widget (plist-put (cdr widget) property value))) 432 (setcdr widget (plist-put (cdr widget) property value))))
495 433
496 (defun widget-get (widget property) 434 ;; Recoded in C, for efficiency:
497 "In WIDGET, get the value of PROPERTY. 435 (when (or (not (fboundp 'widget-get))
436 widget-shadow-subrs)
437 (defun widget-get (widget property)
438 "In WIDGET, get the value of PROPERTY.
498 The value could either be specified when the widget was created, or 439 The value could either be specified when the widget was created, or
499 later with `widget-put'." 440 later with `widget-put'."
500 (let ((missing t) 441 (let ((missing t)
501 value tmp) 442 value tmp)
502 (while missing 443 (while missing
503 (cond ((setq tmp (widget-plist-member (cdr widget) property)) 444 (cond ((setq tmp (widget-plist-member (cdr widget) property))
504 (setq value (car (cdr tmp)) 445 (setq value (car (cdr tmp))
505 missing nil)) 446 missing nil))
506 ((setq tmp (car widget)) 447 ((setq tmp (car widget))
507 (setq widget (get tmp 'widget-type))) 448 (setq widget (get tmp 'widget-type)))
508 (t 449 (t
509 (setq missing nil)))) 450 (setq missing nil))))
510 value)) 451 value)))
511 452
512 (defun widget-get-indirect (widget property) 453 (defun widget-get-indirect (widget property)
513 "In WIDGET, get the value of PROPERTY. 454 "In WIDGET, get the value of PROPERTY.
514 If the value is a symbol, return its binding. 455 If the value is a symbol, return its binding.
515 Otherwise, just return the value." 456 Otherwise, just return the value."
524 t) 465 t)
525 ((car widget) 466 ((car widget)
526 (widget-member (get (car widget) 'widget-type) property)) 467 (widget-member (get (car widget) 'widget-type) property))
527 (t nil))) 468 (t nil)))
528 469
529 ;;;###autoload 470 (when (or (not (fboundp 'widget-apply))
530 (defun widget-apply (widget property &rest args) 471 widget-shadow-subrs)
531 "Apply the value of WIDGET's PROPERTY to the widget itself. 472 ;;This is in C, so don't ###utoload
473 (defun widget-apply (widget property &rest args)
474 "Apply the value of WIDGET's PROPERTY to the widget itself.
532 ARGS are passed as extra arguments to the function." 475 ARGS are passed as extra arguments to the function."
533 (apply (widget-get widget property) widget args)) 476 (apply (widget-get widget property) widget args)))
534 477
535 (defun widget-value (widget) 478 (defun widget-value (widget)
536 "Extract the current value of WIDGET." 479 "Extract the current value of WIDGET."
537 (widget-apply widget 480 (widget-apply widget
538 :value-to-external (widget-apply widget :value-get))) 481 :value-to-external (widget-apply widget :value-get)))
556 "Apply :action in WIDGET in response to EVENT." 499 "Apply :action in WIDGET in response to EVENT."
557 (if (widget-apply widget :active) 500 (if (widget-apply widget :active)
558 (widget-apply widget :action event) 501 (widget-apply widget :action event)
559 (error "Attempt to perform action on inactive widget"))) 502 (error "Attempt to perform action on inactive widget")))
560 503
504
561 ;;; Helper functions. 505 ;;; Helper functions.
562 ;; 506 ;;
563 ;; These are widget specific. 507 ;; These are widget specific.
564 508
565 ;;;###autoload 509 ;;;###autoload
595 539
596 If FUNCTION returns non-nil, the walk is cancelled. 540 If FUNCTION returns non-nil, the walk is cancelled.
597 541
598 The arguments MAPARG, and BUFFER default to nil and (current-buffer), 542 The arguments MAPARG, and BUFFER default to nil and (current-buffer),
599 respectively." 543 respectively."
600 (let ((cur (point-min)) 544 (map-extents (lambda (extent ignore)
601 (widget nil) 545 ;; If FUNCTION returns non-nil, we bail out
602 ;; (parent nil) 546 (funcall function (extent-property extent 'button) maparg))
603 (overlays (if buffer 547 nil nil nil nil nil
604 (save-excursion (set-buffer buffer) (overlay-lists)) 548 'button))
605 (overlay-lists)))) 549
606 (setq overlays (append (car overlays) (cdr overlays))) 550
607 (while (setq cur (pop overlays))
608 (setq widget (overlay-get cur 'button))
609 (if (and widget (funcall function widget maparg))
610 (setq overlays nil)))))
611
612 ;;; Glyphs. 551 ;;; Glyphs.
613 552
614 (defcustom widget-glyph-directory (concat data-directory "custom/") 553 (defcustom widget-glyph-directory (locate-data-directory "custom")
615 "Where widget glyphs are located. 554 "Where widget glyphs are located.
616 If this variable is nil, widget will try to locate the directory 555 If this variable is nil, widget will try to locate the directory
617 automatically." 556 automatically."
618 :group 'widgets 557 :group 'widgets
619 :type 'directory) 558 :type 'directory)
631 :type '(repeat (cons :format "%v" 570 :type '(repeat (cons :format "%v"
632 (symbol :tag "Image Format" unknown) 571 (symbol :tag "Image Format" unknown)
633 (repeat :tag "Suffixes" 572 (repeat :tag "Suffixes"
634 (string :format "%v"))))) 573 (string :format "%v")))))
635 574
575 (defvar widget-glyph-cache nil
576 "Cache of glyphs associated with strings (files).")
577
636 (defun widget-glyph-find (image tag) 578 (defun widget-glyph-find (image tag)
637 "Create a glyph corresponding to IMAGE with string TAG as fallback. 579 "Create a glyph corresponding to IMAGE with string TAG as fallback.
638 IMAGE should either already be a glyph, or be a file name sans 580 IMAGE can already be a glyph, or a file name sans extension (xpm,
639 extension (xpm, xbm, gif, jpg, or png) located in 581 xbm, gif, jpg, or png) located in `widget-glyph-directory', or
640 `widget-glyph-directory'." 582 in one of the data directories.
641 (cond ((not (and image 583 It can also be a valid image instantiator, in which case it will be
642 (string-match "XEmacs" emacs-version) 584 used to make the glyph, with an additional TAG string fallback.
643 widget-glyph-enable 585 If IMAGE is a list, it will be given unchanged to `make-glyph'."
644 (fboundp 'make-glyph) 586 (cond ((not (and image widget-glyph-enable))
645 (fboundp 'locate-file) 587 ;; We don't want to use glyphs.
646 image))
647 ;; We don't want or can't use glyphs.
648 nil) 588 nil)
649 ((and (fboundp 'glyphp) 589 ((glyphp image)
650 (glyphp image))
651 ;; Already a glyph. Use it. 590 ;; Already a glyph. Use it.
652 image) 591 image)
653 ((stringp image) 592 ((stringp image)
654 ;; A string. Look it up in relevant directories. 593 ;; A string. Look it up in the cache first...
655 (let* ((dirlist (list (or widget-glyph-directory 594 (or (lax-plist-get widget-glyph-cache image)
656 (concat data-directory 595 ;; ...and then in the relevant directories
657 "custom/")) 596 (let* ((dirlist (cons (or widget-glyph-directory
658 data-directory)) 597 (locate-data-directory "custom"))
659 (formats widget-image-conversion) 598 data-directory-list))
660 file) 599 (formats widget-image-conversion)
661 (while (and formats (not file)) 600 file)
662 (when (valid-image-instantiator-format-p (car (car formats))) 601 (while (and formats (not file))
663 (setq file (locate-file image dirlist 602 (when (valid-image-instantiator-format-p (caar formats))
664 (mapconcat 'identity 603 (setq file (locate-file image dirlist
665 (cdr (car formats)) 604 (mapconcat 'identity (cdar formats)
666 ":")))) 605 ":"))))
667 (unless file 606 (unless file
668 (setq formats (cdr formats)))) 607 (pop formats)))
669 (and file 608 (when file
670 ;; We create a glyph with the file as the default image 609 ;; We create a glyph with the file as the default image
671 ;; instantiator, and the TAG fallback 610 ;; instantiator, and the TAG fallback
672 (make-glyph (list (vector (car (car formats)) ':file file) 611 (let ((glyph (make-glyph `([,(caar formats) :file ,file]
673 (vector 'string ':data tag)))))) 612 [string :data ,tag]))))
613 ;; Cache the glyph
614 (setq widget-glyph-cache
615 (lax-plist-put widget-glyph-cache image glyph))
616 ;; ...and return it
617 glyph)))))
674 ((valid-instantiator-p image 'image) 618 ((valid-instantiator-p image 'image)
675 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.) 619 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.)
676 (make-glyph (list image 620 (make-glyph `(,image [string :data ,tag])))
677 (vector 'string ':data tag))))
678 ((consp image) 621 ((consp image)
679 ;; This could be virtually anything. Let `make-glyph' sort it out. 622 ;; This could be virtually anything. Let `make-glyph' sort it out.
680 (make-glyph image)) 623 (make-glyph image))
681 (t 624 (t
682 ;; Oh well. 625 ;; Oh well.
683 nil))) 626 nil)))
684 627
685 (defun widget-glyph-insert (widget tag image &optional down inactive) 628 (defun widget-glyph-insert (widget tag image &optional down inactive)
686 "In WIDGET, insert the text TAG or, if supported, IMAGE. 629 "In WIDGET, insert the text TAG or, if supported, IMAGE.
687 IMAGE should either be a glyph, an image instantiator, or an image file 630 IMAGE should either be a glyph, an image instantiator, an image file
688 name sans extension (xpm, xbm, gif, jpg, or png) located in 631 name sans extension (xpm, xbm, gif, jpg, or png) located in
689 `widget-glyph-directory'. 632 `widget-glyph-directory', or anything else allowed by
633 `widget-glyph-find'.
690 634
691 Optional arguments DOWN and INACTIVE is used instead of IMAGE when the 635 Optional arguments DOWN and INACTIVE is used instead of IMAGE when the
692 glyph is pressed or inactive, respectively. 636 glyph is pressed or inactive, respectively.
693
694 WARNING: If you call this with a glyph, and you want the user to be
695 able to invoke the glyph, make sure it is unique. If you use the
696 same glyph for multiple widgets, invoking any of the glyphs will
697 cause the last created widget to be invoked.
698 637
699 Instead of an instantiator, you can also use a list of instantiators, 638 Instead of an instantiator, you can also use a list of instantiators,
700 or whatever `make-glyph' will accept. However, in that case you must 639 or whatever `make-glyph' will accept. However, in that case you must
701 provide the fallback TAG as a part of the instantiator yourself." 640 provide the fallback TAG as a part of the instantiator yourself."
702 (let ((glyph (widget-glyph-find image tag))) 641 (let ((glyph (widget-glyph-find image tag)))
703 (if glyph 642 (if glyph
704 (widget-glyph-insert-glyph widget 643 (widget-glyph-insert-glyph widget glyph
705 glyph
706 (widget-glyph-find down tag) 644 (widget-glyph-find down tag)
707 (widget-glyph-find inactive tag)) 645 (widget-glyph-find inactive tag))
708 (insert tag)))) 646 (insert tag))))
709 647
710 (defun widget-glyph-insert-glyph (widget glyph &optional down inactive) 648 (defun widget-glyph-insert-glyph (widget glyph &optional down inactive)
711 "In WIDGET, insert GLYPH. 649 "In WIDGET, insert GLYPH.
712 If optional arguments DOWN and INACTIVE are given, they should be 650 If optional arguments DOWN and INACTIVE are given, they should be
713 glyphs used when the widget is pushed and inactive, respectively." 651 glyphs used when the widget is pushed and inactive, respectively."
714 (when widget
715 (set-glyph-property glyph 'widget widget)
716 (when down
717 (set-glyph-property down 'widget widget))
718 (when inactive
719 (set-glyph-property inactive 'widget widget)))
720 (insert "*") 652 (insert "*")
721 (let ((ext (make-extent (point) (1- (point)))) 653 (let ((extent (make-extent (point) (1- (point))))
722 (help-echo (and widget (widget-get widget :help-echo)))) 654 (help-echo (and widget (widget-get widget :help-echo))))
723 (set-extent-property ext 'invisible t) 655 (set-extent-property extent 'widget widget)
724 (set-extent-property ext 'start-open t) 656 (set-extent-property extent 'invisible t)
725 (set-extent-property ext 'end-open t) 657 (set-extent-property extent 'start-open t)
726 (set-extent-end-glyph ext glyph) 658 (set-extent-property extent 'end-open t)
659 (set-extent-end-glyph extent glyph)
727 (when help-echo 660 (when help-echo
728 (set-extent-property ext 'balloon-help help-echo) 661 (set-extent-property extent 'balloon-help help-echo)
729 (set-extent-property ext 'help-echo help-echo))) 662 (set-extent-property extent 'help-echo help-echo)))
730 (when widget 663 (when widget
731 (widget-put widget :glyph-up glyph) 664 (widget-put widget :glyph-up glyph)
732 (when down (widget-put widget :glyph-down down)) 665 (when down (widget-put widget :glyph-down down))
733 (when inactive (widget-put widget :glyph-inactive inactive)))) 666 (when inactive (widget-put widget :glyph-inactive inactive))))
734 667
668
735 ;;; Buttons. 669 ;;; Buttons.
736 670
737 (defgroup widget-button nil 671 (defgroup widget-button nil
738 "The look of various kinds of buttons." 672 "The look of various kinds of buttons."
739 :group 'widgets) 673 :group 'widgets)
746 (defcustom widget-button-suffix "" 680 (defcustom widget-button-suffix ""
747 "String used as suffix for buttons." 681 "String used as suffix for buttons."
748 :type 'string 682 :type 'string
749 :group 'widget-button) 683 :group 'widget-button)
750 684
685
751 ;;; Creating Widgets. 686 ;;; Creating Widgets.
752 687
753 ;;;###autoload 688 ;;;###autoload
754 (defun widget-create (type &rest args) 689 (defun widget-create (type &rest args)
755 "Create widget of TYPE. 690 "Create widget of TYPE.
838 ;; Convert the :value to internal format. 773 ;; Convert the :value to internal format.
839 (if (widget-member widget :value) 774 (if (widget-member widget :value)
840 (let ((value (widget-get widget :value))) 775 (let ((value (widget-get widget :value)))
841 (widget-put widget 776 (widget-put widget
842 :value (widget-apply widget :value-to-internal value)))) 777 :value (widget-apply widget :value-to-internal value))))
843 ;; Return the newly create widget. 778 ;; Return the newly created widget.
844 widget)) 779 widget))
845 780
846 (defun widget-insert (&rest args) 781 (defun widget-insert (&rest args)
847 "Call `insert' with ARGS and make the text read only." 782 "Call `insert' with ARGS and make the text read only."
848 (let ((inhibit-read-only t) 783 (let ((inhibit-read-only t)
877 and TO will be used as the widgets end points, as well as the widgets 812 and TO will be used as the widgets end points, as well as the widgets
878 button end points." 813 button end points."
879 (apply 'widget-convert-text type from to from to args)) 814 (apply 'widget-convert-text type from to from to args))
880 815
881 (defun widget-leave-text (widget) 816 (defun widget-leave-text (widget)
882 "Remove markers and overlays from WIDGET and its children." 817 "Remove markers and extents from WIDGET and its children."
883 (let ((from (widget-get widget :from)) 818 (let ((from (widget-get widget :from))
884 (to (widget-get widget :to)) 819 (to (widget-get widget :to))
885 (button (widget-get widget :button-overlay)) 820 (button (widget-get widget :button-extent))
886 (sample (widget-get widget :sample-overlay)) 821 (sample (widget-get widget :sample-extent))
887 (doc (widget-get widget :doc-overlay)) 822 (doc (widget-get widget :doc-extent))
888 (field (widget-get widget :field-overlay)) 823 (field (widget-get widget :field-extent))
889 (children (widget-get widget :children))) 824 (children (widget-get widget :children)))
890 (set-marker from nil) 825 (set-marker from nil)
891 (set-marker to nil) 826 (set-marker to nil)
827 ;; Maybe we should delete the extents here? As this code doesn't
828 ;; remove them from widget structures, maybe it's safer to just
829 ;; detach them. That's what `delete-overlay' did.
892 (when button 830 (when button
893 (delete-overlay button)) 831 (detach-extent button))
894 (when sample 832 (when sample
895 (delete-overlay sample)) 833 (detach-extent sample))
896 (when doc 834 (when doc
897 (delete-overlay doc)) 835 (detach-extent doc))
898 (when field 836 (when field
899 (delete-overlay field)) 837 (detach-extent field))
900 (mapcar 'widget-leave-text children))) 838 (mapc 'widget-leave-text children)))
901 839
840
902 ;;; Keymap and Commands. 841 ;;; Keymap and Commands.
903 842
904 (defvar widget-keymap nil 843 (defvar widget-keymap nil
905 "Keymap containing useful binding for buffers containing widgets. 844 "Keymap containing useful binding for buffers containing widgets.
906 Recommended as a parent keymap for modes using widgets.") 845 Recommended as a parent keymap for modes using widgets.")
907 846
908 (unless widget-keymap 847 (unless widget-keymap
909 (setq widget-keymap (make-sparse-keymap)) 848 (setq widget-keymap (make-sparse-keymap))
910 (define-key widget-keymap "\t" 'widget-forward) 849 (define-key widget-keymap [tab] 'widget-forward)
911 (define-key widget-keymap [(shift tab)] 'widget-backward) 850 (define-key widget-keymap [(shift tab)] 'widget-backward)
851 (define-key widget-keymap [(meta tab)] 'widget-backward)
912 (define-key widget-keymap [backtab] 'widget-backward) 852 (define-key widget-keymap [backtab] 'widget-backward)
913 (if (string-match "XEmacs" emacs-version) 853 ;;Glyph support.
914 (progn 854 (define-key widget-keymap [button1] 'widget-button1-click)
915 ;;Glyph support. 855 (define-key widget-keymap [button2] 'widget-button-click)
916 (define-key widget-keymap [button1] 'widget-button1-click)
917 (define-key widget-keymap [button2] 'widget-button-click))
918 (define-key widget-keymap [down-mouse-2] 'widget-button-click))
919 (define-key widget-keymap "\C-m" 'widget-button-press)) 856 (define-key widget-keymap "\C-m" 'widget-button-press))
920 857
921 (defvar widget-global-map global-map 858 (defvar widget-global-map global-map
922 "Keymap used for events the widget does not handle themselves.") 859 "Keymap used for events the widget does not handle themselves.")
923 (make-variable-buffer-local 'widget-global-map) 860 (make-variable-buffer-local 'widget-global-map)
924 861
925 (defvar widget-field-keymap nil 862 (defvar widget-field-keymap nil
926 "Keymap used inside an editable field.") 863 "Keymap used inside an editable field.")
927 864
928 (unless widget-field-keymap 865 (unless widget-field-keymap
929 (setq widget-field-keymap (copy-keymap widget-keymap)) 866 (setq widget-field-keymap (make-sparse-keymap))
930 (unless (string-match "XEmacs" (emacs-version)) 867 (set-keymap-parents widget-field-keymap global-map)
931 (define-key widget-field-keymap [menu-bar] 'nil))
932 (define-key widget-field-keymap "\C-k" 'widget-kill-line) 868 (define-key widget-field-keymap "\C-k" 'widget-kill-line)
933 (define-key widget-field-keymap "\M-\t" 'widget-complete) 869 (define-key widget-field-keymap [(meta tab)] 'widget-complete)
870 (define-key widget-field-keymap [tab] 'widget-forward)
871 (define-key widget-field-keymap [(shift tab)] 'widget-backward)
934 (define-key widget-field-keymap "\C-m" 'widget-field-activate) 872 (define-key widget-field-keymap "\C-m" 'widget-field-activate)
935 (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line) 873 (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line)
936 (define-key widget-field-keymap "\C-e" 'widget-end-of-line) 874 (define-key widget-field-keymap "\C-e" 'widget-end-of-line)
937 (set-keymap-parent widget-field-keymap global-map)) 875 (define-key widget-field-keymap "\C-t" 'widget-transpose-chars))
938 876
939 (defvar widget-text-keymap nil 877 (defvar widget-text-keymap nil
940 "Keymap used inside a text field.") 878 "Keymap used inside a text field.")
941 879
942 (unless widget-text-keymap 880 (unless widget-text-keymap
943 (setq widget-text-keymap (copy-keymap widget-keymap)) 881 (setq widget-text-keymap (make-sparse-keymap))
944 (unless (string-match "XEmacs" (emacs-version)) 882 (set-keymap-parents widget-field-keymap global-map)
945 (define-key widget-text-keymap [menu-bar] 'nil))
946 (define-key widget-text-keymap "\C-a" 'widget-beginning-of-line) 883 (define-key widget-text-keymap "\C-a" 'widget-beginning-of-line)
947 (define-key widget-text-keymap "\C-e" 'widget-end-of-line) 884 (define-key widget-text-keymap "\C-e" 'widget-end-of-line)
948 (set-keymap-parent widget-text-keymap global-map)) 885 (define-key widget-text-keymap "\C-t" 'widget-transpose-chars))
886
949 887
950 (defun widget-field-activate (pos &optional event) 888 (defun widget-field-activate (pos &optional event)
951 "Invoke the ediable field at point." 889 "Invoke the ediable field at point."
952 (interactive "@d") 890 (interactive "@d")
953 (let ((field (get-char-property pos 'field))) 891 (let ((field (get-char-property pos 'field)))
965 :group 'widget-faces) 903 :group 'widget-faces)
966 904
967 (defun widget-button-click (event) 905 (defun widget-button-click (event)
968 "Invoke button below mouse pointer." 906 "Invoke button below mouse pointer."
969 (interactive "@e") 907 (interactive "@e")
970 (cond ((and (fboundp 'event-glyph) 908 (cond ((event-glyph event)
971 (event-glyph event))
972 (widget-glyph-click event)) 909 (widget-glyph-click event))
973 ((widget-event-point event) 910 ((widget-event-point event)
974 (let* ((pos (widget-event-point event)) 911 (let* ((pos (widget-event-point event))
975 (button (get-char-property pos 'button))) 912 (button (get-char-property pos 'button)))
976 (if button 913 (if button
977 (let* ((overlay (widget-get button :button-overlay)) 914 (let* ((extent (widget-get button :button-extent))
978 (face (overlay-get overlay 'face)) 915 (face (extent-property extent 'face))
979 (mouse-face (overlay-get overlay 'mouse-face))) 916 (mouse-face (extent-property extent 'mouse-face)))
980 (unwind-protect 917 (unwind-protect
981 (let ((track-mouse t)) 918 (progn
982 (overlay-put overlay 919 (set-extent-property extent 'face
983 'face 'widget-button-pressed-face) 920 'widget-button-pressed-face)
984 (overlay-put overlay 921 (set-extent-property extent 'mouse-face
985 'mouse-face 'widget-button-pressed-face) 922 'widget-button-pressed-face)
986 (unless (widget-apply button :mouse-down-action event) 923 (unless (widget-apply button :mouse-down-action event)
987 (while (not (button-release-event-p event)) 924 (while (not (button-release-event-p event))
988 (setq event (widget-read-event) 925 (setq event (next-event)
989 pos (widget-event-point event)) 926 pos (widget-event-point event))
990 (if (and pos 927 (if (and pos
991 (eq (get-char-property pos 'button) 928 (eq (get-char-property pos 'button)
992 button)) 929 button))
993 (progn 930 (progn
994 (overlay-put overlay 931 (set-extent-property extent 'face
995 'face 932 'widget-button-pressed-face)
996 'widget-button-pressed-face) 933 (set-extent-property extent 'mouse-face
997 (overlay-put overlay 934 'widget-button-pressed-face))
998 'mouse-face 935 (set-extent-property extent 'face face)
999 'widget-button-pressed-face)) 936 (set-extent-property extent
1000 (overlay-put overlay 'face face) 937 'mouse-face mouse-face))))
1001 (overlay-put overlay 'mouse-face mouse-face))))
1002 (when (and pos 938 (when (and pos
1003 (eq (get-char-property pos 'button) button)) 939 (eq (get-char-property pos 'button) button))
1004 (widget-apply-action button event))) 940 (widget-apply-action button event)))
1005 (overlay-put overlay 'face face) 941 (set-extent-property extent 'face face)
1006 (overlay-put overlay 'mouse-face mouse-face))) 942 (set-extent-property extent 'mouse-face mouse-face)))
1007 (let ((up t) 943 (let ((up t)
1008 command) 944 command)
1009 ;; Find the global command to run, and check whether it 945 ;; Find the global command to run, and check whether it
1010 ;; is bound to an up event. 946 ;; is bound to an up event.
1011 (cond ((setq command ;down event 947 (cond ((setq command ;down event
1012 (lookup-key widget-global-map [ button2 ])) 948 (lookup-key widget-global-map [button2]))
1013 (setq up nil))
1014 ((setq command ;down event
1015 (lookup-key widget-global-map [ down-mouse-2 ]))
1016 (setq up nil)) 949 (setq up nil))
1017 ((setq command ;up event 950 ((setq command ;up event
1018 (lookup-key widget-global-map [ button2up ]))) 951 (lookup-key widget-global-map [button2up]))))
1019 ((setq command ;up event
1020 (lookup-key widget-global-map [ mouse-2]))))
1021 (when up 952 (when up
1022 ;; Don't execute up events twice. 953 ;; Don't execute up events twice.
1023 (while (not (button-release-event-p event)) 954 (while (not (button-release-event-p event))
1024 (setq event (widget-read-event)))) 955 (setq event (next-event))))
1025 (when command 956 (when command
1026 (call-interactively command)))))) 957 (call-interactively command))))))
1027 (t 958 (t
1028 (message "You clicked somewhere weird.")))) 959 (message "You clicked somewhere weird."))))
1029 960
1030 (defun widget-button1-click (event) 961 (defun widget-button1-click (event)
1031 "Invoke glyph below mouse pointer." 962 "Invoke glyph below mouse pointer."
1032 (interactive "@e") 963 (interactive "@e")
1033 (if (and (fboundp 'event-glyph) 964 (if (event-glyph event)
1034 (event-glyph event))
1035 (widget-glyph-click event) 965 (widget-glyph-click event)
1036 (call-interactively (lookup-key widget-global-map (this-command-keys))))) 966 (let ((command (lookup-key widget-global-map (this-command-keys))))
967 (and (commandp command)
968 (call-interactively command)))))
1037 969
1038 (defun widget-glyph-click (event) 970 (defun widget-glyph-click (event)
1039 "Handle click on a glyph." 971 "Handle click on a glyph."
1040 (let* ((glyph (event-glyph event)) 972 (let* ((glyph (event-glyph event))
1041 (widget (glyph-property glyph 'widget))
1042 (extent (event-glyph-extent event)) 973 (extent (event-glyph-extent event))
974 (widget (extent-property extent 'widget))
1043 (down-glyph (or (and widget (widget-get widget :glyph-down)) glyph)) 975 (down-glyph (or (and widget (widget-get widget :glyph-down)) glyph))
1044 (up-glyph (or (and widget (widget-get widget :glyph-up)) glyph)) 976 (up-glyph (or (and widget (widget-get widget :glyph-up)) glyph))
1045 (last event)) 977 (last event))
1046 ;; Wait for the release. 978 ;; Wait for the release.
1047 (while (not (button-release-event-p last)) 979 (while (not (button-release-event-p last))
1052 ;; Release glyph. 984 ;; Release glyph.
1053 (when down-glyph 985 (when down-glyph
1054 (set-extent-property extent 'end-glyph up-glyph)) 986 (set-extent-property extent 'end-glyph up-glyph))
1055 ;; Apply widget action. 987 ;; Apply widget action.
1056 (when (eq extent (event-glyph-extent last)) 988 (when (eq extent (event-glyph-extent last))
1057 (let ((widget (glyph-property (event-glyph event) 'widget))) 989 (let ((widget (extent-property (event-glyph-extent event) 'widget)))
1058 (cond ((null widget) 990 (cond ((null widget)
1059 (message "You clicked on a glyph.")) 991 (message "You clicked on a glyph."))
1060 ((not (widget-apply widget :active)) 992 ((not (widget-apply widget :active))
1061 (message "This glyph is inactive.")) 993 (message "This glyph is inactive."))
1062 (t 994 (t
1075 (defun widget-tabable-at (&optional pos) 1007 (defun widget-tabable-at (&optional pos)
1076 "Return the tabable widget at POS, or nil. 1008 "Return the tabable widget at POS, or nil.
1077 POS defaults to the value of (point)." 1009 POS defaults to the value of (point)."
1078 (unless pos 1010 (unless pos
1079 (setq pos (point))) 1011 (setq pos (point)))
1080 (let ((widget (or (get-char-property (point) 'button) 1012 (let ((widget (widget-at pos)))
1081 (get-char-property (point) 'field))))
1082 (if widget 1013 (if widget
1083 (let ((order (widget-get widget :tab-order))) 1014 (let ((order (widget-get widget :tab-order)))
1084 (if order 1015 (if order
1085 (if (>= order 0) 1016 (if (>= order 0)
1086 widget 1017 widget
1087 nil) 1018 nil)
1088 widget)) 1019 widget))
1089 nil))) 1020 nil)))
1090 1021
1091 (defcustom widget-use-overlay-change (string-match "XEmacs" emacs-version) 1022 ;; Return the button or field extent at point.
1092 "If non-nil, use overlay change functions to tab around in the buffer. 1023 (defun widget-button-or-field-extent (pos)
1093 This is much faster, but doesn't work reliably on Emacs 19.34." 1024 (or (and (get-char-property pos 'button)
1094 :type 'boolean 1025 (widget-get (get-char-property pos 'button)
1095 :group 'widgets) 1026 :button-extent))
1027 (and (get-char-property pos 'field)
1028 (widget-get (get-char-property pos 'field)
1029 :field-extent))))
1030
1031 (defun widget-next-button-or-field (pos)
1032 "Find the next button, or field, and return its start position.
1033 If none is found, return (point-max).
1034 Internal function, don't use it outside `wid-edit'."
1035 (let* ((at-point (widget-button-or-field-extent pos))
1036 (extent (map-extents
1037 (lambda (ext ignore)
1038 (if (or (extent-property ext 'button)
1039 (extent-property ext 'field))
1040 ext
1041 nil))
1042 nil (if at-point (extent-end-position at-point) pos) nil)))
1043 (if extent
1044 (extent-start-position extent)
1045 (point-max))))
1046
1047 (defun widget-previous-button-or-field (pos)
1048 "Find the previous button, or field, and return its start position.
1049 If none is found, return (point-min).
1050 Internal function, don't use it outside `wid-edit'."
1051 (let* ((at-point (widget-button-or-field-extent pos))
1052 previous-extent)
1053 (map-extents
1054 (lambda (ext ignore)
1055 (when (or (extent-property ext 'button)
1056 (extent-property ext 'field))
1057 (if (eq ext at-point)
1058 previous-extent
1059 (setq previous-extent ext)
1060 nil)))
1061 nil nil pos)
1062 (if previous-extent
1063 (extent-start-position previous-extent)
1064 (point-min))))
1096 1065
1097 (defun widget-move (arg) 1066 (defun widget-move (arg)
1098 "Move point to the ARG next field or button. 1067 "Move point to the ARG next field or button.
1099 ARG may be negative to move backward." 1068 ARG may be negative to move backward."
1100 (or (bobp) (> arg 0) (backward-char))
1101 (let ((pos (point)) 1069 (let ((pos (point))
1102 (number arg) 1070 (number arg)
1103 (old (widget-tabable-at))) 1071 (old (widget-tabable-at)))
1104 ;; Forward. 1072 ;; Forward.
1105 (while (> arg 0) 1073 (while (> arg 0)
1106 (cond ((eobp) 1074 (goto-char (if (eobp)
1107 (goto-char (point-min))) 1075 (point-min)
1108 (widget-use-overlay-change 1076 (widget-next-button-or-field (point))))
1109 (goto-char (next-overlay-change (point))))
1110 (t
1111 (forward-char 1)))
1112 (and (eq pos (point)) 1077 (and (eq pos (point))
1113 (eq arg number) 1078 (eq arg number)
1114 (error "No buttons or fields found")) 1079 (error "No buttons or fields found"))
1115 (let ((new (widget-tabable-at))) 1080 (let ((new (widget-tabable-at)))
1116 (when new 1081 (when new
1117 (unless (eq new old) 1082 (unless (eq new old)
1118 (setq arg (1- arg)) 1083 (setq arg (1- arg))
1119 (setq old new))))) 1084 (setq old new)))))
1120 ;; Backward. 1085 ;; Backward.
1121 (while (< arg 0) 1086 (while (< arg 0)
1122 (cond ((bobp) 1087 (goto-char (if (bobp)
1123 (goto-char (point-max))) 1088 (point-max)
1124 (widget-use-overlay-change 1089 (widget-previous-button-or-field (point))))
1125 (goto-char (previous-overlay-change (point))))
1126 (t
1127 (backward-char 1)))
1128 (and (eq pos (point)) 1090 (and (eq pos (point))
1129 (eq arg number) 1091 (eq arg number)
1130 (error "No buttons or fields found")) 1092 (error "No buttons or fields found"))
1131 (let ((new (widget-tabable-at))) 1093 (let ((new (widget-tabable-at)))
1132 (when new 1094 (when new
1133 (unless (eq new old) 1095 (unless (eq new old)
1134 (setq arg (1+ arg)))))) 1096 (incf arg)))))
1135 (let ((new (widget-tabable-at))) 1097 (let ((new (widget-tabable-at)))
1136 (while (eq (widget-tabable-at) new) 1098 (goto-char (extent-start-position (or (widget-get new :button-extent)
1137 (backward-char))) 1099 (widget-get new :field-extent))))))
1138 (forward-char))
1139 (widget-echo-help (point)) 1100 (widget-echo-help (point))
1140 (run-hooks 'widget-move-hook)) 1101 (run-hooks 'widget-move-hook))
1141 1102
1142 (defun widget-forward (arg) 1103 (defun widget-forward (arg)
1143 "Move point to the next field or button. 1104 "Move point to the next field or button.
1153 (run-hooks 'widget-backward-hook) 1114 (run-hooks 'widget-backward-hook)
1154 (widget-move (- arg))) 1115 (widget-move (- arg)))
1155 1116
1156 (defun widget-beginning-of-line () 1117 (defun widget-beginning-of-line ()
1157 "Go to beginning of field or beginning of line, whichever is first." 1118 "Go to beginning of field or beginning of line, whichever is first."
1158 (interactive) 1119 (interactive "_")
1159 (let* ((field (widget-field-find (point))) 1120 (let* ((field (widget-field-find (point)))
1160 (start (and field (widget-field-start field)))) 1121 (start (and field (widget-field-start field))))
1161 (if (and start (not (eq start (point)))) 1122 (if (and start (not (eq start (point))))
1162 (goto-char start) 1123 (goto-char start)
1163 (call-interactively 'beginning-of-line))) 1124 (call-interactively 'beginning-of-line))))
1164 ;; XEmacs: preserve the region
1165 (setq zmacs-region-stays t))
1166 1125
1167 (defun widget-end-of-line () 1126 (defun widget-end-of-line ()
1168 "Go to end of field or end of line, whichever is first." 1127 "Go to end of field or end of line, whichever is first."
1169 (interactive) 1128 (interactive "_")
1170 (let* ((field (widget-field-find (point))) 1129 (let* ((field (widget-field-find (point)))
1171 (end (and field (widget-field-end field)))) 1130 (end (and field (widget-field-end field))))
1172 (if (and end (not (eq end (point)))) 1131 (if (and end (not (eq end (point))))
1173 (goto-char end) 1132 (goto-char end)
1174 (call-interactively 'end-of-line))) 1133 (call-interactively 'end-of-line))))
1175 ;; XEmacs: preserve the region
1176 (setq zmacs-region-stays t))
1177 1134
1178 (defun widget-kill-line () 1135 (defun widget-kill-line ()
1179 "Kill to end of field or end of line, whichever is first." 1136 "Kill to end of field or end of line, whichever is first."
1180 (interactive) 1137 (interactive)
1181 (let* ((field (widget-field-find (point))) 1138 (let* ((field (widget-field-find (point)))
1183 (end (and field (widget-field-end field)))) 1140 (end (and field (widget-field-end field))))
1184 (if (and field (> newline end)) 1141 (if (and field (> newline end))
1185 (kill-region (point) end) 1142 (kill-region (point) end)
1186 (call-interactively 'kill-line)))) 1143 (call-interactively 'kill-line))))
1187 1144
1145 (defun widget-transpose-chars (arg)
1146 "Like `transpose-chars', but works correctly at end of widget."
1147 (interactive "*P")
1148 (let* ((field (widget-field-find (point)))
1149 (start (and field (widget-field-start field)))
1150 (end (and field (widget-field-end field)))
1151 (last-non-space (and start end
1152 (save-excursion
1153 (goto-char end)
1154 (skip-chars-backward " \t\n" start)
1155 (point)))))
1156 (if (and last-non-space
1157 (= last-non-space (1+ start)))
1158 ;; 1-character field
1159 nil
1160 (when (and (null arg)
1161 (= last-non-space (point)))
1162 (forward-char -1))
1163 (transpose-chars arg))))
1164
1188 (defcustom widget-complete-field (lookup-key global-map "\M-\t") 1165 (defcustom widget-complete-field (lookup-key global-map "\M-\t")
1189 "Default function to call for completion inside fields." 1166 "Default function to call for completion inside fields."
1190 :options '(ispell-complete-word complete-tag lisp-complete-symbol) 1167 :options '(ispell-complete-word complete-tag lisp-complete-symbol)
1191 :type 'function 1168 :type 'function
1192 :group 'widgets) 1169 :group 'widgets)
1198 (let ((field (widget-field-find (point)))) 1175 (let ((field (widget-field-find (point))))
1199 (if field 1176 (if field
1200 (widget-apply field :complete) 1177 (widget-apply field :complete)
1201 (error "Not in an editable field")))) 1178 (error "Not in an editable field"))))
1202 1179
1180
1203 ;;; Setting up the buffer. 1181 ;;; Setting up the buffer.
1204 1182
1205 (defvar widget-field-new nil) 1183 (defvar widget-field-new nil)
1206 ;; List of all newly created editable fields in the buffer. 1184 ;; List of all newly created editable fields in the buffer.
1207 (make-variable-buffer-local 'widget-field-new) 1185 (make-variable-buffer-local 'widget-field-new)
1218 field) 1196 field)
1219 (while widget-field-new 1197 (while widget-field-new
1220 (setq field (car widget-field-new) 1198 (setq field (car widget-field-new)
1221 widget-field-new (cdr widget-field-new) 1199 widget-field-new (cdr widget-field-new)
1222 widget-field-list (cons field widget-field-list)) 1200 widget-field-list (cons field widget-field-list))
1223 (let ((from (car (widget-get field :field-overlay))) 1201 (let ((extent (widget-get field :field-extent)))
1224 (to (cdr (widget-get field :field-overlay)))) 1202 (widget-specify-field field
1225 (widget-specify-field field 1203 (extent-start-position extent)
1226 (marker-position from) (marker-position to)) 1204 (extent-end-position extent))
1227 (set-marker from nil) 1205 (delete-extent extent))))
1228 (set-marker to nil))))
1229 (widget-clear-undo) 1206 (widget-clear-undo)
1230 (widget-add-change)) 1207 (widget-add-change))
1231 1208
1232 (defvar widget-field-last nil) 1209 (defvar widget-field-last nil)
1233 ;; Last field containing point. 1210 ;; Last field containing point.
1237 ;; The widget data before the change. 1214 ;; The widget data before the change.
1238 (make-variable-buffer-local 'widget-field-was) 1215 (make-variable-buffer-local 'widget-field-was)
1239 1216
1240 (defun widget-field-buffer (widget) 1217 (defun widget-field-buffer (widget)
1241 "Return the start of WIDGET's editing field." 1218 "Return the start of WIDGET's editing field."
1242 (let ((overlay (widget-get widget :field-overlay))) 1219 (let ((extent (widget-get widget :field-extent)))
1243 (and overlay (overlay-buffer overlay)))) 1220 (and extent (extent-object extent))))
1244 1221
1245 (defun widget-field-start (widget) 1222 (defun widget-field-start (widget)
1246 "Return the start of WIDGET's editing field." 1223 "Return the start of WIDGET's editing field."
1247 (let ((overlay (widget-get widget :field-overlay))) 1224 (let ((extent (widget-get widget :field-extent)))
1248 (and overlay (overlay-start overlay)))) 1225 (and extent (extent-start-position extent))))
1249 1226
1250 (defun widget-field-end (widget) 1227 (defun widget-field-end (widget)
1251 "Return the end of WIDGET's editing field." 1228 "Return the end of WIDGET's editing field."
1252 (let ((overlay (widget-get widget :field-overlay))) 1229 (let ((extent (widget-get widget :field-extent)))
1253 ;; Don't subtract one if local-map works at the end of the overlay. 1230 ;; Don't subtract one if local-map works at the end of the extent.
1254 (and overlay (if (or widget-field-add-space 1231 (and extent (if (or widget-field-add-space
1255 (null (widget-get widget :size))) 1232 (null (widget-get widget :size)))
1256 (1- (overlay-end overlay)) 1233 (1- (extent-end-position extent))
1257 (overlay-end overlay))))) 1234 (extent-end-position extent)))))
1258 1235
1259 (defun widget-field-find (pos) 1236 (defun widget-field-find (pos)
1260 "Return the field at POS. 1237 "Return the field at POS.
1261 Unlike (get-char-property POS 'field) this, works with empty fields too." 1238 Unlike (get-char-property POS 'field) this, works with empty fields too."
1262 (let ((fields widget-field-list) 1239 (let ((fields widget-field-list)
1338 (while (< begin end) 1315 (while (< begin end)
1339 (let ((old (char-after begin))) 1316 (let ((old (char-after begin)))
1340 (unless (eq old secret) 1317 (unless (eq old secret)
1341 (subst-char-in-region begin (1+ begin) old secret) 1318 (subst-char-in-region begin (1+ begin) old secret)
1342 (put-text-property begin (1+ begin) 'secret old)) 1319 (put-text-property begin (1+ begin) 'secret old))
1343 (setq begin (1+ begin))))))) 1320 (incf begin))))))
1344 (widget-apply field :notify field))) 1321 (widget-apply field :notify field)))
1345 (error (debug "After Change")))) 1322 (error (debug "After Change"))))
1346 1323
1324
1347 ;;; Widget Functions 1325 ;;; Widget Functions
1348 ;; 1326 ;;
1349 ;; These functions are used in the definition of multiple widgets. 1327 ;; These functions are used in the definition of multiple widgets.
1350 1328
1351 (defun widget-parent-action (widget &optional event) 1329 (defun widget-parent-action (widget &optional event)
1353 Optional EVENT is the event that triggered the action." 1331 Optional EVENT is the event that triggered the action."
1354 (widget-apply (widget-get widget :parent) :action event)) 1332 (widget-apply (widget-get widget :parent) :action event))
1355 1333
1356 (defun widget-children-value-delete (widget) 1334 (defun widget-children-value-delete (widget)
1357 "Delete all :children and :buttons in WIDGET." 1335 "Delete all :children and :buttons in WIDGET."
1358 (mapcar 'widget-delete (widget-get widget :children)) 1336 (mapc 'widget-delete (widget-get widget :children))
1359 (widget-put widget :children nil) 1337 (widget-put widget :children nil)
1360 (mapcar 'widget-delete (widget-get widget :buttons)) 1338 (mapc 'widget-delete (widget-get widget :buttons))
1361 (widget-put widget :buttons nil)) 1339 (widget-put widget :buttons nil))
1362 1340
1363 (defun widget-children-validate (widget) 1341 (defun widget-children-validate (widget)
1364 "All the :children must be valid." 1342 "All the :children must be valid."
1365 (let ((children (widget-get widget :children)) 1343 (let ((children (widget-get widget :children))
1451 ((eq escape ?\}) 1429 ((eq escape ?\})
1452 (setq sample-end (point))) 1430 (setq sample-end (point)))
1453 ((eq escape ?n) 1431 ((eq escape ?n)
1454 (when (widget-get widget :indent) 1432 (when (widget-get widget :indent)
1455 (insert "\n") 1433 (insert "\n")
1456 (insert-char ? (widget-get widget :indent)))) 1434 (insert-char ?\ (widget-get widget :indent))))
1457 ((eq escape ?t) 1435 ((eq escape ?t)
1458 (let ((glyph (widget-get widget :tag-glyph)) 1436 (let ((glyph (widget-get widget :tag-glyph))
1459 (tag (widget-get widget :tag))) 1437 (tag (widget-get widget :tag)))
1460 (cond (glyph 1438 (cond (glyph
1461 (widget-glyph-insert widget (or tag "image") glyph)) 1439 (widget-glyph-insert widget (or tag "image") glyph))
1475 (setq doc-end (point))))) 1453 (setq doc-end (point)))))
1476 ((eq escape ?v) 1454 ((eq escape ?v)
1477 (if (and button-begin (not button-end)) 1455 (if (and button-begin (not button-end))
1478 (widget-apply widget :value-create) 1456 (widget-apply widget :value-create)
1479 (setq value-pos (point)))) 1457 (setq value-pos (point))))
1480 (t 1458 (t
1481 (widget-apply widget :format-handler escape))))) 1459 (widget-apply widget :format-handler escape)))))
1482 ;; Specify button, sample, and doc, and insert value. 1460 ;; Specify button, sample, and doc, and insert value.
1483 (and button-begin button-end 1461 (and button-begin button-end
1484 (widget-specify-button widget button-begin button-end)) 1462 (widget-specify-button widget button-begin button-end))
1485 (and sample-begin sample-end 1463 (and sample-begin sample-end
1551 1529
1552 (defun widget-default-delete (widget) 1530 (defun widget-default-delete (widget)
1553 ;; Remove widget from the buffer. 1531 ;; Remove widget from the buffer.
1554 (let ((from (widget-get widget :from)) 1532 (let ((from (widget-get widget :from))
1555 (to (widget-get widget :to)) 1533 (to (widget-get widget :to))
1556 (inactive-overlay (widget-get widget :inactive)) 1534 (inactive-extent (widget-get widget :inactive))
1557 (button-overlay (widget-get widget :button-overlay)) 1535 (button-extent (widget-get widget :button-extent))
1558 (sample-overlay (widget-get widget :sample-overlay)) 1536 (sample-extent (widget-get widget :sample-extent))
1559 (doc-overlay (widget-get widget :doc-overlay)) 1537 (doc-extent (widget-get widget :doc-extent))
1560 before-change-functions 1538 before-change-functions
1561 after-change-functions 1539 after-change-functions
1562 (inhibit-read-only t)) 1540 (inhibit-read-only t))
1563 (widget-apply widget :value-delete) 1541 (widget-apply widget :value-delete)
1564 (when inactive-overlay 1542 (when inactive-extent
1565 (delete-overlay inactive-overlay)) 1543 (detach-extent inactive-extent))
1566 (when button-overlay 1544 (when button-extent
1567 (delete-overlay button-overlay)) 1545 (detach-extent button-extent))
1568 (when sample-overlay 1546 (when sample-extent
1569 (delete-overlay sample-overlay)) 1547 (detach-extent sample-extent))
1570 (when doc-overlay 1548 (when doc-extent
1571 (delete-overlay doc-overlay)) 1549 (detach-extent doc-extent))
1572 (when (< from to) 1550 (when (< from to)
1573 ;; Kludge: this doesn't need to be true for empty formats. 1551 ;; Kludge: this doesn't need to be true for empty formats.
1574 (delete-region from to)) 1552 (delete-region from to))
1575 (set-marker from nil) 1553 (set-marker from nil)
1576 (set-marker to nil)) 1554 (set-marker to nil))
1688 ;; Just notify itself. 1666 ;; Just notify itself.
1689 (widget-apply widget :notify widget event)) 1667 (widget-apply widget :notify widget event))
1690 1668
1691 ;;; The `push-button' Widget. 1669 ;;; The `push-button' Widget.
1692 1670
1693 (defcustom widget-push-button-gui t 1671 (defcustom widget-push-button-gui widget-glyph-enable
1694 "If non nil, use GUI push buttons when available." 1672 "If non nil, use GUI push buttons when available."
1695 :group 'widgets 1673 :group 'widgets
1696 :type 'boolean) 1674 :type 'boolean)
1697 1675
1698 ;; Cache already created GUI objects. 1676 ;; Cache already created GUI objects.
1720 (let* ((tag (or (widget-get widget :tag) 1698 (let* ((tag (or (widget-get widget :tag)
1721 (widget-get widget :value))) 1699 (widget-get widget :value)))
1722 (tag-glyph (widget-get widget :tag-glyph)) 1700 (tag-glyph (widget-get widget :tag-glyph))
1723 (text (concat widget-push-button-prefix 1701 (text (concat widget-push-button-prefix
1724 tag widget-push-button-suffix)) 1702 tag widget-push-button-suffix))
1725 (gui (cdr (assoc tag widget-push-button-cache)))) 1703 (gui-glyphs (lax-plist-get widget-push-button-cache tag)))
1726 (cond (tag-glyph 1704 (cond (tag-glyph
1727 (widget-glyph-insert widget text tag-glyph)) 1705 (widget-glyph-insert widget text tag-glyph))
1728 ((and (fboundp 'make-gui-button) 1706 ;; We must check for console-on-window-system-p here,
1729 (fboundp 'make-glyph) 1707 ;; because GUI will not work otherwise (it needs RGB
1730 widget-push-button-gui 1708 ;; components for colors, and they are not known on TTYs).
1731 (fboundp 'device-on-window-system-p) 1709 ((and widget-push-button-gui
1732 (device-on-window-system-p) 1710 (console-on-window-system-p))
1733 (string-match "XEmacs" emacs-version)) 1711 (unless gui-glyphs
1734 (unless gui 1712 (let ((gui (make-gui-button tag 'widget-gui-action widget)))
1735 (setq gui (make-gui-button tag 'widget-gui-action widget)) 1713 (setq
1736 (push (cons tag gui) widget-push-button-cache)) 1714 gui-glyphs
1737 (widget-glyph-insert-glyph widget 1715 (list
1738 (make-glyph 1716 (make-glyph `(,(nth 0 (aref gui 1)) [string :data ,text]))
1739 (list (nth 0 (aref gui 1)) 1717 (make-glyph `(,(nth 1 (aref gui 1)) [string :data ,text]))
1740 (vector 'string ':data text))) 1718 (make-glyph `(,(nth 2 (aref gui 1)) [string :data ,text]))))
1741 (make-glyph 1719 (setq widget-push-button-cache
1742 (list (nth 1 (aref gui 1)) 1720 (lax-plist-put widget-push-button-cache tag gui-glyphs))))
1743 (vector 'string ':data text))) 1721 (widget-glyph-insert-glyph
1744 (make-glyph 1722 widget (nth 0 gui-glyphs) (nth 1 gui-glyphs) (nth 2 gui-glyphs)))
1745 (list (nth 2 (aref gui 1))
1746 (vector 'string ':data text)))))
1747 (t 1723 (t
1748 (insert text))))) 1724 (insert text)))))
1749 1725
1750 (defun widget-gui-action (widget) 1726 (defun widget-gui-action (widget)
1751 "Apply :action for WIDGET." 1727 "Apply :action for WIDGET."
1772 1748
1773 ;;; The `info-link' Widget. 1749 ;;; The `info-link' Widget.
1774 1750
1775 (define-widget 'info-link 'link 1751 (define-widget 'info-link 'link
1776 "A link to an info file." 1752 "A link to an info file."
1753 :help-echo 'widget-info-link-help-echo
1777 :action 'widget-info-link-action) 1754 :action 'widget-info-link-action)
1755
1756 (defun widget-info-link-help-echo (widget)
1757 (concat "Read the manual entry `" (widget-value widget) "'"))
1778 1758
1779 (defun widget-info-link-action (widget &optional event) 1759 (defun widget-info-link-action (widget &optional event)
1780 "Open the info node specified by WIDGET." 1760 "Open the info node specified by WIDGET."
1781 (Info-goto-node (widget-value widget))) 1761 (Info-goto-node (widget-value widget)))
1782 1762
1783 ;;; The `url-link' Widget. 1763 ;;; The `url-link' Widget.
1784 1764
1785 (define-widget 'url-link 'link 1765 (define-widget 'url-link 'link
1786 "A link to an www page." 1766 "A link to an www page."
1767 :help-echo 'widget-url-link-help-echo
1787 :action 'widget-url-link-action) 1768 :action 'widget-url-link-action)
1769
1770 (defun widget-url-link-help-echo (widget)
1771 (concat "Go to <URL:" (widget-value widget) ">"))
1788 1772
1789 (defun widget-url-link-action (widget &optional event) 1773 (defun widget-url-link-action (widget &optional event)
1790 "Open the url specified by WIDGET." 1774 "Open the url specified by WIDGET."
1791 (require 'browse-url) 1775 (require 'browse-url)
1792 (funcall browse-url-browser-function (widget-value widget))) 1776 (funcall browse-url-browser-function (widget-value widget)))
1803 1787
1804 ;;; The `emacs-library-link' Widget. 1788 ;;; The `emacs-library-link' Widget.
1805 1789
1806 (define-widget 'emacs-library-link 'link 1790 (define-widget 'emacs-library-link 'link
1807 "A link to an Emacs Lisp library file." 1791 "A link to an Emacs Lisp library file."
1792 :help-echo 'widget-emacs-library-link-help-echo
1808 :action 'widget-emacs-library-link-action) 1793 :action 'widget-emacs-library-link-action)
1794
1795 (defun widget-emacs-library-link-help-echo (widget)
1796 (concat "Visit " (widget-value widget)))
1809 1797
1810 (defun widget-emacs-library-link-action (widget &optional event) 1798 (defun widget-emacs-library-link-action (widget &optional event)
1811 "Find the Emacs Library file specified by WIDGET." 1799 "Find the Emacs Library file specified by WIDGET."
1812 (find-file (locate-library (widget-value widget)))) 1800 (find-file (locate-library (widget-value widget))))
1813 1801
1814 ;;; The `emacs-commentary-link' Widget. 1802 ;;; The `emacs-commentary-link' Widget.
1815 1803
1816 (define-widget 'emacs-commentary-link 'link 1804 (define-widget 'emacs-commentary-link 'link
1817 "A link to Commentary in an Emacs Lisp library file." 1805 "A link to Commentary in an Emacs Lisp library file."
1818 :action 'widget-emacs-commentary-link-action) 1806 :action 'widget-emacs-commentary-link-action)
1819 1807
1820 (defun widget-emacs-commentary-link-action (widget &optional event) 1808 (defun widget-emacs-commentary-link-action (widget &optional event)
1821 "Find the Commentary section of the Emacs file specified by WIDGET." 1809 "Find the Commentary section of the Emacs file specified by WIDGET."
1822 (finder-commentary (widget-value widget))) 1810 (finder-commentary (widget-value widget)))
1823 1811
1824 ;;; The `editable-field' Widget. 1812 ;;; The `editable-field' Widget.
1843 1831
1844 (defvar widget-field-history nil 1832 (defvar widget-field-history nil
1845 "History of field minibuffer edits.") 1833 "History of field minibuffer edits.")
1846 1834
1847 (defun widget-field-prompt-internal (widget prompt initial history) 1835 (defun widget-field-prompt-internal (widget prompt initial history)
1848 ;; Read string for WIDGET promptinhg with PROMPT. 1836 ;; Read string for WIDGET prompting with PROMPT.
1849 ;; INITIAL is the initial input and HISTORY is a symbol containing 1837 ;; INITIAL is the initial input and HISTORY is a symbol containing
1850 ;; the earlier input. 1838 ;; the earlier input.
1851 (read-string prompt initial history)) 1839 (read-string prompt initial history))
1852 1840
1853 (defun widget-field-prompt-value (widget prompt value unbound) 1841 (defun widget-field-prompt-value (widget prompt value unbound)
1862 (widget-apply widget :value-to-external answer)))) 1850 (widget-apply widget :value-to-external answer))))
1863 1851
1864 (defvar widget-edit-functions nil) 1852 (defvar widget-edit-functions nil)
1865 1853
1866 (defun widget-field-action (widget &optional event) 1854 (defun widget-field-action (widget &optional event)
1867 ;; Move to next field. 1855 ;; Edit the value in the minibuffer.
1868 (widget-forward 1) 1856 (let ((invalid (widget-apply widget :validate)))
1857 (let ((prompt (concat (widget-apply widget :menu-tag-get) ": "))
1858 (value (unless invalid
1859 (widget-value widget))))
1860 (let ((answer (widget-apply widget :prompt-value prompt value invalid)))
1861 (widget-value-set widget answer)))
1862 (widget-apply widget :notify widget event)
1863 (widget-setup))
1869 (run-hook-with-args 'widget-edit-functions widget)) 1864 (run-hook-with-args 'widget-edit-functions widget))
1865
1866 ;(defun widget-field-action (widget &optional event)
1867 ; ;; Move to next field.
1868 ; (widget-forward 1)
1869 ; (run-hook-with-args 'widget-edit-functions widget))
1870 1870
1871 (defun widget-field-validate (widget) 1871 (defun widget-field-validate (widget)
1872 ;; Valid if the content matches `:valid-regexp'. 1872 ;; Valid if the content matches `:valid-regexp'.
1873 (save-excursion 1873 (save-excursion
1874 (let ((value (widget-apply widget :value-get)) 1874 (let ((value (widget-apply widget :value-get))
1880 (defun widget-field-value-create (widget) 1880 (defun widget-field-value-create (widget)
1881 ;; Create an editable text field. 1881 ;; Create an editable text field.
1882 (let ((size (widget-get widget :size)) 1882 (let ((size (widget-get widget :size))
1883 (value (widget-get widget :value)) 1883 (value (widget-get widget :value))
1884 (from (point)) 1884 (from (point))
1885 ;; This is changed to a real overlay in `widget-setup'. We 1885 ;; This used to make `field-overlay' a cons of two markers,
1886 ;; need the end points to behave differently until 1886 ;; and revert them to a real overlay in `widget-setup',
1887 ;; `widget-setup' is called. 1887 ;; because you can't change overlay insertion type. However,
1888 (overlay (cons (make-marker) (make-marker)))) 1888 ;; we can do that with extents.
1889 (widget-put widget :field-overlay overlay) 1889 extent)
1890 (insert value) 1890 (insert value)
1891 (and size 1891 (and size
1892 (< (length value) size) 1892 (< (length value) size)
1893 (insert-char ?\ (- size (length value)))) 1893 (insert-char ?\ (- size (length value))))
1894 (unless (memq widget widget-field-list) 1894 (unless (memq widget widget-field-list)
1895 (setq widget-field-new (cons widget widget-field-new))) 1895 (push widget widget-field-new))
1896 (move-marker (cdr overlay) (point)) 1896 (setq extent (make-extent from (point)))
1897 (set-marker-insertion-type (cdr overlay) nil) 1897 (set-extent-property extent 'end-open t)
1898 (widget-put widget :field-extent extent)
1898 (when (null size) 1899 (when (null size)
1899 (insert ?\n)) 1900 (insert ?\n))
1900 (move-marker (car overlay) from) 1901 (set-extent-property extent 'start-open t)))
1901 (set-marker-insertion-type (car overlay) t)))
1902 1902
1903 (defun widget-field-value-delete (widget) 1903 (defun widget-field-value-delete (widget)
1904 ;; Remove the widget from the list of active editing fields. 1904 ;; Remove the widget from the list of active editing fields.
1905 (setq widget-field-list (delq widget widget-field-list)) 1905 (setq widget-field-list (delq widget widget-field-list))
1906 ;; These are nil if the :format string doesn't contain `%v'. 1906 ;; These are nil if the :format string doesn't contain `%v'.
1907 (let ((overlay (widget-get widget :field-overlay))) 1907 (let ((extent (widget-get widget :field-extent)))
1908 (when overlay 1908 (when extent
1909 (delete-overlay overlay)))) 1909 (detach-extent extent))))
1910 1910
1911 (defun widget-field-value-get (widget) 1911 (defun widget-field-value-get (widget)
1912 ;; Return current text in editing field. 1912 ;; Return current text in editing field.
1913 (let ((from (widget-field-start widget)) 1913 (let ((from (widget-field-start widget))
1914 (to (widget-field-end widget)) 1914 (to (widget-field-end widget))
1915 (buffer (widget-field-buffer widget)) 1915 (buffer (widget-field-buffer widget))
1916 (size (widget-get widget :size)) 1916 (size (widget-get widget :size))
1917 (secret (widget-get widget :secret)) 1917 (secret (widget-get widget :secret))
1918 (old (current-buffer))) 1918 (old (current-buffer)))
1919 (if (and from to) 1919 (if (and from to)
1920 (progn 1920 (progn
1921 (set-buffer buffer) 1921 (set-buffer buffer)
1922 (while (and size 1922 (while (and size
1923 (not (zerop size)) 1923 (not (zerop size))
1924 (> to from) 1924 (> to from)
1925 (eq (char-after (1- to)) ?\ )) 1925 (eq (char-after (1- to)) ?\ ))
1928 (when secret 1928 (when secret
1929 (let ((index 0)) 1929 (let ((index 0))
1930 (while (< (+ from index) to) 1930 (while (< (+ from index) to)
1931 (aset result index 1931 (aset result index
1932 (get-char-property (+ from index) 'secret)) 1932 (get-char-property (+ from index) 'secret))
1933 (setq index (1+ index))))) 1933 (incf index))))
1934 (set-buffer old) 1934 (set-buffer old)
1935 result)) 1935 result))
1936 (widget-get widget :value)))) 1936 (widget-get widget :value))))
1937 1937
1938 (defun widget-field-match (widget value) 1938 (defun widget-field-match (widget value)
2002 2002
2003 (defun widget-choice-mouse-down-action (widget &optional event) 2003 (defun widget-choice-mouse-down-action (widget &optional event)
2004 ;; Return non-nil if we need a menu. 2004 ;; Return non-nil if we need a menu.
2005 (let ((args (widget-get widget :args)) 2005 (let ((args (widget-get widget :args))
2006 (old (widget-get widget :choice))) 2006 (old (widget-get widget :choice)))
2007 (cond ((not window-system) 2007 (cond ((not (console-on-window-system-p))
2008 ;; No place to pop up a menu. 2008 ;; No place to pop up a menu.
2009 nil)
2010 ((not (or (fboundp 'x-popup-menu) (fboundp 'popup-menu)))
2011 ;; No way to pop up a menu.
2012 nil) 2009 nil)
2013 ((< (length args) 2) 2010 ((< (length args) 2)
2014 ;; Empty or singleton list, just return the value. 2011 ;; Empty or singleton list, just return the value.
2015 nil) 2012 nil)
2016 ((> (length args) widget-menu-max-size) 2013 ((> (length args) widget-menu-max-size)
2234 values (cdr vals) 2231 values (cdr vals)
2235 args (delq answer args)))) 2232 args (delq answer args))))
2236 (greedy 2233 (greedy
2237 (setq rest (append rest (list (car values))) 2234 (setq rest (append rest (list (car values)))
2238 values (cdr values))) 2235 values (cdr values)))
2239 (t 2236 (t
2240 (setq rest (append rest values) 2237 (setq rest (append rest values)
2241 values nil))))) 2238 values nil)))))
2242 (cons found rest))) 2239 (cons found rest)))
2243 2240
2244 (defun widget-checklist-match-find (widget vals) 2241 (defun widget-checklist-match-find (widget vals)
2584 (let ((type (nth 0 (widget-get widget :args))) 2581 (let ((type (nth 0 (widget-get widget :args)))
2585 (ok t) 2582 (ok t)
2586 found) 2583 found)
2587 (while (and value ok) 2584 (while (and value ok)
2588 (let ((answer (widget-match-inline type value))) 2585 (let ((answer (widget-match-inline type value)))
2589 (if answer 2586 (if answer
2590 (setq found (append found (car answer)) 2587 (setq found (append found (car answer))
2591 value (cdr answer)) 2588 value (cdr answer))
2592 (setq ok nil)))) 2589 (setq ok nil))))
2593 (cons found value))) 2590 (cons found value)))
2594 2591
2736 argument answer found) 2733 argument answer found)
2737 (while args 2734 (while args
2738 (setq argument (car args) 2735 (setq argument (car args)
2739 args (cdr args) 2736 args (cdr args)
2740 answer (widget-match-inline argument vals)) 2737 answer (widget-match-inline argument vals))
2741 (if answer 2738 (if answer
2742 (setq vals (cdr answer) 2739 (setq vals (cdr answer)
2743 found (append found (car answer))) 2740 found (append found (car answer)))
2744 (setq vals nil 2741 (setq vals nil
2745 args nil))) 2742 args nil)))
2746 (if answer 2743 (if answer
2875 buttons) 2872 buttons)
2876 (insert before " ") 2873 (insert before " ")
2877 (widget-documentation-link-add widget start (point)) 2874 (widget-documentation-link-add widget start (point))
2878 (push (widget-create-child-and-convert 2875 (push (widget-create-child-and-convert
2879 widget 'visibility 2876 widget 'visibility
2880 :help-echo "Show or hide rest of the documentation." 2877 :help-echo (lambda (widget)
2878 ;; This can get called directly from
2879 ;; default-mouse-motion-handler, with an
2880 ;; extent argument.
2881 (and (extentp widget)
2882 (setq
2883 widget (widget-at
2884 (extent-start-position widget))))
2885 (concat
2886 (if (widget-value widget)
2887 "Hide" "Show")
2888 " the rest of the documentation."))
2881 :off "More" 2889 :off "More"
2882 :action 'widget-parent-action 2890 :action 'widget-parent-action
2883 shown) 2891 shown)
2884 buttons) 2892 buttons)
2885 (when shown 2893 (when shown
3078 "A lisp variable." 3086 "A lisp variable."
3079 :prompt-match 'boundp 3087 :prompt-match 'boundp
3080 :prompt-history 'widget-variable-prompt-value-history 3088 :prompt-history 'widget-variable-prompt-value-history
3081 :tag "Variable") 3089 :tag "Variable")
3082 3090
3083 (when (featurep 'mule) 3091 ;; This part issues a warning when compiling without Mule. Is there a
3084 (defvar widget-coding-system-prompt-value-history nil 3092 ;; way of shutting it up?
3085 "History of input to `widget-coding-system-prompt-value'.") 3093 ;;
3086 3094 ;; OK, I'll simply comment the whole thing out, until someone decides
3087 (define-widget 'coding-system 'symbol 3095 ;; to do something with it.
3088 "A MULE coding-system." 3096 ;(defvar widget-coding-system-prompt-value-history nil
3089 :format "%{%t%}: %v" 3097 ; "History of input to `widget-coding-system-prompt-value'.")
3090 :tag "Coding system" 3098
3091 :prompt-history 'widget-coding-system-prompt-value-history 3099 ;(define-widget 'coding-system 'symbol
3092 :prompt-value 'widget-coding-system-prompt-value 3100 ; "A MULE coding-system."
3093 :action 'widget-coding-system-action) 3101 ; :format "%{%t%}: %v"
3094 3102 ; :tag "Coding system"
3095 (defun widget-coding-system-prompt-value (widget prompt value unbound) 3103 ; :prompt-history 'widget-coding-system-prompt-value-history
3096 ;; Read coding-system from minibuffer. 3104 ; :prompt-value 'widget-coding-system-prompt-value
3097 (intern 3105 ; :action 'widget-coding-system-action)
3098 (completing-read (format "%s (default %s) " prompt value) 3106
3099 (mapcar (function 3107 ;(defun widget-coding-system-prompt-value (widget prompt value unbound)
3100 (lambda (sym) 3108 ; ;; Read coding-system from minibuffer.
3101 (list (symbol-name sym)) 3109 ; (intern
3102 )) 3110 ; (completing-read (format "%s (default %s) " prompt value)
3103 (coding-system-list))))) 3111 ; (mapcar (lambda (sym)
3104 3112 ; (list (symbol-name sym)))
3105 (defun widget-coding-system-action (widget &optional event) 3113 ; (coding-system-list)))))
3106 ;; Read a file name from the minibuffer. 3114
3107 (let ((answer 3115 ;(defun widget-coding-system-action (widget &optional event)
3108 (widget-coding-system-prompt-value 3116 ; ;; Read a file name from the minibuffer.
3109 widget 3117 ; (let ((answer
3110 (widget-apply widget :menu-tag-get) 3118 ; (widget-coding-system-prompt-value
3111 (widget-value widget) 3119 ; widget
3112 t))) 3120 ; (widget-apply widget :menu-tag-get)
3113 (widget-value-set widget answer) 3121 ; (widget-value widget)
3114 (widget-apply widget :notify widget event) 3122 ; t)))
3115 (widget-setup))) 3123 ; (widget-value-set widget answer)
3116 ) 3124 ; (widget-apply widget :notify widget event)
3125 ; (widget-setup)))
3117 3126
3118 (define-widget 'sexp 'editable-field 3127 (define-widget 'sexp 'editable-field
3119 "An arbitrary lisp expression." 3128 "An arbitrary lisp expression."
3120 :tag "Lisp expression" 3129 :tag "Lisp expression"
3121 :format "%{%t%}: %v" 3130 :format "%{%t%}: %v"
3232 :value-to-external (lambda (widget value) 3241 :value-to-external (lambda (widget value)
3233 (if (stringp value) 3242 (if (stringp value)
3234 (aref value 0) 3243 (aref value 0)
3235 value)) 3244 value))
3236 :match (lambda (widget value) 3245 :match (lambda (widget value)
3237 (if (fboundp 'characterp) 3246 (characterp value)))
3238 (characterp value)
3239 (integerp value))))
3240 3247
3241 (define-widget 'list 'group 3248 (define-widget 'list 'group
3242 "A lisp list." 3249 "A lisp list."
3243 :tag "List" 3250 :tag "List"
3244 :format "%{%t%}:\n%v") 3251 :format "%{%t%}:\n%v")
3369 (let* ((prefix (buffer-substring-no-properties (widget-field-start widget) 3376 (let* ((prefix (buffer-substring-no-properties (widget-field-start widget)
3370 (point))) 3377 (point)))
3371 (list (widget-color-choice-list)) 3378 (list (widget-color-choice-list))
3372 (completion (try-completion prefix list))) 3379 (completion (try-completion prefix list)))
3373 (cond ((eq completion t) 3380 (cond ((eq completion t)
3374 (message "Exact match.")) 3381 (message "Exact match"))
3375 ((null completion) 3382 ((null completion)
3376 (error "Can't find completion for \"%s\"" prefix)) 3383 (error "Can't find completion for \"%s\"" prefix))
3377 ((not (string-equal prefix completion)) 3384 ((not (string-equal prefix completion))
3378 (insert-and-inherit (substring completion (length prefix)))) 3385 (insert-and-inherit (substring completion (length prefix))))
3379 (t 3386 (t
3386 (defun widget-color-sample-face-get (widget) 3393 (defun widget-color-sample-face-get (widget)
3387 (let* ((value (condition-case nil 3394 (let* ((value (condition-case nil
3388 (widget-value widget) 3395 (widget-value widget)
3389 (error (widget-get widget :value)))) 3396 (error (widget-get widget :value))))
3390 (symbol (intern (concat "fg:" value)))) 3397 (symbol (intern (concat "fg:" value))))
3391 (if (string-match "XEmacs" emacs-version) 3398 (prog1 symbol
3392 (prog1 symbol 3399 (or (find-face symbol)
3393 (or (find-face symbol) 3400 (set-face-foreground (make-face symbol) value)))))
3394 (set-face-foreground (make-face symbol) value)))
3395 (condition-case nil
3396 (facemenu-get-face symbol)
3397 (error 'default)))))
3398 3401
3399 (defvar widget-color-choice-list nil) 3402 (defvar widget-color-choice-list nil)
3400 ;; Variable holding the possible colors. 3403 ;; Variable holding the possible colors.
3401 3404
3402 (defun widget-color-choice-list () 3405 (defun widget-color-choice-list ()
3403 (unless widget-color-choice-list 3406 (or widget-color-choice-list
3404 (setq widget-color-choice-list 3407 (setq widget-color-choice-list (read-color-completion-table))))
3405 (if (fboundp 'read-color-completion-table)
3406 (read-color-completion-table)
3407 (mapcar '(lambda (color) (list color))
3408 (x-defined-colors)))))
3409 widget-color-choice-list)
3410 3408
3411 (defvar widget-color-history nil 3409 (defvar widget-color-history nil
3412 "History of entered colors") 3410 "History of entered colors")
3413 3411
3414 (defun widget-color-action (widget &optional event) 3412 (defun widget-color-action (widget &optional event)
3434 (widget-value-set widget answer) 3432 (widget-value-set widget answer)
3435 (widget-setup) 3433 (widget-setup)
3436 (widget-apply widget :notify widget event)))) 3434 (widget-apply widget :notify widget event))))
3437 3435
3438 (defun widget-color-notify (widget child &optional event) 3436 (defun widget-color-notify (widget child &optional event)
3439 "Update the sample, and notofy the parent." 3437 "Update the sample, and notify the parent."
3440 (overlay-put (widget-get widget :sample-overlay) 3438 (set-extent-property (widget-get widget :sample-extent)
3441 'face (widget-apply widget :sample-face-get)) 3439 'face (widget-apply widget :sample-face-get))
3442 (widget-default-notify widget child event)) 3440 (widget-default-notify widget child event))
3443
3444 ;;; The Help Echo
3445
3446 (defun widget-echo-help-mouse ()
3447 "Display the help message for the widget under the mouse.
3448 Enable with (run-with-idle-timer 1 t 'widget-echo-help-mouse)"
3449 (let* ((pos (mouse-position))
3450 (frame (car pos))
3451 (x (car (cdr pos)))
3452 (y (cdr (cdr pos)))
3453 (win (window-at x y frame))
3454 (where (coordinates-in-window-p (cons x y) win)))
3455 (when (consp where)
3456 (save-window-excursion
3457 (progn ; save-excursion
3458 (select-window win)
3459 (let* ((result (compute-motion (window-start win)
3460 '(0 . 0)
3461 (window-end win)
3462 where
3463 (window-width win)
3464 (cons (window-hscroll) 0)
3465 win)))
3466 (when (and (eq (nth 1 result) x)
3467 (eq (nth 2 result) y))
3468 (widget-echo-help (nth 0 result))))))))
3469 (unless track-mouse
3470 (setq track-mouse t)
3471 (add-hook 'post-command-hook 'widget-stop-mouse-tracking)))
3472
3473 (defun widget-stop-mouse-tracking (&rest args)
3474 "Stop the mouse tracking done while idle."
3475 (remove-hook 'post-command-hook 'widget-stop-mouse-tracking)
3476 (setq track-mouse nil))
3477 3441
3478 (defun widget-at (pos) 3442 (defun widget-at (pos)
3479 "The button or field at POS." 3443 "The button or field at POS."
3480 (or (get-char-property pos 'button) 3444 (or (get-char-property pos 'button)
3481 (get-char-property pos 'field))) 3445 (get-char-property pos 'field)))
3484 "Display the help echo for widget at POS." 3448 "Display the help echo for widget at POS."
3485 (let* ((widget (widget-at pos)) 3449 (let* ((widget (widget-at pos))
3486 (help-echo (and widget (widget-get widget :help-echo)))) 3450 (help-echo (and widget (widget-get widget :help-echo))))
3487 (cond ((stringp help-echo) 3451 (cond ((stringp help-echo)
3488 (message "%s" help-echo)) 3452 (message "%s" help-echo))
3489 ((and (symbolp help-echo) (fboundp help-echo) 3453 ((and (functionp help-echo)
3490 (stringp (setq help-echo (funcall help-echo widget)))) 3454 (stringp (setq help-echo (funcall help-echo widget))))
3491 (message "%s" help-echo))))) 3455 (message "%s" help-echo)))))
3492 3456
3493 ;;; The End: 3457 ;;; The End:
3494 3458