
Programmierschnittstelle fr MultiDialog           Modifizierbarer
Erster Entwurf vom 21.12.1993                      Fensterdialog-Treiber
                                                   von Helmut Neukirchen
                               e-mail: hn@pool.informatik.rwth-aachen.de


            Hierbei handelt es sich nur um einen Entwurf auf dem Papier,
                              die endgltige Spezifikation wird sich mit
                                   hoher Wahrscheinlichkeit noch ndern!
                      Bisher ist noch nichts davon implementiert worden.
                        Ebenso fehlen noch Library- und Include-Dateien.


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Vorab

               Allen Programmierern, denen die derzeitige Zusammenarbeit
                    mit dem residenten Fensterdialog-Treiber MultiDialog 
                          (im folgenden MD genannt) zu unflexibel und zu 
                         Speicherintensiv ist, sollte durch die folgende 
                                 Programmierschnittstelle geholfen sein!

Es ist vorgesehen, die Aufrufe ber selbstdefinierte AES-calls
durchzufhren. Dazu sollen die Nummern 240-249 verwendet werden.
Mir ist natrlich klar, da es ein Risiko bedeutet, neue
AES-calls einzurichten, aber es gibt mehrere Grnde, die mich
zu diesem Entschlu fhrten:
1. Passen die Aufrufe von der Funktion her in die AES.
2. MD bentigt den AESPB der aufrufenden Applikation; fr
   beide Seiten drfte hier ein AES-call am bequemsten sein.
3. Ich mu lediglich den Trap #2-Dispatcher von MD erweitern.
4. Hat mir Eric Smith zwar nicht versichern knnen, da die
   Nummern 240-249 nicht fr andere Zwecke verwendet werden, 
   allerdings hlt er es fr unwahrscheinlich.
5. Haben gerade MiNT und NVDI gezeigt, da es sinnvoll sein kann,
   das TOS um neue Aufrufe zu erweitern.

Sollten trotz alledem Bedenken vorliegen, weil z.B. die Calls
bereits anderweitig belegt sind, oder jemand bessere Ideen hat,
so mge man mir das mitteilen.


Nun jedoch in medias res:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Philosophie

Ziel beim Entwurf der Programmierschnittstelle war es, das gewohnte
Dialog-Handling beizubehalten, damit bei nicht aktiviertem MultiDialog
keine vllig anderen Routinen zum Einsatz kommen mssen. 
D.h. die eigentliche Dialogbehandlung wird weiterhin ber

form_center(dialog,size_x,size_y,size_w,size_h)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)  /* wird neuerdings gefordert */
form_dial(FMD_START, size_x, size_y, size_w, size_h, 
                     size_x, size_y, size_w, size_h)
objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h)

rc=form_do(dialog,ROOT)

form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
                      size_x, size_y, size_w, size_h)
wind_update(END_MCTRL)  /* wird neuerdings gefordert */
wind_update(END_UPDATE)

durchgefhrt.

Zustzlich gibt es dann aber Aufrufe, um eigene Redraw-Handler
Fenstertitel, etc. zu setzen, die dann vor Beginn der Dialog-
Behandlung aufgerufen werden mssen. Hierbei kommen teilweise
sogenannte Callback-Routinen zum Einsatz (s.u.).

Abweichend vom Prinzip, die originale form_do-Routine aufzurufen,
gibt es auerdem eine erweiterte form_do-Routine, die z.B.
nicht-modale Dialoge (d.h. Fenster-Dialoge, auf die eine Applikation
nicht warten mu) ermglicht. Programmiersprachen, die keine
Callback-Routinen ermglichen (z.B. BASIC), sind ebenfalls auf
diesen Aufruf angewiesen (hierbei mu man dann allerdings bei
nicht aktiviertem MD auf ein anderes Dialoghandling ausweichen). 

Fr die Programmierschnittstelle existieren folgende Aufrufe, die 
mglichst in Anlehnung an die bestehenden AES wind_xxxxxx-Aufrufe 
gehalten wurden:


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Neue Aufrufe

