Bei intensiver Nutzung der GEM-Routinen kann es schon manchmal zu unangenehmen Begleiterscheinungen kommen, einfach gesagt, zu einem Programmabsturz. Sei es durch nicht initialisierte AES-Befehle oder durch falsche Parameter bei der Bildschirmausgabe. Gegen die zweite Ursache, die auftritt, wenn Ausgabebefehle einen Bereich weit außerhalb des Bildschirms ansprechen, existiert eine Routine, die die ßildschirmausgabe auf einen bestimmten Bereich beschränkt. Dadurch werden alle illegalen Bildschirmkoordinaten eliminiert. Natürlich kann auch ein kleiner Ausschnitt gewählt werden. Die darauffolgenden GEM-Grafikbefehle finden dann nur innerhalb des definierten Bereiches statt. Die Größe des Ausschnittes wird in diesem Unterprogramm in den Variablen ’XPOSl; YPOS1; XPOS2; YPOS2’ angegeben. Diese Routine arbeitet nur mit den GEM-Routinen zusammen, bei Basic-Ausgabebefehlen wird das Clipping nicht beachtet, bzw. sogar ausgeschaltet, so daß nachfolgende GEM-Ausgaberoutinen den gesamten Bildschirm ansprechen. Das angegebene Beispiel demonstriert die Funktionsweise dieses Befehls. Prinzipieller Aufruf:
XPOS 1 = .. : YPOS1 = ..:
XPOS2 = .. : YP0S2 :
Gosub CLIPPING
Diese Routine erspart beispielsweise bei Kurvendiskussionen die ständige Abfrage, ob die errechneten Werte außerhalb des erlaubten Bereiches liegen, und erleichtern bzw. beschleunigen die Berechnung.
64200 CLIPPING:
64202 ' —> XPOS1, YPOS1, XPOS2, YPOS2
64204 poke contrl ,129
64210 poke intin, 1 'Ausschnitt ein (0=aus)
64212 poke ptsin ,XPOS1 '0
64214 poke ptsin+2,YPOS1 '0
64216 poke ptsin+4,XPOS2 '600
64218 poke ptsin+6,XPOS2 '400
64220 vdisys
64222 return
64224 '-------------------------------
Routine CLIPPING
Trotz der vielen vorgegebenen Füllmuster soll dennoch auf die Möglichkeit zum freien Definieren des Musters hingewiesen werden. Bei dem Füllmuster handelt es sich um ein 16^ 16 Bit großes Muster, das bei allen ausfüllenden Grafikoperationen zur Geltung kommt. Dazu gehören neben den Basic-Befehlen ’PCIRCLE; PELLIPSE; FILL’ auch die schon zuvor besprochenen GEM-Routinen ’RECHTECK’, ’RECHTECKRUND’ und 'POLYGON’.
Die Werte des Füllmusters, bestehend aus 16 Worten (2 Byte), werden hierbei in Data-Zeilen abgelegt und mit dem dazugehörenden Namen versehen. Die Definition des neuen Musters geschieht durch:
Restore MUSTER
Gosub FUELLMUSTER
Die Aktivierung dieses Musters wird durch ’COLOR 1,1,1,1,4 vorgenommen.
63500 FUELLMUSTER:
63502 ' —> restore MUSTER
63504 poke contrl,112
63506 poke contrl+6,16
63508 for st=0 to 30 step 2
63510 read muster
63512 poke intin+st,muster
63514 next : vdisys
63516 return
63518 ’---------------------
Routine FÜLLMUSTER
5 ’merge "FUELLMUSTER.bas“
6 ’merge “RECHTECK.bas“
7 ’merge “RECHTECKRUND.bas“
9 '
10 fullw 2 :clearw 2
20 WURM:
30 data 0,8064,16320,26208,30560,32736
40 data 29132,16318,8054,7782,7372,7384
50 data 4080,2022,60,24
60 RESTORE WURM: gosub fuellmuster
70 color 1 , 1 , 1 , 1,4
80 pellipse 130,100,100,60
90 '
100 xpos1= 270:ypos1-30 : xpos2=350:ypos2=300
110 gosub rechteck
120 '
130 xpos1 — 400:ypos1 = 200: xpos2=500:ypos2=300
140 fuell=1: gosub rechteckrund
150 '
160 warte= inp(2)
170 end
Listing 2: Definition eines Füllmusters
Zwei der interessantesten GEM-Routinen sind laut Leserzuschriften — die zum Verändern der Schriftart und der Schriftgröße, welche schon im ersten Teil des Kurses besprochen wurden. Eine weitere Routine erlaubt auf dem Monochrommonitor die Größendefinition des Zeichensatzes in 24 Stufen (siehe Bild). Die Routine arbeitet mit allen Schriftarten zusammen (kursiv, ...). Alle Schriftarten, die von der Normalgröße abweichen, können nicht per ’PRINT’ ausgegeben werden, da dieser Befehl nur auf Standardgröße ausgelegt ist. Hierzu dient die GEM-Ausgaberoutine.
Der Aufruf erfolgt durch:
ZEICHENHOEHE = (3 .. 26) :
Gosub ZEICHENHOCH
Bei monochromem Monitor beträgt der Parameter der normalen Schrifthöhe ’12’, bei einem Farbmonitor hingegen, auf Grund der niedrigeren Vertikalauflösung, ’6’. Die unterschiedlichen Auflösungsstufen eines Farbmonitors sind auch dafür verantwortlich, daß die entstehenden Schriftgrößen nicht denen eines Monochrommonitors entsprechen, sondern grundsätzlich größer sind.
5 ’merge "ZEICHENHOCH.bas“
6 ’merge "TEXTAUSGABE.bas“
7 ’merge "GRAFIKAUSSCHNITT.BAS"
9 '
10 fullw 2:clearw 2
20 XPOS1=0:YPOS1=0:XPOS2=600:YP0S2=360
30 gosub grafikausschnitt
40 for zeichenhoehe= 1 to 12
50 gosub zeichenhoch
60 xpos=30 :ypos=25*zeichenhoehe
70 text$=“Sehriftgroesse !"
80 gosub textausgabe: next
90 xpos=300: ypos=0
100 for zeichenhoehe= 13 to 26
110 gosub zeichenhoch
120 ypos=ypos+zeichenhoehe+4 : gosub textausgabe:next
130 zeichenhoehe=13: gosub zeichenhoch
140 warte=inp(2):end
Listing 3: Einstellen der Zeichenhöhe
65300 ZEICHENHOCH:
65302 '--> ZEICHENHOEHE
65304 poke contrl,12
65306 poke ptsin+2,zeichenhoehe
65308 vdisys
65310 return
65312 ' ------------------------
Routine ZEICHENHÖHE
Entsprechendes gilt für die Routine 'Schriftgröße’ die schon im ersten Teil erwähnt wurde. Der Unterschied zwischen diesen zwei Routinen besteht in der Schrittweite, in der die verschiedenen Größen angegeben werden können.
'Schriftgroesse' läßt nur sechs Größenstufen zu, während ’Schrifthöhe’ durch Bildung von Zwischenstufen eine fast kontinuierliche Größe ermöglicht, bei denen einige allerdings etwas unsauber abgebildet werden. Für bestimmte Anwendungen ist es aber sicher von Vorteil, eine passende Schrift auszuwählen. Bei mittlerer oder niedriger Auflösungsstufe (Farbe) stehen die kleinsten Größen nicht zur Verfügung.
Normalerweise werden alle Grafikoperationen, die ein Füllmuster beinhalten, mit einer Linie umrahmt. Mit der folgenden Routine kann dieser Effekt ausgeschaltet werden.
RAHMEN = (0 , 1) :
Gosub UMRAHMUNG
Bei Aneinanderreihung von Füllkörpern entsteht so eine geschlossene Fläche.
Die Funktion arbeitet mit folgenden Basic- bzw. GEM-Befehlen zusammen:
pcircle
pellipse
rechteck
rechteckrund
polygon
64250 UMRAHMUNG: 64252 '--> RAHMEN (0,1) 64254 POKE contrl,104 64256 poke intin,rahmen 64258 vdisys 64260 return 64262 ’---------------
Routine UMRAHMUNG
5 ’merge ”UMRAHMUNG.bas "
9 '
10 fullw 2: clearw 2
20 color 1, 1, 1,3,3
30 rahmen=1 :gosub umrahmung
40 pcircle 150,150,100,0,2800
50 rahmen=0 :gosub umrahmung
60 pcircle 400,150,100,0,2800
70 warte = inp(2)
80 end
Listing 4: Umrahmung ein/aus
Das AES bietet auch einige interessante Befehle, die von der Maus unterstützt werden. Neben der auch im VDI enthaltenen 'Position & Tastenabfrage’, existiert eine Routine, die kontrolliert, ob sich die Maus in einem bestimmten Rechteck befindet, und eine weitere, die das Markieren von Bildschirmbereichen ermöglicht.
Dabei ist zu beachten, das AES-Routinen einer Initialisierung durch ’INIT’ bedürfen.
62900 INIT:
62902 aes#=9b
62904 control = peektaesH)
62906 global = peek(aes#+4 )
62908 giritiri = peek(aes#+8 )
62910 gintaut = peek(aes#+12)
62912 addriri = peek(aes#+16)
62914 addrout = peek(aes#+20) 62916 return
62918 ’---------------------
Diese Routine enthält die gleichen Funktionen wie die VDI-Routine zur Mausabfrage. Mit ihr kann die Position der Maus und die Information über die Maustasten ermittelt werden. Zusätzlich gibt sie noch den Status der 'CONTROL, ALTERNATE’ und den beiden 'SHIFT’-Tasten zurück.
Der Aufruf erfolgt durch:
Gosub MOUSE
Die Informationen über Mausposition, Maustasten und der Tastatur sind anschließend in den Variablen MAUSX, MAUSY, TASTE und KEY enthalten. Die erhaltenen Werte sind folgendermaßen zu interpretieren.
TASTE:
Taste | Wert |
---|---|
links | 1 |
rechts | 2 |
links + rechts | 3 |
KEY:
Taste | Wert |
---|---|
Shift rechts | 1 |
Shift links | 2 |
Control | 4 |
Alternate | 8 |
5 ' merge "INIT.bas“
6 ' merge “MOUSE.bas“
9 '
10 gosub init
20 Start:
30 gosub mouse
40 print mausx,mausy,taste,key
50 goto Start
Listing 5: Abfrage der Mausposition
Diese Routine kontrolliert die Anwesenheit des Maussymbols in einem bestimmten, vordefinierten Rechteck. Der Anfangspunkt wird in XPOS und YPOS übergeben und legt die linke obere Ecke fest, die Variablen BREIT und HOCH bestimmen die horizontale und vertikale Ausdehnung des Bildschirmausschnittes, auf den die Routine reagiert. Dazu existieren zwei verschiedene Modi. Entweder wartet die Routine, bis die Maus den Bildschirmausschnitt betritt oder, bis sie ihn verläßt. Dies wird in Speicherzelle ’GINTIN’ festgelegt, wobei eine Null bewirkt, daß die Routine wartet, bis die Maus in den Bereich eintritt, eine Eins entsprechend das Gegenteil. Der Aufruf erfolgt durch:
XPOS1 = .. : YPOS1 = ..:
BREIT = .. : HOCH = ..:
GOSUB EVENTMAUS
62500 EVENTMAUS:
62502 ' —> XPOS1 ; YPOS1
62504 ’ —> BREIT ; HOCH
62506 poke gintin,0
62508 poke gintin+2,xpos1+1
62510 poke gintin+4,ypos1+38
62512 poke gintin+6,breit
62514 poke gintin+8,hoch
62516 gemsys 22
62518 return
62520 '----------------------
5 'merge "INIT.bas"
6 'merge "EVENTMAUS.bas”
7 'merge "SHOWMAUS.bas"
8 'merge "RECHTECK.bas"
9 '
10 gosub init
20 fullw 2 : color 1,1,1,3,3
30 xpos1=100:ypos1=100:xpos2=150:ypos2=120
40 breit = 50 : hoch = 20
50 Start:
55 gosub rechteck
60 gosub showmaus
70 gosub eventmaus:
80 out 2,7 : goto Start
90 end
Routine EVENTMAUS
Listing 6: Warten auf Mausereignis
63030 SHOWMAUS:
63032 poke contrl,122
63034 poke intin,0
63036 vdisys
63038 return
63040 '---------------
63042 HIDEMAUS:
63044 poke contrl,123
63046 vdisys
63048 return
63049 '---------------
64000 RECHTECK:
64002 ' --> XPOS1 ; YPOS1 ; XPOS2 ; YP0S2
64004 poke contrl ,11
64006 poke contrl+2 ,2
64008 poke contrl+6 ,0
64010 poke contrl+10,1
64012 poke ptsin ,XPOS1 +1
64014 poke ptsin+2,YPOS1 +38
64016 poke ptsin+4,XPOS2 +1
64018 poke ptsin+6,YP0S2 +38
64020 vdisys
64022 return
64024 '-------------------------------------
Routine RECHTECK Routinen SHOWMAUS / HIDEMAUS
62200 RUBBERBOX:
62202 '—> MAUSX ; MAUSY
62204 ' <— BREIT ; HOCH
62206 poke gintin , mausx+1
62208 poke gintin+2 , mausy+38
62210 poke gintin+4 , 1
62212 poke gintin+6 , 1
62214 AES.3: gemsys 70
62216 breit = peek(gintout+2)
62218 hoch = peek(gintout+4)
62220 if hoch<3 or breit<3 then goto AES.3
62222 return
62224 ' -----------------------------------------
Routine RUBBERBOX
5 ' merge "INIT.bas"
6 ’ merge "MOUSE.bas“
7 ' merge "RUBBERBOX.bas"
10 gosub INIT
20 openw 2:clearw 2
30 Start: gosub MOUSE
40 if taste=l then gosub rubberbox else goto start
50 ? "Die Box ist "breit" breit und "hoch“ hoch"
60 end
Listing 7: Rechteckdefinition mit Maus
Zwei weitere, nützliche Routinen dienen zum Festlegen eines Rechtecks mit der Maus. Die erste erzeugt ein Rechteck, dessen eine Ecke fixiert ist, wobei die andere, bei gedrückter Maustaste, der Mausbewegung folgt.
Die linke obere Ecke wird durch Anklicken mit der Maus bestimmt. Daraufhin entsteht ein gestricheltes Rechteck, das den Bewegungen der Maus folgt. Dabei muß die linke Maustaste gedrückt bleiben.
Sobald sie losgelassen wird, gibt die Routine die Breite und Höhe des momentan markierten Rechtecks zurück.
Der Aufruf erfolgt durch:
Gosub RUBBERBOX
Bevor diese Routine angesprochen wird, sollte mit Hilfe des ’MOUSE’-Unterprogrammes abgefragt werden, ob die linke Maustaste gedrückt wurde, um den Startpunkt des Rechtecks an die betreffende Stelle zu legen. ’RUBBERBOX’ entnimmt dann den Startpunkt aus den von der MOUSE-Routine stammenden Variablen MAUSX und MAUSY.
Diese Routine dient zum Verschieben eines Rechtecks. Die Größe des zu verschiebenden Rechtecks wird dabei vorgegeben (BREIT,HOCH). Es ist zweckmäßig, die Anfangskoordinaten mittels der MOUSE-Routine festzulegen, damit der Anfangspunkt des Rechtecks auch der Mausposition entspricht. Die Routine ist deshalb darauf ausgelegt, daß sie den Anfangspunkt den Variablen MAUSX und MAUSY entnimmt. Weiterhin ist diese Routine in der Lage, einen Bereich zu kennzeichnen, den dieses Rechteck nicht verlassen kann. Definiert wird er in X.MIN, Y.MIN und X.MAX, YMAX.
Aufruf durch
X.MIN = .. : Y.MIN = .. X.MAX = .. ;
Y.MAX = .. BREIT = .. : HOCH = ..
Gosub DRAGBOX
Die Routine gibt in den Variablen XPOS1 und YPOS1 die neue Lage des Rechtecks an das Hauptprogramm zurück.
Bei dem Beispielprogramm hierzu kommen neben der Rechteckroutine zwei weitere VDI-Routinen zur Geltung. Sie sorgen dafür, daß die Maus bei gegebener Zeit sichtbar bzw. unsichtbar wird, da sonst das Rechteck an dem Punkt, wo es mit der Maus überlappt, gelöscht würde. Um das zu verhindern, wird vor Aufruf einer GEM-Ausgaberoutine, die Maus mittels ’Gosub HIDEMAUS’ aus- und anschließend durch ’Gosub SHOWMAUS’ wieder eingeschaltet.
Aus diesem Beispiel wird ersichtlich, daß gerade durch Kombination der einzelnen GEM-Routinen die besten Ergebnisse erzielt werden. Auch die hier angeführten Demoprogramme demonstrieren lediglich die prinzipielle Arbeitsweise der einzelnen Routinen, die sicherlich in fast allen Programmen ihre Anwendung finden und Ihnen helfen, den ATARI ST ein wenig mehr auszureizen.
Zur umfangreichen GEM Nutzung ist aber trotzdem die Verwendung einer anderen Programmiersprache (C, Pascal) sehr empfehlenswert bzw. unbedingt anzuraten, da einerseits nicht alle Routinen im Basic ansprechbar sind und andererseits die Handhabung wesentlich bequemer ist, nicht zuletzt auch wegen des Geschwindigkeitsgewinns einer Compilersprache. So mag sich mancher C-Programmierer sicher gewundert haben, wieso man die GEM-Routinen, die in C ohne Kompromisse aufrufbar sind, in einer Sprache anwendet, die für solche Anwendungen weniger geeignet ist. Den Basic-Pro-grammierern aber hoffen wir, eine Hilfe für die ausgedehntere Nutzung ihres Rechners gegeben zu haben, und nicht zuletzt einen Anreiz auf die GEM-Programmierung in C oder Pascal.
★ Ende des Kurses ★
62250 DRAGBOX:
62252 ’ —> BREIT ; HOCH
62254 ’ —> X.MIN ; Y.MIN
62256 ' —> X.MAX ; Y.MAX
62258 ’ <— XPOS1 5 YPOS1
62260 poke control+2,8
62262 poke control+4,3
62264 poke gintin, breit
62266 poke gintin+2, hoch
62268 poke gintin+4, mausx+1
62270 poke gintin+6, mausy+38
62272 poke gintin+8, x.min+1
62274 poke gintin+10,y.min+38
62276 poke gintin+L2,x.max+1
62278 poke gintin+14,y.max+38
62280 gemsys 71
62282 xpos1=peek(gintout+2)-1
62284 ypos1=peek(gintout+4)-38
62286 return 62288 ’----------------------
Routine DRAGBOX
3 ’merge "INIT.bas"
4 ’merge "DRAGBOX.bas"
5 ’merge “MOUSE.bas"
6 ’merge "RECHTECK.bas"
7 'merge "SHOWMAUS.bas"
8 ’merge "HIDEMAUS.bas"
9 '
10 gosub init
20 fullw 2:clearw 2: color 1,1,1,2,3
30 breit =200:hoch =150:x.min=100:y.min=100
40 x.max=500:y.max=250
50 gosub mouse
60 Start: gosub mouse
70 if taste=l then gosub dragbox else goto Start
80 xpos2 = xpos1+breit: ypos2 = ypos1+hoch
90 gosub hidemaus: gosub rechteck
100 gosub showmaus
110 gotoxy 0,0
120 ?"Das Rechteck befindet sich nun bei " xpos1,ypos1
130 end
Listing 8: Rechteckverschieben mit Maus