Mercurial > hg > xemacs-beta
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 |