]> Wbuild users manual

NAME

wbuild - build X Window System widgets from compact descriptions

SYNOPSIS

wbuild [-h dir] [-p prefix] [-c dir] [-d dir] [-i file] [-s] [-n] [-l] [file,...]

DESCRIPTION

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.

OPTIONS

Wbuild accepts the following options:

-h dir
the directory where the public and private header files will be put, e.g., `-h /usr/include/X11/Xpro'. The default is `./X11'.
-p prefix
the directory prefix in #include directives. E.g., the option `-p X11/Xpro' will result in the line #include <X11/Xpro/MyClassP.h> near the top of the implementation file.
-c dir
the directory where the implementation file will be put. Default is the current directory.
-d dir
the directory where the TeX-file will be put. Default is the current directory.
-i file
the file with the intrinsic widget classes. Default `wbuild.cfg'.
-s
generate sgml instead of TeX.
-n
generate Nroff instead of TeX. Options `-s' and `-n' are mutually exclusive. If they are both present, the last one will be taken.
-l
omit #line directives from the C file. The compiler's error messages will not refer to the specification file, but to the C file itself.
-o class
only generate the named class. This is useful in Makefiles, e.g., to re-generate only those C files that are out of date.

Instead of the -i option, it is also possible to use the environment variable WBUILDCFG.

Input format

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:

@nodoc
Do not generate documentation for this class.
@nocode
Do not generate C code for this class.
@guard=identifier
Put #ifndef identifier at the start of the public header file. By default, the identifier is the name of the file plus _H.
@guardP=identifier
Idem, but for the private header file.
@file=identifier
The base name of the generated C files. E.g., @class XgCommon (Composite) @file=Common will create files `Common.c', `Common.h' and `CommonP.h', instead of `XgCommon.c', etc.

Next follow at most 11 different divisions (in any order). Each starts with a keyword:

@public
Contains public instance variables (also known as `resources').
@private
Contains private instance variables.
@classvars
Class variables.
@methods
Methods, both new and redefined.
@actions
Action functions.
@translations
Default translations.
@utilities
Local functions, types, macros, etc.
@exports
Convenience functions, types, macros, etc. that will be made accessible through the public header file.
@constraints
Constraint resources (if the widget is a Constraint widget).
@private-constraints
Private constraint variables (if the widget a Constraint widget).
@imports
Imported files and external declarations.

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:

@
This section contains text (documentation).
@def
Defines a macro.
@var
Declares a variable.
@type
Defines a new type.
@proc
Defines a function.
@trans
Defines a default translation.
@incl
Includes a files.

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.

The @public division

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.

The @private division

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

The @classvars division

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

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;

The @actions division

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

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

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.

The @exports division

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 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.

The @private-constraints division

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.

The @imports division

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

The use of `self' ($) and `super' (#)

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.

Automatic inheritance

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.

Conditional compilation

Wbuild has limited support for #ifdef, #endif and their ilk. These directives can only be used in the following way:

  1. They can only occur in function bodies
  2. The # must be in column 1, with no whitespace after the #
  3. The balancing of #if and #endif isn't checked
Note that the directives are not evaluated by Wbuild. They are copied unchanged to the produced C code.

Example

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);
}

Core and Composite methods

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:

class_initialize()
The special symbol $ (`self') is not defined in this function.
class_part_initialize(WidgetClass class)
There is little reason to override this method. Wbuild uses it to implement inheritance. If you redefine it, you are responsible for inheritance yourself!
initialize(Widget request, $, ArgList args, Cardinal *num_args)
initialize_hook($, ArgList args, Cardinal *num_args)
This method is obsolete.
realize($, XtValueMask *mask, XSetWindowAttributes *attributes)
destroy($)
resize($)
expose($, XEvent *event, Region region)
Boolean set_values(Widget old, Widget request, $, ArgList args, Cardinal *num_args)
Boolean set_values_hook($, ArgList args, Cardinal *num_args)
This method is obsolete.
set_values_almost(Widget old, $, XtWidgetGeometry *request, XtWidgetGeometry *reply)
get_values_hook($, ArgList args, Cardinal *num_args)
Boolean accept_focus($, Time *time)
XtGeometryResult query_geometry($, XtWidgetGeometry *request, XtWidgetGeometry *reply)
display_accelerator($, String str)

The Composite class:

XtGeometryResult geometry_manager(Widget child, XtWidgetGeometry *request, XtWidgetGeometry *reply)
The special symbol $ is also defined inside this function.
change_managed($)
insert_child(Widget child)
The special symbol $ is also defined inside this function.
delete_child(Widget child)
The special symbol $ is also defined inside this function.

DIAGNOSTICS

(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.

BUGS

Wbuild has insufficient support for Constraint widgets. It is possible to write them with Wbuild, but it is difficult.

FILES

Wbuild expects the following file to be present:

wbuild.cfg
Specifications for intrinsic classes (but see the -i option and the WBUILDCFG environment variable).

SEE ALSO

Adian Nye and Tim O'Reilly, X Toolkit Intrinsics Programming Manual, O'Reilly & Associates, Inc., Sebastopol, CA, 1990.