
 +-----------------------------------------+
 |+---------------------------------------+|
 ||  Dokumentation zur GEM-Force-Library  ||
 |+---------------------------------------+|
 +-----------------------------------------+


Inhaltsverzeichnis
==================

1 Vorwort 
2 Das Modul-Konzept 
3 Die Struktur der GEM-Force-Library
4 Modul GLOBAL
5 Modul WINDOWS
6 Modul TOS


1. Vorwort
==========

Die Ihnen vorliegende GEM-Force-Library fr Pure C ist ein Versuch, die oftmals 
langwierige GEM-Programmierung zu vereinfachen und Funktionen zur Verfgung zu 
stellen, die zwar kompakt und leistungsfhig sein sollen, jedoch den 
Programmierer in seiner Flexibilitt nicht einschrnken sollen. Aus diesem 
Grund wurde - im Gegensatz zu anderen verbreiteten Libraries - keine Funktion 
geschrieben, die die AES-Events empfngt (evnt_multi) und verarbeitet, ohne da 
der Programmierer direkt Zugriff darauf hat; das wre zwar in einigen Bereichen 
fr den unerfahreneren Programmierer einfacher, schrnkt aber auf der anderen 
Seite den erfahreneren Programmierer zu sehr ein.
Ich hoffe Ihnen mit der GEM-Force-Library ein Instrument an die Hand zu geben, 
mit dem Sie (wenigstens mit Grundkenntnissen der GEM-Programmierung und 
natrlich C bewaffnet) einfacher GEM-Programme schreiben knnen. Dabei sollte 
es keine Rolle spielen, ob Sie fortgeschrittener Anfnger oder schon angehender 
Profi sind. In jedem Fall: Viel Erfolg !
An dieser Stelle mchte ich noch den Brdern Jrgen und Dieter Gei, den 
Autoren des Buches "Vom Anfnger zum GEM-Profi", erschienen im Hthig-Verlag, 
danken. Viele der in der Library enthaltenen Funktionen lehnen sich sehr eng an 
die von ihnen vorgestellten Funktionen an. Ohne ihr Einverstndnis wre diese 
Library in dieser Form nicht mglich gewesen. Also: Herzlichen Dank !
GEM-Force wurde geschrieben von:

Ren Rosendahl, Software-Entwicklung
Kameruner Str. 107
32791 Lage
Telefon 05232/78916 (ab 17.00 Uhr !)
BLZ 476 501 30 (Sparkasse Detmold)
Konto 176004000

Bevor nun auf die eigentlichen Funktionen eingegangen wird, mu noch etwas 
grundlegendes erklrt werden, und zwar...


2. Das Modul-Konzept
====================

Das in GEM-Force realisierte Modul-Konzept ist im Grunde das gleiche, das auch 
in dem Buch "Vom Anfnger zum GEM-Profi" von den Gebrdern Gei vorgestellt 
wurde. Es teilt Variablen und Funktionen in Bezug auf ihren Geltungsbereich in 
die Arten lokal und global bezogen auf das C-Modul ein, in dem diese definiert 
sind. Die lokalen Funktionen/Variablen sind modul-lokal, d. h. static, whrend 
die globalen in allen Modulen definiert sind.
Die Vorgehensweise ist folgende:
1. Alle globalen Funktionen und Variablen werden mit "GLOBAL" gekennzeichnet 
und in ein Header-File fr das jeweilige Modul geschrieben.
2. Die modul-lokalen Funktionen und Variablen werden mit "LOCAL" gekennzeichnet 
und im C-Source selber zu Beginn definiert.
3. Jedes Modul mu als erste Header-Datei die Datei "GFIMPORT.H" laden und dann 
die Header-Dateien der Module, die "importiert" werden sollen, sowie die 
normalen Standard-Header-Dateien.
4. Anschlieend folgt die Header-Datei "GFEXPORT.H" und die Header-Datei des 
Moduls selbst.
Mit dieser Vorgehensweise ist es mglich, wie in Modula Variablen und 
Funktionen bezogen auf das jeweilige Modul zu importieren bzw. exportieren.
In dem Header-File  "GFIMPORT.H" werden zustzlich noch die Funktionen min und 
max, sowie der Typ BOOLEAN mit seinen Ausprgungen TRUE und FALSE definiert.


3. Die Struktur der GEM-Force-Library
=====================================

Aufbauend auf diese Modul-Struktur gliedert sich die GEM-Force-Library (intern) 
in 3 Module: das Modul GLOBAL, das Modul WINDOWS und das Modul TOS. Fr jedes 
dieser Module gibt es ein ein eigenes Header-File, das Sie inkludieren mssen, 
wenn Sie Funktionen des jeweiligen Moduls nutzen wollen.


4. Modul GLOBAL
===============

Dieses Modul stellt allgemeingltige Hilfsfunktionen fr die GEM-Programmierung 
zur Verfgung. Soll dieses Modul von GEM-Force genutzt werden, ist die Header-
Datei "GFGLOBAL.H" zu importieren. Die in diesem File enthaltenen Define-
Anweisungen sind nicht so interessant; wer Interesse hat, schaue sie sich in 
der Datei selbst an.
Erwhnenswert sind noch folgende Typ-Definitionen, die ebenfalls in der Header-
Datei enthalten sind:

typedef struct
{
   int x, y, w, h;
} RECT;

typedef struct
{
   long x, y, w, h;
} LRECT;

RECT und LRECT sind jeweils Typen fr die Speicherung von Rechtecken.

Ein weiterer Typ ist:

typedef struct
{
   int     ascii_code;
   int     scan_code;
   BOOLEAN shift;
   BOOLEAN ctrl;
   BOOLEAN alt;
   int     kreturn;
   int     kstate;
} KEYINFO;

KEYINFO enthlt Informationen ber eine Tastaturaktion.

Es folgt nun eine Aufzhlung der enthaltenen Funktionen:


GLOBAL BOOLEAN init_gem ( void )

Diese Funktion sollte zu Beginn aller GEM-Programme aufgerufen werden. Sie 
meldet das Programm zuerst beim VDI und dann bei den AES an und fllt dabei 
globale Variablen, die sich bei der GEM-Programmierung immer als ntzlich 
erweisen:
GLOBAL int appl_id      die Application-ID der Applikation
GLOBAL int phys_handle  das physikalische Workstation-Handle des Bildschirms 
GLOBAL int vdi_handle   das Handle der virtuellen Bildschirm-Workstation, 
                        welches fr alle weiteren VDI-Aufrufe bentigt wird
GLOBAL int tos          die TOS-Version GLOBAL 
int colors              die Anzahl der darstellbaren Farben (monochrom = 2 !)
GLOBAL RECT desk        das Rechteck des benutzbaren Bildschirms (ganzer 
                        Bildschirm abzglich Menleiste)
GLOBAL RECT clip        das aktuell eingestellte Clipping-Rechteck
GLOBAL int gl_wbox, gl_hbox die Breite und Hhe der Box, die ein Zeichen des 
                        Systemzeichensatzes einschiet (z. B. 8 x 16)
GLOBAL int gl_wchar, gl_hchar die Breite und Hhe eines Zeichens des 
                        Systemzeichensatzes
GLOBAL int gl_wattr, gl_hattr  die Breite und Hhe der Box, die ein Be-
                        dienelement eines Fensters einschliet (z. B. die 
                        Closer-Box)
GLOBAL long gdos        0, wenn kein GDOS installiert ist, sonst das Ergebnis 
                        des Aufrufs von vq_vgdos (siehe auch die Eintrge im 
                        Header fr Vergleiche !)
Weiterhin werden noch folgende globale Variablen initialisiert:
GLOBAL int blinkrate    Blinkrate fr PopUp-Mens (Initialwert 2)
GLOBAL BOOLEAN grow_shrink Zeichnen von Grow- bzw. Shrink-Boxen bei Fenstern 
                        und Dialogboxen (Initialwert TRUE)
GLOBAL BOOLEAN save_bg  automatisches Sichern des Hintergrundes bei Dialogboxen 
                        (Initialwert TRUE)
Wie fr die meisten BOOLEAN-Funktionen gilt: Die Funktion gibt TRUE zurck, 
wenn alles geklappt hat, sonst FALSE.


GLOBAL void exit_gem ( void )

Diese Funktion ist das Gegenstck zu init_gem und meldet das Programm beim GEM 
ab, indem sie die geffnete virtuelle Bildschirm-Workstation schliet, den von 
einer geladenen Resource-Datei bentigten Speicherplatz wieder freigibt und 
appl_exit aufruft.


GLOBAL BOOLEAN rsc_load ( char err_norsc, char *filename )

In der Regel wird man bei GEM-Programmen mit RSC-Dateien arbeiten wollen; 
deshalb bietet diese Funktion einen vereinfachten Aufruf der Funktion 
rsrc_load; dazu wird die Maus als Biene dargestellt und die Datei geladen. Im 
Fehlerfall ertnt ein Glockensignal und eine Fehlermeldung wird (mit Hilfe 
einer Alert-Box) auf den Bildschirm gebracht. Um die Library sprachunabhngig 
und individuell einsetzbar zu machen, wird keine Standard-Fehlermeldung 
gemacht, sondern eine von Ihnen zu bergebende Alert-Meldung angezeigt. Im 
Erfolgsfall liefert die Funktion TRUE zurck.


