# HG changeset patch # User Richard M. Stallman # Date 827718376 0 # Node ID 62fc4d7a846fc3123d37c2e4b0fd2656b8513d18 # Parent b39dde411ac8c8fdcf91b44010378d1e3cccc1ae (destroy_all_children): New arg first_child_to_destroy. (make_menu_in_widget): New arg keep_first_children. (xm_update_menu): Preserve the first children even if later ones have a structural change. (update_one_menu_entry): Use this_one_change field. diff -r b39dde411ac8 -r 62fc4d7a846f lwlib/lwlib-Xm.c --- a/lwlib/lwlib-Xm.c Mon Mar 25 01:42:05 1996 +0000 +++ b/lwlib/lwlib-Xm.c Mon Mar 25 01:46:16 1996 +0000 @@ -147,9 +147,13 @@ return result; } +/* Destroy all of the children of WIDGET + starting with number FIRST_CHILD_TO_DESTROY. */ + static void -destroy_all_children (widget) +destroy_all_children (widget, first_child_to_destroy) Widget widget; + int first_child_to_destroy; { Widget* children; unsigned int number; @@ -158,17 +162,14 @@ children = XtCompositeChildren (widget, &number); if (children) { + XtUnmanageChildren (children + first_child_to_destroy, + number - first_child_to_destroy); + /* Unmanage all children and destroy them. They will only be - * really destroyed when we get out of DispatchEvent. */ - for (i = 0; i < number; i++) - { - Widget child = children [i]; - if (!child->core.being_destroyed) - { - XtUnmanageChild (child); - XtDestroyWidget (child); - } - } + really destroyed when we get out of DispatchEvent. */ + for (i = first_child_to_destroy; i < number; i++) + XtDestroyWidget (children[i]); + XtFree ((char *) children); } } @@ -337,11 +338,14 @@ return True; } +/* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */ + static void -make_menu_in_widget (instance, widget, val) +make_menu_in_widget (instance, widget, val, keep_first_children) widget_instance* instance; Widget widget; widget_value* val; + int keep_first_children; { Widget* children = 0; int num_children; @@ -353,6 +357,11 @@ int ac; Boolean menubar_p; + Widget* old_children; + unsigned int old_num_children; + + old_children = XtCompositeChildren (widget, &old_num_children); + /* Allocate the children array */ for (num_children = 0, cur = val; cur; num_children++, cur = cur->next); children = (Widget*)XtMalloc (num_children * sizeof (Widget)); @@ -368,7 +377,18 @@ XtAddCallback (XtParent (widget), XmNpopdownCallback, xm_pop_down_callback, (XtPointer)instance); - for (child_index = 0, cur = val; cur; child_index++, cur = cur->next) + /* Preserve the first KEEP_FIRST_CHILDREN old children. */ + for (child_index = 0, cur = val; child_index < keep_first_children; + child_index++, cur = cur->next) + children[child_index] = old_children[child_index]; + + /* Check that those are all we have + (the caller should have deleted the rest). */ + if (old_num_children != keep_first_children) + abort (); + + /* Create the rest. */ + for (child_index = keep_first_children; cur; child_index++, cur = cur->next) { ac = 0; XtSetArg (al [ac], XmNsensitive, cur->enabled); ac++; @@ -405,7 +425,7 @@ else { menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0); - make_menu_in_widget (instance, menu, cur->contents); + make_menu_in_widget (instance, menu, cur->contents, 0); XtSetArg (al [ac], XmNsubMenuId, menu); ac++; button = XmCreateCascadeButton (widget, cur->name, al, ac); @@ -430,6 +450,8 @@ } XtFree ((char *) children); + if (old_children) + XtFree ((char *) old_children); } static void @@ -444,7 +466,7 @@ Widget menu; widget_value* contents; - if (val->change == NO_CHANGE) + if (val->this_one_change == NO_CHANGE) return; /* update the sensitivity and userdata */ @@ -455,7 +477,7 @@ 0); /* update the menu button as a label. */ - if (val->change >= VISIBLE_CHANGE) + if (val->this_one_change >= VISIBLE_CHANGE) xm_update_label (instance, widget, val); /* update the pulldown/pullaside as needed */ @@ -471,7 +493,7 @@ if (contents) { menu = XmCreatePulldownMenu (XtParent (widget), XtName (widget), NULL, 0); - make_menu_in_widget (instance, menu, contents); + make_menu_in_widget (instance, menu, contents, 0); ac = 0; XtSetArg (al [ac], XmNsubMenuId, menu); ac++; XtSetValues (widget, al, ac); @@ -495,39 +517,64 @@ widget_value* val; Boolean deep_p; { + Widget* children; + unsigned int num_children; + int num_children_to_keep = 0; + int i; + widget_value* cur; + + children = XtCompositeChildren (widget, &num_children); + /* Widget is a RowColumn widget whose contents have to be updated * to reflect the list of items in val->contents */ - if (val->contents->change == STRUCTURAL_CHANGE) + + /* See how many buttons we can keep, and how many we + must completely replace. */ + if (val->contents == 0) + num_children_to_keep = 0; + else if (val->contents->change == STRUCTURAL_CHANGE) { - destroy_all_children (widget); - make_menu_in_widget (instance, widget, val->contents); + if (children) + { + for (i = 0, cur = val->contents; i < num_children; + i++, cur = cur->next) + { + if (cur->this_one_change == STRUCTURAL_CHANGE) + break; + } + + num_children_to_keep = i; + } } else + num_children_to_keep = num_children; + + /* Update all the buttons of the RowColumn, in order, + except for those we are going to replace entirely. */ + if (children) { - /* Update all the buttons of the RowColumn in order. */ - Widget* children; - unsigned int num_children; - int i; - widget_value* cur; - - children = XtCompositeChildren (widget, &num_children); - if (children) + for (i = 0, cur = val->contents; i < num_children_to_keep; i++) { - for (i = 0, cur = val->contents; i < num_children; i++) - { - if (!cur) - abort (); - if (children [i]->core.being_destroyed - || strcmp (XtName (children [i]), cur->name)) - continue; - update_one_menu_entry (instance, children [i], cur, deep_p); - cur = cur->next; - } - XtFree ((char *) children); + if (!cur) + abort (); + if (children [i]->core.being_destroyed + || strcmp (XtName (children [i]), cur->name)) + continue; + update_one_menu_entry (instance, children [i], cur, deep_p); + cur = cur->next; } - if (cur) - abort (); } + + /* Now replace from scratch all the buttons after the last + place that the top-level structure changed. */ + if (val->contents->change == STRUCTURAL_CHANGE) + { + destroy_all_children (widget, num_children_to_keep); + make_menu_in_widget (instance, widget, val->contents, + num_children_to_keep); + } + + XtFree ((char *) children); }