C for Yourself - part 26

Steve Mumford describes how to handle templates with the developing Acorn User WIMP library

Last month I introduced the basics of creating a WIMP library. To continue then, we'll look at the functions that allow template loading and window manipulation.

You may remember that the template-loading routine in the original WimpC example was somewhat ungainly; this time round, it's been replaced with several functions that provide a much more flexible interface. There are three stages to work through when extracting template data - you must first open the file, read the data for each window you wish to create, then close the file again once you've finished. Three functions are provided in AULib to cover these requirements, and there are au_opentemplate, au_loadtemplate and au_closetemplate respectively. A typical loading cycle, taken from the example on the cover disc, looks like this:

if (au_loadtemplate("MainWindow", &win_array[0], 0) == 0)
  au_report_error(1, "Template not found!", 1, appname);
  QUIT_FLAG = 1;
au_openwin_from_templatedata(&win_array[0], -1);

The au_opentemplate function takes the name of the template file to be accessed, and simply sets things up for the actual loading process - howver, before this can be done you must prepare an area of memory in which to hold the information. In the original example, I took the easy way out by defining two large global data blocks at the beginning of the program; they were far bigger than they needed to be, and they had no inherent structure.

AULib defines a new structure type named window_data that holds the window's name, its all-important handle, and pointers to a buffer and some workspace that store the window's definition and data about its icons. Before templates can be loaded, you must declare an appropriate number of these structures - in our example I've created a global array of window_data structures at the start of the program.

Once you've defined a structure to hold the window information, you can load a template by instructing AULib to search through the file for a particular name. au_loadtemplate takes three parameters, the first being the name of the template to use within the file, followed by a pointer to the structure that's going to hold the data, with an integer as the third argument - normally zero, but it can be non-zero if used in wildcarded searches. The function returns an integer relating to the position of the next entry after the chosen template; if this is zero, it means the template couldn't be found. This should be trapped and the program halted if this could cause a crash, hence the check made in the example shown above.

If there are several windows in the main file whose names begin with Main, for example, it's possible to load them all one after the other by calling au_template with Main* as the search string. As mentioned above, au_loadtemplate returns an integer that indicates where the next match is and, using this value in the next call, informs the function as to where it should start subsequent searches from.

There's a slight catch; because the wildcarded name is replaced in memory with the full window identifier when a match is found, the datablock that holds the shortened name must be large enough to accomodate the full string - in the example above this is not necessarily the case because we're creating a temporary character array on the fly. In order to avoid crashes, this declaration should be made by hand to ensure that the array will be large enough:

char name[12] = "Main*";
int call = 0;
int index = 0;

  call = au_loadtemplate(name, &win_array[index++], call);
  strcpy(name, "Main*");
} while (call != 0);

The fragment shown above will cycle through all templates beginning with Main and load them into win_array - note that because name will be filled with the actual name of a successful match, it must be re-initialised with the wildcarded string in order to continue the hunt successfully.

Once you've loaded all the templates that you need, a simple call to au_closetemplate will tidy up afterwards, and the windows can then be displayed on screen by calling au_openwin_from_templatedata with a pointer to the window_data structure and an integer denoting its position on the window stack - normally -1 to display it over the top of everything else.

Next month, I'll get round to discussing menu creation, and add a little more functionality to the library - bye for now.

Source: Acorn User - 170 - July 1996
Publication: Acorn User
Contributor: Steve Mumford