diff lisp/w3/w3-forms.el @ 16:0293115a14e9 r19-15b91

Import from CVS: tag r19-15b91
author cvs
date Mon, 13 Aug 2007 08:49:20 +0200
parents 9ee227acff29
children 859a2309aef8
line wrap: on
line diff
--- a/lisp/w3/w3-forms.el	Mon Aug 13 08:48:43 2007 +0200
+++ b/lisp/w3/w3-forms.el	Mon Aug 13 08:49:20 2007 +0200
@@ -1,12 +1,12 @@
 ;;; w3-forms.el --- Emacs-w3 forms parsing code for new display engine
 ;; Author: wmperry
-;; Created: 1997/01/02 20:20:29
-;; Version: 1.32
+;; Created: 1997/01/28 14:21:54
+;; Version: 1.55
 ;; Keywords: faces, help, comm, data, languages
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Copyright (c) 1996 by William M. Perry (wmperry@cs.indiana.edu)
-;;; Copyright (c) 1996 Free Software Foundation, Inc.
+;;; Copyright (c) 1996, 1997 Free Software Foundation, Inc.
 ;;;
 ;;; This file is part of GNU Emacs.
 ;;;
@@ -36,8 +36,16 @@
 (require 'w3-vars)
 (require 'mule-sysdp)
 
+(define-widget-keywords :emacspeak-help :w3-form-data)
+
+(defvar w3-form-keymap (copy-keymap global-map))
+(define-key w3-form-keymap "\r"          'w3-form-maybe-submit-by-keypress)
+(define-key w3-form-keymap "\n"          'w3-form-maybe-submit-by-keypress)
+(define-key w3-form-keymap "\t"          'w3-widget-forward)
+(define-key w3-form-keymap [(shift tab)] 'w3-widget-backward)
+
 ;; A form entry area is a vector
-;; [ type name default-value value maxlength options widget]
+;; [ type name default-value value maxlength options widget plist]
 ;; Where:
 ;;          type = symbol defining what type of form entry area it is
 ;;                 (ie: file, radio)
@@ -53,6 +61,7 @@
 (defsubst w3-form-element-options       (obj) (aref obj 6))
 (defsubst w3-form-element-action        (obj) (aref obj 7))
 (defsubst w3-form-element-widget        (obj) (aref obj 8))
+(defsubst w3-form-element-plist         (obj) (aref obj 9))
 
 (defsubst w3-form-element-set-type          (obj val) (aset obj 0 val))
 (defsubst w3-form-element-set-name          (obj val) (aset obj 1 val))
@@ -63,32 +72,51 @@
 (defsubst w3-form-element-set-options       (obj val) (aset obj 6 val))
 (defsubst w3-form-element-set-action        (obj val) (aset obj 7 val))
 (defsubst w3-form-element-set-widget        (obj val) (aset obj 8 val))
+(defsubst w3-form-element-set-plist         (obj val) (aset obj 9 val))
 
-;; The main function - this adds a single widget to the form
-(defun w3-form-add-element (type name value size maxlength default
-				 action options number id checked
-				 face)
-  (let* ((name (or name (case type
-			      ((submit reset) nil)
-			      (otherwise (symbol-name type)))))
-	 (el (vector type
-		     name
-		     default
-		     value
-		     size
-		     maxlength
-		     options
-		     action nil))
-	 (size (if size
-		   (+ 2 size)
-		 (case type
-		   ((checkbox radio) 3)
-		   ((reset submit)
-		    (+ 2 (length (or value (symbol-name type)))))
-		   (multiline 21)
-		   (hidden nil)
-		   (otherwise 22))))
-	 )
+(defun w3-form-determine-size (el size)
+  (case (w3-form-element-type el)
+    (checkbox 3)
+    (radio 4)
+    ((reset submit) (+ 2 (length (or (w3-form-element-value el)
+				     (symbol-name
+				      (w3-form-element-type el))))))
+    (multiline 21)
+    (hidden nil)
+    (file (or size 26))
+    ((float password text int) (or size 20))
+    (image (+ 2 (length (or
+			 (plist-get (w3-form-element-plist el) 'alt)
+			 "Form-Image"))))
+    (option
+     (or size
+	 (length (caar (sort (w3-form-element-options el)
+			     (function
+			      (lambda (x y)
+				(>= (length (car x)) (length (car y))))))))))
+    (otherwise (or size 22))))    
+ 
+;;###autoload
+(defun w3-form-add-element (plist face)
+  (let* ((action (plist-get plist 'action))
+	 (el (vector (plist-get plist 'type)
+		     (plist-get plist 'name)
+		     (plist-get plist 'default)
+		     (plist-get plist 'value)
+		     (plist-get plist 'size)
+		     (plist-get plist 'maxlength)
+		     (plist-get plist 'options)
+		     action
+		     nil
+		     plist))
+	 (size (w3-form-determine-size el (plist-get plist 'size)))
+	 (node (assoc action w3-form-elements)))
+    (if (and (eq (plist-get plist 'type) 'hidden)
+	     (not (assq '*table-autolayout w3-display-open-element-stack)))
+	(if node
+	    (setcdr node (cons el (cdr node)))
+	  (setq w3-form-elements (cons (cons action (list el))
+				       w3-form-elements))))
     (if size
 	(set-text-properties (point)
 			     (progn (insert-char ?T size) (point))
@@ -103,7 +131,8 @@
     (while st
       (if (setq info (get-text-property st 'w3-form-info))
 	  (progn
-	    (setq nd (next-single-property-change st 'w3-form-info)
+	    (setq nd (or (next-single-property-change st 'w3-form-info)
+			 (point-max))
 		  action (w3-form-element-action info)
 		  node (assoc action w3-form-elements))
 	    (goto-char st)
@@ -118,6 +147,34 @@
 	    (setq st (next-single-property-change st 'w3-form-info)))
 	(setq st (next-single-property-change st 'w3-form-info))))))
 
+(defsubst w3-form-mark-widget (widget el)
+  (let ((widgets (list widget))
+	(children (widget-get widget :children))
+	(parent (widget-get widget :parent)))
+    (w3-form-element-set-widget el widget)
+    ;; Get _all_ the children associated with this widget
+    (while children
+      (setq widgets (cons (car children) widgets))
+      (if (widget-get (car children) :children)
+	  (setq children (append children
+				 (widget-get (car children) :children))))
+      (setq children (cdr children)))
+    (while (widget-get widget :parent)
+      (setq widget (widget-get widget :parent)
+	    widgets (cons widget widgets)))
+    (setq children (widget-get widget :buttons))
+    ;; Special case for radio buttons
+    (while children
+      (setq widgets (cons (car children) widgets))
+      (if (widget-get (car children) :children)
+	  (setq children (append children
+				 (widget-get (car children) :children))))
+      (setq children (cdr children)))
+    (while widgets
+      (setq widget (pop widgets))
+      (widget-put widget :emacspeak-help 'w3-form-summarize-field)
+      (widget-put widget :w3-form-data el))))
+
 (defun w3-form-add-element-internal (el)
   (let* ((widget nil)
 	 (buffer-read-only nil)
@@ -126,11 +183,11 @@
     (setq widget-creation-function (or (get (w3-form-element-type el)
 					    'w3-widget-creation-function)
 				       'w3-form-default-widget-creator)
-	  widget (funcall widget-creation-function el nil))
+	  widget (and (fboundp widget-creation-function)
+		      (funcall widget-creation-function el nil)))
     (if (not widget)
 	nil
-      (w3-form-element-set-widget el widget)
-      (widget-put widget 'w3-form-data el))))
+      (w3-form-mark-widget widget el))))
 
 ;; These properties tell the add-element function how to actually create
 ;; each type of widget.
@@ -145,14 +202,46 @@
 (put 'keygen    'w3-widget-creation-function 'w3-form-create-keygen-list)
 (put 'button    'w3-widget-creation-function 'w3-form-create-button)
 (put 'image	'w3-widget-creation-function 'w3-form-create-image)
+(put 'int       'w3-widget-creation-function 'w3-form-create-integer)
+(put 'float     'w3-widget-creation-function 'w3-form-create-float)
+(put 'custom    'w3-widget-creation-function 'w3-form-create-custom)
+(put 'text      'w3-widget-creation-function 'w3-form-create-text)
+(put 'password  'w3-widget-creation-function 'w3-form-create-password)
+
+;; Custom support.
+(defvar w3-custom-options nil)
+(make-variable-buffer-local 'w3-custom-options)
+
+(defun w3-form-create-custom (el face)
+  (require 'custom-edit)
+  (let* ((name (w3-form-element-name el))
+	 (var-name (w3-form-element-value el))
+	 (type (plist-get (w3-form-element-plist el) 'custom-type))
+	 (widget (widget-create (cond ((string-equal type "variable")
+				       'custom-variable)
+				      ((string-equal type "face")
+				       'custom-face)
+				      ((string-equal type "group")
+				       'custom-group)
+				      (t 'item)) (intern var-name))))
+    (custom-magic-reset widget)
+    (push widget w3-custom-options)
+    widget))
 
 (defun w3-form-create-checkbox (el face)
-  (widget-create 'checkbox :value-face face
+  (widget-create 'checkbox
+		 :value-face face
 		 (and (w3-form-element-default-value el) t)))
 
+(defun w3-form-radio-button-update (widget child event)
+  (widget-radio-action widget child event)
+  (w3-form-mark-widget widget (widget-get widget :w3-form-data)))
+
 (defun w3-form-create-radio-button (el face)
   (let* ((name (w3-form-element-name el))
-	 (formobj (cdr (assoc name w3-form-radio-elements)))
+	 (action (w3-form-element-action el))
+	 (uniqid (cons name action))
+	 (formobj (cdr (assoc uniqid w3-form-radio-elements)))
 	 (widget nil)
 	 )
     (if formobj
@@ -163,17 +252,24 @@
 				       :format "%t"
 				       :tag ""
 				       :value (w3-form-element-value el)))
+	  (w3-form-mark-widget widget el)
 	  (if (w3-form-element-default-value el)
-	      (widget-value-set widget (w3-form-element-value el)))
+	      (progn
+		(widget-put widget 'w3-form-default-value
+			    (w3-form-element-value el))
+		(widget-value-set widget (w3-form-element-value el))))
 	  nil)
-      (setq widget (widget-create 'radio-button-choice
-				  :value (w3-form-element-value el)
-				  (list 'item
-					:format "%t"
-					:tag ""
-					:value (w3-form-element-value el)))
-	    w3-form-radio-elements (cons (cons name el)
+      (setq widget (widget-create
+		    'radio-button-choice
+		    :value (w3-form-element-value el)
+		    :action 'w3-form-radio-button-update
+		    (list 'item
+			  :format "%t"
+			  :tag ""
+			  :value (w3-form-element-value el)))
+	    w3-form-radio-elements (cons (cons uniqid el)
 					 w3-form-radio-elements))
+      (widget-put widget 'w3-form-default-value (w3-form-element-value el))
       widget)))
 
 (defun w3-form-create-button (el face)
@@ -182,13 +278,17 @@
   (let ((val (w3-form-element-value el)))
     (if (or (not val) (string= val ""))
 	(setq val "Push Me"))
-    (widget-create 'push-button :notify 'ignore :button-face face val)))
+    (widget-create 'push-button
+		   :notify 'ignore
+		   :button-face face
+		   val)))
 
 (defun w3-form-create-image (el face)
-  (let ((widget (widget-create 'push-button
-			       :notify 'w3-form-submit/reset-callback
-			       :value "Form-Image")))
-    widget))
+  (widget-create 'push-button
+		 :notify 'w3-form-submit/reset-callback
+		 :value (or
+			 (plist-get (w3-form-element-plist el) 'alt)
+			 "Form-Image")))
 
 (defun w3-form-create-submit-button (el face)
   (let ((val (w3-form-element-value el)))
@@ -201,7 +301,11 @@
 		   :button-face face val)))
 
 (defun w3-form-create-file-browser (el face)
-  (widget-create 'file :value-face face :value (w3-form-element-value el)))
+  (widget-create 'file
+		 :value-face face
+		 :size (w3-form-element-size el)
+		 :must-match t
+		 :value (w3-form-element-value el)))
 
 (defvar w3-form-valid-key-sizes
   '(
@@ -233,60 +337,222 @@
 	   options)))
 
 (defun w3-form-create-option-list (el face)
-  (let ((widget (apply 'widget-create 'menu-choice
+  (let* ((size (w3-form-determine-size el nil))
+	 (widget (apply 'widget-create 'menu-choice
 		       :value (w3-form-element-value el)
 		       :ignore-case t
 		       :tag "Choose"
 		       :format "%v"
-		       :size (w3-form-element-size el)
+		       :size size
 		       :value-face face
 		       (mapcar
 			(function
 			 (lambda (x)
 			   (list 'choice-item :format "%[%t%]"
-				 :tag (car x) :value (car x))))
+				 :emacspeak-help 'w3-form-summarize-field
+				 :tag (mule-truncate-string (car x) size ? )
+				 :value (car x))))
 			(w3-form-element-options el)))))
     (widget-value-set widget (w3-form-element-value el))
     widget))
 
 ;(defun w3-form-create-multiline (el face)
-;  ;; FIX THIS! - need to padd out with newlines or something...
-;  (widget-create 'field :value-face face (w3-form-element-value el)))
+;  (widget-create 'text :value-face face (w3-form-element-value el)))
 
 (defun w3-form-create-multiline (el face)
-  (widget-create 'push-button :notify 'w3-do-text-entry "Multiline text area"))
+  (widget-create 'push-button
+		 :notify 'w3-do-text-entry
+		 "Multiline text area"))
+
+(defun w3-form-create-integer (el face)
+  (widget-create 'integer
+		 :size (w3-form-element-size el)
+		 :value-face face
+		 :tag ""
+		 :format "%v"
+		 :keymap w3-form-keymap
+		 :w3-form-data el
+		 (w3-form-element-value el)))
+
+(defun w3-form-create-float (el face)
+  (widget-create 'number
+		 :size (w3-form-element-size el)
+		 :value-face face
+		 :format "%v"
+		 :tag ""
+		 :keymap w3-form-keymap
+		 :w3-form-data el
+		 (w3-form-element-value el)))
+
+(defun w3-form-create-text (el face)
+  (widget-create 'editable-field
+		 :keymap w3-form-keymap
+		 :size (w3-form-element-size el)
+		 :value-face face
+		 :w3-form-data el
+		 (w3-form-element-value el)))
+
+(defun w3-form-create-password (el face)
+  ;; *sigh*  This will fail under XEmacs, but I can yell at them about
+  ;; upgrading separately for the release of 19.15 and 20.0
+  (if (boundp :secret)
+      (widget-create 'editable-field
+		     :secret ?*
+		     :keymap w3-form-keymap
+		     :size (w3-form-element-size el)
+		     :value-face face
+		     :w3-form-data el
+		     (w3-form-element-value el))
+    (w3-form-default-widget-creator el face)))
 
 (defun w3-form-default-widget-creator (el face)
   (widget-create 'link
 		 :notify 'w3-form-default-button-callback
+		 :value-to-internal 'w3-form-default-button-update
 		 :size (w3-form-element-size el)
-		 :tag (mule-truncate-string (w3-form-element-value el)
-					    (w3-form-element-size el) ?_)
 		 :value-face face
+		 :w3-form-data el
 		 (w3-form-element-value el)))
 
+(defun w3-form-default-button-update (w v)
+  (let ((info (widget-get w :w3-form-data)))
+    (widget-put w :tag 
+		(if info
+		    (mule-truncate-string
+		     (if (eq 'password (w3-form-element-type info))
+			 (make-string (length v) ?*)
+		       v)
+		     (w3-form-element-size info) ?_)))
+    v))
+
 (defun w3-form-default-button-callback (widget &rest ignore)
-  (let* ((obj (widget-get widget 'w3-form-data))
+  (let* ((obj (widget-get widget :w3-form-data))
 	 (typ (w3-form-element-type obj))
 	 (def (widget-value widget))
 	 (val nil)
 	 )
     (case typ
       (password
-       (setq val (funcall url-passwd-entry-func "Password: " def))
-       (widget-put widget :tag (mule-truncate-string
-				(make-string (length val) ?*)
-				(w3-form-element-size obj) ?_)))
+       (setq val (funcall url-passwd-entry-func "Password: " def)))
       (otherwise
        (setq val (read-string
-		  (concat (capitalize (symbol-name typ)) ": ") def))
-       (widget-put widget :tag (mule-truncate-string
-				val (w3-form-element-size obj) ?_))))
+		  (concat (capitalize (symbol-name typ)) ": ") def))))
     (widget-value-set widget val))
   (apply 'w3-form-possibly-submit widget ignore))
+
+;; These properties tell the help-echo function how to summarize each
+;; type of widget.
+(put 'checkbox  'w3-summarize-function 'w3-form-summarize-checkbox)
+(put 'multiline 'w3-summarize-function 'w3-form-summarize-multiline)
+(put 'radio     'w3-summarize-function 'w3-form-summarize-radio-button)
+(put 'reset     'w3-summarize-function 'w3-form-summarize-submit-button)
+(put 'submit    'w3-summarize-function 'w3-form-summarize-submit-button)
+(put 'button    'w3-summarize-function 'w3-form-summarize-submit-button)
+(put 'file      'w3-summarize-function 'w3-form-summarize-file-browser)
+(put 'option    'w3-summarize-function 'w3-form-summarize-option-list)
+(put 'keygen    'w3-summarize-function 'w3-form-summarize-keygen-list)
+(put 'image	'w3-summarize-function 'w3-form-summarize-image)
+(put 'hidden    'w3-summariez-function 'ignore)
+
+(defun w3-form-summarize-field (widget &rest ignore)
+  "Sumarize a widget that should be a W3 form entry area.
+This can be used as the :help-echo property of all w3 form entry widgets."
+  (let ((info nil)
+	(func nil)
+	(msg nil)
+	)
+    (setq info (widget-get widget :w3-form-data))
+    (if info
+	nil
+      (while (widget-get widget :parent)
+	(setq widget (widget-get widget :parent)))
+      (setq info (widget-get widget :w3-form-data)))
+    (if (not info)
+	(signal 'wrong-type-argument (list 'w3-form-widget widget)))
+    (setq func (or (get (w3-form-element-type info) 'w3-summarize-function)
+		   'w3-form-summarize-default)
+	  msg (and (fboundp func) (funcall func info widget)))
+    ;; FIXME!  This should be removed once emacspeak is updated to
+    ;; more closely follow the widget-y way of just returning the string
+    ;; instead of having the underlying :help-echo or :emacspeak-help
+    ;; implementation do it.
+    (message "%s" msg)))
+
+(defsubst w3-form-field-label (data)
+  ;;; FIXXX!!! Need to reimplement using the new forms implementation!
+  (declare (special w3-form-labels))
+  nil)
+
+(defun w3-form-summarize-default (data widget)
+  (let ((label (w3-form-field-label data))
+	(name  (w3-form-element-name data))
+	(value (widget-value (w3-form-element-widget data))))
+    (format "Text field %s set to: %s" (or label (concat "called " name))
+	    value)))
+
+(defun w3-form-summarize-multiline (data widget)
+  (let ((name (w3-form-element-name data))
+        (label (w3-form-field-label data))
+        (value (w3-form-element-value data)))
+    (format "Multiline text input %s set to: %s"
+	    (or label (concat "called " name))
+	    value)))
+
+(defun w3-form-summarize-checkbox (data widget)
+  (let ((name (w3-form-element-name data))
+	(label (w3-form-field-label data))
+	(checked (widget-value (w3-form-element-widget data))))
+    (format "Checkbox %s is %s" (or label name) (if checked "on" "off"))))
+
+(defun w3-form-summarize-option-list (data widget)
+  (let ((name (w3-form-element-name data))
+	(label (w3-form-field-label data))
+	(default (w3-form-element-default-value data)))
+    (format "Option list (%s) set to: %s" (or label name)
+	    (widget-value (w3-form-element-widget data)))))
+
+(defun w3-form-summarize-image (data widget)
+  (let ((name (w3-form-element-name data))
+	(label (w3-form-field-label data)))
+    (concat "Image entry " (or label (concat "called " name)))))
+
+(defun w3-form-summarize-submit-button (data widget)
+  (let*  ((type (w3-form-element-type data))
+	  (label (w3-form-field-label data))
+	  (button-text (widget-value (w3-form-element-widget data)))
+	  (type-desc (case type
+		       (submit "Submit Form")
+		       (reset "Reset Form")
+		       (button "A Button"))))
+    (format "%s: %s" type-desc (or label button-text ""))))
+
+(defun w3-form-summarize-radio-button (data widget)
+  (let ((name (w3-form-element-name data))
+	(label (w3-form-field-label data))
+	(cur-value (widget-value (w3-form-element-widget data)))
+	(this-value (widget-value widget)))
+    (format "Radio button %s is %s, could be %s" (or label name) cur-value
+	    this-value)))
+
+(defun w3-form-summarize-file-browser (data widget)
+  (let ((name (w3-form-element-name data))
+	(label (w3-form-field-label data))
+	(file (widget-value (w3-form-element-widget data))))
+    (format "File entry %s pointing to: %s" (or label name) (or file
+								"[nothing]"))))
+
+(defun w3-form-summarize-keygen-list (data widget)
+  )
+
+
+(defun w3-form-maybe-submit-by-keypress ()
+  (interactive)
+  (let ((widget (widget-at (point))))
+    (if widget
+	(w3-form-possibly-submit widget))))
 
 (defun w3-form-possibly-submit (widget &rest ignore)
-  (let* ((formobj (widget-get widget 'w3-form-data))
+  (let* ((formobj (widget-get widget :w3-form-data))
 	 (ident (w3-form-element-action formobj))
 	 (widgets (w3-all-widgets ident))
 	 (text-fields 0)
@@ -313,7 +579,7 @@
 	(w3-submit-form ident))))
 
 (defun w3-form-submit/reset-callback (widget &rest ignore)
-  (let* ((formobj (widget-get widget 'w3-form-data))
+  (let* ((formobj (widget-get widget :w3-form-data))
 	 (w3-submit-button formobj))
     (case (w3-form-element-type formobj)
       (submit (w3-submit-form (w3-form-element-action formobj)))
@@ -326,7 +592,7 @@
 
 (defun w3-do-text-entry (widget &rest ignore)
   (let* ((data (list widget (current-buffer)))
-	 (formobj (widget-get widget 'w3-form-data))
+	 (formobj (widget-get widget :w3-form-data))
 	 (buff (get-buffer-create (format "Form Entry: %s"
 					  (w3-form-element-name formobj)))))
     (switch-to-buffer-other-window buff)
@@ -342,7 +608,7 @@
   (interactive)
   (if w3-current-last-buffer
       (let* ((widget (nth 0 w3-current-last-buffer))
-	     (formobj (widget-get widget 'w3-form-data))
+	     (formobj (widget-get widget :w3-form-data))
 	     (buff (nth 1 w3-current-last-buffer))
 	     (valu (buffer-string))
 	     (inhibit-read-only t)
@@ -375,16 +641,21 @@
 	(case type
 	  ((submit reset image) nil)
 	  (radio
-	   ;; Ack - how!?
-	   )
+	   (setq deft (widget-get widget 'w3-form-default-value))
+	   (if (and widget deft)
+	       (widget-value-set widget deft)))
 	  (checkbox
 	   (if deft
 	       (widget-value-set widget t)
 	     (widget-value-set widget nil)))
+	  (multiline
+	   (w3-form-element-set-value formobj (w3-form-element-default-value
+					       formobj)))
 	  (file
 	   (widget-value-set widget deft))
 	  (otherwise
-	   (widget-value-set widget deft)))))))
+	   (widget-value-set widget deft))))
+      (widget-setup))))
 
 (defun w3-form-encode-helper (formobjs)
   (let (
@@ -397,6 +668,7 @@
 	    formobjs (cdr formobjs)
 	    temp (case type
 		   (reset nil)
+		   (button nil)
 		   (image
 		    (if (and (eq submit-button-data formobj)
 			     (w3-form-element-name formobj))
@@ -418,8 +690,11 @@
 		   (radio
 		    (let* ((radio-name (w3-form-element-name formobj))
 			   (radio-object (cdr-safe
-					  (assoc radio-name
-						 w3-form-radio-elements)))
+					  (assoc
+					   (cons
+					    radio-name
+					    (w3-form-element-action formobj))
+					   w3-form-radio-elements)))
 			   (chosen-widget (and radio-object
 					       (widget-radio-chosen
 						(w3-form-element-widget
@@ -427,6 +702,11 @@
 		      (if (assoc radio-name result)
 			  nil
 			(cons radio-name (widget-value chosen-widget)))))
+		   ((int float)
+		    (cons (w3-form-element-name formobj)
+			  (number-to-string (or (condition-case ()
+						    (widget-value widget)
+						  (error nil)) 0))))
 		   (checkbox
 		    (if (widget-value widget)
 			(cons (w3-form-element-name formobj)