Part 4 - Boxing clever

Last time, I was saying that the use of a library (.h) file would, in the long term save piles of time in that the common parts of any application can be accessed without the need to constantly type the code back in.

The constant typing, while on one hand does make you more familiar with the form of the structures and unions, does also have the downside in that you may rush and make a mistake which will break (render useless or at least, partially inoperative) your program.

If you have not already purchased from RISCOS Ltd the excellent PRM CD or have obtained the StrongHelp manuals, you will soon run into trouble - infact, after this tutorial, I'd say you won't be able to get much further without them....

Okay, onto the library. I'll deal with the Wimp_Poll block here.

recap :

_swi(Wimp_Poll,_INR(0,1)|_OUTR(0,1),mask,block,&reason code,&block);

where mask is what we reason codes we want to see and block is the 256 byte block. &block contains the returned value from the call.

Given that there are 17 reason codes for the WIMP itself (excluding 14-16) and with the exception of reason 0 & 3-5 (no reason), the return values all have multiple components (such as Mouse Click - this has a 6 return values). The upshot of this is that the returned block will need interpretting. While this may not be overly difficult, it would be tedious to have to constantly work out the offset (position from start of the returned value).

How do set about creating such a library then?

It can be done one of two ways - have all the reason code return values in one mammoth structure or (as I will and do) create a number of small structures and include them all in the main structure.

Let's take an example - reason code 6 - mouse click. The call from the poll returns

offset	meaning
0	Mouse x position
4	Mouse y position
8	Buttons
12	Window handle
16	Icon handle
20	Button state prior to click

This can be simply translated into a structure like so

typedef struct mousey {
                       int mouse_x;
                       int mouse_y;
                       int buttons;
                       int window_handle;
                       int ic;
                       int pre_button;
                      } mousey;

Similar mini-structures can also be built up for the other reason codes, and being a structure, there is no reason that if you had say defined

typedef struct win_han {
                        int wh;
                       } win_han;

that this could not be included in the mousey structure as

typedef struct mousey {
                       int mouse_x;
                       int mouse_y;
                       int buttons;
                       win_han window_handle;
                       int ic;
                       int pre_button;
                      } mousey;

When all of this mini structures have been completed, they can be wrapped up into one large structure. Remember though that the WIMP can return messages other than the ones already outlined, so you must ensure this is catered for. Doing this is simple

typedef struct wimp_block {
                           union {
                                  *bits*
                                 } poll;
                           char memory[256];
                          } wimp_block;

in other words, it's either the union or the memory block. (The full version of this is given on both here or this month cover disc).

SWI or SWIX?

An area I've not yet covered is if the _swi or _swix form should be used - indeed, what the difference actually is!

Whenever making a system call (OS call), RISC OS will return either a zero for a successful call or non zero for a failed call. If the x form of the call is made, then this returned value can be tested. If you don't use the x call, an error may be generated which can vary from helpful (such as illegal window call) or complete gibberish (abort on data fetch at &0322311ac).

Testing for the returned value is a good idea and simple to perform

if ((_swix(somecall,params))!=0) error_message("swi failed);

While not incorrect, the above line is an example of psuedo code.

Psuedo code?

When developing a program of any sort of complexity, unless you know what you are doing, psuedo code is probably one of the most useful methods of learning.

For instance - say you want to write a comparison routine. First off you would set yourself an aim - in this case to compare two numbers and see if they're the same and if they are, if they are divisable by 4 with the answer being an integer.

Next, you write the psuedo code :

is no1 == no2 ?
if no exit totally
if yes
 does no2 divide by 4 with no remainder?
if no exit with message "are ="
 message "are = and /4 cleanly"
exit totally

This is a vague language which follows the structures of a number of computer languages.

It is only a small step to convert this into C

if (no1!=no2)
{
 printf("not equal\n";
 return -1;
}
else
{
 if (no2%4==0)
  printf("are = and /4 cleanly\n") ;
 else
  printf("are = and not /4 cleanly\n");
}

(alright, the above is nothing amazing, it's really just to demonstrate a point!)

A second structure which you will need is one for the error handling. The WIMP provides us with a useful (if slightly outdated) error box.

For now, our code to handle the error box is deliberately simple and is this

void report_error(const int error_number,const char *error_message)
{
 error_block error;
 error.value=error_number;
 sprintf(error.text,"%.251s",error_message);
 _swix(Wimp_ReportError,_INR(0,2),err_block,1,task_name);
}
task_name is predefined at the start of the code.

That's all I wish to cover for this time. Up next, let's get going on some code.