home *** CD-ROM | disk | FTP | other *** search
- *******************************************************************************
- *
- * KeyMenu-Handler.asm V1.03 02 Mar 1991
- *
- *
- *
- * This program is loaded by 'KeyMenu' and stays resident in the
- * system until the user runs KeyMenu with the 'QUIT' option.
- *
- *
- *
- * Modification History:
- *
- * Date By Modification
- * -------- -------------------- --------------------------------------
- * 09/09/89 Ken Lowther Initial release, V1.01
- *
- * 09/13/89 Ken Lowther V1.02 - added qualifier keys to move
- * mouse pointer to first/last item.
- *
- * 09/24/89 Ken Lowther V1.02 - corrected positioning of mouse
- * pointer on menus. The pointer was being
- * positioned 1 pixel to the left. This
- * really only mattered when the menu is
- * 1 pixel wide.
- *
- * 09/30/89 Ken Lowther V1.02 - Keymenu no longer creates a
- * process for this module. Changed 'main'
- * to set the DOS return code and return
- * in case this module gets 'execute'ed.
- *
- * 10/03/89 Ken Lowther V1.02 - Changed to ignore the 1st
- * occurance of a 'repeated' key. This
- * is to fix a problem that occurs when
- * there are more than 2 bitplanes in the
- * screen.
- *
- * 03/02/91 Ken Lowther V1.03 - Modified to use PointerPos
- * events rather than RawMouse events to
- * position intuition's pointer. This
- * allows Keymenu to co-exist with most
- * mouse accelerators.
- *
- * 03/02/91 Ken Lowther V1.03 - Re-installed intuition pointer
- * blanking option.
- *
- *******************************************************************************
- nolist
- include "macros.i"
- include "exec/types.i"
- include "exec/strings.i"
- include "exec/nodes.i"
- include "exec/ports.i"
- include "exec/execbase.i"
- include "exec/ables.i"
- include "exec/interrupts.i"
- include "exec/memory.i"
- include "devices/inputevent.i"
- include "intuition/intuition.i"
- include "libraries/dos.i"
- include "libraries/dosextens.i"
- include "keymenu-handler.i"
- list
- nomlist
-
- *******************************************************************************
- * *
- * Displacements into Select routine. *
- * *
- *******************************************************************************
- s_top equ si_top-si_jmp-2
- s_adjacent_top equ si_adjacent_top-si_jmp-2
- s_adjacent_up equ si_adjacent_up-si_jmp-2
- s_up equ si_up-si_jmp-2
- s_adjacent_right equ si_adjacent_right-si_jmp-2
- s_right equ si_right-si_jmp-2
- s_leftmost equ si_leftmost-si_jmp-2
- s_adjacent_down equ si_adjacent_down-si_jmp-2
- s_bottom equ si_bottom-si_jmp-2
- s_adjacent_left equ si_adjacent_left-si_jmp-2
- s_down equ si_down-si_jmp-2
- s_left equ si_left-si_jmp-2
- s_rightmost equ si_rightmost-si_jmp-2
-
- gbl equr a4 ; handler global area
-
- cseg
- near code
- *******************************************************************************
- * *
- * main *
- * *
- * This is the main routine of KeyMenu-Handler. It is where execution *
- * begins. Here we perform the following functions: *
- * 1) Initialize program. This consists of determining what task we *
- * are and finding the public message port that the KeyMenu *
- * program created for us. If the port doesn't exist or if *
- * another task already owns it, we just exit (this can happen if *
- * the user somehow manages to run this program instead of *
- * KeyMenu). The global area behind the message port, created by *
- * Keymenu, is updated with our task address, the signal number *
- * to use to send messages to us, the address of our input *
- * handler routine and the version number of this program. We *
- * then signal KeyMenu that we are initialized. *
- * 2) Wait for one of two events to occur. Either a message has been *
- * directed to us via the public message port or KeyMenu has *
- * signalled us to stop. Process the event as appropriate. *
- * 3) Step 2, above, is repeated until our 'active' flag is reset. *
- * This occurs when, at our request, the input_handler sends a *
- * message to us indicating it is ready to stop. We then cleanup *
- * any resources we have allocated and return to AmigaDOS. *
- * *
- * Input Registers: *
- * None. *
- * *
- * Output Registers: *
- * None. *
- * *
- *******************************************************************************
- main movem.l mainregs,-(sp) ; save entry registers
- *-----------------------------------------------------------------------------*
- * do initialization *
- *-----------------------------------------------------------------------------*
- move.l AbsExecBase,a6 ; setup base for exec.library
- sub.l a1,a1 ; set to find our task
- Call FindTask ; get pointer to our task
- move.l d0,a2 ; get task address
- clr.l pr_ConsoleTask(a2) ; clear console handler pointer
- lea myport(pc),a1 ; pointer to port name
- Call FindPort ; go find our port
- tst.l d0 ; does it exist ?
- beq main060 ; no, must have it, get out
- move.l d0,gbl ; save pointer to our world
- tst.l MP_SIGTASK(gbl) ; is a task already there ?
- bne main060 ; yes, branch
- *-----------------------------------------------------------------------------*
- * everything seems ok, update our global area and signal KeyMenu to *
- * go ahead and add our input_handler routine to the input.device *
- *-----------------------------------------------------------------------------*
- moveq.l #-1,d0
- Call AllocSignal ; get a signal for our task
- move.b d0,MP_SIGBIT(gbl) ; save the signal number
- move.l a2,MP_SIGTASK(gbl) ; make our task the one to signal
- move.l a2,gb_handtask(gbl)
- lea input_handler(pc),a1 ; get addr of input handler code
- move.l a1,gb_handler+IS_CODE(gbl) ; put it in interrupt struct
- jsr dosignal ; go signal companion task
- moveq.l #1,d4 ; set active flag
- *-----------------------------------------------------------------------------*
- * if we are still active, wait for something to happen *
- *-----------------------------------------------------------------------------*
- main010 tst.w d4 ; are we still active ?
- beq main050 ; no, go clean things up
- clr.l d1 ; clear work register
- move.b MP_SIGBIT(gbl),d1 ; get signal bit number
- bset.l d1,d0 ; create signal mask
- bset.l #SIGBREAKB_CTRL_C,d0 ; set break bit
- Call Wait ; wait for something to happen
- *-----------------------------------------------------------------------------*
- * An event occurred! Determine if KeyMenu signalled 'CTRL C' *
- * telling us to stop. If not, there must be a message waiting on *
- * the message port. *
- *-----------------------------------------------------------------------------*
- btst.l #SIGBREAKB_CTRL_C,d0 ; did user request us to stop ?
- beq main015 ; no, branch
- bset.b #FLAGB_Stop_requested,gb_flags(gbl) ; set stop requested
- ; this tells the input handler to
- ; stop the next time it is entered
- bra main010 ; go wait for input handler to stop
- *-----------------------------------------------------------------------------*
- * get a message from the message port and determine what it is *
- *-----------------------------------------------------------------------------*
- main015 move.l gbl,a0 ; get address of message port
- Call GetMsg ; get any message placed there
- tst.l d0 ; was there a message queued ?
- beq main010 ; no, branch
- move.l d0,a2 ; save message address
- cmp.w #req_stopped,LN_NAME(a2) ; stop message ?
- bne main020 ; no, branch
- *-----------------------------------------------------------------------------*
- * A 'stop' message was received from the input handler. Clear our *
- * 'active' flag. *
- *-----------------------------------------------------------------------------*
- clr.l d4 ; yes, clear active flag
- main020 cmp.w #req_clearpointer,LN_NAME(a2) ; clear pointer request ?
- bne main030 ; no, branch
- *-----------------------------------------------------------------------------*
- * A 'clearpointer' request was received from the input handler. *
- * This causes us to reset the intuition pointer to its previous *
- * condition prior to our blanking it. *
- *-----------------------------------------------------------------------------*
- tst.l gb_Pointer(gbl) ; is any pointer info saved ?
- beq main025 ; no, branch
- move.l gb_window(gbl),a0 ; yes, setup to do 'SetPointer'
- move.l gb_Pointer(gbl),a1 ; this will restore the window's
- move.b gb_PtrHeight(gbl),d0 ; custom pointer
- ext.w d0
- ext.l d0
- move.b gb_PtrWidth(gbl),d1
- ext.w d1
- ext.l d1
- move.b gb_XOffset(gbl),d2
- ext.w d2
- ext.l d2
- move.b gb_YOffset(gbl),d3
- ext.w d3
- ext.l d3
- Call SetPointer,gb_IBase(gbl) ; restore the custom pointer
- clr.l gb_Pointer(gbl) ; clear pointer info
- bra main030
- main025 move.l gb_window(gbl),a0
- Call ClearPointer,gb_IBase(gbl) ; reset back to intuition's
- ; pointer
- main030 cmp.w #req_setpointer,LN_NAME(a2) ; set pointer request ?
- bne main040 ; no, branch
- *-----------------------------------------------------------------------------*
- * A 'setpointer' request was received from the input handler. This *
- * causes us to save info about the current custom pointer, if any, *
- * and call 'SetPointer' using our own 'blank' pointer. This removes *
- * the pointer from the user's view during menu operations. *
- *-----------------------------------------------------------------------------*
- move.l gb_window(gbl),a0
- tst.l wd_Pointer(a0) ; is there a custom pointer ?
- beq main035 ; no, branch
- move.l wd_Pointer(a0),gb_Pointer(gbl) ; save custom pointer info
- move.b wd_PtrHeight(a0),gb_PtrHeight(gbl)
- move.b wd_PtrWidth(a0),gb_PtrWidth(gbl)
- move.b wd_XOffset(a0),gb_XOffset(gbl)
- move.b wd_YOffset(a0),gb_YOffset(gbl)
- main035 move.l gb_blank_ptr(gbl),a1 ; setup to call 'SetPointer'
- moveq.l #-1,d0
- moveq.l #-1,d1
- clr.l d2
- clr.l d3
- Call SetPointer,gb_IBase(gbl)
- *-----------------------------------------------------------------------------*
- * free the message we received and loop to see if there is more *
- *-----------------------------------------------------------------------------*
- main040 clr.l d0
- move.l a2,a1 ; setup addr of block to free
- move.w MN_LENGTH(a1),d0 ; setup length of block to free
- Call FreeMem ; go free it
- bra main015 ; loop for next message
-
- myport portname
-
- *-----------------------------------------------------------------------------*
- * We are no longer active, cleanup after ourselves and get out *
- *-----------------------------------------------------------------------------*
- main050 move.l gbl,a0 ; get address of message port
- Call GetMsg ; get any message placed there
- tst.l d0 ; was there a message queued ?
- beq main055 ; no, branch
- move.l d0,a1 ; setup to free the block
- clr.l d0
- move.w MN_LENGTH(a1),d0 ; setup length of block to free
- Call FreeMem ; go free it
- bra main050 ; loop for next message
- main055 clr.l d0
- move.b MP_SIGBIT(gbl),d0 ; get signal number
- Call FreeSignal ; go free it
- Forbid
- jsr dosignal ; go signal companion task
- main060 movem.l (sp)+,mainregs ; restore entry registers
- rts ; return to AmigaDOS
- mainregs reg d1-d7/a0-a6
-
-
- *******************************************************************************
- * *
- * dosignal *
- * *
- * Send a signal to our companion task (should be KeyMenu). *
- * *
- * Input Registers: *
- * a4 - global work area *
- * *
- * Output Registers: *
- * None. *
- * *
- *******************************************************************************
- dosignal clr.l d1 ; clear work register
- move.b gb_tasksignum(gbl),d1 ; get keymenu task signal number
- bset.l d1,d0 ; create signal mask
- move.l gb_task(gbl),a1 ; get task to signal
- Call Signal ; signal the task that we are ready
- rts
-
- ******************************************************************************
- * *
- * input_handler *
- * *
- * This routine is added to the input.device's list of handlers by the *
- * KeyMenu program. It is called whenever an input event, such as a *
- * keyboard press or mouse movement, occurs. In general, the input event *
- * chain is scanned to see if the user has pressed any one of the *
- * various keys that we care about. If so, the input event representing *
- * that keypress is replaced with a mouse event(s) to accomplish *
- * KeyMenu's purpose. Note that the memory associated with event(s) that *
- * are removed from the list actually belongs to the creator of that *
- * event. It is the event creator's responsibility to free this memory. *
- * See the RKM for more info about input handlers and the input.device *
- * *
- * Input Registers: *
- * a0 - input event chain, a forward reference linked list with the *
- * last event in the chain containing a 'NULL' reference. *
- * a1 - global work area *
- * *
- * Output Registers: *
- * d0 - new input event chain *
- * *
- *******************************************************************************
- input_handler
-
- laste equr a1 ; last event handled in chain
- ev equr a2 ; original event passed to us
- ep equr a3 ; current event pointer
-
- movem.l ihregs,-(sp) ; save registers
- move.l a1,gbl ; setup pointer to our world
- move.l a0,ev ; save pointer to input event chain
- *-----------------------------------------------------------------------------*
- * If 'stop' has been posted, check to see if there is currently a *
- * menu active. If so, wait for the user to get out of it otherwise *
- * send a 'stop' message (actually means 'ready to stop') to the *
- * KeyMenu-Handler process. *
- *-----------------------------------------------------------------------------*
- btst.b #FLAGB_Stop_requested,gb_flags(gbl) ; stop requested ?
- beq ih010 ; no, branch
- btst.b #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
- bne ih010 ; yes, branch
- btst.b #FLAGB_Stopped,gb_flags(gbl) ; stop already been posted ?
- bne ih010 ; yes, branch
- moveq.l #req_stopped,d0 ; set type fo request to send
- jsr sendrequest ; go send it
- bset.b #FLAGB_Stopped,gb_flags(gbl) ; indicate stop has been posted
- *-----------------------------------------------------------------------------*
- * Begin stepping through the input event chain *
- *-----------------------------------------------------------------------------*
- ih010 FORBID ; don't let anyone mess with events
- sub.l laste,laste ; clear last event register
- move.l ev,ep ; setup event work register
- bclr.b #FLAGB_Events_inserted,gb_flags(gbl) ; clear inserted flag
- bra ih040 ; go see if an event exists
- ih015 cmp.b #IECLASS_RAWKEY,ie_Class(ep) ; Raw key event ?
- bne ih025 ; no, branch
- *-----------------------------------------------------------------------------*
- * This is a RAWKEY event (keypress/keyrelease). *
- *-----------------------------------------------------------------------------*
- jsr Check_RawKey_Event ; go look at this one
- beq ih030 ; do we keep it ? yes, branch
- move.l laste,d0 ; was there a previous event ?
- bne ih020 ; yes, branch
- move.l ie_NextEvent(ep),ev ; drop the event
- bra ih035
- ih020 move.l ie_NextEvent(ep),ie_NextEvent(laste)
- bra ih035 ; loop
- *-----------------------------------------------------------------------------*
- * Here we look for a 'MENUDOWN' event. If this occurs while we have *
- * a menu active, it indicates that the user pressed the right mouse *
- * button intending to take over menu selection with the mouse. *
- *-----------------------------------------------------------------------------*
- ih025 cmp.b #IECLASS_RAWMOUSE,ie_Class(ep) ; is this a raw mouse event ?
- bne ih030 ; no, branch
- cmp.w #MENUDOWN,ie_Code(ep) ; is it a menu down event ?
- bne ih030 ; no, branch
- btst.b #FLAGB_MActive,gb_flags(gbl) ; is a menu in progress ?
- beq ih030 ; no, branch
- bclr.b #FLAGB_MActive,gb_flags(gbl) ; give control of menu to mouse
- moveq.l #req_clearpointer,d0
- jsr sendrequest ; go reset intuition pointer
- *-----------------------------------------------------------------------------*
- * Now we look to see if we inserted any events in the chain. If so, *
- * we must get out. This is because we only have a fixed number of *
- * input event areas allocated (3) and they can be used only once *
- * per invocation of the handler. This could be a potential problem *
- * in that we could miss events that we care about (since we don't *
- * look at the remaining events in the event chain). However, this *
- * is nothing that would cause harm to the system. It would just *
- * appear to the user as though a keypress intended to cause a menu *
- * operation didn't take. This is better than incuring the overhead *
- * and buffer management problems associated with dynamically *
- * allocating input events. *
- *-----------------------------------------------------------------------------*
- ih030 move.l ep,laste ; save this event
- ih035 btst.b #FLAGB_Events_inserted,gb_flags(gbl) ; were events inserted?
- bne ih045 ; yes, branch
- *-----------------------------------------------------------------------------*
- * Setup to process the next event if one exists, otherwise get out *
- *-----------------------------------------------------------------------------*
- move.l ie_NextEvent(ep),ep ; get next event
- ih040 move.l ep,d0 ; set cc
- bne ih015 ; go check it
- ih045 PERMIT
- move.l ev,d0 ; pass event on
- movem.l (sp)+,ihregs ; restore registers
- rts ; return to input device
- ihregs reg a0/a1/a2/a3/a4/a6
-
- *******************************************************************************
- * *
- * sendrequest *
- * *
- * This routine is called by the input handler when it wishes to send a *
- * request message to the KeyMenu-Handler process. There are currently *
- * three kinds of messages that may be sent: *
- * 1) req_setpointer, to blank the intuition pointer during menu *
- * operations. *
- * 2) req_clearpointer, to restore the intuition pointer when menu *
- * operations are finished. *
- * 3) req_stopped, to signal that the handler is ready to stop. *
- * Sendrequest is always called regardless of the setting of the hide *
- * intuition pointer option. This is where we determine whether or not *
- * to actually send the request. *
- * *
- * Input Registers: *
- * d0 - type of request to be sent *
- * a4 - global work area *
- * *
- * Output Registers: *
- * none. *
- * *
- *******************************************************************************
- sendrequest movem.l sendreqregs,-(sp) ; save entry registers
- btst.b #FLAGB_Blank_pointer,gb_flags(gbl) ; blank pointer option on ?
- bne sendreq010 ; yes, branch
- cmp.w #req_stopped,d0 ; is this a 'stopped' request ?
- bne sendreq020 ; no, branch
- sendreq010 move.l d0,d2 ; save request type
- move.l #MEMF_CLEAR+MEMF_PUBLIC,d1 ; set attributes
- move.l #MN_SIZE,d0 ; set size of block
- Call AllocMem ; go allocate a block
- tst.l d0 ; was a block given to us ?
- beq sendreq020 ; no, branch
- move.l d0,a1 ; yes, save pointer to block
- move.w d2,LN_NAME(a1) ; format message
- clr.l MN_REPLYPORT(a1)
- move.w #MN_SIZE,MN_LENGTH(a1)
- move.l gbl,a0
- Call PutMsg ; write it to the port
- sendreq020 movem.l (sp)+,sendreqregs ; restore registers
- rts ; return to caller
- sendreqregs reg a0/a1/d0-d2
-
- *******************************************************************************
- * *
- * Check_RawKey_Event *
- * *
- * This routine checks each RAWKEY event (keypress/keyrelease) to see if *
- * it is one that we are interested in. If it is, the event that is *
- * passed to us is replaced with events to do the appropriate KeyMenu *
- * function. Events that have no meaning for us are passed back to the *
- * caller indicating that they should remain in the input event chain. *
- * *
- * Input Registers: *
- * a3 - rawkey event to be checked *
- * a4 - global work area *
- * *
- * Output Registers: *
- * d0 - 0=discard the event, 1=keep the event *
- * *
- *******************************************************************************
- Check_RawKey_Event
- movem.l creregs,-(sp) ; save registers
- clr.l d0
- btst.b #IEQUALIFIER_REPEAT_R,ie_Qualifier(a3) ; is it a repeat ?
- beq cre003 ; no, branch
- btst.b #FLAGB_Repeat_skipped,gb_flags(gbl) ; have we skipped one ?
- bne cre004 ; yes, branch
- bset.b #FLAGB_Repeat_skipped,gb_flags(gbl) ; indicate repeat skipped
- bra cre_remove ; remove it from the input chain
- cre003 bclr.b #FLAGB_Repeat_skipped,gb_flags(gbl) ; clear repeat skipped
- cre004 btst.b #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
- bne cre035 ; yes, branch
- *-----------------------------------------------------------------------------*
- * A menu is not currently active, check to see if one is being *
- * activated (keypress of the configured activation key). *
- *-----------------------------------------------------------------------------*
- move.b gb_AKey(gbl),d0 ; get configured activation key code
- cmp.w ie_Code(a3),d0 ; Menu Activate Key ?
- bne cre010 ; no, branch
- *-----------------------------------------------------------------------------*
- * The user pressed the menu activation key, set a flag indicating *
- * that fact and wait to see if the key is released without pressing *
- * any other keys. *
- *-----------------------------------------------------------------------------*
- bset.b #FLAGB_AKey_down,gb_flags(gbl) ; indicate Menu activate key
- ; down
- cre005 bra cre_remove ; remove this event
- cre010 bset.l #IECODE_UP_PREFIX_R,d0 ; form keyrelease keycode
- cmp.w ie_Code(a3),d0 ; is it activate menu keyrelease ?
- beq cre014 ; yes, branch
- cre012 bclr.b #FLAGB_AKey_down,gb_flags(gbl) ; clear activate key down
- bra cre_keep ; keep this event
- cre014 btst.b #FLAGB_AKey_down,gb_flags(gbl) ; is activate key down still
- ; posted ?
- beq cre012 ; no, branch
- *-----------------------------------------------------------------------------*
- * The user pressed and released the menu activation key without *
- * hitting any other keys, find the current window and see if it has *
- * a menu. *
- *-----------------------------------------------------------------------------*
- move.l gb_IBase(gbl),a5 ; get intuitionbase
- move.l ib_ActiveWindow(a5),d0 ; get current window
- beq cre005 ; if none, branch
- move.l d0,a1 ; save pointer to current window
- move.l wd_MenuStrip(a1),d0 ; get window's menu
- beq cre005 ; if none, branch
- move.l d0,a0 ; save menu for use later
- move.l wd_Flags(a1),d0 ; get window's flags
- btst.l #MENUSTATE_B,d0 ; is a menu already active ?
- bne cre005 ; yes, branch
- *-----------------------------------------------------------------------------*
- * The current window has a menu, check the RMBTRAP flag. If this is *
- * set and the user didn't specify that we can clear it, then we *
- * can't use this menu. *
- *-----------------------------------------------------------------------------*
- btst.l #RMBTRAP_B,d0 ; is RMBTRAP set in window ?
- beq cre015 ; no, branch
- btst.b #FLAGB_Clear_rmbtrap,gb_flags(gbl) ; clear rmbtrap option
- ; set ?
- beq cre005 ; no, ignore the menu
- bclr.l #RMBTRAP_B,d0 ; clear RMBTRAP bit
- move.l d0,wd_Flags(a1) ; update window's flags
- *-----------------------------------------------------------------------------*
- * Finally, a menu we can use. Update our globals. *
- *-----------------------------------------------------------------------------*
- cre015 move.l a0,gb_menu(gbl) ; update our Menu pointer
- move.l a1,gb_window(gbl) ; update our window pointer
- *-----------------------------------------------------------------------------*
- * Now look to see if the menu and menu item saved in our globals is *
- * still valid for this menu. If so, we will position the mouse on *
- * them otherwise we'll put the mouse on the topmost item in the *
- * leftmost menu. *
- *-----------------------------------------------------------------------------*
- move.l gb_currentmenu(gbl),a1 ; get saved menu
- jsr Verify_Item ; go verify currentmenu
- bne cre020 ; does it exist ? yes, use it
- move.w #s_leftmost,d0 ; no, setup to find leftmost menu
- jsr Select_Item ; go select a Menu
- move.l d0,gb_currentmenu(gbl) ; update our globals with new menu
- cre020 move.l gb_currentmenu(gbl),a0 ; get current menu
- move.l mu_FirstItem(a0),a0 ; point to first menu item
- move.l gb_currentitem(gbl),a1 ; get current menu item
- jsr Verify_Item ; go verify current item
- bne cre025 ; does it exist ? yes, branch
- move.w #s_top,d0 ; no, setup to find top menuitem
- jsr Select_Item ; go select menu item
- move.l d0,gb_currentitem(gbl) ; update our globals
- *-----------------------------------------------------------------------------*
- * Save the current mouse position so we can put it back where we *
- * found it when we're done. set/clear various flags reflecting our *
- * current state. Three events are inserted in the event chain. *
- * A rawmouse menudown event that causes intuition to activate the *
- * menu followed by two pointerpos events to position the pointer *
- * first on the desired menu then on the menu item within that menu. *
- *-----------------------------------------------------------------------------*
- cre025 move.w ib_MouseX(a5),gb_old_MouseX(gbl) ; save current X
- move.w ib_MouseY(a5),gb_old_MouseY(gbl) ; save current Y
- clr.l gb_currentsubitem(gbl) ; no subitem at present
- move.w #MENUDOWN,d0 ; setup to insert a menudown event
- move.l a3,a1 ; event to attach new event to
- jsr Insert_RawMouse_Event ; go insert the rawmouse event
- moveq.l #2,d0 ; indicate 2 events to be built
- move.l a0,a1 ; event to attach new events to
- jsr db010 ; go build the necessary events
- bclr.b #FLAGB_AKey_down,gb_flags(gbl) ; no longer waiting for
- ; activate key down event
- move.l #req_setpointer,d0 ; setup to send request
- cre027 bchg.b #FLAGB_MActive,gb_flags(gbl) ; invert menu active bit
- jsr sendrequest ; send pointer req to our task
- bra cre_remove ; go to common return
- *-----------------------------------------------------------------------------*
- * A menu is currently active, check for the various keys that we *
- * care about. *
- *-----------------------------------------------------------------------------*
- cre035 move.b gb_DKey(gbl),d0
- cmp.w ie_Code(a3),d0 ; Deactivate key ?
- bne cre040 ; no, branch
- *-----------------------------------------------------------------------------*
- * The menu 'deactivate' key was pressed. Three events are inserted *
- * in the event chain. They consist of a pointerpos event to *
- * position the pointer in the menu strip followed by a rawmouse *
- * menuup event that causes intuition to deactivate the menu without *
- * selecting anything followed by another pointerpos event to put *
- * the pointer back where we found it when the menu was activated. *
- *-----------------------------------------------------------------------------*
- moveq.l #3,d0 ; build 2 events
- jsr dobuild ; go build mouse event(s)
- move.w #MENUUP,d0 ; setup for a menu up rawmouse event
- move.l a0,a1 ; event to attach new event to
- jsr Insert_RawMouse_Event ; go insert the a rawmouse event
- move.l #req_clearpointer,d0 ; setup to restore pointer
- bra cre027 ; get out
-
- cre040 move.b gb_SKey(gbl),d0
- cmp.w ie_Code(a3),d0 ; Select Key ?
- bne cre055 ; yes, branch
- *-----------------------------------------------------------------------------*
- * The menu 'select' key was pressed. Two events are inserted in the *
- * event chain. They consist of a menuup rawmouse event to select *
- * the current menu item, followed by a pointer event to put the *
- * pointer back where we found it when the menu was activated. *
- *-----------------------------------------------------------------------------*
- move.l a3,a1 ; event to attach new ones to
- move.w #MENUUP,d0 ; set type of rawmouse event
- jsr Insert_RawMouse_Event ; go insert a menuup event
- move.l gb_IBase(gbl),a5 ; get intuitionbase address
- move.w gb_old_MouseX(gbl),d0 ; get saved mouse x coordinate
- move.w gb_old_MouseY(gbl),d1 ; get saved mouse y cooridnate
- move.l a0,a1 ; event to attach new event to
- lea gb_ppos1(gbl),a0 ; new event to be inserted
- jsr Insert_PointerPos_Event
- move.l #req_clearpointer,d0 ; setup to restore pointer
- bra cre027 ; get out
-
- cre055 move.b gb_RightKey(gbl),d0
- cmp.w ie_Code(a3),d0 ; Move Right ?
- bne cre060 ; no, branch
- move.w #s_adjacent_right,d1 ; 1st selection choice
- move.w #s_right,d2 ; 2nd selection choice
- move.w #s_leftmost,d3 ; 3rd selection choice
- bra cre065
- cre060 move.b gb_LeftKey(gbl),d0
- cmp.w ie_Code(a3),d0 ; Move Left ?
- bne cre125 ; no, branch
- move.w #s_adjacent_left,d1 ; 1st selection choice
- move.w #s_left,d2 ; 2nd selection choice
- move.w #s_rightmost,d3 ; 3rd selection choice
- cre065 move.b ie_Qualifier+1(a3),d0 ; get key qualifier
- and.b gb_Qual(gbl),d0 ; was qualifier key present ?
- beq cre067 ; no,branch
- *-----------------------------------------------------------------------------*
- * The menu 'right' or 'left' key was pressed. See if a qualifier *
- * key was also present. If so, we move to either rightmost or *
- * leftmost menu. *
- *-----------------------------------------------------------------------------*
- move.w #s_rightmost,d0 ; select rightmost
- cmp.w d0,d3 ; same selection ?
- bne cre107 ; no, branch
- move.w #s_leftmost,d0 ; select leftmost
- bra cre107 ; go choose the menu
- *-----------------------------------------------------------------------------*
- * The menu 'right' or 'left' key was pressed. Now we must see if *
- * a subitem list exists for the current menu item. *
- *-----------------------------------------------------------------------------*
- cre067 move.l gb_currentitem(gbl),a0 ; get current menu item ptr
- move.l mi_SubItem(a0),a1 ; get its menu subitem ptr, if any
- move.l a1,d0 ; set cc
- beq cre100 ; no subitems on this menu, branch
- *-----------------------------------------------------------------------------*
- * There are subitems attached to this menu item. Some explanation *
- * is in order here. With Intuition, menu subitems can be rendered *
- * anywhere on the menu display as long as at least one pixel of the *
- * menu subitem overlaps a pixel of its associated menu item. *
- * Generally, subitems are designed to appear either to the right of *
- * its associated menu item or to the left. This affects our *
- * interpretation of what the user wants to do when they press *
- * either the menu right or menu left key. For example, if the menu *
- * subitems are positioned to the right of the menu item and the *
- * menu right key is pressed, this means that the user intends to *
- * step into the menu subitem list. If the menu subitems are *
- * positioned on the left and the menu right key is pressed, the *
- * user wants to step to the next list of menu items on the right *
- * (or wrap to the first set of menu items if we are positioned on *
- * the rightmost menu item). Here we check the leftedge of the *
- * subitem against the leftedge of the menu item to determine if the *
- * subitem's leftedge is less than (or to the left of) the menu *
- * item's leftedge. The result of this comparison is saved in d4 and *
- * is used later in determining what the user's intentions are. *
- *-----------------------------------------------------------------------------*
- move.w mi_LeftEdge(a1),d0 ; get subitem's leftedge
- cmp.w mi_LeftEdge(a0),d0 ; compare to menuitem's leftedge
- slt d4 ; save comparison result
- tst.l gb_currentsubitem(gbl) ; are we processing subitems ?
- bne cre080 ; yes, branch
- *-----------------------------------------------------------------------------*
- * We are positioned on a menu item that has subitems attached and *
- * the user has pressed the menu right or menu left key. Determine *
- * what their intention is. Either they want to step into the *
- * subitem list or they want to select the next menu item. *
- *-----------------------------------------------------------------------------*
- clr.l d0
- move.b gb_RightKey(gbl),d0 ; setup for compare
- cmp.w ie_Code(a3),d0 ; right key ?
- bne cre070 ; no, branch
- tst.b d4 ; are subitems on menu items left ?
- beq cre075 ; no, step into the subitem list
- bra cre100 ; yes, step to next menu item list
- cre070 tst.b d4 ; are subitems on menu items left ?
- beq cre100 ; no, step to next menu item list
- ; yes, step into the subitem list
- *-----------------------------------------------------------------------------*
- * The user wants to step into the subitem list. Select the topmost *
- * adjacent subitem in the list. (Note: there can be subitems *
- * positioned horizontally as well as vertically) *
- *-----------------------------------------------------------------------------*
- cre075 move.w #s_adjacent_top,d0 ; set to select the topmost subitem
- move.l a1,a0 ; list of subitems to choose from
- jsr Select_Item ; go find the subitem
- move.l d0,gb_currentsubitem(gbl) ; save it in our globals
- bra cre085 ; go generate an event
- *-----------------------------------------------------------------------------*
- * We are currently positioned on a menu subitem and the user has *
- * pressed either the menu right key or menu left key. Determine *
- * what their intention is. If there is another subitem positioned *
- * adjacent to the current subitem in the direction of the key that *
- * was pressed, that subitem will be selected. Otherwise, the user *
- * wants to step out of the subitem list. *
- *-----------------------------------------------------------------------------*
- cre080 move.l d1,d0 ; get 1st selection choice
- move.l a1,a0 ; list of subitems to choose from
- move.l gb_currentsubitem(gbl),a1 ; supply current subitem
- jsr Select_Item ; go select next subitem
- cmp.l d0,a1 ; same item selected ?
- beq cre090 ; yes, get out of the subitem list
- move.l d0,gb_currentsubitem(gbl) ; no, save new subitem
- cre085 moveq.l #1,d0 ; set to build only one event
- bra cre175 ; go generate an event
- *-----------------------------------------------------------------------------*
- * The user wants to step out of the subitem list. Determine whether *
- * they want to go back to the menu item associated with the subitem *
- * list or to the next menu item. *
- *-----------------------------------------------------------------------------*
- cre090 clr.l gb_currentsubitem(gbl) ; clear current subitem pointer
- clr.l d0
- move.b gb_RightKey(gbl),d0 ; setup for compare
- cmp.w ie_Code(a3),d0 ; right key ?
- bne cre095 ; no, branch
- tst.b d4 ; are subitems on menu items left ?
- bne cre085 ; yes, go back to subitems menu item
- bra cre100 ; no, go select next menu item list
- cre095 tst.b d4 ; are subitems on menu items left ?
- beq cre085 ; no, go back to subitems menu item
- *-----------------------------------------------------------------------------*
- * Select a menu item. (Note: there can be menu items positioned *
- * horizontally as well as vertically) *
- *-----------------------------------------------------------------------------*
- cre100 move.l d1,d0 ; get 1st selection choice
- move.l gb_currentmenu(gbl),a0 ; get current menu
- move.l mu_FirstItem(a0),a0 ; list of items to choose from
- move.l gb_currentitem(gbl),a1 ; get current menu item
- jsr Select_Item ; go select an item
- cmp.l d0,a1 ; same item selected ?
- bne cre115 ; no, use the new item, branch
- *-----------------------------------------------------------------------------*
- * There are no menu items positioned in the horizontal direction of *
- * the key that was pressed, so we must step to the next menu. *
- *-----------------------------------------------------------------------------*
- move.l d2,d0 ; get 2nd selection choice
- move.l gb_menu(gbl),a0 ; list of menus to choose from
- move.l gb_currentmenu(gbl),a1 ; get current menu
- jsr Select_Item ; go select a menu
- cmp.l d0,a1 ; same menu selected ?
- beq cre105 ; yes, branch
- move.l d0,gb_currentmenu(gbl) ; no, use the new menu
- bra cre110 ; go select an item in the menu
- *-----------------------------------------------------------------------------*
- * There are no menus in the horizontal direction of the key that *
- * was pressed. We will interpret this to mean that the user wants *
- * to wrap to the opposite end of the menu strip. For example, if we *
- * are currently on the rightmost menu and the user presses the menu *
- * right key, we will wrap around to the leftmost menu. *
- *-----------------------------------------------------------------------------*
- cre105 move.l d3,d0 ; set 3rd selection choice
- cre107 move.l gb_menu(gbl),a0 ; list of menus to choose from
- jsr Select_Item ; go select again
- move.l d0,gb_currentmenu(gbl) ; save new menu
- cre110 move.w #s_top,d0 ; set to select topmost menu item
- move.l gb_currentmenu(gbl),a0 ; get current menu
- move.l mu_FirstItem(a0),a0 ; list of items to choose from
- jsr Select_Item ; go select a menu item
- move.l d0,gb_currentitem(gbl) ; save new item
- *-----------------------------------------------------------------------------*
- * Normally, we will generate only one event. A pointerpos event to *
- * position the pointer on the desired menu item or subitem. Here we *
- * have determined that a new menu is to be selected. This requires *
- * us to generate 2 events. The first will be a pointerpos event to *
- * position the pointer in the menu strip over the menu that we want *
- * to select. This causes Intuition to remove the rendering of the *
- * current menu from the display and render the menu that we are *
- * selecting. The second event will be a pointerpos event to *
- * position the pointer on the menu item that we have chosen. *
- *-----------------------------------------------------------------------------*
- moveq.l #2,d0 ; set number of events to build
- bra cre120
- cre115 move.l d0,gb_currentitem(gbl) ; save new item
- moveq.l #1,d0 ; set number of events to build
- cre120 clr.l gb_currentsubitem(gbl) ; clear current subitem pointer
- bra cre175 ; go generate event(s)
-
- cre125 move.b gb_DownKey(gbl),d0 ; setup for compare
- cmp.w ie_Code(a3),d0 ; Down key ?
- bne cre130 ; no, branch
- move.w #s_adjacent_up,d1 ; 1st selection choice
- move.w #s_up,d2 ; 2nd selection choice
- move.w #s_top,d3 ; 3rd selection choice
- bra cre135 ; go handle keypress
- cre130 move.b gb_UpKey(gbl),d0 ; setup for compare
- cmp.w ie_Code(a3),d0 ; Up key ?
- bne cre_keep ; no, pass this event on
- move.w #s_adjacent_down,d1 ; 1st selection choice
- move.w #s_down,d2 ; 2nd selection choice
- move.w #s_bottom,d3 ; 3rd selection choice
- *-----------------------------------------------------------------------------*
- * The menu 'up' or 'down' key was pressed. If we are currently *
- * positioned in a subitem menu, setup to select the appropriate *
- * subitem otherwise setup to select the appropriate menu item. *
- *-----------------------------------------------------------------------------*
- cre135 moveq.l #1,d4 ; set default # events to be created
- tst.l gb_currentsubitem(gbl) ; are we processing subitems ?
- beq cre140 ; no, branch
- move.l gb_currentsubitem(gbl),a1 ; supply parameters to process
- move.l gb_currentitem(gbl),a0 ; menu subitems
- move.l mi_SubItem(a0),a0
- bra cre145
- cre140 move.l gb_currentitem(gbl),a1 ; supply parameters to process menu
- move.l gb_currentmenu(gbl),a0 ; items
- move.l mu_FirstItem(a0),a0
- *-----------------------------------------------------------------------------*
- * Here we check to see if there are subitems attached to the *
- * current menu item. If so, we will generate 2 events. The first *
- * will be a pointerpos event to position the pointer on the menu *
- * strip. The second will be a pointerpos event to position the *
- * pointer on the desired menu item. This is done to cause Intuition *
- * to remove the subitem's rendering from the display in case it *
- * overlaps onto the menu item being selected. Without this, we *
- * would tell Intuition to position the mouse on the new menu item *
- * but the overlapping subitems from the current menu item would *
- * still be displayed causing us to select a menu subitem instead of *
- * the menu item that we intended to select. *
- *-----------------------------------------------------------------------------*
- tst.l mi_SubItem(a1) ; are there subitems attached to
- ; this menu item ?
- beq cre145 ; no, branch
- moveq.l #2,d4 ; yes, use 2 events to select item
- cre145 move.b ie_Qualifier+1(a3),d0 ; get key qualifier
- and.b gb_Qual(gbl),d0 ; was qualifier key present ?
- beq cre147 ; no, branch
- *-----------------------------------------------------------------------------*
- * See if a qualifier key was also present. If so, we move to either *
- * topmost or bottommost menu or submenu item. *
- *-----------------------------------------------------------------------------*
- move.w #s_bottom,d0 ; select bottom
- cmp.w d0,d3 ; same selection ?
- bne cre153 ; no, branch
- move.w #s_top,d0 ; select top
- bra cre153
- cre147 move.l d1,d0 ; get 1st selection choice
- jsr Select_Item ; go select a menuitem or subitem
- cmp.l d0,a1 ; same item selected ?
- bne cre155 ; no, use the new one
- move.l d2,d0 ; get 2nd selection choice
- jsr Select_Item ; select again
- cre150 cmp.l d0,a1 ; same item selected ?
- bne cre155 ; no, use new item
- move.l d3,d0 ; get 3rd selection choice
- cre153 jsr Select_Item ; go select again
- cre155 move.l d0,a1 ; save new item
- cre160 tst.l gb_currentsubitem(gbl) ; are we processing subitems ?
- beq cre165 ; no, branch
- move.l a1,gb_currentsubitem(gbl) ; yes, save new subitem
- bra cre170
- cre165 move.l a1,gb_currentitem(gbl) ; save new item
- cre170 move.l d4,d0 ; get # of events to be generated
- cre175 jsr dobuild ; go build our events
- *-----------------------------------------------------------------------------*
- * Indicate that the original input event passed to this routine is *
- * to be removed from the input event chain and return. *
- *-----------------------------------------------------------------------------*
- cre_remove moveq.l #1,d0 ; indicate old event to be removed
- bra cre_exit ; go to common return
- *-----------------------------------------------------------------------------*
- * Indicate that the original input event passed to this routine is *
- * to be kept in the input event chain and return. *
- *-----------------------------------------------------------------------------*
- cre_keep clr.l d0 ; indicate old event to be kept
- cre_exit movem.l (sp)+,creregs ; restore registers
- rts ; return to caller
- creregs reg a1-a3/a5/d2-d4
-
- *******************************************************************************
- * *
- * dobuild *
- * *
- * This routine is called by Check_RawKey_Event to perform a general *
- * call to the Build_PointerPos_Event routine. *
- * *
- * Input Registers: *
- * a3 - input event to attach new events to *
- * a4 - global work area *
- * *
- * Output Registers: *
- * a0 - new input event *
- * a1 - original input event *
- * *
- *******************************************************************************
- dobuild move.l a3,a1 ; pass original input event
- db010 lea gb_ppos2(gbl),a0 ; point to our input event area
- jsr Build_PointerPos_Event ; go create our input events
- rts ; return to caller
-
- *******************************************************************************
- * *
- * Verify_Item *
- * *
- * This routine is called by Check_RawKey_Event to verify if a menu or *
- * menu item is a member of a provided list of menu/menu items. *
- * *
- * Input Registers: *
- * a0 - menu/menu item list *
- * a1 - item to be verified. *
- * *
- * Output Registers: *
- * d0 - 0=no match, 1=match *
- * *
- *******************************************************************************
- Verify_Item movem.l viregs,-(sp)
- vi010 cmp.l a0,a1 ; does this item match ?
- beq vi015 ; yes, branch
- move.l im_NextItem(a0),d0 ; get next item's address
- beq vi020 ; entire list scanned, branch
- move.l d0,a0 ; use next item's address
- bra vi010 ; loop to check next item
- vi015 moveq.l #1,d0 ; indicate that the item exists
- vi020 movem.l (sp)+,viregs
- rts
- viregs reg a0/a1
-
- *******************************************************************************
- * *
- * Select_Item *
- * *
- * This routine is called to select a menu, menu item or menu subitem. *
- * Given a list of items to choose from, the attribute of the item *
- * desired and the current item; this routine attempts to find a new *
- * item that matches the desired attribute. For example, if d0 contains *
- * 's_up' the list of items provided is scanned to find the closest item *
- * that is physically above the current item on the display. *
- * *
- * Input Registers: *
- * a0 - menu/menu item/menu subitem list *
- * a1 - current item *
- * d0 - type of item desired in relation to current item *
- * *
- * Output Registers: *
- * d0 - selected item (or current item if no item was selected) *
- * *
- *******************************************************************************
- Select_Item
-
- select_type equr d0 ; select type & return value
- item equr a0 ; item list
- currentitem equr a1 ; currentitem
- returnitem equr a2 ; return item
- work equr d1 ; work register
-
- *-----------------------------------------------------------------------------*
- * 'returnitem' contains the address of the item that is being *
- * considered for return to the calling routine. Here we create a *
- * dummy item on the stack that contains extreme values for topedge *
- * and leftedge. The address of this entry is loaded into *
- * 'returnitem' to give us an initial entry to compare against. *
- * For example, if 's_leftmost' is the attribute of the item that we *
- * are searching for, the leftedge field in the dummy entry would *
- * contain 32768. In an effort to find the 'leftmost' item in the *
- * list, the 'si_leftmost' portion of this routine will compare the *
- * leftedge of each item in the list with the leftedge of *
- * 'returnitem'. When an item is found with a leftedge that is less *
- * than returnitem's, its address is placed in returnitem. When the *
- * end of the list is reached, the item with the lowest leftedge *
- * should be contained in 'returnitem' *
- *-----------------------------------------------------------------------------*
- link a5,#-im_size
- movem.l siregs,-(sp)
- move.w #32767,work
- cmp.w #s_leftmost,select_type
- ble si010
- move.w #-32768,work
- si010 lea -im_size(a5),returnitem
- move.w work,im_TopEdge(returnitem) ; setup dummy item
- move.w work,im_LeftEdge(returnitem)
- bra si_jmp ; go to computed jump
- si_adjacent_up
- move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(currentitem),work
- bne si_check_end
- si_up move.w im_TopEdge(item),work
- cmp.w im_TopEdge(currentitem),work
- ble si_check_end
- si_top
- si_adjacent_top
- move.w im_TopEdge(item),work
- cmp.w im_TopEdge(returnitem),work
- bge si015
- move.l item,returnitem
- si015 cmp.w #s_adjacent_top,select_type
- bne si_check_end
- move.w im_TopEdge(item),work
- cmp.w im_TopEdge(returnitem),work
- bne si_check_end
- move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(returnitem),work
- bge si_check_end
- move.l item,returnitem
- bra si_check_end
- si_adjacent_right
- move.w im_TopEdge(item),work
- cmp.w im_TopEdge(currentitem),work
- bne si_check_end
- si_right move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(currentitem),work
- ble si_check_end
- si_leftmost move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(returnitem),work
- bge si_check_end
- move.l item,returnitem
- bra si_check_end
- si_adjacent_down
- move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(currentitem),work
- bne si_check_end
- si_down move.w im_TopEdge(item),work
- cmp.w im_TopEdge(currentitem),work
- bge si_check_end
- si_bottom move.w im_TopEdge(item),work
- cmp.w im_TopEdge(returnitem),work
- ble si_check_end
- move.l item,returnitem
- bra si_check_end
- si_adjacent_left
- move.w im_TopEdge(item),work
- cmp.w im_TopEdge(currentitem),work
- bne si_check_end
- si_left move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(currentitem),work
- bge si_check_end
- si_rightmost
- move.w im_LeftEdge(item),work
- cmp.w im_LeftEdge(returnitem),work
- ble si_check_end
- move.l item,returnitem
- si_check_end
- move.l im_NextItem(item),item
- move.l item,work ; set cc
- beq si_end
- si_jmp jmp (pc,d0.w) ; jump to proper routine
- si_end lea -im_size(a5),item
- cmp.l item,returnitem ; still pointing to dummy item ?
- bne si_return ; no, branch
- move.l currentitem,returnitem ; yes, pass currentitem back
- si_return move.l returnitem,d0 ; set return
- movem.l (sp)+,siregs ; restore regs
- unlk a5 ; remove area from stack
- rts ; return to caller
- siregs reg d1/a0-a2
-
- *******************************************************************************
- * *
- * Insert_PointerPos_Event *
- * *
- * This routine creates a pointerpos event and attaches it to the input *
- * event provided. *
- * *
- * Input Registers: *
- * a0 - new event to be inserted *
- * a1 - input event to attach new event to *
- * d0 - Mouse X coordinate to place in new event *
- * d1 - Mouse Y coordinate to place in new event *
- * *
- * Output Registers: *
- * none. *
- * *
- *******************************************************************************
- Insert_PointerPos_Event
- move.b #IECLASS_POINTERPOS,ie_Class(a0) ; build mousemove event
- move.w #IECODE_NOBUTTON,ie_Code(a0)
- move.w d0,ie_X(a0) ; set coordinates
- move.w d1,ie_Y(a0)
- bra ire010
-
- *******************************************************************************
- * *
- * Insert_RawMouse_Event *
- * *
- * This routine creates a rawmouse event and attaches it to the input *
- * event provided. *
- * *
- * Input Registers: *
- * a1 - input event to attach new event to *
- * d0 - type of rawmouse event *
- * *
- * Output Registers: *
- * none. *
- * *
- *******************************************************************************
- Insert_RawMouse_Event
- lea gb_rawm(gbl),a0
- move.b #IECLASS_RAWMOUSE,ie_Class(a0) ; build rawmouse event
- move.w d0,ie_Code(a0)
- clr.w ie_X(a0)
- clr.w ie_Y(a0)
- ire010 clr.b ie_SubClass(a0)
- clr.w ie_Qualifier(a0)
- move.l ie_NextEvent(a1),ie_NextEvent(a0) ; chain to original event
- move.l a0,ie_NextEvent(a1)
- rts ; return to caller
-
- *******************************************************************************
- * *
- * Build_PointerPos_Event *
- * *
- * This routine creates pointer position event(s) and attaches them to *
- * the input event provided. The resolution of the current screen is *
- * taken into account when generating the events. The coordinates of the *
- * pointer position events are alway represented in the highest *
- * resolution i.e. 640x400. The coordinate fields of menus, menu items, *
- * etc. are represented in the resolution of the screen to which the *
- * menu is attached. When we position the pointer on anything but a *
- * hires interlace screen, we must adjust the coordinates that are taken *
- * from the menus to allow for this. *
- * *
- * Input Registers: *
- * a0 - address of input event to be built *
- * a1 - original input event *
- * d0 - number of input events to generate. *
- * *
- * Output Registers: *
- * none. *
- * *
- *******************************************************************************
- Build_PointerPos_Event
-
- iheight equr d1
- iwidth equr d1
- itopedge equr d2
- ileftedge equr d2
- mheight equr d3
- mwidth equr d3
- mtopedge equr d4
- mleftedge equr d4
- offsetx equr d5
- offsety equr d6
-
- movem.l breregs,-(sp) ; save registers
- jsr Insert_PointerPos_Event ; go insert new event
- move.l gb_window(gbl),a2 ; get current window
- move.l wd_WScreen(a2),a2 ; get window's screen
- move.l gb_currentmenu(gbl),a3 ; get current menu
- move.w mu_TopEdge(a3),mtopedge ; get menu's topedge
- add.w sc_ViewPort+vp_DyOffset(a2),mtopedge ; add screen's offset
- swap mtopedge
- move.w mu_LeftEdge(a3),mleftedge ; get menu's leftedge
- add.w sc_ViewPort+vp_DxOffset(a2),mleftedge ; add screen's offset
- clr.l mheight
- move.b sc_BarHeight(a2),mheight ; get menu's height
- swap mheight
- move.w mu_Width(a3),mwidth ; get menu's width
- move.l gb_currentitem(gbl),a3 ; get current menuitem
- move.w mi_TopEdge(a3),itopedge ; get menuitem's topedge
- swap itopedge
- move.w mi_LeftEdge(a3),ileftedge ; get menuitem's leftedge
- move.w mi_Height(a3),iheight ; get menuitem's height
- swap iheight
- move.w mi_Width(a3),iwidth ; get menuitem's width
- move.l gb_currentsubitem(gbl),a5 ; is there a subitem ?
- move.l a5,d5 ; set cc
- beq bre010 ; no, branch
- add.w mi_LeftEdge(a5),ileftedge ; yes, add subitem's leftedge
- move.w mi_Width(a5),iwidth ; use subitem's width
- swap ileftedge
- add.w mi_TopEdge(a5),itopedge ; add subitem's topedge
- swap itopedge
- swap iwidth
- move.w mi_Height(a5),iheight ; use subitem's height
- swap iheight
- bra bre025
- bre010 move.l mi_SubItem(a3),a5 ; is there a subitem for this item ?
- move.l a5,d5 ; set cc
- beq bre025 ; no, branch
- move.w mi_LeftEdge(a5),d5 ; yes, get subitem's leftedge
- cmp.w mi_LeftEdge(a3),d5 ; is it's leftedge less than item's?
- bge bre020 ; no, branch
- add.w d5,ileftedge ; yes, add subitems leftedge
- add.w mi_Width(a5),ileftedge ; add subitem's width
- move.w mi_LeftEdge(a3),iwidth ; get items leftedge
- add.w mi_Width(a3),iwidth ; add its width
- move.l ileftedge,d5 ; get item's leftedge
- bge bre015 ; if its positive, branch
- neg d5 ; make it positive
- bre015 sub.w d5,iwidth
- bra bre025
- bre020 movem.l d0/a0,-(sp) ; save our registers
- move.l a5,a0 ; pass subitem pointer
- move.l #s_adjacent_top,d0 ; set select type
- jsr Select_Item
- move.l d0,a5 ; get selected item
- movem.l (sp)+,d0/a0 ; restore our registers
- move.w mi_LeftEdge(a5),iwidth
- sub.w #1,iwidth
- bre025 move.w sc_ViewPort+vp_Modes(a2),d5 ; get screen modes
- btst.l #V_HIRES_B,d5 ; is this a hires screen ?
- bne bre030 ; yes, branch
- asl.w #1,iwidth ; no, adjust coordinates for hires
- asl.w #1,ileftedge
- asl.w #1,mwidth
- asl.w #1,mleftedge
- bre030 btst.l #V_LACE_B,d5 ; is this an interlace screen ?
- bne bre035 ; yes, branch
- swap iwidth ; no, adjust coordinates for interlace
- swap ileftedge
- swap mwidth
- swap mleftedge
- asl.w #1,iheight
- asl.w #1,itopedge
- asl.w #1,mheight
- asl.w #1,mtopedge
- swap iheight
- swap itopedge
- swap mheight
- swap mtopedge
- bre035 move.l gb_IBase(gbl),a5 ; get intuition base
- addq.w #1,mleftedge
- move.w mleftedge,offsetx ; get menu leftedge
- move.w offsetx,ie_X(a0) ; update event's X coordinate
- swap mleftedge
- addq.w #1,mtopedge
- move.w mtopedge,offsety ; get menu topedge
- move.w offsety,ie_Y(a0) ; update event's Y coordinate
- asr.w #1,mwidth ; divide menu width by 2
- move.w ileftedge,offsetx ; get item leftedge
- asr.w #1,iwidth ; divide item width by 2
- add.w iwidth,offsetx ; add it to offsetx
- swap mwidth
- move.w mheight,offsety ; get menu height
- asr.w #1,mheight ; divide menu height by 2
- swap mheight
- swap ileftedge
- add.w itopedge,offsety ; add item topedge
- swap iwidth
- asr #1,iheight ; divide item height by 2
- add.w iheight,offsety ; add to offsety
- cmp.w #1,d0 ; one event to be generated ?
- bne bre040 ; no, branch
- add.w offsetx,ie_X(a0) ; adjust mouse x coordinate
- add.w offsety,ie_Y(a0) ; adjust mouse y coordinate
- bra bre045
- bre040 cmp.w #3,d0 ; go to saved mouse position ?
- bne bre042 ; no, branch
- move.w gb_old_MouseX(gbl),offsetx
- move.w gb_old_MouseY(gbl),offsety
- bra bre044
- bre042 add.w ie_X(a0),offsetx
- add.w ie_Y(a0),offsety
- bre044 add.w mwidth,ie_X(a0) ; add menu width to current item
- swap mwidth
- add.w mheight,ie_Y(a0) ; add menu height to current item
- move.l a0,a1 ; event to attach new event to
- lea gb_ppos1(gbl),a0 ; new event area
- move.w offsetx,d0
- move.w offsety,d1
- jsr Insert_PointerPos_Event ; go add the event to the chain
- bre045 bset.b #FLAGB_Events_inserted,gb_flags(gbl) ; indicate events added
- movem.l (sp)+,breregs
- rts ; return to caller
- breregs reg a0-a5/d1-d6
-
- end
-