GLOBAL BOOLEAN init_tree ( int index, OBJECT **tree, BOOLEAN is_dialog);

Mit Hilfe eines einzigen Funktionsaufrufes, der fr jeden in Ihrer Resource-
Datei enthaltenen Baum gettigt werden sollte, werden eine ganze Menge 
verschiedener Dinge fr die Initialisierung eines Objekt-Baumes gemacht. Zuerst 
einmal wird die Adresse ermittelt; dazu wird der Parameter **tree bentigt, das 
heit ein Zeiger auf einen Zeiger auf einen Objektbaum (ein Zeiger auf einen 
Zeiger ist notwendig, da der Zeiger selbst ja verndert werden soll).
Des weiteren werden alle Images und Icons, die in diesem Baum enthalten sind, 
ins gertespezifische Format umgewandelt, damit deren Darstellung auch auf 
Rechnern mit Grafikkarten richtig funktioniert.
Besonderer Leckerbissen: Alle enthaltenen benutzerdefinierten Objekte (das sind 
Check-Boxes, Radio-Buttons, berschriftenobjekte, eine "Move-Corner" fr 
fliegende Dialoge und Unterstreichungen) werden fertig vorbereitet.
Damit das funktionieren kann, sind ein paar Dinge notwendig: Es mu einen 
globalen OBJECT-Pointer namens userimg geben, der auf einen Objektbaum zeigt, 
der die Images der Check-Boxes und Radio-Buttons fr die verschiedenen 
Auflsungen enthlt. Dazu sollte einfach der in der mitgelieferten Datei 
GFUSRIMG.RSC enthaltene Dialog in Ihr eigenes Resource-File kopiert werden. Die 
Objekte in diesem Baum drfen dabei auf gar keinen Fall andere Objekt-Nummern 
bekommen; am besten Sie verndern also nichts daran. Weitere Voraussetzung ist, 
da dieser Baum als aller erster mit der Funktion init_tree vorbereitet wird 
(andernfalls kann spter nicht auf dessen Adresse zugegriffen werden !).
Wenn Sie nun benutzerdefinierte Objekte in Ihrer Resource-Datei verwenden 
wollen, sollten Sie diese aus der ebenfalls mitgelieferten Datei GFOBJLIB.RSC 
kopieren; hier sind normale Objekte enthalten, die als Platzhalter fr die 
benutzerdefinierten Objekte dienen und die bereits einen entsprechenden 
extended type haben.
Nach der Initialisierung mit init_tree werden dann die echten Objekte 
erscheinen, wenn der Dialog am Bildschirm angezeigt wird.
Der letzte Parameter is_dialog ist mit TRUE zu belegen, wenn der Objekt-Baum 
ein Dialog ist, sonst mit FALSE.


GLOBAL void dialog_on ( OBJECT *tree )

Wir bleiben bei den Dialogen: Erster Schritt bei der Dialogverarbeitung ist es 
natrlich, die Dialoge erst einmal fr den Benutzer sichtbar zu machen. Das 
knnen Sie mit Hilfe dieser Funktion erledigen, welche einen Objektbaum auf den 
Bildschirm zeichnet.
Sie brauchen sich dabei weder um das Zentrieren des Dialogs, das Retten des 
Hintergrundes, die Maus oder sonst etwas kmmern: Dies alles und noch mehr wird 
automatisch erledigt. Eins ist jedoch zu beachten: Da intern nur ein einziger 
Speicherblock fr das Retten des Hintergrunds benutzt werden kann, drfen 
Dialoge nicht bereinander gezeichnet werden; andernfalls knnte nur der 
Hintergrund des letzten richtig restauriert werden, und es gbe Probleme beim 
Freigeben dieses Speicherbereichs.


GLOBAL void dialog_off ( OBJECT *tree )

Unschwer zu erraten: dialog_off beseitigt einen Dialog wieder vom Bildschirm 
und kmmert sich ggf. um das Zurckkopieren des Hintergrundes usw.


GLOBAL int form_dialog ( OBJECT *tree, int edit_object )

Der Aufruf dieser Funktion ersetzt das normale form_do vollstndig, arbeitet 
also einen Dialog ab, bis ein Exit- oder Touchexit-Button bettigt wird. 
"Nebenbei" werden noch fliegende Dialoge realisiert, sofern der Dialog ein 
entsprechendes Objekt enthlt.


GLOBAL int do_dialog ( OBJECT *tree, int edit_object )

Der Aufruf dieser Funktion fat die letzten drei Funktionen zusammen: Der 
Dialog wird dargestellt, verwaltet und wieder vom Bildschirm gelscht. Sie 
knnen also eine ganze Dialogverarbeitung mit einem einzigen Befehl durchfhren 
!
Einen Haken hat das ganze natrlich: Wurde ein Touchexit-Button bettigt, ist 
der Dialog natrlich auch vom Bildschirm verschwunden, obwohl diese Art Objekte 
meist verwandt werden, wenn eine Aktion im Dialog ausgelst werden soll, ohne 
da dieser verschwindet.
Aus diesem Grund wurden die vorherigen Funktionen fr den Anwender global 
gehalten: So kann der Dialog dargestellt (dialog_on), in einer einfachen 
Schleife solange verarbeitet werden, bis ein "echtes" Exit-Objekt (also kein  
Touchexit-Objekt) bettigt wurde (form_dialog), und anschlieend wieder vom 
Bildschirm gelscht werden (dialog_off). Fertig !


GLOBAL void store_dial ( OBJECT *tree )

Jeder kennt die Dialogboxen, die zum Verlassen einen OK- und einen Abbruch-
Button haben. Wird letzterer bettigt, werden die vorigen Inhalte wieder in die 
Dialogbox eingetragen (was man erst beim nchsten Aufruf zu sehen bekommt) und 
keine weitere Aktion ausgelst.
Dieser Mechanismus erfordert es, da das Programm sich vor dem Verndern durch 
den Benutzer alle Textfelder und Buttons merkt. Und das erfordert wieder 
lstigen Programmieraufwand.
Nicht so mit GEM-Force ! Obige Funktion erledigt dies fr Sie, indem der 
gesamte Baum durchlaufen wird und Status bzw. Inhalt aller Objekte, die die 
Flags SELECTABLE oder EDITABLE haben,  in internen Arrays gespeichert werden, 
und zwar bis zu 20 Buttons und 10 Textfelder mit einer maximalen Lnge von 70 
Zeichen.


GLOBAL void restore_dial ( OBJECT *tree )

Wurde der Abbruch-Button bettigt, knnen Sie nun ganz einfach mit der Funktion 
restore_dial den Dialog wieder herstellen, ohne sich um Einzelheiten kmmern zu 
mssen.


GLOBAL void draw_grow_shrink ( RECT *ende, int mode )

Meistens, wenn man Grow- oder Shrink-Boxen zeichnen mchte, ist der Start- bzw. 
Endpunkt die Bildschirmmitte. Dieser Vorgang wird durch draw_grow_shrink 
vereinfacht, da Sie nur noch das grere Rechteck (das Zielrechteck bei Grow- 
bzw. das Quellrechteck Shrink-Boxen) angeben mssen, sowie den Parameter 
FMD_GROW bzw. FMD_SHRINK der AES-Funktion form_dial. Die Bildschirmmitte wird 
automatisch errechnet sowie die Boxen gezeichnet, sofern die Variable 
grow_shrink den Wert TRUE hat.


GLOBAL void hide_mouse ( void )

Nun kommen wir zu den Routinen, mit denen die Maus manipuliert werden kann. Die 
hier zuerst genannte lt die Maus verschwinden. Intern wird hierzu ein Zhler 
verwaltet, der bewirkt, da die Maus sooft ausgeschaltet werden mu, wie sie 
eingeschaltet wurde, bevor sie wirklich verschwindet. Umgekehrt gilt, da die 
Maus genauso oft eingeschaltet werden mu, wie sie ausgeschaltet wurde, bevor 
sie erscheint.
Welchen Sinn hat das ? Zum Beispiel wird in einer Fehlerroutine die Maus 
eingeschaltet, um eine Alert-Box verarbeiten zu knnen. Am Ende wird die Maus 
wieder ausgeschaltet. So schn, so gut. Was passiert aber nun, wenn die Maus 
vor Ausfhren der Fehlerroutine bereits eingeschaltet war ? Wrde der oben 
beschriebene Mechanismus nicht verwandt, wrde sie am Ende der Routine wieder 
ausgeschaltet, obwohl vielleicht die aufrufende Funktion von einer 
angeschalteten Maus ausgeht. Dies kann mit diesem "Maus-Stack" nicht passieren.


GLOBAL void show_mouse ( void )

Diese Funktion schaltet die Maus erwartungsgem nach dem oben beschriebenen 
Mechanismus wieder ein.


GLOBAL void busy_mouse ( void )

Die Mausform "Biene" wird eingestellt. Auch fr das Umschalten von Biene auf 
Pfeil und umgekehrt wird ein "Maus-Stack" fr die Mausform (Biene oder Pfeil) 
verwendet.


GLOBAL void arrow_mouse ( void )

Das Umschalten von Biene auf Pfeil-Form erledigt diese Funktion.


