GDOS-Zeichensätze IN MAXON-PASCAL

MAXON-PASCAL bietet durch die UNITS GEMVdi und GEMAes vollen Zugriff auf alle VDI- und AES-Routinen. So ist es auch kein Problem, das GDOS zu integrieren, um so eine grosse HARDware-Kompatibilität zu erreichen. Als kleine Anregung möchte ich zeigen, wie man GDOS-Bildschirmzeichensätze in eigene Programme einbindet.

Bild 1: Die geladenen GDOS-Zeichensätze können für die Schriftausgabe im Fenster gewählt werden. Der ausgewählte Schrifttyp wird dann im Menü mit einem Haken gekennzeichnet.

Das GDOS (Graphics Device Operating System) ist ein Programm, das die Verwaltung von verschiedenen Gerätetreibern (Bildschirm, Drucker, Metafile etc.) mit den dazugehörigen Zeichensätzen übernimmt. Über das GDOS ist somit eine komfortable Kommunikation zwischen eigenen Programmen und der Hardware möglich. Bei einem Wechsel der Hardware muß nur das GDOS angepaßt werden, und somit ist das eigene Programm ohne Anpassung auf einer Vielfalt von Hardware-Zusammenstellungen (z.B TT, Großbildschirm, Beschleunigungskarten etc.) lauffähig. Trotz dieser Möglichkeit hoher Kompatibilität wird das GDOS von den meisten Programmierern immer noch stiefmütterlich behandelt, obwohl es in den meisten Programmiersprachen sehr leicht über die VDI-Aufrufe genutzt werden kann. Diese Unbeliebtheit folgt wahrscheinlich aus seiner geringen Geschwindigkeit. Aber durch die Entwicklung hin zu Beschleunigungskarten und Programmen (NVDI, Quick ST etc.) bzw. zu schnelleren Rechnern (TT und Mega STE) wird dieses Manko immer mehr aufgehoben. Ich möchte zur Demonstration des GDOS ein kleines Programm in MAXON-Pascal vorstellen, das die GDOS-Bildschirmzeichensätze nutzt.

Ich möchte nun im folgenden auf das Zusammenspiel zwischen GDOS und VDI eingehen und die von mir benutzten VDI-Routinen genau beschreiben:

Das GDOS lädt beim Starten die Datei ASSIGN.SYS, in der die zu ladenden Gerätetreiber und Zeichensätze aufgeführt sind. Nähere Information über Aufbau und Bedeutung dieser Datei findet man in [2], Die in dieser Datei angegebenen Zeichensätze für den Bildschirm wollen wir nun mit unserem Programm einladen und zur Textausgabe im Fenster einsetzen. Zum Laden benutzt man die Funktion

anzahl:= vst_load_fonts(vdi_handle, select);
anzahl,vdi_handle,select: INTEGER;

die alle verfügbaren Zeichensätze in den Speicher lädt und uns die Anzahl der geladenen Zeichensätze übergibt. Man übergibt ihr als Parameter das Vdi_handle (die Kennung, die man beim Öffnen der virtuellen Workstation erhalten hat) und den Wert select = 0. Zur Auswahl zwischen den einzelnen Zeichensätzen dient uns die Prozedur

vst_font(vdi_handle,font); 
vdi_handle,font: INTEGER;

wobei font den Index des jeweiligen Zeichensatzes darstellt. Allerdings haben wir beim Laden noch keinerlei Informationen über die Indizes oder die Namen unserer geladenen Fonts erhalten. Hier hilft die Funktion vqt_name. Dieser Routine übergibt man als Parameter elementnum, als wievielter der Zeichensatz geladen wurde (hierbei zählt der Systemzeichensatz als Nummer 1) und erhält Name und Index zurück.

index:= vqt_name(vdi_handle,elementnum,name);

index,vdi_handle,elementnum: INTEGER;
name: STRING80;

Jetzt kann man die Zeichensätze leicht mittels vst_font aus wählen. Am Programmende werden die Zeichensätze mittels vst_unloadfonts aus dem Speicher gelöscht:

vst_unload_fonts(vdi_handle, select);

In select übergeben wir wieder den Wert 0. Weitere Informationen über diese Routinen findet man in [1] und [2], Im englischsprachigen Handbuch sind die Parameter leider teilweise falsch beschrieben.

