
   Dokumentation zu GEMLIB.A
   Geschrieben mit und fr Sozobon-C
   von Holger Weets
   benutzt wurde die GEMFAST - Bibliothek Version 1.31
   Stand: 11.09.91, Version 2.0

   Kurz-bersicht:
      void fm_center(OBJECT *addr)
      void fm_mcenter(OBJECT *addr)
      void fm_sdial(OBJECT *addr)
      void fm_fdial(OBJECT *addr)

      void i_rmbut()
      void e_rmbut()

      void val_save(OBJECT *addr)
      void val_restore(OBJECT *addr, flag)

      int mousex()
      int mousey()
      int mousebut()

      void m_type(int maustyp)
      void m_arrow()
      void m_bee()
      void show_mouse()
      void hide_mouse()

      void ob_draw(OBJECT *addr, int index)

      char *gt_ptext(OBJECT *addr, int index)

      int fsel(char *name, char *titel)
      int fsel_e(char *name, char *titel, char *extension)
      int fsel_exinput(char *path, char *name, int *button, char *title)

      void sbitblt(int x1, int y1, int w, int h, int x2, int y2, int modus)
      void mbitblt(int x, int y, int w, int h, char *mem, int flag)

      int vwk_open()
      int vq_gdos()

      int dialog(OBJECT *addr)
      int adialog(OBJECT *addr)

      char *scr_save(OBJECT *addr)
      void scr_restore(OBJECT *addr, char *mem)


   Beschreibung der Funktionen:

   void fm_center(OBJECT *addr)
      Diese Funktion zentriert einen Objekt-Baum in der Mitte des Bild-
      schirmes. Da bei Verwendung der GEMLIB-Fnktionen die bei form_center()
      anzugebenen x/y/w/h - Koordinaten nicht bentigt werden, wurde diese
      Funktion implementiert.


   void fm_mcenter(OBJECT *addr)
      Diese Funktion richtet einen Objekt-Baum nach der Position der Maus
      aus. Wenn mglich, erscheint der Dialog so auf dem Bildschirm, da
      seine linke obere Ecke mit der Mausposition identisch ist. Es ist
      immer gewhrleistet, da der Dialog nicht aus dem Bildschirm hinaus-
      ragt und nicht in die Menue-Zeile rutscht.


   void fm_sdial(OBJECT *addr)
      Diese Funktion ist eine Kurzform von
         form_dial(FMD_START, ...)


   void fm_fdial(OBJECT *addr)
      Diese Funktion ist eine Kurzform von
         form_dial(FMD_FINISH, ...)


   int mousex()
      Diese Funktion liefert die X-Position der Maus.


   int mousey()
      Diese Funktion liefert die X-Position der Maus.


   int mousebut()
      Diese Funktion liefert den Zustand der Maustasten.
      Die drei letztgenannten Funktionen bedienen sich der Funktion
      graf_mkstate(). Sie haben den Vorteil, da niemals berflssige
      Parameter bergeben werden, auerdem verkrzt die Verwendung dieser
      Funktionen die Programmlnge.

      Die drei letztgenannten Funktionen wurden in Assembler geschrieben
      und befinden sich im selben Modul. Zusammen sind sie nur unwesentlich
      lnger, als ein (!) Aufruf von graf_mkstate().


   void i_rmbut()
      Diese Funktion installiert eine Funktion zur berlistung von GEM,
      was die Abfrage der rechten Maustaste angeht. Insbesondere mit der
      evnt_multi() - Funktion ist es nicht mglich, gleichzeitig die
      linke und die rechte Maustaste abzufragen.
      Diese Funktion behebt diesen Mangel: der multi() - Aufruf liefert zwar
      immer noch als Ereignis die linke Maustaste, jedoch kann die wirklich
      gedrckte Taste aus dem Wert der Variablen <char rmbut> abgelesen
      werden: ist sie ungleich 0, so wurde die rechte Maustaste gedrckt,
      ansonsten die linke.
      Da fr die Installation der Routine das VDI bentigt wird, mu eine
      globale Variable <int vwk_handle> existieren, in der das Handle der
      geffneten Workstation steht.


   void e_rmbut()
      Diese Funktion ist das Gegenstck zu i_rmbut() und mu UNBEDINGT
      sptestens am Ende des Programmes aufgerufen werden. Am Besten wie
      folgt vorgehen:
         .
         .
         i_rmbut();
         event = evnt_multi(...);
         e_rmbut();
         .
         .

   int vwk_open()
      Diese Funktion fhrt die Standard-Anmeldung beim VDI durch, indem eine
      virtuelle Workstation geoeffnet und deren Handle als Funktions-Ergebnis
      zurckgeliefert wird. Dieses Handle sollte in eine globale Variable
      geschrieben werden, damit das Abmelden am Ende des Programmes ordnungs-
      gem ablaufen kann.


   int fsel(char *name, char *titel)
      Diese Funktion dient dazu, einen Dateinamen per Fileselectbox zu holen.
      Je nach Betriebs-System wird die jeweils neuste Fileselectbox benutzt,
      um den Dateinamen einzulesen. (Dazu mu AES mit appl_init() initiali-
      siert worden sein und somit in global[] Werte stehen)
      Der Default-Name wird in <name> mitgegeben, in dieser Variablen wird
      auch der vollstndige Name der gewhlten Datei zurckgeliefert. Der
      String in <titel> dient als berschrift, bei der alten Fileselectbox
      wird er ber diese in einer weien Box dargestellt, ansonsten direkt
      in ihr. Achtung: die Box-Attribute der Workstation werden verndert.

      Exportiert werden die Variablen
         char pfad[]
      und
         char lastfile[]

      In <pfad> steht der zuletzt verwendete Pfad, er wird ebenfalls ver-
      wendet, falls <name> leer oder unvollstndig ist. Diese Variable wird
      berschrieben.
      In <lastfile> steht der zuletzt verwendete Dateiname, dieser wird
      verwendet, wenn <name> leer ist.
      Auf diese Variable kann zugegriffen werden durch die Deklaration
         'extern char lastfile[], pfad[];'.

      Zurckgegeben wird der gedrckte Knopf, also
         1: OK
         0: ABBRUCH


   int fsel_e(char *name, char *titel, char *extension)
      Funktioniert wie fsel(), nur da hier zustzlich eine Endung mitgegeben
      wird (bei fsel() ist dies immer '*.*')
      Die Extension wird hierbei OHNE '*.' angegeben.
      Beispiel: fsel_e(name, "select file", "C")


   int fsel_exinput(char *path, char *name, int *button, char *title)
      Diese Funktion ersetzt die aus AESFAST, welche die Tests selbst
      durchfhrt, ob nun TOS >= 1.04 aktuell ist, und im negativen
      Fall eine Simulation der neuen Box mit der alten vornimmt. Damit
      wre die Simulation bei Verwendung der fsel-Funktionen aus GEMLIB
      jedoch doppelt vorhanden! Da meine Simulation genauso gut funktio-
      niert, seine jedoch erheblich lnger ist, habe ich ein neues
      Binding hierfr geschrieben. Alle betreffenden Programme sollten
      etwa 700 Bytes krzer werden (!)


   void ob_draw(OBJECT *addr, int index)
      Diese Funktion ist eine Kurzform von
         objc_draw(addr, index, 8, 0, 0, 0, 0);


   int dialog(OBJECT *addr)
      Diese Funktion fhrt einen vollstndigen Standard-Dialog aus.
      Der Dialog wird zunchst zentriert und gezeichnet.
      Dann wird die AES-Funktion form_do() aufgerufen, und aus deren Ergebnis
      das Bit 15 (Kennzeichnung fr: Dialog wurde mit Doppelklick verlassen)
      ausgefiltert, die Abstrze wegen vergessener Abfrage auf dieses Bit
      gehren also der Vergangenheit an.
      Ist der Dialog beendet, so wird er (mit fm_fdial(), siehe dort) vom
      Bildschirm verbannt, sptestens nach dem nchsten redraw() ist er weg.
      Auerdem wird der Status des Exit-Objektes, der vom GEM auf SELECTED
      gesetzt wird, wieder in den alten Zustand berfhrt.

      Zurckgegeben wird (natrlich) die Nummer des Exit-Buttons.


   int adialog(OBJECT *addr)
      Funktioniert wie dialog(), nur da der Bildschirm-Hintergrund mittels
      scr_save() gerettet und mit scr_restore() (siehe dort) wieder-
      hergestellt wird, was bei Programmen, die mit Fenstern arbeiten,
      einen betrchtlichen Geschwindigkeits-Vorteil bringt.


   char *scr_save(OBJECT *addr)
      Diese Funktion berechnet aus <addr>, welcher Teil des Bildschirmes
      durch da Objekt verdeckt wrde, und rettet diesen. Hierzu wird ein
      entsprechend groer Speicher per malloc() geholt und der Bildschirm-
      Ausschnitt mittels mbitblt() in diesen kopiert.
      Zurckgeliefert wird ein Zeiger auf diesen Speicherbereich.


   void scr_restore(OBJECT *addr, char *mem);
      Diese Funktion ist das Gegenstck zu scr_save(). Sie stellt den durch
      das Objekt <addr> verdeckten Bildschirm-Ausschnitt wieder her und gibt
      den dafr bentigten Speicher wieder frei.


   void sbitblt(int x1, int y1, int w, int h, int x2, int y2, int modus)
      Diese Funktion kopiert den rechteckigen Bildschirm-Ausschnitt
      (x1, y1, w, h) an die Bildschirm-Position (x2, y2, w, h), wobei
      <modus> der Verknpfungs-Modus ist (die Werte hierfr knnen z.B. im
      Profibuch oder im Programmierer-Lexikon nachgelesen werden).

      Diese Routine luft in allen Auflsungen und erwartet einen
      globalen Parameter namens <vwk_handle>, in dem das Handle einer
      virtuellen Workstation (open_vwk() ) steht.
      Auer <modus> sind natrlich alle Parameter Pixel-Koordinaten, und be-
      nutzt wird die VDI-Funtion vro_cpyfm().
      Das Maus ein- und aus-schalten ist in dieser Funktion bereits enthalten.


   void mbitblt(int x, int y, int w, int h, char *mem, int flag)
      Diese Funktion kopiert einen rechteckigen Bildschirm-Ausschnitt in
      den Speicher und umgekehrt.
      Ist <flag> ungleich 0, so wird der Bildschirm-Ausschnitt (x,y,w,h)
      an die Adresse <mem> kopiert (VORSICHT: an dieser Adresse mu gengend
      Speicher zur Verfgung stehen !!!)
      Wenn <flag> hingegen gleich 0 ist, dann wird der Speicherbereich ab
      <mem> in den Bildschirm-Ausschnitt (x,y,w,h) kopiert. Da sich VDI die
      ursprngliche Gre des im Speicher befindlichen BIT-Blocks nicht merkt,
      kommt es zu merkwrdigen Effekten, wenn die ursprngliche Breite nicht
      mit der aktuellen bereinstimmt.
      TIP: Breite und Hhe in die ersten beiden Words des Speicherbereiches
           schreiben, und als Parameter dann
           *mem     fr w,
           *(mem+1) fr h und
           mem+2    fr mem bergeben.
      Auch diese Funktion arbeitet in allen Auflsungen und erwartet
      einen globalen Parameter namens <vwk_handle> (Bedeutung siehe oben).
      Vor Aufruf dieser Funktion sollte die Maus ausgeschaltet werden, da
      sie sonst evtl. berschrieben bzw. mitkopiert wird. Das Maus ein-
      und ausschalten wurde hier untrlassen, damit sich diese Funktion
      auch zur Verwendung in USERDEF-Objekten eignet.


   void hide_mouse()
      Diese Funktion schaltet die Maus aus (graf_mouse()).


   void show_mouse()
      Diese Funktion schaltet die Maus ein. (graf_mouse()). Da GEM die Auf-
      rufe von M_OFF und M_ON mitzhlt, mssen immer genausoviele show_mouse()
      Aufrufe gettigt werden, wie vorher hide_mouse() Aufrufe gemacht wurden,
      damit die Maus wieder sichtbar wird.


   void m_type(int maustyp)
      Diese Funktion setzt den Mautyp per graf_mouse().


   void m_arrow()
      Diese Funktion setzt das Aussehen der Maus auf die Pfeil-Form.


   void m_bee()
      Diese Funktion setzt das Aussehen der Maus auf die Bienen-Form.

      Die fnf letztgenannten Funktionen wurden in Assembler geschrieben
      und befinden sich alle im selben Modul. Dadurch sind alle Funktionen
      zusammen nur etwa so lang, wie zwei graf_mouse() - Aufrufe in C.


   void val_save(OBJECT *addr)
      Diese Funktion merkt sich die Zustnde aller vernderlichen Objekte
      in einer Dialogbox. Es sind dies all diejenigen Objekte, bei denen
      entweder das SELECTABLE-, EXIT-, TOUCHEXIT- oder EDITABLE- Flag gesetzt
      sind.
      Bei editierbaren Objekten wird der zu editierende String kopiert
      (<te_ptext> aus dem TEDINFO), und bei den anderen Objekten wird
      der Wert von <ob_state> kopiert.
      val_save() wird im Zusammenhang mit der folgenden Funktion verwendet,
      um die Programmier-Arbeit, die fr die Umsetzung eines Abbruch-Knopfes
      ntig ist (alle nderungen rckgngig zu machen), einzusparen.


   void val_restore(OBJECT *addr, int flag)
      Diese Funktion ist sozusagen das Gegenstck zu val_save(). Wird fr
      <flag> ein Wert ungleich 0 bergeben, so werden alle nderungen, die
      seit dem Aufruf von val_save() am Dialog per form_do durchgefhrt
      wurden, rckgngig gemacht.
      Wird <flag> zu 0 bergeben, so werden nur die Kopien der vernderlichen
      Objekt-Parameter gelscht.
      Beispiel:
         Bisher sah eine Dialog-Routine etwa so aus:

         int merk1, merk2, ...;
         char t1[50], t2[50], ...;
         merk1 = Test[KNOPF1].ob_state;      /* Knopf 1 merken */
         merk2 = Test[KNOPF2].ob_state;      /* Knopf 2 merken */
         .
         .
         /*** Strings merken ***/
         strcpy(t1, ((TEDINFO *)(Test[EDIT1].ob_spec)->te_ptext);
         strcpy(t2, ((TEDINFO *)(Test[EDIT2].ob_spec)->te_ptext);
         .
         .
         box_draw(Test);
         erg = form_do(Test, 0);
         box_undraw(Test);
         if (erg == CANCEL) {             /* Shit: Abbruch... */
            Test[KNOPF1].ob_state = merk1;
            Test[KNOPF2].ob_state = merk2;
            .
            .
            strcpy(((TEDINFO *)(Test[EDIT1].ob_spec)->te_ptext, t1);
            strcpy(((TEDINFO *)(Test[EDIT2].ob_spec)->te_ptext, t2);
            .
            .
         }

      Mit den beschriebenen Funktionen sieht das ganze so aus:

         val_save(Test);                     /* alle Werte retten */
         box_draw(Test);                     /* Dialog zeichnen */
         erg = form_do(Test, 0);             /* ausfllen lassen */
         box_undraw(Test);                   /* Dialog entfernen */
         val_restore(Test, (erg == CANCEL)); /* alte Werte ggfls. */
                                             /* wiederherstellen */

      Man stelle sich die Code-Einsparung bei 20 solcher Funktionen mit
      jeweils 10 Knpfen und 5 Edit-Feldern vor ...


   char *gt_ptext(OBJECT *addr, int index)
      Diese Funktion liefert einen Zeiger auf das Textfeld in der TEDINFO-
      Struktur des Objektes addr[i], ist also eine Kurzform von
         p = ((TEDINFO *)addr[i].ob_spec)->te_ptext
      Die Funktion hat den Vorteil der besseren Lesbarkeit und macht
      Programme, die hufig TEDINFO's auslesen, krzer.


   int vq_gdos()
      Diese Funktion testet, ob GDOS installiert ist, oder nicht. Falls
      nicht, so liefert sie 0, einen Wert ungleich 0 sonst. Diese Funktion
      ist unverndert aus dem Profibuch bernommen worden.


