home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk470.lzh / KeyMenu / KeyMenu-Handler.asm < prev    next >
Assembly Source File  |  1991-03-10  |  81KB  |  1,269 lines

  1. *******************************************************************************
  2. *
  3. * KeyMenu-Handler.asm  V1.03  02 Mar 1991
  4. *
  5. *
  6. *
  7. *   This program is loaded by 'KeyMenu' and stays resident in the 
  8. *   system until the user runs KeyMenu with the 'QUIT' option.
  9. *   
  10. *
  11. *
  12. * Modification History:
  13. *
  14. *       Date       By                       Modification
  15. *     --------  --------------------    --------------------------------------
  16. *     09/09/89  Ken Lowther             Initial release, V1.01
  17. *
  18. *     09/13/89  Ken Lowther             V1.02 - added qualifier keys to move
  19. *                                       mouse pointer to first/last item.
  20. *
  21. *     09/24/89  Ken Lowther             V1.02 - corrected positioning of mouse
  22. *                                       pointer on menus. The pointer was being
  23. *                                       positioned 1 pixel to the left. This
  24. *                                       really only mattered when the menu is
  25. *                                       1 pixel wide.
  26. *
  27. *     09/30/89  Ken Lowther             V1.02 - Keymenu no longer creates a 
  28. *                                       process for this module. Changed 'main'
  29. *                                       to set the DOS return code and return
  30. *                                       in case this module gets 'execute'ed.
  31. *
  32. *     10/03/89  Ken Lowther             V1.02 - Changed to ignore the 1st 
  33. *                                       occurance of a 'repeated' key. This
  34. *                                       is to fix a problem that occurs when
  35. *                                       there are more than 2 bitplanes in the
  36. *                                       screen.
  37. *
  38. *     03/02/91  Ken Lowther             V1.03 - Modified to use PointerPos 
  39. *                                       events rather than RawMouse events to
  40. *                                       position intuition's pointer. This 
  41. *                                       allows Keymenu to co-exist with most
  42. *                                       mouse accelerators.
  43. *
  44. *     03/02/91  Ken Lowther             V1.03 - Re-installed intuition pointer
  45. *                                       blanking option.
  46. *
  47. *******************************************************************************
  48.             nolist
  49.             include "macros.i"
  50.             include "exec/types.i"
  51.             include "exec/strings.i"
  52.             include "exec/nodes.i"
  53.             include "exec/ports.i"
  54.             include "exec/execbase.i"
  55.             include "exec/ables.i"
  56.             include "exec/interrupts.i"
  57.             include "exec/memory.i"
  58.             include "devices/inputevent.i"
  59.             include "intuition/intuition.i"
  60.             include "libraries/dos.i"
  61.             include "libraries/dosextens.i"
  62.             include "keymenu-handler.i"
  63.             list 
  64.             nomlist
  65.  
  66. *******************************************************************************
  67. *                                                                             *
  68. *   Displacements into Select routine.                                        *
  69. *                                                                             *
  70. *******************************************************************************
  71. s_top               equ                 si_top-si_jmp-2
  72. s_adjacent_top      equ                 si_adjacent_top-si_jmp-2
  73. s_adjacent_up       equ                 si_adjacent_up-si_jmp-2
  74. s_up                equ                 si_up-si_jmp-2
  75. s_adjacent_right    equ                 si_adjacent_right-si_jmp-2
  76. s_right             equ                 si_right-si_jmp-2
  77. s_leftmost          equ                 si_leftmost-si_jmp-2
  78. s_adjacent_down     equ                 si_adjacent_down-si_jmp-2
  79. s_bottom            equ                 si_bottom-si_jmp-2
  80. s_adjacent_left     equ                 si_adjacent_left-si_jmp-2
  81. s_down              equ                 si_down-si_jmp-2
  82. s_left              equ                 si_left-si_jmp-2
  83. s_rightmost         equ                 si_rightmost-si_jmp-2
  84.  
  85. gbl         equr    a4                  ; handler global area
  86.  
  87.             cseg
  88.             near    code
  89. *******************************************************************************
  90. *                                                                             * 
  91. *       main                                                                  *
  92. *                                                                             *
  93. *       This is the main routine of KeyMenu-Handler. It is where execution    *
  94. *       begins. Here we perform the following functions:                      *
  95. *           1) Initialize program. This consists of determining what task we  *
  96. *              are and finding the public message port that the KeyMenu       *
  97. *              program created for us. If the port doesn't exist or if        *
  98. *              another task already owns it, we just exit (this can happen if *
  99. *              the user somehow manages to run this program instead of        *
  100. *              KeyMenu). The global area behind the message port, created by  *
  101. *              Keymenu, is updated with our task address, the signal number   *
  102. *              to use to send messages to us, the address of our input        *
  103. *              handler routine and the version number of this program. We     *
  104. *              then signal KeyMenu that we are initialized.                   *
  105. *           2) Wait for one of two events to occur. Either a message has been *
  106. *              directed to us via the public message port or KeyMenu has      *
  107. *              signalled us to stop. Process the event as appropriate.        *
  108. *           3) Step 2, above, is repeated until our 'active' flag is reset.   *
  109. *              This occurs when, at our request, the input_handler sends a    *
  110. *              message to us indicating it is ready to stop. We then cleanup  *
  111. *              any resources we have allocated and return to AmigaDOS.        *
  112. *                                                                             *
  113. *       Input Registers:                                                      *
  114. *           None.                                                             *
  115. *                                                                             *
  116. *       Output Registers:                                                     *
  117. *           None.                                                             *
  118. *                                                                             *
  119. *******************************************************************************
  120. main        movem.l mainregs,-(sp)          ; save entry registers
  121. *-----------------------------------------------------------------------------*
  122. *           do initialization                                                 *
  123. *-----------------------------------------------------------------------------*
  124.             move.l  AbsExecBase,a6          ; setup base for exec.library
  125.             sub.l   a1,a1                   ; set to find our task
  126.             Call    FindTask                ; get pointer to our task
  127.             move.l  d0,a2                   ; get task address
  128.             clr.l   pr_ConsoleTask(a2)      ; clear console handler pointer
  129.             lea     myport(pc),a1           ; pointer to port name
  130.             Call    FindPort                ; go find our port
  131.             tst.l   d0                      ; does it exist ?
  132.             beq     main060                 ; no, must have it, get out
  133.             move.l  d0,gbl                  ; save pointer to our world
  134.             tst.l   MP_SIGTASK(gbl)         ; is a task already there ?
  135.             bne     main060                 ; yes, branch
  136. *-----------------------------------------------------------------------------*
  137. *           everything seems ok, update our global area and signal KeyMenu to *
  138. *           go ahead and add our input_handler routine to the input.device    *
  139. *-----------------------------------------------------------------------------*
  140.             moveq.l #-1,d0                   
  141.             Call    AllocSignal             ; get a signal for our task
  142.             move.b  d0,MP_SIGBIT(gbl)       ; save the signal number
  143.             move.l  a2,MP_SIGTASK(gbl)      ; make our task the one to signal
  144.             move.l  a2,gb_handtask(gbl)
  145.             lea     input_handler(pc),a1    ; get addr of input handler code
  146.             move.l  a1,gb_handler+IS_CODE(gbl) ; put it in interrupt struct
  147.             jsr     dosignal                ; go signal companion task
  148.             moveq.l #1,d4                   ; set active flag
  149. *-----------------------------------------------------------------------------*
  150. *           if we are still active, wait for something to happen              *
  151. *-----------------------------------------------------------------------------*
  152. main010     tst.w   d4                      ; are we still active ?
  153.             beq     main050                 ; no, go clean things up
  154.             clr.l   d1                      ; clear work register
  155.             move.b  MP_SIGBIT(gbl),d1       ; get signal bit number
  156.             bset.l  d1,d0                   ; create signal mask
  157.             bset.l  #SIGBREAKB_CTRL_C,d0    ; set break bit
  158.             Call    Wait                    ; wait for something to happen
  159. *-----------------------------------------------------------------------------*
  160. *           An event occurred! Determine if KeyMenu signalled 'CTRL C'        *
  161. *           telling us to stop. If not, there must be a message waiting on    *
  162. *           the message port.                                                 *
  163. *-----------------------------------------------------------------------------*
  164.             btst.l  #SIGBREAKB_CTRL_C,d0    ; did user request us to stop ?
  165.             beq     main015                 ; no, branch
  166.             bset.b  #FLAGB_Stop_requested,gb_flags(gbl) ; set stop requested
  167.                                             ; this tells the input handler to 
  168.                                             ; stop the next time it is entered
  169.             bra     main010                 ; go wait for input handler to stop
  170. *-----------------------------------------------------------------------------*
  171. *           get a message from the message port and determine what it is      *
  172. *-----------------------------------------------------------------------------*
  173. main015     move.l  gbl,a0                  ; get address of message port
  174.             Call    GetMsg                  ; get any message placed there
  175.             tst.l   d0                      ; was there a message queued ?
  176.             beq     main010                 ; no, branch
  177.             move.l  d0,a2                   ; save message address
  178.             cmp.w   #req_stopped,LN_NAME(a2) ; stop message ?
  179.             bne     main020                 ; no, branch
  180. *-----------------------------------------------------------------------------*
  181. *           A 'stop' message was received from the input handler. Clear our   *
  182. *           'active' flag.                                                    *
  183. *-----------------------------------------------------------------------------*
  184.             clr.l   d4                      ; yes, clear active flag
  185. main020     cmp.w   #req_clearpointer,LN_NAME(a2) ; clear pointer request ?
  186.             bne     main030                 ; no, branch
  187. *-----------------------------------------------------------------------------*
  188. *           A 'clearpointer' request was received from the input handler.     *
  189. *           This causes us to reset the intuition pointer to its previous     *
  190. *           condition prior to our blanking it.                               *
  191. *-----------------------------------------------------------------------------*
  192.             tst.l   gb_Pointer(gbl)         ; is any pointer info saved ?
  193.             beq     main025                 ; no, branch
  194.             move.l  gb_window(gbl),a0       ; yes, setup to do 'SetPointer'
  195.             move.l  gb_Pointer(gbl),a1      ; this will restore the window's
  196.             move.b  gb_PtrHeight(gbl),d0    ; custom pointer
  197.             ext.w   d0
  198.             ext.l   d0
  199.             move.b  gb_PtrWidth(gbl),d1
  200.             ext.w   d1
  201.             ext.l   d1
  202.             move.b  gb_XOffset(gbl),d2
  203.             ext.w   d2
  204.             ext.l   d2
  205.             move.b  gb_YOffset(gbl),d3
  206.             ext.w   d3
  207.             ext.l   d3
  208.             Call    SetPointer,gb_IBase(gbl) ; restore the custom pointer
  209.             clr.l   gb_Pointer(gbl)         ; clear pointer info
  210.             bra     main030
  211. main025     move.l  gb_window(gbl),a0
  212.             Call    ClearPointer,gb_IBase(gbl) ; reset back to intuition's
  213.                                                ; pointer
  214. main030     cmp.w   #req_setpointer,LN_NAME(a2) ; set pointer request ?
  215.             bne     main040                 ; no, branch
  216. *-----------------------------------------------------------------------------*
  217. *           A 'setpointer' request was received from the input handler. This  *
  218. *           causes us to save info about the current custom pointer, if any,  *
  219. *           and call 'SetPointer' using our own 'blank' pointer. This removes *
  220. *           the pointer from the user's view during menu operations.          *
  221. *-----------------------------------------------------------------------------*
  222.             move.l  gb_window(gbl),a0        
  223.             tst.l   wd_Pointer(a0)          ; is there a custom pointer ?
  224.             beq     main035                 ; no, branch
  225.             move.l  wd_Pointer(a0),gb_Pointer(gbl) ; save custom pointer info
  226.             move.b  wd_PtrHeight(a0),gb_PtrHeight(gbl)
  227.             move.b  wd_PtrWidth(a0),gb_PtrWidth(gbl)
  228.             move.b  wd_XOffset(a0),gb_XOffset(gbl)
  229.             move.b  wd_YOffset(a0),gb_YOffset(gbl)
  230. main035     move.l  gb_blank_ptr(gbl),a1    ; setup to call 'SetPointer'
  231.             moveq.l #-1,d0
  232.             moveq.l #-1,d1
  233.             clr.l   d2
  234.             clr.l   d3
  235.             Call    SetPointer,gb_IBase(gbl)
  236. *-----------------------------------------------------------------------------*
  237. *           free the message we received and loop to see if there is more     * 
  238. *-----------------------------------------------------------------------------*
  239. main040     clr.l   d0
  240.             move.l  a2,a1                   ; setup addr of block to free
  241.             move.w  MN_LENGTH(a1),d0        ; setup length of block to free
  242.             Call    FreeMem                 ; go free it
  243.             bra     main015                 ; loop for next message
  244.  
  245. myport      portname
  246.             
  247. *-----------------------------------------------------------------------------*
  248. *           We are no longer active, cleanup after ourselves and get out      *
  249. *-----------------------------------------------------------------------------*
  250. main050     move.l  gbl,a0                  ; get address of message port
  251.             Call    GetMsg                  ; get any message placed there
  252.             tst.l   d0                      ; was there a message queued ?
  253.             beq     main055                 ; no, branch
  254.             move.l  d0,a1                   ; setup to free the block
  255.             clr.l   d0
  256.             move.w  MN_LENGTH(a1),d0        ; setup length of block to free
  257.             Call    FreeMem                 ; go free it
  258.             bra     main050                 ; loop for next message
  259. main055     clr.l   d0
  260.             move.b  MP_SIGBIT(gbl),d0       ; get signal number
  261.             Call    FreeSignal              ; go free it
  262.             Forbid
  263.             jsr     dosignal                ; go signal companion task
  264. main060     movem.l (sp)+,mainregs          ; restore entry registers
  265.             rts                             ; return to AmigaDOS
  266. mainregs    reg     d1-d7/a0-a6
  267.  
  268.  
  269. *******************************************************************************
  270. *                                                                             * 
  271. *       dosignal                                                              *
  272. *                                                                             *
  273. *       Send a signal to our companion task (should be KeyMenu).              *
  274. *                                                                             *
  275. *       Input Registers:                                                      *
  276. *           a4 - global work area                                             *
  277. *                                                                             *
  278. *       Output Registers:                                                     *
  279. *           None.                                                             *
  280. *                                                                             *
  281. *******************************************************************************
  282. dosignal    clr.l   d1                      ; clear work register
  283.             move.b  gb_tasksignum(gbl),d1   ; get keymenu task signal number
  284.             bset.l  d1,d0                   ; create signal mask
  285.             move.l  gb_task(gbl),a1         ; get task to signal
  286.             Call    Signal                  ; signal the task that we are ready
  287.             rts
  288.  
  289. ******************************************************************************
  290. *                                                                             * 
  291. *       input_handler                                                         *
  292. *                                                                             *
  293. *       This routine is added to the input.device's list of handlers by the   *
  294. *       KeyMenu program. It is called whenever an input event, such as a      *
  295. *       keyboard press or mouse movement, occurs. In general, the input event *
  296. *       chain is scanned to see if the user has pressed any one of the        *
  297. *       various keys that we care about. If so, the input event representing  *
  298. *       that keypress is replaced with a mouse event(s) to accomplish         *
  299. *       KeyMenu's purpose. Note that the memory associated with event(s) that *
  300. *       are removed from the list actually belongs to the creator of that     *
  301. *       event. It is the event creator's responsibility to free this memory.  *
  302. *       See the RKM for more info about input handlers and the input.device   *
  303. *                                                                             *
  304. *       Input Registers:                                                      *
  305. *           a0 - input event chain, a forward reference linked list with the  *
  306. *                last event in the chain containing a 'NULL' reference.       *
  307. *           a1 - global work area                                             *
  308. *                                                                             *
  309. *       Output Registers:                                                     *
  310. *           d0 - new input event chain                                        *
  311. *                                                                             *
  312. *******************************************************************************
  313. input_handler
  314.  
  315. laste       equr    a1                      ; last event handled in chain
  316. ev          equr    a2                      ; original event passed to us
  317. ep          equr    a3                      ; current event pointer
  318.  
  319.             movem.l ihregs,-(sp)            ; save registers
  320.             move.l  a1,gbl                  ; setup pointer to our world
  321.             move.l  a0,ev                   ; save pointer to input event chain
  322. *-----------------------------------------------------------------------------*
  323. *           If 'stop' has been posted, check to see if there is currently a   *
  324. *           menu active. If so, wait for the user to get out of it otherwise  *
  325. *           send a 'stop' message (actually means 'ready to stop') to the     *
  326. *           KeyMenu-Handler process.                                          *
  327. *-----------------------------------------------------------------------------*
  328.             btst.b  #FLAGB_Stop_requested,gb_flags(gbl) ; stop requested ?
  329.             beq     ih010                   ; no, branch
  330.             btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
  331.             bne     ih010                        ; yes, branch
  332.             btst.b  #FLAGB_Stopped,gb_flags(gbl) ; stop already been posted ?
  333.             bne     ih010                        ; yes, branch
  334.             moveq.l #req_stopped,d0         ; set type fo request to send
  335.             jsr     sendrequest             ; go send it
  336.             bset.b  #FLAGB_Stopped,gb_flags(gbl) ; indicate stop has been posted
  337. *-----------------------------------------------------------------------------*
  338. *           Begin stepping through the input event chain                      *
  339. *-----------------------------------------------------------------------------*
  340. ih010       FORBID                          ; don't let anyone mess with events
  341.             sub.l   laste,laste             ; clear last event register
  342.             move.l  ev,ep                   ; setup event work register
  343.             bclr.b  #FLAGB_Events_inserted,gb_flags(gbl) ; clear inserted flag
  344.             bra     ih040                   ; go see if an event exists
  345. ih015       cmp.b   #IECLASS_RAWKEY,ie_Class(ep) ; Raw key event ?
  346.             bne     ih025                   ; no, branch
  347. *-----------------------------------------------------------------------------*
  348. *           This is a RAWKEY event (keypress/keyrelease).                     *
  349. *-----------------------------------------------------------------------------*
  350.             jsr     Check_RawKey_Event      ; go look at this one
  351.             beq     ih030                   ; do we keep it ? yes, branch
  352.             move.l  laste,d0                ; was there a previous event ?
  353.             bne     ih020                   ; yes, branch
  354.             move.l  ie_NextEvent(ep),ev     ; drop the event
  355.             bra     ih035                     
  356. ih020       move.l  ie_NextEvent(ep),ie_NextEvent(laste)
  357.             bra     ih035                   ; loop
  358. *-----------------------------------------------------------------------------*
  359. *           Here we look for a 'MENUDOWN' event. If this occurs while we have *
  360. *           a menu active, it indicates that the user pressed the right mouse *
  361. *           button intending to take over menu selection with the mouse.      *
  362. *-----------------------------------------------------------------------------*
  363. ih025       cmp.b   #IECLASS_RAWMOUSE,ie_Class(ep) ; is this a raw mouse event ?
  364.             bne     ih030                   ; no, branch
  365.             cmp.w   #MENUDOWN,ie_Code(ep)   ; is it a menu down event ?
  366.             bne     ih030                   ; no, branch
  367.             btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu in progress ?
  368.             beq     ih030                   ; no, branch
  369.             bclr.b  #FLAGB_MActive,gb_flags(gbl) ; give control of menu to mouse
  370.             moveq.l #req_clearpointer,d0
  371.             jsr     sendrequest             ; go reset intuition pointer
  372. *-----------------------------------------------------------------------------*
  373. *           Now we look to see if we inserted any events in the chain. If so, *
  374. *           we must get out. This is because we only have a fixed number of   *
  375. *           input event areas allocated (3) and they can be used only once    *
  376. *           per invocation of the handler. This could be a potential problem  *
  377. *           in that we could miss events that we care about (since we don't   *
  378. *           look at the remaining events in the event chain). However, this   *
  379. *           is nothing that would cause harm to the system. It would just     *
  380. *           appear to the user as though a keypress intended to cause a menu  *
  381. *           operation didn't take. This is better than incuring the overhead  *
  382. *           and buffer management problems associated with dynamically        *
  383. *           allocating input events.                                          *
  384. *-----------------------------------------------------------------------------*
  385. ih030       move.l  ep,laste                ; save this event
  386. ih035       btst.b  #FLAGB_Events_inserted,gb_flags(gbl) ; were events inserted?
  387.             bne     ih045                   ; yes, branch
  388. *-----------------------------------------------------------------------------*
  389. *           Setup to process the next event if one exists, otherwise get out  *
  390. *-----------------------------------------------------------------------------*
  391.             move.l  ie_NextEvent(ep),ep     ; get next event
  392. ih040       move.l  ep,d0                   ; set cc
  393.             bne     ih015                   ; go check it
  394. ih045       PERMIT
  395.             move.l  ev,d0                   ; pass event on
  396.             movem.l (sp)+,ihregs            ; restore registers
  397.             rts                             ; return to input device
  398. ihregs      reg     a0/a1/a2/a3/a4/a6
  399.  
  400. *******************************************************************************
  401. *                                                                             * 
  402. *       sendrequest                                                           *
  403. *                                                                             *
  404. *       This routine is called by the input handler when it wishes to send a  *
  405. *       request message to the KeyMenu-Handler process. There are currently   *
  406. *       three kinds of messages that may be sent:                             *
  407. *           1)  req_setpointer, to blank the intuition pointer during menu    *
  408. *               operations.                                                   *
  409. *           2)  req_clearpointer, to restore the intuition pointer when menu  *
  410. *               operations are finished.                                      *
  411. *           3)  req_stopped, to signal that the handler is ready to stop.     *
  412. *       Sendrequest is always called regardless of the setting of the hide    *
  413. *       intuition pointer option. This is where we determine whether or not   *
  414. *       to actually send the request.                                         *
  415. *                                                                             *
  416. *       Input Registers:                                                      *
  417. *           d0 - type of request to be sent                                   *
  418. *           a4 - global work area                                             *
  419. *                                                                             *
  420. *       Output Registers:                                                     *
  421. *           none.                                                             *
  422. *                                                                             *
  423. *******************************************************************************
  424. sendrequest movem.l sendreqregs,-(sp)       ; save entry registers
  425.             btst.b  #FLAGB_Blank_pointer,gb_flags(gbl) ; blank pointer option on ?
  426.             bne     sendreq010              ; yes, branch
  427.             cmp.w   #req_stopped,d0         ; is this a 'stopped' request ?
  428.             bne     sendreq020              ; no, branch
  429. sendreq010  move.l  d0,d2                   ; save request type
  430.             move.l  #MEMF_CLEAR+MEMF_PUBLIC,d1 ; set attributes
  431.             move.l  #MN_SIZE,d0             ; set size of block
  432.             Call    AllocMem                ; go allocate a block
  433.             tst.l   d0                      ; was a block given to us ?
  434.             beq     sendreq020              ; no, branch
  435.             move.l  d0,a1                   ; yes, save pointer to block
  436.             move.w  d2,LN_NAME(a1)          ; format message
  437.             clr.l   MN_REPLYPORT(a1)
  438.             move.w  #MN_SIZE,MN_LENGTH(a1)
  439.             move.l  gbl,a0
  440.             Call    PutMsg                  ; write it to the port
  441. sendreq020  movem.l (sp)+,sendreqregs       ; restore registers
  442.             rts                             ; return to caller
  443. sendreqregs reg     a0/a1/d0-d2
  444.  
  445. *******************************************************************************
  446. *                                                                             * 
  447. *       Check_RawKey_Event                                                    *
  448. *                                                                             *
  449. *       This routine checks each RAWKEY event (keypress/keyrelease) to see if *
  450. *       it is one that we are interested in. If it is, the event that is      *
  451. *       passed to us is replaced with events to do the appropriate KeyMenu    *
  452. *       function. Events that have no meaning for us are passed back to the   *
  453. *       caller indicating that they should remain in the input event chain.   *
  454. *                                                                             *
  455. *       Input Registers:                                                      *
  456. *           a3 - rawkey event to be checked                                   *
  457. *           a4 - global work area                                             *
  458. *                                                                             *
  459. *       Output Registers:                                                     *
  460. *           d0 - 0=discard the event, 1=keep the event                        *
  461. *                                                                             *
  462. *******************************************************************************
  463. Check_RawKey_Event
  464.             movem.l creregs,-(sp)           ; save registers
  465.             clr.l   d0
  466.             btst.b  #IEQUALIFIER_REPEAT_R,ie_Qualifier(a3)  ; is it a repeat ?
  467.             beq     cre003                  ; no, branch
  468.             btst.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; have we skipped one ?
  469.             bne     cre004                  ; yes, branch
  470.             bset.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; indicate repeat skipped
  471.             bra     cre_remove              ; remove it from the input chain
  472. cre003      bclr.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; clear repeat skipped
  473. cre004      btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
  474.             bne     cre035                  ; yes, branch
  475. *-----------------------------------------------------------------------------*
  476. *           A menu is not currently active, check to see if one is being      *
  477. *           activated (keypress of the configured activation key).            *
  478. *-----------------------------------------------------------------------------*
  479.             move.b  gb_AKey(gbl),d0         ; get configured activation key code
  480.             cmp.w   ie_Code(a3),d0          ; Menu Activate Key ?
  481.             bne     cre010                  ; no, branch
  482. *-----------------------------------------------------------------------------*
  483. *           The user pressed the menu activation key, set a flag indicating   *
  484. *           that fact and wait to see if the key is released without pressing *
  485. *           any other keys.                                                   *
  486. *-----------------------------------------------------------------------------*
  487.             bset.b  #FLAGB_AKey_down,gb_flags(gbl) ; indicate Menu activate key
  488.                                                    ; down
  489. cre005      bra     cre_remove              ; remove this event
  490. cre010      bset.l  #IECODE_UP_PREFIX_R,d0  ; form keyrelease keycode
  491.             cmp.w   ie_Code(a3),d0          ; is it activate menu keyrelease ?
  492.             beq     cre014                  ; yes, branch
  493. cre012      bclr.b  #FLAGB_AKey_down,gb_flags(gbl) ; clear activate key down
  494.             bra     cre_keep                ; keep this event
  495. cre014      btst.b  #FLAGB_AKey_down,gb_flags(gbl) ; is activate key down still
  496.                                                    ; posted ?
  497.             beq     cre012                  ; no, branch
  498. *-----------------------------------------------------------------------------*
  499. *           The user pressed and released the menu activation key without     *
  500. *           hitting any other keys, find the current window and see if it has *
  501. *           a menu.                                                           *
  502. *-----------------------------------------------------------------------------*
  503.             move.l  gb_IBase(gbl),a5        ; get intuitionbase
  504.             move.l  ib_ActiveWindow(a5),d0  ; get current window
  505.             beq     cre005                  ; if none, branch
  506.             move.l  d0,a1                   ; save pointer to current window
  507.             move.l  wd_MenuStrip(a1),d0     ; get window's menu
  508.             beq     cre005                  ; if none, branch
  509.             move.l  d0,a0                   ; save menu for use later
  510.             move.l  wd_Flags(a1),d0         ; get window's flags
  511.             btst.l  #MENUSTATE_B,d0         ; is a menu already active ?
  512.             bne     cre005                  ; yes, branch
  513. *-----------------------------------------------------------------------------*
  514. *           The current window has a menu, check the RMBTRAP flag. If this is *
  515. *           set and the user didn't specify that we can clear it, then we     *
  516. *           can't use this menu.                                              *
  517. *-----------------------------------------------------------------------------*
  518.             btst.l  #RMBTRAP_B,d0           ; is RMBTRAP set in window ?
  519.             beq     cre015                  ; no, branch
  520.             btst.b  #FLAGB_Clear_rmbtrap,gb_flags(gbl) ; clear rmbtrap option 
  521.                                                        ; set ?
  522.             beq     cre005                  ; no, ignore the menu
  523.             bclr.l  #RMBTRAP_B,d0           ; clear RMBTRAP bit
  524.             move.l  d0,wd_Flags(a1)         ; update window's flags
  525. *-----------------------------------------------------------------------------*
  526. *           Finally, a menu we can use. Update our globals.                   *
  527. *-----------------------------------------------------------------------------*
  528. cre015      move.l  a0,gb_menu(gbl)         ; update our Menu pointer
  529.             move.l  a1,gb_window(gbl)       ; update our window pointer
  530. *-----------------------------------------------------------------------------*
  531. *           Now look to see if the menu and menu item saved in our globals is *
  532. *           still valid for this menu. If so, we will position the mouse on   *
  533. *           them otherwise we'll put the mouse on the topmost item in the     *
  534. *           leftmost menu.                                                    *
  535. *-----------------------------------------------------------------------------*
  536.             move.l  gb_currentmenu(gbl),a1  ; get saved menu
  537.             jsr     Verify_Item             ; go verify currentmenu
  538.             bne     cre020                  ; does it exist ? yes, use it
  539.             move.w  #s_leftmost,d0          ; no, setup to find leftmost menu
  540.             jsr     Select_Item             ; go select a Menu
  541.             move.l  d0,gb_currentmenu(gbl)  ; update our globals with new menu
  542. cre020      move.l  gb_currentmenu(gbl),a0  ; get current menu
  543.             move.l  mu_FirstItem(a0),a0     ; point to first menu item
  544.             move.l  gb_currentitem(gbl),a1  ; get current menu item
  545.             jsr     Verify_Item             ; go verify current item
  546.             bne     cre025                  ; does it exist ? yes, branch
  547.             move.w  #s_top,d0               ; no, setup to find top menuitem
  548.             jsr     Select_Item             ; go select menu item
  549.             move.l  d0,gb_currentitem(gbl)  ; update our globals
  550. *-----------------------------------------------------------------------------*
  551. *           Save the current mouse position so we can put it back where we    *
  552. *           found it when we're done. set/clear various flags reflecting our  *
  553. *           current state. Three events are inserted in the event chain.      *
  554. *           A rawmouse menudown event that causes intuition to activate the   *
  555. *           menu followed by two pointerpos events to position the pointer    *
  556. *           first on the desired menu then on the menu item within that menu. *
  557. *-----------------------------------------------------------------------------*
  558. cre025      move.w  ib_MouseX(a5),gb_old_MouseX(gbl) ; save current X
  559.             move.w  ib_MouseY(a5),gb_old_MouseY(gbl) ; save current Y
  560.             clr.l   gb_currentsubitem(gbl)  ; no subitem at present
  561.             move.w  #MENUDOWN,d0            ; setup to insert a menudown event
  562.             move.l  a3,a1                   ; event to attach new event to
  563.             jsr     Insert_RawMouse_Event   ; go insert the rawmouse event
  564.             moveq.l #2,d0                   ; indicate 2 events to be built
  565.             move.l  a0,a1                   ; event to attach new events to
  566.             jsr     db010                   ; go build the necessary events
  567.             bclr.b  #FLAGB_AKey_down,gb_flags(gbl) ; no longer waiting for
  568.                                                    ; activate key down event
  569.             move.l  #req_setpointer,d0      ; setup to send request
  570. cre027      bchg.b  #FLAGB_MActive,gb_flags(gbl) ; invert menu active bit
  571.             jsr     sendrequest             ; send pointer req to our task
  572.             bra     cre_remove              ; go to common return
  573. *-----------------------------------------------------------------------------*
  574. *           A menu is currently active, check for the various keys that we    *
  575. *           care about.                                                       *
  576. *-----------------------------------------------------------------------------*
  577. cre035      move.b  gb_DKey(gbl),d0
  578.             cmp.w   ie_Code(a3),d0          ; Deactivate key ?
  579.             bne     cre040                  ; no, branch
  580. *-----------------------------------------------------------------------------*
  581. *           The menu 'deactivate' key was pressed. Three events are inserted  *
  582. *           in the event chain. They consist of a pointerpos event to         *
  583. *           position the pointer in the menu strip followed by a rawmouse     *
  584. *           menuup event that causes intuition to deactivate the menu without *
  585. *           selecting anything followed by another pointerpos event to put    *
  586. *           the pointer back where we found it when the menu was activated.   *
  587. *-----------------------------------------------------------------------------*
  588.             moveq.l #3,d0                   ; build 2 events
  589.             jsr     dobuild                 ; go build mouse event(s)
  590.             move.w  #MENUUP,d0              ; setup for a menu up rawmouse event
  591.             move.l  a0,a1                   ; event to attach new event to
  592.             jsr     Insert_RawMouse_Event   ; go insert the a rawmouse event
  593.             move.l  #req_clearpointer,d0    ; setup to restore pointer
  594.             bra     cre027                  ; get out
  595.  
  596. cre040      move.b  gb_SKey(gbl),d0
  597.             cmp.w   ie_Code(a3),d0          ; Select Key ?
  598.             bne     cre055                  ; yes, branch
  599. *-----------------------------------------------------------------------------*
  600. *           The menu 'select' key was pressed. Two events are inserted in the *
  601. *           event chain. They consist of a menuup rawmouse event to select    *
  602. *           the current menu item, followed by a pointer event to put the     *
  603. *           pointer back where we found it when the menu was activated.       *
  604. *-----------------------------------------------------------------------------*
  605.             move.l  a3,a1                   ; event to attach new ones to
  606.             move.w  #MENUUP,d0              ; set type of rawmouse event
  607.             jsr     Insert_RawMouse_Event   ; go insert a menuup event
  608.             move.l  gb_IBase(gbl),a5        ; get intuitionbase address
  609.             move.w  gb_old_MouseX(gbl),d0   ; get saved mouse x coordinate
  610.             move.w  gb_old_MouseY(gbl),d1   ; get saved mouse y cooridnate
  611.             move.l  a0,a1                   ; event to attach new event to
  612.             lea     gb_ppos1(gbl),a0        ; new event to be inserted
  613.             jsr     Insert_PointerPos_Event   
  614.             move.l  #req_clearpointer,d0    ; setup to restore pointer
  615.             bra     cre027                  ; get out
  616.  
  617. cre055      move.b  gb_RightKey(gbl),d0
  618.             cmp.w   ie_Code(a3),d0          ; Move Right ?
  619.             bne     cre060                  ; no, branch
  620.             move.w  #s_adjacent_right,d1    ; 1st selection choice
  621.             move.w  #s_right,d2             ; 2nd selection choice
  622.             move.w  #s_leftmost,d3          ; 3rd selection choice
  623.             bra     cre065
  624. cre060      move.b  gb_LeftKey(gbl),d0
  625.             cmp.w   ie_Code(a3),d0          ; Move Left ?
  626.             bne     cre125                  ; no, branch
  627.             move.w  #s_adjacent_left,d1     ; 1st selection choice
  628.             move.w  #s_left,d2              ; 2nd selection choice
  629.             move.w  #s_rightmost,d3         ; 3rd selection choice
  630. cre065      move.b  ie_Qualifier+1(a3),d0   ; get key qualifier
  631.             and.b   gb_Qual(gbl),d0         ; was qualifier key present ?
  632.             beq     cre067                  ; no,branch
  633. *-----------------------------------------------------------------------------*
  634. *           The menu 'right' or 'left' key was pressed. See if a qualifier    *
  635. *           key was also present. If so, we move to either rightmost or       *
  636. *           leftmost menu.                                                    *
  637. *-----------------------------------------------------------------------------*
  638.             move.w  #s_rightmost,d0         ; select rightmost
  639.             cmp.w   d0,d3                   ; same selection ?
  640.             bne     cre107                  ; no, branch
  641.             move.w  #s_leftmost,d0          ; select leftmost
  642.             bra     cre107                  ; go choose the menu
  643. *-----------------------------------------------------------------------------*
  644. *           The menu 'right' or 'left' key was pressed. Now we must see if    *
  645. *           a subitem list exists for the current menu item.                  *
  646. *-----------------------------------------------------------------------------*
  647. cre067      move.l  gb_currentitem(gbl),a0  ; get current menu item ptr
  648.             move.l  mi_SubItem(a0),a1       ; get its menu subitem ptr, if any
  649.             move.l  a1,d0                   ; set cc
  650.             beq     cre100                  ; no subitems on this menu, branch
  651. *-----------------------------------------------------------------------------*
  652. *           There are subitems attached to this menu item. Some explanation   *
  653. *           is in order here. With Intuition, menu subitems can be rendered   *
  654. *           anywhere on the menu display as long as at least one pixel of the *
  655. *           menu subitem overlaps a pixel of its associated menu item.        *
  656. *           Generally, subitems are designed to appear either to the right of *
  657. *           its associated menu item or to the left. This affects our         *
  658. *           interpretation of what the user wants to do when they press       *
  659. *           either the menu right or menu left key.  For example, if the menu *
  660. *           subitems are positioned to the right of the menu item and the     *
  661. *           menu right key is pressed, this means that the user intends to    *
  662. *           step into the menu subitem list. If the menu subitems are         *
  663. *           positioned on the left and the menu right key is pressed, the     *
  664. *           user wants to step to the next list of menu items on the right    *
  665. *           (or wrap to the first set of menu items if we are positioned on   *
  666. *           the rightmost menu item). Here we check the leftedge of the       * 
  667. *           subitem against the leftedge of the menu item to determine if the *
  668. *           subitem's leftedge is less than (or to the left of) the menu      *
  669. *           item's leftedge. The result of this comparison is saved in d4 and *
  670. *           is used later in determining what the user's intentions are.      *
  671. *-----------------------------------------------------------------------------*
  672.             move.w  mi_LeftEdge(a1),d0      ; get subitem's leftedge
  673.             cmp.w   mi_LeftEdge(a0),d0      ; compare to menuitem's leftedge
  674.             slt     d4                      ; save comparison result
  675.             tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  676.             bne     cre080                  ; yes, branch
  677. *-----------------------------------------------------------------------------*
  678. *           We are positioned on a menu item that has subitems attached and   *
  679. *           the user has pressed the menu right or menu left key. Determine   *
  680. *           what their intention is. Either they want to step into the        *
  681. *           subitem list or they want to select the next menu item.           *
  682. *-----------------------------------------------------------------------------*
  683.             clr.l   d0
  684.             move.b  gb_RightKey(gbl),d0     ; setup for compare
  685.             cmp.w   ie_Code(a3),d0          ; right key ?
  686.             bne     cre070                  ; no, branch
  687.             tst.b   d4                      ; are subitems on menu items left ?
  688.             beq     cre075                  ; no, step into the subitem list
  689.             bra     cre100                  ; yes, step to next menu item list
  690. cre070      tst.b   d4                      ; are subitems on menu items left ?
  691.             beq     cre100                  ; no, step to next menu item list
  692.                                             ; yes, step into the subitem list
  693. *-----------------------------------------------------------------------------*
  694. *           The user wants to step into the subitem list. Select the topmost  *
  695. *           adjacent subitem in the list. (Note: there can be subitems        *
  696. *           positioned horizontally as well as vertically)                    * 
  697. *-----------------------------------------------------------------------------*
  698. cre075      move.w  #s_adjacent_top,d0      ; set to select the topmost subitem
  699.             move.l  a1,a0                   ; list of subitems to choose from
  700.             jsr     Select_Item             ; go find the subitem
  701.             move.l  d0,gb_currentsubitem(gbl) ; save it in our globals
  702.             bra     cre085                  ; go generate an event
  703. *-----------------------------------------------------------------------------*
  704. *           We are currently positioned on a menu subitem and the user has    *
  705. *           pressed either the menu right key or menu left key. Determine     *
  706. *           what their intention is. If there is another subitem positioned   *
  707. *           adjacent to the current subitem in the direction of the key that  *
  708. *           was pressed, that subitem will be selected. Otherwise, the user   *
  709. *           wants to step out of the subitem list.                            *
  710. *-----------------------------------------------------------------------------*
  711. cre080      move.l  d1,d0                   ; get 1st selection choice
  712.             move.l  a1,a0                   ; list of subitems to choose from
  713.             move.l  gb_currentsubitem(gbl),a1 ; supply current subitem
  714.             jsr     Select_Item             ; go select next subitem
  715.             cmp.l   d0,a1                   ; same item selected ?
  716.             beq     cre090                  ; yes, get out of the subitem list
  717.             move.l  d0,gb_currentsubitem(gbl) ; no, save new subitem
  718. cre085      moveq.l #1,d0                   ; set to build only one event
  719.             bra     cre175                  ; go generate an event
  720. *-----------------------------------------------------------------------------*
  721. *           The user wants to step out of the subitem list. Determine whether *
  722. *           they want to go back to the menu item associated with the subitem *
  723. *           list or to the next menu item.                                    *
  724. *-----------------------------------------------------------------------------*
  725. cre090      clr.l   gb_currentsubitem(gbl)  ; clear current subitem pointer
  726.             clr.l   d0
  727.             move.b  gb_RightKey(gbl),d0     ; setup for compare
  728.             cmp.w   ie_Code(a3),d0          ; right key ?
  729.             bne     cre095                  ; no, branch
  730.             tst.b   d4                      ; are subitems on menu items left ?
  731.             bne     cre085                  ; yes, go back to subitems menu item
  732.             bra     cre100                  ; no, go select next menu item list
  733. cre095      tst.b   d4                      ; are subitems on menu items left ?
  734.             beq     cre085                  ; no, go back to subitems menu item
  735. *-----------------------------------------------------------------------------*
  736. *           Select a menu item. (Note: there can be menu items positioned     *
  737. *           horizontally as well as vertically)                               *
  738. *-----------------------------------------------------------------------------*
  739. cre100      move.l  d1,d0                   ; get 1st selection choice
  740.             move.l  gb_currentmenu(gbl),a0  ; get current menu
  741.             move.l  mu_FirstItem(a0),a0     ; list of items to choose from
  742.             move.l  gb_currentitem(gbl),a1  ; get current menu item
  743.             jsr     Select_Item             ; go select an item
  744.             cmp.l   d0,a1                   ; same item selected ?
  745.             bne     cre115                  ; no, use the new item, branch
  746. *-----------------------------------------------------------------------------*
  747. *           There are no menu items positioned in the horizontal direction of *
  748. *           the key that was pressed, so we must step to the next menu.       *
  749. *-----------------------------------------------------------------------------*
  750.             move.l  d2,d0                   ; get 2nd selection choice
  751.             move.l  gb_menu(gbl),a0         ; list of menus to choose from
  752.             move.l  gb_currentmenu(gbl),a1  ; get current menu
  753.             jsr     Select_Item             ; go select a menu
  754.             cmp.l   d0,a1                   ; same menu selected ?
  755.             beq     cre105                  ; yes, branch
  756.             move.l  d0,gb_currentmenu(gbl)  ; no, use the new menu
  757.             bra     cre110                  ; go select an item in the menu
  758. *-----------------------------------------------------------------------------*
  759. *           There are no menus in the horizontal direction of the key that    *
  760. *           was pressed. We will interpret this to mean that the user wants   *
  761. *           to wrap to the opposite end of the menu strip. For example, if we *
  762. *           are currently on the rightmost menu and the user presses the menu *
  763. *           right key, we will wrap around to the leftmost menu.              *
  764. *-----------------------------------------------------------------------------*
  765. cre105      move.l  d3,d0                   ; set 3rd selection choice
  766. cre107      move.l  gb_menu(gbl),a0         ; list of menus to choose from
  767.             jsr     Select_Item             ; go select again
  768.             move.l  d0,gb_currentmenu(gbl)  ; save new menu
  769. cre110      move.w  #s_top,d0               ; set to select topmost menu item
  770.             move.l  gb_currentmenu(gbl),a0  ; get current menu
  771.             move.l  mu_FirstItem(a0),a0     ; list of items to choose from
  772.             jsr     Select_Item             ; go select a menu item
  773.             move.l  d0,gb_currentitem(gbl)  ; save new item
  774. *-----------------------------------------------------------------------------*
  775. *           Normally, we will generate only one event. A pointerpos event to  *
  776. *           position the pointer on the desired menu item or subitem. Here we *
  777. *           have determined that a new menu is to be selected. This requires  *
  778. *           us to generate 2 events. The first will be a pointerpos event to  *
  779. *           position the pointer in the menu strip over the menu that we want *
  780. *           to select. This causes Intuition to remove the rendering of the   *
  781. *           current menu from the display and render the menu that we are     *
  782. *           selecting. The second event will be a pointerpos event to         *
  783. *           position the pointer on the menu item that we have chosen.        *
  784. *-----------------------------------------------------------------------------*
  785.             moveq.l #2,d0                   ; set number of events to build
  786.             bra     cre120
  787. cre115      move.l  d0,gb_currentitem(gbl)  ; save new item
  788.             moveq.l #1,d0                   ; set number of events to build
  789. cre120      clr.l   gb_currentsubitem(gbl)  ; clear current subitem pointer
  790.             bra     cre175                  ; go generate event(s)
  791.  
  792. cre125      move.b  gb_DownKey(gbl),d0      ; setup for compare
  793.             cmp.w   ie_Code(a3),d0          ; Down key ?
  794.             bne     cre130                  ; no, branch
  795.             move.w  #s_adjacent_up,d1       ; 1st selection choice
  796.             move.w  #s_up,d2                ; 2nd selection choice
  797.             move.w  #s_top,d3               ; 3rd selection choice
  798.             bra     cre135                  ; go handle keypress
  799. cre130      move.b  gb_UpKey(gbl),d0        ; setup for compare
  800.             cmp.w   ie_Code(a3),d0          ; Up key ?
  801.             bne     cre_keep                ; no, pass this event on
  802.             move.w  #s_adjacent_down,d1     ; 1st selection choice
  803.             move.w  #s_down,d2              ; 2nd selection choice
  804.             move.w  #s_bottom,d3            ; 3rd selection choice
  805. *-----------------------------------------------------------------------------*
  806. *           The menu 'up' or 'down' key was pressed. If we are currently      *
  807. *           positioned in a subitem menu, setup to select the appropriate     *
  808. *           subitem otherwise setup to select the appropriate menu item.      *
  809. *-----------------------------------------------------------------------------*
  810. cre135      moveq.l #1,d4                   ; set default # events to be created
  811.             tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  812.             beq     cre140                  ; no, branch
  813.             move.l  gb_currentsubitem(gbl),a1 ; supply parameters to process
  814.             move.l  gb_currentitem(gbl),a0    ; menu subitems
  815.             move.l  mi_SubItem(a0),a0
  816.             bra     cre145
  817. cre140      move.l  gb_currentitem(gbl),a1  ; supply parameters to process menu
  818.             move.l  gb_currentmenu(gbl),a0  ; items
  819.             move.l  mu_FirstItem(a0),a0
  820. *-----------------------------------------------------------------------------*
  821. *           Here we check to see if there are subitems attached to the        *
  822. *           current menu item. If so, we will generate 2 events. The first    *
  823. *           will be a pointerpos event to position the pointer on the menu    *
  824. *           strip. The second will be a pointerpos event to position the      *
  825. *           pointer on the desired menu item. This is done to cause Intuition *
  826. *           to remove the subitem's rendering from the display in case it     *
  827. *           overlaps onto the menu item being selected. Without this, we      *
  828. *           would tell Intuition to position the mouse on the new menu item   *
  829. *           but the overlapping subitems from the current menu item would     *
  830. *           still be displayed causing us to select a menu subitem instead of *
  831. *           the menu item that we intended to select.                         *
  832. *-----------------------------------------------------------------------------*
  833.             tst.l   mi_SubItem(a1)          ; are there subitems attached to
  834.                                             ; this menu item ?
  835.             beq     cre145                  ; no, branch
  836.             moveq.l #2,d4                   ; yes, use 2 events to select item
  837. cre145      move.b  ie_Qualifier+1(a3),d0   ; get key qualifier
  838.             and.b   gb_Qual(gbl),d0         ; was qualifier key present ?
  839.             beq     cre147                  ; no, branch
  840. *-----------------------------------------------------------------------------*
  841. *           See if a qualifier key was also present. If so, we move to either *
  842. *           topmost or bottommost menu or submenu item.                       *
  843. *-----------------------------------------------------------------------------*
  844.             move.w  #s_bottom,d0            ; select bottom
  845.             cmp.w   d0,d3                   ; same selection ?
  846.             bne     cre153                  ; no, branch
  847.             move.w  #s_top,d0               ; select top
  848.             bra     cre153
  849. cre147      move.l  d1,d0                   ; get 1st selection choice
  850.             jsr     Select_Item             ; go select a menuitem or subitem
  851.             cmp.l   d0,a1                   ; same item selected ?
  852.             bne     cre155                  ; no, use the new one
  853.             move.l  d2,d0                   ; get 2nd selection choice
  854.             jsr     Select_Item             ; select again
  855. cre150      cmp.l   d0,a1                   ; same item selected ?
  856.             bne     cre155                  ; no, use new item
  857.             move.l  d3,d0                   ; get 3rd selection choice
  858. cre153      jsr     Select_Item             ; go select again
  859. cre155      move.l  d0,a1                   ; save new item
  860. cre160      tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  861.             beq     cre165                  ; no, branch
  862.             move.l  a1,gb_currentsubitem(gbl) ; yes, save new subitem
  863.             bra     cre170
  864. cre165      move.l  a1,gb_currentitem(gbl)  ; save new item
  865. cre170      move.l  d4,d0                   ; get # of events to be generated
  866. cre175      jsr     dobuild                 ; go build our events
  867. *-----------------------------------------------------------------------------*
  868. *           Indicate that the original input event passed to this routine is  *
  869. *           to be removed from the input event chain and return.              *
  870. *-----------------------------------------------------------------------------*
  871. cre_remove  moveq.l #1,d0                   ; indicate old event to be removed
  872.             bra     cre_exit                ; go to common return
  873. *-----------------------------------------------------------------------------*
  874. *           Indicate that the original input event passed to this routine is  *
  875. *           to be kept in the input event chain and return.                   *
  876. *-----------------------------------------------------------------------------*
  877. cre_keep    clr.l   d0                      ; indicate old event to be kept
  878. cre_exit    movem.l (sp)+,creregs           ; restore registers
  879.             rts                             ; return to caller
  880. creregs     reg     a1-a3/a5/d2-d4
  881.  
  882. *******************************************************************************
  883. *                                                                             * 
  884. *       dobuild                                                               *
  885. *                                                                             *
  886. *       This routine is called by Check_RawKey_Event to perform a general     *
  887. *       call to the Build_PointerPos_Event routine.                           *
  888. *                                                                             *
  889. *       Input Registers:                                                      *
  890. *           a3 - input event to attach new events to                          *
  891. *           a4 - global work area                                             *
  892. *                                                                             *
  893. *       Output Registers:                                                     *
  894. *           a0 - new input event                                              *
  895. *           a1 - original input event                                         *
  896. *                                                                             *
  897. *******************************************************************************
  898. dobuild     move.l  a3,a1                   ; pass original input event
  899. db010       lea     gb_ppos2(gbl),a0        ; point to our input event area
  900.             jsr     Build_PointerPos_Event  ; go create our input events
  901.             rts                             ; return to caller
  902.  
  903. *******************************************************************************
  904. *                                                                             * 
  905. *       Verify_Item                                                           *
  906. *                                                                             *
  907. *       This routine is called by Check_RawKey_Event to verify if a menu or   *
  908. *       menu item is a member of a provided list of menu/menu items.          *
  909. *                                                                             *
  910. *       Input Registers:                                                      *
  911. *           a0 - menu/menu item list                                          *
  912. *           a1 - item to be verified.                                         *
  913. *                                                                             *
  914. *       Output Registers:                                                     *
  915. *           d0 - 0=no match, 1=match                                          *
  916. *                                                                             *
  917. *******************************************************************************
  918. Verify_Item movem.l viregs,-(sp)
  919. vi010       cmp.l   a0,a1                   ; does this item match ?
  920.             beq     vi015                   ; yes, branch
  921.             move.l  im_NextItem(a0),d0      ; get next item's address
  922.             beq     vi020                   ; entire list scanned, branch
  923.             move.l  d0,a0                   ; use next item's address
  924.             bra     vi010                   ; loop to check next item
  925. vi015       moveq.l #1,d0                   ; indicate that the item exists
  926. vi020       movem.l (sp)+,viregs
  927.             rts
  928. viregs      reg     a0/a1
  929.  
  930. *******************************************************************************
  931. *                                                                             * 
  932. *       Select_Item                                                           *
  933. *                                                                             *
  934. *       This routine is called to select a menu, menu item or menu subitem.   *
  935. *       Given a list of items to choose from, the attribute of the item       *
  936. *       desired and the current item; this routine attempts to find a new     *
  937. *       item that matches the desired attribute. For example, if d0 contains  *
  938. *       's_up' the list of items provided is scanned to find the closest item *
  939. *       that is physically above the current item on the display.             *
  940. *                                                                             *
  941. *       Input Registers:                                                      *
  942. *           a0 - menu/menu item/menu subitem list                             *
  943. *           a1 - current item                                                 *
  944. *           d0 - type of item desired in relation to current item             *
  945. *                                                                             *
  946. *       Output Registers:                                                     *
  947. *           d0 - selected item (or current item if no item was selected)      *
  948. *                                                                             *
  949. *******************************************************************************
  950. Select_Item
  951.  
  952. select_type equr    d0                      ; select type & return value
  953. item        equr    a0                      ; item list
  954. currentitem equr    a1                      ; currentitem
  955. returnitem  equr    a2                      ; return item
  956. work        equr    d1                      ; work register
  957.  
  958. *-----------------------------------------------------------------------------*
  959. *           'returnitem' contains the address of the item that is being       *
  960. *           considered for return to the calling routine. Here we create a    *
  961. *           dummy item on the stack that contains extreme values for topedge  *
  962. *           and leftedge. The address of this entry is loaded into            *
  963. *           'returnitem' to give us an initial entry to compare against.      *
  964. *           For example, if 's_leftmost' is the attribute of the item that we *
  965. *           are searching for, the leftedge field in the dummy entry would    *
  966. *           contain 32768. In an effort to find the 'leftmost' item in the    *
  967. *           list, the 'si_leftmost' portion of this routine will compare the  *
  968. *           leftedge of each item in the list with the leftedge of            *
  969. *           'returnitem'. When an item is found with a leftedge that is less  *
  970. *           than returnitem's, its address is placed in returnitem. When the  *
  971. *           end of the list is reached, the item with the lowest leftedge     *
  972. *           should be contained in 'returnitem'                               *
  973. *-----------------------------------------------------------------------------*
  974.             link    a5,#-im_size
  975.             movem.l siregs,-(sp)
  976.             move.w  #32767,work
  977.             cmp.w   #s_leftmost,select_type
  978.             ble     si010
  979.             move.w  #-32768,work
  980. si010       lea     -im_size(a5),returnitem          
  981.             move.w  work,im_TopEdge(returnitem) ; setup dummy item
  982.             move.w  work,im_LeftEdge(returnitem)
  983.             bra     si_jmp                  ; go to computed jump
  984. si_adjacent_up
  985.             move.w  im_LeftEdge(item),work
  986.             cmp.w   im_LeftEdge(currentitem),work
  987.             bne     si_check_end
  988. si_up       move.w  im_TopEdge(item),work
  989.             cmp.w   im_TopEdge(currentitem),work
  990.             ble     si_check_end
  991. si_top
  992. si_adjacent_top
  993.             move.w  im_TopEdge(item),work
  994.             cmp.w   im_TopEdge(returnitem),work
  995.             bge     si015
  996.             move.l  item,returnitem
  997. si015       cmp.w   #s_adjacent_top,select_type
  998.             bne     si_check_end
  999.             move.w  im_TopEdge(item),work
  1000.             cmp.w   im_TopEdge(returnitem),work
  1001.             bne     si_check_end
  1002.             move.w  im_LeftEdge(item),work
  1003.             cmp.w   im_LeftEdge(returnitem),work
  1004.             bge     si_check_end
  1005.             move.l  item,returnitem
  1006.             bra     si_check_end
  1007. si_adjacent_right
  1008.             move.w  im_TopEdge(item),work
  1009.             cmp.w   im_TopEdge(currentitem),work
  1010.             bne     si_check_end
  1011. si_right    move.w  im_LeftEdge(item),work
  1012.             cmp.w   im_LeftEdge(currentitem),work
  1013.             ble     si_check_end
  1014. si_leftmost move.w  im_LeftEdge(item),work
  1015.             cmp.w   im_LeftEdge(returnitem),work
  1016.             bge     si_check_end
  1017.             move.l  item,returnitem
  1018.             bra     si_check_end
  1019. si_adjacent_down
  1020.             move.w  im_LeftEdge(item),work
  1021.             cmp.w   im_LeftEdge(currentitem),work
  1022.             bne     si_check_end
  1023. si_down     move.w  im_TopEdge(item),work
  1024.             cmp.w   im_TopEdge(currentitem),work
  1025.             bge     si_check_end
  1026. si_bottom   move.w  im_TopEdge(item),work
  1027.             cmp.w   im_TopEdge(returnitem),work
  1028.             ble     si_check_end
  1029.             move.l  item,returnitem
  1030.             bra     si_check_end
  1031. si_adjacent_left
  1032.             move.w  im_TopEdge(item),work
  1033.             cmp.w   im_TopEdge(currentitem),work
  1034.             bne     si_check_end
  1035. si_left     move.w  im_LeftEdge(item),work
  1036.             cmp.w   im_LeftEdge(currentitem),work
  1037.             bge     si_check_end
  1038. si_rightmost
  1039.             move.w  im_LeftEdge(item),work
  1040.             cmp.w   im_LeftEdge(returnitem),work
  1041.             ble     si_check_end
  1042.             move.l  item,returnitem
  1043. si_check_end
  1044.             move.l  im_NextItem(item),item
  1045.             move.l  item,work               ; set cc
  1046.             beq     si_end
  1047. si_jmp      jmp     (pc,d0.w)               ; jump to proper routine
  1048. si_end      lea     -im_size(a5),item
  1049.             cmp.l   item,returnitem         ; still pointing to dummy item ?
  1050.             bne     si_return               ; no, branch
  1051.             move.l  currentitem,returnitem  ; yes, pass currentitem back
  1052. si_return   move.l  returnitem,d0           ; set return 
  1053.             movem.l (sp)+,siregs            ; restore regs
  1054.             unlk    a5                      ; remove area from stack
  1055.             rts                             ; return to caller
  1056. siregs      reg     d1/a0-a2
  1057.  
  1058. *******************************************************************************
  1059. *                                                                             * 
  1060. *       Insert_PointerPos_Event                                               *
  1061. *                                                                             *
  1062. *       This routine creates a pointerpos event and attaches it to the input  *
  1063. *       event provided.                                                       *
  1064. *                                                                             *
  1065. *       Input Registers:                                                      *
  1066. *           a0 - new event to be inserted                                     *
  1067. *           a1 - input event to attach new event to                           *
  1068. *           d0 - Mouse X coordinate to place in new event                     *
  1069. *           d1 - Mouse Y coordinate to place in new event                     *
  1070. *                                                                             *
  1071. *       Output Registers:                                                     *
  1072. *           none.                                                             *
  1073. *                                                                             *
  1074. *******************************************************************************
  1075. Insert_PointerPos_Event
  1076.             move.b  #IECLASS_POINTERPOS,ie_Class(a0) ; build mousemove event
  1077.             move.w  #IECODE_NOBUTTON,ie_Code(a0)
  1078.             move.w  d0,ie_X(a0)             ; set coordinates
  1079.             move.w  d1,ie_Y(a0)
  1080.             bra     ire010
  1081.  
  1082. *******************************************************************************
  1083. *                                                                             * 
  1084. *       Insert_RawMouse_Event                                                 *
  1085. *                                                                             *
  1086. *       This routine creates a rawmouse event and attaches it to the input    *
  1087. *       event provided.                                                       *
  1088. *                                                                             *
  1089. *       Input Registers:                                                      *
  1090. *           a1 - input event to attach new event to                           *
  1091. *           d0 - type of rawmouse event                                       *
  1092. *                                                                             *
  1093. *       Output Registers:                                                     *
  1094. *           none.                                                             *
  1095. *                                                                             *
  1096. *******************************************************************************
  1097. Insert_RawMouse_Event
  1098.             lea     gb_rawm(gbl),a0
  1099.             move.b  #IECLASS_RAWMOUSE,ie_Class(a0) ; build rawmouse event
  1100.             move.w  d0,ie_Code(a0)
  1101.             clr.w   ie_X(a0)
  1102.             clr.w   ie_Y(a0)
  1103. ire010      clr.b   ie_SubClass(a0)
  1104.             clr.w   ie_Qualifier(a0)
  1105.             move.l  ie_NextEvent(a1),ie_NextEvent(a0) ; chain to original event
  1106.             move.l  a0,ie_NextEvent(a1)
  1107.             rts                             ; return to caller
  1108.  
  1109. *******************************************************************************
  1110. *                                                                             * 
  1111. *       Build_PointerPos_Event                                                *
  1112. *                                                                             *
  1113. *       This routine creates pointer position event(s) and attaches them to   *
  1114. *       the input event provided. The resolution of the current screen is     *
  1115. *       taken into account when generating the events. The coordinates of the *
  1116. *       pointer position events are alway represented in the highest          *
  1117. *       resolution i.e. 640x400. The coordinate fields of menus, menu items,  *
  1118. *       etc. are represented in the resolution of the screen to which the     *
  1119. *       menu is attached. When we position the pointer on anything but a      *
  1120. *       hires interlace screen, we must adjust the coordinates that are taken *
  1121. *       from the menus to allow for this.                                     *
  1122. *                                                                             *
  1123. *       Input Registers:                                                      *
  1124. *           a0 - address of input event to be built                           *
  1125. *           a1 - original input event                                         *
  1126. *           d0 - number of input events to generate.                          *
  1127. *                                                                             *
  1128. *       Output Registers:                                                     *
  1129. *           none.                                                             *
  1130. *                                                                             *
  1131. *******************************************************************************
  1132. Build_PointerPos_Event
  1133.  
  1134. iheight     equr    d1
  1135. iwidth      equr    d1
  1136. itopedge    equr    d2
  1137. ileftedge   equr    d2
  1138. mheight     equr    d3
  1139. mwidth      equr    d3
  1140. mtopedge    equr    d4
  1141. mleftedge   equr    d4
  1142. offsetx     equr    d5
  1143. offsety     equr    d6
  1144.  
  1145.             movem.l breregs,-(sp)           ; save registers
  1146.             jsr     Insert_PointerPos_Event   ; go insert new event
  1147.             move.l  gb_window(gbl),a2       ; get current window
  1148.             move.l  wd_WScreen(a2),a2       ; get window's screen
  1149.             move.l  gb_currentmenu(gbl),a3  ; get current menu
  1150.             move.w  mu_TopEdge(a3),mtopedge ; get menu's topedge
  1151.             add.w   sc_ViewPort+vp_DyOffset(a2),mtopedge ; add screen's offset
  1152.             swap    mtopedge
  1153.             move.w  mu_LeftEdge(a3),mleftedge ; get menu's leftedge
  1154.             add.w   sc_ViewPort+vp_DxOffset(a2),mleftedge ; add screen's offset
  1155.             clr.l   mheight
  1156.             move.b  sc_BarHeight(a2),mheight ; get menu's height
  1157.             swap    mheight
  1158.             move.w  mu_Width(a3),mwidth     ; get menu's width
  1159.             move.l  gb_currentitem(gbl),a3  ; get current menuitem
  1160.             move.w  mi_TopEdge(a3),itopedge ; get menuitem's topedge
  1161.             swap    itopedge
  1162.             move.w  mi_LeftEdge(a3),ileftedge ; get menuitem's leftedge
  1163.             move.w  mi_Height(a3),iheight   ; get menuitem's height
  1164.             swap    iheight
  1165.             move.w  mi_Width(a3),iwidth     ; get menuitem's width
  1166.             move.l  gb_currentsubitem(gbl),a5 ; is there a subitem ?
  1167.             move.l  a5,d5                   ; set cc
  1168.             beq     bre010                   ; no, branch
  1169.             add.w   mi_LeftEdge(a5),ileftedge ; yes, add subitem's leftedge
  1170.             move.w  mi_Width(a5),iwidth     ; use subitem's width
  1171.             swap    ileftedge
  1172.             add.w   mi_TopEdge(a5),itopedge ; add subitem's topedge
  1173.             swap    itopedge
  1174.             swap    iwidth
  1175.             move.w   mi_Height(a5),iheight  ; use subitem's height
  1176.             swap    iheight
  1177.             bra     bre025
  1178. bre010      move.l  mi_SubItem(a3),a5       ; is there a subitem for this item ?
  1179.             move.l  a5,d5                   ; set cc
  1180.             beq     bre025                  ; no, branch
  1181.             move.w  mi_LeftEdge(a5),d5      ; yes, get subitem's leftedge
  1182.             cmp.w   mi_LeftEdge(a3),d5      ; is it's leftedge less than item's?
  1183.             bge     bre020                  ; no, branch
  1184.             add.w   d5,ileftedge            ; yes, add subitems leftedge
  1185.             add.w   mi_Width(a5),ileftedge  ; add subitem's width
  1186.             move.w  mi_LeftEdge(a3),iwidth  ; get items leftedge
  1187.             add.w   mi_Width(a3),iwidth     ; add its width
  1188.             move.l  ileftedge,d5            ; get item's leftedge
  1189.             bge     bre015                  ; if its positive, branch
  1190.             neg     d5                      ; make it positive
  1191. bre015      sub.w   d5,iwidth
  1192.             bra     bre025
  1193. bre020      movem.l d0/a0,-(sp)             ; save our registers
  1194.             move.l  a5,a0                   ; pass subitem pointer
  1195.             move.l  #s_adjacent_top,d0      ; set select type
  1196.             jsr     Select_Item
  1197.             move.l  d0,a5                   ; get selected item
  1198.             movem.l (sp)+,d0/a0             ; restore our registers
  1199.             move.w  mi_LeftEdge(a5),iwidth
  1200.             sub.w   #1,iwidth
  1201. bre025      move.w  sc_ViewPort+vp_Modes(a2),d5 ; get screen modes
  1202.             btst.l  #V_HIRES_B,d5           ; is this a hires screen ?
  1203.             bne     bre030                  ; yes, branch
  1204.             asl.w   #1,iwidth               ; no, adjust coordinates for hires
  1205.             asl.w   #1,ileftedge
  1206.             asl.w   #1,mwidth
  1207.             asl.w   #1,mleftedge
  1208. bre030      btst.l  #V_LACE_B,d5            ; is this an interlace screen ?
  1209.             bne     bre035                  ; yes, branch
  1210.             swap    iwidth                  ; no, adjust coordinates for interlace
  1211.             swap    ileftedge
  1212.             swap    mwidth
  1213.             swap    mleftedge
  1214.             asl.w   #1,iheight
  1215.             asl.w   #1,itopedge
  1216.             asl.w   #1,mheight
  1217.             asl.w   #1,mtopedge
  1218.             swap    iheight
  1219.             swap    itopedge
  1220.             swap    mheight
  1221.             swap    mtopedge
  1222. bre035      move.l  gb_IBase(gbl),a5        ; get intuition base
  1223.             addq.w  #1,mleftedge
  1224.             move.w  mleftedge,offsetx       ; get menu leftedge
  1225.             move.w  offsetx,ie_X(a0)        ; update event's X coordinate
  1226.             swap    mleftedge
  1227.             addq.w  #1,mtopedge
  1228.             move.w  mtopedge,offsety        ; get menu topedge
  1229.             move.w  offsety,ie_Y(a0)        ; update event's Y coordinate
  1230.             asr.w   #1,mwidth               ; divide menu width by 2
  1231.             move.w  ileftedge,offsetx       ; get item leftedge
  1232.             asr.w   #1,iwidth               ; divide item width by 2
  1233.             add.w   iwidth,offsetx          ; add it to offsetx
  1234.             swap    mwidth
  1235.             move.w  mheight,offsety         ; get menu height
  1236.             asr.w   #1,mheight              ; divide menu height by 2
  1237.             swap    mheight
  1238.             swap    ileftedge
  1239.             add.w   itopedge,offsety        ; add item topedge
  1240.             swap    iwidth
  1241.             asr     #1,iheight              ; divide item height by 2
  1242.             add.w   iheight,offsety         ; add to offsety
  1243.             cmp.w   #1,d0                   ; one event to be generated ?
  1244.             bne     bre040                  ; no, branch
  1245.             add.w   offsetx,ie_X(a0)        ; adjust mouse x coordinate
  1246.             add.w   offsety,ie_Y(a0)        ; adjust mouse y coordinate
  1247.             bra     bre045
  1248. bre040      cmp.w   #3,d0                   ; go to saved mouse position ?
  1249.             bne     bre042                  ; no, branch
  1250.             move.w  gb_old_MouseX(gbl),offsetx
  1251.             move.w  gb_old_MouseY(gbl),offsety
  1252.             bra     bre044
  1253. bre042      add.w   ie_X(a0),offsetx
  1254.             add.w   ie_Y(a0),offsety
  1255. bre044      add.w   mwidth,ie_X(a0)         ; add menu width to current item
  1256.             swap    mwidth
  1257.             add.w   mheight,ie_Y(a0)        ; add menu height to current item
  1258.             move.l  a0,a1                   ; event to attach new event to
  1259.             lea     gb_ppos1(gbl),a0        ; new event area
  1260.             move.w  offsetx,d0
  1261.             move.w  offsety,d1
  1262.             jsr     Insert_PointerPos_Event   ; go add the event to the chain
  1263. bre045      bset.b  #FLAGB_Events_inserted,gb_flags(gbl) ; indicate events added
  1264.             movem.l (sp)+,breregs
  1265.             rts                             ; return to caller
  1266. breregs     reg     a0-a5/d1-d6
  1267.  
  1268.             end
  1269.