                    Die MyDial-Funktionsbibliothek


Vorwort

Das  ist nun mein zweiter Versuch die MyDials zu  dokumentieren.  Beim 
ersten mal hatte ich wenig Zeit und noch weniger Lust,  und das wirkte 
sich  dann  auch  auf  die erste  "Anleitung"  aus,  die  ihren  Namen 
eigentlich nicht verdiente. Ich hoffe, da mir das Unterfangen diesmal 
besser  gelingt.  Da ich die MyDials grtenteils selber  programmiert 
habe,  besteht  natrlich  die  Gefahr,  da ich  einige  Dinge  nicht 
erlutere,  weil sie mir einfach selbstverstndlich  erscheinen.

Wenn  irgendwas unklar sein sollte oder Sie Probleme mit  der  Library 
haben,  dann  knnen  Sie  mich jeder Zeit ber die  Firma  Shift  er-
reichen.  Wenn Sie ein Modem besitzen sollten,  knnen Sie Ihre Fragen 
und Verbesserungsvorschlge ber Ihre Mailbox direkt an mich  richten. 
Meine Adresse lautet: "Olaf_Meisiek@fl.maus.de".


1   Einleitung

  1.1 Was sind die MyDials

Die  MyDials  sind eine Routinensammlung,  die  'fliegende'  und  ber 
Tastatur bedienbare Dialoge auf einfache Weise ermglichen.  Sie  bie-
ten echte Radiobuttons (kleine runde Knpfe),  Checkboxen (ankreuzbare 
Kstchen),  Popup-Mens,  komfortable  Eingaberoutinen in  Editfelder, 
verschiebbare Dialoge,  tastaturbedienbare Buttons,  Untersttzung der 
HELP und UNDO Tasten,  Sonderzeicheneingabe und noch einiges mehr. Die 
MyDials  sind  kein eigentlicher Bestandteil  des  Interface-Programm-
pakets,  sondern  eine  Zugabe,  fr deren  Vollstndigkeit  und  Ver-
wendbarkeit die Firma SHIFT keine Haftung bernimmt.


  1.2 Verwendung der MyDials in eigenen Programmen

Voraussetzung  fr  die Verwendung der MyDials in  eigenen  Programmen 
ist,  da  Sie ber eine Originalversion von Interface  verfgen.  Die 
Verwendung  der  MyDials ohne eine Originalversion von  Interface  ist 
nicht gestattet.

In  der  letzten Anleitung hatte ich um ein Belegexemplar  jedes  Pro-
grammes gebeten,  welches die MyDials einsetzt.  Dies ist jetzt  nicht 
mehr  notwendig.  Ich freue mich aber trotzdem,  wenn mir jemand  sein 
Programm zuschickt,  weil es mich interessiert,  fr welche  Programme 
die MyDials verwendet werden.


  1.3 Wer kann die MyDials verwenden?

Jeder,  der Turbo C, Pure C oder einen Linker besitzt, der Turbo C bzw 
Pure  C-Librarys linken kann.  Leider sind die Pure C  Librarys  nicht 
Digital Research-kompatibel,  d.h.  bis auf wenige Ausnahmen kann  man 
die MyDials nur in Verbindung mit Pure C bzw Turbo C einsetzen.

Der  Einsatz  der MyDials unter GFA und Omikron Basic ist  jetzt  auch 
mglich.  Auf der Diskette befinden sich die dafr notwendigen Routin-
en.  Da ich mich mit Basic nicht auskenne,  kann ich spezielle  Fragen 
zur Einbindung nicht selber beantworten.  Fragen dazu sollten also  an 
Shift  geschickt werden,  damit sie an den Autor der  jeweiligen  Ein-
bindung weitergereicht werden knnen.

Fr  Modula 2 gibt es ein Programm,  das Pure C-Librarys zu  Modula  2 
Programmen linken kann; dort sollte es also wieder machbar sein.

Auf  besonderen Wunsch kann ich jedem Interessenten auch eine  Digital 
Research-kompatible MyDial-Library zuschicken.  Das wird aber nur  den 
wenigsten weiterhelfen,  da die MyDials einige Funktionen aus der Pure 
C Library aufrufen.  Mir ist leider keine Mglichkeit  bekannt,  diese 
Funktionen ebenfalls in die MyDial-Library zu bernehmen.  Daher wrde 
eine Digital Research-kompatible Library nur denjenigen  weiterhelfen, 
die  auerdem  eine  Library besitzen,  die die von  den  MyDials  be-
ntigten  Routinen bereitstellt.  Das knnte fr einige andere  C-Com-
piler auf dem Atari zutreffen.


  1.4 MyDial-Dateien und ihre Bedeutung

NKCC-Ordner:

NKCC  ist  eine  Library von Harald  Siegmund,  die  von  den  MyDials 
verwendet wird.  Diese Library ermglicht es,  da jede Tastenkombina-
tion  lnderunabhngig  korrekt erkannt und ausgewertet  werden  kann. 
NKCC_TOS.O mu mit den MyDials gelinkt werden.  Eine Anleitung zu NKCC 
steht in der Datei NKCC.DOC.
Noch  eine Warnung:  In dem Ordner befindet sich  der  Vollstndigkeit 
halber  auch  die NKCC.O Library.  Diese Library sollte  unter  keinen 
Umstnden  verwendet  werden,  da diese Library nicht  unter  MultiTOS 
oder  Mag!X fehlerfrei luft.  Diese Warnung gilt nur fr die auf  der 
Interface-Diskette  mitgelieferte Version.  Es ist  durchaus  mglich, 
da  es inzwischen eine neuere Version von Harald Siegmund (dem  Autor 
von NKCC) gibt,  die diese Probleme nicht mehr bereitet.  Die  MyDials 
bentigen aber in jedem Fall nur NKCC_TOS.O.


MYDIALG.LIB:

In dieser Datei sind alle MyDial-Routinen enthalten.  Auerdem enthlt 
sie  einige Routinen aus dem Modul GLOBAL vom Buch "Vom  Anfnger  zum 
GEM-Profi", die die MyDials bentigen.


MYDIAL.LIB:

In  dieser  Datei sind alle MyDial-Routinen  enthalten.  Wenn  Sie  in 
ihrem  Programm  Routinen aus dem Buch "Vom  Anfnger  zum  GEM-Profi" 
verwenden und auch das Modul GLOBAL.C eingebunden haben,  dann  mssen 
Sie  diese  Library verwenden.  Sie mssen dann aber aus  Ihrem  Modul 
GLOBAL.C  die Routine "popup_menu" lschen,  da diese mit  erweitertem 
Funktionsumfang bereits in den MyDials enthalten ist.

Bitte  benutzen Sie die Software aus der 2.Auflage  des  Buches.  Wenn 
Sie diese noch nicht haben sollten,  dann wenden Sie sich bitte an den 
Hthig  Verlag.  Wenn Sie dem Verlag Ihre Originaldiskette mit  10,-DM 
zuschicken,  bekommen  Sie die neueste Software-Version.

Die MyDial-Routinen stehen in der Datei MYDIAL.H.


PORTAB.H:

Bitte  includen Sie diese Headerdatei VOR der  MyDial-Headerdatei.  In 
PORTAB.H  sind alle fr die MyDials wichtigen Definitionen  enthalten. 
Nheres  ber  diese Datei finden Sie im Buch "Vom Anfnger  zum  GEM-
Profi".  Wer  PORTAB.H bereits besitzt,  braucht es nicht durch  diese 
Version zu ersetzen.


  1.5 Wie funktionieren die MyDials?

Damit  die MyDials Dialoge verschieben knnen  und  tastaturbedienbare 
Objekte  bearbeiten knnen,  mssen sie etwas Vorarbeit  leisten.  Die 
MyDials  berprfen nmlich den Objekttyp und stellen  bei  besonderen 
Typen  eigene Routinen fr diese Objekte zur Verfgung.  In der  Regel 
handelt es sich bei diesen Objekten um sogenannte "erweiterte" Objekt-
typen.

Mit Interface kann man sehr leicht solch ein Objekt erzeugen. Wenn sie 
ein Objekt in Interface editieren,  knnen sich rechts oben im  Dialog 
das  Feld "Erweiterter Typ" sehen.  Dort trgt man einfach  eine  Zahl 
ein,  um  den MyDials spter mitzuteilen,  da dieses Objekt  speziell 
behandelt werden soll.

Fr  jede  Objektart gibt es eine andere  Nummer,  die  man  eintragen 
kann.  Manchmal  mu man zustzlich zur Nummer auch  einen  bestimmten 
"normalen" Objekttyp verwenden,  oder bestimmte Flags setzen.  In  der 
Interface-Resource  finden  sie sehr viele Beispiele  fr  solche  er-
weiterten Objekte.


  1.6 Welche erweiterten Objekttypen gibt es?

Ich werde jetzt alle von den MyDials untersttzten erweiterten Objekt-
typen aufzhlen.  Dabei werden der erweiterte Typ, der normale Objekt-
typ (soweit notwendig),  die bentigten Objektflags und -states, sowie 
die Flags,  die auf keinen Fall gesetzt werden drfen, angegeben. Alle 
Flags,  die  weder  unter die eine,  noch unter die  andere  Kategorie 
fallen, drfen bei Bedarf zustzlich gesetzt werden.


Verschiebeobjekt
Erweiterter Typ : 17
Gesetzte Flags  : TOUCHEXIT
Anm:  Wenn  man mit der Maus irgendein Objekt mit dem erweiterten  Typ 
      17  anklickt  und daran zieht,  kann man dadurch  den  gesammten 
      Dialog verschieben.

FlyDial-Ecke
Normaler Typ    : IBOX
Erweiterter Typ : 17
Gesetzte Flags  : OUTLINED, CROSSED
Anm:  Dieses  Objekt entspricht in der Funktion dem  Verschiebeobjekt. 
      Es wird aber von den MyDials als "Eselsohr" gezeichnet.

Radiobutton
Normaler Typ    : BUTTON oder STRING
Erweiterter Typ : 18
Gesetzte Flags  : RBUTTON (Radiobutton)
Anm:  Ein Radiobutton mit diesem Typ ist ein runder Button,  neben dem 
      der Text steht.  Da der Button relativ klein ist,  kann man  ihn 
      auch   selektieren,   indem  man  den  daneben  stehenden   Text 
      anklickt.

