		include     "All.i"
		include     "exec/types.i"
		include     "PopUp.i"

		xref	    @PopUpMenu

		xdef	    @QueTimer
		xdef	    @AbortTimer
		xdef	    PopUpSemaphore

; @ before label means standard c function (D0-D1/A0-A1 destroyed etc)
; _ before label means ordinary variable
;   nothing before label means variable located in code segment
; uppercase labels means constants placed in code segment
;

		section     text,code
;	Make room for global data on stack
ProgStart:	lea	    -Globals_SIZEOF(SP),SP
		move.l	    SP,A4

;	Clear all global data
		move.l	    SP,A0
		move.w	    #Globals_SIZEOF/2-1,D1
		moveq.l     #0,D0

1$		move.w	    D0,(A0)+
		dbra	    D1,1$

;	Move ExecBase to the data area. two reasons
;	  1. Easy to reach when needed [MOVE.L	(A4),A6]
;	  2. Faster if data area is in FAST RAM
		move.l	    (AbsExecBase).w,A6
		move.l	    A6,_ExecBase(A4)   ; Lets hope this is FAST RAM

;	Get the address of our task
		move.l	    ThisTask(A6),A5  ; A5 = ThisTask

; ------------------------------------------------------------------------------
;		moveq.l     #0,D0

;	Started form CLI ?
		tst.l	    pr_CLI(A5)
		bne	    FromCLI	    ; Yes

;	Wait for startup message.
		lea	    pr_MsgPort(A5),A0
		libcall     WaitPort		; (A0=port)

		lea	    pr_MsgPort(A5),A0
		libcall     GetMsg		; (A0=port)

;
FromCLI:	move.l	    D0,_WBenchMsg(A4)

;	Open Dos library
		lea	    DOSNAME(PC),A1
		moveq.l     #KICK204,D0        ; Need version 2.04
		libcall     OpenLibrary 	; (A1=libname,D0=version)

		move.l	    D0,_DOSBase(A4)
		beq	    NoDos	       ; No dos !!!?

;	Clear the hotkey field
		lea	    DEFAULTHOTKEY(PC),A0
		lea	    _HotKeyString(A4),A1
1$		move.b	    (A0)+,(A1)+
		bne	    1$

;	Parse arguments
		call	    ParseArgs		; ()

; ------------------------------------------------------------------------------

;  D0.b = Options
;  D1.b = CX_PRIORITY
;  _HotKeyString(A4) = HotKey

;	Save the entered options
		move.b	    D0,_CxHandlerData+ssd_Options(A4)

; -----------------------------------------------------------------------------
;	Create our broker
;	Set the broker priority
		lea	    BrokerData(PC),A2
		move.b	    D1,nb_Pri(A2)

;	We need a port in the NewBroker structure
		libcall     CreateMsgPort	; ()

		move.l	    D0,nb_Port(A2)
		beq	    NoBrokerPort

;	Open Commodities library
		lea	    COMMODITYNAME(PC),A1
		moveq.l     #KICK204,D0        ; Kick 2.04 needed here
		libcall     OpenLibrary 	; (A1=libname,D0=version)

		move.l	    D0,_CxBase(A4)
		move.l	    D0,CxBase	       ; For the inputhandler
		beq	    NoCommodity

		move.l	    D0,A6

;	Start up the broker
		move.l	    A2,A0		; A2 = BrokerData
		moveq.l     #0,D0
		libcall     CxBroker		; (A0=nb,D0=error)

		move.l	    D0,_PopUpBroker(A4)

;	If we can't create the broker PopUpMenu is probably already running
		beq	    NoBroker
; -----------------------------------------------------------------------------

;	PopUpMenu is not installed
;	Open needed libraries (All these are in ROM so they can be permanent)
;	Intuition
		move.l	    _ExecBase(A4),A6
		lea	    INTUITIONNAME(PC),A1
		moveq.l     #KICK204,D0
		libcall     OpenLibrary 	; (A1=libname,D0=version)

		move.l	    D0,_IntuitionBase(A4)
		move.l	    D0,IBase		 ; for the inputhandler
		beq	    NoIntuition

;	Graphics
		lea	    GFXNAME(PC),A1
		moveq.l     #KICK204,D0
		libcall     OpenLibrary 	; (A1=libname,D0=version)

		move.l	    D0,_GfxBase(A4)
		beq	    NoGraphics

;	Layers
		lea	    LAYERSNAME(PC),A1
		moveq	    #KICK204,D0
		libcall     OpenLibrary 	; (A1=libname,D0=version)

		move.l	    D0,_LayersBase(A4)
		beq	    NoLayers

; ------------------------------------------------------------------------------
;	We need a replyport for the intuimessages
		libcall     CreateMsgPort	; ()

		move.l	    D0,_ReplyPort(A4)
		beq	    NoReplyPort

; ------------------------------------------------------------------------------
;	We need the timer device
;	Create a port
		libcall     CreateMsgPort	; ()

		move.l	    D0,_TimerPort(A4)
		beq	    NoTimerPort

;	Create a IOStdReq
		move.l	    D0,A0
		moveq.l     #IOTV_SIZE,D0
		libcall     CreateIORequest	; (A0=port,D0=size)

		move.l	    D0,_TimerReqBlock(A4)
		beq	    NoTimerIOStdReq

;	Open the timer device, (UNIT_VBLANK)
		lea	    TIMERNAME(PC),A0
		move.l	    D0,A1
		moveq.l     #UNIT_VBLANK,D0
		moveq.l     #0,D1
		libcall     OpenDevice		; (A0=devname,D0=unit,A1=ioRequest,d1=flags)

		tst.l	    D0
		bne	    NoTimerDevice    ; OpenDevice failed

;	Start a timer. CheckIO will crash if no timer is started
		moveq.l     #1,D0	     ; Shortest possible timer 1/50s
		call	    QueTimer	     ; (D0=length)

; ---------------------------------------------------------------------------------

;	Create a semaphore to use in the intuition patch
;	  the semaphore is in this code segment so we can reach
;	  it directly in the patched functions.
		lea	    PopUpSemaphore(PC),A0
		libcall     InitSemaphore	; (A0=sigSem)

;	Patch the Intuition function to use the semaphore
;	ClearMenuStrip, OnMenu, OffMenu, must be patched.
;	 SetMenuStrip and ResetMenuStrip not needed since Programs are not
;	 allowed to use these functions without clearing the menu-strip
;	 with ClearMenuStrip before.
;
;	Patch	ClearMenuStrip

		lea	    @MyClearMenuStrip(PC),A0
		move.l	    A0,D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOClearMenuStrip,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

		move.l	    D0,OldClearMenuStrip
		beq	    NoClearMenuPatch

;	Patch	OnMenu
		lea	    @MyOnMenu(PC),A0
		move.l	    A0,D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOOnMenu,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

		move.l	    D0,OldOnMenu
		beq	    NoOnMenuPatch

;	Patch	OffMenu
		lea	    @MyOffMenu(PC),A0
		move.l	    A0,D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOOffMenu,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

		move.l	    D0,OldOffMenu
		beq	    NoOffMenuPatch

; ---------------------------------------------------------------------------
;	Init the datafield for the inputhandler
		lea	    _CxHandlerData(A4),A2

;	Poiter to our task
		move.l	    A5,ssd_PopUpMenuTask(A2)

;	Clear other fields (Flags, EndQualifier)
;[Not needed]	moveq.l     #0,D0
;		move.b	    D0,ssd_Flags(A2)
;		move.w	    D0,ssd_EndQualifier(A2)

;	We need a lot of signals, make a loop
		lea	    ssd_FirstSignal(A2),A3
		moveq.l     #NO_OF_SIGNALS-1,D2

NextSignal	moveq.l     #-1,D0
		libcall     AllocSignal 	; (D0=signalNum)

		move.w	    D0,ssi_Num(A3)
		bmi	    NoSignal

		moveq.l     #1,D1
		asl.l	    D0,D1
		move.l	    D1,ssi_Mask(A3)

		addq.l	    #ssi_SIZEOF,A3
		dbra	    D2,NextSignal

; ----------------------------------------------------------------------------
;	Add a notify on the IControlPrefs

		lea	    NotifyData(PC),A3
		move.b	    ssd_NotifySig+ssi_Num+1(A2),nr_SignalNum(A3)
		move.l	    A5,nr_Task(A3)      ; A5 = ThisTask

		move.l	    _DOSBase(A4),A6
		move.l	    A3,D1
		libcall     StartNotify 	; (D1=notify)

		tst.l	    D0
		bpl	    NoFileNotify

; ----------------------------------------------------------------------------
;			     Broker
;			    /	  \
;		       Custom	  Filter (Hotkey)
;				  /    \
;			      Signal	Translate
;
		move.l	    _CxBase(A4),A6

;	Create a custom object
		moveq.l     #CX_CUSTOM,D0
		lea	    @PopUpHandler(PC),A0
		move.l	    A2,A1		; A2 = _CxHandlerData
		libcall     CreateCxObj 	; (D0=type,A0=arg1,A1=arg2)

		move.l	    D0,A1
		move.l	    A1,D0
		beq	    NoCustomCxObj

;	Attach it to the broker
		move.l	    _PopUpBroker(A4),A0
		libcall     AttachCxObj 	; (A0 = headObj,A1=co)

; ---------------------------------------------------------------------------

;	Add the hotkey to broker
;	Create a filter object
		moveq.l     #CX_FILTER,D0
		lea	    _HotKeyString(A4),A0
		sub.l	    A1,A1
		libcall     CreateCxObj 	; (D0=type,A0=arg1,A1=arg2)

		move.l	    D0,_HotKeyFilterCxObj(A4)
		beq	    NoFilterCxObj
		move.l	    D0,A2	   ; Save filter object in A2

;	Check errorcode
		move.l	    A2,A0
		libcall     CxObjError		; (A0=co)

		tst.l	    D0
		beq	    FilterOK

;	the Hotkey was bad => change to default
		lea	    DEFAULTHOTKEY(PC),A0
		lea	    _HotKeyString(A4),A1
1$		move.b	    (A0)+,(A1)+
		bne	    1$

		move.l	    A2,A0
		lea	    DEFAULTHOTKEY(PC),A1
		libcall     SetFilter		; (A0=filter,A1=text)

		bset	    #OPENOPTWINDOW_B0,_CxHandlerData+ssd_Options(A4)

