TOS2GEM: TOS-Ausgaben sauber im GEM-Fenster (1)

Einige werden das Problem kennen: Da hat man eine schöne Shell für ein kommandozeilenorientiertes Programm (beispielsweise einen Compiler aus dem UNIX-Bereich) geschrieben, doch ohne MultiTOS und ähnliche Systeme ist es nicht ohne weiteres möglich, die Ausgaben des TOS-Programms sauber in ein GEM-Fenster zu lenken.

Eine Lösung für dieses Problem bietet das Freeware-Utility TOS2GEM, das eine flexible Ausgabeumlenkung über eine Cookie-Schnittstelle bietet und dessen Benutzung im folgenden Artikel vorgestellt werden soll. TOS2GEM ist ein Utility für den Autoordner, das dort einen Cookie anlegt und dann bereit ist, über diesen angesteuert zu werden. Das aufrufende Programm erhält dadurch eine einfache Möglichkeit, die Ausgaben, die normalerweise direkt auf den Bildschirm geschrieben werden (also alles, was über GEMDOS oder BIOS läuft), als VDI-Text in einen frei definierbaren Bereich des GEM-Bildschirms zu lenken. TOS2GEM simuliert somit also einen TOS-Bildschirm (Terminal) per VDI, wobei, bis auf die Farbsequenzen, ein kompletter VT52-Emulator vorhanden ist. Der von TOS2GEM simulierte Bildschirm kann dabei beliebige Ausmaße haben, es können nur Teile davon sichtbar sein, und ein beliebiger nichtproportionaler Font kann für den umgelenkten TOS-Output benutzt werden.

Der Hauptvorteil dieser Methode ist, daß man sich viel Programmierarbeit spart, da TOS2GEM die wichtigsten Aufgaben selbst übernimmt. Außerdem ist es die einzig wirklich saubere Methode, aus GEM-Programmen heraus die Ausgaben von TOS-Program-men abzufangen und in Echtzeit umzulenken, da hierzu Vektoren verbogen werden müssen, was Applikationen untersagt ist.

Dieser Artikel soll aber keine reine Beschreibung von TOS2GEM sein, er wird vielmehr die Steuerung über den Cookie erläutern und was dabei zu beachten ist. Außerdem liefert er eine fertige Routinensammlung für Pure C und Gnu C, mit der die Einbindung von TOS2GEM in eigene Programme stark vereinfacht wird (was nicht heißen soll, daß es ohne diese Routinen besonders schwierig wäre).

Der Cookie

Da TOS2GEM über einen Cookie angesprochen wird, muß natürlich zuerst die Kennung T2GM gesucht werden, ist ein solcher „Keks" vorhanden, ist sein Wert ein Zeiger auf folgende C-Struktur:

typedef struct {
WORD    date;               /* Offset 0x00 */
WORD    (*reserve) (void);  /* 0x02 */
WORD    (*init)(void);      /* 0x06 */
WORD    (*deinit)(void);    /* 0x0a */
WORD    (*switchoutput)
        (void);             /* 0x0e */
char    *text_buffer;       /* 0x12 */
WORD    max_lines,          /* 0x16 */
        x_size, y_size,     /* 0x18, 0x1a */
        x_vis,              /* 0x1c */
        y_vis,              /* 0x1e */
        x_off, y_off,       /* 0x20, 0x22 */
        char_w, char_h,     /* 0x24, 0x26 */
        vdi_handle,         /* 0x28 */
        y_offset,           /* 0x2a */
        text_offset,        /* 0x2c */
        cursor_handle,      /* 0x2e */
        reserved            /* 0x30 */}
        [RESERVED_SIZE]; 
TOS2GEM_COOKIE;

Eine Beschreibung der einzelnen Elemente befindet sich in Tabelle 1.

Bildschirm und Textpuffer

TOS2GEM simuliert, wie bereits erwähnt, einen TOS-Bildschirm, dessen Größe (in Zeichen) durch die Cookie-Elemente x_size, y_size, x_vis und y_vis festgelegt wird. Für den Inhalt dieses Bildschirms wird ein Textpuffer benötigt, der zusätzlich die Möglichkeit bietet, ältere Ausgaben zu puffern. Der schematische Aufbau des Textpuffers findet sich in Abbildung 1.