VDI-Aufrufe, die das GDOS benötigen, wie z.B. vst_load_fonts, verabschieden sich bei nicht installiertem GDOS in der Regel mit ein paar Bomben. Leider gibt es keine VDI-Routine, die das Vorhandensein von GDOS überprüft. Es gibt aber eine von Atari beschriebene Routine, die überprüft, ob GDOS installiert ist.[1] Die Funktion liefert den Wert 0, falls GDOS nicht installiert ist. Ich habe diese Routine mit Namen vq_gdos in Assembler mit aufgeführt. Um sie ins Pascal-Programm einzubinden, muß man die Funktion vq_gdos als EXTERNAL deklarieren und die assemblierte Routine hinzulinken (Compiler-Direktive {$L GDOS.O}). Dieses Problem stellt sich natürlich mit dem integrierten Inlineassembler nicht mehr, der bei Erscheinen dieses Artikel schon Bestandteil des Entwicklungpaketes sein wird. Dann muß die Routine nur mittels Inline-Anweisungen eingebunden werden.

Menübehandlung

Um im Programm zwischen den einzelnen Zeichensätzen wählen zu können, möchte ich den Schriften Menüeinträge zuordnen. Dazu erstelle ich zuerst mit Hilfe eines Resource Construction Sets einen Menübaum mit drei Titeln: GDOS Demo, Programmende und Schriften. Im Menü Schriften benenne ich die Box, in der sich die Einträge befinden, als MENU BOX. Dann kann ich später über die Object-Struktur (siehe Listing und [1]) auf die Größe der Box zugreifen. Ich füge nun 10 Einträge mit der Länge von 18 Zeichen und dem Text unbelegt ein. In diese trage ich während des Programmablaufs die Zeichensatznamen mittels menu_text ein. (Deshalb unbedingt auf die Länge von 18 Zeichen achten). Jetzt gebe ich dem ersten Eintrag den Namen SCHRIFT1. Zum Schluß brauche ich nur noch dem Quit- und dem Infoeintrag einen Namen zu geben, (siehe auch Listing ZEICHEN.I) und man kann mit dem Programmieren loslegen.

Jetzt ein paar Worte zum gesamten Programmaufbau: Nach einer Überprüfung der GDOS-Installation und erfolgreicher GEM-Initialisierung laden wir die Zeichensätze und erfragen deren Namen und Index. Die Namen tragen wir ins Menü Schriften ein. Wir verstecken nun noch restliche Menüeinträge und passen die Größe der Menübox an. Der System-Font wird als aktueller Zeichensatz im Menü abgehakt dargestellt. Damit ist die Routine Menü-Vorbereitung abgeschlossen. Nun öffnen wir ein Ausgabefenster, in dem wir einen Text ausgeben, damit wir die Zeichensätze auch sehen können. Jetzt kann man bequem mit Hilfe des Menüs zwischen den Schrifttypen umschalten.

Hat man in aller Ruhe alle Schriften bewundert, kann man das Programm beenden. Jetzt wird das Fenster geschlossen und gelöscht. Dann löschen wir noch das Menü und die Zeichensätze aus dem Speicher und melden uns bei GEM ab.

Literatur:

[1] Jankowski, Reschke, Rabisch, Atari ST Profibuch, Sybex-Verlag
[2] Geiß, D. und J., Vom Anfänger zum GEM-Profi, Hüthig-Verlag

PROGRAM GDOS_Zeischensaetze (INPUT,OUTPUT);

USES GEMDecl,GEMVdi,GEMAes;

CONST
{$I GDOS\ZEICHEN.I}

TYPE
    NAMEN_FELD = ARRAY[1..10] OF STRING[32]

{ Die Struktur Objekt enthält alle wichtigen }
{ Informationen über Objekte. (z.B. Boxen,   }
{ Menutitel,-einträge) siehe hierzu in [1]  }
    Object = RECORD
            o_next, o_start, o_end,
            o_type, o_flags, o_status : INTEGER;
            o_spec : POINTER;
            o_x, o_y, o_w, o_h : INTEGER;
        END;

    Tree = ARRAY [0..50] of Object;
    TreePtr = ATree;


