Index: src/console.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/console.h,v retrieving revision 1.22.2.19 diff -u -r1.22.2.19 console.h --- src/console.h 2000/02/07 07:59:36 1.22.2.19 +++ src/console.h 2000/02/09 18:38:20 @@ -223,6 +223,7 @@ struct display_glyph_area* dga); void (*resize_subwindow_method) (Lisp_Image_Instance *, int w, int h); void (*update_subwindow_method) (Lisp_Image_Instance *); + void (*update_widget_method) (Lisp_Image_Instance *); int (*image_instance_equal_method) (Lisp_Image_Instance *, Lisp_Image_Instance *, int depth); Index: src/frame-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/frame-msw.c,v retrieving revision 1.29.2.12 diff -u -r1.29.2.12 frame-msw.c --- src/frame-msw.c 2000/02/03 21:17:58 1.29.2.12 +++ src/frame-msw.c 2000/02/09 18:38:23 @@ -730,9 +730,6 @@ static void msprinter_init_frame_1 (struct frame *f, Lisp_Object props) { - HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))); - Lisp_Object frame_obj = Qnil; - /* Make sure this is the only frame on device. Windows printer can handle only one job at a time. */ if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f))))) @@ -951,7 +948,6 @@ static void msprinter_set_frame_properties (struct frame *f, Lisp_Object plist) { - BOOL size_changed_p = FALSE; Lisp_Object tail; /* Extract the properties from plist */ Index: src/glyphs-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v retrieving revision 1.21.2.42 diff -u -r1.21.2.42 glyphs-msw.c --- src/glyphs-msw.c 2000/02/07 07:59:52 1.21.2.42 +++ src/glyphs-msw.c 2000/02/09 18:38:31 @@ -2159,32 +2159,47 @@ | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); } +/* Simply resize the window here. */ +static void +mswindows_update_subwindow (Lisp_Image_Instance *p) +{ + mswindows_resize_subwindow (p, + IMAGE_INSTANCE_WIDTH (p), + IMAGE_INSTANCE_HEIGHT (p)); +} + /* when you click on a widget you may activate another widget this needs to be checked and all appropriate widgets updated */ static void -mswindows_update_subwindow (Lisp_Image_Instance *p) +mswindows_update_widget (Lisp_Image_Instance *p) { - /* Now do widget specific updates. */ - if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) + /* Possibly update the face font and colors. */ + if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)) { - /* buttons checked or otherwise */ - if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton)) - { - if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (p))) - SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), - BM_SETCHECK, (WPARAM)BST_CHECKED, 0); - else - SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), - BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); - } - /* set the widget font from the widget face */ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), WM_SETFONT, (WPARAM) mswindows_widget_hfont - (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)), + (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)), MAKELPARAM (TRUE, 0)); } + /* Possibly update the dimensions. */ + if (IMAGE_INSTANCE_SIZE_CHANGED (p)) + { + mswindows_resize_subwindow (p, + IMAGE_INSTANCE_WIDTH (p), + IMAGE_INSTANCE_HEIGHT (p)); + } + /* Possibly update the text in the widget. */ + if (IMAGE_INSTANCE_TEXT_CHANGED (p)) + { + Extbyte* lparam=0; + TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p), + C_STRING_ALLOCA, lparam, + Qnative); + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + WM_SETTEXT, 0, (LPARAM)lparam); + } } /* register widgets into our hastable so that we can cope with the @@ -2490,6 +2505,20 @@ } } +/* Update the state of a button. */ +static void +mswindows_button_update (Lisp_Object image_instance) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + /* buttons checked or otherwise */ + if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (ii))) + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + BM_SETCHECK, (WPARAM)BST_CHECKED, 0); + else + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); +} + /* instantiate an edit control */ static void mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, @@ -2689,26 +2718,20 @@ } /* set the properties of a tab control */ -static Lisp_Object -mswindows_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) +static void +mswindows_tab_control_update (Lisp_Object image_instance) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - if (EQ (prop, Q_items)) + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)); { HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); int i = 0; Lisp_Object rest; - check_valid_item_list_1 (val); /* delete the pre-existing items */ SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0); - IMAGE_INSTANCE_WIDGET_ITEMS (ii) = - Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), - parse_gui_item_tree_children (val)); - /* add items to the tab */ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) { @@ -2716,10 +2739,7 @@ IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), i); i++; } - - return Qt; } - return Qunbound; } /* instantiate a static control possible for putting other things in */ @@ -2853,43 +2873,21 @@ return Qunbound; } -/* set the properties of a control */ -static Lisp_Object -mswindows_widget_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) -{ - Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - if (EQ (prop, Q_text)) - { - Extbyte* lparam=0; - CHECK_STRING (val); - TO_EXTERNAL_FORMAT (LISP_STRING, val, - C_STRING_ALLOCA, lparam, - Qnative); - SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), - WM_SETTEXT, 0, (LPARAM)lparam); - /* We don't return Qt here so that other widget methods can be - called afterwards. */ - } - return Qunbound; -} - /* set the properties of a progres guage */ -static Lisp_Object -mswindows_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) +static void +mswindows_progress_gauge_update (Lisp_Object image_instance) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - if (EQ (prop, Q_percent)) + + if (IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii)) { + /* #### I'm not convinced we should store this in the plist. */ + Lisp_Object val = Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), + Q_percent, Qnil); CHECK_INT (val); SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), PBM_SETPOS, (WPARAM)XINT (val), 0); - return Qt; } - return Qunbound; } LRESULT WINAPI @@ -2936,6 +2934,7 @@ CONSOLE_HAS_METHOD (mswindows, unmap_subwindow); CONSOLE_HAS_METHOD (mswindows, map_subwindow); CONSOLE_HAS_METHOD (mswindows, update_subwindow); + CONSOLE_HAS_METHOD (mswindows, update_widget); CONSOLE_HAS_METHOD (mswindows, image_instance_equal); CONSOLE_HAS_METHOD (mswindows, image_instance_hash); CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage); @@ -2979,6 +2978,7 @@ INITIALIZE_DEVICE_IIFORMAT (mswindows, button); IIFORMAT_HAS_DEVMETHOD (mswindows, button, property); IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate); + IIFORMAT_HAS_DEVMETHOD (mswindows, button, update); INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field); IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate); @@ -2988,7 +2988,6 @@ INITIALIZE_DEVICE_IIFORMAT (mswindows, widget); IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property); - IIFORMAT_HAS_DEVMETHOD (mswindows, widget, set_property); /* label */ INITIALIZE_DEVICE_IIFORMAT (mswindows, label); @@ -3005,7 +3004,7 @@ /* progress gauge */ INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge); - IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, set_property); + IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, update); IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate); /* tree view widget */ @@ -3016,7 +3015,7 @@ /* tab control widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control); IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate); - IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, set_property); + IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, update); #endif /* windows bitmap format */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp"); Index: src/glyphs-widget.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/glyphs-widget.c,v retrieving revision 1.1.2.25 diff -u -r1.1.2.25 glyphs-widget.c --- src/glyphs-widget.c 2000/02/07 07:59:50 1.1.2.25 +++ src/glyphs-widget.c 2000/02/09 18:38:35 @@ -291,6 +291,7 @@ if (EQ (prop, Q_text)) { IMAGE_INSTANCE_WIDGET_TEXT (ii) = val; + IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1; } /* Now try device specific methods first ... */ @@ -320,6 +321,36 @@ return val; } +/* 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 *_set_property. Thus +*_set_property 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. */ +void +update_widget (Lisp_Object widget) +{ + Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget); + struct image_instantiator_methods* meths; + + if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET) + return; + + /* Device generic methods. We must update the widget's size as it + may have been changed by the the layout routines. We also do this + here so that explicit resizing from lisp does not result in + synchronous updates. */ + MAYBE_DEVMETH (XDEVICE (ii->device), update_widget, (ii)); + + /* Device-format specific methods */ + meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + MAYBE_IIFORMAT_METH (meths, update, (widget)); +} + /* Query for a widgets desired geometry. If no type specific method is provided then use the widget text to calculate sizes. */ static void @@ -522,8 +553,10 @@ /* We are going to be sneaky here and add the border text as just another child, the layout and output routines don't know this and will just display at the offsets we prescribe. */ - children = Fcons (glyph_image_instance (border, domain, ERROR_ME, 1), - children); + Lisp_Object gii = glyph_image_instance (border, domain, ERROR_ME, 1); + /* make sure we are designated as the parent. */ + XIMAGE_INSTANCE_PARENT (gii) = image_instance; + children = Fcons (gii, children); IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0); } else @@ -536,6 +569,8 @@ { /* make sure the image is instantiated */ Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1); + /* make sure we are designated as the parent. */ + XIMAGE_INSTANCE_PARENT (gii) = image_instance; children = Fcons (gii, children); /* Make sure elements in the layout are in the order the user expected. */ @@ -711,6 +746,51 @@ } } +/* Get the geometry of a tab control. This is based on the number of + items and text therin in the tab control. */ +static Lisp_Object +tab_control_set_property (Lisp_Object image_instance, + Lisp_Object prop, + Lisp_Object val) +{ + /* Record new items for update. *_tab_control_update will do the + rest. */ + if (EQ (prop, Q_items)) + { + Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + check_valid_item_list_1 (val); + + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + parse_gui_item_tree_children (val)); + + IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1; + + return Qt; + } + return Qunbound; +} + +/* set the properties of a progres guage */ +static Lisp_Object +progress_gauge_set_property (Lisp_Object image_instance, + Lisp_Object prop, + Lisp_Object val) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_percent)) + { + CHECK_INT (val); + IMAGE_INSTANCE_WIDGET_PROPS (ii) + = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val); + IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii) = 1; + + return Qt; + } + return Qunbound; +} + /***************************************************************************** * widget layout * @@ -1096,6 +1176,7 @@ IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget); + IIFORMAT_HAS_METHOD (progress_gauge, set_property); VALID_WIDGET_KEYWORDS (progress_gauge); VALID_GUI_KEYWORDS (progress_gauge); } @@ -1119,6 +1200,7 @@ IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget); IIFORMAT_HAS_METHOD (tab_control, query_geometry); + IIFORMAT_HAS_METHOD (tab_control, set_property); VALID_WIDGET_KEYWORDS (tab_control); VALID_GUI_KEYWORDS (tab_control); IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation); Index: src/glyphs-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v retrieving revision 1.49.2.50 diff -u -r1.49.2.50 glyphs-x.c --- src/glyphs-x.c 2000/02/07 07:59:53 1.49.2.50 +++ src/glyphs-x.c 2000/02/09 18:38:43 @@ -408,7 +408,8 @@ #endif lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p)); lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); - IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; + IMAGE_INSTANCE_X_WIDGET_ID (p) = (void*)0xDEADBEEF; + IMAGE_INSTANCE_X_CLIPWIDGET (p) = (void*)0xDEADBEEF; } } else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) @@ -2164,27 +2165,76 @@ static void x_update_subwindow (Lisp_Image_Instance *p) { + /* Update the subwindow size if necessary. */ + if (IMAGE_INSTANCE_SIZE_CHANGED (p)) + { + XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), + IMAGE_INSTANCE_X_SUBWINDOW_ID (p), + IMAGE_INSTANCE_WIDTH (p), + IMAGE_INSTANCE_HEIGHT (p)); + } +} + +/* Update all attributes that have changed. Lwlib actually does most + of this for us. */ +static void +x_update_widget (Lisp_Image_Instance *p) +{ #ifdef HAVE_WIDGETS - if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) + widget_value* wv = 0; + Boolean deep_p = False; + /* Possibly update the size. */ + if (IMAGE_INSTANCE_SIZE_CHANGED (p)) { - widget_value* wv = gui_items_to_widget_values - (IMAGE_INSTANCE_WIDGET_ITEMS (p)); + Arg al[2]; - /* This seems ugly, but I'm not sure what else to do. */ - if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qtab_control)) + assert (IMAGE_INSTANCE_X_WIDGET_ID (p) != (void*)0xDEADBEEF + && + IMAGE_INSTANCE_X_CLIPWIDGET (p) != (void*)0xDEADBEEF) ; + + if ( !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)) + || + IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed ) { - update_tab_widget_face (wv, p, - IMAGE_INSTANCE_SUBWINDOW_FRAME (p)); + Lisp_Object sw; + XSETIMAGE_INSTANCE (sw, p); + signal_simple_error ("XEmacs bug: subwindow is deleted", sw); } - /* update the colors and font */ + + XtSetArg (al [0], XtNwidth, (Dimension)IMAGE_INSTANCE_WIDTH (p)); + XtSetArg (al [1], XtNheight, (Dimension)IMAGE_INSTANCE_HEIGHT (p)); + XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (p), al, 2); + } + + /* First get the items if they have changed since this is a structural change. */ + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) + { + wv = gui_items_to_widget_values + (IMAGE_INSTANCE_WIDGET_ITEMS (p)); + deep_p = True; + } + + /* Possibly update the colors and font */ + if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)) + { update_widget_face (wv, p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)); + } - /* now modify the widget */ - lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), - wv, True); - free_widget_value_tree (wv); - /* subwindow resizing now gets done by the parent function. */ + /* Possibly update the text. */ + if (IMAGE_INSTANCE_TEXT_CHANGED (p)) + { + char* str; + Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p); + TO_EXTERNAL_FORMAT (LISP_STRING, val, + C_STRING_ALLOCA, str, + Qnative); + wv->value = str; } + + /* now modify the widget */ + lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), + wv, deep_p); + free_widget_value_tree (wv); #endif } @@ -2272,34 +2322,6 @@ } #endif -static void -x_resize_subwindow (Lisp_Image_Instance* ii, int w, int h) -{ - if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) - { - XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii), - IMAGE_INSTANCE_X_SUBWINDOW_ID (ii), - w, h); - } - else /* must be a widget */ - { - Arg al[2]; - - if ( !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (ii)) - || - IMAGE_INSTANCE_X_WIDGET_ID (ii)->core.being_destroyed ) - { - Lisp_Object sw; - XSETIMAGE_INSTANCE (sw, ii); - signal_simple_error ("XEmacs bug: subwindow is deleted", sw); - } - - XtSetArg (al [0], XtNwidth, (Dimension)w); - XtSetArg (al [1], XtNheight, (Dimension)h); - XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2); - } -} - #ifdef HAVE_WIDGETS @@ -2482,35 +2504,6 @@ free_widget_value_tree (wv); } -static Lisp_Object -x_widget_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) -{ - Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - /* Modify the text properties of the widget */ - if (EQ (prop, Q_text)) - { - char* str; - widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); - CHECK_STRING (val); - TO_EXTERNAL_FORMAT (LISP_STRING, val, - C_STRING_ALLOCA, str, - Qnative); - wv->value = str; - lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False); - } - - /* Modify the text properties of the widget */ - else if (EQ (prop, Q_face)) - { - widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); - update_widget_face (wv, ii, IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); - lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False); - } - return Qunbound; -} - /* get properties of a control */ static Lisp_Object x_widget_property (Lisp_Object image_instance, Lisp_Object prop) @@ -2603,21 +2596,20 @@ } /* set the properties of a progres guage */ -static Lisp_Object -x_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) +static void +x_progress_gauge_update (Lisp_Object image_instance) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - if (EQ (prop, Q_percent)) + if (IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii)) { Arg al [1]; - CHECK_INT (val); + /* #### I'm not convinced we should store this in the plist. */ + Lisp_Object val = Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), + Q_percent, Qnil); XtSetArg (al[0], XtNvalue, XINT (val)); XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1); - return Qt; } - return Qunbound; } /* instantiate an edit control */ @@ -2674,33 +2666,21 @@ } /* set the properties of a tab control */ -static Lisp_Object -x_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop, - Lisp_Object val) +static void +x_tab_control_update (Lisp_Object image_instance) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - if (EQ (prop, Q_items)) + /* Possibly update the face. */ + if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)) { - widget_value * wv = 0; - check_valid_item_list_1 (val); - - IMAGE_INSTANCE_WIDGET_ITEMS (ii) = - Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), - parse_gui_item_tree_children (val)); - - wv = gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); - + widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); update_tab_widget_face (wv, ii, IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True); - free_widget_value_tree (wv); - return Qt; } - - return Qunbound; } /* instantiate a static control possible for putting other things in */ @@ -2747,7 +2727,7 @@ CONSOLE_HAS_METHOD (x, locate_pixmap_file); CONSOLE_HAS_METHOD (x, unmap_subwindow); CONSOLE_HAS_METHOD (x, map_subwindow); - CONSOLE_HAS_METHOD (x, resize_subwindow); + CONSOLE_HAS_METHOD (x, update_widget); CONSOLE_HAS_METHOD (x, update_subwindow); } @@ -2788,10 +2768,9 @@ INITIALIZE_DEVICE_IIFORMAT (x, widget); IIFORMAT_HAS_DEVMETHOD (x, widget, property); - IIFORMAT_HAS_DEVMETHOD (x, widget, set_property); /* progress gauge */ INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge); - IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, set_property); + IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, update); IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate); /* text field */ INITIALIZE_DEVICE_IIFORMAT (x, edit_field); @@ -2800,12 +2779,12 @@ /* combo box */ INITIALIZE_DEVICE_IIFORMAT (x, combo_box); IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate); - IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, set_property, tab_control); + IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, update, tab_control); #endif /* tab control widget */ INITIALIZE_DEVICE_IIFORMAT (x, tab_control); IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate); - IIFORMAT_HAS_DEVMETHOD (x, tab_control, set_property); + IIFORMAT_HAS_DEVMETHOD (x, tab_control, update); /* label */ INITIALIZE_DEVICE_IIFORMAT (x, label); IIFORMAT_HAS_DEVMETHOD (x, label, instantiate); Index: src/glyphs.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v retrieving revision 1.23.2.46 diff -u -r1.23.2.46 glyphs.c --- src/glyphs.c 2000/02/07 22:37:11 1.23.2.46 +++ src/glyphs.c 2000/02/09 18:38:55 @@ -128,6 +128,7 @@ static void glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale); +static void set_image_instance_dirty_p (Lisp_Object instance, int dirty); static void register_ignored_expose (struct frame* f, int x, int y, int width, int height); /* Unfortunately windows and X are different. In windows BeginPaint() will prevent WM_PAINT messages being generated so it is unnecessary @@ -971,7 +972,7 @@ lp->y_offset = 0; lp->width = 0; lp->height = 0; - lp->glyph = glyph; + lp->parent = glyph; MARK_IMAGE_INSTANCE_CHANGED (lp); /* So that layouts get done. */ XSETIMAGE_INSTANCE (val, lp); MARK_GLYPHS_CHANGED; /* So that the dirty flag gets reset. */ @@ -1135,6 +1136,19 @@ } } +/* Recurse up the hierarchy looking for the topmost glyph. This means + that instances in layouts will inherit face properties from their + parent. */ +Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii) +{ + if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii))) + { + return image_instance_parent_glyph + (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii))); + } + return IMAGE_INSTANCE_PARENT (ii); +} + static Lisp_Object make_image_instance_1 (Lisp_Object data, Lisp_Object device, Lisp_Object dest_types) @@ -1351,12 +1365,9 @@ val = Qnil; } } - - /* Make sure the image instance gets redisplayed. - ### This currently does not change the dirty state of an - enclosing layout which may be bad. */ - MARK_IMAGE_INSTANCE_CHANGED (ii); + /* Make sure the image instance gets redisplayed. */ + set_image_instance_dirty_p (image_instance, 1); MARK_SUBWINDOWS_STATE_CHANGED; MARK_GLYPHS_CHANGED; @@ -1685,6 +1696,7 @@ we set the glyph geometry and lay it out. */ IMAGE_INSTANCE_WIDTH (ii) = width; IMAGE_INSTANCE_HEIGHT (ii) = height; + IMAGE_INSTANCE_SIZE_CHANGED (ii) =1; if (meths && HAS_IIFORMAT_METH_P (meths, layout)) { @@ -3688,6 +3700,22 @@ } } +static void +set_image_instance_dirty_p (Lisp_Object instance, int dirty) +{ + if (IMAGE_INSTANCEP (instance)) + { + XIMAGE_INSTANCE_DIRTYP (instance) = dirty; + /* Now cascade up the hierarchy. */ + set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance), + dirty); + } + else if (GLYPHP (instance)) + { + XGLYPH_DIRTYP (instance) = dirty; + } +} + /* #### do we need to cache this info to speed things up? */ Lisp_Object @@ -4201,18 +4229,24 @@ { Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); - if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET - || - NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) - return; + if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET) + { + update_widget (subwindow); + /* Reset the changed flags. */ + IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0; + IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii) = 0; + IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; + IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0; + IMAGE_INSTANCE_WIDGET_LAYOUT_CHANGED (ii) = 0; + } + else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW + && + !NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) + { + MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); + } - MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); - /* We must update the window's size as it may have been changed by - the the layout routines. We also do this here so that explicit resizing - from lisp does not result in synchronous updates. */ - MAYBE_DEVMETH (XDEVICE (ii->device), resize_subwindow, (ii, - IMAGE_INSTANCE_WIDTH (ii), - IMAGE_INSTANCE_HEIGHT (ii))); + IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0; } /* Update all the subwindows on a frame. */ @@ -4388,23 +4422,26 @@ (subwindow, width, height)) { int neww, newh; + Lisp_Image_Instance* ii; CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); + ii = XIMAGE_INSTANCE (subwindow); if (NILP (width)) - neww = XIMAGE_INSTANCE_WIDTH (subwindow); + neww = IMAGE_INSTANCE_WIDTH (ii); else neww = XINT (width); if (NILP (height)) - newh = XIMAGE_INSTANCE_HEIGHT (subwindow); + newh = IMAGE_INSTANCE_HEIGHT (ii); else newh = XINT (height); /* The actual resizing gets done asychronously by update_subwindow. */ - XIMAGE_INSTANCE_HEIGHT (subwindow) = newh; - XIMAGE_INSTANCE_WIDTH (subwindow) = neww; + IMAGE_INSTANCE_HEIGHT (ii) = newh; + IMAGE_INSTANCE_WIDTH (ii) = neww; + IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1; /* need to update the cachels as redisplay will not do this */ update_subwindow_cachel (subwindow); @@ -4543,7 +4580,9 @@ also might not. */ MARK_DEVICE_FRAMES_GLYPHS_CHANGED (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))); - MARK_IMAGE_INSTANCE_CHANGED (ii); + /* Cascade dirtiness so that we can have an animated glyph in a layout + for instance. */ + set_image_instance_dirty_p (value, 1); } } } Index: src/glyphs.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v retrieving revision 1.18.2.30 diff -u -r1.18.2.30 glyphs.h --- src/glyphs.h 2000/02/07 07:59:56 1.18.2.30 +++ src/glyphs.h 2000/02/09 18:38:58 @@ -143,6 +143,8 @@ Lisp_Object (*set_property_method) (Lisp_Object image_instance, Lisp_Object property, Lisp_Object val); + /* Asynchronously update properties. */ + void (*update_method) (Lisp_Object image_instance); /* Find out the desired geometry, as given by disp, of this image instance. Actual geometry is stored in the appropriate slots in the @@ -482,11 +484,13 @@ Lisp_Object name; /* The glyph from which we were instantiated. This is a weak reference. */ - Lisp_Object glyph; + Lisp_Object parent; enum image_instance_type type; unsigned int x_offset, y_offset; /* for layout purposes */ unsigned int width, height; unsigned int dirty : 1; + unsigned int size_changed : 1; + unsigned int text_changed : 1; union { struct @@ -525,6 +529,11 @@ Lisp_Object type; Lisp_Object props; /* properties or border*/ Lisp_Object items; /* a list of gui_items or children */ + /* Change flags to augment dirty. */ + unsigned int face_changed : 1; + unsigned int items_changed : 1; + unsigned int percent_changed : 1; + unsigned int layout_changed : 1; } subwindow; } u; @@ -543,7 +552,8 @@ /* Accessor macros. */ #define IMAGE_INSTANCE_DEVICE(i) ((i)->device) #define IMAGE_INSTANCE_NAME(i) ((i)->name) -#define IMAGE_INSTANCE_GLYPH(i) ((i)->glyph) +#define IMAGE_INSTANCE_PARENT(i) ((i)->parent) +#define IMAGE_INSTANCE_GLYPH(i) (image_instance_parent_glyph(i)) #define IMAGE_INSTANCE_TYPE(i) ((i)->type) #define IMAGE_INSTANCE_XOFFSET(i) ((i)->x_offset) #define IMAGE_INSTANCE_YOFFSET(i) ((i)->y_offset) @@ -556,6 +566,19 @@ #define IMAGE_INSTANCE_FACE(i) \ XGLYPH_FACE (IMAGE_INSTANCE_GLYPH (i)) +/* Changed flags */ +#define IMAGE_INSTANCE_TEXT_CHANGED(i) ((i)->text_changed) +#define IMAGE_INSTANCE_SIZE_CHANGED(i) ((i)->size_changed) +#define IMAGE_INSTANCE_WIDGET_FACE_CHANGED(i) \ + ((i)->u.subwindow.face_changed) +#define IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(i) \ + ((i)->u.subwindow.items_changed) +#define IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED(i) \ + ((i)->u.subwindow.percent_changed) +#define IMAGE_INSTANCE_WIDGET_LAYOUT_CHANGED(i) \ + ((i)->u.subwindow.layout_changed) + +/* Text properties */ #define IMAGE_INSTANCE_TEXT_STRING(i) ((i)->u.text.string) #define IMAGE_INSTANCE_TEXT_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) @@ -565,6 +588,7 @@ #define IMAGE_INSTANCE_TEXT_ASCENT(i) \ (IMAGE_INSTANCE_TEXT_HEIGHT(i) - IMAGE_INSTANCE_TEXT_DESCENT(i)) +/* Pixmap properties */ #define IMAGE_INSTANCE_PIXMAP_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) #define IMAGE_INSTANCE_PIXMAP_HEIGHT(i) \ @@ -582,6 +606,7 @@ #define IMAGE_INSTANCE_PIXMAP_MAXSLICE(i) ((i)->u.pixmap.maxslice) #define IMAGE_INSTANCE_PIXMAP_TIMEOUT(i) ((i)->u.pixmap.timeout) +/* Subwindow properties */ #define IMAGE_INSTANCE_SUBWINDOW_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) #define IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) \ @@ -599,6 +624,7 @@ #define IMAGE_INSTANCE_SUBWINDOW_JUSTIFY(i) \ ((i)->u.subwindow.justification) +/* Widget properties */ #define IMAGE_INSTANCE_WIDGET_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) #define IMAGE_INSTANCE_WIDGET_HEIGHT(i) \ @@ -618,6 +644,7 @@ IMAGE_INSTANCE_WIDGET_ITEMS (i)) #define IMAGE_INSTANCE_WIDGET_TEXT(i) XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (i))->name +/* Layout properties */ #define IMAGE_INSTANCE_LAYOUT_CHILDREN(i) ((i)->u.subwindow.items) #define IMAGE_INSTANCE_LAYOUT_BORDER(i) ((i)->u.subwindow.props) @@ -627,6 +654,8 @@ IMAGE_INSTANCE_NAME (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_GLYPH(i) \ IMAGE_INSTANCE_GLYPH (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PARENT(i) \ + IMAGE_INSTANCE_PARENT (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TYPE(i) \ IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_XOFFSET(i) \ @@ -945,6 +974,8 @@ struct display_glyph_area *dga); void update_frame_subwindows (struct frame *f); int find_matching_subwindow (struct frame* f, int x, int y, int width, int height); +void update_widget (Lisp_Object widget); +Lisp_Object image_instance_parent_glyph (struct Lisp_Image_Instance*); struct expose_ignore { Index: src/redisplay-output.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay-output.c,v retrieving revision 1.11.2.25 diff -u -r1.11.2.25 redisplay-output.c --- src/redisplay-output.c 2000/02/07 07:59:51 1.11.2.25 +++ src/redisplay-output.c 2000/02/09 18:39:08 @@ -1206,6 +1206,23 @@ redisplay_output_layout Output a widget hierarchy. This can safely call itself recursively. + + #### The complexity of outputting layouts is deciding whether to do + it or not. Consider a layout enclosing some text, the text changes + and is marked as dirty, but the enclosing layout has not been marked + as dirty so no updates occur and the text will potentially be + truncated. Alternatively we hold a back pointer in the image + instance to the parent and mark the parent as dirty. But the layout + code assumes that if the layout is dirty then the whole layout should + be redisplayed, so we then get lots of flashing even though only the + text has changed size. Of course if the text shrinks in size then we + do actually need to redisplay the layout to repaint the exposed + area. So what happens if we make a non-structural change liek + changing color? Either we redisplay everything, or we redisplay + nothing. These are exactly the issues lwlib has to grapple with. We + really need to know what has actually changed and make a layout + decision based on that. We also really need to know what has changed + so that we can only make the neccessary changes in update_subwindow. ****************************************************************************/ void redisplay_output_layout (struct window *w, @@ -1246,7 +1263,11 @@ /* Highly dodgy optimization. We want to only output the whole layout if we really have to. */ - if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (p)) + if (frame_really_changed + || IMAGE_INSTANCE_WIDGET_LAYOUT_CHANGED (p) + || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) + || IMAGE_INSTANCE_SIZE_CHANGED (p) + || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) { /* First clear the area we are drawing into. This is the easiest thing to do since we have many gaps that we have to make sure are