;*************************************************************************
;*
;* Dieses Programm ist Public Domain und wurde mit dem Profimat-Assembler
;* von Data Becker erstellt. Das Kopieren für den privaten
;* Gebrauch ist erlaubt. Sollen das Programm oder Teile daraus für
;* kommerzielle Zwecke verwendet werden, bitte ich darum, sich mit
;* mir in Verbindung zu setzen.
;*
;* © 1988 Richard Englert, Flößaustraße 160, 8510 Fürth, Tel.:0911/708255
;*
;* letzte Änderung: 22-05-1988
;*
;*************************************************************************
;*
;* MouseTool V:  a) bringt Window in den Vordergrund, bei denen
;*                  die Depth-Arrangers nicht mehr erreicht
;*                  werden können.
;*               b) vergrößert Windows auf maximale Größe
;*               c) verkleinert Windows auf minimale Größe
;*               d) schaltet Mauszeiger ein und aus
;*
;* Start von der Workbench.
;* a) Mauszeiger auf Window fahren und beide Mausknöpfe drücken
;*    (den linken zuerst, siehe Listing)
;* b) Mauszeiger auf Window fahren, linken Mausknopf und linke
;*    Amiga- bzw. Commodoretaste drücken
;* c) Mauszeiger auf Window fahren, linken Mausknopf und linke
;*    ALT-Taste drücken
;* d) Mauszeiger auf Window fahren, linken Mausknopf und rechte
;*    ALT-Taste drücken
;*
;* Um MouseTool V aus dem Speicher zu entfernen, linken Maus-
;* knopf und CTRL-Taste drücken.
;*
;*************************************************************************

 INCLUDE 'ram:Amiga.ASM'

; verwendete AmigaDOS-Funktionen

_LVOOpenLibrary   EQU -$0228
_LVOCloseLibrary  EQU -$019e
_LVOWBenchToFront EQU -$0156
_LVOWindowToFront EQU -$0138
_LVOSetTaskPri    EQU -$012c
_LVODelay         EQU -$00c6
_LVOSizeWindow    EQU -$0120
_LVOMoveWindow    EQU -$00a8
_LVOWait          EQU -$013e
_LVOAllocSignal   EQU -$014a
_LVOSetSignal     EQU -$0132
_LVOSignal        EQU -$0144
_LVOAddIntServer  EQU -$00a8
_LVOPermit        EQU -$008a
_LVORemIntServer  EQU -$00ae
_LVOFreeSignal    EQU -$0150
_LVOSetPointer    EQU -$010e

; Konstanten

ActiveWindow   = $34
ActiveScreen   = $38
FirstScreen    = $3c
LeftEdge       = $4
TopEdge        = $6
Width          = $8
Height         = $a
sc_Width       = $c
sc_Height      = $e
MinWidth       = $10
MinHeight      = $12
MaxWidth       = $14
MaxHeight      = $16
NT_INTERRUPT   = $2
INTB_VERTB     = $5
potinp         = $16
custom         = $DFF000
ciaa           = $BFE001
ciasdr         = $C00

;*************************************************************************
;Hauptprogramm:
;*************************************************************************

 INIT_AMIGA

 LEA IntuitionName,A1            ;Intuition Library öffnen
 MOVEQ #0,D0
 CALLSYS OpenLibrary
 MOVE.L D0,IntuitionBase
 BEQ EXIT

 LEA DosName,A1                  ;Dos Library öffnen
 MOVEQ #0,D0
 CALLSYS OpenLibrary
 MOVE.L D0,DosBase
 BEQ EXIT

 LEA GfxName,A1                  ;Graphics Library öffnen
 MOVEQ #0,D0
 CALLSYS OpenLibrary
 MOVE.L D0,GfxBase
 BEQ EXIT

 MOVE.L #0,A1                    ;eigene Task-Struktur finden
 LINKSYS FindTask,ExecBase
 MOVE.L D0,ThisTask

 MOVEQ #-1,D0
 LINKSYS AllocSignal,ExecBase    ;neues Signal finden
 TST.L D0
 BMI CloseLib

 MOVEQ #1,D1
 LSL.L D0,D1
 MOVE.L D1,sig

 MOVEQ #INTB_VERTB,D0            ;neuen Interrupt Server
 LEA IntNode,A1                  ;in System-Liste einfügen
 LINKSYS AddIntServer,ExecBase