Bei der Ausgabe muß der durch x_vis und y_vis angegebene sichtbare Ausschnitt komplett unverdeckt sein, d.h., das Fenster, in dem ersieh befindet, darf nicht von anderen überlappt werden (es darf aber teilweise aus dem Bildschirm ragen). Ist y_vis kleiner als y_size, wird der sichtbare Ausschnitt von TOS2GEM automatisch so verschoben, daß der Cursor darin liegt. Das Cookie-Element y_offset gibt dabei an, die wievielte Zeile (die Zählung beginnt mit 0) des gesamten TOS2GEM-Bildschirms die erste des sichtbaren Ausschnitts ist. In x-Richtung wird nicht automatisch verschoben, hier wird immer nur der linke Teil des sichtbaren Ausschnitts dargestellt (wenn die Ausgabeumlenkung aktiv ist).

Das Cookie-Element text_offset gibt an, welche Zeile des Textpuffers die erste des aktuellen TOS2GEM-Bildschirms (nicht des sichtbaren Ausschnitts!) ist. Zu Beginn ist dieser Wert 0, ebenso wie y_offset. Bei der Ausgabe wird nun, wenn der untere Rand des Gesamtbildschirms erreicht ist, text_offset um eins erhöht, bis der Textpuffer voll ist. Ab dann geht jeweils die erste Zeile, die ja die ältesten Ausgaben beinhaltet, verloren. Voll ist der Textpuffer dann, wenn text_offset = max_lines - y_size ist, was man sich am besten an der Skizze verdeutlicht.

Prinzipielle Vorgehensweise

Da TOS2GEM nur einen Cookie bereitstellt, in dem Werte eingetragen werden können, kann auch nurjeweils ein Programm die Schnittstelle benutzen.

Tabelle 1: Beschreibung der Cookie-Elemente