GLOBAL void set_mouse ( int number, MFORM *addr )

Diese Routine setzt die aktuelle Mausform. Falls number 255 ist, wird auf die 
benutzerdefinierte Mausform umgeschaltet, auf die addr zeigt. Fr den nchsten 
Befehl merkt sich die Funktion in der globalen Variablen mousenumber und 
mouseform die letzte Mausform.


GLOBAL void last_mouse ( void )

Schaltet auf die zuletzt eingeschaltete Mausform zurck.


GLOBAL BOOLEAN select_file ( char *name, char *path, char *suffix, char *label, 
char *filename )

Sollen in einem GEM-Programm Dateien geladen oder gesichert werden, kommt in 
der Regel die Dateiauswahlbox ins Spiel. Um deren Aufruf zu vereinfachen wurde 
diese Funktion geschrieben.
name ist dabei der Name (ohne Pfad) der Datei, der in der Dateiauswahlbox als 
Default vorgegeben wird.
path ist der Pfad obiger Datei, der ebenfalls in der Dateiauswahlbox angezeigt 
wird.
suffix ist die Dateimaske einschlielich Extension, die darber bestimmt, 
welche Dateien in der Dateiauswahlbox angezeigt werden (z. B. *.*, *.C etc.).
label ist der Text, der oben in der Dateiauswahlbox angezeigt wird. Dieses 
Feature ist erst ab TOS 1.04 verfgbar, was aber von der Routine bercksichtigt 
wird.
Der Rckgabewert der Funktion ist TRUE, wenn der OK-Button bettigt wurde und 
zustzlich noch ein Dateiname ausgewhlt wurde, der dann in filename steht. In 
allen anderen Fllen wird FALSE zurckgegeben.


GLOBAL void divide_filename ( char *filename, char *path, char *file)

In der letzten Funktion wurden als Eingabeparameter Pfad und Dateiname 
verlangt. Damit das Aufsplitten eines vollstndigen Pfadnamens mglichst 
komfortabel und einfach ist, wurde diese Funktion geschaffen.
Der Parameter filename gibt den vollstndigen Dateinamen an. Dieser wird in 
Pfad und reinen Dateinamen gesplittet und die Ergebnisse in den anderen beiden 
Variablen gespeichert, und zwar genau dann, wenn der jeweilige Zeiger kein 
NULL-Zeiger ist. So ist es mglich z. B. nur den Pfad, nicht aber den 
Dateinamen, zu extrahieren.


GLOBAL void call_mortimer ( char *command )

Wenn Sie stolzer Besitzer des Multi-Utilities MORTIMER der Pforzheimer Firma 
OMIKRON sind, dann knnen Sie mit dieser Funktion Ihren Buttler aus Ihrem C-
Programm heraus aufrufen, und zwar direkt mit einem Kommando (siehe MORTIMER-
Handbuch). Ist kein MORTIMER installiert, bewirkt der Funktionsaufruf nichts.


GLOBAL void do_state (OBJECT *tree, int obj, unsigned int state )
GLOBAL void undo_state (OBJECT *tree, int obj, unsigned int state)

Jetzt kommen wir zu den Funktionen, die sich mit der Manipulation von Objekten 
beschftigen. Die ersten beiden hier genannten befassen sich mit dem Status von 
Objekten.
Mit do_state knnen ein oder mehrere Status-Flags des Objektes obj in 
Objektbaum tree gesetzt werden. Dazu sind die in AES.H definierten Flags zu 
verwenden und ggf. mit "oder" zu verknpfen.
Mit undo_state knnen analog ein oder mehrere Status-Flags zurckgesetzt 
werden.


GLOBAL void flip_state (OBJECT *tree, int obj, unsigned int state )

Diese und alle weiteren Funktionen, die mit flip beginnen, setzen einen oder 
mehrere Flags, wenn diese vorher nicht gesetzt waren, oder setzen diese zurck, 
falls sie vorher gesetzt waren.


GLOBAL int find_state (OBJECT *tree, int obj, unsigned int state )

Diese Funktion erlaubt es, nach einem Objekt zu suchen, das einen bestimmten 
Status hat. Dabei wird ab dem Objekt obj gesucht. Wurde kein Objekt gefunden, 
wird NIL zurckgegeben.


GLOBAL BOOLEAN is_state (OBJECT *tree, int obj, unsigned int state )

Natrlich mssen der Status und andere Objekt-Attribute auch abgefragt werden 
knnen. Dies geschieht mit den Objektfunktionen, die mit is beginnen.


GLOBAL void do_flags (OBJECT *tree, int obj, unsigned int flag )
GLOBAL void undo_flags (OBJECT *tree, int obj, unsigned int flag)
GLOBAL void flip_flags (OBJECT *tree, int obj, unsigned int flag )
GLOBAL int find_flags (OBJECT *tree, int obj, unsigned int flag )
GLOBAL BOOLEAN is_flags (OBJECT *tree, int obj, unsigned int flag )

Analog zu den eben betrachteten Funktionen arbeiten diese Funktionen, die sich 
anstatt mit dem Objekt-Status mit den Objekt-Flags beschftigen.


GLOBAL int find_type ( OBJECT *tree, int obj, unsigned int type)

Wenn Sie einmal ein Objekt eines bestimmten Typs in einem Objekt-Baum suchen, 
wird Ihnen diese Funktion weiterhelfen. Auch hier kann wieder ein Start-Objekt 
angegeben werden, ab dem gesucht werden soll. Wurde kein passendes Objekt 
gefunden, wird NIL zurckgegeben.


GLOBAL void set_rbutton ( OBJECT *tree, int obj, int lower,int upper )

Will man einen Radio-Button selektieren, mssen vorher alle anderen Radio-
Buttons deselektiert werden. Dies erledigt diese Funktion automatisch. Neben 
dem Objekt, das selektiert werden soll mssen daher noch der erste und der 
letzte der zusammengehrigen Radio-Buttons angegeben werden. Objekte, die sich 
zwar durch ihre Objekt-Nummer zwischen diesen Grenzen befinden, aber keine 
Radio-Buttons sind (was immer mal passieren kann), werden dabei nicht 
verndert.


GLOBAL int get_rbutton ( OBJECT *tree, int obj )

Natrlich mu man auch Radio-Buttons abfragen knnen. Dazu dient diese Routine, 
der auer der Adresse des Objekt-Baums auch noch ein Objekt angegeben werden 
mu, ab dem gesucht wird. Voraussetzung ist allerdings, da auch wirklich ein 
Radio-Button selektiert ist.


GLOBAL void deselect_obj ( OBJECT *obj, int ind )

Eine fast berflssige Funktion (kann durch undo_state mit entsprechenden 
Parametern ersetzt werden), aber es gibt sie trotzdem. Wie der Name bereits 
verrt deselektiert sie Objekte.


GLOBAL void set_te_ptext ( OBJECT *obj, int ind, const char *str )

Diese ntzliche Routine kopiert einen String in ein Textobjekt. Dabei wird die 
maximale Lnge des Objektes bercksichtigt und ntigenfalls der String gekrzt.


GLOBAL void objc_rect ( OBJECT *tree, int obj, RECT *rect, BOOLEAN calc_border)

In vielen Fllen kann es ntzlich sein, ein Rechteck zu ermitteln, das ein 
bestimmtes Objekt einhllt. Dies tut obige Funktion, wobei das ermittelte 
Rechteck anschlieend in rect steht. Der letzte Parameter gibt dabei noch an, 
ob der Rand bei Objekten des Typs G_BOX, G_IBOX, G_BOXCHAR mit bercksichtigt 
werden soll. Zu diesem Rand gehren auch die Attribute SHADOWED und OUTLINED.


GLOBAL void text_default ( void )

Oftmals, wenn man Text mit Hilfe von VDI-Funktionen ausgeben will, mu man 
vorher mhsam den Textstil, den Font richtiger Gre, die Ausrichtung u. v. m. 
einstellen, obwohl man eigentlich den Text nur "ganz normal" ausgeben mchte. 
Abhilfe schafft da diese Funktion, die alle diese Attribute auf Default-Werte 
zurcksetzt und den Standard-Systemfont (z. B. 8 x 16 bei monochrom, 
hochauflsend) einstellt.


GLOBAL void line_default ( void )

Das gleiche in grn (?!), diesmal nur fr die Ausgabe von Linien.


GLOBAL void bell( void )

In den meisten Programmen macht sich ein kleiner "Ping" hier und da ganz gut 
(z. B. wenn ein Fehler aufgetreten ist). Dies erledigt die Funktion bell.


GLOBAL void rect2array ( const RECT *rect, int *array )
GLOBAL void array2rect ( const int *array, RECT *rect )

Alle Jahre wieder kommt man in die Verlegenheit, mit Rechtecken und 
verschiedenen Arten von Arrays herumzuwirbeln. Um Ihnen einen Groteil dieser 
Arbeit abzunehmen folgen nun eine ganze Reihe von Funktionen, die sich mit 
Rechtecken auseinandersetzen.
Die ersten beiden kopieren den Inhalt eines Rechtecks in ein Array, das eine 
Punktliste enthalten soll  (also x1, y1, x2 und y2), und umgekehrt. Die dazu 
notwendigen Umrechnungen werden dabei automatisch durchgefhrt.


