Previous Next Contents Index Doc Set Home


Generating Code

7



7.1 Introduction

Up to this point, you have used the interactive features of WorkShop Visual to build a working prototype of a user interface. Now you can use the code generation features to produce the files necessary to convert that design into a free-standing program. Code can be generated as C, C++, or UIL.

In this chapter, you will:

This chapter also includes an analysis of the code which is generated into the various files and a discussion of strategies for arranging your files.

Prerequisites
You need some knowledge of C, C++, or UIL to understand the generated code files and to supply code for callback functions. You also need some knowledge of the X Window System.


7.2 The Generate Menu

The Generate Menu is used to generate source code, X resource files and Makefiles from your design. The Generate Menu has six items: "C", "C++", "UIL", "X Resources", "Makefile" and "Generate". The first five options generate the type of file selected provided that you have set up that file in the Generate dialog.

The "Generate" option displays the Generate dialog.


Note - In Microsoft Windows mode the Generate Menu has an additional selection to generate Microsoft Windows resource files. This is discussed in the Building the Application section on page 11-378 of the Cross Platform Tutorial chapter.
C is used for the examples in this chapter. The procedure for generating C++ is exactly the same and you may use C++ for the tutorial if you prefer. The procedure for UIL is very similar to the procedure for C with the exception of one additional step which is discussed in the Setting the Language section on page 222.


7.3 Generate Dialog

To display the Generate dialog, pull down the Generate menu and select "Generate".

Figure  7-1 Generate dialog
This dialog gives you an overview of all the files which can be generated from your design. The dialog contains some default settings, including default filenames. The default filename is appropriate to the type of file and the language being generated. You can change the defaults in the application resource file. See the Filters section on page 723 for more details.

7.3.1 Setting up the Dialog

Before setting up individual files to be generated, you need to set two options which affect all the files:

7.3.2 Setting the Language

For the language, use the "Language" option menu at the top of the dialog. You have a choice of C, C++ and UIL. When in Microsoft Windows mode, you have the additional choices "C++ (Motif XP)" and "C++ (Microsoft Windows MFC)". See Chapter 10, "Cross Platform Development" for more details about Microsoft Windows mode, Motif XP and MFC. This tutorial uses the C language, so:

   Make sure that "C" is selected from the "Language" option menu.

Special Notes for UIL

When you work in UIL, the code generation procedure is basically the same as for C. However, because UIL is not as powerful a language as C, there are some features of WorkShop Visual which cannot be implemented in UIL. To get the full functionality of your design, a supplementary C file must be generated in addition to your UIL file.

When you select "UIL" from the Language option menu, enter the name of the UIL file in the "UIL" field and the name of the supplementary C file in the "Code" field. You must also specify a name for the compiled UIL file. This is done by pressing the Code "Options" button and then entering the name in the "Uid file" field.

"Includes" (see the Setting up the Primary Source File section on page 223), "Main program", and "Links" (see the Code Generation Options section on page 232) can be generated into the C file but not into the UIL.

UIL is a Motif-specific language and does not work with widgets outside the Motif toolkit. If your design contains a widget from another toolkit, you must use C or C++.

7.3.3 Setting the Base Directory

To set the base directory you can type it directly into the text box labelled "Directory" or you can press the "Browse" button. The "Browse" button displays a file selection box so that you can find and select a directory. The filenames of the files to be generated are relative to the base directory. By default, the base directory is the directory from which you last opened a saved design or, if you are working on a new design, the directory from which you invoked WorkShop Visual. The default, which is shown enclosed in brackets, is not saved into your ".xd" file. An explicitly named directory will be saved.

You can type an absolute pathname into the filename text boxes. This method is not recommended because you would have to do this for every file. It is easier and less prone to typing mistakes if you set up the directory first and assume all files are relative to that directory.

7.3.4 Setting up the Primary Source File

In the text box labelled "Code", enter the filename of your primary source file. A description and explanation of this file is given in the Analysis of the Primary Module section on page 244.

1. Type: icecream.c into the text box labelled "Code".

By convention, all C files, including primary source files and stubs files, have the suffix .c.

2. Check that the "Generate" toggle next to the text box is set.

Only those files which have the "Generate" toggle set will be generated.

3. Press the button labelled "Options" beside the "Code" filename.

This button displays the options relevant to the primary source file.

Figure  7-2 Primary Source File Options Dialog
The Options Dialog for the primary source file offers the following:


Note - If you generate a separate code and main program file, you must include the generated externs file so that both files can use the same variables.

4. Press "Ok" to close the Options dialog.

5. Press "Apply" in the Generate dialog.

This will save everything you have set up without generating straight away.

Notes on Including a Header File

If you are generating an Externs file for your design (see the Setting up the Externs File section on page 226), you would normally type the name of the externs file in the text box labelled "Include Header File" in the Code Options dialog. Your source file is then generated with a line like this at the top:

#include "NameOfFile.h"
By default, the header file is contained within quotation marks (`"` and `"') but you may use angle brackets (`<' and `>') if you prefer. For example, to change the line shown above you would type <NameOfFile.h> in the "Include Header File" text box. The following line would then be generated:

#include <NameOfFile.h>
If you wish to include both an external header file (not created by WorkShop Visual) and an Externs file created by WorkShop Visual in your code file, you can enter the name of the external header file in the "Include Header File" field and then make sure that this header file includes the Externs file generated by WorkShop Visual.

When you set the "Include Header File" toggle in the Code Options dialog and enter the name of the externs file, the file is included in the code file, the stubs file (if you are generating one) and the main program file (if it is different from the code file).

If you are generating a separate code and main program file, you must include the externs file because they both use variables which are defined in the externs file.

