← ST-Computer 12 / 1991

Control-Shift-Maus

Programmierpraxis

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.

Installation

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.

Neue Mausroutine

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

  1. Byte Header von $F8 bis $FB *
  2. Byte Mausbewegung in x-Richtung
  3. Byte Mausbewegung in y-Richtung
  • wird von CS-Maus benutzt

_run und kbshift

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.

Mauspakete

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.

Shift und Control

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-Belegung des Tastaturstatus’**

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

  • wird von CS-Maus benutzt
Offset | Bezeichnung | Beschreibung ------ | ----------- | ------------ 0 | midivec | Midi-Eingabe 4 | vkbderr | Tastaturfehler 8 | vmiderr | Midi-Fehler 12 | statvec | Status von IKBD lesen 16 | mousevec | Mausabfrage * 20 | clockvec | Uhrzeitabfrage 24 | joyvec | Joystick-Abfrage 28 | midisys | Midi-Systemvektor 32 | ikbdsys | | KBD-Systemvektor
**Belegung der KBDVECS-Struktur**
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
Ralf Stachs