GLOBAL void xywh2array  ( int x, int y, int w, int h, int *array )
GLOBAL void array2xywh  ( const int *array, int *x, int *y, int *w, int *h )
GLOBAL void xywh2rect ( int x, int y, int w, int h, RECT *rect )
GLOBAL void rect2xywh ( const RECT *rect, int *x, int *y, int *w, int *h)

Manchmal hat man Position, Breite und Hhe eines Rechtecks auch in getrennten 
Variablen gespeichert (x, y, w und h) und mchte sie nun in ein Array oder ein 
Rechteck kopieren oder umgekehrt. Auch hierfr gibt es entsprechende 
Funktionen.


GLOBAL BOOLEAN rc_intersect (const RECT *p1, RECT *p2)

Besonders im Rahmen der Fensterverwaltung kommt es vor, da Rechtecke 
miteinander geschnitten werden mssen. Dies erledigt diese Routine fr Sie, 
wobei das Ergebnis im zweiten bergebenen Rechteck abgespeichert wird und der 
Rckgabewert Auskunft darber gibt, ob sich die Rechtecke berhaupt schneiden.


GLOBAL void rc_union ( const RECT *p1, RECT *p2)

Das Gegenstck zum Schneiden von Rechtecken ist das Vereinigen zu einem groen 
Rechteck. Das Ergebnis wird wieder im zweiten Parameter abgelegt.


GLOBAL BOOLEAN rc_equal ( const RECT *p1, const RECT *p2)

Ein Vergleich, ob zwei Rechtecke identisch sind, kann mit rc_equal durchgefhrt 
werden.


GLOBAL void set_clip ( BOOLEAN set, const RECT *r )

Besonders im Zusammenhang mit Fenstern ist das Clipping angesagt. Die obige 
Funktion setzt das Clipping-Rectangle (set=TRUE) oder setzt ein gesetztes 
Clipping zurck (set=FALSE). Ist der bergebene Zeiger ein NULL-Zeiger, wird 
der Desktop als Clipping-Bereich verwendet. Es wird auch sichergestellt, da in 
jedem Fall maximal der Desktop selbst als Clipping-Bereich verwendet wird.
Damit berall im Programm das gerade aktive Clipping-Rechteck abgefragt werden 
kann, wird dieses in der globalen Rechteck-Variablen clip gespeichert. 


GLOBAL BOOLEAN inside ( int x, int y, const RECT *r )

Die letzte Rechteck-Funktion testet, ob ein bestimmter Punkt innerhalb eines 
Rechtecks liegt.


GLOBAL BOOLEAN find_menu_item ( OBJECT *menu, KEYINFO *ki, int *title, int 
*item )

In den neueren GEM-Programmen ist es Gang und Gbe, mit Tastatur-Shortcuts 
Men-Funktionen auszulsen. Im Programm mu nach einer solchen Eingabe meist 
mit Hilfe von langen switch-Statements die Tastaturaktion abgefragt und die 
richtige Funktion aufgerufen werden. Wird dann der Shortcut gendert, mssen 
Resource-File und Programm mhsam angepat werden.
Die Benutzer von GEM-Force haben es da viel einfacher: Die Funktion 
find_menu_item erledigt bereits eine ganze Menge fr den Programmierer, und 
zwar wurde hier ein anderer, geschickterer Weg beschritten: Sie bergeben der 
Funktion nur Informationen ber das Keyboard-Event (siehe nchste Funktion), 
und die Routine gibt Ihnen den gewhlten Meneintrag zurck, der direkt anhand 
der Resource im Speicher gesucht wird. Dabei gibt der Return-Wert der Funktion 
an, ob ein Meneintrag gefunden wurde oder nicht. Anschlieend knnen Sie im 
Programm so verfahren, als wre das Men direkt ausgewhlt worden.
Sollen die Shortcuts gendert werden, reicht es nun, die RSC-Datei anzupassen.
Die Funktion erkennt bisher folgende Tastaturkombinationen:
- Control + Taste ("Dach" und Zeichen),
- Shift + Funktionstaste (Pfeil nach oben und "Fxx") und
- Alternate + Taste (Raute und Zeichen).
Andere Kombinationen werden bisher noch nicht erkannt.


GLOBAL void get_keyinfo ( int mkstate, int mkreturn, KEYINFO *ki )

Der in der letzten Funktion zu bergebende Zeiger ki ist ein Zeiger auf eine 
KEYINFO-Struktur. Eine solche ist in Ihrem Programm anzulegen und nach einem 
Tastatur-Event mit obigem Funktionsaufruf zu initialisieren. Die bergebenen 
Parameter sind die gleichnamigen Rckgabeparameter der evnt_multi-Funktion der 
AES.


GLOBAL int popup_menu ( OBJECT *tree, int obj, int x, int y, int center_obj, 
BOOLEAN relative, int bmsk )

Als Bonbon dieses Teiles der GEM-Force-Library noch eine handliche Funktion fr 
die komplette Verwaltung von PopUp-Mens. Es wird davon ausgegangen, da das 
PopUp-Men sich als Kind-Objekt in einem Objekt-Baum befindet. In der Regel ist 
ohnehin blich, PopUps und hnliche Objekte in einem Objekt-Baum zu "sammeln". 
Daher ist nicht nur ein Objekt-Baum anzugeben, sondern auch der Index des 
Vater-Objektes des PopUp-Mens. x und y sind Koordinaten, an denen das Men 
erscheinen soll, und zwar entweder als absolute Koordinaten (relative=FALSE) 
oder als Koordinaten relativ zum Mauszeiger (relative=TRUE). Die Funktion 
berwacht selbstndig, da das Men nicht aus dem Bildschirm herausragt.
Als weitere Option ist es mglich, mit center_obj ein Objekt (einen Eintrag im 
PopUp-Men) anzugeben, auf dem der Mauszeiger beim erscheinen des Mens stehen 
soll. Schlielich kann mit bmsk noch gesteuert werden, mit welchem Mausknopf 
das Men verlassen werden soll, indem eine entsprechende Maske (das 
niederwertigste Bit ist der linke Mausknopf usw.) angegeben wird.
Am besten, Sie experimentieren ein wenig mit den Parametern, um zu sehen, 
welcher was bewirkt.


5. Modul WINDOWS
================

Dieses Modul stellt Funktionen fr die Fensterverwaltung in Form eines Window-
Managers zur Verfgung. Soll dieses GEM-Force-Modul genutzt werden, ist die 
Header-Datei "GFWINDWS.H" zu importieren.
Bevor nher auf die Funktionen eingegangen wird, soll das dem Window-Manager 
zugrundeliegende Konzept nher erlutert werden.
Zuerst einmal ist wichtig zu wissen, wie ein Fenster eingeteilt ist.
Der Fensterinhalt ist in Work- und Scroll-Bereich eingeteilt. Der Work-Bereich 
umfat immer das gesamte Fensterinnere, whrend der Scroll-Bereich kleiner sein 
kann, so da (wie in der Abbildung zu sehen) ein Rand entstehen kann, welcher 
bei Bettigung der Slider oder hnlichen Aktionen nicht verndert werden. 
Anders der Scrollbereich, denn auf diesen beziehen sich diese Aktionen, er wird 
also entsprechend gescrollt. Natrlich mu es nicht alle Rnder geben bzw. mu 
es berhaupt Randbereiche geben. In letzterem Fall wre also der Workbereich 
genauso gro wie der Scrollbereich.
Kommen wir nun zur grundlegendsten Struktur des Moduls WINDOWS, und zwar der 
Struktur, die alle Informationen zu einem Fenster enthlt:

typedef struct window
{
        int handle;     /* Handle fr Fenster */
        BOOLEAN opened; /* Fenster geffnet */
        unsigned int flags; /* Flags des Fensters */
        unsigned int kind;  /* Art des Fensters */
        int class;      /* Klasse des Fensters */
        LRECT doc;      /* Dokumentgre, Position */
        int xfac;       /* X-Factor des Dokumentes */
        int yfac;       /* Y-Factor des Dokumentes */
        int xunits;     /* X-Scroll-Einheiten */
        int yunits;     /* Y-Scroll-Einheiten */
        RECT scroll;    /* Scrollbereich */
        RECT work;      /* Arbeitsbereich */
        long special;   /* fr speziellen Gebrauch */
        char name[128]; /* Name des Fensters */
        char info[128]; /* Infozeile im Fenster */
        OBJECT *object; /* Objektbaum fr Fenster */
        BOOLEAN (*test) (WINDOWP, int );/* Test vor einer Aktion */
        void (*open) (WINDOWP);         /* Aktion vor dem ffnen */
        void (*close) (WINDOWP);        /* Aktion nach dem Schlieen */
        void (*delete) (WINDOWP);       /* Aktion vor dem Lschen */
        void (*draw) (WINDOWP);         /* Zeichnen-Funktion */
        void (*arrow) (WINDOWP,int,long,long ); /* Pfeil-Aktion */
        void (*snap) (WINDOWP, RECT *, int );   /* Schnapp-Aktion */
        void (*top) (WINDOWP);          /* Aktion nach Top */
        void (*untop) (WINDOWP);        /* Aktion vor Untop */
} WINDOW;

