;                          QMouse 1.0  by Lyman Epp
;
;        Another "Mouse Accelerator???"  What for?  It seems that all the
;        other mouse accelerators have been written in "C".  This is okay,
;        but the programs are 10-20K.  This mouse accelerator is written
;        in assembler and contains most of the features of the others, but
;        the program size is less than 3K bytes!  Also, the source is
;        included so that you can add more features (please send me a copy
;        if you do.)  QMouse stands for "Quick Mouse."
;
;        This is being distributed as ShareWare.  If you think that QMouse
;        is useful, please send $10.  If you don't think that it is useful,
;        then why are you using it?  Your response will insure the release
;        of more quality programs for your Amiga!  Programs already in the
;        works include: a disk based print spooler, a window dump that
;        converts the window bitmap back to text, a file viewer, and more.
;
;                Lyman R. Epp
;                10072 Wirt Plaza #15
;                Omaha, Nebraska 68134


        section text,CODE

        INCLUDE "exec/types.i"
        INCLUDE "exec/libraries.i"
        INCLUDE "exec/interrupts.i"
        INCLUDE "exec/memory.i"
        INCLUDE "libraries/dosextens.i"
        INCLUDE "devices/input.i"
        INCLUDE "devices/inputevent.i"
        INCLUDE "graphics/clip.i"
        INCLUDE "graphics/gfx.i"
        INCLUDE "graphics/gfxbase.i"
        INCLUDE "graphics/copper.i"
        INCLUDE "hardware/custom.i"
        INCLUDE "hardware/dmabits.i"
        INCLUDE "intuition/intuition.i"
        INCLUDE "intuition/intuitionbase.i"


RAW_M               EQU     $37
RAW_ESCAPE          EQU     $45

CLOCK_WIDTH         EQU     44

FLAGB_BLANK         EQU     0
FLAGB_POINTEROFF    EQU     1
FLAGB_NO_AMIGA_M    EQU     2
FLAGB_CLOCK         EQU     3

POSTB_BLANK         EQU     0
POSTB_UNBLANK       EQU     1
POSTB_NEWCLI        EQU     2
POSTB_TIMER         EQU     3
POSTB_SHUFFLE       EQU     4
POSTB_QUIT          EQU     5



        STRUCTURE work,0

        APTR    dosBase
        APTR    gfxBase
        APTR    layersBase
        APTR    intuitionBase

        APTR    commandLine
        APTR    qmouseTask
        ULONG   qmouseSignal
        UBYTE   qmousePost
        UBYTE   qmouseFlag

        APTR    inputDev
        APTR    clockWindow
        APTR    blankScreen
        APTR    blankSprite
        APTR    saveSprite
        ULONG   nullHandle
        ULONG   timerSec
        UWORD   blankTimer
        UWORD   pointerTimer
        UWORD   clicksLeft
        APTR    clickWindow
        STRUCT  clickTime,8

        STRUCT  execCommand,100

        STRUCT  inputReqBlk,IOSTD_SIZE
        STRUCT  handlerStuff,IS_SIZE

        LABEL   work_SIZEOF



        XREF    _AbsExecBase
        XREF    CreatePort
        XREF    DeletePort


CALLSYS MACRO
        xref    _LVO\1
        CALLLIB _LVO\1
        ENDM

LINKSYS MACRO
        xref    _LVO\1
        LINKLIB _LVO\1,\2
        ENDM

ON_DISPLAY  MACRO
        move.l  #$dff000,a0
        move.w  #BITSET!DMAF_RASTER,dmacon(a0)
        ENDM

OFF_DISPLAY  MACRO
        move.l  #$dff000,a0
        move.w  #BITCLR!DMAF_RASTER,dmacon(a0)
        ENDM


        section text,CODE

