                           Three Flights Up
                           ----------------


              The new Programmer's Guide to Let 'em Fly!

                       (includes version 1.20)

                              April 1993

                     (c) 1991-93 by Oliver Scheel

             ... this guide (however) goes Freaky Deaky!


                             Introduction
                             ============

Tja,  nun ist es soweit,  der komplett berarbeitete Guide ist da.  Er
soll  dazu  dienen  die programmiertechnischen  Mglichkeiten  in  Zu-
sammenhang mit Let 'em Fly!  nherzubringen.  Um jedoch hochgesteckten
Erwartungen entgegenzuwirken:  Er kann das Gehirn des einzelnen  nicht
ersetzen,   also   nichts  fr  den  Ex  US-Prsidenten  Ronny   ("The
President's brain's missin'!").

Nun  denn,  fr diesen Guide sind C-Kenntnisse (und  nach  Mglichkeit
auch  Assemblerkenntisse) erforderlich.  Eine Untersttzung  von  GFA-
Basic  (oder Omikron-Basic) wird es von meiner Seite her nicht  geben,
da  ich noch nie mit Basic auf dem ST gearbeitet habe (ich stelle  mir
es  aber ziemlich kompliziert vor) und natrlich  gewisse  Abneigungen
gegen  Basic  auf  dem  ST habe.  Da  eine  echte  strukturierte  Pro-
grammierung unter Basic nicht mglich ist (da kann der Herr  Ostrowski
noch  so  viel `while's und `case's einbauen),  drfte  besonders  der
Zugriff  auf die Struktur nicht ganz einfach sein.  Auch  wenn  dieser
Absatz  etwas  hart kommt,  mu ich aber leider sagen,  da  ich  mich
recht  hufig ber GFA-Basic Programme aufregen mu.  Dabei meine  ich
nicht  unbedingt die der Freizeitprogrammierer,  sondern eher die  der
`Professionellen'.


Der Lieferumfang und die Kondome (h, Konditionen)
--------------------------------------------------
Dieses Paket ist Public Domain,  d.h. es darf frei kopiert und benutzt
werden.  Der  Vertrieb  ber  einen PD-Versand ist  nur  mit  schrift-
licher(!)  Genehmigung meinerseits  mglich.  Zuwiderhandlungen  werde
ich strafrechtlich verfolgen.

Zu `Three Flights Up' gehren folgende Dateien:

     - 3FLIGHTS.TXT      Dieser Text
     - CHANGES.TXT       Die komplette Changes-Liste von Let 'em Fly!
     - MULTITOS.TXT      Bemerkungen  zu  Let 'em Fly!   und  MultiTOS
                         (Wichtig!)
     - FUTURE.TXT        Die Zukunft von Let 'em Fly!

     - LTMF_LIB.C        Eine Library fr C
     - LTMF_LIB.H        Dazu das Header-File
     - DO_SAMPL.C        Ein form_do() Sample

Das  Paket darf nur komplett mit diesen Dateien weitergegeben  werden!
Es  ist  erlaubt die *.C Dateien fr die  eigenenen  Anforderungen  zu
verndern.  Es  ist  jedoch NICHT erlaubt  diese  vernderten  Dateien
weiterzugeben.  Fr  Fehlerkorrekturen  habe ich natrlich  immer  ein
offenes Ohr.


                       First Flight (Internes)
                       =======================

Na, wo hngen wir denn berall drin?
------------------------------------
Let 'em  Fly!  verbiegt den TRAP #2 (AES/VDI) und den TRAP #13  (BIOS)
und  benutzt  dazu  die XBRA-Kennung  `LTMF'.  Unter  bestimmten  Vor-
raussetzungen verbiegt Let 'em Fly!  den etv_critic Vektor.  Ansonsten
wird noch ein Cookie-Jar installiert (s.u.).

Der Werdegang einer Dialogbox bei installiertem Let 'em Fly!
------------------------------------------------------------

Normalerweise  wird in einem Programm eine Dialogbox nach dem  folgen-
den Schema abgearbeitet:

     [...]

     form_center(dialog, &x, &y, &w, &h);
     form_dial(FMD_START, 0, 0, 0, 0, x, y, w, h);
     objc_draw(dialog, ROOT, MAX_DEPTH, x, y, w, h);
     choice = form_do(dialog, 0);
     form_dial(FMD_FINISH, 0, 0, 0, 0, x, y, w, h);

     [...]

Let 'em Fly!  hngt in allen eben benutzten Funktionen drin und mischt
mehr oder weniger krftig mit. Da dies die grundlegenden Funktionen im
Dialogbox-Handling  sind,  werden die Einflsse von  Let 'em Fly!  auf
diese Funktionen jetzt im einzelnen beschrieben:

form_center(dialog, ...)
------------------------
Hier  wird  der Dialog normalerweise  zentriert.  Bei  eingeschaltetem
`Save   Position'  werden  nur  die  Tree-Koordinaten  mit   Korrektur
zurckgegeben.  Ist  der  `VSCR-Support' aktiv,  so wird die  Box  von
Let 'em Fly! im gerade sichtbaren Ausschnitt zentriert.

form_dial(FMD_START, ...)
-------------------------
ber  diese Funktion sichert Let 'em Fly!  den  Dialogbox-Hintergrund.
Der bergebene Bereich sollte daher mglichst genau angegeben  werden.
Wird  eine  LTMF-Version  ab 1.14 benutzt,  so  kann  man  auch  einen
greren  Ausschnitt bergeben,  Let 'em Fly!  transformiert dann  bei
Bedarf die Koordinaten. `form_center()' liefert bei 'normalen' Dialog-
boxen richtige Ergebnisse,  Probleme gibt's z.B. bei SHADOWED Ones. Im
Zweifelsfall lieber ein bichen mehr angeben.
     Konnte  der Hintergrund nicht gesichert werden,  so wird die  UR-
Routine aufgerufen.

objc_draw(dialog, ...)
----------------------
Let 'em Fly! setzt hier nur einige interne Flags.

form_do(dialog, ...)
--------------------
Hier greift Let 'em Fly!  in die Vollen.  Zwei AES-Funktionen,  die in
form_do() benutzt werden (und form_do() selbst natrlich  auch),  wur-
den  komplett  neu programmiert und  ins  Betriebssystem  eingebunden:
`form_keybd()'  und  `objc_edit()'.   Bei  selbstgebauten   form_do()-
Routinen  sollte  man  daher Gebrauch  von  diesen  beiden  Funktionen
machen,  insbesondere  von objc_edit(),  da hier u.a.  der  Clipboard-
Support,  die History und die Special Character Box integriert wurden.
Auch  sollte  man  nicht zuviele Tastenkombinationen  vor  dem  Aufruf
herausfiltern.
     Innerhalb  von  `form_do()' wird dann u.a.  der  Objektbaum  nach
Tastenkombination durchgescannt.  Diese (rekursive) Funktion  arbeitet
wie folgt:
     Das  entsprechende  Objekt mu  entweder  SELECTABLE,  EXIT  oder
     TOUCHEXIT  sein  und darf nicht DISABLED oder  geHIDETREEd  sein.
     Ist  der  Parent geHIDETREEd,  so werden die  Children  ebenfalls
     nicht  durchsucht.  Jetzt wird geprft,  ob sich ein Text in  dem
     Objekt  befindet.  Falls  ja,  dann wird dieser Text  nach  einer
     freien  Tastenkombination abgesucht.  Falls  nicht,  dann  schaut
     Let 'em Fly!  nach,  ob das nchste Objekt in der Liste(!)  einen
     Text   enthlt  und  dieses  Objekt   nicht   SELECTABLE,   EXIT,
     TOUCHEXIT,  DISABLED oder geHIDETREEd ist.  Dieser Text wird dann
     zur  Zuweisung der Tastenkombination  benutzt.  Die  Y-Koordinate
     des Ersatzobjektes mu auf +/- 3 Pixel bereinstimmen.  Daher ist
     darauf  zu achten,  da die Dialogbox richtig sortiert  ist.  Der
     Text  des  `Abbruch'-Buttons  sollte mit  einem  der  oben  schon
     aufgefhrten bereinstimmen.  Zu beachten ist,  da es auch  eine
     HELP-Taste geben kann.  Weiterhin ist es ab Version 1.10  mglich
     die Tasten gezielt zu vergeben (s.u.).

Ebenso  wurden  in  `form_do()' das `Fly Delay'  (ab  V1.17)  und  die
direkte Cursor-Positionierung implementiert.
     Let 'em Fly!  lscht  ab  Version 1.17 vor dem  Eintritt  in  den
Event-Loop den Tastaturbuffer.  Die Let 'em Fly! Funktion ist brigens
sehr  kompatibel  zum Original,  da sie auf  den  (inzwischen  ffent-
lichen) D.R. form_do() Sourcen basiert.

form_dial(FMD_FINISH, ...)
--------------------------
Das ist das Gegenstck zu FMD_START. Hier wird dann der Bildschirmaus-
schnitt  wieder  korrekt hergestellt.  Konnte der  Hintergrund  vorher
nicht  gesichert  werden,  so  wird hier  ein  Redraw  ausgelst.  Die
Hauptapplikation wird somit aufgefordert den Bildschirmausschnitt wie-
der herzustellen.
     Die  FMD_STARTs und FINISHes sind gegen die untere (0) und  obere
(6) Grenze abgesichert.  Natrlich sollte man darauf achten, da es zu
jedem  FMD_START  auch  nur ein  entsprechendes  FMD_FINISH  (und  um-
gekehrt) gibt,  ansonsten kann man Let 'em Fly! durcheinander bringen.
Werden zuviele FINISHes aufgerufen,  so wird ein entsprechender Redraw
erzeugt (s.a. Third Flight).


Steuerung von Let 'em Fly! ber die Extended Objects
----------------------------------------------------

Ab  Version  1.10  werden  die  erweiterten  Objekttypen  benutzt,  um
Let 'em Fly!  innerhalb  von Dialogen `steuern' zu knnen.  Es  knnen
jetzt  so bei einigen Dialogen Funktionen abgeschaltet werden und  die
Tasten  gezielt  vergeben werden.  Der Extended Object Type  im  ROOT-
Objekt  mu ein Magic enthalten,  damit  Let 'em Fly!  wei,  da  die
restlichen  Werte des Dialogs gltig sind.  Damit  sollen  Kollisionen
mit fremden Dialogroutinen vermieden werden.
     ber  die Objekt-Flags 10 und 11 im ROOT-Objekt knnen  die  Key-
Dials  und der Extended Editor global (also fr diesen  Dialog)  abge-
schaltet  werden.  Das  Objekt-Flag  14 erzwingt  ein  Zentrieren  des
Dialogs  (interessant bei eingeschaltetem `Save Position').  ber  das
Objekt-Flag  12 kann ein Dialog flugunfhig gemacht  werden.  Das  ist
dann interessant,  wenn ein Programm mit den fliegenden Dialogen nicht
zurrechtkommt.
     Das  Objekt-Flag 15 wird brigens von Let 'em  Fly!  benutzt,  um
einen  bereits zentrierten Dialog zu markieren.  Dies  ist  unabhngig
vom Magic und kann nur durch den Schalter `Save Position'  unterdrckt
werden.
     Fr  die  restlichen Objekte im Dialog wird das  Extended  Object
Byte  dazu  benutzt  um Tasten gezielt  zu  vergeben.  Es  wird  dabei
zwischen normalen Tasten (A-Z,  0-9) und Sondertasten (HELP, UNDO, F1-
F10)  unterschieden.  Weiterhin  kann man bestimmen,  ob  das  nchste
Objekt fr die Tastenvergabe benutzt werden soll.
     Die  Objekt-Flags  10 und 11 haben die gleiche Bedeutung  wie  im
ROOT-Objekt, sind jedoch nur lokal wirksam.

So,  und hier die genaue Belegung der Bits and Bytes (die Flags werden
von 0, entspricht Bit 0, ab an gezhlt!):

ROOT-Objekt
-----------
- Extended Object Byte (erweiterter Objekttyp)
     MAGIC 0x89 (137)    Sagt Let 'em Fly!,  da die restlichen  Werte
                         im Dialog gltig sind.
     GLOBOFF 0x71 (113)  Hiermit wird Let 'em Fly!  fr diesen  Dialog
                         komplett(!)  ausgeschaltet.  Das Byte  stimmt
                         mit dem in FormDoIt! benutzten berein.

- Objekt-Flags
     Flag 11   Schaltet die Key Dials global aus.
     Flag 12   Macht den Dialog flug_un_fhig.
     Flag 13   Rastet  den  Dialog  nach dem Fliegen  wieder  auf  das
               ursprngliche Byte-Alignment ein.
     Flag 14   Erzwingt  ein Zentrieren des Dialogs (entspricht  `Save
               Position' OFF).

restliche Objekte
-----------------
- Extended Object Byte (erweiterter Objekttyp)
     Das  Byte wird in zwei Nibbles ( 4 Bit)  unterteilt.  Das  obere
     Nibble konfiguriert das untere Nibble.  Eine kleine Grafik drfte
     hier hilfreich sein:

     +---+---+---+---+----------------+
     | E | F | S | T | Key Identifier |
     +---+---+---+---+----------------+
       ^   ^   ^   ^   ^
       |   |   |   |   +----  Identifiziert  die  Taste.   Ist  dieses
       |   |   |   |          Nibble nicht gesetzt,  also gleich Null,
       |   |   |   |          so vergibt Let 'em Fly!  die Taste  nach
       |   |   |   |          dem  herkmmlichen  Verfahren.   Besitzt
       |   |   |   |          dieses Nibble einen Wert (1-15), so wird
       |   |   |   |          damit die Position(!) der Taste im  Text
       |   |   |   |          angegeben.  Vorsicht: Der Zhler beginnt
       |   |   |   |          mit  1 (also nicht mit 0)  und  fhrende
       |   |   |   |          Spaces werden mitgezhlt!
       |   |   |   |
       |   |   |   +--------  Zeigt  an,  da das nchste  Objekt  zur
       |   |   |              Tastenvergabe  benutzt werden  soll.  Es
       |   |   |              mu kein Key Identifier verhanden  sein.
       |   |   |              In  diesem Fall sucht sich  Let 'em Fly!
       |   |   |              die Taste selbst aus.
       |   |   |
       |   |   +------------  Dieses Bit sagt,  da dieses Objekt  mit
       |   |                  einer  Sondertaste belegt  werden  soll.
       |   |                  Der   Key  Identifier  mu  dann   einen
       |   |                  gltigen Wert haben:
       |   |                        1 - UNDO
       |   |                        2 - HELP
       |   |                        3 - F1
       |   |                         [...]
       |   |                       12 - F10
       |   |                  Weiterhin wird das Objekt noch nach  dem
       |   |                  Let 'em Fly! Algorithmus mit einer Taste
       |   |                  belegt.   Man  kann  es  aber  ber  das
       |   |                  ObFlag 12 unterdrcken.
       |   |
       |   +----------------  ber  dieses  Bit  wird  das  Flugobjekt
       |                      festgelegt. Eine Kombination mit den an-
       |                      deren  beiden Bits ist  nicht  sinnvoll.
       |                      Das untere Nibble (Key Identifier)  sagt
       |                      dann   aus,   ob  das   Flugobjekt   Ex-
       |                      clusivrechte besitzt (d.h.  es kann  nur
       |                      ber  dieses Objekt  `geflogen'  werden)
       |                      oder nicht. Dabei gilt:
       |                           0 -  Exclusiv
       |                           1 -  Inclusiv (d.h.  Background und
       |                                Flugobjekt).
       |                           2 -  sinnlos
       |                           3 -  Inclusiv,   jedoch  wird   das
       |                                Objekt unter keinen  Umstnden
       |                                von Let 'em Fly! gelscht.
       |
       +--------------------  Zeigt  an,  da bei diesem  Objekt  eine
                              sog.  EXAPPLBLK-Struktur benutzt  wurde.
                              Die  Struktur  wird  weiter  unten   be-
                              schrieben.

     Zu   beachten   ist,   da  auch   weiterhin   die   automatische
     Tastenvergabe aktiv ist.  Wird UNDO ber die ExObTypes  vergeben,
     so ist es gegen eine weitere automatische Vergabe geschtzt.  Bei
     HELP ist dies nicht der Fall!

     Special ab V1.17:   Ab  dieser  Version wird auch  das  FormDoIt!
                         Byte  (0x71  /  113)  zur  Unterdrckung  der
                         Tastenvergabe   fr  das   jeweilige   Objekt
                         untersttzt.  Da dieser Wert eh sinnlos  ist,
                         gibt es daher auch keine Kollisionen.

- Objekt-Flags
     Flag 11   Schaltet  die Key Dials fr dieses Objekt  (und  dessen
               Unterobjekte!) aus.
     Flag 12   Wird  eine  Taste mit  einer  Sondertaste  (z.B.  UNDO)
               belegt,   so   wurde  trotzdem  noch   eine   `normale'
               Tastenkmbination  dafr  herausgesucht.   Durch  setzen
               dieses Flags kann man es (erfolgreich) verhindern.

Vorsicht: Fr   Kollisionen  bei  der  Tastenvergabe  ist   der   Pro-
          grammierer,  bzw.  der Vernderer des RSC-Files selbst  ver-
          antwortlich!


Natrlich kann man auch `fremde' RSC-Files modifizieren, jedoch sollte
man hier sehr vorsichtig sein.  Vielleicht werden die Bits ja auch vom
Programm selbst benutzt und verndert.
     Weiterhin  ist es selbstverstndlich,  da  vernderte  RSC-Files
grundstzlich NICHT weitergegeben werden drfen!!!  Falls ich  solchen
Fllen  auf  die  Spur  kommen  sollte,   so  bekommt  derjenige   er-
heblichen(!) rger von mir!

Abhngigkeiten zwischen Schalter, ob_flags und Funktionen
---------------------------------------------------------

     Function       | Switch            | ob_flags (only with MAGIC)
     ---------------+-------------------+---------------------------
     form_do()      | Let 'em Fly ON/OFF| ExObType Value 0x71 (113)
                    | Key Dials         | Flag 11 / ExObType 0x71
     form_dial()    | Flying ON/OFF     | Flag 12 (ROOT-only)
                    | Grow/Shrink       | ---
                    | Send Redraw       | ---
     form_center()  | Save Position     | Flag 14
                    | VSCR Support      | no flag available yet
     form_alert()   | Alert/Error-Boxes | ---
     form_error()   | Alert/Error-Boxes | ---
     form_keybd()   | Extended Editor   | ---
     objc_edit()    | Extended Editor   | ---
     appl_exit()    | - no switch -     | ---
     ---------------+-------------------+---------------------------
     di_fly()       | Flying ON/OFF     | Flag 12 (ROOT-only)
                    | Solid/Hollow Fl.  | ---


Die EXAPPLBLK-Struktur
----------------------
Um Benutzerdefinierte Objekte ins Resource einzubinden,  mu man  eine
spezielle Struktur benutzen (USERBLK),  die weitere Informationen  fr
das AES enthlt.  Die EXAPPLBLK-Struktur ist eine erweiterte  USERBLK-
Struktur und sieht wie folgt aus:

typedef struct
{
        int cdecl        (*ub_code)(struct __parmblk *parmblock);
        union obspecptr  *ub_spec;       /* old ob_spec */
        int              ub_type;        /* old ob_type */
} EXAPPLBLK;

`ub_code' ist der Zeiger auf die Funktion zum Malen des Objekts,
`ub_spec' ist ein Zeiger auf den alten ObSpec und
`ub_type' der alte Objekt-Typ (der neue mu ja G_USERDEF sein).

Fr weitere Informationen zu benutzerdefinierten Objekten verweise ich
an dieser Stelle auf das neue Profibuch.

ber diese Struktur kann Let 'em Fly!  nun auch bei entsprechenden be-
nutzerdefinierten Objekten Tasten vergeben.

Ich  nutze jetzt die Mglichkeit um hier auf eine Library  von  Markus
Nick aufmerksam machen.  Sie heit `Ruby' und ermglicht es Flugecken,
runde Radio-Buttons und Check-Boxen in ein Resource  einzubinden.  Die
Flugfhigkeit und die Tastenvergabe bernimmt Let 'em Fly!.  Somit ist
nur  der Let 'em Fly!-unabhngige Teil im eigentlichen  Programm  ent-
halten,  was sich natrlich auf die Gre positiv auswirkt.  Weiterhin
ist  das  Format  in  den  Grundelementen  kompatibel  zu  denen   der
Fly/My/MagicDials,  d.h.  sptere Library-Wechsel sind relativ einfach
zu bewerkstelligen.
     `Ruby'  sollte  inzwischen  in jeder gut  sortierten  Mailbox  zu
finden  sein.  Ebenso kann diese Library auch ber einen  adressierten
und frankierten Rckumschlag bei mir oder beim Markus bezogen werden.


                      Second Flight (The Cookie)
                      ==========================

Let 'em Fly!  installiert einen Cookie mit der Kennung `LTMF', welcher
auf die folgende Struktur zeigt:


typedef struct
{
        unsigned int    version;        /* Version im BCD-Format*/
        struct
        {
                unsigned light  : 1;    /* light version (read) */
                unsigned niceln : 1;    /* niceline             */
                unsigned jumpin : 1;    /* jumpin' dials        */
                unsigned flyswi : 1;    /* conf. flymode switch */
                unsigned vscr   : 1;    /* virtual scr. support */
                unsigned center : 1;    /* center mode          */
                unsigned keys   : 1;    /* key handling         */
                unsigned edit   : 1;    /* extended editor      */
                unsigned redraw : 1;    /* send redraw message  */
                unsigned flytyp : 1;    /* solid/hollow fly     */
                unsigned fly    : 1;    /* flying on/off        */
                unsigned alert  : 1;    /* Alerts/Errors on/off */
                unsigned mouse  : 1;    /* dials to mouse       */
                unsigned f_grow : 1;    /* grow/shrink boxes    */
                unsigned g_grow : 1;
                unsigned bypass : 1;    /* ON/OFF highest prio  */
        } config;
        int     conf2;                  /* reserved             */
        int     reserved;               /* reserved             */
        void    cdecl   (*di_fly)(OBJECT *tree);
        void    cdecl   (*obj_clsize)(OBJECT *tree, int obj,
                                    int *x, int *y, int *w, int *h);
        int     cdecl   (*do_key)(int key, int kshift);
        int     cdecl   (*init_keys)(OBJECT *tree);
        int     cdecl   (*lookup_key)(int key, int kshift);
        int     cdecl   (*di_moveto)(OBJECT *tree, int mx, int my);
        int     cdecl   (*di_center)(OBJECT *tree);
        int     ucol;   /* underscore color     */
        int     aicol;  /* alert icon color     */
        int     aframe; /* alert frame size     */
        int     flydelay; /* delay before flying (form_do()-only) */
        int     cdecl   (*hist_insert)(char *string);
        char    cdecl   (*ins_spcchar)(void);
        void    cdecl   (*init_niceline)(OBJECT *tree);
} LTMFLY;


Die  Variablen  und  Funktionen  werden  jetzt  ab  hier  genauer  be-
schrieben.  Dabei  steht  die Zahl in der Klammer fr  den  Zeitpunkts
(Version)  des  Einzugs in Let 'em Fly!.  Will man  auf  entsprechende
Teile zugreifen,  so mu man vorher die Version prfen, ansonsten kann
es zu berraschungseffekten kommen.  Ausnahme: Die Version ist kleiner
oder gleich 1.02. Das ist nmlich die erste offizielle Release.

1.) Die Variablen (bzw. Konstanten)
-----------------------------------

version
-------
Hier  ist  die Version von Let 'em Fly!  im  BCD-Format  (0x0114  ent-
spricht 1.14) zu finden.

light (1.00)
------------
Zeigt  an  welche Version geladen wurde (light  oder  normal).  Dieses
Flag darf nicht verndert werden!

niceln (1.18)
-------------
Konfiguriert das in Let 'em Fly! integrierte Niceline.

jumpin (1.15)
-------------
Schaltet die Jumpin' Dials ein.

flyswi (1.13)
-------------
Ist  dieses  Flag  gesetzt,  so  wird die  rechte  Maustaste  fr  den
Flugmodus (Ghost-Flights) umgeschaltet bzw. invertiert.

vscr (1.10)
-----------
Zeigt an, ob der VSCR-Cookie ausgewertet und benutzt werden soll.

center (1.03)
-------------
Bestimmt  den Center-Mode.  Dabei gilt 1 fr nicht centern und  0  fr
centern.

keys (1.00)
-----------
Schaltet die Key Dials ein.

edit (1.00)
-----------
ber dieses Flag wird der Extended Editor eingeschaltet.

redraw (1.02)
-------------
Zeigt  an,  ob  nach  dem Lschen der Dialogbox  ein  Redraw  gesendet
werden soll.

flytyp (1.00)
-------------
Bestimmt den Flugmodus (0: Solid, 1: Hollow).

fly (1.00)
----------
Schaltet die fliegenden Dialoge aus.

alert (1.00)
------------
Konfiguriert die neuen Alert-Boxen.

mouse
-----
Zentriert die Dialoge an der Mausposition.

f_grow (1.00)
-------------
Ist dieses Flag gelscht,  so werden die FMD_GROW/SHRINK-Aufrufe igno-
riert.

g_grow (1.00)
-------------
Genauso  wie  `f_grow',  jedoch  gilt die  ganze  Geschichte  fr  die
graf_grow/shrinkbox()-Aufrufe.

bypass (1.00)
-------------
Hier  ist  das  Master-Flag.  Ist es  gesetzt,  so  wird  Let 'em Fly!
deaktiviert.


ucol (1.13)
-----------
Bestimmt die Farbe und die Form der Underscores.  Ist Bit 0 vom oberen
Byte  gesetzt,  so  werden  anstelle der  Underscores  die  Buchstaben
eingefrbt (natrlich ohne dabei zu tropfen).

aicol (1.13)
------------
Reprsentiert die Farbe der Alert-Icons.

aframe (1.13)
-------------
Bistimmt die Rahmendicke der Alert-Boxen.

flydelay (1.15)
---------------
Gibt  die  Zeit  (ohne  Einheit im  Bereich  von  0-10)  zwischen  dem
Mausklick und dem Flug an.

2.) Die Funktionen
------------------

Let 'em Fly!  stellt  auch  einige Funktionen  zur  Verfgung,  welche
besonders fr eigene form_do()-Routinen ntzlich sein knnten.  Um die
Funktionen  zu benutzen sollte man das Bindings `LTMF_LIB'  verwenden,
da  hier  u.a.  auch die  unterschiedlichen  Versionen  bercksichtigt
werden.  Die jetzt folgende Beschreibung bezieht sich auf das Binding.
Weiterhin verweise ich auch auf das form_do()-Beispiel, welches einige
Let 'em Fly! Funktionen benutzt.

int di_fly(OBJECT *tree) (1.00)
-------------------------------
ber diese Funktion kann man Dialoge fliegen lassen.  Der  Bildschirm-
ausschnitt mu vorher mit FMD_START korrekt gesichert worden sein. Die
genaue Verwendung ist aus dem form_do()-Sample zu entnehmen.

int di_moveto(OBJECT *tree, int x, int y) (1.15)
------------------------------------------------
Diese  Funktion  wird  von den Jumpin' Dials  benutzt.  Sie  lt  den
Dialog (maus)zentriert an die angugebende Position springen.
ber diese Funktion kann man jetzt auch testen ob ein Dialog flugfhig
ist bzw.  ob der Hintergrund gesichert werden konnte.  Dazu wurden  in
LTMF_LIB.H zwei Macros definiert.

int di_center(OBJECT *tree) (1.17)
----------------------------------
Hiermit kann ein Dialog re-centered werden.

int obj_clsize(OBJECT *tree, int obj, int *x, *y, *w, *h) (1.10)
----------------------------------------------------------------
Diese  Funktion berechnet die wahren Ausmae eines  Objekts.  Es  wird
auch  der  SHADOWED-Status korrekt behandelt.  Eigentlich  sollte  sie
fester Bestandteil des AES sein.

int init_keys(OBJECT *tree) (1.13)
----------------------------------
Benutzt  man eine eigene form_do()-Routine,  will aber trotzdem  nicht
auf  die  Tastaturbedienbarkeit verzichten,  so kann  man  mit  dieser
Funktion  die Tastenvergabe von Let 'em Fly!  aufrufen.  Dabei  werden
dann auch die Strichlein gemalt, d.h. sie darf erst aufgerufen werden,
wenn sich der Dialog auf dem Bildschirm befindet.

int lookup_key(int key, int kbshift) (1.13)
-------------------------------------------
Hat  man  vorher  init_keys()  aufgerufen und  einen  Wert  !=  0  zu-
rckbekommen,  dann kann man die eingehenden Keyboard-Events von  die-
ser Funktion checken lassen,  um zu gucken,  ob ein Objekt ber  einen
Shortcut  angewhlt  wurde.  Diese Funktion mu VOR  form_keybd()  und
objc_edit() aufgerufen werden!

int set_do_key(void (*key_handler)()) (1.12)
--------------------------------------------
Oft  ist  es so,  da man eigene Tasten  mit  einbinden  mchte,  aber
denoch  nicht  auf  den Let 'em Fly!  Support  verzichten  zu  wollen.
Let 'em Fly!  erlaubt  es daher einen benutzerdefinierten  Key-Handler
zu  installieren (do_key() im Cookie).  Hier erstmal ein kleines  Bei-
spiel:


[...]

#include <ltmf_lib.h>

[...]

int cdecl my_keys(int key, int kshift)
{
     printf("%04x %04x\n\r", key, kshift);
     return(0);
}

[...]

int do_dialog(OBJECT *tree)
{
     int  what;

     draw_dialog(tree);
     set_do_key(my_keys);          /* Routine einklinken */
     what = form_do(tree, 0);
     set_do_key(0l);               /* und wieder ausklinken. */
     undraw_dialog(tree);
     return(what);
}

[...]

Dieses kleine Beispielprogramm macht nichts anderes,  als einen Dialog
darzustellen und abzuarbeiten,  jedoch werden die Tastendrcke  inner-
halb von form_do() mit printf() auf dem Bildschirm ausgegeben.

Die Funktion zur Tastenbearbeitung mu folgenden Regeln folgen:

int cdecl do_key(int key, int kshift);

Eingabe:  key       Enthlt  den  Tastencode.  Er stimmt mit  dem  von
                    evnt_keybd() zurckgegebenen  berein,  d.h.  Bits
                    0..7  enthalten den ASCII-Code und Bits 8..15  den
                    Scancode.
          kshift    Enthlt  den Shiftstatus,  der  von  evnt_button()
                    geliefert wurde.

Return:   0         Taste  konnte  nicht  verarbeitet   werden,   bzw.
                    Let 'em Fly!  sieht  den Tastencode als gltig  an
                    und versucht ihn selbst zu verarbeiten.
          1         Taste  konnte  verarbeitet  werden.   Let 'em Fly!
                    ignoriert die Taste nun.
          2         Wie  `1',   jedoch  wird  der  Dialog   zustzlich
                    abgebrochen  und als Ergebnis (bei form_do())  `0'
                    zurckgeliefert.

Wird innerhalb dieser Routinen ein Dialog dargestellt,  so wird dieser
nicht   von  Let 'em Fly!   untersttzt,   da  der  TRAP-Handler   von
Let 'em Fly! nicht reentrant ist.

Weiterhin mu der Programmierer dafr Sorge tragen, da der Funktions-
Pointer  nach Beendigung des Dialogs auf `0L' zurckgesetzt  wird.  Es
knnten  sonst berraschende Effekte  (z.B.  Bomben)  auftreten.  Aus-
nahme:  Man  will nur mal kurz eine Alert-Box  darstellen.  In  diesem
Fall wird die neue Tastenroutine von Let 'em Fly! nicht aufgerufen.

int ins_spcchar(void) (1.15)
----------------------------
Let 'em Fly!  besitzt ab Version 1.15 eine Box, in der man die `blen'
Zeichen  eingeben kann.  Diese Box kann man ber diese Funktion  nicht
nur innerhalb, sondern auch auerhalb von Dialogen benutzen.

int hist_insert(char *string) (1.16)
------------------------------------
Manchmal  ist es sinnvoll Strings manuell in die  Let 'em Fly!-History
einzufgen. Diese Funktion macht den Weg frei ...

int init_niceline(OBJECT *tree) (1.18)
--------------------------------------
Mit dieser Funktion kann man `zu Fu' die Niceline fr einen  Menbaum
installieren.  Bei diesem Menbaum kann es sich auch um ein Popup-Men
handeln.  Beim  Aufruf  dieser Funktion  werden  alle  G_STRINGs,  die
DISABLED sind und `---' enthalten durch die Nicelines ersetzt.

int init_flyobj(OBJECT *tree)
-----------------------------
Let 'em Fly!  untersttzt ab Version 1.17 explizit  sog.  Flugobjekte.
Diese  Objekte  werden  mit bestimmten  Eigenschaften  versehen  (s.a.
ExObTypes).  Kann ein Dialog nicht fliegen (z.B. Speicherplatzmangel),
so  wird  dieses Objekt gelscht.  Da sich die  Flugecke  von  Julians
FlyDials  irgendwie eingebrgert hat,  kann man ber diese  (externe!)
Funktion  eine eben solche installieren.  Das zu  verwandelnde  Objekt
mu  natrlich die richtige Kennung und vernnftige Ausmae  besitzen.
Am  besten ist es,  wenn man eine G_BOX mit  OUTLINED-Status  benutzt.
Diese  Funktion wird z.B.  von Selectric,  Take-Off 2 und der  Fuzzy-
Clock ab Version 1.06 benutzt.
Bemerkung: Es wird hier natrlich ein USERDEF installiert. Um auch mit
Accessories  und  TSRs (Terminate & Stay Resident)  ohne  Probleme  zu
funktionieren,  wird die Workstation vom AES benutzt.  Die  Attribute,
die verndert werden, werden natrlich gesichert.


              Third Flight (Tips & Tricks & Guidelines)
              =========================================

Das mit dem Redraw einzelner Objekte ...
----------------------------------------
...  machen  viele  noch falsch.  Wird ein Dialog  durch  Let 'em Fly!
flugfhig,  so  kann sich ja die Position der Box und somit  auch  der
einzelnen  Objekte  ndern.  Da objc_draw() und  objc_change()  jedoch
Clipping-Koordinaten  bentigen,  mssen diese vor *JEDEM* Aufruf  neu
berechnet  werden.   Viele  benutzen  nur  die,   die  am  Anfang  von
form_center()  zurckgeliefert wurden,  was natrlich zu Problemen  in
der  Bidlschirmdarstellung fhrt.  Das TOS bercksichtigt es ja  auch,
sonst  wrde Let 'em Fly!  berhaupt nicht  funktionieren.  Um  diesen
Mistand  zu  beheben,  folgen nun entsprechende  Funktionen,  die  a)
komfortabel  und b) Let 'em Fly!-fest sind.  Sie sollten  sich  selbst
erklren ...