VAR workin          : IntIn_Array;
    workout         : WorkOut_Array;
    men             : TREEPtr;

{ folgende Felder sind für Schriftinformationen } 
    schrift_index   : ARRAY_10;
{ Index }
    SCHRIFT         : ARRAY_10;
{ Nummer des Menüeintrages }
    schrift_text    : NAMEN_FELD;
{ Name der Schrift }

    GDOS_FEHLT,RSC_FEHLT,
    INFO            : STRING;
    x0,y0,w0,ch_bh, 
    h0,anzahl,junk,
    handle,vdi_handle : INTEGER;
    fenst_titel     : STRING;


FUNCTION vq_gdos:INTEGER;
EXTERNAL;
{ Unsere Assembler Routine }
{$L GDOS\GDOS.O}

FUNCTION Init_Resource:BOOLEAN;
VAR ResourceName :  STRING;
    fehler       :  INTEGER;
BEGIN

{ Wegen C-Konvention endet String mit ASCII 0 } 
    ResourceName := 'ZEICHEN.RSC' + #0;
{ und beginnt bei STRING[1] }
    rsrc_load(addr(ResourceName[1]));

    fehler:=GemError;
    IF fehler = 0 THEN
        junk:=form_alert(1,addr(RSC_FEHLT[1]))
    ELSE
        rsrc_gaddr(R_TREE,MENU, men); 
        Init_Resource:=fehler>0;
{ true: RCS geladen }

END;

FUNCTION Init_Gem:BOOLEAN;
VAR aes_handle,la:INTEGER;
    rsc_load:BOOLEAN;
BEGIN
    AES_handle := appl_init;
{ Beim AES anmelden }
    
    IF AES_handle >= 0 THEN BEGIN

        vdi_handle:=graf_handle(la,ch_bh,la,la);
{ Kennung des physikalischen Arbeitsgerätes und } 
{ Höhe des Zeichensatzes erfragen               }