7.3.5 Setting up the Stubs File

Callback stubs, i.e. "empty" routines with the specified callback or method name, are generated for all callbacks and callback methods in your design. These are generated into a separate source file called a Stubs File. If you have callbacks or methods in your design, generating a stubs file allows you to compile the application since the callbacks are referenced from the main source code. It is left to you, however, to add the required functionality to the callback routines. You are shown how to do this in the Adding Callback Functionality section on page 239.

Along with the callback stubs, WorkShop Visual generates special comments. These comments are explained in the Stubs File Comments section on page 243.

Your design has just one callback: quit(). For now, generate a stubs file with an empty quit() function. The dummy function lets you compile, link and run your application as a prototype. Later (in the Adding Callback Functionality section on page 239), you will add functionality to quit() to complete your application.

1. Type: stubs.c in the text box labelled "Stubs".

2. Set the "Generate" toggle next to the text box.

Remember that only those files with a selected "Generate" toggle will be generated.

There are no separate options for the Stubs file.

7.3.6 Setting up the Externs File

WorkShop Visual can generate a header file with extern declarations for all widgets which are global in scope, C++ class definitions and C structure definitions for your design. Global widgets include all widgets which you have explicitly named and those which you have designated as global on the Core resource panel.

To set up an Externs file, type the name of the file in the text box labelled "Externs" and set the "Generate" toggle next to it. By convention, Externs files have the suffix .h.

   Make sure that the "Generate" toggle next to the text box labelled "Externs" is not set because you do not need an externs file for the tutorial.
To include the generated Externs file in your primary module, see the description of the Options dialog in the Setting up the Primary Source File section on page 223. WorkShop Visual then generates a #include directive instead of explicit type definitions in the primary source file. Global widgets are still allocated in the main source file when you do this.

The Externs file is also useful for including in your stubs file or other code files where you access global widgets or refer to type definitions. See the Global Widget Variables section on page 196 for more details.

There are no separate options for the Externs file.

7.3.7 Setting up the Pixmaps File

The Pixmaps file is similar to the Externs file. It is a header file with static declarations of all the pixmaps in your design. Generating one of these files lets you keep the cumbersome definitions of pixmap structures separate from your primary source file.

To generate a Pixmaps file, type the name of the file into the text box labelled "Pixmaps" and set the corresponding "Generate" toggle. By convention, Pixmaps files have the suffix .h.

   Make sure that the "Generate" toggle next to the text box labelled "Pixmaps" is not set because you do not need a pixmaps file for the tutorial.

7.3.8 Setting up the Main Program File

The main program file is a file containing the main() procedure. By generating a separate file you can keep this procedure away from the rest of your source code. This is useful if you need to edit the procedure to perform some of your own initializations or call other parts of your application before starting off the user interface. If you edit this file, make sure that you generate it only once as subsequent generations will overwrite your changes. A full description of the main() procedure is provided in the Description of the Main Program section on page 248.

If you wish the main() procedure to be generated into the primary source file, make sure that the text box labelled "Main program" contains the same name as the "Code" text box and the corresponding "Generate" toggle is set.

For the tutorial:

1. Check that the base directory is set.

See the Setting the Base Directory section on page 222.

2. Type: icecream.c into the text box labelled "Main Program".

3. Check that the "Generate" toggle next to the "Main Program" text box is set.

There are no separate options for this file.

7.3.9 Setting up the X Resource File

As you have seen in Chapter 3, "Resources", resource settings need to be available or they are not applied when your interface runs. You can make them available in one of two places: the primary source file or the X resource file. Generating resources into the source file is known as hard-wiring them.

1. Check that the base directory is set. See the Setting the Base Directory section on page 222.

2. Type into the text box labelled "X resources" the filename: icecream.res

3. Set the "Generate" toggle next to the text box.

You can control which resources are generated and into which file by setting the options described in the Code Generation Options section on page 232.

Making X Find Your Resource File

X does not automatically recognize icecream.res as your application's resource file. One recommended method of telling X where to find this file is to copy the resource file to the designated application resource directory (/usr/lib/X11/app-defaults on POSIX systems). The filename in that directory should be the application class name, XDTutorial, without a suffix (see the Code Generation Options section on page 232 for details on how to set the application class name). This method avoids any confusion of this application-specific resource file with other files you might be using.

Because you may not have access permission to the application resource directory, a different method is described here.

4. Set the environment variable XENVIRONMENT to the filename of the resource file.

The exact syntax for doing this will differ depending on which shell you are using. For a C shell, enter:

setenv XENVIRONMENT icecream.res

For a Bourne shell, enter:

XENVIRONMENT=icecream.res; export XENVIRONMENT 
There are other ways to get X to recognize your X resource file. To find out what they are, you will need to look them up in a book about the X Window System. See Appendix D, "Further Reading" for the names of some books you may wish to try.

7.3.10 Setting up the Makefile

WorkShop Visual can generate a makefile containing compilation instructions for all the files required by your design with the correct dependencies. For the tutorial, your makefile needs to compile both icecream.c and stubs.c. It also needs to link the resulting object files with the required libraries.

1. Check that the base directory is set to the directory where your primary source file and stubs file have been or will be generated.

2. Type "Makefile" into the text box labelled "Makefile" and check that the "Generate" toggle is set.

The Makefile Template

In order to generate a makefile, WorkShop Visual uses an internal makefile template.

For more details on makefile generation and customization in general see Chapter 15, "Makefile Generation", starting on page 525. For information on makefile configuration see the Makefile Template section on page 623. For details on how to change the makefile template application resource, see the Generation section on page 726 in Appendix , "Application Defaults".

Makefile Generation Options

Pressing the button labelled "Options" beside the makefile text box produces the dialog shown in Figure 7-3.

