CHAPTER
8

Structured Code Generation and
Reusable Definitions

This chapter describes how Sun WorkShop Visual helps you to control the structure of the generated code. Being able to do this is essential for creating reusable widget hierarchies. These reusable hierarchies, known as definitions, appear on the widget palette and can be added to the hierarchy like any other widget. A detailed description of definitions also appears in this chapter.

Sun WorkShop Visual provides controls for structuring your generated code so that it is more flexible and can be reused more easily. Before reading this section, you should review the structure of the default generated code in Analysis of the Primary Module. In particular, note that the default code has a single creation procedure for each Shell in the design. Widgets are declared as local if they have not been named and global if they are named or are Application Shells.

The structured code controls let you:

Designate any widget in the hierarchy to have its own creation function that returns the widget, including its descendants

Designate any widget to have its own creation function that returns a structure containing the widget and its named descendants

Designate any widget to be defined as a C++ class with descendant widgets as members

Designate a widget as a place-holding container that serves only to house a collection of child widgets

Explicitly specify a widget as global, local, or static

Sun WorkShop Visual's controls for structuring code are located on the "Code generation" page of the Core resource panel.

The simplest case of structured code generation is to designate a widget as a function structure. This makes Sun WorkShop Visual generate a separate function that creates that widget and its descendants. This function is called by the creation procedure for the enclosing widget.

To do this, select the "Code generation" page of the Core resource panel and select "Function" from the "Structure" option menu.

FIGURE 8-1 Example: Structure

The hierarchy shown in Figure 8-1 produces the following generated code, slightly simplified for clarity:1

The next type of code structuring is the data structure. This is similar to a function structure, in that Sun WorkShop Visual generates a separate creation procedure for the widget and its descendants. When a widget is designated as a data structure, Sun WorkShop Visual also generates a typedef for a structure including that widget and its children. The creation procedure for the widget creates and sets up that type of structure and returns a pointer to it. A deletion function (delete_<widget_name>) is also generated so that the allocated memory can be freed.

To designate a widget as a data structure, select the "Code generation" page from the Core resource panel and select "Data structure" from the "Structure" option menu.

Using the same hierarchy as shown above, but with button_box designated as a data structure, the following code is produced, slightly simplified for clarity:2

/* First the type declarations are generated for the data structure. */

typedef struct button_box_s {

Widget button_box;

Widget b1;

} button_box_t, *button_box_p;

Widget shell = (Widget) NULL;

Widget form = (Widget) NULL;

button_box_p button_box = (button_box_p) NULL;

/* The creation procedure returns a pointer to a button_box structure. */

button_box_p create_button_box (Widget parent)

{

Widget children[1]; /* Children to manage */

button_box_p button_box = (button_box_p)NULL;

/* Space is allocated for the structure and the fields are filled in. */

The use of C++ classes is very similar to data structures. Sun WorkShop Visual does not wrap each widget in the hierarchy with a C++ class, but instead designates sections of the hierarchy as classes in their own right. Each widget designated as a C++ class has a class defined for it. Its named descendant widgets become members of that class and widget creation and widget destruction methods are supplied. In addition, if the class contains members that are themselves (pointers to) classes, a constructor and destructor method is generated to create and destroy these members. Note that the widgets are not created at the time of the class instance but by an explicit call to the widget creation function. Similarly, destroying the class instance does not destroy the widgets.

To designate a widget as a C++ class, select the "Code generation" page of the Core resource panel and select "C++/Java class" from the "Structure" option menu. Note that if you designate a widget as a C++ class, then generate C, the widget is treated as a data structure.

The C++ code generated from this example is shown below, simplified for clarity:3

Classes are declared for button_box and shell:

class button_box_c: public xd_XmRowColumn_c {

public:

virtual void create (Widget parent, char *widget_name =

NULL);

protected:

Widget button_box;

Widget b1;

Widget b2;

};

typedef button_box_c *button_box_p;

The shell class has constructor and destructor functions because it contains a pointer to class (or data structure) member:

class shell_c: public xd_XmDialog_c {

public:

virtual void create (Widget parent, char *widget_name =

NULL);

shell_c();

virtual ~shell_c();

protected:

Widget shell;

Widget form;

Widget text;

button_box_p button_box;

};

typedef shell_c *shell_p;

shell_p shell = (shell_p) NULL;

The creation function now becomes a method of the class. This method is declared public in the Sun WorkShop Visual base class, which is supplied with the release:

void button_box_c::create (Widget parent, char *widget_name)

{

Widget children[2]; /* Children to manage */

Arg al[64]; /* Arg List */

register int ac = 0; /* Arg Count */

if ( !widget_name )

widget_name = "button_box";

button_box = XmCreateRowColumn ( parent, widget_name,

al, ac );

_xd_rootwidget is a protected member of the class that stores the widget that is at the root of the sub-hierarchy. This lets the base class operate on the widget:

_xd_rootwidget = button_box;

b1 = XmCreatePushButton ( button_box, "b1", al, ac );

b2 = XmCreatePushButton ( button_box, "b2", al, ac );

children[ac++] = b1;

children[ac++] = b2;

XtManageChildren(children, ac);

ac = 0;

}

// The Shell's creation method calls that for the button box.

void shell_c::create (Widget parent, char *widget_name)

{

Widget children[2]; /* Children to manage */

Arg al[64]; /* Arg List */

register int ac = 0; /* Arg Count */

if ( !widget_name )

widget_name = "shell";

XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;

shell = XmCreateDialogShell ( parent, widget_name, al,

ac );

ac = 0;

_xd_rootwidget = shell;

XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;

form = XmCreateForm ( shell, "form", al, ac );

ac = 0;

text = XmCreateText ( form, "text", al, ac );

The button box class is instantiated in the constructor method and so at this point only the widgets need to be created:

button_box->create ( form, "button_box" );

XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET);

ac++;

XtSetArg(al[ac], XmNtopWidget,

button_box->xd_rootwidget()); ac++;

XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM);

