Schon wieder ein Programm, mit dem die Tastaturbelegung geändert werden kann, werden Sie vielleicht fragen. Dieses arbeitet allerdings etwas anders als üblich und ist auch anders programmiert. Der Interrupt-Programmierer wird hoffentlich einige Anregungen finden.
Die meisten Programme dieser Art legen die sonst nicht erreichbaren Sonderzeichen des ATARI-Zeichensatzes auf bestimmte Tastenkombinationen mit ALT, CTRL, usw. oder schalten die Tastatur komplett um. Das hat den Nachteil, daß man Tastaturbelegungstabellen im Kopf oder vor sich liegen haben muß.
Viele Zeichen kann man sich aber aus zwei anderen zusammengesetzt denken, so z.B. die Buchstaben mit Akzenten (á, à, usw.). Quasi durch Zusammensetzen kann man solche Zeichen mit dem Programm EXTKEY auf den Bildschirm bringen. Dazu gibt man zunächst das “Hauptzeichen” (z.B. ‘a’) ein, danach drückt man CTRL zusammen mit dem “Nebenzeichen” (z.B. CTRL-'~’), und schon sieht man ein ‘ã’ vor sich. Bei geshifteten Nebenzeichen muß SHIFT-CTRL betätigt werden (z.B. ergeben 'i' und SHIFT-CTRL-’^’ ein î).
Dieses Verfahren bietet sich auch bei einigen mathematischen Symbolen an. Mit EXTKEY sind alle Zeichen, die in Tabelle 1 stehen, auf diese Weise erreichbar (zu jedem Nebenzeichen sind die erzeugbaren Sonderzeichen angegeben)
´ : á, é, í, ó, ú, É
` : à, è, ì, ò, ù, À
^ (Dach) : â, ê, î, ô, û
: (Doppelp.): ä, ë, ï, ö, ü, ÿ, Ä, Ö, Ü
~ (Tilde) : ã, ñ, õ, Ã, Ñ, Õ
BACKSPACE : æ, ÿ, , Æ, Y (Hauptzeichen sind a,i,o,..)
, (Komma) : ç, Ç
. (Punkt) : å, Å
/ : |, \
- (Minus) : £, Ø
_ (Unterst.): ±, =, ä , a , a
Tab. 1: Diese Zeichen sind durch EXTKEY auf einfache Art und Weise zu erreichen
Damit dürfte das Schreiben in Fremdsprachen zum Kinderspiel werden. Die anderen Zeichen, bei denen mir keine Idee kam, wie man sie zusammensetzen könnte, sind über ALT oder SHIFT-ALT in Kombination mit “normalen” Tasten erreichbar. Dabei wurde auf eine sinnvolle Belegung geachtet, aber hier hat ja jeder seine eigenen Ansichten, was vernünftig ist.
EXTKEY läuft problemlos mit WORDPLUS, TEMPUS, MEGAMAX-Editor, GFA-BASIC (Input-Befehl) und sogar mit TEMPELMON. Auch in GEM-Dialogboxen gibt es keine Schwierigkeiten.
Bei Programmen, die bestimmte Tastenkombinationen für eigene Zwecke benutzen (wie etwa TEMPUS), “gewinnt” EXTKEY. Um trotzdem vernünftig arbeiten zu können, kann EXTKEY mit ALT-SHIFT-SHIFT ab- und wieder angeschaltet werden. Auch läuft EXTKEY mit allen TOS-Versionen, da keine unsauberen Zugriffe auf nicht-dokumentierte Systemvariablen gemacht werden.
Das Programm ist voll relokatibel geschrieben, kann also leicht in andere Programme eingebaut werden.
In der Initialisierungsroutine ‘alt_init’ wird EXTKEY im System installiert. Dazu wird der Vektor ‘ikbdsys’ verbogen, und das Programm wird resident im Speicher installiert.
In der ‘ikbdsys'-Routine wird ein vom Tastaturprozessor ausgelöster Interrupt analysiert, wobei dann in die Routinen für Maus-, Tastatur- und Joystick-Behandlung verzweigt wird.
Die ‘ikbdsys’-Routine von EXTKEY (‘kbdrv’) besorgt sich zuerst die Adresse des BIOS-Tastaturpuffers mit der XBIOS-Funktion ‘Iorec’ und merkt sich die Position des ersten Zeichens. Dann wird die Original-ikbdsys-Routine aufgerufen, die nun erst einmal die Hauptarbeit macht. Danach wird überprüft, ob ‘ikbdsys’ etwas in den Tastaturpuffer geschrieben hat. Wenn dies der Fall ist, kann EXTKEY aktiv werden.
ASCII- und Scan-Kode werden untersucht. Ein mit ALT oder ALT-SHIFT erreichtes Zeichen wird einfach über das eingegebene Zeichen in den Tastaturpuffer geschrieben.
Bei der Zusammensetzung mit CTRL wird das eingetippte Nebenzeichen durch ein Backspace ersetzt und das auszugebende Zeichen im Tastaturpuffer angefügt. Da wohl jedes Programm BACKSPACE richtig vergeht, wird es das Hauptzeichen löschen und durch das Sonderzeichen ersetzen.
Damit es keine Konfusionen gibt, müssen Haupt- und Nebenzeichen unmittelbar nacheinander eingegeben werden, sonst wird die Eingabe von EXTKEY ignoriert.
Ein Problem ergab die automatische Tastenwiederholung. Sie wird von einer anderen Interrupt-Routine erledigt (Systemtimer). Da die BIOS-Tastatur-Routine hier bestimmte Variablen setzt, die legal nicht zugänglich sind, würde die Wiederholfunktion falsche Zeichen wiederholen. Daher wird die Tastenwiederholung bei den durch EXTKEY erreichbaren Sonderzeichen abgeschaltet. Bei den normalen Zeichen wird sie wieder aktiviert, dies allerdings immer. Diese Einschränkung dürfte aber nicht allzu gravierend sein.
Wer schon einmal in einer Interrupt-Routine BIOS-Aufrufe gemacht hat, wird sein blaues Wunder erlebt haben. Schuld daran ist ein Fehler im BIOS, der aber umgangen werden kann.
Die Systemvariable ‘savptr’ ($4a2) zeigt auf einen Stack (wächst nach unten), auf dem das BIOS bei jedem Aufruf Prozessor-Register ablegt. Dadurch ist das BIOS “reentrant”, d.h. es kann aus sich selbst heraus auf gerufen werden. Während des Rettens der Register werden die Interrupts allerdings nicht gesperrt, daher kann es passieren, daß bei BIOS-Aufrufen im Interrupt schon gerettete Register in dieser “save area” überschrieben werden.
Eine Möglichkeit, dies zu umgehen, besteht darin, den ‘savptr’ zu Beginn der eigenen Interrupt-Routine herunterzusetzen und am Ende wieder zurück. Dies kann aber zu Konflikten mit anderen Programmen führen, die ebenfalls den ‘savptr’ manipulieren. Eine bessere Möglichkeit (Dank an Thomas!) ist, für die Dauer des Interrupts eine eigene save area einzurichten. Er braucht theoretisch nur für einen BIOS-Aufruf auszureichen, wenn es keine weiteren Verschachtelungen gibt. Sicherheitshalber wurde hier Platz für zwei Aufrufe gelassen. Wenn alle Programme nach diesem Schema verfahren, sollte es keine Komplikationen wie “Programm “A läuft nicht mit Programm B" geben. Zum Aufbau der Tabelle, die das Zusammensetzen steuert (vergleiche Listing).
Dem Scancode des Nebenzeichens folgen ASCII-Codes für Hauptzeichen und Sonderzeichen (immer abwechselnd). Diese Folge wird durch ein Nullbyte beendet. Dann folgt der nächste Nebenzeichen-Scancode usw. Ganz am Ende sind zwei Nullbytes.
;Extended Keyboard macht gesamten
;Atari-Zeichensatz über ALT und CTRL zugänglich
;Tastenbelegung nach Tabellen im Programm
;
;Version 1.2
;15.2.1988
;(C) A.Esser
;
;Systemvariablen
conterm = $484
savptr * $4a2
;BIOS-FunKtionen
kbshift = 11
;XBIOS-Funktionen
iorec = 14
kbdvbase = 34
supexec = 38
;GEMDOS-Funktionen
cconws = $09
ptermres = $31
;Struktur des I/O-Puffer
IBUF = 0
IBUFSIZE= 4
IBUFHD = 6
IBUFTL = 8
;Struktur KBDVECS
IKBDSYS = 32
;Konstanten
SAVSIZE * $2e ;Größe des BIOS-Save-Bereichs
bra alt_init ;installieren
kbdrv:
lea tsavp,A0 ;BIOS-savptr merken
move.l savptr,(A0)
lea endarea,A0 ;und auf eigenen Bereich umsetzen
move.l A0,savptr ;ermöglicht BIOS-Aufrufe im Interrupt
move.w #1,-(A7) ;IOREC für Tastatur holen
move.w #iorec,-(A7)
trap #14
addq.w #4,A7
move.l D0,A0
move.w IBUFTL(A0),-(A7) ;alten Tai1-Index merken
move.l A8,-(A7) ;IOREC-Zeiger merken
move.l oldvec,A0 ;zuerst Standard-IKBD-Routine ausführen
jsr (A0) ;setzt uoraus, daß keine Parameter auf Stack
move.w #-1,-(A7)
move.w #kbshift,-(A7) ;Tastenstatus holen nach D0
trap #13
addq.w #4,A7
move.l (A7)+,A1 ;IOREC-Zeiger zurück
move.w IBUFTL(A1),D2 ;neuer Tail Index
cmp.w (A7)+,D2 ;mit altem vergleichen
beq nokey ;-> keine neue Taste registriert
move.b activ,D1
bne finis ;-> EXTKEY abgeschaltet
move.l IBUF(A1),A2 ;Zeiger auf IO buffer
move.l 0(A2,D2.w),D1 ;letzte Taste (ASCII in 0-7, Scan in 16-23)
move.l D1,D3
move.w D0,D3
swap D3 ;Scan-Code nach 0-7, Status nach 16-23
cmp.b #$78,D3 ;spez. ALT-Scan Code (für 1..0.ß,') ?
bcs.s kbdrv1 ;-> nein
sub.b #$76,D3 ;umrechnen auf norm. Scan-Codes
kbdrv1:
ext.w D3 ;Bit 8-15 (evtl. Tasten-Status) löschen
and.b #$03,D0 ;L-Shift oder R-Shift ?
beq.s kbdrv2 ;-> nicht gedrückt
bset #7,D3 ;"geshifteter Scan-Code"
kbdrv2:
btst #19,D3
beq.s no_alt ;-> ALT nicht gedrückt
lea altt,A0
move.b 0(A0,D3.w),D1 ;Ersatzzeichen aus Tab. für ALT holen
bra.s store ;und fertig
no_alt:
btst #18,D3
beq.s regis ;-> auch kein CTRL: EXTKEY tut nichts
lea ctrlt,A0
look1: ;CTRL-Zeichen in TAB suchen
move.b (A0)+,D0
beq.s regis ;-> kein gültiges CTRL-2eichen
cmp.b D0,D3
beq.s look4 ;-> gefunden
look2:
tst.b (A0)+,D0 ;Infos zu diesem CTRL überlesen
bne.s 1ook2
bra.s look1
look3: ;letztes Zeichen umwandelbar?
addq.l #1,A0 ;Ersatzzeichen überlesen
1ook4:
move.b (A0)+,D0
beq.s regis ;-> CTRL bei diesem Zeichen nicht möglich
cmp.b lastc,D0
bne.s look3
move.b (A0),D1 ;Ersatzzeichen (erst bei 'store' geschrieben)
bclr #26,D1 ;CTRL-Bit löschen
move.l #$0E0008,0(A2,D2.W) ;altes Zeichen durch Backspace ersetzen
addq.w #4,D2 ;Tail-Index erhöhen
emp.w IBUFSIZE(A1),D2 ;Wrap around
bcs.s look5
moveq #0,D2
1ook5:
cmp.w IBUFHD(A1),D2 ;Puffer voll ?
beq.s regis ;-> Abbruch (passiert normalerweise nicht)
move.w D2,IBUFTL(A1) ;neuen Tail-Index speichern
store: ;neues Zeichen in Puffer schreiben
move.l D1,0(A2,D2.w)
bclr #1,conterm ;Repeat aus: sonst falsche Zeichen
regis: ;ASCII-Kode merken (0 falls nicht vorhanden)
lea lastc,A0
move.b D1,(A0)
finis:
move.l tsavp,savptr ;alten BIOS-Savebereich wieder aktivieren
rts ;IKBD-Interrupt fertig
nokey: ;keine Taste gedrückt
bset #1,conterm ;Repeat ein
cmp.b #$0B,D0 ;ALT-SHIFT-SHIFT ?
bne.s finis
lea activ,A0
not.b (A0) ;Umschalten zwischen aktiv/inaktiv
bra.s finis ;fertig
;
oldvec: dc.l 0 ;alter ikbdsys-Uektor
laste: dc.b 0 ;letztes Zeichen (ASCII)
activ: dc.b 0 ;Flag ob EXTKEY inaktiv
tsavp: dc.l 0 ;gemerkter BlOS-savptr
ALIGN
savarea: ds.b 2*SAVSIZE ;sicherheitshalber für 2 BIOS-Aufrufe
endarea:
;
ctrlt: dc.b $0d ;': E,a,e,i,o,u
dc.b $45.$90
dc.b $61,$a0,$65,$82,$69,$a1,$6f,$a2,$75,$a3,0
dc.b $0e ;BS: AE,IJ,OE,ae,ij,oe
dc.b $41,$92,$49.$c1,$4f,$b5
dc.b $61,$91,$69,$c0,$6f,$b4,0
dc.b $2b ;~: A,N,O,a,n,o
dc.b $41,$b7,$4e,$a5,$4f,$B8
dc.b $61,$b0,$6e,$a4,$6f,$b1,0
dc.b $33 ;.: C.c
dc.b $43,$80,$63,$87,0
dc.b $34 ;.: A.a
dc.b $41,$8f,$61,$86,0
dc.b $35 ;-: :,L,Y
dc.b $3a,$f6,$4c,$9c,$59,$9d,0
dc.b $88 ;/: O,o
dc.b $4f,$b2,$6f,$b3,0
dc.b $8d ;': A.a.e.i.o.u
dc.b $41,$B6
dc.b $61,$85,$65,$8a,$69,$8d,$6f,$95,$75,$97,0
dc.b $a9 ;^: a,e,i,o,u
dc.b $61,$83,$65,$88,$69,$8c,$6f,$93,$75,$96,8
dc.b $b4 ;:: A,O,U,a,e,i,o,u,y
dc.b $41,$8e,$4f,$99,$55,$9a
dc.b $61,$84,$65,$89,$69,$8b,$6f,$94,$75,$81,$79,$98,0
dc.b $b5 ;_: +,<,=,7,a,o
dc.b $2b,$f1,$3c,$f3,$3d,$f0,$3e,$f2
dc.b $61,$a6,$6f,$a7,0
dc.b 0,0
;ASCII-Kodes für Scan Kodes mit ALT
altt: dc.b $00,$1b,$ad,$fd,$fe,$9b,$bd,$be ;____123456
dc.b $bf,$a9,$aa,$df,$a8,$ba,$08,$09 ;7890ß'___
dc.b $bc,$ea,$ee,$1a,$e7,$ec,$f4,$1c ;qwertzui
dc.b $1d,$e3,$40,$f1,$0d,$00,$e0,$e5 ;opü*_as
dc.b $eb,$ed,$e8,$9f,$f5,$1e,$1f,$5b ;dfghjk1ö
dc.b $5d,$ef,$00,$f7,$e4,$7f,$e2,$e9 ;ä#_'yxcu
dc.b $e1,$fc,$e6,$f9,$f8,$f6,$00,$00 ;bnm,.-_
dc.b $00,$20,$00,$00,$00,$00,$00,$00 ;_________
dc.b $00,$00,$00,$00,$80,$00,$00,$00 ;_________
dc.b $00,$00,$ec,$00,$00,$00,$f1,$00 ;_-_____+_
dc.b $00,$00,$00,$7f,$80,$08,$08,$00 ;_________
dc.b $00,$00,$00,$00,$00,$00,$00,$00 ;_________
dc.b $ae,$00,$00,$7b,$7d,$f6,$fb,$17 ;<_()/*7
dc.b $18,$19,$14,$15,$16,$11,$12,$13 ;89456123
dc.b $18,$2c,$0d,$00,$00,$00,$08,$00 ;0________
dc.b $00,$00,$00,$00,$00,$00,$00,$00 ;_________
;ASCII-Kodes für ALT+Shift
dc.b $00,$1b,$08,$ab,$00,$ac,$00,$00 ;_!"§$%&
dc.b $00,$00,$00,$f0,$d0,$60,$08,$09 ;/()=?'__
dc.b $d4,$c7,$d3,$d5,$d7,$c8,$d8,$db ;QUERTZUI
dc.b $dc,$d2,$5c,$fb,$0d,$00,$c2,$d6 ;OPÜ*__AS
dc.b $c5,$d9,$ca,$c6,$cb,$cc,$cd,$7b ;DFGHJKLÖ
dc.b $7d,$de,$00,$bb,$d1,$c9,$c4,$da ;fiA_IYXCU
dc.b $c3,$cf,$ce,$fa,$b9,$00,$00,$00 ;BNMi:____
dc.b $00,$20,$00,$00,$00,$00,$00,$00 ;_________
dc.b $00,$00,$00,$00,$00,$00,$00,$00 ;_________
dc.b $00,$00,$ec,$00,$00,$00,$f1,$00 ;_-_____+_
dc.b $00,$00,$00,$7f,$00,$00,$00,$00 ;_________
dc.b $00,$00,$80,$00,$00,$00,$00,$00 ;_________
dc.b $ae,$00,$00,$7b,$7d,$f6,$fb,$17 ;<___()/*7
dc.b $18,$19,$14,$15,$16,$11,$12,$13 ;894S6123
dc.b $10,$2c,$0d,$00,$00,$00,$00,$00 ;0________
ALIGN
alt_init:
move.w #kbdvbase,-(A7)
trap #14
addq.l #2,A7
move.l D0,-(A7) ;Zeiger auf Vektortabelle
lea alt_in1,A0 ;Init. im Supervisor-Mode durchführen
move.l A0,-(A7)
move.w #supexec,-(A7)
trap #14
adda.w #10,A7
pea mess ;Meldung ausgeben
move.w #cconws,-(A7)
trap #1
addq.l #6,A7
lea alt_init,A0 ;Länge des residenten Teils berechnen
suba.l 4(A7),A0 ;Base page
clr.w -(A7)
move.l A0,-(A7)
move.w #ptermres,-(A7) ;Programm resident installieren und beenden
trap #1
illegal ;falls doch noch Rückkehr aus Ptermres
alt_in1:
move.l 8(A7),A2 ;Zeiger auf Vektortabelle
move SR,-(A7) ;SR retten
ori #$700,SR ;IPL 7
lea oldvec,A0 ;alten ikbdsys-Vektor merken
move.l IKBDSYS(A2),(A0)
lea kbdrv,A1 ;und umsetzen
move.l A1,IKBDSYS(A2)
moue (A7)+,SR ;SR zurück
rts
;
mess:
dc.b 13,'Extended keyboard V1.2 installed.',13,10
dc.b '(C) 1988 A.Esser',13,10