home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d7xx
/
d756
/
popupmenu.lha
/
PopUpMenu
/
Source
/
PopUp.a
< prev
next >
Wrap
Text File
|
1992-11-06
|
77KB
|
3,178 lines
include "All.i"
include "exec/types.i"
include "PopUp.i"
xref PopUpSemaphore
xref @QueTimer
xref @AbortTimer
xdef @PopUpMenu
VBORDERSIZE equ 4 ; Vertical border (pixels)
HBORDERSIZE equ 2 ; Horizontal border (pixels)
OVERLAP equ 8 ; Overlap itemwindow->menuwindow (pixels)
ITEMWINDOW equ 0
SUBWINDOW equ WORD_MAX
ITEMFILL equ 0
HIGHLIGHTON equ 1
HIGHLIGHTOFF equ 0
section text,code
**********************************************
* BOOL PopUpMenu(VOID) *
* *
* Input: *
* none *
* Output: *
* return FALSE if MENU_UP will come *
**********************************************
@PopUpMenu: movem.l D2-D5/A2/A3/A6,-(SP)
; Get the semaphore
lea PopUpSemaphore(PC),A0
move.l _ExecBase(A4),A6
libcall ObtainSemaphore ; Exclusive lock
; Set returncode to FALSE
moveq.l #FALSE,D0
move.w D0,-(SP)
; Be sure the window is still open
call FindWindow
tst.w D0
beq Abort2 ; Quick abort
; Lock the screen
move.l _Screen(A4),A3
lea sc_LayerInfo(A3),A2
move.l A2,A0
move.l _LayersBase(A4),A6
libcall LockLayers
*********************
* A2 = LayerInfo *
* A3 = Screen *
* A6 = LayersBase *
*********************
; Clear the global variables used
lea _ClearStart(A4),A0
move.w #(_ClearEnd-_ClearStart)/2-1,D0
moveq.l #0,D4 ; Use D4 (no need to clear it later)
1$ move.w D4,(A0)+
dbra D0,1$
; No selections done so far.
move.w D0,_FirstSelected(A4) ; MENUNULL
; if screen is LORES use larger "Amiga-key" symbol
btst #V_HIRES_B0,sc_ViewPort+vp_Modes(A3)
bne 2$
move.w #TRUE,_ScreenType(A4)
; Initialize our rastport
2$ lea _Rp(A4),A1
move.l _GfxBase(A4),A6
libcall InitRastPort
; Set default font to screen font
lea _Rp(A4),A1
move.l sc_RastPort+rp_Font(A3),A0
libcall SetFont
; Find the with of the default command key
lea -te_SIZEOF(SP),SP
move.l sc_RastPort+rp_Font(A3),A0
move.l SP,A1
libcall FontExtent
move.w te_Extent+ra_MaxX(SP),_CommKeyWidth(A4)
lea te_SIZEOF(SP),SP
; find the height of menu texts
move.b sc_BarHeight(A3),_MenuTextHeight+1(A4)
; We use the screen's bitmap
lea sc_BitMap(A3),A0
move.l A0,_Rp+rp_BitMap(A4)
; Use the window pens when drawing the menus
move.l _ActiveWindow(A4),A0
move.w wd_DetailPen(A0),_DetailPen(A4) ; move both pens
; Get the menus [ use D3 here, see below ]
move.l wd_MenuStrip(A0),D3
move.l D3,_Menus(A4)
beq NoMenus ; OOPS!
; Set MENUSTATE flag
bset #WFLG_MENUSTATE_B2,wd_Flags+2(A0)
; if we have used these menus before start at last selection
; D3 = Menus
lea _LastMenus(A4),A0
move.l D3,A1 ; A1 = What to look for
;[not needed] moveq.l #0,D4 ; D4 = Selected [ nothing yet ]
moveq.l #MAXREMEMBER-1,D0
3$ move.l llm_Menus(A0),D1
move.w llm_Num(A0),D2
move.l D3,llm_Menus(A0)
move.w D4,llm_Num(A0)
exg.l D1,D3
exg.l D2,D4
addq.l #llm_SIZEOF,A0
cmp.l A1,D3 ; Found the right one ?
dbeq D0,3$
beq 4$ ; Found one
moveq.l #1,D4 ; not used before -> start at top
4$ move.w D4,_LastMenus+llm_Num(A4)
move.w D4,D0
beq OpenMenus
; calculate position in menuwindow.
subq.w #1,D0
mulu.w _MenuTextHeight(A4),D0
; Open the menus.
OpenMenus: call OpenMenuWindow
tst.w D0
beq NoMenus
********************
* A2 = LayerInfo *
* A3 = Screen
* A6 = GfxBase *
********************
; Abort the timer if it is running.
call AbortTimer
; Start up a new timer.
moveq.l #INPUT_DEVICE_WAIT,D0
call QueTimer
; Combine the signals we use
move.l _TimerSigMask(A4),D3
or.l _CxHandlerData+ssd_MouseMovedSig+ssi_Mask(A4),D3
or.l _CxHandlerData+ssd_MenuUpSig+ssi_Mask(A4),D3
or.l _CxHandlerData+ssd_SelectUpSig+ssi_Mask(A4),D3
or.l _CxHandlerData+ssd_SelectDownSig+ssi_Mask(A4),D3
; Clear local variables
moveq.l #FALSE,D2 ; D2 = Waiting
moveq.l #FALSE,D4 ; D4 = SelDown
*****************************************
* D2 = Waiting A2 = LayerInfo *
* D3 = AllSig *
* D4 = SelDown *
*****************************************
; SignalBits = Wait(MouseMovedSig | MenuUpSig | SelectUpSig | SelectDownSig | TimerSig);
WaitNextSig: move.l D3,D0
move.l _ExecBase(A4),A6
libcall Wait
move.l D0,D5
*****************************************
* D2 = Waiting A2 = LayerInfo *
* D3 = AllSig *
* D4 = SelDown A6 = SysBase *
* D5 = SignalBits *
*****************************************
; Inputhandler alive ?
and.l _CxHandlerData+ssd_MouseMovedSig+ssi_Mask(A4),D0
beq SelectDown
; Clear waiting flag
moveq.l #FALSE,D2
; Get the mouse coordinates
move.w sc_MouseX(A3),D0
move.w sc_MouseY(A3),D1
cmp.w _MouseX(A4),D0
bne MouseMoved
cmp.w _MouseY(A4),D1
beq SelectDown ; mouse not moved
; remember the new mouse coordinates
MouseMoved: move.w D0,_MouseX(A4)
move.w D1,_MouseY(A4)
; if CLICKMENUS we should only do selection if selectbutton is pressed
btst #CLICKMENUS_B0,_CxHandlerData+ssd_Options(A4)
beq 1$
tst.w D4 ; SelectButton down
beq SelectDown ; No
call SelectItem
bra SelectDown
; do selection
1$ call SelectItem
tst.w D0
beq SelectDown ; nothing selected
; if selectbutton is down we are drag-selecting
tst.w D4
beq SelectDown
; is it possible to select the item ?
call CheckSelected
tst.l D0
beq SelectDown ; No
; rememember that this item is drag selected (set MENUTOGGLED flag)
move.l D0,A0
bset #MENUTOGGLED_B0,mi_Flags(A0)
*****************************************
* D2 = Waiting A2 = LayerInfo *
* D3 = AllSig *
* D4 = SelDown A6 = SysBase *
* D5 = SignalBits *
*****************************************
; user pressed the selectbutton ?
SelectDown: move.l D5,D0
and.l _CxHandlerData+ssd_SelectDownSig+ssi_Mask(A4),D0
beq MenuUp ; No
; if clickmenus just do selection
btst #CLICKMENUS_B0,_CxHandlerData+ssd_Options(A4)
beq 1$
call SelectItem
bra 2$
; otherwise start drag-selection
1$ call CheckSelected
; remember where we started the drag-select
move.l D0,_FirstDrag(A4)
beq MenuUp ; nothing selected
move.l D0,A0
bset #MENUTOGGLED_B0,mi_Flags(A0)
; SelDown = TRUE
2$ moveq.l #TRUE,D4
*****************************************
* D2 = Waiting A2 = LayerInfo *
* D3 = AllSig *
* D4 = SelDown A6 = SysBase *
* D5 = SignalBits *
*****************************************
; User released the menu button ?
MenuUp: move.l D5,D0
and.l _CxHandlerData+ssd_MenuUpSig+ssi_Mask(A4),D0
beq SelectUp ; No
; Set new returncode
moveq.l #TRUE,D0
move.w D0,(SP)
; if select-button is pressed, end the drag-selection
tst.w D4
beq 1$
call ClearToggle
bra NoMoreSel
; do the last selection
1$ call CheckSelected
bra NoMoreSel
*****************************************
* D2 = Waiting A2 = LayerInfo *
* D3 = AllSig *
* D4 = SelDown A6 = SysBase *
* D5 = SignalBits *
*****************************************
* Select-button released
SelectUp: move.l D5,D0
and.l _CxHandlerData+ssd_SelectUpSig+ssi_Mask(A4),D0
beq Timer ; No
moveq.l #FALSE,D4 ; seldown
; If CLICKMENUS just do selection
btst #CLICKMENUS_B0,_CxHandlerData+ssd_Options(A4)
beq 1$
call CheckSelected
tst.l D0
beq Timer
moveq.l #TRUE,D1 ; No MENU_UP will come
move.w D1,(SP)
; Disable MENU_UP
bclr #MENUS_ON_B,_CxHandlerData+ssd_Flags(A4)
bra NoMoreSel ; end selection
; end the drag-select
1$ call ClearToggle
;*****************************************
;* D2 = Waiting A2 = LayerInfo *
;* D3 = AllSig *
;* D4 = SelDown A6 = SysBase *
;* D5 = SignalBits *
;*****************************************
; Timer finished ?
Timer: move.l D5,D0
and.l _TimerSigMask(A4),D0
beq NextSig ; No
; Have something else happened since last timer event ?
tst.w D2
beq NoLockup ; Yes
; The input.device has stopped.
; Remove everything from the screen.
lea _SubWindow(A4),A0
call SwapBits
lea _ItemWindow(A4),A0
call SwapBits
lea _MenuWindow(A4),A0
call SwapBits
; Unlock the screen.
move.l A2,A0
move.l _LayersBase(A4),A6
libcall UnlockLayers
; Wait for the input.device to start again
move.l D3,D0 ; Any reply will do
move.l _ExecBase(A4),A6
libcall Wait
; Is the screen and window still open ?
call FindWindow
tst.w D0
bne OKToLock
; The window is gone!!! Abort.
lea _SubWindow(A4),A0
call RemoveBitMap
lea _ItemWindow(A4),A0
call RemoveBitMap
lea _MenuWindow(A4),A0
call RemoveBitMap
bra Abort2
; Lock the screen again.
OKToLock: move.l A2,A0
move.l _LayersBase(A4),A6
libcall LockLayers
; Put everything back on the screen.
lea _MenuWindow(A4),A0
call SwapBits
lea _ItemWindow(A4),A0
call SwapBits
lea _SubWindow(A4),A0
call SwapBits
; Waiting = FALSE
moveq.l #FALSE,D2
bra NewTimer
; Waiting = TRUE
NoLockup: moveq.l #TRUE,D2
; Start a new timer.
NewTimer: moveq.l #INPUT_DEVICE_WAIT,D0
call QueTimer
NextSig: bra WaitNextSig
; All selections done.
; Close all windows.
NoMoreSel: call CloseSubWindow
call CloseItemWindow
call CloseMenuWindow
; Remember the last selection for another time.
move.w _CurrentMenuNr(A4),_LastMenus+llm_Num(A4)
; Clear the MENUSTATE flag
NoMenus: move.l _ActiveWindow(A4),A0
bclr #WFLG_MENUSTATE_B2,wd_Flags+2(A0)
; Unlock the screen.
move.l A2,A0
move.l _LayersBase(A4),A6
libcall UnlockLayers
; Tell the window the good news (MENUPICK).
move.w _FirstSelected(A4),D0
call TellWindow
; Release the semaphore
Abort2: lea PopUpSemaphore(PC),A0
move.l _ExecBase(A4),A6
libcall ReleaseSemaphore
move.w (SP)+,D0
movem.l (SP)+,D2-D5/A2/A3/A6
rts
;*****************************************
;* struct MenuItem *CheckSelected() *
;* *
;* Input: *
;* none *
;* Output: *
;* return - Selected item or NULL *
;*****************************************
@CheckSelected:
movem.l D2/A2/A6,-(SP)
; Fix Checkmarks etc.
call FinalSelect
; Nothing selected ?
cmp.w #MENUNULL,D0
beq NoSelection ; Yes
move.w D0,D2 ; D2 = Selected
; Get the address to the selected item
move.l _Menus(A4),A0
move.l _IntuitionBase(A4),A6
libcall ItemAddress
move.l D0,A2 ; A2 = SelectedAddr
; is thist the first selection ?
move.l _LastSelected(A4),D0
beq FirstSel ; Yes
; Same selection as last time ?
cmp.l D0,A2
beq NoSelection ; Yes
; run down the list of selection to se if this item have been selected before
moveq.l #0,D0
move.w _FirstSelected(A4),D0
move.l _Menus(A4),A0
libcall ItemAddress
move.l D0,A0
; Special case if it was the first selection
cmp.w _FirstSelected(A4),D2
bne 1$
; remove the first selection
move.w mi_NextSelect(A0),_FirstSelected(A4)
bra NextSelFixed
; follow the NextSelect chain
1$ moveq.l #0,D0
move.w mi_NextSelect(A0),D0
cmp.w #MENUNULL,D0 ; No more selections
beq NextSelFixed
; have we found the item ?
cmp.w D2,D0
bne 2$ ; No
; remove it from the chain
move.w mi_NextSelect(A2),mi_NextSelect(A0)
bra NextSelFixed
; Get next item in chain
2$ move.l _Menus(A4),A0
libcall ItemAddress
move.l D0,A0
bra 1$
; Add the item to the chain
NextSelFixed: move.l _LastSelected(A4),A0
move.w D2,mi_NextSelect(A0)
bra EndChain
FirstSel: move.w D2,_FirstSelected(A4)
; end the NextSelect chain
EndChain: move.w #MENUNULL,mi_NextSelect(A2)
move.l A2,_LastSelected(A4)
move.l A2,D0
bra CheckDone
NoSelection: moveq.l #NULL,D0
CheckDone: movem.l (SP)+,D2/A2/A6
rts
;**********************************************
;* VOID ClearToggle() *
;* run down the drag-select list and remove *
;* the MENUTOGGLED bit. *
;* Input *
;* none *
;* Output *
;* none *
;**********************************************
; Any items drag selected ?
@ClearToggle: move.l A6,-(SP)
move.l _FirstDrag(A4),A0
move.l A0,D0
beq 2$ ; No
move.l _IntuitionBase(A4),A6
; Clear MENUTOGGLED bit
1$ bclr #MENUTOGGLED_B0,mi_Flags(A0)
; Find the next item in list
moveq.l #0,D0
move.w mi_NextSelect(A0),D0
cmp.w #MENUNULL,D0
beq 2$ ; No more items
move.l _Menus(A4),A0
libcall ItemAddress
move.l D0,A0
bra 1$
2$ move.l (SP)+,A6
rts
;************************************************
;* FindItemNr(Item,ItemList) - Find nr of item. *
;* *
;* Input: *
;* Item - Item to look for. *
;* ItemList - all items on same level. *
;* Output: *
;* return - Nr of Item or NOITEM *
;************************************************
; Init a counter
@FindItemNr: moveq.l #0,D0
bra 2$
; Is this the item ?
1$ cmp.l A0,A1
beq 3$ ; Yes
; Increment counter
addq.w #1,D0
; Get next item
move.l mi_NextItem(A1),A1
2$ move.l A1,D1
bne 1$
moveq.l #NOITEM,D0
3$ rts
;*************************************************
;* FindWindow() - Check if window is still open. *
;* *
;* Input: *
;* none *
;* Output: *
;* return - TRUE if window is open. *
;*************************************************
@FindWindow: move.l D2,-(SP)
move.l A6,-(SP)
; Must lock IntuitionBase while we do this
moveq.l #0,D0
move.l _IntuitionBase(A4),A6
libcall LockIBase
; Get the first open screen
move.l ib_FirstScreen(A6),A0
; run down the list of screens to find our one
1$ move.l A0,D1
beq 5$ ; No more screens
cmp.l _Screen(A4),A0
bne 4$ ; Wrong screen, try next
; Get the first window on the screen
move.l sc_FirstWindow(A0),A1
; find our window
2$ move.l A1,D1
beq 5$ ; No more windows
cmp.l _ActiveWindow(A4),A1
bne 3$ ; wrong window, try next
moveq.l #TRUE,D2 ; Success
bra 6$
3$ move.l wd_NextWindow(A1),A1
bra 2$
4$ move.l sc_NextScreen(A0),A0
bra 1$
5$ moveq.l #FALSE,D2 ; Unsuccessful
; Unlock IntuitionBase
6$ move.l D0,A0
libcall UnlockIBase
move.l D2,D0
move.l (SP)+,A6
move.l (SP)+,D2
rts
;***************************************************
;* MouseInWindow(Window) - Is mouse inside window. *
;* *
;* Input: *
;* Window - Window to check. *
;* Output: *
;* return - TRUE if mouse inside. *
;***************************************************
@MouseInWindow: moveq.l #FALSE,D0
; MouseX > Window->LeftEdge ?
move.w _MouseX(A4),D1
cmp.w wwd_LeftEdge(A0),D1
ble 1$
; MouseX < Window->RightEdge ?
cmp.w wwd_RightEdge(A0),D1
bge.b 1$
; MouseY > Window->TopEdge ?
move.w _MouseY(A4),D1
cmp.w wwd_TopEdge(A0),D1
ble 1$
; MouseY < Window->Bottom ?
cmp.w wwd_Bottom(A0),D1
bge 1$
moveq.l #TRUE,D0
1$ rts
;****************************************************************
;* FindMouseItem(Window) - Check if mouse inside an item. *
;* *
;* Input: *
;* ItemWindow - Window with items *
;* Output: *
;* return - Pointer to item under the mousepointer (or NULL). *
;****************************************************************
@FindMouseItem: move.w D2,-(SP)
; MouseWinX = MouseX + Window->LeftValue
move.w _MouseX(A4),D1
add.w wwd_LeftValue(A0),D1
; MouseWinY = MouseY + Window->TopValue
move.w _MouseY(A4),D2
add.w wwd_TopValue(A0),D2
; Get first item in this window
move.l wwd_Items(A0),A0
; MouseWinY >= Item->TopEdge ?
1$ move.w mi_TopEdge(A0),D0
cmp.w D0,D2
blt 2$ ; No
; MouseWinY <= Item->TopEdge + Item->Height ?
add.w mi_Height(A0),D0
cmp.w D0,D2
bgt 2$ ; No
; MouseWinX >= Item->LeftEdge ?
move.w mi_LeftEdge(A0),D0
cmp.w D0,D1
blt 2$ ; No
; MouseWinX <= Item->LeftEdge + Item->Width ?
add.w mi_Width(A0),D0
cmp.w D0,D1
bgt 2$ ;
; Item found, return it
move.l A0,D0
bra 3$
; Try next item.
2$ move.l mi_NextItem(A0),A0
move.l A0,D0
bne 1$
3$ move.w (SP)+,D2
rts
;******************************************
;* OpenMenuWindow(StartPos) *
;* *
;* Input: *
;* StartPos - Position from menutop. *
;* Output: *
;* return - TRUE if window opened. *
;******************************************
@OpenMenuWindow:
movem.l D5-D7/A3/A5,-(SP)
move.w D0,D7
; Sort menus after their LeftEdge
call SortMenus
move.l _GfxBase(A4),A6
; Special case if just one menu
move.l _Menus(A4),A3
tst.l mu_NextMenu(A3)
bne 2$ ; More than one
; Single menu name option set ?
btst #SHOWSINGLEMENU_B0,_CxHandlerData+ssd_Options(A4)
bne 2$ ; Yes
; if the menu is disabled, disable all items
lea _ItemWindow(A4),A0
moveq.l #MENUENABLED,D0
and.w mu_Flags(A3),D0
move.w D0,wwd_ItemsEnabled(A0)
; Set windows items
move.l mu_FirstItem(A3),wwd_Items(A0)
; FindItemWinSize(ItemWindow, ITEMWINDOW)
moveq.l #ITEMWINDOW,D0
call FindItemWinSize
tst.l D0
beq 2$ ; No items
; MenuWidth = Size.Right - Size.left
move.w _Size+wws_Right(A4),D6
sub.w _Size+wws_Left(A4),D6
; Length = TextLength(&Rp,MenuPtr->MenuName,Mystrlen(MenuPtr->MenuName))
move.l mu_MenuName(A3),A0
call Mystrlen
lea _Rp(A4),A1
move.l mu_MenuName(A3),A0
libcall TextLength
; Will menu fit inside menuwindow
cmp.w D0,D6
bge 1$ ; Yes
; Increse window size [Size.Right += Length - MenuWidth]
move.w _Size+wws_Right(A4),D1
add.w D0,D1
sub.w D6,D1
move.w D1,_Size+wws_Right(A4)
; MenuWidth = Length
move.w D0,D6
; Add border
1$ addq.w #2*VBORDERSIZE,D6
; MenuHeight = Size.bottom - Size.Top + 2 * HBORDERSIZE + MenuTextHeight
move.w _Size+wws_Bottom(A4),D5
sub.w _Size+wws_Top(A4),D5
addq.w #2*HBORDERSIZE,D5
add.w _MenuTextHeight(A4),D5
; MenuTop = 0
moveq.l #0,D7
; Window = ItemWindow
lea _ItemWindow(A4),A3
; Window->CommKeySize = Size.CommKey
move.w _Size+wws_CommKey(A4),wwd_CommKeySize(A3)
bra PosLeft
; MenuWidth = 0
2$ moveq.l #0,D6
; MenuHeight = HBORDERSIZE + 1
moveq.l #HBORDERSIZE+1,D5
;****************************************
;* Find width & height of window needed *
;****************************************
;***********************************
;* D5 = MenuHeight A3 = Menus *
;* D6 = MenuWidth A6 = GfxBase *
;* D7 = MenuTop *
;***********************************
; Length = TextLength(&Rp,MenuPtr->MenuName,Mystrlen(MenuPtr->MenuName))
3$ move.l mu_MenuName(A3),A0
call Mystrlen
lea _Rp(A4),A1
move.l mu_MenuName(A3),A0
libcall TextLength
; MenuPtr->Width > Length ?
move.w mu_Width(A3),D1
cmp.w D0,D1
bls 4$ ; No
; Length = MenuPtr->Width
move.l D1,D0
; Length > MenuWidth ?
4$ cmp.w D6,D0
bls 5$ ; No
; MenuWidth = Length
move.w D0,D6
; MenuHeight += MenuTextHeight
5$ add.w _MenuTextHeight(A4),D5
; Check next menu.
move.l mu_NextMenu(A3),A3
move.l A3,D0
bne 3$
; MenuWidth += (2 * VBORDERSIZE + 1)
addq.w #2*VBORDERSIZE,D6
addq.w #1,D6
; Window = MenuWindow
lea _MenuWindow(A4),A3
;************************************
;* Position window on screen (Left) *
;************************************
;***********************************
;* A3 = Window *
;* D5 = MenuHeight A6 = GfxBase *
;* D6 = MenuWidth *
;* D7 = MenuTop *
;***********************************
; MenuLeft = Screen->MouseX - MenuWidth / 2
PosLeft: move.w D6,D0
lsr.w #1,D0
move.l _Screen(A4),A0
move.w sc_MouseX(A0),D1
sub.w D0,D1
; MenuLeft < 0 ?
bge 1$ * No
; MenuLeft = 0
moveq.l #0,D1
; MenuLeft > Screen->Width - MenuWidth ?
1$ move.w sc_Width(A0),D0
sub.w D6,D0
cmp.w D0,D1
ble PosTop * No
; MenuLeft = Screen->Width - MenuWidth
move.w D0,D1
;***********************************
;* Position window on screen (Top) *
;***********************************
;***********************************
;* D1 = MenuLeft A3 = Window *
;* D5 = MenuHeight A0 = Screen *
;* D6 = MenuWidth A6 = GfxBase *
;* D7 = MenuTop *
;***********************************
; MenuTop > MenuHeight ? (Menus has changed)
PosTop: cmp.w D5,D7
ble 1$ * No
; MenuTop = 0
moveq.l #0,D7
; MenuTop = Screen->MouseY - MenuTextHeight/2 - MenuTop
1$ move.w _MenuTextHeight(A4),D0
lsr.w #1,D0
add.w D0,D7
sub.w sc_MouseY(A0),D7
neg.w D7
; MenuTop < 0 ?
bpl.b 2$ * No
; MenuTop = 0
moveq.l #0,D7
; MenuTop > Screen->Height - MenuHeight ?
2$ move.w sc_Height(A0),D0
sub.w D5,D0
cmp.w D0,D7
ble 3$ * No
; MenuTop = Screen->Height - MenuHeight
move.l D0,D7
; Window->TopEdge = MenuTop
3$ move.w D7,wwd_TopEdge(A3)
; Window->Height = MenuHeight
move.w D5,wwd_Height(A3)
; Window->LeftEdge = MenuLeft
move.w D1,wwd_LeftEdge(A3)
; Window->Width = MenuWidth;
move.w D6,wwd_Width(A3)
;*******************************
;* Open window with right size *
;*******************************
; BuildBitMap(Window)
Open: move.l A3,A0
call BuildBitMap
; Window opened OK ?
tst.w D0
beq OpenMenuDone ; No
; Window == ItemWindow ? [ only if single menu ]
lea _ItemWindow(A4),A0
cmp.l A0,A3
bne 1$ ; No
; ItemWindow.leftValue = Size.left - WindowLeft - VBORDERSIZE
move.w _Size+wws_Left(A4),D0
sub.w wwd_LeftEdge(A3),D0
subq.w #VBORDERSIZE,D0
move.w D0,wwd_LeftValue(A3)
; ItemWindow.TopValue = Size.Top - WindowTop - HBORDERSIZE - MenuTextHeight
move.w _Size+wws_Top(A4),D0
sub.w wwd_TopEdge(A3),D0
subq.w #HBORDERSIZE,D0
sub.w _MenuTextHeight(A4),D0
move.w D0,wwd_TopValue(A3)
; DrawAllItems(&ItemWindow)
move.l A3,A0
call DrawAllItems
; CurrentMenuNr = 1
moveq.l #1,D0
move.w D0,_CurrentMenuNr(A4)
bra 2$
; Clear window
1$ move.l A3,A0
call ClearWindow
; DrawAllMenus(Window)
2$ move.l A3,A0
call DrawAllMenus
moveq.l #TRUE,D0
OpenMenuDone: movem.l (SP)+,D5-D7/A3/A6
rts
;**************************************
;* BOOL SortMenus(VOID) - *
;* sort menus after their LeftEdge *
;**************************************
@SortMenus: movem.l A2/A3/A5,-(SP)
move.l _Menus(A4),A0
lea _MenuSorted(A4),A1
move.l A1,A2
; First menu
move.l A0,(A2)+
bra 4$
1$ move.w mu_LeftEdge(A0),D0
move.l A2,A3
2$ move.l -4(A3),A5
cmp.w mu_LeftEdge(A5),D0
bge 3$
move.l -4(A3),(A3)
subq.l #4,A3
cmp.l A3,A1
bne 2$
3$ move.l A0,(A3)
addq.l #4,A2
4$ move.l mu_NextMenu(A0),A0
move.l A0,D0
bne 1$
movem.l (SP)+,A2/A3/A5
rts
;*****************************************************************
;* OpenItemWindow(ItemWindow,WindowType,LeftPos,RightPos,TopPos) *
;* A0 D0 D1 D2 D3 *
;* Input: *
;* ItemWindow - Window to open. *
;* WindowType.w - ITEMWINDOW or SUBWINDOW *
;* LeftPos,RightPos,TopPos - Position(s) for new window. *
;* Output: *
;* return - TRUE if OK *
;*****************************************************************
@OpenItemWindow:
movem.l D4/D5/A2,-(SP)
move.l A0,A2
move.l D0,D4
move.l D1,D5
; FindItemWinSize(Window,WindowType)
call FindItemWinSize
; Empty menu ?
tst.l D0
beq 1$ ; Yes
; Set largest CommKeySize [Window->CommKeySize = Size.CommKey]
move.w _Size+wws_CommKey(A4),wwd_CommKeySize(A2)
; PosItemWinLeft(Window,WindowType,LeftPos,RightPos)
move.l A2,A0
move.w D4,D0
move.l D5,D1
call PosItemWinLeft
; PosItemWinTop(Window, TopPos, WindowType)
move.l A2,A0
move.w D3,D0
move.w D4,D1
call PosItemWinTop
; BuildBitMap(Window)
move.l A2,A0
call BuildBitMap
tst.w D0
beq 1$
; DrawAllItems(Window)
move.l A2,A0
call DrawAllItems
moveq.l #TRUE,D0
1$ movem.l (SP)+,D4/D5/A2
rts
;******************************************************
;* PosItemWinLeft(Window,WindowType,LeftPos,RightPos) *
;* - Position window on screen (left) *
;* *
;* Input: *
;* Window - Window to position. *
;* ParentWindow - Window to position next to. *
;* WindowType.w - ITEMWINDOW or SUBWINDOW. *
;* *
;* Possible positions: *
;* 1. At real position (a'la intuition). *
;* 2. At right side of parent. *
;* 3. At left side of parent. *
;* 4. On the side that covers parent least. *
;******************************************************
@PosItemWinLeft:
movem.l D3-D7/A2,-(SP)
; LeftValue = Size.left - VBORDERSIZE
move.w _Size+wws_Left(A4),D6
subq.w #VBORDERSIZE,D6
; WindowWidth = Size.Right - LeftValue + VBORDERSIZE
move.w _Size+wws_Right(A4),D5
sub.w D6,D5
addq.w #VBORDERSIZE,D5
; LeftPos2 = ParentWindow->LeftEdge - WindowWidth + OVERLAP
move.w D1,D4
sub.w D5,D4
addq.w #OVERLAP,D4
; MaxLeft = Screen->Width - WindowWidth
move.l _Screen(A4),A2
move.w sc_Width(A2),D3
sub.w D5,D3
;**********************************************
;* D0 = WindowType A0 = Window *
;* D1 = LeftPos A1 = ParentWindow *
;* D2 = RightPos A2 = Screen *
;* D3 = MaxLeft *
;* D4 = LeftPos2 *
;* D5 = WindowWidth *
;* D6 = LeftValue *
;* D7 = WindowLeft *
;**********************************************
; WindowType == ITEMWINDOW ?
tst.w D0
beq 1$ ; Yes
; WindowLeft = ParentWindow->LeftEdge + LeftValue
move.w D1,D7
add.w D6,D7
; WindowLeft > MaxLeft ?
cmp.w D7,D3
blt 1$ ; Yes
; WindowLeft < 0 ?
tst.w D7
bpl.b 2$ ; No
; WindowLeft = ParentWindow->RightEdge - OVERLAP
1$ move.w D2,D7
subq.w #OVERLAP,D7
; WindowLeft > MaxLeft ?
2$ cmp.w D7,D3
bge 4$ ; No
; LeftPos2 > MaxLeft - WindowLeft ?
move.w D3,D0
sub.w D7,D0
cmp.w D4,D0
bge 3$ ; No
; WindowLeft = (LeftPos2 > 0) ? LeftPos2 : 0
move.w D4,D7
bgt 4$
moveq.l #0,D3 ; MaxLeft not needed any more
; WindowLeft = MaxLeft
3$ move.w D3,D7
; WindowWidth < ParentWindow->LeftEdge + OVERLAP - WindowLeft ?
4$ move.w D1,D0
addq.w #OVERLAP,D0
sub.w D7,D0
cmp.w D5,D0
ble 5$ ; No
; WindowWidth = ParentWindow->LeftEdge + OVERLAP - WindowLeft
move.w D0,D5
; Window->LeftEdge = WindowLeft
5$ move.w D7,wwd_LeftEdge(A0)
; Window->LeftValue = LeftValue - WindowLeft
sub.w D7,D6
move.w D6,wwd_LeftValue(A0)
; Window->Width = WindowWidth
move.w D5,wwd_Width(A0)
movem.l (SP)+,D3-D7/A2
rts
;*****************************************************
;* PosItemWinTop(Window,TopPos, WindowType) *
;* - Position Window on screen (Top). *
;* *
;* Input: *
;* Window - Window to position. (A0) *
;* TopPos.w - (D0) *
;* WindowType.w - ITEMWINDOW or SUBWINDOW (D1) *
;*****************************************************
@PosItemWinTop:
movem.l D4-D7,-(SP)
; TopValue = Size.Top - HBORDERSIZE
move.w _Size+wws_Top(A4),D6
subq.w #HBORDERSIZE,D6
; WindowHeight = Size.bottom - TopValue + HBORDERSIZE
move.w _Size+wws_Bottom(A4),D4
sub.w D6,D4
addq.w #HBORDERSIZE,D4
move.l _Screen(A4),A1
; WindowTop = TopPos
move.w D0,D5
; WindowType == ITEMWINDOW ?
tst.w D1
bne 1$ ; No
; Center Items ?
btst #ITEMSCENTERED_B0,_CxHandlerData+ssd_Options(A4)
beq 1$ * No
; WindowTop += (MenuTextHeight - WindowHeight) / 2
move.w _MenuTextHeight(A4),D1
sub.w D4,D1
asr.w #1,D1
add.w D1,D5
bra 2$
; WindowTop = TopPos + TopValue
1$ add.w D6,D5
;***********************************
;* D0 = TopPos A0 = Window *
;* D4 = WindowHeight A1 = Screen *
;* D5 = WindowTop *
;* D6 = TopValue *
;***********************************
; WindowTop > Screen->Height - WindowHeight ?
2$ move.w sc_Height(A1),D0
sub.w D4,D0
cmp.w D5,D0
bge 3$ ; No
; WindowTop = Screen->Height - WindowHeight
move.w D0,D5
; WindowTop < 0 ?
3$ tst.w D5
bpl.b 4$ ; No
; WindowTop = 0
moveq.l #0,D5
; Window->TopEdge = WindowTop
4$ move.w D5,wwd_TopEdge(A0)
; Window->TopValue = TopValue - WindowTop
sub.w D5,D6
move.w D6,wwd_TopValue(A0)
; Window->Height = WindowHeight
move.w D4,wwd_Height(A0)
movem.l (SP)+,D4-D7
rts
;********************************************************
;* TellWindow(MenuNum) - Send Fake Menu Event. *
;* D0 *
;* Input: *
;* MenuNum - Menu number to send. *
;* Output: *
;* none *
;********************************************************
@TellWindow: move.l A6,-(SP)
lea -ie_SIZEOF(SP),SP
; MyEvent.ie_Class = IECLASS_MENULIST
move.b #IECLASS_MENULIST,ie_Class(SP)
; MyEvent.ie_Code = MenuNumber
move.w D0,ie_Code(SP)
; MyEvent.ie_Qualifier = InputSignals.EndQualifier
move.w _CxHandlerData+ssd_EndQualifier(A4),ie_Qualifier(SP)
; MyEvent.ie_NextEvent = NULL
clr.l (SP)
; MyEvent.ie_EventAddress = ActiveWindow
move.l _ActiveWindow(A4),ie_EventAddress(SP)
; Intuition will set the mouse position in the MENUPICK message
; Get current time.
lea ie_TimeStamp+TV_SECS(SP),A0
lea ie_TimeStamp+TV_MICRO(SP),A1
move.l _IntuitionBase(A4),A6
libcall CurrentTime
; Send the menu event
move.l _CxBase(A4),A6
move.l SP,A0
libcall AddIEvents
1$ lea ie_SIZEOF(SP),SP
move.l (SP)+,A6
rts
;****************************************
;* DrawAllItems(Window) *
;* *
;* Input: *
;* Window - Window to draw into. *
;* *
;* Output: *
;* none *
;****************************************
@DrawAllItems: move.l A2,-(SP)
move.l A3,-(SP)
move.l A0,A3
; ClearWindow(Window)
call ClearWindow
; Item = Window->Items
move.l wwd_Items(A3),A2
; DrawMenuItem(Window, Item, ITEMFILL)
1$ moveq.l #ITEMFILL,D0
move.l A3,A0
move.l A2,A1
call DrawMenuItem
; Item = Item->NextItem
move.l mi_NextItem(A2),A2
move.l A2,D0
bne 1$
move.l (SP)+,A3
move.l (SP)+,A2
rts
;*********************************
;* ClearWindow(window) *
;* *
;* Input: *
;* Window - Window to clear. *
;* Output: *
;* none *
;*********************************
@ClearWindow: movem.l D2-D5/A2/A3/A6,-(SP)
move.l A0,A3
lea _Rp(A4),A2
move.l _GfxBase(A4),A6
;*********************
;* A2 = Rp *
;* A3 = Window *
;* A6 = GfxBase *
;*********************
; SetDrMd(Rp, JAM1)
move.l A2,A1
moveq.l #RP_JAM1,D0
libcall SetDrMd
; SetAPen(Rp,DetailPen)
move.l A2,A1
moveq.l #0,D0
move.b _DetailPen(A4),D0
libcall SetAPen
; Left = Window->LeftEdge
moveq.l #0,D0
move.w wwd_LeftEdge(A3),D0
; Top = Window->TopEdge
moveq.l #0,D1
move.w wwd_TopEdge(A3),D1
; Right = Window->RightEdge
moveq.l #0,D2
move.w wwd_RightEdge(A3),D2
; Bottom = Window->Bottom
moveq.l #0,D3
move.w wwd_Bottom(A3),D3
; DrawRect(Left, Top, Right, Bottom)
move.l A2,A1
bsr DrawRect
; Save Left & Top.
move.l D0,D4
move.l D1,D5
; SetAPen(Rp,BlockPen)
move.l A2,A1
moveq.l #0,D0
move.b _BlockPen(A4),D0
libcall SetAPen
; RectFill(Left, Top, Right, Bottom)
move.l A2,A1
move.l D4,D0
move.l D5,D1
libcall RectFill
movem.l (SP)+,D2-D5/A2/A3/A6
rts
;*******************************
;* VOID CloseSubWindow(VOID) *
;* VOID CloseItemWindow(VOID) *
;* VOID CloseMenuWindow(VOID) *
;*******************************
@CloseSubWindow:
lea _SubWindow(A4),A0
tst.w wwd_BitMapOk(A0)
beq CloseQuit ; Not open
move.l wwd_Current(A0),A1
move.l A1,D0
beq 1$ ; No item selected
bclr #HIGHITEM_B0,mi_Flags(A1)
clr.l wwd_Current(A0)
; If subitems are shown ItemWindow.Current must be something.
1$ move.l _ItemWindow+wwd_Current(A4),A1
bclr #ISDRAWN_B0,mi_Flags(A1)
bra Close
@CloseItemWindow:
lea _ItemWindow(A4),A0
tst.w wwd_BitMapOk(A0)
beq CloseQuit ; Not open
move.l wwd_Current(A0),A1
move.l A1,D0
beq 1$ ; No item selected
bclr #HIGHITEM_B0,mi_Flags(A1)
clr.l wwd_Current(A0)
1$ move.l _MenuWindow+wwd_Current(A4),A1
move.l A1,D0
beq Close
bclr #MIDRAWN_B0,mu_Flags(A1)
bra Close
@CloseMenuWindow:
lea _MenuWindow(A4),A0
Close: move.l A0,-(SP)
; Remove window from screen.
; call MoveToScreen ; (Dont care about data in window)
call SwapBits
; Remove all bitplanes.
move.l (SP)+,A0
call RemoveBitMap
CloseQuit: rts
;****************************************
;* BuildBitMap(Window) - OpenWindow *
;* *
;* Input: *
;* Window - Window to open. *
;* Output: *
;* return - TRUE if window opened. *
;****************************************
@BuildBitMap: movem.l D2-D5/A2/A3/A6,-(SP)
move.l A0,A3
; WindowWidth = Window->Width
moveq.l #0,D3
move.w wwd_Width(A3),D3
; WindowHeight = Window->Height
moveq.l #0,D2
move.w wwd_Height(A3),D2
move.l _Screen(A4),A0
;**************************************
;* D2 = WindowHeight A0 = Screen *
;* D3 = WindowWidth A3 = Window *
;**************************************
; Is window to big for screen ?
; WindowWidth > Screen->Width
cmp.w sc_Width(A0),D3
bgt Fail * Yes
; WindowHeight > Screen->Height
cmp.w sc_Height(A0),D2
bgt Fail * Yes
; Window->RightEdge = Window->LeftEdge + WindowWidth - 1
move.l D3,D0
add.w wwd_LeftEdge(A3),D0
subq.l #1,D0
move.w D0,wwd_RightEdge(A3)
; Window->Bottom = Window->TopEdge + WindowHeight - 1
move.l D2,D0
add.w wwd_TopEdge(A3),D0
subq.l #1,D0
move.w D0,wwd_Bottom(A3)
; Depth = Screen->BitMap.Depth
moveq.l #0,D5
move.b sc_BitMap+bm_Depth(A0),D5
move.l _GfxBase(A4),A6
;***************************************
;* D2 = WindowHeight A0 = Screen *
;* D3 = WindowWidth A3 = Window *
;* D5 = Depth A6 = GfxBase *
;***************************************
; InitBitMap(&Window->Bm,Depth,WindowWidth,WindowHeight)
lea wwd_Bm(A3),A0
move.l D5,D0
move.l D3,D1
libcall InitBitMap
; Window->BitMapOk = TRUE
move.w #TRUE,wwd_BitMapOk(A3)
; Counter = 0
moveq.l #0,D4
; Plane = &Window->Bm.Planes[0]
lea wwd_Bm+bm_Planes(A3),A2
;***************************************
;* D2 = WindowHeight A2 = Planes *
;* D3 = WindowWidth A3 = Window *
;* D4 = Counter A6 = GfxBase *
;* D5 = Depth *
;***************************************
; More planes to allocate ?
BuildNextPl: cmp.w D4,D5
beq AllRastersOK
addq.w #1,D4
; Plane++ = AllocRaster(WindowWidth,WindowHeight)
move.l D3,D0
move.l D2,D1
libcall AllocRaster
move.l D0,(A2)+
; Out of ChipRam ?
bne BuildNextPl ; No
; RemoveBitMap(Window)
move.l A3,A0
call RemoveBitMap
; return FALSE
Fail: moveq.l #FALSE,D0
bra BuildDone
; Make window visible.
AllRastersOK: move.l A3,A0
call MoveFromScreen ; Don't care whats in offscreen bitmap
; return TRUE
moveq.l #TRUE,D0
BuildDone: movem.l (SP)+,D2-D5/A2/A3/A6
rts
;***************************************************************
;* VOID RemoveBitMap(Window) - *
;* Remove allocated rasters in the BitMap structure. *
;* *
;* Input: *
;* Window - Window with bitmap. *
;* Output: *
;* none *
;***************************************************************
@RemoveBitMap: movem.l D4-D7/A2/A6,-(SP)
; Anything to remove ?
tst.w wwd_BitMapOk(A0)
beq RemoveDone
clr.w wwd_BitMapOk(A0)
; Remove all allocated rasters.
moveq.l #0,D7
lea wwd_Bm(A0),A2
move.b bm_Depth(A2),D7
moveq.l #0,D6
move.w wwd_Width(A0),D6
moveq.l #0,D5
move.w wwd_Height(A0),D5
addq.l #bm_Planes,A2
move.l _GfxBase(A4),A6
; Counter = 0
moveq.l #0,D4
;*************************************
;* D4 = Counter A2 = Planes *
;* D5 = WindowHeight A0 = Window *
;* D6 = WindowWidth A6 = GfxBase *
;* D7 = Depth *
;*************************************
RemoveNextPl: cmp.w D4,D7
beq RemoveDone
addq.w #1,D4
; This raster allocated ?
move.l (A2)+,A0
move.l A0,D0
beq RemoveDone
; FreeRaster(Planes++,Width,Height);
move.l D6,D0
move.l D5,D1
libcall FreeRaster
bra RemoveNextPl
RemoveDone: movem.l (SP)+,D4-D7/A2/A6
rts
ALLPLANES equ -1
;*********************************************
;* Move data from screen to offscreen bitmap *
;*********************************************
@MoveFromScreen:
movem.l D2-D7/A2/A6,-(SP)
bsr LoadSwapData
bra MoveTo1
;*********************************************
;* Move data from offscreen bitmap to screen *
;*********************************************
@MoveToScreen: movem.l D2-D7/A2/A6,-(SP)
bsr LoadSwapData
exg.l A0,A1
exg.l D0,D2
exg.l D1,D3
MoveTo1: moveq.l #-$40,D6 ; A = B (ABC+ABNC)
libcall BltBitMap
movem.l (SP)+,D2-D7/A2/A6
rts
;************************************
;* Swap screen and offscreen bitmap *
;************************************
@SwapBits: tst.w wwd_BitMapOk(A0)
beq 1$
movem.l D2-D7/A2/A6,-(SP)
bsr LoadSwapData
moveq.l #ABNC+ANBC,D6 ; A = B ^ C (ABNC+ANBC)
bsr Swap ; OffScreen = (OffScreen XOR OnScreen )
bsr Swap ; OnScreen = (OnScreen XOR OffScreen)
bsr Swap ; OffScreen = (OffScreen XOR OnScreen )
movem.l (SP)+,D2-D7/A2/A6
1$ rts
Swap: movem.l D0/D1/A0/A1,-(SP)
libcall BltBitMap
movem.l (SP)+,D0/D1/A0/A1
exg.l A0,A1
exg.l D0,D2
exg.l D1,D3
rts
;**************************************************
;* LoadSwapData(Window) - load data for BltBitMap *
;* *
;* D0,D1 = SrcX,SrcY (on screen) *
;* D2,D3 = DextX,DestY (off screen) *
;* D4,D5 = SizeX,SizeY (both) *
;* D7 = ALLPLANES *
;* A0 = SrcBitmap (on screen) *
;* A1 = DestBitMap (off screen) *
;* A2 = TempA = NULL (bitmaps can't overlap) *
;* A6 = GfxBase *
;**************************************************
; SrcX = Window->LeftEdge
LoadSwapData: moveq.l #0,D0
move.w wwd_LeftEdge(A0),D0
; SrcY = Window->TopEdge
moveq.l #0,D1
move.w wwd_TopEdge(A0),D1
; DestX = 0
moveq.l #0,D2
; DestY = 0
moveq.l #0,D3
; SizeX = Window->Width
moveq.l #0,D4
move.w wwd_Width(A0),D4
; SizeY = Window->Height
moveq.l #0,D5
move.w wwd_Height(A0),D5
; Mask = ALLPLANES
moveq.l #ALLPLANES,D7
; TempA = NULL
sub.l A2,A2
move.l _GfxBase(A4),A6
; Off-screen bitmap = Window->BitMap
lea wwd_Bm(A0),A1
; On-screen bitmap = Rp.BitMap (= Screen.BitMap)
move.l _Rp+rp_BitMap(A4),A0
rts
;*********************************************
;* FindItemWinSize(Window,WindowType) *
;* *
;* Find width and hight needed for all items *
;*********************************************
@FindItemWinSize:
move.l A2,-(SP)
move.l D2,-(SP)
; SizeOk = FALSE
moveq.l #FALSE,D2
; Item = Window->Items
move.l wwd_Items(A0),A2
; Size.left = WORD_MAX
move.w #WORD_MAX,_Size+wws_Left(A4)
; Size.Top = WindowType (ITEMWINDOW -> TopPos >= 0), SUBWINDOW -> no limit
move.w D0,_Size+wws_Top(A4)
; Size.Right = Size.bottom = WORD_MIN
move.w #WORD_MIN,D0
move.w D0,_Size+wws_Right(A4)
move.w D0,_Size+wws_Bottom(A4)
; Size.CommKey = 0
move.w D2,_Size+wws_CommKey(A4)
; SizeOk |= CheckItemSize(Item,Item->ItemFill)
1$ move.l A2,A0
move.l mi_ItemFill(A0),A1
call CheckItemSize
or.l D0,D2
; Item->Flags & HIGHFLAGS == HIGHIMAGE ?
move.w #HIGHFLAGS,D0
and.w mi_Flags(A2),D0
bne 2$
; SizeOk |= CheckItemSize(Item,Item->SelectFill)
move.l A2,A0
move.l mi_SelectFill(A0),A1
call CheckItemSize
or.l D0,D2
; Check next item.
2$ move.l mi_NextItem(A2),A2
move.l A2,D0
bne 1$
; return SizeOK
move.l D2,D0
move.l (SP)+,D2
move.l (SP)+,A2
rts
;*********************************************************
;* CheckItemSize(Item,Contents) - *
;* find the size needed to include Item in window. *
;* *
;* Input: *
;* Item (A0) Item to check. *
;* Contents (A1) What to fill (ItemFill/SelectFill). *
;* Output: *
;* Size New size of window *
;* return TRUE if anything is found. *
;*********************************************************
@CheckItemSize:
; Anything to check ?
move.l A1,D0
bne 1$ ; Yes
rts
1$ movem.l D2-D7/A2/A3/A5/A6,-(SP)
lea -te_SIZEOF(SP),SP
move.l A0,A2 ; A2 = Item to check
move.l A1,A5 ; A5 = What to check
lea _Size(A4),A3 ; A3 = SizeSoFar
; if item has command key check size of font
; Default size if ItemImage or no font specified
moveq.l #COMMSEQ,D0
and.w mi_Flags(A2),D0
beq Check ; No CommKey
move.w _CommKeyWidth(A4),D3 ; deafult size
moveq.l #ITEMTEXT,D0
and.w mi_Flags(A2),D0
beq 2$
; Command key uses same font as first IText string
move.l it_ITextFont(A5),D0
beq 2$ ; No font specified
; Open the font
move.l _GfxBase(A4),A6
move.l D0,A0
libcall OpenFont ; (A0=textAttr)
move.l D0,D2
beq 2$ ; Font not resident
; FontExtent(TextFont,&ExtentData)
move.l D0,A0
move.l SP,A1
libcall FontExtent
move.w te_Extent+ra_MaxX(SP),D3
; Close the font again
move.l D2,A1
libcall CloseFont ; (A1=textFont)
; Larger than current max ? (SizeSoFar->CommKey)
2$ cmp.w wws_CommKey(A3),D3
bls Check
move.w D3,wws_CommKey(A3)
; ImTxLeft = ItemLeft = Item->LeftEdge
Check: move.w mi_LeftEdge(A2),D3
move.w D3,D7
; ImTxTop = ItemTop = Item->TopEdge
move.w mi_TopEdge(A2),D2
move.w D2,D6
; ITEMTEXT or ITEMIMAGE ?
moveq.l #ITEMTEXT,D0
and.w mi_Flags(A2),D0
beq ItemImage
; Add IText position to left and top.
; ImTxLeft += IText.leftEdge
add.w it_LeftEdge(A5),D7
; ImTxTop += IText.TopEdge
add.w it_TopEdge(A5),D6
; ImTxRight = ImTxLeft
move.w D7,D5
; ImTxBottom = ImTxTop
move.w D6,D4
; What font to use ?
move.l it_ITextFont(A5),D0
beq DefaultFont
; Add height and length of string.
; ImTxBottom += ITextFont->ta_YSize
move.l D0,A0
add.w ta_YSize(A0),D4
; ImTxRight += IntuiTextLength(IText)
move.l A5,A0
move.l _IntuitionBase(A4),A6
libcall IntuiTextLength
add.w D0,D5
bra NextText
; Add hight and length of string with default font.
; TextExtent(Rp,Itext,strlen(IText),&ExtentData)
DefaultFont: move.l A2,-(SP)
move.l it_IText(A5),A0
call Mystrlen
lea _Rp(A4),A1
move.l it_IText(A5),A0
lea 4(SP),A2
move.l _GfxBase(A4),A6
libcall TextExtent
; ImTxBottom += te_Height
add.w te_Height(A2),D4
; ImTxRight += te_Extent.MaxX
add.w te_Extent+ra_MaxX(A2),D5
move.l (SP)+,A2
; Move to next text.
NextText: move.l it_NextText(A5),A5
bra CheckLeft
; ImTxLeft += Image.leftEdge
ItemImage: add.w ig_LeftEdge(A5),D7
; ImTxTop += Image.TopEdge
add.w ig_TopEdge(A5),D6
; ImTxRight = ImTxLeft + Image.width
move.w D7,D5
add.w ig_Width(A5),D5
; ImTxBottom = ImTxTop + Image.Height
move.w D6,D4
add.w ig_Height(A5),D4
; Move to next image
move.l ig_NextImage(A5),A5
; Compare with size in SizeSoFar
; ItemLeft = Min(ImTxLeft, ItemLeft)
CheckLeft: cmp.w D7,D3
bge 1$
move.w D3,D7
; SizeSoFar.left = Min(SizeSoFar.left, ItemLeft)
1$: cmp.w wws_Left(A3),D7
bge CheckRight
move.w D7,wws_Left(A3)
; ItemRight = Max(ItemLeft + Item.width, ImTxRight)
CheckRight: add.w mi_Width(A2),D3
cmp.w D5,D3
ble 1$
move.w D3,D5
; SizeSoFar.Right = Max(SizeSoFar.Right, ItemRight)
1$: cmp.w wws_Right(A3),D5
ble CheckTop
move.w D5,wws_Right(A3)
; ItemTop = Min(ItemTop, ImTxTop).
CheckTop: cmp.w D6,D2
bge 1$
move.w D2,D6
; SizeSoFar.Top = Min(SizeSoFar.Top, ItemTop)
1$ cmp.w wws_Top(A3),D6
bge CheckBottom
move.w D6,wws_Top(A3)
; ItemBottom = Max(ItemLeft + Item.Height, ImTxBottom)
CheckBottom: add.w mi_Height(A2),D2
cmp.w D4,D2
ble 1$
move.w D2,D4
; SizeSoFar.bottom = Max(SizeSoFar.bottom, ItemBottom)
1$ cmp.w wws_Bottom(A3),D4
ble 2$
move.w D4,wws_Bottom(A3)
; Anything more to check
2$ move.l A5,D0
bne Check
lea te_SIZEOF(SP),SP
moveq.l #TRUE,D0
movem.l (SP)+,D2-D7/A2/A3/A5/A6
rts
;*****************************************
;* SelectItem(VOID) - Do selection *
;* Input: *
;* Output: *
;* return - Selected Item or NULL *
;*****************************************
@SelectItem: movem.l D2/D3/A2/A3/A5,-(SP)
;********************
;* Check subwindow. *
;********************
; SubWindow.bitMapOk == TRUE ?
lea _SubWindow(A4),A2
tst.w wwd_BitMapOk(A2)
beq CheckItem ; Not open
; Mouse in SubWindow ?
move.l A2,A0
call MouseInWindow
tst.w D0
beq 2$ ; Not in window
; NewSubItem = FindMouseItem(&SubWindow)
move.l A2,A0
call FindMouseItem
move.l D0,A3
; Anything changed ? [NewSubItem == SubWindow.Current]
move.l wwd_Current(A2),A0
cmp.l A0,A3
beq SelectDone ; Nothing changed
;***********************
;* A0 = CurrentSubItem *
;* A2 = SubWindow *
;* A3 = NewSubItem *
;***********************
; SubWindow.Current == NULL ? [Anything highlighted]
move.l A0,D0
beq 1$ ; Yes
; HighLightItem(&SubWindow,HIGHLIGHTOFF)
moveq.l #HIGHLIGHTOFF,D0 ; [HIGHLIGHTOFF = TRUE]
move.l A2,A0
call HighLightItem
; SubWindow.Current = NewSubItem.
1$ move.l A3,wwd_Current(A2)
; SubWindow.Current == NULL ?
beq SelectDone ; Yes
; HighLightItem(&SubWindow,HIGHLIGHTON)
moveq.l #HIGHLIGHTON,D0 ; [HIGHLIGHTON = FALSE]
move.l A2,A0
call HighLightItem
; Selectable item ?
tst.w D0
beq SelectDone ; No
; return NewSubItem
moveq.l #TRUE,D0
bra SelectQuit
; Anything highlighted
2$ move.l wwd_Current(A2),A0
move.l A0,D0
beq CheckItem
; HighLightItem(&SubWindow,HIGHLIGHTOFF)
move.l A2,A0
moveq.l #HIGHLIGHTOFF,D0
call HighLightItem
; SubWindow.Current = NULL
clr.l wwd_Current(A2)
;*********************
;* Check itemwindow. *
;*********************
; ItemWindow.bitMapOk == TRUE ?
CheckItem: lea _ItemWindow(A4),A3
tst.w wwd_BitMapOk(A3)
beq CheckMenu ; No
; Mouse in ItemWindow ?
move.l A3,A0
call MouseInWindow
tst.w D0
beq 3$ ; No
; NewItem = FindMouseItem(&ItemWindow).
move.l A3,A0
call FindMouseItem
move.l D0,A5
move.l wwd_Current(A3),D2
;***************************************
;* A2 = SubWindow D2 = CurrentItem *
;* A3 = ItemWindow *
;* A5 = NewItem *
;***************************************
; NewItem == CurrentItem ?
cmp.l D2,A5
beq SelectDone ; Yes
; CurrentItem == NULL ?
tst.l D2
beq 2$ ; Yes
; SubWindow open ?
tst.w wwd_BitMapOk(A2)
beq 1$ ; No
; CloseSubWindow()
call CloseSubWindow
; HighLightItem(&ItemWindow,HIGHLIGHTOFF)
1$ moveq.l #HIGHLIGHTOFF,D0
move.l A3,A0
call HighLightItem
; ItemWindow.Current = NewItem.
2$ move.l A5,_ItemWindow+wwd_Current(A4)
; NewItem == NULL ?
move.l A5,D2
beq SelectDone ; Yes
; HighLightItem(&ItemWindow,HIGHLIGHTON)
moveQ #0,D0
move.l A3,A0
call HighLightItem
; SubWindow.ItemsEnabled = ItemWindow.ItemsEnabled ?
; (NewItem->Flags & ITEMENABLED) : 0
move.w _ItemWindow+wwd_ItemsEnabled(A4),D1
beq 25$
moveq.l #ITEMENABLED,D1
and.w mi_Flags(A5),D1
25$ move.w D1,_SubWindow+wwd_ItemsEnabled(A4)
; SubWindow.Items = NewItem->SubItem.
move.l mi_SubItem(A5),_SubWindow+wwd_Items(A4)
; SubWindow.Items == NULL ?
bne 28$ ; No
; Possible to highlight item ?
tst.w D0
beq SelectDone ; No
; return TRUE
moveq.l #TRUE,D0
bra SelectQuit
; Open item window
; OpenItemWindow(SubWindow,SUBWINDOW,
; CurrentItem->LeftEdge - ItemWindow->LeftValue,
; CurrentItem->LeftEdge + CurrentItem->Width - ItemWindow->LeftValue,
; CurrentItem->TopEdge - ItemWindow->TopValue)
28$ move.w #SUBWINDOW,D0
move.l D2,A0
move.w mi_LeftEdge(A0),D1
sub.w _ItemWindow+wwd_LeftValue(A4),D1
move.w D1,D2
add.w mi_Width(A0),D2
move.w mi_TopEdge(A0),D3
sub.w _ItemWindow+wwd_TopValue(A4),D3
move.l A2,A0
call OpenItemWindow
; Window opened ?
tst.w D0
beq 29$ ; No
; Set ISDRAWN bit [ NewItem.Flags |= ISDRAWNBIT ]
bset #ISDRAWN_B0,mi_Flags(A5)
29$ bra SelectDone
; ItemWindow.Current == NULL ?
3$ tst.l wwd_Current(A3)
beq CheckMenu ; Yes
; SubWindow open ?
tst.w wwd_BitMapOk(A2)
bne CheckMenu ; Yes
; HighLightItem(&ItemWindow,HIGHLIGHTOFF)
4$ moveq.l #HIGHLIGHTOFF,D0
move.l A3,A0
call HighLightItem
; ItemWindow.Current = NULL.
clr.l wwd_Current(A3)
;*********************
;* Check menuwindow. *
;*********************
CheckMenu: lea _MenuWindow(A4),A5
;**********************
;* A2 = SubWindow *
;* A3 = ItemWindow *
;* A5 = MenuWindow *
;**********************
; MenuWindow.bitMapOK ?
tst.w wwd_BitMapOk(A5)
beq SelectDone ; No
; MouseInWindow(MenuWindow) ?
move.l A5,A0
call MouseInWindow
tst.w D0
beq SelectDone ; No
; NewMenuNr = (MouseY - MenuWindow.TopEdge - HBORDERSIZE)/MenuTextHeight + 1
; NewMenuNr = NewMenuNr < 0 ? 0 : NewMenuNr
moveq.l #0,D2
move.w _MouseY(A4),D2
sub.w wwd_TopEdge(A5),D2
subq.w #HBORDERSIZE,D2
bpl 05$
moveq.l #1,D2
bra 07$
05$ divu.w _MenuTextHeight(A4),D2
addq.w #1,D2
; NewMenuNr == CurrentMenuNr ?
07$ move.w _CurrentMenuNr(A4),D3
cmp.w D3,D2
beq SelectDone ; Yes
;****************************************
;* A2 = SubWindow D2 = NewMenuNr *
;* A3 = ItemWindow D3 = CurrentMenuNr *
;* A5 = MenuWindow *
;****************************************
; CurrentMenuNr == 0 ?
tst.w D3
beq 2$ ; Yes
; ItemWindow.bitMapOk
tst.w wwd_BitMapOk(A3)
beq 1$ ; No
; Close sub and item windows
call CloseSubWindow
call CloseItemWindow
; ToggleMenu(CurrentMenuNr,MenuWindow.Current) - HIGHLIGHTOFF -
1$ move.w D3,D0
move.l wwd_Current(A5),A0
call ToggleMenu
; MenuWindow.Current = FindMenuPtr(NewMenuNr)
2$ lea _MenuSorted-4(A4),A0
move.w D2,D0
lsl.w #2,D0
move.l 0(A0,D0.w),wwd_Current(A5)
; MenuWindow.Current == NULL ?
bne 3$ ; No
; CurrentMenuNr = 0
clr.w _CurrentMenuNr(A4)
bra SelectDone
; CurrentMenuNr = LastSelectedNum = NewMenuNr
3$ move.w D2,_CurrentMenuNr(A4)
move.w D2,_LastSelectedNum(A4)
move.w D2,D3
; ItemWindow.ItemsEnabled = MenuWindow.Current->Flags & MENUENABLED
move.l wwd_Current(A5),A0
moveq.l #MENUENABLED,D0
and.w mu_Flags(A0),D0
move.w D0,wwd_ItemsEnabled(A3)
; ItemWindow.Items = MenuWindow.Current->FirstItem
move.l mu_FirstItem(A0),wwd_Items(A3)
; ToggleMenu(NewMenuNr,MenuWindow.Current) - HIGHLIGHTON -
move.w D2,D0
call ToggleMenu
; ItemWindow->Items == NULL ?
tst.l wwd_Items(A3)
beq SelectDone ; Yes
; ItemsTopPos = (CurrentMenuNr - 1) * MenuTextHeight + MenuWindow.TopEdge + HBORDERSIZE
subq.w #1,D3
mulu.w _MenuTextHeight(A4),D3
add.w _MenuWindow+wwd_TopEdge(A4),D3
addq.w #HBORDERSIZE,D3
; OpenItemWindow(ItemWindow,ITEMWINDOW,
; MenuWindow.leftEdge, MenuWindow.RightEdge, ItemsTopPos)
move.l A3,A0
moveq.l #ITEMWINDOW,D0
moveq.l #0,D1
move.w _MenuWindow+wwd_LeftEdge(A4),D1
moveq.l #0,D2
move.w _MenuWindow+wwd_RightEdge(A4),D2
call OpenItemWindow
; Window opened ?
tst.w D0
beq SelectDone ; NO
; Set MIDRAWN flag
move.l wwd_Current(A5),A0
bset #MIDRAWN_B0,mu_Flags(A0)
SelectDone: moveq.l #FALSE,D0
SelectQuit: movem.l (SP)+,D2/D3/A2/A3/A5
rts
;*****************************************************************
;* FinalSelect() - Do checkmarking and calculate Menupick value. *
;* *
;* Input: *
;* none *
;* Output: *
;* return - MenuPick-value or MENUNULL. *
;*****************************************************************
@FinalSelect: move.l D2,-(SP)
; SubItemNr = NOSUB
moveq.l #NOSUB,D2
; SubWindow.Current == NULL ?
move.l _SubWindow+wwd_Current(A4),D0
beq 1$ ; Yes
move.l D0,A0
; SubWindow.Current->Flags & SubWindow.ItemsEnabled & ITEMENABLED ?
move.w mi_Flags(A0),D1
moveq.l #ITEMENABLED,D0
and.w D1,D0
and.w _SubWindow+wwd_ItemsEnabled(A4),D0
beq 2$ ; No
; SubWindow.Current->Flags & MENUTOGGLED ?
btst #MENUTOGGLED_B0+8,D1
bne 2$ ; Yes
; Find the number of the selected subitem
move.l _SubWindow+wwd_Items(A4),A1
call FindItemNr
and.w #NOSUB,D0 ; NOITEM > NOSUB
move.l D0,D2
; Subitem selected -> checkmark and draw all subitems again.
; CheckMark(&SubWindow)
lea _SubWindow(A4),A0
call CheckMark
; Anything changed ?
tst.w D0
beq 3$ ; No
; DrawAllItems(&SubWindow)
lea _SubWindow(A4),A0
call DrawAllItems
; HighLightItem(&SubWindow,HIGHLIGHTON)
moveq.l #HIGHLIGHTON,D0
lea _SubWindow(A4),A0
call HighLightItem
bra 3$
; ItemWindow.Current == NULL ?
1$ move.l _ItemWindow+wwd_Current(A4),D0
beq 2$ ; Yes
move.l D0,A0
; ItemWindow.Current->SubItem == NULL ?
tst.l mi_SubItem(A0)
bne 2$ ; No
; ItemWindow.Current->Flags & ITEMENABLED ?
move.w mi_Flags(A0),D1
btst #ITEMENABLED_B1,D1
beq 2$ ; No
; ItemWindow.Current->Flags & MENUTOGGLED ?
btst #MENUTOGGLED_B0+8,D1
bne 2$ ; Yes
; ItemWindow.ItemsEnabled & MENUENABLED ?
tst.w _ItemWindow+wwd_ItemsEnabled(A4)
bne 3$ ; Yes
; Nothing is selected -> exit
2$ moveq.l #-1,D0 ; MENUNULL
bra 6$
; CheckMark(ItemWindow)
3$ lea _ItemWindow(A4),A0
call CheckMark
tst.w D0
beq 38$
; Remove SubWindow (if any).
lea _SubWindow(A4),A0
call SwapBits
; DrawAllItems(&ItemWindow)
lea _ItemWindow(A4),A0
call DrawAllItems
; Check if ItemWindow & MenuWindow is Same (4.0)
tst.w _MenuWindow+wwd_BitMapOk(A4)
bne 35$
; DrawAllMenus(ItemWindow)
lea _ItemWindow(A4),A0
call DrawAllMenus
; HighLightItem(&ItemWindow,HIGHLIGHTON)
35$ moveq.l #HIGHLIGHTON,D0
lea _ItemWindow(A4),A0
call HighLightItem
; Restore subwindow. (if any)
lea _SubWindow(A4),A0
call SwapBits
; Find number of selected item,
38$ move.l _ItemWindow+wwd_Current(A4),A0
move.l _ItemWindow+wwd_Items(A4),A1
call FindItemNr
; MenuNum = SHIFTMENU(FindRealMenuNum(CurrentMenuNr)) |
; SHIFTITEM(ItemNr) |
; SHIFTSUB(SubItemNr)
lsl.w #6,D2
or.w D2,D0
lsl.w #5,D0
lea _MenuSorted-4(A4),A0
move.w _CurrentMenuNr(A4),D1
lsl.w #2,D1
move.l 0(A0,D1.W),A1
move.l _Menus(A4),A0
bra 5$
4$ move.l mu_NextMenu(A0),A0
addq.w #1,D0
5$ cmp.l A0,A1
bne 4$
6$ move.l (SP)+,D2
rts
;*****************************************************
;* BOOL CheckMark(Window) - Checkmark selected item. *
;* *
;* Input: *
;* Window - Window to checkmark *
;* Output: *
;* return.w - TRUE if checkmarked *
;*****************************************************
@CheckMark: move.l wwd_Items(A0),A1
move.l wwd_Current(A0),A0
moveq.l #FALSE,D0
move.w mi_Flags(A0),D1
; Selected->Flags & CHECKIT ?
btst #CHECKIT_B1,D1
beq 4$ ; No
; Selected->Flags & CHECKED ?
btst #CHECKED_B0+8,D1
beq 1$ ; No
; Selected->Flags & MENUTOGGLE ?
btst #MENUTOGGLE_B1,D1
beq 4$ ; No
; Selected->Flags &= ~CHECKED - Togglemenu -
bclr #CHECKED_B0,mi_Flags(A0)
bra 35$
; Selected->Flags |= CHECKED
1$ bset #CHECKED_B0,mi_Flags(A0)
; Handle mutual exclusion.
; Exclude = Selected->MutualExclude
move.l mi_MutualExclude(A0),D0
beq 35$
; Exclude >>= 1
2$ lsr.l #1,D0
bcc 3$
; Items->Flags &= ~CHECKED
bclr #CHECKED_B0,mi_Flags(A1)
; Items = Items->NextItem
3$ move.l mi_NextItem(A1),A1
; More items ?
move.l A1,D1
bne 2$ ; Yes
35$ moveq.l #TRUE,D0
4$ rts
*************************************************************
* VOID DrawMenuItem(Window, Item, Mode) *
* *
* Input: *
* Window - Data about window to draw item into. *
* Item - Item to draw. *
* Mode.w - ITEMFILL = Draw Item. *
* SELECTFILL = Draw selected item (if any). *
* OUTPUT *
* none *
*************************************************************
@DrawMenuItem: movem.l D2-D7/A2/A3/A5/A6,-(SP)
move.l A1,A3
move.l A0,-(SP)
********************************************************
* D0 = Mode A0 = Window (SP) Window *
* A1 = Item *
* A3 = Item *
********************************************************
; Left = Item->LeftEdge - Window->LeftValue
move.w mi_LeftEdge(A3),D7
sub.w wwd_LeftValue(A0),D7
ext.l D7
; Right = Left + Item->Width - 1
move.l D7,D2
add.w mi_Width(A3),D2
subq.l #1,D2
; ItemTop = Top = Item->TopEdge - Window->TopValue
move.w mi_TopEdge(A3),D6
sub.w wwd_TopValue(A0),D6
ext.l D6
move.l D6,D4
; Bottom = Top + Item->Height - 1
move.l D6,D3
add.w mi_Height(A3),D3
subq.l #1,D3
lea _Rp(A4),A5
move.l _IntuitionBase(A4),A6
; Find what to Draw.
move.l mi_ItemFill(A3),A2
tst.w D0 ; Mode == ITEMFILL ?
beq CheckDraw
; Use selectfill.
move.l mi_SelectFill(A3),A2
***************************************************************
* D0 = Mode A0 = Window (SP) Window *
* A1 = Item *
* D2 = Right A2 = Fill *
* D3 = Bottom A3 = Item *
* D4 = ItemTop *
* D6 = Top A5 = Rp *
* D7 = Left A6 = IntuitionBase *
***************************************************************
; Anything to draw ?
CheckDraw: move.l A2,D0
beq DrawDone
; Draw the item.
DrawItem: move.l A5,A0 ; Rp
move.l A2,A1 ; Fill
move.l D7,D0 ; Left
move.l D6,D1 ; Top
moveq.l #ITEMTEXT,D5
and.w mi_Flags(A3),D5
beq DrawImage
; PrintIText(Fill, Left, Top)
libcall PrintIText
; ItemTop += Fill.TopEdge
add.w it_TopEdge(A2),D4
bra DrawCheckMark
; DrawImage(Fill, Left, Top)
DrawImage: libcall DrawImage
; ItemTop += Fill.TopEdge
add.w ig_TopEdge(A2),D4
***********************************************************
* D2 = Right A2 = Fill (SP) Window *
* D3 = Bottom A3 = Item *
* D4 = ItemTop A5 = Rp *
* D6 = Top A6 = IntuitionBase *
* D7 = Left *
***********************************************************
; Draw CheckMark ?
DrawCheckMark: btst #CHECKIT_B1,mi_Flags+1(A3)
beq DrawCommKey
btst #CHECKED_B0,mi_Flags(A3)
beq DrawCommKey
; DrawImage(ActiveWindow->CheckMark, Left, ItemTop)
move.l _ActiveWindow(A4),A0
move.l wd_CheckMark(A0),A1 ; CheckMark
move.l D7,D0 ; Left
move.l D4,D1 ; ItemTop (New 3.7)
move.l A5,A0 ; Rp
libcall DrawImage
***********************************************************
* D2 = Right A2 = Fill (SP) Window *
* D3 = Bottom A3 = Item *
* D4 = ItemTop A5 = Rp *
* D6 = Top A6 = IntuitionBase *
* D7 = Left *
***********************************************************
; Restore DrawMode [SetDrMd(JAM1)]
DrawCommKey: move.l _GfxBase(A4),A6
move.l A5,A1 ; Rp
moveq.l #RP_JAM1,D0
libcall SetDrMd ; (A1=rastPort,D0=drawmode)
; Has item a commad key ?
moveq.l #COMMSEQ,D0
and.w mi_Flags(A3),D0
beq GhostItem ; No
; D5 = OldFont (NULL if default)
moveq.l #NULL,D5
; Find font to use
moveq.l #ITEMTEXT,D0
and.w mi_Flags(A3),D0
beq DefaultCommKey ; ITEMIMAGE => Use default font
move.l mi_ItemFill(A3),D0 ; no itemfill => Use default font
beq DefaultCommKey
move.l D0,A0
move.l it_ITextFont(A0),D0
beq DefaultCommKey ; No font specified => Use default
; We have to open the font to use.
move.l D0,A0
libcall OpenFont ; (A0=textAttr)
tst.l D0
beq DefaultCommKey ; Font is not resident => use default symbol position
move.l rp_Font(A5),D1
cmp.l D0,D1
bne 10$
; Same as deafult font
move.l D0,A1 ; Same as default
libcall CloseFont ; (A1=textFont)
bra DefaultCommKey
10$ move.l D1,D5 ; D5 = OldFont
move.l D0,A0
move.l A5,A1
libcall SetFont ; (A1=rastPort,A0=textFont)
***********************************************************
* D2 = Right A2 = Fill (SP) Window *
* D3 = Bottom A3 = Item *
* D4 = ItemTop A5 = Rp *
* D5 = OldFont *
* D6 = Top A6 = GfxBase *
* D7 = Left *
***********************************************************
; SetAPen(DetailPen)
DefaultCommKey: moveq.l #0,D0
move.b _DetailPen(A4),D0
move.l A5,A1
libcall SetAPen ; (A1=rastPort,D0=pennum)
; KeyLeft = Right - Window->CommKeySize
move.l D2,D0
move.l (SP),A0
sub.w wwd_CommKeySize(A0),D0
; KeyTop = ItemTop + Rp.TxBaseLine;
move.l D4,D1
add.w rp_TxBaseline(A5),D1
; Move(KeyLeft,KeyTop)
move.l D0,-(SP)
move.l D1,-(SP)
move.l A5,A1
libcall Move ; (A1=rastPort,D0=x,D1=y)
; Text(Rp,Item->Command,1)
move.l A5,A1
lea mi_Command(A3),A0
moveq.l #1,D0
libcall Text ; (A1=rastPort,A0=stringPointer,D0=count)
; KeyTop -= AMIGAKEYHEIGHT-1
move.l (SP)+,D1
move.l (SP)+,D0
subq.l #AMIGAKEYHEIGHT-1,D1
; if (KeyTop < ItemTop) KeyTop = ItemTop
cmp.w D1,D4
ble 1$
move.l D4,D1
; DrawImage(Rp,MyAmigaKeyImage[ScreenType], KeyLeft, KeyTop);
1$ move.l _IntuitionBase(A4),A6
move.l A5,A0
lea MyAmigaKeyImage(PC),A1
tst.w _ScreenType(A4)
beq 2$
lea ig_SIZEOF(A1),A1
2$ libcall DrawImage ; (A0=rastPort,A1=image,D0=leftOffset,D1=topOffset)
move.l _GfxBase(A4),A6
; Restore old font ?
tst.l D5
beq GhostItem
; Close the new font
move.l rp_Font(A5),A1
libcall CloseFont ; (A1=textFont)
move.l D5,A0
move.l A5,A1
libcall SetFont ; (A1=rastPort,A0=textFont)
***********************************************************
* D2 = Right A2 = Fill (SP) = Window *
* D3 = Bottom A3 = Item *
* D4 = ItemTop A5 = Rp *
* D6 = Top A6 = GfxBase *
* D7 = Left *
***********************************************************
; Ghost Item ?
GhostItem: moveq.l #ITEMENABLED,D0
and.w mi_Flags(A3),D0
beq 1$
move.l (SP),A2
tst.w wwd_ItemsEnabled(A2)
bne DrawDone
; SetAfPt(&Rp, GhostPattern, 1)
1$ lea GhostPattern(PC),A0
move.l A0,_Rp+rp_AreaPtrn(A4)
moveq.l #1,D0
move.b D0,_Rp+rp_AreaPtSz(A4)
; SetAPen(BlockPen)
move.b _BlockPen(A4),D0
move.l A5,A1
libcall SetAPen ; (A1=rastPort,D0=pennum)
; RectFill(Left, Top, Right, Bottom)
move.l A5,A1
move.l D7,D0
move.l D6,D1
libcall RectFill
; SetAfPt(NormalPattern, 1)
lea NormalPattern(PC),A0
move.l A0,_Rp+rp_AreaPtrn(A4)
DrawDone: addq.l #4,SP ; forget Window
movem.l (SP)+,D2-D7/A2/A3/A5/A6
rts
***************************************************
* BOOL HighLightItem(Window, Mode) *
* *
* Input: *
* Window - Data for the window to draw in. *
* Mode.w - HIGHLIGHTON or HIGHLIGHTOFF. *
* Output: *
* return - TRUE if item highlighted *
* (may be HIGHNONE) *
***************************************************
@HighLightItem: movem.l D2-D4/A2/A3/A5/A6,-(SP)
move.l wwd_Current(A0),A3
; Possible to highlight item ?
move.w mi_Flags(A3),D4
btst #ITEMENABLED_B1,D4
beq 1$ ; No
tst.w wwd_ItemsEnabled(A0)
bne 15$ ; Yes
; return FALSE
1$ moveq.l #FALSE,D0
bra HighLightQuit
; start highlighting
15$ move.l A0,A2
lea _Rp(A4),A5
move.l _GfxBase(A4),A6
; Set or clear HIGHITEM flag
bclr #HIGHITEM_B0+8,D4
; Mode = !Mode
moveq.l #1,D1
addq.w #1,D0
and.w D1,D0
; !Mode = HIGHLIGHTOFF ?
beq 2$ * Yes
bset #HIGHITEM_B0+8,D4
2$ move.w D4,mi_Flags(A3)
***********************************************
* D0 = !Mode A0 = Window *
* D4 = Window.Current.Flags A2 = Window *
* A3 = Item *
* A5 = Rp *
* A6 = GfxBase *
***********************************************
and.w #HIGHFLAGS,D4
bne NotHighImage
; DrawMenuItem(Window, Item, !Mode);
HighImage: move.l A3,A1
call DrawMenuItem
bra HighlightDone
; SetDrMd(COMPLEMENT)
NotHighImage: moveq.l #RP_COMPLEMENT,D0
move.l A5,A1
libcall SetDrMd
; Left = Item->LeftEdge - Window->LeftValue
move.w mi_LeftEdge(A3),D0
sub.w wwd_LeftValue(A2),D0
ext.l D0
; Right = Left + Item->Width - 1
move.l D0,D2
add.w mi_Width(A3),D2
subq.l #1,D2
; Top = Item->TopEdge - Window->TopValue
move.w mi_TopEdge(A3),D1
sub.w wwd_TopValue(A2),D1
ext.l D1
; Bottom = Top + Item->Height - 1
move.l D1,D3
add.w mi_Height(A3),D3
subq.l #1,D3
move.l A5,A1
***********************************
* D0 = Left *
* D1 = Top *
* D2 = Right *
* D3 = Bottom A5 = Rp *
* D4 = HighFlags A6 = GfxBase *
***********************************
; Check out kind of highlighting.
cmp.w #HIGHBOX,D4
beq HighBox
cmp.w #HIGHCOMP,D4
bne HighlightDone
; RectFill(Left, Top, Right, Bottom)
HighComp: libcall RectFill
bra HighlightDone
; DrawRect(Left-4, Top-2, Right + 4, Bottom + 2)
HighBox: subq.l #4,D0
subq.l #2,D1
addq.l #4,D2
addq.l #2,D3
bsr DrawRect
bsr DrawRect
; return TRUE
HighlightDone: moveq.l #TRUE,D0
HighLightQuit: movem.l (SP)+,D2-D4/A2/A3/A5/A6
rts
*********************************************
* VOID ToggleMenu(Number,Menu) *
* *
* Input: *
* Number.w - Menu to highlight. *
* Menu - Pointer to the Menu structure. *
* Output: *
* none *
*********************************************
@ToggleMenu: movem.l D2/D3/A6,-(SP)
; Menu enabled ?
moveq.l #MENUENABLED,D2
and.w mu_Flags(A0),D2
beq ToggleDone
move.w D0,D3
; Set drawmode = COMPLEMENT.
move.l _GfxBase(A4),A6
lea _Rp(A4),A1
moveq.l #RP_COMPLEMENT,D0
libcall SetDrMd
; Invert menu.
; Bottom = Number * MenuTextHeight + MenuWindow.TopEdge.
move.w _MenuTextHeight(A4),D2
mulu.w D2,D3
add.w _MenuWindow+wwd_TopEdge(A4),D3
; Top = Bottom - MenuTextHeight + HBORDERSIZE.
move.l D3,D1
sub.l D2,D1
addq.l #HBORDERSIZE,D1
; Left = MenuWindow.leftEdge + VBORDERSIZE.
moveq.l #VBORDERSIZE,D0
add.w _MenuWindow+wwd_LeftEdge(A4),D0
; Right = MenuWindow.RightEdge - VBORDERSIZE.
move.w _MenuWindow+wwd_RightEdge(A4),D2
subq.l #VBORDERSIZE,D2
; RectFill(Rp,Left,Top,Right,Bottom)
lea _Rp(A4),A1
libcall RectFill
ToggleDone: movem.l (SP)+,D2/D3/A6
rts
*******************************************************
* VOID DrawAllMenus(Window) *
* *
* Input: *
* Window - Window to draw into (may be itemwindow) *
* Output: *
* none *
*******************************************************
@DrawAllMenus: movem.l D2-D5/A2/A3/A5/A6,-(SP)
; MenuLeft = Window.leftEdge + VBORDERSIZE
moveq.l #VBORDERSIZE,D5
add.w wwd_LeftEdge(A0),D5 ; 4.0
; MenuTop = Window.TopEdge + HBORDERSIZE+1 [+1 here instead of TxBaseline+1 later]
moveq.l #HBORDERSIZE+1,D4
add.w wwd_TopEdge(A0),D4 ; 4.0
; MenuRight = Window.RightEdge - VBORDERSIZE
move.w wwd_RightEdge(A0),D2 ; 4.0
subq.w #VBORDERSIZE,D2
ext.l D2
; MenuSortedT = MenuSorted;
lea _MenuSorted(A4),A3
lea _Rp(A4),A5
move.l _GfxBase(A4),A6
****************************************
* D2 = MenuRight *
* D4 = MenuTop A3 = MenuSortedT *
* D5 = MenuLeft A5 = Rp *
* A6 = GfxBase *
****************************************
NextMenu: move.l (A3)+,A2
; SetAPen(Rp,DetailPen)
moveq.l #0,D0
move.b _DetailPen(A4),D0
move.l A5,A1
libcall SetAPen
; Move(Rp, MenuLeft, MenuTop + Rp.TxBaseline)
move.l D5,D0
move.l D4,D1
add.w _Rp+rp_TxBaseline(A4),D1 * 4.4
move.l A5,A1
libcall Move
; Text(Rp,(*MenuSortedT)->MenuName,Mystrlen((*MenuSortedT)->MenuName))
move.l mu_MenuName(A2),A0
call Mystrlen
move.l A5,A1
move.l mu_MenuName(A2),A0
libcall Text
; NextMenuTop = MenuTop + MenuTextHeight
move.l D4,D3
add.w _MenuTextHeight(A4),D3
; GhostItem ?
moveq.l #MENUENABLED,D0
and.w mu_Flags(A2),D0
bne NoMenuGhost
; SetAfPt(Rp, GhostPattern, 1)
lea GhostPattern(PC),A0
move.l A0,_Rp+rp_AreaPtrn(A4)
moveq.l #1,D0
move.b D0,_Rp+rp_AreaPtSz(A4)
; SetAPen(Rp,BlockPen)
move.b _BlockPen(A4),D0
move.l A5,A1
libcall SetAPen
; RectFill(Rp,MenuLeft,MenuTop + HBORDERSIZE,MenuRight,NextMenuTop)
move.l D5,D0
move.l D4,D1
addq.w #HBORDERSIZE,D1
move.l A5,A1
libcall RectFill
; SetAfPt(&Rp,NormalPattern,1);
lea NormalPattern(PC),A0
move.l A0,_Rp+rp_AreaPtrn(A4)
; MenuTop = NextMenuTop
NoMenuGhost: move.l D3,D4
; More menus ?
move.l (A3),D0
bne NextMenu
movem.l (SP)+,D2-D5/A2/A3/A5/A6
rts
;*******************************************************
;* ULONG Mystrlen(String) - A short (and fast) strlen. *
;* *
;* Input: *
;* String - pointer to a null-terminated string. *
;* Output: *
;* return - length of string. max 32767 chars *
;*******************************************************
@Mystrlen: moveq.l #-1,D0
1$ tst.b (A0)+
dbeq D0,1$
neg.l D0
subq.l #1,D0
rts
**********************************************
* DrawRect(Rp,Left+2,Top+1,Right-2,Bottom-1) *
* A1 D0 D1 D2 D3 *
* A6 = GfxBase, A1 not destroyed *
**********************************************
DrawRect: movem.l D4/D5/A2,-(SP)
move.l D0,D4
move.l D1,D5
move.l A1,A2
; Move(Rp,Left,Top)
libcall Move
; Draw(Rp,Left++,Bottom)
move.l D4,D0
move.l D3,D1
move.l A2,A1
libcall Draw
addq.l #1,D4
; Draw(Rp,Right,Bottom--)
move.l D2,D0
move.l D3,D1
move.l A2,A1
libcall Draw
subq.l #1,D3
; Draw(Rp,Right--,Top)
move.l D2,D0
move.l D5,D1
move.l A2,A1
libcall Draw
subq.l #1,D2
; Draw(Rp,Left,Top++)
move.l D4,D0
move.l D5,D1
move.l A2,A1
libcall Draw
addq.l #1,D5
; Draw(Rp,Left++,Bottom)
move.l D4,D0
move.l D3,D1
move.l A2,A1
libcall Draw
addq.l #1,D4
; Move(Rp,Right,Bottom)
move.l D2,D0
move.l D3,D1
move.l A2,A1
libcall Move
; Draw(Rp,Right--,Top)
move.l D2,D0
move.l D5,D1
move.l A2,A1
libcall Draw
subq.l #1,D2
move.l D4,D0
move.l D5,D1
move.l A2,A1
movem.l (SP)+,D4/D5/A2
rts
; Put these images in the code segment
MyAmigaKeyImage:
dc.w -25,0 ; ig_LeftEdge, ig_TopEdge
dc.w 23,AMIGAKEYHEIGHT ; ig_Width, ig_Height
dc.w 1 ; ig_Depth
dc.l AmigaKeyHighRes ; ig_ImageData
dc.b 1,0 ; ig_PlanePick, ig_PlaneOnOff
dc.l NULL ; ig_NextImage
dc.w -16,0 ; ig_LeftEdge, ig_TopEdge
dc.w 14,AMIGAKEYHEIGHT ; ig_Width, ig_Height
dc.w 1 ; ig_Depth
dc.l AmigaKeyLoRes ; ig_ImageData
dc.b 1,0 ; ig_PlanePick, ig_PlaneOnOff
dc.l NULL ; ig_NextImage
GhostPattern: dc.w %0001000100010001
dc.w %0100010001000100
NormalPattern: dc.w %1111111111111111
dc.w %1111111111111111
section ImageData,DATA,CHIP
AmigaKeyHighRes:
dc.l %11000000000000000000011000000000
dc.l %00000000000000111100000000000000
dc.l %00000000000011111100000000000000
dc.l %00000000001110011100000000000000
dc.l %00000000111000011100000000000000
dc.l %00000011111111111100000000000000
dc.l %00011111100000111111000000000000
dc.l %11000000000000000000011000000000
AmigaKeyLoRes: dc.w %1000000000000100
dc.w %0000000011100000
dc.w %0000000111100000
dc.w %0000001101100000
dc.w %0000011001100000
dc.w %0000111111100000
dc.w %0011110011110000
dc.w %1000000000000100
AMIGAKEYHEIGHT equ (*-AmigaKeyLoRes)/2
end