Die Funktionen drfen nur aufgerufen werden, wenn ber den MDIA-Cookie
und das Fhigkeiten-Wort festgestellt wurde, da ein MultiDialog
installiert ist, das eine Programmierschnittstelle besitzt.

int md_installed(); /* 0: MultiDialog nicht installiert; sonst: Installiert */
int mdprog_available(); /* 0: Programmierschnittstelle nicht vorhanden,
                           sonst: Vorhanden */
(Dieser Aufruf ist kein AES-Aufruf, sondern bedient sich des MD-Cookies.
Beispiel-Algorithmus hierfr wird nachgereicht!)

Der Rckgabewert der Funktionen ist bei den kritischen Aufrufen
unbedingt zu beachten. In vielen Fllen sind die Funktionen nur fr 
bereits geffnete Dialogfenster oder aktiviertes MultiDialog definiert!



int mdial_create(void *md_credraw, int md_cresvd1, int md_cresvd2)

 Bereitet modifizierbaren Dialog vor und liefert dazu ein
 Dialoghandle zurck.
 Wenn MultiDialog installiert und nicht abgeschaltet ist, wird dieser 
 Aufruf unabhngig von evtl. Benutzer-Einstellungen so interpretiert,
 da ein Dialog-Fenster bei FormDo geffnet werden soll! (Was allerdings
 nicht heit, da die weiteren Aufrufe alle erfolgreich sind.)

 Ergebnis: <0: Fehler (z.B. MultiDialog abgeschaltet), >0: Dialoghandle

 md_credraw: 0: Bildschirm puffern; !=0: Bildschirm nicht puffern,
 md_credraw als Zeiger auf Callback-Redraw-Routine

 md_cresvd1, md_cresvd2: reserviert, auf 0 setzen!



int mdial_delete(int md_dhandle)

 Entfernt modifizierte Einstellungen, die zum Dialoghandle 
 md_dhandle gehren.

 Ergebnis: 0: Fehler (z.B. ungltiges Handle)



int mdial_get(int md_ghandle, int md_gfield, 
              int *md_gw1, int *md_gw2, int *md_gw3, int *md_gw4)

 Liefert je nach Funktionsnummer verschiedene Information ber einen 
 von MultiDialog abgefangenen Dialog.

 Ergebnis: 0: Fehler (z.B. ungltiges Handle, nicht definiertes md_gfield,
 aber auch evtl. wenn gar kein Dialogfenster geffnet ist!)

 md_ghandle: Handle des gewnschten Dialoges (in einigen Fllen kann hier
 auch 0 angegeben werden, wenn es sich nmlich um Aufrufe handelt, die
 nicht auf einem speziellen Dialog arbeiten.)

 md_gfield: Gewnschte Information, 
            die Bedeutung der weiteren Parameter hngt davon ab:
 (Die Parameter md_gw1-4, die z.Z. bei den jeweiligen Funktionen noch nicht 
 definiert sind, knnen in Zukunft eine Bedeutung bekommen. Deshalb darf
 man sich nicht darauf verlassen, da diese nicht verndert werden!)

  MF_VERSION (0): liefert Informationen ber die MultiDialog-Version
      md_gw1: Versionsnummer, BCD-kodiert ($0123=V1.23)
      md_gw2: Beta-Flag, Patchlevel
      md_gw3: Versionsdatum, GEMDOS-Format
      md_gw4: reserviert

  MF_GLOBONOFF (1): liefert globalen An/Aus-Schalter zurck
      md_gw1: 0: MD vom Benutzer abgeschaltet, 1: MD aktiviert

  MF_WKIND (40): Liefert von MultiDialog untersttzte Fensterkomponenten.
      md_gw1: Bitvektor, wie wi_crkind bei wind_create(wi_crkind,...)

  MF_WCURRXYWH (41): Gesamtgre und Position des Dialogfensters
    (nur fr geffnetes Dialogfenster definiert, sonst gibt es eine Fehler.)
      md_gw1: x
      md_gw2: y
      md_gw3: w
      md_gw4: h
  
  MF_WHANDLE (42): Liefert Fenster-Handle des Dialogfensters
    (nur fr geffnetes Dialogfenster definiert, sonst gibt es eine Fehler.)
    Nach Mglichkeit sollte man dieses Handle nur fr Ausknfte verwenden.
    Man sollte ber dieses Handle auf keinen Fall, den Zustand eines
    Dialogfensters (z.B. per wind_set) verndern, sondern entsprechende 
    mdial_xxxx-Aufrufe verwenden.
      md_gw1: Fensterhandle
      
  MF_WISONTOP (43): Liefert zurck, ob Dialogfenster oberstes Fenster ist
    (nur fr geffnetes Dialogfenster definiert, sonst gibt es eine Fehler.)
      md_gw1: 1: Fenster ist oberstes Fenster, 0: Fenster ist nicht oberstes



