--------------------------------------------------------------------------------
-       GEM-Fensterprogrammierung in GFA-BASIC, Versuch einer Einfhrung       -
-       anhand der Beispielapplikation TWO_VIEW                                -
--------------------------------------------------------------------------------

Hallo!
------

Immer wieder vermelden GFA-Programmierer Schwierigkeiten mit dem Einstieg
in die saubere GEM-Fenster-Programmierung. Diesen Zeitgenossen soll mit
dem vorliegen Beispielprogramm und diesem Text geholfen werden...

Das Programm TWO_VIEW ist in der compilierten Form eigentlich
Bestandteil der Archiver-Shell Two-in-One. Da es aber zum einen nichts tut,
was ein erfahrener Programmierer nicht selbst innerhalb krzester Zeit auf
die Beine stellen knnte, _und_ es sich IMO (DF-Slang, In My Opinion) gut
fr eine GEM-Einfhrung eignet, habe ich einer Verffentlichung in dieser
Form zugestimmt. Das Programm darf im compilierten Zustand nicht weiterge-
geben werden!

Natrlich drfen Sie die hier verwendeten Routinen in eigenen Programmen
verwenden, ich knnte das auch schlecht kontrollieren. ber eine Erwhnung
in der Programmdokumentation wrde ich mich in diesem Falle freuen.

Ich kann und will hier aber keine komplette Einfhrung in die GEM-Program-
mierung geben, dazu gibt es bessere Quellen (siehe beiliegendes GFA-FAQ).

Was tut das Programm?
---------------------

Es ldt und zeigt einen beliebigen ASCII-Text in einem GEM-Fenster an.
Dies geschieht 100% sauber, also ohne LINE-A, unter Beachtung von
Hintergrundscrolling usw. Auerdem benutzt es kein Stringfeld fr den
Text, sondern einen mit MALLOC() angeforderten Bereich. Daher wird die
Gre des anzuzeigenden Textes nur durch den Speicher begrenzt.

ERGO!pro am Werk
----------------

Das vorliegende Programm macht Gebrauch von den ERGO!pro-Prprozessor-
kommandos. Wer ERGO!pro nicht kennt, sollte es unbedingt kennenlernen,
da es unserer bescheidenen Meinung das non-plus-ultra fr GFA-BASIC-
Programmierer darstellt. Nhere Infos dazu gibt es bei

 Columbus Soft
 Kinzigweg 1
 64297 Darmstadt
 Telefon/Fax: 06151-596875

Der ERGO-Prprozessor (PP) 'behandelt' den Quellcode vor dem Compilieren,
indem er hnlich dem Prprozessor der Sprache C bestimmte Teile des
Listings ersetzt.

Folgende PP-Kommandos werden in TWO_VIEW benutzt:

 ++SYM : Konstanten fr die GEM-Meldungen etc. in 'gem_init'. Dies
         entspricht professionellem Programmierstil, der in anderen
         Hochsprachen schon lngst mglich war.

 CMP : Sollte immer gesetzt werden, da es nur im Interpreter ntige
       Programmzeilen entfernt.
 GER : Sollte fr die normale, deutsche Version gesetzt werden. ENG
       dann bitte nicht setzen.
 ENG : Erzeugt eine englische Version des Programms, GER dann bitte
       nicht setzen.

Nicht-ERGO!-Benutzer sollten die mit '-ENG' (und ggf. auch '-CMP') gekenn-
zeichneten Zeilen bzw. die mit '--ENG' gekapselten Bereiche aus dem Source
entfernen. Nicht wundern, da einige Aktionen im Interpreter sonst zweimal
ausgefhrt werden!

Textpufferverwaltung
--------------------

Wie bereits gesagt wird der anzuzeigende Text in einem mit MALLOC() ange-
forderten Speicherbereich verwaltet. Zustzlich wird die Ausgabe ber
Assembler-Unterroutinen abgewickelt. Das hat lediglich historische und
Geschwindigkeitsgrnde, es wre kein Problem, diese Routinen direkt in
GFA zu realisieren.

Wie funktioniert's? Der Text wird in den Textpuffer geladen (an die Adresse
't_puffer%'). Danach werden alle ASCII 13 + ASCII 10 (Linefeed) durch ein
Space + Nullbyte berschrieben ('t_wandeln'). So kann die Assemblerroutine
'zeilenadr(z&)' die Adresse einer Textzeile besser ermitteln, da einfach
nur das z. Nullbyte gesucht werden mu.

brigens: Die Textpufferverwaltung von TWO_VIEW ist, da aus einem anderen
Programm bernommen, theoretisch in der Lage, einen weiteren Text hinzuzu-
laden. Daher das in diesem Fall unntig komplizierte Handling mit 't_enough',
't_start%' usw.

Allgemeine Programmtiertips mit Bezug auf TWO_VIEW
--------------------------------------------------

* Zeichenbreite und -hhe: Eine sehr wichtige Vorarbeit fr GEM-Programme
  wird gleich am Anfang erledigt: Das Ermitteln der von den AES verwendeten
  Zeichenhhe und -breite ber GRAF_HANDLE() und Ihre Speicherung in 'wchar&'
  und 'hchar&'. Diese Werte sollten immer im Programm benutzt werden, wenn
  es ntig ist (z.B. in 'fenster_redraw_part'). Absolute Werte wie 16 sind
  zu vermeiden!

* Heimatdirectory: Hat fr ein GEM-Programm eine wichtige Bedeutung. Hier
  findet es z.B. sein RSC-File oder ggf. weitere Dateien (z.B. INF). Daher
  sollte es immer in einer Variablen (hier: 'homedir$') abgelegt werden.
  In compilierten Programmen wird es ermittelt, im Interpreter absolut
  gesetzt (siehe 'init').