ac++;

XtSetValues ( text,al, ac );

ac = 0;

XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM);

ac++;

XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM);

ac++;

XtSetValues ( button_box->xd_rootwidget(),al, ac );

ac = 0;

children[ac++] = text;

children[ac++] = button_box->xd_rootwidget();

XtManageChildren(children, ac);

ac = 0;

}

shell_c::shell_c()

{

Instantiate the child classes:

button_box = new button_box_c;

}

shell_c::~shell_c()

{

Free the child classes:

delete button_box;

}

If a widget is designated a C++ class and C code is generated, the widget is treated as if it were a data structure.

By default, the generated class is derived from one of the supplied Sun WorkShop Visual base classes. You can override this by specifying the base class in the field below the C++ Access option menu. The Sun WorkShop Visual base classes supplied with the release provide minimal support, sufficient for the generated code to execute correctly. You can modify and extend those classes to provide reusable methods that suit your approach to GUI development.

Descendant widgets appear as protected members of the class if they are named, or if they are themselves data structures or C++ classes. It is therefore important to name the C++ class widget itself and any of its descendants that you want to access as class members. You can alter the default access control by selecting the required level (Public, Protected, or Private) from the C++ Access option menu.

Using an unnamed widget for the C++ class widget itself does not cause an immediate error. However, this is not recommended as numbers assigned by Sun WorkShop Visual can change when you edit your hierarchy.

Callback Methods

The X toolkit functions which invoke callback functions expect a callback function in the following form:

void my_callback (Widget, XtPointer, XtPointer)

An ordinary member function is not suitable as a callback function because the C++ compiler passes it an extra first parameter - the this pointer - that lets it find the instance data for the object. If you use an ordinary member function as a callback function, the member function interprets the widget pointer as the instance data pointer and does not work as expected.

Sun WorkShop Visual uses a common technique to work around this. A static member function (which does not expect a this pointer) is declared and used as the callback function:

The client data parameter is used to pass in a pointer to the instance. The static member function merely calls an ordinary non-static member function using that instance pointer and passes on the widget and call data parameters. The non-static member function has the following form:

virtual void my_callback (Widget, XtPointer call_data)

Sun WorkShop Visual generates both function declarations, all the code for the static callback function and a stub for the regular member function which is written by you. Note, because this function is declared as virtual, you can override it in a derived class to modify the behavior. For a discussion of this technique, see "Object-Oriented Programming with C++ and OSF/Motif" by Douglas Young.

Editing Callback Methods

When you add a callback method, Sun WorkShop Visual also adds a declaration for the method (if it has not already been declared). Pressing the "Methods" button in the Callbacks dialog shows you a list of the methods declared in the enclosing class of the currently selected widget.

