comparison lisp/wid-edit.el @ 17799:0df9495348e7

Synched with 1.97.
author Per Abrahamsen <abraham@dina.kvl.dk>
date Wed, 14 May 1997 17:31:13 +0000
parents d6545cfb6c5a
children bccd356a3b7c
comparison
equal deleted inserted replaced
17798:f59c9a63514b 17799:0df9495348e7
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Keywords: extensions 6 ;; Keywords: extensions
7 ;; Version: 1.90 7 ;; Version: 1.97
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
11 11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify 12 ;; GNU Emacs is free software; you can redistribute it and/or modify
63 (set-extent-property ext 'atomic t))) 63 (set-extent-property ext 'atomic t)))
64 (defun widget-make-intangible (from to size) 64 (defun widget-make-intangible (from to size)
65 "Make text between FROM and TO intangible." 65 "Make text between FROM and TO intangible."
66 (put-text-property from to 'intangible 'front))) 66 (put-text-property from to 'intangible 'front)))
67 67
68 (if (string-match "XEmacs" emacs-version)
69 (defun widget-event-point (event)
70 "Character position of the end of event if that exists, or nil."
71 (if (mouse-event-p event)
72 (event-point event)
73 nil))
74 (defun widget-event-point (event)
75 "Character position of the end of event if that exists, or nil."
76 (posn-point (event-end event))))
77
68 ;; The following should go away when bundled with Emacs. 78 ;; The following should go away when bundled with Emacs.
69 (condition-case () 79 (condition-case ()
70 (require 'custom) 80 (require 'custom)
71 (error nil)) 81 (error nil))
72 82
80 (when (fboundp 'copy-face) 90 (when (fboundp 'copy-face)
81 (copy-face 'default 'widget-documentation-face) 91 (copy-face 'default 'widget-documentation-face)
82 (copy-face 'bold 'widget-button-face) 92 (copy-face 'bold 'widget-button-face)
83 (copy-face 'italic 'widget-field-face))) 93 (copy-face 'italic 'widget-field-face)))
84 94
85 (unless (fboundp 'event-point) 95 (unless (fboundp 'button-release-event-p)
86 ;; XEmacs function missing in Emacs. 96 ;; XEmacs function missing from Emacs.
87 (defun event-point (event) 97 (defun button-release-event-p (event)
88 "Return the character position of the given mouse-motion, button-press, 98 "Non-nil if EVENT is a mouse-button-release event object."
89 or button-release event. If the event did not occur over a window, or did 99 (and (eventp event)
90 not occur over text, then this returns nil. Otherwise, it returns an index 100 (memq (event-basic-type event) '(mouse-1 mouse-2 mouse-3))
91 into the buffer visible in the event's window." 101 (or (memq 'click (event-modifiers event))
92 (posn-point (event-start event)))) 102 (memq 'drag (event-modifiers event))))))
93 103
94 (unless (fboundp 'error-message-string) 104 (unless (fboundp 'error-message-string)
95 ;; Emacs function missing in XEmacs. 105 ;; Emacs function missing in XEmacs.
96 (defun error-message-string (obj) 106 (defun error-message-string (obj)
97 "Convert an error value to an error message." 107 "Convert an error value to an error message."
140 (t 150 (t
141 (:italic t))) 151 (:italic t)))
142 "Face used for editable fields." 152 "Face used for editable fields."
143 :group 'widgets) 153 :group 'widgets)
144 154
145 (defcustom widget-menu-max-size 40
146 "Largest number of items allowed in a popup-menu.
147 Larger menus are read through the minibuffer."
148 :group 'widgets
149 :type 'integer)
150
151 ;;; Utility functions. 155 ;;; Utility functions.
152 ;; 156 ;;
153 ;; These are not really widget specific. 157 ;; These are not really widget specific.
154 158
155 (defsubst widget-plist-member (plist prop) 159 (defsubst widget-plist-member (plist prop)
176 180
177 (defun widget-clear-undo () 181 (defun widget-clear-undo ()
178 "Clear all undo information." 182 "Clear all undo information."
179 (buffer-disable-undo (current-buffer)) 183 (buffer-disable-undo (current-buffer))
180 (buffer-enable-undo)) 184 (buffer-enable-undo))
185
186 (defcustom widget-menu-max-size 40
187 "Largest number of items allowed in a popup-menu.
188 Larger menus are read through the minibuffer."
189 :group 'widgets
190 :type 'integer)
181 191
182 (defun widget-choose (title items &optional event) 192 (defun widget-choose (title items &optional event)
183 "Choose an item from a list. 193 "Choose an item from a list.
184 194
185 First argument TITLE is the name of the list. 195 First argument TITLE is the name of the list.
223 (when (stringp try) 233 (when (stringp try)
224 (setq val try)) 234 (setq val try))
225 (cdr (assoc val items))) 235 (cdr (assoc val items)))
226 nil))))) 236 nil)))))
227 237
228 (defun widget-get-sibling (widget)
229 "Get the item WIDGET is assumed to toggle.
230 This is only meaningful for radio buttons or checkboxes in a list."
231 (let* ((parent (widget-get widget :parent))
232 (children (widget-get parent :children))
233 child)
234 (catch 'child
235 (while children
236 (setq child (car children)
237 children (cdr children))
238 (when (eq (widget-get child :button) widget)
239 (throw 'child child)))
240 nil)))
241
242 ;;; Helper functions.
243 ;;
244 ;; These are widget specific.
245
246 ;;;###autoload
247 (defun widget-prompt-value (widget prompt &optional value unbound)
248 "Prompt for a value matching WIDGET, using PROMPT.
249 The current value is assumed to be VALUE, unless UNBOUND is non-nil."
250 (unless (listp widget)
251 (setq widget (list widget)))
252 (setq widget (widget-convert widget))
253 (let ((answer (widget-apply widget :prompt-value prompt value unbound)))
254 (unless (widget-apply widget :match answer)
255 (error "Value does not match %S type." (car widget)))
256 answer))
257
258 ;;; Widget text specifications. 238 ;;; Widget text specifications.
259 ;; 239 ;;
260 ;; These functions are for specifying text properties. 240 ;; These functions are for specifying text properties.
261 241
262 (defun widget-specify-none (from to) 242 (defun widget-specify-none (from to)
523 (defun widget-apply-action (widget &optional event) 503 (defun widget-apply-action (widget &optional event)
524 "Apply :action in WIDGET in response to EVENT." 504 "Apply :action in WIDGET in response to EVENT."
525 (if (widget-apply widget :active) 505 (if (widget-apply widget :active)
526 (widget-apply widget :action event) 506 (widget-apply widget :action event)
527 (error "Attempt to perform action on inactive widget"))) 507 (error "Attempt to perform action on inactive widget")))
508
509 ;;; Helper functions.
510 ;;
511 ;; These are widget specific.
512
513 ;;;###autoload
514 (defun widget-prompt-value (widget prompt &optional value unbound)
515 "Prompt for a value matching WIDGET, using PROMPT.
516 The current value is assumed to be VALUE, unless UNBOUND is non-nil."
517 (unless (listp widget)
518 (setq widget (list widget)))
519 (setq prompt (format "[%s] %s" (widget-type widget) prompt))
520 (setq widget (widget-convert widget))
521 (let ((answer (widget-apply widget :prompt-value prompt value unbound)))
522 (unless (widget-apply widget :match answer)
523 (error "Value does not match %S type." (car widget)))
524 answer))
525
526 (defun widget-get-sibling (widget)
527 "Get the item WIDGET is assumed to toggle.
528 This is only meaningful for radio buttons or checkboxes in a list."
529 (let* ((parent (widget-get widget :parent))
530 (children (widget-get parent :children))
531 child)
532 (catch 'child
533 (while children
534 (setq child (car children)
535 children (cdr children))
536 (when (eq (widget-get child :button) widget)
537 (throw 'child child)))
538 nil)))
528 539
529 ;;; Glyphs. 540 ;;; Glyphs.
530 541
531 (defcustom widget-glyph-directory (concat data-directory "custom/") 542 (defcustom widget-glyph-directory (concat data-directory "custom/")
532 "Where widget glyphs are located. 543 "Where widget glyphs are located.
570 (if (file-readable-p file) 581 (if (file-readable-p file)
571 (widget-glyph-insert-glyph widget tag (make-glyph file)) 582 (widget-glyph-insert-glyph widget tag (make-glyph file))
572 ;; File not readable, give up. 583 ;; File not readable, give up.
573 (insert tag)))))) 584 (insert tag))))))
574 585
575 (defun widget-glyph-insert-glyph (widget tag glyph) 586 (defun widget-glyph-insert-glyph (widget tag glyph &optional down inactive)
576 "In WIDGET, with alternative text TAG, insert GLYPH." 587 "In WIDGET, with alternative text TAG, insert GLYPH."
577 (set-glyph-image glyph (cons 'tty tag)) 588 (set-glyph-image glyph (cons 'tty tag))
578 (set-glyph-property glyph 'widget widget) 589 (set-glyph-property glyph 'widget widget)
590 (when down
591 (set-glyph-image down (cons 'tty tag))
592 (set-glyph-property down 'widget widget))
593 (when inactive
594 (set-glyph-image inactive (cons 'tty tag))
595 (set-glyph-property inactive 'widget widget))
579 (insert "*") 596 (insert "*")
580 (add-text-properties (1- (point)) (point) 597 (add-text-properties (1- (point)) (point)
581 (list 'invisible t 598 (list 'invisible t
582 'end-glyph glyph)) 599 'end-glyph glyph))
600 (widget-put widget :glyph-up glyph)
601 (when down (widget-put widget :glyph-down down))
602 (when inactive (widget-put widget :glyph-inactive inactive))
583 (let ((help-echo (widget-get widget :help-echo))) 603 (let ((help-echo (widget-get widget :help-echo)))
584 (when help-echo 604 (when help-echo
585 (let ((extent (extent-at (1- (point)) nil 'end-glyph)) 605 (let ((extent (extent-at (1- (point)) nil 'end-glyph))
586 (help-property (if (featurep 'balloon-help) 606 (help-property (if (featurep 'balloon-help)
587 'balloon-help 607 'balloon-help
704 (define-key widget-keymap "\C-k" 'widget-kill-line) 724 (define-key widget-keymap "\C-k" 'widget-kill-line)
705 (define-key widget-keymap "\t" 'widget-forward) 725 (define-key widget-keymap "\t" 'widget-forward)
706 (define-key widget-keymap "\M-\t" 'widget-backward) 726 (define-key widget-keymap "\M-\t" 'widget-backward)
707 (define-key widget-keymap [(shift tab)] 'widget-backward) 727 (define-key widget-keymap [(shift tab)] 'widget-backward)
708 (define-key widget-keymap [backtab] 'widget-backward) 728 (define-key widget-keymap [backtab] 'widget-backward)
709 (if (string-match "XEmacs" (emacs-version)) 729 (if (string-match "XEmacs" emacs-version)
710 (progn 730 (progn
711 (define-key widget-keymap [button2] 'widget-button-click) 731 ;;Glyph support.
712 (define-key widget-keymap [button1] 'widget-button1-click)) 732 (define-key widget-keymap [button1] 'widget-button1-click)
713 (define-key widget-keymap [mouse-2] 'ignore) 733 (define-key widget-keymap [button2] 'widget-button-click))
714 (define-key widget-keymap [down-mouse-2] 'widget-button-click)) 734 (define-key widget-keymap [down-mouse-2] 'widget-button-click))
715 (define-key widget-keymap "\C-m" 'widget-button-press)) 735 (define-key widget-keymap "\C-m" 'widget-button-press))
716 736
717 (defvar widget-global-map global-map 737 (defvar widget-global-map global-map
718 "Keymap used for events the widget does not handle themselves.") 738 "Keymap used for events the widget does not handle themselves.")
748 (if field 768 (if field
749 (widget-apply-action field event) 769 (widget-apply-action field event)
750 (call-interactively 770 (call-interactively
751 (lookup-key widget-global-map (this-command-keys)))))) 771 (lookup-key widget-global-map (this-command-keys))))))
752 772
773 (defface widget-button-pressed-face
774 '((((class color))
775 (:foreground "red"))
776 (t
777 (:bold t :underline t)))
778 "Face used for pressed buttons."
779 :group 'widgets)
780
753 (defun widget-button-click (event) 781 (defun widget-button-click (event)
754 "Activate button below mouse pointer." 782 "Activate button below mouse pointer."
755 (interactive "@e") 783 (interactive "@e")
756 (cond ((and (fboundp 'event-glyph) 784 (cond ((and (fboundp 'event-glyph)
757 (event-glyph event)) 785 (event-glyph event))
758 (let ((widget (glyph-property (event-glyph event) 'widget))) 786 (widget-glyph-click event))
759 (if widget 787 ((widget-event-point event)
760 (widget-apply-action widget event) 788 (let* ((pos (widget-event-point event))
761 (message "You clicked on a glyph.")))) 789 (button (get-text-property pos 'button)))
762 ((event-point event)
763 (let ((button (get-text-property (event-point event) 'button)))
764 (if button 790 (if button
765 (widget-apply-action button event) 791 (let ((begin (previous-single-property-change (1+ pos) 'button))
792 (end (next-single-property-change pos 'button))
793 overlay)
794 (unwind-protect
795 (let ((track-mouse t))
796 (setq overlay (make-overlay begin end))
797 (overlay-put overlay 'face 'widget-button-pressed-face)
798 (overlay-put overlay
799 'mouse-face 'widget-button-pressed-face)
800 (unless (widget-apply button :mouse-down-action event)
801 (while (not (button-release-event-p event))
802 (setq event (if (fboundp 'read-event)
803 (read-event)
804 (next-event))
805 pos (widget-event-point event))
806 (if (and pos
807 (eq (get-text-property pos 'button)
808 button))
809 (progn
810 (overlay-put overlay
811 'face
812 'widget-button-pressed-face)
813 (overlay-put overlay
814 'mouse-face
815 'widget-button-pressed-face))
816 (overlay-put overlay 'face nil)
817 (overlay-put overlay 'mouse-face nil))))
818
819 (when (and pos
820 (eq (get-text-property pos 'button) button))
821 (widget-apply-action button event)))
822 (delete-overlay overlay)))
766 (call-interactively 823 (call-interactively
767 (or (lookup-key widget-global-map [ button2 ]) 824 (or (lookup-key widget-global-map [ button2 ])
768 (lookup-key widget-global-map [ down-mouse-2 ]) 825 (lookup-key widget-global-map [ down-mouse-2 ])
769 (lookup-key widget-global-map [ mouse-2])))))) 826 (lookup-key widget-global-map [ mouse-2]))))))
770 (t 827 (t
773 (defun widget-button1-click (event) 830 (defun widget-button1-click (event)
774 "Activate glyph below mouse pointer." 831 "Activate glyph below mouse pointer."
775 (interactive "@e") 832 (interactive "@e")
776 (if (and (fboundp 'event-glyph) 833 (if (and (fboundp 'event-glyph)
777 (event-glyph event)) 834 (event-glyph event))
835 (widget-glyph-click event)
836 (call-interactively (lookup-key widget-global-map (this-command-keys)))))
837
838 (defun widget-glyph-click (event)
839 "Handle click on a glyph."
840 (let* ((glyph (event-glyph event))
841 (widget (glyph-property glyph 'widget))
842 (extent (event-glyph-extent event))
843 (down-glyph (or (and widget (widget-get widget :glyph-down)) glyph))
844 (up-glyph (or (and widget (widget-get widget :glyph-up)) glyph))
845 (last event))
846 ;; Wait for the release.
847 (while (not (button-release-event-p last))
848 (if (eq extent (event-glyph-extent last))
849 (set-extent-property extent 'end-glyph down-glyph)
850 (set-extent-property extent 'end-glyph up-glyph))
851 (setq last (next-event event)))
852 ;; Release glyph.
853 (when down-glyph
854 (set-extent-property extent 'end-glyph up-glyph))
855 ;; Apply widget action.
856 (when (eq extent (event-glyph-extent last))
778 (let ((widget (glyph-property (event-glyph event) 'widget))) 857 (let ((widget (glyph-property (event-glyph event) 'widget)))
779 (if widget 858 (cond ((null widget)
780 (widget-apply-action widget event) 859 (message "You clicked on a glyph."))
781 (message "You clicked on a glyph."))) 860 ((not (widget-apply widget :active))
782 (call-interactively (lookup-key widget-global-map (this-command-keys))))) 861 (message "This glyph is inactive."))
862 (t
863 (widget-apply-action widget event)))))))
783 864
784 (defun widget-button-press (pos &optional event) 865 (defun widget-button-press (pos &optional event)
785 "Activate button at POS." 866 "Activate button at POS."
786 (interactive "@d") 867 (interactive "@d")
787 (let ((button (get-text-property pos 'button))) 868 (let ((button (get-text-property pos 'button)))
1005 1086
1006 ;;; Widget Functions 1087 ;;; Widget Functions
1007 ;; 1088 ;;
1008 ;; These functions are used in the definition of multiple widgets. 1089 ;; These functions are used in the definition of multiple widgets.
1009 1090
1091 (defun widget-parent-action (widget &optional event)
1092 "Tell :parent of WIDGET to handle the :action.
1093 Optional EVENT is the event that triggered the action."
1094 (widget-apply (widget-get widget :parent) :action event))
1095
1010 (defun widget-children-value-delete (widget) 1096 (defun widget-children-value-delete (widget)
1011 "Delete all :children and :buttons in WIDGET." 1097 "Delete all :children and :buttons in WIDGET."
1012 (mapcar 'widget-delete (widget-get widget :children)) 1098 (mapcar 'widget-delete (widget-get widget :children))
1013 (widget-put widget :children nil) 1099 (widget-put widget :children nil)
1014 (mapcar 'widget-delete (widget-get widget :buttons)) 1100 (mapcar 'widget-delete (widget-get widget :buttons))
1015 (widget-put widget :buttons nil)) 1101 (widget-put widget :buttons nil))
1016 1102
1103 (defun widget-children-validate (widget)
1104 "All the :children must be valid."
1105 (let ((children (widget-get widget :children))
1106 child found)
1107 (while (and children (not found))
1108 (setq child (car children)
1109 children (cdr children)
1110 found (widget-apply child :validate)))
1111 found))
1112
1017 (defun widget-types-convert-widget (widget) 1113 (defun widget-types-convert-widget (widget)
1018 "Convert :args as widget types in WIDGET." 1114 "Convert :args as widget types in WIDGET."
1019 (widget-put widget :args (mapcar 'widget-convert (widget-get widget :args))) 1115 (widget-put widget :args (mapcar 'widget-convert (widget-get widget :args)))
1020 widget) 1116 widget)
1117
1118 (defun widget-value-convert-widget (widget)
1119 "Initialize :value from :args in WIDGET."
1120 (let ((args (widget-get widget :args)))
1121 (when args
1122 (widget-put widget :value (car args))
1123 ;; Don't convert :value here, as this is done in `widget-convert'.
1124 ;; (widget-put widget :value (widget-apply widget
1125 ;; :value-to-internal (car args)))
1126 (widget-put widget :args nil)))
1127 widget)
1128
1129 (defun widget-value-value-get (widget)
1130 "Return the :value property of WIDGET."
1131 (widget-get widget :value))
1021 1132
1022 ;;; The `default' Widget. 1133 ;;; The `default' Widget.
1023 1134
1024 (define-widget 'default nil 1135 (define-widget 'default nil
1025 "Basic widget other widgets are derived from." 1136 "Basic widget other widgets are derived from."
1037 :menu-tag-get 'widget-default-menu-tag-get 1148 :menu-tag-get 'widget-default-menu-tag-get
1038 :validate (lambda (widget) nil) 1149 :validate (lambda (widget) nil)
1039 :active 'widget-default-active 1150 :active 'widget-default-active
1040 :activate 'widget-specify-active 1151 :activate 'widget-specify-active
1041 :deactivate 'widget-default-deactivate 1152 :deactivate 'widget-default-deactivate
1153 :mouse-down-action (lambda (widget event) nil)
1042 :action 'widget-default-action 1154 :action 'widget-default-action
1043 :notify 'widget-default-notify 1155 :notify 'widget-default-notify
1044 :prompt-value 'widget-default-prompt-value) 1156 :prompt-value 'widget-default-prompt-value)
1045 1157
1046 (defun widget-default-create (widget) 1158 (defun widget-default-create (widget)
1231 1343
1232 ;;; The `item' Widget. 1344 ;;; The `item' Widget.
1233 1345
1234 (define-widget 'item 'default 1346 (define-widget 'item 'default
1235 "Constant items for inclusion in other widgets." 1347 "Constant items for inclusion in other widgets."
1236 :convert-widget 'widget-item-convert-widget 1348 :convert-widget 'widget-value-convert-widget
1237 :value-create 'widget-item-value-create 1349 :value-create 'widget-item-value-create
1238 :value-delete 'ignore 1350 :value-delete 'ignore
1239 :value-get 'widget-item-value-get 1351 :value-get 'widget-value-value-get
1240 :match 'widget-item-match 1352 :match 'widget-item-match
1241 :match-inline 'widget-item-match-inline 1353 :match-inline 'widget-item-match-inline
1242 :action 'widget-item-action 1354 :action 'widget-item-action
1243 :format "%t\n") 1355 :format "%t\n")
1244
1245 (defun widget-item-convert-widget (widget)
1246 ;; Initialize :value from :args in WIDGET.
1247 (let ((args (widget-get widget :args)))
1248 (when args
1249 (widget-put widget :value (widget-apply widget
1250 :value-to-internal (car args)))
1251 (widget-put widget :args nil)))
1252 widget)
1253 1356
1254 (defun widget-item-value-create (widget) 1357 (defun widget-item-value-create (widget)
1255 ;; Insert the printed representation of the value. 1358 ;; Insert the printed representation of the value.
1256 (let ((standard-output (current-buffer))) 1359 (let ((standard-output (current-buffer)))
1257 (princ (widget-get widget :value)))) 1360 (princ (widget-get widget :value))))
1270 (cons head (subseq values (length value)))))))) 1373 (cons head (subseq values (length value))))))))
1271 1374
1272 (defun widget-item-action (widget &optional event) 1375 (defun widget-item-action (widget &optional event)
1273 ;; Just notify itself. 1376 ;; Just notify itself.
1274 (widget-apply widget :notify widget event)) 1377 (widget-apply widget :notify widget event))
1275
1276 (defun widget-item-value-get (widget)
1277 ;; Items are simple.
1278 (widget-get widget :value))
1279 1378
1280 ;;; The `push-button' Widget. 1379 ;;; The `push-button' Widget.
1281 1380
1282 (defcustom widget-push-button-gui t 1381 (defcustom widget-push-button-gui t
1283 "If non nil, use GUI push buttons when available." 1382 "If non nil, use GUI push buttons when available."
1308 (progn 1407 (progn
1309 (unless gui 1408 (unless gui
1310 (setq gui (make-gui-button tag 'widget-gui-action widget)) 1409 (setq gui (make-gui-button tag 'widget-gui-action widget))
1311 (push (cons tag gui) widget-push-button-cache)) 1410 (push (cons tag gui) widget-push-button-cache))
1312 (widget-glyph-insert-glyph widget text 1411 (widget-glyph-insert-glyph widget text
1313 (make-glyph (car (aref gui 1))))) 1412 (make-glyph (nth 0 (aref gui 1)))
1413 (make-glyph (nth 1 (aref gui 1)))
1414 (make-glyph (nth 2 (aref gui 1)))))
1314 (insert text)))) 1415 (insert text))))
1315 1416
1316 (defun widget-gui-action (widget) 1417 (defun widget-gui-action (widget)
1317 "Apply :action for WIDGET." 1418 "Apply :action for WIDGET."
1318 (widget-apply-action widget (this-command-keys))) 1419 (widget-apply-action widget (this-command-keys)))
1330 "A link to an info file." 1431 "A link to an info file."
1331 :action 'widget-info-link-action) 1432 :action 'widget-info-link-action)
1332 1433
1333 (defun widget-info-link-action (widget &optional event) 1434 (defun widget-info-link-action (widget &optional event)
1334 "Open the info node specified by WIDGET." 1435 "Open the info node specified by WIDGET."
1335 (Info-goto-node (widget-value widget)) 1436 (Info-goto-node (widget-value widget)))
1336 ;; Steal button release event.
1337 (if (and (fboundp 'button-press-event-p)
1338 (fboundp 'next-command-event))
1339 ;; XEmacs
1340 (and event
1341 (button-press-event-p event)
1342 (next-command-event))
1343 ;; Emacs
1344 (when (memq 'down (event-modifiers event))
1345 (read-event))))
1346 1437
1347 ;;; The `url-link' Widget. 1438 ;;; The `url-link' Widget.
1348 1439
1349 (define-widget 'url-link 'link 1440 (define-widget 'url-link 'link
1350 "A link to an www page." 1441 "A link to an www page."
1357 1448
1358 ;;; The `editable-field' Widget. 1449 ;;; The `editable-field' Widget.
1359 1450
1360 (define-widget 'editable-field 'default 1451 (define-widget 'editable-field 'default
1361 "An editable text field." 1452 "An editable text field."
1362 :convert-widget 'widget-item-convert-widget 1453 :convert-widget 'widget-value-convert-widget
1363 :keymap widget-field-keymap 1454 :keymap widget-field-keymap
1364 :format "%v" 1455 :format "%v"
1365 :value "" 1456 :value ""
1457 :prompt-internal 'widget-field-prompt-internal
1458 :prompt-history 'widget-field-history
1459 :prompt-value 'widget-field-prompt-value
1366 :action 'widget-field-action 1460 :action 'widget-field-action
1367 :validate 'widget-field-validate 1461 :validate 'widget-field-validate
1368 :valid-regexp "" 1462 :valid-regexp ""
1369 :error "No match" 1463 :error "No match"
1370 :value-create 'widget-field-value-create 1464 :value-create 'widget-field-value-create
1371 :value-delete 'widget-field-value-delete 1465 :value-delete 'widget-field-value-delete
1372 :value-get 'widget-field-value-get 1466 :value-get 'widget-field-value-get
1373 :match 'widget-field-match) 1467 :match 'widget-field-match)
1374 1468
1375 ;; History of field minibuffer edits. 1469 (defvar widget-field-history nil
1376 (defvar widget-field-history nil) 1470 "History of field minibuffer edits.")
1471
1472 (defun widget-field-prompt-internal (widget prompt initial history)
1473 ;; Read string for WIDGET promptinhg with PROMPT.
1474 ;; INITIAL is the initial input and HISTORY is a symbol containing
1475 ;; the earlier input.
1476 (read-string prompt initial history))
1477
1478 (defun widget-field-prompt-value (widget prompt value unbound)
1479 ;; Prompt for a string.
1480 (let ((initial (if unbound
1481 nil
1482 (cons (widget-apply widget :value-to-internal
1483 value) 0)))
1484 (history (widget-get widget :prompt-history)))
1485 (let ((answer (widget-apply widget
1486 :prompt-internal prompt initial history)))
1487 (widget-apply widget :value-to-external answer))))
1377 1488
1378 (defun widget-field-action (widget &optional event) 1489 (defun widget-field-action (widget &optional event)
1379 ;; Edit the value in the minibuffer. 1490 ;; Edit the value in the minibuffer.
1380 (let ((tag (widget-apply widget :menu-tag-get)) 1491 (let ((invalid (widget-apply widget :validate)))
1381 (invalid (widget-apply widget :validate))) 1492 (let ((prompt (concat (widget-apply widget :menu-tag-get) ": "))
1382 (when invalid 1493 (value (unless invalid
1383 (error (widget-get invalid :error))) 1494 (widget-value widget))))
1384 (widget-value-set widget 1495 (let ((answer (widget-apply widget :prompt-value prompt value invalid) ))
1385 (widget-apply widget 1496 (widget-value-set widget answer)))
1386 :value-to-external
1387 (read-string (concat tag ": ")
1388 (widget-apply
1389 widget
1390 :value-to-internal
1391 (widget-value widget))
1392 'widget-field-history)))
1393 (widget-apply widget :notify widget event) 1497 (widget-apply widget :notify widget event)
1394 (widget-setup))) 1498 (widget-setup)))
1395 1499
1396 (defun widget-field-validate (widget) 1500 (defun widget-field-validate (widget)
1397 ;; Valid if the content matches `:valid-regexp'. 1501 ;; Valid if the content matches `:valid-regexp'.
1447 (not (zerop size)) 1551 (not (zerop size))
1448 (> to from) 1552 (> to from)
1449 (eq (char-after (1- to)) ?\ )) 1553 (eq (char-after (1- to)) ?\ ))
1450 (setq to (1- to))) 1554 (setq to (1- to)))
1451 (let ((result (buffer-substring-no-properties from to))) 1555 (let ((result (buffer-substring-no-properties from to)))
1556 (when (string-match "XEmacs" emacs-version)
1557 ;; XEmacs 20.1 bug: b-s-n-p doesn't clear all properties.
1558 (setq result (format "%s" result)))
1452 (when secret 1559 (when secret
1453 (let ((index 0)) 1560 (let ((index 0))
1454 (while (< (+ from index) to) 1561 (while (< (+ from index) to)
1455 (aset result index 1562 (aset result index
1456 (get-text-property (+ from index) 'secret)) 1563 (get-text-property (+ from index) 'secret))
1480 :void '(item :format "invalid (%t)\n") 1587 :void '(item :format "invalid (%t)\n")
1481 :value-create 'widget-choice-value-create 1588 :value-create 'widget-choice-value-create
1482 :value-delete 'widget-children-value-delete 1589 :value-delete 'widget-children-value-delete
1483 :value-get 'widget-choice-value-get 1590 :value-get 'widget-choice-value-get
1484 :value-inline 'widget-choice-value-inline 1591 :value-inline 'widget-choice-value-inline
1592 :mouse-down-action 'widget-choice-mouse-down-action
1485 :action 'widget-choice-action 1593 :action 'widget-choice-action
1486 :error "Make a choice" 1594 :error "Make a choice"
1487 :validate 'widget-choice-validate 1595 :validate 'widget-choice-validate
1488 :match 'widget-choice-match 1596 :match 'widget-choice-match
1489 :match-inline 'widget-choice-match-inline) 1597 :match-inline 'widget-choice-match-inline)
1514 1622
1515 (defun widget-choice-value-inline (widget) 1623 (defun widget-choice-value-inline (widget)
1516 ;; Get value of the child widget. 1624 ;; Get value of the child widget.
1517 (widget-apply (car (widget-get widget :children)) :value-inline)) 1625 (widget-apply (car (widget-get widget :children)) :value-inline))
1518 1626
1627 (defcustom widget-choice-toggle nil
1628 "If non-nil, a binary choice will just toggle between the values.
1629 Otherwise, the user will explicitly have to choose between the values
1630 when he activate the menu."
1631 :type 'boolean
1632 :group 'widgets)
1633
1634 (defun widget-choice-mouse-down-action (widget &optional event)
1635 ;; Return non-nil if we need a menu.
1636 (let ((args (widget-get widget :args))
1637 (old (widget-get widget :choice)))
1638 (cond ((not window-system)
1639 ;; No place to pop up a menu.
1640 nil)
1641 ((not (or (fboundp 'x-popup-menu) (fboundp 'popup-menu)))
1642 ;; No way to pop up a menu.
1643 nil)
1644 ((< (length args) 2)
1645 ;; Empty or singleton list, just return the value.
1646 nil)
1647 ((> (length args) widget-menu-max-size)
1648 ;; Too long, prompt.
1649 nil)
1650 ((> (length args) 2)
1651 ;; Reasonable sized list, use menu.
1652 t)
1653 ((and widget-choice-toggle (memq old args))
1654 ;; We toggle.
1655 nil)
1656 (t
1657 ;; Ask which of the two.
1658 t))))
1659
1519 (defun widget-choice-action (widget &optional event) 1660 (defun widget-choice-action (widget &optional event)
1520 ;; Make a choice. 1661 ;; Make a choice.
1521 (let ((args (widget-get widget :args)) 1662 (let ((args (widget-get widget :args))
1522 (old (widget-get widget :choice)) 1663 (old (widget-get widget :choice))
1523 (tag (widget-apply widget :menu-tag-get)) 1664 (tag (widget-apply widget :menu-tag-get))
1532 (setq current 1673 (setq current
1533 (cond ((= (length args) 0) 1674 (cond ((= (length args) 0)
1534 nil) 1675 nil)
1535 ((= (length args) 1) 1676 ((= (length args) 1)
1536 (nth 0 args)) 1677 (nth 0 args))
1537 ((and (= (length args) 2) 1678 ((and widget-choice-toggle
1679 (= (length args) 2)
1538 (memq old args)) 1680 (memq old args))
1539 (if (eq old (nth 0 args)) 1681 (if (eq old (nth 0 args))
1540 (nth 1 args) 1682 (nth 1 args)
1541 (nth 0 args))) 1683 (nth 0 args)))
1542 (t 1684 (t
1787 1929
1788 ;;; The `choice-item' Widget. 1930 ;;; The `choice-item' Widget.
1789 1931
1790 (define-widget 'choice-item 'item 1932 (define-widget 'choice-item 'item
1791 "Button items that delegate action events to their parents." 1933 "Button items that delegate action events to their parents."
1792 :action 'widget-choice-item-action 1934 :action 'widget-parent-action
1793 :format "%[%t%] \n") 1935 :format "%[%t%] \n")
1794
1795 (defun widget-choice-item-action (widget &optional event)
1796 ;; Tell parent what happened.
1797 (widget-apply (widget-get widget :parent) :action event))
1798 1936
1799 ;;; The `radio-button' Widget. 1937 ;;; The `radio-button' Widget.
1800 1938
1801 (define-widget 'radio-button 'toggle 1939 (define-widget 'radio-button 'toggle
1802 "A radio button for use in the `radio' widget." 1940 "A radio button for use in the `radio' widget."
2015 :entry-format "%i %d %v" 2153 :entry-format "%i %d %v"
2016 :menu-tag "editable-list" 2154 :menu-tag "editable-list"
2017 :value-create 'widget-editable-list-value-create 2155 :value-create 'widget-editable-list-value-create
2018 :value-delete 'widget-children-value-delete 2156 :value-delete 'widget-children-value-delete
2019 :value-get 'widget-editable-list-value-get 2157 :value-get 'widget-editable-list-value-get
2020 :validate 'widget-editable-list-validate 2158 :validate 'widget-children-validate
2021 :match 'widget-editable-list-match 2159 :match 'widget-editable-list-match
2022 :match-inline 'widget-editable-list-match-inline 2160 :match-inline 'widget-editable-list-match-inline
2023 :insert-before 'widget-editable-list-insert-before 2161 :insert-before 'widget-editable-list-insert-before
2024 :delete-at 'widget-editable-list-delete-at) 2162 :delete-at 'widget-editable-list-delete-at)
2025 2163
2059 2197
2060 (defun widget-editable-list-value-get (widget) 2198 (defun widget-editable-list-value-get (widget)
2061 ;; Get value of the child widget. 2199 ;; Get value of the child widget.
2062 (apply 'append (mapcar (lambda (child) (widget-apply child :value-inline)) 2200 (apply 'append (mapcar (lambda (child) (widget-apply child :value-inline))
2063 (widget-get widget :children)))) 2201 (widget-get widget :children))))
2064
2065 (defun widget-editable-list-validate (widget)
2066 ;; All the chilren must be valid.
2067 (let ((children (widget-get widget :children))
2068 child found)
2069 (while (and children (not found))
2070 (setq child (car children)
2071 children (cdr children)
2072 found (widget-apply child :validate)))
2073 found))
2074 2202
2075 (defun widget-editable-list-match (widget value) 2203 (defun widget-editable-list-match (widget value)
2076 ;; Value must be a list and all the members must match the type. 2204 ;; Value must be a list and all the members must match the type.
2077 (and (listp value) 2205 (and (listp value)
2078 (null (cdr (widget-editable-list-match-inline widget value))))) 2206 (null (cdr (widget-editable-list-match-inline widget value)))))
2193 :convert-widget 'widget-types-convert-widget 2321 :convert-widget 'widget-types-convert-widget
2194 :format "%v" 2322 :format "%v"
2195 :value-create 'widget-group-value-create 2323 :value-create 'widget-group-value-create
2196 :value-delete 'widget-children-value-delete 2324 :value-delete 'widget-children-value-delete
2197 :value-get 'widget-editable-list-value-get 2325 :value-get 'widget-editable-list-value-get
2198 :validate 'widget-editable-list-validate 2326 :validate 'widget-children-validate
2199 :match 'widget-group-match 2327 :match 'widget-group-match
2200 :match-inline 'widget-group-match-inline) 2328 :match-inline 'widget-group-match-inline)
2201 2329
2202 (defun widget-group-value-create (widget) 2330 (defun widget-group-value-create (widget)
2203 ;; Create each component. 2331 ;; Create each component.
2282 (define-widget 'variable-item 'const 2410 (define-widget 'variable-item 'const
2283 "An immutable variable name." 2411 "An immutable variable name."
2284 :format "%v\n%h" 2412 :format "%v\n%h"
2285 :documentation-property 'variable-documentation) 2413 :documentation-property 'variable-documentation)
2286 2414
2415 (defvar widget-string-prompt-value-history nil
2416 "History of input to `widget-string-prompt-value'.")
2417
2287 (define-widget 'string 'editable-field 2418 (define-widget 'string 'editable-field
2288 "A string" 2419 "A string"
2289 :prompt-value 'widget-string-prompt-value
2290 :tag "String" 2420 :tag "String"
2291 :format "%[%t%]: %v") 2421 :format "%{%t%}: %v"
2292 2422 :prompt-history 'widget-string-prompt-value-history)
2293 (defvar widget-string-prompt-value-history nil
2294 "History of input to `widget-string-prompt-value'.")
2295
2296 (defun widget-string-prompt-value (widget prompt value unbound)
2297 ;; Read a string.
2298 (read-string prompt (if unbound nil (cons value 1))
2299 'widget-string-prompt-value-history))
2300 2423
2301 (define-widget 'regexp 'string 2424 (define-widget 'regexp 'string
2302 "A regular expression." 2425 "A regular expression."
2303 :match 'widget-regexp-match 2426 :match 'widget-regexp-match
2304 :validate 'widget-regexp-validate 2427 :validate 'widget-regexp-validate
2305 :tag "Regexp") 2428 :tag "Regexp")
2306 2429
2307 (defun widget-regexp-match (widget value) 2430 (defun widget-regexp-match (widget value)
2308 ;; Match valid regexps. 2431 ;; Match valid regexps.
2309 (and (stringp value) 2432 (and (stringp value)
2310 (condition-case data 2433 (condition-case nil
2311 (prog1 t 2434 (prog1 t
2312 (string-match value "")) 2435 (string-match value ""))
2313 (error nil)))) 2436 (error nil))))
2314 2437
2315 (defun widget-regexp-validate (widget) 2438 (defun widget-regexp-validate (widget)
2323 2446
2324 (define-widget 'file 'string 2447 (define-widget 'file 'string
2325 "A file widget. 2448 "A file widget.
2326 It will read a file name from the minibuffer when activated." 2449 It will read a file name from the minibuffer when activated."
2327 :prompt-value 'widget-file-prompt-value 2450 :prompt-value 'widget-file-prompt-value
2328 :format "%[%t%]: %v" 2451 :format "%{%t%}: %v"
2329 :tag "File" 2452 :tag "File"
2330 :action 'widget-file-action) 2453 :action 'widget-file-action)
2331 2454
2332 (defun widget-file-prompt-value (widget prompt value unbound) 2455 (defun widget-file-prompt-value (widget prompt value unbound)
2333 ;; Read file from minibuffer. 2456 ;; Read file from minibuffer.
2334 (abbreviate-file-name 2457 (abbreviate-file-name
2335 (if unbound 2458 (if unbound
2336 (read-file-name prompt) 2459 (read-file-name prompt)
2337 (let ((prompt2 (concat prompt "(default `" value "') ")) 2460 (let ((prompt2 (format "%s (default %s) " prompt value))
2338 (dir (file-name-directory value)) 2461 (dir (file-name-directory value))
2339 (file (file-name-nondirectory value)) 2462 (file (file-name-nondirectory value))
2340 (must-match (widget-get widget :must-match))) 2463 (must-match (widget-get widget :must-match)))
2341 (read-file-name prompt2 dir nil must-match file))))) 2464 (read-file-name prompt2 dir nil must-match file)))))
2342 2465
2356 (define-widget 'directory 'file 2479 (define-widget 'directory 'file
2357 "A directory widget. 2480 "A directory widget.
2358 It will read a directory name from the minibuffer when activated." 2481 It will read a directory name from the minibuffer when activated."
2359 :tag "Directory") 2482 :tag "Directory")
2360 2483
2361 (define-widget 'symbol 'string 2484 (defvar widget-symbol-prompt-value-history nil
2485 "History of input to `widget-symbol-prompt-value'.")
2486
2487 (define-widget 'symbol 'editable-field
2362 "A lisp symbol." 2488 "A lisp symbol."
2363 :value nil 2489 :value nil
2364 :tag "Symbol" 2490 :tag "Symbol"
2491 :format "%{%t%}: %v"
2365 :match (lambda (widget value) (symbolp value)) 2492 :match (lambda (widget value) (symbolp value))
2493 :prompt-internal 'widget-symbol-prompt-internal
2494 :prompt-match 'symbolp
2495 :prompt-history 'widget-symbol-prompt-value-history
2366 :value-to-internal (lambda (widget value) 2496 :value-to-internal (lambda (widget value)
2367 (if (symbolp value) 2497 (if (symbolp value)
2368 (symbol-name value) 2498 (symbol-name value)
2369 value)) 2499 value))
2370 :value-to-external (lambda (widget value) 2500 :value-to-external (lambda (widget value)
2371 (if (stringp value) 2501 (if (stringp value)
2372 (intern value) 2502 (intern value)
2373 value))) 2503 value)))
2374 2504
2505 (defun widget-symbol-prompt-internal (widget prompt initial history)
2506 ;; Read file from minibuffer.
2507 (let ((answer (completing-read prompt obarray
2508 (widget-get widget :prompt-match)
2509 nil initial history)))
2510 (if (and (stringp answer)
2511 (not (zerop (length answer))))
2512 answer
2513 (error "No value"))))
2514
2515 (defvar widget-function-prompt-value-history nil
2516 "History of input to `widget-function-prompt-value'.")
2517
2375 (define-widget 'function 'sexp 2518 (define-widget 'function 'sexp
2376 ;; Should complete on functions.
2377 "A lisp function." 2519 "A lisp function."
2520 :prompt-value 'widget-field-prompt-value
2521 :prompt-internal 'widget-symbol-prompt-internal
2522 :prompt-match 'fboundp
2523 :prompt-history 'widget-function-prompt-value-history
2524 :action 'widget-field-action
2378 :tag "Function") 2525 :tag "Function")
2526
2527 (defvar widget-variable-prompt-value-history nil
2528 "History of input to `widget-variable-prompt-value'.")
2379 2529
2380 (define-widget 'variable 'symbol 2530 (define-widget 'variable 'symbol
2381 ;; Should complete on variables. 2531 ;; Should complete on variables.
2382 "A lisp variable." 2532 "A lisp variable."
2533 :prompt-match 'boundp
2534 :prompt-history 'widget-variable-prompt-value-history
2383 :tag "Variable") 2535 :tag "Variable")
2384 2536
2385 (define-widget 'sexp 'string 2537 (define-widget 'sexp 'editable-field
2386 "An arbitrary lisp expression." 2538 "An arbitrary lisp expression."
2387 :tag "Lisp expression" 2539 :tag "Lisp expression"
2540 :format "%{%t%}: %v"
2388 :value nil 2541 :value nil
2389 :validate 'widget-sexp-validate 2542 :validate 'widget-sexp-validate
2390 :match (lambda (widget value) t) 2543 :match (lambda (widget value) t)
2391 :value-to-internal 'widget-sexp-value-to-internal 2544 :value-to-internal 'widget-sexp-value-to-internal
2392 :value-to-external (lambda (widget value) (read value)) 2545 :value-to-external (lambda (widget value) (read value))
2546 :prompt-history 'widget-sexp-prompt-value-history
2393 :prompt-value 'widget-sexp-prompt-value) 2547 :prompt-value 'widget-sexp-prompt-value)
2394 2548
2395 (defun widget-sexp-value-to-internal (widget value) 2549 (defun widget-sexp-value-to-internal (widget value)
2396 ;; Use pp for printer representation. 2550 ;; Use pp for printer representation.
2397 (let ((pp (pp-to-string value))) 2551 (let ((pp (pp-to-string value)))
2428 "History of input to `widget-sexp-prompt-value'.") 2582 "History of input to `widget-sexp-prompt-value'.")
2429 2583
2430 (defun widget-sexp-prompt-value (widget prompt value unbound) 2584 (defun widget-sexp-prompt-value (widget prompt value unbound)
2431 ;; Read an arbitrary sexp. 2585 ;; Read an arbitrary sexp.
2432 (let ((found (read-string prompt 2586 (let ((found (read-string prompt
2433 (if unbound nil (cons (prin1-to-string value) 1)) 2587 (if unbound nil (cons (prin1-to-string value) 0))
2434 'widget-sexp-prompt-value))) 2588 (widget-get widget :prompt-history))))
2435 (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*")))) 2589 (save-excursion
2436 (erase-buffer) 2590 (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*"))))
2437 (insert found) 2591 (erase-buffer)
2438 (goto-char (point-min)) 2592 (insert found)
2439 (let ((answer (read buffer))) 2593 (goto-char (point-min))
2440 (unless (eobp) 2594 (let ((answer (read buffer)))
2441 (error "Junk at end of expression: %s" 2595 (unless (eobp)
2442 (buffer-substring (point) (point-max)))) 2596 (error "Junk at end of expression: %s"
2443 answer)))) 2597 (buffer-substring (point) (point-max))))
2444 2598 answer)))))
2599
2445 (define-widget 'integer 'sexp 2600 (define-widget 'integer 'sexp
2446 "An integer." 2601 "An integer."
2447 :tag "Integer" 2602 :tag "Integer"
2448 :value 0 2603 :value 0
2449 :type-error "This field should contain an integer" 2604 :type-error "This field should contain an integer"
2451 (if (integerp value) 2606 (if (integerp value)
2452 (prin1-to-string value) 2607 (prin1-to-string value)
2453 value)) 2608 value))
2454 :match (lambda (widget value) (integerp value))) 2609 :match (lambda (widget value) (integerp value)))
2455 2610
2456 (define-widget 'character 'string 2611 (define-widget 'character 'editable-field
2457 "An character." 2612 "An character."
2458 :tag "Character" 2613 :tag "Character"
2459 :value 0 2614 :value 0
2460 :size 1 2615 :size 1
2461 :format "%{%t%}: %v\n" 2616 :format "%{%t%}: %v\n"
2462 :valid-regexp "\\`.\\'" 2617 :valid-regexp "\\`.\\'"
2463 :error "This field should contain a single character" 2618 :error "This field should contain a single character"
2464 :value-to-internal (lambda (widget value) 2619 :value-to-internal (lambda (widget value)
2465 (if (integerp value) 2620 (if (stringp value)
2466 (char-to-string value) 2621 value
2467 value)) 2622 (char-to-string value)))
2468 :value-to-external (lambda (widget value) 2623 :value-to-external (lambda (widget value)
2469 (if (stringp value) 2624 (if (stringp value)
2470 (aref value 0) 2625 (aref value 0)
2471 value)) 2626 value))
2472 :match (lambda (widget value) (integerp value))) 2627 :match (lambda (widget value)
2628 (if (fboundp 'characterp)
2629 (characterp value)
2630 (integerp value))))
2473 2631
2474 (define-widget 'number 'sexp 2632 (define-widget 'number 'sexp
2475 "A floating point number." 2633 "A floating point number."
2476 :tag "Number" 2634 :tag "Number"
2477 :value 0.0 2635 :value 0.0
2516 (widget-apply widget :value-to-internal value)))) 2674 (widget-apply widget :value-to-internal value))))
2517 2675
2518 (define-widget 'choice 'menu-choice 2676 (define-widget 'choice 'menu-choice
2519 "A union of several sexp types." 2677 "A union of several sexp types."
2520 :tag "Choice" 2678 :tag "Choice"
2521 :format "%[%t%]: %v") 2679 :format "%[%t%]: %v"
2680 :prompt-value 'widget-choice-prompt-value)
2681
2682 (defun widget-choice-prompt-value (widget prompt value unbound)
2683 "Make a choice."
2684 (let ((args (widget-get widget :args))
2685 (completion-ignore-case (widget-get widget :case-fold))
2686 current choices old)
2687 ;; Find the first arg that match VALUE.
2688 (let ((look args))
2689 (while look
2690 (if (widget-apply (car look) :match value)
2691 (setq old (car look)
2692 look nil)
2693 (setq look (cdr look)))))
2694 ;; Find new choice.
2695 (setq current
2696 (cond ((= (length args) 0)
2697 nil)
2698 ((= (length args) 1)
2699 (nth 0 args))
2700 ((and (= (length args) 2)
2701 (memq old args))
2702 (if (eq old (nth 0 args))
2703 (nth 1 args)
2704 (nth 0 args)))
2705 (t
2706 (while args
2707 (setq current (car args)
2708 args (cdr args))
2709 (setq choices
2710 (cons (cons (widget-apply current :menu-tag-get)
2711 current)
2712 choices)))
2713 (let ((val (completing-read prompt choices nil t)))
2714 (if (stringp val)
2715 (let ((try (try-completion val choices)))
2716 (when (stringp try)
2717 (setq val try))
2718 (cdr (assoc val choices)))
2719 nil)))))
2720 (if current
2721 (widget-prompt-value current prompt nil t)
2722 value)))
2522 2723
2523 (define-widget 'radio 'radio-button-choice 2724 (define-widget 'radio 'radio-button-choice
2524 "A union of several sexp types." 2725 "A union of several sexp types."
2525 :tag "Choice" 2726 :tag "Choice"
2526 :format "%{%t%}:\n%v") 2727 :format "%{%t%}:\n%v"
2728 :prompt-value 'widget-choice-prompt-value)
2527 2729
2528 (define-widget 'repeat 'editable-list 2730 (define-widget 'repeat 'editable-list
2529 "A variable length homogeneous list." 2731 "A variable length homogeneous list."
2530 :tag "Repeat" 2732 :tag "Repeat"
2531 :format "%{%t%}:\n%v%i\n") 2733 :format "%{%t%}:\n%v%i\n")
2537 2739
2538 (define-widget 'boolean 'toggle 2740 (define-widget 'boolean 'toggle
2539 "To be nil or non-nil, that is the question." 2741 "To be nil or non-nil, that is the question."
2540 :tag "Boolean" 2742 :tag "Boolean"
2541 :prompt-value 'widget-boolean-prompt-value 2743 :prompt-value 'widget-boolean-prompt-value
2542 :format "%{%t%}: %[%v%]\n") 2744 :format "%[%t%]: %v\n")
2543 2745
2544 (defun widget-boolean-prompt-value (widget prompt value unbound) 2746 (defun widget-boolean-prompt-value (widget prompt value unbound)
2545 ;; Toggle a boolean. 2747 ;; Toggle a boolean.
2546 (cond (unbound 2748 (y-or-n-p prompt))
2547 (y-or-n-p prompt))
2548 (value
2549 (message "Off")
2550 nil)
2551 (t
2552 (message "On")
2553 t)))
2554 2749
2555 ;;; The `color' Widget. 2750 ;;; The `color' Widget.
2556 2751
2557 (define-widget 'color-item 'choice-item 2752 (define-widget 'color-item 'choice-item
2558 "A color name (with sample)." 2753 "A color name (with sample)."