int mdial_set(int md_shandle, int md_sfield, 
              int md_sw1, int md_sw2, int md_sw3, int md_sw4)

 Setzt je nach Funktionsnummer verschiedene Parameter fr einen Dialog.

 Ergebnis: 0: Fehler (z.B. ungltiges Handle, nicht definiertes md_gfield,
 aber evtl. auch wenn gar kein Dialogfenster geffnet ist!)

 md_shandle: Handle des gewnschten Dialoges (0=neuester)

 md_sfield: Gewnschte Information,
            die Bedeutung der weiteren Parameter hngt davon ab:
 (z.Z. noch nicht definierte Parameter md1-4 sind auf 0 zu setzen!)

  MF_GLOBONOFF (1): Schaltet MD global an/aus
    (Nach Mglichkeit nicht verwenden, diese Wahl sollte man dem Benutzer
    berlassen! Wenn Aufrufe gemacht werden sollen, die von MD nicht 
    abgefangen werden sollen, ist zunchst die Frage zu beantworten, 
    warum sie nicht abgefangen werden sollen. Die einzigen Situationen, 
    die mir hier einfallen, sind solche, die man besser nicht ber 
    Dialogroutinen, sondern ber richtige Fensterfunktionen abwickelt.)
      md_sw1: 0: MD abgeschalten, 1: MD aktivieren

  MF_REDRAWTYPE (20): Setzt von MD anzuwendendes Redrawverfahren
      md_sw1: 0: MultiDialog puffert den gesamten Bildschirm und
                 erfllt damit Redraw-Anforderungen
              1: MultiDialog erledigt nur den Redraw fr MultiDialoge,
                 alle anderen Fenster werden von Applikation redrawt,
                 so da der Bildschirm nicht gerettet werden mu,
                 was einiges an Speicher spart.

  MF_EVNTTIMER (23): Sorgt dafr, da bei MultiDialogs evnt_multi-Aufruf
    auerdem auf einen Timer-Event gewartet wird (der dann selbst
    ausgewertet werden sollte. Ist keine PRE/POST-EVENT-Callbackroutine
    installiert, so wird der Dialog mit Rckgabewert md_sw3 abgebrochen.). 
    Ntzlich fr Info-Boxen, die nach einiger Zeit von selbst 
    verschwinden sollen, aber den Bildschirm nicht blockieren.
    (Es ist zu beachten, da - falls form_do nicht durch den Timer-Event
    beendet wurde - nach verlassen von form_do noch ein Timer-Event
    auftreten kann, falls die Applikation dann z.B. per evnt_multi auf
    einen solchen wartet!)
      md_sw1: wie ev_tlocount bei evnt_timer
      md_sw2: wie ev_thicount bei evnt_timer
      md_sw3: Rckgabewert, falls form_do durch den Timer beendet wird

  MF_CALLBACKSTYLE (25): Setzt Parameterbergabe-Konvention fr Callback
      md_sw1: 0: cdecl-style (Standard C) Default-Einstellung!
             (1: pascal-style (Pascal)) derzeit nicht untersttzt, 
                 Rckgabewert beachten!

  MF_CBREDRAW (26): Setzt Zeiger auf Callback-Routine fr Fenster-Redraw
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_CBPREEV (27): Setzt Zeiger auf Callback-Routine fr externe Event-
    Verarbeitung, bevor MultiDialog die Events auswertet
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_CBPOSTEV (28): Setzt Zeiger auf Callback-Routine fr externe Event-
    Verarbeitung, nachdem MultiDialog die Events ausgewertet hat
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_CBFORMKEYBD (29): Setzt Zeiger auf Callback-Routine fr externe 
    form_keybd()-Routine
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_CBFORMBUTTON (30): Setzt Zeiger auf Callback-Routine fr externe 
    form_button()-Routine
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_CBOBJCEDIT (31): Setzt Zeiger auf Callback-Routine fr externe 
    objc_edit()-Routine
    (Default: 0, d.h. nicht aufrufen)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_WNAME (50): Setzt Fensternamen
    (Default: MultiDialog: <APP_NAME>)
      md_sw1: High-Word des Zeigers
      md_sw2: Low-Word des Zeigers

  MF_WADDKIND (52): Fgt Fensterkomponenten hinzu
      md_sw1: Bitvektor, wie wi_crkind bei wind_create(wi_crkind,...)
      md_sw2: Return-Wert fr form_do, wenn ein WM_CLOSED-Event auftritt.
              (0: WM_CLOSED nicht auswerten)

  MF_WREMKIND (53): Entfernt Fensterkomponenten 
      md_sw1: Bitvektor, wie wi_crkind bei wind_create(wi_crkind,...)