QMouse:
        move.l  _AbsExecBase,a6
        lea     workarea,a5
        move.l  a0,commandLine(a5)      ; save command line addr for later

        lea     dosName(pc),a1          ; open "dos.library"
        moveq   #0,d0
        CALLSYS OpenLibrary
        move.l  d0,dosBase(a5)
        beq     abort

        lea     graphicsName(pc),a1     ; open "graphics.library"
        moveq   #0,d0
        CALLSYS OpenLibrary
        move.l  d0,gfxBase(a5)
        beq     abort

        lea     layersName(pc),a1     ; open "layers.library"
        moveq   #0,d0
        CALLSYS OpenLibrary
        move.l  d0,layersBase(a5)
        beq     abort

        lea     intuitionName(pc),a1    ; open "intuition.library"
        moveq   #0,d0
        CALLSYS OpenLibrary
        move.l  d0,intuitionBase(a5)
        beq     abort

        lea     qmousePortName(pc),a1
        CALLSYS FindPort
        tst.l   d0
        bne     abort

        movem.l defaultCommand(pc),d0-d1
        movem.l d0-d1,execCommand(a5)
        bsr     ParseInput

        move.l  #12,d0
        move.l  #MEMF_CHIP!MEMF_PUBLIC!MEMF_CLEAR,d1
        CALLSYS AllocMem                ; allocate working storage
        move.l  d0,blankSprite(a5)
        beq     abort
        move.l  d0,a0
        move.w  #$FE00,(a0)
        move.w  #$FF00,2(a0)

        move.w  screenSecs(pc),blankTimer(a5)
        move.w  pointerSecs(pc),pointerTimer(a5)

        lea     nullName(pc),a1
        move.l  a1,d1
        move.l  #MODE_NEWFILE,d2
        LINKSYS Open,dosBase(a5)
        move.l  d0,nullHandle(a5)
        beq     abort

        sub.l   a1,a1
        CALLSYS FindTask
        move.l  d0,qmouseTask(a5)
        move.l  d0,a1
        move.b  pr_MsgPort+MP_SIGBIT(a1),d1
        moveq   #0,d0
        bset    d1,d0
        move.l  d0,qmouseSignal(a5)

        btst    #FLAGB_CLOCK,qmouseFlag(a5)
        beq     Main_NoClock
        lea     clockNewWindow(pc),a0
        LINKSYS OpenWindow,intuitionBase(a5)
        move.l  d0,clockWindow(a5)
        beq     abort
        bsr     Clock
Main_NoClock:

        lea     qmousePortName(pc),a0
        moveq   #0,d0
        bsr     CreatePort
        tst.l   d0
        beq     abort

        lea     inputReqBlk(a5),a1
        move.b  #NT_MESSAGE,LN_TYPE(a1)
        move.w  #IOSTD_SIZE,MN_LENGTH(a1)
        move.l  d0,MN_REPLYPORT(a1)

        lea     inputName(pc),a0
        moveq   #0,d0
        moveq   #0,d1
        CALLSYS OpenDevice              ; A1 still contains inputReqBlk
        move.l  d0,inputDev(a5)
        bne     abort

        lea     MyHandler(pc),a1
        lea     handlerStuff(a5),a0
        move.b  #51,LN_PRI(a0)
        move.l  a1,IS_CODE(a0)

        lea     inputReqBlk(a5),a1
        move.l  a0,IO_DATA(a1)
        move.w  #IND_ADDHANDLER,IO_COMMAND(a1)
        CALLSYS DoIO

        move.l  qmouseTask(a5),a1
        moveq   #10,d0
        CALLSYS SetTaskPri

Main_Wait:
        move.l  qmouseSignal(a5),d0
        CALLSYS Wait

        bclr    #POSTB_BLANK,qmousePost(a5)
        beq     Main_Blank
        bsr     BlankScreen
Main_Blank:
        bclr    #POSTB_UNBLANK,qmousePost(a5)
        beq     Main_Unblank
        bsr     UnblankScreen
Main_Unblank:
        bclr    #POSTB_TIMER,qmousePost(a5)
        beq     Main_Timer
        bsr     Clock
Main_Timer:
        bclr    #POSTB_NEWCLI,qmousePost(a5)
        beq     Main_Newcli
        bsr     NewCLI
Main_Newcli:
        bclr    #POSTB_SHUFFLE,qmousePost(a5)
        beq     Main_Shuffle
        bsr     ScreenShuffle