----- cut here ------------------------------------------------------

/* ---------------------------------------------------------------- */
/*   Berechne die _absoluten_ Koordinaten eines Objekts             */
/* ---------------------------------------------------------------- */

void obj_xywh(OBJECT *tree, int obj, GRECT *p)
{
        objc_offset(tree, obj, &p->g_x, &p->g_y);
        p->g_w = tree[obj].ob_width;
        p->g_h = tree[obj].ob_height;
}

/* ---------------------------------------------------------------- */
/*   Redraw eines einzelnen Objekts unter Bercksichtigung der      */
/*   _aktuellen_ Position.                                          */
/* ---------------------------------------------------------------- */

void obj_update(OBJECT *tree, int obj)
{
        GRECT   p;

        obj_xywh(tree, obj, &p);
        objc_draw(tree, obj, MAX_DEPTH, p.g_x, p.g_y, p.g_w, p.g_h);
}

/* ---------------------------------------------------------------- */
/*   Objekt-Status eines Objekts verndern. Dabei gilt ~STATUS fr  */
/*   Status lschen.                                                */
/* ---------------------------------------------------------------- */

void obj_stchange(OBJECT *tree, int obj, int state, int update)
{
        if(state < 0)
                tree[obj].ob_state &= state;
        else
                tree[obj].ob_state |= state;
        if(update)
                obj_update(tree, obj);
}