int mdial_xformdo(int md_xdohandle, OBJECT *md_xdotree, 
                  int *md_xdostartob, int *md_xdopbuff)

 Fhrt Fensterdialog-Verwaltung durch. Bricht ab, falls ein EXIT-Objekt
 gewhlt wurde oder wenn ein Event aufgetreten ist, den MD nicht
 verarbeiten kann.
 
 Ergebnis: -1: Event aufgetreten, der md_xdopbuff zu entnehmen ist,
           sonst: angeklicktes Objekt.

 md_xdohandle: Dialoghandle, um Dialog zu bestimmen, auf den mdial_xformdo
               angewandt werden soll.

 md_xdotree: Zeiger auf Objektbaum des Dialogs
 
 md_xdostartob: Zeiger, der auf die Nummer des zu editierendes EDIT-Objekt
                zeigt. Bei einem Wert von 0 sucht sich die Routine das
                erste EDIT-Objekt und setzt den Cursor ans Zeilenende (wenn
                ein EDIT-Objekt berhaupt existiert), jeder andere Wert 
                wird als Objektnummer aufgefasst, wobei der Cursor bei 
                erneutem Aufruf an seiner vorherigen Position stehen bleibt. 
                ber diesen Zeiger bekommt der Aufrufer auch mitgeteilt, 
                welches Objekt momentan den Cursor besitzt
                (0: kein EDIT-Objekt vorhanden).
                
 md_xdopbuff: Zeiger auf einen Messagepuffer. Falls mdial_xformdo -1
              zurckliefert, ist die dort enthaltene Nachricht auszuwerten.
              Hierbei handelt es sich um die blichen AES-Nachrichten.
              Hierber knnen auch Nachrichten an mdial_xformdo bergeben
              werden. Jeder Nachricht ungleich Null wird beim Aufruf
              von mdial_xformdo als erstes ausgewertet.
                
                

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Callback-Routinen

                        Bisher wurde immer von Callback-Routinen geredet, 
                                        was ist damit berhaupt gemeint ?

Nun, wenn eine Applikation whrend eines von MultiDialog abgefangenen
Dialoges z.B. den Redraw der eigenen Fenster bernehmen soll, so mu
MultiDialog die Redraw-Routine der Applikation aufrufen knnen. Dazu
bergibt die Applikation vor dem ffnen des Dialogfensters einen Zeiger
auf eine solche Funktion. Dieses Verfahren nennt man Callback.
(es wird z.B. auch bei CPX-Modulen angewandt.)

Da diesen Callback-Routinen auch noch Parameter bergeben werden, ist
es ntig, festzulegen, auf welche Art das geschieht:
z.Z. ist nur
- Standard C (d.h. ber den Stack)
mglich. Vorgesehen ist aber auch
- Pascal
- Assembler bzw. PureC
Die Funktionen knnen auch Werte zurckliefern. Dabei handelt es sich um
16-Bit Integerwerte, die in D0 zurckgeliefert werden.

