File: impl.txt
Author: Heinz Schmidt
Created: Sun Oct 21 13:10:15 1990
Copyright (C) International Computer Science Institute, 1990

This document describes the low level interface to XView and some of the
implementation decisions.


Implementation notes 
====================

Terminology: XView -- XView 2.0 shared with Sun
             XVAUX -- the C part of our interface to XView (in C/xvaux.c)
             CSTR  -- sather strings to C strings (in cstr.sa, C/cstraux.c)
             XVLOW -- the low level Sather part this interface (in xvlow.sa)
             SaWS  -- Sather window system, high-level classes interfacing to XView
                      (in window.sa, command.sa)
             xv_   -- prefix of many XView constants and procedures
             sxv_  -- prefix of some XVAUX functions

             user  -- the user of the Sather application clicking the mouse and
                      typing textual input etc.
             programmer -- the programmer of the Sather application making
                      use of the Sather -- xview interface
             caller -- the class or routine in Sather that calls an XVAUX
                      function or another Sather routine.
                      Also the XVAUX function that calls a SaWS routine.
             callee -- inverse of above
             event  -- a C struct in XView recording some user/program action.
             event handler
                    -- a function or routine called in response to some event or
                       the original user/program action.
             handler object
                    -- an instance of a Sather class comprising a number of event
                       handlers to deal with certain kinds of events related to that 
                       object.

Interfaces:

The implementation is in terms of function calls, we avoid use of macros
to be able to run the code with the Sather interpreter. Also data
passed from XView to Sather is limited. Typically handles are passed
but the referenced objects cannot be accessed directly. Only simple
data (int,string) is passed from Sather to C to not interfere with GC.

Xview makes extensive use of variable arguments to allow a flexible way
of creating and manipulating objects and subobject with one call.
Sather does not support variable arguments. Usually we call a C function
declared with a sufficient number of argumetns and fill the unused ones with 0. 

1. XVLOW <--CALLS--> XView

   * XVLOW supports only a subset of the keys (constants)
     indicating the kinds and properties of objects to be created and
     the way they are going to respond to events
   * only a fixed number of XVLOW callbacks can be registered for certain
     types of events. Their names are fixed and they are supported
     in XVLOW classes and linkage is by means of the .sather (c_name) option.

2. XVLOW <--CALLS--> XVAUX

   * some higher level C functions are built on top of the Xview functions
     to hide details of for instance event access and event handling. Also
     XView macros are wrapped in C functions or simple interfaces to 
     complex XView features are provided (such as simple notices).
   * XVAUX mediates in callback registration. Some event handlers are
     offered by XVLOW are actually XVAUX functions, which preprocess events
     and call, or dispatch to, the proper XVLOW functions.
     The Sather-XView programmer may decide to indirect callbacks in this way 
     at any time without breaking Sather code.

3. XVLOW <--CALLS--> Sather objects

   * XVLOW maps XView handles to Sather objects (windows, menus ...) via
     hashtables. When registered XVLOW routines are called back by XView,
     they save some of the callback parameters, use one of them to
     find the proper Sather handler object and dispatch to a standard routine
     of that object. Typically the routine is postfixed with '_action'.

In the following sections we summarize the major functions of the
Sather Xview interface and their implementation. We focus on the XVLOW
--CALLS-> XVAUX/xview --CALLS--> XVLOW interface, not on the
programmer's use of higher-level SaWS Classes. The later is described
in a short SaWS doc text.

Steps of application built-up
=============================

