+-----------------------------------------+ |+---------------------------------------+| || 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 leistungsf„hig sein sollen, jedoch den Programmierer in seiner Flexibilit„t nicht einschr„nken sollen. Aus diesem Grund wurde - im Gegensatz zu anderen verbreiteten Libraries - keine Funktion geschrieben, die die AES-Events empf„ngt (evnt_multi) und verarbeitet, ohne daž der Programmierer direkt Zugriff darauf hat; das w„re zwar in einigen Bereichen fr den unerfahreneren Programmierer einfacher, schr„nkt 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 k”nnen. Dabei sollte es keine Rolle spielen, ob Sie fortgeschrittener Anf„nger oder schon angehender Profi sind. In jedem Fall: Viel Erfolg ! An dieser Stelle m”chte ich noch den Brdern Jrgen und Dieter Geiž, den Autoren des Buches "Vom Anf„nger 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 Einverst„ndnis w„re diese Library in dieser Form nicht m”glich 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 erkl„rt 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 Anf„nger 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, w„hrend 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. Anschliežend folgt die Header-Datei "GFEXPORT.H" und die Header-Datei des Moduls selbst. Mit dieser Vorgehensweise ist es m”glich, wie in Modula Variablen und Funktionen bezogen auf das jeweilige Modul zu importieren bzw. exportieren. In dem Header-File "GFIMPORT.H" werden zus„tzlich noch die Funktionen min und max, sowie der Typ BOOLEAN mit seinen Auspr„gungen 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. Erw„hnenswert 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 enth„lt Informationen ber eine Tastaturaktion. Es folgt nun eine Aufz„hlung 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 ben”tigt 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 H”he der Box, die ein Zeichen des Systemzeichensatzes einschiežt (z. B. 8 x 16) GLOBAL int gl_wchar, gl_hchar die Breite und H”he eines Zeichens des Systemzeichensatzes GLOBAL int gl_wattr, gl_hattr die Breite und H”he der Box, die ein Be- dienelement eines Fensters einschliežt (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 Eintr„ge 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 ge”ffnete virtuelle Bildschirm-Workstation schliežt, den von einer geladenen Resource-Datei ben”tigten 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 ert”nt ein Glockensignal und eine Fehlermeldung wird (mit Hilfe einer Alert-Box) auf den Bildschirm gebracht. Um die Library sprachunabh„ngig 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 get„tigt 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 ben”tigt, das heižt ein Zeiger auf einen Zeiger auf einen Objektbaum (ein Zeiger auf einen Zeiger ist notwendig, da der Zeiger selbst ja ver„ndert werden soll). Des weiteren werden alle Images und Icons, die in diesem Baum enthalten sind, ins ger„tespezifische 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 Aufl”sungen enth„lt. 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 ver„ndern also nichts daran. Weitere Voraussetzung ist, daž dieser Baum als aller erster mit der Funktion init_tree vorbereitet wird (andernfalls kann sp„ter 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 k”nnen 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 k”nnte nur der Hintergrund des letzten richtig restauriert werden, und es g„be 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 vollst„ndig, arbeitet also einen Dialog ab, bis ein Exit- oder Touchexit-Button bet„tigt wird. "Nebenbei" werden noch fliegende Dialoge realisiert, sofern der Dialog ein entsprechendes Objekt enth„lt. GLOBAL int do_dialog ( OBJECT *tree, int edit_object ) Der Aufruf dieser Funktion fažt die letzten drei Funktionen zusammen: Der Dialog wird dargestellt, verwaltet und wieder vom Bildschirm gel”scht. Sie k”nnen also eine ganze Dialogverarbeitung mit einem einzigen Befehl durchfhren ! Einen Haken hat das ganze natrlich: Wurde ein Touchexit-Button bet„tigt, ist der Dialog natrlich auch vom Bildschirm verschwunden, obwohl diese Art Objekte meist verwandt werden, wenn eine Aktion im Dialog ausgel”st 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) bet„tigt wurde (form_dialog), und anschliežend wieder vom Bildschirm gel”scht 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 bet„tigt, werden die vorigen Inhalte wieder in die Dialogbox eingetragen (was man erst beim n„chsten Aufruf zu sehen bekommt) und keine weitere Aktion ausgel”st. Dieser Mechanismus erfordert es, daž das Programm sich vor dem Ver„ndern durch den Benutzer alle Textfelder und Buttons merkt. Und das erfordert wieder l„stigen 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 L„nge von 70 Zeichen. GLOBAL void restore_dial ( OBJECT *tree ) Wurde der Abbruch-Button bet„tigt, k”nnen 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 m”chte, ist der Start- bzw. Endpunkt die Bildschirmmitte. Dieser Vorgang wird durch draw_grow_shrink vereinfacht, da Sie nur noch das gr”žere 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 l„žt die Maus verschwinden. Intern wird hierzu ein Z„hler 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 k”nnen. Am Ende wird die Maus wieder ausgeschaltet. So sch”n, 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 n„chsten 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 einschliežlich 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 bet„tigt wurde und zus„tzlich noch ein Dateiname ausgew„hlt wurde, der dann in filename steht. In allen anderen F„llen 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 vollst„ndigen Pfadnamens m”glichst komfortabel und einfach ist, wurde diese Funktion geschaffen. Der Parameter filename gibt den vollst„ndigen 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 m”glich 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 k”nnen 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 besch„ftigen. Die ersten beiden hier genannten befassen sich mit dem Status von Objekten. Mit do_state k”nnen 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 k”nnen 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 k”nnen. 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 besch„ftigen. 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 zusammengeh”rigen 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 ver„ndert. GLOBAL int get_rbutton ( OBJECT *tree, int obj ) Natrlich muž man auch Radio-Buttons abfragen k”nnen. Dazu dient diese Routine, der aužer 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 verr„t 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 L„nge des Objektes bercksichtigt und n”tigenfalls der String gekrzt. GLOBAL void objc_rect ( OBJECT *tree, int obj, RECT *rect, BOOLEAN calc_border) In vielen F„llen kann es ntzlich sein, ein Rechteck zu ermitteln, das ein bestimmtes Objekt einhllt. Dies tut obige Funktion, wobei das ermittelte Rechteck anschliežend 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 geh”ren 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 Gr”že, die Ausrichtung u. v. m. einstellen, obwohl man eigentlich den Text nur "ganz normal" ausgeben m”chte. Abhilfe schafft da diese Funktion, die alle diese Attribute auf Default-Werte zurcksetzt und den Standard-Systemfont (z. B. 8 x 16 bei monochrom, hochaufl”send) 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 Grožteil 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 H”he eines Rechtecks auch in getrennten Variablen gespeichert (x, y, w und h) und m”chte 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 grožen 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 G„be, mit Tastatur-Shortcuts Men-Funktionen auszul”sen. 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 ge„ndert, mssen Resource-File und Programm mhsam angepažt 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 n„chste Funktion), und die Routine gibt Ihnen den gew„hlten 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. Anschliežend k”nnen Sie im Programm so verfahren, als w„re das Men direkt ausgew„hlt worden. Sollen die Shortcuts ge„ndert 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 selbst„ndig, daž das Men nicht aus dem Bildschirm herausragt. Als weitere Option ist es m”glich, mit center_obj ein Objekt (einen Eintrag im PopUp-Men) anzugeben, auf dem der Mauszeiger beim erscheinen des Mens stehen soll. Schliežlich 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 n„her auf die Funktionen eingegangen wird, soll das dem Window-Manager zugrundeliegende Konzept n„her erl„utert werden. Zuerst einmal ist wichtig zu wissen, wie ein Fenster eingeteilt ist. Der Fensterinhalt ist in Work- und Scroll-Bereich eingeteilt. Der Work-Bereich umfažt immer das gesamte Fensterinnere, w„hrend der Scroll-Bereich kleiner sein kann, so daž (wie in der Abbildung zu sehen) ein Rand entstehen kann, welcher bei Bet„tigung der Slider oder „hnlichen Aktionen nicht ver„ndert werden. Anders der Scrollbereich, denn auf diesen beziehen sich diese Aktionen, er wird also entsprechend gescrollt. Natrlich muž es nicht alle R„nder geben bzw. muž es berhaupt Randbereiche geben. In letzterem Fall w„re 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 enth„lt: typedef struct window { int handle; /* Handle fr Fenster */ BOOLEAN opened; /* Fenster ge”ffnet */ unsigned int flags; /* Flags des Fensters */ unsigned int kind; /* Art des Fensters */ int class; /* Klasse des Fensters */ LRECT doc; /* Dokumentgr”že, 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 Schliežen */ void (*delete) (WINDOWP); /* Aktion vor dem L”schen */ 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 einschl„gige 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, n„mlich ob es ge”ffnet 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 gr”žeren Objektes an, sei es ein Dokument, eine Grafik etc. Ausgehend von dieser šberlegung wird in doc.w und doc.h die Gr”že 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 ben”tigt, wieviele Pixel eine Einheit umfažt, und zwar sowohl in x- als auch in y-Richtung. Minimal kann hier jeweils eine 1 eingetragen werden. Bei Buchstaben des Systemzeichensatzes w„ren 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 Gr”že des weiter oben beschriebenen Scroll-Bereichs wird in dieser Variable gespeichert. Maximal kann er die Gr”že des Work-Bereichs annehmen. RECT work Analog dazu die Gr”že 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 M”glichkeit 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 M”glichkeit 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 einh„ngen, ist darauf zu achten, daž diese Funktionen jeweils die Parameter entgegennehmen mssen, die im Prototypen beschrieben sind ! Falls Sie keine Funktion einh„ngen wollen, lassen Sie einfach den Initialwert NULL im Zeiger stehen.) Diese Routine wird vom Window-Manager aufgerufen, bevor ein Fenster geschlossen oder gel”scht wird. Der zweite Parameter gibt dabei die Aktion an, die gerade ausgefhrt werden soll (DO_CLOSE, DO_DELETE). Sie k”nnen in der eingeh„ngten Funktion nun testen, ob die Aktion tats„chlich 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 k”nnen, bevor das Fenster wirklich erscheint. void (*delete) ( WINDOWP window ) Die Funktion wird unmittelbar vor dem L”schen 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 h„ufig 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 ben”tigen, k”nnen 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), abh„ngig 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. k”nnen 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 vergr”žert/verkleinert, ist es oft sinnvoll, das Fenster auf eine bestimmte Position oder Gr”že einzurasten (z. B. bei Textfenstern auf ganze Buchstaben und auf eine durch 8 teilbare x-Position). new gibt in diesem Zusammenhang die "angeforderte" Gr”že und Position des gesamten Fensters an und kann von Ihnen in Ihrer Funktion ver„ndert werden. mode zeigt an, ob das Fenster bewegt (MOVED) oder in seiner Gr”že ver„ndert (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 Gr”že und Position hat ! void (*top) (WINDOWP window) Wenn ein Fenster nach oben gebracht wird, so wird diese Funktion angesprungen. Dies kann in zwei F„llen 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 ge”ffnet 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 k”nnen. 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 ge”ffnet 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, unabh„ngig davon, ob sie ge”ffnet, also sichtbar, oder geschlossen sind. Dafr muž natrlich Speicherplatz reserviert werden, wozu wiederum die maximale Anzahl Fenster bekannt sein muž. Die tats„chlich reservierte Anzahl kann unter Umst„nden (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 schliežt alle Fenster, l”scht 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 k”nnen, 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 geh”rige 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 ben”tigt werden; andernfalls k”nnen 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 ge”ffnet sein, wird es vor dem L”schen noch geschlossen. Anschliežend wird die Fensterstruktur gel”scht; das Fenster ist nicht mehr existent. Ausnahme: Ist eine Testfunktion in der Fensterstruktur eingeh„ngt, und gibt diese FALSE zurck, wird das Fenster nicht gel”scht. GLOBAL BOOLEAN open_window ( WINDOWP window ) Ein Fenster zu ”ffnen ist mit dieser Routine m”glich. 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 eingeh„ngt ist, wird diese unmittelbar vor dem ™ffnen angesprungen. GLOBAL void close_window ( WINDOWP window ) Dies ist das Gegenstck zur letzten Funktion. Beim Schliežen 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 eingeh„ngt ist, wird diese unmittelbar vor dem Schliežen angesprungen. Ist eine test-Funktion in der Fensterstruktur eingeh„ngt, 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 zus„tzlich auch gel”scht. 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 eingeh„ngte Zeichenroutine benutzt. Ein eingeh„ngter Objektbaum wird automatisch gezeichnet. Die Maus wird selbst„ndig 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 eingeh„ngte top-Funktion wird anschliežend angesprungen. GLOBAL void untop_window ( WINDOWP window ) Ein Fenster wird von einem anderen (nach oben gebrachten oder neu ge”ffneten Fenster) erstmalig verdeckt (bzw. simuliert diese Funktion dies). Die Funktion setzt die entsprechenden Flags und ruft ggf. eine in die Fensterstruktur eingeh„ngte 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 m”glich, und zwar fr aufw„rts und links !). Verschiedenste Sonderf„lle 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; Aužerdem 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 ausgel”st. 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-Gr”žen werden gesetzt. which kann dabei die Werte HORIZONTAL, VERTICAL oder die Kombination beider annehmen, w„hrend mode Position (SLPOS) oder Gr”že (SLSIZE) oder beides angibt. Ein Neuzeichnen der Slider erfolgt nur dann, wenn sich deren Position wirklich ver„ndert hat. GLOBAL void snap_window ( WINDOWP window, RECT *new, int mode) Die Funktion wird nach dem Verschieben oder Vergr”žern/Verkleinern von Fenstern vom Window-Manager aufgerufen, kann aber im Bedarfsfall auch direkt aufgerufen werden. Zun„chst 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 anf„ngt. Weiterhin wird verhindert, daž ein Fenster zu klein wird. Ist in der Fensterstruktur eine snap-Funktion eingeh„ngt, wird diese aufgerufen, so daž der Programmierer das genaue Einrasten vornehmen kann. new ist dabei die neue Position bzw. Gr”že des Fensters, w„hrend mode angibt, ob das Fenster bewegt (MOVED) oder in seiner Gr”že ver„ndert (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 ge”ffnete Fenster k”nnen 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 Gr”že 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 Gr”že 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 Gr”že ver„ndert, 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 eingeh„ngten Objekt-Baums neu berechnet, d. h. einer neuen Position angepažt. Voraussetzung ist auch hier wieder, daž das Fenster fr die AES existent, n„mlich ge”ffnet, ist. GLOBAL void get_border ( WINDOWP window, int obj, RECT *border ) Diese Funktion errechnet ein Rechteck, das ein Objekt umschliežt, das sich in dem in eine Fenster-Struktur eingeh„ngten Objekt befindet, sofern das dazugeh”rige Fenster ge”ffnet ist. Zu kompliziert !? Na gut, ein Beispiel: In einem ge”ffneten Fenster ist ein Objekt eingeh„ngt (z. B. ein Dialog). In dem Dialog befindet sich ein Text-Objekt, von dem Sie gerne die Umrisse einschliežlich 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 Erkl„rung war zwar kurz, aber etwas unverst„ndlich...) GLOBAL void lock_all ( WINDOWP wp ) Wenn alle Fenster gelockt werden sollen (gelockt heižt, daž sie zwar noch nach unten gebracht aber nicht mehr getoppt werden k”nnen), 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 eingeh„ngte Objekte: Sie zeichnet das Objekt innerhalb des Fensters, w„hrend 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 Fenstergr”že abh„ngig ist. dir gibt die Richtung an (HORIZONTAL, VERTICAL), w„hrend delta die Anzahl Pixel beinhaltet (negative Werte: abh„ngig von der Richtung nach links bzw. abw„rts scrollen). Im Gegensatz zu scroll_window muž nicht der gesamte Fensterinhalt gescrollt werden. GLOBAL void clr_area ( const RECT *area ) Ein Bildschirmausschnitt wird gel”scht, 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 gel”scht, wobei clr_left, clr_right, clr_top und clr_bottom sich auf die Fensterr„nder beziehen. GLOBAL void set_redraw ( WINDOWP window, const RECT *area ) Eine Redraw-Meldung fr einen bestimmten Bereich eines Fensters wird ausgel”st. 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 eingeh„ngt 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 n„chsten beiden Eintr„ge geben die Gr”že des Dokuments an, d. h. die maximale Anzahl Spalten und Zeilen. Bei char array [100][81] w„ren das 80 und 100, da ja ein Null-Byte am Zeilenende abgerechnet werden muž. Der n„chste Parameter legt wie blich die Art des Fensters fest. Die Klasse wird automatisch auf CL_TEXT gesetzt. Zum Schluž muž noch die Gr”že des Fensters (aužen, 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 geh”rt. 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 k”nnen 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 Schliežbox 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 k”nnen. Andernfalls ist hier ein NULL-Zeiger zu bergeben. GLOBAL int num_locked ( void ) Diese Funktion z„hlt 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 vollst„ndiger Dateiname sein. In jedem Fall wird bis auf einen kleinen Rest der gesamte verfgbare Hauptspeicher per malloc reserviert und ber diesen Puffer munter kopiert. Anschliežend wird der Speicherplatz natrlich wieder freigegeben. GLOBAL BOOLEAN test_printer ( void ) Vor dem Drucken sollte man prfen, ob der Drucker tats„chlich 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; anschliežend wird ein CR/LF ausgel”st. 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 gel”scht 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. Anschliežend 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. Anschliežend erfolgt automatisch ein Zeilenvorschub.