Figure  7-3 Makefile Options Dialog
The dialog contains three toggles labelled "New Makefile", "Makefile Template" and "Debugging". The latter option simply adds the "-g" flag to the list of flags to be sent to the compiler so that you can build a version of your application for debugging.

"New Makefile" and "Makefile Template" relate to the two different types of makefile that you can generate: a simple makefile and a makefile with templates. Which one is generated depends on the way in which the toggles in this dialog are set. The two toggles work in conjunction with one another. There are four ways they can be set:

1. The "New Makefile" toggle is set and the "Makefile Template" toggle is not set.

This generates a simple Makefile. You would use this option if you do not wish to add other design files to the application which the makefile will build.

2. Both toggles are set.

This generates a makefile with templates - i.e. with structured comments which serve as templates for updating the file on subsequent generations. Use this option if you are going to add other design files to the application which the makefile will build.

3. The "New Makefile" toggle is not set and the "Makefile Template" toggle is set.

This will add the current design code files to the Makefile which was generated as described in number 2 above.

4. Neither toggle is set.

This works in exactly the same way as number 3 above.

   For the tutorial, set the "New Makefile" toggle but do not set the "Makefile Template" toggle.

You are not going to add any more source files to the tutorial application so you do not need the template comments.

There are a few points to bear in mind when generating a makefile:

7.3.11 Code Generation Options

Before generating any files, you should check to see whether you need to change any of the code generation options. Press the "Options" button at the bottom of the Generate dialog. The dialog in Figure 7-4 appears.

Figure  7-4 Generate Options Dialog
This dialog lets you control where, and whether, the code for links is generated, specify the application class name and control where individual resource types should be generated. These are explained separately below.

Application Class Name

The application class name is used to identify resource settings when you generate an X resource file. Assigning a name other than the default "XApplication" prevents confusion of your resource values with system-wide X resources.

Links Code Generation

Using the option menu labelled "Links", you can choose whether the links are generated into the primary source file, into the stubs file or not generated at all. Alternatively, you could choose to generate the links code declarations only.

The code created as part of the links functionality consists of a set of generic functions (one for each type of link) and the declarations of these functions. Because the functions are always the same, you only need to generate one set of the functions for your whole application. If you are generating code from more than one design, each of which contains links, you only need to generate the functions once but you will need to generate the declarations for each design. The declarations are always generated into the primary source file.

Comment Preludes

This option menu refers to the special comments which appear in the generated code around the areas where preludes can be added. Adding preludes is described in the Customizing the Generated Files: Preludes section on page 254. You can choose whether you wish comments to be added "Always" (whether a prelude has been specified or not), "When Defined" (i.e. only when a prelude has been specified) or "Never". The default is "Never".

The example below shows a comment for a shell pre-manage prelude. Because there is no prelude inside the comment we must assume that "Always" was the selected option:

	/* visu: prelude for shell1: pre-manage >>> */

	/* <<< pre-manage ends. */
	XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
	shell1 = XmCreateDialogShell ( parent, "shell1", al, ac );
	ac = 0;
	/* visu: prelude for form1: pre-create >>> */

	/* <<< pre-create ends. */
	XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
	form1 = XmCreateForm ( shell1, "form1", al, ac );

Control of Resources

The panel in the middle of the Options dialog contains references to each type of resource.

Motif defines the following resource types:

You can specify into which file each resource type should be generated. If a resource is generated into the source code it is then hard-coded and cannot be modified through the resource file. Typically, any resources which are not generated into the source code are generated into the X resource file, where they can be edited by the end user. See the Setting up the X Resource File section on page 228 for more details on X resource files.

The option menu labelled "Callbacks" differs from the others. This is only used for UIL and lets you choose whether callbacks are registered in the UIL code or the C code. By default, they are registered in the UIL. If you use client data, however, you should generate the callbacks into the C code, because structure types cannot be defined in UIL. See the Setting the Language section on page 222 for an explanation of the C for UIL file.

For the tutorial, make the following changes in the Generate Options Dialog:

1. Select "Generated to code" from the "Links" option menu.

2. In the "Application Class Name" text box type: XDTutorial

3. Make sure that the resource type option menus are set as shown in Figure 7-5.

4. Make sure that the "Mask widget resources" radio button is on.

The significance of this radio button is discussed in the Masking Resources section below.

5. Click on "Apply".

Figure  7-5 Resource Settings for Code Generation

7.3.12 Masking Resources

If you look at any resource panel, you will see that it contains unlabeled toggles next to each resource, as shown in Figure 7-6.

Figure  7-6 Resource Panel Masking Toggles
These work in combination with the "Mask widget resources" and "Mask only global resources" radio buttons in the Generate Options dialog. Using these gives you control over the generation of resources on an individual basis.

Mask Widget Resources

The following description applies when the "Mask widget resources" toggle is set:

If an individual resource does not have its resource panel toggle set, the resource is generated according to the option menu for its type in the Generate dialog - i.e. a Label string with the resource panel toggle off will be generated to the file specified by the option menu labelled "Strings".

If an individual resource does have its resource panel toggle set, the resource is generated to the opposite file from the one specified for its type by the option menu in the Generate dialog - i.e. an integer resource with the resource panel toggle on will be generated to the resource file if the "Integers" option menu is set to "Code" and to the code file if the option menu is set to "Resource file".

Another way of saying this is that the option menus in the Generate dialog establish a general rule and the toggles in the Resource Panels identify exceptions to this rule.

Mask Only Global Resources

The following description applies when the "Mask only global resources" is set:

The option menus in the Generate dialog now apply only to global objects (font, color and pixmap objects). These (and only these) are controlled exactly as discussed for all resources in the Masking Resources section above.