Main_Shuffle:
        bclr    #POSTB_QUIT,qmousePost(a5)
        beq     Main_Wait


        lea     inputReqBlk(a5),a1
        move.w  #IND_REMHANDLER,IO_COMMAND(a1)
        CALLSYS DoIO

        lea     inputReqBlk(a5),a1
        CALLSYS CloseDevice

        lea     inputReqBlk(a5),a1
        move.l  MN_REPLYPORT(a1),d0
        bsr     DeletePort

        bsr     PointerOn


abort:
        move.l  clockWindow(a5),d0
        beq     Abort_NoWindow
        move.l  d0,a0
        LINKSYS CloseWindow,intuitionBase(a5)
Abort_NoWindow:
        move.l  blankSprite(a5),d0
        beq     Abort_NoBlankSprite
        move.l  d0,a1
        moveq   #12,d0
        CALLSYS FreeMem
Abort_NoBlankSprite:
        move.l  intuitionBase(a5),d0
        beq     Abort_NoIntuitionLib
        move.l  d0,a1
        CALLSYS CloseLibrary
Abort_NoIntuitionLib:
        move.l  layersBase(a5),d0
        beq     Abort_NoLayersLib
        move.l  d0,a1
        CALLSYS CloseLibrary
Abort_NoLayersLib:
        move.l  gfxBase(a5),d0
        beq     Abort_NoGraphicsLib
        move.l  d0,a1
        CALLSYS CloseLibrary
Abort_NoGraphicsLib:

        moveq   #5,d1
        LINKSYS Exit,dosBase(a5)



ParseInput:
        move.l  commandLine(a5),a2
        moveq   #0,d1                    ; reset quoted flag
Parse_Loop:
        move.b  (a2)+,d2
        cmpi.b  #10,d2
        beq     Parse_Done
        cmpi.b  #'"',d2
        beq     Parse_QuoteChar
        cmpi.b  #'-',d2
        beq     Parse_Option
        cmpi.b  #' ',d2
        beq     Parse_Loop
        bra     ErrUsage

Parse_Done:
        btst    #31,d1
        bne     ErrUsage
        rts

Parse_QuoteChar:
        bset    #31,d1
        bra     Parse_Loop

Parse_Option:
        move.b  (a2)+,d2
        ori.b   #$20,d2                  ; force to lowercase
        cmpi.b  #'a',d2                  ; Accel factor
        beq     Parse_Acc
        cmpi.b  #'c',d2                  ; Clock enable
        beq     Parse_Clock
        cmpi.b  #'e',d2                  ; Execute command
        beq     Parse_Exec
        cmpi.b  #'k',d2                  ; number of clicks (to front)
        beq     Parse_Klick
        cmpi.b  #'m',d2                  ; Amiga-M disable
        beq     Parse_Amiga_M
        cmpi.b  #'p',d2                  ; Pointer Off seconds
        beq     Parse_Pointer
        cmpi.b  #'s',d2                  ; Screen Blank seconds
        beq     Parse_Screen
        cmpi.b  #'t',d2                  ; Accel thresh-hold
        beq     Parse_Thresh
        bra     ErrUsage

Parse_Next:
        bclr    #31,d1
        beq     Parse_Loop
        cmpi.b  #'"',(a2)+
        beq     Parse_Loop
        bra     ErrUsage

Parse_Acc:
        bsr     GetNumber
        move.w  d0,mouseAccel
        bra     Parse_Next

Parse_Clock:
        bset    #FLAGB_CLOCK,qmouseFlag(a5)
        bsr     GetNumber
        tst.w   d0
        beq     Parse_Next
        move.l  intuitionBase(a5),a1
        move.l  ib_FirstScreen(a1),a1
        move.w  sc_Width(a1),d1
        subi.w  #CLOCK_WIDTH,d1
        cmp.w   d1,d0
        bgt     Parse_Next
        lea     clockNewWindow(pc),a1
        move.w  d0,nw_LeftEdge(a1)
        bra     Parse_Next

Parse_Exec:
        lea     execCommand(a5),a1
Parse_ExecLoop:
        move.b  (a2)+,d2
        cmpi.b  #10,d2
        beq     Parse_ExecDone
        btst    #31,d1
        bne     Parse_ExecQuoted
        cmpi.b  #' ',d2                  ; end of the field?
        bne     Parse_ExecMove
        bra     Parse_ExecDone
