;;; wid-edit.el --- Functions for creating and using widgets -*-byte-compile-dynamic: t;-*-
;;
-;; Copyright (C) 1996,97,1999,2000,01,02,2003, 2004 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Maintainer: FSF
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Wishlist items (from widget.texi):
:group 'widgets
:group 'faces)
-(defvar widget-documentation-face 'widget-documentation-face
+(defvar widget-documentation-face 'widget-documentation
"Face used for documentation strings in widgets.
This exists as a variable so it can be set locally in certain buffers.")
-(defface widget-documentation-face '((((class color)
- (background dark))
- (:foreground "lime green"))
- (((class color)
- (background light))
- (:foreground "dark green"))
- (t nil))
+(defface widget-documentation '((((class color)
+ (background dark))
+ (:foreground "lime green"))
+ (((class color)
+ (background light))
+ (:foreground "dark green"))
+ (t nil))
"Face used for documentation text."
:group 'widget-documentation
:group 'widget-faces)
+;; backward compatibility alias
+(put 'widget-documentation-face 'face-alias 'widget-documentation)
-(defvar widget-button-face 'widget-button-face
+(defvar widget-button-face 'widget-button
"Face used for buttons in widgets.
This exists as a variable so it can be set locally in certain buffers.")
-(defface widget-button-face '((t (:weight bold)))
+(defface widget-button '((t (:weight bold)))
"Face used for widget buttons."
:group 'widget-faces)
+;; backward compatibility alias
+(put 'widget-button-face 'face-alias 'widget-button)
(defcustom widget-mouse-face 'highlight
"Face used for widget buttons when the mouse is above them."
;; TTY gets special definitions here and in the next defface, because
;; the gray colors defined for other displays cause black text on a black
;; background, at least on light-background TTYs.
-(defface widget-field-face '((((type tty))
- :background "yellow3"
- :foreground "black")
- (((class grayscale color)
- (background light))
- :background "gray85")
- (((class grayscale color)
- (background dark))
- :background "dim gray")
- (t
- :slant italic))
+(defface widget-field '((((type tty))
+ :background "yellow3"
+ :foreground "black")
+ (((class grayscale color)
+ (background light))
+ :background "gray85")
+ (((class grayscale color)
+ (background dark))
+ :background "dim gray")
+ (t
+ :slant italic))
"Face used for editable fields."
:group 'widget-faces)
-
-(defface widget-single-line-field-face '((((type tty))
- :background "green3"
- :foreground "black")
- (((class grayscale color)
- (background light))
- :background "gray85")
- (((class grayscale color)
- (background dark))
- :background "dim gray")
- (t
- :slant italic))
+;; backward-compatibility alias
+(put 'widget-field-face 'face-alias 'widget-field)
+
+(defface widget-single-line-field '((((type tty))
+ :background "green3"
+ :foreground "black")
+ (((class grayscale color)
+ (background light))
+ :background "gray85")
+ (((class grayscale color)
+ (background dark))
+ :background "dim gray")
+ (t
+ :slant italic))
"Face used for editable fields spanning only a single line."
:group 'widget-faces)
+;; backward-compatibility alias
+(put 'widget-single-line-field-face 'face-alias 'widget-single-line-field)
;;; This causes display-table to be loaded, and not usefully.
;;;(defvar widget-single-line-display-table
(while (not (or (and (>= char ?0) (< char next-digit))
(eq value 'keyboard-quit)))
;; Unread a SPC to lead to our new menu.
- (setq unread-command-events (cons ?\ unread-command-events))
+ (setq unread-command-events (cons ?\s unread-command-events))
(setq keys (read-key-sequence title))
(setq value
(lookup-key overriding-terminal-local-map keys t)
(insert-and-inherit " ")))
(setq to (point)))
(let ((keymap (widget-get widget :keymap))
- (face (or (widget-get widget :value-face) 'widget-field-face))
+ (face (or (widget-get widget :value-face) 'widget-field))
(help-echo (widget-get widget :help-echo))
(follow-link (widget-get widget :follow-link))
(rear-sticky
(end (widget-field-end field)))
(when size
(while (and (> end begin)
- (eq (char-after (1- end)) ?\ ))
+ (eq (char-after (1- end)) ?\s))
(setq end (1- end))))
(while (< begin end)
(let ((old (char-after begin)))
(prog1 (progn ,@form)
(goto-char (point-max))))))
-(defface widget-inactive-face '((((class grayscale color)
- (background dark))
- (:foreground "light gray"))
- (((class grayscale color)
- (background light))
- (:foreground "dim gray"))
- (t
- (:slant italic)))
+(defface widget-inactive
+ '((t :inherit shadow))
"Face used for inactive widgets."
:group 'widget-faces)
+;; backward-compatibility alias
+(put 'widget-inactive-face 'face-alias 'widget-inactive)
(defun widget-specify-inactive (widget from to)
"Make WIDGET inactive for user modifications."
(unless (widget-get widget :inactive)
(let ((overlay (make-overlay from to nil t nil)))
- (overlay-put overlay 'face 'widget-inactive-face)
+ (overlay-put overlay 'face 'widget-inactive)
;; This is disabled, as it makes the mouse cursor change shape.
- ;; (overlay-put overlay 'mouse-face 'widget-inactive-face)
+ ;; (overlay-put overlay 'mouse-face 'widget-inactive)
(overlay-put overlay 'evaporate t)
(overlay-put overlay 'priority 100)
(overlay-put overlay 'modification-hooks '(widget-overlay-inactive))
;; Oh well.
nil)))
-(defvar widget-button-pressed-face 'widget-button-pressed-face
+(defvar widget-button-pressed-face 'widget-button-pressed
"Face used for pressed buttons in widgets.
This exists as a variable so it can be set locally in certain
buffers.")
&optional button-from button-to
&rest args)
"Return a widget of type TYPE with endpoint FROM TO.
-Optional ARGS are extra keyword arguments for TYPE.
-and TO will be used as the widgets end points. If optional arguments
+No text will be inserted to the buffer, instead the text between FROM
+and TO will be used as the widgets end points. If optional arguments
BUTTON-FROM and BUTTON-TO are given, these will be used as the widgets
button end points.
Optional ARGS are extra keyword arguments for TYPE."
(call-interactively
(lookup-key widget-global-map (this-command-keys))))))
-(defface widget-button-pressed-face
- '((((class color))
+(defface widget-button-pressed
+ '((((min-colors 88) (class color))
+ (:foreground "red1"))
+ (((class color))
(:foreground "red"))
(t
(:weight bold :underline t)))
"Face used for pressed buttons."
:group 'widget-faces)
+;; backward-compatibility alias
+(put 'widget-button-pressed-face 'face-alias 'widget-button-pressed)
(defun widget-button-click (event)
"Invoke the button that the mouse is pointing at."
(recenter))
)
- (let ((up t) command)
- ;; Mouse click not on a widget button. Find the global
- ;; command to run, and check whether it is bound to an
- ;; up event.
- (mouse-set-point event)
- (if (memq (event-basic-type event) '(mouse-1 down-mouse-1))
- (cond ((setq command ;down event
- (lookup-key widget-global-map [down-mouse-1]))
- (setq up nil))
- ((setq command ;up event
- (lookup-key widget-global-map [mouse-1]))))
+ (let ((up t) command)
+ ;; Mouse click not on a widget button. Find the global
+ ;; command to run, and check whether it is bound to an
+ ;; up event.
+ (mouse-set-point event)
+ (if (memq (event-basic-type event) '(mouse-1 down-mouse-1))
(cond ((setq command ;down event
- (lookup-key widget-global-map [down-mouse-2]))
+ (lookup-key widget-global-map [down-mouse-1]))
(setq up nil))
((setq command ;up event
- (lookup-key widget-global-map [mouse-2])))))
- (when up
- ;; Don't execute up events twice.
- (while (not (widget-button-release-event-p event))
- (setq event (read-event))))
- (when command
- (call-interactively command)))))
+ (lookup-key widget-global-map [mouse-1]))))
+ (cond ((setq command ;down event
+ (lookup-key widget-global-map [down-mouse-2]))
+ (setq up nil))
+ ((setq command ;up event
+ (lookup-key widget-global-map [mouse-2])))))
+ (when up
+ ;; Don't execute up events twice.
+ (while (not (widget-button-release-event-p event))
+ (setq event (read-event))))
+ (when command
+ (call-interactively command)))))
(message "You clicked somewhere weird.")))
(defun widget-button-press (pos &optional event)
:group 'widgets)
(defun widget-narrow-to-field ()
- "Narrow to field"
+ "Narrow to field."
(interactive)
(let ((field (widget-field-find (point))))
(if field
;; or if a special `boundary' field has been added after the widget
;; field.
(if (overlayp overlay)
- (if (and (not (eq (get-char-property (overlay-end overlay)
- 'field
- (widget-field-buffer widget))
+ (if (and (not (eq (with-current-buffer
+ (widget-field-buffer widget)
+ (save-restriction
+ ;; `widget-narrow-to-field' can be
+ ;; active when this function is called
+ ;; from an change-functions hook. So
+ ;; temporarily remove field narrowing
+ ;; before to call `get-char-property'.
+ (widen)
+ (get-char-property (overlay-end overlay)
+ 'field)))
'boundary))
(or widget-field-add-space
(null (widget-get widget :size))))
(defun widget-field-find (pos)
"Return the field at POS.
-Unlike (get-char-property POS 'field) this, works with empty fields too."
+Unlike (get-char-property POS 'field), this works with empty fields too."
(let ((fields widget-field-list)
field found)
(while fields
;; Field too small.
(save-excursion
(goto-char end)
- (insert-char ?\ (- (+ begin size) end))))
+ (insert-char ?\s (- (+ begin size) end))))
((> (- end begin) size)
;; Field too large and
(if (or (< (point) (+ begin size))
(setq begin (point)))
(save-excursion
(goto-char end)
- (while (and (eq (preceding-char) ?\ )
+ (while (and (eq (preceding-char) ?\s)
(> (point) begin))
(delete-backward-char 1)))))))
(widget-specify-secret field))
((eq escape ?n)
(when (widget-get widget :indent)
(insert ?\n)
- (insert-char ? (widget-get widget :indent))))
+ (insert-char ?\s (widget-get widget :indent))))
((eq escape ?t)
(let ((image (widget-get widget :tag-glyph))
(tag (widget-get widget :tag)))
(when doc-text
(and (eq (preceding-char) ?\n)
(widget-get widget :indent)
- (insert-char ? (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
;; The `*' in the beginning is redundant.
(when (eq (aref doc-text 0) ?*)
(setq doc-text (substring doc-text 1)))
:action 'widget-url-link-action)
(defun widget-url-link-action (widget &optional event)
- "Open the url specified by WIDGET."
+ "Open the URL specified by WIDGET."
(browse-url (widget-value widget)))
;;; The `function-link' Widget.
:action 'widget-emacs-library-link-action)
(defun widget-emacs-library-link-action (widget &optional event)
- "Find the Emacs Library file specified by WIDGET."
+ "Find the Emacs library file specified by WIDGET."
(find-file (locate-library (widget-value widget))))
;;; The `emacs-commentary-link' Widget.
(insert value)
(and size
(< (length value) size)
- (insert-char ?\ (- size (length value))))
+ (insert-char ?\s (- size (length value))))
(unless (memq widget widget-field-list)
(setq widget-field-new (cons widget widget-field-new)))
(move-marker (cdr overlay) (point))
(while (and size
(not (zerop size))
(> to from)
- (eq (char-after (1- to)) ?\ ))
+ (eq (char-after (1- to)) ?\s))
(setq to (1- to)))
(let ((result (buffer-substring-no-properties from to)))
(when secret
(args (widget-get widget :args))
(explicit (widget-get widget :explicit-choice))
current)
- (if (and explicit (equal value (widget-get widget :explicit-choice-value)))
+ (if explicit
(progn
;; If the user specified the choice for this value,
- ;; respect that choice as long as the value is the same.
+ ;; respect that choice.
(widget-put widget :children (list (widget-create-child-value
widget explicit value)))
- (widget-put widget :choice explicit))
+ (widget-put widget :choice explicit)
+ (widget-put widget :explicit-choice nil))
(while args
(setq current (car args)
args (cdr args))
(setq this-explicit t)
(widget-choose tag (reverse choices) event))))
(when current
- ;; If this was an explicit user choice,
- ;; record the choice, and the record the value it was made for.
- ;; widget-choice-value-create will respect this choice,
- ;; as long as the value is the same.
+ ;; If this was an explicit user choice, record the choice,
+ ;; so that widget-choice-value-create will respect it.
(when this-explicit
- (widget-put widget :explicit-choice current)
- (widget-put widget :explicit-choice-value (widget-get widget :value)))
+ (widget-put widget :explicit-choice current))
(widget-value-set widget (widget-default-get current))
(widget-setup)
(widget-apply widget :notify widget event)))
If the item is checked, CHOSEN is a cons whose cdr is the value."
(and (eq (preceding-char) ?\n)
(widget-get widget :indent)
- (insert-char ? (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
(widget-specify-insert
(let* ((children (widget-get widget :children))
(buttons (widget-get widget :buttons))
;; (setq type (widget-convert type))
(and (eq (preceding-char) ?\n)
(widget-get widget :indent)
- (insert-char ? (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
(widget-specify-insert
(let* ((value (widget-get widget :value))
(children (widget-get widget :children))
;; (let ((widget-push-button-gui widget-editable-list-gui))
(cond ((eq escape ?i)
(and (widget-get widget :indent)
- (insert-char ?\ (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
(apply 'widget-create-child-and-convert
widget 'insert-button
(widget-get widget :append-button-args)))
(widget-specify-insert
(save-excursion
(and (widget-get widget :indent)
- (insert-char ?\ (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
(insert (widget-get widget :entry-format)))
;; Parse % escapes in format.
(while (re-search-forward "%\\(.\\)" nil t)
value (cdr answer))
(and (eq (preceding-char) ?\n)
(widget-get widget :indent)
- (insert-char ?\ (widget-get widget :indent)))
+ (insert-char ?\s (widget-get widget :indent)))
(push (cond ((null answer)
(widget-create-child widget arg))
((widget-get arg :inline)
(narrow-to-region from to)
(goto-char (point-min))
(while (search-forward "\n" nil t)
- (insert-char ?\ indent)))))))
+ (insert-char ?\s indent)))))))
;;; The `documentation-string' Widget.
(let ((before (substring doc 0 (match-beginning 0)))
(after (substring doc (match-beginning 0)))
button)
- (insert before ?\ )
+ (insert before ?\s)
(widget-documentation-link-add widget start (point))
(setq button
(widget-create-child-and-convert
(when shown
(setq start (point))
(when (and indent (not (zerop indent)))
- (insert-char ?\ indent))
+ (insert-char ?\s indent))
(insert after)
(widget-documentation-link-add widget start (point)))
(widget-put widget :buttons (list button)))
:match 'widget-regexp-match
:validate 'widget-regexp-validate
;; Doesn't work well with terminating newline.
- ;; :value-face 'widget-single-line-field-face
+ ;; :value-face 'widget-single-line-field
:tag "Regexp")
(defun widget-regexp-match (widget value)
:prompt-value 'widget-file-prompt-value
:format "%{%t%}: %v"
;; Doesn't work well with terminating newline.
- ;; :value-face 'widget-single-line-field-face
+ ;; :value-face 'widget-single-line-field
:tag "File")
(defun widget-file-complete ()
(abbreviate-file-name
(if unbound
(read-file-name prompt)
- (let ((prompt2 (format "%s (default %s) " prompt value))
+ (let ((prompt2 (format "%s (default %s): " prompt value))
(dir (file-name-directory value))
(file (file-name-nondirectory value))
(must-match (widget-get widget :must-match)))
;;; (file (file-name-nondirectory value))
;;; (menu-tag (widget-apply widget :menu-tag-get))
;;; (must-match (widget-get widget :must-match))
-;;; (answer (read-file-name (concat menu-tag ": (default `" value "') ")
+;;; (answer (read-file-name (concat menu-tag " (default " value "): ")
;;; dir nil must-match file)))
;;; (widget-value-set widget (abbreviate-file-name answer))
;;; (widget-setup)
"Read coding-system from minibuffer."
(if (widget-get widget :base-only)
(intern
- (completing-read (format "%s (default %s) " prompt value)
+ (completing-read (format "%s (default %s): " prompt value)
(mapcar #'list (coding-system-list t)) nil nil nil
coding-system-history))
- (read-coding-system (format "%s (default %s) " prompt value) value)))
+ (read-coding-system (format "%s (default %s): " prompt value) value)))
(defun widget-coding-system-action (widget &optional event)
(let ((answer
(widget-apply widget :notify widget event))))
(defun widget-color-notify (widget child &optional event)
- "Update the sample, and notofy the parent."
+ "Update the sample, and notify the parent."
(overlay-put (widget-get widget :sample-overlay)
'face (widget-apply widget :sample-face-get))
(widget-default-notify widget child event))