comparison lisp/wid-edit.el @ 1309:00abb1091204

[xemacs-hg @ 2003-02-17 14:50:55 by stephent] charsets-in-region optimization <874r73qa2b.fsf@tleepslib.sk.tsukuba.ac.jp> wid-edit.el synch <87znovote9.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Mon, 17 Feb 2003 14:51:02 +0000
parents 315720febed1
children 1b0339b048ce
comparison
equal deleted inserted replaced
1308:1741c7ce4ac0 1309:00abb1091204
1 ;;; wid-edit.el --- Functions for creating and using widgets. 1 ;;; wid-edit.el --- Functions for creating and using widgets.
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996-1997, 1999-2002 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> 6 ;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org>
7 ;; Keywords: extensions 7 ;; Keywords: extensions
8 ;; Version: 1.9960-x 8 ;; Version: 1.9960-x
25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;; Boston, MA 02111-1307, USA. 26 ;; Boston, MA 02111-1307, USA.
27 27
28 ;;; Commentary: 28 ;;; Commentary:
29 ;; 29 ;;
30 ;; See `widget.el'. 30 ;; See `widget.el' and the wishlist in `../man/widget.texi'.
31 31
32 32
33 ;;; Code: 33 ;;; Code:
34 34
35 (require 'widget) 35 (require 'widget)
83 (defcustom widget-mouse-face 'highlight 83 (defcustom widget-mouse-face 'highlight
84 "Face used for widget buttons when the mouse is above them." 84 "Face used for widget buttons when the mouse is above them."
85 :type 'face 85 :type 'face
86 :group 'widget-faces) 86 :group 'widget-faces)
87 87
88 (defface widget-field-face '((((class grayscale color) 88 ;; #### comment from GNU Emacs 21.3.50, test the first spec.
89 ;; TTY gets special definitions here and in the next defface, because
90 ;; the gray colors defined for other displays cause black text on a black
91 ;; background, at least on light-background TTYs.
92 (defface widget-field-face '((((type tty))
93 (:background "yellow3")
94 (:foreground "black"))
95 (((class grayscale color)
89 (background light)) 96 (background light))
90 (:background "gray85")) 97 (:background "gray85"))
91 (((class grayscale color) 98 (((class grayscale color)
92 (background dark)) 99 (background dark))
93 (:background "dim gray")) 100 (:background "dim gray"))
143 (while (and plist (not (eq (car plist) prop))) 150 (while (and plist (not (eq (car plist) prop)))
144 (setq plist (cddr plist))) 151 (setq plist (cddr plist)))
145 plist)) 152 plist))
146 153
147 (defun widget-princ-to-string (object) 154 (defun widget-princ-to-string (object)
148 ;; Return string representation of OBJECT, any Lisp object. 155 "Return string representation of OBJECT, any Lisp object.
149 ;; No quoting characters are used; no delimiters are printed around 156 No quoting characters are used; no delimiters are printed around
150 ;; the contents of strings. 157 the contents of strings."
151 (with-current-buffer (get-buffer-create " *widget-tmp*") 158 (with-current-buffer (get-buffer-create " *widget-tmp*")
152 (erase-buffer) 159 (erase-buffer)
153 (princ object (current-buffer)) 160 (princ object (current-buffer))
154 (buffer-string))) 161 (buffer-string)))
155 162
171 (buffer-enable-undo)) 178 (buffer-enable-undo))
172 179
173 (defcustom widget-menu-max-size 40 180 (defcustom widget-menu-max-size 40
174 "Largest number of items allowed in a popup-menu. 181 "Largest number of items allowed in a popup-menu.
175 Larger menus are read through the minibuffer." 182 Larger menus are read through the minibuffer."
183 :group 'widgets
184 :type 'integer)
185
186 (defcustom widget-menu-max-shortcuts 40
187 "Largest number of items for which it works to choose one with a character.
188 For a larger number of items, the minibuffer is used.
189 #### Not yet implemented in XEmacs."
176 :group 'widgets 190 :group 'widgets
177 :type 'integer) 191 :type 'integer)
178 192
179 (defcustom widget-menu-minibuffer-flag nil 193 (defcustom widget-menu-minibuffer-flag nil
180 "*Control how to ask for a choice from the keyboard. 194 "*Control how to ask for a choice from the keyboard.
274 (when (stringp try) 288 (when (stringp try)
275 (setq val try)) 289 (setq val try))
276 (cdr (assoc val items))) 290 (cdr (assoc val items)))
277 nil))))) 291 nil)))))
278 292
293 ;; GNU Emacs 21.3.50 uses this in `widget-choose'
294 (defun widget-remove-if (predicate list)
295 (let (result (tail list))
296 (while tail
297 (or (funcall predicate (car tail))
298 (setq result (cons (car tail) result)))
299 (setq tail (cdr tail)))
300 (nreverse result)))
301
279 302
280 ;;; Widget text specifications. 303 ;;; Widget text specifications.
281 ;; 304 ;;
282 ;; These functions are for specifying text properties. 305 ;; These functions are for specifying text properties.
283 306
399 help-echo) 422 help-echo)
400 (t 423 (t
401 (format "(widget %S :help-echo %S)" widget help-echo))))) 424 (format "(widget %S :help-echo %S)" widget help-echo)))))
402 425
403 (defun widget-specify-sample (widget from to) 426 (defun widget-specify-sample (widget from to)
404 ;; Specify sample for WIDGET between FROM and TO. 427 "Specify sample for WIDGET between FROM and TO."
405 (let ((face (widget-apply widget :sample-face-get)) 428 (let ((face (widget-apply widget :sample-face-get))
406 (extent (make-extent from to nil))) 429 (extent (make-extent from to nil)))
407 (set-extent-property extent 'start-open t) 430 (set-extent-property extent 'start-open t)
408 (set-extent-property extent 'face face) 431 (set-extent-property extent 'face face)
409 (widget-put widget :sample-extent extent))) 432 (widget-put widget :sample-extent extent)))
410 433
411 (defun widget-specify-doc (widget from to) 434 (defun widget-specify-doc (widget from to)
412 ;; Specify documentation for WIDGET between FROM and TO. 435 "Specify documentation for WIDGET between FROM and TO."
413 (let ((extent (make-extent from to))) 436 (let ((extent (make-extent from to)))
414 (set-extent-property extent 'start-open t) 437 (set-extent-property extent 'start-open t)
415 (set-extent-property extent 'widget-doc widget) 438 (set-extent-property extent 'widget-doc widget)
416 (set-extent-property extent 'face widget-documentation-face) 439 (set-extent-property extent 'face widget-documentation-face)
417 (widget-put widget :doc-extent extent))) 440 (widget-put widget :doc-extent extent)))
549 572
550 (defsubst widget-type (widget) 573 (defsubst widget-type (widget)
551 "Return the type of WIDGET, a symbol." 574 "Return the type of WIDGET, a symbol."
552 (car widget)) 575 (car widget))
553 576
577 ;;;###autoload
578 (defun widgetp (widget)
579 "Return non-nil iff WIDGET is a widget."
580 (if (symbolp widget)
581 (get widget 'widget-type)
582 (and (consp widget)
583 (symbolp (car widget))
584 (get (car widget) 'widget-type))))
585
554 (when (or (not (fboundp 'widget-put)) 586 (when (or (not (fboundp 'widget-put))
555 widget-shadow-subrs) 587 widget-shadow-subrs)
556 (defun widget-put (widget property value) 588 (defun widget-put (widget property value)
557 "In WIDGET set PROPERTY to VALUE. 589 "In WIDGET set PROPERTY to VALUE.
558 The value can later be retrieved with `widget-get'." 590 The value can later be retrieved with `widget-get'."
653 answer)) 685 answer))
654 686
655 (defun widget-get-sibling (widget) 687 (defun widget-get-sibling (widget)
656 "Get the item WIDGET is assumed to toggle. 688 "Get the item WIDGET is assumed to toggle.
657 This is only meaningful for radio buttons or checkboxes in a list." 689 This is only meaningful for radio buttons or checkboxes in a list."
658 (let* ((parent (widget-get widget :parent)) 690 (let* ((children (widget-get (widget-get widget :parent) :children))
659 (children (widget-get parent :children))
660 child) 691 child)
661 (catch 'child 692 (catch 'child
662 (while children 693 (while children
663 (setq child (car children) 694 (setq child (car children)
664 children (cdr children)) 695 children (cdr children))
682 713
683 714
684 ;;; Glyphs. 715 ;;; Glyphs.
685 716
686 (defcustom widget-glyph-directory (locate-data-directory "custom") 717 (defcustom widget-glyph-directory (locate-data-directory "custom")
687 "Where widget glyphs are located. 718 "Where widget button glyphs are located.
688 If this variable is nil, widget will try to locate the directory 719 If this variable is nil, widget will try to locate the directory
689 automatically." 720 automatically."
690 :group 'widgets 721 :group 'widgets
691 :type 'directory) 722 :type 'directory)
692 723
693 (defcustom widget-glyph-enable t 724 (defcustom widget-glyph-enable t
694 "If non nil, use glyphs in images when available." 725 "If non nil, use glyph buttons in widgets when available."
695 :group 'widgets 726 :group 'widgets
696 :type 'boolean) 727 :type 'boolean)
728
729 ;; #### What happens if you try to customize this?
730 (define-compatible-variable-alias 'widget-image-conversion
731 'widget-image-file-name-suffixes)
697 732
698 (defcustom widget-image-file-name-suffixes 733 (defcustom widget-image-file-name-suffixes
699 '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg") 734 '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg")
700 (xbm ".xbm")) 735 (xbm ".xbm"))
701 "Conversion alist from image formats to file name suffixes." 736 "Conversion alist from image formats to file name suffixes."
901 ;;;###autoload 936 ;;;###autoload
902 (defun widget-delete (widget) 937 (defun widget-delete (widget)
903 "Delete WIDGET." 938 "Delete WIDGET."
904 (widget-apply widget :delete)) 939 (widget-apply widget :delete))
905 940
941 (defun widget-copy (widget)
942 "Make a deep copy of WIDGET."
943 (widget-apply (copy-sequence widget) :copy))
944
906 (defun widget-convert (type &rest args) 945 (defun widget-convert (type &rest args)
907 "Convert TYPE to a widget without inserting it in the buffer. 946 "Convert TYPE to a widget without inserting it in the buffer.
908 The optional ARGS are additional keyword arguments." 947 The optional ARGS are additional keyword arguments."
909 ;; Don't touch the type. 948 ;; Don't touch the type.
910 (let* ((widget (if (symbolp type) 949 (let* ((widget (if (symbolp type)
933 (setq widget (funcall convert-widget widget)))) 972 (setq widget (funcall convert-widget widget))))
934 (setq type (get (car type) 'widget-type))) 973 (setq type (get (car type) 'widget-type)))
935 ;; Finally set the keyword args. 974 ;; Finally set the keyword args.
936 (while keys 975 (while keys
937 (let ((next (nth 0 keys))) 976 (let ((next (nth 0 keys)))
938 (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) 977 (if (keywordp next)
939 (progn 978 (progn
940 (widget-put widget next (nth 1 keys)) 979 (widget-put widget next (nth 1 keys))
941 (setq keys (nthcdr 2 keys))) 980 (setq keys (nthcdr 2 keys)))
942 (setq keys nil)))) 981 (setq keys nil))))
943 ;; Convert the :value to internal format. 982 ;; Convert the :value to internal format.
944 (if (widget-member widget :value) 983 (if (widget-member widget :value)
945 (let ((value (widget-get widget :value))) 984 (widget-put widget
946 (widget-put widget 985 :value (widget-apply widget
947 :value (widget-apply widget :value-to-internal value)))) 986 :value-to-internal
987 (widget-get widget :value))))
948 ;; Return the newly created widget. 988 ;; Return the newly created widget.
949 widget)) 989 widget))
950 990
991 ;;;###autoload
951 (defun widget-insert (&rest args) 992 (defun widget-insert (&rest args)
952 "Call `insert' with ARGS even if surrounding text is read only." 993 "Call `insert' with ARGS even if surrounding text is read only."
953 (let ((inhibit-read-only t) 994 (let ((inhibit-read-only t)
954 before-change-functions 995 before-change-functions
955 after-change-functions) 996 after-change-functions)
989 (let ((from (widget-get widget :from)) 1030 (let ((from (widget-get widget :from))
990 (to (widget-get widget :to)) 1031 (to (widget-get widget :to))
991 (button (widget-get widget :button-extent)) 1032 (button (widget-get widget :button-extent))
992 (sample (widget-get widget :sample-extent)) 1033 (sample (widget-get widget :sample-extent))
993 (doc (widget-get widget :doc-extent)) 1034 (doc (widget-get widget :doc-extent))
994 (field (widget-get widget :field-extent)) 1035 (field (widget-get widget :field-extent)))
995 (children (widget-get widget :children)))
996 (set-marker from nil) 1036 (set-marker from nil)
997 (set-marker to nil) 1037 (set-marker to nil)
998 ;; Maybe we should delete the extents here? As this code doesn't 1038 ;; Maybe we should delete the extents here? As this code doesn't
999 ;; remove them from widget structures, maybe it's safer to just 1039 ;; remove them from widget structures, maybe it's safer to just
1000 ;; detach them. That's what `delete-overlay' did. 1040 ;; detach them. That's what GNU-compatible `delete-overlay' does.
1001 (when button 1041 (when button
1002 (detach-extent button)) 1042 (detach-extent button))
1003 (when sample 1043 (when sample
1004 (detach-extent sample)) 1044 (detach-extent sample))
1005 (when doc 1045 (when doc
1006 (detach-extent doc)) 1046 (detach-extent doc))
1007 (when field 1047 (when field
1008 (detach-extent field)) 1048 (detach-extent field))
1009 (mapc 'widget-leave-text children))) 1049 (mapc 'widget-leave-text (widget-get widget :children))))
1010 1050
1011 1051
1012 ;;; Keymap and Commands. 1052 ;;; Keymap and Commands.
1013 1053
1014 (defvar widget-keymap nil 1054 (defvar widget-keymap nil
1412 1452
1413 (defvar widget-field-list nil) 1453 (defvar widget-field-list nil)
1414 ;; List of all editable fields in the buffer. 1454 ;; List of all editable fields in the buffer.
1415 (make-variable-buffer-local 'widget-field-list) 1455 (make-variable-buffer-local 'widget-field-list)
1416 1456
1457 ;; Is this a misnomer?
1458 (defun widget-at (pos)
1459 "The button or field at POS."
1460 (or (get-char-property pos 'button)
1461 (get-char-property pos 'field)))
1462
1463 ;;;###autoload
1417 (defun widget-setup () 1464 (defun widget-setup ()
1418 "Setup current buffer so editing string widgets works." 1465 "Setup current buffer so editing string widgets works."
1419 (let ((inhibit-read-only t) 1466 (let ((inhibit-read-only t)
1420 (after-change-functions nil) 1467 (after-change-functions nil)
1421 before-change-functions 1468 before-change-functions
1444 1491
1445 (defvar widget-field-was nil) 1492 (defvar widget-field-was nil)
1446 ;; The widget data before the change. 1493 ;; The widget data before the change.
1447 (make-variable-buffer-local 'widget-field-was) 1494 (make-variable-buffer-local 'widget-field-was)
1448 1495
1496 (defun widget-field-at (pos)
1497 "Return the widget field at POS, or nil if none."
1498 (let ((field (get-char-property (or pos (point)) 'field)))
1499 (if (eq field 'boundary)
1500 nil
1501 field)))
1502
1449 (defun widget-field-buffer (widget) 1503 (defun widget-field-buffer (widget)
1450 "Return the buffer containing WIDGET. 1504 "Return the buffer containing WIDGET.
1451 1505
1452 It is an error to use this function after creating the widget but before 1506 It is an error to use this function after creating the widget but before
1453 invoking `widget-setup'." 1507 invoking `widget-setup'."
1478 "Return the field at POS. 1532 "Return the field at POS.
1479 Unlike (get-char-property POS 'field) this, works with empty fields too. 1533 Unlike (get-char-property POS 'field) this, works with empty fields too.
1480 1534
1481 Warning: using this function after creating the widget but before invoking 1535 Warning: using this function after creating the widget but before invoking
1482 `widget-setup' will always fail." 1536 `widget-setup' will always fail."
1537 ;; XEmacs: use `map-extents' instead of a while loop
1483 (let ((field-extent (map-extents (lambda (extent ignore) 1538 (let ((field-extent (map-extents (lambda (extent ignore)
1484 extent) 1539 extent)
1485 nil pos pos nil nil 'field))) 1540 nil pos pos nil nil 'field)))
1486 (and field-extent 1541 (and field-extent
1487 (extent-property field-extent 'field)))) 1542 (extent-property field-extent 'field))))
1488
1489 ;; Old version, without `map-extents'.
1490 ;(defun widget-field-find (pos)
1491 ; (let ((fields widget-field-list)
1492 ; field found)
1493 ; (while fields
1494 ; (setq field (car fields)
1495 ; fields (cdr fields))
1496 ; (let ((start (widget-field-start field))
1497 ; (end (widget-field-end field)))
1498 ; (when (and (<= start pos) (<= pos end))
1499 ; (when found
1500 ; (debug "Overlapping fields"))
1501 ; (setq found field))))
1502 ; found))
1503 1543
1504 ;; Warning: using this function after creating the widget but before 1544 ;; Warning: using this function after creating the widget but before
1505 ;; invoking `widget-setup' will always fail. 1545 ;; invoking `widget-setup' will always fail.
1506 (defun widget-before-change (from to) 1546 (defun widget-before-change (from to)
1507 ;; Barf if the text changed is outside the editable fields. 1547 ;; Barf if the text changed is outside the editable fields.
1539 (add-hook 'before-change-functions 'widget-before-change nil t) 1579 (add-hook 'before-change-functions 'widget-before-change nil t)
1540 (make-local-hook 'after-change-functions) 1580 (make-local-hook 'after-change-functions)
1541 (add-hook 'after-change-functions 'widget-after-change nil t)) 1581 (add-hook 'after-change-functions 'widget-after-change nil t))
1542 1582
1543 (defun widget-after-change (from to old) 1583 (defun widget-after-change (from to old)
1544 ;; Adjust field size and text properties. 1584 "Adjust field size and text properties.
1545 1585
1546 ;; Also, notify the widgets (so, for example, a variable changes its 1586 Also, notify the widgets (so, for example, a variable changes its
1547 ;; state to `modified'. when it is being edited.) 1587 state to `modified'. when it is being edited)."
1548 (condition-case nil 1588 (condition-case nil
1549 (let ((field (widget-field-find from)) 1589 (let ((field (widget-field-find from))
1550 (other (widget-field-find to))) 1590 (other (widget-field-find to)))
1551 (when field 1591 (when field
1552 (unless (eq field other) 1592 (unless (eq field other)
1602 (setq child (car children) 1642 (setq child (car children)
1603 children (cdr children) 1643 children (cdr children)
1604 found (widget-apply child :validate))) 1644 found (widget-apply child :validate)))
1605 found)) 1645 found))
1606 1646
1607 (defun widget-types-convert-widget (widget) 1647 (defun widget-types-copy (widget)
1648 "Copy :args as widget types in WIDGET."
1649 (widget-put widget :args (mapcar 'widget-copy (widget-get widget :args)))
1650 widget)
1651
1652 ;; Made defsubst to speed up face editor creation.
1653 (defsubst widget-types-convert-widget (widget)
1608 "Convert :args as widget types in WIDGET." 1654 "Convert :args as widget types in WIDGET."
1609 (widget-put widget :args (mapcar 'widget-convert (widget-get widget :args))) 1655 (widget-put widget :args (mapcar 'widget-convert (widget-get widget :args)))
1610 widget) 1656 widget)
1611 1657
1612 (defun widget-value-convert-widget (widget) 1658 (defun widget-value-convert-widget (widget)
1643 :delete 'widget-default-delete 1689 :delete 'widget-default-delete
1644 :value-set 'widget-default-value-set 1690 :value-set 'widget-default-value-set
1645 :value-inline 'widget-default-value-inline 1691 :value-inline 'widget-default-value-inline
1646 :default-get 'widget-default-default-get 1692 :default-get 'widget-default-default-get
1647 :menu-tag-get 'widget-default-menu-tag-get 1693 :menu-tag-get 'widget-default-menu-tag-get
1648 :validate (lambda (widget) nil) 1694 :validate #'ignore
1649 :active 'widget-default-active 1695 :active 'widget-default-active
1650 :activate 'widget-specify-active 1696 :activate 'widget-specify-active
1651 :deactivate 'widget-default-deactivate 1697 :deactivate 'widget-default-deactivate
1652 :mouse-down-action (lambda (widget event) nil) 1698 :mouse-down-action #'ignore
1653 :action 'widget-default-action 1699 :action 'widget-default-action
1654 :notify 'widget-default-notify 1700 :notify 'widget-default-notify
1655 :prompt-value 'widget-default-prompt-value) 1701 :prompt-value 'widget-default-prompt-value)
1656 1702
1657 (defun widget-default-complete (widget) 1703 (defun widget-default-complete (widget)
1658 "Call the value of the :complete-function property of WIDGET. 1704 "Call the value of the :complete-function property of WIDGET.
1659 If that does not exists, call the value of `widget-complete-field'." 1705 If that does not exists, call the value of `widget-complete-field'."
1660 (let ((fun (widget-get widget :complete-function))) 1706 (call-interactively (or (widget-get widget :complete-function)
1661 (call-interactively (or fun widget-complete-field)))) 1707 widget-complete-field)))
1662 1708
1663 (defun widget-default-create (widget) 1709 (defun widget-default-create (widget)
1664 "Create WIDGET at point in the current buffer." 1710 "Create WIDGET at point in the current buffer."
1665 (widget-specify-insert 1711 (widget-specify-insert
1666 (let ((from (point)) 1712 (let ((from (point))
1668 sample-begin sample-end 1714 sample-begin sample-end
1669 doc-begin doc-end 1715 doc-begin doc-end
1670 value-pos) 1716 value-pos)
1671 (insert (widget-get widget :format)) 1717 (insert (widget-get widget :format))
1672 (goto-char from) 1718 (goto-char from)
1673 ;; Parse escapes in format. Coding this in C would speed up 1719 ;; Parse escapes in format.
1674 ;; things *a lot*. 1720 ;; Coding this in C would speed up things *a lot*.
1675 (while (re-search-forward "%\\(.\\)" nil t) 1721 (while (re-search-forward "%\\(.\\)" nil t)
1676 (let ((escape (aref (match-string 1) 0))) 1722 (let ((escape (aref (match-string 1) 0)))
1677 (replace-match "" t t) 1723 (replace-match "" t t)
1678 (cond ((eq escape ?%) 1724 (cond ((eq escape ?%)
1679 (insert "%")) 1725 (insert ?%))
1680 ((eq escape ?\[) 1726 ((eq escape ?\[)
1681 (setq button-begin (point-marker)) 1727 (setq button-begin (point-marker))
1682 (set-marker-insertion-type button-begin nil)) 1728 (set-marker-insertion-type button-begin nil))
1683 ((eq escape ?\]) 1729 ((eq escape ?\])
1684 (setq button-end (point-marker)) 1730 (setq button-end (point-marker))
1687 (setq sample-begin (point))) 1733 (setq sample-begin (point)))
1688 ((eq escape ?\}) 1734 ((eq escape ?\})
1689 (setq sample-end (point))) 1735 (setq sample-end (point)))
1690 ((eq escape ?n) 1736 ((eq escape ?n)
1691 (when (widget-get widget :indent) 1737 (when (widget-get widget :indent)
1692 (insert "\n") 1738 (insert ?\n)
1693 (insert-char ?\ (widget-get widget :indent)))) 1739 (insert-char ?\ (widget-get widget :indent))))
1694 ((eq escape ?t) 1740 ((eq escape ?t)
1695 (let* ((tag (widget-get widget :tag)) 1741 (let* ((tag (widget-get widget :tag))
1696 (glyph (widget-get widget :tag-glyph))) 1742 (glyph (widget-get widget :tag-glyph)))
1697 (cond (glyph 1743 (cond (glyph
1699 (widget-glyph-insert 1745 (widget-glyph-insert
1700 widget (or tag "Image") glyph))) 1746 widget (or tag "Image") glyph)))
1701 (tag 1747 (tag
1702 (insert tag)) 1748 (insert tag))
1703 (t 1749 (t
1704 (let ((standard-output (current-buffer))) 1750 (princ (widget-get widget :value)
1705 (princ (widget-get widget :value))))))) 1751 (current-buffer))))))
1706 ((eq escape ?d) 1752 ((eq escape ?d)
1707 (let ((doc (widget-get widget :doc))) 1753 (let ((doc (widget-get widget :doc)))
1708 (when doc 1754 (when doc
1709 (setq doc-begin (point)) 1755 (setq doc-begin (point))
1710 (insert doc) 1756 (insert doc)
1711 (while (eq (preceding-char) ?\n) 1757 (while (eq (preceding-char) ?\n)
1712 (delete-backward-char 1)) 1758 (delete-backward-char 1))
1713 (insert "\n") 1759 (insert ?\n)
1714 (setq doc-end (point))))) 1760 (setq doc-end (point)))))
1715 ((eq escape ?v) 1761 ((eq escape ?v)
1716 (if (and button-begin (not button-end)) 1762 (if (and button-begin (not button-end))
1717 (widget-apply widget :value-create) 1763 (widget-apply widget :value-create)
1718 (setq value-pos (point-marker)))) 1764 (setq value-pos (point-marker))))
1749 ;; We recognize the %h escape by default. 1795 ;; We recognize the %h escape by default.
1750 (let* ((buttons (widget-get widget :buttons))) 1796 (let* ((buttons (widget-get widget :buttons)))
1751 (cond ((eq escape ?h) 1797 (cond ((eq escape ?h)
1752 (let* ((doc-property (widget-get widget :documentation-property)) 1798 (let* ((doc-property (widget-get widget :documentation-property))
1753 (doc-try (cond ((widget-get widget :doc)) 1799 (doc-try (cond ((widget-get widget :doc))
1800 ((functionp doc-property)
1801 (funcall doc-property
1802 (widget-get widget :value)))
1754 ((symbolp doc-property) 1803 ((symbolp doc-property)
1755 (documentation-property 1804 (documentation-property
1756 (widget-get widget :value) 1805 (widget-get widget :value)
1757 doc-property)) 1806 doc-property))))
1758 (t
1759 (funcall doc-property
1760 (widget-get widget :value)))))
1761 (doc-text (and (stringp doc-try) 1807 (doc-text (and (stringp doc-try)
1762 (> (length doc-try) 1) 1808 (> (length doc-try) 1)
1763 doc-try)) 1809 doc-try))
1764 (doc-indent (widget-get widget :documentation-indent))) 1810 (doc-indent (widget-get widget :documentation-indent)))
1765 (when doc-text 1811 (when doc-text
1839 (save-excursion 1885 (save-excursion
1840 (goto-char (widget-get widget :from)) 1886 (goto-char (widget-get widget :from))
1841 (widget-apply widget :delete) 1887 (widget-apply widget :delete)
1842 (widget-put widget :value value) 1888 (widget-put widget :value value)
1843 (widget-apply widget :create)) 1889 (widget-apply widget :create))
1844 (when offset 1890 (if offset
1845 (if (< offset 0) 1891 (if (< offset 0)
1846 (goto-char (+ (widget-get widget :to) offset 1)) 1892 (goto-char (+ (widget-get widget :to) offset 1))
1847 (goto-char (min (+ from offset) (1- (widget-get widget :to)))))))) 1893 (goto-char (min (+ from offset) (1- (widget-get widget :to))))))))
1848 1894
1849 (defun widget-default-value-inline (widget) 1895 (defun widget-default-value-inline (widget)
1850 "Wrap value in a list unless it is inline." 1896 "Wrap value in a list unless it is inline."
1851 (if (widget-get widget :inline) 1897 (if (widget-get widget :inline)
1852 (widget-value widget) 1898 (widget-value widget)
1906 :action 'widget-item-action 1952 :action 'widget-item-action
1907 :format "%t\n") 1953 :format "%t\n")
1908 1954
1909 (defun widget-item-value-create (widget) 1955 (defun widget-item-value-create (widget)
1910 "Insert the printed representation of the value." 1956 "Insert the printed representation of the value."
1911 (let ((standard-output (current-buffer))) 1957 (princ (widget-get widget :value) (current-buffer)))
1912 (princ (widget-get widget :value))))
1913 1958
1914 (defun widget-item-match (widget value) 1959 (defun widget-item-match (widget value)
1915 ;; Match if the value is the same. 1960 ;; Match if the value is the same.
1916 (equal (widget-get widget :value) value)) 1961 (equal (widget-get widget :value) value))
1917 1962
1927 (defun widget-sublist (list start &optional end) 1972 (defun widget-sublist (list start &optional end)
1928 "Return the sublist of LIST from START to END. 1973 "Return the sublist of LIST from START to END.
1929 If END is omitted, it defaults to the length of LIST." 1974 If END is omitted, it defaults to the length of LIST."
1930 (if (> start 0) (setq list (nthcdr start list))) 1975 (if (> start 0) (setq list (nthcdr start list)))
1931 (if end 1976 (if end
1932 (if (<= end start) 1977 (unless (<= end start)
1933 nil
1934 (setq list (copy-sequence list)) 1978 (setq list (copy-sequence list))
1935 (setcdr (nthcdr (- end start 1) list) nil) 1979 (setcdr (nthcdr (- end start 1) list) nil)
1936 list) 1980 list)
1937 (copy-sequence list))) 1981 (copy-sequence list)))
1938 1982
2033 (defun widget-url-link-help-echo (widget) 2077 (defun widget-url-link-help-echo (widget)
2034 (concat "Visit <URL:" (widget-value widget) ">")) 2078 (concat "Visit <URL:" (widget-value widget) ">"))
2035 2079
2036 (defun widget-url-link-action (widget &optional event) 2080 (defun widget-url-link-action (widget &optional event)
2037 "Open the url specified by WIDGET." 2081 "Open the url specified by WIDGET."
2038 (if-fboundp 'browse-url 2082 (if (fboundp 'browse-url)
2039 (browse-url (widget-value widget)) 2083 (browse-url (widget-value widget))
2040 ;; #### Should subclass a 'missing-package error. 2084 ;; #### Should subclass a 'missing-package error.
2041 (error 'unimplemented "No `browse-url' package; cannot follow URLs in this XEmacs"))) 2085 (error 'unimplemented
2086 "No `browse-url' package; cannot follow URLs in this XEmacs")))
2042 2087
2043 ;;; The `function-link' Widget. 2088 ;;; The `function-link' Widget.
2044 2089
2045 (define-widget 'function-link 'link 2090 (define-widget 'function-link 'link
2046 "A link to an Emacs function." 2091 "A link to an Emacs function."
2099 (define-widget 'editable-field 'default 2144 (define-widget 'editable-field 'default
2100 "An editable text field." 2145 "An editable text field."
2101 :convert-widget 'widget-value-convert-widget 2146 :convert-widget 'widget-value-convert-widget
2102 :keymap widget-field-keymap 2147 :keymap widget-field-keymap
2103 :format "%v" 2148 :format "%v"
2149 :help-echo "M-TAB: complete field; RET: enter value"
2104 :value "" 2150 :value ""
2105 :prompt-internal 'widget-field-prompt-internal 2151 :prompt-internal 'widget-field-prompt-internal
2106 :prompt-history 'widget-field-history 2152 :prompt-history 'widget-field-history
2107 :prompt-value 'widget-field-prompt-value 2153 :prompt-value 'widget-field-prompt-value
2108 :action 'widget-field-action 2154 :action 'widget-field-action
2109 :validate 'widget-field-validate 2155 :validate 'widget-field-validate
2110 :valid-regexp "" 2156 :valid-regexp ""
2111 :error "No match" 2157 :error "Field's value doesn't match allowed forms"
2112 :value-create 'widget-field-value-create 2158 :value-create 'widget-field-value-create
2113 :value-delete 'widget-field-value-delete 2159 :value-delete 'widget-field-value-delete
2114 :value-get 'widget-field-value-get 2160 :value-get 'widget-field-value-get
2115 :match 'widget-field-match) 2161 :match 'widget-field-match)
2116 2162
2123 the earlier input." 2169 the earlier input."
2124 (read-string prompt initial history)) 2170 (read-string prompt initial history))
2125 2171
2126 (defun widget-field-prompt-value (widget prompt value unbound) 2172 (defun widget-field-prompt-value (widget prompt value unbound)
2127 "Prompt for a string." 2173 "Prompt for a string."
2128 (let ((initial (if unbound 2174 (widget-apply widget
2129 nil 2175 :value-to-external
2130 (cons (widget-apply widget :value-to-internal 2176 (widget-apply widget
2131 value) 0))) 2177 :prompt-internal prompt
2132 (history (widget-get widget :prompt-history))) 2178 (unless unbound
2133 (let ((answer (widget-apply widget 2179 (cons (widget-apply widget
2134 :prompt-internal prompt initial history))) 2180 :value-to-internal value)
2135 (widget-apply widget :value-to-external answer)))) 2181 0))
2182 (widget-get widget :prompt-history))))
2136 2183
2137 (defvar widget-edit-functions nil) 2184 (defvar widget-edit-functions nil)
2138 2185
2139 (defun widget-field-action (widget &optional event) 2186 (defun widget-field-action (widget &optional event)
2140 ;; Edit the value in the minibuffer. 2187 ;; Edit the value in the minibuffer.
2165 ; (widget-forward 1) 2212 ; (widget-forward 1)
2166 ; (run-hook-with-args 'widget-edit-functions widget)) 2213 ; (run-hook-with-args 'widget-edit-functions widget))
2167 2214
2168 (defun widget-field-validate (widget) 2215 (defun widget-field-validate (widget)
2169 "Valid if the content matches `:valid-regexp'." 2216 "Valid if the content matches `:valid-regexp'."
2170 (save-excursion 2217 (save-excursion ; XEmacs
2171 (let ((value (widget-apply widget :value-get)) 2218 (unless (string-match (widget-get widget :valid-regexp)
2172 (regexp (widget-get widget :valid-regexp))) 2219 (widget-apply widget :value-get))
2173 (if (string-match regexp value) 2220 widget)))
2174 nil
2175 widget))))
2176 2221
2177 (defun widget-field-value-create (widget) 2222 (defun widget-field-value-create (widget)
2178 "Create an editable text field." 2223 "Create an editable text field."
2179 (let ((size (widget-get widget :size)) 2224 (let ((size (widget-get widget :size))
2180 (value (widget-get widget :value)) 2225 (value (widget-get widget :value))
2239 (stringp value)) 2284 (stringp value))
2240 2285
2241 ;;; The `text' Widget. 2286 ;;; The `text' Widget.
2242 2287
2243 (define-widget 'text 'editable-field 2288 (define-widget 'text 'editable-field
2244 :keymap widget-text-keymap 2289 "A multiline text area."
2245 "A multiline text area.") 2290 :keymap widget-text-keymap)
2246 2291
2247 ;;; The `menu-choice' Widget. 2292 ;;; The `menu-choice' Widget.
2248 2293
2249 (define-widget 'menu-choice 'default 2294 (define-widget 'menu-choice 'default
2250 "A menu of options." 2295 "A menu of options."
2379 (widget-apply widget :notify widget event))) 2424 (widget-apply widget :notify widget event)))
2380 (run-hook-with-args 'widget-edit-functions widget)) 2425 (run-hook-with-args 'widget-edit-functions widget))
2381 2426
2382 (defun widget-choice-validate (widget) 2427 (defun widget-choice-validate (widget)
2383 ;; Valid if we have made a valid choice. 2428 ;; Valid if we have made a valid choice.
2384 (let ((void (widget-get widget :void)) 2429 (if (eq (widget-get widget :void) (widget-get widget :choice))
2385 (choice (widget-get widget :choice)) 2430 widget
2386 (child (car (widget-get widget :children)))) 2431 (widget-apply (car (widget-get widget :children)) :validate)))
2387 (if (eq void choice)
2388 widget
2389 (widget-apply child :validate))))
2390 2432
2391 (defun widget-choice-match (widget value) 2433 (defun widget-choice-match (widget value)
2392 ;; Matches if one of the choices matches. 2434 ;; Matches if one of the choices matches.
2393 (let ((args (widget-get widget :args)) 2435 (let ((args (widget-get widget :args))
2394 current found) 2436 current found)
2501 ;; Parse % escapes in format. 2543 ;; Parse % escapes in format.
2502 (while (re-search-forward "%\\([bv%]\\)" nil t) 2544 (while (re-search-forward "%\\([bv%]\\)" nil t)
2503 (let ((escape (aref (match-string 1) 0))) 2545 (let ((escape (aref (match-string 1) 0)))
2504 (replace-match "" t t) 2546 (replace-match "" t t)
2505 (cond ((eq escape ?%) 2547 (cond ((eq escape ?%)
2506 (insert "%")) 2548 (insert ?%))
2507 ((eq escape ?b) 2549 ((eq escape ?b)
2508 (setq button (apply 'widget-create-child-and-convert 2550 (setq button (apply 'widget-create-child-and-convert
2509 widget 'checkbox 2551 widget 'checkbox
2510 :value (not (null chosen)) 2552 :value (not (null chosen))
2511 button-args))) 2553 button-args)))
2686 ;; Parse % escapes in format. 2728 ;; Parse % escapes in format.
2687 (while (re-search-forward "%\\([bv%]\\)" nil t) 2729 (while (re-search-forward "%\\([bv%]\\)" nil t)
2688 (let ((escape (aref (match-string 1) 0))) 2730 (let ((escape (aref (match-string 1) 0)))
2689 (replace-match "" t t) 2731 (replace-match "" t t)
2690 (cond ((eq escape ?%) 2732 (cond ((eq escape ?%)
2691 (insert "%")) 2733 (insert ?%))
2692 ((eq escape ?b) 2734 ((eq escape ?b)
2693 (setq button (apply 'widget-create-child-and-convert 2735 (setq button (apply 'widget-create-child-and-convert
2694 widget 'radio-button 2736 widget 'radio-button
2695 :value (not (null chosen)) 2737 :value (not (null chosen))
2696 button-args))) 2738 button-args)))
2723 (let ((children (widget-get widget :children)) 2765 (let ((children (widget-get widget :children))
2724 current found) 2766 current found)
2725 (while children 2767 (while children
2726 (setq current (car children) 2768 (setq current (car children)
2727 children (cdr children)) 2769 children (cdr children))
2728 (let* ((button (widget-get current :button)) 2770 (when (widget-apply (widget-get current :button) :value-get)
2729 (value (widget-apply button :value-get))) 2771 (setq found current
2730 (when value 2772 children nil)))
2731 (setq found current
2732 children nil))))
2733 found)) 2773 found))
2734 2774
2735 (defun widget-radio-value-inline (widget) 2775 (defun widget-radio-value-inline (widget)
2736 ;; Get value of the child widget. 2776 ;; Get value of the child widget.
2737 (let ((children (widget-get widget :children)) 2777 (let ((children (widget-get widget :children))
2738 current found) 2778 current found)
2739 (while children 2779 (while children
2740 (setq current (car children) 2780 (setq current (car children)
2741 children (cdr children)) 2781 children (cdr children))
2742 (let* ((button (widget-get current :button)) 2782 (when (widget-apply (widget-get current :button) :value-get)
2743 (value (widget-apply button :value-get))) 2783 (setq found (widget-apply current :value-inline)
2744 (when value 2784 children nil)))
2745 (setq found (widget-apply current :value-inline)
2746 children nil))))
2747 found)) 2785 found))
2748 2786
2749 (defun widget-radio-value-set (widget value) 2787 (defun widget-radio-value-set (widget value)
2750 ;; We can't just delete and recreate a radio widget, since children 2788 ;; We can't just delete and recreate a radio widget, since children
2751 ;; can be added after the original creation and won't be recreated 2789 ;; can be added after the original creation and won't be recreated
2862 2900
2863 (defun widget-editable-list-value-create (widget) 2901 (defun widget-editable-list-value-create (widget)
2864 ;; Insert all values 2902 ;; Insert all values
2865 (let* ((value (widget-get widget :value)) 2903 (let* ((value (widget-get widget :value))
2866 (type (nth 0 (widget-get widget :args))) 2904 (type (nth 0 (widget-get widget :args)))
2867 (inlinep (widget-get type :inline))
2868 children) 2905 children)
2869 (widget-put widget :value-pos (copy-marker (point))) 2906 (widget-put widget :value-pos (copy-marker (point)))
2870 (set-marker-insertion-type (widget-get widget :value-pos) t) 2907 (set-marker-insertion-type (widget-get widget :value-pos) t)
2871 (while value 2908 (while value
2872 (let ((answer (widget-match-inline type value))) 2909 (let ((answer (widget-match-inline type value)))
2873 (if answer 2910 (if answer
2874 (setq children (cons (widget-editable-list-entry-create 2911 (setq children (cons (widget-editable-list-entry-create
2875 widget 2912 widget
2876 (if inlinep 2913 (if (widget-get type :inline)
2877 (car answer) 2914 (car answer)
2878 (car (car answer))) 2915 (car (car answer)))
2879 t) 2916 t)
2880 children) 2917 children)
2881 value (cdr answer)) 2918 value (cdr answer))
2969 ;; Parse % escapes in format. 3006 ;; Parse % escapes in format.
2970 (while (re-search-forward "%\\(.\\)" nil t) 3007 (while (re-search-forward "%\\(.\\)" nil t)
2971 (let ((escape (aref (match-string 1) 0))) 3008 (let ((escape (aref (match-string 1) 0)))
2972 (replace-match "" t t) 3009 (replace-match "" t t)
2973 (cond ((eq escape ?%) 3010 (cond ((eq escape ?%)
2974 (insert "%")) 3011 (insert ?%))
2975 ((eq escape ?i) 3012 ((eq escape ?i)
2976 (setq insert (apply 'widget-create-child-and-convert 3013 (setq insert (apply 'widget-create-child-and-convert
2977 widget 'insert-button 3014 widget 'insert-button
2978 (widget-get widget :insert-button-args)))) 3015 (widget-get widget :insert-button-args))))
2979 ((eq escape ?d) 3016 ((eq escape ?d)
3189 (start (point))) 3226 (start (point)))
3190 (if (string-match "\n" doc) 3227 (if (string-match "\n" doc)
3191 (let ((before (substring doc 0 (match-beginning 0))) 3228 (let ((before (substring doc 0 (match-beginning 0)))
3192 (after (substring doc (match-beginning 0))) 3229 (after (substring doc (match-beginning 0)))
3193 buttons) 3230 buttons)
3194 (insert before " ") 3231 (insert before ?\ )
3195 (widget-documentation-link-add widget start (point)) 3232 (widget-documentation-link-add widget start (point))
3196 (push (widget-create-child-and-convert 3233 (push (widget-create-child-and-convert
3197 widget 'visibility 3234 widget 'visibility
3198 :help-echo (lambda (widget) 3235 :help-echo (lambda (widget)
3199 (concat 3236 (concat
3211 (insert after) 3248 (insert after)
3212 (widget-documentation-link-add widget start (point))) 3249 (widget-documentation-link-add widget start (point)))
3213 (widget-put widget :buttons buttons)) 3250 (widget-put widget :buttons buttons))
3214 (insert doc) 3251 (insert doc)
3215 (widget-documentation-link-add widget start (point)))) 3252 (widget-documentation-link-add widget start (point))))
3216 (insert "\n")) 3253 (insert ?\n))
3217 3254
3218 (defun widget-documentation-string-action (widget &rest ignore) 3255 (defun widget-documentation-string-action (widget &rest ignore)
3219 ;; Toggle documentation. 3256 ;; Toggle documentation.
3220 (let ((parent (widget-get widget :parent))) 3257 (let ((parent (widget-get widget :parent)))
3221 (widget-put parent :documentation-shown 3258 (widget-put parent :documentation-shown
3222 (not (widget-get parent :documentation-shown)))) 3259 (not (widget-get parent :documentation-shown))))
3223 ;; Redraw. 3260 ;; Redraw.
3224 (widget-value-set widget (widget-value widget))) 3261 (widget-value-set widget (widget-value widget)))
3225 3262
3263
3226 ;;; The Sexp Widgets. 3264 ;;; The Sexp Widgets.
3227 3265
3228 (define-widget 'const 'item 3266 (define-widget 'const 'item
3229 "An immutable sexp." 3267 "An immutable sexp."
3230 :prompt-value 'widget-const-prompt-value 3268 :prompt-value 'widget-const-prompt-value
3245 (define-widget 'variable-item 'const 3283 (define-widget 'variable-item 'const
3246 "An immutable variable name." 3284 "An immutable variable name."
3247 :format "%v\n%h" 3285 :format "%v\n%h"
3248 :documentation-property 'variable-documentation) 3286 :documentation-property 'variable-documentation)
3249 3287
3288 (define-widget 'other 'sexp
3289 "Matches any value, but doesn't let the user edit the value.
3290 This is useful as last item in a `choice' widget.
3291 You should use this widget type with a default value,
3292 as in (other DEFAULT) or (other :tag \"NAME\" DEFAULT).
3293 If the user selects this alternative, that specifies DEFAULT
3294 as the value."
3295 :tag "Other"
3296 :format "%t%n"
3297 :value 'other)
3298
3250 (defvar widget-string-prompt-value-history nil 3299 (defvar widget-string-prompt-value-history nil
3251 "History of input to `widget-string-prompt-value'.") 3300 "History of input to `widget-string-prompt-value'.")
3252 3301
3253 (define-widget 'string 'editable-field 3302 (define-widget 'string 'editable-field
3254 "A string" 3303 "A string"
3273 (string-match value "")) 3322 (string-match value ""))
3274 (error nil)))) 3323 (error nil))))
3275 3324
3276 (defun widget-regexp-validate (widget) 3325 (defun widget-regexp-validate (widget)
3277 "Check that the value of WIDGET is a valid regexp." 3326 "Check that the value of WIDGET is a valid regexp."
3278 (let ((value (widget-value widget))) 3327 (condition-case data
3279 (condition-case data 3328 (prog1 nil
3280 (prog1 nil 3329 (string-match (widget-value widget) ""))
3281 (string-match value "")) 3330 (error (widget-put widget :error (error-message-string data))
3282 (error (widget-put widget :error (error-message-string data)) 3331 widget)))
3283 widget))))
3284 3332
3285 (define-widget 'file 'string 3333 (define-widget 'file 'string
3286 "A file widget. 3334 "A file widget.
3287 It will read a file name from the minibuffer when invoked." 3335 It will read a file name from the minibuffer when invoked."
3288 :complete-function 'widget-file-complete 3336 :complete-function 'widget-file-complete
3310 ((not (string= name-part completion)) 3358 ((not (string= name-part completion))
3311 (delete-region beg end) 3359 (delete-region beg end)
3312 (insert (expand-file-name completion directory))) 3360 (insert (expand-file-name completion directory)))
3313 (t 3361 (t
3314 (message "Making completion list...") 3362 (message "Making completion list...")
3315 (let ((list (file-name-all-completions name-part directory))) 3363 (with-output-to-temp-buffer "*Completions*"
3316 (setq list (sort list 'string<)) 3364 (display-completion-list
3317 (with-output-to-temp-buffer "*Completions*" 3365 (sort (file-name-all-completions name-part directory)
3318 (display-completion-list list))) 3366 'string<)))
3319 (message "Making completion list...%s" "done"))))) 3367 (message "Making completion list...%s" "done")))))
3320 3368
3321 (defun widget-file-prompt-value (widget prompt value unbound) 3369 (defun widget-file-prompt-value (widget prompt value unbound)
3322 ;; Read file from minibuffer. 3370 ;; Read file from minibuffer.
3323 (abbreviate-file-name 3371 (abbreviate-file-name
3406 ;; This part issues a warning when compiling without Mule. Is there a 3454 ;; This part issues a warning when compiling without Mule. Is there a
3407 ;; way of shutting it up? 3455 ;; way of shutting it up?
3408 ;; 3456 ;;
3409 ;; OK, I'll simply comment the whole thing out, until someone decides 3457 ;; OK, I'll simply comment the whole thing out, until someone decides
3410 ;; to do something with it. 3458 ;; to do something with it.
3411 ;(defvar widget-coding-system-prompt-value-history nil 3459
3412 ; "History of input to `widget-coding-system-prompt-value'.") 3460 ;; OK, _I_'ll simply comment it back in, so somebody will get irritated and
3413 3461 ;; do something about it.
3414 ;(define-widget 'coding-system 'symbol 3462
3415 ; "A MULE coding-system." 3463 (defvar widget-coding-system-prompt-value-history nil
3416 ; :format "%{%t%}: %v" 3464 "History of input to `widget-coding-system-prompt-value'.")
3417 ; :tag "Coding system" 3465
3418 ; :prompt-history 'widget-coding-system-prompt-value-history 3466 (define-widget 'coding-system 'symbol
3419 ; :prompt-value 'widget-coding-system-prompt-value 3467 "A MULE coding-system."
3420 ; :action 'widget-coding-system-action) 3468 :format "%{%t%}: %v"
3421 3469 :tag "Coding system"
3422 ;(defun widget-coding-system-prompt-value (widget prompt value unbound) 3470 :prompt-history 'widget-coding-system-prompt-value-history
3423 ; ;; Read coding-system from minibuffer. 3471 :prompt-value 'widget-coding-system-prompt-value
3424 ; (intern 3472 :action 'widget-coding-system-action)
3425 ; (completing-read (format "%s (default %s) " prompt value) 3473
3426 ; (mapcar (lambda (sym) 3474 (defun widget-coding-system-prompt-value (widget prompt value unbound)
3427 ; (list (symbol-name sym))) 3475 ;; Read coding-system from minibuffer.
3428 ; (coding-system-list))))) 3476 (intern
3429 3477 (completing-read (format "%s (default %s) " prompt value)
3430 ;(defun widget-coding-system-action (widget &optional event) 3478 (mapcar (lambda (sym)
3431 ; ;; Read a file name from the minibuffer. 3479 (list (symbol-name sym)))
3432 ; (let ((answer 3480 (coding-system-list)))))
3433 ; (widget-coding-system-prompt-value 3481
3434 ; widget 3482 (defun widget-coding-system-action (widget &optional event)
3435 ; (widget-apply widget :menu-tag-get) 3483 ;; Read a file name from the minibuffer.
3436 ; (widget-value widget) 3484 (let ((answer
3437 ; t))) 3485 (widget-coding-system-prompt-value
3438 ; (widget-value-set widget answer) 3486 widget
3439 ; (widget-apply widget :notify widget event) 3487 (widget-apply widget :menu-tag-get)
3440 ; (widget-setup))) 3488 (widget-value widget)
3489 t)))
3490 (widget-value-set widget answer)
3491 (widget-apply widget :notify widget event)
3492 (widget-setup)))
3441 3493
3442 (define-widget 'sexp 'editable-field 3494 (define-widget 'sexp 'editable-field
3443 "An arbitrary Lisp expression." 3495 "An arbitrary Lisp expression."
3444 :tag "Lisp expression" 3496 :tag "Lisp expression"
3445 :format "%{%t%}: %v" 3497 :format "%{%t%}: %v"
3537 :tag "Number" 3589 :tag "Number"
3538 :value 0.0 3590 :value 0.0
3539 :type-error "This field should contain a number (floating point or integer)" 3591 :type-error "This field should contain a number (floating point or integer)"
3540 :match-alternatives '(numberp)) 3592 :match-alternatives '(numberp))
3541 3593
3594 (define-widget 'float 'restricted-sexp
3595 "A floating point number."
3596 :tag "Floating point number"
3597 :value 0.0
3598 :type-error "This field should contain a floating point number"
3599 :match-alternatives '(floatp))
3600
3542 (define-widget 'character 'editable-field 3601 (define-widget 'character 'editable-field
3543 "A character." 3602 "A character."
3544 :tag "Character" 3603 :tag "Character"
3545 :value ?\0 3604 :value ?\0
3605 :size 1
3546 :format "%{%t%}: %v" 3606 :format "%{%t%}: %v"
3547 :valid-regexp "\\`[\0-\377]\\'" 3607 :valid-regexp "\\`[\0-\377]\\'"
3548 :error "This field should contain a single character" 3608 :error "This field should contain a single character"
3549 :value-to-internal (lambda (widget value) 3609 :value-to-internal (lambda (widget value)
3550 (if (stringp value) 3610 (if (stringp value)
3581 :format "%{%t%}:\n%v" 3641 :format "%{%t%}:\n%v"
3582 :match 'widget-cons-match 3642 :match 'widget-cons-match
3583 :value-to-internal (lambda (widget value) 3643 :value-to-internal (lambda (widget value)
3584 (list (car value) (cdr value))) 3644 (list (car value) (cdr value)))
3585 :value-to-external (lambda (widget value) 3645 :value-to-external (lambda (widget value)
3586 (cons (car value) (cadr value)))) 3646 (cons (nth 0 value) (nth 1 value))))
3587 3647
3588 (defun widget-cons-match (widget value) 3648 (defun widget-cons-match (widget value)
3589 (and (consp value) 3649 (and (consp value)
3590 (widget-group-match widget 3650 (widget-group-match widget
3591 (widget-apply widget :value-to-internal value)))) 3651 (widget-apply widget :value-to-internal value))))
3592 3652
3653 ;;; The `plist' Widget.
3654 ;;
3655 ;; Property lists.
3656
3657 (define-widget 'plist 'list
3658 "A property list."
3659 :key-type '(symbol :tag "Key")
3660 :value-type '(sexp :tag "Value")
3661 :convert-widget 'widget-plist-convert-widget
3662 :tag "Plist")
3663
3664 (defvar widget-plist-value-type) ;Dynamic variable
3665
3666 (defun widget-plist-convert-widget (widget)
3667 ;; Handle `:options'.
3668 (let* ((options (widget-get widget :options))
3669 (widget-plist-value-type (widget-get widget :value-type))
3670 (other `(editable-list :inline t
3671 (group :inline t
3672 ,(widget-get widget :key-type)
3673 ,widget-plist-value-type)))
3674 (args (if options
3675 (list `(checklist :inline t
3676 :greedy t
3677 ,@(mapcar 'widget-plist-convert-option
3678 options))
3679 other)
3680 (list other))))
3681 (widget-put widget :args args)
3682 widget))
3683
3684 (defun widget-plist-convert-option (option)
3685 ;; Convert a single plist option.
3686 (let (key-type value-type)
3687 (if (listp option)
3688 (let ((key (nth 0 option)))
3689 (setq value-type (nth 1 option))
3690 (if (listp key)
3691 (setq key-type key)
3692 (setq key-type `(const ,key))))
3693 (setq key-type `(const ,option)
3694 value-type widget-plist-value-type))
3695 `(group :format "Key: %v" :inline t ,key-type ,value-type)))
3696
3697
3698 ;;; The `alist' Widget.
3699 ;;
3700 ;; Association lists.
3701
3702 (define-widget 'alist 'list
3703 "An association list."
3704 :key-type '(sexp :tag "Key")
3705 :value-type '(sexp :tag "Value")
3706 :convert-widget 'widget-alist-convert-widget
3707 :tag "Alist")
3708
3709 (defvar widget-alist-value-type) ;Dynamic variable
3710
3711 (defun widget-alist-convert-widget (widget)
3712 ;; Handle `:options'.
3713 (let* ((options (widget-get widget :options))
3714 (widget-alist-value-type (widget-get widget :value-type))
3715 (other `(editable-list :inline t
3716 (cons :format "%v"
3717 ,(widget-get widget :key-type)
3718 ,widget-alist-value-type)))
3719 (args (if options
3720 (list `(checklist :inline t
3721 :greedy t
3722 ,@(mapcar 'widget-alist-convert-option
3723 options))
3724 other)
3725 (list other))))
3726 (widget-put widget :args args)
3727 widget))
3728
3729 (defun widget-alist-convert-option (option)
3730 ;; Convert a single alist option.
3731 (let (key-type value-type)
3732 (if (listp option)
3733 (let ((key (nth 0 option)))
3734 (setq value-type (nth 1 option))
3735 (if (listp key)
3736 (setq key-type key)
3737 (setq key-type `(const ,key))))
3738 (setq key-type `(const ,option)
3739 value-type widget-alist-value-type))
3740 `(cons :format "Key: %v" ,key-type ,value-type)))
3741
3742
3593 (define-widget 'choice 'menu-choice 3743 (define-widget 'choice 'menu-choice
3594 "A union of several sexp types." 3744 "A union of several sexp types."
3595 :tag "Choice" 3745 :tag "Choice"
3596 :format "%{%t%}: %[Value Menu%] %v" 3746 :format "%{%t%}: %[Value Menu%] %v"
3597 :button-prefix 'widget-push-button-prefix 3747 :button-prefix 'widget-push-button-prefix
3696 (error "Can't find completion for \"%s\"" prefix)) 3846 (error "Can't find completion for \"%s\"" prefix))
3697 ((not (string-equal prefix completion)) 3847 ((not (string-equal prefix completion))
3698 (insert (substring completion (length prefix)))) 3848 (insert (substring completion (length prefix))))
3699 (t 3849 (t
3700 (message "Making completion list...") 3850 (message "Making completion list...")
3701 (let ((list (all-completions prefix list nil))) 3851 (with-output-to-temp-buffer "*Completions*"
3702 (with-output-to-temp-buffer "*Completions*" 3852 (display-completion-list (all-completions prefix list nil)))
3703 (display-completion-list list)))
3704 (message "Making completion list...done"))))) 3853 (message "Making completion list...done")))))
3705 3854
3706 (defun widget-color-sample-face-get (widget) 3855 (defun widget-color-sample-face-get (widget)
3707 (or (widget-get widget :sample-face) 3856 (or (widget-get widget :sample-face)
3708 (let ((color (widget-value widget)) 3857 (let ((color (widget-value widget))
3735 (if (valid-color-name-p color) 3884 (if (valid-color-name-p color)
3736 (set-face-foreground face color) 3885 (set-face-foreground face color)
3737 (remove-face-property face 'foreground))) 3886 (remove-face-property face 'foreground)))
3738 (widget-default-notify widget child event)) 3887 (widget-default-notify widget child event))
3739 3888
3740 ;; Is this a misnomer?
3741 (defun widget-at (pos)
3742 "The button or field at POS."
3743 (or (get-char-property pos 'button)
3744 (get-char-property pos 'field)))
3745
3746 ;;; The Help Echo 3889 ;;; The Help Echo
3747 3890
3748 (defun widget-echo-help (pos) 3891 (defun widget-echo-help (pos)
3749 "Display the help-echo text for widget at POS." 3892 "Display the help-echo text for widget at POS."
3750 (let* ((widget (widget-at pos)) 3893 (let* ((widget (widget-at pos))
3751 (help-echo (and widget (widget-get widget :help-echo)))) 3894 (help-echo (and widget (widget-get widget :help-echo))))
3752 (and (functionp help-echo) 3895 (if (functionp help-echo)
3753 (setq help-echo (funcall help-echo widget))) 3896 (setq help-echo (funcall help-echo widget)))
3754 (when (stringp help-echo) 3897 (if (stringp help-echo)
3755 (display-message 'help-echo help-echo)))) 3898 (display-message 'help-echo help-echo))))
3756 3899
3757 ;;; The End: 3900 ;;; The End:
3758 3901
3759 (provide 'wid-edit) 3902 (provide 'wid-edit)
3760 3903