{ Parameter für den v_opnvwk-Aufruf }
        FOR la := 0 TO 9 DO workin[la] := 1; 
        workin[10] := 2; { Rasterkoordinaten }

        v_opnvwk(workin, vdi_handle, workout);
{ virtueller Bildschirm eröffnen }

        rsc_load:=Init_Resource;
        END;
    Init_Gem := (AES_handle >= 0) AND rsc_load;
{ Hat alles geklappt! Dann kann's losgehen }
END;

PROCEDURE Exit_Gem;
BEGIN
    rsrc_free;
    v_clsvwk(vdi_handle);
{ Virtueller Bildscchirm abmelden } 
    appl_exit;
{ Beim AES abmelden }
END;

PROCEDURE Do_Redraw(window,x0,y0,w0,h0:INTEGER); 
VAR p:ARRAY_4;
BEGIN
{ Bearbeitung beginnen }
    wind_update(BEG_UPDATE); p[0] : = x0;
    p[1] := y0; 
    p[2] := x0 + w0 - 1; 
    p[3] := y0 + h0 - 1;
{ Zeichenbereich festlegen } 
    vs_clip(vdi_handle, 1, p);
{ Parameter festlegen und Fensterhintergrund }
{ malen                                      }
    vsf_color(vdi_handle, WHITE); 
    vsf_interior(vdi_handle, SOLID); 
    vr_recfl(vdi_handle, p);
{ Text ausgeben }
    v_gtext(vdi_handle, x0+40, y0+40, 'Das ist ein GDOS-Zeichensatz ! ');
    wind_update(END_UPDATE)

END ;


PROCEDURE Menu_Vorbereitung;
VAR     la      :   INTEGER;
        hilf    :   STRING;
BEGIN
{ Zeichensätze laden }
    anzahl:=vst_load_fonts(vdi_handle,0); 
    anzahl:=anzahl+1;
{ Systemzeichensatz zählt auch }

{ Namen und Index werden erfragt    }
{ und in Felder eingetragen         }
    FOR la := 1 TO anzahl DO 
        schrift_index[la]:= vqt_name(vdi_handle,la,schrift_text[la]);

    FOR la:=1 TO anzahl DO 
{ Namen der Zeichensätze als Menüeinträge } 
        BEGIN
        hilf:=Copy(schrift_text[la],1,16); 
        hilf:=Concat('  ',hilf);
{ Index des Menüeintrages wird in SCHRIFT[ ] }
{ gespeichert                                }
        Schrift[la]:=SCHRIFT1+la-1; 
        menu_text(men,Schrift[la],addr(hilf[1])) 
        END;

    FOR la:=anzahl+1 TO 11 DO 
{ restliche Einträge verstecken }
        men^[SCHRIFTl+la-1].o_flags:=men^[SCHRIFT1+la-1].o_flags OR HIDETREE;
{ Größe der Menübox anpassen }
        men^[MENU_BOX].o_h:=anzahl*ch_bh;

{ Systemzeichensatz ist ausgewählt }
        Menu_iCheck(men,SCHRIFT[1],1);
END;

PROCEDURE Event_Loop;
VAR     la,dummy:   INTEGER;
        last    :   INTEGER;
        msg     :   ARRAY[0..15] OF INTEGER;
        schluss :   BOOLEAN;

BEGIN
    last:=SCHRIFT[1];
{ last merkt sich Menüindex, der zuletztaus-    }
{ ausgewählten Schrift                          }

    schluss:=FALSE;
    REPEAT
        Evnt_mesag(@msg) ;
        IF msg[0] = MN_SELECTED THEN 
        BEGIN FOR la:=1 TO anzahl DO
            IF msg[4] = SCHRIFT[la] THEN 
{ Schrift setzen und Menüeintrag        }
{ kennzeichnen                          }
                BEGIN
                vst_font(vdi_handle, schrift_index[la]);
                Do_Redraw(handle,x0,y0,w0,h0); 
                menu_icheck(men,last,0); 
                menu_icheck(men,SCHRIFT[la],1); 
                last:=SCHRIFT[la];
                END;
        IF msg[4] = ENDE THEN 
            schluss:=TRUE;
        IF msg[4] = ABOUT THEN
            junk:=form_alert(1,addr(INFO[1])); 
        menu_tnormal(men,msg[3],1);
        END;

    UNTIL Schluss;

END;



BEGIN {HAUPTPROGRAM}
    GDOS_FEHLT:='[3][ | GDOS ist nicht installiert ! ][Ende]'+#00 ;
    RSC_FEHLT:='[3][ | ZEICHNEN.RSC nicht gefunden ! ][Ende]'+#00 ;
    INFO:='[0][ | GDOS-Demo by Wolfgang Sattler !][OK]'+#00;

    junk:=0;
    IF vq_gdos = 0 THEN
        junk:=form_alert(1,addr(GDOS_FEHLT[1])); 
    IF Init_Gem AND (junk=0) THEN 
        BEGIN
        Menu_Vorbereitung; 
        menu_bar(men,1);

        x0:=10; 
        y0:=100; 
        w0:=400; 
        h0:=100;
        fenst_titel:=' Ausgabefenster '+#00 +#00; 
        handle:=wind_create(NAME,x0,y0,w0,h0); 
        wind_set(handle,WF_NAME,HiPtr(fenst_titel[1]),LoPtr(fenst_titel[1]),0,0); 
        wind_open(handle,x0,y0,w0,h0); 
        wind_get(handle,WF_WORKXYWH, x0,y0,w0,h0);
        Do_Redraw(handle,x0,y0,w0,h0);
        
        graf_mouse(ARROW, NIL);

        Event_Loop;

        wind_close(handle); 
        wind_delete(handle); 
        menu_bar(men,0); 
        vst_unload_fonts(vdi_handle,0);
{ löscht Zeichensätze aus dem Speicher }

        Exit_Gem;
        END;

END.
; Assemblerroutine zur Überprüfung der 
; GDOS-Installation
; Erstellt mit MAS-68K von Borland

                .xdef VQ_GDOS 
VQ_GDOS:        move.l (a7)+,a0
                    ; Rücksprungadresse merken 
                move.w #-2,d0 
                trap   #2 
                cmp.w  #-2,d0 
                sne    d0
                ext.w  d0 
                move.l d0,(sp) 
                jmp (a0)
                    ; zurück zum Hauptprogramm
                .end

Wolfgang Sattler
Aus: ST-Computer 06 / 1991, Seite 82

Links

Copyright-Bestimmungen: siehe Über diese Seite