Das Desktop bietet bisher die Möglichkeit, mehrere Dateien oder Icons zu selektieren. dabei muss man bei gedrückter Shift-Taste die Dateien mit dem Mauszeiger anklicken. Ab TOS 1.4 kann man Dateien auch verschieben, das heißt, die Quelldatei wird kopiert und anschliessend gelöscht. Sollen Dateien verschoben werden, muss die Control-Taste gedrückt sein. Wollte man bisher mehrere Dateien verschieben, musste man die Control- und Shift-Taste drücken und die Dateien mit dem Mauszeiger selektieren. Das Programm Control-Shift-Maus ( CS-Maus) ermöglicht jetzt mit Hilfe der rechten Maustaste ein Verschieben oder Kopieren von einzelnen oder mehreren Dateien ohne zusätzliches Drücken der Shift-oder Control-Taste.
Sollen mit CS-Maus mehrere Dateien ausgewählt werden, muß man anstelle der Shift-Taste die rechte Maustaste drücken. Beim Verschieben von Dateien wird auch die Control-Taste durch die rechte Maustaste ersetzt. Das Selektieren der Datei geschieht wie bisher mit einem Klick der linken Maustaste. Will man mit CS-Maus mehrere Dateien verschieben, drückt man einfach die rechte Maustaste wählt die Dateien aus und verschiebt sie bei gedrückter rechter Maustaste in das Zielverzeichnis. Das Selektieren oder Verschieben mehrerer Dateien ist wie bisher mit der Shift-oder Control-Taste möglich. Auch das Kopieren von einem nicht aktiven Fenster in das aktive bei gedrückter rechter Maustaste ist wie bisher möglich.
CS-Maus kann man aus dem Auto-Ordner starten oder direkt vom Desktop. Will man CS-Maus ausschalten, muß das Programm ein zweites Mal gestartet werden. Es wird dann die Meldung ‘CS-Maus AUS’ ausgegeben. Das Einschalten geschieht durch ein erneutes Starten des Programms. CS-Maus ist nur im Desktop aktiv; sobald ein Programm gestartet wird, schaltet es sich selber aus.
Nun zur Beschreibung des Listings. Das Programm springt zuerst zur Installierungsroutine (INSTALL). Dort werden eine neue Mausroutine installiert und die Adressen von kbshift und run geholt. Die Routine Kbdvbase (XBIOS 34) liefert einen Zeiger auf die KBDVECS-Struktur. In dieser Struktur ist der Mausvektor (.mousevec) enthalten. Das Betriebssystem springt bei jeder Mausbewegung durch diesen Vektor. Da CS-Maus die neue Mausroutine mit dem XBRA-Protokoll anmeldet, kann es auch feststellen, ob CS-Maus schon installiert ist. Eine Verfolgung der Kette ist nur dann möglich, wenn sich jede neue Mausroutine an das XBRA-Protokoll hält. War CS-Maus schon installiert, wird das Programm ein- oder ausgeschaltet. Dazu wird das Flag MAUS-OFF invertiert. Dieses befindet sich 13 Bytes hinter der schon installierten Mausroutine. War die Installation erfolgreich, werden die neue Mausroutine (NEW_MOUSE) und die VBL-Routine (NEU_VBL) resident im Speicher gehalten.
Wird CS-Maus zum ersten Mal installiert, muß zwischen einem Start aus dem Auto-Ordner und einem vom Desktop unterschieden werden. Deshalb wird versucht, eine Applikation anzumelden (APPL_INIT AES 10). Wird CS-Maus aus dem Auto-Ordner gestartet, ist die ap_version gleich Null, da das AES noch nicht initialisiert ist. Bei einem Start vom Desktop wird der alte Mausvektor in OLD -VEC gespeichert und die Adresse der neuen Mausroutine in die KBDVECS-Struktur eingetragen. Da der Mausvektor erst nach dem Starten aller Programme aus dem Auto-Ordner belegt wird, muß man bei einem Start von CS-Maus aus dem Auto-Ordner anders Vorgehen. Dabei wird eine VBL-Routine {NEU_VBL) installiert. Diese wartet jetzt solange, bis der Mausvektor überschrieben wird. Ist dies der Fall, wird wie beim Starten vom Desktop der alte Mausvektor in OLD_VEC gespeichert und die Adresse der neuen Mausroutine in die KB-DVECS-Struktur eingetragen. Danach wird die VBL-Routine gelöscht.
Aufbau eines Mauspaketes
Die Zeiger j-un und kbshift sind in der SYSHDR-Struktur abgelegt. Das ist aber erst ab TOS 1.2 der Fall. Bei älteren TOS-Versionen liegen jun bei $602C und kbshift bei $E1B. Den Zeiger auf die SYSHDR-Struktur erhält man durch die Systemvariable _sysbase ($4-f2). _run enthält die Adresse des Zeigers der aktuellen Basepage. Die Länge des Programmcodes ist mit einem Offset von $C in der Basepage abgelegt. Ist die Länge des Programmcodes gleich Null, ist das aktuelle Programm das Desktop. _run wird dazu benutzt, CS-Maus auszuschalten, wenn ein Programm gestartet wird. Der Zeiger kbshift zeigt auf ein Byte, in dem der Tastaturstatus abgelegt ist. Dabei entspricht Bit 0 der rechten Shift-Taste und Bit 2 der Control-Taste. Man kann den Tastaturstatus auslesen oder setzen.
Der Tastaturprozessor schickt bei jeder Mausbewegung Pakete zur Mausroutine. Diese Mauspakete bestehen aus drei Bytes, deren Adresse ist im Register A0 enthalten. Das erste Byte enthält den Header. In diesem Byte ist der Status der Mausknöpfe abgelegt. Dabei entspricht B it 0 der rechten und Bit 1 der linken Maustaste. Ist eine Taste gedrückt, ist das entsprechende Bit gesetzt. Der Wert des Headers liegt bei Mausbewegungen von $F8 bis $FB. Die relative Mausbewegung in x-Richtung enthält das zweite Byte. Die Mausbewegung in y-Richtung ist im dritten Byte enthalten. Die neue Mausroutine, die nach der erfolgreichen Installation jetzt jedes Mauspaket zuerst erhält, benötigt nur das erste Byte.
Die neue Mausroutine testet zuerst, ob ein Mauspaket angekommen ist; danach, ob CS-Maus ein- oder ausgeschaltet ist. Wenn der Programmcode gleich Null ist (Desktop aktiv), wird der Maus-Header auf einen rechten Mausdruck getestet. Ist dies der Fall, wird der Zeiger auf den Tastaturstatus geholt. Nun setzt man Bit 0 (Shift) und Bit 2 (Control). Die beiden Bits werden gelöscht, sobald eine Mausbewegung erfolgt, bei der nicht die rechte Maustaste gedrückt ist. Auch wenn das aktuelle Programm nicht mehr das Desktop ist, werden die Bits gelöscht.
Literatur:
[1] Atari ST Profibuch, Sybex
[2] ST Computer 6/90, Seite 83, Springmaus
Bit 0: Shift-Taste rechts *
Bit 1: Shift-Taste links Bit 2: Control-Taste *
Bit 3: Alternate-Taste
Bit 4: Caps Lock gesetzt
Bit 5: Maustaste rechts (Clr Home)
Bit 6: Maustaste links (Insert)
Bit 7: reserviert
Offset | Bezeichnung | Beschreibung |
---|---|---|
0 | os_entry | Einsprungadresse |
2 | os_version | TOS-Version * |
4 | os_start | Startadresse des OS-Codes |
8 | os_base | Anfangsadresse des Betriebssystems |
12 | os_membot | Beginn des freien RAM |
16 | os_shell | Default Shell |
20 | os_magic | Zeiger auf GEM-Magic-Variable |
24 | os_gendat | Erstellungsdatum BCD-Format |
28 | os_palmode | PAL oder NTSC |
30 | os_gendatg | Erstellungsdatum GEMDOS-Format |
Folgende Variablen erst ab TOS 1.2
32 | *_root | Zeiger auf ‘mifl'-Liste |
36 | kbshift | Zeiger auf Bit-Belegung des Tastaturstatus * |
40 | **_run | Zeiger auf aktuelle Basepage * |
Belegung der SYSHDR-Struktur
*-------------------------*
* Control-Shift-Maus *
* by Ralf Stachs *
* ------------------------*
* (c) 1991 MAXON Computer *
* ------------------------*
;TRAPS
GEMDOS equ 1
BIOS equ 13
XBIOS equ 14
*******************************************
;Programmteil der resident im Speicher
;gehalten wird v. RESI_ANFANG bis RESI_ENDE
*******************************************
TEXT
RESI_ANFANG:
bra INSTALL
;zur Installationroutine springen
;Flags
******
;FIRST ->Rechte Maustaste zum ersten mal gedruckt
; 0->Rechte Maustaste noch nicht gedrückt
; 1->Rechte Maustaste war schon gedrückt
;MAUS_OFF ->schaltet CS_Maus an oder aus
; $00 CS_Maus an
; $FF CS_MAUS aus
FIRST: dc.b 0
MAOS_OFF: dc.b 0
dc.b "XBRA” ;XBRA Protokoll
dc.b "RS11" ;eigene Kennung
0LD_VEC: dc.l 0 ;alter Mausvektor
;neue Mausroutine
*****************
NEW_MOUSE:
movem.l d0/a0-a2,-(sp) ;Register retten
;Maus Header?
move.b (a0),d0 ;Header Kopf in d0
cmp.b #$f8,d0 ;kleiner $f8
blt ENDE ;ja
cmp.b #$fb,d0 ;größer $fb
bgt ENDE ;ja
;Maus ausgeschaltet TOS?
move.l A_MOUSE_FLAG,a1 ;Flag für Maus aus (MOUSE_FLAG)
tst.b (a1) ;Maus ausgeschaltet
bne ENDE ;ja
;CS_Maus ausgeschaltet7
tst.b MAUS_OFF ;CS_MAUS ausgeschaltet
bne ENDE ;ja
;aktuelles PRG Desktop?
move.l A_RUN,a1 ;a1=Adresse auf Zeiger der aktuellen Basepage
move.l (a1),a2 ;a2=Zeiger auf Basepage
tst.l $C(a2) ;Länge des Programmcode = 0
bne SP_11 ;nein, nicht Desktop
;Rechte Maustaste gedrückt
btst.b #0,(a0) ;rechte Maustaste gedrückt
beq SP_11 ;nein, Flags und Tasten löschen
;wenn FIRST noch gesetzt
;Rechte Maustaste zum ersten mal gedrückt
tst.b FIRST ;zum ersten mal
bne ENDE ;nein
;Control und Shift Taste setzen
move.l A_KBSHIFT,a1 ;Adresse von Kbshift in a1
or.b #%00000101,(a1) ;Control Taste (Bit 2) setzen
;und Shift Taste (Bit 0) setzen
move.b #1,FIRST ;Flag setzen
bra ENDE
;Control und Shift Taste löschen
SP_11: tst.b FIRST ;First Flag noch gesetzt
beq ENDE ;Nein, dann Ende
move.l A_KBSHIFT,a1 ;Adresse von Kbshift in a1
and.b #%11111010,(a1) ;Control-Taste (Bit 2) löschen
;und Shift Taste (Bit 0) löschen
move.b #0,FIRST ;Flag löschen
;alte Mausroutine anspringen
ENDE: movem.l (sp)+,d0/a0-a2 ;Register zurückschreiben
move.l OLD_VEC,-(sp) ;alte Mausroutine
rts ;anspringen
;VBL-Routine bei Start aus AUTO-Ordner
**************************************
dc.b "XBRA" ;XBRA Protokoll
dc.b "RS12" ;eigene Kennung
dc.l 0 ;alter Vektor nicht benutzt
NEU_VBL:
move.l A_KBDV,a0 ;kdbv Adresse nach a0
lea 16(a0),a1 ;Adresse Mausvektor a1
lea OLD_VEC,a0 ;alter Mausvektor vom Betriebssystem
cmp.l (a0)+,(a1)+ ;alter Mausvektor noch da
beq SP_3 ;ja
move.l -(a1),OLD_VEC ;alten Mausvektor sichern
move.l #NEW_MOUSE,(a1) ;neue Mausroutine initialisieren
move.l A_VBL_SLOT,a0 ;vbl-Slot löschen
move.l #0,(a0)
SP_3: rts
;Adressen
*********
;A_KBDV -> Adresse der kbdv Tabelle
;A_VBL_SLOT -> Adresse des VBL-Slot
;A_MOUSE_FLAG -> Adresse von MOUSE_FLAG
; MOUSE_FLAG = 0 ->Maus-Interuptbehandlung ein
; MOUSE_FLAG <>0 ->Maus-Interuptbehandlung aus
;A_KBSHIFT -> Adresse von Kbshift
;A_RUN -> Adresse von Zeiger auf aktueller Basepage
A_KBDV: dc.l 0
A_VBL_SLOT: dc.l 0
A_MOUSE_FLAG: dc.l 0
A_KBSHIFT: dc.l 0
A_RUN : dc.l 0
RESI_ENDE:
*************************
;Instalierung von CS_Maus
*************************
;gesammten Programmspeicher belegen
EVEN
INSTALL:
move.l sp,a6 ;Adresse BASEPAGE
lea USTACK,sp ;neuer Stack
move.l 4(a6),a6 ;Speicher belegen
move.l $c(a6),a4
adda.l $14(a6),a4
adda.l $1c(a6),a4
pea 256(a4)
pea (a6)
clr.w -(sp)
move.w #74,-(sp) ;Mshrink aufrufen
trap #GEMD0S
lea 12(sp),sp
;Adresse KBDVECS holen
move #34,-(a7) ;Kbdvbase aufrufen
trap #XBIOS
addq.l #2,a7
move.l d0,A_KBDV ;Adresse der Vektortabelle sichern
;CS_Maus schon installiert?
move.l A_KBDV,a1 ;Adresse der Vektortabelle nach a1
move.l 16(a1),a2 ;Adresse von Mausroutine in a2
move.l a2,a0 ;a0 zum suchen
SP_1: cmp.l #"RS11",-8(a0) ;CS_Maus schon vorhanden
beq SP_2 ;ja, CS_MAUS init.
cmp.l #"XBRA",-12(a0) ;XBRA Kennung
bne SP_4 ;CS_Maus installieren
;Original Mausvektor oder kein XBRA Protokoll
move.l -4(a0),a1 ;Adresse der nächsten Mausroutine
move.l a1,a0 ;von a1 nach a0
bra SP_1 ;weiter
;CS_Maus war schon installiert
*****************************
SP_2: not.b -13(a0) ;MAUS_OFF invertieren
bne SP_7
;Meldung CS_Maus einschalten
pea STRING_3
move.w #9,-(sp)
trap #GEMDOS
addq.l #6,sp
bra SP_8 ;ende
;Meldung CS_Maus auschalten
SP_7: pea STRING_4
move.w #9,-(sp)
trap #GEMDOS
addq.l #6,sp
;PRG beenden
SP_8: clr.w -(sp) trap #GEMDOS
;CS_MAUS instalieren
********************
;alten Vektor sichern
SP_4: lea OLD_VEC,a0
move.l a2,(a0)
;AES-anmelden
move.w #10,d0 ;Applikation anmelden
bsr AES_INIT ;AES aufrufen
tst.w AES_GLOBAL ;starten aus AUTO-Ordner
beq SP_6 ;ja, keine ap_version
;Vom Desktop starten
********************
;maus installieren
lea DESKTOP,a0 ;Adresse von Desktop nach a0
pea (a0)
move.w #38,-(sp) ;Supexec aufrufen
trap #XBIOS
addq.l #6,sp
bra SP_5
;Aus AUTO-Ordner starten
************************
;Unterprogramm im Supervisor-Modus ausführen
SP_6: lea AUTO,a0 ;Adresse von auto nach a0
pea (a0)
move.w #$26,-(sp) ;Supexec aufrufen
trap #XBIOS
addq.l #6,sp
;Adresse von MOUSE_FLAG holen
SP_5: dc.w $a000 ;Adresse negative Line-A Variabelen
sub.l #$153,a0 ;Adresse MOUSE-FLAG berechnen
move.l a0,A_MOUSE_FLAG ;MOUSE FLAG merken
;installierung i.o.
pea STRING_1
move.w #9,-(sp)
trap #GEMDOS
addq.l #6,sp
;Speicherplatz für Mausroutine
;resident im Speicher halten
clr.w -(sp)
pea RESI_ENDE-RESI_ANFANG+256
move.w #49,-(a7) ;Ptermres aufrufen
trap #GEMDOS
***************************
;Unterprogramme von CS_MAUS
***************************
;PRG im Supervisor-Modus Mausroutine installieren
*******************************************
;starten aus AUTO Ordner
;VBL installieren
AUTO: move.w $454,d0 ;Anzahl der VBL-Routinen (nvbls)
lsl #2,d0 ;Anzahl*4
move.l $456,a0 ;Zeiger auf VBL (_vblqueue)
clr d1 ;Zähler
WEITER: tst.l 4(a0,d1) ;VBL Slot frei
beq FREI ;ja
add #4,d1 ;nächster Slotpointer
cmp.w d0,d1 ;alle slots abgefragt
bne WEITER
;CS_Maus nicht initialisieren
pea STRING_2 ;Alle Slots besetzt
move.w #9,-(sp)
trap #GEMDOS
addq.l #6,sp
clr.w -(sp) ;PRG beenden
trap #GEMDOS
FREI: lea 4(a0,d1),a2 ;Adresse Slot in a2
lea NEU_VBL,a1 ;Adresse neue Routine
move.l a1,(a2) ;neue Routine einhängen
lea A_VBL_SLOT,a1 ;Slot Adresse
move.l a2,(a1) ;sichern
;Adresse von Kbshift ermitteln und
;Adresse von Zeiger auf aktueller Basepage
SP_10: move.l #$e1b,A_KBSHIFT ;Vorgabe für TOS 1.0 (Kbshift)
move.l #$602c,A_RUN ;Vorgabe für TOS 1.0 (Basepage)
move.l $4f2,a0 ;(a0) _sysbase
cmp.w #$0100,2(a0) ;TOS 1 0
beq SP_9 ;ja
move.l 36(a0),a1 ;(a1) Adresse von Kbshift
move.l a1,A_KBSHIFT ;Adresse merken
move.l 40(a0),a1 ;(a1) Adresse auf Zeiger der aktuellen Basepage
move.l a1,A_RUN ;Adresse merken
SP_9: rts
;PRG im Supervisor-Modus Mausroutine instal1ieren
*******************************************
;Starten vom Desktop
DESKTOP:
move.l A_KBDV,a0 ;Keyboardadresse nach a0
lea NEW_MOUSE,a1 ;Adresse neue Mausroutine
move.l a1,16(a0) ;neuen Vektor setzen
;Kbshift und Zeiger auf
bra SP_10 ;aktueller Basepage ermitteln
;AES aufrufen
*************
AES_INIT:
lea CONTRL,a0 ;Adresse CONTRL nach a0
move.w d0,(a0)+ ;Opcode
clr.w (a0)+ ;einträge INIT_IN
move.w #1,(a0) ;einträge INIT_OUT
clr.w (a0)+ ;einträge ADDR_IN
clr.w (a0) ;einträge ADDR_OUT
move.l #AES_DATA,d1 ;Adresse AES-Array
move.w #$c8,d0 ;AES-Aufruf
trap #2
rts
DATA
EVEN
STRING_1:
dc.b 27,"E",27,"p"
dc.b 13,10,"+***************************+"
dc.b 13,10,"+ +"
dc.b 13,10,"+ Control-Shift-Maus 1.0 +"
dc.b 13,10,"+ CS_MAUS +"
dc.b 13,10,"+ +"
dc.b 13,10,"+ 7/91 Ralf Stachs +"
dc.b 13,10,”+ ST Computer +"
dc.b 13,10,"+ +"
dc.b 13,10,"+***************************+"
dc.b 13,10
dc.b 27,"q",0
EVEN
STRING_2:
dc.b 13,10,"Alle VBL-Slots besetzt",13, 10,0
EVEN
STRING_3:
dc.b 27,"E"
dc.b 13,10,"*****************"
dc.b 13,10,"* CS_MAUS EIN *"
dc.b 13,10,"*****************",0
EVEN
STRING_4:
dc.b 27,"E",27,"p"
dc.b 13,10,"*****************"
dc.b 13,10,"* CS_MAUS AUS *"
dc.b 13,10,"*****************"
dc.b 27,"q",0
EVEN
AES_DATA:
dc.l CONTRL
dc.l AES_GLOBAL
dc.l INIT_IN
dc.l INIT_OUT
dc.l ADDR_IN
dc.l ADDR_OUT
BSS
AES_GLOBAL: ds.w 15
CONTRL: ds.w 10
INIT_IN: ds.w 128
INIT_OUT: ds.w 128
ADDR_IN: ds.l 128
ADDR_OUT: ds.l 128
ds.b 100
USTACK: ds.w 0