YAWN(3Y)

NAME
YAWN - Yet Another Widget Neatener

DESCRIPTION

YAWN is a library of useful functions for X widget management.

It is designed to work together with X11 Release 5, the X Toolkit and the Athena Widget Set to supply an elegant streamlined look-and-feel to accompany the unpolicied functionality provided by Xt and Xaw. In this YAWN has something in common with OSF Motif, although YAWN is a much simpler convenience tool, is entirely interoperable with Xt/Xaw code, has a different look-and-feel, and is free.

USAGE

  Initialisation and Cleaning Up

YAWN provides two simple initialisation and exit functions:

void YInitialise(widget, helpCallback)
       Widget widget;
       YHelpCallback helpCallback;

    This initialises the YAWN library. widget may be any existing managed composite widget (such as your top-level shell widget). helpCallback is a function to be called when the Help button on a YAWN dialogue box is pressed: the argument passed into the callback will be the tag string that was passed in to the creation function for that box (see below). helpCallback may be NULL, in which case no such callback will be called.

    YHelpCallback is defined as:
            typedef void  (* YHelpCallback)(String);

    You may call YInitialise more than once with different arguments if you wish.

void YCleanUp(void)

    Deallocates any storage allocated by YAWN in the current session (except menu records). Programs making use of YAWN should be sure to call YCleanUp before exiting.

    Do not use any other YAWN functions after having called YCleanUp. You may invoke YCleanUp even if YInitialise has not been called.

  Shading

Most of the widgets created under YAWN's jurisdiction are given shaded backgrounds. There are various possible shades, and which shade is used for a given widget will determine the colour (on a colour display) or stipple (on a monochrome display) used for that widget's background. On a colour display, the colours corresponding to the shades are retrieved from X resources; when YAWN is initialised, it creates a set of ``mock'' Athena Label widgets as children of a widget named yawn, and draws the colour resources from those. Shade values care specified in the library interface as a type YShade. This can take on the following values:

NoShade
    The widget's background will not be shaded. On a colour display, it will take on the value retrieved from the yawn.noShade.background resource.

LightShade
    The widget's background will be shaded in a light grey stipple on mono displays, and coloured in the value of yawn.lightShade.background on colour ones.

MediumShade
    The widget's background will be shaded in an even grey stipple on mono displays, and coloured in the value of yawn.mediumShade.background on colour ones.

SurroundShade
    The widget's background will not be shaded. On a colour display, it will take on the value retrieved from the yawn.surroundShade.background resource. This is usually used for the surrounding boxes of action buttons and labels.

In all cases, the foreground and background colours to be used on a monochrome display are taken from the values of yawn.mono.foreground and yawn.mono.background.

  Widget Creation

YAWN supports a number of ``dedicated'' widgets; these are normal Athena widgets which, when created through the YAWN toolkit, are given a standard look through the use of resources and surrounding widgets. These can all be manipulated subsequently either with or without the use of YAWN. In addition, functions are provided to make creation of common standard Athena widgets easier and quicker.

Widget YCreateWidget(name, class, parent)
       String name;
       WidgetClass class;
       Widget parent;

    This creates and returns a new managed Xt/Athena widget with the given name, class and parent and a NULL resource argument list.

    YCreateWidget is implemented as a macro.

Widget YCreateUnmanagedWidget(name, class, parent, shade)
       String name;
       WidgetClass class;
       Widget parent;
       YShade shade;

    This creates and returns a new unmanaged Xt/Athena widget with the given name, class and parent and a NULL resource argument list.

Widget YCreateShadedWidget(name, class, parent, shade)
       String name;
       WidgetClass class;
       Widget parent;
       YShade shade;

    This creates and returns a new managed widget with the given name, class and parent and a NULL resource argument list, and sets its backgroundPixmap resource according to shade. The YShade type is described above, under Shading.

Widget YCreateLabel(name, parent)
Widget YCreateCommand(name, parent)
Widget YCreateRepeater(name, parent)
Widget YCreateMenuButton(name, parent)
       String name;
       Widget parent;

    These functions each create and return a new managed Athena Label, Command, Repeater or MenuButton widget, child of a new Box widget, in turn child of the passed parent widget. Both widgets (the requested widget and its surrounding box) will be called name.

    YCreateCommand and YCreateMenuButton also set the leftBitmap resource of the command or menu button widget to display an appropriate form of arrow.

    YCreateLabel is implemented as a macro.