/* ---------------------------------------------------------------- */
/*   Objekt-Flags eines Objekts verndern. Dabei gilt ~FLAG fr     */
/*   Flag lschen.                                                  */
/* ---------------------------------------------------------------- */

void obj_flchange(OBJECT *tree, int obj, int flag, int update)
{
        if(flag < 0)
                tree[obj].ob_flags &= flag;
        else
                tree[obj].ob_flags |= flag;
        if(update)
                obj_update(tree, obj);
}

----- cut here again ------------------------------------------------

Bei  den  beiden letzten Funktionen ist zu  beachten,  da  diese  nur
Flags/Stati  bis  zur  Nummer  14  korrekt  behandeln,  da  sonst  ein
Vorzeichenfehler auftritt.  Fr den normalen Hausgebrauch reichen  sie
aber vllig aus.
Nochwas:  Wenn  man mit VDI-Funktionen in die Box malt  (z.B.  Edison-
Utilities),   dann  mu  man  ebenfalls  vorher  ein  obj_xywh()  bzw.
objc_offset()  aufrufen,  um den Offset und das Clipping-Rectangle  zu
erhalten!

Senden von Redraws
------------------
In  manchen  Situationen mu man sich selbst  (also  der  Applikation)
einen Redraw senden,  um z.B.  einen Desktop-Redraw auszulsen. Hierzu
gibt es zwei Verfahren: 1.) Das Senden einer Message ber appl_write()
und   2.)  ein  form_dial(FMD_FINISH, ...)  mit   den   entsprechenden
Koordinaten (dabei vorher *KEIN* form_dial(FMD_START, ...) machen,  da
es  a) nicht notwendig und vllig berflssig ist und b)  Let 'em Fly!
Versionen  vor  1.18  in diesem  Fall  keinen  Redraw  senden).  Beide
Mglichkeiten sind von Atari offiziell dokumentiert.

