C The Wimp (part 3 - Wimp Poll)

As I said in the last instalment, one of the most important parts of any WIMP application is the poll routine.

Recap

Event mask (in r0)

The event mask is a 32-bit number (an int) which either allows or disallows various event types.

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 mask is possibly one of the best examples of using a bit structure (I covered this in C from the Top Part 10). By setting any bit to 1, that operation will be masked out.

Setting (or passing) mask as 0 will mean that the poll will accept all of the event codes passed back.


  Bit   Meaning when set
  0     Don't return NULL reason
  1     Don't return Redraw window; queue it.
  2-3   0
  4     Don't return Pointer Leaving
  5     Don't return Pointer Entering
  6     Don't return Mouse Click; queue it.
  7     0
  8     Don't return Key Pressed; queue it.
  9-10  0
  11    Don't return Lose Caret
  12    Don't return Gain Caret
  13    Don't return pollword nonzero
  14-16 0
  17    Don't return User Message

256 byte block (r1)

In all versions of RISC OS so far, the value returned in r1 after Wimp_Poll is the same as the value passed in.

The 256-byte block can mean anything. It will contain window handles, menu handles, messages, mouse clicks, scroll requests (and the list goes on).

We could set up this memory block very simply with something akin to

int *block=malloc(256);

(which must also be checked to ensure there is enough memory available in the first place!) but given that the value out will be the same as the value in, how can we read this without ending up in a right mess?

In Basic, we would use a rather messy method (in my opinion) of using lines like

CASE (reason%) OF
WHEN 6  : PROCclick(block%!8)
WHEN 24 : PROCkeypress(block%!24)
ENDCASE

This can lead to all sorts of problems in remembering what the contents of block% contain.

In C, we have the struct function to get around this sort of problem. It is far simpler to set up a series of typedef'd structs, then place these inside another master structure within a union and then, as a catcher, have an int array outside of the structure which will take up 256 bytes.

The example here, inside the program, would have a block of memory on the stack reserved for it using malloc.

The major advantage of using this type of structure is that we know what exactly is going on within the poll memory block.

This is also a very good example of using a library to save you time in the long run - could you imagine the pain in the neck problems of having to decode the block by hand or setting up the poll struct at the start of each application?

To save time, I have included on the cover disc (and therefore also on the Archive website) a header file called Wimp_Block. Have a look at it and see how it works.

Reason codes (out r0)

The reason codes are the codes which the poll loop should react upon. These values are only from Wimp_Poll and not from any other event an application will create.


  Reason   Action
  0        No reason
  1        Redraw window
  2        Open window
  3        Close window
  4        Pointer leaving window
  5        Pointer entering window
  6        Mouse click
  7        User drag box
  8        Key pressed
  9        Menu selection
  10       Scroll request
  11       Lose caret
  12       Gain caret
  13       Pollword non-zero
  14-16    Reserved
  17       User message
  18       User message recorded
  19       User message acknowledge

typedef struct poll_win{
                        int window_handle ;
                        int min_x;
                        int min_y;
                        int max_x;
                        int max_y;
                        int scroll_x;
                        int scroll_y;
                        int open_handle;
                        int flags;
                       } poll_win;

typedef struct wimp_block{
                          union{ 
                                int null;
                                pointer redraw;
                                poll_win open_win;
                               } poll;
                          char mem[256];
                         } wimp_block;

Priority :
Highest : 17-19
Next : 1-6, 8, 9
Next : all other codes
Lowest : 0

For the moment, you don't need to worry about what any of these reason codes actually mean; they will be explained as we go along.

The format of the wimp_poll routine is much the same as any other switch/case system.

r1 passes back a reason code which the switch must act upon. The simplest of these, is NULL.

A NULL event means that nothing has happened which the application must act upon. It just sits there doing nothing. When nothing is happening, the RISC OS multitasking system knows this, so dedicates less time to that application until a non-NULL event occurs in the application to wake it up.

All of the other reason codes are for acting on or with a window.

That's all for this time. I'll develop the idea of libraries for the wimp_poll routine next time. Be warned though, it will not be short, but once done, will make life simpler.


Source: Archive Magazine 14.6
Publication: Archive Magazine
Contributor: Paul Johnson