HomeProtokolleXAccXSSI-Protokoll

15.14 xFSL-Schnittstelle

Spätestens seit der Einführung von Vektorfonts erfreut sich das GDOS, das jahrelang auf dem Atari ein Schattendasein führte, steigender Beliebtheit. Immer mehr Programme bieten die Möglichkeit, für die Ausgabe (und teilweise auch für die Eingabe) einen anderen Font als den Systemfont zu verwenden.

Um nun einen Font auswählen zu können, benötigt man einen Fontselektor. Und damit nicht jeder Programmierer sein eigenes Süppchen kocht und im Sinne einer einheitlichen Bedienung entstand der Wunsch nach einer Systemerweiterung, die einen Fontselektor — ähnlich wie einen Fileselektor — für alle Programme zur Verfügung stellt.

Das erste derartige Programm war der UFSL von Michael Thänitz. Er stellt über einen Cookie Routinen zum Aufruf eines Fontselektors zur Verfügung. Diese Schnittstelle wird bereits von einer Reihe von Programmen verwendet und es gibt auch bereits weitere Fontselektoren, die über diese Schnittstelle aufgerufen werden können.

Zwar läßt sich nun über die UFSL–Schnittstelle ein Fontselektor aufrufen, doch hat diese Schnittstelle bereits eine Reihe von — zum Teil inkompatiblen — Änderungen und Erweiterungen hinter sich. Daher gehen die meisten Programme heute davon aus, daß sie nur die ursprüngliche einfache UFSL-Schnittstelle zur Verfügung haben. Im Endeffekt bleiben also die Erweiterungen ungenutzt und wenn in einem Programm dann doch einmal ein etwas leistungsfähigerer Fontselektor benötigt wird, dann geht man doch wieder dazu über, extra für das Programm einen neuen Fontselektor zu schreiben. Etwas überspitzt formuliert wird hier also die Idee eines externen Fontselektors ad absurdum geführt ...

Durch den Wildwuchs an der UFSL-Schnittstelle erschien es sinnvoller, einen klaren Trennstrich zu ziehen und eine komplett neue Schnittstelle zu entwickeln, die dann auch über einen neuen Cookie angeboten wird.

Dieser Text beschreibt diese neue Schnittstelle, über die nicht nur einfach ein Fontselektor aufgerufen, sondern auch in vielfältiger Weise Einfluß auf diesen genommen werden kann.

15.14.1 Die xFSL–Schnittstelle

Über die xFSL–Schnittstelle hat der Aufrufer (d.h. das Programm, das den Fontselektor aufruft) wesentlich mehr Einfluß auf den Fontselektor, sein Verhalten und auf die zur Auswahl angebotenen Fonts.

Bei der Konzeption der neuen Schnittstelle wurde versucht, auf die Möglichkeiten der verschiedenen Programmiersprachen Rücksicht zu nehmen (z.B. Vermeidung von Zeigern auf Funktionen) und gleichzeitig für mögliche Erweiterungen der Schnittstelle gerüstet zu sein.

Die Anpassung eines Programms an die xFSL–Schnittstelle sollte eine Sache von wenigen Minuten sein, zumal Beispielaufrufe in verschiedenen Programmiersprachen mitgeliefert werden. Die Umsetzung spezieller Wünsche ist natürlich u.U. etwas aufwendiger, sollte aber auch kein unlösbares Problem darstellen.

Es folgt die Beschreibung des xFSL–Cookies sowie der verschiedenen xFSL–Aufrufe und Parameter ...

15.14.1.1 Der xFSL–Cookie

Wenn ein Fontselektor installiert ist, der die xFSL–Schnittstelle unterstützt, dann existiert ein Cookie xFSL, dessen Wert ein Zeiger auf die folgende Struktur ist:

typedef struct
{
 unsigned long xfsl;       /* Magic 'xFSL'              */
 unsigned int  revision;   /* Schnittstellen-Revision   */
 unsigned long product;    /* Kennung des Fontselektors */
 unsigned int  version;    /* Version des Fontselektors */
 xFSL_INPUT    xfsl_input; /* einfacher Aufruf          */
 xFSL_INIT     xfsl_init;  /* Init-Aufruf               */
 xFSL_EVENT    xfsl_event; /* Event-Aufruf              */
 xFSL_EXIT     xfsl_exit;  /* Exit-Aufruf               */
 xFSL_INFO     xfsl_info;  /* Info-Aufruf               */
} xFSL;

Die Komponenten der Struktur im einzelnen:

(xfsl Hier steht, nur zur Sicherheit, nochmals die ASCII–Zeichenfolge xFSL (entspricht hexadezimal $7846534C).
revision Dies ist die Revisionsnummer der xFSL–Schnittstelle, sie enthält z.Z. den Wert 4. Sollte die Schnittstelle erweitert werden, so werden dort entsprechend höhere Werte zu finden sein.
product Hier findet sich eine Kennung für den tatsächlich installierten Fontselektor. Diese Angabe ist jedoch nur als zusätzliche Information gedacht und sollte von Anwendungsprogrammen, die den Fontselektor aufrufen wollen, nicht ausgewertet werden!

Bisher verwendete Kennungen:

Kennung Fontselektor
CLVN Calvino
FSEL FontSel
HUGO HuGo!


Die Kennung (wie auch die folgende Versionsnummer) wurde nur für Programme eingeführt, die eine Information über den installierten Fontselektor ausgeben wollen (z.B. das Programm SysInfo).
version Die Versionsnummer des installierten Fontselektors als BCD–Zahl (z.B. hexadezimal $100 für Version 1.00). Hier gelten sinngemäß die Anmerkungen zum Feld product.
xfsl_input Dies ist der Einsprungpunkt für einen vereinfachten Aufruf des Fontselektors. Der Fontselektor erscheint dann immer als modaler Dialog und die meisten zusätzlichen Features der xFSL–Schnittstelle können nicht angesprochen werden.
xfsl_init, xfsl_event, xfsl_exit Diese drei Funktionen bilden zusammen den erweiterten Fontselektor–Aufruf. Hierüber können alle neuen Features angesprochen werden. Die Vorgehensweise entspricht dem Darstellen eines GEM-Dialogs:

  1. Fontselektor darstellen (xfsl_init)

  2. Eventbehandlung in einer Schleife, bis OK oder Abbruch angewählt wurde (xfsl_event)

  3. Fontselektor vom Bildschirm entfernen (xfsl_exit

xfsl_info Über diese Aufruf können einige der Features des installierten Fontselektors abgefragt werden, z.B. Drag&Drop–Unterstützung.

15.14.1.2 Der vereinfachte Aufruf (xfsl_input)

xfsl_input ist der Einsprungpunkt für einen vereinfachten Aufruf. Der Fontselektor kann darüber nur als modaler Dialog aufgerufen werden. Außerdem kann eine Überschrift angegeben und eingeschränkt werden, welche Arten von Fonts der Selektor zur Auswahl stellen soll.

int xfsl_input (int           vdihandle,
                unsigned int  fontflags,
                const char   *headline,
                int          *id,
                int          *size
               );

Die Parameter im einzelnen:

vdihandle Hier übergeben Sie das Handle einer von Ihrem Programm bereits geöffneten virtuellen VDI–Workstation (wenn Sie in Ihrem Programm einen Font einstellen wollen, müssen Sie ja ohnehin eine solche VDI-Workstation öffnen). Der Fontselektor übernimmt dann den auf dieser Workstation gerade eingestellten Font als aktuellen Font (vorausgesetzt, er wird durch die Fontflags überhaupt zur Auswahl gestellt).

Statt eines gültigen Handles können Sie aber auch einfach eine Null übergeben, dann wird der Fontselektor den Font anzeigen, den Sie in den Parametern id und size übergeben.

Wenn Sie ein VDI–Workstation–Handle übergeben, wird der ausgewählte Font auf dieser Workstation auch gleich eingestellt.
fontflags Über die Fontflags können Sie festlegen, welche Fonts überhaupt zur Auswahl gestellt werden.
headline Hier können Sie eine Überschrift angeben, die dann im Fontselektor erscheint. Fehlt die Überschrift (Übergabe von 0L), dann wird ein Defaulttext (Fontauswahl o.ä.) eingesetzt.
id In dieser Variablen wird die ID des ausgewählten Zeichensatzes zurückgeliefert (natürlich nur, wenn auch wirklich ein Zeichensatz ausgewählt wurde). Dieser Zeichensatz kann nun direkt mit der VDI-Funktion vst_font() eingestellt werden.

Wenn Sie in vdihandle eine Null übergeben, wird der Fontselektor den in id angegebenen Font anzeigen.
size In dieser Variablen wird die Größe des ausgewählten Fonts in Punkt zurückgegeben (auch nur, wenn wirklich ein neuer Zeichensatz ausgewählt wurde). Wenn es sich um einen Bitmapfont handelt, kann diese Größe mit der VDI–Funktion vst_point eingestellt werden. Für Vektorfonts sollte die Funktion vst_arbpt aufgerufen werden.

Wenn Sie in vdihandle eine Null übergeben, wird der Fontselektor den in id angegebenen Font in der in size angegebenen Größe anzeigen.

Rückgaben

xfsl_input liefert eine negative Zahl zurück, wenn ein Fehler aufgetreten ist. Eine 0 wird zurückgegeben, wenn Abbruch angewählt wurde. Wird eine 1 zurück geliefert, dann wurde ein neuer Font ausgewählt.

Die Rückgabewerte sind für alle xFSL–Funktionen gleich und aufwärtskompatibel zu den Rückgabewerten des UFSL.

15.14.1.3 Der erweiterte Aufruf

Der erweiterte xFSL–Aufruf besteht aus drei einzelnen Funktionsaufrufen:

xfsl_init Stellt den Fontselektor auf dem Bildschirm dar. Außerdem werden hier die Parameter übergeben.
xfsl_event Diese Funktion wird solange immer wieder aufgerufen, bis im Fontselektor ein Font ausgewählt, oder Abbruch angewählt wurde.
xfsl_exit Entfernt den Fontselektor wieder vom Bildschirm.

In C kann das dann beispielsweise so ausssehen:

xhandle = xfsl->xfsl_init (vdihandle, &xpar);
if (xhandle >= 0)
{
  do
  {
    ret = xfsl->xfsl_event (xhandle, 0L);
    if (ret == xFS_HELP)
      ...;  /* Hilfefunktion aufrufen */
    else if (ret == xFS_POPUP)
      ...;  /* Popup behandeln        */
    else if (ret == xFS_EVENT)
      ...;  /* AES-Event bearbeiten   */
  } while ((ret != xFS_OK) && (ret != xFS_STOP));
  xfsl->xfsl_exit (xhandle);
}

Diese Dreiteilung hat u.a. den Vorteil, daß zur Bearbeitung der Ereignisse (Hilfe–Button, Popup, AES–Events) keine Zeiger auf Funktionen übergeben werden müssen (was in einigen Programmiersprachen nur schwer zu realisieren ist). Auch läßt sich die Schnittstelle so leicht um weitere Ereignisse erweitern, falls dies einmal nötig sein sollte.

15.14.1.3.1 xfsl_init

Dieser Aufruf bringt nicht nur den Fontselektor auf den Bildschirm, er bestimmt auch, welche Fonts angezeigt werden sollen, ob ein User–Popup verwendet wird und einiges mehr.

int xsfl_init (int       vdihandle,
               xFSL_PAR *xpar
              );

Die beiden Parameter bedeuten:

vdihandle Hier übergeben Sie, wie schon beim vereinfachten Aufruf, das Handle einer von Ihrem Programm bereits geöffneten virtuellen VDI–Workstation oder einfach eine Null.

Wenn Sie ein gültiges Workstation–Handle übergeben, wird der Fontselektor den auf dieser Workstation aktuellen Font übernehmen und anzeigen — sofern er duch die Fontflags (in der xFSL_PAR–Struktur) überhaupt zur Auswahl gestellt wird. Ist dies nicht der Fall, wird der Fontselektor einen Font aus den zur Verfügung stehenden auswählen und anzeigen.

Übergeben Sie als Workstation–Handle eine Null, dann wird der Font aus der PFONTINFO–Struktur (auf die ein Zeiger in der xFSL_PAR–Struktur zeigt) übernommen und angezeigt.

Wenn Sie ein VDI–Workstation–Handle übergeben, wird der ausgewählte Font auf dieser Workstation auch gleich eingestellt.
xpar Dies ist ein Zeiger (d.h. die Adresse) auf eine xFSL_PAR–Struktur, die alle weiteren Angaben für den Fontselektor enthält.

Wegen der Vielzahl der Möglichkeiten wurde dieser Struktur ein eigener Abschnitt gewidmet.

Für die Returncodes der Funktion gilt wieder: Ein negativer Rückgabewert deutet auf einen Fehler hin. Positive Werte haben hier eine etwas abweichende Bedeutung: Eine 0 heißt, der Fontselektor wurde (erfolgreich) als modaler Dialog geöffnet. Andere positive Werte entsprechen dem Fensterhandle des geöffneten Fontselektors. Somit können Sie das Fenster des Fontselektors beispielsweise bei einem AV–Server anmelden.

Im Erfolgsfalle (Rückgabe größer oder gleich 0) sollten Sie sich das Handle in einer Variablen merken, da es für die folgenden Aufrufe (xfsl_event und xfsl_exit) noch benötigt wird.

Hinweis: Wenn der Fontselektor als Fenster dargestellt werden sollte, xfsl_init aber den Fehler xFS_NO_WINDOW liefert (kein Fenster mehr frei), dann sollte möglichst versucht werden, den Fontselektor wenigstens als Dialog darzustellen (Kontrollflag CC_WINDOW löschen und nochmals xfsl_init aufrufen).

Merke: Der Anwender will einen Fontselektor, keine Fehlermeldung.

15.14.1.3.2 xfsl_event

Wenn der Fontselektor initialisiert und auf den Bildschirm gebracht wurde, übernimmt xfsl_event die Hauptarbeit.

int xfsl_event (int    xhandle,
                EVENT *event
               );

Die beiden Parameter bedeuten:

xhandle Das Handle des Fontselektors, wie es von xfsl_init geliefert wurde.
event Zeiger auf eine EVENT–Struktur, wie sie von Pure C verwendet wird. In dieser Struktur liefert der Fontselektor AES–Events zurück, die er nicht selbst bearbeiten konnte. Außerdem können Sie über die Eingabeparameter dem Fontselektor auch mitteilen, über welche Ereignisse sie überhaupt unterrichtet werden wollen.

Der Zeiger kann aber auch einfach Null sein, wenn Sie keine (weiteren) Events auswerten wollen. Soll der Fontselektor als Fensterdialog betrieben werden und der Aufrufer (d.h. Ihr Programm) hat noch weitere Fenster offen, dann müssen Sie aber zumindest die Redraw–Meldungen auswerten!

Beispiel: Wenn Sie in ev_mflags das Flag MU_MESAG setzen, wird der Fontselektor alle eintreffenden AES–Nachrichten, die er nicht selbst bearbeiten kann, an den Aufrufer zurückliefern.

Hinweis: Es ist natürlich auch möglich, Timer–Events zu bekommen. Diese sollten aber sparsam eingesetzt werden und nicht zu kurz sein, da der Fontselektor dazu jedesmal erst seine eigene Event–Schleife verlassen muß. 250 ms mögen als — unverbindliche — untere Grenze gelten.

Die möglichen Rückgabewerte von xfsl_event:

xFS_STOP Im Fontselektor wurde der Button Abbruch oder (so vorhanden) der Closer des Fensterdialogs angewählt.

Wenn das Kontrollflag CC_CLOSER gesetzt ist und der Closer angeklickt wurde, enthält die PFONTINFO–Struktur, auf die der Zeiger in der xFSL_PAR–Struktur zeigt, aber trotzdem Angaben darüber, welcher Font zuletzt im Fontselektor angewählt worden war. Anders wäre diese Information sonst ja nicht zu erhalten.
xFS_OK Es wurde ein Font ausgewählt und OK angewählt. Welcher Font ausgewählt wurde, beschreibt die PFONTINFO–Struktur, auf die der Zeiger in der xFSL_PAR–Struktur zeigt. Wenn bei xfsl_init ein gültiges VDI–Handle übergeben wurde, dann wird der ausgewählte Font auch gleich auf dieser VDI–Workstation eingestellt.
xFS_HELP Der Hilfe–Button wurde angewählt (kann natürlich nur auftreten, wenn Sie ihn haben einblenden lassen). Es liegt nun am Aufrufer, wie er darauf reagiert. Im Normalfall wird man wohl eine Hilfe geben, z.B. indem man eine Hilfsseite anzeigt oder anzeigen läßt.
xFS_EVENT Ein AES–Event ist aufgetreten, den der Fontselektor nicht bearbeiten konnte (z.B. eine Redraw–Meldung für ein anderes Fenster). Welcher Event es genau war, können Sie dem Feld ev_mwich der EVENT–Struktur entnehmen.

Accessories sollten bei Eintreffen der Nachricht AC_CLOSE den Aufruf von xfsl_exit nicht vergessen! Gleiches gilt analog für die Nachricht AP_TERM.
xFS_POPUP Am User–Popup (sofern vorhanden) wurde ein Veränderung vorgenommen. Bei dem Popup–Eintrag, der geändert wurde, ist im Element fontflags das Bit FF_CHANGED gesetzt. Der Popup–Eintrag, der jetzt angewählt wurde und bei Rückkehr in den Fontselektor (beim nächsten xfsl_event–Aufruf) der aktuelle des Popups sein wird, steht im Element sel_entry.

Sie haben jetzt noch die Möglichkeit, Änderungen an den Popup–Einträgen vorzunehmen, beispielsweise die Fontflags zu ändern oder den geänderten Font in alle anderen Popup-Einträge zu übernehmen (auf diese Weise ist es auch möglich, das Popup für eine andere Information zu verwenden, die mit den ausgewählten Fonts nichts zu tun hat). Die Texte und die Anzahl der Popup-Einträge dürfen aber nicht verändert werden!
andere Werte: Andere positive Werte sollten ignoriert werden. Es ist möglich, daß die Schnittstelle um weitere Rückgabewerte (Ereignisse) erweitert wird.

Negative Werte zeigen einen Fehler an, der Fontselektor sollte dann abgebrochen werden. Dazu muß aber unbedingt noch xfsl_exit aufgerufen werden!
15.14.1.3.3 xfsl_exit

Mit dem xfsl_exit–Aufruf wird der Fontselektor wieder vom Bildschirm entfernt:

void xfsl_exit (int xhandle);

Dabei ist xhandle wieder das Handle des Fontselektors, wie es von xfsl_init geliefert wurde.

xfsl_exit muß immer dann aufgerufen werden, wenn die Behandlung des Fontselektors beendet werden soll. Sei es dadurch, daß ein Font ausgewählt oder Abbruch angewählt wurde, oder daß xfsl_event einen Fehler meldete. Wenn schon der xfsl_init–Aufruf fehlgeschlagen ist, darf xfsl_exit nicht aufgerufen werden (logisch, da man ja auch kein gültiges Handle hat).

Der Aufruf von xfsl_exit sollte auch bei Eintreffen der Nachrichten AC_CLOSE und AP_TERM nicht vergessen werden!

15.14.1.3.4 Der Info–Aufruf (xfsl_info)

Über diesen Aufruf können einige der Features des installierten Fontselektors abgefragt werden:

long xfsl_info (void);

Wenn der Rückgabewert positiv ist, dann stehen die folgenden Flags für vorhandene Features (negative Rückgabewerte sind, wie üblich, Fehlermeldungen):

Name Wert Bedeutung
XF_SIZE 0x0001 Größenänderung möglich
XF_COLOR 0x0002 Farbänderung möglich
XF_ATTR 0x0004 Attributänderung möglich
XF_WIDTH 0x0008 Breitenänderung möglich
XF_KERN 0x0010 Kerningänderung möglich
XF_SKEW 0x0020 Neigungsänderung möglich
XF_ALIGN 0x0040 Änderung der Ausrichtung möglich
XF_ROTATION 0x0080 Textrotation möglich
XF_FIX31 0x0100 fix31-Unterstützung
XF_POPUP 0x0200 Popup-Unterstützung
XF_DRAGDROP 0x0400 Drag&Drop-Unterstützung
XF_MAPPING 0x0800 beherrscht Mapping

Weitere Features des Fontselektors lassen sich indirekt über das Element control der xFSL_PAR–Struktur abfragen: Bei einem erfolgreichen xfsl_init–Aufruf werden diejenigen Kontrollflags gelöscht, die der Fontselektor nicht kennt.

15.14.1.3.5 Die VDI–Workstation

Bei den Aufrufen xfsl_input und xfsl_init kann jeweils das Handle einer vom Aufrufer bereits geöffneten virtuellen VDI–Workstation übergeben werden. Davon, ob man tatsächlich ein Handle einer Workstation oder einfach eine Null übergibt, hängt das weitere Verhalten des Fontselektors ab:

Übergibt man ein gültiges Handle, so wird der Fontselektor versuchen, den auf der entsprechenden Workstation gerade aktuellen Font zu ermitteln und diesen dann — sofern er zu den übergebenen Fontflags paßt — auch einstellen und zur Auswahl anbieten. Paßt der aktuelle Font nicht zu den Fontflags (wenn z.B. nur Vektorfonts angeboten werden sollen, der aktuelle Font aber ein Bitmapfont ist), so wird der Fontselektor einen Font aus den tatsächlich angebotenen auswählen und als aktuellen Font präsentieren.

Wählt der Anwender nun einen Font aus und beendet den Fontselektor mit OK, so wird dieser Font auch gleich auf der übergebenen Workstation eingestellt, so daß das aufrufende Programm dies nicht mehr übernehmen muß.

Dabei gilt es zu beachten, daß der Fontselektor ebenfalls eine eigene VDI–Workstation öffnet und diese intern und zur Auswahl der Fonts verwendet. U.a. wird er für diese Workstation auch vst_load_fonts() aufrufen (sofern ein GDOS installiert ist). Dies kann zu unerwarteten Resultaten führen, wenn auf der übergebenen Workstation noch kein vst_load_fonts() aufgerufen wurde und der Anwender im Fontselektor einen Font auswählt, der erst nach einem vst_load_fonts()–Aufruf zur Verfügung steht!


Statt eines Workstation–Handles kann man aber auch einfach eine Null übergeben. Der Fontselektor wird den aktuellen Font dann aus den übergebenen Parametern (beim xfsl_input–Aufruf) bzw. aus der xFSL_PAR–Struktur (beim xfsl_init–Aufruf) ermitteln.

Der ausgewählte Font wird dann (logischerweise) auch nur in den Parametern bzw. der xFSL_PAR–Struktur zurückgegeben und der Aufrufer muß ihn dann selbst einstellen.

15.14.1.3.6 Die xFSL_PAR-Struktur

Über diese Struktur haben Sie weitgehenden Einfluß auf das Verhalten des Fontselektors und die Art der dargestellten Fonts. Daher fällt die Beschreibung der Möglichkeiten auch etwas länger aus ...

typedef struct
{
 int            par_size;    /* Größe der xFSL_PAR-Struktur   */
 int            pfi_size;    /* Größe der PFONTINFO-Struktur  */
 unsigned long  control;     /* Kontrollflags                 */
 const char    *headline;    /* Überschrift oder 0L           */
 const char    *example;     /* Beispieltext oder 0L          */
 const char    *helptext;    /* Text des Hilfe-Buttons od. 0L */
 PFONTINFO     *font;        /* Zeiger auf Fontinfo-Struktur  */
 unsigned int   fontflags;   /* erlaubte Fontarten            */
 const char    *poptext;     /* Text vor dem Popup oder 0L    */
 int            num_entries; /* Anzahl der Einträge (0..n)    */
 int            sel_entry;   /* Selektierter Eintrag (0..n-1) */
 xFSL_PENTRY   *popup;       /* Zeiger auf ein Popup oder 0L  */
 char          *helpinfo;    /* Zeiger auf Hilfedatei/-seite  */
} xFSL_PAR;

Trotz der Vielzahl der Einträge ist eigentlich alles ganz einfach, zumal Sie Felder, die Sie nicht benötigen oder deren Bedeutung Ihnen noch nicht klar ist, einfach mit Null ausfüllen können, worauf der Fontselektor dann sinnvolle Defaultwerte annehmen wird.

Die Felder im einzelnen:

par_size Dieses Feld darf nicht auf Null gesetzt werden, hier wird die Größe der xFSL_PAR–Struktur in Bytes eingetragen, weshalb man in C einfach schreiben kann
xpar.par_size=sizeof(xFSL_PAR);


Die Größe der Struktur beträgt z.Z. 42 Bytes. Sollte die Struktur erweitert werden, kann der Fontselektor an der Größenangabe erkennen, ob er es mit einer neuen oder einer alten Struktur zu tun hat.
pfi_size Auch dieses Feld darf nicht Null sein, hier muß die Größe der PFONTINFO–Struktur eingetragen werden, also
xpar.pfi_size=sizeof(PFONTINFO);


Die aktuelle Größe der PFONTINFO–Struktur beträgt 38 Bytes und könnte ebenfalls in Zukunft erweitert werden.
control Dies sind die sogenannten Kontrollflags, über die das Verhalten des Fontselektors beeinflußt werden kann (z.B. ob er als Fenster oder als Dialog erscheinen soll).

Diesen Flags wurde ein eigener Abschnitt gewidmet.
headline Dies ist, wie schon vom einfachen Aufruf her bekannt, ein Zeiger auf eine Überschrift für den Fontselektor. Fehlt diese (d.h. headline enthält Null), dann wird der Fontselektor eine Default–Überschrift einsetzen.

Die Länge der Überschrift sollte sich in dem noch vom UFSL vorgegebenen Rahmen (34 Zeichen) bewegen, der Fontselektor wird längere Überschriften aber ggfs. kürzen.
example Ein Zeiger auf einen Beispieltext. Der Fontselektor zeigt für den jeweils eingestellten Font ein Schriftbeispiel an, dessen Text hiermit vorgegeben werden kann. Fehlt dieser Text (d.h. example enthält Null), wird der Fontselektor einen Defaulttext anzeigen (z.B. den Namen des jeweiligen Zeichensatzes).
helptext Dies ist der Text für einen Button, der links unten im Fontselektor eingeblendet werden kann. Im Normalfall wird man dort einen Button mit der Aufschrift Hilfe oder Help einblenden wollen, um dem Anwender die Funktion des Fontselektors zu erklären, und wofür der ausgewählte Font verwendet wird.

Fehlt dieser Text (d.h. helptext enthält Null), wird auch kein Hilfe-Button eingeblendet. Dann wird xfsl_event auch nicht den Rückgabewert xFS_HELP liefern.

Man sollte einen kurzen Text wählen (etwa 8 Zeichen), der Fontselektor wird längere Texte aber ggfs. kürzen.
font Dies ist ein Zeiger auf eine Struktur (PFONTINFO), die einen Font beschreibt. Die Struktur wird sowohl zur Übergabe von Werten an den Fontselektor als auch zur Rückgabe des ausgewählten Fonts verwendet.

Auch dieser Struktur ist ein eigener Abschnitt gewidmet.
fontflags Dies sind wieder die vom einfachen Aufruf bekannten Fontflags, mit denen Sie die zur Auswahl gestellten Fonts beeinflußen können.
poptext, num_entries, sel_entry, popup: Mit diesen vier Parametern können Sie ein zusätzliches Popup in den Fontselektor einblenden lassen. Wegen der vielfältigen Möglichkeiten gibt's dafür auch wieder einen eigenen Abschnitt.

Wollen Sie kein Popup, so setzen Sie diese vier Werte einfach auf Null.
helpinfo Dies ist ein reiner Ausgabeparameter: Wenn der Hilfe–Button angewählt wurde (sofern vorhanden, siehe helptext), dann steht hier ein Zeiger auf einen Dateinamen einer Hilfedatei und den Namen einer Seite, die angezeigt werden kann. Der Dateiname wird ohne Pfad und Extension angegeben, der Seitenname folgt direkt dahinter, durch ein Komma getrennt.
Der String darf nur gelesen, aber nicht verändert werden!


Wenn Sie bei xFS_HELP nicht selbst eine Hilfe anzeigen wollen, dann können Sie mit diesen Informationen ein Hilfesystem (z.B. ST–Guide) aufrufen.

Beispiel: xfsl_event gibt xFS_HELP zurück, in helpinfo findet sich ein Zeiger auf den String
toll,Der tollste Fontselektor aller Zeiten


Daraus läßt sich dann folgender Aufruf für ST-Guide erstellen:
*:\toll.hyp Der tollste Fontselektor aller Zeiten


Man hängt also an den Dateinamen die Extension für das jeweilige Hilfesystem an und übergibt den Teil nach dem ersten Komma als Seitenname.

Um es nochmals zu betonen: Felder, die sie nicht benötigen oder noch nicht verstehen, können Sie zunächst einfach auf Null setzen. Ausnahmen sind nur

15.14.1.3.7 Die Kontrollflags

Über die Kontrollflags kann das Verhalten des Fontselektors beeinflußt werden.

Name Wert Bedeutung
CC_WINDOW 0x0001 Fontselektor als Fenster
CC_APPMODAL 0x0002 Fontselektor ist applikationsmodal
CC_FIX31 0x0004 alle Größenangaben in 1/65536 Punkt
CC_FAKESTYLE 0x0008 Schnitte simulieren (nur Bitmapfonts)
CC_CLOSER 0x0010 Fenster mit Closer, kein OK-Button
CC_NOSIZE 0x0100 Größe nicht ändern
CC_NOCOLOR 0x0200 Farbe nicht ändern
CC_NOATTR 0x0400 Attribute nicht ändern
CC_NOWIDTH 0x0800 Breite nicht ändern
CC_NOKERN 0x1000 Kerning nicht ändern
CC_NOSKEW 0x2000 Skewing nicht ändern
CC_NOALIGN 0x4000 Ausrichtung nicht ändern
CC_NOROTATION 0x8000 Textrotation nicht ändern
CC_DFLTSIZE 0x10000 Schriftgröße "Default"
CC_INVSTYLE 0x20000 Attribut "Invers"

Die Funktion der einzelnen Flags sollte sich schon aus den Namen und den Kurzbeschreibungen ergeben. Hier noch einige Anmerkungen:

Bitte beachten: Nicht alle Fontselektoren unterstützen auch alle Kontrollflags! Wenn ein Fontselektor ein Flag nicht unterstützt, so wird er es einfach ignorieren. Bei einem erfolgreichen(!) xfsl_init-Aufruf wird der Fontselektor diejenigen Flags im Element control der xFSL_PAR-Struktur löschen, die er nicht versteht.

15.14.1.3.8 Die PFONTINFO-Struktur

Diese Struktur beschreibt einen Font. Sie enthält nach dem Aufruf des Fontselektors den ausgewählten Font. Zudem werden diese Angaben vom Fontselektor schon beim Aufruf ausgewertet (und der so beschriebene Font angezeigt), wenn als VDI–Handle eine Null übergeben wird.

typedef struct
{
 int          fontid;     /* ID des Fonts                  */
 int          fonttype;   /* Typ des Fonts                 */
 char        *fontname;   /* Name des Fonts                */
 union fsize  fontsize;   /* Fontgröße in pt oder fix31    */
 union fsize  fontwidth;  /* Breite in pt oder fix31       */
 char         trackkern;  /* Track-Kerning                 */
 char         pairkern;   /* Paar-Kerning                  */
 int          fontattr;   /* Attribute                     */
 int          fontskew;   /* Neigung                       */
 int          fontcol;    /* Farbe                         */
 int          backcol;    /* Text-Hintergrundfarbe         */
 int          halign;     /* horizontale Textausrichtung   */
 int          valign;     /* vertikale Textausrichtung     */
 int          rotation;   /* Textrotation in 1/10 Grad     */
 int          validtype;  /* Typ (V_CHAR_...) oder Mapping */
 int         *validchars; /* benötigte Zeichen oder 0L     */
} PFONTINFO;

Die Elemente im einzelnen:

fontid Die ID des Fonts, wie sie auch von der VDI–Funktion vqt_name() zurückgegegeben wird. Die Font–ID ist eine Zahl ungleich Null (kann also auch negativ sein).
fonttype Der Typ des Fonts, wie er ab Speedo 5 bzw. NVDI 3 verwendet wird:

Name Wert Fontart
BITMAP_FONT 0x0001 Pixel
SPEEDO_FONT 0x0002 Speedo
TT_FONT 0x0004 TrueType
PFB_FONT 0x0008 Type 1 (Postscript)


Diese Angaben sind z.Z. nur zur Information, aber ohne Bedeutung für den Fontselektor. Allerdings wird es künftig möglich sein, einen Font nicht nur anhand seiner ID, sondern auch anhand seines Namens zu setzen, wobei dann noch zusätzlich der Fonttyp benötigt wird.

Der Fonttyp ist aber auch von Interesse, wenn man die Größe des Fonts ändern will: Bei Bitmapfonts geschieht dies mit der VDI–Funktion vst_point(), bei allen anderen Typen (Vektorfonts) mit der Funktion vst_arbpt().
fontname Der Name des Fonts, wie er von vqt_name() geliefert wurde (möglicherweise wurden mehrfache Leerzeichen entfernt).

Der Aufrufer muß selbst genügend Platz für den Fontnamen zur Verfügung stellen, also für 32 Zeichen und ein Nullbyte! Wenn Sie den Fontnamen nicht benötigen, können Sie den Zeiger auch einfach auf Null setzen.
fontsize Die Größe des Fonts in Punkt (pt) oder 1/65536 Punkt (Typ fix31):
union fsize
{
 int   size;    /* Fontgröße in Punkt         */
 fix31 size31;  /* Fontgröße in 1/65536 Punkt */
};


Welche der beiden Angaben gültig ist, wird global über das Kontrollflag CC_FIX31 geregelt.
fontwidth Breite des Fonts in Punkt (pt) oder 1/65536 Punkt (Typ fix31):
union fsize
{
 int   size;    /* Fontgröße in Punkt         */
 fix31 size31;  /* Fontgröße in 1/65536 Punkt */
};


Welche der beiden Angaben gültig ist, wird global über das Kontrollflag CC_FIX31 geregelt.

Die Breite kann mit den VDI–Funktionen vst_width() in Punkt und mit vst_setsize() in fix31 eingestellt werden.
trackkern Dieser Parameter gibt die Art des Track–Kernings für vst_kern() an. Gültige Werte sind:

Wert Kerning
0 kein Kerning
1 normales Kerning
2 enges Kerning
3 sehr enges Kerning
pairkern Mit diesem Parameter kann das Pair–Kerning aus– (0) oder eingeschaltet (1) werden, vgl. vst_kern().
fontattr Dies sind die Fontattribute (Texteffekte), wie sie auch von der VDI–Funktion vst_effects() verwendet werden.

Calvino verwendet dieses Feld nur dann, wenn das Kontrollflag CC_FAKESTYLE gesetzt ist.
fontskew Die Neigung des Fonts in 1/10 Grad, vgl. vst_skew().
fontcol Die Farbe des Fonts. Es werden die VDI–Farben verwendet, d.h. 0 = Weiß, 1 = Schwarz, usw., vgl. vst_color().
backcol Die Hintergrundfarbe des Textes. Es werden die VDI–Farben verwendet, d.h. 0 = Weiß, 1 = Schwarz, usw. Das Setzen einer Text–Hintergrundfarbe wird vom VDI nicht direkt unterstützt, es obliegt daher dem Aufrufer, ob und wie dieser Parameter verwendet wird.
halign Hierüber kann die horizontale Textausrichtung angegeben werden: Der Text soll linksbündig, rechtsbündig oder zentriert ausgegeben werden.

Name Wert Ausrichtung
THA_LEFT 0 linksbündig
THA_CENTER 1 zentriert
THA_RIGHT 2 rechtsbündig


Diese Werte entsprechen dem Parameter für die horizontale Ausrichtung beim VDI–Aufruf vst_alignment().
valign Hierüber kann die vertikale Textausrichtung angegeben werden: Der Text soll an der Oberkante oder der Unterkante ausgerichtet oder (vertikal) zentriert ausgegeben werden.

Name Wert Ausrichtung
TVA_BOTTOM 0 an der Text-Unterkante
TVA_CENTER 1 vertikal zentriert
TVA_TOP 2 an der Text-Oberkante


Diese Werte entsprechen absichtlich nicht dem Parameter zur vertikalen Ausrichtung bei vst_alignment()! Die dort verwendeten Werte (Zeichenunterkante, Zeichenzellenunterkante) sind für den normalen Anwender wenig intuitiv und sollten daher nicht Teil des User–Interfaces sein (was sie bei der Auswahl im Fontselektor aber wären). Die Ausrichtung muß daher vom aufrufenden Programm in die richtigen Werte konvertiert werden.
rotation Textrotation in 1/10 Grad, wie sie auch von der VDI–Funktion vst_rotation() verwendet wird.

Fehlen noch die beiden Parameter validtype und validchars:

Manchmal ist es wichtig, sicherzustellen, daß der Font bestimmte Zeichen enthält. Dafür gibt es zwei Möglichkeiten:

Wenn validchars Null ist, kann man mit validtype eine der folgenden vier Gruppen von Zeichen auswählen:

Name Wert Bereich Kommentar
V_CHAR_IND -1 - "egal"
V_CHAR_ASC -2 32-126 alle druckbaren ASCII-Zeichen
V_CHAR_PRT -3 32-255 alle druckbaren Zeichen
V_CHAR_ALL -4 0-255 wirklich alle Zeichen

Diese vier Gruppen dürften die häufigsten Anwendungsfälle abdecken.

Wenn sowohl validtype als auch validchars Null sind, wird der Fontselektor dies wie V_CHAR_IND behandeln, ebenso bei anderen ungültigen Werten in validtype.


Wenn die vier Gruppen einmal nicht ausreichen, so kann man stattdessen über validtype und validchars auch genauer angeben, welche Zeichen benötigt werden:

validtype enthält dann einen Wert für das vom GDOS zu verwendende Mapping (vgl. vst_charmap()).

Die freie Wahl des Mappings steht nur mit einem entsprechenden GDOS (SpeedoGDOS oder NVDI ab Version 3) zur Verfügung. Z.Z. sind folgende Mappings definiert:

Name Wert Bedeutung
MAP_DIRECT 0 "direktes Mapping"
MAP_ASCII 1 ASCII-Mapping (Default)


Wenn das GDOS kein Mapping beherrscht, wird der Fontselektor nur MAP_ASCII akzeptieren, alle anderen Mappings werden dann ignoriert und ein Test auf Vorhandensein bestimmter Zeichen wird nicht durchgeführt.
validchars ist ein Zeiger auf ein Array von Integers (Words), über das angegeben werden kann, welche Zeichen der Font unbedingt enthalten soll.

Das Array besteht aus einer Folge von Von–Bis–Paaren:
  • zwei aufeinanderfolgende Werte geben einen Bereich (von–bis) an

  • einzelne Zeichen werden durch Verdopplung angegeben

  • das Ende der Liste wird durch ein Von–Bis–Paar angegeben, bei dem bis kleiner ist als von



Beispiel: Es sollen nur Fonts angeboten werden, die alle druckbaren ASCII–Zeichen sowie die deutschen Umlaute enthalten.
xFSL_PAR xpar;
int chars[] = { ' ', '~',  /* ASCII 32..126 */
                'ä','ä', 'ö','ö', 'ü','ü',
                'Ä','Ä', 'Ö','Ö', 'Ü','Ü', 'ß','ß',
                1,0       /* Ende der Liste */
              };

xpar.font->validtype=MAP_ASCII;
xpar.font->validchars=chars;

Zukünftige GDOSse werden wahrscheinlich weitere Mappings unterstützen (BICS, Unicode, ...). Durch die verwendete Codierung wird der Fontselektor auch diese korrekt beherrschen: Das in validtype übergebene Mapping wird einfach eingestellt und dann das Vorhandensein der Zeichen aus validchars abgetestet.

Anmerkung: Die diversen Möglichkeiten mit den Parametern validtype und validchars sollten sparsam und mit Bedacht verwendet werden, da das notwendige Testen der Zeichen je nach GDOS recht lange dauern kann.

15.14.1.3.9 Das User-Popup

Für das benutzerdefinierte Popup (kurz User-Popup) existieren die folgenden Felder in der xFSL_PAR–Struktur:

poptext Zeiger auf einen Text, der vor dem Popup erscheinen soll oder 0L. Dem Fontselektor steht es frei, diesen Text zu ignorieren.
num_entries Anzahl Einträge (d.h. Zeilen) im Popup. Steht hier eine Null, so wird kein Popup angezeigt. Es sollten nicht mehr als 16 Einträge verwendet werden, auch wenn einzelne Fontselektoren u.U. auch mehr Einträge unterstützen.
sel_entry Der selektierte Eintrag im Popup (gezählt wird ab 0). Der Fontselektor legt hier die Nummer des angewählten Popup-Eintrags ab und liest den Wert bei jedem Aufruf von xfsl_event wieder neu aus. Somit können Sie den Fontselektor z.B. auch zwingen, statt dem angewählten Eintrag Nummer 3 den mit der Nummer 5 zu aktivieren (bei xFS_POPUP meldet der Fontselektor nur, welcher Eintrag angewählt wurde, aktiviert wird dieser erst beim Rücksprung in den Fontselektor).
popup Dies ist ein Zeiger auf ein Array von xFSL_PENTRY-Elementen. An der angegebenen Adresse müssen genau so viele Elemente stehen, wie in num_entries angegeben wurden.

Ein Eintrag im Popup ist wie folgt aufgebaut:

typedef struct
{
 char         *entry;      /* Text des Popup-Eintrags       */
 PFONTINFO    *fontinfo;   /* Zeiger auf Fontinfo-Struktur  */
 unsigned int  fontflags;  /* erlaubte Fontarten            */
 long          funcflags;  /* Funktionsflags, nur für HuGo! */
} xFSL_PENTRY;

Die Bedeutung der Elemente dieser Struktur sollte nach den vorangegangenen Ausführungen klar sein. Die Funktionsflags entsprechen den Kontrollflags, bis auf die Flags, die das globale Verhalten des Fontselektors beeinflußen (CC_WINDOW etc.). Diese werden hier ignoriert.

Wichtig: Der Zeiger auf die PFONTINFO–Struktur darf nicht Null sein!

Wenn der Text eines Eintrags mit einem - beginnt, wird der entsprechende Eintrag disabled (in heller Schrift und nicht anwählbar) dargestellt. Dies ist in erster Linie für Trennlinien zwischen den Einträgen gedacht.


Verwendung

Im Prinzip kann man drei Einsatzgebiete für das User-Popup sehen:

  1. Jeder Popup-Eintrag stellt den Font für einen bestimmten Programmteil ein. Beispielsweise könnte man in einem bestimmten Fenster eines Programms nur nicht–proportionale Fonts zulassen wollen, in einem anderen keine Vektorfonts, in einem dritten alle Fonts.

  2. Jeder Eintrag stellt eine gewisse Gruppe von Fonts zur Verfügung. Braucht man beispielsweise oft Vektorfonts, könnte ein Popup mit den Einträgen nur Vektorfonts und alle Fonts konstruiert werden.

  3. Das Popupkann aber auch für etwas ganz anderes verwendet werden. Man könnte hier noch eine Information unterbringen, die zwar nichts mit Fonts, aber mit dem Fenster zu tun hat, für das man einen Font einstellen will. Beispielsweise könnte für ein Consolen–Fenster die Art, wie inverse Zeichen darzustellen sind, in Form eines Popups mit den Einträgen invers, fett, unterstrichen zur Auswahl angeboten werden.

    Will man das Popup so zweckentfremden, so muß man bei der Meldung xFS_POPUP den geänderten Font (der sich am gesetzten FF_CHANGED–Flag erkennen läßt) in alle anderen Popup-Einträge übertragen, da sich sonst der im Fontselektor angezeigte Font ändern würde!

15.14.1.4 Die Fontflags

Über die Fontflags können die zur Auswahl gestellten Fonts eingeschränkt werden:

Name Wert Bedeutung
FF_SYSTEM 0x0001 Systemfont (zusätzlich) anzeigen
FF_MONOSPACED 0x0002 monospaced Fonts anzeigen
FF_PROPORTIONAL 0x0004 proportionale Fonts anzeigen
FF_BITMAP 0x0008 Bitmapfonts anzeigen
FF_SPD 0x0010 Speedofonts anzeigen
FF_TTF 0x0020 TrueType-Fonts anzeigen
FF_PFB 0x0040 Type-1-Fonts anzeigen
FF_CFN 0x0080 Calamusfonts anzeigen (n.i.)
FF_VECTOR 0x00F0 alle Vektorfonts anzeigen
FF_ALL 0x00FE alle Fonts anzeigen
FF_CHANGED 0x8000 Änderung erfolgt (nur im Popup)

Die Werte sind so gewählt, daß die einzelnen Flags miteinander verodert werden können. Setzt man für die Fontflags also beispielsweise FF_MONOSPACED|FF_VECTOR ein, so werden nur unproportionale Vektorfonts zur Auswahl gestellt.

Zudem gilt:

15.14.1.5 xFSL Returncodes

Alle xFSL–Aufrufe liefern einheitliche Returncodes (Rückgabewerte) zurück. Dabei steht eine negative Zahl für einen Fehler, eine positive Zahl (oder Null) bedeutet Erfolg bzw. ein Ereignis.

Name Wert Bedeutung
xFS_PARERROR -9 Parameterfehler, z.B. Aufruf nach Rev. 3
xFS_LOADERROR -8 Fehler beim Nachladen des xFSL-Moduls
xFS_RES_ERROR -7 Auflösung zu klein (mind. 640x400 Punkte)
xFS_NO_HANDLE -6 Kein VDI-Handle frei
xFS_NO_WINDOW -5 Kein Fenster(handle) frei
xFS_NO_FONTS -4 Keine Fonts geladen
xFS_NO_FONTSIZE -3 Fontgröße nicht identifizierbar
xFS_ACTIVE -2 Fontselektor ist bereits aktiv
xFS_ERROR -1 allgemeiner Fehler (Speichermangel o.ä.)
xFS_STOP 0 gewählt
xFS_OK 1 gewählt
xFS_HELP 2 Hilfe-Button angewählt
xFS_EVENT 3 AES-Event aufgetreten
xFS_POPUP 4 Änderung am User-Popup

Diese Werte wurden aufwärtskompatibel zum Fontselektor UFSL gewählt (dieser kennt die Returncodes -4, -3, -2, -1, 0 und 1).

Darüber hinaus können auch Gemdos-Fehlermeldungen (Werte kleiner oder gleich -32) auftreten, insbesondere kann xfsl_init auch den Wert EINVFN (-32) liefern, wenn der Fontselektor den erweiterten Aufruf nicht unterstützt.

Beim Aufruf xfsl_init entsprechen positive Rückgabewerte dem Fensterhandle des Fontselektors (0 bedeutet, daß der Fontselektor als modaler Dialog geöffnet wurde).

Es ist möglich, daß die Liste der Returncodes in Zukunft um weitere Fehler (Werte kleiner -9) oder Ereignisse (Werte größer 4) erweitert wird. Dies sollte beim Programmentwurf berücksichtigt werden: Bei unbekannten Fehlern sollte abgebrochen, unbekannte Ereignisse sollten ignoriert werden.

15.14.1.6 Die Pure-C-Event-Struktur

Die GEM–Bibliothek von Pure C verwendet eine spezielle Struktur, in der die Parameter der AES-Funktion evnt_multi() zusammengefaßt sind. Diese Struktur wird auch von xfsl_event verwendet.

typedef struct /* Special type for EventMulti */
{
 /* Eingabeparameter */
 int ev_mflags,
     ev_mbclicks, ev_bmask, ev_mbstate,
     ev_mm1flags, ev_mm1x, ev_mm1y, ev_mm1width, ev_mm1height,
     ev_mm2flags, ev_mm2x, ev_mm2y, ev_mm2width, ev_mm2height,
     ev_mtlocount, ev_mthicount;

 /* Ausgabeparameter */
 int ev_mwich,
     ev_mmox, ev_mmoy, ev_mmobutton, ev_mmokstate,
     ev_mkreturn, ev_mbreturn;

 /* Message-Buffer */
 int ev_mmgpbuf[8];
} EVENT;

Die Elemente der Struktur entsprechen denen des evnt_multi()–Aufrufs. Auch die Reihenfolge der Parameter ist — bis auf wenige Ausnahmen — identisch. Das Feld ev_mwich enthält die aufgetretenen Events in der gleichen Kodierung wie ev_mflags.

15.14.2 xFSL Tips und Hinweise

In den folgenden Abschnitten soll versucht werden, noch einige Tips und Hinweise zur xFSL–Schnittstelle zu geben.

15.14.2.1 Ein einfacher Aufruf

Angesichts der Vielzahl der Parameter und Einstellmöglichkeiten erscheint folgender Hinweis angebracht:

Keine Panik!

Ein xFSL–Aufruf ist einfacher als es zunächst scheint. Insbesondere kann hier die Strategie der schrittweisen Verfeinerung angewendet werden, da man (fast) alle Parameter zunächst einmal auf Null setzen kann.

Ein möglichst einfacher xFSL–Aufruf kann z.B. so aussehen:

#include 
#include <aes.h>
#include <vdi.h>
#include 

void call_xfsl (void)
{
  int xhandle, xret;
  xFSL_PAR xpar;
  PFONTINFO pfont;
  xFSL *xfsl;

  memset (&xpar, 0, sizeof (xFSL_PAR));
  memset (&pfont, 0, sizeof (PFONTINFO));

  xpar.par_size = sizeof (xFSL_PAR);
  xpar.pfi_size = sizeof (PFONTINFO);
  xpar.font = &pfont;
  xpar.font->fontcol = BLACK;

  if (get_cookie ('xFSL', &xfsl))
  {
    xhandle = xfsl->xfsl_init (0, &xpar);
    if (xhandle >= 0)
    {
     do
       xret = xfsl->xfsl_event (xhandle, 0L);
     while (xret > xFS_OK);
     xfsl->xfsl_exit (xhandle);
     if (xret == xFS_STOP)
       printf ("Abbruch\n");
     else if (xret == xFS_OK)
       printf ("Font mit ID %d ausgewählt\n", xpar.font->fontid);
     else if (xret < 0)
       printf ("Fehler %d\n", xret);
   }
   else
     printf ("Fehler %d\n", xhandle);
  }
  else
    printf ("Cookie nicht gefunden!\n");
}

Mit den beiden memset–Aufrufen werden alle Elemente der Strukturen xFSL_PAR und PFONTINFO auf Null gesetzt. Anschließend werden einige unbedingt nötige Werte eingetragen:

Mehr ist an Vorbereitungen nicht nötig, es folgt nun der eigentliche Aufruf. Zunächst wird der xFSL–Cookie gesucht. Im Erfolgsfall wird nun der Fontselektor initialisiert, indem die xFSL_PAR–Struktur übergeben wird. War dieser Aufruf erfolgreich (xhandle ist größer oder gleich Null), so befindet sich der Fontselektor bereits auf dem Bildschirm. In der Hauptschleife wird nun gewartet, bis der Fontselektor entweder mit xFS_STOP oder xFS_OK vom Anwender beendet wird oder bis ein Fehler auftritt (andere positive Rückgabewerte werden hier einfach ignoriert). Mit dem Aufruf von xfsl_exit wird der Fontselektor wieder vom Bildschirm entfernt und anschließend der Rückgabewert ausgewertet.

Das war doch gar nicht so kompliziert, oder? Von hier aus können Sie nun mit den diversen Parametern und Flags weiter experimentieren.

15.14.2.2 Fragen und Antworten

Wie kann ich feststellen, welche Features der Fontselektor bietet?

Direkt kann dies für einige Features über die Funktion xfsl_info geschehen. Indirekt können weitere Features über das Feld control in der xFSL_PAR–Struktur abgefragt werden: Nach einem erfolgreichen xfsl_init–Aufruf wird der Fontselektor diejenigen Kontrollflags löschen, die er nicht versteht.


Wie soll sich mein Programm verhalten, wenn es feststellt, daß der Fontselektor das gewünschte Feature nicht unterstützt?

Wenn überhaupt ein Fontselektor installiert ist, sollte dieser auch auf jeden Fall verwendet werden. Je nachdem, wie wichtig das vermißte Feature ist, könnte sich Ihr Programm nach Alternativen umsehen (z.B. über das Font-Protokoll) oder versuchen, das fehlende Feature zu kompensieren.

Auch hier gilt wieder: Der Anwender wollte einen Fontselektor, keine Fehlermeldung. Wenn das fehlende Feature nur schwer zu kompensieren ist, dann sollten Sie den Anwender einmalig(!) mit einem entsprechenden Hinweis informieren, aber trotzdem den Fontselektor aufrufen. Auch wenn die Auswahl dann nicht mit dem gewünschten Komfort geschehen kann, ist dies für den Anwender immer noch weniger frustrierend, als überhaupt keinen Font auswählen zu können.

Einige Beispiele: Sollte über das Popup der Font für bestimmte Fenster des Programms eingestellt werden, so sollte er bei fehlendem Popup für das oberste Fenster des Programms übernommen werden. Unterstützt der Fontselektor das Sperren der Größenänderung nicht, so sollte die zurückgelieferte Größe einfach ignoriert werden und — wenn sie von der gewünschten Größe abweicht — der Anwender durch einen Hinweis davon in Kenntnis gesetzt werden.

Man sollte sich übrigens nicht darauf verlassen, daß der Fontselektor beim nächsten Aufruf noch der gleiche ist bzw. die gleichen Features unterstützt! Die Fontselektoren, die mit einem Overlay (XFSL.OVL) arbeiten können durch einfaches Umkopieren des Overlays jederzeit ohne Reset ausgewechselt werden.


Was hat es mit diesem Mapping auf sich?

Vektorfonts enthalten meist wesentlich mehr als die üblichen 256 Zeichen, noch dazu normalerweise nicht in der gewohnten ASCII–Codierung (beispielsweise könnte das Leerzeichen auf Position 0 statt auf 32 liegen). Daher werden die entsprechenden Zeichen aus dem Font auf die normalen 256 Zeichen gemappt (d.h. abgebildet), so daß sich das Leerzeichen wie gewohnt an Position 32 befindet, unabhängig davon, welche Position es innerhalb des Fonts hat. Dieses bezeichnet man als ASCII–Mapping.

Per Default ist das ASCII–Mapping aktiv. Dadurch kann man aber die Zeichen, die außerhalb des ASCII–Zeichensatzes liegen, nicht ansprechen. Als zweites Mapping steht daher das direkte Mapping zur Verfügung. Hier hat man nun Zugriff auf alle Zeichen eines Fonts. Allerdings muß man dazu auch wissen, um welche Art von Font es sich handelt und wieviele Zeichen der Font enthält: Speedofonts haben meist 564 Zeichen, TrueType–Fonts können (theoretisch) bis zu 65536 Zeichen enthalten. Diese Information erhält man nach dem Umschalten auf das direkte Mapping mit der VDI–Funktion vqt_fontinfo():

 int minADE, maxADE;

 vst_charmap(handle,0);
 vqt_fontinfo(handle,&minADE,&maxADE,dumarray,&dummy,dumarray);

In minADE erhält man den kleinsten, in maxADE den größten gültigen Zeichenindex.

Das direkte Mapping ist für normale Anwendungen nur eingeschränkt brauchbar. Im Gegensatz zum ASCII–Mapping, das ein einheitliches Mapping für alle Arten von Fonts darstellt, muß man hier nämlich ganz genau wissen, um welche Art von Font es sich handelt. So haben z.B. die Speedo–Symbolfonts eine andere Codierung als die normalen Speedofonts. D.h. daß man an Position 64 eines solchen Symbolfonts nicht das gleiche Zeichen vorfinden wird wie bei einem normalen Speedofont.

Andere Mappings als ASCII sind daher z.Z. für den Großteil der Programme uninteressant. Künftige GDOSse werden aber möglicherweise noch andere einheitliche Mappings (z.B. Unicode oder BICS) anbieten, bei denen man sich dann wieder darauf verlassen kann, daß an einer bestimmten Position auch immer das gleiche Zeichen liegt (ähnlich wie beim ASCII–Mapping, nur eben auch bei Positionen größer 255).


15.14.2.3 xFLS Programmiertechnische Hinweise

Die Beschreibung der xFSL–Schnittstelle in diesem Text erfolgt in Pure C. In den folgenden Abschnitten werden die Datentypen und Besonderheiten von Pure C näher beschrieben, damit xFSL–Aufrufe auch aus anderen Programmiersprachen und C–Dialekten gelingen.

15.14.2.3.1 Datentypen

In diesem Text werden die folgenden Datentypen verwendet:

 Name            Größe
----------------------------------------
 int             16 Bit mit Vorzeichen
 unsigned int    16 Bit ohne Vorzeichen
 long            32 Bit mit Vorzeichen
 unsigned long   32 Bit ohne Vorzeichen

Der Datentyp char ist ein (ASCII–)Zeichen und wird hier nur als Zeigertyp verwendet, d.h. als Zeiger auf einen C–String (eine Folge von Zeichen, die mit einem Nullbyte abgeschloßen sind).


Union

Eine Union entspricht einem varianten Record in Pascal. Es handelt sich um eine Struktur, deren einzelne Elemente übereinander liegen, d.h. denselben Speicherbereich belegen. Welches Element gerade gültig ist, ergibt sich aus dem Kontext bzw. bleibt dem Programmierer überlassen.

Beispiel: In der Struktur PFONTINFO wird für die Größenangabe eine Union fsize verwendet:

union fsize
{
 int   size;    /* Fontgröße in Punkt         */
 fix31 size31;  /* Fontgröße in 1/65536 Punkt */
};

Der Speicherbedarf dieser Union beträgt vier Bytes, da der Typ fix31 vier Bytes groß ist. Man könnte nun dem Element size31 eine Größenangabe in 1/65536 Punkt zuweisen und dann den Wert in ganzen Punkt aus dem Element size auslesen — dies ist aber nicht empfehlenswert, da bei der Umrechnung fix31 nach pt immer gerundet werden sollte, s.u.


fix31

Der Datentyp fix31 ist eine Festkommazahl, bei dem die oberen 16 Bit den vorzeichenbehafteten Vorkomma-Anteil darstellen und die unteren 16 Bit den vorzeichenlosen Nachkomma-Anteil. Er wird ausschließlich für Größenangaben von Fonts verwendet, die damit auf 1/65536 Punkt genau angegeben werden können.

Bei der Umrechnung von fix31 nach pt darf man das Runden nicht vergessen. Zitat aus dem NVDI–Guide:

Man darf nie, nie, niemals den Nachkommateil einfach abschneiden!

15.14.2.3.2 xFSL Parameterübergabe

Die Übergabe der Parameter bei allen xFSL–Aufrufen geschieht über den Stack nach C–Konvention. D.h. daß der beim Aufruf am weitesten rechts stehende Parameter zuerst auf den Stack gelegt wird und der am weitesten links stehende Parameter zum Schluß, d.h. beim Einsprung in den Fontselektor, obenauf liegt.

15.14.2.3.3 Pure C und cdecl

Pure C übergibt die Parameter an Funktionen normalerweise in Registern. Für eine Übergabe über den Stack muß entweder das Schlüsselwort cdecl verwendet werden (wie im Includefile XFSL.H geschehen) oder der Compilerschalter -H gesetzt werden.

Das Schlüsselwort cdecl ist eine Pure–C–spezifische Erweiterung und wird daher bei gesetztem Compilerschalter -A (ANSI-Konformität) angemahnt.

15.14.3 Revisions–History

Revision 4


Revision 3


ältere Revisionen

15.14.4 Programmübersicht

Es folgt eine Übersicht über alle z.Z. erhältlichen Fontselektoren, die über eine UFSL– oder eine xFSL–Schnittstelle (oder beides) verfügen.

Desweiteren folgt eine Liste von Programmen, die einen Fontselektor mit einer der beiden Schnittstellen verwenden.

15.14.4.1 Fontselektor–Übersicht

Eine kleine Übersicht über die existierenden Fontselektoren:

UFSL

von Michael Thänitz
Dies ist der Prototyp aller externen Fontselektoren. Die letzte veröffentliche Version ist 0.97, danach hat Michael leider die Entwicklung eingestellt. Dankenswerterweise hat er aber die Quelltexte veröffentlicht.

FontSel

von Holger Weets und Christoph Zwerschke
Ein kleiner, aber auch etwas spartanischer Fontselektor von Holger Weets, der seit der Version 1.02 von Christoph Zwerschke weiterentwickelt wird. Ab der Version 1.02 wird auch die xFSL-Schnittstelle unterstützt.

xUFSL

von Stefan Rogel
Der xUFSL bietet gegenüber den bisher genannten Fontselektoren viele zusätzliche Features. Da diese über die existierende UFSL-Schnittstelle nicht angesprochen werden konnten, hat Stefan die Schnittstelle erweitert. Das Design der ersten Version war, vorsichtig ausgedrückt, umstritten. Letzte veröffentlichte Version: 1.05. Nachfolger des xUFSL ist ...

HuGo

von Stefan Rogel
HuGo! ist der an die xFSL–Schnittstelle angepaßte Nachfolger des xUFSL (die UFSL-Schnittstelle wird ebenfalls noch unterstützt, nicht aber die speziellen Erweiterungen des xUFSL an der UFSL–Schnittstelle). Die Namensänderung wurde vollzogen, um Verwechslungen zu vermeiden.

Calvino

von Dirk Haun
Zusammen mit HuGo! der erste Fontselektor mit xFSL–Schnittstelle. Auch Calvino unterstützt noch die einfache UFSL–Schnittstelle.

FONT_SEL und FONT_PAL

von Christian Grunenberg
Diese beiden Programme arbeiten auf Drag&Drop–Basis, sie unterstützen also weder die UFSL– noch die xFSL–Schnittstelle, dafür aber das Font–Protokoll. FONT_SEL ist ein Fontselektor, FONT_PAL eine Fontpalette (mit integriertem Fontselektor).

15.14.4.2 Programme, die einen Fontselektor unterstützen

Folgende Programme unterstützen einen externen Fontselektor (Stand 16.08.1998, alle Angaben und E-Mail-Adressen ohne Gewähr):

Program Category Author UFSL xFSL
800XL-Deejay Laufwerksemulator Kolja Koischwitz +
APP_List Systemutility Ralf Zimmermann +
Bellini Grafikprogramm Ingo Dehne +
BibelST Bibel-Software Reinhard Bartel +
Cat2Maus MausTausch Harald Sommerfeldt +
Chatwin Shell Dirk Haun @ LB +F +F
CyPress Textverarbeitung Rene Bartholomay +F
DB-Point Newsreader Michael Heng +
Disk Cake Diskutility Christoph Zwerschke + +
Egale Dateiutility David Reitter + +
Everest Editor Oliver Schmidt +
Face Value App.Builder/Lib Vegard Hofsoy - +
Floh Filelisten-Util. Heiko Schaefer +
GEMAR Backup Steffen Engel +
GEM-Fontviewer Zeichensatz-Anzeige Reinhard Bartel + +
GEM-Plan Tabellenverwaltung Reiner Rosin +F
Hitchcock Systemutility Thorsten Pohlmann +
IdeaList ASCII-Druckprogramm Christoph Bartholme +
Imagin Funktionsplotter Reinhard Maier +
Jedi GAL-Assembler Ralf Zimmermann +
Kandinsky Zeichenprogramm Ulrich Rossgoderer +
MagiC!Conf MagiC-Utility Christian Ratsch +
MasterBrowse Dateiviewer Michel Forget +
MenuInfo Systemutility Dirk Hagedorn +F
Okami Newsreader Wolfram Rösler +
Photo Line Bildverarbeitung Gerhard Huber +
QED Editor Christian Felsch +
RoadRunner Autofahrtplanung Andreas Schrell +F
SaugUtility dito Frank Rüger +
Schecks Businessoftware Christian Lehmann +
ST-Guide Hypertext Holger Weets +
STJ-Oberon Programmiersprache Stephan Junker + +
Texel Tabellenkalkulation Thomas Much + +
UpToCASE CASE-Tool Michael Nolte +
VESAL Lernprogramm Peter Klasen +
Zeig's mir Dateiviewer Reiner Rosin + +F

(+: unterstützt, F: als Fensterdialog; E-Mail-Adressen: MausNet)


15.14.5 Die UFSL–Schnittstelle

Der Vollständigkeit halber folgt hier noch die Original–Beschreibung von Michael Thänitz zur ursprünglichen UFSL-Schnittstelle:

Programmierschnittstelle:

UFSL ist eine Fontauswahlbox für den Autoordner. Sie bietet dem Programmierer eine einfache Programmierschnittstelle über einen Cookie.

Der Cookie lautet: UFSL.
Der Cookie liefert einen Zeiger auf folgende Struktur:

 typedef struct
 {
  unsigned long  id;      /* UFSL ID (UFSL)       */
  unsigned int   version; /* Version (BCD-Format) */
  int dialtyp;            /* 0=Dialog, 1=Fenster  */
  int cdecl (*font_selinit)(void);
  int cdecl (*font_selinput)(
              int vdihandle,
              int dummy,
              char *text,    /* eigener Text, max. 34 Zeichen      */
              int ftype,     /* 1=nur monospaced Fonts, 0=alles    */
              int *fretid,   /* eingestellte FontId                */
              int *fretsize  /* eingestellte Fontgröße             */
              );
  OBJECT *helpbutton;           /* Typ: BOXTEXT                    */
  void cdecl (*helpfunc)(void); /* Benutzerdefinierte Helpfkt.     */

  /**** ab Version 0.91 ********************************************/
  char *examplestr;            /* Beispieltext für Fontdarstellung */

  /**** ab Version 0.96 ********************************************/
  void cdecl (*msgfunc)(int event, int msgbuf[]);/* Redrawfunktion */

  /**** ab Version 0.97 ********************************************/
  int cdecl (*fontsel_exinput)(
              int vdihandle,
              int ftype,     /* 1=nur monospaced Fonts, 0=alles    */
              char *text,    /* eigener Text, max. 34 Zeichen      */
              int *fretid,   /* eingestellte FontId                */
              int *fretsize  /* eingestellte Fontgröße             */
              );
 } UFSL;

Aufruf:

UFSL *ufsl;
ufsl=(UFSL *)get_cookie('UFSL');
ufsl->helpfunc= my_helpfunc;   /* Hilfefunktion oder NULL */
ufsl->msgfunc = my_msghandler; /* Redrawfunktion oder NULL,
                                  Dialtyp beachten */
ufsl->fontsel_input(vdihandle,"Bitte Font auswählen",0,&id,&size);
oder
ufsl->fontsel_input(vdihandle,NULL,0,&id,&size);

Returncodes:

 1 : Alles OK, Werte gültig.
 0 : Abbruch gewählt.
-1 : Out of memory.
-2 : Unzulässiger Mehrfachaufruf.
-3 : Fontgröße konnte nicht identifiziert werden.
-4 : Anzahl Fonts muß größer null sein.

Sonderfunktionen:

void cdecl (*helpfunc)(void); /* Benutzerdefinierte Helpfkt.     */

UFSL kann eine benutzerdefinierbare Hilfefunktion über den ebenfalls optionalen Hilfebutton aufrufen. helpfunc() benötigt keine Parameter und liefert auch keinen Wert zurück.

void cdecl (*msgfunc)(int event, int msgbuf[]); /* Redrawfunktion */

Bei Verwendung von UFSL als Fensterdialog ist es notwendig eine Redrawfunktion zur Verfügung zu stellen. Sie schickt die anfallenden Events an das aufrufende Programm zurück, damit nach Verschieben des Dialogs die Hintergrundfenster restauriert werden können. msgfunc() liefert als ersten Parameter das Ergebnis von evnt_multi() und als zweiten Parameter die MsgPipe. Ein Returncode wird nicht benötigt. Das Anwenderprogramm muá die nötigen Routinen zur Fensterbehandlung zur Verfügung stellen. wind_update(..._UPDATE) wird von UFSL nicht gesetzt, obliegt also dem rufenden Anwenderprogramm. Prinzipbedingt (?) ist die Memoryprotection von MTOS auszuschalten.

Grundsätzlich gilt es zu überlegen, ob tatsächlich alle Events entsprechend beantwortet werden sollen. Ein WM_TOPPED, das andere eigene Fenster nach vorn bringt, sollte wohl nicht beantwortet werden, da UFSL naturgemäá nur applikationsmodal sein kann, da UFSL ja in einem eigenen form_do() sprich evnt_multi() kreist.

15.14.6 Hinweise für Autoren anderer Fontselektoren

Autoren anderer Fontselektoren sind dazu eingeladen, sich der xFSL–Schnittstelle anzuschließen. Im Prinzip kann jeder Fontselektor, der als TSR konzipiert ist, mit der xFSL–Schnittstelle ausgerüstet werden.

Damit keine Mißverständnisse entstehen: Die Overlay–Technik und die Reentranz, wie sie Calvino und HuGo! bieten, sind nicht Teil der eigentlichen Schnittstelle und müssen von anderen Fontselektoren daher auch nicht unterstützt werden. Allerdings ist auch die Schnittstelle zwischen dem residenten Teil (Shell) und dem nachgeladenen Teil (Overlay) genormt und kann daher auch von anderen Fontselektoren verwendet werden. Eine Beschreibung dieser internen Schnittstelle ist auf Anfrage erhältlich, siehe Kontaktadressen.

Da bereits eine Reihe von Programmen die alte UFSL–Schnittstelle unterstützen, erscheint es ratsam, auch in neuen Fontselektoren diese Schnittstelle noch zur Verfügung zu stellen. Jedoch zeigt ein kurzer Blick auf diese Programme, daß sie fast ausschließlich den Fontselektor als modalen Dialog aufrufen. Die Empfehlung lautet daher, eine minimale UFSL–Unterstützung einzubauen (nur als modaler Dialog) und dafür die xFSL–Schnittstelle möglichst weitgehend zu implementieren, da zu erwarten steht, daß gerade die — nun endlich genormten — Erweiterungen gegenüber der UFSL-Schnittstelle von den Programmen verwendet werden sollen.

Ein Fontselektor sollte möglichst die folgenden zusätzlichen Features bieten:

Folgende Konventionen wurden für einen xFSL–Fontselektor vereinbart:


HomeProtokolleXAccXSSI-Protokoll