Redrawunterdrckung beim Lschen von Info-`Dialogen'
----------------------------------------------------
Will  man nur mal eine Dialogbox auf den Bildschirm zaubern,  um  eine
kleine Info anzuzeigen (z.B.  `Sortiere ...'),  ohne da eine  Eingabe
vom Benutzer erwartet wird,  so wird von Let 'em Fly! immer ein Redraw
beim Lschen der Box gesendet,  da einige Programme das  brauchen.  Da
hilft auch das Abschalten von `Send Redraw' alleine nichts.  Dies  ist
dann hinderlich,  wenn man Let 'em Fly!  das Buffern des Hintergrundes
berlassen will.  Man kann es aber unterdrcken, indem man (zustzlich
zum   vorrbergehenden   Abschalten  von  `Send  Redraw'!)   vor   dem
FMD_FINISH  ein Dummy-objc_find() macht.  Der Aufruf sieht  wie  folgt
aus:

          objc_find(tree, ROOT, MAX_DEPTH, 0, 0);


Tastenvergabe in nicht-modalen Dialogen (die in den Fenstern)
-------------------------------------------------------------
Vergibt  man bei diesen Dialogen die Tasten ber init_keys(),  so  ist
darauf  zu achten,  da sich der Dialog im obersten Fenster  befindet.
Ansonsten sollte man auf einen Aufruf bei einem Redraw verzichten,  da
es in diesem Fall zu Bildschirmmll kommt.