All other resources are controlled only by their individual resource panel toggles. They are generated into the code file if the resource panel toggle is off and into the resource file if the resource panel toggle is on.

Examples of Masking Effects

In many cases, designers want to generate most strings into an X resource file so that they can be edited easily. This makes it possible to produce a foreign-language version of the application simply by editing the X resource file. To do this, you generate strings into the X resource file. However, there may be a few strings, such as the company's address, which you do not want users to be able to change. You can hard-wire these few string resources by setting their individual masking toggles.

Similarly, you might want to let users edit nearly all color resources except for your company colors. To do this, set the masking toggles on the individual resources which control the company colors. When you generate code, generate colors as a group into the resource file. WorkShop Visual hard-wires the tagged ones into the source code.

Default Settings

Default resource values, shown in brackets on the resource panels, are never generated into either file. In this case, Motif calculates the resource value at run time. The result may be different from the default value you saw while building the interface, depending on the platform you run the program on. Using default values is often helpful in making your application portable.

7.3.13 Finishing the Generate dialog

When you have finished setting up the files you wish to generate and their options in the Generate dialog, you can press "Apply" to save the settings or "Generate" to generate the files straight away. If you select "Apply" you can invoke the Generate dialog when you are ready and then generate all the selected files, or you can select the relevant button on the toolbar (or in the Generate menu) to generate individual files using the settings you applied earlier without producing the generate dialog again. If you have set the "Apply on Generate" toggle, pressing "Generate" performs a "Apply" as well as generating the requested files.

7.3.14 Running the tutorial

Having set up the Generate dialog with the files you wish to generate and their associated options, you are now ready to generate code and run your prototype application.

1. To generate all the files for your prototype, display the Generate dialog and press the "Generate" button.

2. Make sure that you are in the directory where the files were generated, as specified in the Generate dialog.

3. Set VISUROOT to the path to the root of the WorkShop Visual installation directory.

4. To build your prototype, type: make

5. Make sure that X can find your X resource file.

See the Setting up the X Resource File section on page 228.

6. To run your prototype, type: icecream

Figure  7-7 Interface Prototype Running
As in the dynamic display, all the widgets in your prototype are functional. You can click on the buttons, pull down the menus, and so on. Your prototype also includes links. You can display the help screen by pulling down the menu at the right side of the screen and clicking on its single entry; you can make the help screen disappear by clicking on its button.

Although your prototype also calls quit() when you click on exit_button, quit() doesn't do anything because you have not yet supplied the code to make it functional. This will be added in the Adding Callback Functionality below. To terminate your prototype when you have finished examining it:

7. Use the window manager to close the main window.


7.4 Adding Callback Functionality

All that remains to complete the tutorial is adding functionality to quit(). WorkShop Visual provides a means of editing callbacks directly in the stubs file.

7.4.1 Editing Callback Code from within WorkShop Visual

The Callbacks dialog contains a button labelled "Edit Code". Next to this button there is an option menu allowing you to tell WorkShop Visual which language the stubs file is using. This is to prevent ambiguity if you are generating both C and C++. You will not normally need to use this option menu as WorkShop Visual will usually choose the correct value for you. See the Designating a Callback section on page 188 for a description of the Callbacks dialog.

Setting up Callback and Prelude Editing section on page 615 WorkShop Visual uses the SunSoft Workshop Edit Server when you press the "Edit code" button. The stubs file is opened in a separate editing window with the insertion point inside the function brackets of the selected callback. As you select other callbacks the insertion point moves around the file so that you are always at the correct place. If you try to regenerate the stubs file when there are unsaved changes in the Edit Server window, you will be prompted to save those changes first.

Before allowing you to edit the stubs file, WorkShop Visual checks to see whether there have been any changes to the design since the last stubs file generation. If so, you are asked whether you wish to regenerate the file before editing. You cannot edit the file if you do not regenerate it.

If you have unsaved changes in an editing window when you try to regenerate the stubs file, you will be asked if you wish to save the file first. If you do save the file first, any callback code you have added will be preserved. See the Incremental Stubs File Generation section on page 241 for more details. If you choose to regenerate without saving changes, any changes made since the last save will be lost.

7.4.2 Editing the Callback

If you do not wish to use WorkShop Visual to edit your callback:

   Open stubs.c with a text editor and skip ahead to Step 5.
To edit your callback from within WorkShop Visual:

1. Select the exit_button widget.

2. Click on the Callbacks button in the toolbar or select "Callbacks" from the Widget menu.

3. Select "quit()" from the list of callbacks.

4. Press the button labelled "Edit code".

Pressing this button opens stubs.c.

7.4.3 Editing the Stubs File

The code for quit() looks like this:

void 
quit (Widget w, XtPointer client_data, XtPointer xt_call_data )
{
	XmPushButtonCallbackStruct *call_data = 
(XmPushButtonCallbackStruct *) xt_call_data;
}

5. Replace the text between the braces of quit() by: exit (0);

6. Save the file.

7. Remake your executable and run the program.

Refer back to the Running the tutorial section on page 238 for details on how to do this.

The "Exit" button is now functional. To quit your program:

8. Pull down the Procedures menu of your interface and click on the "Exit" button.

The Callback Functions section on page 194 looks at callbacks in more detail, including the parameters passed to them and the ways in which you can access and manipulate widgets in your design.

The tutorial is now complete. The remainder of this section looks in more detail at the issues discussed in previous sections.

7.4.4 Incremental Stubs File Generation

When you subsequently generate the same stubs file, WorkShop Visual reads the special comments in that file in order to work out which callbacks and methods have already been generated. In this way you can add your own code to the stub and it will not be overwritten.