Der hier vielfach vorkommende Typ WINDOWP ist als Zeiger auf die Struktur 
WINDOW definiert. Wer hier ber Formulierungen wie "BOOLEAN (*test) (WINDOWP, 
int );" stolpert und diese nicht deuten kann: Hier wird eine hervorragende 
Eigenschaft der Programmiersprache C genutzt, und zwar die Speicherung von 
Zeigern auf Funktionen. Eine Zuweisung an einen solchen Zeiger wrde ber den 
Namen der Funktion geschehen, denn der Name einer Funktion ist ein Zeiger auf 
dieselbe (hnlich den Arrays). Ein Referenzieren eines solchen Zeigers mit 
Hilfe des "*"-Operators wrde eine solche Funktion aufrufen. Fr weitergehende 
Informationen zu diesem Thema sei auf einschlgige C-Literatur verwiesen.
Die einzelnen Struktur-Elemente haben folgende Bedeutung:

int handle
Dies ist das Handle, das bei den AES ein Fenster identifiziert und ber das mit 
AES-Funktionen auf Fenster zugegriffen wird.

BOOLEAN opened
Der Zustand des Fensters, nmlich ob es geffnet ist oder nicht.

unsigned int flags
Verschiedene Flags, die das Verhalten des Fensters beeinflussen. Die Flags 
werden vom Window-Manager weitestgehend selbst gesetzt und verwaltet. Dabei 
existieren folgende Flags:
# define WI_NONE        0x0000  /* Keine Flags */
# define WI_FULLED      0x0001  /* Fenster auf voller Groesse */
# define WI_LOCKED      0x0002  /* Fenster gelockt */
# define WI_FIRSTDRW    0x0004  /* Fenster erstesmal gezeichnet */
# define WI_ONTOP       0x0010  /* Fenster ist oben */
# define WI_NOTOP       0x0020  /* Fenster darf nicht nach oben */
# define WI_RESIDENT    0x0040  /* Fenster resident */
# define WI_NOSCROLL    0x0100  /* kein Scrolling */

unsigned int kind
Informationen darber, welche Fensterelemente das Fenster hat (siehe AES.H). 
Der Einfachheit befindet sich in GFWINDWS.H noch das Makro ALL fr alle 
Fensterelemente.

int class
Die Klasse des Fensters, d. h. die Zuordnung zu einer Klasse von Fenstern, die 
die gleichen Eigenschaften haben. Die Klasse kann vom Benutzer frei definiert 
werden. Nur die Klasse CL_TEXT wird von GEM-Force genutzt und bezeichnet Text-
Fenster.

LRECT doc
Fenster zeigen in der Regel den Ausschnitt eines greren Objektes an, sei es 
ein Dokument, eine Grafik etc. Ausgehend von dieser berlegung wird in doc.w 
und doc.h die Gre dieses Dokuments angegeben, und zwar in Einheiten (Pixel 
bei Bildern, Buchstaben bei Text-Dokumenten usw.). doc.x und doc.y geben die 
aktuelle Position des Fenster-Ausschnitts  innerhalb des Dokumentes an.

int xfac, yfac
Da die Angaben in den letzten beschrieben Variablen sich immer auf Einheiten 
(Buchstaben, Pixel usw.) beziehen, wird noch die Information bentigt, wieviele 
Pixel eine Einheit umfat, und zwar sowohl in x- als auch in y-Richtung. 
Minimal kann hier jeweils eine 1 eingetragen werden. Bei Buchstaben des 
Systemzeichensatzes wren die beiden Werte z. B. 8 und 16.

int xuntits, yuntits
Soll in einem Dokument gescrollt werden, mu bekannt sein, um wieviel Einheiten 
sich der Bildausschnitt verschiebt, wenn ein Pfeil im Fensterrandbereich 
angeklickt wird. Diese Information wird fr x- und y-Richtung in obigen 
Variablen abgelegt.

RECT scroll
Die Gre des weiter oben beschriebenen Scroll-Bereichs wird in dieser Variable 
gespeichert. Maximal kann er die Gre des Work-Bereichs annehmen.

RECT work
Analog dazu die Gre des Work-Bereichs.

long special
Wer kennt es nicht, das ob_spec-Element der AES-Objekt-Struktur. Es dient zum 
Aufnehmen verschiedener Informationen, besonders Zeiger auf diverse Strukturen. 
Grundvoraussetzung ist an dieser Stelle natrlich das saubere Casting auf 
Zeiger des entsprechenden Typs.
Die Funktion dieser Variable ist im Grunde die gleiche: Es soll die Mglichkeit 
geschaffen werden, weitere Informationen einem Fenster zuzuordnen, indem man 
einen Zeiger auf diese Informationen hier speichert. Natrlich kann dies auch 
eine einfache long-Zahl sein. So wird z. B. fr Textfenster in dieser Variablen 
ein Zeiger auf ein Text-Array gespeichert.

char name[128]
Damit das Kind auch einen Namen hat: der Fenstertitel.

char info[128]
Der Text fr die Infozeile.

OBJECT *object
Eine weitere Option fr ein Fenster ist es, einen Objekt-Baum darin anzeigen zu 
lassen. Wenn Sie diese Mglichkeit nutzen wollen, geben Sie hier einen 
entsprechenden Zeiger an. Zu beachten ist, da das Objekt nur im Scroll-
Bereich, nicht aber im Randbereich (sofern berhaupt vorhanden) gezeichnet 
wird.
Viele Aktionen (z. B. das Zeichnen des Objektes und das Anpassen der 
Koordinaten beim Verschieben des Fensters) werden Ihnen vom Window-Manager 
abgenommen, so da Sie sich nur noch um die wichtigen Dinge kmmern mssen. Am 
besten Sie probieren es einfach mal aus.

BOOLEAN (*test) ( WINDOWP window, int action )
Hier kommen wir endlich zum ersten in der Struktur enthaltenen Zeiger auf eine 
Funktion. (Noch eine kurze Anmerkung: Wenn Sie Ihre eigenen Funktionen in 
diesen Zeigern einhngen, ist darauf zu achten, da diese Funktionen jeweils 
die Parameter entgegennehmen mssen, die im Prototypen beschrieben sind ! Falls 
Sie keine Funktion einhngen wollen, lassen Sie einfach den Initialwert NULL im 
Zeiger stehen.)
Diese Routine wird vom Window-Manager aufgerufen, bevor ein Fenster geschlossen 
oder gelscht wird. Der zweite Parameter gibt dabei die Aktion an, die gerade 
ausgefhrt werden soll (DO_CLOSE, DO_DELETE). Sie knnen in der eingehngten 
Funktion nun testen, ob die Aktion tatschlich durchgefhrt werden soll; falls 
nicht geben Sie einfach FALSE zurck, andernfalls TRUE.

void (*open) ( WINDOWP window )
Die Funktion wird unmittelbar vor dem ffnen eines Fensters aufgerufen, so da 
Sie noch bestimmte Arbeiten durchfhren knnen, bevor das Fenster wirklich 
erscheint.

void (*delete) ( WINDOWP window )
Die Funktion wird unmittelbar vor dem Lschen eines Fensters aufgerufen.

void (*draw) ( WINDOWP window )
Dies ist wohl mit Abstand die wichtigste Routine in der Fensterstruktur, denn 
sie ist fr das Zeichnen des Fensterinhalts verantwortlich und wird hufig vom 
Window-Manager aufgerufen. Wichtig in diesem Zusammenhang ist, da Sie sich 
nicht mehr um das Clipping kmmern mssen; das erledigt GEM-Force bereits fr 
Sie. Falls Sie in Ihrer Funktion Informationen ber das Clipping-Rectangle 
bentigen, knnen Sie in der globalen Variablen RECT clip nachsehen.

void (*arrow) ( WINDOWP window ,int dir,long oldpos, long newpos )
Diese Funktion wird aufgerufen, wenn der Benutzer einen Pfeil angeklickt hat 
oder einen Schieber bewegt oder angeklickt hat. dir gibt dabei die Richtung an 
(HORIZONTAL, VERTICAL). oldpos ist die alte Position, newpos die neue Position 
im Dokument (siehe doc), abhngig von dir entweder horizontal oder vertikal.
Innerhalb dieser Funktion sollten
1. die neue Position innerhalb des Dokuments in doc bertragen werden,
2. die Slider neu gesetzt werden und
3. der Fensterinhalt gescrollt werden.
Voraussetzung ist natrlich, da Sie die jeweilige Scroll-Aktion erlauben 
wollen; andernfalls brauchen Sie obige Arbeiten natrlich nicht zu erledigen. 
Ggf. knnen auch noch andere sinnvolle Dinge erledigt werden, z. B. das 
Vorrcken eines internen Cursors fr Textzeilen u. v. m.

void (*snap) ( WINDOWP window, RECT *new, int mode )
Wird ein Fenster bewegt oder vergrert/verkleinert, ist es oft sinnvoll, das 
Fenster auf eine bestimmte Position oder Gre einzurasten (z. B. bei 
Textfenstern auf ganze Buchstaben und auf eine durch 8 teilbare x-Position). 
new gibt in diesem Zusammenhang die "angeforderte" Gre und Position des 
gesamten Fensters an und kann von Ihnen in Ihrer Funktion verndert werden. 
mode zeigt an, ob das Fenster bewegt (MOVED) oder in seiner Gre verndert 
(SIZED) oder beides wurde.
Zu beachten ist, da beim ersten ffnen eines Fensters kein Snapping 
stattfindet; Sie mssen also selbst Sorge dafr tragen, da das Fenster zu 
diesem Zeitpunkt die richtige Gre und Position hat !