Das Sortieren der Objekte
-------------------------
Damit  sinnvolle Ergebnisse bei der Verwendung von Ersatzobjekten  bei
der Tastenvergabe entstehen,  mssen die Objekte auch richtig sortiert
sein.  Am  besten ist es,  wenn man den ganzen Dialog von  links  nach
rechts und von oben nach unten sortiert.

Umlaute als Shortcuts
---------------------
Damit Let 'em Fly! international bleibt, ohne enormen Aufwand dafr zu
treiben,  kann  man  *keine* Umlaute und Sonderzeichen  als  Shortcuts
mibrauchen.

Schnere Buttons
----------------
Da Let 'em Fly!  unter die Buchstaben seine Striche malt, stoen diese
in  der  Regel am Boxrand an,  was natrlich nicht  unbedingt  optimal
aussieht.  Daher empfehle ich die Boxen,  welche nur ein Zeichen  hoch
sind,  um  2  Pixel  in Y-Richtung zu  vergrern  (siehe  FuzzyClock,
Selectric, Take-Off 2, LET_CONF).

Der Aufbau der RSCs fr die Icons der Alertboxen
------------------------------------------------
Let 'em Fly!  erwartet  in  der Datei LET_ICON.RSC seine Icons  welche
sinnvollerweise  in  einer  G_BOX abgelegt  sein  sollten.  Die  Icons
mssen von links nach rechts sortiert sein,  da sonst die  Zuweisungen
nicht stimmen.  Die Gre der Icons betrgt 32x32 Pixel. Zum Editieren
wird ein Resource-Construction-Set und u.U. ein Icon-Editor bentigt.
     Ab  Version  1.17 knnen eine variable Anzahl von  Icons  ersetzt
