Wer schon einmal mit PCs gearbeitet hat, kennt sie: Hotkeys — Tastenkombinationen, mit denen sich langwierige Mausaktionen auf einen Wimpernschlag reduzieren lassen.
Short-Cuts haben leider den Nachteil, daß sie nur während der Laufzeit eines Programms abrufbar sind. Es gibt nur wenige pro-grammübergreifende Utilities. Dabei handelt es sich zum größten Teil um Accessories, die über einen »evnt_button« Sondertasten abfragen. Da die Anzahl dieser Tasten begrenzt ist (zwei Shift-, eine Alternate und eine Control-Taste), kommt es leicht zu Kollisionen. Will man z.B. eine Kompilierung mit Shift-Shift unterbrechen, kann es passieren, daß gleichzeitig auch die Festplatte parkt.
Wir stellen hier ein Programm vor, das eigene Funktionen auf beliebige Tastenkombinationen legt — soweit es der ST/TT eben gestattet. Jede Routine ist unabhängig von den anderen Programmteilen lauffähig und kann in eigene Programme eingebunden werden. Dazu hängt man zuerst den Assemblersource an HOTKEY. Dann trägt man in der Tabelle »HOTKEYS« den Tastencode ein. Für Experten: Es handelt sich um das obere Wort, das Bconin(2) bei gesetztem 3. Bit in conterm zurückgibt, also Sondertasten und Scancode. Man beachte dabei die Endmarke Null. Außerdem wird in der Tabelle »ROUTINEN« — dort, wo der Tastencode steht — die Adresse der neuen Routine eingefügt.
Ein Tastendruck löst nun einen (ACIA-) Interrupt aus. Dabei werden die Informationen zu dieser Taste (Sondertasten, Scan- und ASCII-Code) ermittelt. Dies geschieht in einem Ringspeicher mit der Funktion Iorec (XBIOS(14,1)). Bleibt die Taste über längere Zeit gedrückt, setzt die Tastenwiederholung ein. In diesem Fall werden die Tasten-Informationen nicht im ACIA-Interrupt gespeichert, sondern im Timer C, einem 200-Hz-Zähler.
Nun speichert das Programm die Adresse der Iorec-Struktur. Bei der Installation von Hotkey werden die Vektoren des ACIA-Interrupts und Timer C auf die eigenen Routinen gebogen. Schließlich wird das Programm resident verlassen, d.h. es bleibt im Speicher. Jeder Tastendruck führt dann in eine eigene Routine, die zuerst mal alle Register rettet. Dann holt sie sich die Position des Schreibzeigers aus der Iorec-Struktur. Nachdem eine der Originalroutinen aufgerufen wurde, vergleicht das Programm die nun alte Position des Schreibzeigers mit der aktuellen. Differieren sie, hat der Zeiger sich also bewegt, wurde eine Taste gedrückt und deren Tastencode im Ringspeicher abgelegt. Der für uns relevante Teil — das obere Wort — wird aus dem Buffer gelesen und mit den in Tabelle Hotkey aufgeführten Werten verglichen. Wird beim Vergleich die Endmarke Null erreicht, handelt es sich nicht um einen Hotkey — der Tastendruck wird ignoriert. Andernfalls wird die Taste aus dem Buffer gelöscht. Ist die entsprechende Routine ausgeführt, werden alle Register restauriert und die Exception mit einem RTE verlassen.
Leider kann man nicht alle Utilities in Hotkey installieren. Das fangt bei TOS-Programmen an, die ja GEM nicht nutzen. Auch bei TOS-Routinen ist Vorsicht geboten! TOS ist nicht reentrant. Auch GDOS scheint sich mit Hotkey nicht ganz zu vertragen: Startet man beide im AUTO-Ordner, führt dies zum Absturz. (mn)
; *********************************
; * HOTKEY *
; * *
; * by Michael Krusemark *
; * Ravensburger Str.44 *
; * 7900 Ulm - 11 *
; *********************************
RSHT EQU $0100 ; Codes der Sondertasten
LSHT EQU $0200 ; müssen auf Scancode
CNTR EQU $0400 ; addiert werden
ALT EQU $0800
BUF EQU 0 ; Offsets der
SIZ EQU 4 ; lorec-Structur
TL EQU 8
START: pea LOGO(PC) ; Logo
move.w #9,-(SP) ; mit Cconws
trap #1 ; ausgeben
addq.l #6,SP
move.w #1,-(SP) ; Iorec für Tastatur
move.w #$0E,-(SP) ; holen
trap #14
addq.l #4,SP
move.l D0,IOREC ; Adresse der Struktur sichern
pea INSTALL(PC) ; Hotkey
move.w #$26,-(SP) ; im Supervisor-Modus
trap #14 ; installieren
addq.l #6,SP
clr.w -(SP) ; HOTKEY resident
move.l #ENDE-START+256,-(SP)
move.w #$31,-(SP) ; verlassen
trap #1
INSTALL: lea HZ200(PC),A0 ; Vektor für
lea $0114,A1 ; Timer C
move.l (A1),(A0)+ ; (200 Hz Zähler)
move.l A0,(A1) ; verbiegen
lea ACIA(PC),A0 ; das gleiche
lea $0118,A1 ; auch mit
move.l (A1),(A0)+ ; dem
move.l A0,(A1) ; ACIA-Interrupt
rts ; HOTKEY ist nun installiert
DC.L 'XBRA' ; XBRA-Protokoll
DC.L 'HTKY' ; ID
ACIA: DS.L 1 ; alter ACIA-Vektor
movem.l D0-A6,-(SP) ; Register retten
movea.l IOREC(PC),A0 ; Adresse von Iorec der Tastatur
move.w TL(A0),D3 ; altes Tail
movea.l ACIA(PC),A1 ; Adresse der orginal ACIA-Routine
bra.s EXCEPT ; Exception simulieren
DC.L 'XBRA’ ; XBRA-Protokoll
DC.L 'HTKY' ; ID von HoTKeY
HZ200: DS.L 1 ; alter Timer C-Vekior
movem.l D0-A6,-(SP) ; regiser retten
movea.l IOREC(PC),A0 ; Adresse von Iorcc
move.w TL(A0,D3 ; altes Tail
movea.l HZ200(PC),A1 ; Adresse der orginal Timer-Routine
bset #3,$0484.w ; Sondertasten beachten
EXCEPT: pea WEITER(PC) ; Rücksprungadrcsse
move SR,-(SP) ; Statusregister
pea (A1) ; Exception
rts ; simulieren
WEITER: move.w TL(A0),D0 ; neues Tail
cmp.w D0,D3 ; gleich altes Tail
beq.s EXIT ; dann wurde nichts eingegeben
movea.l BUF(A0),A1 ; Adresse des Ringbuffers
move.w 0(A1,D0.w),D1 ; Zeichen holen
lea HOTKEYS(PC),A2; Tabelle der Hotkeys
lea ROUTINEN(PC),A1; Tabelle der Routinen
SEARCH: movea.l (A1)+,A3 ; Sprungadresse
move.w (A2)+,D2 ; Hotkey aus Tabelle
beq.s EXIT ; Endmarke?, dann raus
sub.w D1,D2 ; wenn nicht gleich,
bne.s SEARCH ; dann weiter suchen
move.w D3,TL(A0) ; Zeichen aus Buffer löschen
jsr (A3) ; Zeichen war Hotkey, also springen
EXIT: movem.l (SP)+,D0-A6 ; Register restaurieren
rte ; ReTurn from Exception
BLACK: bchg #0,$FFFF820A.w ; Monitor an/aus
rts
HDPARK: st $043E.w ; Flock setzen
bne.s HAVE_PARKED ; Flock!=0, dann HD nicht parken
moveq #20,D7 ; Zeit für Timeout
lea $FFFF8604.w,A0 ; disketr
move.w #$88,2(A0) ; DMA-Betrieb
move.l #$1B0088,(A0) ; (START/)STOP-UNIT
bsr.s WARTE ; Claus Brod's Zeiteisen
move.w #2,D3 ; 3X 0L auf DMA
WR_CMD: move.l #$8A,(A0) ; ausgeben
bsr.s WARTE ; und wieder warten
dbra D3,WR_CMD
move.l #$8A,(A0) ; STOP-UNIT
bsr.s WARTE ; schon wieder warten
move.l #$0A,(A0) ; jetzt geht's bei der HD erst los
move.l #800,D7 ; deshalb lassen wir ihr
bsr.s WARTE ; jetzt etwas mehr Zeit
HAVE_PARKED: clr.w $043E.w ; Flock löschen
rts ; HD müßte geparkt sein
WARTE: add.l D7,D0 ; Zeit bis Timeout
WAIT: btst #5,$FFFFFA01.w ; HDC-lnterrupt?
beq.s READY ; ja, dann fertig
cmp.l $04BA.w,D0 ; Zeit abgelaufen?
bne.s WAIT ; nein, dann noch warten
addq.l #4,SP ; TIMEOUT, es stimmt was nicht
bra.s HAVE_PARKED ; dann lassen wir 's besser
READY: rts ; kein Timeout
WARM: movea.l $04F2.w,A0 ; OS-Start
jmp (A0) ; in Reset springen
; Warmstart
KALT: clr.w $0420.w ; ein Magic löschen
movea.l $04F2.w,A0 ; OS-Start
jmp (A0) ; Reset (Kaltstart)
CHANGEHZ: bchg #1,$FFFF820A.w
rts
INVERS: bchg #0,$FFFF8240.w
rts
DATA
; Tabelle der Hotkeys
HOTKEYS: DC.W CNTR+ALT+25 ; ^ALT P
DC.W CNTR+ALT+48 ; ^ALT B
DC.W CNTR+ALT+83 ; ^ALT Delete
DC.W CNTR+ALT+RSHT+83 ; ^ALT RShift Delete
DC.W CNTR+ALT+46 ; ^ALT C
DC.W CNTR+ALT+23 ; ^ALT+I
; Sondertaste+Scancode
DC.W 0 ; Endmarke
; Tabelle der Routinen
ROUTINEN: DC.L HDPARK,BLACK,WARM,KALT,CHANGEHZ,INVERS
LOGO: DC.B 13,10
DC.B '************************************ ' ,13,10
DC.B '* HOTKEYS installiert * ' ,13,10
DC.B '* by Michael Krusemark * ' ,13,10
DC.B '* Ravensburger Str.44 * ' ,13,10
DC.B '* 7900 Ulm-11 * ' ,13,10
DC.B '************************************ ' ,13,10, 0
BSS
IOREC: DS.L 1
ENDE:
END