Checkbox
Normaler Typ    : BUTTON
Erweiterter Typ : 18
Gesetzte Flags  : -
Ungesetzte Flags: RBUTTON, EXIT, SHADOWED
Anm:  Eine Checkbox sieht fast wie ein Radiobutton aus.  An Stelle des 
      runden Buttons wird aber eine quadratische Box gezeichnet.
      Wenn  das Flag SELECTED gesetzt ist,  wird eine Checkbox  durch-
      gestrichen dargestellt.
      Wenn das Flag CHECKED gesetzt ist,  aber SELECTED nicht  gesetzt 
      ist, wird die Checkbox mit einem Punktmuster gefllt.
      Aus  diesen 3 Zustnden kann man sich leicht  einen  "TriState"-
      Button programmieren,  der z.B. von Interface verwendet wird, um 
      in  mehreren Objekten Flags gleichzeitig zu  setzten  (Menpunkt 
      "Flags setzen...").

Popupbutton
Normaler Typ    : BUTTON
Erweiterter Typ : 18
Gesetzte Flags  : SHADOWED
Ungesetzte Flags: RBUTTON, EXIT
Anm:  Dieser  Button entspricht dem Exitbutton,  darf aber  nicht  das 
      EXIT-Flag zu besitzen.  In der Interface-Resource wird er nur im 
      Fileselektor fr das Pfad-Popup verwendet.  Er steht links neben 
      dem  Pfad,  und enthlt sinnigerweise den  Text  "Pfad".  Diesen 
      Objekttyp  sollte man normalerweise nicht fr Popups  verwenden, 
      wenn  der  Popup-Button den Text des  zuletzt  angewhlten  Ein-
      trages  beinhalten  soll.  Interface verwendet fr  die  eigenen 
      Popups  immer  einen  ganz  normalen  BoxText-Button  ohne   er-
      weiterten Objekttyp.

Exitbutton
Normaler Typ    : BUTTON
Erweiterter Typ : 18
Gesetzte Flags  : EXIT
Ungesetzte Flags: RBUTTON
Anm:  Ein Exitbutton entspricht einem ganz normalen Button.  Der  ein-
      zige Unterschied ist, da er tastaturbedienbar ist.

String
Normaler Typ    : STRING
Erweiterter Typ : 18
Ungesetzte Flags: RBUTTON, EXIT
Anm:  Dies ist ein tastaturbedienbarer String. Man knnte ihn z.B. fr 
      die einzelnen Eintrge eines Popups verwenden,  damit man  einen 
      Eintrag  direkt  ber  Tastatur  auswhlen  kann.   Die  MyDials 
      verkraften seit Interface 2.0 auch tastaturbedienbare Strings in 
      den eigenen Popup-Routinen.

Typ 18 Undobutton
Erweiterter Typ : 18
Gesetzte Flags  : ob_flags 11
Anm:  Wenn  ob_flags 11 in irgendeinem erweiterten Objekt vom  Typ  18 
      gesetzt wurde,  kann man dieses Objekt auch ber die  UNDO-Taste 
      anwhlen.   Interface  benutzt  das  z.B.  fr  alle  "Abbruch"-
      Buttons.

Unterstrichen
Normaler Typ    : STRING oder BUTTON
Erweiterter Typ : 19
Anm:  Solch  ein  Objekt  wird von  den  MyDials  als  unterstrichener 
      String dargestellt.  Interface benutzt diesen Objekttyp fr alle 
      Dialogberschriften.  Der Unterstrich hat die Lnge der  Objekt-
      breite.

Boxtitel
Normaler Typ    : BUTTON
Erweiterter Typ : 20
Anm:  Ein Boxtitel wird als groer Rahmen gezeichnet,  in dem der Text 
      des  Objekts links oben als berschrift steht.  Boxtitel  werden 
      von Interface z.B. in dem Resource-Info Dialog eingesetzt.

Helpbutton
Erweiterter Typ : 21
Anm:  Alle Objekte vom erweitertem Typ 21 lassen sich durch die  HELP-
      Taste  auswhlen.  Der Typ und die Flags des Objekts sind  egal, 
      es  hat sich aber eingebrgert,  einen Help-Button  als  BoxText 
      mit  den Flags EXIT,  OUTLINED und  SHADOWED  darzustellen.  Der 
      Text sollte Kleinschrift und zentriert sein.  Help-Buttons  gibt 
      es jetzt in Interface in jeder Objekt-Dialogbox.

Circlebutton
Normaler Typ    : BOXCHAR
Erweiterter Typ : 22
Anm:  Ein  Circlebutton  wird in der Regel immer  zusammen  mit  einem 
      Popup verwendet.  Der Button wird als kleine Box mit einem darin 
      befindlichen Kreispfeil dargestellt.  Mit diesem Objekt kann man 
      schnell  den  nchsten popup-Eintrag  aufrufen,  ohne  erst  das 
      Popup  anwhlen zu mssen.  Circlebuttons werden  von  Interface 
      z.B. in der BoxText-Dialogbox verwendet.

Undobutton
Erweiterter Typ : 31
Anm:  Ein  Undobutton entspricht in der Bedienung dem Helpbutton  (Typ 
      21).  Natrlich  dient hier die UNDO-Taste zur Auswahl  des  Ob-
      jekts.

Mehrzeilige Eingabefelder
Normaler Typ    : FTEXT oder FBOXTEXT
Erweiterter Typ : 0 (Null)
Gesetzte Flags  : EDITABLE, ob_flags 10
Anm:  Diesen  Objekttypen gab es schon in den Interface  1.0  MyDials, 
      er  wurde  aber von mir nicht dokumentiert,  da  er  etwas  kom-
      plizierter  zu handhaben ist.  Mehrzeilige Eingabefelder  werden 
      von Interface z.B.  in der FreeString-Dialogbox eingesetzt.  Da-
      bei  verhalten sich mehrere  aufeinanderfolgende  Eingabefelder, 
      als wenn sie ein einziges Feld wren.


2   Programmierung mit den MyDials

  2.1 Ablaufschema

Am Programmstart
- Initialisierung von NKCC
- Initialisierung der MyDials
- Initialisierung der Programmresource mit den MyDials

beliebige Nutzung der MyDial-Routinen

Am Programmende
- Deinitialisierung der MyDials
- Deinitialisierung von NKCC


  2.2 Ein Beispielprogramm

Das folgende Beispielprogramm soll einen Eindruck vermitteln,  wie die 
MyDials  in ein Hauptprogramm eingebunden werden.  Dabei  werden  NKCC 
und die MyDials initialisiert. Die MyDials ffnen intern eine Worksta-
tion, damit sie nicht die Parameter des Hauptprogramms verstellen.
In  der  alten  MyDial-Version mute  NKCC  ein  VDI-Workstationhandle 
bergeben  werden.  Das  ist nicht mehr ntig,  da man  nur  noch  die 
NKCC_TOS.LIB  verwenden  sollte,  die keine  VDI-  und  AES-Funktionen 
enthlt.


#include <portab.h>
#include <aes.h>
#include <vdi.h>

#include <nkcc.h>
#include <mglobal.h>
#include <mydial.h>

WORD phys_handle, vdi_handle;

main()
{
  /* NKCC und die MyDials werden initialisiert */
  nkc_init (NKI_NO200HZ, 0);                     /* Initialisiere NKCC */
  nkc_set (0);

  if (dial_init (Malloc, Mfree, NULL, NULL, NULL) == TRUE)
  {
    /* Das Hauptprogramm folgt      */

    dial_alert (NULL, "[0][Die Initialisierung|hat geklappt!][[OK]", 1, 1, ALI_LEFT);

    /* Das war das Hauptprogramm... */

    dial_exit ();   /* MyDials deinitialisieren */
  }

  nkc_exit ();      /* NKCC deinitialisieren    */

  return (0);
}

Die  Pure C-Projektdatei knnte fr das kurze Programm  z.B.  so  aus-
sehen:

               ; MYDEMO.PRJ
               ; ----------
mydemo.prg     ; Name
=              ; list of modules follows...
pcstart.o      ; startup code
mydemo         ; Hauptprogramm
mydialg.lib    ; Mydial lib
pcstdlib.lib   ; standard lib
pctoslib.lib   ; TOS lib
pcgemlib.lib   ; AES and VDI lib
nkcc_tos.o     ; NKCC lib


  2.3 Die Bedeutung der einzelnen MyDial-Routinen

    2.3.1 Initialisierung

      2.3.1.1 dial_init

GLOBAL BOOLEAN dial_init (VOID *alc, VOID *fr, WORD *mnum,
                          MFORM **mform, BOOLEAN *gs);

alc = Zeiger auf eine Speicherreservierungs-Routine (z.B. Malloc)

fr = Zeiger  auf eine Routine,  die den reservierten  Speicher  wieder 
     freigibt (z.B. Mfree).

mnum = Zeiger  auf  eine Integer-Variable,  in der  der  zuletzt  ver-
       wendete Maustyp steht (z.B. ARROW).
Der  Wert wird gebraucht,  damit die MyDials immer die richtige  Maus-
form  restaurieren  knnen.   Die  Maustypen  werden  dem   AES-Befehl 
"graf_mouse"  bergeben.  Eine Aufzhlung aller  mglichen  Mausformen 
steht   z.B.   im  Profibuch  in  der  Erluterung   des   AES-Befehls 
"graf_mouse".

mform = Zeiger auf einen Zeiger,  der auf eine selbstdefinierte  Maus-
        form zeigt.
Dieser Zeiger wird nur gebraucht,  wenn *mnum den Wert 255  (USER_DEF) 
enthlt.

gs =  Wenn diese Variable den Wert TRUE enthlt,  zeichnen die MyDials 
      Grow/Shrinkboxen, sonst nicht.

Man  braucht  nicht alle Werte anzugeben.  Wenn  das  eigene  Programm 
diese  Variablen nicht enthalten sollte,  kann man  auch  NULL-Pointer 
bergeben. Der krzestmgliche "dial_init" Aufruf sieht so aus:

ret = dial_init (Malloc, Mfree, NULL, NULL, NULL);

Wenn  "dial_init" den Wert FALSE zurckgibt,  hat die  Initialisierung 
nicht  geklappt.  Das  Programm sollte dann  mit  einer  Fehlermeldung 
beendet werden.  Die Initialisierung kann nur schiefgehen,  wenn nicht 
gengend Speicher vorhanden ist.


      2.3.1.2 dial_exit

GLOBAL BOOLEAN dial_exit (VOID);

dial_exit   deinitialisiert   die  MyDials.   Wenn  die   MyDials   am 
Programmstart  initialisiert  werden  konnten,   mu  am  Programmende 
dial_exit  aufgerufen  werden,  damit die  MyDials  z.B.  ihre  eigene 
Workstation schlieen knnen.


      2.3.1.3 dial_fix