Parse_ExecQuoted:
        cmpi.b  #'"',d2                  ; end of the field?
        beq     Parse_ExecDone
Parse_ExecMove:
        move.b  d2,(a1)+
        bra     Parse_ExecLoop
Parse_ExecDone:
        move.b  -(a2),d2                 ; point at char that terminated
        clr.b   (a1)                     ; terminate the execute string
        bra     Parse_Next

Parse_Klick:
        bsr     GetNumber
        move.w  d0,numClicks
        bra     Parse_Next

Parse_Amiga_M:
        bset    #FLAGB_NO_AMIGA_M,qmouseFlag(a5)
        bra     Parse_Next

Parse_Pointer:
        bsr     GetNumber
        move.w  d0,pointerSecs
        bra     Parse_Next

Parse_Screen:
        bsr     GetNumber
        move.w  d0,screenSecs
        bra     Parse_Next

Parse_Thresh:
        bsr     GetNumber
        move.w  d0,accelThresh
        bra     Parse_Next


GetNumber:
        moveq   #0,d0
        moveq   #0,d2
GetNumberLoop:
        move.b  (a2)+,d2
        cmpi.b  #'0',d2
        blt     GetNumber_Exit
        cmpi.b  #'9',d2
        bgt     GetNumber_Exit
        subi.b  #'0',d2
        mulu    #10,d0
        add.w   d2,d0
        bra     GetNumberLoop
GetNumber_Exit:
        move.b  -(a2),d2                 ; point at char that terminated
        rts


ErrUsage:
        lea     ERR_USAGE(pc),a2
        move.l  a2,d2
        moveq   #ERR_USAGE_SIZE,d3
        bra     ErrDisplay

ErrFatal:
        lea     ERR_FATAL(pc),a2
        move.l  a2,d2
        moveq   #ERR_FATAL_SIZE,d3
        bra     ErrDisplay

ErrDisplay:
        LINKSYS Output,dosBase(a5)
        move.l  d0,d1
        LINKSYS Write,dosBase(a5)
        bra     abort



PointerOff:
        move.l  gfxBase(a5),a1
        move.l  gb_copinit(a1),a1
        bset    #FLAGB_POINTEROFF,qmouseFlag(a5)
        bne     PointerOffSkip
        move.w  copinit_sprstrtup+2(a1),saveSprite+0(a5)
        move.w  copinit_sprstrtup+6(a1),saveSprite+2(a5)
PointerOffSkip:
        move.w  blankSprite+0(a5),copinit_sprstrtup+2(a1)
        move.w  blankSprite+2(a5),copinit_sprstrtup+6(a1)

PointerOff_End:
        rts



PointerOn:
        bclr    #FLAGB_POINTEROFF,qmouseFlag(a5)
        beq     PointerOn_End

        move.l  gfxBase(a5),a1
        move.l  gb_copinit(a1),a1
        move.w  saveSprite+0(a5),copinit_sprstrtup+2(a1)
        move.w  saveSprite+2(a5),copinit_sprstrtup+6(a1)

PointerOn_End:
        rts



BlankScreen:
        lea     blankNewScreen(pc),a0
        LINKSYS OpenScreen,intuitionBase(a5)
        move.l  d0,blankScreen(a5)
        beq     Blank_End

        move.l  d0,a0
        lea     sc_ViewPort(a0),a0
        moveq   #0,d0
        moveq   #0,d1
        moveq   #0,d2
        moveq   #0,d3
        LINKSYS SetRGB4,gfxBase(a5)

        OFF_DISPLAY

        bset    #FLAGB_BLANK,qmouseFlag(a5)

Blank_End:
        rts



UnblankScreen:
        bclr    #FLAGB_BLANK,qmouseFlag(a5)
        beq     Unblank_End

        move.l  blankScreen(a5),a0
        LINKSYS CloseScreen,intuitionBase(a5)

        ON_DISPLAY

Unblank_End:
        rts



NewCLI:
        LINKSYS WBenchToFront,intuitionBase(a5)

        lea     execCommand(a5),a1
        move.l  a1,d1
        move.l  nullHandle(a5),d2
        move.l  d2,d3
        LINKSYS Execute,dosBase(a5)

NewCLI_End:
        rts