Loop:
 MOVE.L sig,D0
 LINKSYS Wait,ExecBase           ;auf Interrupt-Signal warten

 CMP.B #$39,ciaa+ciasdr          ;CONTROL gedrückt
 BEQ EXIT
 CMP.B #$37,ciaa+ciasdr          ;linke ALT gedrückt
 BEQ Small
 CMP.B #$33,ciaa+ciasdr          ;linke SHIFT gedrückt
 BEQ Full
 CMP.B #$35,ciaa+ciasdr          ;rechte ALT gedrückt
 BEQ ToggleMouse
 BTST #10,custom+potinp          ;rechter Mausknopf gedrückt
 BNE loop

ToFront:                         ;beide Maus-Buttoms gedrückt
 BSR Find                        ;Window-Struktur finden
 LINKSYS Forbid,ExecBase
 LINKSYS WindowToFront,IntuitionBase   ;Window nach vorne
 BSR Delay10                           ;für 1/5 s einschläfern
 LINKSYS Permit,ExecBase
 BRA loop                        ;Tastatur abfragen

Full:                            ;Window auf volle Größe
 BSR Find
 LINKSYS Forbid,ExecBase
 MOVE.W sc_Width(A1),D6          ;Screenausmaße X/Y nach D6/D7
 MOVE.W sc_Height(A1),D7
 MOVE.W MaxWidth(A0),D0          ;max. Window-Breite
 CMP.W #-1,D0                    ;unendlich
 BNE weiter1                     ;nein, dann WEITER1
 MOVE.W D6,D0                    ;ja, dann max.Windowbreite=
                                 ;Screenbreite
weiter1:
 MOVE.W MaxHeight(A0),D1         ;max. Window-Höhe
 CMP.W #-1,D1                    ;unedlich
 BNE weiter2                     ;nein, dann WEITER2
 MOVE.W D7,D1                    ;ja, dann max.Windowhöhe=
                                 ;Screenhöhe
weiter2:
 MOVE.W Width(A0),D2             ;Differenz von augenblickl.
 MOVE.W Height(A0),D3            ;Window-Breite/-Höhe und
 SUB.W D2,D0                     ;max. Windowbreite/-Höhe nach
 SUB.W D3,D1                     ;D0/D1
 MOVE.W LeftEdge(A0),D4
 MOVE.W TopEdge(A0),D5
 ADD.W D4,D2
 ADD.W D5,D3
 ADD.W D0,D2
 ADD.W D1,D3
 CMP.W D6,D2                     ;testen,ob max.Größe noch auf
 BGT Move1                       ;Screen paßt.Zu breit,=>MOVE1
 CMP.W D7,D3                     ;Window zu hoch,
 BGT Move1                       ;dann MOVE1

FullSize:
 LINKSYS SizeWindow,IntuitionBase   ;Window vergrößern
 BSR Delay10                        ;für 1/5 s einschläfern
 LINKSYS Permit,ExecBase
 BRA loop

Move1:                           ;Window wäre zu groß
 MOVEM.L D0-D1/A0,-(A7)          ;deshalb muß es zuerst in das
 NEG.W D4                        ;linke obere Eck des Screens
 NEG.W D5                        ;verschoben werden.
 MOVE.W D4,D0                    ;Verschiebung um D0/D1
 MOVE.W D5,D1
 LINKSYS MoveWindow,IntuitionBase  ;Window verschieben
 BSR Delay10                       ;für 1/5 s einschläfern
 MOVEM.L (A7)+,D0-D1/A0          ;alte Registerinhalte holen
 BRA FullSize                    ;Window vergrößern

Small:                           ;Window auf minimale Größe
 BSR Find
 LINKSYS Forbid,ExecBase
 MOVE.W MinWidth(A0),D0
 MOVE.W MinHeight(A0),D1
 MOVE.W Width(A0),D2
 MOVE.W Height(A0),D3
 SUB.W D2,D0                     ;Verkleinerung um D0/D1 (X-/
 SUB.W D3,D1                     ;Y-Richtung)
 LINKSYS SizeWindow,IntuitionBase    ;Window verkleinern
 BSR Delay10                       ;für 1/5 s einschläfern
 LINKSYS Permit,ExecBase
 BRA loop

Find:
 MOVE.L IntuitionBase,A0
 MOVE.L ActiveScreen(A0),A1
 MOVE.L ActiveWindow(A0),A0      ;Aktives Window
 RTS

