2. Let's make a start

Hopefully, you will have written a couple of command line programs and grown happy using the _swi function. By the end of this tutorial, you will see how quickly a (very) basic WIMP application can be written.

All WIMP programs have 2 features in common - they all have to initialise themselves with the Task Manager and all have to use a poll loop - both are _swi accessed, so will all have values in and out.

SWI Wimp_Initialise

On entry
	r0	Last wimp version * 100
   r1	0x4B534154 ("TASK")
	r2	Task description
	r3	Messages list required

On exit
	r0	Current wimp version*100
	r1	Task handle

The wimp version relates to the RISC OS version. This is normally 310 (corresponding to OS 3.10), though 350, 360, 370 and 400 are all used. 200 (OS 2.00) is unlikely to be seen now.

r1 is actually just a fudge to filter out all the old pre-RISC OS programs which are not likely to pass this on initialisation!

The task handle is the name by which the task manager knows what the application is. Every application, be it WIMP or command line will have had one of these assigned to it on start up.

The poll loop is the manner by which the program itself keeps up to date with what events have been recieved.

Events?

All wimp programs rely on events. These events are the likes of the pointer entering or leaving a window or the mouse being clicked. That said, even when the program is just sitting there, twiddling it's electronic thumbs or generally just chilling out, the program is still recieving events, namely NULL events.

SWI Wimp_Poll

On entry
	r0	event mask
	r1	pointer to a 256 byte block
	r3	pollword pointer in RMA

On exit
	r0	event reason code
	r1	pointer to block of data

The event mask allows (or disallows) certain events. For now, we'll happily ignore it and accept all events.

The event reason code is just the result of the current wimp poll. For a NULL event, this will be 0.

How do we code this up though?

Remember two points, the task handle is unique to the program and may be needed elsewhere.

It is a good idea therefore to set this up as a global variable. The same applies to the task name and some method of generating the 256 byte block of memory. Everything else is really just a matter of calling the correct _swi commands.

The full app looks like this

/* C the WIMP - part 1.
  This program registers itself with the task manager and does nothing else. Note, the swi call is not trap handled with the _swix version 
  of the function */

#include "swis.h"
#include <stdlib.h>

int task_handle;
int *mem_block;
int quit=0;

#define task_name "C the WIMP 1"
#define TRUE 1

void register_task(void)
{
 _swi(Wimp_Initialise,
 _INR(0,3)|_OUT(1),310,0x4b534154,task_name,NULL,&task_handle);
}

void initialise(void)
{
 mem_block=malloc(256);
 if (!mem_block) exit(1);
}

void event_poll(void)
{
 int reason;
 _swi(Wimp_Poll,_INR(0,1)|_OUT(0),0,mem_block,&reason);
 if (reason==0) event_poll();
}

int main(void)
{
 initialise();
 register_task();
 if (TRUE) event_poll();
 return 0;
}
Huge eh! The app

When compiled, the following is seen in the task display window

The program will now just sit there. It won't interfere with your computer (other than taking a chunk of memory - the chunk size will be the same as the NEXT size in the task window).

This is not a true multi-tasking program as they only way to kill the task (other than a power reset, which is a tad extreme) is to highlight the registered name (here it is C the WIMP 1), press MENU on the mouse and select Quit on the menu.

There is only one other thing missing here which is of upmost importance to a WIMP application, error handling.

A swi which handles errors is Wimp_ReportError. Unfortunately, it's not a multi-tasking error box, but does the job.

Wimp_ReportError (editted)

On entry
	r0	256 byte block of memory
	r1	flags
	r2	application name

On exit
	r0	corrupt
	r1	0 if nothing selected
		1 if OK selected
		2 if cancel
		3-5 for extra buttons

flags control the buttons on the error box. These vary but are all bit set.

Wimp_ReportError flags
Bit	Result
	0	OK box
	1	Cancel box
	2	Highlight Cancel (or OK if there is no Cancel box)
	3	Don't do "Press space or click mouse to continue"
	4	Don't prefix title with "Error from "
	5	Return immediately with r1=0 and box open.
	6	Simulate icon click in box according to bits 0 and 1
	7	Don't beep
	8	Use catagories (dealt with later)
	9-11	Categories
	12-31	Reserved. Must be 0.

As it stands though, the program, while it has the 256 byte block set up, cannot hold the data required for the swi call.

You see the block should contain the following

bytes 0 - 3 : int
bytes 4 - 255 : char, \0 terminated.

The simplest way to do this is to declare error_block as a structure.

By the addition of the following lines, the application will now act more like a real application.

(insert at the beginning)

#include "string.h"

(replace the int *mem_block;)

typedef struct error_block {
                            int value;
                            char text[252];
                           } error_block;

(add prior to initialise())

void report_error(const int error_number,const char *error_message)
{
 error_block error;
 error.value=error_number;
 sprintf(error.text,"%.251s",error_message);
 _swi(Wimp_ReportError,_INR(0,2),error,1,task_name);
}

remove initialise(); function completely and in the main() routine, the line which calls the function.

(changes in event_poll())
delete the if (reason==0) line

switch(reason)
{
 case 0 : report_error(255,"This program does nothing useful");
          break;
}

recompile and you're away.

This time, the program produces the error box and terminates when you select OKAY. This can be avoided by adding back in the if (reason==0) line which had just been deleted.One thing you may have noticed is that with the exception of main(), all the functions are void. The reason for this is that all of the functions don't need to return any values. It can be argued that wimp_poll should return a value, but as you've seen, the loop is simpler to keep within a void system.

There you have it.

You can see that creating an application which will multi-task is quite easy - but then, we've not actually hit upon anything difficult!

Next time, we'll have a deeper look at the wimp poll routine and how to make it far more efficient by using a structure instead of an empty memory block.

Until then, keep plugging away!