void (*top) (WINDOWP window)
Wenn ein Fenster nach oben gebracht wird, so wird diese Funktion angesprungen. 
Dies kann in zwei Fllen passieren:
1. Die AES senden die Message WM_TOPPED an die Applikation.
2. Ein Fenster wird geschlossen, und das bis dahin zweitoberste Fenster kommt 
nach oben. In einem solchen Fall sorgt GEM-Force dafr, da diese Routine fr 
das neue oberste Fenster angesprungen wird.

void (*untop) (WINDOWP window)
Diese Funktion ist das Gegenstck zur letzten Funktion: Hier wird das bisher 
oberste Fenster nach unten gebracht, und zwar wenn ein anderes Fenster getoppt 
wird oder ein neues Fenster geffnet wird.
Da eine entsprechende Message im ATARI-GEM noch nicht implementiert ist, sorgt 
GEM-Force selbst dafr.

So, geschafft. Jetzt sollten Sie das Prinzip des GEM-Force-Window-Managers 
verstanden haben, so da wir uns jetzt den "echten" Funktionen im einzelnen 
zuwenden knnen.


GLOBAL BOOLEAN init_windows ( char *err_nowindow, int max_reswind )

Wenn Sie Funktionen aus dem Windows-Modul von GEM-Force verwenden wollen, mu 
dieses Modul zu Beginn initialisiert werden. Dies geschieht mit obiger 
Funktion. Zu bergeben sind eine Alert-Meldung, die immer dann angezeigt wird, 
wenn ein Fenster geffnet werden soll, aber keines mehr zur Verfgung steht, 
und die gewnschte Anzahl der maximal gleichzeitig im Speicher residenten 
Fenster.
Das Grundprinzip des Window-Managers ist es, Fenster mit ihrer Window-Struktur 
im Speicher zu halten, unabhngig davon, ob sie geffnet, also sichtbar, oder 
geschlossen sind. Dafr mu natrlich Speicherplatz reserviert werden, wozu 
wiederum die maximale Anzahl Fenster bekannt sein mu. Die tatschlich 
reservierte Anzahl kann unter Umstnden (z. B. bei Speichermangel) auch kleiner 
sein.
Der Return-Wert ist TRUE, wenn wenigstens Speicher fr ein einziges Fenster 
reserviert werden konnte, FALSE sonst.


GLOBAL void exit_windows ( void ) 

Um Ihr Programm zu terminieren sollten Sie auch diese Funktion aufrufen, denn 
sie schliet alle Fenster, lscht diese und gibt den reservierten Speicher der 
Fenster-Strukturen wieder frei.


GLOBAL BOOLEAN handle_window_events ( int *msg )

Diese Funktion ist das Kernstck des Window-Managers. Sie sollte direkt nach 
Ihrer evnt_multi-Schleife aufgerufen werden, wobei ein Zeiger auf den Event-
Buffer bergeben wird. In ihr werden alle fr den Window-Manager relevanten 
(Message-) Events verarbeitet und an die einzelnen Fenster weitergeleitet. 
Textfenster (siehe weiter unten) werden an dieser Stelle ebenfalls voll-
automatisch verwaltet.
Wurde das Event innerhalb der Funktion verarbeitet, wird TRUE zurckgegeben, 
sonst FALSE.
Generell gilt: GEM-Force verarbeitet in seinem Window-Manager nur Message-
Events. Alle anderen Events sind vom Programmierer selbst zu verarbeiten.


GLOBAL WINDOWP create_window ( unsigned int kind, int class )

Bevor Fenster-Events verarbeitet werden knnen, mu man natrlich erst einmal 
Fenster produzieren. Dazu rufen Sie obige Funktion auf und bergeben ihr die 
Art des gewnschten Fensters (Flags aus AES.H) sowie die Klasse des Fensters. 
Die Fenster-Klasse ist eine von Ihnen frei vorzugebende Klassifizierung von 
Fenstern, d. h. in der Regel ein Gruppenbegriff fr eine bestimmte Art Fenster. 
Nur die Klasse CL_TEXT ist bereits vordefiniert (siehe weiter unten).
Als Rckgabewert der Funktion bekommen Sie einen Zeiger auf die zum Fenster 
gehrige Window-Struktur. Haben Sie ein Fenster erfolgreich kreiert 
(Rckgabewert ungleich NULL), sollten Sie selbst - abgesehen von Art und Klasse 
- alle anderen (wichtigen) Elemente in der Fensterstruktur initialisieren. 
Funktionszeiger brauchen nur dann initialisiert zu werden, wenn Sie bentigt 
werden; andernfalls knnen Sie die NULL-Zeiger darin stehen lassen, die GEM-
Force automatisch in die Struktur schreibt.
Konnte kein Fenster mehr kreiert werden (nicht mehr genug Speicher, siehe 
init_windows), wird die bei init_gem angegebene Alert-Meldung angezeigt.


GLOBAL void delete_window ( WINDOWP window )

Soll ein Fenster auf Nimmer-Wiedersehen verschwinden, steht Ihnen diese 
Funktion zur Verfgung. Sollte das betreffende Fenster noch geffnet sein, wird 
es vor dem Lschen noch geschlossen. Anschlieend wird die Fensterstruktur 
gelscht; das Fenster ist nicht mehr existent. Ausnahme: Ist eine Testfunktion 
in der Fensterstruktur eingehngt, und gibt diese FALSE zurck, wird das 
Fenster nicht gelscht.


GLOBAL BOOLEAN open_window ( WINDOWP window )

Ein Fenster zu ffnen ist mit dieser Routine mglich. Sind noch GEM-Fenster 
verfgbar, wird das Fenster gezeichnet und der gesamte Fensterinhalt mit wei 
initialisiert (Return-Wert TRUE). Andernfalls erscheint die bei init_gem 
angegebene Alert-Meldung (Return-Wert FALSE).
Beim ffnen eines Fensters werden ausgehend von der Bildschirmmitte Grow-Boxes 
gezeichnet, sofern die globale Variable grow_shrink den Wert TRUE hat.
Wenn eine entsprechende open-Funktion in die Fensterstruktur eingehngt ist, 
wird diese unmittelbar vor dem ffnen angesprungen.


GLOBAL void close_window ( WINDOWP window )

Dies ist das Gegenstck zur letzten Funktion. Beim Schlieen eines Fensters 
werden ausgehend von der Bildschirmmitte Shrink-Boxes gezeichnet, sofern die 
globale Variable grow_shrink den Wert TRUE hat.
Wenn eine entsprechende close-Funktion in die Fensterstruktur eingehngt ist, 
wird diese unmittelbar vor dem Schlieen angesprungen.
Ist eine test-Funktion in der Fensterstruktur eingehngt, und gibt diese FALSE 
zurck, wird das Fenster nicht geschlossen.


GLOBAL void close_top ( void )

Das oberste Fenster wird geschlossen.


GLOBAL void close_all ( BOOLEAN delete )

Alle GEM-Force-Fenster werden geschlossen. Ist der zweite Parameter TRUE, 
werden die Fenster zustzlich auch gelscht.


GLOBAL void draw_window ( WINDOWP window )

Der gesamte Fensterinhalt wird - ohne die Rechteckliste zu bercksichtigen - 
neu gezeichnet; soll nur ein Teil neu gezeichnet werden, mu das Clipping 
vorher entsprechend gesetzt werden. An dieser Stelle wird die von Ihnen in die 
Fensterstruktur eingehngte Zeichenroutine benutzt. Ein eingehngter Objektbaum 
wird automatisch gezeichnet. Die Maus wird selbstndig versteckt.


GLOBAL void redraw_window ( WINDOWP window, const RECT *area)

Ein bestimmter Bereich wird unter Bercksichtigung der Rechteckliste neu 
gezeichnet. 


GLOBAL void top_window ( WINDOWP window )

Ein Fenster wird nach oben gebracht, d. h. getoppt, sofern die Fenster-Flags 
(siehe oben) dies zulassen. Eine von Ihnen eingehngte top-Funktion wird 
anschlieend angesprungen.


GLOBAL void untop_window ( WINDOWP window )

Ein Fenster wird von einem anderen (nach oben gebrachten oder neu geffneten 
Fenster) erstmalig verdeckt (bzw. simuliert diese Funktion dies). Die Funktion 
setzt die entsprechenden Flags und ruft ggf. eine in die Fensterstruktur 
eingehngte untop-Routine auf.


GLOBAL void scroll_window ( WINDOWP window, int dir, long delta )

Der Inhalt eines Fensters wird um eine beliebige Anzahl von Pixeln in eine 
Richtung (HORIZONTAL/VERTICAL) gescrollt, wobei die Maus automatisch versteckt 
wird. delta gibt dabei die Anzahl Pixel an (auch negative Werte sind mglich, 
und zwar fr aufwrts und links !).
Verschiedenste Sonderflle wie das Scrollen um ganze Seiten, aus dem Bildschirm 
herausragende Fenster, nicht oben liegende Fenster u. . werden hierbei 
bercksichtigt; ggf. wird die Rechteckliste bercksichtigt.