GLOBAL VOID dial_fix (OBJECT *tree, BOOLEAN is_dialog);

tree = Adresse des Baumes

is_dialog = Wenn TRUE,  dann ist es eine Dialogbox,  wenn FALSE,  dann 
            ist es ein Menbaum

dial_fix   mu   am   Programmstart  des   Hauptprogramms   nach   der 
Initialisierung  der MyDials fr jeden Baum des Hauptprogramms  einmal 
aufgerufen  werden.   Die  MyDials  initialisieren  in  dial_fix   die 
erweiterten  Objekttypen  und tragen darin ihre  Zeichenroutinen  ein. 
Auerdem  pat dial_fix die Werte ob_width und ob_height  der  OBJECT-
Struktur  aller Icons und Images an die gltige Auflsung an,  da  das 
AES dabei bei rsrc_load Fehler macht.

Zu  jedem  benutzerdefinierten Objekt legen die MyDials  die  Struktur 
OBBLK  an (Definition in MYDIAL.H).  Diese Struktur enthlt die  USER-
BLK-Struktur  und den ehemaligen Objekttyp,  damit man auch  nach  der 
Anpassung den alten Objekttyp erfahren kann.


    2.3.2 Die Dialogroutinen

Wenn man die Dialogroutinen einsetzen will,  mu man unbedingt  vorher 
den Bildschirmbereich reservieren und nachdem der Dialog  verschwunden 
ist, wieder freigeben.
Das sieht so aus:

wind_update (BEG_UPDATE);       /* GEM Bildschirmausgaben anmelden */

/* Dialogbearbeitung */

wind_update (END_UPDATE);       /* Bildschirm fr andere Prozesse  */
                                /* wieder freigeben                */

Die  meisten  Programmierer rufen wind_update direkt nach  dem  Haupt-
evnt_multi auf,  und knnen sich einen zweiten Aufruf vor den  Dialog-
routinen natrlich sparen.
Wenn  man  wind_update vergessen sollte,  werden  alle  Mausklicks  an 
andere  Applikationen durchgereicht und selektieren z.B.  Objekte  auf 
dem Desktop,  obwohl man eigentlich nur die Verschiebeecke des Dialogs 
angeklickt hatte...


      2.3.2.1 HndlDial

GLOBAL WORD HndlDial (OBJECT *tree, WORD def, BOOLEAN grow_shrink,
                      RECT *size, BOOLEAN *ok);

tree = Adresse des Dialogbaumes

def = Default-Editobjekt, in der Regel ROOT (ROOT = 0)

grow_shrink = Bei TRUE Grow/Shrinkbox zeichnen, bei FALSE nicht zeich-
              nen

size =  Ausgangsposition der Grow/Shrinkbox,  bei NULL wird die  Bild-
        schirmmitte genommen

ok =  Bei  TRUE konnte der Hintergrund restauriert werden.  Bei  FALSE 
      fhren  die  MyDials noch ein  form_dial  (FMD_FINISH,...)  aus, 
      damit  eine  Redraw-Message  abgeschickt  wird.  Wenn  Sie  zwei 
      Dialogboxen  schachteln  (d.h.  aus einer Box heraus  noch  eine 
      zweite aufrufen),  dann mssen Sie bei ok == FALSE die erste Box 
      neu zeichnen,  da der Hintergrund der zweiten Box beim Verlassen 
      aus Speichermangel nicht restauriert werden konnte.

Rckgabewert =  Index  des Objektes,  durch das der  Dialog  verlassen 
                wurde.

HndlDial fhrt eine komplette Dialogabarbeitung durch. Der Dialog wird 
gezeichnet,  ausgefhrt  und wieder vom  Bildschirm  entfernt.  Intern 
verwendet  HndlDial dazu die Routinen  open_dial,  dial_draw,  dial_do 
und close_dial (in dieser Reihenfolge).


      2.3.2.2 open_dial

GLOBAL BOOLEAN open_dial (OBJECT *tree, BOOLEAN grow, RECT *size,
                          DIALINFO *dialinfo);

tree =  Adresse des Dialogbaumes

grow =  Bei TRUE Grow/Shrinkbox zeichnen, bei FALSE nicht zeichnen

size =  Ausgangsposition der Grow/Shrinkbox,  bei NULL wird die  Bild-
        schirmmitte genommen

dialinfo =  open_dial  merkt sich in der Dialinfo-Struktur  die  Gre 
            der Dialogbox inklusive aller Attribute und den  Speicher-
            bereich,  in  dem der Hintergrund der Dialogbox  gesichert 
            wurde.  Die  Dialinfo-Struktur wird  u.a.  von  close_dial 
            bentigt, um den Bildschirm wieder zu restaurieren.
            DIALINFO ist in MYDIAL.H deklariert.

Rckgabewert =  Bei  TRUE konnte der Hintergrund der  Dialogbox  nicht 
                gespeichert werden.  Bei FALSE fhren die MyDials noch 
                in    der    Funktion   close_dial    ein    form_dial 
                (FMD_FINISH,...) aus,  damit eine Redraw-Message abge-
                schickt  wird.  Wenn Sie zwei  Dialogboxen  schachteln 
                (d.h.  aus  einer  Box heraus noch  eine  zweite  auf-
                rufen),   dann  mssen  Sie  bei  ok  ==  FALSE   nach 
                close_dial die erste Box neu zeichnen,  da der Hinter-
                grund  der  zweiten Box beim Verlassen  aus  Speicher-
                mangel nicht restauriert werden konnte.

open_dial  zentriert  den Dialog,  zeichnet  eine  Grow/Shrinkbox  und 
sichert den Desktopbereich,  ber dem die Dialogbox gezeichnet  werden 
soll.  Auerdem  wird  die DIALINFO-Struktur  mit  den  entsprechenden 
Werten initialisiert.  open_dial zeichnet den Dialog nicht. Das mssen 
Sie danach noch selber mit dial_draw oder objc_draw erledigen.

Der  Dialog wird von open_dial nur zentriert,  wenn sowohl die X-  als 
auch die Y- Position des Dialoges 0 ist (ob_x und ob_y =  0).  Dadurch 
erscheint  der  Dialog  bei allen folgenden Aufrufen  an  der  letzten 
Position,  an  die  er verschoben wurde.  Wenn man ein  erneutes  Zen-
trieren  erzwingen will,  mu man nur die X- und Y-Position des  ROOT-
Objekts wieder auf Null setzen.


      2.3.2.3 close_dial

GLOBAL BOOLEAN close_dial (BOOLEAN shrink, RECT *size,
                           DIALINFO *dialinfo);

shrink =  Bei TRUE Grow/Shrinkbox zeichnen, bei FALSE nicht zeichnen

size =  Endposition der Grow/Shrinkbox,  bei NULL wird die Bildschirm-
        mitte genommen

dialinfo =  Diese   Struktur   wurde  von   open_dial   initialisiert. 
            close_dial  findet darin die Gre der Dialogbox  und  die 
            Adresse des Hintergrundbuffers.

Rckgabewert =  close_dial gibt immer TRUE zurck.

close_dial  zeichnet  eine Grow/Shrinkbox und  restauriert  den  Bild-
schirm wieder.  Wenn der Bildschirmhintergrund in open_dial aus  Spei-
chermangel nicht gesichert werden konnt,  sendet close_dial noch  eine 
Redraw-Message (FMD_FINISH) an das AES.


      2.3.2.4 dial_center

GLOBAL VOID dial_center (OBJECT *tree);

tree =  Adresse des Dialogbaumes

dial_center  initialisiert  die Dialogbox so,  da sie  genau  in  der 
Bildschirmmitte  gezeichnet wird.  Da dial_center intern von  HndlDial 
bzw.  open_dial  ausgefhrt wird,  braucht man diese Funktion  in  der 
Regel nicht (es sei denn, man verzichtet auf HndlDial/open_dial).


      2.3.2.5 dial_start

GLOBAL BOOLEAN dial_start (OBJECT *tree, DIALINFO *di);

tree =  Adresse des Dialogbaumes

dialinfo =  dial_start  merkt sich in der Dialinfo-Struktur die  Gre 
            der Dialogbox inklusive aller Attribute und den  Speicher-
            bereich,  in  dem der Hintergrund der Dialogbox  gesichert 
            wurde.  Die  Dialinfo-Struktur wird  u.a.  von  close_dial 
            bentigt, um den Bildschirm wieder zu restaurieren.
            DIALINFO ist in MYDIAL.H deklariert.

Rckgabewert =  Bei  TRUE konnte der Hintergrund der  Dialogbox  nicht 
                gespeichert werden.  Bei FALSE fhren die MyDials noch 
                in close_dial ein form_dial (FMD_FINISH,...) aus,  da-
                mit  eine Redraw-Message abgeschickt  wird.  Wenn  Sie 
                zwei  Dialogboxen  schachteln  (d.h.   aus  einer  Box 
                heraus  noch eine zweite aufrufen),  dann  mssen  Sie 
                bei  ok  == FALSE nach close_dial die  erste  Box  neu 
                zeichnen,  da  der  Hintergrund der zweiten  Box  beim 
                Verlassen aus Speichermangel nicht restauriert  werden 
                konnte.

dial_start  initialisiert die DIALINFO-Struktur und buffert den  Bild-
schirmbereich,  ber  dem die Dialogbox gezeichnet  werden  soll.  Vor 
dial_start  mu  man dial_center oder eine eigene  Funtkion  aufrufen, 
damit im Dialogbaum die Zeichenposition gespeichert  wird.  dial_start 
wird  von  open_dial  aufgerufen.  Wenn man  HndlDial  oder  open_dial 
verwendet, mu man dial_start nicht benutzen.


      2.3.2.6 dial_draw

GLOBAL VOID dial_draw (DIALINFO *di);

di =  DIALINFO-Struktur,  die  durch  open_dial oder  dial_start  ini-
      tialisiert wurde.

dial_draw  zeichnet  den  Dialog.   dial_draw  fhrt  intern  nur  ein 
objc_draw aus, wobei objc_draw die Werte der DIALINFO-Struktur berge-
ben  werden.  Man  kann also an Stelle von  dial_draw  auch  objc_draw 
verwenden, mu dann aber natrlich mehr Parameter bergeben.


      2.3.2.7 dial_do

GLOBAL WORD dial_do (DIALINFO *di, WORD edit_obj);

di =  DIALINFO-Struktur,  die  durch  open_dial oder  dial_start  ini-
      tialisiert wurde.

