Das Grafiksystem für CP/M Plus und CP/M-86

GSX ohne Geheimnisse

Teil 3: Noch mehr Funktionen und eine Programmbibliothek für Turbo-Pascal

Martin Kotulla
Mit der Vielzahl der Grafik-Funktionen, die im letzten Teil dieser Serie vorgestellt wurden, ist es beileibe nicht getan. Es fehlten beispielsweise noch Funktionen für Text und Farbe. Und als krönender Abschluß wird Ihnen eine Prozedurenbibliothek für Turbo-Pascal geboten.

Die Begriffe 'Polymarker' und 'Polyline' werden Ihnen nach der Lektüre der letzten c't nicht mehr unbekannt vorkommen. Neu hinzu gesellen sich noch drei Funktionen, die mit 'Polymarkers' und 'Polylines' zu tun haben.

Die Funktion 15 trägt den offiziellen Namen 'Set Polyline Linetype' und hat die Aufgabe, das Muster festzulegen, mit dem Linien gezeichnet werden. Diese Funktion ist in etwa mit dem MASK-Befehl im Schneider-BASIC vergleichbar, den nur die BASIC-Interpreter im CPC 664 und CPC 6128 verstehen.

GSX bietet fünf vordefinierte Linienmuster an:

Muster 1:Durchgehende LinieBinärmuster1111111111111111
Muster 2:Gestrichelte LinieBinärmuster1111111000000000
Muster 3:Gepunktete LinieBinärmuster1110000011100000
Muster 4:Gepunktet und gestricheltBinärmuster1111111000111000
Muster 5:Lang gestricheltBinärmuster1111111111110000

Die GSX-Funktion 'Set Polyline Linetype' legt das Muster für alle folgenden Grafikausgaben fest, bis entweder die Grafikdarstellung von GSX abgeschaltet oder eine neue Workstation geöffnet wird.

Die benötigten Parameter entsprechen so ziemlich denen ähnlicher GDOS-Funktionen:

contrl(1) - Funktionsnummer 15
contrl(2) - Stets auf 0 gesetzt
intin(1) - Musternummer

Eine kleine Prozedur ist in Turbo-Pascal schnell geschrieben und könnte beispielsweise so aussehen:

Procedure LineType(LType:Integer);

