software:diy:pascal:pascalk
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende Überarbeitung | |||
| software:diy:pascal:pascalk [12/11/2006 18:11] – Teil 4 eingefügt mischroeder | software:diy:pascal:pascalk [Unbekanntes Datum] (aktuell) – Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== Pascal Programmierkurs ====== | ||
| + | **__von Torsten Häßer__** | ||
| + | |||
| + | ====== Teil 1 ====== | ||
| + | |||
| + | ===== Vorweg ===== | ||
| + | Als ich vor gut einem halben Jahr meinen Portfolio (im weiteren Verlauf liebevoll Pofi genannt) bekommen habe, war eine der tollsten Dinge an dem kleinen Kasten, daß man nicht nur auf die internen Anwendungen beschränkt war. Nach der ersten RAM-Karte und den ersten Quellen für Pofisoft machte sich dann aber schnell der Wunsch breit, daß man das, was man nicht bekommen konnte ebend selbst schreibt. | ||
| + | |||
| + | Gesagt, getan. Ich war natürlich der Meinung, PC bleibt PC und Programme die für den PC geschrieben sind laufen auch auf dem Pofi. Einschränkungen ergeben sich daher nur aus der Größe des Bildschirms und der Größe der Programme. Was lag da also näher als die Programmiersprache zu benutzen, in der ich auch sonst meinen Unsinn produziere. | ||
| + | |||
| + | Ich suchte also eines meiner alten Listings heraus und feilte ein bißchen an der Bilschirmausgabe herum, um diese dann auf den Pofi zu übertragen. Die Überraschung war nicht schlecht als ich dezent vom Transferprogramm darauf hingewiesen wurde, daß zu wenig Platz auf dem Pofi ist. Wenn man sich einmal den Dimensionssprung vor Augen führt, mit dem wir es hier zu tun | ||
| + | haben ist das auch wenig verwunderlich. Unser kleiner Liebling hat nun einmal von Haus aus keine Festplatte und nur 640 KB RAM. Programme, die man vorher für relativ klein gehalten hat, sind aus der Sicht des Pofi regelrechte Speicherriesen. | ||
| + | |||
| + | Nachdem ich also etwas Platz geschaffen hatte, paßte es dann doch noch auf die RAM-Karte. Start ... BUM. Ich mußte dann erstmal für eine geraume Zeit die Batterien entfernen, um den Pofi wieder zu beleben ( ein wirklich zäher kleiner Bursche, wenn es darum geht Daten im RAM zu halten ). | ||
| + | |||
| + | Resümee dieser Aktion : Einfache Portierung der Programme ist anscheinend nicht möglich. Na gut. Ich war allerdings dickköpfig genug, um mich nicht so leicht von meinem Vorhaben abbringen zu lassen. Es hat mich dann viel Mühe gekostet an einigermaßen brauchbare Unterlagen zu kommen, die mir bei diesem Problem behilflich sein konnten. Darum geht es also in diesem(n) Artikel(n). Kein Programmierkurs in Pascal. Dafür gibt es genügend andere und bessere Literatur (siehe Anhang). Es geht darum, wie ich Anwendungen schreibe die speziell auf den Portfolio zugeschnitten sind und trotzdem mit einer PC-Hochsprache compiliert werden. | ||
| + | |||
| + | ===== Die ersten Schritte ===== | ||
| + | |||
| + | Grundsätzlich müssen Pascal-Programme für den Pofi also vor allem immer mit dem vorhandenen Speicherplatz vor Augen geschrieben werden. Pascal selber geht bei der Übersetzung des Codes nicht gerade sparsam damit um. Debug-Informationen, | ||
| + | |||
| + | Ein kleines Beispiel : | ||
| + | <code pascal> | ||
| + | PROGRAM DISK_WRITE; | ||
| + | VAR f : TEXT; | ||
| + | BEGIN | ||
| + | ASSIGN ( f, ' | ||
| + | REWRITE ( f ); | ||
| + | WRITELN ( f, 'Hello World ...' ); | ||
| + | CLOSE ( f ); | ||
| + | END. | ||
| + | </ | ||
| + | |||
| + | Dieses Programm ist, wenn man es mit den Voreinstellungen von Pascal compiliert tatsächlich **3,55 KB** groß. Nimmt man jetzt alle unnützen Optionen raus ( vor allem natürlich die Option I/ | ||
| + | |||
| + | Ich hoffe, das war beeindruckend. | ||
| + | |||
| + | Um die Freude aber wieder ein wenig zu dämpfen : | ||
| + | |||
| + | Grundsätzlich muß man natürlich wissen, daß Programme die man in einer Hochsprache schreibt übersetzt immer recht groß sein werden. Man hat ebend als Programmierer keinen bzw. nur geringen Einfluß darauf, wie der Compiler den Code übersetzt und was er alles dort rein schreibt. Deshalb lohnt sich die Verwendung einer Hochsprache generell nur dann, wenn man recht umfangreiche und komplexe Applikationen schreiben will. Für kleine Tools und Systemprogramme werden die kleinen Basic-Dialekte für den Pofi sicherlich immer geeigneter sein. Es sei denn, man ist ein Bit-Hexer und beherrscht die hohe Kunst der Assemblerprogrammierung ... :o) | ||
| + | |||
| + | Ok. Wir wollen also ein umfangreiches Programm verfassen und wir wollen auch die netten und übersichtlichen Strukturen eines Hochsprachenquelltextes nicht vermissen. Was kommen dabei also für Probleme auf uns zu. | ||
| + | |||
| + | Natürlich gibt es ein paar entscheidende Unterschiede zwischen einem // | ||
| + | |||
| + | ===== Die Units ===== | ||
| + | |||
| + | Tataaaa ... Der nächste Hammer. Die Pascal-CRT-Unit kann man leider nicht verwenden. Sie ist verantwortlich für den massiven Absturz, den ich in der Einleitung beschrieben habe. Anscheinend wird hier doch näher an der Hardware gearbeitet als es von außen scheint. Es gibt aber wohl kaum ein DOS-Programm, | ||
| + | |||
| + | "Oh Gott ... was kommt jetzt ...". Grundsätzlich hört sich das natürlich schlimmer an als es ist. Sehen wir uns erst einmal an, was das für Funktionen sind. | ||
| + | |||
| + | CRT.TPU Funktionen und Prozeduren | ||
| + | |||
| + | AssignCrt | ||
| + | ClrScr | ||
| + | DelLine | ||
| + | HighVideo | ||
| + | KeyPressed | ||
| + | NormVideo | ||
| + | ReadKey | ||
| + | TextBackground TextColor | ||
| + | TextMode | ||
| + | WhereY | ||
| + | |||
| + | Verschiedene Funktionen können wir schon mal ausschließen, | ||
| + | |||
| + | ClrEol ClrScr Delay | ||
| + | DelLine GotoXY InsLine | ||
| + | KeyPressed ReadKey Sound | ||
| + | TextMode WhereX WhereY | ||
| + | Window | ||
| + | |||
| + | Ich muß dazu noch bemerken, daß ich die Funktionen **ClrEol**, **InsLine**, | ||
| + | |||
| + | Vielleicht werde ich diese Sachen aber zu einem späteren Zeitpunkt noch mit einbauen. Wenn sich aber Leute damit schon beschäftigt haben und eine einigermaßen gute und stabile Lösung darbieten können, wäre ich natürlich dankbar, wenn ich mir diese Mühe sparen könnte ... :o) | ||
| + | |||
| + | Wichtig bei der ganzen Sache ist für uns natürlich auch, daß die neuen Funktionen weitgehend aufrufkompatibel zu den gewohnten bleiben. Wir wollen ja schließlich keine neuen Befehle lernen, sondern in gewohnter Weise weiter machen können. Ich hab mich also mal daran gemacht und aus verschiedenen Quellen diese Sachen zusammen gesucht(( in den Downloads der einzelnen Kurse liegen die Units mit drin )). | ||
| + | |||
| + | Ich will jetzt auch gar nicht so intensiv darauf eingehen wie die einzelnen Routinen | ||
| + | |||
| + | Auffallend für Leute, die sich schon einmal näher mit den DOS-Interrupts beschäftigt haben, ist sicherlich, daß beim Pofi der Interrupt $61 eine wichtige Rolle spielt. Wie weiter oben im Text schon erwähnt, fehlen im Pofi-BIOS einige Funktionen. Diesen Mißstand versuchen wir nun mit Hilfe der speziellen Pofi-Funktionen im Int $61 auszugleichen. Die Interrupts $60 ( dieser wird uns im zweiten Teil noch intensiv beschäftigen ) und $61 sind im PC-BIOS unbelegt. Dadurch wird deutlich, daß es ungemein schwierig und aufwendig wird, ein Programm zu schreiben, daß sowohl auf dem Pofi als auch auf dem PC läuft. Leider wird es uns aber kaum erspart bleiben diese Funktionen zu benutzen. Wenn ich also kompatibel programmieren will, dann muß ich alles doppelt schreiben. Andererseits bietet sich hier auch die Möglichkeit an, PC-User davor zu bewahren, unsere Pofi-Programme aus Versehen auf ihrem Rechner zu starten. Sollte der Int $61 also auf 0000:0000 zeigen, dann ist das ein relativ sicheres Zeichen, daß unser Programm keinen Pofi vor sich hat. Sicherheitslücken gibt es natürlich immer. Sollte ein PC-Programm also diesen Interrupt benutzen, dann sehen wir schon wieder alt aus. | ||
| + | |||
| + | Zurück zum eigentlichen Thema. Der Pofi hat bekanntlich drei Textmodi. Unser Pofi beherrscht neben seinem eigenen 40x8 Modus auch noch den zum PC kompatiblen 80x25 Modus. Beim 80x25 Modus wird nun noch zwischen statisch und dynamisch unterschieden. Da der Pofi allerdings nur ein Display von 40x8 Zeichen hat, wirkt in diesem Modus das Display wie eine Art Fenster, das man dann über den eigentlichen Bildschirm von 80x25 Zeichen bewegen muß. Die Umschaltung zwischen diesen Betriebsarten erfolgt nun mit Hilfe der Funktion $0E des Interrupt $61. Die Abfrage des aktuellen Modus wird auch über diese Funktion erledigt. So schön wie der 80x25 Modus vielleicht auch sein mag, aber es ist doch sehr lästig, ständig den gerade sichtbaren Bereich verschieben zu müssen, um alles auf dem Bildschirm verfolgen zu können. Ich empfehle deshalb immer den 40x8 Modus zu benutzen. Eine zweite Besonderheit ist in diesem Zusammenhang auch sicherlich die Tatsache, daß das LCD-Display keine Attribute darstellen kann. Das heißt, daß ich nicht die Möglichkeit habe einen Text zum Beispiel invertiert darzustellen. Aus diesem Grund fallen ja auch ein paar der Funktionen der CRT-Unit für uns weg. Es zeigt aber auch, daß wir uns andere Mittel und Wege suchen müssen, um Menüs und Auswahlbalken zu verwalten und für den Benutzer kenntlich zu machen. | ||
| + | |||
| + | Als weiteren wichtigen Punkt müssen wir uns mit den Routinen KeyPressed und ReadKey beschäftigen. Es gibt drei Funktionen die uns vom BIOS zur Kommuni- kation mit der Tastatur zur Verfügung gestellt werden. Diese Funktionen werden nun über den Interrupt $16 aufgerufen. Wichtig ist nun der Unterschied zwischen den Funktionen $00 und $01. Die Funktion $00 liest ein Zeichen aus dem Tastaturpuffer und falls kein Zeichen vorhanden sein sollte, wird so lange gewartet, bis ein Zeichen vorliegt. Die Funktion $01 hingegen prüft lediglich, ob ein Zeichen im Puffer vorhanden ist und gibt den Wert des Zeichens zurück, ohne es zu löschen. Um das Zeichen zu löschen muß also ein weiteres mal die Funktion $00 aufgerufen werden. So, wo ist nun das Problem dabei? Beim Aufruf von $00 wird ein Timer gestartet, der nach Ablauf einer bestimmten Zeit die berühmte Power-Down-Sequenz einleitet. Mit dieser Selbstabschaltung wird ein nicht unerheblicher Stromspar-Effekt erzielt. Das ist ja genau genommen auch erwünscht. Leider ist es in diesem Stromsparmodus nicht mehr möglich auf eventuelle Hardware-Interrupts der seriellen Schnittstelle zu reagieren. Wenn ich in meinen Programmen also darauf angewiesen bin, bleibt mir nichts anderes übrig, als mir eine eigene Routine zu schreiben, die die Funktion $01 verwendet. Denn hierbei wird die Kontrolle gerade nicht an das BIOS übergeben. Die in der Unit implementierten Funktionen ReadKey und KeyPressed verwenden nun beide die Funktion $01. Dadurch wird aber wie gesagt der Power-Down verhindert, und wenn ein Programm nun lange auf eine Eingabe des Benutzers wartet, dann schaltet sich der Rechner nicht ab. Wem das nicht paßt, sollte diese beiden Funktionen unter Verwendung der $00 Funktion programmieren. Man kann natürlich beide Versionen in die Unit aufnehmen, was allerdings im Wiederspruch zur Maßgabe steht, da diese dann kompatibel zur Orginal CRT-Unit sind. | ||
| + | |||
| + | Soviel also zu diesem Thema. Das soll aber anderweitig noch mal behandelt werden. | ||
| + | Abschließend noch ein paar kurze Worte zu den Routinen Sound und Delay. Die Sound-Funktion wird vom Pofi sehr komfortabel über den Interrut $61 ( was auch sonst ) angesprochen. Sie ist nicht aufrufkompatibel, | ||
| + | |||
| + | Die Delay-Prozedur ist eigentlich nur eine Zählerschleife und deshalb für genaue Zeitmessungen oder Ähnliches vollkommen ungeeignet. Die Werte für die Anzahl der Durchläufe sind reine Erfahrungswerte. Ich halte aber auch mehr Aufwand für nicht nötig, weil mir bisher noch kein Programm eingefallen ist, bei dem es auf einen unheimlich genauen Zeittakt ankommen würde. | ||
| + | |||
| + | So, das war also eine kleine Zusammenfassung der Schwierigkeiten und vor allem auch der Lösungsansätze einiger Probleme. Ich denke, daß nun eine Grundlage geschaffen sein sollte, um endlich auch Programme in Pascal für den Pofi zu stricken. Es gibt natürlich noch hunderte von Details über die Besonderheiten des Pofi zu sagen. Das hat allerdings nicht speziell etwas mit der Pascalprogrammierung zu tun und eignet sich deshalb bestimmt gut als eine Art Grundlagenartikel. | ||
| + | Ich will aber diesen Text jetzt nicht einfach so enden lassen. | ||
| + | Geplant ist eigentlich so etwas wie ein Kurs. Was soll also voraussichtlich noch unser Thema sein? Vor allem die speziellen Funktion die uns das BIOS noch so zur Verfügung stellt. Für die Insider seien hier nur kurz die PofiMenüs erwähnt, wie sie von den internen Applikationen her bekannt sind. | ||
| + | |||
| + | Ich will mich hier allerdings nicht festlegen. Ich habe diesen Artikel jetzt in den letzten drei Tagen verbrochen. Es gibt also bestimmt noch viele ungeklärte Fragen und auch Verbesserungsvorschläge. Ich bin für Unterstützung, | ||
| + | |||
| + | |||
| + | ====== Teil 2 ====== | ||
| + | |||
| + | ===== Das AES ===== | ||
| + | |||
| + | Man kann sagen was man will. Aber die Firma ATARI hatte in Ihrer Glanzzeit immer einen Riecher für Sachen, die ihrer Zeit eigentlich weit voraus waren. So wie die ATARI-ST Serie vom Betriebssystem her den damaligen PC's überlegen war, genau so ist das Portfolio-DOS dem damaligen PC-DOS in einem Punkt überlegen. Den Leuten, die schon mal auf anderen Plattformen wie Amiga, Mac oder eben ST's programmiert haben wird der Begriff " | ||
| + | |||
| + | AES steht für " | ||
| + | |||
| + | Wir kennen alle die Benutzerführung die die internen Anwendungen des Pofi bieten. Die Menüs, die Fenster und die Hinweisboxen. So etwas in eigenen Programmen zu realiesieren ist gar nicht so schwierig. Das Portfolio-AES stellt uns alles Notwendige zur Verfügung. Die Funktionen des AES sind alle durch den Interrupt $60 zu erreichen. | ||
| + | |||
| + | Zuerst aber mal eine kleine Auflistung : | ||
| + | |||
| + | Fn $00 Get version number (of ROMs) | ||
| + | Fn $01 Line Editor | ||
| + | Fn $02 Get current application | ||
| + | Fn $03 Reserved for custom add-ins ( Funktionen für die Hook-Files, die vom Texteditor aufgerufen werden können ) | ||
| + | Fn $08 Screen Save/ | ||
| + | Fn $09 Draw box | ||
| + | Fn $0F Menu handling | ||
| + | Fn $10 Box area calculation | ||
| + | Fn $12 Message windows | ||
| + | Fn $14 Error windows | ||
| + | |||
| + | Das ist also unser Werkzeug. Die Funktionen Fn $00 - Fn $03 sind allerdings nicht Thema in diesem Teil des Kurses. Interressant sind hier ohnehin nur der "Line Editor" | ||
| + | |||
| + | ===== 1.0 Fn $08 Screen Save/ | ||
| + | |||
| + | Diese Funktion gibt uns die Möglichkeit, | ||
| + | |||
| + | - SaveScreen ( xtl, ytl, xbr, ybr, buffer ) => die ersten beiden XY-Koordinaten beschreiben die obere-linke Ecke und das zweite Paar die unter-rechte Ecke. In der Variablen " | ||
| + | - RestoreScreen ( xtl, ytl, xbr, ybr, buffer ) => die Daten/ | ||
| + | |||
| + | ===== 2.0 Fn $09 Draw box ===== | ||
| + | |||
| + | Mit Hilfe dieser Funktion kann ich eine Box bzw. einen Rahmen zeichnen lassen. Die Koordinatenangaben, | ||
| + | |||
| + | Die Implementation | ||
| + | |||
| + | ===== 3.0 Fn $0F Menu handling ===== | ||
| + | |||
| + | Das ist eine der mächtigsten und nützlichsten Funktionen überhaupt. Mit ihrer Hilfe kann man die bekannten Menüs aus den internen Applikationen aufrufen. Das Handling dieser Menüs ist denkbar einfach. Mit ESC kann man sie abbrechen. Durch die Cursor-Tasten kann man zu den einzelnen Menüpunkten springen. Durch drücken des ersten Buchstaben des Menütextes wird der Menüpunkt direkt aufgerufen. Wem das zu kurz war, soll nochmal lesen, oder sich seine Portfolioanleitung schnappen um es sich dort noch mal durchlesen ... | ||
| + | |||
| + | In der Unit sieht der Funktionsaufruf folgendermaßen aus: | ||
| + | |||
| + | => Menu ( xtl, ytl, MenuTitle, MenuText, DefaultsText , selectedItem ) | ||
| + | |||
| + | Die Werte für **" | ||
| + | |||
| + | **Beispiel: | ||
| + | |||
| + | <code pascal> | ||
| + | MenuText := 'Point #1' + Chr(0) + 'Point #2' + Chr(0) + ' | ||
| + | </ | ||
| + | |||
| + | Die Funktion zerlegt den String dann selbsständig, | ||
| + | <code pascal> | ||
| + | DefaultText := '' | ||
| + | </ | ||
| + | dann würde am rechten Rand in der Zeile, wo der Menüeintrag //Ende//, steht dann das dazugehörige //bye bye// auftauchen. Wem das immer noch nicht ganz klar ist, der sollte sich als Beispiel das Menü im Texteditor des Portfolio ansehen. Rechts neben dem Eintrag " | ||
| + | |||
| + | ===== 4.0 Fn $10 Box area calculation ===== | ||
| + | |||
| + | Hiermit kann man sich eine Menge Arbeit ersparen. Mit Hilfe dieser Funktion kann man im voraus einige Daten ermitteln, die für das Menühandling oder auch für die später erklärte Funktion //Message Windows// nötig sind. Die Eingabewerte sind die gleichen wie beim Aufruf von //Menu//. Der Unterschied ist, daß man als Rückgabedaten die Koordinaten der rechten-unteren Ecke bekommt. Das ist sehr wichtig. Als Programmierer ist man selbst dafür verantwortlich, | ||
| + | |||
| + | => BoxAreaCalculation ( xtl, ytl, TitleText, MenuText, DefaultsText, | ||
| + | |||
| + | ===== 5.0 Fn $12 Message windows ===== | ||
| + | |||
| + | Der Funktion wird genau wie bei //" | ||
| + | |||
| + | In der Unit sieht das ganze dann so aus: | ||
| + | |||
| + | => MessageWindow ( xtl, ytl, WindowTitle, | ||
| + | |||
| + | ===== 6.0 Fn $14 Error windows ===== | ||
| + | |||
| + | Die "Error Windows" | ||
| + | |||
| + | => ErrorWindow ( xtl, ytl, ErrorText ) | ||
| + | |||
| + | So, das war also die Funktionsbeschreibung. Wenn zur Benutzung der Unit noch irgendwelche Unklarheiten bestehen, schlage ich vor, sich einfach mal den Quelltext des Demoprogramms anzusehen und an sonsten einfach mal probieren. | ||
| + | |||
| + | Gehen wir noch ein klein wenig tiefer ins Detail , was die Implementation der Funktionen in Pascal angeht. Es sollten jetzt aber auch die Leute weiterlesen, | ||
| + | |||
| + | Ich will das ganze mal an einem Beispiel exemplarisch zeigen. Nehmen wir uns die Funktion **Message Windows** vor. | ||
| + | Bevor ich die Funktion vom Befehl | ||
| + | |||
| + | INTR($60, ___) | ||
| + | |||
| + | aufrufen lassen kann, muß ich die Parameter vorher in die Prozessorregister geschrieben habe. Der Zugriff auf diese Register erfolgt über einen durch Pascal vorgegeben Recordtyp Namens **Registers**. Durch diesen Record kann ich alle Register belegen und der INTR-Befehl schreibt den Inhalt dieses Records dann in die Prozessorrrgister und löst den angegeben Software-Interrupt aus. So weit so gut. Die Schwierigkeiten für Pascal-Programmierer ergeben sich erst dann, wenn man Pascal-Datentypen an diese Register übergeben muß. Sehen wir uns mal an, wie die Funktion Fn $12 die Daten haben will: | ||
| + | |||
| + | Ich zitiere aus der Orginalbeschreibung von DIP | ||
| + | |||
| + | Fn 12H Message Windows | ||
| + | Parameters: | ||
| + | DX Top left of box | ||
| + | DS: | ||
| + | |||
| + | Returns: | ||
| + | | ||
| + | Description: | ||
| + | is taken as the title. This service is used for information messages, | ||
| + | such as loading, saving etc. | ||
| + | |||
| + | Jetzt steht da, daß die obere-linke Ecke im Register DX eingetragen werden muß. DX kann ich nun aber auch getrennt in High- und Low-Byte belegen. Ich habe nun also zwei Zahlen, die die X- und Y-Position beschreiben. DIP hat nun festgelegt, das Werte für X-Koordinaten immer im Low-Byte und die Y-Koordinaten im High-Byte abzulegen sind. | ||
| + | |||
| + | Das heißt, daß ich DX wie folgt belegen muß: '' | ||
| + | |||
| + | Na gut, das hat uns noch keine Schwierigkeiten bereitet. Wie soll man nun aber seinen Pascal-String an DS:SI übergeben. Und was soll dieser Zusatz '' | ||
| + | |||
| + | C-Programmierer haben es da einfacher. C verwaltet Strings nämlich genau so wie es hier verlangt wird. Ohne Angabe wieviel Zeichen ein String enthält und am Ende zwei Nullzeichen. Pascal verwaltet Strings ganz anders. In einem Pascal-String ist das erste Zeichen reserviert. Dort steht die Länge des Strings. Pascal-Prozeduren wissen also immer von Anfang an, wieviele Zeichen sie lesen müssen. Eine Write-Anweisung in Pascal stellt das erste Zeichen nicht dar und beginnt mit der Ausgabe des Strings erst ab dem zweiten Zeichen. Es werden dann eben auch nur so viele Zeichen dargestellt, | ||
| + | |||
| + | Wieder zurück zum eigentlichen Thema ... | ||
| + | |||
| + | Wir müssen also zuerst zwei Nullzeichen an das Ende unseres Strings anfügen. Damit hätten wir die Länge gekennzeichnet. Nun braucht man noch die Startadresse des Strings, weil ab dieser Stelle die Daten gelesen werden. Diese Adresse bekommt man mit dem Pascal-Befehlen SEG und OFS. SEG liefert die Segmentadresse des Datenbereichs zurück und OFS den Offsetwert, ab dem gelsen wird. Der Wert den SEG zurückgibt, | ||
| + | |||
| + | DS := SEG(___) und SI := OFS(___) + 1 | ||
| + | |||
| + | Die Addition bei der Zuweisung von SI bewirkt, daß die Adresse die Position des zweiten Zeichens unseres Strings angibt. Mit dem ersten Zeichen kann ich ja nichts anfangen, da Pascal hier die Länge speichert. Durch diese Eingriffe fällt es der Routine überhaupt nicht auf, daß sie es mit einem Pascal- und nicht mit einem C-String zu tun hat. Wie das dann in der Praxis aussieht, findet man in der PortAES-Unit. | ||
| + | |||
| + | Wo wir gerade beim Erklären von internen Sachen der Unit sind, kommen wir auch gleich noch auf die Begründung, | ||
| + | |||
| + | Das liegt wieder in den Pascal-Strings begründet. Ein Pascal-String kann maximal 255 Zeichen aufnehmen. Das bedeutet, daß mir für die Datenübergabe an die Menüfunktion auch nicht unendlich viele Zeichen zur Verfügung stehen. Nehmen wir einmal an, ich will ein Menü oder " | ||
| + | |||
| + | Der Menütitel muß auch im Menütext enthalten sein und durch ein Nullzeichen getrennt sein. | ||
| + | |||
| + | '' | ||
| + | |||
| + | Zeichen, die noch für den Menütitel übrig bleiben. Das wäre also das maximale Fassungsvermögen, | ||
| + | |||
| + | Alles in allem sind die Funktionen sowieso für den 40x8 Zeichenmodus konzipiert und ich denke auch, daß dies ohnehin der bevorzugte Modus sein sollte und die Einschränkungen in der Unit deshalb auch nicht besonders schmerzen. | ||
| + | |||
| + | Sollten irgendwelche Informatiker/ | ||
| + | |||
| + | Ich habe mich diesmal entschloßen, | ||
| + | |||
| + | |||
| + | |||
| + | ====== Teil 3 ====== | ||
| + | |||
| + | In den letzten beiden Kursteilen ging es um die Grundlagen, die ich brauche, um überhaupt Programme auf dem Portfolio schreiben zu können. In diesem Teil soll es nun um die Praxis gehen. | ||
| + | |||
| + | ===== Vorweg ===== | ||
| + | |||
| + | Bevor wir aber etwas Handfestes anfangen, will ich noch ein paar allgemeine Sachen zur praktischen Seite der Programmierung sagen. Wenn ich nun anfange ein Programm zu schreiben, stehe ich vor zwei Problemen. | ||
| + | |||
| + | * Wenn ich spezielle Funktionen des Portfolio nutzen will, kann ich die Programme nicht unter einem normalen PC-DOS testen. Ich meine damit die Routinen, die vom Portfolio-AES zur Verfügung gestellt werden. Also wie kann ich meine Programme testen ohne sie jedesmal auf den Portfolio zu überspielen. | ||
| + | *Aus diesem Problem ergibt sich natürlich auch noch ein zweites. Da ich die Programme nicht auf dem PC laufen lassen kann, kann ich auch nicht die Funktionen zum Debugging nutzen, die mir das PASCAL zur Verfügung stellt. | ||
| + | |||
| + | Ich kann also nicht ein Programm während der Laufzeit kurz unterbrechen, | ||
| + | |||
| + | Zumindest das erste Problem läßt sich recht leicht lösen. Ich muß natürlich nicht die Programme erst auf den Portfolio übertragen, | ||
| + | |||
| + | Das Problem mit dem Debugging ist damit aber immer noch nicht ganz behoben. Natürlich kann ich jetzt so verfahren, und nach den TSR-Programmen das PASCAL starten. Jetzt muß ich die Programme nicht mehr übersetzen und dann laufen lassen, sondern kann sie direkt vom PASCAL-Editor starten und das Programm über Haltepunkte stoppen und meine Variablenwerte einsehen. Wem das genügt der ist damit natürlich bestens bedient. Nun leben wir aber im Zeitalter von Windows 95 und OS/2 und ich kann nicht einfach nur in einem Single-Task-System arbeiten. Ich zumindest nicht. Ich bin es seit meinem ersten Computer (ein ATARI 1040STFM ) gewohnt, mit Fenstern und der Maus zu arbeiten. | ||
| + | |||
| + | Auf meinem PC läuft Windows 95 (Oh Gott ... ich habe mich geoutet) und ich will natürlich auch da weiter alle Programm parallel laufen lassen ohne sie jedesmal neu starten zu müssen. Prinzipiell kann ich allerdings auch unter Windows eine virtuelle DOS-Sitzung starten und die TSR-Programme und den PASCAL- Editor dort hochfahren. Es geht auch so, wenn auch sehr viel schwieriger. | ||
| + | |||
| + | Dann ist da noch die Frage, welches PASCAL nimmt man denn nun. Ich persönlich benutze PASCAL 7.0 (und dann möglichst die Oberfläche unter Windows). Ab dieser PASCAL-Version unterstützt der Editor die farbliche Markierung von Schlüsselwörtern, | ||
| + | |||
| + | ==== Hooks ==== | ||
| + | |||
| + | O.K. ... soweit zu unseren Werkzeugen. | ||
| + | |||
| + | Dieser Kursteil soll sich ja mit einem konkreten Beispiel befassen. Es sieht also so aus, daß ich euch ein Programm | ||
| + | |||
| + | Ups ... was ist ein Hook-File. Vielleicht ist es manchen Portfolio-Usern noch nicht aufgefallen, | ||
| + | |||
| + | Das Geheimnis ist, ich kann vom Texteditor kleine Programme nachladen, die dann irgendwas mit meinem Text anstellen können. Hook-Files müssen immer im Root-Verzeichnis von Laufwerk A liegen, und die Dateiendung .HOO haben. Aufgerufen werden diese netten kleinen Helfer über die Taste < | ||
| + | |||
| + | Die Textverarbeitung wird dabei aber nicht beendet und der gerade bearbeitete Text geht verloren. Nein ... ich habe vielmehr über spezielle BIOS-Funktionen, | ||
| + | |||
| + | Ich kann also von meinem kleinen Hook-File aus den Text komplett bearbeiten. Man sieht also, ich kann wunderbar kleine Zusatzfunktionen für die doch manchmal recht magere Textverarbeitung schreiben. Schreiben wir uns also so eine kleine Funktionserweiterung. Hook-Files sind eigentlich nichts anderes als normale Programme, bei denen man die Endung .EXE durch .HOO ersetzt hat. Hook-Files sind nur als normale Programme recht nutzlos, weil sie ja voraussetzen, | ||
| + | |||
| + | Das Problem ist, daß diese Programme recht klein sein müssen. Wenn ich nur einen Standard-Portfolio mit 128kByte RAM habe, und die Textverarbeitung hat auch noch etwas geladen, dann bleibt nicht mehr so viel Platz, um unsere kleinen Helfer unterzubringen. PASCAL ist da auf Grund der Größe, die die übersetzten Programme haben auch nicht die beste Sprache, um so etwas zu realisieren. Wir beweisen aber nun, daß es doch geht. | ||
| + | |||
| + | === Quellcode für ein HOOkfile === | ||
| + | <code pascal> | ||
| + | Program DatumUndUhrzeitHook; | ||
| + | |||
| + | {$M 1024, 0, 0} | ||
| + | |||
| + | Uses PortAES, Dos; { verwendete Units } | ||
| + | |||
| + | Function Expandieren ( zahl : Word ) : String; | ||
| + | Var zahlenString : String; | ||
| + | Begin | ||
| + | Str( zahl, zahlenString ); | ||
| + | | ||
| + | If Length( zahlenString ) < 2 Then | ||
| + | Expandieren := ' | ||
| + | End; { Zusatzfunktion um Zahlen in Strings zu wandeln } | ||
| + | |||
| + | Procedure SendeString ( wasSenden : String ); | ||
| + | Var reg : Registers; | ||
| + | Begin | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | Intr( $60, reg ); | ||
| + | End; { BIOS-Routine Int 60H Fn 03H Unterfunktin EDHO_INS } | ||
| + | |||
| + | Const wochenTage : Array [ 0 .. 6 ] Of String | ||
| + | = ( ' | ||
| + | |||
| + | Const MenueTitel = 'Was einfgen ?'; | ||
| + | |||
| + | Const MenueText = 'Datum ... ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | Var jahr, monat, tag, wochenTag, stunden, minuten, hilf : Word; | ||
| + | datum, uhrzeit : String; | ||
| + | puffer : ScreenBufferType; | ||
| + | auswahl : Byte; | ||
| + | |||
| + | Begin | ||
| + | | ||
| + | | ||
| + | jahr := jahr Mod 100; | ||
| + | datum := wochenTage[ wochenTag ] + ' ' + | ||
| + | Expandieren( tag ) + ' | ||
| + | Expandieren( monat ) + ' | ||
| + | Expandieren( jahr ); | ||
| + | | ||
| + | | ||
| + | Expandieren( minuten ) + ' Uhr'; | ||
| + | If Menu( 1, 1, MenueTitel, MenueText, Chr(0), auswahl ) Then | ||
| + | Case auswahl Of | ||
| + | 0 : SendeString( datum ); | ||
| + | 1 : SendeString( uhrzeit ); | ||
| + | 2 : SendeString( datum + ' / ' + uhrzeit ); | ||
| + | End; | ||
| + | | ||
| + | End. | ||
| + | </ | ||
| + | |||
| + | Das Hook-File soll, wenn es aufgerufen wird, das aktuelle Datum oder die Uhrzeit oder auch beides als String in den Text einfügen. Die Auswahl, was eingefügt wird, geschieht über eines der üblichen Portfolio-Menüs. | ||
| + | |||
| + | ===== Gehen wir nun den Quelltext langsam durch ... ===== | ||
| + | |||
| + | Wie schon im ersten Teil des Kurses erwähnt, muß ich den Speicherbedarf des Programms so gering wie möglich halten. Das bedeutet, daß ich mir nur soviel Speicher reserviere, wie ich auch benötige. Die Zeile mit der {$M ... Anweisung macht den Compiler darauf aufmerksam, daß mein Programm nur 3072 Byte für seinen lokalen Stack reservieren möchte. Ich kann die Bytes für den Stack leider immer nur in 1024er Schritten reservieren. Dadurch kommt diese Zahl zustande. 2048 Bytes führen zu einem Stack-Überlauf also reserviere ich 1024 mehr. | ||
| + | |||
| + | Das Programm benutzt wie schon erwähnt die Menüfunktionen, | ||
| + | |||
| + | Die kleine Funktion **“Expandieren“** wandelt einen numerischen Wert vom Typ **“Word“** in einen String um. Wenn der Wert nur einstellig sein sollte, dann wird vorne noch eine Null als ASCII-Zeichen angefügt. Das ist nötig, wenn ich als Anzahl der Minuten nur die Ziffer 6 bekomme, denn ansonsten würde meine Uhrzeit ja **21:6 Uhr** lauten. Und das sieht wirklich nicht so schön aus. Zum Umwandeln der Zahl in einen String, benutzt das Programm die PASCAL-Funktion **“STR“**. Dann wird geprüft, ob die Länge des Strings kleiner als zwei ist und wenn ja, dann wird besagte Null noch vorne angeheftet. | ||
| + | |||
| + | Als Funktion liefert sie den sich ergebenden String direkt zurück. Weil ich diese Funktion mehrere Male benötige, habe ich sie in eine Funktion außerhalb der Hauptschleife platziert. Der PASCAL-Compiler braucht bei der Übersetzung zwar mehr Speicher für den Sprung in eine Subroutine, wenn ich diese aber wirklich öfter brauche, spart es mir doch wieder mehr Speicherplatz, | ||
| + | |||
| + | Die Prozedur **SendeString** ist sozusagen das Herz des Systems. Sie stellt die Schnittstelle zur Textverarbeitung dar. In der Variablen **“wasSenden“** wird der Text übergeben, den ich einfügen will. Da ich in dieser Prozedur einen Interrupt aufrufe, muß ich mir eine Variable anlegen, in der ich die Prozessor-Register direkt mit Werten füllen kann. Die DOS-Unit stellt mir einen passenden Datentyp zur Verfügung. Diese Interrupt-Routine ist natürlich nur speziell auf dem Portfolio vorhanden. In “reg.ah“ wird die Funktionsnummer übergeben. Da diese Funktion auch noch andere Unterfunktionen hat, muß ich die Nummer dieser Unterfunktion im AH-Register übergeben. Die Funktion $03 beinhaltet alle Routinen, die von Hook-Files verwendet werden können, um mit der Textverarbeitung zu kommunizieren. | ||
| + | |||
| + | Hier mal eine kleine Auflistung, die aus der Orginalbeschreibung von DIP stammt : | ||
| + | |||
| + | Fn 03H Reserved for CustomAdd-ins | ||
| + | | ||
| + | A series of “hooks“ are provided into the Editor to enable users to control the Editor from outside. | ||
| + | | ||
| + | There are 6 Editor “hooks“. These enable an application spawned within the Editor to access a limited number of | ||
| + | internal functions which modify the text and environment. | ||
| + | |||
| + | EDHO_GOTO Move the cursor position | ||
| + | EDHO_GET Get the cursor position | ||
| + | EDHO_REF Refresh the screen | ||
| + | EDHO_LOC Get location of character at cursor | ||
| + | EDHO_INS Insert string into text | ||
| + | EDHO_DEL Delete characters from text | ||
| + | |||
| + | |||
| + | Wir benötigen für unsere Zwecke die Unterfunktion EDHO_INS. Die Funktion benötigt die Segmentadresse im ES-Register und die Offsetadresse im BX-Register. Das BIOS erwartet allerdings einen sogenannten C-String, daß heißt einen nullterminierten String. Aus diesem Grund muß ich an meinen PASCAL-String auch noch ein Nullzeichen anhängen. Das bekomme ich durch die Funktion “CHR(0)“ oder indem ich einfache **“# | ||
| + | |||
| + | Die drei nun folgenden Konstantendeklarationen sind einfach nur eine Hilfe, um im Programm selber einige Wertzuweisungen zu sparen. Es ist ohnehin besser, wenn ich Daten, die sich nie verändern werden als Konstanten in den Quelltext einbringe. Es spart mir unter Umständen wieder einiges an Speicherplatz bei dem später übersetzten Programm. “wochenTage“ ist eine sogenannte typisierte Konstante. Ich kann auf die Elemente wie in einem normalen Array zugreifen. Hier habe ich mir die Strings für die Wochentage abgelegt. Den Wert, den ich später bei der Datumsabfrage zurückbekomme, | ||
| + | |||
| + | Nun die globalen Variablen. Die Namen sind so gewählt, daß sie eigentlich aussagekräftig genug sein müßten. In den beiden Strings **“datum“** und **“uhrzeit“** wird der darzustellende String zusammengestückelt. **“puffer“** ist für meine Sicherungskopie des Bildschirms und in **“auswahl“** bekomme ich die Wahl des Users zurückgeliefert. | ||
| + | |||
| + | Machen wir uns an das Hauptprogramm. Zuerst einmal bin ich selber dafür verantwortlich, | ||
| + | |||
| + | Diese Sicherheit hätte ich also. Nun kann ich ganz beruhigt zur Arbeit schreiten. Die beiden Prozeduren **“GetDate“** und **“GetTime“** sind Standardroutinen aus der PASCAL-Unit : DOS. Mit ihrer Hilfe kann ich das aktuelle Datum und die Uhrzeit erfragen. **“GetDate“** gibt mir nicht nur das Datum zurück, sondern meldet mir auch gleichzeitig noch, welchen Wochentag wir haben. Nett ... Wenn ich es schon so leicht gemacht bekomme, dann will ich das auch nutzen und den Wochentag in meinem Datumsstring mit anzeigen. | ||
| + | |||
| + | Nun muß man wissen, in welcher Form mir die Prozedur den Wochentag zurückgibt. Der Wochentag ist eine Zahl zwischen 0 und 6. Null bedeutet dabei Sonntag und sechs bedeutet Samstag. Das erklärt, warum die Indizes meiner Wochentagskonstante von 0 bis 6 gehen und warum der Inhalt dann mit “So“ anfängt und nicht mit Montag. Ich kann jetzt, wie oben schon mal erwähnt, den Rückgabewert von “GetDate“ direkt als Index für das Array benutzen. | ||
| + | |||
| + | Es ist natürlich eine Geschmacksfrage wie mein Datum dargestellt wird. Ich mag es, wenn ich zum Beispiel bei der Jahreszahl die **“19“** weglassen kann und wenn Tage und Monate mit nur einer Ziffer mit einer führenden Null verschönt werden. Um von der Jahreszahl nur die letzten beiden Ziffern zu bekommen, wende ich einen kleinen Trick an. | ||
| + | |||
| + | Der Rechenausdruck MOD (Modulo) führt eine ganzzahlige Division durch und gibt als Ergebnis den ganzzahligen Rest zurück. Bei **“1996 MOD 100“** wäre 100 also 19 mal in 1996 enthalten. **“19 mal 100 gleich 1900“** Der ganzzahlige Rest ist also 96. Und schon habe ich nur noch die letzten beiden Ziffern. Dieses Ergebnis schreibe ich mir dann wieder in die Variable **“jahr“** zurück, weil ich ja nur das haben will. Die nun folgende vierzeilige Anweisung ist natürlich nur eine Anweisung, die ich der Übersichtlichkeit halber aber in vier Zeilen verteile. Es handelt sich hierbei um eine ganz normale Stringverkettung. Zwischen den einzelnen Angaben werden noch Leerzeichen und Punkte eingebaut. Die Formatierung von einer Zahl in einen String übernimmt die Funktion “Expandieren“. Außerdem wird der String auch noch um die führende Null erweitert falls erforderlich. | ||
| + | |||
| + | Die **“GetTime“** Funktion brauche ich nun ja wohl nicht mehr zu erklären. Die Funktion würde mir auch noch die Sekunden und die hundertstel Sekunden zurückgeben. Aber so genau wollte ich die Uhrzeit ja nicht haben. Also kann ich für diese beiden Werte eine Hilfsvariable einsetzen, deren Inhalt nicht beachtet wird. An dieser Stelle noch ein kleiner Hinweis. Es gibt doch einen Unterschied, | ||
| + | |||
| + | Gut ... meine Ausgabestrings sind also erstellt und formatiert. Nun geht es darum, den User zu fragen, was er denn bitte schön eingefügt haben möchte. Wir lassen ihm ja die Wahl, ob er nur das Datum, nur die Uhrzeit oder vielleicht beides haben möchte. Für diese Auswahl zeigen wir ihm ein Menü. | ||
| + | |||
| + | **Ein Portfolio-Menü.** | ||
| + | |||
| + | Die Menüfunktion stammt auch wieder aus der PortAES-Unit und ihre Parameter und ihre Benutzung sind im zweiten Kursteil beschrieben. Nur kurz ... mit den ersten beiden Zahlenparametern lege ich die linke-obere Ecke des Menüs fest, ich positioniere es also. Wichtig ist, daß die Funktion einen Wahrheitswert zurück liefert, ob eine gültige Auswahl getroffen wurde oder nicht. Sollte der User das Menü mit Escape abgebrochen haben, dann würde die IF-Anweisung und die daraus folgende CASE-Anweisung gar nicht ausgeführt werden und es würde gar nichts passieren. Unser Programm beendet sich sang und klanglos und löst sich nach der Wiederherstellung des Bildschirms in Luft auf. Sollte aber einer der Menüpunkte angewählt werden, dann war das Starten des Programms nicht sinnlos und wir können zeigen, was in uns steckt. Bei drei Menüpunkten kann unser Rückgabewert in **“auswahl“** zwischen 0 und 2 liegen. Je nachdem was nun in “auswahl“ steht, sende ich mit Hilfe der EDHO_INS Funktion den passenden String an die Textverarbeitung. | ||
| + | |||
| + | Zum Schluß muß noch der Bildschirm restauriert werden, um die Hinterlassenschaften unseres Menüs zu beseitigen und unser Hook-File wird beendet. Sobald die Textverarbeitung wieder die Kontrolle hat, erscheint wie von Zauberhand unser String. | ||
| + | |||
| + | Noch etwas zur Benutzung dieses Hook-Files. Ab einer bestimmten Größe, die das Programm im geladenen Zustand im Speicher einnimmt, kann es sein, daß das Hook-File nicht mehr geladen wird. Das tritt meist dann auf, wenn noch ein anderes Programm im Hintergrund schlummert. Viele benutzen vielleicht den File-Manager FM.EXE. Starte ich die Textverarbeitung über dieses Programm, dann schafft es die Textverarbeitung nicht mehr das Hook-File nachzuladen. Es ist also meistens besser, wenn man die Textverarbeitung von der DOS-Oberfläche startet. Damit sind diese Schwierigkeiten weitgehend behoben. | ||
| + | |||
| + | So, ich hoffe, daß das nicht zu schwer war. Eigentlich nicht. Man sieht, wie man mit einfachen Mitteln eine Erweiterung für die Textverarbeitung verfassen kann. Denkbar wäre jetzt zum Beispiel mit der EDHO_INS Funktion eine Art von Textbaustein-Verwaltung. Häufig gebrauchte Textinhalte können so auf Knopfdruck einfach eingefügt werden. Vielleicht hat ja der eine oder andere Geschmack daran gefunden, kleine PASCAL-Programme zu erstellen. Vielleicht haben ja auch einige Nichtprogrammierer die den Text gelesen haben, Lust bekommen, selber zu programmieren. Ich kann nur sagen, es ist ein tolles Gefühl, wenn man weiß, daß ein kleines Wunderwerk, das gerade auf dem Bildschirm zu sehen ist, von einem selbst stammt. Jeder Programmierer, | ||
| + | |||
| + | Falls jemand also anfangen will zu programmieren : Es gibt viele gute Bücher, um den Einstieg selber zu finden und ein Turbo PASCAL 6.0 kann ich schon auf CD gebrannt in jeder Computerabteilung der Kaufhäuser für nicht mal 40,-DM bekommen. | ||
| + | Programmierkurs für PASCAL 4 | ||
| + | |||
| + | ====== Teil 4 ====== | ||
| + | |||
| + | ==== Die Grafikprogrammierung ==== | ||
| + | |||
| + | So ... Freunde. Wir haben es nun fast geschafft, die Grundlagen der Pascalprogrammierung auf dem Portfolio zusammenzutragen. Ein Bereich fehlt aber noch. Etwas, daß eigentlich immer dazugehört und was für die meisten Leute das absolut Höchste ist. | ||
| + | |||
| + | Es geht um die Grafikprogrammierung. Ich muß zugeben, daß es mir lieber gewesen wäre, wenn ich mir dieses Thema hätte sparen können. Ich bin zwar auch fasziniert von den Möglichkeiten, | ||
| + | |||
| + | Es gibt zwei mittelgroße Probleme, die uns erst einmal beschäftigen müssen. Ziel eines jeden Kurses war es bisher, am Ende eine Art Prototyp zu haben, auf dem man dann seine eigenen Programme aufbauen kann. Meistens waren das Pascal-Units, | ||
| + | |||
| + | Leider haben wir aber noch ein viel größeres Problem. Grafikprogrammierung ist grundsätzlich immer eine zeitkritische Angelegenheit. Zwar sind für die meisten Funktionen, wie das Setzen eines Pixels auf dem Bildschirm, keine großen Programmierkünste erforderlich. Wenn Sie aber einen Kreis zeichnen wollen, müssen Sie schon Berechnungen anstellen, an welchen Koordinaten auf dem Bildschirm die Pixel gesetzt werden sollen. Hier liegt nun das große Problem, was auf einem 4,5MHz getakteten Portfolio noch viel schwerer ins Gewicht fällt als auf anderen Systemen. Der Kleine ist nun mal nicht der schnellste Rechner unter der Sonne. Wenn ich nun noch eine Hochsprache wie Pascal verwende, die mit der Anzahl der Befehle, die für eine Funktion ausgeführt werden müssen, sehr hoch ist, bin ich in Bezug auf die Grafik schon auf der Verliererseite. Die einzige Möglichkeit, | ||
| + | |||
| + | Damit wird klar, daß die Grafikunit, die zu diesem Teil des Kurses gehört, größten Teils in Maschinensprache verfaßt ist. Maschinensprache ist aber ja eigentlich nicht unser Thema. Deshalb wird es die meisten von euch nicht interessieren, | ||
| + | |||
| + | Ich persönlich bin auch kein großer Assembler Programmierer, | ||
| + | |||
| + | Folgende Befehle sind in der Unit implementiert : | ||
| + | ^ ^ ^ | ||
| + | | Arc | Bar | | ||
| + | | Bar3D | Box | | ||
| + | | Circle | ClearDevice | | ||
| + | | CloseGraph | DrawPoly | | ||
| + | | Ellipse | FillEllipse | | ||
| + | | FillPoly | FloodFill | | ||
| + | | GetColor | GetPixel | | ||
| + | | InitGraph | Line | | ||
| + | | LineRel | LineTo | | ||
| + | | MoveRel | MoveTo | | ||
| + | | OutTextXY | PieSlice | | ||
| + | | PutPixwl | | ||
| + | | Sector | ||
| + | | SetFillStyle | SetTextStyle | | ||
| + | | TextPixel | | | ||
| + | |||
| + | Welche Parameter diese Routinen benötigen, und wie ich sie verwende, kann ich aufgrund der Kompatibilität in der Pascal Hilfe nachlesen. Bei den zwei folgenden Befehlen sind jedoch Abweichungen zu denen der Original Unit notwendig geworden : | ||
| + | |||
| + | Bei OutTextXY können nur ASCII-Codes bis einschließlich 127 ausgegeben werden. | ||
| + | |||
| + | Und der Befehl SetTextStyle besitzt eine etwas andere Aufrufsyntax: | ||
| + | |||
| + | |||
| + | ^ Nummer ^ Erklärung ^ | ||
| + | | 1 | Zeichen nicht gekippt, keine Kursivschrift | | ||
| + | | 2 | Zeichen nicht gekippt, Kursivschrift nach links | | ||
| + | | 3 | Zeichen nicht gekippt, Kursivschrift nach rechts | | ||
| + | | 4 | Zeichen um 180° gekippt, keine Kursivschrift | | ||
| + | | 5 | Zeichen um 180° gekippt, Kursivschrift nach links | | ||
| + | | 6 | Zeichen um 180° gekippt, Kursivschrift nach rechts | | ||
| + | | 7 | Zeichen um 90° gekippt, keine Kursivschrift | | ||
| + | | 8 | Zeichen um 90° gekippt, Kursivschrift nach links | | ||
| + | | 9 | Zeichen um 90° gekippt, Kursivschrift nach rechts | | ||
| + | | 10 | Zeichen um 270° gekippt, keine Kursivschrift | | ||
| + | | 11 | Zeichen um 270° gekippt, Kursivschrift nach links | | ||
| + | | 12 | Zeichen um 270° gekippt, Kursivschrift nach rechts | | ||
| + | Statt eines weiteren Parameters bei der Original-Unit, | ||
| + | |||
| + | Aus Kompatibilitätsgründen wurde die Routine InitGraph original übernommen. Das bedeutet, daß ein Pfadname für einen Grafiktreiber angegeben werden muß. Da die Portfolio-Unit aber gar keinen Treiber benötigt, können Sie eingeben, was Sie wollen. | ||
| + | |||
| + | Mit den oben genannten Grafikbefehlen sollten die meisten Leute schon etwas anfangen können. Einige Befehle, um zum Beispiel Grafiken im PGC Format einzulesen oder abzuspeichern, | ||
| + | |||
| + | Mit dieser Unit haben wir nun Grundlagen für die Grafikprogrammierung auf dem Portfolio geschaffen, die für jemanden ausreichen sollten, der keine Lust und Zeit hat, sich mit der langwierigen Assembler-Umsetzung auseinanderzusetzen. Den Quelltext der Unit abzudrucken ist leider nicht möglich, da ihr Umfang so groß ist, daß es den Rahmen der PofoInfo bei weitem sprengen würde. Das bedeutet nicht, daß man die Unit nicht bekommen kann. Denn der Pascal Kurs ist zusammen mit den Units, die in diesem Rahmen entstanden sind, beim PCD erhältlich. | ||
| + | |||
| + | Auch wenn dieser Teil des Kurses qualitativ und quantitativ nicht mit den vorherigen Teilen mithalten kann, soll er doch den Abschluß des Kurses bilden. Abschluß des Kurses bedeutet, daß mit diesem vierten Teil sämtliche Grundlagen besprochen sein sollten. Das heißt natürlich nicht, daß dies das Ende von Artikeln zum Thema Pascal Progammierung auf dem Portfolio ist, jedoch sollte nun jeder in der Lage sein, diese Grundkenntnisse in eigene Programme umzusetzen. Spezielle Probleme und Sonderfunktionen könnten Inhalt weiterer Artikel sein. | ||
| + | An dieser Stelle deshalb noch einmal ein letzter Aufruf an alle, die glauben ,daß wichtige Bereiche nicht besprochen wurden. Eine Email genügt und ich werde mich mit der gewünschten Thematik auseinandersetzen (es sei denn, es betrifft den Bereich Grafik...: | ||
| + | |||
| + | |||
| + | |||
| + | ===== Anhang ===== | ||
| + | |||
| + | verwendete Quellen : | ||
| + | * Portfolio Programmierpraxis | ||
| + | * Frank Riemenschneider, | ||
| + | * Verlag : Markt& | ||
| + | * Portfolio Technical Reference Guide | ||
| + | * DIP | ||
| + | * Diverse Texte aus diversen Mailboxen | ||
| + | |||
| + | ===== Download ===== | ||
| + | |||
| + | [[pwfd> | ||
| + | [[pwfd> | ||
| + | [[pwfd> | ||
| + | [[pwfd> | ||
