
                       GEM PROGRAMMING by Jonathan White

                                   ARTICLE 8

     Hello again. This month's article  is  a  bit different, as instead of
     dealing with a set of functions  grouped  under a particular topic, we
     are going to look at one particular function. Why? Well, the function,
     called evnt_multi is not  only  the  largest  and most complicated AES
     function. It's one of the most vital to any GEM program.

     The GEM system  communicates  user  input  to  your  program either as
     messages or events. Each type of message or event has its own function
     to detect it happening, but  the  problem  is  all these functions are
     'blind' to the  rest  of  the  inputs.  While  you  are  waiting for a
     keypress,  the  user  could  be  frantically  clicking  the  mouse  on
     something and you would never  get  to  hear  about it, until the user
     pressed a key, then you  would  get  the  keypress and your next mouse
     check would get a flurry of mouse events..

     So, in their wisdom, the Atari  system programmers provided a function
     that is basically 'wait until SOMETHING happens, then, whatever it is,
     tell me about it',. This  is  what  evnt_multi does. Thus, any PROGRAM
     actually devolves down into this..

     START
             evnt_multi
             if mouse event deal with it
             if keyboard event deal with it
             if message deal with it
             redraw screen if necessary
             GOTO START

     Of  course,  each  line  here  hides  a  multitude  of  possible  sins
     (messages, for example, encompass the whole of window management), but
     most GEM programs follow this basic logic.

     The first thing we  should  do,  I  suppose,  is  give  you the 'book'
     definition of evnt_multi()

     WORD evnt_multi(events, clicks, bmask, bstate,  m1flag, m1x, m1y, m1w,
     m1h, m2flag, m2x, m2y, m2w, m2h, msg,  timelo, timehi, mx, my, mb ,ks,
     kc, mc)

     WORD events,  clicks,  bmask,  bstate,  m1flag,  m1x,  m1y,  m1w, m1h,
     m2flag, m2x, m2y, m2w, m2h;
     WORD msg[8];
     WORD timelo, timehi;
     WORD *mx, *my, *mb, *ks, *kc, *mc;

     Jolly good! Now , what does all  this  MEAN, I hear you asking.. Well,
     we'll have to go through them, and  actually you have met most of them
     before in the relevant 'sub function'.

     event   Is a bitmap that tells evnt_multi what events you want it to
             check for, it has (binary) values as follows

             1       MU_KEYBD        wait for keypress
             2       MU_BUTTON       wait for specific mouse state
             4       MU_M1           wait for a mouse/ rectangle event
             8       MU-M2           wait for a second mouse / rectangle
                                     event
             16      MU_MESAG        Wait for a message
             32      MU_TIMER        Wait a specified time


     Thus, if you were interested in mouse  or keyboard clicks, but not any
     of
     the others, you would give event a value of 3.

     Evnt_multi RETURNS a similar value, with bits set to mark which events
     have occurred.

     clicks  The number of times  the  mouse  buttons  must match the given
             state before the  function will return.

     bmask   The mouse buttons to watch; 1= left, 2=right, 3=both

     bstate  The state to watch for; 0=both  up, 1=left down, 2=right down,
             3=both  down.

     m1flag  waiting for the  mouse  to  enter  or  leave  first rectangle;
             0=enter, 1=leave.

     m1x, m1y, m1w, m1h      The first rectangle to watch for.

     m2flag  as m1flag for the second rectangle.

     m2x, m2y, m2w, m2h      The second rectangle to watch for.

     timelo  Low word of a 32 bit timer.

     timehi  High word of a 32 bit timer.
             These two together specify the number of milliseconds to wait
             before returning. Note that, at present, this function has NO
             guarantee of accuracy.

     msg     A 16 byte buffer containing the message received.  For details
             of possible messages see article 3.

     mx      The final horizontal position of the mouse

     my      The final vertical position of the mouse

     mb      The final mouse button state    0=both   up,    1=left   down,
             2=right down, 3=both down

     ks      Settings of the shift key on exit.
                     bit     key
                     0       Right shift
                     1       Left shift
                     2       control
                     3       alt

     kc      The keycode of the key pressed by the user.

     mc      The number  of  times  the  mouse  buttons  matched  the state
             specified in BSTATE. This is always a number of 1 or greater.


     NOTES:

     The function returns when the  first  of the requested events happens,
     rather than when all of them have happened.

     Secondly, the pointer variables  (from  mx  onwards) are ALWAYS filled
     in, regardless of the events requested.


     THE USE OF EVNT_MULTI

     The way I normally use evnt_multi is to  use the value it returns as a
     'seed' for a set of  if  then  statements.  I  dare  say with a little
     thought a 'case' statement could be  used,  but,  while this is a more
     elegant solution, we gain little from the extra effort in real terms..

     Each if statement looks like this..

     result=evnt_multi(...)

     if ((result & MU_KEYBD)==MU_KEYBD)
             {
                     /* do processing for keyboard event */
             }
     if ((result & MU_MESAG)==MU_MESAG)
             {
                     /* do processing for message */
             }
     etc..

     In certain  circumstances  you  might  be  able  to  say  you  are not
     interested in, or will never receive, a  certain type of event, but in
     general you should at  least  make  some  provision for detecting each
     type, especially if  you  intend  to  use  advanced  features  such as
     keyboard shortcuts and windowed dialogue boxes.

     Note also that NONE OF  THESE  EVENTS  ARE EXCLUSIVE. Just because you
     get a  window event, doesn't mean there isn't also a mouse or keyboard
     event waiting to be  processed.  You  aren't  finished once you finish
     processing the first event.

     However, one important fact must be considered. Evnt_multi freezes the
     system until it returns. This  may  not  matter  much in terms of your
     program execution, but it can  have  a  big  effect on systems running
     multitasking OS's such as multiTOS or MagiC (or whatever that's called
     this week). Not that this should stop you using evnt_multi, as all the
     other 'event detectors' have the same  effect, but it is best possibly
     to only use it where you need to, rather than wherever you think it is
     necessary. The reason, for example,  that  you can't  access the menus
     when a dialogue box is on the  screen  is that the system routine that
     displays the dialogue box  (called  form_do,  and  we'll get onto that
     soon enough) uses evnt_multi to trap  events for the box, therefore no
     other part of the system can receive events. One solution is to always
     use timer events as  part  of  your  evnt_multi, therefore the routine
     will always exit after  (say)  a  couple  of milliseconds. This 'time-
     slicing' will make your programs much more multitasking friendly.

     And that just about covers evnt_multi. I find that, with it being such
     a big function, it's always  worth  checking  it has the parameters it
     expects, as that's a common source of (my) mistakes.

     Next month, we start a new major topic, the subject of dialogue boxes.
     These are quite a complex  subject,  so  we  shall  cover them in some
     detail. The first article will deal  with the data structures involved
     in them and the concepts  we  need  to  understand before beginning to
     construct them, a good resource construction  kit is an essential tool
     for the serious GEM  programmer.  There  are  a  couple  of  good PD /
     Shareware ones (MKRSC and ORCS) but  the current Ferrari among them is
     Interface, sold by Compo,  if  they've  got  round  to translating the
     manual yet). So, there  is  no  quick  reference  this month, and I'll
     catch you again soon.