Cookie-Element Beschreibung
date Dieses Wort gibt das Versionsdatum des aktiven TOS2GEM an. Das Format entspricht dem Rückgabewert von Tgdetdate. Anhand dieses Datums ist es möglich festzustellen, ob ein Feature nutzbar ist, das erst ab einer bestimmten TOS2GEM-Version vorhanden ist. Z. B. funktioniert die Anpassung an geänderte Werte von y_vis bei Reaktivierung der Ausgabeumlenkung erst seit TOS2GEM vom 03.01.1995 richtig, der dazugehörige Wert für date ist 7715.
reserve Über diesen Funktionspointer wird TOS2GEM für das aufrufende Programm reserviert, bis es durch deinit wieder freigegeben wird. Sollte eine Reservierung nicht möglich sein, erhält man 0 als Rückgabe«ert, sonst 1.
init Dieser Funktionspointer dient zur erstmaligen Aktivierung der Ausgabeumlenkung nach erfolgter Belegung des Cookies. Dabei wird 0 geliefert, wenn der Aufruf ohne vorherige Reservierung getätigt wurde, oder wenn der Cookie fehlerhaft belegt ist. Init erledigt zusätzlich folgende Aufgaben- Löschen des Textpuffers und des sichtbaren Ausschnitts, Initialisierung interner Variablen (u. a. auch y.offset und text.off set), Vorbereitung der VDI-Workstation(sl sowie Einschalten des Cursors und des Wraps am Zeilenende.
deinit Gibt TOS2GEM wieder frei, hebt also die Reservierung auf. Der Funktionspointer deinit kann zu jeder Zeit, auch bei aktiver Ausgabeumlenkung, aufgerufen werden Hatte der Aufrufer TOS2GEM nicht reserviert liefert deinit eine Null, sonst 1.
switch_output Schaltet die Ausgabeumlenkung um und setzt bzw. entfernt dabei, falls nötig, auch den Cursor. War die Umlenkung aktiv wird sie ausgeschaltet. Im anderen Fall wird sie reaktiviert und der sichtbare Ausschnitt an Änderungen im Cookie angepaßt und neugezeichnet (funktioniert nur dann 100%ig, wenn date >= 7715 ist). Rückgabewert wie bei deinit.
text_buffer Zeiger auf den Textpuffer, welcher am besten per malloc angefordert wird. Er benötigt folgende Größe: max-lines * (x.size + 1) Bytes. Jede Zeile ist x_size Zeichen lang, plus abschließendem Nullbyte, kann also als C-String angesprochen werden.
max_lines Anzahl der Zeilen im TextpufFer inklusive dem aktuellen Bildschirm, also immer > y.size).
x_size Breite des «on TOS2GEM zu simulierenden Textbildschirms in Zeichen.
y_size Höhe des zu simulierenden TOS-Bildschirms in Zeilen.
x_vis Gibt an, wieviele Zeichen in x-Richtung sichtbar sein sollen (nur in diesem Bereich wird ausgegeben).
y_vis Analogon zu x_vis für die Vertikale.
x_off X-Position des TOS-Bildschirms innerhalb des VDI-Screens. Pixelwert!
y_off Y-Position des Textbildschirms. Pixelwert!
char_w Breite eines Zeichens des benutzten Fonts in Pixeln. Wichtig: TOS2GEM kann nur mit unproportionalen Fonts wie dem Systemzeichensatz arbeiten!
char_h Höhe eines Zeichens in Pixeln.
vdi_handle Hier muß stehen welches VDI-Handle TOS2GEM für die Ausgaben benutzen soll. Es ist am zweckmäßigsten, dafür eine eigene Workstation zur Verfügung zu stellen, da man bis auf Font- und Clippingänderungen sowie Textausgaben zum Redraw tunlichst seine Finger von diesem Handle lassen sollte!
y_offset Reiner Auslesewert der angibt, welche Zeile des gesamten TOS-Bildschirms gerade die oberste des sichtbaren Ausschnitts ist. Dies ist nach Abschaltung der Ausgabeumlenkung wichtig, um feststellen zu können, was momentan der Inhalt des sichtbaren Ausschnitts ist. Zählung beginnt bei 0.
text_offset Ist, wie y_offset, ein Auslesewert, der es nach Deaktivieren der Ausgabeumlenkung ermöglicht, die Zeile des Textpuffers zu ermitteln, die gerade die erste des TOS-Gesamtbildschirms ist. Auch hier beginnt die Zählung bei Null.
cursor_handle Hier kann ein zweites VDI-Handle angegeben werden, das ausschließlich für das Zeichnen des Cursors zuständig ist. (bringt eine spürbare Beschleunigung der Ausgabe). Ist dies nicht gewünscht, muß eine Null eingetragen werden (was übrigens auch der Handle-Rückgabewert von v_opnvwk ist, wenn keine Workstation geöffnet werden kann).
reserved Dieser Teil des Cookies ist bislang unbenutzt. Bei der Belegung muß das Array, dessen Größe in der Headerdatei durch die Konstante RESERVED.SIZE angegeben ist, komplett mit Nullen gefüllt werden, um keine Probleme mit zukünftigen Versionen von TOS2GEM zu riskieren. Nicht mit reserve verwechseln!

Um dies sicherzustellen, muß man zuallererst versuchen, sich bei T0S2-GEM anzumelden. Dies geschieht über die Funktion reserve. Nur wenn diese einen Wert ungleich 0 geliefert hat, ist sichergestellt, daß TOS2GEM benutzt werden kann und Werte in die Cookie-Struktur eingetragen werden dürfen (man kann sich leicht vorstellen, welches Chaos es gäbe, wenn ein Programm seine Daten einträgt, während ein anderes noch mit TOS2GEM arbeitet). Zwar ist TOS2GEM hauptsächlich für den Einsatz unter SingleTOS gedacht (da die meisten Multitasking-Systeme bei korrektem Aufruf TOS-Programme sowieso in einem Fenster starten), es läuft aber auch in Mehrprozeßumgebungen, und gerade da ist das Reservieren unerläßlich! Um dies zusätzlich abzusichern, sind alle Cookie-Funktionen neben reserve wirkungslos, wenn sie nicht vom gleichen Prozeß aufgerufen werden, der als letzter erfolgreich reserve aufrufen konnte.

Nach erfolgreicher Reservierung sollte der Cookie mit passenden Werten belegt werden. Dabei ist es unbedingt notwendig, das Feld reserved mit Nullen zu füllen, da nur so gewährleistet ist, daß das Programm auch mit zukünftigen Versionen von TOS2GEM zusammenarbeitet, bei denen beispielsweise einer der bislang reservierten Werte das Verhalten von TOS2GEM verändert, wenn er ungleich Null ist.