By default, Sun WorkShop Visual declares methods as not pure virtual and with public access. If these attributes are not as you intended, use the Method Declarations dialog to change them. See Method Declarations for details.

To find which widget is the enclosing class, use "Structure colors" from the "View" menu, as described in Structure Colors, and select the nearest ancestor of the widget for which you have added a method. Of course, this would be the same widget if it is defined as a C++ class.

Method Access Control

By default, methods added by Sun WorkShop Visual have public access. You can control the access for individual callback methods using the "Access" option menu in the Method Declarations dialog.

Pure Virtual Methods

You can set the "Pure virtual" toggle to declare the non-static member function as pure virtual. For example, if you set this toggle for a callback method OnNew() in a menubar class, Sun WorkShop Visual would declare the method as:

class menubar_c: public xd_XmMenuBar_c {

...

public:

...

virtual void OnNew( Widget, XtPointer ) = 0;

};

Because the function is pure virtual, you do not have to provide an implementation of menubar_c::OnNew() andmenubar_c becomes an abstract class. That is, you cannot create an instance of menubar_c but only use it as a base class for others.

By default, methods added by Sun WorkShop Visual are not pure virtual.

Deleting Callback Methods

When you remove a callback method from a widget you are only removing the use of the method (the call to it). When you add a method callback in Sun WorkShop Visual, a declaration of the method is automatically added for you. If you want to remove this declaration as well you must remove it from the method declarations list of the widget which is the enclosing class. See Method Declarations for more information on how to do this and for information on the declaration added by Sun WorkShop Visual.

Changing the Structure and Invalidating Methods

When a callback method is added, the method is declared in the enclosing class, as described above. If you change the structure of this widget (the enclosing class) so that it is no longer a class, the method becomes invalid. To help you when this happens, Sun WorkShop Visual displays the Invalidated Methods dialog, shown in Figure 8-4.

This dialog is modal - you can not continue working on your design until it is closed. It is only ever displayed when you change a widget's structure in such a way that method declarations are made invalid.

FIGURE 8-4 Invalidated Methods Dialog

The Widget list on the left shows all the widgets with methods which are invalidated by changing the structure. When you select a widget any invalidated methods are listed on the right. For each selected method, this dialog shows you the class in which it is currently declared and suggests a new class for the declaration of your method. The "Proposed Class" is always the nearest ancestor class. If there is no other suitable class, this dialog serves as a warning that the method will become a function.

Pressing "Declare" changes the declaration of the selected method to the "Proposed Class". Pressing "Declare All" changes each invalidated method to its respective "Proposed Class".

You can add additional data or function members to a C++ class using the "Code preludes" dialog. Select "Public methods", "Protected methods", or "Private methods" and type your declarations into the text area (or into the code if you are editing in place). C++ code preludes are generated into the class declaration, both in the primary module and in the Externs file.

To add a function to a class it is often better to write a new class derived from the generated class. The logical gap between the subclass and generated base class can be used to add members and provide implementations for virtual functions.

By default, Sun WorkShop Visual derives the name of a C++ class from the variable name of the root widget and so the class for the widget menubar is menubar_c:

class menubar_c: public xd_XmMenuBar_c {

...

};

When Sun WorkShop Visual generates code to create an instance of the class, it uses the same name:

menubar = new menubar_c;

You can change the default behavior so that Sun WorkShop Visual declares the generated class under one name and creates the instance under another. For example:

menubar = new mymenubar_c;

To make this change, use the "Instantiate as" field on the Code Generation page of the Core resource panel.

By default, Sun WorkShop Visual derives a generated class from a base class appropriate to the type of the root widget. For example, a class with a MenuBar at the root of its widget hierarchy is derived from xd_XmMenuBar_c. The name of the base class can be changed in the Core resource panel.

The Sun WorkShop Visual distribution contains a sample implementation of a set of base classes. These can be used as they stand or modified to add extra functionality appropriate to a particular application area.

A Makefile is included to build the sample base classes. Sun WorkShop Visual makes two assumptions about the base classes:

There is a data member _xd_rootwidget of type Widget.

There is an accessor function xd_rootwidget() that returns the value of _xd_rootwidget to be retrieved.

These assumptions, together with a few items of basic class restrictions, are encapsulated in the class xd_base_c:

class xd_base_c

