An error a day 2 ....

Last time, I covered the basic use of MessageTrans and how to use a message file. While this is fine for small applications, it does not really help if you have something happen which is part of a group of problems.

For instance, say you have a list of devices (drive 0, drive 1, drive 2, drive 3, drive 4 and drive 5) and also (say) 3 faults which could occur (disc is unformatted, format unknown, has exploded taking the drive with it). Under the system demonstrated last time, you would need 15 messages (say disc_err1: to disc_err16:). While this is not going to make any difference to the image filesize by much, it will to the messages file. This can be simplified to 1 main message and 3 error message (the faults).

It would take the format

disc_err:The disc in drive %0 has a fault (%1)
fault1:disc is unformatted
fault2:format unknown
fault3:has exploded and taking the drive with it.

The %0 and %1 tell MessageTrans that something will be substituted into these positions. If nothing is provided %0 and %1 will be displayed.

If you look at any large application (say Impression or TechWriter) and examine the messages files, you will see quite a number of these.

How to code these up

Coding is very similar to how was demonstrated last time. If you recall, the lookup function was this

char *lookup(char *token)
{
 char *out,*buff;
 int size;
 _kernel_oserror *er;
 buff = malloc(256);
 if (buff == NULL)
 {
  strcpy (er->errmess,"Lookup malloc failed");
  er->errnum = 0;
  wimp_error (er);
  exit (EXIT_FAILURE);
 }
 er = _swix(MessageTrans_Lookup,_INR(0,7)|_OUT(2),mess,token,buff,
            size,0,0,0,0,&out);
 E(er);
 if (er != NULL)
 {
  strcpy (er->errmess,lookup("LookFail"));
  er->errnum=0;
  wimp_error (er);
 }
 free (buff);
 return out;
}

Our new function has to take into account that we can substitute 4 parts in the message lookup (%0 to %3). This is performed by changing the prototype to

char *lookup2 (char *token, char *sub1, char *sub2,
               char *sub3, char *sub4)

We have changed the name (it's handy to keep both functions though - while it will increase the final image size, it does mean we can lookup either one message or a multiple message) and added that we want 4 other tokens taken into consideration.

In lookup2, the internals will be the same as lookup (you can cut and paste them if you wish!), with the exception of the swi call itself. Instead of

er = _swix(MessageTrans_Lookup,_INR(0,7)|_OUT(2),
                        mess,token,buff,size,0,0,0,0,&out);

we now have

er = _swix(MessageTrans_Lookup,_INR(0,7)|_OUT(2),
            mess,token,buff,size,sub1,sub2,sub3,sub4,&out);

In the calling routine, we now have to specify which function we wish to use. You'll now see why keeping both is useful.

Say we did not have the faults listed separately, we could call the function by using

strcpy (message,lookup2("disc_err","drive 0"
                        "disc is unformatted","",""));

(remember, if there is nothing to substitute, an empty string has to be passed.)

This is fine, with the exception of one thing. RISC OS is used worldwide. Not just in English speaking countries, so in some far flung land the phrase "disc is unformatted" may not be understood. To this end, we can either call lookup2 recursively or we can call lookup as part of the function call itself i.e.

strcpy (message,lookup2("disc_err","0",
                        lookup("fault_2"),"",""));

or

strcpy (message,lookup2("disc_err","0",
                       lookup2("fault_2","","",""),"",""));

By using this method, your application can be used by anyone in any country (as long as they have first translated the messages file into their native language).

Okay, enough for now. As with last time, see if you can change the source file from last time to use the lookup functions. Next time, we'll return to the WIMP