Bei der Belegung von x_off, y_off, char_w und char_h darf nicht vergessen werden, daß es sich hierbei um Pixel-Angaben handelt, während alle anderen Größen in Zeichen bzw. in Zeilen gemessen werden. x_off und y_off lassen sich am besten mit wind_calc ermitteln, wobei gleichzeitig auch noch ein passendes Rahmenfenster und die Werte für x_vis und y_vis als „Nebenprodukt" anfallen. Ebenso bequem kann man char_w und char_h durch vst_point ermitteln (cell_width und cell_height sind nämlich genau die benötigten Werte), wobei man auch hier gleich zwei Fliegen mit einer Klappe schlägt: TOS2GEM benutzt nämlich immer die Font-Attribute, die auf der im Cookie angegeben VDI-Workstation gesetzt sind, und mit diesem Aufruf wird eben gleichzeitig auch eine bestimmte Höhe eingestellt.

Ist der Cookie fertig belegt, muß init aufgerufen werden. Da hierbei der sichtbare Ausschnitt grafisch gelöscht und die Ausgabeumlenkung aktiviert wird, sollte dieser Aufruf in dem Moment erfolgen, in dem man bereits ein Fenster als Rahmen geöffnet hat. Im Anschluß läßt sich ja die Umlenkung per switch_output auch wieder ausschalten. Wichtig ist auf jeden Fall, daß init der erste Aufruf nach erfolgter Belegung des Cookies ist, da nur so wichtige interne Vorbereitungen getroffen werden, ohne die eine korrekte Funktion nicht möglich ist.

Was man nicht vergessen sollte: Sobald man bei laufender Umlenkung eine der Funktionen des Cookies aufruft, die direkt auf den Bildschirm schreiben, muß dieser mittels wind_update(BEG_UPDATE) gesperrt und die Maus abgeschaltet sein.

Während die Ausgabeumlenkung aktiv ist, kann man beliebig Bildschirmausgaben per BIOS oder GEMDOS tätigen oder auch TOS-Programme per Pexec nachstarten. Alle diese Ausgaben werden von TOS2GEM abgefangen und in den Pseudobildschirm umgelenkt. In den Zeiten, in denen die Umlenkung per switch_output abgeschaltet ist, dürfen die Werte im Cookie beliebig verändert werden (wobei y_offset und text_offset eigentlich nur als Auslesevariablen gedacht sind und daher nicht manipuliert werden sollten).

Auf Änderungen, die nur Größe und Position des sichtbaren Ausschnitts oder die Font-Größe betreffen, stellt sich TOS2GEM beim nächsten Reaktivieren der Ausgabeumlenkung automatisch ein. Wurde hingegen einer der Werte max_lines, y_size oder x_size geändert, muß ein Aufruf von init folgen, da sich hierbei auch die Struktur

des Textpuffers ändert und somit angepaßt werden muß. Dabei darf nicht vergessen werden, daß durch init der komplette Textpuffer gelöscht und die Variablen y_offset und text_offset auf 0 zurückgesetzt werden, da deren Inhalt nicht mehr gültig ist.

Am Ende des Programms ist es unerläßlich, TOS2GEM durch einen Aufruf von deinit wieder für andere Prozesse freizugeben. Ob hierbei die Ausgabeumlenkung aktiv war oder nicht, ist egal. Fehlt dieser Aufruf, können nachfolgende Programme TOS2GEM nicht mehr in Anspruch nehmen, und der Anwender muß T2G_RESET.PRG bemühen, um die Blockade aufzuheben (letzteres ist beispielsweise auch dann nötig, wenn ein Programm während der Benutzung von TOS2GEM abstürzt).

Mit dieser kurzen Einführung sollte es bereits möglich sein, Programme mit TOS2GEM-Unterstützung zu schreiben. Da man aber von Natur aus bemüht ist, sich die Arbeit so einfach wie möglich zu machen, wird im nächsten Teil des Artikels eine Library für Pure C und Gnu C beschrieben, die die Ansteuerung von TOS2GEM aus eigenen Programmen heraus beinahe zum Kinderspiel macht. Listing 1 zeigt als kleinen Vorgeschmack ein minimales Demoprogramm, das mit Hilfe der Library erstellt wurde.

Thomas Binder & Dirk Klemmt

