C for Yourself - part 25

Steve Mumford starts the process of building a WIMP library.

Over the past few months, I've been presenting you with sections of C source code that would use kernel SWI calls to initialise a task on the Desktop. So far, the various routines that carry out the necessary jobs have been 'hard wired' into the program - if I had wanted to write another menu, I'd have to head to the reference manuals once more and recalculate all those flags. This isn't an ideal state of affairs, particularly if you do a lot of coding. One answer to this problem is to create a library of functions that you can link with your own source code when the application is compiled.

What are the benefits? The greatest advantage is that it hides the complexity of the data blocks and the SWI calls behind an interface that's hopefully easy to remember. Admittedly, while you're developing the library, the compilation gets a little trickier and it's worthwhile getting to grips with your compiler's Make utility to manage your project. However, once your library contains all the functions you require, all you need to do to give a program access to those routines is #include a header file and link in your pre-compiled library object code. This month, I've been preparing a simple WIMP C library named AULib and converting the existing !RunImage file to make use of it.

The application I've presented on the cover disc has two extra components - the C source for AULib, stored in the C directory along with the main source code, and an AULib header file that contains various #define statements and structure definitions, as well as the prototyping information for the functions held in the library. At present, it's still fairly basic in its functionality, but the !RunImage file is already much simpler than it was - I'll run through a few of the features provided below.

Firstly, AULib defines a function to initialise a task on the desktop - it takes the required RISC OS version number multiplied by 100 as its first parameter, along with a pointer to the application name and a pointer to the list of messages that you wish the WIMP to pass on to you. On its return, it gives you your application's task handle, which you should store away for reference later. In use, it looks something like this:

#define VERSION_NUMBER 310
int task_handle;
char appname[] = "My Application";
long int msglist[1] = {0};

task_handle = au_initialise(VERSION_NUMBER, appname, msglist);

Although it's possible to call au_initialise with an application name in quotes, such as:

task_handle = au_initialise(310, "Another application", msglist);

this can cause confusion later as you'll probably want to provide the same application name for use in error boxes and the like. So it makes sense to store it in a globally accessible variable.

The use of #define to create a list of constants in the header file allows mnemonics to be created that make the flags necessary for a lot of SWI calls much easier to remember - I've made use of them to manage creation of icons and menus. Here's an example, in which individual flags are merged into one integer by using the bitwise OR operator:

ibar_icon_handle = au_create_iconbar_icon(IBAR_PRIOR_APP, IBAR_ONRIGHT,
      ICON_ISSPRITE | ICON_HCENTRE |
      ICON_VCENTRE | ICON_CLICKNOTIFIESONCE, "!newwimpc");

This might look like a bit of a mouthful at first, but once you've become familiar with the various tokens, it's much easier to edit the icon's behaviour. This function takes four parameters:

Finally, it returns a handle to the new icon.

That's all I've got space for this month, but next time I'll explain the other functions used in the cover disc example, including the improved menu creation routine. You might like to compare this month's !RunImage file to the one presented last issue; hopefully, it should be somewhat easier to follow. See you next time.


Source: Acorn User - 169 - June 1996
Publication: Acorn User
Contributor: Steve Mumford