edit_obj =  Default Editobjekt, in der Regel ROOT (ROOT = 0)

Rckgabewert =  Index  des Objektes,  durch das der  Dialog  verlassen 
                wurde.

dial_do entspricht weitestgehend form_dial,  ist aber wesentlich  kom-
fortabler.  dial_do ruft automatisch die Verschiebefunktion auf, falls 
die FlyDial-Ecke angeklickt wurde,  und wertet alle Shortcuts aus. Man 
kann den Cursor mit der Maus positionieren,  mehrzeilige Eingabefelder 
ausfllen  und noch einiges mehr.  Alle besonderen  Tastaturfunktionen 
werden in der Interface-Anleitung in Kapitel 1.7 beschrieben.

dial_do  kann  auch Eingaben in FBoxText-Objekte  mit  dem  SMALL-Font 
vornehmen.  form_do  wrde dabei bestenfalls Pixelmll auf  dem  Bild-
schirm anzeigen.


      2.3.2.8 dial_move

GLOBAL VOID dial_move (DIALINFO *di, WORD x, WORD y, WORD w, WORD h);

di =  DIALINFO-Struktur,  die  durch  open_dial oder  dial_start  ini-
      tialisiert wurde.

x,y,w,h = Rechteck,  innerhalb dessen der Dialog verschoben wird. Nor-
          malerweise sollte man dafr die Desktopwerte ohne  Menzeile 
          angeben.

dial_move  verschiebt einen Dialog innerhalb  eines  Begrenzungsrecht-
ecks.  Wenn die Maustaste losgelassen wird,  wird dial_move verlassen. 
dial_move wird von dial_do automatisch aufgerufen.  Daher braucht  man 
diese  Funktion  nur,  wenn  man die  Dialogbearbeitung  ohne  dial_do 
komplett  selbst vornehmen mu.  In diesem Fall  sollte man  dial_move 
aufrufen,  wenn   der Benutzer ein Objekt mit dem erweitertem  Objekt-
typen 17 angeklickt hat.


      2.3.2.9 dial_end

GLOBAL VOID dial_end (DIALINFO *di);

di =  DIALINFO-Struktur,  die  durch  open_dial oder  dial_start  ini-
      tialisiert wurde.

dial_end  restauriert  den  Hintergrund der  Dialogbox  und  gibt  den 
Speicher  wieder  frei.  Wenn der Hintergrund nicht  gebuffert  werden 
konnte,  sendet dial_end eine Redraw-Message (FMD_FINISH) ans AES.  Da 
dial_end  intern von dial_close aufgerufen wird,  mu man diese  Funk-
tion in der Regel nicht benutzen.


    2.3.3 Einklinken einer eigenen Tastaturroutine in dial_do

Man  kann in dial_do eine eigene Tastaturroutine  einklinken.  dial_do 
springt  dann bei jeder Tastenfunktion erst diese Tastaturroutine  an. 
Nur wenn diese meldet,  da es die Taste nicht auswerten konnte,  wird 
die Taste danach noch von dial_do ausgewertet.


      2.3.3.1 get_Keybd

GLOBAL FORMKEYFUNC get_Keybd (VOID);

Rckgabewert =  Die  Adresse der momentan eingeklinkten  Routine.  Bei 
                NULL ist keine Routine eingeklinkt.

get_Keybd liefert die Adresse der momentan eingeklinkten Routine.  Die 
Funktion wird z.B.  gebraucht,  wenn man aus einer Dialogbox mit einer 
eingeklinkten  Routine  eine zweite aufruft,  in  die  ebenfalls  eine 
eigene  Tastaturroutine eingeklinkt werden soll.  In diesem  Fall  mu 
man  sich nmlich die Adresse der alten Funktion merken und  die  neue 
eintragen.  Wenn  die zweite Dialogbox verlassen wurde,  mu  man  die 
Tastaturroutine der ersten Dialogbox wieder restaurieren.  

FORMKEYFUNC  ist  in  MYDIAL.H  deklariert und wird  in  bei  der  Er-
luterung von set_Keybd beschrieben.


    2.3.3.2 set_Keybd

GLOBAL VOID set_Keybd (FORMKEYFUNC fun);

fun = Ein Zeiger auf eine eigene Funktion,  die die Tastaturereignisse 
      auswerten soll.  Dieser Routine werden mehrere Parameter berge-
      ben,  die  im  groen und ganzen den Parametern  von  form_keybd 
      entsprechen.

Mit  set_Keybd  kann  man  eine  eigene  Tastaturroutine  in   dial_do 
einklinken,  die die Tasten ggf selbst auswertet. Um den Vorgang etwas 
besser   zu  erlutern,   folgt  ein  Ausschnitt  aus  dem   Interface 
Fileselektor-Source.  Der Fileselektor klinkt die Routine "fsel_keybd" 
in dial_do ein, um alle Sondertasten auszuwerten.

Die einzelnen Parameter der FORMKEYFUNC-Struktur haben folgende Bedeu-
tungen (siehe dazu auch fsel_keybd-Source):

tree =  Adresse des Dialogbaumes

edit_obj =  Objektnummer des aktuellen EDIT-Objektes

next_obj =  Ist  momentan  immer 0 und wird nur  aus  Kompatibilitts-
            grnden zu form_keybd bergeben

kr =  Enthlt  den  ASCII- und Scancode vom  zweitletzten  evnt_multi-
      Parameter (pkr).  Wird von NKCC bentigt,  um einen normalisier-
      ten Tastaturcode zu erzeugen.

ks =  Enthlt  den Zustand der Sondertasten und entspricht dem  dritt-
      letzten Parameter von evnt_multi (pks).

onext_obj = Enthlt  das nchste Editobjekt (das Objekt,  auf dem  der 
            Cursor stehen soll).  Knnte man ndern, um den Cursor auf 
            ein bestimmtes Objekt zu stellen.

okr = Entspricht kr.  Mit diesem Parameter kann man eine andere  Taste 
      an die MyDials zurckgeben.  Die MyDials werten dann diese  neue 
      Taste aus.

Wichtig:  Die mit set_Keybd eingeklinkte Routine wird von den  MyDials 
          automatisch wieder in dial_end auf NULL gesetzt,  sobald der 
          Dialog  verlassen wurde.  Man mu die Routine also  bei  dem 
          nchsten Dialogaufruf wieder erneut einklinken. 


/*******************************************************************
Keyboard-Handler
*******************************************************************/

LOCAL WORD fsel_keybd(OBJECT *tree, WORD edit_obj, WORD next_obj,
                      WORD kr, WORD ks, WORD *onext_obj, UWORD *okr)

{ WORD selobj, nkc_key, klicks = 1, ascii;

  nkc_key = normkey (ks, kr);  /* Tastencode in NKCC-Code wandeln */

--------------------------------------------------------------------
es folgen einige gelschte (unwichtige) Zeilen
            ...
--------------------------------------------------------------------

  { ascii = nkc_key & 0x00FF;

    switch ( nkc_key )
    {
      case NKF_FUNC|NKF_CTRL|NK_ESC:        /* ESCAPE         */
                  selobj = SELHEAD;
                  break;
      case NKF_FUNC|NKF_CTRL|SP:            /* SPACE          */
                  selobj = SELHEAD;
                  break;
      case NKF_FUNC|NKF_CTRL|NK_BS:         /* BACKSPACE      */
                  selobj = SELCLOSE;
                  break;
      case NKF_FUNC|NKF_CTRL|NK_CLRHOME:    /* CLR/HOME       */
                  klicks = 2;
                  selobj = USELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NKF_SHIFT|NK_CLRHOME: /*SHIFT-CLR/HOME*/
                  klicks = 2;
                  selobj = DSELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NK_UP:         /* Cursor oben    */
                  selobj = USELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NK_DOWN:       /* Cursor unten   */
                  selobj = DSELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NKF_SHIFT|NK_UP: /* SHIFT Cursor oben  */
                  selobj = BSELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NKF_SHIFT|NK_DOWN: /*SHIFT Cursor unten*/
                  selobj = SSELECT;
                  break;
      case NKF_FUNC|NKF_CTRL|NKF_SHIFT|NK_LEFT: /* Cursor links   */
                  selobj = INFOL;
                  break;
      case NKF_FUNC|NKF_CTRL|NKF_SHIFT|NK_RIGHT:/* Cursor rechts  */
                  selobj = INFOR;
                  break;
    }
    
    if ( selobj != NIL && !(tree[selobj].ob_flags & HIDETREE) )
    {
      *okr = 0;
      return (form_button(tree, selobj, klicks, onext_obj));
    }
  }
  return (NIL);
}

Der  Fileselektor wertet die Tasten aus.  Wenn eine  Tastenkombination 
erkannt  wurde,  fhrt der Fileselektor ein form_button auf  das  ent-
sprechende  Objekt  aus  und  gibt  den  Return-Wert  von  form_button 
zurck.

Entweder  wertet man die Taste selbst aus und gibt einen Wert  zurck, 
den  auch  form_button zurckgeben wrde,  oder man gibt  NIL  zurck, 
damit  die  Taste danach doch noch von den MyDials  ausgewertet  wird. 
Man kann den Rckgabewert auch verndern,  indem man den neuen  ASCII-
Wert  in  okr  zurckgibt.  Die  MyDials wrden  dann  die  Taste  ins 
Editfeld eintragen, deren Wert in okr zurckgegeben wurde.

Ein Beispiel:

*okr  =  127;
return (NIL);

An  dem  Source  kann  man auch  sehr  schn  sehen,  wie  leicht  man 
Tastenkombinationen  mit NKCC abfragen kann,  ohne da man eine  Scan-
code-Tabelle bentigt.  Da NKCC auerdem auch auf auslndischen Tasta-
turen  immer  korrekte Werte liefert,  mchte ich  nicht  mehr  darauf 
verzichten.


    2.3.4 Einklinken einer eigenen Anpassungsroutine in dial_fix

Man  kann in dial_fix eine eigene Routine einklinken,  die immer  dann 
aufgerufen  wird,  wenn die MyDials einen erweiterten Objekttyp  nicht 
kennen.  Dadurch  kann  man leichter  weitere  erweiterte  Objekttypen 
anpassen,  ohne da man nach dial_fix nochmal in einer eigenen Routine 
den ganzen Objektbaum nach diesen Objekten absuchen mu.

    2.3.4.1 set_fixobj

GLOBAL VOID set_fixobj (FIXOBJFUNC fun);