WorkShop Visual then appends any new callbacks or methods to the end of the stubs file. Whenever a new stubs file is generated, the old version is copied to a file with the name you have specified and a .bak extension.


Note - When you remove a callback from a widget in WorkShop Visual, the callback stub will remain in the stubs file. If you want to remove the routine, you will need to open the stubs file and remove the comment above the callback routine.
Below is the listing of a stubs file containing one callback, named quit:

/*
** Generated by WorkShop Visual 
*/
The Beginning of the Prelude:

/*
** WorkShop Visual generated prelude.
** Do not edit lines before "End of WorkShop Visual generated 
prelude"
** Lines beginning ** WorkShop Visual Stub indicate a stub
** which will not be output on re-generation
*/
/*
**LIBS: -lXm -lXt -lX11
*/
The End of the Prelude:

/* End of WorkShop Visual generated prelude */
Special Comment to Indicate a Stub:

/*
** WorkShop Visual Stub quit
*/
void 
quit (Widget w, XtPointer client_data, XtPointer xt_call_data )
{
        XmPushButtonCallbackStruct *call_data = 
			(XmPushButtonCallbackStruct *) xt_call_data;
}

7.4.5 Stubs File Comments

At the beginning of the file there is a prelude which WorkShop Visual reads and, effectively, throws away. The prelude is always regenerated anew. Before every stub WorkShop Visual generates a comment giving the name of the callback or method. In this way WorkShop Visual can calculate which stubs it still needs to generate, having read the existing stubs file.


Note - You should not alter these comments in any way unless you wish WorkShop Visual to regenerate the stub.

7.4.6 Regeneration of Callback Stubs

If you wish WorkShop Visual to regenerate one of the stubs, simply remove the comment preceding the stub and the stub itself. If you remove only one or the other, one of the following will occur:

Remember that regeneration of a stub will lose the contents of the routine.

WorkShop Visual will not remove old stubs even though a special comment no longer matches a callback or callback method.

7.4.7 Regeneration of the Whole File

You may wish WorkShop Visual to regenerate the whole file anew if, for example, you have deleted some callbacks or changed some names, the old ones are still being generated and the file is starting to become full of redundant code. In order to do this, simply remove, or change the name of, the stubs file and the ".bak" file. If WorkShop Visual cannot find a file with the name you have specified for the stubs file, it will generate a new file.


7.5 Analysis of the Primary Module

From top to bottom, your primary code module contains the following sections:

This section analyzes the code in your file.

   Open icecream.c with the text editor and inspect it as you read.
The optional portions of the file can be included or excluded by setting toggles on the control panel. These toggles, and the advantages and disadvantages of including the optional sections, are discussed in the Code Generation Options section on page 232.

7.5.1 The Header Section

The primary module has the following header material, in this order:

Your file does not need to have a module heading or module prelude. You can specify code to be inserted in these places from within WorkShop Visual. The procedure for doing so is discussed in the Customizing the Generated Files: Preludes section on page 254.

After some standard WorkShop Visual comments, there is a list of #include statements needed for the code in your module. The #include statements are optional and are controlled by the toggles in the Code Options dialog - see the Setting up the Primary Source File section on page 223.

WorkShop Visual also needs to include its own header file in order to define the base classes that it uses. If you wish to change the name of the file to be included, or not include a base class header file at all, refer to the Generation section on page 726 for details of the application resource that you will need to change.

7.5.2 Link Functions or Link Declarations

Next, the module contains code for the link functions. The following code fragment shows a typical link function:

void XDunmanage_link ( Widget w, XtPointer client_data, XtPointer 
call_data )
Generation of this code is optional and is controlled by the Generate Options dialog - see the Code Generation Options section on page 232.

7.5.3 Variable Declarations

In this section, all globally defined widgets in the design are declared. The following lines are typical:

Widget exit_button = (Widget) NULL;
Widget help_cascade = (Widget) NULL;
Only global widgets are declared here. By default, widgets are local in scope. Local widgets are defined in the function which creates their parent Shell and cannot be referenced elsewhere in your application. To make a widget global, you can:

Note that the variable names of Application Shells and Top level Shells are always global in WorkShop Visual and therefore should not be made local. See the Shell Types section on page 75 for more information on the different shell types.

7.5.4 Variable Names

Variable names must be unique. If you "Read" or "Paste" widgets into your design whose variable names duplicate names of existing widgets, WorkShop Visual silently removes the duplicate names and assigns new, local, names of the form widget_type<n>, e.g. shell4, form5, etc.

By convention, variable names of widgets should begin with a lower-case letter. This helps avoid conflict with Motif declarations.

7.5.5 Creation Procedures

By default, WorkShop Visual generates a creation procedure for each Shell widget in your design. The creation procedures are the heart of the generated code. Each creation procedure does the following:

The creation procedures do not display the Shell. Usually, windows are displayed by a function call in the main() procedure or in a callback routine.

By default, creation procedures have the form create_<shell name>, based on the variable name of the Shell. Your design has two Shells: a Dialog Shell, named help_window, and an Application Shell, named myFirstShell. It therefore has two creation procedures: create_myFirstShell and create_help_window. You can change the name of a creation procedure in a code prelude, discussed later in this chapter.

create_help_window has the following form:

void create_help_window (Widget parent)
{
	. . .
}
The function body has function calls which create the Dialog Shell itself:

help_window = XmCreateDialogShell ( parent, "help_window", al, 
ac );
Dialog Shells, unlike Application Shells, are dependent on another Shell, parent. See the Shell Types section on page 75 for more details concerning the various Shell types and their respective behavior.

create_help_window also creates all the Shell's children. The DialogTemplate child, to which you gave an explicit variable name, is created and assigned to a global variable:

dialog_2 = XmCreateMessageBox ( help_window, "dialog_2", al, ac);
The Label, if you did not name it explicitly, is assigned to a local variable as illustrated below. (Note that the widget variable name may be different in your code.)

label1 = XmCreateLabel ( dialog_2, "label1",al,ac);
create_myFirstShell, the creation procedure for your Application Shell, has different arguments because it is a different type of Shell:

void create_shell_1 (Display *display, char *app_name, int 
app_argc, char **app_argv)
{
. . .
}
See the Shell Pre-create Prelude section on page 259 for a discussion of these arguments.

This function is similar to create_help_window, although it is considerably longer as your main window has more child widgets than the help window.

7.5.6 Callback Procedures

The primary module does not include callback functions themselves. However, it does add any callbacks you have specified to each widget's callback list. create_myFirstShell contains the following lines (not necessarily together) which create the exit_button and add the quit callback.

exit_button = XmCreatePushButton ( rowcol1, "exit_button", al, 
ac );
. . .
XtAddCallback (exit_button, XmNactivateCallback, quit, NULL);
An extern declaration of quit() is generated earlier in the source file.

The "Show" link on the widget help_button inserts an Activate callback to the WorkShop Visual function XDmanage_link. The code which creates help_button and adds a link to it looks much like the code which creates exit_button and adds its callback.

help_button = XmCreatePushButton ( rowcol2, "help_button", al, 
ac );
. . .
XtAddCallback (help_button,XmNactivateCallback, XDmanage_link, 
(XtPointer) &xd_links[0] );

7.5.7 Description of the Main Program

A minimal main() procedure is either generated into a separate file or at the end of your primary module. See the Setting up the Main Program File section on page 227 for details on generating this procedure into a separate file.

WorkShop Visual's main() procedure does the following things:

As you have seen, this main() procedure is sufficient to run the interface and check its behavior. In many applications, very little additional code is needed in main() because most functionality is handled in callbacks. However, if you need to initialize other parts of your application, you should generate a separate main() procedure source file from the Generate dialog once only and edit the file. Termination code goes in the callback function which is invoked to exit the application.

   Close the file icecream.c.


7.6 Resource File Syntax

The syntax for generated resource files, by default, is as follows:

<application name>*<widget name>.<resource>: <value>

For identification purposes, the widget's variable name (not the widget name) precedes the list of its resources in a comment. If a group of widgets share a widget name, however, only one variable name from the group appears. A comment is also generated for any widget which has no resources generated into the file.

7.6.1 Example Syntax

   Open your X resource file (icecream.res) with a text editor and look at it.
The file fragment below includes only String resources.

! button1
XDTutorial*button1.labelString: Cone

! button2
XDTutorial*button2.labelString: Dish

! button3
XDTutorial*button3.labelString: Cancel

! procedure_cascade
XDTutorial*procedure_cascade.labelString: Procedures

! button4
XDTutorial*button4.labelString: Wash Dishes...

! button5
XDTutorial*button5.labelString: Count Money

! exit_button
XDTutorial*exit_button.labelString: Exit
XDTutorial*exit_button.accelerator: Ctrl<Key>E
XDTutorial*exit_button.acceleratorText: Control + E

! help_cascade
XDTutorial*help_cascade.labelString: Help
XDTutorial*help_cascade.mnemonic: H

! help_button
XDTutorial*help_button.labelString: About This Layout
XDTutorial*help_button.mnemonic: A
An end user can change any of these strings by editing its value in the X resource file. For example, the second line could be changed to read:

XDTutorial*procedure_cascade.labelString: Closing Up
Resource values in the X resource file are overridden by values for the same resource in the .Xdefaults file in the user's home directory.

7.6.2 Include in Resource Binding

If you have set any of the "Include in resource binding" toggles (found on the "Code generation" page of the Core Resource panel) for any widgets in your design, your resource file will look slightly different. The syntax that WorkShop Visual generates for resource files by default is very general - it applies to all widgets with the specified widget name within the whole application. It is often the case that you have more than one widget with the same name. Tight bindings give you more control over widget resources.


Note - This section only discusses the syntax of the generated resource file, refer to the Tight Bindings section on page 98 for a thorough explanation of tight bindings.
The example given in the Tight Bindings section on page 98 would produce the following line:

XDTutorial*FirstForm*OkButton.labelString: Ok

7.6.3 Loose Bindings

If you have set any loose bindings, these will appear at the top of the generated resource file. Their syntax is slightly different as they never refer to individual widgets.


Note - This section only describes the syntax of resource files - for a thorough explanation of loose bindings, refer to the Loose Bindings section on page 90.
The example given in the Loose Bindings section on page 90 would generate the following line in the resource file:

XDTutorial*XmDialogShell*MyForm.MyButton.labelString: Bound

7.6.4 Shared Resource Values

To identify a widget completely, X requires a list of all the widget's ancestors in the hierarchy as well as the widget's own name. In the generated X resource file, WorkShop Visual uses a wildcard (*) instead of a list of specific ancestors. Thus, each widget is distinguished only by the application name and the widget name, and any widgets which share a widget name, also share any resources generated into the X resource file.

The following lines are taken from WorkShop Visual's own X resource file:

/* dialog buttons */
visu*apply_button.labelString: Apply
visu*cancel_button.labelString: Close
WorkShop Visual has several buttons, in several places, which have the widget name apply_button. All these buttons share the label string "Apply". Similarly, all buttons with the widget name cancel_button share the label string "Close". These strings can be changed on all buttons at once by editing one line of the X resource file.

By contrast, resources generated into the source file are always set separately for each widget, even if widgets share a widget name.


7.7 Arranging Your Files

