+/* Update the displayed properties of a widget.
+
+ #### This has been adapted from the original set_property functions
+ and thus reuses the state management of that. A better solution is
+ to simply re-parse the instantiator when items need updating. This
+ make comparing differences much simpler and obviates the need for a
+ lot of the state variables.
+
+ #### property is still a valid function since we have to be able to
+ extract information from the actual widget.
+
+ #### update_widget should probably be re-written to use the
+ instantiator. We probably want to keep a record of the differences
+ also to make this easy. We would also need a pending_instantiator
+ so that changes could be delayed. */
+static void
+widget_update (Lisp_Object image_instance, Lisp_Object instantiator)
+{
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ struct image_instantiator_methods* meths;
+ struct gcpro gcpro1;
+
+ Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
+ Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
+ Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+ Lisp_Object descriptor_item = Qnil;
+
+ GCPRO1 (descriptor_item);
+
+ /* Pick up any generic properties that we might need to keep hold
+ of.
+ #### This is potentially bogus because it is changing the items
+ in place rather than in the pending items. */
+ if (!NILP (text))
+ {
+ IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
+ IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
+ }
+
+ /* Retrieve the gui item information. This is easy if we have been
+ provided with a vector, more difficult if we have just been given
+ keywords.
+
+ #### This is inconsistent with instantiation in that you have to
+ have the :descriptor keyword for updates in order to recognise
+ changes. */
+ if (VECTORP (desc))
+ {
+ descriptor_item = gui_parse_item_keywords_no_errors (desc);
+ }
+ else
+ {
+ /* Since we are updating the instantiator could be incomplete
+ and hence the gui item descriptor not well formed. We
+ therefore try updating and discard the results if nothing
+ changed. */
+ descriptor_item = copy_gui_item (IMAGE_INSTANCE_WIDGET_ITEM (ii));
+ if (!update_gui_item_keywords (descriptor_item, instantiator))
+ descriptor_item = Qnil;
+ }
+
+ /* Record new items for update. *_redisplay will do the
+ rest. */
+ if (!EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+ &&
+ !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
+ {
+ if (!NILP (items))
+ {
+ if (NILP (descriptor_item))
+ descriptor_item = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+
+ check_valid_item_list (items);
+#ifdef DEBUG_WIDGET_OUTPUT
+ stderr_out ("items for widget %p updated\n",
+ IMAGE_INSTANCE_SUBWINDOW_ID (ii));
+#endif
+ /* Don't set the actual items since we might decide not to use
+ the new ones (because nothing has really changed). If we did
+ set them and didn't use them then we would get into whole
+ heaps of trouble when the old items get GC'd. */
+ descriptor_item = Fcons (descriptor_item, parse_gui_item_tree_children (items));
+ }
+ /* If the descriptor was updated but not the items we need to fill
+ in the `new' items. */
+ else if (!NILP (descriptor_item)
+ &&
+ CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+ {
+ descriptor_item = Fcons
+ (descriptor_item,
+ copy_gui_item_tree (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))));
+ }
+ }
+
+ if (!NILP (descriptor_item))
+ {
+ IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = descriptor_item;
+ IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+ }
+
+ UNGCPRO;
+
+ /* Now try device specific methods first ... */
+ meths = decode_device_ii_format (image_instance_device (image_instance),
+ IMAGE_INSTANCE_WIDGET_TYPE (ii),
+ ERROR_ME_NOT);
+ MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
+ /* ... then format specific methods ... */
+ meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
+ ERROR_ME_NOT);
+ MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
+#if 0 /* The usefulness of this is dubious. */
+ /* we didn't do any device specific properties, so shove the property in our plist. */
+ IMAGE_INSTANCE_WIDGET_PROPS (ii)
+ = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
+#endif
+}
+
+/* Like the rest of redisplay, we want widget updates to occur
+ asynchronously. Thus toolkit specific methods for setting
+ properties must be called by redisplay instead of by *_update. Thus
+ *_update records the change and this function actually implements
+ it. We want to be slightly clever about this however by supplying
+ format specific functions for the updates instead of lumping them
+ all into this function. Note that there is no need for format
+ generic functions. This is not the same as widget_update! */
+void
+redisplay_widget (Lisp_Object widget)