$if 0
    ķ                        PowerBASIC v3.20
 Ĵ          DASoft          ķ
   Ķ    Copyright 1995     DATE: 1995-10-01 ķ
    FILE NAME   EVENTS  .TXT           by            
                               Don Schullian, Jr.                      
   ͼ                                          
  A license is hereby granted to the holder to use this source code in   
  any program, commercial or otherwise,  without receiving the express   
  permission of the copyright holder and without paying any royalties,   
  as long as this code is not distributed in any compilable format.      
   IE: source code files, PowerBASIC Unit files, and printed listings    
 ͼ 
                   ....................................                   
   ͼ
$endif

BUZZ WORDS:
  Event - a rectangular area of the screen containing 1 or more Items
  Item  - a rectangular area inside an Event
  Hot%  - the mouse cursor is on an Item with a/the button down
  Hit%  - the mouse cursor is on an Item and a/the button has been clicked
  Click - a button was down and is now up (released)

Events are nothing more than visible areas of the screen that contain one,
or more, mouse-sensitive boxes. If the word "box" or "window" works better
for you that's just fine;  the main thing to remember is that these events
are self aware.  The figure below displays 3 stacked events, one on top of
another. Notice that events 2 and 3 cover some portion of the Items in the
first event.

Before we get started; just a moment to make a quick explanation. All the
routines for handling  events work with either text mode or graphics mode.
There is one entry point explicitly for text mode ( fEventOpenT? ) and one
for graphics mode  ( fEventOpenG? ).  They both do the same thing the only
difference is that the  text version  accepts text style addresses and the
graphics version accepts graphics style addresses.

row 1     [ EVENT 1 ]Ŀ
                                    [ EVENT 2 ]Ŀ
            ITEM #1 ITEM #2 ITEM #                              
                 ߳  ITEM #1 ITEM #2 ITEM #3  
            ITEM #4 ITE[ EVENT 3 ]Ŀ    
               ߳                              
          ĳ  ITEM #1 ITEM #2 ITEM #3  
   fig.1                          
                         

To make events "aware" you will dim an array for the NumberOfItems + 1
by 4 for the row/column corners eg. DIM E?(1:4,NumberOfItems?). Then
the coordinates of the Event are loaded into the 0th element(s):
               E?(1,0) = TopRow     : E?(2,0) = LeftColumn
               E?(3,0) = BottomRow  : E?(4,0) = RightColumn

Each Item within the Event is then loaded into it's respective element(s):
      E?(1,1) = 3  :  E?(2,1) = 14 : E?(3,1) = 4  :  E?(4,1) = 22
      E?(1,2) = 3  :  E?(2,2) = 23 : E?(3,2) = 4  :  E?(4,2) = 30
      E?(1,3) = 3  :  E?(2,3) = 31 : E?(3,3) = 4  :  E?(4,3) = 39
      E?(1,4) = 5  :  E?(2,4) = 14 : E?(3,4) = 6  :  E?(4,4) = 22
      E?(1,5) = 5  :  E?(2,5) = 23 : E?(3,5) = 6  :  E?(4,5) = 30
      E?(1,6) = 5  :  E?(2,6) = 31 : E?(3,6) = 6  :  E?(4,6) = 39
                     ( Reference Event 1 above )

The array is then passed to fEventOpenT? along with the number of items in
the event. What is returned is the newly created Event Number. This number
can be used by the calling function to determine if a "hit" belongs to it-
self or to another routine and take appropriate action.

Say What?!

Each new event can cover an existing event as shown above.  If,  lets say,
Event 3 is operating and our user puts the mouse on Item #1 in Event 1 and
pops the button. 2 things can happen:
   1) Event 3 <REQUIRES> an answer so no action is taken on the hit in N1
   2) Event 3 is told that it is no longer required and bails out
      Event 2 (which called Event 3) checks to see if the "hit" belongs to
        it and determines if an answer is <REQUIRED> or not and can:
          1) bail out to Event 1
             Event 1 accepts the "hit" and takes appropriate action
          2) stay in Event 2 until an answer is given
          3) re-call Event 3

In "human" language that would be something like:
  Event 1 is an editing screen full of fields
  Event 2 is a menu of things to do to the data being edited
  Event 3 is a help screen for the menu/editing
            (Eat your heart out Billy)

The only rules that are iron-clad are:
  0) If you don't call EventSetup you get 5 EventBoxes and 100 ItemBoxes
  1) Events must be opened and closed in order
     ie: you can't close #1 until you close #2, etc
  2) Higher event numbers preceded lower event numbers when being checked
     ie: FOR E% = LastEvent% TO 1 STEP -1
           IF MouseHitIsInsideEventBox% THEN
             FOR I% = LastItemInEvent% TO 1 STEP -1
               IF AnItemWasHit% THEN
                 GotOne! = -1
                 EXIT FUNCTION
               END IF
             NEXT
           END IF
         NEXT
  3) You must have created a FUNCTION called fGetKey%
     SEE: M_SETUP.DMO for a good example

Now you've got it!

 CALL EventSetup( NumberOfEvents?, NumberOfItems?? )
   Default is 5,100 which would probably be more than enough for most work
   but you may call this routine to fine-tune your program or to reset all
   the SHARED STATIC variables in the PBU.

 MyEvent? = fOpenEventT?( E?(1,0),  NumberOfItems? )
 MyEvent? = fOpenEventG?( E??(1,0), NumberOfItems? )
   If we are using our array from above then NumberOfItems? would equal 6
   as it is assumed that the event box is included in the array. This way
   is easier on the routines you write. MyEvent? is the current event N.

 CALL EventClose
   Just before exiting the calling routine you will close it's event.

 G% = fEventKey%( HotItem%, ExetKey$ )
   HotItem% (INCOMING)  is the number of the currently "hot" item
   HotItem% (RETURNING) if < 0 the new "hot" item button in "DOWN" status
                        if > 0 the new "hot" item button released (CLICK)
                        if = 0 a key was pressed ( no mouse action )
   ExetKey$ is a list of all acceptable keys or
            if NULL then any key

   RULES:  fEventKey% will not return until:
             1) an acceptable key is pressed
             2) the mouse is "drug" to an item other than ABS(HotItem%)
             3) the button has been "clicked"

           $INCLUDE "KEYCODES.INC"
           DO
             G% = fEventKey%( Hit%, CHR$(027,0,013,0) )
             SELECT CASE G%
               CASE 0                      ' mouse action
                 IF Hit% < 0 THEN             ' button down
                   ELSEif Hit% > 0 THEN       ' <CLICK>
                 END IF
               CASE %MOUSE_DOWN               ' other Event Box is Hot
               CASE %MOUSE_CLICK              ' other Event Box/Item Hit!
               CASE %ENTER_key                ' <ENTER>
               CASE %ESC_key                  ' <ESC>
             END SELECT
           LOOP

 CALL EventCLEAR
   clears keyboard  : SEE ClearKeyboard
   awaits until all mouse buttons are "UP"

 WhichEvent? = fEventLastBox?                      ' these 2 functions are
   returns the value of the last "hit" event box   ' used by the events
                                                   ' "UNDER" the last event
 WhichItem?  = fEventLastItem?                     ' that bailed out to get
   returns the last "hit" item of fEventLastBox?   ' the current mouse info