WorkShop Visual allows considerable flexibility in arranging files to suit your preference. This flexibility requires some care on your part, since you must include all necessary pieces of code, yet avoid duplication, in order for your application to link successfully.

Another consideration is that your file setup should allow changes to your interface in WorkShop Visual after the first pass at generating code. Remember that any changes you make will require regenerating code and, possibly, resource files. Your files and directories should be set up so that when you regenerate files you do not overwrite any coding work you have done.

With these considerations in mind, this section discusses strategies for organizing your code files.

7.7.1 Using Separate Directories

It is a good practice to keep a separate directory for each WorkShop Visual application. Make the directory before you start designing. Save your design file and generate all code files and resource files into that directory.

7.7.2 Keeping Generated Files Unchanged

To avoid errors, do all of your own coding outside the primary module and X resource file generated by WorkShop Visual. Code preludes, module preludes (see the Customizing the Generated Files: Preludes section on page 254) and the various options in the Generate dialog give you some control over the primary module from within WorkShop Visual. Similarly, resource preludes let you adjust the X resource file. If you do not edit these files outside WorkShop Visual, you can regenerate them when you make changes in your design without sacrificing any work you have done.

7.7.3 Keeping Main Separate

The main() procedure almost always needs to be edited. For this reason it is best to generate a separate main program file. You can then edit this file as you wish. Make sure that you do not regenerate the main program file once you have made your own changes to it. See the Setting up the Main Program File section on page 227 for details on how to do generate a separate main program file.

7.7.4 Stubs File

Unlike other generated files, the stubs file is meant to be edited. WorkShop Visual will preserve changes to stubs files on re-generation. See Chapter 6, "Making It All Work" for details on adding, editing and understanding callbacks. See the Adding Callback Functionality section on page 239 for details on editing a stubs file.

7.7.5 Where To Put Links

If your application uses links, you must generate the link functions and function declarations into either the code file or the stubs file.

If your application uses generated code from more than one design file, you should generate the link functions declarations into all the primary modules but generate the link functions into only one file.

7.7.6 Where to Put Includes

If your make procedure involves compiling the primary module and the application code separately, you should turn on the "Include Header File" toggle for the primary source code file. This procedure was followed in the tutorial. See the Setting up the Primary Source File section on page 223 for details on how to do this.

Another strategy involves writing a #include directive to include the generated code in your application code file and compile all the code together. If you do this, you should turn on "Include Header File" only once for the primary module and turn it off when you generate the stubs file.


7.8 Customizing the Generated Files: Preludes

WorkShop Visual lets you edit the primary source file, which it generates, in order to add lines of your own code, here called preludes. All preludes can be entered by typing them into WorkShop Visual and allowing WorkShop Visual to insert them into the code at the appropriate place. There are several types of prelude, distinguished by where the code is inserted.


7.9 Module Preludes

The "Module prelude..." command in the "Module" menu lets you enter a heading prelude, a module prelude and a resource prelude in your code, using the dialog shown in Figure 7-8.

Figure  7-8 Module Prelude Dialog
Selecting one of the toggles which appear in the representative text, allows you to edit that type of prelude. There are two ways of adding a code prelude:

Use the "Edit in place" toggle to specify which of the above you wish to use. If the "Edit in place" toggle is set, the generated code is opened for you to add your code. See the Using the Edit Mechanism section on page 261 for more details on this.

If the "Edit in place" toggle is not set, a large text widget appears on the right of the dialog. Enter your code here. You should type the code exactly as if you were using a text editor to type any other code. This means that you should observe all the rules and conventions of the target language, including end of line markers, bracketing conventions etc. You should always press Return after the last line in a prelude.

7.9.1 Heading Prelude

The heading prelude is inserted at the beginning of the main program file, the code file, the externs file and the stubs file. Typically, a module heading would contain a comment with information such as the program name, SCCS ID, or version number.

7.9.2 Module Prelude

The module prelude is inserted at the top of the generated code file - just after WorkShop Visual's generated #include statements, if you asked for them. The module prelude can be used to supply #define or #include statements or extern declarations which are needed by your code. The module prelude is generated only into the primary module, not the stubs file.

7.9.3 Resource Prelude

The resource prelude is inserted at the beginning of the X resource file to specify application resources - i.e. resources which refer to the whole application and not to individual widgets. Use the following syntax:

ApplicationName*resource: value
For example:

visu*symbolFont: -*-symbol-medium-r-normal--14*
Although these resource bindings apply to all widgets in the application, they are overridden by more specific resource settings on individual widgets or groups of widgets with a common name.

You may also wish to include comments or SCCS IDs in a resource prelude.

See the Loose Bindings section on page 90 for information on setting up loose resource bindings for the whole module and for individual widgets.


7.10 Code Preludes

While module preludes apply to the whole module, code preludes apply to individual widgets. This means that the code will be inserted before the widget is created or managed. To add prelude code:

1. Select the widget to which you wish to add code

2. Select "Code Preludes" from the "Widget" menu

The Code Prelude dialog is shown in Figure 7-9:

Figure  7-9 Code Preludes Dialog

7.10.1 Code Preludes Dialog

The Code Prelude dialog contains text representing generated code for the selected widget. This code is representative only, so that you can see where the preludes will be added. This is not the actual generated code.

This dialog contains two sections - one for C code (labelled "Code preludes") and one for C++ (labelled "Method preludes"). Within both sections of text are toggles allowing you to choose whether you wish to edit the various kinds of prelude. There are two kinds of code prelude which can be used with C: Pre-create and Pre-manage. These are discussed in the Pre-create Preludes section on page 258 and the Pre-manage Preludes section on page 260.