Widget YCreateArrowButton(name, parent, direction)
       String name;
       Widget parent;
       YArrowDirection direction;

    Creates and returns a new managed surrounded Athena Repeater widget. The widget will display a single arrow pointing in the direction given by direction.

    The YArrowDirection type is defined as an enum of the elements YArrowLeft, YArrowRight, YArrowUp and YArrowDown.

Widget YCreateToggle(name, parent, callback)
       String name;
       Widget parent;
       XtCallbackProc callback;

    Creates and returns a new managed Toggle widget. This is not the Athena Toggle widget, but an Athena Command widget with a callback set; as such, it cannot be used as part of a radio group. The Toggle widget will begin in an unset state, and when it is clicked, its state will toggle and the function callback will be called. The client_data argument passed to callback will be a Boolean indicator of the Toggle's newly entered state.

Widget YCreateSurroundedWidget(name, class, parent, shade1, shade2)
       String name;
       WidgetClass class;
       Widget parent;
       YShade shade1, shade2;

    Creates and returns a widget, surrounded (as in YCreateLabel) by a Box widget. The widget may be of any class. The backgroundPixmap or background colour of the Box will be set according to shade1, and that of its child will be set according to shade2.

    YCreateSurroundedWidget is implemented as a macro.

  Resource Value Manipulation

YAWN includes two macros to assist with getting and setting X toolkit resources, plus a function to manipulate the state of the YAWN Toggle widget (see YCreateToggle above).

void YSetValue(widget, resource, value)
       Widget widget;
       String resource;
       XtArgVal value;

    Sets the resource resource on widget widget to value. It's lazier than using XtSetArg/XtSetValues, especially if you only want to set one resource value.

    YSetValue is implemented as a macro.

void YGetValue(widget, resource, value)
       Widget widget;
       String resource;
       XtArgVal value;

    Gets the value of the resource resource on widget widget, and stores it in the space pointed to by value. This is equivalent to using XtSetArg/XtGetValues for one resource value.

    YGetValue is implemented as a macro.

void YSetToggleValue(toggle, value)
Boolean YGetToggleValue(toggle)
       Widget toggle;
       Boolean value;

    Set and get the state of a Toggle (of the kind returned by YCreateToggle), respectively. The Toggle's visible window and internal records will be updated to reflect any change in state.

  Message Output

YAWN provides a limited capability for output of text intertwingled with font changing information. This is similar to a restricted form of X Compound Text, where only one font per line of text may be specified. This facility is most likely to be useful in displaying small amounts of static text, such as in an information or ``About'' box.

void YMessageInitialise(bitmap, basefont)
       Pixmap bitmap;
       String basefont;

    This function initialises the YAWN message boxes. It declares that the pixmap bitmap should be displayed in the top-left of any message box (or, if it is NULL, that no pixmap should be displayed), and that the font basefont should be used for displaying non-italic non-bold message texts (or, if NULL, that an ugly default should be chosen instead). Italic and bold fonts will be derived automatically, provided basefont is a valid XLFD descriptor and suitable fonts are available. If you require oblique (as opposed to italic) or demibold (as opposed to bold) fonts, you should declare the oblique/demibold version as the base font or it will not be found.

    You may call YMessageInitialise as many times as you like.

void YMessage(parent, name, label, text, number)
       Widget parent;
       String name, label;
       YMessageString *text;
       int number;

    Pops up an asynchronous, non-grabbing textual display window called name as a child of parent. If a non-NULL bitmap was supplied in the call to YMessageInitialise, it will be displayed in the top left of the window.

    If text is non-NULL, its contents will be displayed centrally in the window. These should be an array of number YMessageString structures, which are defined as -

            typedef struct _YMessageString {
                   String text;
                   Boolean bold;
                   Boolean italic;
            } YMessageString;

    Here the text field describes a line of text, which will be drawn centrally on a line on its own, either normally, or in bold, italic or bold-italic face. The latter are controlled by the bold and italic fields. To simplify initialising these structures, the special symbols YMessageNormal, YMessageBold, YMessageItalic and YMessageBoldItalic are provided: they expand into

                False,False
                 True,False
                False,True
                 True,True

    respectively, corresponding to the necessary field settings in the structure.

    The message window will also contain a confirmation button, which will be labelled label. The label argument may not be NULL.

  Querying the User