fun = Ein Zeiger auf eine eigene Funktion,  die nicht erkannte  erwei-
      terte Objekttypen anpassen soll.

Die einzelnen Parameter der FIXOBJFUNC-Struktur haben folgende  Bedeu-
tungen:

tree =  Adresse des Dialogbaumes

obj  =  Nummer des anzupassenden Objekts


    2.3.4.2 get_fixobj

GLOBAL FIXOBJFUNC get_fixobj (VOID);

Rckgabewert =  Ein  Zeiger  auf die momentan  eingetragene  Funktion. 
                Wenn noch keine Funktion eingetragen wurde,  wird NULL 
                zurckgeliefert.


    2.3.4.3 add_ublock

GLOBAL USERBLK *add_ublock (WORD cdecl (*code)(PARMBLK *parmblock),
                            LONG obspec, WORD type);

*code  =  Ein  Zeiger auf die Zeichenfunktion,  die in  den  Userblock 
          eingetragen werden soll.

obspec =  Der  alte  obspec-Wert,  der in  der  Userblock-Struktur  im 
          Parameter ob_parm gesichert werden soll.

type   =  Der alte Objekttyp,  der direkt hinter der  Userblock-Struk-
          tur  gesichert  wird (siehe dazu  auch  OBBLK-Struktur,  de-
          klariert in MYDIAL.H).

Rckgabewert =  Ein  Zeiger  auf die neu  angelegte  USERBLK-Struktur. 
                Wenn  dafr nicht genug Speicher vorhanden  war,  wird 
                NULL zurckgeliefert.

add_ublock  wird i.d.R.  nur von den MyDials in der  Routine  dial_fix 
aufgerufen,  um eine USERBLK-Struktur anlegen zu lassen. Wenn man eine 
eigene Funktion in dial_fix eingeklinkt hat,  kann man diese  Funktion 
dafr  verwenden,  fr die eigenen erweiterten Objekte  eine  USERBLK-
Struktur anlegen zu lassen.
Wenn  die  USERBLK-Struktur angelegt werden konnte,  mu man  den  von 
add_ublock  zurckgelieferten  Zeiger  in  den  ob_spec-Parameter  des 
Objekts eintragen.

Ein Beispiel aus den MyDials:

switch (xtype)
{
  case TITLELINE:
    if (type == G_BUTTON)
    {
      if ((userblk = add_ublock (draw_titleline, (LONG)ob->ob_spec,
                                 ob->ob_type)) != NULL)
      {
        ob->ob_height++;
        ob->ob_type = (ob->ob_type & 0xff00) | G_USERDEF;
        ob->ob_spec = (LONG)userblk;
      }
   }
   break;
}


    2.3.5 Mehrzeilige Eingabefelder

In  Interface  gibt  es  mehrere  Dialogboxen,  die  mehrzeilige  Ein-
gabefelder verwenden (z.B.  Free String). Diese Felder werden weitest-
gehends  von  den MyDials verwaltet,  trotzdem ist der  Einsatz  nicht 
besonders  leicht,  da das Hauptprogramm einige Dinge  erledigen  mu. 
Aus  dem  Grund  hatte ich diese Funktion auch  nicht  in  der  ersten 
MyDial-"Anleitung" dokumentiert. Das Versumnis mchte ich jetzt nach-
holen.

Alle  zusammenhngenden Eingabefelder,  die zu einem groen  Feld  zu-
sammengefat  werden sollen,  mssen das selbe Parent  besitzen.  Wenn 
man  mehrere mehrzeilige Eingabeobjekte in einer  Dialogbox  verwenden 
will,  mu  man  sie in  unterschiedlichen  Parents  unterbringen.  Im 
Prinzip funktioniert das genauso wie bei Radiobuttons.

Man  mu zu Programmstart den bentigten Speicherplatz fr  den  voll-
stndigen  String  zur Verfgung stellen.  In Interface luft  es  wie 
folgt ab:

GLOBAL VOID fix_objs (tree)
OBJECT  *tree;

{
  WORD    obj;
  OBJECT  *ob;
  UWORD   type, xtype;
  WORD    par, new, len;
  BYTE    *txt;

  if (tree != NULL)
  {
    obj = NIL;

    do
    {
      ob    = &tree [++obj];        /* Adresse des Objekts holen */
      type  = ob->ob_type & 0xFF;   /* Objekttyp                 */
      xtype = ob->ob_type >> 8;     /* erweiterter Objekttyp     */


      switch (type)
      {
        case G_FTEXT   :
        case G_FBOXTEXT:
          /* Lnge eines mehrzeiligen Eingabeobjektes berechnen */
          if (ob->ob_flags & FLAGS10)
          { len = 0;
            par = parent (tree, obj);
            if (par == NIL) par = ROOT;
            new = tree[par].ob_head;
            while (new != NIL && new != par)
            { switch (tree[new].ob_type & 0xff)
              { case G_FTEXT   :
                case G_FBOXTEXT:
                  if (tree[new].ob_flags & FLAGS10)
                    len += ((TEDINFO *)tree[new].ob_spec)->te_txtlen - 1;
                  break;
              }
              new = tree[new].ob_next;
            }

            /* Fr diese Lnge Speicher allozieren, und die einzelnen */
            /* Felder zu einem Feld zusammenfassen                    */
            if (len)
            { if ((txt = mem_alloc (len + 1)) == NULL)
                dial_alert (NULL, alertmsg[NOMEMORY], 1, 1, ALI_LEFT);
              else
              { memset (txt, 0, len + 1);
                len = 0;
                new = tree[par].ob_head;
                while (new != NIL && new != par)
                { switch (tree[new].ob_type & 0xff)
                  { case G_FTEXT   :
                    case G_FBOXTEXT:
                      if (tree[new].ob_flags & FLAGS10)
                      { ((TEDINFO *)tree[new].ob_spec)->te_ptext = &txt[len];
                        len += ((TEDINFO *)tree[new].ob_spec)->te_txtlen - 1;
                        undo_flags (tree, new, FLAGS10);
                        /* ob_flags 15 setzen, wenn das Editobjekt */
                        /* erfolgreich angepat werden konnte      */
                        do_flags (tree, new, FLAGS15);
                      }
                      break;
                  }
                  new = tree[new].ob_next;
                }
              }
            }
          }
          break;
      }
    } while (! (ob->ob_flags & LASTOB));
  } /* if */
} /* fix_objs */

In der Routine,  die den Dialog aufruft und auswertet,  mu  folgendes 
geschehen:

LOCAL BOOLEAN edit_alert (window, obj)
WINDOWP window;
WORD    obj;

