C the WIMP
3. Wimp Poll
As I said in the last installment, one of the most important parts of any WIMP application is the poll routine.
Recap
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
Event mask (in r0)
The event mask is a 32 bit number (an int) which either allows or disallows various event types
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
The mask is possibly one of the best examples of using a bit structure (I covered this in C from the Top 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.
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 this memory block up 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 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 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% contains.
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.
For example
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;
Which inside of 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 in
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 that having to decode the block by hand or setting
up the poll struct at the start of each application would have?
To save time, I have included on the cover disc (what do you mean, your subscription doesn't have the cover disc? Upgrade now!!!) 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.
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.
Reason | Action | 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 |
Priority : | Highest : 17 - 19 | Next : 1-6, 8, 9 | Next : all other codes |
Lowest : 0 |
The format of the wimp_poll routine is much the same as any other switch/case system.
r1 passes back as 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. The app 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.