At 02:13 PM 8/10/00 +0900, Stephen J. Turnbull wrote:
On the other hand, I think that using Lisp ojects in the widget's
internal structure is a dubious design decision. For example, in the
loop at line 2744 of src/glyphs-x.c, the fact that you are chasing two
lists which are assumed to be isomorphic is concealed by the use of
the LIST_LOOP macro. I'm not even sure that they should be isomorphic.
(Eg, we could surely avoid this crash by using a circular list of
children, which would not be isomorphic to the monotonic list of
buffers. This might result in a different kind of bug, of course.)
Remember that this is only neccessary under X because of lwlib. Under
mswindows the glyph structure encapsulates all of this information.
Another thing is that for a tabs widget, I don't see why any of
its
children ever need to be destroyed before the tabs manager itself is
destroyed. Memory leak? Yes, but it's bounded. The tab widget takes
up screen real estate, so (absent a mad list-creating function whose
value is assigned as the label list for the tabs widget) the user
won't let it grow too much. (Of course we should worry about extreme
behavior; I'm talking about the ordinary case.) So I see the
interface to the widget as
struct tabs {
LispObject current_list_of_strings; /* read only */
LispObject requested_list_of_strings; /* effectively write only */
LispObject current_top_widget; /* read only */
LispObject requested_top_widget; /* effectively write only */
LispObject current_display_parameter_list; /* faces etc, read only */
LispObject requested_display_parameter_list; /* effectively write only */
}
The implementation would be a private TabsWidget object. (In practice
the requested_* objects would be parts of a separate instantiator, as
Ben is requesting, rather than a permanent part of the structure.)
The point of this design is that you _never_ have to read data from
the lw- or Xt-level TabsWidget. Your comments sprinkled throughout
the code indicate that that is problematic. And it's easy enough to
generate SIGSEGVs just reading Xt objects :-(.
The interface would be to setf the RLOS or get the CLOS. When you
setf the RLOS, the widget's redisplay callback notices this, and walks
both lists. When corresponding objects differ, set
tabLabelWidget.string(i) = CLOS(i) = RLOS(i) and a dirty flag on
tabLabelWidget(i). In case len(RLOS) > len(CLOS), new TabLabelWidgets
are allocated and initialized. Optionally, if len(RLOS) < len(CLOS),
you could free some TabLabelWidgets, but unless there are a lot to be
freed it's probably better to just unmanage them.
Note that this could actually be efficiently separated into two loops,
since you only need to compare addresses of tabLabelWidget.string(i)
and CLOS(i).
Similar considerations would apply to the top tab and the display
parameters, except that those would be fixed structures. This should
make it possible to set all the labels, display parameters, and the
topWidget with one call to XtSetValues().
I don't think this is so different from what you're doing now, except
that discussing it this way shows that all this stuff could be handled
in about three places in the code (tabs instantiation, tabs redisplay,
and the implementation of TabsSetValues() in lwlib/xlwtabs.[ch]). But
at the moment things seem to be spread out all over. (At least,
looking at TabsSetValues(), x_tab_control_instantiate(), and
x_tab_control_redisplay() gives the impression that something must be
handled elsewhere.) And the role of things like the hook in buffer.c
get confused; it looks like it's tab-specific when actually it's
intended as a general facility that wasn't needed until buffer tabs
came along.
The correct solution given our current use of lwlib would be to factor the
code into lwlib so that lw_modify_all_widgets did the Right Thing. And this
is possible. However, doing this in lwlib is always a complete PIA *and*
difficult to get right *and* takes a long time. When actually what we are
trying to do is quite simple.
The abstraction of lwlib is laudable but IMHO makes things more complicated.
The mswindows code was very easy to get right because of the absence of lwlib.
BTW the current lisp structure using gui_items is mainly because we already
have functions to convert these into what lwlib is expecting.
andy
--------------------------------------------------------------
Dr Andy Piper
Principal Consultant, BEA Systems Ltd