GLOBAL void arrow_window ( WINDOWP window, int arrow, int amount)

Ein Fenster reagiert auf das Anklicken eines Pfeils oder eines Sliders usw. 
arrow ist ein aus AES.H entnommenes Flag:
WA_UPPAGE       Seite nach oben,
WA_DNPAGE       Seite nach unten,
WA_UPLINE       Zeile nach oben,
WA_DNLINE       Zeile nach unten,
WA_LFPAGE       Seite nach links,
WA_RTPAGE       Seite nach rechts,
WA_LFLINE       Zeile nach links,
WA_RTLINE       Zeile nach rechts;
Auerdem wird noch die Anzahl der Einheiten angegeben, um die gescrollt werden 
soll.
Diese Routine wird vom Window-Manager auch intern aufgerufen, wenn ein 
entsprechendes Event aufgetreten ist.
Es wird auch berwacht, da nicht ber den Rand hinaus gescrollt werden kann; 
in solch einem Falle wird auch kein Scrolling oder Neuzeichnen ausgelst.
Nach Berechnung der neuen Position im Dokument wird die Funktion arrow der 
Fensterstruktur aufgerufen.
Ein in die Struktur eingeklinkter Objektbaum reagiert automatisch richtig auf 
die Aktion.


GLOBAL void h_slider ( WINDOWP window, int new_value )

Ein Fenster reagiert auf das Bewegen des horizontalen Schiebers, wobei der 
zweite Parameter der vom GEM gelieferte neue Wert fr den Schieber (0-1000) 
ist. Nach Berechnen des neuen Schieber-Wertes wird wie beim Anklicken eines 
Pfeils reagiert.


GLOBAL void v_slider ( WINDOWP window, int new_value )

Ein Fenster reagiert auf das Bewegen des vertikalen Schiebers, wobei der zweite 
Parameter der vom GEM gelieferte neue Wert fr den Schieber (0-1000) ist. Nach 
Berechnen des neuen Schieber-Wertes wird wie beim Anklicken eines Pfeils 
reagiert.


GLOBAL void set_sliders ( WINDOWP window, int which, int mode)

Die Schieber-Positionen und/oder die Schieber-Gren werden gesetzt. which kann 
dabei die Werte HORIZONTAL, VERTICAL oder die Kombination beider annehmen, 
whrend mode Position (SLPOS) oder Gre (SLSIZE) oder beides angibt. Ein 
Neuzeichnen der Slider erfolgt nur dann, wenn sich deren Position wirklich 
verndert hat.


GLOBAL void snap_window ( WINDOWP window, RECT *new, int mode)

Die Funktion wird nach dem Verschieben oder Vergrern/Verkleinern von Fenstern 
vom Window-Manager aufgerufen, kann aber im Bedarfsfall auch direkt aufgerufen 
werden. Zunchst wird geprft, ob der linke Fenster-Rand genau am linken 
Bildschirmrand liegt; ist dies der Fall, wird die x-Position des Fensters auf -
1 gesetzt, wodurch der Fenster-Workbereich genau auf x-Position 0 anfngt. 
Weiterhin wird verhindert, da ein Fenster zu klein wird.
Ist in der Fensterstruktur eine snap-Funktion eingehngt, wird diese 
aufgerufen, so da der Programmierer das genaue Einrasten vornehmen kann.
new ist dabei die neue Position bzw. Gre des Fensters, whrend mode angibt, 
ob das Fenster bewegt (MOVED) oder in seiner Gre verndert (SIZED) oder 
beides wurde.
Voraussetzung bei Aufruf dieser Funktion ist, da das betreffende Fenster 
sichtbar am Bildschirm, d. h. opened ist, da hier intern mit AES-Funktionen 
gearbeitet wird, ein Fenster allerdings erst beim open_window fr die AES 
kreiert (wind_create) und damit existent wird ! Ein geschlossenes Fenster hat 
somit kein AES-Handle. Konsequenz: Noch nicht geffnete Fenster knnen nur von 
Hand "gesnappt" werden.


GLOBAL void full_window ( WINDOWP window )

"Ich wei, was Sie sagen wollen, und Sie haben Recht...", so die Worte eines 
bekannten Serienhelden. Es ist offensichtlich, was diese Funktion tut: Das 
betreffende Fenster wird auf seine maximale Gre gebracht, wobei sowohl Grow-
Boxes gezeichnet werden (sofern grow_shrink auf TRUE steht) als auch die snap-
Funktion aufgerufen wird.


GLOBAL void size_window ( WINDOWP window, const RECT *new)

Das Fenster wird auf eine neue Gre gesetzt; zuvor wird jedoch wiederum die 
snap-Funktion aufgerufen. Die Schieber werden automatisch gesetzt.


GLOBAL void move_window ( WINDOWP window, const RECT *new )

Das Fenster wird auf eine neue Position gesetzt; zuvor wird wiederum die snap-
Funktion aufgerufen. Die Schieber werden wieder automatisch gesetzt.


GLOBAL void get_work ( WINDOWP window, BOOLEAN work)

Wurde die Position eines Fensters oder seine Gre verndert, kann mit dieser 
Funktion (sofern es GEM-Force nicht sowieso automatisch tut) der neue Work-
Bereich errechnet werden (wenn das gleichnamige Flag gesetzt ist). Gleichzeitig 
werden auch die neuen Koordinaten des Scroll-Bereichs berechnet.
In jedem Fall werden die Koordinaten eines eingehngten Objekt-Baums neu 
berechnet, d. h. einer neuen Position angepat.
Voraussetzung ist auch hier wieder, da das Fenster fr die AES existent, 
nmlich geffnet, ist.


GLOBAL void get_border ( WINDOWP window, int obj, RECT *border )

Diese Funktion errechnet ein Rechteck, das ein Objekt umschliet, das sich in 
dem in eine Fenster-Struktur eingehngten Objekt befindet, sofern das 
dazugehrige Fenster geffnet ist. Zu kompliziert !? Na gut, ein Beispiel: In 
einem geffneten Fenster ist ein Objekt eingehngt (z. B. ein Dialog). In dem 
Dialog befindet sich ein Text-Objekt, von dem Sie gerne die Umrisse 
einschlielich Rand und Schatten (!) wissen wollen (z. B. um eine Dragbox zu 
zeichnen). Sie bergeben also den Fensterpointer, den Index des Textobjektes 
innerhalb des Objektbaums und einen Zeiger auf ein Rechteck. Fertig. (Ich gebe 
es ja zu: Die erste Erklrung war zwar kurz, aber etwas unverstndlich...)


GLOBAL void lock_all ( WINDOWP wp )

Wenn alle Fenster gelockt werden sollen (gelockt heit, da sie zwar noch nach 
unten gebracht aber nicht mehr getoppt werden knnen), sollten Sie diese 
Funktion benutzen. Geben Sie statt einem NULL-Zeiger einem Fenster-Zeiger mit, 
wird dieses Fenster vor dem Locken ausgeschlossen. Dies ist z. B. bei der 
Programmierung modaler Dialoge in Fenstern interessant.


GLOBAL void unlock_all ( void )

Gelockte Fenster werden von dieser Routine wieder in den "Normal-Zustand" 
gebracht.


GLOBAL void draw_object ( WINDOWP window, int obj )

Eine weitere Funktion fr eingehngte Objekte: Sie zeichnet das Objekt 
innerhalb des Fensters, whrend Rechteckliste und Scroll-Bereich beachtet 
werden.


GLOBAL void scroll_area ( const RECT *area, int dir, int delta )

Ein rechteckiger Bildschirmausschnitt wird um eine beliebige Anzahl Pixel in 
eine Richtung gescrollt, der jedoch nicht von der aktuellen Fenstergre 
abhngig ist. dir gibt die Richtung an (HORIZONTAL, VERTICAL), whrend delta 
die Anzahl Pixel beinhaltet (negative Werte: abhngig von der Richtung nach 
links bzw. abwrts scrollen). Im Gegensatz zu scroll_window mu nicht der 
gesamte Fensterinhalt gescrollt werden.


GLOBAL void clr_area ( const RECT *area )

Ein Bildschirmausschnitt wird gelscht, d. h. mit wei gefllt.


GLOBAL void clr_work ( WINDOWP window )
GLOBAL void clr_scroll ( WINDOWP window )
GLOBAL void clr_left ( WINDOWP window )
GLOBAL void clr_top ( WINDOWP window )
GLOBAL void clr_right ( WINDOWP window )
GLOBAL void clr_bottom ( WINDOWP window )

Die verschiedenen Bereiche eines Fensters werden gelscht, wobei clr_left, 
clr_right, clr_top und clr_bottom sich auf die Fensterrnder beziehen.


GLOBAL void set_redraw ( WINDOWP window, const RECT *area )

Eine Redraw-Meldung fr einen bestimmten Bereich eines Fensters wird ausgelst. 
Dies ist der sauberste Weg, einen Fensterbereich neu zeichnen zu lassen.