;	Attach filter to the broker
FilterOK:	move.l	    A2,A1
		move.l	    _PopUpBroker(A4),A0
		libcall     AttachCxObj 	; (A0=headObj,A1=co)

;	Create a signal object	(CTRL F means wake up)
		moveq.l     #CX_SIGNAL,D0
		move.l	    A5,A0	  ; A5 = ThisTask
		sub.l	    A1,A1
		move.w	    #SIGBREAKB_CTRL_F,A1
		libcall     CreateCxObj 	; (D0=type,A0=arg1,A1=arg2)

		move.l	    D0,A1
		move.l	    A1,D0
		beq	    NoSignalCxObj

;	Attach it to the filter
		move.l	    A2,A0	; Filter object
		libcall     AttachCxObj 	; (A0=headObj,A1=co)

;	Create a translator object to remove the hotkey event
		moveq.l     #CX_TRANSLATE,D0
		sub.l	    A0,A0
		sub.l	    A1,A1
		libcall     CreateCxObj 	; (D0=type,A0=arg1,A1=arg2)

		move.l	    D0,A1
		move.l	    A1,D0
		beq	    NoTranslatorCxObj

;	Attach it to the filter object
		move.l	    A2,A0
		libcall     AttachCxObj 	; (A0=headObj,A1=co)

; ------------------------------------------------------------------------------
;	Activate the broker
		move.l	    _PopUpBroker(A4),A0
		moveq.l     #TRUE,D0
		libcall     ActivateCxObj	; (A0=co,D0=true)

;	Everything opened OK start the main loop

		call	    PopUpMainLoop

		move.l	    _PopUpBroker(A4),A0
		moveq.l     #FALSE,D0
		libcall     ActivateCxObj	; (A0=co,D0=true)

;	All CXObj:s are removed together with the broker
NoTranslatorCxObj:
NoSignalCxObj:
NoFilterCxObj:
NoCustomCxObj:	move.l	    _DOSBase(A4),A6
		lea	    NotifyData(PC),A0
		move.l	    A0,D1
		libcall     EndNotify		; (D1=notify)

NoFileNotify:	move.l	    _ExecBase(A4),A6
		lea	    _CxHandlerData+ssd_LastSignal(A4),A3
		moveq.l     #-1,D2

NoSignal1:	moveq.l     #0,D0
		move.w	    ssi_Num(A3),D0
		libcall     FreeSignal		; (D0=signalNum)

		addq.w	    #1,D2

NoSignal:	subq.l	    #ssi_SIZEOF,A3
		cmp.w	    #NO_OF_SIGNALS-1,D2
		bne	    NoSignal1

NoSignal2:	move.l	    OldOffMenu(PC),D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOOffMenu,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

NoOffMenuPatch: move.l	    OldOnMenu(PC),D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOOnMenu,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

NoOnMenuPatch:	move.l	    OldClearMenuStrip(PC),D0
		move.l	    _IntuitionBase(A4),A1
		move.w	    #_LVOClearMenuStrip,A0
		libcall     SetFunction 	; (A1=library,A0=funcOffset,D0=newFunction)

NoClearMenuPatch:
		move.l	    _TimerReqBlock(A4),A1
		libcall     CloseDevice 	; (A1=ioRequest)

NoTimerDevice:	move.l	    _TimerReqBlock(A4),A0
		libcall     DeleteIORequest	; (A0=ioRequest)

NoTimerIOStdReq:
		move.l	    _TimerPort(A4),A0
		libcall     DeleteMsgPort	; (A0=port)

NoTimerPort:	move.l	    _ReplyPort(A4),A0
		libcall     DeleteMsgPort	; (A0=port)

NoReplyPort:	move.l	    _LayersBase(A4),A1
		libcall     CloseLibrary	; (A1=library)

NoLayers:	move.l	    _GfxBase(A4),A1
		libcall     CloseLibrary	; (A1=library)

NoGraphics:	move.l	    _IntuitionBase(A4),A1
		libcall     CloseLibrary	; (A1=library)

NoIntuition:	move.l	    _CxBase(A4),A6
		move.l	    _PopUpBroker(A4),A0
		libcall     DeleteCxObjAll	; (A0=co)

NoBroker:	move.l	    _ExecBase(A4),A6
		move.l	    _CxBase(A4),A1
		libcall     CloseLibrary	; (A1=library)

		lea	    BrokerData(PC),A2

NoCommodity:	move.l	    nb_Port(A2),A0
		call	    MyDeletePort	; (A0=port)

NoBrokerPort:	move.l	    _DOSBase(A4),A1
		libcall     CloseLibrary	; (A1=library)

NoDos:		move.l	    _WBenchMsg(A4),D3
		beq	    NoDos1

		libcall     Forbid		; ()

		move.l	    D3,A1
		libcall     ReplyMsg		; (A1=message)

NoDos1: 	lea	    Globals_SIZEOF(SP),SP
		moveq.l     #0,D0
		rts

;*************************
;*  VOID PopUpMainLoop() *
;*************************
QUIT_B		equ	    0
VERIFYOK_B	equ	    1
POPUP_B 	equ	    2
ACTIVEWAITING_B equ	    3
DISAPPEAR_B	equ	    4
APPEAR_B	equ	    5
ENABLE_B	equ	    6
DISABLE_B	equ	    7

QUIT_F		equ	    %00000001
VERIFYOK_F	equ	    %00000010
POPUP_F 	equ	    %00000100
ACTIVEWAITING_F equ	    %00001000
DISAPPEAR_F	equ	    %00010000
APPEAR_F	equ	    %00100000
ENABLE_F	equ	    %01000000
DISABLE_F	equ	    %10000000

VERIFYMSG	equ	    TRUE
MENUUPMSG	equ	    FALSE

		STRUCTURE   MainLocal,0
		UWORD	    loc_TimeOut
		ULONG	    loc_Signals
		ULONG	    loc_BrokerSigMask
		ULONG	    loc_ReplySigMask
		LABEL	    loc_SIZEOF

;* D2 = SignalBits
;* D3 = Magic
;* D4 = TotalMessages
;* D5 = OptWinSig
;* D6 = Flags
;* D7 = NrOfMessages

@PopUpMainLoop: movem.l     D2-D7/A2-A3/A6,-(SP)
		lea	    -loc_SIZEOF(SP),SP

;  NrOfMessages = OptWinSig = TotalMessages = Magic = 0
		moveq.l     #0,D7
		move.l	    D7,D5
		move.l	    D7,D4
		move.l	    D7,D3

;  Flags = Options & OPENOPTWINDOW  [OPENOPTWINDOW == APPEAR_FLAG]
		move.b	    _CxHandlerData+ssd_Options(A4),D6
		and.b	    #OPENOPTWINDOW,D6

;  ReplySigMask = 1 << ReplyPort->mp_SigBit
		moveq.l     #0,D0
		move.l	    _ReplyPort(A4),A0
		moveq.l     #1,D2
		move.b	    MP_SIGBIT(A0),D0
		asl.l	    D0,D2
		move.l	    D2,loc_ReplySigMask(SP)

;  BrokerSigMask = 1 << BrokerData.nb_Port->mp_SigBit
		lea	    BrokerData+nb_Port(PC),A0
		move.l	    (A0),A0
		move.b	    MP_SIGBIT(A0),D0
		moveq.l     #1,D1
		asl.l	    D0,D1
		move.l	    D1,loc_BrokerSigMask(SP)
		or.l	    D1,D2

;  TimerSigMask = 1 << TimerPort->mp_SigBit
		move.l	    _TimerPort(A4),A0
		move.b	    MP_SIGBIT(A0),D0
		moveq.l     #1,D1
		asl.l	    D0,D1
		move.l	    D1,_TimerSigMask(A4)
		or.l	    D1,D2

;  Signals = ReplySigMask | BrokerSigMask | TimerSigMask |
;	     MenuUpSigMask | MenuDownSigMask | NotifySigMask |
;	     SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F
		or.l	    _CxHandlerData+ssd_MenuUpSig+ssi_Mask(A4),D2
		or.l	    _CxHandlerData+ssd_MenuDownSig+ssi_Mask(A4),D2
		or.l	    _CxHandlerData+ssd_NotifySig+ssi_Mask(A4),D2
		or.w	    #SIGBREAKF_CTRL_C!SIGBREAKF_CTRL_F,D2
		move.l	    D2,loc_Signals(SP)

;  TimeOut = GetTimeOutPrefs()
		call	    GetTimeOutPrefs

		move.w	    D0,(SP)     ; loc_TimeOut

;  SignalBits = Wait(Signals | OptWinSig)
WaitEvent:	move.l	    _ExecBase(A4),A6
		move.l	    loc_Signals(SP),D0
		or.l	    D5,D0
		libcall     Wait	; (d0=signalSet)

		move.l	    D0,D2

;   SignalBits & MenuUpSigMask ?
MenuUpEvent:	and.l	    _CxHandlerData+ssd_MenuUpSig+ssi_Mask(A4),D0
		beq	    MenuDownEvent

;  Flags & POPUP_FLAG ?   [No preparation is done]
		btst	    #POPUP_B,D6
		beq	    ReplyEvent

;  NrOfMessages = 0  [forget messages sent]
		moveq.l     #0,D7

;  Magic += 1	     [stop counting them]
		addq.l	    #1,D3

;  TotalMessages += SendMessage(MENUUPMSG,0)  [Send cancel messages]
		moveq.l     #0,D0
		moveq.l     #0,D1
		call	    SendMessages

		add.w	    D0,D4

;  Flags &= (QUIT_FLAG | DISABLE_FLAG)       Clear all Flags
		and.b	    #QUIT_F!DISABLE_F,D6

;  AbortTimer()   Prepare for a new MENU_DOWN
		call	    AbortTimer

		bra	    ReplyEvent

;  SignalBits & MenuDownSigMask ?
MenuDownEvent:	move.l	    D2,D0
		and.l	    _CxHandlerData+ssd_MenuDownSig+ssi_Mask(A4),D0
		beq	    ReplyEvent

;  Lock = LockIBase(0)
		move.l	    _IntuitionBase(A4),A6
		moveq.l     #0,D0
		libcall     LockIBase	    ; (d0=dontknow)

		move.l	    D0,A2

;  ActiveWindow = IntuitionBase->ActiveWindow
		move.l	    ib_ActiveWindow(A6),A3
		move.l	    A3,_ActiveWindow(A4)

		move.l	    A3,D0
		beq	    2$