From within XView the following steps make up the use of xview
functionality:

   a. initialize the system

   b. build dialog objects by

      i. use of generic xview routines (xv_create, xv_set, and xv_get)
         to build xview objects, or by
      ii. use of XVAUX routines implemented in terms of these generic routines
         to build xview objects at startup time or dynamically.

   c. start the dialog main-loop of the xview Notifier. The notifier
      detects events and calls the application callback routines registered
      in (b).

   e. destroy the top level dialog objects (which in turn will 
      destroy all their inferior objects.


XView generic functions
=======================

The state of all XView dialog objects is completely defined in terms
of properties that can be inquired by xv_get and most of which can be
set by xv_set. Setting a property has the immediate sideefect on the
presentation of the object if the presentation is visible.  For
instance, setting the xv_show attribute to true let's xview make all
the necessary Xlib calls to show the dialog object on the screen and
may in turn lead to a number of events generated by xview server such
as calling the window_repaint_event_handler if the window shown was
partly hidden before setting the property.  All properties have simple
defaults; some of them will depend on the Xresource database settings
and can be customized by the user.  Some will follow from the Openlook
style and will be enforced by Xview.  A fixed setting by the Sather
application should follow the Openlook application style guidelines.

The XView generic functions xv_create, xv_set and xv_get are directly
called by XVLOW to create objects, to set and get their properties.
Since parameters passed to these functions must adhere to the XView
calling conventions, this interface is considered fragile.  Typically
XVLOW and SaWS will offer safer Sather routines that build on top of
these generic functions.  

All generic functions take a sequence of keys (constants) as arguments
to allow XView an efficient creation of and access to its objects.
XView uses bit masks, bit shifts and other efficient techniques to do
the generic functions job efficiently.

For most of the xview keys, XVLOW offers constants of the same name.

   constant frame_base:               INT := C::to_xv_(typ_off+6);        

During the initialization of the Sather system these constants will be
initialized with the corresponding xview key value using a a call to
the cvaux to_xv_ function. XVAUX has a table mapping Sather integers
to to xview keys. The arguments to tx_xv_, here type_off+6 are fixed
and known in XVAUX. In this way the XVAUX initialization does not
depend on the actual values of XView keys. Only XVAUX needs to be
recompiled when key values change in xview in a new release. Other
changes like deletion of a key in the XView implementation may require
changes in the XVAUX and or the XVAUX implementation of course.

Some properties have string values or array-of-string values.  For
converting Sather strings to C strings, CSTRAUX funtions are used. All
the CSTRAUX functions are listed in a C class of cstr.sa and are
automatically available to the Sather application.  (This requires
inclusion of the cstraux.o binary of course.)


XVAUX functions
===============

XVAUX offers some functions on top of XView related to

- notices
- access to rectangles and rectangle lists passed to callbacks
- event registration 
- dispatching window events to avoid the need to access events in SaWS

The event registration function tell XView what windows want to listen to
and also register a callback to intercept events and dispatch to the
proper handler in XVLOW.


XVAUX callbacks
===============

A fixed number of callbacks is supported. The names are known in XVAUX
where they are declared as C externals. The .sather files must list
all these callbacks with the (c_name) option.  A list of the
appropriate (c_name) options is contained in the file
sather/ui/c_name_list. In the link edit step the corresponding
function references will be resolved including the buildup of a table
of function addresses that can be used to register these functions as
callbacks of XView objects.

Analogous to the XView key values the addresses of these functions
are constant values in XVAUX

   constant canvas_repaint_proc:      INT := C::sxv_cb_adr(1);

initialized at Sather startup by means of the XVAUX function
sxv_cb_adr that looks up the address in a table.

For XVLOW it is invisible whether the corresponding function has an
intermediate handler inside the XVAUX package which preprocesses
events and calls the external XVLOW routine or whether the XVLOW
routine is directly registered. This gives the SaWS implementor some
freedom in adapting the C code to new versions of XView if necesssary
without the need to change the Sather code.

The callbacks are documented in the class X of the XVLOW package.
Their names are chosen to reflect the socalled 'semantic event' level
of XView that distinguishes a number of events and realizes them but a
fixed allocation to pointing device buttons (like SELECT, ADJUST,
MENU) or by internally handling certain events such as window
configuration events.

The XVLOW callbacks are registerd when XView objects are created that
need to respond to events. Usually this mechanism is hidden from the
Sather programmer. Some types of event handling XView object are
encapsulated by a corresponding Sather object that has a reference to
the XView object. For these objects the XVLOW package has a mapping
from XView objects to Sather objects. (No references to Sather objects
are ever passed to XView to avoid interference with the Sather
garbarge collection). Callbacks are called with a reference to the
XView objects (but with self bound to void).  The callbacks can then
use the object map to dispatch the event (call) to the proper Sather
handler object.

Canvas windows are the most common windows where the application
is likely to handle the various events. Note that XView splits
a canvas window into three window objects, of which the so-called
canvas-paint window is the one passed to the event handling routines.
The different sxv routines take different XView windows as parameters.
For instance, the notice functions (cf. below) want the canvas window,
while event registration requires the canvas-paint window and
Xlib drawing routines expect the Xwindow handle.

A note on event types:

Multiple event handling routines have the disadvantage of multiple
external function declarations in XVAUX and multiple (c_name) options
in the .sather file. Their advantage is however that we do not need to
merge different functionalities (number and type of parameters) in one
event handling routine known to XVAUX. This would require that we roll
our own event handling mechanism, which we want to avoid for
simplicity of our interface and the comfort that comes with the
well-thought-out XView package. Also it might turn out that we would
indeed loose some efficiency, since XView already dispatches to
different callbacks and to reduce the number of callbacks we would
have to merge the calls on the C side (XVAUX) and dispatch again on
the Sather side which adds additional code and time to do the
discrimination into different types of events. 
[ Some coarse analysis of the runtime cost in either case can be found
at the end of this file.]

KEY_DATA
========

XVAUX/XVLOW exploits the XView capability to associate an arbitrary number
of application properties with XView objects. key_data is, for
instance, used to associate popup frames with window buttons and the
main-menu with a window. 


Command Handling
================

The XVLOW package offers a uniform handling of commands. Commands are
Sather objects that support a common set of attributes and routines.
They are handler objects associating actions to panel and menu items.

Some commands enclose own context specific information. XVLOW fills 
in the corresponding attributes when handling an event before calling
the event handler 'cmd_action' of the command. For instance, the XView
item that was receiving the event one of the attributes typically.

The 'cmd_action' routine executes the command. Typically this is the
only routine to be redefined in subclasses.  Some commands encapsulate
operations on other objects they are associated with. In the test
suite for SaWS we have some examples of commands that have additional
attributes like 'frame' that are filled by the application ahead of
installing the command. Our test commands for instance change the
title of a frame as a response to button or menu item selection.

Separation of commands from the user interface objects allows dynamic
command installation. Moreover different events can be 'mapped' to the
same command by installing commands multiply or calling the command
action from within the application. This can be exploited if the user
has multiple ways to invoke the same application function like typing
in a command name, selecting from a menu or using accelerators, i.e.
function keys and/or key sequences that allow a fast selection if
choices are present.

[[ Why aren't command just functions? function parameters cannot be
passed in Sather's type system. So we form an implicit closure, i.e.
an object representing a function, some of which arguments are bound,
here simulated by putting these argument into the object as values of
its attributes. 

Why aren't operations simply 'installed' in the operation-invoking
user interface object like a button image or an item?  1. functions
cannot be passed and hence not be installed, cf. above. 2. the same
operation may be invoked in different ways by the user such as typing
the operation name pressing a key or clicking into a button or menu
item. 3. It appears useful to separate the definition of commands from
(a) window operations and (b) application operations. No separation
would imply (a) writing new routines (for window subclasses) or (b)
ditto for the application classes.  Separate commands can deal with
both and treat both the application and the user interface objects as
mainly passive objects.
]]
 

Notices
=======

Notices are special XView panels that grab all user input and must be
answered or dismissed before the user can go on with other activities.
The XVLOW package supports three kinds of notices:

 notification: the user must explicitly dismiss the notification
 confirmation: the user must confirm or cancel the notification
 query:        the user must select one of n alternative.

These functions are based on XVAUX functions called by XVLOW. The XVAUX
functions hide the event access and return a boolean result or
an integer (query) indicating the result of the query.
The implementation in XVAUX takes care that no collision of return codes
with XView codes such xv_failure are possible.


Menu choices
============

To support synchronous menu choices, XVLOW support two kinds of menus:
single and subset choice. Both are supported by scroll lists presented
in a separate panel.The properties are setup such that the user must
explicitly choose or dismiss the choice before continuing to operate
with any other window. 

Note that panels are usually windows that the user can make
permanently visible and that generate events when the user interacts
with them. We have found the following panels useful
but not yet provided Sather abstractions for them:

Command panels: offers command buttons and the appropriate items for
setting the options under which the commands should act. The items
offered should refer to settings that the user may need to change
frequently prior to using the commands offered or options that
the user needs to be aware of in the context of the commands offered.

Variables panels: offers items to set options under which window
commands should act. These panels are useful for settings that
change less often such as properties related to a user's profile, 
or for global settings that apply to various commands such as 
read-only versus edit modes.


Event-driven application
========================

All other dialog objects we support offer an event-driven paradigm for
the way the application and the user interact.  The user's interaction
with XView objects generates events that drive the application by means
of the registered callback routines.



Examples
========

Most XView examples can directly be 'translated' into the appropriate
Sather notation.  The mapping from XView to sather names is as
follows:

 XView						Sather

 all keys like:					lower case constant: 
 XV_HEIGHT					xv_height

 procedure values for registering		lower case untyped name (delete prefix)
 callbacks with attribute like:                 ending in 'action':
 CANVAS_REPAINT_PROC				repaint_action

 For simple applications there is no need to call XView directly. Extensions
 of our interface may need to call xv_set, xv_create. Only a limited fixed number
 of argument is allowed.

 
XView examples (from xview/examples) translated in window.sa:
 - notices
 - menus
 - buttons

Advanced examples:
 - move_it.c panel prototyper base
 - glyphs.c  image panel buttons/items 


Appendix 1: Coarse analysis of rolling our own event handling
=============================================================

To reduce the number of callbacks, i.e. Sather functions known to XVAUX,
we would have to roll our own event handling and registration.
Beside other disadvantages it seems we would also loose some runtime.

We also would have roll our own callback registration mechanism in
XVAUX to be able to tell XVLOW the kind of event in terms of
discrimating codes passed as parameters. Moreover the event handling
would have to go through at least two additional stages

1. call of XVAUX event handler, which calls the unique XVLOW handler
with the discriminating argument(s).
2. dispatch in XVLOW according to the event-type.
3. and maybe lookup of the class of object responsible for handling this
   type of event (this could also be encoded in the discriminating code).

In the latter case, XView would call the unique XVLOW callback
directly.  But it would be called with differing numbers and types of
arguments.  It would have to carefully analyse the arguments to figure
out what kind of event handling is desired without accessing
potentially missing arguments or calling on properties that the XView
object passed do not have.

Our solution avoids all this hassle. It takes advantage of the
high-level XView event handling. Yet it encapsulates and implements an
abstraction that could be realized in a different way on a different
user interface platform. (Maybe with more code).

In a sense the XVLOW package and the XVAUX package together form a 
unit that implements the desired UI abstraction for Sather.
And as it happens the cut between XVLOW and XVAUX has few C externals
for the price of some Sather externals that can be called from C.

The current implementation takes one table lookup at callback
registration time.o and after the XView internal event handling
requires 1 C function call to the Sather callback, 1 object lookup
mapping XView object to Sather object and 1 Sather dispatched call to
handle the event in the proper object. Moreover it has the 'right'
number and types of parameters and does not require to multiple C
calls to access an event data structure to figure out more about the
kind of the event.

For a callback that is handled inside XVAUX, the current implementation
requires 1 additional C function call plus some macro accesses to
event structures and/or KEY_DATA (cf. below) of the XView dialog
object to pass only the relevant parameters to Sather. Except for
rectangles and rectangle lists (cf. below) these arguments are either
defined by Sather (integer codes to identify commands for instance) or
uninterpreted xvobject pointers that are used to map to the proper
Sather object in the fixed set of callbacks or that are passed back to
XView functions such as xv_set (to set properties of those objects).

Appendix 2: Tables in Sather vs. key_data in XView
==================================================

-- Hashtables mapping from Xview handles to Sather objects can be
-- greater-equal twice as fast as indexing into an array of Sather objects where 
-- indexes are stored as client data in XView object.
--
-- Average hashing time (XView handle to Sather handler object) 1000000 times
--   User: 0.001115 System: 0.000009 Total: 0.001125
-- Average array access time (index client data in XView object) 1000000 times
--   User: 0.002903 System: 0.000014 Total: 0.002916

