In this series we will be bringing you a variety of procedures and functions which we hope will form a library of useful building blocks. These may be used when and where you choose, and may be incorporated into a program either by typing the code in directly, by appending it using the Arc's APPEND instruction (which automatically renumbers the incoming program lines), or by using the LIBRARY or INSTALL statements (see RISC User Volume 1 Issue 2).
Although the WIMP provides a useful environment for the Arc, it is not easy to program, and carries a significant overhead in length of code. For those who sometimes prefer to go it alone, we begin our procedure library with two mouse related utilites which do not make use of the WIMP.
This first procedure repeatedly checks the mouse and/or keyboard to see if the user has supplied an input of the required type. The type of input is specified by a single parameter, as follows:
Value Effect 0 Wait for button release 1-7 Wait for specified button press 8 Wait for any button 16 Wait for keyboard input
For example if you insert the line:
PROCmousewait(4)
into a program, the program will halt until the Select button is pressed (since on the Arc, Select has the value 4, Menu 2 and Adjust 1). To make the procedure return after any button is pressed, use:
PROCmousewait(8)
If you add 16 to the parameter, then it will also return if the user presses any key on the keyboard. Thus:
PROCmousewait(1+16)
will wait until any key, or mouse button 1 (Adjust) is pressed, while:
PROCmousewait(16)
will wait for any key, but ignore the state of the mouse.
When the procedure returns it sets four global variables: w%, x%, y% and z%. The first takes the ASCII value of any key pressed (-1 if none pressed), while x%, y% and z% are the x and y co-ordinates of the mouse pointer at the time of selection, and z% is the value of the button pressed, or 0 if the mouse was not used.
If you call the procedure with the parameter zero, the routine will return as soon as all mouse buttons are released. This is very useful, because, even though we can flush the mouse buffer with *FX21,9, this does not prevent a user's single click from being read as a whole sequence of responses. The only way to avoid this is to wait until the mouse is clear of presses between button checks. The procedure caters for this in a second way: if you place a negative sign in front of the calling parameter, the procedure will first wait until no button is pressed, and then wait for the requested one.
This very short function determines whether the mouse pointer is within a specified rectangle, and is extremely useful in the processing of mouse selections. It takes six parameters: the x and y co-ordinates of the pointer (as read by PROCmousewait for example), the bottom left-hand co-ordinates of the rectangle in question, and its width and height respectively. I have added a "d" to the function name as a reminder that the last two parameters are not absolute co-ordinates, but "differences".
As an example of the use of this function, the following two lines will wait for the Select button to be pressed, and then check if the pointer is within a rectangle at X,Y and of width W and height H:
PROCmousewait(-4)
IF FNpositiond(x%,y%,X,Y,W,H) VDU7
If the pointer is over the defined area, a beep will sound.
The short program accompanying the two procedures in the listing provides a further example of their use. If you run it, a rectangle will appear, and each time you press the Select button, the word "Inside" or "Outside" will be displayed, indicating the position of the pointer relative to the rectangle.
Next month we will provide procedures to streamline the task of drawing selection boxes on the screen, and of determining which one has been selected by the user.
10 REM >Mse1prcs
20 REM Procedure/Function Library
30 REM Version A 0.3
40 REM Author Lee Calcraft
50 REM RISC User April 1989
60 REM Program Subject to Copyright
70 :
80 MODE12
90 PRINT"Select to test grid"
100 PRINT"or Menu to quit"
110 OFF:*POINTER
120 RECTANGLE 200,300,800,100
130 REPEAT
140 PROCmousewait(-8)
150 IF z%=4 THEN
160 PRINTTAB(0,6);
170 IF FNpositiond(x%,y%,200,300,800,100) PRINT"Inside " ELSE PRINT"Outside"
180 ENDIF
190 UNTIL z%=2
200 ON
210 END
220 ==================================
230 DEFPROCmousewait(n)
240 REM 0-7: Wait for this mouse state
250 REM neg: Wait for zero first
260 REM 8: Wait for any button
270 REM 16: Wait for keypress
280 LOCAL anypress,inkey,m
290 *FX21,9
300 IF n<0 THEN PROCmousewait(0):n=ABS(n)
310 IF (n AND 16)>0 THEN inkey=TRUE:*FX21
320 IF (n AND 8)>0 THEN anypress=TRUE
330 m=n AND 7:w%=-1
340 REPEAT
350 MOUSE x%,y%,z%
360 IF inkey THEN w%=INKEY(0)
370 UNTIL (z%=m AND NOT (n>7 AND m=0)) OR (anypress AND (z%>0)) OR (inkey AND (w%>-1))
380 ENDPROC
390 ==================================
400 DEFFNpositiond(x%,y%,x1%,y1%,xd%,yd%)
410 =x%>x1% AND x%<x1%+xd% AND y%>y1% AND y%<y1%+yd%
420 ==================================