		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


