Nachdem Anfang November Adimens 2.1 erschien, folgte Mitte des gleichen Monats die schon lange angekündigte Programmiersprache namens Aditalk. Aditalk muß nicht unbedingt zusammen mit Adimens 2.1 betrieben werden, es ist auch als eigenständiges Programm funktionsfähig, da es alle notwendigen Datenbankfunktionen zur Verfügung stellt und alle notwendigen Module mitgeliefert werden.
Neben Aditalk vertreibt ATARI auch noch die Programme C-PROG und BAS-PROG von ADI, die beide allerdings um die 2000 Mark kosten und sich mehr an den professionellen Anwendungsautor wenden.Mit diesen Programmbibliotheken ist es möglich, alle Datenbankfunktionen von Adimens in selbstgeschriebenen C- oder BASIC-Programmen zu verwenden.
Aditalk ist mehr für den Anwender gedacht, der einfache Prozesse automatisieren oder verhältnismäßig simple Aufgaben lösen will.
Das Programm wird mit Handbuch auf einer doppelseitigen Diskette geliefert. Neben der Programmiersprache und der Datei für die Hilfe-Funktion befinden sich auf der Diskette die schon von Adimens 2.1 bekannten Programme INIT, REORG und das jetzt MSH genannte COMMAND sowie eine einfache Auftragsbearbeitung als Beispiel, inklusive Datenbank und mehrerer Programmdateien.
Zumindest das Programm INIT hat seit dem Erscheinen schon mehrfache Überarbeitungen und Korrekturen erfahren, was auch in einer Datei auf der Diskette dokumentiert ist. Leider war nicht zu erfahren, wie registrierte Anwender in den Genuß dieser und zukünftiger Updates gelangen sollen, wird doch im Dementi des Handbuchs ausdrücklich sämtliche Verantwortung (und Kosten) für Reparaturen auf den Kunden abgewälzt. Es besteht aber Hoffnung, daß die Wirklichkeit nicht ganz so unfreundlich aussieht. Zumindest gibt es in der ATARI-Mailbox in Raunheim eine eigene Ecke für die Anwender von Adimens und Aditalk.
Im Gegensatz zu landläufigen Gerüchten ist Aditalk nicht dBase-kompatibel. weder dBase II noch III. Man kann also nicht direkt Anwendungen übernehmen, die man etwa für dBMAN oder ein anderes kompatibles Programm entworfen hat. Allerdings hat man bei vielen Kommandos eine dBase sehr verwandte Syntax verwendet. Die Tücke bei der Übersetzung steckt aber im Detail, da manche Funktionen, die man liebgewonnen hat, nicht existieren bzw. vollkommen anders implementiert wurden. Wie auch bei EXEC (Adimens-Bedienoberfläche) sind die Funktionen zur Erstellung einer Datei ausgelagert, darum wird auch hier das Modul INIT mitgeliefert. Durch diese Trennung von Datenbearbeitung und -erstellung sind die Daten zwischen TALK, EXEC und allen anderen Modulen austauschbar.
Ich werde mich in diesem Test ausschließlich auf das Modul TALK beschränken, da alle anderen Module schon im Zusammenhang mit Adimens 2.1 bzw 1.6 besprochen wurden. Im Gegensatz zu EXEC und INIT ist TALK kein GEM-Programm sondern eine TOS-Anwendung, man muß also auf die Maus verzichten. TALK kennt im wesentlichen zwei Bedienmodi und zwei Datenbankzustände. Entweder befindet man sich im Dialogmodus oder es wird ein Programm abgearbeitet. Viele Funktionen stehen nur zur Verfügung, wenn eine Datenbank geöffnet ist. Im Dialogmodus sind die meisten Funktionstasten belegt, was in einer Statuszeile angezeigt wird und davon abhängig ist, ob eine Datenbank geöffnet wurde oder nicht, und ob ein Indexschlüssel definiert wurde.
TALK kennt ebenso wie dBase eine Reihe von ‘Schaltern’, womit man verschiedene Betriebszustände definieren kann. Zusätzlich zum normalen Befehl ‹SET...TO...› ist es möglich, per Funktionstaste ein Menü aufzurufen, in dem man diese Schalter verstellen sowie für jedes mögliche Ausgabegerät (Device) eine Umlenkung der auszugebenden Daten definieren kann. Gibt man etwa bei dem Device Output 'PRN:' als Ausgabedatei an. wird die Ausgabe zusätzlich zum Bildschirm auch über die parallele Schnittstelle an einen angeschlossenen Drucker ausgegeben, sofern man den Schalter Output auf ON stellt.
Neben den bereits von Adimens bekannten Datentypen CHAR (Zeichenkette), INTEGER (Ganzzahl), REAL (Fließkommazahl), PRICE (Geldbetrag) und DATE (Datum) gibt es noch den neuen Typ LOGIC (wahr/falsch), der von einer Reihe von Funktionen zurückgegeben wird. TALK verfügt über alle gängigen Operationen (- + * / NOT OR AND ‹‹=>>= ‹> =) für Zahlenwerte und läßt bis zu 255 global gültige Variablen zu. Eine in einem beliebigen Teilprogramm definierte Variable ist also auch in jedem anderen Teil verfügbar. Lokale Variablen sind leider überhaupt nicht vorgesehen. Immerhin kann man aber einen Variablennamen mit einer neuen Variablen besetzen, falls die ursprüngliche Variable nicht mehr benötigt wird, oder solche Variablen mit ‹RELEASE› wieder löschen. Merkmals- und Variablennamen dürfen Buchstaben, Zahlen und den Unterstrich enthalten, Merkmalsnamen zusätzlich auch eine Reihe von Sonderzeichen, damit die vollständige Kompatibilität zu Adimens (EXEC) gewahrt bleibt. Solche Namen müssen allerdings mit 2 Doppelkreuzen (#) eingefaßt werden.
Zur einfachen Bearbeitung von Menüs mit mehreren Wahlmöglichkeiten steht neben den bereits von BASIC bekannten Verzweigungsbefehlen‹IF.. THEN ..ELSE.. ENDIF› auch die Anweisung ‹ DO CASE..CASE.. OTHERWISE.. END-CASE › zur Verfügung. Auch gibt es im wesentlichen zwei Schleifenkonstrukte, nämlich ‹DO WHILE..ENDDO › für allgemeine Aufgaben und ‹ ROLL.. END-ROLL › im Zusammenhang mit der Bearbeitung mehrerer Datensätze in einer geöffneten Datenbank. Die ROLL-Anweisung kann noch durch eine zusätzliche Bedingung auf bestimmte Datensätze beschränkt werden.
Als Ergänzung zu den Befehlen zur Datenmanipulation stehen einige Befehle zur Verfügung, die allgemeine Aufgaben übernehmen sollen. So gibt es einen ‹ DEBUG ›-Befehl, der einem Programmmierer bei der Fehlersuche behilflich sein soll. Doch leider passiert es oft genug, daß sich eine kleine Ungenauigkeit im Programm erst an sehr viel späterer Stelle stark auswirkt. Da hilft dieses ansonsten nützliche Utility leider nicht viel. Mit dem ‹ RUN ›-Befehl kann man ein externes Shell-Programm aufrufen, sofern genug Speicher zur Verfügung steht. Mit dem Befehlspaar ‹ SUSPEND ›,‹ RESUME › ist es möglich während der Programmentwicklung den Lauf z.B. zur Kontrolle von Variableninhalten (‹ SHOW MEMORY ›) abzubrechen, und falls ein Programm lange läuft, kann man mit ‹ BELL › den Benutzer auch akustisch auffordem. wieder an seinen ATARI zurückzukehren. Es gibt zwei Möglichkeiten, ein Programm endgültig zu verlassen, mit ‹ RETURN › kehrt man immer um eine Programmebene bis zum Dialogmodus zurück, mit ‹ QUIT › verläßt man Aditalk. Damit man konstante Werte, die sich nur selten ändern, nicht im Programm oder in jedem Datensatz verewigen muß, gibt es das Befehlspaar ‹ SAVE ›,‹ RESTORE ›, mit dessen Hilfe man ausgewählte Variablen in einer Datei ablegen kann und sie später bei Bedarf wieder zur Verfügung hat. Zum Beispiel kann man so den Mehrwertsteuersatz ablegen oder, falls man mehr als die zugelassenen 255 Variablen benötigt, einen Teil Zwischenspeichern. Mit CLEAR MEM wird der gesamte Variablenspeicher gelöscht.
Aditalk arbeitet nach dem Prinzip eines halbkompilierenden Interpreters. Aus dem mit einem beliebigen externen Editor erstellten Sourcecode (Endung .TLK), in dem keine Textsteuerzeichen enthalten sein dürfen, wie sie etwa von 1st-word (plus) im WP-Modus produziert werden, wird in einem Übersetzungslauf der ausführbare Zwischenkode (Endung .TLP) erzeugt. Im Zuge dieser Umwandlung werden die Befehlsworte in sogenannte Token umgewandelt und feste Werte vorberechnet. Man kann dieses Verfahren auch bei älteren Compilern finden, etwa beim UCSD-p-Pascal. Bei dieser Übersetzung gehen die Informationen über die Zeile, in der ein Befehl stand natürlich verloren, darum wird bei jedem auftretenden Fehler die Übersetzung mit einer entsprechenden Meldung abgebrochen, und der Programmierer kann den Fehler ausmerzen. Durch dieses Verfahren wird garantiert, daß die Programme bei der Ausführung zumindest semantisch fehlerfrei sind. Die übersetzten Programme werden mit dem Befehl ‹DO› aufgerufen. Ein einzelnes Programm kann 128 KByte lang sein, darf aber nur aus einer Ebene bestehen. Es ist jedoch möglich, mehrere Programme zu einer Maximaltiefe von 92 Ebenen zu verschachteln. Bei der Umwandlung werden übrigens alle Befehle, Variablen- und Merkmalsnamen in Großbuchstaben umgewandelt, schreibt man also in einem Programm
STORE 5 TO A
STORE 3 TO a
SUSPEND,
so findet man beim späteren Programmlauf beim Betrachten der Variablen folgendes Ergebnis:
A = 3
In diesem Zusammenhang sei gleich noch auf einen groben Fehler aufmerksam gemacht. Folgende Zeilen:
SET UPSHIFT OFF
/* Einschalten der */
/*Unterscheidung Groß/klein */
STORE “abc” to A
STORE “ABC” to B
? (A=B)
bringen nicht das erwartete Ergebnis ‘FALSE’ sondern die falsche Aussage ‘TRUE'. Im Gegensatz dazu erhält man das korrekte Ergebnis, wenn man nur die jeweils ersten Zeichen mit Hilfe folgender Zeile vergleicht
? ASC(A) = ASC(B)
/* ASC ermittelt den ASCII-CODE */
/* des 1. Zeichens eines Strings */.
Wie bereits erwähnt, braucht man zum Erstellen eines Programmes einen externen Editor, da nicht alle Befehle im Dialogmodus ausgeführt werden können, insbesondere gilt dies für die Schleifen- und Bedingungs-Konstrukte. Es ist jedoch möglich, im Dialogmodus mehrere Zeilen zu ‘Mikro'programmen zusammenzufassen, indem man an ein Zeilenende ein Semikolon anhängt. Alle so eingegebenen Zeilen werden en bloc ausgeführt, sobald eine Zeile ohne Semikolon eingegeben wird.
Aditalk unterscheidet zwischen 3 Kommandotypen: den Funktionen zum Arbeiten mit den Datenbeständen, den allgemeinen Befehlen und den allgemeinen Funktionen.
Zur ersten Gruppe gehören Befehle wie ‹OPEN› und ‹CLOSE› zum Öffnen bzw. Schließen einer Datenbank sowie ‹USE› und ‹INDEX›, mit deren Hilfe man die zu bearbeitende Datei und, falls gewünscht, den Suchschlüssel bestimmt. Mit ‹FIRST›, ‹LAST› und ‹SKIP› kann man sich in der aktuellen Datei bewegen und mit ‹JUMP..TO..›, ‹SELECT› und ‹BACK› ist der Zugriff auf mehrere Dateien einer Datenbank gleichzeitig möglich.
Zur Suche in den Daten stehen die Befehle ‹FIND› und ‹LOCATE› zur Verfügung, wobei ‹FIND› nurnach Schlüsseln suchen kann und daher wesentlich schneller ist als sein Gegenstück. Auch der bereits erwähnte Befehl ‹JUMP..TO..› kann zur Suche eingesetzt werden, wobei der Schlüssel auch aus einer anderen Datei stammen kann. Beim Suchen mit ‹JUMP..TO..› wird der aktuelle Datensatz im Gegensatz zu den Bewegungs- und Suchbefehlen nicht überschrieben, wodurch man bis zu 3 Datensätze gleichzeitig im Speicher halten kann.
Ein schönes Anschauungsbeispiel für den JUMP-Befehl wird in der mitgelieferten Beispielanwendung vorgeführt.
Ob man bei einer Suche eventuell über den letzten Datensatz hinausgeschossen ist, sann man mit der Funktion ‹EOF› (end of file, Dateiende) feststellen. Zur Manipula-:ion der Datensätze stehen die Befehle ‹NEW› (Leeren des Datensatzes), ‹REPLACE..WITH..› und ‹EDIT› zur Verfügung. Wird ein Datensatz ediert, kann man sich mit der Taste Fl die Definition für das aktuelle Merkmal anzeigen lassen, also den Typ und die Länge. Allerdings werden erst durch ‹INSERT› (neu einfügen) oder ‹UPDATE› die Änderungen in die Datei geschrieben. Anm: Wird ein Datensatz mit ‹NEW› gelöscht, vergißt TALK auch, um welchen Datensatz es sich gehandelt hat. So kann man nicht mit ‹NEW› die Felder leeren, die Maske mit ‹EDIT› edieren und mit ‹UPDATE› zurückschreiben, wenn ein Datensatz komplett geändert werden muß, sondern muß alle Werte explizit auf Null, bzw. einen alternativen Ausgangswert setzen.)
Mit ‹DELETE› werden Datensätze in der Datei gelöscht. Es ist möglich, Datensätze ganz oder teilweise als Maske (‹DISPLAY›) oder Liste anzuzeigen (‹LIST›). Statistisch kann man die Daten mit den Funktionen ‹COUNT›, ‹MIN1MUM›, ‹MAXIMUM›, ‹AVERAGE› und ‹SUM› auswerten.
Mit ‹SHOW STRUCTURE› kann man sich jederzeit die Definition der Datenbank anschauen.
Alle bisher genannten Befehle bezogen sich ausschließlich auf die in den Dateien abgelegten Datensätze und Merkmale, auch für Variablen sind die bereits weiter oben genannten Kontrollstrukturen sowie die nachfolgend aufgeführten Befehle gültig. So weist man einer Variablenliste mit der Anweisung ‹STORE..TO..› einen Wert zu, Ausdrücke wie
A = 5 oder A — A + 1
sind leider nicht möglich, dafür aber z.B.
STORE 5 TO A,B,C ,
wodurch die Variablen A,B und C alle den Wert 5 erhalten.
Die Ein-/Ausgabebefehle sind äußerst eng an dB ASE angelehnt, so bewirkt ‹?...› eine Ausgabe in eine neue Zeile, ‹??...› die Ausgabe ab der aktuellen Cursorposition und ‹@ X,Y ??...› die Ausgabe an der Position X,Y. Der Befehl ‹CLEAR› zum Löschen des Bildschirms kann ebenfalls mit einer X-Y-Koordinate angegeben werden, die dann der linken oberen Ecke des zu löschenden Quadranten entspricht.
Die Befehle ‹WAIT..TO..› und ‹ACCEPT..TO..› unterbrechen den Programmablauf und warten auf eine Eingabe von der Tastatur, die bei ACCEPT mit Return abgeschlossen werden muß. Besonders hilfreich ist die Möglichkeit, die Funktionstasten auszuwerten, die die Zeichenketten '‘F01” bis “F10” erzeugen. Die sogenannten Maskenbefehle sind allesamt von dBase bekannt.
Mit ‹SAY› werden Kommentartexte ausgegeben, mit ‹GET› können Merkmale und bereits definierte Variablen verändert werden. Die Eingaben bei ‹GET› können mit den Anweisungen ‹PICTURE› und ‹RANGE› eingeschränkt werden. Bis zu 64 GET-Anweisungen können parallel aufgerufen werden. Mit dem Befehl ‹READ› bzw. ‹READ SAVE› (wenn man die aktuelle Maske andernorts nochmal bearbeiten will) wird die Maske angezeigt und die Eingabe ermöglicht.
/* Beispiel Uhrzeit */
/* Die Anzeige sieht so aus: 12:00 */
CLEAR
STORE “12:” TO STUNDE
STORE “00” TO MINUTE @ 3,5 SAY “Wie spät ? “
GET STUNDE PICTURE “##A”
RANGE “00”, “23”
@ ROW(),COL()+3 GET MINUTE PICTURE “##”
RANGE “00", “59”
READ
In diesem Beispiel kann man erkennen, daß jede logische Befehlseinheit in eine neue Zeile geschrieben werden kann, aber nicht muß. Eine Zeile darf aber nie länger als 80 Zeichen sein.
Die Funktionen von Aditalk zeichnen sich dadurch aus, daß ihre Parameter im Gegensatz zu den Befehlen in Klammern angegeben werden müsssen. Die erste von sechs Gruppen umfaßt alle Funktionen zur Behandlung von Zeichenketten (Strings). Mit ihnen kann man Strings vergleichen, in Groß- und Kleinbuchstaben umwandeln, Leerzeichenketten erzeugen, andere Typen in Strings umwandeln, Teilstrings ausfiltern, Leerzeichen aus Strings entfernen sowie von einzelnen Zeichen den ASCII-Code ermitteln bzw. aus dem ASCII-Code das Zeichen erzeugen.
Bei der Ausgabe von Strings muß darauf geachtet werden, daß man sie immer mit ‹+› verknüpft, da sonst besonders bei der Ausgabe von Steuerkodes für den Drucker oder den Bildschirm (VT-52 Emulation möglich) unerwünschte Ergebnisse auftreten können.
Mit der zweiten Gruppe der Funktionen lassen sich die logische Position des Cursors und des Druckkopfes feststellen.
Die dritte Gruppe umfaßt die Datumsfunktionen. Mit ‹DATE()› und ‹TIME()› lassen sich Systemdatum und -zeit feststellen. Es ist auch möglich aus dem Datum das Jahr, den Monat und den Tag zu extrahieren.
Außer den bereits genannten mathematischen Operationen stehen noch folgende Funktionen zur Verfügung, die in der vierten Gruppe zusammengefaßt sind: Exponentialfunktion, Logarithmus, Potenz und Quadratwurzel.
Zur fünften Gruppe gehören die ‹lNT›egerfunktion. die aber nicht nur aus Fließkommazahlen ganze Zahlen macht sondern auch aus Strings, die nur aus Ziffern bestehen. Bei dBase macht das die hier nicht vorhandene VALuefunktion. Mit der ‹ROUND›-Funktion bestimmt man die Anzahl der signifikanten Stellen einer Zahl.
Die letzte ‘Gruppe' besteht nur aus der Funktion ‹TYPE›, mit deren Hilfe man den Typ einer Variablen oder eines Merkmals bestimmen kann.
Mit diesen über 80 Kommandos, die noch durch diverse Parameter beeinflußt werden können, bietet Aditalk alles Nötige, um einfache und mäßig komplexe Anwendungen zu programmieren. Am Ende des Artikels findet sich ein Beispiel, mit dem es möglich ist, aus dem Datum den Wochentag zu bestimmen. Diese Funktion fehlt leider in TALK.
Das Handbuch zu Aditalk umfaßt knapp 200 Seiten, in denen die Module INIT, TALK und REORG beschrieben werden. Im Anhang sind die auch auf Diskette vorhandenen Sourcetexte für die Beispielanwendung nochmals abgedruckt.
Das TALK-Modul wird auf 125 Seiten beschrieben und enthält als einziger Teil neben dem Inhaltsverzeichnis auch einen Index, der sich allerdings aufgrund der Modularisierung mitten im Handbuch befindet. Wenn man schnell mal etwas nachschlagen will, sollte man sich also Einlagen zwischen die Module legen.
Das Handbuch ist in zwei Teile gegliedert. Im ersten Teil werden die allgemeine Funktionsweise des Programms und die einzelnen Befehle und Funktionen nach Gruppenzusammengehörigkeit beschrieben. Im zweiten Teil, dem Referenzteil, werden jeweils die Befehle und Funktionen in alphabetischer Reihenfolge beschrieben. Die Trennung zwischen Befehlen und Funktionen ist hier aber eher hinderlich als nützlich, da man meist doch nur das Befehlswort kennt. Außerdem ist beim schnellen Durchblättern nicht genau erkenntlich, welche Kommandos auf einer Seite behandelt werden. Es wäre für den Anwender mit Sicherheit wesentlich einfacher, wenn auf jeder Seite nur ein Befehl abgehandelt würde. Oft werden im Handbuch auch Punkte an Stellen genannt, wo man sie nie vermuten würde, bzw. sie werden gar nicht erst aufgeführt. Es wird z.B. ein internationales Datumsformat erwähnt, jedoch wird nirgendwo erkärt, was es damit auf sich hat.
Dafür sind aber Stellen, die besonders wichtige Punkte beschreiben, entsprechend markiert.
Im Verlauf des Tests habe ich mehrere kleine Anwendungen geschrieben und war mit TALK bis auf einige wenige Fehler sehr zufrieden, auf die ich größtenteils bereits an anderer Stelle hingewiesen habe. Ein letzter, ganz besonders seltsamer Fehler trat im Zusammenhang mit dem SAVE-Befehl auf. Im Dialogmodus funktionierte er einwandfrei, während er im Programmmodus bei der Übersetzung keine Variablennamen mehr annahm. Hier muß unbedingt Abhilfe geschaffen werden. Es gibt jedoch einige Punkte, die bei der Programmierung unbedingt beachtet werden müssen. So muß der Datensatzzeiger zu Beginn und Ende einer Programmschleife auf die gleiche Datei zeigen. Man muß insbesondere, wenn man mit ‹JUMP..TO..› in eine andere Datei verzweigt, auf der gleichen Schleifentiefe ein ‹BACK› durchführen, wenn man diesen Befehl in einem Schleifenkonstrukt benutzt. Ein anderer Punkt, bei dem man aufpassen muß, ist die Bildschirmausgabe. Wo immer möglich, sollte man explizit definieren, an welcher Stelle auf dem Bildschirm die Ausabe erscheinen soll, damit man keine Überraschungen erlebt. Es ist außerdem aufgefallen, daß das Setzen von Schaltern ein ‹CLEAR› auslöst. Wem es möglich ist, der kann ja mal die im Listing auskommentierte Zeile ‹SET OUTPUT OFF› wieder in die Ausführung einbeziehen.
Die Firma ADI hat mit Aditalk eine Daten bankprogrammiersprache auf den Markt gebracht, die alle Grundanforderungen und mehr erfüllt, die man an eine ‘Query language’ stellen darf. Aufgrund seines günstigen Preises wird es wohl in vielen kleinen Büros und vielleicht sogar bei der großen Gruppe der semiprofessionellen Anwender auf gute Resonanz stoßen, da sich gerade für diese Gruppe die Möglichkeit bietet, selbstgeschriebene Anwendungen zu vermarkten. Allerdings ist es wichtig, daß die genannten Fehler und Problemsituationen entfernt bzw. besser dokumentiert werden.
Bezugsadresse: Bei allen autorisierten ATARI -Händlern
/* Demonstrationsprogramm für Aditalk / / Name: WOTA.TLK / / Aufgabe: Berechnung eines Wochentags aus einem Datum / / Variablen : Vergleichsdatum, Tage, T, Tag / / by CSM */
CLEAR /* Bildschirm löschen */
SET SHARESC OFF /* Keinen Platz für Masken reservieren */
SET OUTPUT TO "PRN:,64,80" /* Parallele Ausgabe auf Bildschirm / / und Drucker vorbereiten und / / Drucker auf 64 Zeilen zu 80 Zeichen stellen */
STORE <25.12.99> TO Vergleichsdatum @ 12,5 ACCEPT "Auch auf den Drucker ? (j/n)" TO Ok IF Ok = "J" OR Ok = "F01" /* Auch die Fl-Taste als JA erkennen / SET OUTPUT ON / 2. Ausgabekanal (Drucker) öffnen / ELSE SET OUTPUT OFF / oder schliessen */ ENDIF
@ 15, 5 ?? DATE() /* Aktuelles Systemdatum 3 Zeilen / / tiefer zeigen */
STORE Vergleichsdatum - DATE() TO Tage STORE Tage - INT(Tage / 7.0) * 7 TO T /* INT (Tage / 7) * 7 liefert falsches / / Ergebnis ! / DO CASE / Wochentag bestimmen / CASE T = 0 STORE "Sonnabend " TO Tag CASE T = 6 STORE "Sonntag " TO Tag CASE T = 5 STORE "Montag " TO Tag CASE T = 3 STORE "Mittwoch " TO Tag CASE T = 4 STORE "Dienstag " TO Tag CASE T = 1 STORE "Freitag " TO Tag CASE T = 2 STORE "Donnerstag" TO Tag ENDCASE @ row(),col()+3 ?? Tag / und hinter dem Datum ausgeben */
/*SET OUTPUT OFF Drucker aus / BELL / Wecken / @ 23,50 WAIT "Taste..." / und Bestätigung abwarten / QUIT / oder RETURN, falls TALK nicht / / verlassen werden soll */