Mglich sind zur Zeit folgende Callback-Funktionen:

- Redraw: Zeiger auf eine Routine, die den Redraw der Fenster der 
  Applikation erledigt. Es wird ein Zeiger auf den Message-Puffer 
  mit der Redraw-Nachricht bergeben:
  int redraw(int *evnt_mesag)
  Der Rckgabewert hat z.Z. noch keine Bedeutung und ist auf 0 zu setzen.

- PreEvent: Zeiger auf eine Routine, die die Events, die MultiDialog
  bei evnt_multi erhalten hat, auswerten kann. Dieser Routine wird
  ein Zeiger auf den Message-Puffer bergeben. Sie wird aufgerufen,
  bevor MultiDialog seine Events verarbeitet hat. Es mu zurckgegeben
  werden, ob MultiDialog diesen Event ebenfalls auswerten soll. (Dabei
  benutzt MultiDialog denselben Message-Puffer, so da dieser auch
  von der PreEvent-Routine modifiziert werden kann. Nachrichten, die 
  MultiDialog nicht versteht, werden ignoriert). Eine 0 als Rckgabewert 
  bedeutet dabei, da der Event weiterverarbeitet werden soll, 
  eine -1 veranlat MultiDialog, diesen Event zu ignorieren. Jeder 
  andere Wert bricht die Dialogverarbeitung ab und wird als 
  FormDo-Rckgabewert zurckgeliefert (die Werte 0 und -1 sind also
  an dieser Stelle nicht mglich). 
  int pre_event(int *evnt_mesag)

- PostEvent: Zeiger auf eine Routine, die die Events, die MultiDialog
  bei evnt_multi erhalten hat, auswerten kann. Dieser Routine wird
  ein Zeiger auf den Message-Puffer bergeben. Sie wird aufgerufen,
  nachdem MultiDialog seine Events verarbeitet hat. Es mu zurckgegeben
  werden, ob MultiDialog den Dialog abbrechen soll. Eine 0 bedeutet 
  dabei, da MultiDialog weiterarbeiten soll, jeder andere Wert veranlat 
  MultiDialog, den Dialog abzubrechen und als Rckgabewert fr FormDo
  just diesen Wert zu verwenden (der Wert 0 ist an dieser Stelle also
  nicht mglich).
  int post_event(int *evnt_mesag)

Falls das nicht reicht, kann man ausserdem eigene form_keybd, form_button
und objc_edit Routinen installieren, die dann von MultiDialog verwendet
werden:

- FormKeybd: Setzt Zeiger auf eine Routine, die statt der GEM 
  form_keybd()-Routine von MultiDialog verwendet werden soll.
  int form_keybd(OBJECT *fo_ktree, int fo_kobject, int fo_kobnext,
                 int fo_kchar, int *fo_knxtobjct, int *fo_knxtchar)

- FormButton: Wie FormKeybd nur fr form_button.
  int form_button(OBJECT *fo_btree, int fo_bobject, int fo_bclicks,
                  int *fo_bnxtobj)

- ObjcEdit: Weil's so schn war auch fr objc_edit.
  int objc_edit(OBJECT *ob_edtree, int ob_edobject, int ob_edchar,
                int *ob_edidx, int ob_edkind)

In den jeweiligen Routinen sollte man kein allzugroen Faxen machen,
sondern relativ schnell zur Sache kommen. Die Redraw-Routine ist fr's
Redraw da, und fr nichts anderes! Ebenso sollte man z.B. in einer 
Event-Routine auch keine neuen Dialoge starten, stattdessen sollte
man MultiDialog veranlassen, die FormDo-Routine zu beenden und dann 
erst z.B. den neuen Dialog starten.
(Fr nicht-modale Dialoge ist mdial_xformdo da!)
Da MultiDialog (z.Z. nur bedingt) reentrant ist, darf man aus
den Callback-Routinen heraus beliebige GEM-Aufrufe starten.
Die Bedingtheit von MultiDialog's Reentrance uert sich darin, da 
MultiDialog einige AES-Aufrufe, die aus den Callback-Funktionen stammen, 
nicht abfngt, sondern direkt ans AES weiterleitet (nmlich die, die
von MD abgefangen werden)! Die mdial_set/get-Routinen knnen aber auf
jeden Fall aufgerufen werden!


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> einige Beispiele

                                    Ein Bild sagt mehr als tausend Worte:

Deshalb sind an dieser Stelle einige Beispiel-Quelltexte (lauffhig 
unter Pseudo-C 1.1 ;-) abgedruckt.

1. Beispiel:
Es soll ein Dialog garantiert von MultiDialog abgefangen werden und
einen eigenen Fenstertitel sowie einen CLOSER, der ABBRUCH zurckliefert,
besitzen:

#define ABBRUCH  21  			/* BUTTON in Baum DIALOG */
int dhandle;                    /* Variable fr Dialoghandle */
char *wname=" Fenster-Dialog "; /* Zeiger auf Fenster-Titel */


if mdprog_available()           /* mdial_xxxx-Aufrufe erlaubt ? */
  dhandle=mdial_create(NULL, 0, 0); /* Dialog anmelden, kein Redraw-Callback */
else
  dhandle=-1; /* Merken, da mdial_xxxx-Aufrufe nicht erlaubt sind */

if dhandle>0                    /* mdial_create erfolgreich ? */
{
  /* Fenstername setzen */
  mdial_set(dhandle, MF_WNAME, (int)(wname>>16),(int)wname, 0, 0);
  /* CLOSER, der dem Button ABBRUCH entspricht, hinzufgen */
  mdial_set(dhandle, MF_WADDKIND, CLOSE, ABBRUCH, 0, 0);
}

/* Dialogbearbeitung wie blich */
form_center(dialog,size_x,size_y,size_w,size_h)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)          /* wird neuerdings gefordert */
form_dial(FMD_START, size_x, size_y, size_w, size_h, 
                     size_x, size_y, size_w, size_h)
objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h)

rc=form_do(dialog,ROOT)

form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
                      size_x, size_y, size_w, size_h)
wind_update(END_MCTRL)          /* wird neuerdings gefordert */
wind_update(END_UPDATE)


if dhandle>0                    /* mdial_create erfolgreich ? */
  /* Dialog abmelden, Modifikationen rckgngig machen */
  mdial_delete(dhandle); 



2. Beispiel:
Eine Applikation mchte den Redraw der nicht-Dialog-Fenster selber
erledigen, was u.a. sehr viel Speicher spart ist (sehr lobenswert!):

int dhandle;                    /* Variable fr Dialoghandle */
int cdecl redraw_callback(int *evnt_mesag);	/* Prototyp fr Redraw-Routine */
    ^^^^^ (fr Turbo/Pure C, um Parameterbergabe auf dem Stack zu erzwingen)

if mdprog_available()           /* mdial_xxxx-Aufrufe erlaubt ? */
  dhandle=mdial_create(redraw_callback, 0, 0); /* Dialog anmelden, Zeiger auf Redraw-Callback-Routine */
	/* da ein Callback-Zeiger angegeben wurde, puffert MD den Bildschirm
	nicht, die Callback Parameterbergabe steht defaultmig auf Standard C */
else
  dhandle=-1; /* Merken, da mdial_xxxx-Aufrufe nicht erlaubt sind */


/* Dialogbearbeitung wie blich */
form_center(dialog,size_x,size_y,size_w,size_h)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)  /* wird neuerdings gefordert */
form_dial(FMD_START, size_x, size_y, size_w, size_h, 
                     size_x, size_y, size_w, size_h)
objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h)

rc=form_do(dialog,ROOT)

form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
                      size_x, size_y, size_w, size_h)
wind_update(END_MCTRL)  /* wird neuerdings gefordert */
wind_update(END_UPDATE)


if dhandle>0                    /* mdial_create erfolgreich ? */
  /* Dialog abmelden, Modifikationen rckgngig machen */
  mdial_delete(dhandle); 


/* Und jetzt die Redraw-Routine, die per Callback aufgerufen wird
   und die nicht-Dialogfenster der Applikation redrawt. */