YAWN provides two mechanisms for synchronous user querying. The Xt/Athena toolkit and widgets offer no standard query synchronising mechanism: a query requires the use of a callback function to record the user's answer. The YAWN query functions block the calling program completely until the answer has been obtained, giving the result as the return value from the querying function. Although less flexible than the X toolkit approach, this is much simpler and frequently very useful.

int YQuery()

    This function pops up a query dialogue box to ask the user a question, and returns the user's answer.

    This is a variable argument-list function, written using the ``varargs'' macro set, which effectively takes arguments as follows:

    int YQuery(parent, message, buttons, default,
               cancel, label0, ..., helpTag)
           Widget parent;
           String message;
           Cardinal n;
           Cardinal default;
           Cardinal cancel;
           String label0 (...);
           String helpTag;

    parent is the widget to make the query box a child of; message is the text to display in the query label. The box will have n buttons, labelled label0 ... labeln. When the box is popped up, the X pointer will be warped to the button numbered default, unless default is -1.

    If the helpTag argument is non-NULL, the box will have a ``Help'' button, pressing which will invoke the helpCallback that was passed to the YInitialise function, passing it the helpTag.

    If message is NULL, there will be no message label in the query box.

    YQuery returns an integer indicating which of the buttons the user pressed, counting upwards from 0 as the leftmost. If for some reason it exited without a button's having been pressed, YQuery returns -1.

String YGetUserInput(parent, message, default, orientation, helpTag)
       Widget parent;
       String message;
       String default;
       YOrientation orientation;
       String helpTag;

    Pops up a dialogue box to ask the user a question and obtain an answer in the form of a string. The box contains a message label, displaying message (unless message is NULL, in which case no label will appear), a text input box, with default input string default (or with no default string if default is NULL), and Apply and Cancel buttons. If helpTag is non-NULL, there will also be a Help button; see YQuery above for details.

    If orientation is YOrientHorizontal, the box will be laid out horizontally, with the text input area to the right of the message area; if it is YOrientVertical, the arrangement will have the text area below the message area. Vertical orientation often looks good if a wide input is needed, and horizontal if a narrower one is needed.

    The function behaves synchronously: it blocks until the user has pressed either the Apply or Cancel button on the dialogue box. It returns the entered string, or NULL if the user pressed the Cancel button.

  Creating Modal Menus

YAWN supports the use of modal menus. These consist of Athena simple menus, with some functions to support modal behaviour. As YAWN provides a reasonably rich interface to the menu functionality, it should not be necessary to refer to the underlying Athena menus, and programmers should avoid doing so. There is no guarantee that YAWN will always construct its menus in the same way.