;  Screen = ActiveWindow->WScreen
		move.l	    wd_WScreen(A3),_Screen(A4)

;  Send messages to every window with MENUVERIFY set
;  TotalMessages += NrOfMessages = SendMessage(VERIFYMSG,Magic)
		moveq.l     #VERIFYMSG,D0
		move.l	    D3,D1
		call	    SendMessages

		add.w	    D0,D4
		move.l	    D0,D7

;  NrOfMessages > 0 ?	  if messages were sent start a timer
		beq	    1$

;  QueTimer(TimeOut)
		move.w	    (SP),D0      ; loc_TimeOut
		call	    QueTimer

;  ActiveWindow->IDCMPFlags & IDCMP_MENUVERIFY
		btst	    #IDCMP_MENUVERIFY_B2,wd_IDCMPFlags+2(A3)
		beq	    1$

;  Flags |= ACTIVEWAITING_FLAG
		bset	    #ACTIVEWAITING_B,D6

;  Flags |= POPUP_FLAG | VERIFYOK_FLAG	     Pop-up the menus ASAP
1$		or.b	    #POPUP_F!VERIFYOK_F,D6

;  UnlockIBase(Lock)
2$		move.l	    A2,A0
		libcall     UnlockIBase     ; (a0=iblock)

		move.l	    _ExecBase(A4),A6
;  /*-----------------------------------------------------------------------------*/
;  SignalBits & ReplySigMask
ReplyEvent:	move.l	    D2,D0
		and.l	    loc_ReplySigMask(SP),D0
		beq	    TimerEvent

;  Message = GetMsg(ReplyPort)
MoreReplies	move.l	    _ReplyPort(A4),A0
		libcall     GetMsg	; (A0=port)

		move.l	    D0,A1
		move.l	    A1,D0
		beq	    TimerEvent

;  MENUVERIFY message ?
		btst	    #IDCMP_MENUVERIFY_B2,im_Class+2(A1)
		beq	    2$

;  Message->mmn_Session == Magic  ?   [ is it an old message ]
		cmp.l	    mmn_Session(A1),D3
		bne	    2$

;  The active window may cancel the menu operation
;  Message->IDCMPWindow == ActiveWindow ?
		move.l	    im_IDCMPWindow(A1),A0
		cmp.l	    _ActiveWindow(A4),A0
		bne	    1$

;  Flags &= ~ACTIVEWAITING_FLAG  [active window has replied]
		bclr	    #ACTIVEWAITING_B,D6

;  Message->Code == MENUCANCEL
		cmp.w	    #MENUCANCEL,im_Code(A1)
		bne	    1$

;  Flags &= ~VERIFYOK_FLAG  [ do not pop-up the menus ]
		bclr	    #VERIFYOK_B,D6

;  NrOfMessages -= 1
1$		subq.w	    #1,D7

;  if it was not MENUVERIFY then it must be MOUSEBUTTONS message
;  FreeMem(Message,sizeof(struct MyMsg))
2$		moveq.l     #mmn_SIZEOF,D0
		libcall     FreeMem	; (A1=memoryBlock,D0=byteSize)

;  TotalMessages -= 1
		subq.w	    #1,D4

		bra	    MoreReplies

;  /*-----------------------------------------------------------------------------*/
;  SignalBits & TimerSigMask ?
TimerEvent:	move.l	    D2,D0
		and.l	    _TimerSigMask(A4),D0
		beq	    AllReplied

;  GetMsg(TimerPort)  Get rid of the message
		move.l	    _TimerPort(A4),A0
		libcall     GetMsg	    ; (A0=port)

		tst.l	    D0
		beq	    AllReplied

;  did the active window reply before timeout ?
;  Flags & ACTIVEWAITING_FLAG ?
		btst	    #ACTIVEWAITING_B,D6
		beq	    1$

;  Flags &= ~VERIFYOK_FLAG  [ cancel menu operation ]
		bclr	    #VERIFYOK_B,D6

;  NrOfMessages = 0	  forget messages sent
1$		moveq.l     #0,D7

;  Magic += 1	       don't count them
		addq.l	    #1,D3