int cdecl redraw_callback(int *evnt_mesag)	/* ber den Messagebuffer wird die 
                            Informationen bergeben, was zu redrawen ist */
{
	my_redraw(evnt_mesag[3], evnt_mesag[4],evnt_mesag[5],
	          evnt_mesag[6],evnt_mesag[7]); /* persnliche Redraw-Routine */
	return(0); /* z.Z. keine Bedeutung, auf 0 setzen */
}

/* und das ist dann jeweilige Redraw-Routine der Applikation */
void my_redraw(int handle, int x, int y, int w, int h)
{
	... /* Beispiele fr Redraw-Routinen siehe z.B. Profibuch */
}



3. Beispiel:
Eine Dialogbox (z.B. Info-Box) soll fr 5 Sekunden angezeigt werden:

#define ABBRUCH  21  			/* BUTTON in Baum DIALOG */
int dhandle;                    /* Variable fr Dialoghandle */
char *wname=" Fenster-Dialog "; /* Zeiger auf Fenster-Titel */

if mdprog_available()           /* mdial_xxxx-Aufrufe erlaubt ? */
  dhandle=mdial_create(NULL, 0, 0); /* Dialog anmelden, kein Redraw-Callback */
else
  dhandle=-1; /* Merken, da mdial_xxxx-Aufrufe nicht erlaubt sind */

if dhandle>0                    /* mdial_create erfolgreich ? */
{
  /* evnt_timer auf 5000ms setzen und ABBRUCH als Rckgabewert fr
     form_do setzen, falls der Timer-Event auftritt */
  mdial_set(dhandle, MF_EVNTTIMER, 5000, 0, ABBRUCH, 0);
}

/* Dialogbearbeitung wie blich */
form_center(dialog,size_x,size_y,size_w,size_h)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)  /* wird neuerdings gefordert */
form_dial(FMD_START, size_x, size_y, size_w, size_h, 
                     size_x, size_y, size_w, size_h)
objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h)

rc=form_do(dialog,ROOT)

form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
                      size_x, size_y, size_w, size_h)
wind_update(END_MCTRL)  /* wird neuerdings gefordert */
wind_update(END_UPDATE)


if dhandle>0                    /* mdial_create erfolgreich ? */
  /* Dialog abmelden, Modifikationen rckgngig machen */
  mdial_delete(dhandle); 

/* Es kann jetzt evtl. noch der Timer-Event auftreten, falls form_do
   nicht durch den Timer-Event, sondern durch einen EXIT-Button
   beendet wurde! */



4. Beispiel:
Nun noch ein Fensterdialog mittels mdial_xformdo (Redraw fr
nicht-Dialogfenster sollen von der Applikation bernommen):

#define ABBRUCH  21  			/* BUTTON in Baum DIALOG */
int dhandle;                    /* Variable fr Dialoghandle */
int msg_buff[8];				/* Buffer fr Nachrichten */
int edit_object;				/* Speicherplatz fr Position des Edit-Cursors */
int message;					/* Hilfsvariable fr eingetroffene Nachricht */
int whandle;					/* Windowhandle des Dialogfensters */
BOOLEAN abort;					/* Abortflag fr Schleife */

if mdprog_available()           /* mdial_xxxx-Aufrufe erlaubt ? */
  dhandle=mdial_create(NULL, 0, 0); /* Dialog anmelden, kein Redraw-Callback */
else
  dhandle=-1; /* Merken, da mdial_xxxx-Aufrufe nicht erlaubt sind */

