ADVERT: RMR Software
Please visit the sponsor of this series, and don't forget to say where you heard of them!
3-Lib banner

The Absolute Beginners Guide to OPL

Part 24 - Looping the loop!


Please ensure you have the latest version (1.4) of the RMREvent example program before reading through this tutorial. If you use an older version, some of the text may not make sense.


We're looking today at the way RMREvent handles system, pen and keyboard events without breaking sweat. Most probably, your very first OPL program used GET inside a loop:

WHILE 1
  k%=GET
  IF k%=48 THEN
  etc. etc.
ENDWH

In other words, a single keyboard character is read in each time through the loop and then acted upon. The problem comes when needing to handle such complexities as a user dragging the pen across the screen or a PsiWin backup asking the program to close down. The classic solution to all this is the 'event loop' and it looks remarkably similar to the simple loop above, as we shall see.

The important part of the main procedure is this:
DO
  Run:
UNTIL FOREVER

Screen shot

Before we 'drill down' to examine the Run: procedure in more detail, note the DO...UNTIL loop. we haven't seen this concept before in this series, but the principle is almost identical to WHILE...ENDWH and I hope it's obvious after a moment's study. The UNTIL FOREVER is particularly elegant, and making your source code read as much as possible like plain english is always a goal at the back of the programmer's mind. Note that FOREVER is just a constant set to zero, it's not some magic new OPL keyword! 8-)

Now to explore what Run: actually does.

Screen shot

Reducing it to its general form of:
PROC Run:
DO
  GETEVENT32 A&()
  IF A&(1)=first option
    etc. etc.
  ELSE
    etc. etc.
  ENDIF
UNTIL FOREVER
RETURN
ENDP

we can see that the idea is again to carry on looping forever. Well, at least until an error of some kind, in which case RMR have seen to it that the error is nicely reported, control returned to the main loop and that things carry on happily thereafter. Again, this is another good programming principle: your program should never crash. Sure, errors can happen (printers being off-line, files being unavailable, whatever), but your program should always 'handle' things and survive if at all possible.

Inside the loop, the first command is GETEVENT32 A&() and it's vital to get to grips with this as its operation is the core of the event loop.

GETEVENT32 does just about what it says. It waits for an event (a keystroke, system message, pen tap etc) and returns information about the event in the integer array A&() that you've set up specially. The manual says that the array must have at least 16 elements, but RMR have chosen to give it 20 (just in case). See the OPL manual for exact details on the content of each array element, but the most important is A&(1), which contains the 'event code' for that particular event. It's also important to realise that keypresses and pen taps usually generate more than one event each. For example, pressing a key involves the 'Key down' event, a key event code corresponding to the key pressed and the 'Key up' event. To better understand the way event codes are generated by EPOC, have a look at the OPL/32 "Demo" application in the ROM (you can easily get a copy by choosing the "Create standard files" command from within an OPL/32 document). The "Events" menu option inside the Demo application is an excellent way to get a feel for what your program needs to be able to trap. Try tapping and dragging the pen on different parts of the screen, pressing different keys etc., while you watch the reporting of each event that gets generated. Press the Esc key to quit when you're done.

Screen shot

Back in RMREvent, you can see that the event loop in Run: involves grabbing the event itself, checking whether it's something really major (like needing to close down or being switched to the background) and then passing the code to a procedure called Action_Pen_or_Keypress: for detailed handling. Don't worry for now about the block of lines which detect whether the user had Shift or Control pressed down during the event; suffice it to say that variables Shift% and Control% get set to the appropriate logical state, to put what happens in Action_Pen_or_Keypress: into the proper perspective.

It may seem confusing to you for RMR to use this series of procedures within procedures, but it's really just an extension of the things we've been learning so far, as each procedure does a specific job at the right level. If all of this logic were combined into a single stream of commands in the top level procedure (quite possible), the code would be a lot less elegant. Different authors will always find different degrees of granularity acceptable to them in the great 'performance versus readability' trade-off.

On to Action_Pen_or_Keypress: itself. This is basically one large IF...ELSE...ENDIF sequence - testing Key& for various values and then performing the appropriate actions. RMREvent is, of course, only an example program and so little work actually gets done. In a real-world program, this would be the place in which you call the major routines of your application. Cast your eye down the list of tests on Key& and try to get a feel for what's happening.

Screen shot

Let me pick out a few points of note:

Whew! That's quite enough to stretch the old brain cells for now. More next week!


Go to next lesson | Programming index