werden,  jedoch  nicht individuell,  sondern nur  zusammenhngend  be-
ginnend mit dem ersten Icon.
     Die  ersten  drei Icons sind fr die  Alertboxen  gedacht  (siehe
auch  mitgelieferte  Icons).  Die restlichen drei Icons sind  fr  die
Event-Critic  Boxen.  Dabei reprsentiert das erste einen  allgemeinen
Diskettenfehler,  das  zweite eine schreibgeschtzte Diskette und  das
dritte eine zu wechselnde Diskette.


                              Nachschlag
                              ==========

Hmm,  ich wei garnicht was ich hier schreiben soll. Na auf jeden Fall
bedanke  ich  mich mal an dieser Stelle fr die  vielen  Hinweise  und
Problemanfragen  einiger Programmierer,  die somit `Three Flights  Up'
zu  dieser  Form verholfen haben (und natrlich auch  bei  denen,  die
dazu   beigetragen  haben,   da  die   Programmierschnittstelle   in-
zwischen  diesen Umfang erreicht hat).  Falls noch  irgendwelche  Ver-
besserungsvorschlge etc. da sind, hier ...


meine Adresse ...

Oliver Scheel
Rothehausstr. 28
W-5000 Kln 30 (ab 1.7. 50823 Kln)

MausNet:  Oliver Scheel @ K2
InterNet: Oliver_Scheel@k2.maus.de

WICHTIG:  Meine  Adresse  kann  sich zum  September  '93  hin  ndern!
Nheres ist dann der Zeitschrift ST-Magazin zu entnehmen.


Let 'em Fly!     Man fliegt nicht mehr ohne ...




----
Rchzschreipfler (c) 1991-92 by Oliver Scheel
