 WDIALOG
 =======

 As of: 05.03.96 (V1.04)

 (c) 1996 by Sven & Wilfried Behne

 Intentions, conditions, ovations
 --------------------------------

 The user interface under GEM has been  highly developed the last ten years.
 Present-day programs work with window  dialogs,  radio buttons, check boxes
 and much more.
 Since these extensions haven't been integrated  in TOS, programmers have to
 repeatedly "reinvent the wheel": In most cases the program is linked with a
 library that only assumes the AES  functions  of the earliest TOS versions.
 All extensions are realized through the program code of the library.

 Unfortunately this has the disadvantage of causing the program size to grow
 considerably (which in  multitasking  contexts  costs  just  the memory you
 don't have) "merely" for reasons of visual appearance, and the abilities of
 newer OS versions are not or only partially used.

 Hence, we have chosen a different approach with the following stipulations:

 - Compact, resident extension makes often  needed routines (window dialogs,
   list boxes and font selector) available.

 - High degree of flexibility of the routines;  i.e. no static limits in the
   number of dialogs  or  simultaneously  open  font  selectors;  List boxes
   capable of dealing with more than just text objects, multiple selections,
   auto-scrolling, etc. ...

 - Advantages and extensions of the  OS  should  be  put to use (3D effects,
   clipboard in edit fields, ...).

 - Extended object types (group names,  radio  buttons, etc.) are assumed to
   be available, so that the RSC file stays compact.

 - Object types  missing  in  older  OS  versions  should  be  automatically
   generated through a short routine (-> ADAPTRSC.C).

 - The design of the program interface  should  fit the "personality" of the
   OS (no "dino-tuning" with 3D effects under TOS 1.0).

 From this WDIALOG has emerged. A system extension of 29 kB size, that makes
 available MagiC 4 compatible AES extensions.


 Installation
 ------------

 Copy WDIALOG.PRG to the AUTO folder and restart the system.


 Conditions
 ----------

 The documentation to WDIALOG and  the  archive  contents of WDIALOG.LZH are
 Public Domain, i.e. can be freely copied  and used. The archive may only be
 distributed in its entirety!
 It is allowed to change the source files for own requests.
 It is however NOT allowed to circulate these changed files.
 Selling them for money is _prohibited_.

 Distribution of WDIALOG together with  other  software products is allowed,
 as long as _no_ additional cost  thereby  is introduced to the customer and
 the recommended retail price of this software does not exceed 50 DM.

 ** Exceptions require written consent of the authors!
 Violations will be prosecuted. **

 The copyright remains solely with the authors, Sven & Wilfried Behne

 To WDIALOG.LZH belong the following files:

    - DOC_WDLG.TXT
    - WDIALOG.PRG
    - SAMPLE  folder  with  the   programs   and  sources  to  WDLG_SMP.APP,
      XOBJ_SMP.APP, FNT_SMPL.APP and FNT_SMP2.APP.
    - Snapshots of example programs under  TOS  1.04  and MagiC 4 (16-colour
      IMGs).

 We have of course always an  open  ear  for requests, suggestions and error
 corrections.


 Ausschlu der Haftung
 =====================

 The responsibility for direct and indirect damage, consequential damage and
 third  party  damage  through  use  of  the  system  extension  WDIALOG  is
 disclaimed. Absolutely no guarantees  are  given regarding the completeness
 or correctness of made statements.

 Disclaimer
 ----------
 Most of the products  mentioned  here  are  protected  by  trade marks. The
 missing of separate references does not  mean  that these products are free
 from third party rights.



 WDIALOG Programmer's Guide
 ==========================

 As of: 8.12.95 (draft version)

 This function description to WDIALOG is divided in the parts

 -  Data types and structures
 -  How do I recognize WDIALOG?
 -  Window dialogs
 -  List boxes
 -  Font selector
 -  Conversion of extended object types


 Data Types and Structures
 =========================

  Used data types

 The declarations and descriptions work with the following data types:

 BYTE      8 Bit, signed,         -128 to 127
 UBYTE     8 Bit, unsigned,          0 to 255
 WORD     16 Bit, signed,       -32768 to 32767
 UWORD    16 Bit, unsigned,          0 to 65535
 LONG     32 Bit, signed,  -2147483648 to 2147483647
 ULONG    32 Bit, unsigned,          0 to 4294967295


 How do I recognize WDIALOG?
 ===========================

 Sub-function 7 of appl_getinfo() returns in  the lowest 3 bits of ap_gout1,
 whether the wdlg_xx()/lbox_xx() and fnts_xx()-functions are available.

 Declaration:  WORD appl_getinfo( WORD ap_gtype, WORD *ap_gout1,
                           WORD *ap_gout2, WORD *ap_gout3, WORD *ap_gout4 );

 Call: ap_greturn = appl_getinfo( 7, &ap_gout1,
                                  &ap_gout2, &ap_gout3, &ap_gout4);

 Variable       Value           Meaning
 Input:

 contrl[0]      130             appl_getinfo
 contrl[1]      1               Entries in intin
 contrl[3]      0               Entries in addrin

 intin[0]       ap_gtype        Sub-function number (7)

 Output:

 contrl[2]      5               Entries in intout
 contrl[4]      0               Entries in addrout

 intout[0]      ap_greturn      0: Error 1: OK
 intout[1]      ap_gout1        see description
 intout[2]      ap_gout2
 intout[3]      ap_gout3
 intout[4]      ap_gout4

 Bits in ap_gout1:
 Bit 0:           wdlg_xx() functions are available (1)
 Bit 1:           lbox_xx() functions are available (1)
 Bit 2:           fnts_xx() functions are available (1)

 Note:
 The function appl_getinfo() is not present in all AES versions. In order to
 establish whether it is  there,  you  should  call  appl_find( "?AGI" ). If
 appl_find() returns no error,  appl_getinfo()  is  at  hand. This procedure
 works  with  old  TOS  versions  too,   since  WDIALOG  makes  available  a
 rudimentary appl_getinfo() function and traps appl_find().


 Window Dialogs
 ==============


  WINDOW DIALOG - CREATE (AES 160)

 This function requests memory for a dialog structure and initializes it.

 Declaration: DIALOG *wdlg_create( HNDL_OBJ handle_exit, OBJECT *tree,
                       void *user_data, WORD code, void *data, WORD flags );

 Call:       dialog = wdlg_create( handle_exit, tree,
                                   user_data, code, data, WLG_BKGD );

 Variable       Value           Meaning
 Input:

 contrl[0]      160             wdlg_create
 contrl[1]      2               entries in intin
 contrl[3]      4               entries in addrin

 intin[0]       code            will  be   passed   on,   in   <clicks>,  to
                                handle_exit()
 intin[1]       flags

 addrin[0]      handle_exit     pointer to the service function
 addrin[1]      tree            pointer to the object tree
 addrin[2]      user_data       pointer to user informations
 addrin[3]      data            will   be   passed   on,   in   <data>,   to
                                handle_exit()

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     dialog          pointer to the dialog structure

 Description of <handle_exit>:

 <handle_exit> is the pointer  to  a  service  routine,  that will be called
 from, among others, wdlg_evnt(). <handle_exit> will  be called when an exit
 or touchexit object is clicked  (in  this  case  <obj> is a positive object
 number) or when an event concerning the  dialog has occurred (then <obj> is
 negative and contains a corresponding function number like for instance
 HNDL_CLSD).

 The parameters are passed on the stack and the routine may change registers
 d0-d2/a0-a2.

 Example service routine:

    WORD  cdecl handle_exit( DIALOG *dialog, EVNT *events,
                             WORD obj, WORD clicks, void *data );
    {
       if ( obj < 0 )              /* Event or object number? */
       {
                                   /* All events except HNDL_CLSD */
                                   /* ignored in this example */

          if ( obj == HNDL_CLSD )  /* Closer clicked? */
             return( 0 );          /* Quit */


          if ( obj == HNDL_EDIT )
          {
            /* In window dialogs it can be useful to ignore key
               combinations with Control in input fields, so that shortcuts
               such as Ctrl-V, Ctrl-W or Ctrl-Q can be handled in the event
               loop of the program. In this case a 0 should be returned on
               HNDL_EDIT to prevent that the key is handled by objc_edit().
            */
          }
       }
       else                        /* An Object has been selected */
       {
          switch ( obj )           /* Take actions (if needed) */
          {
             case ...
               .
               .
               .
             case MY_EXIT_OBJECT: ..... return( 0 );   /* Quit */
          }
       }
       return( 1 );                     /* Continue */
    }

    The parameters have the following meanings:

       dialog:  Pointer to a dialog  structure.  No  direct access should be
                made on the structure. The wdlg_xx functions should be used!

       events:  If <obj> is an object number (>= 0), then <events> points to
                the EVNT structure given  to wdlg_evnt(). Otherwise <events>
                is 0L and cannot be used for addressing.

       obj:     >= 0: object number
                < 0:  function number (see below)

       clicks:  Number of mouse clicks (if <obj> refers to an object number)

       data:    Contents depend on <obj>

       Meaning of <data> depend on <obj>:

          If <obj> is a (positive)  object  number, the variable <user_data>
          (see wdlg_create) will be passed in <data>.
          <clicks> contains the number of mouse clicks on this object.

          HNDL_INIT:  <data> is the variable given wdlg_create.
                      If handle_exit()  returns  0,  wdlg_create()  does not
                      create any dialog structure (Error).
                      The variable <code> is passed in <clicks>.

          HNDL_OPEN:  <data> is the variable given wdlg_open.
                      The variable <code> is passed in <clicks>.

          HNDL_CLSD:  <data> is <user_data>. If handle_exit() returns 0, the
                      dialog will be closed - wdlg_evnt() returns 0.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_MOVE:  <data> is <user_data>. If handle_exit() returns 0, the
                      dialog will be closed - wdlg_evnt() returns 0.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_TOPW:  <data> is <user_data>. If handle_exit() returns 0, the
                      dialog will be closed - wdlg_evnt() returns 0.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_UNTP:  <data> is <user_data>. If handle_exit() returns 0, the
                      dialog will be closed - wdlg_evnt() returns 0.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_EDIT:  <data> points to a word with the key code.
                      If handle_exit() returns  1,  the  key  press  will be
                      handled, on 0 ignored.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_EDDN:  <data> points to a word with the key code.
                      <events>  points  to  the   EVNT  structure  given  to
                      wdlg_evnt().

          HNDL_EDCH:  <data> points to word  with  the  object number of the
                      new edit field.

       Of these function numbers only HNDL_CLSD needs to be reacted on.
       Each of the other events can be considered as needed.

   If handle_exit is called with an unknown  function number in <obj> or one
   of the above function numbers is to be ignored, 1 must be returned.


  WINDOW DIALOG - OPEN (AES 161)

 OPEN opens a window with the title  line  <title> at the position <x>, <y>.
 Before wdlg_open() returns to the caller, the service routine <handle_exit>
 (see above)  will  also  be  called  with  the  function  number HNDL_OPEN:
 handle_exit( dialog, HNDL_OPEN, code, data );

 Declaration:  WORD wdlg_open( DIALOG *dialog, BYTE *title, WORD kind,
                               WORD x, WORD y, WORD code, void *data );

 Call:     handle = wdlg_open( dialog, title, NAME + CLOSER + MOVER,
                               x, y, code, data );

 Variable       Value           Meaning
 Input:

 contrl[0]      161             wdlg_open
 contrl[1]      4               entries in intin
 contrl[3]      3               entries in addrin

 intin[0]       kind            Window components (NAME/MOVER/CLOSER)
 intin[1]       x               x coordinates of the dialog or -1 (centred)
 intin[2]       y               y coordinates of the dialog or -1 (centred)
 intin[3]       code            will  be   passed   on,   in   <clicks>,  to
                                handle_exit()

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      title           pointer to the window name or 0L
 addrin[2]      data            will   be   passed   on,   in   <data>,   to
                                handle_exit()

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      handle          handle of the dialog window (0: error)


  WINDOW DIALOG - CLOSE (AES 162)

 This function closes the window dialog <dialog>.

 Declaration:  WORD wdlg_close( DIALOG *dialog );
 Call:              wdlg_close( dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      162             wdlg_close
 contrl[1]      0               entries in intin
 contrl[3]      1               entries in addrin

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  WINDOW DIALOG - DELETE (AES 163)

 This function frees the memory of a window dialog.

 Declaration:  WORD wdlg_delete( DIALOG *dialog );
 Call:              wdlg_delete( dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      163             wdlg_delete
 contrl[1]      0               entries in intin
 contrl[3]      1               entries in addrin

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  WINDOW DIALOG - GET OBJECT TREE (AES 164, 0)

 wdlg_get_tree() returns the address of the object  tree and the size of the
 window (the work area). As long as the dialog size hasn't been changed with
 wdlg_set_size(), the work area corresponds to the  area of the GRECT of the
 root object.

 Declaration: WORD wdlg_get_tree( DIALOG *dialog, OBJECT **tree, GRECT *r );
 Call:             wdlg_get_tree( dialog, &tree, &r );

 Variable       Value           Meaning
 Input:

 contrl[0]      164             wdlg_get
 contrl[1]      1               entries in intin
 contrl[3]      3               entries in addrin

 intin[0]       0               wdlg_get_tree

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      tree            pointer to pointer to object tree
 addrin[2]      rect            pointer to GRECT

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  WINDOW DIALOG - GET EDIT OBJECT (AES 164, 1)

 This function returns the current edit object's number. If the result is 0,
 then there is currently no active edit object.

 Declaration:    WORD wdlg_get_edit( DIALOG *dialog, WORD *cursor );
 Call:     edit_obj = wdlg_get_edit( dialog, &cursor );

 Variable       Value           Meaning
 Input:

 contrl[0]      164             wdlg_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       1               wdlg_get_edit

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      2               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      edit_obj        current edit object's number (or 0 when none
                                is active)
 intout[1]      cursor          character index

 Note:
 In old versions  of  WDIALOG,  <cursor>  is  not  returned.  The binding in
 WDIAL_A.S makes sure that in this case -1 is entered.


  WINDOW DIALOG - GET USERDATA (AES 164, 2)

 This function returns the variable <user_data>, that was passed in the
 call of wdlg_create().

 Declaration:    void *wdlg_get_udata( DIALOG *dialog );
 Call:     user_data = wdlg_get_udata( dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      164             wdlg_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       2               wdlg_get_udata

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     user_data       the pointer user_data


  WINDOW DIALOG - GET WINDOW HANDLE (AES 164, 3)

 GET WINDOW HANDLE returns the handle of the dialog window.

 Declaration:   WORD wdlg_get_handle( DIALOG *dialog );
 Call:      handle = wdlg_get_handle( dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      164             wdlg_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       3               wdlg_get_handle

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      handle          window handle


  WINDOW DIALOG - SET EDIT OBJECT (AES 165, 0)

 SET EDIT OBJECT activates an edit object,  i.e.  the cursor is drawn in the
 object <obj> and deleted from any previously active object.

 Declaration:    WORD wdlg_set_edit( DIALOG *dialog, WORD obj );
 Call:     edit_obj = wdlg_set_edit( dialog, new_edit_obj );

 Variable       Value           Meaning
 Input:

 contrl[0]      165             wdlg_set
 contrl[1]      2               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       0               wdlg_set_edit
 intin[1]       obj             the new edit object's number
                                (or 0, when none should be active)

 addrin[0]      dialog          pointer to the dialog structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      edit_obj        the current edit object number


  WINDOW DIALOG - SET TREE (AES 165, 1)

 SET TREE displays a new object tree  in  the dialog. If the new root object
 has a different size, the window size is adapted. The window contents is in
 any case updated.

 Declaration:  WORD wdlg_set_tree( DIALOG *dialog, OBJECT *new_tree );
 Call:              wdlg_set_tree( dialog, new_tree );

 Variable       Value           Meaning
 Input:

 contrl[0]      165             wdlg_set
 contrl[1]      1               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       1               wdlg_set_tree

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      new_tree        pointer to the new object tree

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  WINDOW DIALOG - SET SIZE (AES 165, 2)

 With wdlg_set_size() the size of a window  dialog can be changed. The GRECT
 <new_size> determines the new position  and  size  of the window work area.
 SET SIZE changes neither position nor size  of the root object. If the root
 object is to be shifted or enlarged,  the object dimensions must be changed
 before the call of wdlg_set_size().

 Declaration:  WORD wdlg_set_size( DIALOG *dialog, GRECT *new_size );
 Call:              wdlg_set_size( dialog, new_size );

 Variable       Value           Meaning
 Input:

 contrl[0]      165             wdlg_set
 contrl[1]      1               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       2               wdlg_set_size

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      new_size        pointer to GRECT

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1

 Note:
 The buttons must always be completely  within  the work area of the window,
 since form_button() doesn't observe the rectangle list.
 The normal use of wdlg_set_size()  are with enlargeable dialogs, containing
 a sizer object in the right bottom corner.


  WINDOW DIALOG - EVENT (AES 166)

 This function must be called in the  event  loop. In the bit array <mwhich>
 the event  bits  concerning  the  window  dialog  will  be  cleared.  After
 wdlg_evnt()  the  EVNT  structure  can  be  used  by  the  application  for
 evaluation of the events determined for it. If wdlg_evnt() returns a 0, the
 window dialog must be closed (call wdlg_close()).

 Declaration:  WORD wdlg_evnt( DIALOG *dialog, EVNT *events );
 Call:       cont = wdlg_evnt( dialog, &events );

 Variable       Value           Meaning
 Input:

 contrl[0]      166             wdlg_evnt
 contrl[1]      0               entries in intin
 contrl[3]      2               entries in addrin

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      events          pointer to the EVNT structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      cont            0: Close dialog
                                1: everything is OK

 Description of the EVNT structure:

 typedef struct
 {
    WORD  mwhich;               /* type of events */
    WORD  mx;                   /* x coordinate of mouse pointer */
    WORD  my;                   /* y coordinate of mouse pointer */
    WORD  mbutton;              /* pressed mouse buttons */
    WORD  kstate;               /* status of shift keys (kbshift) */
    WORD  key;                  /* scan code of pressed key */
    WORD  mclicks;              /* number of mouse clicks */
    WORD  reserved[9];          /* reserved */
    WORD  msg[16];              /* message buffer */
 } EVNT;

 Note:
 The Iconify event is not supported by wdlg_evnt(). Anyone who registers the
 iconifier as a window element  when  wdlg_open()  is called, must therefore
 evaluate this event and handle it  himself.  The  same thing applies if the
 sizer is registered as an element.


  WINDOW DIALOG - REDRAW (AES 167)

 REDRAW works  similar  to  objc_draw().  Contrary  to  that,  however,  the
 rectangle list of the dialog window is observed. Should you want to draw an
 object within the  dialog,  you  should  always  use  wdlg_redraw() and not
 objc_draw(). Just as  with  objc_draw,  the  call  of  wdlg_redraw  must be
 preceded and followed by calls of wind_update().

 Declaration:  void wdlg_redraw( DIALOG *dialog, GRECT *rect, WORD obj,
                                 WORD depth );
 Call:              wdlg_redraw( dialog, &rect, obj, MAX_DEPTH );

 Variable       Value           Meaning
 Input:

 contrl[0]      167             wdlg_redraw
 contrl[1]      2               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       obj             start object number
 intin[1]       depth           number of levels/depth

 addrin[0]      dialog          pointer to the dialog structure
 addrin[1]      rect            pointer to limiting GRECT

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout




 List Boxes
 ==========



 Overview of the functions:
 --------------------------

 lbox_create()          create list box, request memory
 lbox_update()          update AES objects
 lbox_do()              handle button
 lbox_delete()          free memory

 lbox_cnt_items();      get number of list elements
 lbox_get_tree();       get pointer to object tree of dialog
 lbox_get_visible() or
 lbox_get_avis();       get number of visible list box elements (Slider A)
 lbox_get_bvis();       get number of visible list box elements (Slider B)
 lbox_get_udata();      get pointer to program specific data
 lbox_get_first() or
 lbox_get_afirst();     get index of the first visible element (Slider A)
 lbox_get_bfirst();     get index of the first visible element (Slider A)
 lbox_get_slct_idx();   get index of the first selected element
 lbox_get_items();      get pointer to the first element of the list
 lbox_get_item();       get pointer to n-th element
 lbox_get_slct_item();  get pointer to the first selected element
 lbox_get_idx();        get index of an element
 lbox_get_bentries;     get number of elements for slider B

 lbox_set_slider() or
 lbox_set_asldr();      set slider position (Slider A)
 lbox_set_bsldr();      set slider position (Slider B)
 lbox_set_items();      set new element list
 lbox_free_items();     free element list
 lbox_free_list();      free element list
 lbox_set_bentries();   set number of elements for slider B
 lbox_scroll_to()  or
 lbox_ascroll_to();     Shift contents of list box up to a certain element
                        (Slider A)
 lbox_bscroll_to();     Shift contents of list box up to a certain element
                        (Slider B)


 Call schema for modal dialog:
 -----------------------------

 wind_update()           lock screen
 lbox_create()           create list box
 form_center()           centre dialog
 form_dial()             buffer screen section
    .
    .
 Loop:   form_do() <----
            .           |
            .           |
         lbox_do() -----

    .
    .
 End of loop (e.g. OK or Cancel pressed)
    .
    .
 Possibly lbox_get_slct_item()...
    .
    .
 form_dial()             send redraw message
 wind_update()           free screen
 lbox_delete()           free memory for list box



  LIST BOX - CREATE (AES 170)

 This function allocates memory for a  list  box and initializes the objects
 by calling the routine <set> for each  of  the objects given in <objs>. The
 list box is however not drawn!
 Bit 0 of the variable <flags> determines whether the list box is horizontal
 (first element left and last right) or vertical (first element top and last
 bottom).
 Regardless of this main scroll  direction  the  list  box can have a second
 slider, if the elements themselves should  be  scrolled. This can be useful
 for instance in a vertical list box with text elements wider than the box.

 Declaration: LIST_BOX *lbox_create( OBJECT *tree, SLCT_ITEM slct,
               SET_ITEM set, LBOX_ITEM *items, WORD visible_a, WORD first_a,
               WORD *ctrl_objs, WORD *objs, WORD flags, WORD pause_a,
               void *user_data, DIALOG *dialog,
                                   visible_b, first_b, entries_b, pause_b );

 Call:      box = lbox_create( tree, slct_item, set_item, item_list, 10, 0,
                    ctrl_objs, objs, lbox_flags, 20, 0L, 0L, 10, 0, 40, 5 );

 Variable       Value           Meaning
 Input:

 contrl[0]      170             lbox_create
 contrl[1]      4 or 8          entries in intin
 contrl[3]      8               entries in addrin

 intin[0]       visible_a       number of visible entries (Slider A)
 intin[1]       first_a         index of first visible entry (Slider A)
 intin[2]       flags           miscellaneous flags
 intin[3]       pause_a         delay during scrolling in ms (Slider A)

 intin[4]       visible_b       number of visible elements (Slider B)
 intin[5]       first_b         first visible element (Slider B)
 intin[6]       entries_b       number of elements (Slider B)
 intin[7]       pause_b         delay during scrolling in ms (Slider B)

 addrin[0]      tree            pointer to the object tree of the dialog
 addrin[1]      slct            pointer to selection routine
 addrin[2]      set             pointer to set routine
 addrin[3]      items           pointer to linked list with LBOX_ITEMs
 addrin[4]      ctrl_objs       pointer to an array  with the object numbers
                                of the buttons and slider (5 entries)
 addrin[5]      objs            pointer to an array  with the object numbers
                                of the list box entries (<entries> entries)
 addrin[6]      user_data       pointer for application
 addrin[7]      dialog          pointer to the window dialog structure or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     box             pointer to the list box structure or 0L


 Both <slct> as well as <set> are  functions, whose parameters are passed on
 the stack. The functions may change registers d0-d2/a0-a2.

 <slct> is a pointer to a selection routine, that will be called whenever an
 entry is selected or deselected.

    typedef  void  (cdecl *SLCT_ITEM)( LIST_BOX *box, OBJECT *tree,
                    struct _lbox_item *item,
                    void *user_data, WORD obj_index, WORD last_state );

    <box>       points to the list box structure
    <tree>      points to the Object tree of the dialog
    <item>      points to the LBOX_ITEM structure of the selected entry
    <user_data> is the pointer passed to lbox_create()
    <obj_index> is the selected  object's  number.  On  a  double  click the
                topmost bit is set, like after form_do(). Should <obj_index>
                be 0, that means that no object is assigned to the entry; it
                is not  visible.  Normally  this  is  the  case  only during
                scrolling if a selection (that no longer is visible) must be
                cleared because a new object has been selected.
    <last_state> is the current status of the object. <last_state> can also
                have the same value  as  <item->selected>.  In this case the
                function <slct> can normally be immediately terminated.

   <slct> is also called when the selection of an object is revoked!
   The variable <selected> from the LBOX_ITEM structure already contains the
   new status of the object when <slct> is called.

 <set> points to the function that should  enter the contents of a LBOX_ITEM
 in an object of the list box dialog:

    typedef  WORD  (cdecl *SET_ITEM)( LIST_BOX *box, OBJECT *tree,
                     struct _lbox_item *item, WORD obj_index,
                                 void *user_data, GRECT *rect, WORD first );

    <box>       points to the list box structure
    <tree>      points to the object tree of the dialog
    <item>      points to the LBOX_ITEM structure of the entry to set
    <obj_index> is the number of the object to set
    <user_data> is the pointer passed to lbox_create()
    <rect>      is the pointer to the GRECT for the object redraw or 0L
    <first>     contains the first visible element's number for slider B

   For a list box that  contains  only  text  strings,  <set> is typically a
   function that copies a string,  to  which the LBOX_ITEM structure refers,
   to the object <index>.

   <rect> is 0L when a  redraw  of  the  dialog  box  is carried out or when
   lbox_update() has been called.

   <rect> is not 0L when the user  has selected or deselected an object, and
   points to the GRECT for  the  redraw.  The  return  value of <set> is the
   start object number for objc_draw()/wdlg_redraw().
   With list box entries consisting  of  several  objects  it is sometimes a
   good idea, on selection/deselection,  to  shrink  the redraw rectangle or
   change  the  start  object  in   order  to  prevent  unnecessary  drawing
   operations or flicker.

   In most cases the list box  routines  will  after <set> call the function
   objc_draw()/wdlg_redraw(), in order to display the changed contents.

   <first> contains the first visible element's  number for slider B, if the
   list box has got 2 sliders. With  a (vertical) list box with text strings
   and two sliders, for instance, you should when calling lbox_create() give
   the number of visible characters  in  <visible_b>, the full string length
   in <entries_b> and the index of the first visible character in <first_b>.
   If the text  is  scrolled  horizontally,  <set>  will  be  called for all
   visible strings and the area redrawn or shifted.
   If the list box has got only one slider, <first> is always 0.

 <items> points to the first element of  a list of LBOX_ITEMs. The structure
 for the list element must, as  its  first  member, contain a pointer to the
 successor  (next)  and,  as  its  second  member,  a  word  for  the  state
 (selected):

    typedef struct _lbox_item
    {
       struct _lbox_item *next;  /* pointer to the next entry of the list */
       WORD  selected;           /* tells whether the object is selected */

       WORD  data1;              /* data for the program ... */
       void  *data2;
       void  *data3;

    } LBOX_ITEM;

   The structure can however,  if  the  corresponding  type  cast is made on
   call, very well look like the following example:

    typedef struct
    {
       void  *next;
       WORD  selected;

       ... and from here on at applications own discretion ...

    } LB_EXAMPLE;


 <ctrl_objs> is a pointer to an  array  with  5  or 9 entries containing the
 object numbers of the control objects (buttons):

    ctrl_objs[0]:  object number of the BOX or IBOX, containing the actual
                   list box object.
    ctrl_objs[1]:  object number of the button for scrolling up (or left).
    ctrl_objs[2]:  object number of the button for scrolling down (right).
    ctrl_objs[3]:  object number of the slider background box.
    ctrl_objs[4]:  object number of the slider box.

   If the list box has  got  2  sliders,  ctrl_objs[5-8] contain the objects
   numbers of slider B:

    ctrl_objs[5]:  object number of the button for scrolling left (or up).
    ctrl_objs[6]:  object number of the button for scrolling right (down).
    ctrl_objs[7]:  object number of the slider background box.
    ctrl_objs[8]:  object number of the slider box.

   The buttons, the slider and  the  slider background should have TOUCHEXIT
   status. For a list box  that  has  only  got  the  buttons and no slider,
   ctrl_objs[3/4 and 7/8] must contain -1.

 <objs> is an array  with  <entries>  entries,  that  contains  the list box
 objects' numbers (the objects are normally children of ctrl_objs[0]).

    objs[0]:             the first object's number
         .
         .
         .
    objs[entries - 1]:   the last object's number

    The objects should normally have TOUCHEXIT status.


 The word <flags> controls the behaviour of the list box:

 Bit|State|Description
 ---|-----|-----------------------------------------------------------------
  0 |  0  | The box scrolls horizontally.
    |  1  | The box scrolls vertically.
    |     |
  1 |  0  | No automatic scrolling
    |  1  | Automatic scrolling occurs as soon as, with mouse button down,
    |     | the mouse pointer is moved over the first or last element.
    |     |
  2 |  0  | The selection routine is called only when the automatic
    |     | scrolling has ceased, i.e. it will be called for the last
    |     | selected entry.
    |  1  | During automatic scrolling will the selection routine be called
    |     | for each selected entry.
    |     |
  3 |  0  | During movement of the sliders an outline will be displayed
    |     | (graf_slidebox), the list box will be updated only when the
    |     | mouse button has been released.
    |  1  | The slider is a real-time slider.
    |     |
  4 |  0  | Multiple selections in the list box are possible.
    |  1  | Only one element can be selected.
    |     |
  5 |  0  | Multiple selections are possible without Shift key.
    |  1  | Multiple selections are possible only with Shift key.
    |     |
  6 |  0  | On selection the Status is always SELECTED
    |  1  | On selection the Status is always toggled.
    |     |
  7 |  0  | List box has only one slider
    |  1  | List box has two sliders

 #define  LBOX_VERT   1       /* list box with vertical slider */
 #define  LBOX_AUTO   2       /* auto-scrolling */
 #define  LBOX_AUTOSLCT  4    /* automatic display during auto-scrolling */
 #define  LBOX_REAL   8       /* real-time slider */
 #define  LBOX_SNGL   16      /* only one selectable entry at a time */
 #define  LBOX_SHFT   32      /* multiple selections only with shift */
 #define  LBOX_TOGGLE 64      /* toggle entry status on selection */
 #define  LBOX_2SLDRS 128     /* support 2 sliders */

 The flag LBOX_SNGL can be combined  with  LBOX_SHFT or LBOX_TOGGLE in order
 to make possible direct deselection also  when  only  a single entry can be
 selected at a time.
 LBOX_SNGL + LBOX_SHFT  means  that  the  selected  entry  can be deselected
 through a click with pressed  shift  key.  LBOX_SNGL + LBOX_TOGGLE allows a
 selected entry to be deselected through a click even without shift key.

 The pointer <items> can also be 0L,  when  the  list box still is empty and
 contains no entries.


  LIST BOX - UPDATE (AES 171)

 UPDATE updates the contents  of  the  list  box  objects, i.e. the function
 <set> (see above) is called for each object. If <rect> isn't 0L, it will be
 taken to be a pointer to  a  GRECT,  used  for  the redraw of the list box.
 Otherwise the objects will only be updated but not drawn.

 Declaration:  void lbox_update( LIST_BOX *box, GRECT *rect );
 Call:              lbox_update( box, &redraw_rect );

 Variable       Value           Meaning
 Input:

 contrl[0]      171             lbox_update
 contrl[1]      0               entries in intin
 contrl[3]      2               entries in addrin

 addrin[0]      box             pointer to the list box structure
 addrin[1]      rect            pointer to the redraw GRECT or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - DO (AES 172)

 DO reacts to the press of  a  button.  This function should be called after
 form_do() (or from the service function of a window dialog). If an entry of
 the list box was selected with  a  double  click, lbox_do() returns -1. The
 dialog should then be closed as if the OK button were pressed.

 lbox_do() recognizes double clicks  on  a  set  topmost  bit  in the object
 number given to it <obj> (object  number  | 0x8000). In the returned object
 number <slct_obj>, on the other hand, the top bit is always cleared.

 Declaration:      WORD lbox_do( LIST_BOX *box, WORD obj );
 Call:       slct_obj = lbox_do( box, obj );

 Variable       Value           Meaning
 Input:

 contrl[0]      172             lbox_do
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       obj             the selected object's number

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      slct_obj        the selected  object's  number  or  -1  if a
                                double click on an entry occurred


  LIST BOX - DELETE (AES 173)

 DELETE frees the memory for the list box.

 Declaration:  WORD lbox_delete( LIST_BOX *box );
 Call:              lbox_delete( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      173             lbox_delete
 contrl[1]      0               entries in intin
 contrl[3]      1               entries in addrin

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  LIST BOX - COUNT ITEMS (AES 174, 0)

 COUNT ITEMS counts the elements of the linked list.

 Declaration:  WORD lbox_cnt_items( LIST_BOX *box );
 Call:         no = lbox_cnt_items( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       0               lbox_cnt_items

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      no              number of elements in the list


  LIST BOX - GET TREE (AES 174, 1)

 GET TREE returns the pointer to the object tree of the dialog box.

 Declaration:  OBJECT *lbox_get_tree( LIST_BOX *box );
 Call:          tree = lbox_get_tree( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       1               lbox_get_tree

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     tree            pointer to the object tree of the dialog


  LIST BOX - GET NUMBER OF VISIBLE ITEMS, SLIDER A (AES 174, 2)

 GET SIZE returns the number of visible entries.

 Declaration:    WORD lbox_get_visible( LIST_BOX *box );
 Call:      entries = lbox_get_visible( box );
         or entries = lbox_get_avisb( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       2               lbox_get_size

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      entries         number of visible entries


  LIST BOX - GET USER DATA (AES 174, 3)

 ...returns the pointer <user_data>.

 Declaration:     void *lbox_get_udata( LIST_BOX *box );
 Call:      user_data = lbox_get_udata( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       3               lbox_get_udata

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     user_data


  LIST BOX - GET FIRST VISIBLE ITEM, SLIDER A (AES 174, 4)

 GET FIRST returns the index of the first visible element.

 Declaration:  WORD lbox_get_first( LIST_BOX *box );
 Call:      first = lbox_get_first( box );
         or first = lbox_get_afirst( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       4               lbox_get_first

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      first           index of the first visible entry


  LIST BOX - GET INDEX of SELECTED ITEM (AES 174, 5)

 The index of the first selected entry is  inquired. If no entry in the list
 box is selected, -1 is returned.

 Declaration:  WORD lbox_get_slct_idx( LIST_BOX *box );
 Call:      index = lbox_get_slct_idx( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       5               lbox_get_slct_idx

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      index           index of the selected entry


  LIST BOX - GET ITEMS (AES 174, 6)

 GET ITEMS returns a pointer to the list of LBOX_ITEMs.

 Declaration:  LBOX_ITEM *lbox_get_items( LIST_BOX *box );
 Call:            items = lbox_get_items( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       6               lbox_get_items

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     items           pointer to linked list


  LIST BOX - GET ITEM (AES 174, 7)

 GET ITEM returns a pointer to the element <n> of the list.

 Declaration:  LBOX_ITEM *lbox_get_item( LIST_BOX *box, WORD n );
 Call:             item = lbox_get_item( box, n );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      2               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       7               lbox_get_item
 intin[1]       n               index of the element

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     item            pointer to element n or 0L


  LIST BOX - GET SELECTED ITEM (AES 174, 8)

 GET SELECTED ITEM returns a pointer  to  the  first selected element of the
 list.

 Declaration:  LBOX_ITEM *lbox_get_slct_item( LIST_BOX *box );
 Call:             item = lbox_get_slct_item( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       8               lbox_get_slct_item

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     item            pointer to element n or 0L


  LIST BOX - GET ITEM INDEX (AES 174, 9)

 This function returns the index <n> of the element <item>.
 If <item> is no element in the list, the return value is -1.

 Declaration:  WORD lbox_get_idx( LBOX_ITEM *items, LBOX_ITEM *search );
 Call:          n = lbox_get_idx( items, search );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       9               lbox_get_idx

 addrin[0]      items           pointer to the first element of the list
 addrin[1]      search          pointer to the element to search for

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      n               index of the element


  LIST BOX - GET NUMBER OF VISIBLE ITEMS, SLIDER B (AES 174, 10)

 GET SIZE returns the number of visible entries.

 Declaration:    WORD lbox_get_bvis( LIST_BOX *box );
 Call:      entries = lbox_get_bvis( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       10              lbox_get_bvis

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      entries         number of visible entries


  LIST BOX - GET NUMBER OF ITEMS, SLIDER B (AES 174, 11)

 ... returns the number of elements for slider B.

 Declaration:    WORD lbox_get_bentries( LIST_BOX *box );
 Call:      entries = lbox_get_bentries( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       11              lbox_get_bentries

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      entries         number of elements


  LIST BOX - GET FIRST VISIBLE ITEM, SLIDER B (AES 174, 12)

 GET FIRST returns the index of the first visible element (Slider B!).

 Declaration:  WORD lbox_get_bfirst( LIST_BOX *box );
 Call:      first = lbox_get_bfirst( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      174             lbox_get
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       12              lbox_get_bfirst

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      first           index of the first visible entry


  LIST BOX - SET SLIDER A (AES 175, 0)

 This function positions  the  slider  A  and  draws  it  within  the redraw
 rectangle <rect>. The  contents  of  the  list  box  is  not  updated, i.e.
 lbox_update() must possibly be  called.  If  <rect>  is  0L,  then only the
 position of the slider objects is changed, but the objects won't be drawn.

 Declaration: void lbox_set_slider( LIST_BOX *box, WORD first,
                                    GRECT *rect );

 Call:             lbox_set_slider( box, first, &rect );
                or lbox_set_asldr( box, first, &rect );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      2               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       0               lbox_set_slider
 intin[1]       first           index of the first visible entry

 addrin[0]      box             pointer to the list box structure
 addrin[1]      rect            pointer to redraw rectangle or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - SET NEW ITEM LIST (AES 175, 1)

 This function sets a new  list  with  list  box  entries. The old list must
 previously have been freed with lbox_free_items().

 Declaration:  void lbox_set_items( LIST_BOX *box, LBOX_ITEM *items );
 Call:              lbox_set_items( box, items );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      1               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       1               lbox_set_items

 addrin[0]      box             pointer to the list box structure
 addrin[1]      items

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout

 The pointer <items> can also be 0L,  if  the list box is empty and contains
 no entries.


  LIST BOX - FREE ITEMS (AES 175, 2)

 This function returns the memory  for  the  linked  list of LBOX_ITEMs. The
 precondition is that memory was allocated with Malloc() for each element in
 the list. If some non-system memory  management was used for the LBOX_ITEMs
 (e.g. the C standard functions),  then  a  non-system function must also be
 called to free the memory.

 Declaration:  void lbox_free_items( LIST_BOX *box );
 Call:              lbox_free_items( box );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       2               lbox_free_items

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - FREE ITEM LIST (AES 175, 3)

 This function  works  precisely  as  lbox_free_items().  Contrary  to that,
 lbox_free_list() is however called with the  pointer to the first LBOX_ITEM
 of the list.

 Declaration:  void lbox_free_list( LBOX_ITEM *items );
 Call:              lbox_free_list( items );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       3               lbox_free_list

 addrin[0]      items           pointer to linked list of LBOX_ITEMs

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - SCROLL TO, SLIDER A (AES 175, 4)

 This function positions the slider A and updates the contents of the
 list box.  <box_rect>  is  the  redraw  rectangle  for  the  list  box  and
 <slider_rect> is the redraw rectangle for the slider.

 SCROLL TO works  in  principle  like  a  call  of  lbox_set_slider() with a
 following lbox_update(); if possible the  box  is however scrolled, so that
 only little new has to be drawn. Thus,  should the element list of the list
 box have been changed, then lbox_scroll_to() may not be used.

 Declaration:  void lbox_scroll_to( LIST_BOX *box, WORD first,
                                    GRECT *box_rect, GRECT *slider_rect );

 Call:              lbox_scroll_to( box, first, &box_rect, &slider_rect );
                 or lbox_ascroll_to( box, first, &box_rect, &slider_rect );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      2               entries in intin
 contrl[3]      3               entries in addrin

 intin[0]       4               lbox_scroll_to
 intin[1]       first           index of the first visible entry

 addrin[0]      box             pointer to the list box structure
 addrin[1]      box_rect        pointer to redraw rectangle or 0L
 addrin[2]      slider_rect     pointer to redraw rectangle or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - SET SLIDER B (AES 175, 5)

 This function positions  the  slider  B  and  draws  it  within  the redraw
 rectangle <rect>. The  contents  of  the  list  box  is  not  updated, i.e.
 lbox_update() must possibly be  called.  If  <rect>  is  0L,  then only the
 position of the slider objects is changed, but the objects won't be drawn.

 Declaration: void lbox_set_bsldr( LIST_BOX *box, WORD first, GRECT *rect );
 Call:             lbox_set_bsldr( box, first, &rect );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      2               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       5               lbox_set_bsldr
 intin[1]       first           index of the first visible entry

 addrin[0]      box             pointer to the list box structure
 addrin[1]      rect            pointer to redraw rectangle or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - SET NUMBER OF entries, SLIDER B (AES 175, 6)

 This function sets the number of elements (the subdivisions) for
 slider B.

 Declaration:  void lbox_set_bentries( LIST_BOX *box, WORD entries );
 Call:              lbox_set_bentries( box, entries );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      2               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       7               lbox_set_bentries
 intin[1]       entries         number of elements

 addrin[0]      box             pointer to the list box structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  LIST BOX - SCROLL TO, SLIDER B (AES 175, 7)

 This function positions the slider B  and  updates the contents of the list
 box. <box_rect> is the redraw rectangle  for the list box and <slider_rect>
 is the redraw rectangle for the slider.

 SCROLL TO works  in  principle  like  a  call  of  lbox_set_bsldr()  with a
 following lbox_update(); if possible the  box  is however scrolled, so that
 only little new has to be drawn. Thus,  should the element list of the list
 box have been changed, then lbox_bscroll_to() may not be used.

 Declaration:  void lbox_bscroll_to( LIST_BOX *box, WORD first,
                                    GRECT *box_rect, GRECT *slider_rect );
 Call:              lbox_bscroll_to( box, first, &box_rect, &slider_rect );

 Variable       Value           Meaning
 Input:

 contrl[0]      175             lbox_set
 contrl[1]      2               entries in intin
 contrl[3]      3               entries in addrin

 intin[0]       7               lbox_bscroll_to
 intin[1]       first           index of the first visible entry

 addrin[0]      box             pointer to the list box structure
 addrin[1]      box_rect        pointer to redraw rectangle or 0L
 addrin[2]      slider_rect     pointer to redraw rectangle or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout




 Font Selector
 =============



 Overview of the functions:
 --------------------------

 fnts_create()           initialize font selector, request memory
 fnts_open()             open selector dialog in window
 fnts_close()            close window
 fnts_delete()           free memory

 fnts_get_no_styles()    inquire number of styles in a font family
 fnts_get_style()        get ID of n-th style in a family
 fnts_get_name()         get name of a font

 fnts_add()              add own fonts to the selector (e.g. Signum fonts)
 fnts_remove()           remove own fonts from the list

 fnts_evnt()             handle events for dialog in window

 fnts_do()               display modal dialog



 Call schema for selector dialog in window:
 ------------------------------------------

 Program start:             fnts_create()
    .
    .
    .
 Call the font selector:    fnts_open()
    .
    .
    .
 Event loop:                fnts_evnt()
    .                             .
    .                             .
    ......Possibly fnts_get_no_styles()/fnts_get_style()/... (according to
    .                             .               status of the check boxes)
    .                             .
    .                             .
 Close the font selector:   fnts_close()
    .
    .
    .
 Program end:               fnts_delete()



 Call schema for modal selector dialog:
 --------------------------------------

 Program start:             fnts_create()
    .
    .
    .
 Call the font selector:    fnts_do()
    .
    .
    ......Possibly fnts_get_no_styles()/fnts_get_style()/... (according to
    .                                             status of the check boxes)
    .
    .
 Program end:               fnts_delete()



 Function description:
 ---------------------

  FONT SELECTOR - CREATE (AES 180)

 This  function  initializes  the  font   selector.   If  <no_fonts>  is  0,
 vst_load_fonts() is called with <vdi_handle>.  Otherwise <no_fonts> will be
 assumed to be the number  of  all,  via <vdi_handle>, available fonts, i.e.
 the number of all system fonts (work_out[10] on v_opnvwk()/vq_extnd()) plus
 the number of loaded fonts (return value of vst_load_fonts()).

 Declaration: FNT_DIALOG *fnts_create( WORD vdi_handle, WORD no_fonts,
                                       WORD font_flags, WORD dialog_flags,
                                       BYTE *sample, BYTE *opt_button );

 Call:       fnt_dialog = fnts_create( vdi_handle, 0, 0xf,
                                       "The quick brown..." );

 Variable       Value           Meaning
 Input:

 contrl[0]      180             fnts_create
 contrl[1]      4               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       vdi_handle      handle of the VDI workstation to use
 intin[1]       no_fonts        number of available fonts or 0 if
                                     vst_load_fonts() should be called
 intin[2]       font_flags      type of fonts to display
 intin[3]       dialog_flags    appearance of the dialog

 addrin[0]      sample          pointer to string for the example text
 addrin[1]      opt_button      pointer to string for optional button or 0L

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      1               entries in addrout

 addrout[0]     fnt_dialog      pointer to administrative structure

 Description of <font_flags>:

 #define  FNTS_BTMP   1         /* display bitmap fonts */
 #define  FNTS_OUTL   2         /* display vector fonts */
 #define  FNTS_MONO   4         /* display fixed-pitch fonts */
 #define  FNTS_PROP   8         /* display proportional fonts */

 Description of <dialog_flags>:

 #define  FNTS_3D     1         /* display in 3D-look */

 Note:
 Since this function,  depending  on  system  configuration,  takes 1 second
 (possibly even more), it should  be  called  at  program start and not just
 before the display of the font selector.


 **************** Please note: ******************
 The font selector changes the attributes of the workstation designated with
 <vdi_handle>. If the  workstation  passed  to  fnts_create()  is needed for
 other purposes, the attributes must  always  be  first  set, since they may
 have been changed by the font selector.


  FONT SELECTOR - DELETE (AES 181)

 This function frees the memory  for  the  font selector. If <vdi_handle> is
 not equal to 0, vst_unload_fonts() is called.

 Declaration:  WORD fnts_delete( FNT_DIALOG *fnt_dialog, WORD vdi_handle );
 Call:              fnts_delete( fnt_dialog, vdi_handle );

 Variable       Value           Meaning
 Input:

 contrl[0]      181             fnts_delete
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       vdi_handle      handle of the workstation or 0, if
                                     vst_unload_fonts() shouldn't be called

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  FONT SELECTOR - OPEN WINDOW (AES 182)

 OPEN WINDOW opens a window dialog with the font selector. The handle of the
 window is returned, if no error occurred. On error the return value is 0.

 Declaration:  WORD fnts_open( FNT_DIALOG *fnt_dialog, WORD button_flags,
                             WORD x, WORD y, LONG id, LONG pt, LONG ratio );
 Call:       whdl = fnts_open( fnt_dialog, 0x3f0f, -1, -1, id, pt, ratio );

 Variable       Value           Meaning
 Input:

 contrl[0]      182             fnts_open
 contrl[1]      9               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       button_flags    flags for supported buttons
 intin[1]       x               x coordinate of the window or -1 (centred)
 intin[2]       y               y coordinate of the window or -1 (centred)
 intin[3/4]     id              font ID
 intin[5/6]     pt              height in 1/65536 points
 intin[7/8]     ratio           width/height ratio in 1/65536

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      whdl            handle of the window or 0 (error)

 Description of <button_flags>:

 #define  FNTS_SNAME   0x01  /* selected check box for the name */
 #define  FNTS_SSTYLE  0x02  /* selected check box for the style */
 #define  FNTS_SSIZE   0x04  /* selected check box for the height */
 #define  FNTS_SRATIO  0x08  /* selected check box for width/height ratio */

 #define  FNTS_CHNAME  0x0100 /* display check box for the name */
 #define  FNTS_CHSTYLE 0x0200 /* display check box for the style */
 #define  FNTS_CHSIZE  0x0400 /* display check box for the height */
 #define  FNTS_CHRATIO 0x0800 /* display check box for width/height ratio */
 #define  FNTS_RATIO   0x1000 /* adjustable width/height ratio */
 #define  FNTS_BSET    0x2000 /* button "Set" selectable */
 #define  FNTS_BMARK   0x4000 /* button "Mark" selectable */



  FONT SELECTOR - CLOSE WINDOW (AES 183)

 CLOSE WINDOW closes the window of the font selector.

 Declaration:  WORD fnts_close( FNT_DIALOG *fnt_dialog );
 Call:              fnts_close( *fnt_dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      183             fnts_close
 contrl[1]      0               entries in intin
 contrl[3]      1               entries in addrin

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      1


  FONT SELECTOR - GET NUMBER OF STYLES (AES 184, 0)

 This function tells how many fonts belongs  to  the same family as the font
 <id>, i.e. how many styles the family has. <id> is the ID of a font in this
 family, that can be returned by for instance fnts_evnt().

 Declaration:   WORD fnts_get_no_styles( FNT_DIALOG *fnt_dialog, LONG id );
 Call:    no_fonts = fnts_get_no_styles( fnt_dialog, id );

 Variable       Value           Meaning
 Input:

 contrl[0]      184             fnts_get
 contrl[1]      3               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       0               fnts_get_no_styles
 intin[1/2]     id              ID of a font in the family

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      no_fonts        number of styles in the family


  FONT SELECTOR - GET STYLE ID (AES 184, 1)

 GET STYLE ID returns the ID of the  <index>-th font in the family, to which
 the font <id> belongs. <index> must be a number between 1 and the result of
 fnts_get_no_styles().

 Declaration:  LONG fnts_get_style( FNT_DIALOG *fnt_dialog, LONG id,
                                    WORD index );
 Call:   style_id = fnts_get_style( fnt_dialog, id, index );

 Variable       Value           Meaning
 Input:

 contrl[0]      184             fnts_get
 contrl[1]      4               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       1               fnts_get_style
 intin[1/2]     id              ID of a font in the family
 intin[3]       index           index within the family

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      2               entries in intout
 contrl[4]      0               entries in addrout

 intout[0/1]    style_id        ID of the <index>-th font of the family


  FONT SELECTOR - GET FONT NAME (AES 184, 2)

 GET FONT NAME returns the full name, the family name and the style name for
 the font <id>.

 Declaration: WORD fnts_get_name( FNT_DIALOG *fnt_dialog, LONG id,
                     BYTE *full_name, BYTE *family_name, BYTE *style_name );
 Call:       ret = fnts_get_name( FNT_DIALOG *fnt_dialog, id,
                                  &full_name, &family_name, &style_name );

 Variable       Value           Meaning
 Input:

 contrl[0]      184             fnts_get
 contrl[1]      3               entries in intin
 contrl[3]      4               entries in addrin

 intin[0]       2               fnts_get_name
 intin[1/2]     id              font ID

 addrin[0]      fnt_dialog      pointer to administrative structure
 addrin[1]      full_name       pointer to full name or 0L
 addrin[2]      family_name     pointer to family name or 0L
 addrin[3]      style_name      pointer to the style name or 0L

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      ret             0: error  1: everything is OK


  FONT SELECTOR - GET FONT INFO (AES 184, 3)

 Declaration:  WORD fnts_get_info( FNT_DIALOG *fnt_dialog, LONG id,
                                   WORD *mono, WORD *outline );
 Call:      index = fnts_get_info( fnt_dialog, id, &mono, &outline );

 Variable       Value           Meaning
 Input:

 contrl[0]      184             fnts_get
 contrl[1]      3               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       3               fnts_get_info
 intin[1/2]     id              font ID

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      3               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      index           0: error  >0: index for vqt_name()
 intout[1]      mono            flag for fixed-pitch
 intout[2]      outline         flag for vector font


  FONT SELECTOR - ADD USER FONTS (AES 185, 0)

 With ADD USER FONTS a program can  add  own fonts to the fonts displayed by
 the font selector. The ID  of  these  fonts  must  be larger than 65535. In
 addition the pointer to a display routine  must be entered in the structure
 member <display>.

 Declaration:  WORD fnts_add( FNT_DIALOG *fnt_dialog,
                              FNTS_ITEM *user_fonts );
 Call:        ret = fnts_add( fnt_dialog, user_fonts );

 Variable       Value           Meaning
 Input:

 contrl[0]      185             fnts_set
 contrl[1]      1               entries in intin
 contrl[3]      2               entries in addrin

 intin[0]       0               fnts_add

 addrin[0]      fnt_dialog      pointer to administrative structure
 addrin[1]      user_fonts      pointer to program-specific fonts

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      ret             0: error  1: everything is OK

 Declaration of FNTS_ITEM:

 typedef struct _fnts_item
 {
    struct   _fnts_item  *next; /* pointer to next font  or 0L (end of list)
                                */
    UTXT_FN  display;           /* pointer to display  function for program-
                                   specific fonts*/
    LONG     id;                /* font ID ,  >=  65536 for program-specific
                                   fonts */
    WORD     index;             /* must be 0, since no VDI font */
    BYTE     mono;              /* flag for fixed-pitched fonts */
    BYTE     outline;           /* flag for vector font */
    WORD     npts;              /* number of predefined point heights */
    BYTE     *full_name;        /* pointer to the full name */
    BYTE     *family_name;      /* pointer to the family name */
    BYTE     *style_name;       /* pointer to the style name */
    BYTE     *pts;              /* pointer to array with point heights */
    LONG     reserved[4];       /* reserved, must be 0 */
 } FNTS_ITEM;

 typedef  void  (cdecl *UTXT_FN)( WORD x, WORD y, WORD *clip_rect, LONG id,
                                  LONG pt, LONG ratio, BYTE *string );


  FONT SELECTOR - REMOVE USER FONTS (AES 185, 1)

 REMOVE USER FONTS removes  the  fonts  registered  with  ADD FONTS from the
 linked list. If program-specific  fonts  are registered, fnts_remove() must
 be called before fnts_delete().

 Declaration:  void fnts_remove( FNT_DIALOG *fnt_dialog );
 Call:              fnts_remove( fnt_dialog );

 Variable       Value           Meaning
 Input:

 contrl[0]      185             fnts_set
 contrl[1]      1               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       1               fnts_remove

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      0               entries in intout
 contrl[4]      0               entries in addrout


  FONT SELECTOR - UPDATE WINDOW (AES 185, 2)

 Declaration:  WORD fnts_update( FNT_DIALOG *fnt_dialog, WORD button_flags,
                                 LONG id, LONG pt, LONG ratio );
 Call:     result = fnts_update( fnt_dialog, 0x3f0f, id, pt, ratio );

 Variable       Value           Meaning
 Input:

 contrl[0]      185             fnts_set
 contrl[1]      8               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       2               fnts_update
 intin[1]       button_flags    flags for supported buttons
 intin[2/3]     id              font ID
 intin[4/5]     pt              height in 1/65536 points
 intin[6/7]     ratio           width/height ratio in 1/65536

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      1               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      result

 Description of <result>:

  -1: Function not available
   0: Error (not enough memory), the font  selector then must be closed with
      fnts_close().
   1: everything OK

 Description of <button_flags>:

 #define  FNTS_SNAME   0x01  /* selected check box for the name */
 #define  FNTS_SSTYLE  0x02  /* selected check box for the style */
 #define  FNTS_SSIZE   0x04  /* selected check box for the height */
 #define  FNTS_SRATIO  0x08  /* selected check box for width/height ratio */

 #define  FNTS_CHNAME  0x0100 /* display check box for the name */
 #define  FNTS_CHSTYLE 0x0200 /* display check box for the style */
 #define  FNTS_CHSIZE  0x0400 /* display check box for the height */
 #define  FNTS_CHRATIO 0x0800 /* display check box for width/height ratio */
 #define  FNTS_RATIO   0x1000 /* adjustable width/height ratio */
 #define  FNTS_BSET    0x2000 /* button "Set" selectable */
 #define  FNTS_BMARK   0x4000 /* button "Mark" selectable */

 Note:
 In older versions of WDIALOG this functions wasn't available.
 The binding makes sure that in this case -1 is returned in intout[0].


  FONT SELECTOR - HANDLE EVENT (AES 186)

 HANDLE EVENT evaluates  the  passed  EVNT  structure  and  internally calls
 wdlg_evnt(). If one of the Exit  buttons is pressed ("Cancel", "OK", "Set",
 "Mark" or "Options") the function returns  a  0  and the button selected by
 the user is returned in <button>.

 Declaration: WORD fnts_evnt( FNT_DIALOG *fnt_dialog, EVNT *events,
         WORD *button, WORD *check_boxes, LONG *id, LONG *pt, LONG *ratio );

 Call:      cont = fnts_evnt( fnt_dialog, &events, &button, &check_boxes,
                              &id, &pt, &ratio );

 Variable       Value           Meaning
 Input:

 contrl[0]      186             fnts_evnt
 contrl[1]      0               entries in intin
 contrl[3]      2               entries in addrin

 addrin[0]      fnt_dialog      pointer to administrative structure
 addrin[1]      events          pointer to EVNT structure

 Output:

 contrl[2]      9               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      cont            0: Exit button selected
                                1: nothing happened
 intout[1]      button          selected button (or 0)
 intout[2]      check_boxes     status of the check boxes
 intout[3/4]    id              ID of selected font
 intout[5/6]    pt              height in 1/65536 points
 intout[7/8]    ratio           width/height ratio

 Description of <check_boxes>:

 #define  FNTS_SNAME   0x01  /* selected check box for the name */
 #define  FNTS_SSTYLE  0x02  /* selected check box for the style */
 #define  FNTS_SSIZE   0x04  /* selected check box for the height */
 #define  FNTS_SRATIO  0x08  /* selected check box for width/height ratio */


  FONT SELECTOR - DO (AES 187)

 fnts_do() is the modal counterpart to fnts_open()/fnts_evnt()/fnts_close().
 This function opens a modal dialog and  returns to the caller only when one
 of  the  exit  buttons  is  pressed   ("Cancel",  "OK",  "set",  "mark"  or
 "Options").

 Declaration: WORD fnts_do( FNT_DIALOG *fnt_dialog, WORD button_flags,
                            LONG id_in, LONG pt_in, LONG ratio_in,
                       WORD *check_boxes, LONG *id, LONG *pt, LONG *ratio );

 Call:    button = fnts_do( fnt_dialog, button_flags, id_in, pt_in,
                            ratio_in, &check_boxes, &id, &pt, &ratio );

 Variable       Value           Meaning
 Input:

 contrl[0]      187             fnts_do
 contrl[1]      7               entries in intin
 contrl[3]      1               entries in addrin

 intin[0]       button_flags
 intin[1/2]     id_in
 intin[3/4]     pt_in
 intin[5/6]     ratio_in

 addrin[0]      fnt_dialog      pointer to administrative structure

 Output:

 contrl[2]      8               entries in intout
 contrl[4]      0               entries in addrout

 intout[0]      button          selected button (or 0)
 intout[1]      check_boxes     Status of the check boxes
 intout[2/3]    id              ID of the selected font
 intout[4/5]    pt              height in 1/65536 points
 intout[6/7]    ratio           width/height ratio


 ---------------------------------------------------------------------------
 Function and structure definitions: WDIAL_G.H, LISTBX_G.H, FNTS_G.H

 ---------------------------------------------------------------------------
 Assembly bindings for Pure C: WDIAL_A.S

 ---------------------------------------------------------------------------

 Conversion of extended object types
 ===================================

 The module ADAPTRSC.C makes available some useful functions:

 - It returns information on the present AES functions.
 - It adapts RSC files to the (unattractive) MultiTOS peculiarity, enlarging
   3D objects above the dimensions entered in the OBJECT structure.
 - It performs (as far as automatically  possible)  RSC adaptations of 3D to
   2D.
 - It generates, when needed,  automatically  Userdef functions for extended
   MagiC 3 objects: title with  underlining,  group frames, radio button and
   check box (with following string).

 The module takes up ca. 2 kB memory.

 ---------------------------------------------------------------------------
 Example source texts: FNT_SMPLC, FNT_SMP2.C, WDLG_SMP.C, XOBJ_SMP.C,
                       ADAPTRSC.C