ScreenShuffle:
        CALLSYS Forbid

        move.l  intuitionBase(a5),a0
        move.l  ib_FirstScreen(a0),a0
        LINKSYS ScreenToBack,intuitionBase(a5)

        CALLSYS Permit

Shuffle_End:
        rts



Clock:
        btst    #FLAGB_CLOCK,qmouseFlag(a5)
        beq     Clock_End

        move.l  dosBase(a5),a0
        move.l  dl_Root(a0),a0
        move.l  rn_Time+ds_Minute(a0),d0

        divu    #60,d0
        move.l  d0,d1                   ; save for calculating minutes
        moveq   #16,d2                  ; used for shifting later...

        cmpi.w  #12,d0
        ble     Clock_NotPM
        subi.w  #12,d0
Clock_NotPM:
        tst.w   d0
        bne     Clock_NotMidnite
        moveq   #12,d0
Clock_NotMidnite:
        ext.l   d0
        divu    #10,d0
        ori.b   #'0',d0
        cmpi.b  #'0',d0
        bne     Clock_FirstCharOk
        move.b  #' ',d0
Clock_FirstCharOk:
        lea     clockBuffer(pc),a0
        move.b  d0,(a0)
        lsr.l   d2,d0
        ori.b   #'0',d0
        move.b  d0,1(a0)

        lsr.l   d2,d1
        ext.l   d1
        divu    #10,d1
        ori.b   #'0',d1
        move.b  d1,3(a0)
        lsr.l   d2,d1
        ori.b   #'0',d1
        move.b  d1,4(a0)

        moveq   #':',d1
        cmp.b   2(a0),d1
        bne     Clock_FlipFlop
        moveq   #' ',d1
Clock_FlipFlop:
        move.b  d1,2(a0)

        move.l  clockWindow(a5),a0
        move.l  wd_RPort(a0),a0
        lea     clockText(pc),a1
        moveq   #0,d0
        moveq   #0,d1
        LINKSYS PrintIText,intuitionBase(a5)

        move.l  clockWindow(a5),a0
        move.l  wd_RPort(a0),a1
        move.l  rp_Layer(a1),a1
        move.l  lr_ClipRect(a1),d0        ; are there any ClipRect structs ??
        beq     Clock_End                 ; no, the clock isn't obscured!
        move.l  d0,a1
        tst.l   cr_Next(a1)               ; more than one ClipRect ??
        bne     Clock_ToFront             ; yes, clock is obscured!
        tst.l   cr_BitMap(a1)             ; was whole clock copied to BitMap ??
        beq     Clock_End                 ; no, the clock isn't obscured!
Clock_ToFront:
        LINKSYS WindowToFront,intuitionBase(a5)

Clock_End:
        rts


AccelMouse:
        move.w  accelThresh(pc),d1
        cmp.w   d1,d0
        bgt     Accel_Yes
        neg.w   d1
        cmp.w   d1,d0
        bge     Accel_No
Accel_Yes:
        sub.w   d1,d0
        mulu    mouseAccel(pc),d0
        add.w   d1,d0
Accel_No:
        rts


CheckMouseClicks:
        move.l  a0,-(sp)

        bsr     WhichMouseLayer           ; check if pointer is over a layer
        tst.l   d0
        beq     Click_None
        move.l  d0,a1
        move.l  lr_Window(a1),d4          ; check if pointer is over a window
        beq     Click_None
        move.l  lr_ClipRect(a1),d0        ; is this window already up front?
        beq     Click_None                ; yes, don't waste more time!
        move.l  d0,a1
        tst.l   cr_Next(a1)               ; is this window already up front?
        beq     Click_None                ; yes, don't waste more time!

        movem.l ie_TimeStamp(a0),d2-d3
        cmp.l   clickWindow(a5),d4        ; same window as last click?
        bne     Click_DiffWindow          ; no, reset clicks left
        movem.l clickTime(a5),d0-d1       ; let intuition check if they
        LINKSYS DoubleClick,intuitionBase(a5)  ; double clicked soon enough
        tst.l   d0
        bne     Click_CheckCount
Click_DiffWindow:
        move.w  numClicks(pc),clicksLeft(a5)