There are three kinds of method preludes for use with C++: public, private and protected. These relate to their access. The Method Access Control section on page 275 provides more information on method access. You can, however, add both methods and data members in a prelude. The Adding Class Members as a Prelude section on page 307 shows, as part of a tutorial, how to add data members using the Code Prelude dialog.

Clicking over "Code preludes" or "Method preludes" folds away the corresponding text area so that only the other prelude type is visible.

7.10.2 Adding a Code Prelude

Selecting one of the toggles which appear in the representative text, allows you to edit that type of prelude. There are two ways of adding a code prelude:

Use the "Edit in place" toggle to specify which of the above you wish to use. If the "Edit in place" toggle is set, the generated code is opened for you to add your code. See the Using the Edit Mechanism section on page 261 for more details on this.

If the "Edit in place" toggle is not set, a large text widget appears on the right of the dialog. Enter your code here. You should type the pre-creation code exactly as if you were using a text editor to type any other code. This means that you should observe all the rules and conventions of the target language, including end of line markers, bracketing conventions etc.

7.10.3 Pre-create Preludes

Pre-create preludes are inserted into the code before the selected widget is created.

If the selected widget is not a Shell widget, the pre-creation prelude is inserted in the creation procedure for the widget's parent Shell and you can provide any code without restriction. Pre-creation preludes are commonly used to set resources which can only be set at widget creation time. Pre-create preludes for Shells are different and are described in the Shell Pre-create Prelude section on page 259. Below is a segment of generated code showing where pre-create preludes are added:

		...
/* visu: prelude for rowcol1: pre-create >>> */
	Enter pre-create code here
/* <<< pre-create ends. */
rowcol1 = XmCreateRowColumn ( shell11, "rowcol1", al, ac );
		...
If you had selected "Edit in place" and you are editing the generated code directly, make sure that your code is typed into the area surrounded by special comments. It is then preserved when you regenerate code. You must not alter or remove the special comments.

7.10.4 Shell Pre-create Prelude

The code preludes for a Shell differ slightly from those of other widgets. The pre-creation prelude is used to replace the function header for the Shell's creation procedure. You can then, if you wish, define extra parameters.

The generated body of the procedure refers to one or more variables, which, in the default procedure heading, are passed as parameters. While these variables must be in scope, you can choose to pass them as parameters or declare them as global variables. The following variables must be in scope:

Required for Application Shell widgets:
Display *display;
char *app_name;
int app_argc;
char **app_argv;
Required for Dialog Shell or Top level Shell widgets:
Widget parent;
In C for UIL the following are also required:
MrmHierarchy hierarchy_id;
MrmCode *class;
If you do not provide a pre-create prelude for a Shell widget, the creation procedure name defaults to create_<widget-variable-name> with the compulsory parameters as the only parameters.


Note - If you provide a pre-create prelude for a Shell, the call of the creation procedure in the generated default main() program is unlikely to be correct.

Warning - Shell pre-create preludes cannot be edited in place for Motif XP or MFC code. In general, code preludes should not be used for cross-platform designs because, by their very nature, preludes tend to include platform-specific code.

7.10.5 Pre-manage Preludes

The pre-manage prelude appears slightly later than the pre-create prelude in the generated code - just before the widget's callbacks are added. One use of this prelude is to set up client data for the callbacks. Other uses include setting the value of a Text widget, filling a ScrollingList, adding buttons from a file, or any other dynamic initializations. Below is a segment of generated code showing where pre-manage preludes appear:

		...
/* visu: prelude for shell1: pre-manage >>> */
	Enter pre-manage code here
/* <<< pre-manage ends. */
XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
XtSetArg(al[ac], XmNargc, app_argc); ac++;
XtSetArg(al[ac], XmNargv, app_argv); ac++;
		...
If you had selected "Edit in place" and you are editing the generated code directly, make sure that your code is typed into the area surrounded by special comments. It is then preserved when you regenerate code. You must not alter or remove the special comments.

7.10.6 Shell Pre-manage Prelude

A Shell's pre-manage prelude is inserted just after the local declarations in the procedure. Otherwise it is the same as for other widgets.


7.11 Using the Edit Mechanism

Setting up Callback and Prelude Editing section on page 615WorkShop Visual uses the SunSoft Workshop Edit Server when you edit the generated code file. The file is opened in a separate editing window at the appropriate place in the file for the selected prelude type. As you select other prelude types the insertion point moves around the file so that you are always at the correct place. If you try to regenerate the code file when there are unsaved changes in the Edit Server window, you will be prompted to save the changes first.

7.11.1 Prelude Acceptance Chooser

When you regenerate the code file after having added a prelude in place, the Prelude Acceptance Chooser is displayed. This is shown in Figure 7-10. Adding a prelude directly into the Preludes dialog will not cause the Prelude Acceptance Chooser to appear.

Figure  7-10 Prelude Acceptance Chooser
In this dialog, you can choose individual preludes which have changed since the file was last generated and specify whether you wish to accept or reject those preludes. Select the preludes and press the arrow keys to move them from one list to the other. When you press "Ok" only those preludes you chose to accept will be regenerated. Alternatively, you can choose to reject or accept all the newly added preludes. Preludes which you reject are deleted when you "Ok" the dialog and cannot be retrieved at a later date.

Preludes which were added before a previous code generation took place are retained - the Prelude Acceptance Chooser only affects those preludes which have been added since your code file was last generated.


Note - If you unset the "Edit in place" toggle and you have added a prelude since the last code file generation the Prelude Acceptance Chooser is displayed because any new preludes need to be shown in the Preludes dialog.


Previous Next Contents Index Doc Set Home


1 The terms "Header file" and "Externs file" are used interchangeably in both and the User's Guide.