The source code and documentation included here was written by:
    Dan Heller <island!argv@cad.berkeley.edu>
(also see notes about sample program at the end of this file)
-----------------

WidgetWrap.c -- variable argument style programmer interfaces to widgets:
   WidgetCreate(name, class, parent, varargs...);
   WidgetSet(name, varargs);
   WidgetGet(name, varargs);
   GenericWidgetName(buf);

The purpose of this module is to allow the programmer to Create
widgets and set/get widget attributes via a variable argument list
style of function call.  This eliminates the need for many local
variables and bothersome XtSetArg() calls and so forth.  An example
of usage:

   Widget foo;

   foo = WidgetCreate("foo", labelWidgetClass, toplevel,
	XtNlabel,		"Widget",
	XtNforeground,	WhitePixelOfScreen(XtScreen(toplevel)),
	XtNbackground,	BlackPixelOfScreen(XtScreen(toplevel)),
	XtNborderWidth,	1,
	NULL);

As you can see, the list must be NULL terminated.  You may pass up to
to MAXARGS argument pairs.  Increase this number in WidgetWrap.h if
necessary.

By default, WidgetCreate calls XtCreateManagedWidget() -- if you want to
create an unmanaged widget, you can use the parameter pair:

   XtNmanaged		False

(passing "True" is a no-op.)  Similarly, if you want to unmanage a widget
that has already been created, you can pass the same parameter pair in
a WidgetSet call.

If you already have an array of Arg's then you can use the parameter:
   XtNargList
this attribute takes _two_ parameters: the arglist array and the number
of elements in the array.  Now it is possible to pass attributes to the
WidgetCreate(), WidgetSet() and WidgetGet() that are probably common to
many widgets to be created or reset.

For example, you have:

static Arg args[] = {
    XtNforeground,	black,
    XtNbackground,	white,
    XtNwidth,		20,
    XtNheight,		10,
};
... later in your code you have ...

    foo = WidgetCreate("bar", widgetClass, toplevel,
	XtNargList,	args, XtNumber(args),
	NULL);

Finally, there are two more XtN's that the widgetwrap code provides.
You can create toplevel application shell widgets and popup shells
as well as other widget types by passing these parameters:

   XtNpopupShell		pass "True" to create a PopupShellWidget.
   XtNapplicShell		pass "True" to create an applicationShellWidget

These obsolete the need for XtCreatePopupShell() and XtCreateApplicationShell()
Note that for both of these, the "parent" parameter is ignored for the
WidgetCreate() call (you may pass anything, but the parent parameter remains
there for consistency).

The next thing that the WidgetWrap library comes with is a function to
generate widget names.  Most large applciations will create a large number
of widgets.  All widgets have to have unique names, and as noted by the
examples above, the names are typically constant strings which takes up
memory, disk spaces, etc...  Most of the time, there are a great number
of widgets in which their names are unused ... So, if WidgetCreate() gets
NULL as the name of the widget, then a widget name will be created
automatically.  The introduction of this function has saved about 10K
in text space on an application with about 300 widgets.

Before I finish, a note about varargs.  Note that there are many different
implementations of varargs.  To maintain portability, it is important
to never return from a function that uses varargs without calling va_end().
va_start() and va_end() should always exist in the same block of {}'s.
There can be blocks between them, but va_end() shouldn't be in a block
inside of the va_start() stuff.  This is to allow support for weird
implementations which define va_start() to something like:  ".... { "
(pyramid computers for one).
Also, if you use varargs, never declare "known" arguments; extract them
from the vararg list later.

-----------------------
There is a demo program which demonstrates how to use the widgetwrap code
and also provides a nifty little "prompt box".  the public routine is called
PromptBox() and the idea is to call it as:

   PromptBox(OK_BUTTON|CANCEL_BUTTON, "rm: remove %s?", file);

The return value in this case will be OK_BUTTON *or* CANCEL_BUTTON
depending on which the user selected.  You also have the choice of
YES_BUTTON and NO_BUTTON --to use more than one button, OR values together.
