Using the right mouse button with evnt_multi ============================================ You will probably have noticed that very few applications for the Atari make much use of the right mouse button. The reason given was that there was no simple way for a GEM program to do it. It turns out that there has been a legal way to do it all along - Atari finally got around to documenting it a couple of years ago, but only to registered developers. evnt_button ----------- Normally a GEM program is based around an evnt_multi call, but for simplicity I will stick to evnt_button, which only waits for a mouse button event. The parameters are much the same but because it only waits for one event, there are rather less of them :) In C it is int evnt_button( int maxclicks, int mask, int state,short *x, short *y, short *button, short *kstate ) ; It takes three parameters, maxclicks is the number of clicks to wait for, mask is a bitmap showing which buttons you are interested in (1=left, 2=right, 3=both) and state is a bitmap showing what state to wait for. It returns the number of clicks that occurred, and puts the x and y position of the mouse in x and y, the final button state in button and the shift key state in kstate. The way it is normally used is to pass one in mask so that it ignores the right button. Using the right button as a shift key ------------------------------------- The desktop and some other applications use the right button to select things in windows that aren't topped. You have to hold the left button down at the same time. To do this, or use the right mouse button as a shift key like this in any other way, you still use one in the mask, but you check button afterwards to see if the right button was down evnt_button( 1, 0x01, 0x01, &x, &y, &button, &kstate ) ; ^ ^ | Wait for left button down Use left button, ignore right if( button & 0x02 ) /* right button down as well */ else /* left button only */ Waiting for a right button click -------------------------------- It is also possible to wait for a right button click. For example if you want to wait for the right button, and don't care about the left button, evnt_button( 1, 0x02, 0x02, &x, &y, &button, &kstate ) ; ^ ^ | Wait for right button down Use right button, ignore left If you want to wait for both buttons to be down, or just the left or just the right, you have to use three for the mask (1+2) and the state to wait for in state. evnt_button( 1, 0x03, 0x02, &x, &y, &button, &kstate ) ; ^ ^ | Wait for right down, left up Use both buttons evnt_button( 1, 0x03, 0x03, &x, &y, &button, &kstate ) ; ^ ^ | Wait for both to be down Use both buttons Waiting for either click ------------------------ You will notice that you can only wait for one state. There is no way of saying 'Wait for left or right button click'. At least, not if you believe the documentation! Here's where you get the bit not in textbooks :- First... A historical note ----------------- A method used by some older programs, and in fact recommended in the Lattice C manual, involves some clever messing around with vectors. You use the VDI call vex_butv() to install a mouse button handler, and what you do is that whatever click you get you pretend it is a left click and set a variable somewhere to show what sort it really is. Playing around with vectors like this is difficult in C and virtually impossible in basic, but there is a more serious problem with this method. What happens if you are running multitos, and one program tries this? All the other programs will also be affected by your routine and will get all their mouse clicks as left clicks. So Atari announced to developers the official method that had always worked and no one knew about. The bit you won't find in your manuals -------------------------------------- As well as the maximum number of clicks to wait for, the first parameter to evnt_button has another purpose. If you add 0x100 to it (this is 256 in decimal) it means negate the state requirement. For example if the state is zero, it will wait for the button state not to be zero - ie for either button to be down evnt_button( 0x101, 0x03, 0x00, &x, &y, &button, &kstate ) ; ^ ^ ^ | | Wait for NOT(no buttons down ) | Look at both buttons Negate state requirement, wait for one click If you are interested in mouse up events, then you have to wait for one of the buttons to be pressed and then either wait for the state to be zero, or wait for it NOT to be whatever it then is. evnt_button( 0x101, 0x03, 0x00, &x, &y, &button, &kstate ) ; /* Right, now one or the other or both is down */ evnt_button( 0x101, 0x03, button, &x, &y, &button, &kstate ) ; ^ Wait for NOT( previous state ) Summary ------- Using the right button isn't as difficult as it's made out to be. Although all the examples I have done are in C, this should work in any language that lets you call GEM directly, such as Hisoft Basic, GFA Basic 3 or Assembly language (see also ASSEMBLY\EVNT_BUT folder). The information was originally released by Mike Fulton (Atari developer support). Warwick Allison posted it onto the Usenet newsgroup with some accompanying notes, and then Steve Taylor posted a copy of his message onto Turbonet (where I read it). Mark Baker Email : mark.baker@mettav.royle.org Fidonet 2:254/108.17 Turbonet 100:1011/0.17 NeST 90;102/140.17 Atarinet 51:502/100.17