Abb. 1: Aufbau des Textpuffers
/* minidemo.c vom 18.01.1995
 * (c)1995 by MAXON-Computer
 * Autor: Thomas Binder
 * Zweck:
 * Sehr einfaches Beispielprogramm für TOS2GEM und
 * die Anwendung der TOS2GEM-Library von Dirk
 * Klemmt.
*/

#include <aes.h>
#include <vdi.h>
#include <tos.h>
#include <string.h>
#include <portab.h>

/* Pfad ggf. korrigieren */
#include "..\uset2g\uset2g.h"

#define WI_KIND NAME|MOVER 
#define DTEXT " TOS2GEM ""

WORD main(void)
{
    GRECT   work,
            border;
    WORD    window, 
            dummy, 
            event, 
            x, y,
            dx, dy;

    if (appl_init() < 0) 
        return(1);

    graf_mouse(ARROW, 0L);

/*
 * init_t2g übernimmt die gesamte Anmeldung bei
 * TOS2GEM und liefert einen Wert <> 0 zurück,
 * wenn dabei ein Fehler aufgetreten ist. In
 * diesem Fall befindet sich das System im
 * gleichen Zustand wie vor dem Aufruf, d.h. aller
 * evtl, allozierter Speicher und geöffnete VDI-
 * Workstations sind freigegeben.
 * Der hier folgende Aufruf meldet bei TOS2GEM
 * einen TOS-Screen mit 80x25 Zeichen ohne
 * Scrollback an, mit Zeichensatz 1 (Systemfont)
 * in Größe 9 und Farbe schwarz. Es wird keine
 * Mindestversion von TOS2GEM vorausgesetzt, das
 * benutzte Fenster soll die in WI_KIND gesetzten
 * Elemente haben. Außerdem wird kein Extra-Handle
 * fur den Cursor benötigt, und die Environment-
 * Variablen LINES/ROWS und COLUMNS sollen nicht
 * berücksichtigt werden.
 */

    switch (init_t2g(80, 25, 0, 1, 9, BLACK, 0, WI_KIND, 0, 0, 0))
    {
        case T2G_NOTINSTALLED:
            form_alert(1, "[3][TOS2GEM nicht|installiert!][ Abbruch ]"); 
            appl_exit(); 
            return(1); 
        case T2G_CANNOTRESERVE:
            form_alert(1, "[3][TOS2GEM kann nicht|reserviert werden!][ Abbruch ]"); 
            appl_exit(); 
            return(1); 
        case T2G_NOVDIHANDLE:
            form_alert(1, "[3][Kein VDI-Handle|mehr frei!][ Abbruch ]"); 
            appl_exit(); 
            return(1); 
        case T2G_OUTOFMEMORY:
            form_alert(1, "[3][Zu wenig Speicher!|frei!][ Abbruch ]"); 
            appl_exit(); 
            return(1); 
        case T2G_NOERROR: 
            break;

/*
 * Es ist angebracht, auch auf bislang nicht
 * definierte Fehlercodes zu reagieren, falls das
 * Programm irgendwann mit einer neueren Version
 * der TOS2GEM-Library compiliert/gelinkt wird 
 */
        default:
            form_alert(1, "[3][Unbekannter Fehler|bei init_t2g aufge-|treten!][ Abbruch ]"); 
            appl_exit(); 
            return!1);
    }

/*
 * Jetzt werden Rahmen und Arbeitsbereich eines
 * maximal großen Fensters für den TOS2GEM-Screen
 * ermittelt und danach ein entsprechendes Fenster
 * bei den AES angefordert. Bei diesem Aufruf
 * werden die dazugehörigen Parameter von TOS2GEM
 * automatisch auf die ermittelte Große angepaßt. 
 */

    calc_t2gwindow(&border, &work, 0, 0); 
    if ((window = wind.create(WI_KIND, 
        border.g_x, border.g_y, 
        border.g_w, border.g_h)) < 0)
    {
        form_alert(1, "[3][Kein Fenster-Handle|verfügbar!][ Abbruch ]");

/*
 * Wichtig: Soll das Programm nach erfolgreichem
 * init_t2g beendet werden, muß ’unbedingt*
 * exit_t2g aufgerufen werden, um TOS2GEM und die
 * benutzten Systemresourcen wieder freizugeben 
 */
        exit_t2g(); 
        appl_exit(); 
        return(1);
    }
    wind_set(window, WF_NAME," TOS2GEM-Minidemo "); 
    wind_open(window, border.g_x, border.g_y, border.g_w, border.g_h);