Click_CheckCount:
        movem.l d2-d3,clickTime(a5)
        move.l  d4,clickWindow(a5)
        subi.w  #1,clicksLeft(a5)
        bne     Click_End
        move.l  d4,a0
        LINKSYS WindowToFront,intuitionBase(a5)
Click_None:
        move.w  numClicks(pc),clicksLeft(a5)

Click_End:
        move.l  (sp)+,a0
        rts


WhichMouseLayer:
        movem.l d1-d2/a0-a3,-(sp)

        CALLSYS Forbid

        move.l  intuitionBase(a5),a3
        move.l  ib_FirstScreen(a3),d0
        beq     Layer_Exit
Layer_Loop:
        move.l  d0,a2
        move.w  ib_MouseY(a3),d2
        move.w  sc_ViewPort+vp_Modes(a2),d0
        andi.w  #V_LACE,d0
        bne     Layer_Interlace
        lsr.w   #1,d2
Layer_Interlace:
        lea     sc_LayerInfo(a2),a0
        moveq   #0,d0
        move.w  ib_MouseX(a3),d0
        moveq   #0,d1
        move.w  d2,d1
        sub.w   sc_ViewPort+vp_DyOffset(a2),d1
        LINKSYS WhichLayer,layersBase(a5)
        tst.l   d0
        bne     Layer_Exit
        cmp.w   sc_ViewPort+vp_DyOffset(a2),d2
        ble     Layer_Exit
        move.l  sc_NextScreen(a2),d0
        bne     Layer_Loop

Layer_Exit:
        CALLSYS Permit

        movem.l (sp)+,d1-d2/a0-a3
        rts



MyHandler:
        movem.l a0/a5,-(sp)
        lea     workarea,a5

Handler_Loop:
        cmpi.b  #IECLASS_TIMER,ie_Class(a0)
        bne     Handler_NotTimer
        bsr     TimerEvent
        bra     Handler_NextEvent

Handler_NotTimer:
        bsr     NotTimerEvent
        cmpi.b  #IECLASS_RAWMOUSE,ie_Class(a0)
        bne     Handler_NotMouse
        bsr     MouseEvent
        bra     Handler_NextEvent

Handler_NotMouse:
        cmpi.b  #IECLASS_RAWKEY,ie_Class(a0)
        bne     Handler_NextEvent
        bsr     RawKeyEvent

Handler_NextEvent:
        move.l  ie_NextEvent(a0),d0
        move.l  d0,a0
        bne     Handler_Loop

        tst.b   qmousePost(a5)
        beq     Handler_End

        move.l  qmouseTask(a5),a1
        move.l  qmouseSignal(a5),d0
        LINKSYS Signal,_AbsExecBase

Handler_End:
        movem.l (sp)+,d0/a5
        rts



TimerEvent:
        btst    #FLAGB_POINTEROFF,qmouseFlag(a5)  ; Intuition will restore the
        beq     Timer_PointerOK                   ; pointer--make sure its off!
        bsr     PointerOff
Timer_PointerOK:

        move.l  ie_TimeStamp(a0),d0
        cmp.l   timerSec(a5),d0
        beq     Timer_End

        move.l  d0,timerSec(a5)
        bset    #POSTB_TIMER,qmousePost(a5)

        move.w  pointerSecs(pc),d0          ; pointer blank enabled?
        beq     Timer_NotPointer
        btst    #FLAGB_POINTEROFF,qmouseFlag(a5)
        bne     Timer_NotPointer
        subq.w  #1,pointerTimer(a5)
        bne     Timer_NotPointer
        bsr     PointerOff
Timer_NotPointer:

        move.w  screenSecs(pc),d0            ; Screen blank enabled?
        beq     Timer_NotBlank
        btst    #FLAGB_BLANK,qmouseFlag(a5)
        bne     Timer_NotBlank
        subq.w  #1,blankTimer(a5)
        bne     Timer_NotBlank

        bset    #POSTB_BLANK,qmousePost(a5)
Timer_NotBlank:

Timer_End:
        rts



NotTimerEvent:
        move.w  screenSecs(pc),blankTimer(a5)

        btst    #FLAGB_BLANK,qmouseFlag(a5)
        beq     NotTimer_End            ; screen not blank -- return
        bset    #POSTB_UNBLANK,qmousePost(a5)