YMenuId YCreateMenu(menuButton, name, number, elements)
       Widget menuButton;
       String name;
       int number;
       YMenuElement *elements;

    Creates an Athena simple menu and returns an identifier for it. The arguments declare the button (of class menuButtonWidgetClass, such as that returned by YCreateMenuButton) which should call up the menu, the menu name (used for widget identification, but not displayed on the menu itself), the number of entries on the menu, and an array of YMenuElement structures defining the contents of the menu entries. This structure contains the following fields:

                String label;

    The label for the menu entry. If this is NULL, a dividing line will be drawn at this point instead of an entry. The special symbol YMenuDivider is provided, which expands to a whole line of NULL entries for a particularly convenient interface (see the example below).

                unsigned long insensitive_mode_mask;

    A mask indicating which menu modes should cause this menu to be greyed out. How you manage your menu modes is up to you: to YAWN, they are just bitmasks, and a menu item will be greyed out if its insensitive_mode_mask has one or more bits in common with the current mode mask. The latter is maintained by YAWN; it is initialised to 0L, and can be changed by calling YEnterMenuMode and YLeaveMenuMode.

                XtCallbackProc callback;

    A function to be called when this entry is selected by the user. It will receive as its client_data argument a pointer to this YMenuElement structure.

                Widget widget;

    The widget or gadget to be used to draw the menu entry. Applications should normally initialise this to NULL, and it will be filled in by YCreateMenu. If this field is non-NULL, it will not be overwritten. You may or may not find a use for this.

    As an example, given an array declared -

        YMenuElement fileMenu[] = {
          { "Load",         NullMask, FileMenuLoad, NULL, },
          { "Save", NoFileLoadedMask, FileMenuSave, NULL, },
          YMenuDivider,
          { "Exit",         NullMask, FileMenuExit, NULL, },
        ;

    where NullMask is presumably 0L - YAWN does not define this - and NoFileLoadedMask a value with a bit set somewhere, then a call such as

    fileMenuId = YCreateMenu(fileMenuButton, "File Menu",
                             XtNumber(fileMenu), fileMenu);

    would serve to create the menu, instantiate its gadgets and callbacks, and return an identifier for it. Subsequently, the ``Save'' menu option would only be available when the file menu was not in the ``NoFileLoadedMode'' mode (see the section below).

  Manipulating Modal Menus

Several functions not normally part of the Athena simple menu interface are provided to allow control of the YAWN menu modes:

void YEnterMenuMode(menu, mode)
void YLeaveMenuMode(menu, mode)
       YMenuId menu;
       unsigned long mode;

    Causes menu menu to enter or leave mode mode. In effect this sets or clears the bits marked by mode in the current mode mask maintained by YAWN for menu menu, and greys out or restores any affected menu entries in the menu identified by menu.

Boolean YQueryMenuMode(menu, mode)
       YMenuId menu;
       unsigned long mode;

    Determines whether a given menu is in a given mode. If one or more of the bits corresponding to mode are set in the menu's current mode mask, the function returns True; otherwise False.

Widget YGetMenuButtonFromMenu(menu)
       YMenuId menu;

    Returns the menu button widget associated with the given menu id.

void YDestroyMenu(menu)
       YMenuId menu;

    Destroys the given menu and frees any space allocated during the YCreateMenu call that created it. This also resets the widget field in each element of the menu's description record array to NULL.

  File Boxes

YAWN contains a set of powerful file-box facilities. These may be used whenever a program using YAWN requires to obtain the name of a file from the user for reading or writing. The file-box functions provide an extremely simple programmer interface, allowing file names or identifiers to be obtained with a single function call.

void YFileInitialise(directory, prefix, query, backup,
                     readLabel, writeLabel, appendLabel)
       String directory;
       Boolean query, backup;
       String readLabel, writeLabel, appendLabel;

    This function initialises the YAWN file management functions. It must be called before any of the other file functions.

    A call to YFileInitialise declares:

    - The default start-directory (directory) for file selection box listings;

    - Whether file selection boxes should check with the user before possibly overwriting files (query, True if they should check);

    - Whether backups should be made of files to be opened for writing (backup, True if they should - note that making backups of files which are not subsequently opened owing to any kind of file error is a destructive operation);

    - Labels for the Apply buttons on read, write and append file selection boxes (which all default to ``Apply''; you may well wish to set them to ``Load'', ``Save'' and ``Append'' or similar).

    You may call YFileInitialise as many times as you like.

String YFileGetReadFilename(parent, helpTag)
       Widget parent;
       String helpTag;

    Pops up a synchronous file selection box to obtain a filename for reading. The box will be a child of parent. The file will not be opened, but its name will be returned, or NULL if the user cancelled the operation. If helpTag is non-NULL, the box will contain a Help button which, when pressed, will invoke the helpCallback passed in to YInitialise, passing in helpTag as its argument.

String YFileGetWriteFilename(parent, helpTag)
String YFileGetAppendFilename(parent, helpTag)
       Widget parent;
       String helpTag;

    These pop up synchronous file selection boxes to obtain filenames for writing or appending. They differ from the YFileGetReadFilename box in that their filename fields are editable. The file will not be opened, but its name will be returned, or NULL if the user cancelled the operation. The helpTag argument is as for YFileGetReadFilename.

FILE *YFileGetReadFile(parent, helpTag)
FILE *YFileGetWriteFile(parent, helpTag)
FILE *YFileGetAppendFile(parent, helpTag)
       Widget parent;
       String helpTag;

    Pop up synchronous file selection boxes for reading, writing and appending, respectively. These functions differ from YFileGetReadFilename, YFileGetWriteFilename and YFileGetAppendFilename in that they open the files and return file pointers referring to the open files. (The files can be closed with a call to the standard library function fclose.) They return NULL if the user cancelled the operation. The helpTag argument is as for YFileGetReadFilename.

String YFileGetLastFilename(clip)
       Boolean clip;

    Returns a shared string naming the last file obtained for reading, writing or appending by YFileGetReadFile, YFileGetReadFilename and their friends. If the last call to any of these functions yielded a Cancel operation, YFileGetLastFilename will return NULL. If clip is True, YFileGetLastFilename will return only the final element of the file's path name (the actual name of the file); otherwise it will return the whole path name.

  Miscellaneous Convenience Functions

YAWN includes a few miscellaneous functions which may be of use in keeping the programmer's task of maintaining a clean look-and-feel as simple as possible.

Pixmap YCreatePixmapFromData(data, width, height, shade)
       String data;
       unsigned int width, height;
       YShade shade;

    Creates and returns an X pixmap of the same depth as the current display's default, of width width and height height, containing data data. The foreground and background colours of the pixmap will be chosen to fit in well with those of a YAWN-created widget of shade shade. This function behaves otherwise like XCreatePixmapFromBitmapData.

GC YCreateGC(mask, values, shade, clear)
       unsigned long mask;
       XGCValues *values;
       YShade shade;
       Boolean clear;

    Creates and returns a new X graphic context, using the values in values selected by mask, augmented by suitable foreground and background colours for use with a widget of shade shade. If clear is True, the foreground and background colours will be the same, and will both be that which would otherwise have been used for the background only.

XPoint YPushPointerPosition(void)
XPoint YPopPointerPosition(void)

    Record and restore the position of the X pointer on the screen. These may be useful if you wish to warp the pointer to a default button or list item, and then warp it back again.

    These functions deliberately do not use a stack mechanism: they only record the last pointer position. If you push the position several times, the first call to YPopPointerPosition will restore the last pushed position, and any subsequent YPopPointerPosition calls will be ignored. This is in order to avoid restoring the pointer to places that the user had completely forgotten it was ever at in the first place. It also means that push and pop calls need not be in pairs; there need not be a matching pop for each push, or push for each pop.

    Both functions return an XPoint structure recording the current position of the pointer over the root window. If the pointer query failed and no such position is available, the structure will contain zeroes. This should happen only rarely, if ever.

XPoint YPlaceAndPopup(shell, grab)
       Widget shell;
       XtGrabKind grab;

    Realizes and pops up the popup shell widget shell with the Xt grab kind grab. The shell will be positioned at a reasonable point on the screen (not left of or above its parent, nor off the edges of the screen, unless it is impossible to manage otherwise). YPlaceAndPopup also calls YPushPointerPosition, and returns the position of the X pointer.

FILES
YAWN requires no special files. However, for the best results, some care should be taken about the settings in the host program's X resource defaults file. One possible example set, with some rather dubious colour resources, is shown below.

       *borderWidth:                      1
       *highlightThickness:               1
       *SimpleMenu*lineWidth:             1
       *SimpleMenu*SmeLine.height:        2
       *yawn.mono.foreground:             black
       *yawn.mono.background:             white
       *yawn.noShade.foreground:          black
       *yawn.noShade.background:          peachpuff
       *yawn.lightShade.foreground:       black
       *yawn.lightShade.background:       maroon4
       *yawn.mediumShade.foreground:      gold2
       *yawn.mediumShade.background:      midnightblue
       *yawn.surroundShade.foreground:    black
       *yawn.surroundShade.background:    #e0b090

Care should also be taken with font settings, as the default font for many X displays (fixed) is an inordinately ugly one. A fair resource setting to start with might be:

       *font:   -*-lucida-bold-r-*-*-14-*-75-*-*-*-*-*

AUTHOR

Chris Cannam, ma0cc@ss1.bath.ac.uk at the University of Bath.