comparison lisp/wid-edit.el @ 29402:3bb8d5adf524

byte-compile-dynamic since we typically don't use all the widgets. Don't require cl or widget. Remove eval-and-compile. Don't autoload finder-commentary. Doc fixes. (widget-read-event): Removed. Callers changed to use read-event. (widget-button-release-event-p): Renamed from button-release-event-p. (widget-field-add-space, widget-field-use-before-change): Uncustomize. (widget-specify-field): Use keymap property, not local-map. (widget-specify-button): Obey :suppress-face. (widget-specify-insert): Use modern backquote syntax. (widget-image-directory): Renamed from widget-glyph-directory. (widget-image-enable): Renamed from widget-glyph-enable. (widget-image-find): Replaces widget-glyph-find. (widget-button-pressed-face): Move defvar. (widget-image-insert): Replaces widget-glyph-insert. (widget-convert): Use keywordp. (widget-leave-text, widget-children-value-delete): Use mapc. (widget-keymap): Remove XEmacs stuff. (widget-field-keymap, widget-text-keymap): Define all inside defvar. (widget-button-click): Don't set point at the click, but re-centre if we scroll out of window. Rewritten for images v. glyphs &c. (widget-tabable-at): Use POS arg, not point. (widget-beginning-of-line, widget-end-of-line) (widget-item-value-create, widget-sublist, widget-princ-to-string) (widget-sexp-prompt-value, widget-echo-help): Simplify. (widget-default-create): Use widget-image-insert; some rewriting. (widget-visibility-value-create) (widget-push-button-value-create, widget-toggle-value-create): Use widget-image-insert. (checkbox): Create on and off images dynamically. (documentation-link): Change :help-echo. (widget-documentation-link-echo-help): Remove.
author Dave Love <fx@gnu.org>
date Sat, 03 Jun 2000 16:42:14 +0000
parents 6bc5854eef8b
children db8d9c0d471f
comparison
equal deleted inserted replaced
29401:8cecaaeeeaa4 29402:3bb8d5adf524
1 ;;; wid-edit.el --- Functions for creating and using widgets. 1 ;;; wid-edit.el --- Functions for creating and using widgets -*-byte-compile-dynamic: t;-*-
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Maintainer: FSF 6 ;; Maintainer: FSF
27 ;; 27 ;;
28 ;; See `widget.el'. 28 ;; See `widget.el'.
29 29
30 ;;; Code: 30 ;;; Code:
31 31
32 (require 'widget)
33 (eval-when-compile (require 'cl))
34
35 ;;; Compatibility. 32 ;;; Compatibility.
36 33
37 (defun widget-event-point (event) 34 (defun widget-event-point (event)
38 "Character position of the end of event if that exists, or nil." 35 "Character position of the end of event if that exists, or nil."
39 (posn-point (event-end event))) 36 (posn-point (event-end event)))
40 37
41 (defalias 'widget-read-event 'read-event) 38 (autoload 'pp-to-string "pp")
42 39 (autoload 'Info-goto-node "info")
43 (eval-and-compile 40
44 (autoload 'pp-to-string "pp") 41 (defun widget-button-release-event-p (event)
45 (autoload 'Info-goto-node "info") 42 "Non-nil if EVENT is a mouse-button-release event object."
46 (autoload 'finder-commentary "finder" nil t) 43 (and (eventp event)
47 44 (memq (event-basic-type event) '(mouse-1 mouse-2 mouse-3))
48 (unless (fboundp 'button-release-event-p) 45 (or (memq 'click (event-modifiers event))
49 ;; XEmacs function missing from Emacs. 46 (memq 'drag (event-modifiers event)))))
50 (defun button-release-event-p (event)
51 "Non-nil if EVENT is a mouse-button-release event object."
52 (and (eventp event)
53 (memq (event-basic-type event) '(mouse-1 mouse-2 mouse-3))
54 (or (memq 'click (event-modifiers event))
55 (memq 'drag (event-modifiers event)))))))
56 47
57 ;;; Customization. 48 ;;; Customization.
58 49
59 (defgroup widgets nil 50 (defgroup widgets nil
60 "Customization support for the Widget Library." 51 "Customization support for the Widget Library."
105 (background light)) 96 (background light))
106 (:background "gray85")) 97 (:background "gray85"))
107 (((class grayscale color) 98 (((class grayscale color)
108 (background dark)) 99 (background dark))
109 (:background "dim gray")) 100 (:background "dim gray"))
110 (t 101 (t
111 (:italic t))) 102 (:italic t)))
112 "Face used for editable fields." 103 "Face used for editable fields."
113 :group 'widget-faces) 104 :group 'widget-faces)
114 105
115 (defface widget-single-line-field-face '((((class grayscale color) 106 (defface widget-single-line-field-face '((((class grayscale color)
116 (background light)) 107 (background light))
117 (:background "gray85")) 108 (:background "gray85"))
118 (((class grayscale color) 109 (((class grayscale color)
119 (background dark)) 110 (background dark))
120 (:background "dim gray")) 111 (:background "dim gray"))
121 (t 112 (t
122 (:italic t))) 113 (:italic t)))
123 "Face used for editable fields spanning only a single line." 114 "Face used for editable fields spanning only a single line."
124 :group 'widget-faces) 115 :group 'widget-faces)
125 116
126 ;;; This causes display-table to be loaded, and not usefully. 117 ;;; This causes display-table to be loaded, and not usefully.
138 ;;; Utility functions. 129 ;;; Utility functions.
139 ;; 130 ;;
140 ;; These are not really widget specific. 131 ;; These are not really widget specific.
141 132
142 (defun widget-princ-to-string (object) 133 (defun widget-princ-to-string (object)
143 ;; Return string representation of OBJECT, any Lisp object. 134 "Return string representation of OBJECT, any Lisp object.
144 ;; No quoting characters are used; no delimiters are printed around 135 No quoting characters are used; no delimiters are printed around
145 ;; the contents of strings. 136 the contents of strings."
146 (save-excursion 137 (with-output-to-string
147 (set-buffer (get-buffer-create " *widget-tmp*")) 138 (princ object)))
148 (erase-buffer)
149 (let ((standard-output (current-buffer)))
150 (princ object))
151 (buffer-string)))
152 139
153 (defun widget-clear-undo () 140 (defun widget-clear-undo ()
154 "Clear all undo information." 141 "Clear all undo information."
155 (buffer-disable-undo (current-buffer)) 142 (buffer-disable-undo (current-buffer))
156 (buffer-enable-undo)) 143 (buffer-enable-undo))
200 (let ((val (completing-read (concat title ": ") items nil t))) 187 (let ((val (completing-read (concat title ": ") items nil t)))
201 (if (stringp val) 188 (if (stringp val)
202 (let ((try (try-completion val items))) 189 (let ((try (try-completion val items)))
203 (when (stringp try) 190 (when (stringp try)
204 (setq val try)) 191 (setq val try))
205 (cdr (assoc val items))) 192 (cdr (assoc val items))))))
206 nil)))
207 (t 193 (t
208 ;; Construct a menu of the choices 194 ;; Construct a menu of the choices
209 ;; and then use it for prompting for a single character. 195 ;; and then use it for prompting for a single character.
210 (let* ((overriding-terminal-local-map 196 (let* ((overriding-terminal-local-map
211 (make-sparse-keymap)) 197 (make-sparse-keymap))
250 (while (not (or (and (>= char ?0) (< char next-digit)) 236 (while (not (or (and (>= char ?0) (< char next-digit))
251 (eq value 'keyboard-quit))) 237 (eq value 'keyboard-quit)))
252 ;; Unread a SPC to lead to our new menu. 238 ;; Unread a SPC to lead to our new menu.
253 (setq unread-command-events (cons ?\ unread-command-events)) 239 (setq unread-command-events (cons ?\ unread-command-events))
254 (setq keys (read-key-sequence title)) 240 (setq keys (read-key-sequence title))
255 (setq value (lookup-key overriding-terminal-local-map keys t) 241 (setq value
242 (lookup-key overriding-terminal-local-map keys t)
256 char (string-to-char (substring keys 1))) 243 char (string-to-char (substring keys 1)))
257 (cond ((eq value 'scroll-other-window) 244 (cond ((eq value 'scroll-other-window)
258 (let ((minibuffer-scroll-window (get-buffer-window buf))) 245 (let ((minibuffer-scroll-window
246 (get-buffer-window buf)))
259 (if (> 0 arg) 247 (if (> 0 arg)
260 (scroll-other-window-down (window-height minibuffer-scroll-window)) 248 (scroll-other-window-down
249 (window-height minibuffer-scroll-window))
261 (scroll-other-window)) 250 (scroll-other-window))
262 (setq arg 1))) 251 (setq arg 1)))
263 ((eq value 'negative-argument) 252 ((eq value 'negative-argument)
264 (setq arg -1)) 253 (setq arg -1))
265 (t 254 (t
276 (setq tail (cdr tail))) 265 (setq tail (cdr tail)))
277 (nreverse result))) 266 (nreverse result)))
278 267
279 ;;; Widget text specifications. 268 ;;; Widget text specifications.
280 ;; 269 ;;
281 ;; These functions are for specifying text properties. 270 ;; These functions are for specifying text properties.
282 271
283 (defcustom widget-field-add-space 272 (defvar widget-field-add-space t
284 (or (< emacs-major-version 20)
285 (and (eq emacs-major-version 20)
286 (< emacs-minor-version 3))
287 (not (string-match "XEmacs" emacs-version)))
288 "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.
289
290 This is needed on all versions of Emacs, and on XEmacs before 20.3.
291 If you don't add the space, it will become impossible to edit a zero 274 If you don't add the space, it will become impossible to edit a zero
292 size field." 275 size field.")
293 :type 'boolean 276
294 :group 'widgets) 277 (defvar widget-field-use-before-change t
295
296 (defcustom widget-field-use-before-change
297 (and (or (> emacs-minor-version 34)
298 (> emacs-major-version 19))
299 (not (string-match "XEmacs" emacs-version)))
300 "Non-nil means use `before-change-functions' to track editable fields. 278 "Non-nil means use `before-change-functions' to track editable fields.
301 This enables the use of undo, but doesn't work on Emacs 19.34 and earlier. 279 This enables the use of undo, but doesn't work on Emacs 19.34 and earlier.
302 Using before hooks also means that the :notify function can't know the 280 Using before hooks also means that the :notify function can't know the
303 new value." 281 new value.")
304 :type 'boolean
305 :group 'widgets)
306 282
307 (defun widget-specify-field (widget from to) 283 (defun widget-specify-field (widget from to)
308 "Specify editable button for WIDGET between FROM and TO." 284 "Specify editable button for WIDGET between FROM and TO."
309 ;; Terminating space is not part of the field, but necessary in 285 ;; Terminating space is not part of the field, but necessary in
310 ;; order for local-map to work. Remove next sexp if local-map works 286 ;; order for local-map to work. Remove next sexp if local-map works
317 (insert-and-inherit " "))) 293 (insert-and-inherit " ")))
318 (setq to (point))) 294 (setq to (point)))
319 (let ((map (widget-get widget :keymap)) 295 (let ((map (widget-get widget :keymap))
320 (face (or (widget-get widget :value-face) 'widget-field-face)) 296 (face (or (widget-get widget :value-face) 'widget-field-face))
321 (help-echo (widget-get widget :help-echo)) 297 (help-echo (widget-get widget :help-echo))
322 (overlay (make-overlay from to nil 298 (overlay (make-overlay from to nil
323 nil (or (not widget-field-add-space) 299 nil (or (not widget-field-add-space)
324 (widget-get widget :size))))) 300 (widget-get widget :size)))))
325 (widget-put widget :field-overlay overlay) 301 (widget-put widget :field-overlay overlay)
326 ;;(overlay-put overlay 'detachable nil) 302 ;;(overlay-put overlay 'detachable nil)
327 (overlay-put overlay 'field widget) 303 (overlay-put overlay 'field widget)
328 (overlay-put overlay 'local-map map) 304 (overlay-put overlay 'keymap map)
329 ;;(overlay-put overlay 'keymap map)
330 (overlay-put overlay 'face face) 305 (overlay-put overlay 'face face)
331 ;;(overlay-put overlay 'balloon-help help-echo) 306 ;;(overlay-put overlay 'balloon-help help-echo)
332 (if (stringp help-echo) 307 (if (stringp help-echo)
333 (overlay-put overlay 'help-echo help-echo))) 308 (overlay-put overlay 'help-echo help-echo)))
334 (widget-specify-secret widget)) 309 (widget-specify-secret widget))
338 (let ((secret (widget-get field :secret)) 313 (let ((secret (widget-get field :secret))
339 (size (widget-get field :size))) 314 (size (widget-get field :size)))
340 (when secret 315 (when secret
341 (let ((begin (widget-field-start field)) 316 (let ((begin (widget-field-start field))
342 (end (widget-field-end field))) 317 (end (widget-field-end field)))
343 (when size 318 (when size
344 (while (and (> end begin) 319 (while (and (> end begin)
345 (eq (char-after (1- end)) ?\ )) 320 (eq (char-after (1- end)) ?\ ))
346 (setq end (1- end)))) 321 (setq end (1- end))))
347 (while (< begin end) 322 (while (< begin end)
348 (let ((old (char-after begin))) 323 (let ((old (char-after begin)))
356 (let ((face (widget-apply widget :button-face-get)) 331 (let ((face (widget-apply widget :button-face-get))
357 (help-echo (widget-get widget :help-echo)) 332 (help-echo (widget-get widget :help-echo))
358 (overlay (make-overlay from to nil t nil))) 333 (overlay (make-overlay from to nil t nil)))
359 (widget-put widget :button-overlay overlay) 334 (widget-put widget :button-overlay overlay)
360 (overlay-put overlay 'button widget) 335 (overlay-put overlay 'button widget)
361 (overlay-put overlay 'mouse-face widget-mouse-face) 336 ;; We want to avoid the face with image buttons.
337 (unless (widget-get widget :suppress-face)
338 (overlay-put overlay 'face face)
339 (overlay-put overlay 'mouse-face widget-mouse-face))
362 ;;(overlay-put overlay 'balloon-help help-echo) 340 ;;(overlay-put overlay 'balloon-help help-echo)
363 (if (stringp help-echo) 341 (if (stringp help-echo)
364 (overlay-put overlay 'help-echo help-echo)) 342 (overlay-put overlay 'help-echo help-echo))
365 (overlay-put overlay 'face face))) 343 (overlay-put overlay 'face face)))
366 344
367 (defun widget-specify-sample (widget from to) 345 (defun widget-specify-sample (widget from to)
368 ;; Specify sample for WIDGET between FROM and TO. 346 "Specify sample for WIDGET between FROM and TO."
369 (let ((face (widget-apply widget :sample-face-get)) 347 (let ((face (widget-apply widget :sample-face-get))
370 (overlay (make-overlay from to nil t nil))) 348 (overlay (make-overlay from to nil t nil)))
371 (overlay-put overlay 'face face) 349 (overlay-put overlay 'face face)
372 (widget-put widget :sample-overlay overlay))) 350 (widget-put widget :sample-overlay overlay)))
373 351
374 (defun widget-specify-doc (widget from to) 352 (defun widget-specify-doc (widget from to)
375 ;; Specify documentation for WIDGET between FROM and TO. 353 "Specify documentation for WIDGET between FROM and TO."
376 (let ((overlay (make-overlay from to nil t nil))) 354 (let ((overlay (make-overlay from to nil t nil)))
377 (overlay-put overlay 'widget-doc widget) 355 (overlay-put overlay 'widget-doc widget)
378 (overlay-put overlay 'face widget-documentation-face) 356 (overlay-put overlay 'face widget-documentation-face)
379 (widget-put widget :doc-overlay overlay))) 357 (widget-put widget :doc-overlay overlay)))
380 358
381 (defmacro widget-specify-insert (&rest form) 359 (defmacro widget-specify-insert (&rest form)
382 ;; Execute FORM without inheriting any text properties. 360 "Execute FORM without inheriting any text properties."
383 (` 361 `(save-restriction
384 (save-restriction 362 (let ((inhibit-read-only t)
385 (let ((inhibit-read-only t) 363 result
386 result 364 before-change-functions
387 before-change-functions 365 after-change-functions)
388 after-change-functions) 366 (insert "<>")
389 (insert "<>") 367 (narrow-to-region (- (point) 2) (point))
390 (narrow-to-region (- (point) 2) (point)) 368 (goto-char (1+ (point-min)))
391 (goto-char (1+ (point-min))) 369 (setq result (progn ,@form))
392 (setq result (progn (,@ form))) 370 (delete-region (point-min) (1+ (point-min)))
393 (delete-region (point-min) (1+ (point-min))) 371 (delete-region (1- (point-max)) (point-max))
394 (delete-region (1- (point-max)) (point-max)) 372 (goto-char (point-max))
395 (goto-char (point-max)) 373 result)))
396 result))))
397 374
398 (defface widget-inactive-face '((((class grayscale color) 375 (defface widget-inactive-face '((((class grayscale color)
399 (background dark)) 376 (background dark))
400 (:foreground "light gray")) 377 (:foreground "light gray"))
401 (((class grayscale color) 378 (((class grayscale color)
402 (background light)) 379 (background light))
403 (:foreground "dim gray")) 380 (:foreground "dim gray"))
404 (t 381 (t
405 (:italic t))) 382 (:italic t)))
406 "Face used for inactive widgets." 383 "Face used for inactive widgets."
407 :group 'widget-faces) 384 :group 'widget-faces)
408 385
409 (defun widget-specify-inactive (widget from to) 386 (defun widget-specify-inactive (widget from to)
437 "Return the type of WIDGET, a symbol." 414 "Return the type of WIDGET, a symbol."
438 (car widget)) 415 (car widget))
439 416
440 (defun widget-get-indirect (widget property) 417 (defun widget-get-indirect (widget property)
441 "In WIDGET, get the value of PROPERTY. 418 "In WIDGET, get the value of PROPERTY.
442 If the value is a symbol, return its binding. 419 If the value is a symbol, return its binding.
443 Otherwise, just return the value." 420 Otherwise, just return the value."
444 (let ((value (widget-get widget property))) 421 (let ((value (widget-get widget property)))
445 (if (symbolp value) 422 (if (symbolp value)
446 (symbol-value value) 423 (symbol-value value)
447 value))) 424 value)))
497 (setq widget (list widget))) 474 (setq widget (list widget)))
498 (setq prompt (format "[%s] %s" (widget-type widget) prompt)) 475 (setq prompt (format "[%s] %s" (widget-type widget) prompt))
499 (setq widget (widget-convert widget)) 476 (setq widget (widget-convert widget))
500 (let ((answer (widget-apply widget :prompt-value prompt value unbound))) 477 (let ((answer (widget-apply widget :prompt-value prompt value unbound)))
501 (unless (widget-apply widget :match answer) 478 (unless (widget-apply widget :match answer)
502 (error "Value does not match %S type." (car widget))) 479 (error "Value does not match %S type" (car widget)))
503 answer)) 480 answer))
504 481
505 (defun widget-get-sibling (widget) 482 (defun widget-get-sibling (widget)
506 "Get the item WIDGET is assumed to toggle. 483 "Get the item WIDGET is assumed to toggle.
507 This is only meaningful for radio buttons or checkboxes in a list." 484 This is only meaningful for radio buttons or checkboxes in a list."
534 (while (setq cur (pop overlays)) 511 (while (setq cur (pop overlays))
535 (setq widget (overlay-get cur 'button)) 512 (setq widget (overlay-get cur 'button))
536 (if (and widget (funcall function widget maparg)) 513 (if (and widget (funcall function widget maparg))
537 (setq overlays nil))))) 514 (setq overlays nil)))))
538 515
539 ;;; Glyphs. 516 ;;; Images.
540 517
541 (defcustom widget-glyph-directory (concat data-directory "custom/") 518 (defcustom widget-image-directory (file-name-as-directory
542 "Where widget glyphs are located. 519 (expand-file-name "custom" data-directory))
520 "Where widget button images are located.
543 If this variable is nil, widget will try to locate the directory 521 If this variable is nil, widget will try to locate the directory
544 automatically." 522 automatically."
545 :group 'widgets 523 :group 'widgets
546 :type 'directory) 524 :type 'directory)
547 525
548 (defcustom widget-glyph-enable t 526 (defcustom widget-image-enable t
549 "If non nil, use glyphs in images when available." 527 "If non nil, use image buttons in widgets when available."
528 :version "21.1"
550 :group 'widgets 529 :group 'widgets
551 :type 'boolean) 530 :type 'boolean)
552 531
553 (defcustom widget-image-conversion 532 (defcustom widget-image-conversion
554 '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg") 533 '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg")
558 :type '(repeat (cons :format "%v" 537 :type '(repeat (cons :format "%v"
559 (symbol :tag "Image Format" unknown) 538 (symbol :tag "Image Format" unknown)
560 (repeat :tag "Suffixes" 539 (repeat :tag "Suffixes"
561 (string :format "%v"))))) 540 (string :format "%v")))))
562 541
563 (defun widget-glyph-find (image tag) 542 (defun widget-image-find (image)
564 "Create a glyph corresponding to IMAGE with string TAG as fallback. 543 "Create a graphical button from IMAGE.
565 IMAGE should either already be a glyph, or be a file name sans 544 IMAGE should either already be an image, or be a file name sans
566 extension (xpm, xbm, gif, jpg, or png) located in 545 extension (xpm, xbm, gif, jpg, or png) located in
567 `widget-glyph-directory'." 546 `widget-image-directory' or otherwise where `find-image' will find it."
568 (cond ((not (and image 547 (cond ((not (and image widget-image-enable (display-graphic-p)))
569 (string-match "XEmacs" emacs-version) 548 ;; We don't want or can't use images.
570 widget-glyph-enable
571 (fboundp 'make-glyph)
572 (fboundp 'locate-file)
573 image))
574 ;; We don't want or can't use glyphs.
575 nil) 549 nil)
576 ((and (fboundp 'glyphp) 550 ((and (consp image)
577 (glyphp image)) 551 (eq 'image (car image)))
578 ;; Already a glyph. Use it. 552 ;; Already an image spec. Use it.
579 image) 553 image)
580 ((stringp image) 554 ((stringp image)
581 ;; A string. Look it up in relevant directories. 555 ;; A string. Look it up in relevant directories.
582 (let* ((dirlist (list (or widget-glyph-directory 556 (let* ((load-path (cons widget-image-directory load-path))
583 (concat data-directory
584 "custom/"))
585 data-directory))
586 (formats widget-image-conversion) 557 (formats widget-image-conversion)
587 file) 558 specs)
588 (while (and formats (not file)) 559 (dolist (elt widget-image-conversion)
589 (when (valid-image-instantiator-format-p (car (car formats))) 560 (dolist (ext (cdr elt))
590 (setq file (locate-file image dirlist 561 (push (list :type (car elt) :file (concat image ext)) specs)))
591 (mapconcat 'identity 562 (setq specs (nreverse specs))
592 (cdr (car formats)) 563 (find-image specs)))
593 ":"))))
594 (unless file
595 (setq formats (cdr formats))))
596 (and file
597 ;; We create a glyph with the file as the default image
598 ;; instantiator, and the TAG fallback
599 (make-glyph (list (vector (car (car formats)) ':file file)
600 (vector 'string ':data tag))))))
601 ((valid-instantiator-p image 'image)
602 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.)
603 (make-glyph (list image
604 (vector 'string ':data tag))))
605 ((consp image)
606 ;; This could be virtually anything. Let `make-glyph' sort it out.
607 (make-glyph image))
608 (t 564 (t
609 ;; Oh well. 565 ;; Oh well.
610 nil))) 566 nil)))
611 567
612 (defun widget-glyph-insert (widget tag image &optional down inactive) 568 (defvar widget-button-pressed-face 'widget-button-pressed-face
569 "Face used for pressed buttons in widgets.
570 This exists as a variable so it can be set locally in certain
571 buffers.")
572
573 (defun widget-image-insert (widget tag image &optional down inactive)
613 "In WIDGET, insert the text TAG or, if supported, IMAGE. 574 "In WIDGET, insert the text TAG or, if supported, IMAGE.
614 IMAGE should either be a glyph, an image instantiator, or an image file 575 IMAGE should either be an image or an image file name sans extension
615 name sans extension (xpm, xbm, gif, jpg, or png) located in 576 \(xpm, xbm, gif, jpg, or png) located in `widget-image-directory'.
616 `widget-glyph-directory'. 577
617 578 Optional arguments DOWN and INACTIVE are used instead of IMAGE when the
618 Optional arguments DOWN and INACTIVE is used instead of IMAGE when the 579 button is pressed or inactive, respectively. These are currently ignored."
619 glyph is pressed or inactive, respectively. 580 (if (and (display-graphic-p)
620 581 (setq image (widget-image-find image)))
621 WARNING: If you call this with a glyph, and you want the user to be 582 (progn (widget-put widget :suppress-face t)
622 able to invoke the glyph, make sure it is unique. If you use the 583 (insert-image image
623 same glyph for multiple widgets, invoking any of the glyphs will 584 (propertize
624 cause the last created widget to be invoked. 585 tag 'mouse-face widget-button-pressed-face)))
625 586 (insert tag)))
626 Instead of an instantiator, you can also use a list of instantiators,
627 or whatever `make-glyph' will accept. However, in that case you must
628 provide the fallback TAG as a part of the instantiator yourself."
629 (let ((glyph (widget-glyph-find image tag)))
630 (if glyph
631 (widget-glyph-insert-glyph widget
632 glyph
633 (widget-glyph-find down tag)
634 (widget-glyph-find inactive tag))
635 (insert tag))))
636
637 (defun widget-glyph-insert-glyph (widget glyph &optional down inactive)
638 "In WIDGET, insert GLYPH.
639 If optional arguments DOWN and INACTIVE are given, they should be
640 glyphs used when the widget is pushed and inactive, respectively."
641 (when widget
642 (set-glyph-property glyph 'widget widget)
643 (when down
644 (set-glyph-property down 'widget widget))
645 (when inactive
646 (set-glyph-property inactive 'widget widget)))
647 (insert "*")
648 (let ((ext (make-extent (point) (1- (point))))
649 (help-echo (and widget (widget-get widget :help-echo))))
650 (set-extent-property ext 'invisible t)
651 (set-extent-property ext 'start-open t)
652 (set-extent-property ext 'end-open t)
653 (set-extent-end-glyph ext glyph)
654 (when help-echo
655 (set-extent-property ext 'balloon-help help-echo)
656 (set-extent-property ext 'help-echo help-echo)))
657 (when widget
658 (widget-put widget :glyph-up glyph)
659 (when down (widget-put widget :glyph-down down))
660 (when inactive (widget-put widget :glyph-inactive inactive))))
661 587
662 ;;; Buttons. 588 ;;; Buttons.
663 589
664 (defgroup widget-button nil 590 (defgroup widget-button nil
665 "The look of various kinds of buttons." 591 "The look of various kinds of buttons."
677 603
678 ;;; Creating Widgets. 604 ;;; Creating Widgets.
679 605
680 ;;;###autoload 606 ;;;###autoload
681 (defun widget-create (type &rest args) 607 (defun widget-create (type &rest args)
682 "Create widget of TYPE. 608 "Create widget of TYPE.
683 The optional ARGS are additional keyword arguments." 609 The optional ARGS are additional keyword arguments."
684 (let ((widget (apply 'widget-convert type args))) 610 (let ((widget (apply 'widget-convert type args)))
685 (widget-apply widget :create) 611 (widget-apply widget :create)
686 widget)) 612 widget))
687 613
724 (defun widget-delete (widget) 650 (defun widget-delete (widget)
725 "Delete WIDGET." 651 "Delete WIDGET."
726 (widget-apply widget :delete)) 652 (widget-apply widget :delete))
727 653
728 (defun widget-convert (type &rest args) 654 (defun widget-convert (type &rest args)
729 "Convert TYPE to a widget without inserting it in the buffer. 655 "Convert TYPE to a widget without inserting it in the buffer.
730 The optional ARGS are additional keyword arguments." 656 The optional ARGS are additional keyword arguments."
731 ;; Don't touch the type. 657 ;; Don't touch the type.
732 (let* ((widget (if (symbolp type) 658 (let* ((widget (if (symbolp type)
733 (list type) 659 (list type)
734 (copy-sequence type))) 660 (copy-sequence type)))
735 (current widget) 661 (current widget)
736 (keys args)) 662 (keys args))
737 ;; First set the :args keyword. 663 ;; First set the :args keyword.
738 (while (cdr current) ;Look in the type. 664 (while (cdr current) ;Look in the type.
739 (let ((next (car (cdr current)))) 665 (let ((next (car (cdr current))))
740 (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) 666 (if (keywordp next)
741 (setq current (cdr (cdr current))) 667 (setq current (cdr (cdr current)))
742 (setcdr current (list :args (cdr current))) 668 (setcdr current (list :args (cdr current)))
743 (setq current nil)))) 669 (setq current nil))))
744 (while args ;Look in the args. 670 (while args ;Look in the args.
745 (let ((next (nth 0 args))) 671 (let ((next (nth 0 args)))
746 (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) 672 (if (keywordp next)
747 (setq args (nthcdr 2 args)) 673 (setq args (nthcdr 2 args))
748 (widget-put widget :args args) 674 (widget-put widget :args args)
749 (setq args nil)))) 675 (setq args nil))))
750 ;; Then Convert the widget. 676 ;; Then Convert the widget.
751 (setq type widget) 677 (setq type widget)
753 (let ((convert-widget (plist-get (cdr type) :convert-widget))) 679 (let ((convert-widget (plist-get (cdr type) :convert-widget)))
754 (if convert-widget 680 (if convert-widget
755 (setq widget (funcall convert-widget widget)))) 681 (setq widget (funcall convert-widget widget))))
756 (setq type (get (car type) 'widget-type))) 682 (setq type (get (car type) 'widget-type)))
757 ;; Finally set the keyword args. 683 ;; Finally set the keyword args.
758 (while keys 684 (while keys
759 (let ((next (nth 0 keys))) 685 (let ((next (nth 0 keys)))
760 (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) 686 (if (keywordp next)
761 (progn 687 (progn
762 (widget-put widget next (nth 1 keys)) 688 (widget-put widget next (nth 1 keys))
763 (setq keys (nthcdr 2 keys))) 689 (setq keys (nthcdr 2 keys)))
764 (setq keys nil)))) 690 (setq keys nil))))
765 ;; Convert the :value to internal format. 691 ;; Convert the :value to internal format.
766 (if (widget-member widget :value) 692 (if (widget-member widget :value)
823 (delete-overlay sample)) 749 (delete-overlay sample))
824 (when doc 750 (when doc
825 (delete-overlay doc)) 751 (delete-overlay doc))
826 (when field 752 (when field
827 (delete-overlay field)) 753 (delete-overlay field))
828 (mapcar 'widget-leave-text children))) 754 (mapc 'widget-leave-text children)))
829 755
830 ;;; Keymap and Commands. 756 ;;; Keymap and Commands.
831 757
832 (defvar widget-keymap nil 758 (defvar widget-keymap
759 (let ((map (make-sparse-keymap)))
760 (define-key map "\t" 'widget-forward)
761 (define-key map [(shift tab)] 'widget-backward)
762 (define-key map [backtab] 'widget-backward)
763 (define-key map [down-mouse-2] 'widget-button-click)
764 (define-key map "\C-m" 'widget-button-press)
765 map)
833 "Keymap containing useful binding for buffers containing widgets. 766 "Keymap containing useful binding for buffers containing widgets.
834 Recommended as a parent keymap for modes using widgets.") 767 Recommended as a parent keymap for modes using widgets.")
835
836 (unless widget-keymap
837 (setq widget-keymap (make-sparse-keymap))
838 (define-key widget-keymap "\t" 'widget-forward)
839 (define-key widget-keymap [(shift tab)] 'widget-backward)
840 (define-key widget-keymap [backtab] 'widget-backward)
841 (if (string-match "XEmacs" emacs-version)
842 (progn
843 ;;Glyph support.
844 (define-key widget-keymap [button1] 'widget-button1-click)
845 (define-key widget-keymap [button2] 'widget-button-click))
846 (define-key widget-keymap [down-mouse-2] 'widget-button-click))
847 (define-key widget-keymap "\C-m" 'widget-button-press))
848 768
849 (defvar widget-global-map global-map 769 (defvar widget-global-map global-map
850 "Keymap used for events the widget does not handle themselves.") 770 "Keymap used for events the widget does not handle themselves.")
851 (make-variable-buffer-local 'widget-global-map) 771 (make-variable-buffer-local 'widget-global-map)
852 772
853 (defvar widget-field-keymap nil 773 (defvar widget-field-keymap
774 (let ((map (copy-keymap widget-keymap)))
775 (define-key map [menu-bar] nil)
776 (define-key map "\C-k" 'widget-kill-line)
777 (define-key map "\M-\t" 'widget-complete)
778 (define-key map "\C-m" 'widget-field-activate)
779 (define-key map "\C-a" 'widget-beginning-of-line)
780 (define-key map "\C-e" 'widget-end-of-line)
781 (set-keymap-parent map global-map)
782 map)
854 "Keymap used inside an editable field.") 783 "Keymap used inside an editable field.")
855 784
856 (unless widget-field-keymap 785 (defvar widget-text-keymap
857 (setq widget-field-keymap (copy-keymap widget-keymap)) 786 (let ((map (copy-keymap widget-keymap)))
858 (define-key widget-field-keymap [menu-bar] 'nil) 787 (define-key map [menu-bar] 'nil)
859 (define-key widget-field-keymap "\C-k" 'widget-kill-line) 788 (define-key map "\C-a" 'widget-beginning-of-line)
860 (define-key widget-field-keymap "\M-\t" 'widget-complete) 789 (define-key map "\C-e" 'widget-end-of-line)
861 (define-key widget-field-keymap "\C-m" 'widget-field-activate) 790 (set-keymap-parent map global-map)
862 (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line) 791 map)
863 (define-key widget-field-keymap "\C-e" 'widget-end-of-line)
864 (set-keymap-parent widget-field-keymap global-map))
865
866 (defvar widget-text-keymap nil
867 "Keymap used inside a text field.") 792 "Keymap used inside a text field.")
868
869 (unless widget-text-keymap
870 (setq widget-text-keymap (copy-keymap widget-keymap))
871 (define-key widget-text-keymap [menu-bar] 'nil)
872 (define-key widget-text-keymap "\C-a" 'widget-beginning-of-line)
873 (define-key widget-text-keymap "\C-e" 'widget-end-of-line)
874 (set-keymap-parent widget-text-keymap global-map))
875 793
876 (defun widget-field-activate (pos &optional event) 794 (defun widget-field-activate (pos &optional event)
877 "Invoke the ediable field at point." 795 "Invoke the ediable field at point."
878 (interactive "@d") 796 (interactive "@d")
879 (let ((field (get-char-property pos 'field))) 797 (let ((field (get-char-property pos 'field)))
880 (if field 798 (if field
881 (widget-apply-action field event) 799 (widget-apply-action field event)
882 (call-interactively 800 (call-interactively
883 (lookup-key widget-global-map (this-command-keys)))))) 801 (lookup-key widget-global-map (this-command-keys))))))
884 802
885 (defvar widget-button-pressed-face 'widget-button-pressed-face 803 (defface widget-button-pressed-face
886 "Face used for pressed buttons in widgets.
887 This exists as a variable so it can be set locally in certain buffers.")
888
889 (defface widget-button-pressed-face
890 '((((class color)) 804 '((((class color))
891 (:foreground "red")) 805 (:foreground "red"))
892 (t 806 (t
893 (:bold t :underline t))) 807 (:bold t :underline t)))
894 "Face used for pressed buttons." 808 "Face used for pressed buttons."
895 :group 'widget-faces) 809 :group 'widget-faces)
896 810
897 (defun widget-button-click (event) 811 (defun widget-button-click (event)
898 "Invoke the button that the mouse is pointing at, and move there." 812 "Invoke the button that the mouse is pointing at."
899 (interactive "@e") 813 (interactive "@e")
900 (mouse-set-point event) 814 (if (widget-event-point event)
901 (cond ((and (fboundp 'event-glyph) 815 (save-excursion
902 (event-glyph event)) 816 (mouse-set-point event)
903 (widget-glyph-click event)) 817 (let* ((pos (widget-event-point event))
904 ((widget-event-point event) 818 (button (get-char-property pos 'button)))
905 (let* ((pos (widget-event-point event)) 819 (if button
906 (button (get-char-property pos 'button))) 820 (let* ((overlay (widget-get button :button-overlay))
907 (if button 821 (face (overlay-get overlay 'face))
908 (let* ((overlay (widget-get button :button-overlay)) 822 (mouse-face (overlay-get overlay 'mouse-face)))
909 (face (overlay-get overlay 'face)) 823 (unwind-protect
910 (mouse-face (overlay-get overlay 'mouse-face))) 824 (let ((track-mouse t))
911 (unwind-protect 825 (save-excursion
912 (let ((track-mouse t)) 826 (when face ; avoid changing around image
913 (save-excursion 827 (overlay-put overlay
914 (overlay-put overlay 828 'face widget-button-pressed-face)
915 'face widget-button-pressed-face) 829 (overlay-put overlay
916 (overlay-put overlay 830 'mouse-face widget-button-pressed-face))
917 'mouse-face widget-button-pressed-face) 831 (unless (widget-apply button :mouse-down-action event)
918 (unless (widget-apply button :mouse-down-action event) 832 (while (not (widget-button-release-event-p event))
919 (while (not (button-release-event-p event)) 833 (setq event (read-event)
920 (setq event (widget-read-event) 834 pos (widget-event-point event))
921 pos (widget-event-point event)) 835 (if (and pos
922 (if (and pos 836 (eq (get-char-property pos 'button)
923 (eq (get-char-property pos 'button) 837 button))
924 button)) 838 (when face
925 (progn 839 (overlay-put overlay
926 (overlay-put overlay 840 'face
927 'face 841 widget-button-pressed-face)
928 widget-button-pressed-face) 842 (overlay-put overlay
929 (overlay-put overlay 843 'mouse-face
930 'mouse-face 844 widget-button-pressed-face))
931 widget-button-pressed-face)) 845 (overlay-put overlay 'face face)
932 (overlay-put overlay 'face face) 846 (overlay-put overlay 'mouse-face mouse-face))))
933 (overlay-put overlay 'mouse-face mouse-face)))) 847 (when (and pos
934 (when (and pos 848 (eq (get-char-property pos 'button) button))
935 (eq (get-char-property pos 'button) button)) 849 (widget-apply-action button event))))
936 (widget-apply-action button event)))) 850 (overlay-put overlay 'face face)
937 (overlay-put overlay 'face face) 851 (overlay-put overlay 'mouse-face mouse-face)))
938 (overlay-put overlay 'mouse-face mouse-face))) 852 (let ((up t)
939 (let ((up t) 853 command)
940 command) 854 ;; Find the global command to run, and check whether it
941 ;; Find the global command to run, and check whether it 855 ;; is bound to an up event.
942 ;; is bound to an up event. 856 (if (memq (event-basic-type event) '(mouse-1 down-mouse-1))
943 (cond ((setq command ;down event 857 (cond ((setq command ;down event
944 (lookup-key widget-global-map [ button2 ])) 858 (lookup-key widget-global-map [down-mouse-1]))
945 (setq up nil)) 859 (setq up nil))
946 ((setq command ;down event 860 ((setq command ;up event
947 (lookup-key widget-global-map [ down-mouse-2 ])) 861 (lookup-key widget-global-map [mouse-1]))))
948 (setq up nil)) 862 (cond ((setq command ;down event
949 ((setq command ;up event 863 (lookup-key widget-global-map [down-mouse-2]))
950 (lookup-key widget-global-map [ button2up ]))) 864 (setq up nil))
951 ((setq command ;up event 865 ((setq command ;up event
952 (lookup-key widget-global-map [ mouse-2])))) 866 (lookup-key widget-global-map [mouse-2])))))
953 (when up 867 (when up
954 ;; Don't execute up events twice. 868 ;; Don't execute up events twice.
955 (while (not (button-release-event-p event)) 869 (while (not (widget-button-release-event-p event))
956 (setq event (widget-read-event)))) 870 (setq event (read-event))))
957 (when command 871 (when command
958 (call-interactively command)))))) 872 (call-interactively command)))))
959 (t 873 (unless (pos-visible-in-window-p (widget-event-point event))
960 (message "You clicked somewhere weird.")))) 874 (mouse-set-point event)
961 875 (beginning-of-line)
962 (defun widget-button1-click (event) 876 (recenter)))
963 "Invoke glyph below mouse pointer." 877 (message "You clicked somewhere weird.")))
964 (interactive "@e")
965 (if (and (fboundp 'event-glyph)
966 (event-glyph event))
967 (widget-glyph-click event)
968 (call-interactively (lookup-key widget-global-map (this-command-keys)))))
969
970 (defun widget-glyph-click (event)
971 "Handle click on a glyph."
972 (let* ((glyph (event-glyph event))
973 (widget (glyph-property glyph 'widget))
974 (extent (event-glyph-extent event))
975 (down-glyph (or (and widget (widget-get widget :glyph-down)) glyph))
976 (up-glyph (or (and widget (widget-get widget :glyph-up)) glyph))
977 (last event))
978 ;; Wait for the release.
979 (while (not (button-release-event-p last))
980 (if (eq extent (event-glyph-extent last))
981 (set-extent-property extent 'end-glyph down-glyph)
982 (set-extent-property extent 'end-glyph up-glyph))
983 (setq last (read-event event)))
984 ;; Release glyph.
985 (when down-glyph
986 (set-extent-property extent 'end-glyph up-glyph))
987 ;; Apply widget action.
988 (when (eq extent (event-glyph-extent last))
989 (let ((widget (glyph-property (event-glyph event) 'widget)))
990 (cond ((null widget)
991 (message "You clicked on a glyph."))
992 ((not (widget-apply widget :active))
993 (message "This glyph is inactive."))
994 (t
995 (widget-apply-action widget event)))))))
996 878
997 (defun widget-button-press (pos &optional event) 879 (defun widget-button-press (pos &optional event)
998 "Invoke button at POS." 880 "Invoke button at POS."
999 (interactive "@d") 881 (interactive "@d")
1000 (let ((button (get-char-property pos 'button))) 882 (let ((button (get-char-property pos 'button)))
1007 (defun widget-tabable-at (&optional pos) 889 (defun widget-tabable-at (&optional pos)
1008 "Return the tabable widget at POS, or nil. 890 "Return the tabable widget at POS, or nil.
1009 POS defaults to the value of (point)." 891 POS defaults to the value of (point)."
1010 (unless pos 892 (unless pos
1011 (setq pos (point))) 893 (setq pos (point)))
1012 (let ((widget (or (get-char-property (point) 'button) 894 (let ((widget (or (get-char-property pos 'button)
1013 (get-char-property (point) 'field)))) 895 (get-char-property pos 'field))))
1014 (if widget 896 (if widget
1015 (let ((order (widget-get widget :tab-order))) 897 (let ((order (widget-get widget :tab-order)))
1016 (if order 898 (if order
1017 (if (>= order 0) 899 (if (>= order 0)
1018 widget 900 widget)
1019 nil) 901 widget)))))
1020 widget))
1021 nil)))
1022 902
1023 (defvar widget-use-overlay-change t 903 (defvar widget-use-overlay-change t
1024 "If non-nil, use overlay change functions to tab around in the buffer. 904 "If non-nil, use overlay change functions to tab around in the buffer.
1025 This is much faster, but doesn't work reliably on Emacs 19.34.") 905 This is much faster, but doesn't work reliably on Emacs 19.34.")
1026 906
1087 (defun widget-beginning-of-line () 967 (defun widget-beginning-of-line ()
1088 "Go to beginning of field or beginning of line, whichever is first." 968 "Go to beginning of field or beginning of line, whichever is first."
1089 (interactive) 969 (interactive)
1090 (let* ((field (widget-field-find (point))) 970 (let* ((field (widget-field-find (point)))
1091 (start (and field (widget-field-start field))) 971 (start (and field (widget-field-start field)))
1092 (bol (save-excursion 972 (bol (line-beginning-position)))
1093 (beginning-of-line)
1094 (point))))
1095 (goto-char (if start 973 (goto-char (if start
1096 (max start bol) 974 (max start bol)
1097 bol)))) 975 bol))))
1098 976
1099 (defun widget-end-of-line () 977 (defun widget-end-of-line ()
1100 "Go to end of field or end of line, whichever is first." 978 "Go to end of field or end of line, whichever is first."
1101 (interactive) 979 (interactive)
1102 (let* ((field (widget-field-find (point))) 980 (let* ((field (widget-field-find (point)))
1103 (end (and field (widget-field-end field))) 981 (end (and field (widget-field-end field)))
1104 (eol (save-excursion 982 (eol (line-end-position)))
1105 (end-of-line)
1106 (point))))
1107 (goto-char (if end 983 (goto-char (if end
1108 (min end eol) 984 (min end eol)
1109 eol)))) 985 eol))))
1110 986
1111 (defun widget-kill-line () 987 (defun widget-kill-line ()
1153 (setq field (car widget-field-new) 1029 (setq field (car widget-field-new)
1154 widget-field-new (cdr widget-field-new) 1030 widget-field-new (cdr widget-field-new)
1155 widget-field-list (cons field widget-field-list)) 1031 widget-field-list (cons field widget-field-list))
1156 (let ((from (car (widget-get field :field-overlay))) 1032 (let ((from (car (widget-get field :field-overlay)))
1157 (to (cdr (widget-get field :field-overlay)))) 1033 (to (cdr (widget-get field :field-overlay))))
1158 (widget-specify-field field 1034 (widget-specify-field field
1159 (marker-position from) (marker-position to)) 1035 (marker-position from) (marker-position to))
1160 (set-marker from nil) 1036 (set-marker from nil)
1161 (set-marker to nil)))) 1037 (set-marker to nil))))
1162 (widget-clear-undo) 1038 (widget-clear-undo)
1163 (widget-add-change)) 1039 (widget-add-change))
1231 (add-hook 'before-change-functions 'widget-before-change nil t) 1107 (add-hook 'before-change-functions 'widget-before-change nil t)
1232 (make-local-hook 'after-change-functions) 1108 (make-local-hook 'after-change-functions)
1233 (add-hook 'after-change-functions 'widget-after-change nil t)) 1109 (add-hook 'after-change-functions 'widget-after-change nil t))
1234 1110
1235 (defun widget-after-change (from to old) 1111 (defun widget-after-change (from to old)
1236 ;; Adjust field size and text properties. 1112 "Adjust field size and text properties."
1237 (condition-case nil 1113 (condition-case nil
1238 (let ((field (widget-field-find from)) 1114 (let ((field (widget-field-find from))
1239 (other (widget-field-find to))) 1115 (other (widget-field-find to)))
1240 (when field 1116 (when field
1241 (unless (eq field other) 1117 (unless (eq field other)
1242 (debug "Change in different fields")) 1118 (debug "Change in different fields"))
1243 (let ((size (widget-get field :size))) 1119 (let ((size (widget-get field :size)))
1244 (when size 1120 (when size
1245 (let ((begin (widget-field-start field)) 1121 (let ((begin (widget-field-start field))
1246 (end (widget-field-end field))) 1122 (end (widget-field-end field)))
1247 (cond ((< (- end begin) size) 1123 (cond ((< (- end begin) size)
1248 ;; Field too small. 1124 ;; Field too small.
1249 (save-excursion 1125 (save-excursion
1266 (widget-apply field :notify field))) 1142 (widget-apply field :notify field)))
1267 (error (debug "After Change")))) 1143 (error (debug "After Change"))))
1268 1144
1269 ;;; Widget Functions 1145 ;;; Widget Functions
1270 ;; 1146 ;;
1271 ;; These functions are used in the definition of multiple widgets. 1147 ;; These functions are used in the definition of multiple widgets.
1272 1148
1273 (defun widget-parent-action (widget &optional event) 1149 (defun widget-parent-action (widget &optional event)
1274 "Tell :parent of WIDGET to handle the :action. 1150 "Tell :parent of WIDGET to handle the :action.
1275 Optional EVENT is the event that triggered the action." 1151 Optional EVENT is the event that triggered the action."
1276 (widget-apply (widget-get widget :parent) :action event)) 1152 (widget-apply (widget-get widget :parent) :action event))
1277 1153
1278 (defun widget-children-value-delete (widget) 1154 (defun widget-children-value-delete (widget)
1279 "Delete all :children and :buttons in WIDGET." 1155 "Delete all :children and :buttons in WIDGET."
1280 (mapcar 'widget-delete (widget-get widget :children)) 1156 (mapc 'widget-delete (widget-get widget :children))
1281 (widget-put widget :children nil) 1157 (widget-put widget :children nil)
1282 (mapcar 'widget-delete (widget-get widget :buttons)) 1158 (mapc 'widget-delete (widget-get widget :buttons))
1283 (widget-put widget :buttons nil)) 1159 (widget-put widget :buttons nil))
1284 1160
1285 (defun widget-children-validate (widget) 1161 (defun widget-children-validate (widget)
1286 "All the :children must be valid." 1162 "All the :children must be valid."
1287 (let ((children (widget-get widget :children)) 1163 (let ((children (widget-get widget :children))
1298 widget) 1174 widget)
1299 1175
1300 (defun widget-value-convert-widget (widget) 1176 (defun widget-value-convert-widget (widget)
1301 "Initialize :value from :args in WIDGET." 1177 "Initialize :value from :args in WIDGET."
1302 (let ((args (widget-get widget :args))) 1178 (let ((args (widget-get widget :args)))
1303 (when args 1179 (when args
1304 (widget-put widget :value (car args)) 1180 (widget-put widget :value (car args))
1305 ;; Don't convert :value here, as this is done in `widget-convert'. 1181 ;; Don't convert :value here, as this is done in `widget-convert'.
1306 ;; (widget-put widget :value (widget-apply widget 1182 ;; (widget-put widget :value (widget-apply widget
1307 ;; :value-to-internal (car args))) 1183 ;; :value-to-internal (car args)))
1308 (widget-put widget :args nil))) 1184 (widget-put widget :args nil)))
1318 "Basic widget other widgets are derived from." 1194 "Basic widget other widgets are derived from."
1319 :value-to-internal (lambda (widget value) value) 1195 :value-to-internal (lambda (widget value) value)
1320 :value-to-external (lambda (widget value) value) 1196 :value-to-external (lambda (widget value) value)
1321 :button-prefix 'widget-button-prefix 1197 :button-prefix 'widget-button-prefix
1322 :button-suffix 'widget-button-suffix 1198 :button-suffix 'widget-button-suffix
1323 :complete 'widget-default-complete 1199 :complete 'widget-default-complete
1324 :create 'widget-default-create 1200 :create 'widget-default-create
1325 :indent nil 1201 :indent nil
1326 :offset 0 1202 :offset 0
1327 :format-handler 'widget-default-format-handler 1203 :format-handler 'widget-default-format-handler
1328 :button-face-get 'widget-default-button-face-get 1204 :button-face-get 'widget-default-button-face-get
1360 ;; Parse escapes in format. 1236 ;; Parse escapes in format.
1361 (while (re-search-forward "%\\(.\\)" nil t) 1237 (while (re-search-forward "%\\(.\\)" nil t)
1362 (let ((escape (aref (match-string 1) 0))) 1238 (let ((escape (aref (match-string 1) 0)))
1363 (replace-match "" t t) 1239 (replace-match "" t t)
1364 (cond ((eq escape ?%) 1240 (cond ((eq escape ?%)
1365 (insert "%")) 1241 (insert ?%))
1366 ((eq escape ?\[) 1242 ((eq escape ?\[)
1367 (setq button-begin (point)) 1243 (setq button-begin (point))
1368 (insert (widget-get-indirect widget :button-prefix))) 1244 (insert (widget-get-indirect widget :button-prefix)))
1369 ((eq escape ?\]) 1245 ((eq escape ?\])
1370 (insert (widget-get-indirect widget :button-suffix)) 1246 (insert (widget-get-indirect widget :button-suffix))
1373 (setq sample-begin (point))) 1249 (setq sample-begin (point)))
1374 ((eq escape ?\}) 1250 ((eq escape ?\})
1375 (setq sample-end (point))) 1251 (setq sample-end (point)))
1376 ((eq escape ?n) 1252 ((eq escape ?n)
1377 (when (widget-get widget :indent) 1253 (when (widget-get widget :indent)
1378 (insert "\n") 1254 (insert ?\n)
1379 (insert-char ? (widget-get widget :indent)))) 1255 (insert-char ? (widget-get widget :indent))))
1380 ((eq escape ?t) 1256 ((eq escape ?t)
1381 (let ((glyph (widget-get widget :tag-glyph)) 1257 (let ((image (widget-get widget :tag-glyph))
1382 (tag (widget-get widget :tag))) 1258 (tag (widget-get widget :tag)))
1383 (cond (glyph 1259 (cond (image
1384 (widget-glyph-insert widget (or tag "image") glyph)) 1260 (widget-image-insert widget (or tag "image") image))
1385 (tag 1261 (tag
1386 (insert tag)) 1262 (insert tag))
1387 (t 1263 (t
1388 (let ((standard-output (current-buffer))) 1264 (princ (widget-get widget :value)
1389 (princ (widget-get widget :value))))))) 1265 (current-buffer))))))
1390 ((eq escape ?d) 1266 ((eq escape ?d)
1391 (let ((doc (widget-get widget :doc))) 1267 (let ((doc (widget-get widget :doc)))
1392 (when doc 1268 (when doc
1393 (setq doc-begin (point)) 1269 (setq doc-begin (point))
1394 (insert doc) 1270 (insert doc)
1395 (while (eq (preceding-char) ?\n) 1271 (while (eq (preceding-char) ?\n)
1396 (delete-backward-char 1)) 1272 (delete-backward-char 1))
1397 (insert "\n") 1273 (insert ?\n)
1398 (setq doc-end (point))))) 1274 (setq doc-end (point)))))
1399 ((eq escape ?v) 1275 ((eq escape ?v)
1400 (if (and button-begin (not button-end)) 1276 (if (and button-begin (not button-end))
1401 (widget-apply widget :value-create) 1277 (widget-apply widget :value-create)
1402 (setq value-pos (point)))) 1278 (setq value-pos (point))))
1403 (t 1279 (t
1404 (widget-apply widget :format-handler escape))))) 1280 (widget-apply widget :format-handler escape)))))
1405 ;; Specify button, sample, and doc, and insert value. 1281 ;; Specify button, sample, and doc, and insert value.
1406 (and button-begin button-end 1282 (and button-begin button-end
1407 (widget-specify-button widget button-begin button-end)) 1283 (widget-specify-button widget button-begin button-end))
1408 (and sample-begin sample-end 1284 (and sample-begin sample-end
1425 (let* ((buttons (widget-get widget :buttons))) 1301 (let* ((buttons (widget-get widget :buttons)))
1426 (cond ((eq escape ?h) 1302 (cond ((eq escape ?h)
1427 (let* ((doc-property (widget-get widget :documentation-property)) 1303 (let* ((doc-property (widget-get widget :documentation-property))
1428 (doc-try (cond ((widget-get widget :doc)) 1304 (doc-try (cond ((widget-get widget :doc))
1429 ((symbolp doc-property) 1305 ((symbolp doc-property)
1430 (documentation-property 1306 (documentation-property
1431 (widget-get widget :value) 1307 (widget-get widget :value)
1432 doc-property)) 1308 doc-property))
1433 (t 1309 (t
1434 (funcall doc-property 1310 (funcall doc-property
1435 (widget-get widget :value))))) 1311 (widget-get widget :value)))))
1454 ((null doc-indent) 1330 ((null doc-indent)
1455 nil) 1331 nil)
1456 (t 0)) 1332 (t 0))
1457 doc-text) 1333 doc-text)
1458 buttons)))) 1334 buttons))))
1459 (t 1335 (t
1460 (error "Unknown escape `%c'" escape))) 1336 (error "Unknown escape `%c'" escape)))
1461 (widget-put widget :buttons buttons))) 1337 (widget-put widget :buttons buttons)))
1462 1338
1463 (defun widget-default-button-face-get (widget) 1339 (defun widget-default-button-face-get (widget)
1464 ;; Use :button-face or widget-button-face 1340 ;; Use :button-face or widget-button-face
1471 (defun widget-default-sample-face-get (widget) 1347 (defun widget-default-sample-face-get (widget)
1472 ;; Use :sample-face. 1348 ;; Use :sample-face.
1473 (widget-get widget :sample-face)) 1349 (widget-get widget :sample-face))
1474 1350
1475 (defun widget-default-delete (widget) 1351 (defun widget-default-delete (widget)
1476 ;; Remove widget from the buffer. 1352 "Remove widget from the buffer."
1477 (let ((from (widget-get widget :from)) 1353 (let ((from (widget-get widget :from))
1478 (to (widget-get widget :to)) 1354 (to (widget-get widget :to))
1479 (inactive-overlay (widget-get widget :inactive)) 1355 (inactive-overlay (widget-get widget :inactive))
1480 (button-overlay (widget-get widget :button-overlay)) 1356 (button-overlay (widget-get widget :button-overlay))
1481 (sample-overlay (widget-get widget :sample-overlay)) 1357 (sample-overlay (widget-get widget :sample-overlay))
1498 (set-marker from nil) 1374 (set-marker from nil)
1499 (set-marker to nil)) 1375 (set-marker to nil))
1500 (widget-clear-undo)) 1376 (widget-clear-undo))
1501 1377
1502 (defun widget-default-value-set (widget value) 1378 (defun widget-default-value-set (widget value)
1503 ;; Recreate widget with new value. 1379 "Recreate widget with new value."
1504 (let* ((old-pos (point)) 1380 (let* ((old-pos (point))
1505 (from (copy-marker (widget-get widget :from))) 1381 (from (copy-marker (widget-get widget :from)))
1506 (to (copy-marker (widget-get widget :to))) 1382 (to (copy-marker (widget-get widget :to)))
1507 (offset (if (and (<= from old-pos) (<= old-pos to)) 1383 (offset (if (and (<= from old-pos) (<= old-pos to))
1508 (if (>= old-pos (1- to)) 1384 (if (>= old-pos (1- to))
1509 (- old-pos to 1) 1385 (- old-pos to 1)
1510 (- old-pos from))))) 1386 (- old-pos from)))))
1511 ;;??? Bug: this ought to insert the new value before deleting the old one, 1387 ;;??? Bug: this ought to insert the new value before deleting the old one,
1512 ;; so that markers on either side of the value automatically 1388 ;; so that markers on either side of the value automatically
1513 ;; stay on the same side. -- rms. 1389 ;; stay on the same side. -- rms.
1514 (save-excursion 1390 (save-excursion
1515 (goto-char (widget-get widget :from)) 1391 (goto-char (widget-get widget :from))
1516 (widget-apply widget :delete) 1392 (widget-apply widget :delete)
1517 (widget-put widget :value value) 1393 (widget-put widget :value value)
1520 (if (< offset 0) 1396 (if (< offset 0)
1521 (goto-char (+ (widget-get widget :to) offset 1)) 1397 (goto-char (+ (widget-get widget :to) offset 1))
1522 (goto-char (min (+ from offset) (1- (widget-get widget :to)))))))) 1398 (goto-char (min (+ from offset) (1- (widget-get widget :to))))))))
1523 1399
1524 (defun widget-default-value-inline (widget) 1400 (defun widget-default-value-inline (widget)
1525 ;; Wrap value in a list unless it is inline. 1401 "Wrap value in a list unless it is inline."
1526 (if (widget-get widget :inline) 1402 (if (widget-get widget :inline)
1527 (widget-value widget) 1403 (widget-value widget)
1528 (list (widget-value widget)))) 1404 (list (widget-value widget))))
1529 1405
1530 (defun widget-default-default-get (widget) 1406 (defun widget-default-default-get (widget)
1531 ;; Get `:value'. 1407 "Get `:value'."
1532 (widget-get widget :value)) 1408 (widget-get widget :value))
1533 1409
1534 (defun widget-default-menu-tag-get (widget) 1410 (defun widget-default-menu-tag-get (widget)
1535 ;; Use tag or value for menus. 1411 "Use tag or value for menus."
1536 (or (widget-get widget :menu-tag) 1412 (or (widget-get widget :menu-tag)
1537 (widget-get widget :tag) 1413 (widget-get widget :tag)
1538 (widget-princ-to-string (widget-get widget :value)))) 1414 (widget-princ-to-string (widget-get widget :value))))
1539 1415
1540 (defun widget-default-active (widget) 1416 (defun widget-default-active (widget)
1550 (widget-specify-inactive widget 1426 (widget-specify-inactive widget
1551 (widget-get widget :from) 1427 (widget-get widget :from)
1552 (widget-get widget :to))) 1428 (widget-get widget :to)))
1553 1429
1554 (defun widget-default-action (widget &optional event) 1430 (defun widget-default-action (widget &optional event)
1555 ;; Notify the parent when a widget change 1431 "Notify the parent when a widget changes."
1556 (let ((parent (widget-get widget :parent))) 1432 (let ((parent (widget-get widget :parent)))
1557 (when parent 1433 (when parent
1558 (widget-apply parent :notify widget event)))) 1434 (widget-apply parent :notify widget event))))
1559 1435
1560 (defun widget-default-notify (widget child &optional event) 1436 (defun widget-default-notify (widget child &optional event)
1561 ;; Pass notification to parent. 1437 "Pass notification to parent."
1562 (widget-default-action widget event)) 1438 (widget-default-action widget event))
1563 1439
1564 (defun widget-default-prompt-value (widget prompt value unbound) 1440 (defun widget-default-prompt-value (widget prompt value unbound)
1565 ;; Read an arbitrary value. Stolen from `set-variable'. 1441 "Read an arbitrary value. Stolen from `set-variable'."
1566 ;; (let ((initial (if unbound 1442 ;; (let ((initial (if unbound
1567 ;; nil 1443 nil
1568 ;; ;; It would be nice if we could do a `(cons val 1)' here. 1444 ;; It would be nice if we could do a `(cons val 1)' here.
1569 ;; (prin1-to-string (custom-quote value)))))) 1445 ;; (prin1-to-string (custom-quote value))))))
1570 (eval-minibuffer prompt )) 1446 (eval-minibuffer prompt ))
1571 1447
1572 ;;; The `item' Widget. 1448 ;;; The `item' Widget.
1573 1449
1574 (define-widget 'item 'default 1450 (define-widget 'item 'default
1581 :match-inline 'widget-item-match-inline 1457 :match-inline 'widget-item-match-inline
1582 :action 'widget-item-action 1458 :action 'widget-item-action
1583 :format "%t\n") 1459 :format "%t\n")
1584 1460
1585 (defun widget-item-value-create (widget) 1461 (defun widget-item-value-create (widget)
1586 ;; Insert the printed representation of the value. 1462 "Insert the printed representation of the value."
1587 (let ((standard-output (current-buffer))) 1463 (princ (widget-get widget :value) (current-buffer)))
1588 (princ (widget-get widget :value))))
1589 1464
1590 (defun widget-item-match (widget value) 1465 (defun widget-item-match (widget value)
1591 ;; Match if the value is the same. 1466 ;; Match if the value is the same.
1592 (equal (widget-get widget :value) value)) 1467 (equal (widget-get widget :value) value))
1593 1468
1603 (defun widget-sublist (list start &optional end) 1478 (defun widget-sublist (list start &optional end)
1604 "Return the sublist of LIST from START to END. 1479 "Return the sublist of LIST from START to END.
1605 If END is omitted, it defaults to the length of LIST." 1480 If END is omitted, it defaults to the length of LIST."
1606 (if (> start 0) (setq list (nthcdr start list))) 1481 (if (> start 0) (setq list (nthcdr start list)))
1607 (if end 1482 (if end
1608 (if (<= end start) 1483 (unless (<= end start)
1609 nil
1610 (setq list (copy-sequence list)) 1484 (setq list (copy-sequence list))
1611 (setcdr (nthcdr (- end start 1) list) nil) 1485 (setcdr (nthcdr (- end start 1) list) nil)
1612 list) 1486 list)
1613 (copy-sequence list))) 1487 (copy-sequence list)))
1614 1488
1642 :button-suffix "" 1516 :button-suffix ""
1643 :value-create 'widget-push-button-value-create 1517 :value-create 'widget-push-button-value-create
1644 :format "%[%v%]") 1518 :format "%[%v%]")
1645 1519
1646 (defun widget-push-button-value-create (widget) 1520 (defun widget-push-button-value-create (widget)
1647 ;; Insert text representing the `on' and `off' states. 1521 "Insert text representing the `on' and `off' states."
1648 (let* ((tag (or (widget-get widget :tag) 1522 (let* ((tag (or (widget-get widget :tag)
1649 (widget-get widget :value))) 1523 (widget-get widget :value)))
1650 (tag-glyph (widget-get widget :tag-glyph)) 1524 (tag-glyph (widget-get widget :tag-glyph))
1651 (text (concat widget-push-button-prefix 1525 (text (concat widget-push-button-prefix
1652 tag widget-push-button-suffix)) 1526 tag widget-push-button-suffix))
1653 (gui (cdr (assoc tag widget-push-button-cache)))) 1527 (gui (cdr (assoc tag widget-push-button-cache))))
1654 (cond (tag-glyph 1528 (cond (tag-glyph
1655 (widget-glyph-insert widget text tag-glyph)) 1529 (widget-image-insert widget text tag-glyph))
1656 ((and (fboundp 'make-gui-button)
1657 (fboundp 'make-glyph)
1658 widget-push-button-gui
1659 (fboundp 'device-on-window-system-p)
1660 (device-on-window-system-p)
1661 (string-match "XEmacs" emacs-version))
1662 (unless gui
1663 (setq gui (make-gui-button tag 'widget-gui-action widget))
1664 (push (cons tag gui) widget-push-button-cache))
1665 (widget-glyph-insert-glyph widget
1666 (make-glyph
1667 (list (nth 0 (aref gui 1))
1668 (vector 'string ':data text)))
1669 (make-glyph
1670 (list (nth 1 (aref gui 1))
1671 (vector 'string ':data text)))
1672 (make-glyph
1673 (list (nth 2 (aref gui 1))
1674 (vector 'string ':data text)))))
1675 (t 1530 (t
1676 (insert text))))) 1531 (insert text)))))
1677 1532
1678 (defun widget-gui-action (widget) 1533 (defun widget-gui-action (widget)
1679 "Apply :action for WIDGET." 1534 "Apply :action for WIDGET."
1790 1645
1791 (defvar widget-field-history nil 1646 (defvar widget-field-history nil
1792 "History of field minibuffer edits.") 1647 "History of field minibuffer edits.")
1793 1648
1794 (defun widget-field-prompt-internal (widget prompt initial history) 1649 (defun widget-field-prompt-internal (widget prompt initial history)
1795 ;; Read string for WIDGET promptinhg with PROMPT. 1650 "Read string for WIDGET promptinhg with PROMPT.
1796 ;; INITIAL is the initial input and HISTORY is a symbol containing 1651 INITIAL is the initial input and HISTORY is a symbol containing
1797 ;; the earlier input. 1652 the earlier input."
1798 (read-string prompt initial history)) 1653 (read-string prompt initial history))
1799 1654
1800 (defun widget-field-prompt-value (widget prompt value unbound) 1655 (defun widget-field-prompt-value (widget prompt value unbound)
1801 ;; Prompt for a string. 1656 "Prompt for a string."
1802 (let ((initial (if unbound 1657 (let ((initial (if unbound
1803 nil 1658 nil
1804 (cons (widget-apply widget :value-to-internal 1659 (cons (widget-apply widget :value-to-internal
1805 value) 0))) 1660 value) 0)))
1806 (history (widget-get widget :prompt-history))) 1661 (history (widget-get widget :prompt-history)))
1809 (widget-apply widget :value-to-external answer)))) 1664 (widget-apply widget :value-to-external answer))))
1810 1665
1811 (defvar widget-edit-functions nil) 1666 (defvar widget-edit-functions nil)
1812 1667
1813 (defun widget-field-action (widget &optional event) 1668 (defun widget-field-action (widget &optional event)
1814 ;; Move to next field. 1669 "Move to next field."
1815 (widget-forward 1) 1670 (widget-forward 1)
1816 (run-hook-with-args 'widget-edit-functions widget)) 1671 (run-hook-with-args 'widget-edit-functions widget))
1817 1672
1818 (defun widget-field-validate (widget) 1673 (defun widget-field-validate (widget)
1819 ;; Valid if the content matches `:valid-regexp'. 1674 "Valid if the content matches `:valid-regexp'."
1820 (save-excursion 1675 (save-excursion
1821 (let ((value (widget-apply widget :value-get)) 1676 (let ((value (widget-apply widget :value-get))
1822 (regexp (widget-get widget :valid-regexp))) 1677 (regexp (widget-get widget :valid-regexp)))
1823 (if (string-match regexp value) 1678 (if (string-match regexp value)
1824 nil 1679 nil
1825 widget)))) 1680 widget))))
1826 1681
1827 (defun widget-field-value-create (widget) 1682 (defun widget-field-value-create (widget)
1828 ;; Create an editable text field. 1683 "Create an editable text field."
1829 (let ((size (widget-get widget :size)) 1684 (let ((size (widget-get widget :size))
1830 (value (widget-get widget :value)) 1685 (value (widget-get widget :value))
1831 (from (point)) 1686 (from (point))
1832 ;; This is changed to a real overlay in `widget-setup'. We 1687 ;; This is changed to a real overlay in `widget-setup'. We
1833 ;; need the end points to behave differently until 1688 ;; need the end points to behave differently until
1834 ;; `widget-setup' is called. 1689 ;; `widget-setup' is called.
1835 (overlay (cons (make-marker) (make-marker)))) 1690 (overlay (cons (make-marker) (make-marker))))
1836 (widget-put widget :field-overlay overlay) 1691 (widget-put widget :field-overlay overlay)
1837 (insert value) 1692 (insert value)
1838 (and size 1693 (and size
1839 (< (length value) size) 1694 (< (length value) size)
1846 (insert ?\n)) 1701 (insert ?\n))
1847 (move-marker (car overlay) from) 1702 (move-marker (car overlay) from)
1848 (set-marker-insertion-type (car overlay) t))) 1703 (set-marker-insertion-type (car overlay) t)))
1849 1704
1850 (defun widget-field-value-delete (widget) 1705 (defun widget-field-value-delete (widget)
1851 ;; Remove the widget from the list of active editing fields. 1706 "Remove the widget from the list of active editing fields."
1852 (setq widget-field-list (delq widget widget-field-list)) 1707 (setq widget-field-list (delq widget widget-field-list))
1853 ;; These are nil if the :format string doesn't contain `%v'. 1708 ;; These are nil if the :format string doesn't contain `%v'.
1854 (let ((overlay (widget-get widget :field-overlay))) 1709 (let ((overlay (widget-get widget :field-overlay)))
1855 (when overlay 1710 (when overlay
1856 (delete-overlay overlay)))) 1711 (delete-overlay overlay))))
1857 1712
1858 (defun widget-field-value-get (widget) 1713 (defun widget-field-value-get (widget)
1859 ;; Return current text in editing field. 1714 "Return current text in editing field."
1860 (let ((from (widget-field-start widget)) 1715 (let ((from (widget-field-start widget))
1861 (to (widget-field-end widget)) 1716 (to (widget-field-end widget))
1862 (buffer (widget-field-buffer widget)) 1717 (buffer (widget-field-buffer widget))
1863 (size (widget-get widget :size)) 1718 (size (widget-get widget :size))
1864 (secret (widget-get widget :secret)) 1719 (secret (widget-get widget :secret))
1865 (old (current-buffer))) 1720 (old (current-buffer)))
1866 (if (and from to) 1721 (if (and from to)
1867 (progn 1722 (progn
1868 (set-buffer buffer) 1723 (set-buffer buffer)
1869 (while (and size 1724 (while (and size
1870 (not (zerop size)) 1725 (not (zerop size))
1871 (> to from) 1726 (> to from)
1872 (eq (char-after (1- to)) ?\ )) 1727 (eq (char-after (1- to)) ?\ ))
1912 :validate 'widget-choice-validate 1767 :validate 'widget-choice-validate
1913 :match 'widget-choice-match 1768 :match 'widget-choice-match
1914 :match-inline 'widget-choice-match-inline) 1769 :match-inline 'widget-choice-match-inline)
1915 1770
1916 (defun widget-choice-value-create (widget) 1771 (defun widget-choice-value-create (widget)
1917 ;; Insert the first choice that matches the value. 1772 "Insert the first choice that matches the value."
1918 (let ((value (widget-get widget :value)) 1773 (let ((value (widget-get widget :value))
1919 (args (widget-get widget :args)) 1774 (args (widget-get widget :args))
1920 (explicit (widget-get widget :explicit-choice)) 1775 (explicit (widget-get widget :explicit-choice))
1921 (explicit-value (widget-get widget :explicit-choice-value)) 1776 (explicit-value (widget-get widget :explicit-choice-value))
1922 current) 1777 current)
2029 ;; as long as the value is the same. 1884 ;; as long as the value is the same.
2030 (when this-explicit 1885 (when this-explicit
2031 (widget-put widget :explicit-choice current) 1886 (widget-put widget :explicit-choice current)
2032 (widget-put widget :explicit-choice-value (widget-get widget :value))) 1887 (widget-put widget :explicit-choice-value (widget-get widget :value)))
2033 (let ((value (widget-default-get current))) 1888 (let ((value (widget-default-get current)))
2034 (widget-value-set widget 1889 (widget-value-set widget
2035 (widget-apply current :value-to-external value))) 1890 (widget-apply current :value-to-external value)))
2036 (widget-setup) 1891 (widget-setup)
2037 (widget-apply widget :notify widget event))) 1892 (widget-apply widget :notify widget event)))
2038 (run-hook-with-args 'widget-edit-functions widget)) 1893 (run-hook-with-args 'widget-edit-functions widget))
2039 1894
2076 :match (lambda (widget value) t) 1931 :match (lambda (widget value) t)
2077 :on "on" 1932 :on "on"
2078 :off "off") 1933 :off "off")
2079 1934
2080 (defun widget-toggle-value-create (widget) 1935 (defun widget-toggle-value-create (widget)
2081 ;; Insert text representing the `on' and `off' states. 1936 "Insert text representing the `on' and `off' states."
2082 (if (widget-value widget) 1937 (if (widget-value widget)
2083 (widget-glyph-insert widget 1938 (widget-image-insert widget
2084 (widget-get widget :on) 1939 (widget-get widget :on)
2085 (widget-get widget :on-glyph)) 1940 (widget-get widget :on-glyph))
2086 (widget-glyph-insert widget 1941 (widget-image-insert widget
2087 (widget-get widget :off) 1942 (widget-get widget :off)
2088 (widget-get widget :off-glyph)))) 1943 (widget-get widget :off-glyph))))
2089 1944
2090 (defun widget-toggle-action (widget &optional event) 1945 (defun widget-toggle-action (widget &optional event)
2091 ;; Toggle value. 1946 ;; Toggle value.
2099 "A checkbox toggle." 1954 "A checkbox toggle."
2100 :button-suffix "" 1955 :button-suffix ""
2101 :button-prefix "" 1956 :button-prefix ""
2102 :format "%[%v%]" 1957 :format "%[%v%]"
2103 :on "[X]" 1958 :on "[X]"
2104 :on-glyph "check1" 1959 :on-glyph (create-image (make-bool-vector 49 1)
1960 'xbm t :width 7 :height 7
1961 :foreground "grey75" ; like default mode line
1962 :relief -3 :ascent 'center)
2105 :off "[ ]" 1963 :off "[ ]"
2106 :off-glyph "check0" 1964 :off-glyph (create-image (make-bool-vector 49 1)
1965 'xbm t :width 7 :height 7
1966 :foreground "grey75"
1967 :relief 3 :ascent 'center)
2107 :help-echo "Toggle this item." 1968 :help-echo "Toggle this item."
2108 :action 'widget-checkbox-action) 1969 :action 'widget-checkbox-action)
2109 1970
2110 (defun widget-checkbox-action (widget &optional event) 1971 (defun widget-checkbox-action (widget &optional event)
2111 "Toggle checkbox, notify parent, and set active state of sibling." 1972 "Toggle checkbox, notify parent, and set active state of sibling."
2135 1996
2136 (defun widget-checklist-value-create (widget) 1997 (defun widget-checklist-value-create (widget)
2137 ;; Insert all values 1998 ;; Insert all values
2138 (let ((alist (widget-checklist-match-find widget (widget-get widget :value))) 1999 (let ((alist (widget-checklist-match-find widget (widget-get widget :value)))
2139 (args (widget-get widget :args))) 2000 (args (widget-get widget :args)))
2140 (while args 2001 (while args
2141 (widget-checklist-add-item widget (car args) (assq (car args) alist)) 2002 (widget-checklist-add-item widget (car args) (assq (car args) alist))
2142 (setq args (cdr args))) 2003 (setq args (cdr args)))
2143 (widget-put widget :children (nreverse (widget-get widget :children))))) 2004 (widget-put widget :children (nreverse (widget-get widget :children)))))
2144 2005
2145 (defun widget-checklist-add-item (widget type chosen) 2006 (defun widget-checklist-add-item (widget type chosen)
2146 ;; Create checklist item in WIDGET of type TYPE. 2007 "Create checklist item in WIDGET of type TYPE.
2147 ;; If the item is checked, CHOSEN is a cons whose cdr is the value. 2008 If the item is checked, CHOSEN is a cons whose cdr is the value."
2148 (and (eq (preceding-char) ?\n) 2009 (and (eq (preceding-char) ?\n)
2149 (widget-get widget :indent) 2010 (widget-get widget :indent)
2150 (insert-char ? (widget-get widget :indent))) 2011 (insert-char ? (widget-get widget :indent)))
2151 (widget-specify-insert 2012 (widget-specify-insert
2152 (let* ((children (widget-get widget :children)) 2013 (let* ((children (widget-get widget :children))
2153 (buttons (widget-get widget :buttons)) 2014 (buttons (widget-get widget :buttons))
2154 (button-args (or (widget-get type :sibling-args) 2015 (button-args (or (widget-get type :sibling-args)
2155 (widget-get widget :button-args))) 2016 (widget-get widget :button-args)))
2156 (from (point)) 2017 (from (point))
2160 ;; Parse % escapes in format. 2021 ;; Parse % escapes in format.
2161 (while (re-search-forward "%\\([bv%]\\)" nil t) 2022 (while (re-search-forward "%\\([bv%]\\)" nil t)
2162 (let ((escape (aref (match-string 1) 0))) 2023 (let ((escape (aref (match-string 1) 0)))
2163 (replace-match "" t t) 2024 (replace-match "" t t)
2164 (cond ((eq escape ?%) 2025 (cond ((eq escape ?%)
2165 (insert "%")) 2026 (insert ?%))
2166 ((eq escape ?b) 2027 ((eq escape ?b)
2167 (setq button (apply 'widget-create-child-and-convert 2028 (setq button (apply 'widget-create-child-and-convert
2168 widget 'checkbox 2029 widget 'checkbox
2169 :value (not (null chosen)) 2030 :value (not (null chosen))
2170 button-args))) 2031 button-args)))
2178 (widget-create-child-value 2039 (widget-create-child-value
2179 widget type (cdr chosen))) 2040 widget type (cdr chosen)))
2180 (t 2041 (t
2181 (widget-create-child-value 2042 (widget-create-child-value
2182 widget type (car (cdr chosen))))))) 2043 widget type (car (cdr chosen)))))))
2183 (t 2044 (t
2184 (error "Unknown escape `%c'" escape))))) 2045 (error "Unknown escape `%c'" escape)))))
2185 ;; Update properties. 2046 ;; Update properties.
2186 (and button child (widget-put child :button button)) 2047 (and button child (widget-put child :button button))
2187 (and button (widget-put widget :buttons (cons button buttons))) 2048 (and button (widget-put widget :buttons (cons button buttons)))
2188 (and child (widget-put widget :children (cons child children)))))) 2049 (and child (widget-put widget :children (cons child children))))))
2197 (let ((greedy (widget-get widget :greedy)) 2058 (let ((greedy (widget-get widget :greedy))
2198 (args (copy-sequence (widget-get widget :args))) 2059 (args (copy-sequence (widget-get widget :args)))
2199 found rest) 2060 found rest)
2200 (while values 2061 (while values
2201 (let ((answer (widget-checklist-match-up args values))) 2062 (let ((answer (widget-checklist-match-up args values)))
2202 (cond (answer 2063 (cond (answer
2203 (let ((vals (widget-match-inline answer values))) 2064 (let ((vals (widget-match-inline answer values)))
2204 (setq found (append found (car vals)) 2065 (setq found (append found (car vals))
2205 values (cdr vals) 2066 values (cdr vals)
2206 args (delq answer args)))) 2067 args (delq answer args))))
2207 (greedy 2068 (greedy
2208 (setq rest (append rest (list (car values))) 2069 (setq rest (append rest (list (car values)))
2209 values (cdr values))) 2070 values (cdr values)))
2210 (t 2071 (t
2211 (setq rest (append rest values) 2072 (setq rest (append rest values)
2212 values nil))))) 2073 values nil)))))
2213 (cons found rest))) 2074 (cons found rest)))
2214 2075
2215 (defun widget-checklist-match-find (widget vals) 2076 (defun widget-checklist-match-find (widget vals)
2216 ;; Find the vals which match a type in the checklist. 2077 "Find the vals which match a type in the checklist.
2217 ;; Return an alist of (TYPE MATCH). 2078 Return an alist of (TYPE MATCH)."
2218 (let ((greedy (widget-get widget :greedy)) 2079 (let ((greedy (widget-get widget :greedy))
2219 (args (copy-sequence (widget-get widget :args))) 2080 (args (copy-sequence (widget-get widget :args)))
2220 found) 2081 found)
2221 (while vals 2082 (while vals
2222 (let ((answer (widget-checklist-match-up args vals))) 2083 (let ((answer (widget-checklist-match-up args vals)))
2223 (cond (answer 2084 (cond (answer
2224 (let ((match (widget-match-inline answer vals))) 2085 (let ((match (widget-match-inline answer vals)))
2225 (setq found (cons (cons answer (car match)) found) 2086 (setq found (cons (cons answer (car match)) found)
2226 vals (cdr match) 2087 vals (cdr match)
2227 args (delq answer args)))) 2088 args (delq answer args))))
2228 (greedy 2089 (greedy
2229 (setq vals (cdr vals))) 2090 (setq vals (cdr vals)))
2230 (t 2091 (t
2231 (setq vals nil))))) 2092 (setq vals nil)))))
2232 found)) 2093 found))
2233 2094
2234 (defun widget-checklist-match-up (args vals) 2095 (defun widget-checklist-match-up (args vals)
2235 ;; Rerturn the first type from ARGS that matches VALS. 2096 "Return the first type from ARGS that matches VALS."
2236 (let (current found) 2097 (let (current found)
2237 (while (and args (null found)) 2098 (while (and args (null found))
2238 (setq current (car args) 2099 (setq current (car args)
2239 args (cdr args) 2100 args (cdr args)
2240 found (widget-match-inline current vals))) 2101 found (widget-match-inline current vals)))
2241 (if found 2102 (if found
2242 current 2103 current)))
2243 nil)))
2244 2104
2245 (defun widget-checklist-value-get (widget) 2105 (defun widget-checklist-value-get (widget)
2246 ;; The values of all selected items. 2106 ;; The values of all selected items.
2247 (let ((children (widget-get widget :children)) 2107 (let ((children (widget-get widget :children))
2248 child result) 2108 child result)
2249 (while children 2109 (while children
2250 (setq child (car children) 2110 (setq child (car children)
2251 children (cdr children)) 2111 children (cdr children))
2252 (if (widget-value (widget-get child :button)) 2112 (if (widget-value (widget-get child :button))
2253 (setq result (append result (widget-apply child :value-inline))))) 2113 (setq result (append result (widget-apply child :value-inline)))))
2254 result)) 2114 result))
2317 2177
2318 (defun widget-radio-value-create (widget) 2178 (defun widget-radio-value-create (widget)
2319 ;; Insert all values 2179 ;; Insert all values
2320 (let ((args (widget-get widget :args)) 2180 (let ((args (widget-get widget :args))
2321 arg) 2181 arg)
2322 (while args 2182 (while args
2323 (setq arg (car args) 2183 (setq arg (car args)
2324 args (cdr args)) 2184 args (cdr args))
2325 (widget-radio-add-item widget arg)))) 2185 (widget-radio-add-item widget arg))))
2326 2186
2327 (defun widget-radio-add-item (widget type) 2187 (defun widget-radio-add-item (widget type)
2328 "Add to radio widget WIDGET a new radio button item of type TYPE." 2188 "Add to radio widget WIDGET a new radio button item of type TYPE."
2329 ;; (setq type (widget-convert type)) 2189 ;; (setq type (widget-convert type))
2330 (and (eq (preceding-char) ?\n) 2190 (and (eq (preceding-char) ?\n)
2331 (widget-get widget :indent) 2191 (widget-get widget :indent)
2332 (insert-char ? (widget-get widget :indent))) 2192 (insert-char ? (widget-get widget :indent)))
2333 (widget-specify-insert 2193 (widget-specify-insert
2334 (let* ((value (widget-get widget :value)) 2194 (let* ((value (widget-get widget :value))
2335 (children (widget-get widget :children)) 2195 (children (widget-get widget :children))
2336 (buttons (widget-get widget :buttons)) 2196 (buttons (widget-get widget :buttons))
2337 (button-args (or (widget-get type :sibling-args) 2197 (button-args (or (widget-get type :sibling-args)
2338 (widget-get widget :button-args))) 2198 (widget-get widget :button-args)))
2345 ;; Parse % escapes in format. 2205 ;; Parse % escapes in format.
2346 (while (re-search-forward "%\\([bv%]\\)" nil t) 2206 (while (re-search-forward "%\\([bv%]\\)" nil t)
2347 (let ((escape (aref (match-string 1) 0))) 2207 (let ((escape (aref (match-string 1) 0)))
2348 (replace-match "" t t) 2208 (replace-match "" t t)
2349 (cond ((eq escape ?%) 2209 (cond ((eq escape ?%)
2350 (insert "%")) 2210 (insert ?%))
2351 ((eq escape ?b) 2211 ((eq escape ?b)
2352 (setq button (apply 'widget-create-child-and-convert 2212 (setq button (apply 'widget-create-child-and-convert
2353 widget 'radio-button 2213 widget 'radio-button
2354 :value (not (null chosen)) 2214 :value (not (null chosen))
2355 button-args))) 2215 button-args)))
2356 ((eq escape ?v) 2216 ((eq escape ?v)
2357 (setq child (if chosen 2217 (setq child (if chosen
2358 (widget-create-child-value 2218 (widget-create-child-value
2359 widget type value) 2219 widget type value)
2360 (widget-create-child widget type))) 2220 (widget-create-child widget type)))
2361 (unless chosen 2221 (unless chosen
2362 (widget-apply child :deactivate))) 2222 (widget-apply child :deactivate)))
2363 (t 2223 (t
2364 (error "Unknown escape `%c'" escape))))) 2224 (error "Unknown escape `%c'" escape)))))
2365 ;; Update properties. 2225 ;; Update properties.
2366 (when chosen 2226 (when chosen
2367 (widget-put widget :choice type)) 2227 (widget-put widget :choice type))
2368 (when button 2228 (when button
2369 (widget-put child :button button) 2229 (widget-put child :button button)
2370 (widget-put widget :buttons (nconc buttons (list button)))) 2230 (widget-put widget :buttons (nconc buttons (list button))))
2371 (when child 2231 (when child
2372 (widget-put widget :children (nconc children (list child)))) 2232 (widget-put widget :children (nconc children (list child))))
2373 child))) 2233 child)))
2416 children (cdr children)) 2276 children (cdr children))
2417 (let* ((button (widget-get current :button)) 2277 (let* ((button (widget-get current :button))
2418 (match (and (not found) 2278 (match (and (not found)
2419 (widget-apply current :match value)))) 2279 (widget-apply current :match value))))
2420 (widget-value-set button match) 2280 (widget-value-set button match)
2421 (if match 2281 (if match
2422 (progn 2282 (progn
2423 (widget-value-set current value) 2283 (widget-value-set current value)
2424 (widget-apply current :activate)) 2284 (widget-apply current :activate))
2425 (widget-apply current :deactivate)) 2285 (widget-apply current :deactivate))
2426 (setq found (or found match)))))) 2286 (setq found (or found match))))))
2427 2287
2465 :help-echo "Insert a new item into the list at this position." 2325 :help-echo "Insert a new item into the list at this position."
2466 :action 'widget-insert-button-action) 2326 :action 'widget-insert-button-action)
2467 2327
2468 (defun widget-insert-button-action (widget &optional event) 2328 (defun widget-insert-button-action (widget &optional event)
2469 ;; Ask the parent to insert a new item. 2329 ;; Ask the parent to insert a new item.
2470 (widget-apply (widget-get widget :parent) 2330 (widget-apply (widget-get widget :parent)
2471 :insert-before (widget-get widget :widget))) 2331 :insert-before (widget-get widget :widget)))
2472 2332
2473 ;;; The `delete-button' Widget. 2333 ;;; The `delete-button' Widget.
2474 2334
2475 (define-widget 'delete-button 'push-button 2335 (define-widget 'delete-button 'push-button
2478 :help-echo "Delete this item from the list." 2338 :help-echo "Delete this item from the list."
2479 :action 'widget-delete-button-action) 2339 :action 'widget-delete-button-action)
2480 2340
2481 (defun widget-delete-button-action (widget &optional event) 2341 (defun widget-delete-button-action (widget &optional event)
2482 ;; Ask the parent to insert a new item. 2342 ;; Ask the parent to insert a new item.
2483 (widget-apply (widget-get widget :parent) 2343 (widget-apply (widget-get widget :parent)
2484 :delete-at (widget-get widget :widget))) 2344 :delete-at (widget-get widget :widget)))
2485 2345
2486 ;;; The `editable-list' Widget. 2346 ;;; The `editable-list' Widget.
2487 2347
2488 (defcustom widget-editable-list-gui nil 2348 (defcustom widget-editable-list-gui nil
2511 ;; We recognize the insert button. 2371 ;; We recognize the insert button.
2512 (let ((widget-push-button-gui widget-editable-list-gui)) 2372 (let ((widget-push-button-gui widget-editable-list-gui))
2513 (cond ((eq escape ?i) 2373 (cond ((eq escape ?i)
2514 (and (widget-get widget :indent) 2374 (and (widget-get widget :indent)
2515 (insert-char ? (widget-get widget :indent))) 2375 (insert-char ? (widget-get widget :indent)))
2516 (apply 'widget-create-child-and-convert 2376 (apply 'widget-create-child-and-convert
2517 widget 'insert-button 2377 widget 'insert-button
2518 (widget-get widget :append-button-args))) 2378 (widget-get widget :append-button-args)))
2519 (t 2379 (t
2520 (widget-default-format-handler widget escape))))) 2380 (widget-default-format-handler widget escape)))))
2521 2381
2522 (defun widget-editable-list-value-create (widget) 2382 (defun widget-editable-list-value-create (widget)
2523 ;; Insert all values 2383 ;; Insert all values
2524 (let* ((value (widget-get widget :value)) 2384 (let* ((value (widget-get widget :value))
2555 (let ((type (nth 0 (widget-get widget :args))) 2415 (let ((type (nth 0 (widget-get widget :args)))
2556 (ok t) 2416 (ok t)
2557 found) 2417 found)
2558 (while (and value ok) 2418 (while (and value ok)
2559 (let ((answer (widget-match-inline type value))) 2419 (let ((answer (widget-match-inline type value)))
2560 (if answer 2420 (if answer
2561 (setq found (append found (car answer)) 2421 (setq found (append found (car answer))
2562 value (cdr answer)) 2422 value (cdr answer))
2563 (setq ok nil)))) 2423 (setq ok nil))))
2564 (cons found value))) 2424 (cons found value)))
2565 2425
2568 (save-excursion 2428 (save-excursion
2569 (let ((children (widget-get widget :children)) 2429 (let ((children (widget-get widget :children))
2570 (inhibit-read-only t) 2430 (inhibit-read-only t)
2571 before-change-functions 2431 before-change-functions
2572 after-change-functions) 2432 after-change-functions)
2573 (cond (before 2433 (cond (before
2574 (goto-char (widget-get before :entry-from))) 2434 (goto-char (widget-get before :entry-from)))
2575 (t 2435 (t
2576 (goto-char (widget-get widget :value-pos)))) 2436 (goto-char (widget-get widget :value-pos))))
2577 (let ((child (widget-editable-list-entry-create 2437 (let ((child (widget-editable-list-entry-create
2578 widget nil nil))) 2438 widget nil nil)))
2579 (when (< (widget-get child :entry-from) (widget-get widget :from)) 2439 (when (< (widget-get child :entry-from) (widget-get widget :from))
2580 (set-marker (widget-get widget :from) 2440 (set-marker (widget-get widget :from)
2581 (widget-get child :entry-from))) 2441 (widget-get child :entry-from)))
2582 (if (eq (car children) before) 2442 (if (eq (car children) before)
2618 (defun widget-editable-list-entry-create (widget value conv) 2478 (defun widget-editable-list-entry-create (widget value conv)
2619 ;; Create a new entry to the list. 2479 ;; Create a new entry to the list.
2620 (let ((type (nth 0 (widget-get widget :args))) 2480 (let ((type (nth 0 (widget-get widget :args)))
2621 (widget-push-button-gui widget-editable-list-gui) 2481 (widget-push-button-gui widget-editable-list-gui)
2622 child delete insert) 2482 child delete insert)
2623 (widget-specify-insert 2483 (widget-specify-insert
2624 (save-excursion 2484 (save-excursion
2625 (and (widget-get widget :indent) 2485 (and (widget-get widget :indent)
2626 (insert-char ? (widget-get widget :indent))) 2486 (insert-char ? (widget-get widget :indent)))
2627 (insert (widget-get widget :entry-format))) 2487 (insert (widget-get widget :entry-format)))
2628 ;; Parse % escapes in format. 2488 ;; Parse % escapes in format.
2629 (while (re-search-forward "%\\(.\\)" nil t) 2489 (while (re-search-forward "%\\(.\\)" nil t)
2630 (let ((escape (aref (match-string 1) 0))) 2490 (let ((escape (aref (match-string 1) 0)))
2631 (replace-match "" t t) 2491 (replace-match "" t t)
2632 (cond ((eq escape ?%) 2492 (cond ((eq escape ?%)
2633 (insert "%")) 2493 (insert ?%))
2634 ((eq escape ?i) 2494 ((eq escape ?i)
2635 (setq insert (apply 'widget-create-child-and-convert 2495 (setq insert (apply 'widget-create-child-and-convert
2636 widget 'insert-button 2496 widget 'insert-button
2637 (widget-get widget :insert-button-args)))) 2497 (widget-get widget :insert-button-args))))
2638 ((eq escape ?d) 2498 ((eq escape ?d)
2639 (setq delete (apply 'widget-create-child-and-convert 2499 (setq delete (apply 'widget-create-child-and-convert
2640 widget 'delete-button 2500 widget 'delete-button
2641 (widget-get widget :delete-button-args)))) 2501 (widget-get widget :delete-button-args))))
2642 ((eq escape ?v) 2502 ((eq escape ?v)
2643 (if conv 2503 (if conv
2644 (setq child (widget-create-child-value 2504 (setq child (widget-create-child-value
2645 widget type value)) 2505 widget type value))
2646 (setq child (widget-create-child-value 2506 (setq child (widget-create-child-value
2647 widget type 2507 widget type
2648 (widget-apply type :value-to-external 2508 (widget-apply type :value-to-external
2649 (widget-default-get type)))))) 2509 (widget-default-get type))))))
2650 (t 2510 (t
2651 (error "Unknown escape `%c'" escape))))) 2511 (error "Unknown escape `%c'" escape)))))
2652 (widget-put widget 2512 (widget-put widget
2653 :buttons (cons delete 2513 :buttons (cons delete
2654 (cons insert 2514 (cons insert
2655 (widget-get widget :buttons)))) 2515 (widget-get widget :buttons))))
2656 (let ((entry-from (copy-marker (point-min))) 2516 (let ((entry-from (copy-marker (point-min)))
2657 (entry-to (copy-marker (point-max)))) 2517 (entry-to (copy-marker (point-max))))
2658 (set-marker-insertion-type entry-from t) 2518 (set-marker-insertion-type entry-from t)
2715 argument answer found) 2575 argument answer found)
2716 (while args 2576 (while args
2717 (setq argument (car args) 2577 (setq argument (car args)
2718 args (cdr args) 2578 args (cdr args)
2719 answer (widget-match-inline argument vals)) 2579 answer (widget-match-inline argument vals))
2720 (if answer 2580 (if answer
2721 (setq vals (cdr answer) 2581 (setq vals (cdr answer)
2722 found (append found (car answer))) 2582 found (append found (car answer)))
2723 (setq vals nil 2583 (setq vals nil
2724 args nil))) 2584 args nil)))
2725 (if answer 2585 (if answer
2726 (cons found vals) 2586 (cons found vals))))
2727 nil)))
2728 2587
2729 ;;; The `visibility' Widget. 2588 ;;; The `visibility' Widget.
2730 2589
2731 (define-widget 'visibility 'item 2590 (define-widget 'visibility 'item
2732 "An indicator and manipulator for hidden items." 2591 "An indicator and manipulator for hidden items."
2752 (setq off (concat widget-push-button-prefix 2611 (setq off (concat widget-push-button-prefix
2753 off 2612 off
2754 widget-push-button-suffix)) 2613 widget-push-button-suffix))
2755 (setq off "")) 2614 (setq off ""))
2756 (if (widget-value widget) 2615 (if (widget-value widget)
2757 (widget-glyph-insert widget on "down" "down-pushed") 2616 (widget-image-insert widget on "down" "down-pushed")
2758 (widget-glyph-insert widget off "right" "right-pushed")))) 2617 (widget-image-insert widget off "right" "right-pushed"))))
2759 2618
2760 ;;; The `documentation-link' Widget. 2619 ;;; The `documentation-link' Widget.
2761 ;; 2620 ;;
2762 ;; This is a helper widget for `documentation-string'. 2621 ;; This is a helper widget for `documentation-string'.
2763 2622
2764 (define-widget 'documentation-link 'link 2623 (define-widget 'documentation-link 'link
2765 "Link type used in documentation strings." 2624 "Link type used in documentation strings."
2766 :tab-order -1 2625 :tab-order -1
2767 :help-echo 'widget-documentation-link-echo-help 2626 :help-echo "Describe this symbol"
2768 :action 'widget-documentation-link-action) 2627 :action 'widget-documentation-link-action)
2769
2770 (defun widget-documentation-link-echo-help (widget)
2771 "Tell what this link will describe."
2772 (concat "Describe the `" (widget-get widget :value) "' symbol."))
2773 2628
2774 (defun widget-documentation-link-action (widget &optional event) 2629 (defun widget-documentation-link-action (widget &optional event)
2775 "Display documentation for WIDGET's value. Ignore optional argument EVENT." 2630 "Display documentation for WIDGET's value. Ignore optional argument EVENT."
2776 (let* ((string (widget-get widget :value)) 2631 (let* ((string (widget-get widget :value))
2777 (symbol (intern string))) 2632 (symbol (intern string)))
2827 (push (widget-convert-button type begin end :value name) 2682 (push (widget-convert-button type begin end :value name)
2828 buttons))))) 2683 buttons)))))
2829 (widget-put widget :buttons buttons))) 2684 (widget-put widget :buttons buttons)))
2830 (let ((indent (widget-get widget :indent))) 2685 (let ((indent (widget-get widget :indent)))
2831 (when (and indent (not (zerop indent))) 2686 (when (and indent (not (zerop indent)))
2832 (save-excursion 2687 (save-excursion
2833 (save-restriction 2688 (save-restriction
2834 (narrow-to-region from to) 2689 (narrow-to-region from to)
2835 (goto-char (point-min)) 2690 (goto-char (point-min))
2836 (while (search-forward "\n" nil t) 2691 (while (search-forward "\n" nil t)
2837 (insert-char ?\ indent))))))) 2692 (insert-char ?\ indent)))))))
2853 (start (point))) 2708 (start (point)))
2854 (if (string-match "\n" doc) 2709 (if (string-match "\n" doc)
2855 (let ((before (substring doc 0 (match-beginning 0))) 2710 (let ((before (substring doc 0 (match-beginning 0)))
2856 (after (substring doc (match-beginning 0))) 2711 (after (substring doc (match-beginning 0)))
2857 buttons) 2712 buttons)
2858 (insert before " ") 2713 (insert before ?\ )
2859 (widget-documentation-link-add widget start (point)) 2714 (widget-documentation-link-add widget start (point))
2860 (push (widget-create-child-and-convert 2715 (push (widget-create-child-and-convert
2861 widget 'visibility 2716 widget 'visibility
2862 :help-echo "Show or hide rest of the documentation." 2717 :help-echo "Show or hide rest of the documentation."
2863 :off "More" 2718 :off "More"
2872 (insert after) 2727 (insert after)
2873 (widget-documentation-link-add widget start (point))) 2728 (widget-documentation-link-add widget start (point)))
2874 (widget-put widget :buttons buttons)) 2729 (widget-put widget :buttons buttons))
2875 (insert doc) 2730 (insert doc)
2876 (widget-documentation-link-add widget start (point)))) 2731 (widget-documentation-link-add widget start (point))))
2877 (insert "\n")) 2732 (insert ?\n))
2878 2733
2879 (defun widget-documentation-string-action (widget &rest ignore) 2734 (defun widget-documentation-string-action (widget &rest ignore)
2880 ;; Toggle documentation. 2735 ;; Toggle documentation.
2881 (let ((parent (widget-get widget :parent))) 2736 (let ((parent (widget-get widget :parent)))
2882 (widget-put parent :documentation-shown 2737 (widget-put parent :documentation-shown
2883 (not (widget-get parent :documentation-shown)))) 2738 (not (widget-get parent :documentation-shown))))
2884 ;; Redraw. 2739 ;; Redraw.
2885 (widget-value-set widget (widget-value widget))) 2740 (widget-value-set widget (widget-value widget)))
2886 2741
2887 ;;; The Sexp Widgets. 2742 ;;; The Sexp Widgets.
2953 (string-match val "")) 2808 (string-match val ""))
2954 (error (widget-put widget :error (error-message-string data)) 2809 (error (widget-put widget :error (error-message-string data))
2955 widget)))) 2810 widget))))
2956 2811
2957 (define-widget 'file 'string 2812 (define-widget 'file 'string
2958 "A file widget. 2813 "A file widget.
2959 It will read a file name from the minibuffer when invoked." 2814 It will read a file name from the minibuffer when invoked."
2960 :complete-function 'widget-file-complete 2815 :complete-function 'widget-file-complete
2961 :prompt-value 'widget-file-prompt-value 2816 :prompt-value 'widget-file-prompt-value
2962 :format "%{%t%}: %v" 2817 :format "%{%t%}: %v"
2963 ;; Doesn't work well with terminating newline. 2818 ;; Doesn't work well with terminating newline.
3013 ;;; (widget-value-set widget (abbreviate-file-name answer)) 2868 ;;; (widget-value-set widget (abbreviate-file-name answer))
3014 ;;; (widget-setup) 2869 ;;; (widget-setup)
3015 ;;; (widget-apply widget :notify widget event))) 2870 ;;; (widget-apply widget :notify widget event)))
3016 2871
3017 (define-widget 'directory 'file 2872 (define-widget 'directory 'file
3018 "A directory widget. 2873 "A directory widget.
3019 It will read a directory name from the minibuffer when invoked." 2874 It will read a directory name from the minibuffer when invoked."
3020 :tag "Directory") 2875 :tag "Directory")
3021 2876
3022 (defvar widget-symbol-prompt-value-history nil 2877 (defvar widget-symbol-prompt-value-history nil
3023 "History of input to `widget-symbol-prompt-value'.") 2878 "History of input to `widget-symbol-prompt-value'.")
3041 (intern value) 2896 (intern value)
3042 value))) 2897 value)))
3043 2898
3044 (defun widget-symbol-prompt-internal (widget prompt initial history) 2899 (defun widget-symbol-prompt-internal (widget prompt initial history)
3045 ;; Read file from minibuffer. 2900 ;; Read file from minibuffer.
3046 (let ((answer (completing-read prompt obarray 2901 (let ((answer (completing-read prompt obarray
3047 (widget-get widget :prompt-match) 2902 (widget-get widget :prompt-match)
3048 nil initial history))) 2903 nil initial history)))
3049 (if (and (stringp answer) 2904 (if (and (stringp answer)
3050 (not (zerop (length answer)))) 2905 (not (zerop (length answer))))
3051 answer 2906 answer
3087 2942
3088 (defun widget-coding-system-prompt-value (widget prompt value unbound) 2943 (defun widget-coding-system-prompt-value (widget prompt value unbound)
3089 ;; Read coding-system from minibuffer. 2944 ;; Read coding-system from minibuffer.
3090 (intern 2945 (intern
3091 (completing-read (format "%s (default %s) " prompt value) 2946 (completing-read (format "%s (default %s) " prompt value)
3092 (mapcar (function 2947 (mapcar (lambda (sym)
3093 (lambda (sym) 2948 (list (symbol-name sym)))
3094 (list (symbol-name sym))
3095 ))
3096 (coding-system-list))))) 2949 (coding-system-list)))))
3097 2950
3098 (defun widget-coding-system-action (widget &optional event) 2951 (defun widget-coding-system-action (widget &optional event)
3099 ;; Read a file name from the minibuffer. 2952 ;; Read a file name from the minibuffer.
3100 (let ((answer 2953 (let ((answer
3165 (defun widget-sexp-prompt-value (widget prompt value unbound) 3018 (defun widget-sexp-prompt-value (widget prompt value unbound)
3166 ;; Read an arbitrary sexp. 3019 ;; Read an arbitrary sexp.
3167 (let ((found (read-string prompt 3020 (let ((found (read-string prompt
3168 (if unbound nil (cons (prin1-to-string value) 0)) 3021 (if unbound nil (cons (prin1-to-string value) 0))
3169 (widget-get widget :prompt-history)))) 3022 (widget-get widget :prompt-history))))
3170 (save-excursion 3023 (let ((answer (read-from-string found)))
3171 (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*")))) 3024 (unless (= (cdr answer) (length found))
3172 (erase-buffer) 3025 (error "Junk at end of expression: %s"
3173 (insert found) 3026 (substring found (cdr answer))))
3174 (goto-char (point-min)) 3027 (car answer))))
3175 (let ((answer (read buffer)))
3176 (unless (eobp)
3177 (error "Junk at end of expression: %s"
3178 (buffer-substring (point) (point-max))))
3179 answer)))))
3180 3028
3181 (define-widget 'restricted-sexp 'sexp 3029 (define-widget 'restricted-sexp 'sexp
3182 "A Lisp expression restricted to values that match. 3030 "A Lisp expression restricted to values that match.
3183 To use this type, you must define :match or :match-alternatives." 3031 To use this type, you must define :match or :match-alternatives."
3184 :type-error "The specified value is not valid" 3032 :type-error "The specified value is not valid"
3217 3065
3218 (define-widget 'character 'editable-field 3066 (define-widget 'character 'editable-field
3219 "A character." 3067 "A character."
3220 :tag "Character" 3068 :tag "Character"
3221 :value 0 3069 :value 0
3222 :size 1 3070 :size 1
3223 :format "%{%t%}: %v\n" 3071 :format "%{%t%}: %v\n"
3224 :valid-regexp "\\`.\\'" 3072 :valid-regexp "\\`.\\'"
3225 :error "This field should contain a single character" 3073 :error "This field should contain a single character"
3226 :value-to-internal (lambda (widget value) 3074 :value-to-internal (lambda (widget value)
3227 (if (stringp value) 3075 (if (stringp value)
3228 value 3076 value
3229 (char-to-string value))) 3077 (char-to-string value)))
3230 :value-to-external (lambda (widget value) 3078 :value-to-external (lambda (widget value)
3231 (if (stringp value) 3079 (if (stringp value)
3232 (aref value 0) 3080 (aref value 0)
3245 :format "%{%t%}:\n%v" 3093 :format "%{%t%}:\n%v"
3246 :match 'widget-vector-match 3094 :match 'widget-vector-match
3247 :value-to-internal (lambda (widget value) (append value nil)) 3095 :value-to-internal (lambda (widget value) (append value nil))
3248 :value-to-external (lambda (widget value) (apply 'vector value))) 3096 :value-to-external (lambda (widget value) (apply 'vector value)))
3249 3097
3250 (defun widget-vector-match (widget value) 3098 (defun widget-vector-match (widget value)
3251 (and (vectorp value) 3099 (and (vectorp value)
3252 (widget-group-match widget 3100 (widget-group-match widget
3253 (widget-apply widget :value-to-internal value)))) 3101 (widget-apply widget :value-to-internal value))))
3254 3102
3255 (define-widget 'cons 'group 3103 (define-widget 'cons 'group
3260 :value-to-internal (lambda (widget value) 3108 :value-to-internal (lambda (widget value)
3261 (list (car value) (cdr value))) 3109 (list (car value) (cdr value)))
3262 :value-to-external (lambda (widget value) 3110 :value-to-external (lambda (widget value)
3263 (cons (nth 0 value) (nth 1 value)))) 3111 (cons (nth 0 value) (nth 1 value))))
3264 3112
3265 (defun widget-cons-match (widget value) 3113 (defun widget-cons-match (widget value)
3266 (and (consp value) 3114 (and (consp value)
3267 (widget-group-match widget 3115 (widget-group-match widget
3268 (widget-apply widget :value-to-internal value)))) 3116 (widget-apply widget :value-to-internal value))))
3269 3117
3270 ;;; The `plist' Widget. 3118 ;;; The `plist' Widget.
3283 (defun widget-plist-convert-widget (widget) 3131 (defun widget-plist-convert-widget (widget)
3284 ;; Handle `:options'. 3132 ;; Handle `:options'.
3285 (let* ((options (widget-get widget :options)) 3133 (let* ((options (widget-get widget :options))
3286 (key-type (widget-get widget :key-type)) 3134 (key-type (widget-get widget :key-type))
3287 (widget-plist-value-type (widget-get widget :value-type)) 3135 (widget-plist-value-type (widget-get widget :value-type))
3288 (other `(editable-list :inline t 3136 (other `(editable-list :inline t
3289 (group :inline t 3137 (group :inline t
3290 ,key-type 3138 ,key-type
3291 ,widget-plist-value-type))) 3139 ,widget-plist-value-type)))
3292 (args (if options 3140 (args (if options
3293 (list `(checklist :inline t 3141 (list `(checklist :inline t
3329 (defun widget-alist-convert-widget (widget) 3177 (defun widget-alist-convert-widget (widget)
3330 ;; Handle `:options'. 3178 ;; Handle `:options'.
3331 (let* ((options (widget-get widget :options)) 3179 (let* ((options (widget-get widget :options))
3332 (key-type (widget-get widget :key-type)) 3180 (key-type (widget-get widget :key-type))
3333 (widget-alist-value-type (widget-get widget :value-type)) 3181 (widget-alist-value-type (widget-get widget :value-type))
3334 (other `(editable-list :inline t 3182 (other `(editable-list :inline t
3335 (cons :format "%v" 3183 (cons :format "%v"
3336 ,key-type 3184 ,key-type
3337 ,widget-alist-value-type))) 3185 ,widget-alist-value-type)))
3338 (args (if options 3186 (args (if options
3339 (list `(checklist :inline t 3187 (list `(checklist :inline t
3365 :button-prefix 'widget-push-button-prefix 3213 :button-prefix 'widget-push-button-prefix
3366 :button-suffix 'widget-push-button-suffix 3214 :button-suffix 'widget-push-button-suffix
3367 :prompt-value 'widget-choice-prompt-value) 3215 :prompt-value 'widget-choice-prompt-value)
3368 3216
3369 (defun widget-choice-prompt-value (widget prompt value unbound) 3217 (defun widget-choice-prompt-value (widget prompt value unbound)
3370 "Make a choice." 3218 "Make a choice."
3371 (let ((args (widget-get widget :args)) 3219 (let ((args (widget-get widget :args))
3372 (completion-ignore-case (widget-get widget :case-fold)) 3220 (completion-ignore-case (widget-get widget :case-fold))
3373 current choices old) 3221 current choices old)
3374 ;; Find the first arg that match VALUE. 3222 ;; Find the first arg that match VALUE.
3375 (let ((look args)) 3223 (let ((look args))
3438 ;; Toggle a boolean. 3286 ;; Toggle a boolean.
3439 (y-or-n-p prompt)) 3287 (y-or-n-p prompt))
3440 3288
3441 ;;; The `color' Widget. 3289 ;;; The `color' Widget.
3442 3290
3443 (define-widget 'color 'editable-field 3291 (define-widget 'color 'editable-field
3444 "Choose a color name (with sample)." 3292 "Choose a color name (with sample)."
3445 :format "%t: %v (%{sample%})\n" 3293 :format "%t: %v (%{sample%})\n"
3446 :size 10 3294 :size 10
3447 :tag "Color" 3295 :tag "Color"
3448 :value "black" 3296 :value "black"
3499 (widget-setup) 3347 (widget-setup)
3500 (widget-apply widget :notify widget event)))) 3348 (widget-apply widget :notify widget event))))
3501 3349
3502 (defun widget-color-notify (widget child &optional event) 3350 (defun widget-color-notify (widget child &optional event)
3503 "Update the sample, and notofy the parent." 3351 "Update the sample, and notofy the parent."
3504 (overlay-put (widget-get widget :sample-overlay) 3352 (overlay-put (widget-get widget :sample-overlay)
3505 'face (widget-apply widget :sample-face-get)) 3353 'face (widget-apply widget :sample-face-get))
3506 (widget-default-notify widget child event)) 3354 (widget-default-notify widget child event))
3507 3355
3508 ;;; The Help Echo 3356 ;;; The Help Echo
3509 3357
3514 3362
3515 (defun widget-echo-help (pos) 3363 (defun widget-echo-help (pos)
3516 "Display the help echo for widget at POS." 3364 "Display the help echo for widget at POS."
3517 (let* ((widget (widget-at pos)) 3365 (let* ((widget (widget-at pos))
3518 (help-echo (and widget (widget-get widget :help-echo)))) 3366 (help-echo (and widget (widget-get widget :help-echo))))
3519 (cond ((stringp help-echo) 3367 (if (or (stringp help-echo)
3520 (message "%s" help-echo)) 3368 (and (symbolp help-echo) (fboundp help-echo)
3521 ((and (symbolp help-echo) (fboundp help-echo) 3369 (stringp (setq help-echo (funcall help-echo widget)))))
3522 (stringp (setq help-echo (funcall help-echo widget)))) 3370 (message "%s" help-echo))))
3523 (message "%s" help-echo)))))
3524 3371
3525 ;;; The End: 3372 ;;; The End:
3526 3373
3527 (provide 'wid-edit) 3374 (provide 'wid-edit)
3528 3375