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