]>
wbuild - build X Window System widgets from compact descriptions
wbuild [-h dir] [-p prefix] [-c dir] [-d dir] [-i file] [-s] [-n] [-l] [file,...]
Wbuild is a program that helps in writing widgets for the X Window System Toolkit. It lets you concentrate on the parts that are unique to a widget class, because it automatically adds all the code that can be inferred from that. Here is a list of its features:
The input to Wbuild consists of one or more files containing widget class definitions, both C code and documentation. The output is a set of four files for each class: the private and public header files, the implementation file and the documentation. These files are complete and do not need any further editing. In fact, they are not meant to be read by humans.
Wbuild accepts the following options:
Instead of the -i option, it is also possible to use the environment variable WBUILDCFG.
Every input file contains one or more classes. Each class starts with a line of the form
@class Name (Superclass) options
E.g., @class Common (Composite). The following options are possible:
Next follow at most 11 different divisions (in any order). Each starts with a keyword:
Divisions may occur more than once. The contents will be grouped together automatically. Each division contains a series of sections. There are 7 types of sections, each starting with a keyword:
The sections can occur in any order, but the text sections are assumed to document the code section that immediately follows it (if there is one), since the documentation file will retain the order of the sections. There are small differences between the divisions with respect to what sections are allowed in each of them.
Only @var, @def and text (@) sections may occur in the public variables division. The @var sections allow optional parts that are not possible in other divisions. A typical public variable looks like this:
@var type name = value
@var Pixel foreground = XtDefaultForeground
This defines a resource "foreground" of class "Foreground", plus the symbolic constants for use in C code XtNforeground and XtCForeground. It also defines a representation type XtRPixel, if it has not been defined before. The default value of this resource will be XtDefaultForeground. In some cases the resource name should be different from the variables's name, or the representation type is not constructed from the type name. Two optional parts allow for this:
@var <typename> type name <resource> = value
@var <Driver> struct drv_s * drive_name <driveName> = NULL
In this example the type is a complex type without a name, so the name "Driver" is created for it. The variable contains an underscore, which we don't want in the resource name. Since default values for resources may be given in different types (as long as there are converters for them) or even as function calls, the third optional part introduces the representation type of the default value; e.g.,
@var type name = <typename> value
@var Pixel foreground = <String> "black"
@var Dimension bwidth = <CallProc> calc_wd
Note: public variables are inherited together with their default values, but you may want to give such an inherited variable a new default value, like this:
@var width = 100
Wbuild will know that this variable is inherited from Core and fill in the type automatically.
Like the @public divison, the private variables division contains only text and @var and @def sections, but the @var sections are much simpler, since local variables have no resource values and cannot be initialized. A typical local variable looks like this:
@var type name
@var GC gc
Class variables are variables that are shared among all instances of a widget and its subclasses. They must be initialized. In the @classvars division only text, @var and @def sections can occur. Here is an example:
@var int num_instances = 0
Subclasses may want to set the initial values of inherited class variables differently. The following example sets a variable that is inherited from the Core class.
@var compress_motion = False
The @methods division may contain text, @def and @proc sections. New methods can be defined here and inherited ones can be redefined. If you redefine an inherited method, omit its return type and parameter list, since Wbuild will supply them automatically. New methods must give their parameter list in ANSI style, except when there are no parameters. In that case omit the parameter list completely or write just a pair of parenteheses (). To obviate the need for typecasts and knowledge of the various structs, Wbuild allows the symbol `$' (read `self') to occur in functions. See below. A new method might look like this:
@proc create_gc($) { XGCValues values; values.background = $background; $gc = XtGetGC($, GCBackground, &values); }
(The default return type void may be omitted.) An inherited function looks like this:
@proc set_values { if ($background != $old$background) $create_gc($); return False; }
A macro definition looks like this:
@def MAXSIZE = 25
(Don't forget the = sign!) There is no need to keep macros all on one line, as the next example shows:
@def done(t) = if (t < 10) return 100 + t; else return t;
Only text, @def and @proc sections appear in the @actions division, moreover, all functions are assumed to be actions, with parameter list ($, XEvent *event, String *params, Cardinal *num_params). The parameter list may not be redefined. Here is an action definition:
@proc DrawCell { $DrawPixmaps($, $gc, DRAW, event); }
The translations division contains only text and @trans sections. A @trans section follows the normal syntax for translations, except that arguments to action functions should be quoted:
@trans <BtnDown>,<Btn1Up>: confirm()
@trans <LeaveWindow>: popdownSubmenu("subbox")
Unfortunately, the current implementation of Wbuild doesn't allow translations to be inherited.
The @utilities division contains text, local functions (@proc), types (@type), macros (@def) and variables (@var). The only type of section not available here is the @trans section. The format of a @type section is as follows:
@type Info = struct {int n; char *s;}
@type Link = Info *
It is equivalent to these typedefs: typedef struct {...} Info and typedef Info *Link. Variables in this division may be initialised, but need not be:
@var int temp
@var char name[] = "Util"
You should consider using class variables instead of utility variables, because class variables are inherited an can thus be used by subclasses. In all other respects, utility variables and class variables act the same.
Variables, functions, types and macros that should be known outside the widget class and its subclasses, should be placed in the exprots division. Everything defined here will be declared in the public header file. You can put so-called convenience functions here. Variables may be initialized. Note that public variables are accessible via resources, which are also put in the header file. If one of those resources uses a new type, that type has to be defined in the exports division.
The constraints section has exactly the same syntax has the @public section (see above), but it defines the constraint resources that the widget will add to all its children. This section may occur in every type of widget, but it will be meaningless unless the widget is a subclass of the Constraint widget.
This section contains only text sections and @var declarations, with no initial values. The variables are meant to hold private state in addition to the constraint resources.
If any (header) files are to be included or any external variables or functions are to be declared, they can be put in an @imports section. Apart from text sections, only @incl, @proc and @var can occur here. Examples:
@incl "flip_back.xpm"
@incl <fcntl.h>
@proc int read(int fd, char *buf, int nbyte)
@var int errno
Wbuild allows the various structs that are used to implement the widget and the class to be completely hidden. The way to refer to instance variables, class variables, methods and constraints is to prefix them with a $; thus $background refers to the public variable background that is inherited from Core, $set_values refers to the method set_values, etc. A $ by itself is replaced by self (or Widget self if it appears in a parameter list). Most methods have a parameter self, some also have other parameters of type Widget. The set_values method, for example, has the following declaration:
@proc Boolean set_values(Widget old, Widget request, $, Arglist args, Cardinal *num_args)
Within the method, you can refer to variables in these other widgets as in the following example:
if ($background != $old$background) ...
Sometimes, you may want to use a method from the superclass. Use a # instead of a $, as in the next piece of code, which is rewritten from page 207 of `X Toolkit Intrinsics Programming Manual, Motif Edition'):
@proc realize { /* This is already set, but just for example */ *valueMask |= CWBitGravity; attributes->bit_gravity = NorthWestGravity; /* Use realize method from superclass */ #realize($, valueMask, attributes); }
Wbuild looks for the definition of the identifier in the follwing places: (1) instance variables (public and private), (2) methods, (3) class variables, (4) constraints (public and private). In each case, the current class is searched first and then the superclasses.
A widget class that defines new methods should allow subclasses to inherit them. The normal way is to define some symbolic constants and write a method to replace the symbolic constants with real functions. Wbuild does this automatically, so that all methods are always properly inherited. However, since wbuild uses the class_part_initialize method for this, inheritance fails if you write a new class_part_initialize method. In that case you are responsible for implementating inheritance yourself. The easiest way out is to add a call _resolve_inheritance(class) to the class_part_initialize method. This calls a function that wbuild has generated.
Wbuild has limited support for #ifdef, #endif and their ilk. These directives can only be used in the following way:
Here is an example of a complete input for wbuild:
# Button -- Button widget # Bert Bos <bert@let.rug.nl> # Version 2.0 for FWF V4.0 @class XfwfButton(XfwfLabel) @file=Button @ The |XfwfButton| widget is a simple button with a single callback |activate_callback|. Except for that callback, all resources are inherited from the |XfwfLabel| widget. Subclasses provide buttons of other, more specialized types. |XfwfButton| inherits its 3D frame from |XfwfFrame|, the location specification resources from |XfwfBoard| and the multi-line label from |XfwfLabel|. The implementation is also very simple, since nearly all code is inherited from |XfwfLabel|. There are no new or redefined methods. In fact, just six lines of actual code suffice to implement the widget: Object Oriented Programming at its best! @public @ The |activate| is invoked from the |activate| action, which is normally bound to a mouse click. The |call_data| argument of the callbacks routines is filled with a pointer to the event that triggered the action. @var <Callback> XtCallbackList activate = NULL @ The default |frameWidth| is set to 2 pixels. @var Dimension frameWidth = 2; @ In contrast to its superclass XfwfLabel, a button usually takes part in keyboard traversal. @var traversalOn = True @translations @ By default, the |activate| action is bound to a mouse click and to the Enter key. @trans <Btn1Down>: set_shadow("sunken") @trans <Btn1Down>,<Btn1Up>: activate() set_shadow() @trans Button1<Leave>: set_shadow() @trans <Key>Return: set_shadow("sunken") activate() set_shadow() @actions @ The |activate| action just calls the |activate| callback functions, passing the |XEvent| pointer in the |call_data| argument. @proc activate { XtCallCallbackList($, $activate, event); }
The methods for the Core and Composite classes are declared in the wbuild.cfg configuration file. To be able to override these methods, you'll need to know how they are declared. Here is a list, with some remarks. First the Core class:
The Composite class:
(Should be self-explanatory...)
The message foo.w:548: parse error at `' (token = ILL_BODY) indicates that there is a closing brace missing somewhere, usually in the body of a C function. The line number indicates the line where the body started.
Wbuild has insufficient support for Constraint widgets. It is possible to write them with Wbuild, but it is difficult.
Wbuild expects the following file to be present:
Adian Nye and Tim O'Reilly, X Toolkit Intrinsics Programming Manual, O'Reilly & Associates, Inc., Sebastopol, CA, 1990.