{

public:

xd_base_c() {_xd_rootwidget=NULL;}

Widget xd_rootwidget() const {return _xd_rootwidget;}

protected:

Widget _xd_rootwidget;

private:

void operator=(xd_base_c&); // No assignment

xd_base_c(xd_base_c&); // No default copy

};

Sun WorkShop Visual places no other constraints on the base classes used. In other words, any set of base classes can be used provided that they are derived from xd_base_c (or another base class that satisfies Sun WorkShop Visual's assumptions).

Note that actual parameters for the base class constructor can be supplied with the class name. If parameters are supplied (if the base class string contains a '()', the class is forced to have a constructor and the parameter string is passed to the base class. For example, setting the "Base class" string to mymenubar_c ("Hello World") for the widget menubar will cause Sun WorkShop Visual to generate:

The Children Only structure option lets you designate one widget (the Children Only widget) as a container structure for another structure. Children Only widgets provide context for their descendants in the hierarchy, but no code is generated for them. Consider the following example:

FIGURE 8-5 Use of Children Only Structure

When you generate code from the design shown in Figure 8-5, Sun WorkShop Visual produces code for the pulldown menu structure only. This feature lets you generate fragments of the design that can be controlled by your application program.

Note - If you specify a widget as "children only", code is only generated for children which are structured or named. Therefore, if all you have underneath a "children only" widget is unstructured and unnamed widgets, then all you will see in the code is Widget declarations.

Children Only Structure in Microsoft Windows Mode

When you are in Microsoft Windows mode, you cannot make the child of a shell a C++ class. To overcome this, so that you can create a hierarchy with a "children only" shell, add a "dummy" container (a rowcolumn or form widget) beneath the shell and then make the container beneath that a C++ class. This would also be useful for creating definitions in Microsoft Windows mode, where the root widget must be structured but the child of the shell cannot be.

When generating UIL for a design that contains structures of some kind, the approach is basically similar to that for C and C++. Independent hierarchies are generated into the UIL file and separate creation functions are generated into the code file. The creation function fetches the appropriate widgets from the UIL hierarchy and fills in the data structure fields as appropriate.

Widgets are normally declared locally in the enclosing creation function unless they are structured in some way, or named. In this case they are declared in the enclosing structure if there is one, or as global variables. This default behavior can be modified by setting the storage class of a widget in the Core resource panel. Setting the storage class to Local forces a widget that would otherwise be declared globally or within a structure to be local to the creation function. Setting the storage class to Global forces an unnamed widget or a named element of a structure to be global. Global status is especially useful for widget-type resources and links as discussed in Unreachable Widgets. The Static option is similar to Global but the declaration is static to the module.

There is no way to force an unnamed widget into a data structure. Unnamed children of a data structure widget are created and managed locally to the data structure's creation procedure.

Unreachable Widgets

When you use the structured code generation in conjunction with widget-type resources such as XmNdefaultButton for a BulletinBoard, you could specify designs that reference widgets that are not in scope. These are considered unreachable widgets. Sun WorkShop Visual attempts to detect these cases and warns you at code generation time. Also, if you use unreachable widgets in conjunction with Children Only structures or dynamic run-time creation of hierarchies, unexpected failures may result.

FIGURE 8-6 Hierarchy with Unreachable Widgets

An unreachable widget is illustrated in Figure 8-6. b1 must be available to the Form's creation function so that it can be used as the default button argument. However, since b1 is local to the button_box function, it is not in scope in the Form's creation function. Sun WorkShop Visual detects this situation and displays the following warning at code generation time.

FIGURE 8-7 Unreachable Widget Error

Code is still generated but it may not compile or run as expected. The simplest solution to this is to force the appropriate widget to be global by using the Storage Class option.

Once a hierarchy of widgets has been encapsulated as a structure (either a C++ class or a C structure), you can re-use it in other designs by turning it into a definition. A definition is a reusable hierarchy of widgets which is added to the Sun WorkShop Visual widget palette. Selecting a definition from the palette creates an instance of the definition in the design. This instance can be further modified and in turn be made into a definition.

Prerequisites

A widget hierarchy can become a definition provided that:

1.

The root widget has a non-default variable name.

2.

The root widget has been designated as a C++ class or a structure.

3.

The root widget is not part of another definition.

4.

The widget hierarchy does not contain a definition.

5.

The widget hierarchy does not contain any global or static widgets.

Designating a Definition

Designating a definition requires that the design file containing the widget is saved and the widget marked in it as being a definition. To mark the widget as a definition use the Definition toggle in the Widget menu. Creating a definition freezes the widgets within it. Their resource panels are disabled and you cannot add widgets or change widget names. You can edit the widgets that make up a definition only by temporarily removing the definition status. This should be done with caution to avoid conflicts with designs that use the definition. For details, see Modifying a Definition.

To make the definition available for use in other designs Sun WorkShop Visual needs an external reference to it. This is provided by means of a definitions file which is edited using the Edit Definitions dialog.

Definition Shortcut

The "Define" button in the Palette Menu is a quick way of adding a new definition. It designates the currently selected widget as a definition, saves the design and adds the definition to the palette. The header filename for the definition is taken from the type declarations filename in the code generation dialog. No icon is used.

The definitions file is read by Sun WorkShop Visual to establish the set of definitions which are to appear on the palette. The definitions filename is specified by setting the definitionsFileName resource. The default value is $HOME/.xddefinitionsrc.

If you need to work on multiple projects, each of which uses a different set of definitions, you can change the definitions file by setting the resource. For example:

visu.definitionsFileName:/home/project6/xddefs

The value of this resource can include environment variables:

visu.definitionsFileName:$PROJECT_ROOT/xddefs

To change to the new setting, exit and restart Sun WorkShop Visual.

Editing the Definitions File

To modify the definitions file use the Edit Definitions button in the Palette menu.

You can use this dialog to add a new definition, delete a definition, or edit an existing definition. To add a definition, you must supply:

Definition - A definition name

Widget name - The variable name of the root widget of the definition

Save file - The name of a saved design file (.xd)

You can also specify:

Icon resource - A resource name which will be used to locate the pixmap file for the definition. See Specifying the Icon File for further details

Icon file - A file containing a bitmap or xpm pixmap to be used as the palette icon if one is not found using the Icon resource

Include file - The name of the header file that declares the corresponding structure or class. This file is automatically #included in generated code when instances of the definition are used, therefore you will have to make sure that the compiler can locate it. It must be the same name as the externs file generated from the definition

Resource file - The name of the resource file which contains values for the definition. It is included in the generated resource file when instances of the definition are used. It should correspond to the name specified when the resource file was generated for the definition

Family - The family, or group, to which this definition belongs. This is only relevant to the display of definitions on the widget palette. Definitions are grouped together in families. One family is displayed at any given time. You can change which family is displayed by selecting from the option menu above the definitions on the widget palette. By default, definitions are assigned to the "Default" family. You can specify any name for a family. You can also group any number of definitions in the same family

Help information - A document and tag pair which can be used to provide help to users. See Online Help for Definitions for more details

MFC Offset - This field is only present when Sun WorkShop Visual is in Microsoft Windows mode. In Microsoft Windows applications controls are given a unique number by which they are identified. Sun WorkShop Visual attempts to generate unique numbers and in most circumstances there will not be a problem. However when adding widgets to an instance which has a very large number of controls already, it is possible for the numbers to overlap. The MFC offset is added to the id of a control which is being added to an instance. By increasing this number you can make sure that the control's id does not clash with any of the controls in the definition

Attributes not set at creation time can be set later. For example, you can test and debug a definition before designing its icon.

You can use the "Prime" button to fill in several of the fields for the currently selected widget.

Base Directory

If a definition is specified with a relative file name (a name that does not start with /), Sun WorkShop Visual adds the base directory to the front of the file name. If a base directory is not specified, the directory that contains the definitions design file is used.

To specify a base directory, display the Edit Definitions dialog, click on "Base Directory", select a new directory and click on "Apply". The new base directory is saved in your definitions file and is immediately used in the current session of Sun WorkShop Visual. The base directory cannot be changed if the current design contains instances of existing definitions.

Widgets in the definition are frozen. You cannot add or delete widgets, rename them, set constraints on them in the layout editor, or reset resources. To modify a definition, you must temporarily undefine it. When you need to modify a definition, use the following steps:

1.

Open the save file that contains the definition.

2.

Select the root widget of the definition.

3.

Pull down the Widget Menu and turn off the "Definition" toggle.

Turning off the toggle unfreezes the widgets in the definition so you can make any necessary changes. After making your edits:

4.

Select the root widget and set the "Definition" toggle on again.

5.

Regenerate the code file and externs file.

6.

Save the design.

Impact of Modifying a Definition

Changing a definition affects every design file that uses it. Each time you open a design that uses a definition, Sun WorkShop Visual also opens the file that contains the definition and merges information from the two files. If the definition has been modified, Sun WorkShop Visual tries to reconcile the new definition with the design that uses the old version of it.

If any changes cannot be reconciled, Sun WorkShop Visual displays an error message and saves any irreconcilable parts of the design in temporary Sun WorkShop Visual clipboard files. At this stage there are several ways to proceed:

Paste the clipboard file into your design and manually resolve its contents with the new definition

Discard the clipboard file contents altogether

Exit from Sun WorkShop Visual without saving and modify or revert the definition so that it is compatible with the designs that use it

To minimize the risk of incompatibilities:

Avoid changing the names of widgets in the definition

Replace a widget in the definition only with a subclass widget of the same name. For example, replacing a Label "foo" with a PushButton "foo" is normally safe

Definitions are grouped together on the widget palette according to their family. An option menu above the definitions on the widget palette allows you to change which family is currently displayed. See Editing the Definitions File for details on specifying a definition's family.

Modifying and Extending an Instance

Creating an instance of a definition corresponds to creating an instance of the structure (either a C structure or a C++ class). You can modify an instance after you have created it provided that the modifications can be reflected in the generated code. For example, you can set resources on widgets or add children to widgets only if they are accessible (i.e. if they are named and, for C++, they have an appropriate access mode). You cannot remove widgets or change their names. The root widget is an exception. Because the root widget of the instance is always accessible (through the member function xd_rootwidget()), it can always be modified.

Note - You cannot move a widget in the layout editor, or specify constraints for it, unless it is accessible.

Creating a Derived Structure

It is frequently useful to create a new structure that is derived from the definition. To do this simply set the Structure option on the Code generation page of the Core resources dialog. The derived structure can only be set to the same value as the definition, e.g. it is not possible to derive a C++ class from a C structure.

Overriding a Definition Callback Method

Inherited methods from definitions can be overridden in the instance so that the instance has different behavior from that specified in the definition.

Compiling Code Containing an Instance

To compile code generated from a design containing an instance of a definition, you need to link in the definition code too. There are two ways to do this:

1.

Link in a library containing the definition code

2.

Compile the definition code and the instance code together

These are explained separately below.

Using a Library

To link a library containing the definition code in with the instance code, first compile the code for the definition into a library. Usually, on UNIX and using C or C++, this is done in the following way:

make <definitioncode>.o

ar r <definitionlib>.a <definitioncode>.o

You then need to edit your Makefile for the code containing the instance so that:

1.

The compiler can locate the header file for the definition. Sun WorkShop Visual automatically #includes this header file into the code generated for the instance.

2.

The linker can locate the library containing the definition code. Simply add the full pathname of the library to "EXTRALIBS".

Compiling the Definition with the Instance

Another way of compiling the instance of a definition involves generating the definition, the instance of it and a corresponding Makefile into the same directory. You can tell Sun WorkShop Visual to configure the Makefile so that the definition and instance can both be compiled into the same application. The following instructions show you how to do this.

Resource values for widgets that are components of definitions can be either hard-coded or specified in resource files.

Instances and Definition Resource Files

When you specify a resource file for a definition, Sun WorkShop Visual #includes that file in the resource file for any design that contains an instance of the definition. The Xlib mechanisms that read the resource file interpret this directive and use it to find the resource file for the definition.

To record information about a definition and communicate with other developers who are using it, you can provide online help for definitions. The online help is accessed in the Sun WorkShop Visual interface by using the <Tab> and arrow keys to get to the icon or button for the definition, then pressing the <osfHelp> key (usually <F1>).

Help files are stored in subdirectories of the Sun WorkShop Visual help directory. The help directory is determined by the helpDir resource. By default, it is

$VISUROOT/lib/locale/${LANG}/help

where VISUROOT is the path to the Sun WorkShop Visual installation root directory and LANG is the name of your locale (default C).

Text Help Documents

Text help documents are in HTML format. The name of the file is formed by concatenating the document name and marker name. These are joined using the value of the visu.userHelpCatString resource. By default this resource is set to "." The file is then given a ".html" suffix. Sun WorkShop Visual looks for this file in the UserDocs subdirectory of the Sun WorkShop Visual help directory.

1
The comments describing the functions and procedures are not generated.

2
The comments describing the functions and procedures are not generated.

3
The comments describing the functions and procedures are not generated.