* Ereignisse auswerten: Ein echtes GEM-Programm besitzt eine Hauptschleife
  mit dem Befehl EVNT_MULTI, von dem entsprechend den eingetretenen Er-
  eignissen in die entsprechenden Unterroutinen verzweigt wird. Im vorlie-
  genden Programm wren das:

  menu_auswerten
  fenster_auswerten
  tastatur_auswerten
  maus_auswerten

  Es ist sinnvoll, intern ebenfalls diese Prozeduren aufzurufen und nicht
  etwa 'direkt' Aktionen auszufhren. Beispiel: Das Drcken der Tasten-
  kombination <^Q> entspricht dem Anklicken des Menpunktes 'Beenden'.
  Also ruft 'tastatur_auswerten' in diesem Fall 'menu_auswerten' auf.
  Durch diese interne Standardisierung der Schnittstellen erleichtert man
  sich die Arbeit enorm und behlt den berblick. Schlielich mu man ggf.
  nur die Programmzeilen in 'menu_auswerten' anpassen und alle anderen
  Programmteile profitieren davon. Alles klar? :-)

* Textverwaltung: Die Textanzeige wird ber folgende Variablen koordiniert:

  anfs&,anfz&: Enthlt die Spalte/Zeile (bezogen auf den Gesamttext), die
               momentan im Fenster angezeigt wird
  hiz&,liz&  : Enthlt die Anzahl der Textzeilen und die Lnge der lngsten
               Textzeile
  feb&,feh&  : Enthalten die Hhe/Breite des Fensterarbeitsbereiches in
               Zeichen.

  Mit diesen 6 Variablen knnen nun problemlos Fensteraktionen wie das
  Setzen der Slider, Scrollen usw. durchgefhrt werden. Bei mehreren
  Fenstern/Texten sollten diese indiziert werden.

* Redraw: Findet in der Prozedur 'fenster_redraw_part' statt. Theoretisch
  wrde es gengen, hier ein Clipping auf den zu erneuernden Bereich zu
  legen und dann einfach den gesamten Text auszugeben. Dies wre aber
  nicht sehr effektiv und schnell. Daher wird der auszugebende Bereich
  vorher mglichst genau eingeschrnkt (Variablen z1& und z2&, ermittelt
  von der Funktion 'z()'). Zustzlich wird die X- und Y-Position der
  ersten Ausgabe ermittelt, damit in der folgenden Schleife lediglich
  die Y-Position jeweils um 'hchar&' erhht werden mu.

  brigens: Eine horizontale Optimierung der Spalte findet hier nicht
  statt. Es wird also immer die gesamte Zeile ausgegeben.

* Ausgabe der Textzeilen: Eine wichtige Stellung nimmt hierbei die
  VDI-Funktion 'vst_alignment' in der Prozedur 'init' ein. Sie sorgt dafr,
  da die Basislinie fr Textausgaben auf der Grundlinie liegt. D.h., ein
  z.B. mit 'TEXT 8,15,"T"' ausgegebenes Zeichen nimmt tatschlich die Pixel
  0-15 ein. Dies ist fr das Verwalten des Fensterscrollings sehr wichtig!

* Hintergrundscrolling: Es bietet sich an, vor Redrawausgaben zunchst
  zu prfen, ob der gesamte Arbeitsbereich des Fensters 'frei' ist, das
  Fenster also nicht z.B. im Hintergrund liegt (Routine 'fenster_top').
  In diesem Fall kann
  eine schnellere Ausgabe erzielt werden, indem der gescrollte Teil
  gesrollt wird und nur die neu erscheinende Zeile neu gezeichnet
  wird. Ansonsten wird ein Redraw fr das gesamte Fenster ausgelst
  (=langsamer).

* Setzen der Slider-Positionen und -Gren: Erfahrungsgem macht dies
  vielen Leuten Probleme, auch ich habe seinerzeit lange an den ent-
  sprechenden Funktionen 'vslider_siz', 'v_slider_pos' usw. herumgedok-
  tert. Sie haben es da ja nun einfacher. :-) Die Funktionen benutzen
  die bereits oben angefhrten Variablen 'anfs&','anfz&' usw.

* Fenstertitel und -infozeilen: Diese mssen an festen Adressen abgelegt
  werden. Stringadressen ndern sich aber laufend, daher knnen diese
  nicht direkt an die entsprechenden WIND_SET()-Aufrufe bergeben werden.
  Sie sollten vielmehr vorher an eine feste Adresse, z.B. ein INLINE,
  kopiert werden. Dazu dienen im vorliegenden Programm die INLINEs wt%
  und wi% (max. 80 Zeichen + 1 Nullbyte). Benutzt man mehr als ein Fenster,
  mssen die Inlines entsprechend grer sein.

Schluwort
----------

Wie gesagt war dieses Programm ursprnglich nicht als Lernbeispiel gedacht,
man verzeihe mir also etwaige Unzulnglichkeiten. Ebenso sollte klar sein,
da jeder Programmierer seinen eigenen pers. Stil hat und einiges vielleicht
anders gemacht htte. Bei Fragen stehe ich gerne ber eMail zur Verfgung:

 Gregor_Duchalski@do.maus.ruhr.de

Schriftliche Anfragen werden nach Mglichkeit auch beantwortet, das kann
aber etwas dauern:

 Gregor Duchalski
 Im Wiescherfeld 21
 D-44627 Herne

Viel Erfolg!

Herne, 30.12.94

- Laws change, depending on who's making them. Justice will always be justice. -