ToggleMouse:
 MOVE.W Flag,D0                  ;rechte ALT schon mal
 TST D0                          ;gedrückt ?
 BNE MouseOn                     ;nein, ->Mauszeiger ein-
                                 ;schalten

MouseOff:
 MOVE.W #-1,Flag                 ;Flag setzen
 BSR Find
 MOVE.B 78(A0),MouseHeight       ;alte Parameter für Maus-
 MOVE.B 79(A0),MouseWidth        ;zeiger zwischenspeichern
 MOVE.B 80(A0),XOffset
 MOVE.B 81(A0),YOffset
 MOVE.L 74(A0),OldMouseData
 LEA MouseData,A1                ;neue Mauszeigerparameter
 MOVE.L #15,D0                   ;setzen
 MOVE.L #15,D1
 MOVEQ #-1,D2
 MOVEQ #-1,D3
 LINKSYS SetPointer,IntuitionBase   ;und einschalten
 BSR Delay10
 BRA Loop

MouseOn:
 MOVE.W #0,Flag                  ;Flag wieder zurücksetzen
 BSR Find
 MOVE.L OldMouseData,A1          ;gerettete Mauszeiger-
 CLR.L D0
 CLR.L D1
 CLR.L D2                        ;parameter wieder holen
 CLR.L D3
 MOVE.B MouseHeight,D0
 MOVE.B MouseWidth,D1
 MOVE.B XOffset,D2
 MOVE.B YOffset,D3
 LINKSYS SetPointer,IntuitionBase  ;und alten Mauszeiger
 BSR Delay10
 BRA Loop                          ;wieder einschalten

IntCode:                         ;Interrupt Programm
 BTST #6,ciaa                    ;linke Maus-Taste gedrückt
 BNE nono
 MOVEM.L D2-D7/A2-A4,-(SP)
 MOVE.L ThisTask,A1
 MOVE.L sig,D0                ;Signal an Hauptprogramm geben,
 LINKSYS Signal,ExecBase      ;damit es aufwacht
 MOVEM.L (SP)+,D2-D7/A2-A4
nono:
 MOVEQ #0,D0
 RTS

Delay10:                         ;Verzögerungsschleife
 MOVEQ #10,D1                    ;um 10/50 s verzögern
 LINKSYS Delay,DosBase
 RTS

EXIT:                            ;Programm Ende
 MOVEQ #-1,D0
 LINKSYS FreeSignal,ExecBase     ;Signal freigeben
 MOVEQ #INTB_VERTB,D0
 LEA IntNode,A1                  ;Interrupt entfernen
 LINKSYS RemIntServer,ExecBase
CloseLib:
 MOVE.L IntuitionBase,D0         ;Intuition Library schließen
 BEQ.S No_Lib
 MOVE.L D0,A1
 CALLSYS CloseLibrary
 MOVE.L DosBase,D0               ;Dos Library schließen
 BEQ.S No_Lib
 MOVE.L D0,A1
 CALLSYS CloseLibrary
 MOVE.L GfxBase,D0               ;Graphics Library schließen
 BEQ.S No_Lib
 MOVE.L D0,A1
 CALLSYS CloseLibrary
No_Lib:
 EXIT_AMIGA 

 ALIGN
 DATA
IntuitionName:  DC.B 'intuition.library',0
DosName:        DC.B 'dos.library',0
GfxName:        DC.B 'graphics.library',0
 ALIGN
IntName:        DC.B 'MTool',0

 ALIGN.L

IntNode:
                DC.L 0,0
                DC.B NT_INTERRUPT,-60
                DC.L IntName,0,IntCode

 ALIGN
MouseData:      DC.L 0
                DC.L 0,0,0,0,0,0
                DC.L 0,0,0,0,0,0
                DC.L 0,0,0,0,0,0
                DC.L 0,0,0,0,0,0
                DC.L 0,0,0,0,0,0
                DC.L 0

 BSS
IntuitionBase:  DS.L 1
DosBase:        DS.L 1
GfxBase:        DS.L 1
ThisTask:       DS.L 1
sig:            DS.L 1
MouseHeight:    DS.L 1
MouseWidth:     DS.L 1
XOffset:        DS.L 1
YOffset:        DS.L 1
OldMouseData:   DS.L 1
Flag:           DS.W 1

 END

