Glyphs are graphical elements that can be displayed in SXEmacs buffers or gutters. We use the term graphical element here in the broadest possible sense since glyphs can be as mundane as text or as arcane as a native tab widget.
In SXEmacs, glyphs represent the uninstantiated state of graphical elements, i.e. they hold all the information necessary to produce an image on-screen but the image need not exist at this stage, and multiple screen images can be instantiated from a single glyph.
Glyphs are lazily instantiated by calling one of the glyph
functions. This usually occurs within redisplay when
Fglyph_height is called. Instantiation causes an image-instance
to be created and cached. This cache is on a per-device basis for all glyphs
except widget-glyphs, and on a per-window basis for widgets-glyphs. The
caching is done by
image_instantiate and is necessary because it
is generally possible to display an image-instance in multiple
domains. For instance if we create a Pixmap, we can actually display
this on multiple windows - even though we only need a single Pixmap
instance to do this. If caching wasn’t done then it would be necessary
to create image-instances for every displayable occurrence of a glyph -
and every usage - and this would be extremely memory and cpu intensive.
Widget-glyphs (a.k.a native widgets) are not cached in this way. This is because widget-glyph image-instances on screen are toolkit windows, and thus cannot be reused in multiple SXEmacs domains. Thus widget-glyphs are cached on an SXEmacs window basis.
Any action on a glyph first consults the cache before actually instantiating a widget.
Glyph instantiation is a hairy topic and requires some explanation. The
guts of glyph instantiation is contained within
image_instantiate. A glyph contains an image which is a
specifier. When a glyph function - for instance
asks for a property of the glyph that can only be determined from its
instantiated state, then the glyph image is instantiated and an image
instance created. The instantiation process is governed by the specifier
code and goes through a series of steps:
image_validateand at a simple level validates keyword value pairs.
image_copy_instantiator- which will selectively copy values. This is controlled by the way that a keyword is defined either using
IIFORMAT_VALID_NONCOPY_KEYWORD. Note that the image caching and redisplay code relies on instantiator copying to ensure that current and new instantiators are actually different rather than referring to the same thing.
image_instantiate. This involves calling instantiate methods that are specific to the type of image being instantiated.
The final instantiation phase also involves a number of steps. In order to understand these we need to describe a number of concepts.
An image is instantiated in a domain, where a domain can be any one of a device, frame, window or image-instance. The domain gives the image-instance context and identity and properties that affect the appearance of the image-instance may be different for the same glyph instantiated in different domains. An example is the face used to display the image-instance.
Although an image is instantiated in a particular domain the instantiation domain is not necessarily the domain in which the image-instance is cached. For example a pixmap can be instantiated in a window be actually be cached on a per-device basis. The domain in which the image-instance is actually cached is called the governing-domain. A governing-domain is currently either a device or a window. Widget-glyphs and text-glyphs have a window as a governing-domain, all other image-instances have a device as the governing-domain. The governing domain for an image-instance is determined using the governing_domain image-instance method.
Widget-glyphs under X make heavy use of lwlib (see Lucid Widget Library) for manipulating the native toolkit objects. This is primarily so that different toolkits can be supported for widget-glyphs, just as they are supported for features such as menubars etc.
Lwlib is extremely poorly documented and quite hairy so here is my understanding of what goes on.
Lwlib maintains a set of widget_instances which mirror the hierarchical state of Xt widgets. I think this is so that widgets can be updated and manipulated generically by the lwlib library. For instance update_one_widget_instance can cope with multiple types of widget and multiple types of toolkit. Each element in the widget hierarchy is updated from its corresponding widget_instance by walking the widget_instance tree recursively.
This has desirable properties such as lw_modify_all_widgets which is called from glyphs-x.c and updates all the properties of a widget without having to know what the widget is or what toolkit it is from. Unfortunately this also has hairy properties such as making the lwlib code quite complex. And of course lwlib has to know at some level what the widget is and how to set its properties.