NotTimer_End:
        rts



MouseEvent:
        movem.l d1-d3/a0,-(sp)

        move.w  pointerSecs(pc),pointerTimer(a5)

        btst    #FLAGB_POINTEROFF,qmouseFlag(a5)
        beq     Mouse_NotPointer         ; pointer already on -- skip
        bsr     PointerOn
Mouse_NotPointer:

        cmpi.w  #1,mouseAccel
        ble     Mouse_NoAccel
        move.w  ie_Qualifier(a0),d0
        btst    #IEQUALIFIERB_RELATIVEMOUSE,d0
        beq     Mouse_NoAccel
        move.w  ie_X(a0),d0
        bsr     AccelMouse
        move.w  d0,ie_X(a0)
        move.w  ie_Y(a0),d0
        bsr     AccelMouse
        move.w  d0,ie_Y(a0)
Mouse_NoAccel:

        move.w  numClicks(pc),d0            ; click to front enabled?
        beq     Mouse_NoClick
        cmpi.w  #IECODE_LBUTTON,ie_Code(a0)
        bne     Mouse_NoClick
        bsr     CheckMouseClicks
Mouse_NoClick:

Mouse_End:
        movem.l (sp)+,d1-d3/a0
        rts



RawKeyEvent:
        move.w  ie_Qualifier(a0),d0
        btst    #IEQUALIFIERB_LCOMMAND,d0
        beq     RawKey_End

        cmpi.w  #RAW_M,ie_Code(a0)
        bne     RawKey_NotShuffle
        move.b  #IECLASS_NULL,ie_Class(a0)
        bset    #POSTB_SHUFFLE,qmousePost(a5)
RawKey_NotShuffle:

        cmpi.w  #RAW_ESCAPE,ie_Code(a0)
        bne     RawKey_End
        move.b  #IECLASS_NULL,ie_Class(a0)
        btst    #IEQUALIFIERB_CONTROL,d0
        bne     RawKey_Quit
        bset    #POSTB_NEWCLI,qmousePost(a5)
        bra     RawKey_End
RawKey_Quit:
        bset    #POSTB_QUIT,qmousePost(a5)

RawKey_End:
        rts





dosName          dc.b    'dos.library',0
graphicsName     dc.b    'graphics.library',0
layersName       dc.b    'layers.library',0
intuitionName    dc.b    'intuition.library',0
inputName        dc.b    'input.device',0

qmousePortName   dc.b    'QMouse 1.0 Port',0
nullName         dc.b    'NIL:',0

mouseAccel       dc.w    3             ; defaults for these options!
accelThresh      dc.w    3
pointerSecs      dc.w    10
screenSecs       dc.w    600
numClicks        dc.w    2
defaultCommand   dc.b    'NewCLI',0


ERR_USAGE        dc.b    $9b,'0;33mQMouse 1.0',$9b,'0m  by Lyman Epp',10
                 dc.b    'Usage: QMouse -A# -C# -Ecommand -K# -M -P# -S# -T#',10
ERR_USAGE_SIZE   equ     *-ERR_USAGE

ERR_FATAL        dc.b    'QMouse: Fatal error',10
ERR_FATAL_SIZE   equ     *-ERR_FATAL


blankNewScreen   dc.w    0,0,320,30,1
                 dc.b    0,0
                 dc.w    0
                 dc.w    CUSTOMSCREEN
                 dc.l    0,0,0,0

clockNewWindow   ds.w    0
                 dc.w    280,0
                 dc.w    CLOCK_WIDTH,10
                 dc.b    -1,2
                 dc.l    0
                 dc.l    SMART_REFRESH!NOCAREREFRESH
                 dc.l    0,0,0,0,0
                 dc.w    0,0
                 dc.w    0,0
                 dc.w    WBENCHSCREEN

clockBuffer      dc.b    '00:00',0

clockText        ds.w    0
                 dc.b    3,2
                 dc.b    RP_JAM2,0
                 dc.w    2,1
                 dc.l    0
                 dc.l    clockBuffer
                 dc.l    0




        section data,BSS

workarea         ds.b    work_SIZEOF

        end