/*
 * Für den gleich folgenden init-Aufruf muß der
 * Bildschirm für uns reserviert und die Maus
 * ausgeschaltet sein 
 */
    graf_mouse(M_OFF, 0L); 
    wind_update(BEG_UPDATE); 
    wind_update(BEG_MCTRL);
/*
 * Jetzt wird TOS2GEM durch einen Aufruf der init-
 * Funktion aus dem Cookie initialisiert, d.h. der
 * als TOS-Screen angegebene Bereich des Screens
 * wird durch Zeichnen eines weißen Rechtecks
 * gelöscht. TOS2GEM-interne Variablen
 * vorbereitet und die Ausgabeumlenkung aktiviert
 * Diesen Aufruf *nie* vergessen, sonst gibt's
 * Müll!
 */

    if (!t2g->cookie->init())
    {
        wind_update(END_MCTRL); 
        wind_update(END_UPDATE); 
        wind_close(window); 
        wind_delete(window); 
        graf_mouse(M_ON, 0L);

/*
 * Bei Benutzung der Library dürfte zwar kein
 * Fehler beim Aufruf der init-Funktion aus dem
 * Cookie auftreten, arbeitet man aber ohne, ist
 * es (zumindest in der Entwicklungsphase) sehr
 * ratsam, den Rückgabewert zu prüfen!
 */
        form_alert(1, "[3][Fehler bei Initialisierung|von TOS2GEM][ Abbruch ]"); 
        exit_t2g(); 
        appl_exit(); 
        return(1);
    }

/*
 * Kleinere Spielereien. Alle Cconws-Ausgaben
 * werden von TOS2GEM in das vorher geöffnete
 * Fenster umgelenkt.
 */

    Cconws("Demonstration von TOS2GEM. \033f"
        "Zum Beenden eine Taste drucken!\n"); 
    x = 0;
    y = 2; 
    dx = 3; 
    dy = 3; 
    for (;;)
    {
        event = evnt_multi(MU_TIMER|MU_KEYBD,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                NULL, 1, 0, &dummy, &dummy, &dummy, 
                &dummy, &dummy, &dummy); 
        if (event & MU_KEYBD) 
            break;
        Cconws("\033Y");
        Cconout(y + 32);
        Cconout(x + 32);
        Cconws(DTEXT);
        x += dx; 
        y += dy; 
        if (y < 2)
        {
            dy = -dy;
            y = 2 - y;
        }
        if (y > 24)
        {
            dy = -dy; 
            y = 48 - y;
        }
        if (x < 0)
        {
            dx = -dx; 
            x = -x;
        }
        if ((x + (WORD)strlen(DTEXT)) > 79)
        {
            dx = -dx;
            x = 2 * (79 - (WORD)strlen(DTEXT)) - x;
        }
    }
/*
 * Zum Abschluß wird die Ausgabeumlenkung wieder
 * abgeschaltet. Prinzipiell wäre das bei diesem
 * Beispielprogramm nicht nötig, da TOS2GEM danach
 * sowieso wieder deaktiviert wird, aber im
 * Normalfall wird man das Ab- bzw. Umschalten der
 * Umlenkung per switch_output doch benötigen.
 */
    t2g->cookie->switch_output(); 
    wind_update(END_MCTRL); 
    wind_update(END_UPDATE); 
    graf_mouse(M_ON, 0L); 
    wind_close(window); 
    wind_delete(window);

/*
 * Wie bereits erwähnt: Vor Programmende unbedingt
 * exit_t2g aufrufen!
 */
    exit_t2g(); 
    appl_exit(); 
    return(0);
}

; Projektdatei zu minidemo.prg ; Autor: Thomas Binder ; Compiler: Pure C 1.0 ; Erstellt: 07.01.1995 ; Letzte Änderung: 07.01.1995 minidemo.prg .L [] .C [] = pcstart.o ; der Startup-Code minidemo.c ; der Quellcode ..\uset2g\uset2g.prj ; die TOS2GEM-Library pcgemlib.lib ; die AES/VDI-Library pctoslib.lib ; die TOS-Library pcstdlib.lib ; die Standard-Library ; Ende der Projektdatei zu minidemo.prg


Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]