{
  /* unwichtiges gelscht! */

  text = (BYTE *)(kf->tree);
  icon = al_token ((BYTE *)kf->tree, al_str, &txtnum, &butnum);

  /* Dialogfelder initialisieren, dabei Stringrest mit 0 auffllen */
  for (i = 0; i < 5; i++)
  { if (!strcmp (al_str[i], " "))
      memset (((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_ptext, 0, 
              strlen (((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_pvalid));
    else
      strncpy (((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_ptext, al_str[i],
               strlen (((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_pvalid));
  }

  /* Dialogabarbeitung */
  /* ... */
  /* Auswerung des Dialoginhaltes: */

  if (exit_obj == ALOK)
  {
    for (i = 0; i < 5; i++)
    { strncat (alstrg, ((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_ptext,
               strlen (((TEDINFO *)alerttree[ALZ1+i].ob_spec)->te_pvalid));
      strcat (alstrg, "|");
    }
   /* und so weiter... */
  }

  return (ret);
}

Um  es kurz auszudrcken:  Intern liegen die  einzelnen  Eingabefelder 
als  ein  einziger  groer String im  Speicher.  Damit  die  einzelnen 
Felder  trotzdem  voneinander  getrennt werden  knnen,  mu  der  un-
benutzte  Teil bei der Initialisierung mit Nullbytes  aufgefllt  wer-
den.  Sonst  knnte  bei  der Abarbeitung  noch  alter  Buchstabenmll 
auftauchen.

Bei der Auswertung mu man darauf achten,  da man mit strncpy  arbei-
tet.  Wenn  Zeile  1  und 2  zusammenhngen  (d.h.  nicht  mehr  durch 
Nullbytes  getrennt  sind),  wrde  man sonst bei  einem  strcpy  auch 
sofort Zeile 1 und 2 gemeinsam geliefert bekommen.  Wenn man das ganze 
in  einer for...next Schleife abarbeitet,  wrde der  nchste  strcpy-
Befehl dann nochmal Zeile 2 liefern!


      2.3.5.1 find_next

GLOBAL WORD find_next (OBJECT *tree, WORD obj);

tree =  Adresse des Dialogbaumes

obj = Startobjekt

Rckgabewert = Objektindex der nchsten Eingabezeile

find_next sucht ab "obj" die nchste Zeile eines mehrzeiligen Eingabe-
objektes.  find_next wird intern von den MyDials  bentigt.  Interface 
braucht diese Routine fr die Fensterdialoge,  um das nchste Eingabe-
objekt zu finden.


      2.3.5.2 find_prev

GLOBAL WORD find_prev (OBJECT *tree, WORD obj);

tree =  Adresse des Dialogbaumes

obj = Startobjekt

Rckgabewert = Objektindex der vorherigen Eingabezeile

find_prev  sucht ab "obj" die vorhergehende Zeile  eines  mehrzeiligen 
Eingabeobjektes.  find_prev  wird  intern von  den  MyDials  bentigt. 
Interface  braucht diese Routine fr die Fensterdialoge,  um das  vor-
herige Eingabeobjekt zu finden.


    2.3.6 Popup-Routinen

      2.3.6.1 popup_menu

GLOBAL WORD popup_menu (OBJECT *tree, WORD obj, WORD x, WORD y,
                        WORD center_obj, BOOLEAN relative,
                        WORD bmsk, BOOLEAN *ok);

tree =  Adresse des Objektbaums, in dem sich das Popupmen befindet

obj = Wenn der Dialogbaum nur aus dem Popup besteht,  ist obj =  ROOT. 
      Wenn  sich mehrere Popups in dem Dialogbaum befinden,  gibt  obj 
      das  Parent der einzelnen Objekteintrge an (siehe  auch  Inter-
      face-Resource, Baum POPUPS).

x, y =  Position  der linken oberen Popup-Ecke  (bzw.  des  Objektzen-
        trums, wenn center_obj != NIL)

center_obj =  Enthlt den Index des zu zentrierenden Popup-Eintrags

relative =  TRUE:  Popup wird an der Mausposition gezeichnet,  x und y 
            sollten dann 0 sein.

bmsk =  Gibt  den  Mausbutton an,  mit dem das  Popup  verlassen  wird 
        (1 = links, 2 = rechts, 3 = links oder rechts)

ok =  TRUE,  wenn  Hintergund gesichert werden  konnte,  sonst  FALSE. 
      Wenn ein Nullpointer bergeben wird, wird ok nicht gesetzt.

Rckgabewert =  Der ausgewhlte Eintrag,  oder NIL,  wenn kein Eintrag 
                ausgewhlt wurde.

popup_menu  zeichnet  ein Popup und fhrt  die  komplette  Bearbeitung 
durch.  Im Popup drfen beliebige Objekte stehen.  Jedes selektierbare 
Objekt wird invertiert,  wenn die Maus darber steht oder wenn es  mit 
den  Cursortasten angefahren wird.  Man kann  auch  tastaturbedienbare 
Strings im Popup unterbringen, und diese ber den Shortcut anwhlen.

Wenn  ok FALSE enthlt,  mu die aufrufende Routine den Dialog an  der 
Popup-Position neu zeichnen,  da der Speicherplatz nicht  reichte,  um 
den Popup-Hintergrund zu sichern.  Die Popups schicken in diesem  Fall 
eine Redraw-Message ans AES.


      2.3.6.2 popup_select

GLOBAL WORD popup_select (OBJECT *dialtree, WORD btn, OBJECT *poptree,
                          WORD obj, BOOLEAN docheck, WORD docycle,
                          BOOLEAN *ok));

dialtree =  Dialog-Baum

btn = Index  des  Objekts,  das  das Popup  aufruft  (erlaubte  Typen: 
      BoxText, Button, String, Userdef-Boxtext oder Userdef-Button)

poptree = Adresse des Objektbaums, in dem sich das Popupmen befindet

obj = Index  des  Popups.  Die einzelnen Eintrge mssen  aus  Strings 
      oder tastaturbedienbaren Strings (Userdef 19) bestehen.

docheck = Aktiven Popup-Eintrag (mit Button-Text) mit Haken versehen

docycle = DO_POPUP:  Popup anzeigen;
          DO_CYCLE, DO_POPNEXT: nchsten Eintrag darstellen;
          DO_POPPREV: vorherigen Eintrag darstellen

ok =  TRUE,  wenn  Hintergund gesichert werden  konnte,  sonst  FALSE. 
      Wenn ein Nullpointer bergeben wird, wird ok nicht gesetzt.

Rckgabewert =  Der ausgewhlte Eintrag,  oder NIL,  wenn kein Eintrag 
                ausgewhlt wurde.

popup_select verwaltet einen Popup-Button mit einem  Cycle-Button.  Im 
Popup-Button wird immer der Text angezeigt,  der zuletzt im Popup-Men 
ausgewhlt  wurde.  Wenn ein Cycle-Objekt angeklickt wurde,  kann  man 
an  popup_select DO_CYCLE bergeben,  damit die Routine in den  Popup-
Button den nchsten Text des Popups eintrgt.

Wenn man popup_select mit DO_POPUP aufruft,  wird ein Popup  angezeigt 
und  abgearbeitet.  Das  Popup  wird (wenn  mglich)  immer  so  posi-
tioniert,  da  der zuletzt angewhlte Eintrag genau ber  dem  Popup-
Button steht.
 

    2.3.7 Alertboxen

      2.3.7.1 do_alert

GLOBAL WORD do_alert (WORD defbut, CONST BYTE *txt);

do_alert  entspricht  in  den  Parametern  form_alert.   Der   einzige 
Unterschied liegt darin,  da man nicht nur 3 Icons,  sondern 16 Icons 
zur  Verfgung hat.  Die Zahl des gewnschten Icons  wird  hexadezimal 
bergeben,  d.h.  die Werte von 0-F sind erlaubt.  Die einzelnen Icons 
kann man sich in Interface ansehen.

Die MyDial-Alerts verfgen selbstverstndlich ber  tastaturbedienbare 
Buttons. Vor dem Zeichen, das als Shortcut verwendet werden soll, gibt 
man  einfach  eine eckige Klammer ein.  Ein gltiger Alert  mit  einem 
Shortcut auf dem "O" von "OK" knnte also so aussehen:

do_alert (1, "[5][Testalert][[OK]");

Wenn man eine Textzeile des Alert zentriert oder rechtsbndig ausgeben 
mchte,  gibt  man dafr einfach ein spezielles Sonderzeichen  an  der 
ersten Position des Strings ein.  Diese Sonderzeichen sind in MYDIAL.H 
als ALCENTER (\001)  und ALRIGHT (\002) definiert.

Ein Beispielalert:

do_alert (1, "[6][linksbndig|\001zentriert|\002rechtsbndig][[OK]";


      2.3.7.2 dial_alert

GLOBAL WORD dial_alert (BITBLK *alicon, CONST BYTE *string,
                        WORD defbut, WORD undobut, WORD align);

alicon =  Zeiger  auf ein eigenes Icon.  Bei NULL wird die  Iconangabe 
          im String verwendet

string =  Alertstring wie in form_alert

defbut =  Default Exitbutton

undobut = Default  Undobutton;  wird  bei  Druck auf  die  UNDO  Taste 
          selektiert

align = Positionieren   des   Alerttextes:    ALI_LEFT,    ALI_CENTER, 
        ALI_RIGHT  zentrieren  den kompletten  Alerttext  linksbndig, 
        zentriert  oder rechtsbndig.  Die 3 Konstanten sind in  VDI.H 
        definiert.  Einzelne Zeilen knnen durch voranstellen von  AL-
        CENTER oder ALRIGHT anders positioniert werden.

Rckgabewert =  dial_alert  gibt den gleichen Wert wie form_alert  zu-
                rck

dial_alert wird von do_alert aufgerufen.  Mit dial_alert kann man  ein 
eigenes  Image  im Alert anzeigen und  einen  Undo-Button  definieren. 
Wenn  der  Text eines Buttons mit einem Punkt  beginnt,  wird  er  als 
Default-Button  verwendet.  Beginnt er mit einem Doppelpunkt,  ist  es 
der Default-Undobutton.  In diesen beiden Fllen werden die Werte  von 
defbut und undobut ignoriert.


      2.3.7.3 get_icon

GLOBAL BITBLK *get_icon (WORD icon);

icon =  Ziffer zwischen 0 - 15

Rckgabewert =  Zeiger auf die BITBLK-Struktur des entsprechenden  Al-
                ertbox-Icons der MyDials.


      2.3.7.4 al_token

GLOBAL WORD al_token (CONST BYTE *f_alert, BYTE str[8][50],
                      WORD *txtnum, WORD *butnum);

f_alert = Zeiger auf den Alertstring

str = Zeiger auf einen Buffer,  auf den al_token die Strings aufteilen 
      soll

txtnum =  Liefert die Anzahl der Textzeilen des Alerts

butnum =  Liefert die Anzahl der Alertbuttons

Rckgabewert =  Nummer des Alert-Icons (z.B. fr get_icon)

al_token teilt einen Alertstring in einzelne Strings auf und  schreibt 
sie in "str".  Die ersten 5 Strings enthalten den normalen  Text,  die 
restlichen 3 Strings enthalten die Buttontexte


    2.3.8 Diverse ntzlich Hilfsroutinen der MyDials

      2.3.8.1 getcookie

GLOBAL BOOLEAN getcookie (LONG cookie, LONG *p_value);

cookie =  Wert des zu suchenden Cookies

p_value = Zeiger auf die Info-Struktur des Cookies.

Rckgabewert =  Bei TRUE wurde der Cookie gefunden, sonst FALSE.

getcookie  sucht  einen Cookie.  Die MyDials suchen nach  dem  "VSCR"-
Cookie,  um Dialoge auch unter Bigscreen und anderen virtuellen  Bild-
schirmmanagern immer im sichtbaren Teil zu positionieren.


      2.3.8.2 ask_vscr

GLOBAL BOOLEAN ask_vscr (VOID);

Rckgabewert =  Wenn es einen VSCR-Cookie gibt und der  Bildschirmaus-
                schnitt kleiner als der gesamte Bildschirm  ist,  wird 
                TRUE zurckgegeben.

Die  MyDials  fragen mit dieser Funktion,  ob ein  Programm  wie  z.B. 
Bigscreen  installiert ist,  das einen groen Bildschirm  vorspiegelt, 
aber  immer nur einen Ausschnitt davon auf dem Monitor  anzeigt.  Wenn 
das der Fall ist,  zentrieren die MyDials die Dialoge immer auf diesem 
sichtbaren  Teil,  damit  man nicht die ganze Flche nach  dem  Dialog 
absuchen mu.
Einige  Programme  installieren auch  einen  VSCR-Cookie,  obwohl  der 
ganze  Bildschirm angezeigt wird (z.B.  NVDI fr  CrazyDots).  Deshalb 
berprft  diese Funktion auch noch,  ob der sichtbare  Bildschirmaus-
schnitt  vielleicht  mit dem gesamten  Bildschirm  bereinstimmt,  und 
gibt in dem Fall FALSE zurck.


      2.3.8.3 parent

GLOBAL WORD parent (OBJECT *tree, WORD obj);

tree =  Adresse des Dialogbaumes

obj = Adresse des Objekts

Rckgabewert =  parent  liefert das bergeordnete Objekt (Parent)  ei-
                nes  Objekts.  Wenn es kein Parent gibt,  weil  obj  = 
                ROOT war, liefert parent NIL zurck.


      2.3.8.4 get_obspec

GLOBAL LONG get_obspec (OBJECT *tree, WORD obj);

tree =  Adresse des Dialogbaumes

obj = Adresse des Objekts

Rckgabewert =  ob_spec-Wert des Objekts.

get_obspec  liefert auch bei USERDEF-Objekten den  korrekten  ob_spec-
Wert.  Der ob_spec-Wert wird bei der Initialisierung des Objekts durch 
einen Zeiger auf eine USERBLK-Struktur berschrieben.  In dieser USER-
BLK-Struktur  wird der alte ob_spec-Wert wieder  abgelegt.  get_obspec 
liefert  bei USERDEF-Objekten den ursprnglichen ob_spec-Wert aus  der 
USERBLK-Struktur zurck.


      2.3.8.5 set_obspec

GLOBAL VOID set_obspec (OBJECT *tree, WORD obj, LONG obspec);

tree =  Adresse des Dialogbaumes

obj = Adresse des Objekts

obspec =  Neuer ob_spec-Wert

set_obspec  ersetzt den alten ob_spec-Wert eines Objekts  durch  einen 
neuen  Wert.  Bei USERDEF-Objekten wird der neue Wert in die  USERBLK-
Struktur eingetragen.


      2.3.8.6 normkey

GLOBAL UWORD normkey (WORD ks, WORD kr);

ks =  Der  Zustand der Sondertasten.  ks entspricht  dem  drittletzten 
      Parameter von evnt_multi (pks).

kr =  der  ASCII- und Scancode vom  zweitletzten  evnt_multi-Parameter 
      (pkr). Wird von NKCC bentigt, um einen normalisierten Tastatur-
      code zu erzeugen.

Mit  normkey kann man den evnt_multi-Tastencode in den  normalisierten 
NKCC-Tastencode  wandeln.  Dadurch  kann man wesentlich  leichter  und 
sicherer alle Sondertasten und Tastenkombinationen abfragen,  da  NKCC 
tastaturunabhngige  Werte  liefert.  Siehe dazu auch NKCC.H  und  die 
NKCC-Anleitung auf dieser Diskette.


      2.3.8.7 get_idx

GLOBAL WORD get_idx (OBJECT *tree, WORD obj, WORD cpos);

tree =  Adresse des Dialogbaumes

obj = Adresse des Objekts

cpos =  Cursorposition innerhalb eines Editobjekts

Rckgabewert =  Die  absolute Cursorposition.  Wenn das Editobjekt  so 
                aussieht "Datum:  __/__/____",  und der Cursor auf der 
                ersten Position (0) steht,  betrgt die absolute Posi-
                tion 7,  da vor der ersten Cursorposition 7 Buchstaben 
                der Maske stehen.

get_idx  wird von den MyDials intern fr die MyDial-Funktion  obj_edit 
gebraucht.  Auerdem wird es von Interface fr die Fensterdialoge ver-
wendet.


      2.3.8.8 form_Keybd

GLOBAL WORD form_Keybd (OBJECT *tree, WORD edit_obj, WORD next_obj,
                        WORD kr, WORD ks, WORD *onext_obj, UWORD *okr);

tree =  Adresse des Dialogbaumes

edit_obj =  Objektnummer des aktuellen EDIT-Objektes

next_obj =  Ist  momentan  immer 0 und wird nur  aus  Kompatibilitts-
            grnden an form_keybd bergeben

kr =  Enthlt  den  ASCII- und Scancode vom  zweitletzten  evnt_multi-
      Parameter (pkr).  Wird von NKCC bentigt,  um einen normalisier-
      ten Tastaturcode zu erzeugen.

ks =  Enthlt  den Zustand der Sondertasten und entspricht dem  dritt-
      letzten Parameter von evnt_multi (pks).

onext_obj = Enthlt  nach  der Rckkehr das  nchste  Editobjekt  (das 
            Objekt, auf dem der Cursor stehen soll).

okr = Entspricht kr.

Rckgabewert =  siehe form_keybd

form_Keybd  entspricht  form_keybd.  Es  ruft nur  vor  der  Shortcut-
Auswertung  und  vor der Ausfhrung von  form_keybd  die  einklinkbare 
Tastaturroutine auf (siehe set_Keybd).  form_Keybd wird intern von den 
MyDials und von Interface fr die Fensterdialoge verwendet.


      2.3.8.9 shortcut

GLOBAL WORD shortcut (OBJECT *tree, WORD startobj, WORD ks, WORD kr);

tree =  Adresse des Dialogbaumes

startobj =  Anfangsobjekt, dessen Childs auf Shortcuts untersucht wer-
            den sollen

ks =  Enthlt  den Zustand der Sondertasten und entspricht dem  dritt-
      letzten Parameter von evnt_multi (pks).

kr =  Enthlt  den  ASCII- und Scancode vom  zweitletzten  evnt_multi-
      Parameter (pkr).  Wird von NKCC bentigt,  um einen normalisier-
      ten Tastaturcode zu erzeugen.

Rckgabewert =  Objektindex  des Objekts,  da den  Shortcut  enthlt. 
                Wenn  der  Shortcut nicht  gefunden  wurde,  wird  NIL 
                zurckgegeben.

shortcut  wird  intern  von  den MyDials und  von  Interface  fr  die 
Fensterdialoge verwendet.


      2.3.8.10 obj_edit

GLOBAL WORD obj_edit (OBJECT *ob_edtree, WORD ob_edobject, WORD kstate,
                      WORD ob_edchar, WORD *ob_edidx, WORD ob_edkind,
                      WORD mode, WORD *next_obj, WORD winhndl));

ob_edtree = Adresse des Dialogbaumes

ob_edobject = Objektnummer des aktuellen EDIT-Objektes

kstate =  Enthlt  den  Zustand der Sondertasten  und  entspricht  dem 
          drittletzten Parameter von evnt_multi (pks).

ob_edchar = Enthlt   den   ASCII-  und  Scancode   vom   zweitletzten 
            evnt_multi-Parameter  (pkr).  Wird von NKCC  bentigt,  um 
            einen normalisierten Tastaturcode zu erzeugen.

ob_edidx =  Cursorposition innerhalb des Objekts

ob_edkind = Art der Editfunktion
            ED_INIT:  obj_edit initialisieren, Cursor einschalten
            ED_CHAR:  Zeichen verarbeiten
            ED_END :  Cursor wieder ausschalten

mode =  TRUE:   obj_edit  macht keine Bildschirmausgaben und fgt  das 
                Zeichen nur in den Editstring ein.  Dadurch verhindert 
                man  ein hektisches Geflacker,  wenn  mehrere  Zeichen 
                auf  einmal eingefgt werden sollen  (z.B.  Clipboard-
                String  in  Editfeld  einfgen).  TRUE  wird  nur  von 
                obj_edit  intern verwendet,  um sich  rekursiv  selbst 
                aufzurufen.
        FALSE:  Bildschirmausgaben sind erlaubt (Default-Mode)

next_obj =  Enthlt das nchste Edit-Objekt.  Wird u.U.  von  obj_edit 
            gendert.

winhndl = winhndl  ist ein Fensterhandle.  Wenn winhndl  ungleich  NIL 
          ist,  wird  der Cursor ber die Rechteckliste  des  Fensters 
          gezeichnet,  zu der winhndl gehrt.  Wird von Interface  fr 
          die Fensterdialoge verwendet.

obj_edit  wird  von  den  MyDials intern und  von  Interface  fr  die 
Fensterdialoge verwendet.  Durch das eigene obj_edit wurden die ganzen 
besonderen Tastaturfunktionen der MyDials verwirklicht.


      2.3.8.11 scrap_clear

GLOBAL WORD scrap_clear (VOID);

scrap_clear lscht das GEM-Clipboard.

Alle MyDial-Clipboard-Routinen knnen nur funktionieren,  wenn  irgend 
ein  Programm  bereits den Clipboard-Pfad mit  scrp_write  eingestellt 
hat.  Das  Hauptprogramm  sollte  also vor  dem  MyDial-Einsatz  (wenn 
ntig)  den  Clipboard-Pfad setzen und  ggfs.  einen  Clipboard-Ordner 
erzeugen.


      2.3.8.12 ascii_head

GLOBAL VOID ascii_head (BYTE *header);

header =  Ein  Zeiger  auf  die neue  berschrift  der  MyDial  ASCII-
          Tabelle.

Da  man  die MyDial-Resource bestenfalls  mit  einem  Diskettenmonitor 
ndern  knnte  gibt es diesen Aufruf,  damit man damit  den  einzigen 
deutschsprachigen Text der MyDials ndern kann.  ascii_head ndert nur 
den Zeiger des Textes,  d.h. der bergebene Text mu auch weiterhin an 
der alten Stelle bleiben und darf nicht berschrieben werden.


      2.3.8.13 my_menu_key

GLOBAL BOOLEAN my_menu_key  (OBJECT *menu, MKINFO *mk, WORD *title,
                             WORD *item);

menu  = Menbaum
mk    = Struktur, die die gedrckte Taste beschreibt
title = Enthlt als Ergebnis den Mentitel von "item"
item  = Enthlt  als  Ergebnis den Meneintrag,  zu dem  der  Shortcut 
        pat
Rckgabewert =  TRUE, wenn der Shortcurt gefunden wurde, sonst FALSE

my_menu_key  sucht in einem Menbaum nach einem Shortcut.  In  mk  mu 
die Taste beschrieben werden,  nach der die Funktion suchen soll.  Die 
MKINFO-Struktur ist in MGLOBAL.H definiert.
Die  MKINFO-Struktur mu wie folgt mit den  evnt_multi-Werten  gefllt 
werden:

/* direkt hinter dem Haupt-evnt_multi folgt: */
mk.scan_code = mk.kreturn;
mk.kreturn = normkey (mk.kstate, mk.kreturn);
if (mk.kreturn & NKF_SHIFT)     /* beide SHIFT Tasten setzen */
  mk.kreturn |= NKF_SHIFT;
mk.kreturn &= ~NKF_CAPS;        /* CAPSLOCK lschen */
mk.shift  = (mk.kstate & (K_RSHIFT | K_LSHIFT)) != 0;
mk.ctrl   = (mk.kstate & K_CTRL) != 0;
mk.alt    = (mk.kstate & K_ALT) != 0;

mk.kstate  und mk.kreturn enthalten vor der Ausfhrung  dieser  Zeilen 
die Rckgabewerte kstate und kreturn von evnt_multi.

Wenn  man  die  Gei-Librarys verwendet,  kann  man  die  Gei-Routine 
is_menu_key durch my_menu_key ersetzen.  my_menu_key erkennt auch kom-
binierte Shortcuts wie z.B. Shift-Control-U.


      2.3.8.14 get_sysfnt

GLOBAL BOOLEAN get_sysfnt (WORD vdi_handle, WORD *font_id, 
                       WORD *gl_point, WORD *gl_wchar, WORD *gl_hchar);

vdi_handle = aktuelle Workstation
font_id    = liefert die Systemfont ID (s. vst_font)
gl_point   = liefert die Punktgre des Systemfonts (s. vst_point)
gl_wchar   = liefert die Breite des Sytemfonts
gl_hchar   = liefert die Hhe des Systemfonts (s. vst_height)

get_sysfnt wird von den MyDials beim ffnen der Workstation verwendet, 
um  den  aktuellen Systemfont und die Zeichengre  zu  erfragen.  Die 
Funktion liefert auch unter MultiTOS korrekte Ergebnisse.
Auerdem  setzt  die Funktion fr die bergebene Workstation  den  er-
mittelten Systemfont.


  2.4 Ein Beispielprogramm fr die Dialogbearbeitung

HndlDial  arbeitet einen Dialog komplett ab,  deshalb erspare ich  mir 
dafr  ein  Beispiel.   Wenn  man  einen  Dialog  mit  open_dial   und 
close_dial abarbeiten mu,  um u.U.  Touchexit-Objekte auszuwerten und 
Teile des Dialoges neu zu zeichnen, kann man wie folgt vorgehen:


LOCAL VOID show_form (tree, editobj)
OBJECT *tree;
WORD   editobj;

{ WORD     but, zw;
  DIALINFO di;

  open_dial (tree, TRUE, NULL, &di);

  dial_draw (&di);

  /* Solange Touchexit-Objekte angeklickt wurden, soll der Dialog */
  /* nicht verlassen werden.                                      */

  do
  {
    but = dial_do (&di, editobj) & 0x7fff;
    tree[but].ob_state &= ~SELECTED;
    objc_draw (tree, ROOT, MAX_DEPTH, di.x, di.y, di.w, di.h);
  }
  while (tree[but].ob_flags & TOUCHEXIT);

  close_dial (FALSE, NULL, &di);
}


3   Dialoge in Fenster legen

Es ist nicht besonders schwer,  einen Dialog in ein Fenster zu  legen, 
es ist nur viel Arbeit :-) Im Prinzip funktioniert es so:

1.  Man ffnet ein Fenster mit der Gre des Dialoges.

2.  Man  zeichnet  den  Dialog in das Fenster  mit  dem  Clipping  der 
    Fensterrechteckliste.

3.  Der  Fenster-form_do  (den  Sie noch  programmieren  mssen)  wird 
    angesprungen, wenn...
    - sich  der Dialog im obersten Fenster befindet und  Ihr  Programm 
      ein Tastaturevent gemeldet bekommt.
    - Ihnen  ein  Button-Event gemeldet wurde und unter der  Maus  der 
      Fensterdialog liegt.

4.  Wenn ein Exit- oder Touchexit-Objekt angeklickt wurde,  wird  eine 
    Routine angesprungen,  die das Objekt auswertet und  zurckmeldet, 
    ob der Dialog nach der Auswertung geschlossen werden soll.


Damit das ganze auch funktioniert,  mu man natrlich wissen,  wie der 
form_do  (oder besser noch dial_do) Befehl intern arbeitet.  Denn  man 
mu  ja  die Ereignisse genauso verarbeiten,  damit  es  keine  Unter-
schiede in der Handhabung des Dialoges gibt.  Deshalb folgt jetzt  der 
MyDial-dial_do Source:


/*****************************************************************************/

GLOBAL WORD dial_do (di, edit_obj)
DIALINFO *di;
WORD     edit_obj;

{ WORD  but;

  do
  {
    but = form_xdo (di->Tree, edit_obj);
    if ((di->Tree[but & 0x7fff].ob_type >> 8) == DIALMOVER)   /* Dial Mover */
    {
      graf_mouse (FLAT_HAND, NULL);
      dial_move (di, mydesk.x, mydesk.y, mydesk.w, mydesk.h);
      graf_mouse (*my_mousnumber, *my_mousform);
    }
    else
      return (but);
  }
  while (TRUE);
}

/*****************************************************************************/

LOCAL WORD find_obj (tree, start_obj, which)
OBJECT *tree;                       /* routine to find the next editable */
WORD   start_obj;                   /* text field, or a field that is as */
WORD   which;                       /* marked as a default return field. */

{ WORD obj, flag, theflag, inc;

  obj = 0;
  flag = EDITABLE;
  inc = 1;

  switch (which)
  {
    case FMD_BACKWARD:
      inc = -1;                    /* fall thru */
    case FMD_FORWARD:
      obj = start_obj + inc;
      break;
    case FMD_DEFLT:
      flag = DEFAULT;
      break;
  }

  while (obj >= 0)
  {
    theflag = tree[obj].ob_flags;

    if (theflag & flag)
     return (obj);

    if (theflag & LASTOB)
     obj = -1;
    else
     obj += inc;
  }

  return (start_obj);
}

/*****************************************************************************/

LOCAL WORD fm_inifld (tree, start_fld)
OBJECT *tree;
WORD   start_fld;

{
  if (!start_fld)         /* position cursor on the starting field */
    start_fld = find_obj(tree, 0, FMD_FORWARD);

  return (start_fld);
}

/*****************************************************************************/
/* Neue form_do Routine                                                      */
/*****************************************************************************/

LOCAL WORD form_xdo (tree, start_fld)
OBJECT *tree;
WORD   start_fld;

{ WORD   edit_obj;
  WORD   next_obj;
  WORD   which, cont;
  WORD   idx, len, wbox;
  WORD   mx, my, mb, ks, br;
  UWORD  kr, knorm;
  RECT   work;
  TEDINFO *ob_spec;

  wind_update (BEG_UPDATE);
  wind_update (BEG_MCTRL);

  /* set starting field to edit, if want first editing field then walk tree */
  next_obj = fm_inifld (tree, start_fld);
  edit_obj = 0;

  cont = TRUE;                              /* interact with user */
  while (cont)
  {
    /* position cursor on the selected editting field */
    if ((next_obj != 0) && (edit_obj != next_obj))
    {
      edit_obj = next_obj;
      next_obj = 0;
      obj_edit(tree, edit_obj, 0, 0, &idx, EDINIT, FALSE, &edit_obj, NIL);
    }
                                            /* wait for mouse or key */
    which = evnt_multi(MU_KEYBD | MU_BUTTON,
                  0x02, 0x01, 0x01,
                  0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0,
                  NULL,
                  0, 0,
                  &mx, &my, &mb, &ks, &kr, &br);

    if (which & MU_KEYBD)                   /* handle keyboard event*/
    {
      knorm = normkey (ks, kr);
      {
        if ((tree[edit_obj].ob_flags && FLAGS15) && (knorm == (NKF_FUNC|NK_UP) &&
            find_prev (tree, edit_obj) != NIL) || (knorm == (NKF_FUNC|NK_DOWN) &&
            find_next (tree, edit_obj) != NIL))
        {
          obj_edit(tree, edit_obj, ks, kr, &idx, EDCHAR, FALSE, &edit_obj, NIL);
          next_obj = edit_obj;
          kr = 0;
        }
        else
          cont = form_Keybd(tree, edit_obj, next_obj, kr, ks, &next_obj, &kr);
      }

      if (kr)
      {
        obj_edit(tree, edit_obj, ks, kr, &idx, EDCHAR, FALSE, &edit_obj, NIL);
        next_obj = edit_obj;
      }
      else
        if ((tree[edit_obj].ob_flags & EXIT) && edit_obj != next_obj && cont)
        {
          next_obj = edit_obj;
          cont = edit_obj = FALSE;
        }
    }

    if (which & MU_BUTTON)                  /* handle button event  */
    {
      next_obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
      if (next_obj == NIL)
      {
        mybeep();
        next_obj = 0;
      }
      else
      {
        cont = form_button(tree, next_obj, br, &next_obj);

        if ((tree[edit_obj].ob_flags & EXIT) && edit_obj != next_obj && cont)
        {
          next_obj = edit_obj;
          cont = edit_obj = FALSE;
        }
        if (cont && (tree[next_obj].ob_flags & EDITABLE))
        {
          if (next_obj != edit_obj)
          {
            obj_edit(tree, edit_obj, ks, 0, &idx, EDEND, FALSE, &edit_obj, NIL);
            edit_obj = next_obj;
            next_obj = 0;
          }
          objc_rect(tree, edit_obj, &work, FALSE);

          ob_spec = (TEDINFO *)get_obspec(tree, edit_obj);

          if (ob_spec->te_font == SMALL)
            wbox = 6;
          else
            wbox = mygl_wbox;

          switch (ob_spec->te_just)
          {
            case TE_RIGHT:
              work.x += work.w - wbox * (ob_spec->te_tmplen - 1);
              break;
            case TE_CNTR:
              work.x += (work.w - wbox * (ob_spec->te_tmplen - 1)) / 2;
              break;
          }
          idx = (mx - work.x + wbox / 2) / wbox;
          len = ob_spec->te_tmplen - 1;
          if (idx > len)
            idx = len;
          idx = get_idx (tree, edit_obj, idx);
          obj_edit(tree, edit_obj, ks, 0, &idx, EDCHAR, FALSE, &edit_obj, NIL);
        }
      }
    }
    /* handle end of field, clean up */
    if ((!cont) || ((next_obj != 0) && (next_obj != edit_obj)))
      obj_edit(tree, edit_obj, ks, 0, &idx, EDEND, FALSE, &edit_obj, NIL);
  }

  wind_update(END_MCTRL);
  wind_update(END_UPDATE);

  /* return exit object, hi bit may be set if exit obj. was double-clicked */
  return (next_obj);
}

Alle Routinen,  die von form_xdo aufgerufen werden,  sind in  MYDIAL.H 
von auen zugngig.  Man mu also eigentlich nur noch das aufgetretene 
Event  an  die  Routine  bergeben  und  es  anstelle  des   form_xdo-
evnt_multi auswerten.  Etwas komplizierter ist es zwar schon, aber mit 
diesen  Routinen sollte jeder,  der sich etwas mit Fenstern  auskennt, 
seine Dialoge in Fenster legen knnen.

Etwas leichter haben es alle,  die die Gei-Routinen aus dem Buch "Vom 
Anfnger  zum GEM-Profi" 2.Auflage benutzen.  In der 2.Auflage  werden 
nmlich bereits Fensterdialoge benutzt und man braucht eigentlich  nur 
noch  im Modul WINDOW.C die Routinen "click_window"  und  "key_window" 
an die MyDials anzupassen.

In Interface kann man jederzeit zwischen Fensterdialogen und  normalen 
Dialogen umschalten,  weil Interface einfach die Dialogberschrift  in 
den  Fenstertitel bernimmt und das Fenster so klein  macht,  da  die 
FlyDial-Ecke und die Dialogberschrift nicht angezeigt werden.

Wie  bereits  schon oben gesagt,  helfe ich jedem  gerne  weiter,  der 
Fragen zu dem Thema hat.

form_xdo  basiert brigens auf dem Original Digital Research  form_do-
Source. Ich habs nur "etwas" an die MyDials angepat.


D A S   W A R ' S
Tippfehler  sind wie immer absichtlich im Text versteckt  worden.  Wer 
alle findet, bekommt einen Keks!