if dhandle<0                    /* mdial_create erfolgreich ? */
{								/* Nein: normalen Dialog ausfhren */
	form_center(dialog,size_x,size_y,size_w,size_h);
	wind_update(BEG_UPDATE);
	wind_update(BEG_MCTRL);  /* wird neuerdings gefordert */
	form_dial(FMD_START, size_x, size_y, size_w, size_h, 
	                     size_x, size_y, size_w, size_h);
	objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h);
	
	rc=form_do(dialog, ROOT);
	
	form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
	                      size_x, size_y, size_w, size_h);
	wind_update(END_MCTRL);  /* wird neuerdings gefordert */
	wind_update(END_UPDATE);
}
else
{								/* mdial_create hat geklappt! */
	/* Dialogvorbeitung wie blich */
	form_center(dialog,size_x,size_y,size_w,size_h);
	wind_update(BEG_UPDATE);
	wind_update(BEG_MCTRL);  /* wird neuerdings gefordert */
	form_dial(FMD_START, size_x, size_y, size_w, size_h, 
	                     size_x, size_y, size_w, size_h);
	objc_draw(dialog,ROOT,MAX_DEPTH,size_x, size_y, size_w, size_h);
	
	/* Jetzt kommt mdial_xformdo mit externer Event-Verarbeitung */
	edit_object=0;	/* Am Anfang, das Edit-Objekt von Xformdo bestimmen lassen */
	do
	{
		rc=mdial_xform_do(dhandle, dialog, &edit_object, msg_buff); /* Dialoghandle,
           Zeiger auf Dialogbaum, Edit-Objekt, Zeiger auf Nachrichtenbuffer */
		if (rc!=-1)			/* ungleich -1, d.h. Button gedrckt */
		{
			rc&=0x7fff;		/* Doppelklick ausmaskieren */
			dialog[rc].state&=~SELECTED;	/* Objekt deselektieren */
			switch (rx)		/* Buttons auswerten */
			{
				case ABBRUCH: abort=TRUE; break;	/* Dialogschleife beenden */
				case ...
			}
		}
		else				/* Message zu verarbeiten */
		{
			message=msg_buff[0];		/* eingetroffene Nachricht merken */
			msg_buff[0]=0;				/* Default: nchster Xformdo-Aufruf erhlt keine Nachricht */
			switch (msg_buff[0])	/* Nachrichten auswerten */
			{
				case WM_REDRAW:
					my_redraw(msg_buff[3], msg_buff[4], msg_buff[5],
	          		msg_buff[6], msg_buff[7]); /* persnliche Redraw-Routine (vgl. 2. Beispiel) */
				break;
				case WM_TOPPED:
					msg_buff[0]=WM_TOPPED;	/* xformdo soll sein Dialogfenster toppen */
					/* Handle des Dialogfensters besorgen: */
					if (mdial_get(dhandle, MF_WHANDLE, &whandle, 
					    &dummy, &dummy, &dummy)!=0)	/* whandle gltig ? */
					{								/* Ja! */
						msg_buff[0]=WM_TOPPED;	/* xformdo soll sein Dialogfenster toppen */
						msg_buff[3]=whandle;	/* Dialogfenster soll getoppt werden */
					}
				break;
				case WM_MOVED:
				case WM_SIZED:
					wind_set(msg_buff[3],WF_CURRXYWH, msg_buff[4], msg_buff[5],
	          		msg_buff[6], msg_buff[7]);	/* Position der eigenen Fenster verndern */
				break;
				case ...
			}
		}
	} while (abort==FALSE)
	
	/* Dialognachbereitung wie blich */
	form_dial(FMD_FINISH, size_x, size_y, size_w, size_h, 
	                      size_x, size_y, size_w, size_h);
	wind_update(END_MCTRL);  /* wird neuerdings gefordert */
	wind_update(END_UPDATE);
	
	/* Dialog abmelden, Modifikationen rckgngig machen */
	mdial_delete(dhandle); 
}


5. Beispiel:
Und jetzt zwei nicht-modale Dialoge mittels mdial_xformdo:

Ist zwar nicht sehr abgedreht, da es eine Erweiterung des
4. Beispiels darstellt, aber trotzdem fehlt es aus Zeitgrnden
noch...



>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Abspann

        Wie bereits oben angedeutet, handelt es sich hierbei nur um einen
     ersten Entwurf. Verbesserungsvorschlge und Erweiterungen sind nicht
                                       nur willkommen, sondern erwnscht!

Da diese Dokumentation unter Zeitdruck entstanden ist, drften viele 
Fragen offengeblieben sein. Es sollte daher niemand zgern, mir bei
offengebliebenen Fragen zu schreiben, es sollten sich alle (Un)klarheiten 
beheben lassen...

Wenn es die Zeit zult, wird die erste Realisierung dieser Aufrufe in
MultiDialog 1.04 stattfinden, das (hoffentlich) Anfang '94 erscheinen
drfte.
