home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 510.lha / KeyMenu_v1.04 / KeyMenu-Handler.asm next >
Encoding:
Assembly Source File  |  1991-05-07  |  79.6 KB  |  1,273 lines

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