GLOBAL WINDOWP create_textwindow ( char *array, int doc_w, int doc_h, int kind, 
RECT *border )

Der GEM-Force-Window-Manager erleichtert zweifellos die Fensterverwaltung 
erheblich. Trotzdem mag es unntz erscheinen, eine Standard-Fensteranwendung 
wie die Anzeige von Text in einem Fenster selbst zu programmieren. Aus diesem 
Grund wurde obige Funktion geschaffen. Sie erzeugt ein Textfenster und stellt 
(fr den Programmierer unsichtbar) entsprechende Funktionen fr die Verwaltung 
von Textfenstern zur Verfgung, indem diese in die Fenster-Struktur eingehngt 
werden.
bergeben als erster Parameter wird ein char-Zeiger auf ein Array, in dem der 
Text zu finden ist, der angezeigt werden soll (meist werden Sie ein 2-
dimensionales char-Array haben; in diesem Fall reicht ein einfacher Cast auf 
einen einfachen char-Pointer).
Die nchsten beiden Eintrge geben die Gre des Dokuments an, d. h. die 
maximale Anzahl Spalten und Zeilen. Bei char array [100][81] wren das 80 und 
100, da ja ein Null-Byte am Zeilenende abgerechnet werden mu.
Der nchste Parameter legt wie blich die Art des Fensters fest. Die Klasse 
wird automatisch auf CL_TEXT gesetzt.
Zum Schlu mu noch die Gre des Fensters (auen, nicht der Work-Bereich !) 
bergeben werden, die es beim ffnen haben soll. Fertig ! Den Rest erledigt 
GEM-Force (siehe handle_window_events).


GLOBAL WINDOWP search_window ( int class, int mode )

Es folgen einige ntzliche Funktionen fr die Abfrage von Fensterattributen 
sowie das Finden von Fenstern.
Der erste Kandidat sucht ein Fenster einer bestimmten Klasse, wobei mode 
angibt, ob nur offene, geschlossene Fenster oder beide gesucht werden sollen 
(SRCH_CLOSED, SRCH_OPENED, SRCH_ANY).
Wurde kein passendes Fenster gefunden, wird ein NULL-Zeiger zurckgegeben.


GLOBAL WINDOWP find_window ( int handle )

Wenn Sie eine GEM-Fensternachricht bekommen haben und diese selbst auswerten 
wollen, mssen Sie zum mitgelieferten GEM-Handle wissen, welches GEM-Force-
Fenster zu diesem Handle gehrt. Dazu bergeben Sie obiger Funktion das GEM-
Handle und bekommen den entsprechenden Window-Zeiger oder im Fehlerfall einen 
NULL-Zeiger zurckgeliefert.


GLOBAL WINDOWP find_xy_window ( const int x, const int y )

Bei der Fensterverwaltung kann es vorkommen, da Sie ein Fenster suchen, das 
sich an einer bestimmten x- und y-Position befindet (z. B. bei einem erfolgten 
Mausklick). Dies erledigt diese Routine fr Sie, wenn Sie die Koordinaten 
bergeben. Falls kein passendes GEM-Force-Fenster gefunden wurde, wird wieder 
ein NULL-Zeiger zurckgeliefert.


GLOBAL WINDOWP find_top ( void )

Einen Zeiger auf das oberste Fenster knnen Sie mit dieser Funktion ermitteln.


GLOBAL BOOLEAN is_top ( WINDOWP window )

Wie offensichtlich sein drfte, kann mit dieser Routine abgefragt werden, ob 
ein Fenster das oberste ist.


GLOBAL BOOLEAN any_open ( BOOLEAN incl_closer )

Es kann getestet werden, ob irgendwelche Fenster offen sind, wobei noch 
spezifiziert werden kann, ob nur Fenster gesucht werden sollen, die auch eine 
Schliebox haben (TRUE). Sonst werden alle Fenster bei der Suche 
bercksichtigt.


GLOBAL int num_windows ( int class, int mode, WINDOWP winds[] )

Die Anzahl der Fenster einer oder aller Klassen (class = NIL) kann ermittelt 
werden. Dabei kann noch angegeben werden, ob offene oder geschlossene Fenster 
oder beide bercksichtigt werden sollen (mode SRCH_CLOSED, SRCH_OPENED, 
SRCH_ANY).
Wird ein Zeiger auf ein Array fr Window-Zeiger bergeben, werden alle 
gefundenen Fensterzeiger hier eingetragen, so da z. B. mit allen gefundenen 
Fenstern bestimmte Aktionen durchgefhrt werden knnen. Andernfalls ist hier 
ein NULL-Zeiger zu bergeben.


GLOBAL int num_locked ( void )

Diese Funktion zhlt die Fenster, deren Flags WI_LOCKED enthalten. (Zur 
Erinnerung: ein gelocktes Fenster kann zwar nach unten gebracht, nicht aber 
wieder getoppt werden.)


6. Modul TOS
============

Dieses Modul stellt ein paar ntzliche Funktionen zur Verfgung. Einige dieser 
Funktionen sind zwar in einer GEM-Library etwas fehl am Platze, jedoch kann der 
ein oder andere sie vielleicht sinnvoll in TOS-Programmen einsetzen. Soll 
dieses Modul von GEM-Force genutzt werden, ist die Header-Datei "GF_TOS.H" zu 
importieren.


GLOBAL BOOLEAN copy ( const char *quelle, const char *ziel )

Es ist immer wieder ntzlich, wenn man Dateien kopieren kann. Das erledigt 
diese Funktion fr Sie. Die Quelle darf auch Wildcards enthalten; in diesem 
Falle wird vom Ziel nur der Pfad beachtet. Andernfalls mu die Zieldatei ein 
vollstndiger Dateiname sein.
In jedem Fall wird bis auf einen kleinen Rest der gesamte verfgbare 
Hauptspeicher per malloc reserviert und ber diesen Puffer munter kopiert. 
Anschlieend wird der Speicherplatz natrlich wieder freigegeben.


GLOBAL BOOLEAN test_printer ( void )

Vor dem Drucken sollte man prfen, ob der Drucker tatschlich bereit dazu ist, 
weil sonst Probleme "vorprogrammiert" sind; diese kleine Routine gibt TRUE 
zurck wenn, der Drukker bereit ist, FALSE sonst.


GLOBAL BOOLEAN file_exist ( const char *filename ) 

Es wird geprft, ob eine bestimmte Datei existiert.


GLOBAL BOOLEAN path_exist ( const char *pathname )

Es wird geprft, ob ein bestimmter Pfad existiert.


GLOBAL void lprint ( char *string, BOOLEAN convert )

Eine Zeichenkette wird an den Drucker gesendet; anschlieend wird ein CR/LF 
ausgelst. Der zweite Parameter steuert dabei, ob deutsche Umlaute bereits 
richtig gedruckt werden sollen, was beim Drucken von Text sehr hilfreich ist. 
Wird FALSE bergeben, erfolgt keine Konvertierung.


GLOBAL void supervisor ( BOOLEAN mode )

Mu einmal betriebssystemnah programmiert werden, mu fter zwischen 
Supervisor-Mode und dem normalen Modus umgeschaltet werden. Wird TRUE 
bergeben, wird der Supervisor-Mode angeschaltet, sonst wird er ausgeschaltet.
Wichtig ist, da nicht "von Hand", d. h. ohne diese Funktion, eingeschaltet und 
dann mit der Funktion ausgeschaltet werden darf (und umgekehrt), da sich die 
Routine beim Einschalten statisch die alte Stack-Adresse merkt und diese beim 
Ausschalten wieder verwendet.


GLOBAL void poke ( long adr, char wert )
GLOBAL void wpoke ( long adr, int wert )
GLOBAL void lpoke ( long adr, long wert )
GLOBAL char peek ( long adr )
GLOBAL int wpeek ( long adr )
GLOBAL long lpeek ( long adr )

Wer schon einmal mit BASIC programmiert hat, wird diese Funktionen kennen: poke 
schreibt einen Wert an eine Speicheradresse (wpoke ein Wort, lpoke ein 
Langwort). peek dagegen liest den Inhalt einer Speicheradresse aus und gibt den 
Wert mit entsprechendem Typ zurck.


GLOBAL void cls ( void )

Nun folgen waschechte TOS-Funktionen: Bei der ersten wird der Bildschirm 
gelscht und der Cursor in der linken oberen Ecke des Bildschirms positioniert.


GLOBAL void cursor_on ( void )
GLOBAL void cursor_off ( void )

Der Cursor wird an-/ausgeschaltet.


GLOBAL void at ( int zeile, int spalte )

Der Cursor wird an eine bestimmte Stelle auf dem Bildschirm gesetzt.


GLOBAL void print_at ( int zeile, int spalte, const char *text )

Ein Text wird an einer bestimmten Position auf dem Bildschirm ausgegeben. 
Anschlieend erfolgt automatisch ein Zeilenvorschub.


GLOBAL void tab ( int spalte )

Der Cursor wird in der aktuellen Zeile in eine bestimmte Spalte gesetzt.


GLOBAL void print_tab ( int spalte, const char *text )

Ein Text wird an einer bestimmten Position in der aktuellen Zeile auf dem 
Bildschirm ausgegeben. Anschlieend erfolgt automatisch ein Zeilenvorschub.