Begin
  contrl[1]:=15;
  contrl[2]:=0;
  intin[1]:=LType;
  Bdos(115,Addr(pblock[1]);
End;

Natürlich ist es nicht ganz leicht, sich so richtig vorzustellen, welches Aussehen die verschiedenen Linienmuster haben. Das Programm 'LineStyles' zeigt alle fünf Muster auf dem Bildschirm an.

GSX kennt verschiedene Linienmuster.

Eine andere Funktion hat beim Schneider CPC und Joyce keinerlei Wirkung. An sich sollte 'Set Polyline Line Width' die Breite von Linien festlegen. Aber sie ist weder beim Druckertreiber noch bei den Bildschirmtreibern vorhanden. Falls Sie Lust haben, einen eigenen Treiber zu schreiben, oder in der glücklichen Lage sind, einen passenden Device-Treiber gefunden zu haben, seien hier die Übergabeparameter angegeben:

contrl(1) - Funktionsnummer 16
contrl(2) - Stets auf 1 gesetzt
ptsin(1) - Linienbreite in NDC
ptsin(2) - Stets auf 0 gesetzt

Die GSX-Funktion meldet in ptsout(1) die tatsächlich gesetzte Linienbreite zurück.

Eine andere Funktion versetzt den Benutzer in die Lage, die Größe der Marker zu verändern: 'Set Marker Height' (Opcode 19). Sie arbeitet allerdings nur mit dem Drucker zusammen, der insgesamt zwölf verschiedene Markergrößen anbietet.

In Turbo-Pascal lautet eine einfache Prozedur zur Festlegung der Höhe von Markern so:

Procedure SetHeight(Hgt:Integer);

Begin
  contrl[1]:=19;
  contrl[2]:=1;
  ptsin[1]:=0;
  ptsin[2]:=Hgt;
  Bdos(115,Addr(pblock[1]);
End;
Beachten Sie hier bitte unbedingt, daß die Größenangabe in 'Device Units' zu erfolgen hat. Die Wertereihe lautet zum Beispiel für den Drucker 390, 780, 1170, 1560, 1950, 2341, 2731 ..., wobei die letztgenannten Werte wahrscheinlich Rundungsfehler von GSX darstellen dürften. Die Größendefinition anhand der 'Device Units' bedeutet nichts anderes, als daß auch Marker im NDC-System von (0,0) bis (32767,32767) erfaßt werden.

Wenn Sie mit Ihnen unbekannten Gerätetreibern arbeiten, ist es zu empfehlen, einige Probeläufe mit der Funktion 'Set Marker Height' zu unternehmen und nach deren Aufruf die Variable ptsout(2) auszulesen. Sie enthält die tatsächlich vom GDOS aufgrund der technischen Möglichkeiten des Gerätetreibers gewählte Markergröße.

Text und Grafik gemischt

Grafiken zu erstellen ist schön und gut, aber irgendwann einmal soll auch Text auf dem Bild erscheinen. Sei es eine Achsenbeschriftung von Funktionsgraphen oder eine Bildunterschrift, irgendwie müssen Buchstaben oder Zahlen dargestellt werden. Der Besitzer eines Schneider CPC oder Joyce wird sich das gar nicht als besonderes Problem vorstellen. Schließlich kennen die beiden Computer keine voneinander getrennten Text- und Grafikmodi wie etwa der IBM PC, sondern arbeiten ständig mit hochauflösender Grafik.

Daher klappt beispielsweise auch die Ausgabe der Treiber-Spezifikationen mittels 'Write' problemlos (Programm Show-Caps in der letzten c't). Bei einem PC-Kompatiblen wie etwa dem Schneider PC sieht man hingegen nur ein paar Linienmuster auf dem Bildschirm. Wie man sich hierbei aus der Affäre ziehen kann, wird c't noch in der nächsten Ausgabe vorstellen.

Es gibt aber auch noch einen anderen Weg, um Texte mittels GSX auf den Bildschirm zu bekommen, der auch für den CPC 6128 und den Joyce empfehlenswert ist. Denn GOTOXY (zur Text-Cursor-Positionierung) und WRITE arbeiten nur mit dem Bildschirm korrekt, versagen aber bei Drucker- beziehungsweise Plotterausgabe. Damit wäre das Konzept der Geräteunabhängigkeit von GSX-Grafiken wohl außer Kraft gesetzt.

Außerdem kann man mit GOTOXY den Cursor nur auf ganze Textzeilen und -spalten setzen, aber nicht auf jeden Grafik-Punkt.

GSX bietet daher die GDOS-Funktion 8 an, die schlicht 'Text' heißt. Sie schreibt eine Zeichenkette an die angegebene Position des Grafik-Cursors in NDC (NDC steht bekanntlich für 'Normalized Device Coordinates') - siehe Teil 2 der GSX-Serie.

Die zu druckende Zeichenkette wird Byte für Byte im Datenfeld 'intin' abgelegt. Aber seien Sie nicht zu geizig mit dem Speicherplatz: Für jeden Buchstaben und jedes Symbol wird ein kompletter Integerwert von 16 Bit Breite reserviert. Wenn Sie den String 'Hallo' anzeigen wollen, legen Sie die Buchstaben so im intin-Array ab:

intin(1)= ord('H')
intin(2)= ord('A')
intin(3)= ord('L')
intin(4)= ord('L')
intin(5)= ord('O')

Damit 'verschwendet' GSX bei jedem Buchstaben ein Byte. Aber dieses Speicherplatz-Opfer wird wohl noch tragbar sein...

Doch die GDOS-Funktion 8 ist allein mit dem zu plottenden Text-String nicht zufrieden. Sie will die Länge der Zeichenkette im Feldelement contrl(4) übermittelt bekommen und die (x,y)-Koordinate des ersten Buchstaben in ptsin(1) und ptsin(2). Außerdem muß man noch contrl(2) immer auf den Wert 1 setzen. Und nicht vergessen sollte man, die Funktionsnummer in das Element contrl(1) einzutragen. Fassen wir das noch einmal zusammen:

contrl(1) - Funktionsnummer 8
contrl(2) - Stets 1
contrl(4) - Länge des Textes
intin - Zeichenkette
ptsin(1) - x-Koordinate
ptsin(2) - y-Koordinate

Ein Beispiel für die Programmierung einer Prozedur 'GraphText', die einen beliebigen Text-String in Turbo-Pascal auf der GSX-Workstation darstellt, enthält die abgedruckte Turbo-Pascal-Bibliothek 'TurboGsxLib'.

Nur mit dem Drucker oder einem verbesserten Bildschirmtreiber sind die beiden Funktionen 'Set Character Height' (Festlegen der Zeichengröße) und 'Set Character Up Vector' (Bestimmung der Zeichen-Drehrichtung) zu gebrauchen.

'Set Character Height' bestimmt, welche Höhe ein Zeichen auf dem Drucker annimmt. Die Funktion besitzt die Nummer 12 und übernimmt die gewünschte Zeichenhöhe in ND-Koordinaten im Array-Element ptsin(2):

contrl(1) - Funktionsnummer 12
contrl(2) - Stets 1
ptsin(1) - Stets 0
ptsin(2) - Zeichenhöhe in NDC

Dabei geht GSX nicht von der Größe der Zeichenmatrix, zum Beispiel acht mal acht, aus, sondern von der tatsächlichen Größe des Symbols. Als Grundlage zur Berechnung der Zeichengröße dient dem GDOS der Buchstabe 'W', weil er die größten Dimensionen aller Zeichen besitzt.

Einen Buchstaben in verschiedenen Drehrichtungen anzuzeigen ist dagegen schon eine diffizilere Sache. An sich ist GSX darauf eingerichtet, daß Buchstaben in 1/3600-Schritten - also in Zehntelgraden - gedreht werden können. Aber das ist wohl nur mit einem Plotter oder einem extrem hochauflösenden Bildschirm möglich. Die Druckertreiber des Schneider CPC und Joyce unterstützen immerhin die vier Hauptrichtungen: nach oben und unten, nach links und nach rechts.

Die GDOS-Funktion 'Set Character Up Vector' übernimmt die gewünschte Drehrichtung in einigen Elementen des Feldes intin. Aus 'Freundlichkeit' gegenüber den Programmiererkollegen läßt Digital Research zwei Wege zu, die Drehrichtung anzugeben:

-im Array-Element intin(1) als Winkel in Zehntelgraden zwischen 0 und 3600;
-in intin(2) als 100 x cos(Winkel) und intin(3) als 100 x sin(Winkel).

Der erste Weg wird den meisten von uns wohl vertrauter erscheinen. GSX zählt die Grade gegen den Uhrzeigersinn ab:

           90
           !
           !
           !
180 -------+------- 0
           !
           !
           !
          270
Zeichen mit 0 Grad Drehung ihrer Grundlinie entsprechen der ganz normalen Schrift. 90-Grad-Zeichen sind 'nach links umgekippt' und so weiter. Die von 'Set Character Up Vector' weiterhin verlangten Argumente sind contrl(1)=13 (Funktionsnummer) und contrl(2)=0.

Die folgende Turbo-Prozedur übernimmt die Drehrichtung der Grundlinie der Zeichen im Wertebereich 0 bis 360 und wandelt sie in die GSX-konforme Darstellung um:

Procedure CharRotate(Angle:Integer);

Begin
  contrl[1]:=13;
  contrl[2]:=0;
  intin[1]:=Angle*10;
  intin[2]:=0;
  intin[3]:=0;
  Bdos(115,Addr(pblock[1]);
End;
Keinerlei Anwendung findet bei den Gerätetreibern von CPC und Joyce die GSX-Funktion 'Set Text Font', die einen anderen Schrifttyp zur Textdarstellung anwählt. Verwirklicht wird dieses Konzept allenfalls vom Grafikprogramm DR-Draw, bei dem verschiedene Font-Dateien mitgeliefert werden. Der Vollständigkeit halber hier die zu übergebenden Werte:

contrl(1) - Funktionsnummer 21
contrl(2) - Stets auf 0 gesetzt
intin(1) - Nummer der Schrift

Farben über Farben

Alle bisher vorgestellten Grafiken waren eintönig monochrom. Nun ist der Bildschirmtreiber DDSCREEN beziehungsweise DDMODE2 genausowenig farbfähig wie die meisten Matrixdrucker. Aber zumindest die CPC-Besitzer können ja auch im MODE 1 (DDMODE1.PRL, 4 Farben, 40 Zeichen pro Zeile) oder gar im MODE 0 arbeiten (DDMODE0.PRL, 16 Farben, 20 Zeichen/Zeile). Deshalb sind von Digital Research in GSX auch Funktionen vorgesehen worden, die die Darstellung von Farben beeinflussen.

War es schon schwierig, einen einheitlichen Grafikstandard für viele verschiedene Computer zu entwickeln, gilt dies natürlich ganz besonders im Bereich der Farbdarstellung. Hier sind die Unterschiede besonders kraß. Da gibt es zuerst einmal Peripheriegeräte, die gar keine Farben darstellen können. Andere bieten eine festgelegte Zahl von Farben, etwa acht oder sechzehn. Wieder andere arbeiten mit Farbpaletten. Der 'Videokünstler', sprich Grafikprogrammierer, sucht sich bei diesen Geräten aus einer relativ großen Anzahl von Farben einige bestimmte aus, die er gleichzeitig verwenden will. Und ganz teure CAD-Stationen, die allerdings wohl kaum mit GSX arbeiten werden (obwohl es dafür durchaus vorbereitet ist), bieten Farbtöne, deren Zahl in die Tausende bis Millionen geht.

Das Prinzip der Farbpaletten (Stichwort: Color Lookup Table) ist den CPC-Freunden bereits vom Locomotive-BASIC her bekannt: Einer kleineren Anzahl von PENs kann eine größere Menge von INKs zugeordnet werden. Ähnlich arbeitet auch GSX.

GSX zerlegt alle Farbtöne in die Grundfarben Rot, Grün und Blau (R-G-B). Wenn Sie eine Farbe definieren wollen, geben Sie die Intensität der drei Grundfarben in Promille an. Wenn Sie eine Palette aus RGB-Farben erstellt haben, deren Anzahl vom Video-Modus abhängt, können Sie die tatsächlich angezeigten Farben von Linien, Markern, Texten und Füllmustern getrennt bestimmen.

DieGSX-Funktion 14 heißt 'Set Color Representation' und ist mit dem INK-Befehl des Schneider-BASIC vergleichbar. Sie erwartet die Farbstiftnummer und die Intensitäten der Grundfarben Rot, Grün und Blau im Bereich von 0 bis 1000:

contrl(1) - Funktionsnummer 14
contrl(2) - Wert stets 0
intin(1) - Farbstiftnummer
intin(2) - Rot-Anteil
intin(3) - Grün-Anteil
intin(4) - Blau-Anteil

Im Bildschirm-MODE 1 des CPC sind vier Farbstifte, im MODE 0 deren sechzehn zulässig.

Die Funktionen zur Auswahl einer Farbe für ein bestimmtes Grafikobjekt sind identisch aufgebaut:

17 - Set Polyline Color Linienfarbe

20 - Set Polymarker Color Markerfarbe

22 - Set Text Color Textfarbe

25 - Set Fill Color Füllfarbe

Die Parameterübergabe ist bei all diesen Funktionen gleich:

contrl(1) Funktionsnummer
contrl(2) Stets 0
intin(1) Farbstiftnummer

Da der Schneider CPC nur 27 verschiedene Farben darstellen kann und nicht etwa jeweils 1000 in den drei Grundfarben mischt, führen viele Zahlenwerte zu identischen Farben. Hier hilft eigentlich nur Experimentieren. Als Grundlage können Sie die Regel nehmen, daß RGB = (0,0,0) Schwarz ergibt, RGB = (1000,1000,1000) hingegen Weiß. Setzt man zwei Farbanteile auf Null, wird die verbleibende Grundfarbe dargestellt. So wählt RGB = (1000,0,0) einen roten Farbton aus.

Ein Beispiel für die Anwendung der Farbmöglichkeiten von GSX zeigt das Turbo-Programm 'Colors'. Es demonstriert auch gleich noch einen beliebten Effekt, der durch die Technik der Farbpaletten unterstützt wird: das Flimmern von Farben durch schnellen Wechsel der Palettenfarben.

Funktionieren kann 'Colors' natürlich nur, wenn Sie einen farbfähigen Gerätetreiber verwenden. Dazu müssen Sie die Zuweisungsdatei ASSIGN.SYS abändern:

01 A:DDMODE1
oder
01 A:DDMODE0

Einige bunte Linien demonstrieren die Farbmöglichkeiten unter GSX.

GSX per 'Include'

Nun aber zur Programmbibliothek für Turbo-Pascal. Wie Sie aus den Beschreibungen der GSX-Funktionen vielleicht schon ersehen konnten, ist diese Grafikerweiterung sehr leistungsfähig. Aber die Umsetzung in praktisch nutzbare Grafikroutinen ist oft nicht ganz leicht. Deshalb finden Sie hier eine komplette Bibliothek mit Grafikprozeduren für Turbo-Pascal.

Sie ist ganz nach dem inzwischen üblich gewordenen Toolbox-Prinzip aufgebaut. Das bedeutet, daß Sie bei Programmen, die GSX-Routinen aufrufen wollen, lediglich im Deklarationsteil einen Include-Befehl einfügen müssen:

(*$ITURBOGSX.LIB*)
Wie TURBO.COM oder das kompilierte Programm mit GENGRAF nachbehandelt werden müssen, wissen Sie ja bereits seit einiger Zeit.

Wenn ein Programm GSX-Grafiken erzeugen will, muß es unbedingt vorher mindestens einmal die Prozedur GraphInit aufrufen. Denn GraphInit stellt für GSX die Beziehungen zwischen den Datenfeldern her.

Erst dann können Sie mit dem Prozeduraufruf OpenWorkstation eine virtuelle Workstation öffnen. Im Gegensatz zu den OpenWorkstation-Prozeduren in den bisherigen Beispielprogrammen ist die Prozedur hier um einige Übergabeparameter erweitert worden, die bestimmte Voreinstellungen möglich machen.

Die Bibliothek verwendet die Teilbereichstypen von Turbo-Pascal. Das macht die Programmierung übersichtlicher, als wenn Sie mit Zahlenwerten hantieren müßten.

Linien und Muster

Als Linientypen sind zugelassen:
– Solid (durchgehende Linie)
– Dash (gestrichelte Linie)
– Dot (gepunktete Linie)
– DashDot (gestrichelt und gepunktet)
– LongDash (lange Striche)

Folgende Markertypen sind vorgesehen:
– Pixel (Punkt)
– Plus (Pluszeichen)
– Asterisk (Sternchen)
– Circle (kleiner Kreis,'o')
– XSign ('X')

An Mustern zum Füllen von Flächen bietet GSXTURBO.LIB folgendes:
– Empty (kein Füllen)
– Full (normales Füllen)
– Halftone (gepunktetes Muster)
– Hatch (Füllen mit Linien)

Für das Füllen mit Linien ('Hatch') kann die Drehrichtung der Linien bestimmt werden:
– Vertical (vertikale Linien)
– Horizontal (waagerechte Linien)
– Deg45 (um 45 Grad geneigte Linien)
– Deg315 (um 315 Grad geneigte Linien)
– Cross (senkrechte und waagerechte Linien)
– X (um 45 und 315 Grad geneigte Linien)

Der Prozeduraufruf 'Open-Workstation' erwartet folgende Angaben:
– DriverID: Gerätenummer
– LType: Linienmuster
– MType: Markertyp
– FType: Füllmuster
– HType: Schraffurmuster

Ein Aufruf könnte so aussehen:

GraphInit;
OpenWorkstation(1,Solid,Pixel,Full,X);
GraphInit;
Open Workstation(21,Dash,Plus,Hatch,Cross);
Im Vergleich dazu sind die Prozeduren zum Schließen, Löschen oder Updating einer Workstation geradezu einfach zu benutzen:

CloseWorkstation;
ClearWorkstation;
UpdateWorkstation;
Die Prozedur PlotPoint setzt einen Grafikpunkt an eine beliebige Stelle auf dem virtuellen Gerät. Sie benötigt die x- und y-Koordinate des Punktes:

PlotPoint(x,y);
PlotPoint(2000,30000);
DrawLine zieht eine Linie vom ersten angegebenen (x,y)-Koordinatenpaar zum zweiten:

DrawLine(altx,alty,neux,neuy);
DrawLine(0,0,32767,32767);
DrawLine(32767,0,0,32767);

Alphanumerik

Die Pascal-Prozedur Graph-Text druckt eine Zeichenkette an Grafik-Koordinaten:

GraphText(Meldung,x,y);
GraphText('Hallo',10000,10000);
Mit CharHeight kann man die Größe von Zeichen festlegen. Der entsprechende GDOS-Aufruf wird allerdings beim Schneider CPC nur vom Druckertreiber unterstützt. Sie müssen, abhängig vom jeweiligen Treiber, selbst die Größenabstufungen im ND-Koordinatensystem herausfinden:

CharHeight(Höhe);
CharHeight(1170);
CharRotate funktioniert ebenfalls nur mit dem Druckertreiber korrekt und erlaubt die Drehung von Zeichen. Der Prozedur übergibt man die gewünschte Gradzahl zwischen 0 und 360:

CharRotate(Drehungsgrad);
CharRotate(180);
Die darauffolgenden Graph-Text-Aufrufe werden dann in der entsprechenden Richtung ausgeführt.

LineType legt fest, welches Muster GSX beim Zeichnen von Linien verwenden soll. Zulässig sind Solid, Dash, Dot, DashDot und LongDash:

LineType(Linientyp);
LineType(DashDot);
LineWidth wurde eigentlich nur der Vollständigkeit halber aufgenommen. Denn es ist nicht einfach, einen passenden Gerätetreiber zu finden, der verschiedene Linienbreiten unterstützt.

Anwendungsbeispiel:

LineWidth(Linienbreite);
LineWidth(2000);
Das Muster des Markers kann mit Hilfe der Prozedur Marker-Type bestimmt werden. Mögliche Aussehensmuster sind Pixel, Plus, Asterisk, Circle und XSign:

MarkerType(Markeraussehen);
MarkerType(Circle);
MarkerHeight teilt GSX mit, welche Größe die Marker besitzen sollen. Die Größenangabe erfolgt innerhalb der ND-Koordinaten. Welche Werte zulässig sind, ist vom verwendeten Device-Treiber abhängig. Aufruf:

MarkerHeight(Markerhöhe);
MarkerHeight(1170);
TextFont weist das GDOS an, einen anderen Schrifttyp zu verwenden. Das wird allerdings von kaum einem Treiber unterstützt:

TextFont(Schriftnummer);
TextFont(2);
Die Turbo-Prozedur FillStyle sucht ein neues Muster aus, das beim Füllen von grafischen Körpern angewendet werden soll. Zulässig sind Empty, Full, HalfTone und Hatch:

FillStyle(Füllmuster);
FillStyle(HalfTone);
Abgeschlossen wird die Reihe der GSX-Prozeduren mit HatchStyle. HatchStyle wählt das Schraffurmuster beim Füllen von grafischen Flächen aus. Unterstützt werden hier Vertical, Horizontal, Deg45, Deg315, Cross und X:

HatchStyle(Schraffurmuster);
HatchStyle(Deg315);

Fehl-Farben

Vollständig ist die Pascal-Bibliothek GSXTURBO.LIB natürlich nicht. So fehlen beispielsweise alle GSX-Aufrufe zur Verwendung von Farben. Das ist dadurch bedingt, daß der Joyce-Bildschirm sowie die meisten Drucker nur monochrome Grafiken erstellen können und auch der einfarbige Treiber DDMODE2 beim CPC 6128 am häufigsten verwendet wird. Sollten Sie aber dennoch Farben benötigen, können Sie sicher leicht anhand der bisher erworbenen Kenntnisse eigene Prozeduren oder Funktionen schreiben, die diese Aufgabe bewältigen.

Außerdem fehlt noch ein Satz von Funktionen, die bestimmte Terminal-Befehle verwalten (Cursor-Steuerung, Umschalten zwischen Grafik- und Alphamodus und vieles mehr). Diese sogenannten ESCAPE-Funktionen werden zusammen mit den Anpassungen für Turbo-86 im vierten und letzten Teil der Serie zur Sprache kommen.

Das Turbo-Programm 'GsxDemo' zeigt drei kurze Beispiele für die Anwendung von GSX-Funktionen aus Turbo-Pascal heraus. Es soll eine Anregung für Sie sein, selbst auf diesem Gebiet aktiv zu werden.

Zur Anregung ein Demo-Programm, das die vorgestellte Turbo-Bibliothek nutzt.
Turbo-Bibliothek der wichtigsten GSX-Funktionen, ohne Farb- und ESCAPE-Funktionen.
[Part 2] [Overview] [Part 4]

Scanned by Werner Cirsovius
December 2002
© Heise Verlag