;  /*-----------------------------------------------------------------------------*/
;  ready to pop-up the menus ?
;  NrOfMessages == 0 AND Flags & (POPUP_FLAG | VERIFYOK_FLAG) == (POPUP_FLAG | VERIFYOK_FLAG)) {
AllReplied:	tst.w	    D7
		bne	    BrokerMessage
		move.b	    D6,D0
		and.b	    #POPUP_F!VERIFYOK_F,D0
		subq.b	    #POPUP_F!VERIFYOK_F,D0
		bne	    BrokerMessage

;  PopUpMenu()
		call	    PopUpMenu

		bclr	    #VERIFYOK_B,D6
		tst.w	    D0		    ; MENUUP Handled ?
		beq	    BrokerMessage   ; No

;  TotalMessages += SendMessage(MENUUPMSG,0) [PopUpMenu ended with MENUUP]
		moveq.l     #MENUUPMSG,D0
		moveq.l     #0,D1
		call	    SendMessages

		add.w	    D0,D4

;  Flags &= (QUIT_FLAG | DISABLE_FLAG)
		and.b	    #QUIT_F!DISABLE_F,D6

;  /*-----------------------------------------------------------------------------*/
;  SignalBits & BrokerSigMask ?
BrokerMessage:	move.l	    D2,D0
		and.l	    loc_BrokerSigMask(SP),D0
		beq	    CTRLCEvent

;  Message = GetMsg(BrokerData.nb_Port)
MoreBrokerMsg:	lea	    BrokerData+nb_Port(PC),A0
		move.l	    (A0),A0
		libcall     GetMsg	; (A0=port)

		move.l	    D0,A2
		move.l	    A2,D0
		beq	    CTRLCEvent

;  CxMsgType(Message) == CXM_COMMAND [ should be the only possible message ]
		move.l	    _CxBase(A4),A6
		move.l	    A2,A0
		libcall     CxMsgType

		moveq.l     #CXM_COMMAND,D1
		cmp.l	    D0,D1
		bne	    ReplyBroker

;  Set flags according to command sent
		move.l	    A2,A0
		libcall     CxMsgID

		lea	    CXCMDCOMMANDS(PC),A0
		moveq.l     #NoOfCommands-1,D1
1$		cmp.b	    (A0),D0
		bne	    2$
		or.b	    1(A0),D6
		bra	    ReplyBroker

2$		addq.l	    #2,A0
		dbra	    D1,1$

;  ReplyMsg(Message);
ReplyBroker:	move.l	    _ExecBase(A4),A6
		move.l	    A2,A1
		libcall     ReplyMsg	; (A1=message)

		bra	    MoreBrokerMsg

;  /*-----------------------------------------------------------------------------*/
;  SignalBits & SIGBREAKF_CTRL_C ?
CTRLCEvent:	btst	    #SIGBREAKB_CTRL_C,D2
		beq	    OptWinEvent

;  Flags |= (QUIT_FLAG | DISAPPEAR_FLAG | DISABLE_FLAG)
		or.b	    #QUIT_F!DISAPPEAR_F!DISABLE_F,D6

;  /*-----------------------------------------------------------------------------*/
;  SignalBits & OptWinSig ?
OptWinEvent:	move.l	    D2,D0
		and.l	    D5,D0
		beq	    CTRLFEvent

;  HandleOptWindow()
		call	    HandleOptWindow

		tst.w	    D0

;  No change
		beq	    CTRLFEvent
		bpl	    1$

;  User wants to quit
;  Flags |= (QUIT_FLAG | DISAPPEAR_FLAG | DISABLE_FLAG)
		or.b	    #QUIT_F!DISABLE_F,D6

;  User wants to close the window
;  Flags |= DISAPPEAR_FLAG
1$		bset	    #DISAPPEAR_B,D6

;  /*---------------------------------------------------------------------------*/
;  SignalBits & SIGBREAKF_CTRL_F
CTRLFEvent:	btst	    #SIGBREAKB_CTRL_F,D2
		beq	    NotifyEvent

;  Flags |= (APPEAR_FLAG | ENABLE_FLAG)
		or.b	    #APPEAR_F!ENABLE_F,D6

;  /*-----------------------------------------------------------------------------*/
;  SignalBits & NotifySigMask
NotifyEvent:	move.l	    D2,D0
		and.l	    _CxHandlerData+ssd_NotifySig+ssi_Mask(A4),D0
		beq	    CheckFlags

;  TimeOut = GetTimeOutPrefs()
		call	    GetTimeOutPrefs

		move.w	    D0,(SP)     loc_TimeOut

;  /*-----------------------------------------------------------------------------*/
;  if (Flags & DISAPPEAR_FLAG)
CheckFlags:	btst	    #DISAPPEAR_B,D6
		beq	    1$

;  window open ?
		tst.l	    D5
		beq	    1$

;  CloseOptWindow()
		call	    CloseOptWindow

;  OptWinSig = 0
		moveq.l     #0,D5

;  Handle the different flags
;  Flags & APPEAR_FLAG	 [ Open window or bring it to front ]
1$		btst	    #APPEAR_B,D6
		beq	    2$

;  OptWinSig = OpenOptWindow(OptWinSig)
		move.l	    D5,D0
		call	    OpenOptWindow

		move.l	    D0,D5

;  Flags & ENABLE_FLAG	[ Enable the broker ]
2$		btst	    #ENABLE_B,D6
		beq	    3$

;  ActivateCxObj(PopUpBroker,TRUE)
		move.l	    _CxBase(A4),A6
		move.l	    _PopUpBroker(A4),A0
		moveq.l     #TRUE,D0
		libcall     ActivateCxObj

;  Flags &= ~QUIT_FLAG;
		bclr	    #QUIT_F,D6

;  Flags & DISABLE_FLAG   [ disable the broker ]
3$		btst	    #DISABLE_B,D6
		beq	    4$

;  Flags & POPUP_FLAG == 0   [ can't disable if we are waiting to popup ]
		btst	    #POPUP_B,D6
		bne	    4$

;  ActivateCxObj((struct CxObj *)PopUpBroker,FALSE)
		move.l	    _CxBase(A4),A6
		move.l	    _PopUpBroker(A4),A0
		moveq.l     #FALSE,D0
		libcall     ActivateCxObj

;  Flags &= ~DISABLE_FLAG
		bclr	    #DISABLE_B,D6

;  We can't quit if some windows have not replied yet
;  TotalMessages == 0 AND Flags & QUIT_FLAG AND Flags & DISABLE_FLAG == 0
4$		tst.w	    D4
		bne	    5$
		btst	    #QUIT_B,D6
		beq	    5$
		btst	    #DISABLE_B,D6
		beq	    MainLoopDone

;  These flags do not survive multiple events
;  Flags &= ~(DISAPPEAR_FLAG | APPEAR_FLAG | ENABLE_FLAG)
5$		and.b	    #~(DISAPPEAR_F!APPEAR_F|ENABLE_F),D6
		bra	    WaitEvent

MainLoopDone:	lea	    loc_SIZEOF(SP),SP
		movem.l     (SP)+,D2-D7/A2-A3/A6
		rts

;****************************************************
;* UWORD SendMessages(UWORD Kind, ULONG MagicCode)  *
;*						    *
;* Input:					    *
;*   Kind	MENUVERIFY or MOUSEBUTTONS messages *
;*   MagicCode	Session number			    *
;* Output:					    *
;*   return	Messages sent			    *
;****************************************************
@SendMessages:	movem.l     D2-D4/A2-A3/A6,-(SP)
		move.l	    D0,D2
		move.l	    D1,D3

;  Forbid while we are moving through the list.
;  don't know if LockIBase supports multiple locks from same task.
		move.l	    _ExecBase(A4),A6
		libcall     Forbid	; ()

;  NrOfMessages = 0
		moveq.l     #0,D4

;  Window = Screen->FirstWindow
		move.l	    _Screen(A4),A0
		move.l	    sc_FirstWindow(A0),A3
		bra	    CheckWindow

;  Window->IDCMPFlags & IDCMP_MENUVERIFY
NextWindow:	btst	    #IDCMP_MENUVERIFY_B2,wd_IDCMPFlags+2(A3)
		beq	    NoMenuVerify

;  Message = AllocMem(sizeof(struct MyMsg),MEMF_PUBLIC|MEMF_CLEAR)
		moveq.l     #mmn_SIZEOF,D0
		move.l	    #MEMF_PUBLIC!MEMF_CLEAR,D1
		libcall     AllocMem

		move.l	    D0,A2
		tst.l	    D0
		beq	    NoMemory

;  Message->mmn_IntuiMessage.ExecMessage.mn_Node.ln_Type = NT_MESSAGE
		move.b	    #NT_MESSAGE,im_ExecMessage+LN_TYPE(A2)

;  Message->mmn_IntuiMessage.ExecMessage.mn_ReplyPort = ReplyPort
		move.l	    _ReplyPort(A4),im_ExecMessage+MN_REPLYPORT(A2)

;  Message->mmn_IntuiMessage.ExecMessage.mn_Length = sizeof(struct IntuiMessage)
		move.w	    #im_SIZEOF,im_ExecMessage+MN_LENGTH(A2)

;  Kind == VERIFYMSG
		tst.w	    D2
		beq	    1$

;  Message->mmn_IntuiMessage.Class = IDCMP_MENUVERIFY
		moveq.l     #0,D0
		bset	    #IDCMP_MENUVERIFY_B2+8,D0

;  the active window should have a MENUHOT code all others MENUWAITING
		moveq.l     #MENUWAITING,D1
		cmp.l	    _ActiveWindow(A4),A3
		bne	    2$

		moveq.l     #MENUHOT,D1
		bra	    2$

;  Message->mmn_IntuiMessage.Class = IDCMP_MOUSEBUTTONS
1$		moveq.l     #IDCMP_MOUSEBUTTONS,D0

;  Message->mmn_IntuiMessage.Code = MENUUP
		move.w	    #MENUUP,D1		  ; MENUUP

2$		move.l	    D0,im_Class(A2)
		move.w	    D1,im_Code(A2)

;  Message->mmn_IntuiMessage.Qualifier = CxHandlerData.ssd_EndQualifier
		move.w	    _CxHandlerData+ssd_EndQualifier(A4),im_Qualifier(A2)

;  Message->mmn_IntuiMessage.IDCMPWindow = Window
		move.l	    A3,im_IDCMPWindow(A2)

;  CurrentTime(&Message->mmn_IntuiMessage.Seconds, &Message->mmn_IntuiMessage.Micros)
		lea	    im_Seconds(A2),A0
		lea	    im_Micros(A2),A1
		move.l	    _IntuitionBase(A4),A6
		libcall     CurrentTime

;  Dont set mouse position if window has DELTAMOVE
		btst	    #IDCMP_DELTAMOVE_B1,wd_IDCMPFlags+1(A3)
		bne	    3$

;  Message->mmn_IntuiMessage.MouseX = Window->MouseX
;  Message->mmn_IntuiMessage.MouseY = Window->MouseY
		move.w	    wd_MouseX(A3),im_MouseX(A2)
		move.w	    wd_MouseY(A3),im_MouseY(A2)

;  Message->mmn_Session = MagicCode
3$		move.l	    D3,mmn_Session(A2)

;  PutMsg(Window->UserPort, Message)
		move.l	    _ExecBase(A4),A6
		move.l	    wd_UserPort(A3),A0
		move.l	    A2,A1
		libcall     PutMsg

;  NrOfMessages += 1
		addq.w	    #1,D4

;  Window = Window->NextWindow
NoMemory:
NoMenuVerify:	move.l	    wd_NextWindow(A3),A3

CheckWindow:	move.l	    A3,D0
		bne	    NextWindow

NoMoreWindows:	libcall     Permit	; ()

		move.l	    D4,D0
		movem.l     (SP)+,D2-D4/A2-A3/A6
		rts

;***********************************************************
;* GetTimeOutPrefs()  - read timeout value from prefs file *
;***********************************************************
; We do only need to read up to the TimeOut field
TimeOutBytes	equ	    ic_TimeOut+2

@GetTimeOutPrefs:
		movem.l     D2/D3/A2/A3/A6,-(SP)

;   TimeOut = DEFAULT_TIMEOUT
		moveq.l     #DEFAULT_TIMEOUT,D3

;   IFFParseBase = OpenLibrary("iffparse.library",KICK204)
		move.l	    _ExecBase(A4),A6
		lea	    IFFNAME(PC),A1
		moveq.l     #KICK204,D0
		libcall     OpenLibrary

		tst.l	    D0
		beq	    NoIFFLib

		move.l	    D0,A2

;   IFFHandle = AllocIFF()
		move.l	    A2,A6
		libcall     AllocIFF

		tst.l	    D0
		beq	    NoIFFHandle

		move.l	    D0,A3

;   IFFHandle->iff_Stream = Open("ENV:sys/icontrol.prefs",MODE_OLDFILE))
		move.l	    _DOSBase(A4),A6
		lea	    ICNTRLFILENAME(PC),A0
		move.l	    A0,D1
		move.l	    #MODE_OLDFILE,D2
		libcall     Open

		move.l	    D0,iff_Stream(A3)
		beq	    NoStream

;   InitIFFasDOS(IFFHandle)
		move.l	    A2,A6
		move.l	    A3,A0
		libcall     InitIFFasDOS

;   OpenIFF(IFFHandle,IFFF_READ)
		move.l	    A3,A0
		moveq.l     #IFFF_READ,D0
		libcall     OpenIFF

		tst.l	    D0
		bne	    NoOpenIFF

;   StopChunk(IFFHandle,ID_PREF,ID_ICTL);
		move.l	    A3,A0
		move.l	    #'PREF',D0
		move.l	    #'ICTL',D1
		libcall     StopChunk

;   ParseIFF(IFFHandle,IFFPARSE_SCAN)
ParseAgain:	move.l	    A3,A0
		moveq.l     #IFFPARSE_SCAN,D0
		libcall     ParseIFF

		tst.l	    D0
		beq	    ParseOK

		addq.l	    #-IFFERR_EOC,D0
		beq	    ParseAgain

		bra	    ParseError

;   ReadChunkBytes(IFFHandle, &ICP, 0x12)
ParseOK:	lea	    -TimeOutBytes(SP),SP
		move.l	    A3,A0
		move.l	    SP,A1
		moveq.l     #TimeOutBytes,D0
		libcall     ReadChunkBytes

		cmp.w	    #TimeOutBytes,D0
		bne	    ReadError

		move.w	    ic_TimeOut(SP),D3

ReadError:	lea	    TimeOutBytes(SP),SP

;   CloseIFF(IFFHandle)
ParseError:	move.l	    A3,A0
		libcall     CloseIFF

;   Close(IFFHandle->iff_Stream)
NoOpenIFF	move.l	    _DOSBase(A4),A6
		move.l	    iff_Stream(A3),D1
		libcall     Close

;   FreeIFF(IFFHandle)
NoStream:	move.l	    A2,A6
		move.l	    A3,A0
		libcall     FreeIFF

;   CloseLibrary(IFFParseBase)
NoIFFHandle:	move.l	    _ExecBase(A4),A6
		move.l	    A2,A1
		libcall     CloseLibrary

;   return TimeOut
NoIFFLib:	move.l	    D3,D0

		movem.l     (SP)+,D2/D3/A2/A3/A6
		rts

;************************************
;* VOID PopUpHandler(CxMsg,CxObj)   *
;*				    *
;************************************
@PopUpHandler:	movem.l     D2/A2-A4/A6,-(SP)
		move.l	    A0,A2
		move.l	    CxBase,A6	; can't use local here

;   Get the data from the CxMsg
		libcall     CxMsgData	; (A0=cxm)

		move.l	    D0,A3	; A3 = InputEvent
		move.l	    A2,A0
		libcall     CxMsgID	; (A0=cxm)

		move.l	    D0,A4	; A4 = InputData

		move.l	    (AbsExecBase).w,A6

;   Move the flags to a register for speed
		move.b	    ssd_Flags(A4),D2

;   Are the menus pop-up'ed now ?
		btst	    #MENUS_ON_B,D2
		beq	    NotOn

;   Tell the PopUpMenu task that the input.device is alive
		move.l	    ssd_PopUpMenuTask(A4),A1
		move.l	    ssd_MouseMovedSig+ssi_Mask(A4),D0
		libcall     Signal		; (A1=task,D0=signalSet)

;   When the menus are displayed only RAWMOUSE events passes
		moveq.l     #IECLASS_RAWMOUSE,D0
		cmp.b	    ie_Class(A3),D0
		bne	    RemoveEvent

;   Move the code to a register for speed
		move.w	    ie_Code(A3),D1

;   Selectbutton pressed ?
		cmpi.w	    #SELECTDOWN,D1
		bne	    CheckSelUp		; No

		bset	    #S_DOWN_B,D2
		move.l	    ssd_SelectDownSig+ssi_Mask(A4),D0
		bra	    SigAndRemove	; dont care about qualifiers

;   Selectbutton released ?
CheckSelUp:	cmpi.w	    #SELECTUP,D1
		bne	    CheckMenuUp 	; No

		bclr	    #S_DOWN_B,D2
		move.l	    ssd_SelectUpSig+ssi_Mask(A4),D0
		bra	    SigAndRemoveQ	; qualifiers needed for clickmenus

;   Menu-button released ?
CheckMenuUp:	cmpi.w	    #MENUUP,D1
		bne	    CheckMenuDown	; No

		bclr	    #M_DOWN_B,D2

;   Menu operation stops only if CLICKON is set
		btst	    #CLICKON_B,D2
		beq	    RemoveEvent

		bclr	    #CLICKON_B,D2
		bclr	    #MENUS_ON_B,D2
		move.l	    ssd_MenuUpSig+ssi_Mask(A4),D0
		bra	    SigAndRemoveQ	; qualifiers needed

;   Menu-button pressed ?
CheckMenuDown:	cmpi.w	    #MENUDOWN,D1
		bne	    KeepEvent		; No

		bset	    #M_DOWN_B,D2
		bset	    #CLICKON_B,D2
		bra	    RemoveEvent

;   Menus are not pop-up'ed
;
NotOn:		moveq.l     #IECLASS_RAWMOUSE,D0
		cmp.b	    ie_Class(A3),D0
		bne	    KeepEvent

;   Move code to register for speed
		move.w	    ie_Code(A3),D1

;   SelectButton released ?  We only care if it was down when
;   the menuoperation was finished.
		cmpi.w	    #SELECTUP,D1
		bne	    1$

		btst	    #S_DOWN_B,D2
		beq	    KeepEvent

		bclr	    #S_DOWN_B,D2
		bra	    RemoveEvent

;   Menu-button released ?
1$		cmpi.w	    #MENUUP,D1
		bne	    2$

		btst	    #M_DOWN_B,D2
		beq	    KeepEvent

		bclr	    #M_DOWN_B,D2
		bra	    RemoveEvent

;   Menu-button pressed ?
2$		cmpi.w	    #MENUDOWN,D1
		bne	    KeepEvent		; No

;   No menus if any other mousebutton is pressed
MenuPressed:	move.w	    ie_Qualifier(A3),D1
		move.w	    #IEQUALIFIER_MIDBUTTON+IEQUALIFIER_LEFTBUTTON,D0
		and.w	    D1,D0
		bne	    KeepEvent

;   Are any other qalifiers pressed ?
		move.w	    #QUALIFIERS,D0
		and.w	    D1,D0
		beq	    1$			; No

;   Should we pop-up the menus with qualifier ?
		btst	    #POPUPWITHQUAL_B0,ssd_Options(A4)
		beq	    KeepEvent		; No
		bra	    QualifierOk

;   Should we pop-up the menus without qualifiers ?
1$		btst	    #POPUPNOQUAL_B0,ssd_Options(A4)
		beq	    KeepEvent		; No

;   Menu-button pressed and we should pop-up the menus.
;   Do we have an active screen to put the menus on ?
QualifierOk:	move.l	    IBase,A1
		move.l	    ib_ActiveScreen(A1),A0
		move.l	    A0,D0
		beq	    KeepEvent		; No

;   Is the mouse in the titlebar ? [if so, use standard menus]
		move.b	    sc_BarHeight(A0),D0
		ext.w	    D0
		cmp.w	    sc_MouseY(A0),D0
		bgt	    KeepEvent		; Yes

;   Do we have an active window on the screen ?
		move.l	    ib_ActiveWindow(A1),A0
		move.l	    A0,D0
		beq	    KeepEvent		; No

;   Is a requester blocking the window ?
;   (RKM says we shouldn't trust the ReqCount field, but what to do ?)
		tst.w	    wd_ReqCount(A0)
		bne	    KeepEvent		; Yes

;   Does the window have menus ?
		tst.l	    wd_MenuStrip(A0)
		beq	    KeepEvent		; No

;   Is the RMBTRAP flag set ?
		btst	    #WFLG_RMBTRAP_B1,wd_Flags+1(A0)
		bne	    KeepEvent		; Yes

;   Everything is OK, set flags
		bset	    #MENUS_ON_B,D2
		bset	    #M_DOWN_B,D2

;   If we are using clickmenus, menu-button must be relased twice
		btst	    #CLICKMENUS_B0,ssd_Options(A4)
		bne	    1$

;   Otherwise once is enough
		bset	    #CLICKON_B,D2

;   Tell the popupmenu task to popup the menus.
1$		move.l	    ssd_MenuDownSig+ssi_Mask(A4),D0

;   Save the qualifiers pressed now
SigAndRemoveQ:	move.w	    ie_Qualifier(A3),ssd_EndQualifier(A4)

;   Signal to the PopUpMenu task
SigAndRemove:	move.l	    ssd_PopUpMenuTask(A4),A1
		libcall     Signal		; (A1=task,D0=signalSet)

;   Remove the event from the input stream
RemoveEvent:	move.l	    CxBase,A6
		move.l	    A2,A0
		libcall     DisposeCxMsg	; (A0=cxm)

KeepEvent:	move.b	    D2,ssd_Flags(A4)

		movem.l     (SP)+,D2/A2-A4/A6
		rts

;********************************************
;* MyClearMenuStrip,			    *
;* MyOnMenu, MyOffMenu			    *
;*					    *
;* My replacements for intuition functions. *
;********************************************
@MyClearMenuStrip:
		lea	    OldClearMenuStrip(PC),A1
		bra	    CallOldFunction

@MyOnMenu:	lea	    OldOnMenu(PC),A1
		bra	    CallOldFunction

@MyOffMenu:	lea	    OldOffMenu(PC),A1

;    Obtain our semaphore and then call the intuition function.
CallOldFunction:
		move.l	    A6,-(SP)
		movem.l     D0/A0-A1/A6,-(SP)
		move.l	    (AbsExecBase).w,A6

;    We use shared access here so multiple tasks can use it
		lea	    PopUpSemaphore(PC),A0
		libcall     ObtainSemaphoreShared ; (A0=sigSem)

		movem.l     (SP)+,D0/A0-A1/A6
		move.l	    (A1),A1
		jsr	    (A1)
		move.l	    (AbsExecBase).w,A6

		lea	    PopUpSemaphore(PC),A0
		libcall     ReleaseSemaphore	 ; (A0=sigSem)

		move.l	    (SP)+,A6
		rts

;************************************************
;* VOID QueTimer(UWORD Length) - Start a timer  *
;*						*
;* Input:					*
;*   Length  - Length before timer in VBLANKS	*
;* Output:					*
;*   none					*
;************************************************
@QueTimer:	move.l	    A6,-(SP)
		move.l	    _TimerReqBlock(A4),A1

;   TimerReqBlock->tr_node.io_Command = TR_ADDREQUEST
		move.w	    #TR_ADDREQUEST,IO_COMMAND(A1)

;   TimerReqBlock->tr_time.tv_secs = 0;
		clr.l	    IOTV_TIME+TV_SECS(A1)

;   TimerReqBlock->tr_time.tv_micro = Length*20000    [20000 micros == 1 VBLANK]
		mulu.w	    #20000,D0
		move.l	    D0,IOTV_TIME+TV_MICRO(A1)

;   SendIO(TimerReqBlock);
		move.l	    _ExecBase(A4),A6
		libcall     SendIO	; (A1=ioRequest)

		move.l	    (SP)+,A6
		rts

;**************************
;* VOID AbortTimer(VOID)  *
;**************************
@AbortTimer:	move.l	    A2,-(SP)
		move.l	    A6,-(SP)
		move.l	    _ExecBase(A4),A6
		move.l	    _TimerReqBlock(A4),A2

;   Any timer going on ?     [ CheckIO(TimerReqBlock) ]
		move.l	    A2,A1
		libcall     CheckIO

		tst.l	    D0
		bne	    NoTimerRunning

;   Abort the timer   [ AbortIO(TimerReqBlock) ]
		move.l	    A2,A1
		libcall     AbortIO

;   Wait for abort message  [ WaitIO(TimerReqBlock) ]
		move.l	    A2,A1
		libcall     WaitIO

;   Remove timersignal	 [ SetSignal(0,TimerSigMask) ]
		moveq.l     #0,D0
		move.l	    _TimerSigMask(A4),D1
		libcall     SetSignal	    ; (D0=newSignals,D1=signalMask)

NoTimerRunning: move.l	    (SP)+,A6
		move.l	    (SP)+,A2
		rts

;************************************************************
;* UBYTE ParseArgs(VOID)   get user arguments both CLI & WB *
;*							    *
;* Input						    *
;*   none						    *
;* Output						    *
;*   return    Options					    *
;*   D1        Broker priority				    *
;************************************************************
		STRUCTURE   Args,0
		ULONG	    arg_ClickMenus
		ULONG	    arg_ShowSingle
		ULONG	    arg_CenterItems
		ULONG	    arg_PopWithQual
		ULONG	    arg_PopUp
		APTR	    arg_PopKey
		LONG	    arg_Pri
		LABEL	    arg_SIZEOF

@ParseArgs:	movem.l     D2-D5/A2-A3/A6,-(SP)

;    Workbench or cli arguments ?
		lea	    DefaultArgs(PC),A2
		tst.l	    _WBenchMsg(A4)
		bne	    GetWBArgs

;    Rda = ReadArgs(Template,&DefaultArgs,NULL)
GetCLIArgs:	move.l	    _DOSBase(A4),A6
		lea	    TEMPLATETEXT(PC),A0
		move.l	    A0,D1
		move.l	    A2,D2
		moveq.l     #0,D3
		libcall     ReadArgs

		move.l	    D0,D2

;   IconBase = OldCD = DiskObj = 0
;[Not needed]	moveq.l     #0,D3
		moveq.l     #0,D4
		moveq.l     #0,D5
		bra	    GetArgDone

;   Open icon library, any version will do
GetWBArgs:	move.l	    _ExecBase(A4),A6
		lea	    ICONNAME(PC),A1
		moveq.l     #0,D0
		libcall     OpenLibrary 	; (A1=libName,D0=version)

		move.l	    D0,D3
		beq	    GetArgDone

;    OldCD = CurrentDir(WBenchMsg->sm_ArgList->wa_Lock)
		move.l	    _DOSBase(A4),A6
		move.l	    _WBenchMsg(A4),A3
		move.l	    sm_ArgList(A3),A3
		move.l	    wa_Lock(A3),D1
		libcall     CurrentDir		; (D1=lock)

		move.l	    D0,D4

;    DiskObj = GetDiskObject(WBenchMsg->sm_ArgList->wa_Name)
		move.l	    D3,A6	    ; IconBase
		move.l	    wa_Name(A3),A0
		libcall     GetDiskObject	; (a0=name)

		move.l	    D0,D5
		beq	    GetArgDone

;    ToolTypes = Dobj->do_ToolTypes
		move.l	    D0,A0
		move.l	    do_ToolTypes(A0),A3

;  D2 = Rda
;  D3 = IconBase     A2 = DefaultArgs
;  D4 = OldCD	     A3 = ToolTypes
;  D5 = DiskObject   A6 = IconBase

;  DefaultArgs.ClickMenus = FindToolType(ToolTypes,"CLICKMENUS")
		move.l	    A3,A0
		lea	    ARG_CLICK(PC),A1
		libcall     FindToolType

		move.l	    D0,arg_ClickMenus(A2)

;  DefaultArgs.ShowSingle = FindToolType(ToolTypes,"SHOWSINGLE")
		move.l	    A3,A0
		lea	    ARG_SHOW(PC),A1
		libcall     FindToolType

		move.l	    D0,arg_ShowSingle(A2)

;   DefaultArgs.CenterItems = FindToolType(ToolTypes,"CENTERITEMS")
		move.l	    A3,A0
		lea	    ARG_CENTER(PC),A1
		libcall     FindToolType

		move.l	    D0,arg_CenterItems(A2)

;   DefaultArgs.PopWithQual = FindToolType(ToolTypes,"POPWITHQUAL")
		move.l	    A3,A0
		lea	    ARG_POPWITH(PC),A1
		libcall     FindToolType

		move.l	    D0,arg_PopWithQual(A2)

;   Value = FindToolType(ToolTypes,"CX_POPUP")
		move.l	    A3,A0
		lea	    ARG_CXPOPUP(PC),A1
		libcall     FindToolType

		tst.l	    D0
		beq	    1$

;   DefaultArgs.PopUp = MatchToolValue(Value,"YES")
		move.l	    D0,A0
		lea	    YESTEXT(PC),A1
		libcall     MatchToolValue

		move.l	    D0,arg_PopUp(A2)

;   Value = FindToolType(ToolTypes,"CX_POPKEY")
1$		move.l	    A3,A0
		lea	    ARG_CXPOPKEY(PC),A1
		libcall     FindToolType

		tst.l	    D0
		beq	    2$

;    DefaultArgs.PopKey = Value
		move.l	    D0,arg_PopKey(A2)

;    Value = FindToolType(ToolTypes,"CX_PRIORITY")
2$		move.l	    A3,A0
		lea	    ARG_CXPRI(PC),A1
		libcall     FindToolType

		move.l	    D0,D1
		beq	    3$

;    StrToLong(Value,DefaultArgs.Pri);
		move.l	    _DOSBase(A4),A6
		lea	    arg_Pri(A2),A0
		move.l	    A0,D2
		libcall     StrToLong

		move.l	    D3,A6	    ; restore IconBase

;   Rda = 0
3$		moveq.l     #0,D2

GetArgDone:	moveq.l     #POPUPNOQUAL,D0
		tst.l	    (A2)+
		beq	    1$
		bset	    #CLICKMENUS_B0,D0
1$		tst.l	    (A2)+
		beq	    2$
		bset	    #SHOWSINGLEMENU_B0,D0
2$		tst.l	    (A2)+
		beq	    3$
		bset	    #ITEMSCENTERED_B0,D0
3$		tst.l	    (A2)+
		beq	    4$
		bset	    #POPUPWITHQUAL_B0,D0
4$		tst.l	    (A2)+
		beq	    5$
		bset	    #OPENOPTWINDOW_B0,D0
5$		move.l	    (A2)+,A0
		lea	    _HotKeyString(A4),A1
6$		move.b	    (A0)+,(A1)+
		bne	    6$
		move.l	    (A2),A2         ; CX_PRIORITY

		exg.l	    D0,D5

;  if (DiskObj) FreeDiskObject(DiskObj)
		tst.l	    D0
		beq	    RestoreCD

		move.l	    D0,A0
		libcall     FreeDiskObject

;  if (OldCD)  CurrentDir(OldCD)
RestoreCD:	move.l	    _DOSBase(A4),A6
		move.l	    D4,D1
		beq	    FreeArg

		libcall     CurrentDir	     ; (D1=lock)

;  if (Rda) FreeArgs(Rda)
FreeArg:	move.l	    D2,D1
		beq	    CloseLib

		libcall     FreeArgs

;  if (IconBase)  CloseLibrary(IconBase)
CloseLib:	tst.l	    D3
		beq	    1$

		move.l	    _ExecBase(A4),A6
		move.l	    D3,A1
		libcall     CloseLibrary     ; (A1=library)

1$		move.l	    D5,D0	     ; Options
		move.l	    (A2),D1          ; Priority
		movem.l     (SP)+,D2-D5/A2-A3/A6
		rts

;***********************************************************************
;* VOID MyDeletePort(Port) -  Reply to all pending messages and delete *
;*								       *
;* Input:							       *
;*   Port  - the port to delete 				       *
;***********************************************************************
@MyDeletePort:	move.l	    A2,-(SP)
		move.l	    A6,-(SP)
		move.l	    A0,A2
		move.l	    _ExecBase(A4),A6
1$		move.l	    A2,A0
		libcall     GetMsg	; (A0=port)

		tst.l	    D0
		beq	    2$		; Port is empty
		move.l	    D0,A1
		libcall     ReplyMsg	; (A1=message)

		bra	    1$
2$		move.l	    A2,A0
		libcall     DeleteMsgPort ; (A0=port)

		move.l	    (SP)+,A6
		move.l	    (SP)+,A2
		rts

;****************************************************************
;* ULONG OpenOptWindow(ULONG WindowSig)  - Open option window   *
;*								*
;* Input:							*
;*   WindowSig	 - Current windowsignal or 0 if window not open *
;* Output:							*
;*   return	 - Window signal				*
;****************************************************************
HIDE		equ	    1
KILL		equ	    -1

@OpenOptWindow: movem.l     D2-D3/A2-A3/A5-A6,-(SP)
		tst.l	    D0
		beq	    ReallyOpen

;   Window is already open, move it to front
		move.l	    D0,D2     ; save signal bit
		move.l	    _IntuitionBase(A4),A6

		move.l	    _OptWindow(A4),A0
		libcall     WindowToFront	; (A0=window)

		move.l	    _OptWindow(A4),A0
		libcall     ActivateWindow	; (A0=window)

		move.l	    D2,D0     ; return same bit
		bra	    OpenOptDone

;   Create local variables
ReallyOpen:	lea	    -gng_SIZEOF(SP),SP

;   Open library
		move.l	    _ExecBase(A4),A6
		lea	    GADTOOLSNAME(PC),A1
		moveq.l     #KICK204,D0
		libcall     OpenLibrary 	; (A1=libName,D0=version)

		move.l	    D0,_GadToolsBase(A4)
		beq	    NoGadToolsLib

;   Find the default screen
		move.l	    _IntuitionBase(A4),A6
		lea	    WindowTags(PC),A3     ; A3 = Windowtags
		suba.l	    A0,A0
		libcall     LockPubScreen	  ; (A0=name)

		move.l	    D0,wtag_PubScreen(A3)
		beq	    NoPubScreen

;   Find size of window title bar
		move.l	    D0,A0
		moveq.l     #0,D0
		move.b	    sc_WBorTop(A0),D0
		move.l	    sc_Font(A0),A1
		add.w	    ta_YSize(A1),D0
		addq.w	    #1,D0
		move.w	    D0,gng_TopEdge(SP)

;   Get visual info
		move.l	    _GadToolsBase(A4),A6
		lea	    TagDone(PC),A1
		libcall     GetVisualInfoA	; (A0=screen,A1=taglist)

		move.l	    D0,gng_VisualInfo(SP)
		move.l	    D0,_VisualInfo(A4)
		beq	    NoVisualInfo

;   Init the NewGadget structure
;   Set font = Topaz 8
		lea	    Topaz8Font(PC),A0
		move.l	    A0,gng_TextAttr(SP)

;   ID = 0..N
		clr.w	    gng_GadgetID(SP)

;   LeftEdge is same for first three gadgets
		move.w	    #32,gng_LeftEdge(SP)

;   Width and height is ignored in CHECKBOX gadgets, set them anyway
		move.l	    #$001a000b,gng_Width(SP)  ; Both width and height

;   Same gadgets in the first 5 gadgets
		lea	    CheckBoxTags(PC),A2

;   Checkmark items depending on option status
		move.b	    _CxHandlerData+ssd_Options(A4),D3

;   Create a context to use
		lea	    wtag_Gadgets(A3),A0
		clr.l	    (A0)
		libcall     CreateContext	; (A0=glistptr)

		lea	    _Gadgets(A4),A5

;   Gadget 0 (clickmenus)
		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    CLICKTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0
		addq.w	    #4,gng_TopEdge(A1)

		moveq.l     #CLICKMENUS,D0
		and.l	    D3,D0
		move.l	    D0,12(A2)

		moveq.l     #PLACETEXT_RIGHT,D0
		move.l	    D0,gng_Flags(A1)
		moveq.l     #CHECKBOX_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)+

;   Gadget 1 (show single)
		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    SINGLETEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0
		add.w	    #11,gng_TopEdge(A1)
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #SHOWSINGLEMENU,D0
		and.l	    D3,D0
		move.l	    D0,12(A2)

		moveq.l     #CHECKBOX_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)+

;   Gadget 2 (centered items)
		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    CENTEREDTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		add.w	    #11,gng_TopEdge(A1)
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #ITEMSCENTERED,D0
		and.l	    D3,D0
		move.l	    D0,12(A2)

		moveq.l     #CHECKBOX_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)+

;   Gadget 3 (with qualifier)
		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    WITHTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		add.w	    #14,gng_TopEdge(A1)
		move.w	    #119,gng_LeftEdge(A1)
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #POPUPWITHQUAL,D0
		and.l	    D3,D0
		move.l	    D0,12(A2)

		moveq.l     #CHECKBOX_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)+

;   Gadget 4 (without qualifier)
		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    WITHOUTTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		add.w	    #11,gng_TopEdge(A1)
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #POPUPNOQUAL,D0
		and.l	    D3,D0
		move.l	    D0,12(A2)

		moveq.l     #CHECKBOX_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)+

;   Gadget 5 (hotkey)
		lea	    StringTags(PC),A2

		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    HOTKEYTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		lea	    _HotKeyString(A4),A0     ; Deafult hotkey
		move.l	    A0,4(A2)
		move.l	    D0,A0

		moveq.l     #PLACETEXT_LEFT,D0
		move.l	    D0,gng_Flags(A1)

		move.w	    #72,gng_LeftEdge(A1)
		add.w	    #14,gng_TopEdge(A1)
		move.l	    #$00ce000d,gng_Width(A1) ; Both width and height
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #STRING_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		move.l	    D0,(A5)                  ; last gadget remembered use

;   Gadget 6 (Kill)
		lea	    ButtonTags(PC),A2

		move.l	    SP,A1	       ; A1 = NewGadget
		lea	    KILLTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		moveq.l     #PLACETEXT_IN,D0
		move.l	    D0,gng_Flags(A1)

		move.w	    #20,gng_LeftEdge(A1)
		add.w	    #18,gng_TopEdge(A1)
		move.l	    #$0039000c,gng_Width(A1) ; Both width and height

		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #BUTTON_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

;   Gadget 7 (hide)
		move.l	    SP,A1	       ; A1 = NewGadget

		lea	    HIDETEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		move.w	    #220,gng_LeftEdge(A1)
		addq.w	    #1,gng_GadgetID(A1)

		moveq.l     #BUTTON_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

;   Gadget 7(!) (text)
		move.l	    SP,A1	       ; A1 = NewGadget

		lea	    TEXTTEXT(PC),A0
		move.l	    A0,gng_GadgetText(A1)
		move.l	    D0,A0

		move.w	    #119,gng_LeftEdge(A1)
		sub.w	    #38,gng_TopEdge(A1)

		moveq.l     #PLACETEXT_LEFT,D0
		move.l	    D0,gng_Flags(A1)

		moveq.l     #TEXT_KIND,D0
		libcall     CreateGadgetA	; (D0=kind,A0=gad,A1=ng,A2=taglist)

		tst.l	    D0
		beq	    NoGad

;   open window
		move.l	    _IntuitionBase(A4),A6
		suba.l	    A0,A0
		move.l	    A3,A1		; WindowTags
		libcall     OpenWindowTagList	; (A0=newWindow,A1=tagList)

		move.l	    D0,_OptWindow(A4)

		beq	    NoWindow

;   Draw the gadgets
		move.l	    _GadToolsBase(A4),A6
		move.l	    D0,A0		; Window
		sub.l	    A1,A1
		libcall     GT_RefreshWindow	; (A0=win,A1=req)

;   Find the signalbit
		move.l	    _OptWindow(A4),A0
		move.l	    wd_UserPort(A0),A0
		moveq.l     #0,D1
		move.b	    MP_SIGBIT(A0),D1
		moveq.l     #1,D0
		lsl.l	    D1,D0
		bra	    OpenOk

NoWindow:	move.l	    _GadToolsBase(A4),A6
NoGad:		move.l	    wtag_Gadgets(A3),A0
		libcall     FreeGadgets 	; (A0=gad)

		move.l	    _VisualInfo(A4),A0
		libcall     FreeVisualInfo	; (A0=vi)

NoVisualInfo:	move.l	    wtag_PubScreen(A3),A1
		sub.l	    A0,A0
		move.l	    _IntuitionBase(A4),A6
		libcall     UnlockPubScreen	    ; (A0=name,A1=screen)

NoPubScreen:	move.l	    _GadToolsBase(A4),A1
		move.l	    _ExecBase(A4),A6
		libcall     CloseLibrary	; (A1=library)

NoGadToolsLib:	moveq.l     #0,D0

OpenOk: 	lea	    gng_SIZEOF(SP),SP

OpenOptDone:	movem.l     (SP)+,D2-D3/A2-A3/A5-A6
		rts

;****************************************************************
;* UWORD HandleOptWindow(VOID) - handle message from opt window *
;*								*
;* Output:							*
;*   return    -  0  Nothing special				*
;*		 -1  User selected KILL 			*
;*		  1  User selected HIDE (or closewindow)        *
;****************************************************************
@HandleOptWindow:
		movem.l     D2-D4/A2-A3/A5-A6,-(SP)
		moveq.l     #0,D4	; RetCode = 0

NextMessage:	move.l	    _GadToolsBase(A4),A6
		move.l	    _OptWindow(A4),A5
		move.l	    wd_UserPort(A5),A0
		libcall     GT_GetIMsg	    ; (A0=iport)

		tst.l	    D0
		beq	    NoMoreMessages

		move.l	    D0,A1
		move.l	    im_Class(A1),D2
		move.w	    im_Code(A1),D3
		move.l	    im_IAddress(A1),A2

		libcall     GT_ReplyIMsg    ; (A1=imsg)

		btst	    #IDCMP_VANILLAKEY_B1+16,D2
		beq	    CheckClose

		lea	    KeyData(PC),A0
		moveq.l     #NoOfKeys-1,D1
1$		cmp.b	    (A0),D3
		beq	    2$
		addq.l	    #2,A0
		dbra	    D1,1$

		move.l	    _IntuitionBase(A4),A6
		lea	    WindowTags(PC),A0
		move.l	    wtag_PubScreen(A0),A0
		libcall     DisplayBeep

		bra	    NextMessage       ; Key not handled

;     Find corresponding gadget
2$		moveq.l     #0,D0
		move.b	    1(A0),D0
		move.b	    D0,D2
		lsl.w	    #2,D0

;    Gadget is only valid if GadNr <= 5
		move.l	    _Gadgets(A4,D0.w),A0

		cmp.b	    #5,D2
		bcc	    3$	       ; bhs

;    Toggle gadgets
		lea	    CheckedTags(PC),A3
		moveq.l     #1,D0
		lsl.w	    D2,D0	       ; D0 = Option bit
		move.b	    _CxHandlerData+ssd_Options(A4),D1
		eor.b	    D0,D1	       ; toggle option bit
		move.b	    D1,_CxHandlerData+ssd_Options(A4)
		and.b	    D1,D0
		move.l	    D0,4(A3)
		sub.l	    A2,A2
		move.l	    A5,A1
		libcall     GT_SetGadgetAttrsA ; (A0=gad,A1=win,A2=req,A3=taglist)

		bra	    NextMessage

3$		bne	    CheckButtons

;   Hotkey
		move.l	    _IntuitionBase(A4),A6
		move.l	    A5,A1
		sub.l	    A2,A2
		libcall     ActivateGadget	; (A0=gadgets,A1=window,A2=requester)

		bra	    NextMessage

CheckButtons:	subq.w	    #6,D2
		bne	    HideWindow

;   Kill
		moveq.l     #KILL,D4
		bra	    NextMessage

CheckClose:	btst	    #IDCMP_CLOSEWINDOW_B2+8,D2
		beq	    CheckGadgetUp

;   Hide
HideWindow:	moveq.l     #HIDE,D4
		bra	    NextMessage

CheckGadgetUp:	btst	    #IDCMP_GADGETUP_B3,D2
		beq	    CheckRefresh

		move.w	    gg_GadgetID(A2),D2

		cmp.b	    #5,D2
		bcc	    1$	       ; bhs

;   Togglegadgets
		bchg	    D2,_CxHandlerData+ssd_Options(A4)
		bra	    NextMessage

1$		bne	    CheckButtons

;   Hotkey
		lea	    -ix_SIZEOF(SP),SP
		move.b	    #IX_VERSION,(SP)       ; Don't know if this is needed
		move.l	    _CxBase(A4),A6
		move.l	    gg_SpecialInfo(A2),A0
		move.l	    si_Buffer(A0),A3

		move.l	    A3,A0
		move.l	    SP,A1
		libcall     ParseIX	    ; (A0=description,A1=ix)

		tst.l	    D0
		bne	    WrongHotKey

		move.l	    _HotKeyFilterCxObj(A4),A0
		move.l	    SP,A1
		libcall     SetFilterIX     ; (A0=filter,A1=ix)

;   Copy the string to the hotkeybuffer
		lea	    _HotKeyString(A4),A0
2$		move.b	    (A3)+,(A0)+
		bne	    2$
		bra	    HotKeyDone

WrongHotKey:	move.l	    A2,-(SP)
		move.l	    _IntuitionBase(A4),A6
		move.l	    A5,A0
		lea	    HotKeyReq(PC),A1
		sub.l	    A2,A2
		sub.l	    A3,A3
		libcall     EasyRequestArgs	; (A0=window,A1=easyStruct,A2=idcmpPtr,A3=args)

		move.l	    (SP)+,A2

		tst.l	    D0
		bne	    ChangeHotKey

		move.l	    _GadToolsBase(A4),A6
		lea	    SetStringTags(PC),A3
		lea	    _HotKeyString(A4),A0
		move.l	    A0,4(A3)
		move.l	    A2,A0
		move.l	    A5,A1
		sub.l	    A2,A2
		libcall     GT_SetGadgetAttrsA ; (A0=gad,A1=win,A2=req,A3=taglist)

		bra	    HotKeyDone

ChangeHotKey:	move.l	    A2,A0
		move.l	    A5,A1
		sub.l	    A2,A2
		libcall     ActivateGadget	; (A0=gadgets,A1=window,A2=requester)

HotKeyDone:	lea	    ix_SIZEOF(SP),SP
		bra	    NextMessage

CheckRefresh:	btst	    #IDCMP_REFRESHWINDOW_B3,D2
		beq	    NextMessage

		move.l	    A5,A0
		libcall     GT_BeginRefresh	; (A0=win)

		move.l	    A5,A0
		moveq.l     #TRUE,D0
		libcall     GT_EndRefresh	; (A0=win,D0=complete)

		bra	    NextMessage

NoMoreMessages: move.l	    D4,D0
		movem.l     (SP)+,D2-D4/A2-A3/A5-A6
		rts


;***************************************************
;* VOID CloseOptWindow(VOID) - close option window *
;***************************************************
@CloseOptWindow:
		move.l	    A2,-(SP)
		move.l	    A6,-(SP)

		lea	    WindowTags(PC),A2

;    Remember position of window
		move.l	    _OptWindow(A4),A0
		move.w	    wd_LeftEdge(A0),wtag_Left+2(A2)
		move.w	    wd_TopEdge(A0),wtag_Top+2(A2)

		move.l	    _IntuitionBase(A4),A6
		libcall     CloseWindow 	; (A0=window)

		move.l	    _GadToolsBase(A4),A6
		move.l	    wtag_Gadgets(A2),A0
		libcall     FreeGadgets 	; (A0=gad)

		move.l	    _VisualInfo(A4),A0
		libcall     FreeVisualInfo	; (A0=vi)

		move.l	    A6,A1		; GadToolsBase
		move.l	    _ExecBase(A4),A6
		libcall     CloseLibrary	; (A1=library)

		move.l	    _IntuitionBase(A4),A6
		move.l	    wtag_PubScreen(A2),A1
		sub.l	    A0,A0
		libcall     UnlockPubScreen	; (A0=name,A1=screen)

		move.l	    (SP)+,A6
		move.l	    (SP)+,A2
		rts

;************* S T R I N G   C O N S T A N T S ***************
		even
VERSIONSTRING:	dc.b	    '$VER: PopUpMenu 5.0 (4-Okt-92)',0
		even
CXNAME: 	dc.b	    'PopUpMenu',0
		even
CXTITLE:	dc.b	    'PopUpMenu 5.0 ',$a9,'1992 Martin Adrian',0
		even
CXDESCRIPTION:	dc.b	    'Pop-up menus under mousepointer',0
		even
DOSNAME 	dc.b	    'dos.library',0
		even
INTUITIONNAME:	dc.b	    'intuition.library',0
		even
GFXNAME:	dc.b	    'graphics.library',0
		even
LAYERSNAME:	dc.b	    'layers.library',0
		even
COMMODITYNAME:	dc.b	    'commodities.library',0
		even
ICONNAME	dc.b	    'icon.library',0
		even
GADTOOLSNAME:	dc.b	    'gadtools.library',0
		even
IFFNAME 	dc.b	    'iffparse.library',0
		even
TIMERNAME:	dc.b	    'timer.device',0
		even
ICNTRLFILENAME: dc.b	    'ENV:sys/icontrol.prefs',0
		even
DEFAULTHOTKEY:	dc.b	    'control alt p',0
		even
TEMPLATETEXT:	dc.b	    'CLICKMENUS/S,SHOWSINGLE/S,CENTERITEMS/S,POPWITHQUAL/S,'
		dc.b	    'CX_POPUP/S,CX_POPKEY/K,CX_PRIORITY/K/N',0
		even
ARG_CLICK:	dc.b	    'CLICKMENUS',0
		even
ARG_SHOW:	dc.b	    'SHOWSINGLE',0
		even
ARG_CENTER:	dc.b	    'CENTERITEMS',0
		even
ARG_POPWITH:	dc.b	    'POPWITHQUAL',0
		even
ARG_CXPOPUP:	dc.b	    'CX_POPUP',0
		even
ARG_CXPOPKEY:	dc.b	    'CX_POPKEY',0
		even
ARG_CXPRI:	dc.b	    'CX_PRIORITY',0
		even
YESTEXT:	dc.b	    'YES',0
		even
CLICKTEXT:	dc.b	    '"_Click" menus',0
		even
SINGLETEXT:	dc.b	    '_Show single menu',0
		even
CENTEREDTEXT:	dc.b	    'Center menu_items',0
		even
WITHTEXT:	dc.b	    '_with qualifier',0
		even
WITHOUTTEXT:	dc.b	    'with_out qualifier',0
		even
HOTKEYTEXT:	dc.b	    '_Hotkey',0
		even
KILLTEXT:	dc.b	    '_Kill',0
		even
HIDETEXT:	dc.b	    'Hide',0
		even
TEXTTEXT:	dc.b	    'Pop-up menus',0
		even
WINDOWTITLE:	dc.b	    'PopUpMenu 5.0',0
		even
EASYWINNAME:	equ	    CXNAME
		even
EASYTEXT:	dc.b	    'Invalid hotkey specification!',0
		even
EASYGADGETS:	dc.b	    'Try again|Cancel',0
		even
TOPAZNAME:	dc.b	    'topaz.font',0
		cnop	    0,4

;*************** T A G S **********************
StringTags:	dc.l	    GTST_String,0	; filled in
		dc.l	    GTST_MaxChars,HOTKEYBUFLENGTH
		dc.l	    GA_TabCycle,FALSE
ButtonTags:	dc.l	    GT_Underscore,'_'
TagDone:	dc.l	    TAG_DONE

SetStringTags:	dc.l	    GTST_String,0	; filled in
		dc.l	    TAG_DONE

CheckBoxTags:	dc.l	    GT_Underscore,'_'
CheckedTags:	dc.l	    GTCB_Checked,0	; filled in
		dc.l	    TAG_DONE

WindowTags:
WLeft:		dc.l	    WA_Left,154
WTop:		dc.l	    WA_Top,62
		dc.l	    WA_InnerWidth,290
		dc.l	    WA_InnerHeight,98
		dc.l	    WA_AutoAdjust,TRUE
		dc.l	    WA_IDCMP,IDCMP_GADGETUP!IDCMP_CLOSEWINDOW!IDCMP_VANILLAKEY!IDCMP_REFRESHWINDOW
		dc.l	    WA_Flags,WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET!WFLG_SIMPLE_REFRESH!WFLG_ACTIVATE!WFLG_RMBTRAP
WGad:		dc.l	    WA_Gadgets,0	; filled in
		dc.l	    WA_Title,WINDOWTITLE
WPub:		dc.l	    WA_PubScreen,0	; filled in
		dc.l	    TAG_DONE

wtag_Left:	equ	    (WLeft-WindowTags)+4
wtag_Top:	equ	    (WTop-WindowTags)+4
wtag_Gadgets:	equ	    (WGad-WindowTags)+4
wtag_PubScreen: equ	    (WPub-WindowTags)+4

;**************** T A B L E S ******************
CXCMDCOMMANDS:	dc.b	    CXCMD_DISABLE,DISABLE_F!DISAPPEAR_F
		dc.b	    CXCMD_ENABLE,ENABLE_F
		dc.b	    CXCMD_APPEAR,APPEAR_F!ENABLE_F
		dc.b	    CXCMD_UNIQUE,APPEAR_F!ENABLE_F
		dc.b	    CXCMD_DISAPPEAR,DISAPPEAR_F
		dc.b	    CXCMD_KILL,QUIT_F!DISAPPEAR_F!DISABLE_F
NoOfCommands:	equ	    (*-CXCMDCOMMANDS)/2
		even

KeyData:	dc.b	    'c',0   ; Clickmenus
		dc.b	    'C',0
		dc.b	    's',1   ; single menu
		dc.b	    'S',1
		dc.b	    'i',2   ; centered items
		dc.b	    'I',2
		dc.b	    'w',3   ; with qualifier
		dc.b	    'W',3
		dc.b	    'o',4   ; without qualifier
		dc.b	    'O',4
		dc.b	    'h',5   ; hotkey
		dc.b	    'H',5
		dc.b	    'k',6   ; Kill
		dc.b	    'K',6
		dc.b	    13,7    ; enter (hide)
		dc.b	    27,7    ; Esc   (hide)
NoOfKeys:	equ	    (*-KeyData)/2
		cnop	    0,4

;*************** C O N S T A N T S *************************
BrokerData:	dc.b	    NB_VERSION,0	    ; nb_Version, pad
		dc.l	    CXNAME		    ; nb_Name
		dc.l	    CXTITLE		    ; nb_Title
		dc.l	    CXDESCRIPTION	    ; nb_Descr
		dc.w	    NBU_UNIQUE!NBU_NOTIFY   ; nb_Unique
		dc.w	    COF_SHOW_HIDE	    ; nb_Flags
		dc.b	    0,0 		    ; nb_Pri, pad
		dc.l	    0			    ; nb_Port
		dc.w	    0			    ; nb_ReservedChannel

NotifyData:	dc.l	    ICNTRLFILENAME	; nr_Name
		dc.l	    0			; nr_FullName
		dc.l	    0			; nr_UserData
		dc.l	    NRF_SEND_SIGNAL	; nr_Flags
		dc.l	    0			; nr_Port | nr_Task
		dc.b	    0			; nr_SignalNum
		dc.b	    0,0,0		; nr_Pad
		dc.l	    0,0,0,0		; nr_Reserved
		dc.l	    0			; nr_MsgCount
		dc.l	    0			; nr_Handler

DefaultArgs:	dc.l	    FALSE		; arg_ClickMenus
		dc.l	    FALSE		; arg_ShowSingle
		dc.l	    FALSE		; arg_CenterItems
		dc.l	    FALSE		; arg_PopWithQual
		dc.l	    FALSE		; arg_PopUp
		dc.l	    DEFAULTHOTKEY	; arg_PopKey
		dc.l	    Priority		; arg_Pri

Topaz8Font:	dc.l	    TOPAZNAME		; ta_Name
		dc.w	    8			; ta_YSize
		dc.b	    FS_NORMAL		; ta_Style
		dc.b	    FPF_ROMFONT 	; ta_Flags

HotKeyReq:	dc.l	    es_SIZEOF		; es_StructSize
		dc.l	    0			; es_Flags
		dc.l	    EASYWINNAME 	; es_Title
		dc.l	    EASYTEXT		; es_TextFormat
		dc.l	    EASYGADGETS 	; es_GadgetFormat

;******************** V A R I A B L E S ***********************
;  Used in the new intuition functions
OldClearMenuStrip:
		dc.l	    0
OldOnMenu:	dc.l	    0
OldOffMenu:	dc.l	    0

;  Used in the inputhandler
CxBase: 	dc.l	    0
IBase:		dc.l	    0

;  Used in ParseArgs
Priority	dc.l	    0		; deafult priority = 0

PopUpSemaphore: ds.b	    SS_SIZE	; placed here to reach with (PC)
		end


