
                           GEM OBJECTS AND RESOURCES
                           =========================
                              By: Mrten Lindstrm


 This text just about sums up  what  I  presently know about the subject and
 comes from many sources, perhaps  most  important  of which are articles in
 the 'ST Magazin' - a  German  ST  magazine  now unfortunately dead. For the
 info about colour icons I  admit  to  have  drawn  exclusively on the Atari
 Compendium. (I haven't got a  TOS  version  capable  of dealing with colour
 icons so with them I lack  experiences  of  my  own.) Any further info - or
 corrections - most welcome!


 ABBREVIATIONS:

 In the descriptions below I have used the following abbreviations:

 N = Nybble = half a byte (i.e. 4 bits or 1 hexadecimal digit)
 B = Byte
 W = Word = 2 bytes
 L = Longword = 4 bytes


 POINTERS:

 All pointers and address offsets in an  RSC  file are, on disk, relative to
 file start. Before use in memory,  longword  pointers have to be relocated,
 i.e. the file start address added  to  each pointer. This is done automati-
 cally by RSRC_LOAD. If you  don't  use  RSRC_LOAD,  but include an RSC file
 directly in your program code during assembly/compilation, you will have to
 make sure that the relocation is done by other means.

 One L pointer can be found at offset 12 in each object structure, except in
 those of the simple box types (20, 25 and 27). In a resource with images or
 formatted text objects, further pointers  can  be found in other structures
 (TEDINFO, BITBLK, ICONBLK). See more below.

 Note that WORD offsets are UNSIGNED, which means that they can be up to 64K
 (and also, in assembler  terms,  that  a  single Motorola instruction isn't
 enough to add them to the RSC  base  address; instead you have to load them
 in a cleared data register and add this - as a long - to the base address).


 MEASURES:

 Coordinates and dimensions  are,  in  an  RSC  file  on  disk,  measured in
 CHARACTERS, but note that the  higher  ordered  byte  is reserved for extra
 pixels; i.e. a height of $301  is  to  be  read  as 1 full character plus 3
 extra pixels. (The exception  is  measures  within  the  BITBLK and ICONBLK
 secondary structures for images and icons - see below.)

 When in use in memory, however, all measures are in PIXELS. So in ST colour
 resolutions a height of $301 will  have  been converted into 11 (8+3) while
 in ST high rez the same disk  based  height will have become 19 (16+3). You
 normally don't  have  to  worry  too  much  about  how  this  conversion is
 performed since the AES will do it  for you, either during RSC file loading
 with RSRC_LOAD, or you can  call  the  function RSRC_OBFIX for each object.
 But it still is worth knowing.


 COLOURS:

 Any colour  definition,  in  objects  or  secondary  structures,  is always
 contained in ONE NYBBLE. This gives a range of 16 possible colours:

 0=White, 1=Black,  2=Red,   3=Green,  4=Blue,   5=Cyan, 6=Yellow, 7=Magenta

 8=Light, 9=Dark, 10=Light, 11=Light, 12=Light, 13=Light, 14=Light, 15=Light
   gray     gray      red      green     blue      cyan     yellow   magenta


 OBJECTS AND TREES:

     A GEM object is, on the screen,  a  box.  The box can be invisible, can
 contain text, fill patterns etc.  and  can  in  some  cases be assigned the
 function as a button to be clicked on.

     A GEM object tree is, on the  screen, a collection of boxes within each
 other, together forming a dialogue box or  a  menu. Each of the inner boxes
 is termed 'CHILD' of the next outer box - the 'PARENT' - containing it. The
 outermost box is called the 'ROOT' of the tree.

     In program memory, or in a file,  an  object is a 12-word structure (24
 bytes) which may contain a pointer  to  either  a text string or to further
 structures.

     A tree, in program memory, is  simply  a list of object structures, the
 first of which is the root  object,  provided  that the relational data for
 all objects are sensible. Each object is assigned a number according to its
 place in the tree object list (root=0),  and  these numbers are used in the
 relational data. The first word of  each  object specifies the next sibling
 or, for the last sibling,  parent  (or  -1  for  the root which has neither
 siblings nor parent). And word 2 and 3 give the first and last child of the
 object (-1 for childless objects).

 NOTE: Some experiments that I have made  seem  to indicate that not only do
 the objects of a tree need to be listed in one uninterrupted list of object
 specifications (the first of which must  be the 'progenitor'), but the same
 applies for all 'sub-trees'  within  the  tree.  I.e. all children, 'grand-
 children' etc. of an object need to  be listed immediately after itself and
 before a sibling or any of its offspring is listed.


 RESOURCE FILES:

     Anyone can create  object  trees  directly  in  the  source  text  of a
 program, in which case the one  and  only  requirement  on the order of the
 structures is the one just  mentioned  (for  objects  belonging to the same
 tree). As long as all  pointers  are  right,  different trees can be placed
 wherever desired, and so can all the other, secondary, structures.

     However, as a convenience, a set of  AES routines exists to deal with a
 collection of many object  trees  with  associated  structures, strings and
 images placed together in an RSC  FILE.  The  RSC file in addition has room
 for so called 'free' strings  and  images  -  i.e.  not associated with the
 object-related structures; this makes it  possible  to include for instance
 alertbox definitions as well in an RSC file - as free strings.


     When an RSC file is loaded with RSRC_LOAD two modifications to the file
 data are, as mentioned, made automatically:
 1) All measures are converted from CHARACTERS into PIXELS.
 2) All Long pointers are relocated.
 Not using RSC_LOAD means these modifications must be made some other way.

     What  is  NOT  made   automatically   is   conversion  of  IMAGES/ICONS
 (apparently with the of  exception  colour  icons  in  TOS  4) from the VDI
 standard format, used in the  RSC  file,  into device specific format. This
 isn't a big problem since  the  images  are  'monochrome' (1 plane images),
 which means that errors could occur only with certain graphic cards. Still,
 a perfectionist should let the VDI  function  VR_TRNFM  have a go with each
 mono image in the RSC file.



                              FORMAT OF RSC FILES
                              -------------------

 (All offsets are relative to file start, and UNSIGNED)

 HEADER: (18 words)

 W: RCS version number:  bit 2 set => TOS 4+  (i.e. 0 or 1 = old, 4 = new)
 W: Offset to first object
 W: Offset to first TEDINFO  (secondary structure for formatted text string)
 W: Offset to first ICONBLK  (secondary structure for icon)
 W: Offset to first BITBLK   (secondary structure for simple image)
 W: Offset to pointer table (L) - free strings (typically alertbox strings)
 W: Offset to first string - free or not
 W: Offset to first image data (or mask) - free or not
 W: Offset to pointer table (L) - free images
 W: Offset to pointer table (L) - object trees (i.e. root objects)
 W: Number of objects
 W: Number of trees
 W: Number of TEDINFOs
 W: Number of ICONBLKs
 W: Number of BITBLKs
 W: Number of free strings
 W: Number of free images
 W: File length in bytes (or offset to TOS 4+ extension see v number above)

 After this the structures come,  apparently  always  in the following order
 (this order shouldn't be a requirement, but you never know):

     Strings (null-ended)
     Images
     BITBLKs (14 bytes each)
     ICONBLKs (34 bytes each)
     TEDINFOs (28 bytes each)
     Objects (trees) (24 bytes/object)
     Table of pointers (L) to object trees (i.e. to root objects)
     Table of pointers (L) to free strings
     Table of pointers (L) to free images

 The whole pre-TOS4 RSC file must always be less than 64K in size (since the
 file length is given in just a WORD in the header).

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

 EXTENSION (TOS 4+) may follow after above structures (see v number above):

 L: REAL length of the RSC file (no longer any 64K limit)
 L: Pointer to 'pointer table' to CICONBLKs (for colour icons)
 ?L: Possible further pointers which however not yet are defined.
     -1 = 'Empty' pointer;  0 = No more pointers

 The pointers in the CICONBLK pointer  table  can  actually be zeroed in the
 file, since when loading with  RSRC_LOAD  they will automatically be filled
 in. (This is possible for the AES to  do  because the CICONBLKs are - in an
 RSC file - REQUIRED to follow  directly  on the pointer table.) The pointer
 table is ended with a -1. So the  actual structure, to which the pointer in
 the second longword of the extension is pointing, looks like this in an RSC
 file on disk:

 L: 0 (= there is a first CICONBLK following this table)
 L: 0 (= there is a second CICONBLK following this table)
 ... etc.
 L: -1 = no more CICONBLKs
 1st CICONBLK (and its related structures - se below)
 2nd CICONBLK (               -  "  -               )



                                    OBJECTS
                                    -------

 Each OBJECT is built as follows (12 words = 24 bytes):

 W: # of next sibling object  (for last child: # of parent;  for root: -1)
 W: # of first child object (or -1 for childless object)
 W: # of last child object (or -1 for childless object)

 W: Object type.  B: 'Extended type', program definable.
                  B: Basic object type (20-33) used by system - see below.

 W: Flags -   bit 0: Selectable (in dialogue boxes; not used for menu items)
                  1: Default (= selectable through RETURN key)
                  2: EXIT (when left mouse button pressed and released)
                  3: Editable (Set in G_FTEXT and G_FBOXTEXT objects)
                  4: Radio button (= deselects sibling radio buttons)
                  5: Last object of tree (in object list). IMPORTANT BIT!
                  6: TOUCHEXIT (immediately when left mouse button pressed)
                  7: This and subordinate objects hidden/ignored (See below)
                  8: Further indirection of object spec. (Not normally used)

     TOS 4+ only: 9: 3D 'indicator' (for radio buttons & on/off buttons)
                 10: 3D 'activator' (for exit buttons)
     BOTH 9&10 set: 3D background obj.  =>  any  OUTLINE in 3D, plus if fill
     colour = white and fill pattern = 0  replace with default 3D BG colour.
                 11: Sub-menu attached (for menu items only)

 W: State -   bit 0: Selected (Drawn in inverse video)
                  1: Crossed  (with WHITE lines)
                  2: Checked  (Check mark to the (upper) left)
                  3: Disabled (Any text written in light style)
                  4: Outlined ((Extra) border drawn around object)
                  5: Shadowed (down and right)


 L: Object specification:

  1) Simple       B: Character (for G_BOXCHAR - object type 27), or zero
     boxes        B: Border thickness (0=none,positive=inwards,neg.=outw.)
     possibly     N: Border colour
     with         N: Text colour
     single       N: Fill level (0-7) +8 for any opaque (white) char. backgr
     character    N: Fill colour

  2) For other objects the specification  is  a  pointer  to either a simple
     text string, or to a further structure with more data (see below).


 W: X coordinate relative to the parent
 W: Y coordinate relative to the parent
 W: Width
 W: Height
 --------
 12 words (24 bytes)


 OBJECT TYPES:                                                   Object spec

     Boxes:            20. G_BOX                                 see above
                       25. G_IBOX      Invisible                 see above
                       27. G_BOXCHAR   With single character     see above

     Simple text:      26. G_BUTTON    Centred in box            -> string
                       28. G_STRING                              -> string
                       32. G_TITLE     Menu title                -> string

     Formatted text:   21. G_TEXT                                -> TEDINFO
                       22. G_BOXTEXT   In box                    -> TEDINFO
                       29. G_FTEXT     Editable                  -> TEDINFO
                       30. G_FBOXTEXT  Editable in box           -> TEDINFO

     Images:           23. G_IMAGE                               -> BITBLK
                       31. G_ICON      with mask + possib. text  -> ICONBLK
                       33. G_CICON     Ditto in colour (TOS 4)   -> CICONBLK

     Special objects:  24. G_PROGDEF   Freely definable          -> APPLBLK

 If the indirection flag (bit 8  of  flag  word)  is  set, each of the above
 object  specifications  is  replaced  with  A  POINTER  TO  the  respective
 specification. (This would for most objects  mean  a pointer to a pointer).
 The indirection flag seems however to be  rarely  used (and never in an RSC
 file).


 THE EXTENDED TYPE (the upper type byte) is free to be used for any program-
 defined purpose. For instance a  justification  code  could be placed here,
 telling the program to  justify  (left,  right,  centre) an object (string)
 within its parent before use.  Other  codes  could  instruct the program to
 change the object into a G_PROGDEF.


 NOTE: Objects of type G_PROGDEF never  occur  in  RSC files, but are always
 set up by the program.  Typically  the  to-be-G_PROGDEF object is stored in
 the RSC file as one of the other  standard type objects, but with the upper
 type byte (extended type) filled in as well - with some value that only the
 program will understand and use  to  translate  the object into a G_PROGDEF
 with a suitable APPLBLK. This is the  way  that a program can have dialogue
 boxes with round buttons,  or  buttons  that  when  selected become crossed
 instead of shown inverse video etc.


 EDITABLE OBJECTS - BUGS:

 Only in objects of  types  29  or  30  (G_FTEXT  and G_FBOXTEXT) should the
 editable flag (bit 3) normally be set. It  tells the AES in what objects to
 place any cursor for text editing.  Unfortunately there are (in earlier TOS
 versions) two bugs connected to this flag:

 1) Editable last object:

 One bug shows itself when an editable  object  is  also the last one in the
 object list for a tree (in which case the vitally important last-object bit
 should be set). The object won't  be  found  by  TOS when moving the cursor
 around with the keys. (TOS simply  reads  and acts upon the last-object bit
 before it does the editable bit.) The solution is however very simple. Just
 make sure the last object never is editable, if need be by adding a further
 little invisible box to the end of the list.

 2) Editable hidden objects:

 The other bug makes itself known when an editable object is 'hidden' - i.e.
 when the 'hidden bit' (bit 7  in  flag  word)  is  set in either the object
 itself or in one of its 'ancestors'.  The whole sub-tree, originating in an
 object with its hidden bit set,  should  be  invisible and ignored, but TOS
 does NOT ignore editable objects  when  moving  the  cursor around with the
 keys.

 The idea (or at least  one  of  them)  behind  hidden  sub-trees is to make
 possible alternative  sub-trees  between  which  could  be  easily  toggled
 without the need for a complete rearrangement of the tree.

 A cure for the bug proposed in ST Magazin (by Laurenz Prner in issue 6/92
 of this now extinct  German  magazine)  is  a  sub-routine  that clears any
 editable bits in a  hidden  sub-tree,  plus  another  routine that restores
 these bits when the sub-tree is  made  unhidden again. The objects on which
 to perform these manipulations should  I  think  be  exactly the objects of
 types 29 or 30. (Laurenz Prner proposes another method to mark objects to
 manipulate - making use of one of the currently unused flag bits - but this
 I think would be more prone to cause future incompatibility problems.)



                                    TREES
                                    -----

     An object tree is  stored  as  a  list  of  object structures, and each
 object is identified by its order number  in  this list. The root object is
 always the first object and is assigned the number zero. The last object in
 the list must have its last-object flag set (bit 5 in flag word at offset 8
 or in the BYTE at offset 9 from object start).


 MENUS:

 Whereas the construction of a dialogue box is restrained by very few rules,
 menu object trees always look like follows  (I have used line graphics here
 - if you don't use a PC or  Protext,  use PC_LINES.PRG to get them right on
 screen):
                                                   Ŀ
               Ŀ Ŀ Ĵ TITLE: G_TITLE 
                MENU BAR:    ACTIVE: G_IBOX   
                G_BOX, but   X=2, Y=0, H=     Ŀ
             Ĵ no fill or Ĵ $301, W=enough Ĵ TITLE: G_TITLE 
               border,X=0   for the titles,  
               Y=0,H=$201   not more         Ŀ
                Ĵ TITLE: G_TITLE 
                                                  
 Ŀ                                        Ŀ
   MENU:                                        Ĵ MENU ITEM: G_STRING 
   I_BOX                     Ŀ  
  Extent: Ĵ                   DROPBOX: G_BOX   Ŀ
  Screen                      Border thick-  Ĵ MENU ITEM: G_STRING 
                  Ĵ ness = -1,       
                               Big enough for   Ŀ
                               its menu items  Ĵ MENU ITEM: G_STRING 
              Ŀ     
               DROP AREA:   Ŀ   Ŀ
               G_IBOX,       DROPBOX: G_BOX  Ĵ MENU ITEM: G_STRING 
               Y=$301,       Border thick-    
             Ĵ Extent:    Ĵ ness = -1,     Ĵ Ŀ
                area below    Big enough for  Ĵ MENU ITEM: G_STRING 
                menu bar      its menu items    
                    Ŀ
                               Ŀ Ĵ MENU ITEM: G_STRING 
                                DROPBOX: G_BOX   
                                Border thick-    Ŀ
                              Ĵ ness = -1,     Ĵ MENU ITEM: G_STRING 
                                 Big enough for   
                                 its menu items   Ŀ
                                 Ĵ MENU ITEM: G_STRING 
                                                     

 As can be seen the  root  of  the  MENU  is  a G_IBOX (invisible box) which
 should cover just about the whole  screen  (possibly leaving out the bottom
 lines). It has got two children: the  menu  bar (= top screen line) and the
 drop area (below this). As you can see the height of the menu bar should be
 '$201' (=1 full character plus two  more  pixels),  while the height of its
 child is one pixel more (??? Don't  ask  me why, it's a complete mystery to
 me, but all menus look like this). Also the drop area doesn't begin until 1
 character + 3 pixels down.

 The child of the menu bar, an invisible box called ACTIVE, defines the area
 within which the AES is to watch  the  mouse.  It should be wide enough for
 all the titles but not more.

 First title should be the program  name  (in uppercase letters according to
 at least German standard I think).

 First dropbox should  contain  EIGHT  menu  items,  the  first  of which is
 usually 'About  ...',  the  second  should  be  a  disabled  separator line
 ('---------'  use as many hyphens as  needed).  The remaining six are dummy
 objects used by the AES for  accessories,  and are typically initialized to
 point to strings containing '1',  '2'  etc.  up  to  '6' but I really don't
 think it matters what these strings contain.

 Each title should be preceded by a space and followed by another one.

 The strings used for menu items  should  each begin with two spaces (enough
 for a check mark + space).  The  selectable  flag  is NOT used in menu item
 objects (they are selectable anyway, as long as they aren't disabled).


 For a weird programmer, some  very  small  changes to the above description
 are possible I think, without  jeopardizing  the  function of the menu. For
 instance a second child could be  added  to  the  menu line, in the form of
 some symbol in the upper right  corner  of  the  screen. And for menu items
 could in some cases be used images instead of G_STRINGs.



                              SECONDARY STRUCTURES
                              --------------------
         pointed to by the object specification pointer of some objects


 TEDINFO:  (14 words = 28 bytes)

 L: Pointer to string (If 1st char. is '@' the rest interpreted as spaces)
 L: Pointer to 'template' (= String with underlines for editable positions)
 L: Pointer to 'validation string' (containing symbols for valid characters)
 W: Font: 3=sys(16/8 x8), 5=mini(6x6), 0,1,2=Speedo (0=prop,1=mono,2=bitmap)
 W: =6 (or font-ID with SpeedoGDOS and TOS 4)
 W: Justification (0=left, 1=right, 2=centred)

 W: Colour etc.: N: Border colour            (Border and fill only used with
                 N: Text colour                    G_BOXTEXT and G_FBOXTEXT)
                 N: Fill level (0-7) +8 for any opaque (white) text backgr.
                 N: Fill colour
 W: =0 (or font-size with SpeedoGDOS and TOS 4)
 W: Border thickness (0=none, positive=inwards, negative=outwards)
 W: String length incl. ending NULL byte
 W: Template length incl. ending NULL byte
 --------
 14 words (28 bytes)

 For G_TEXT and G_BOXTEXT (object types 21 and 22) only the first pointer is
 of interest. The other two pointers are used only with the editable objects
 G_FTEXT and G_FBOXTEXT (types 29 and 30).

 For these the text  made  visible  is  a  combination  of text template and
 string. Basically the template comes first  followed by the string, whereby
 however any editable positions (underlines) in  the template are treated as
 free gaps to fill with the characters from the string that are in turn.

 In the validation string each character corresponds to an editable position
 and defines what characters are allowed in this position.

     9   must be a digit (0-9)
     A   uppercase letter or space
     a   uppercase or lowercase letter or space
     N   digit, uppercase letter or space
     n   digit, uppercase or lowercase letter or space
     F   Any valid DOS pathname character plus     : * ?
     P   Any valid DOS pathname character plus   \ : * ?
     p   Any valid DOS pathname character plus   \ :
     X   Anything

 Note that  (contrary  to  what  is  indicated  in  for  instance  the Atari
 compendium) the A, a, N and n  options work just as well with 'non-English'
 letters in the Atari character set. (I.e. the AES is capable of recognizing
 letters in the extended character  set  as  such and to distinguish between
 uppercase and lowercase versions of these.)

 However, this doesn't fully apply when F, P or p is used, to limit input to
 DOS characters. In  this  case  AES  will  for  A-Z  accept  only uppercase
 versions, but from the extended  set  will  unfortunately accept ANY letter
 (e.g. even lowercase  in spite of the fact that uppercase  also exists in
 the set). On the other hand  the  DOS functions themselves are incapable of
 making out the difference  between  uppercase  and  lowercase for these. (I
 would recommend that any lowercase input  is converted, when possible, into
 uppercase before being used in a GEMDOS call.)

 Interestingly  the  AES  will,  as   DOS  characters,  NOT  accept  special
 characters such as  '+'  or  '-'  even  though  these,  like  the 'extended
 letters' are actually tolerated by the DOS functions.

 (The above notes apply  to  my  own  Swedish  TOS,  but  I don't think this
 differs between TOS nationalities.)

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

 BITBLK:  (7 words = 14 bytes, but see under ICONBLK)

 L: Pointer to image data
 W: Width in bytes (must be even)
 W: Height in pixels
 W: X-offset in pixels into image data (skip image part to the left of this)
 W: Y-offset in pixels into image data (skip image rows above)
 W: Colour (0-15)
 -------
 7 words (14 bytes)

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

 ICONBLK:  (17 words = 34 bytes, but see below)
 (ALL measures and coordinates within ICONBLK are IN PIXELS.)

 L: Pointer to mask
 L: Pointer to image
 L: Pointer to icon text string
 N: Foreground colour
 N: Background colour
 B: Icon letter/character
 W: X of icon letter RELATIVE TO THE IMAGE
 W: Y           -   "   -
 W: X of image RELATIVE TO THE OBJECT
 W: Y           -   "   -
 W: Image width in pixels (must be divisible by 16)
 W: Image height i pixels
 W: X of icon text RELATIVE TO THE OBJECT
 W: Y           -   "   -
 W: Width of icon text area
 W: Height      -   "   -
 --------
 17 words (34 bytes)



 The lengths given for BITBLK and  ICONBLK  are  those I have found in newer
 documentation (e.g. the Atari compendium) as well as in existing RSC files.

 But some older sources (Katherine Peel's  Concise Atari ... Reference Guide
 and Abacus' GEM book) add one extra null word to the end of ICONBLK and one
 ditto to the end of BITBLK  (the  latter  according to Peel only). This may
 have been an early specification now dropped, maybe anyone else knows more?
 In any case this probably means  some  caution  is advised in assuming that
 the next ICONBLK will follow at offset 34 from the current one.

 However, in an RSC file on disk  I  think  it can be safely assumed that if
 the longword at offset 34 is non-zero  it  IS the first longword (the image
 pointer) of the next ICONBLK. (Should  it  read  zero it must consist of an
 ending null-word +  only  the  upper  word  of  the  image  pointer  in the
 beginning if next ICONBLK.) And the similar  thing, for offset 14, goes for
 BITBLKs. The argument is of course that,  within  a  file less than 64 K in
 size, any longword address has its upper word zeroed.

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

 CICONBLK (TOS 4): (19 words or 38 bytes)

 17W = ICONBLK (Here the length of 17 words should be certain ?)
 L: In an RSC file on disk: Number of CICONs associated with the icon
    When in use in memory : Pointer to the first CICON.
 --------
 19 words (38 bytes)


 CICON: (11 words = 22 bytes)

 W: Number of colour planes for this CICON
 L: Pointer to image for unselected icon
 L: Pointer to mask for unselected icon
 L: Pointer to image for selected icon (or 0 if "unselected image" used)
 L: Pointer to mask for selected icon (if image pointer wasn't 0)
 L: 0 = No more CICONs  Otherwise pointer to next CICON (or =1 in a file)
 --------
 11 words (22 bytes)

 Colour images should match dimensions etc.  given  in (the part of CICONBLK
 that corresponds to an) ICONBLK. If  the  AES  doesn't  find a CICON with a
 usable number of colour planes, the  mono  icon  defined by ICONBLK will be
 used.


 In an RSC file on disk the CICON pointers don't have to be right (since the
 data will follow immediately after  the  CICON  anyway),  but if a separate
 image is used for selected icons,  this  must  at least be signalled by its
 image pointer being non-zero.

 In an RSC file on disk all structures and data for a colour icon must be in
 the following order:

     CICONBLK
     Mono data
     Mono mask
     12 bytes for any icon text
     First CICON
       its data for unselected icon
       its mask for unselected icon
   (   its data for selected icon  if corresponding CICON  pointer non-zero)
 (     its mask for selected icon  if above CICON data pointer was non-zero)
     Next CICON  etc.

 Should you create colour icons not in an RSC file, you can ignore the above
 but need to make sure the pointers are right.


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

 APPLBLK:  (2 longs or 8 bytes - though the last longword could be omitted)

 L: Pointer to sub-routine for drawing the object on screen
 L: Any data to be passed to the routine by the AES
 --------
 4 words (8 bytes)

 The sub-routine is called by the AES  each  time the object (or part of it)
 needs to be redrawn. It should call  VDI  routines only (no AES), the first
 of which should be VS_CLIP to set a clip rectangle according to coordinates
 received from  the  AES.  Any  VDI  call  could  then  be  used,  including
 VRO_CPYFM, so it would for instance be  possible  to copy an image block of
 pre-drawn fancy buttons and indicators.

 A VDI virtual workstation of  your  own  should  be  used, NOT the physical
 screen workstation of the AES, even though  the sub-routine will be used in
 the AES context.

 A pointer is passed as  input  from  the  AES  and  a  word  value is to be
 returned as output. The input is on  the  stack  - i.e. a longword found at
 4(SP) - and the return value  is  to  be  placed  in  D0 (like with other C
 routines on the ST).

 You are NOT free to  use  all  registers  as  you like. Specifically I have
 established, in experiments, that change of contents  in A5, A6 or D3 leads
 to visible bad results,  but  probably  none  of  registers  D3-D7 or A3-A6
 should be  touched.  On  the  other  hand  registers  D0-D2  and  A0-A2 are
 documented as being  used  as  work  registers  by  the  VDI functions your
 routine is to call and  can  probably  be  used  directly in the routine as
 well.

 An addition there is VERY LITTLE ROOM ON STACK within the routine (a system
 stack is used here), which, among other  things means that you cannot solve
 the previously mentioned problem by  saving  all registers on stack (though
 you can save them elsewhere  of  course).  Some  tests  I have made seem to
 indicate that there is room for only  about  6 or so longwords on the stack
 (with TOS 1.04). Remember that  any  sub-routine  call  will  use up one of
 these.

 Maybe someone else has  got  more  precise official documentation regarding
 use of registers and stack within the custom object drawing routines?


 The INPUT pointer - from 4(SP) - points to the structure PARMBLK:

 PARMBLK: (15 words, set up by the AES - don't worry about where)

 L: Pointer to tree
 W: Object number within tree
 W: Previous state (according to which the object shown on screen at entry)
     if this = Current state, then nothing is on screen at time of entry
 W: Current state (to be drawn by routine or left for the AES to do)
 W: X   of object
 W: Y      -"-
 W: Width  -"-
 W: Height -"-
 W: X of clip rectangle to be set by routine
 W: Y                 - " -
 W: Width             - " -
 W: Height            - " -
 L: The program-defined data from the APPLBLK
 --------
 15 words (30 bytes)

 If Previous state =  Current  state,  then  the  sub-routine  must draw the
 complete object from scratch. If not,  then the routine could possibly just
 add the necessary modifications to make  the object image on screen reflect
 the new state. (Reasonably, the latter case could only occur for selectable
 objects, with the selected bit being toggled on and off.)

 As OUTPUT (in D0.W) should  be  returned  a  word containing the state bits
 that the routine leaves for  the  AES  to  draw.  In most cases the current
 state word is simply read from offset  8  in PARMBLK and returned as it is.
 But the routine could also clear certain bits that it takes care of itself.
 For instance a program defined button could  have a routine draw a cross in
 it when it is selected and  clear  the  selected  state bit from the return
 value to prevent the AES from inverting colours.

 NOTE 1: The AES, in my experience,  doesn't care to draw the SHADOWED state
 for G_PROGDEFs, so any such effect must be drawn by the custom routine.

 NOTE 2: Only in connection to  the  initial drawing (the one where Previous
 state = Current state) the AES (of TOS 1.04) seems to draw ANYTHING AT ALL!
 This  shouldn't  make  a  difference  for  non-selectible  objects,  but  a
 G_PROGDEF that is SELECTABLE probably must  do  any  and all of the desired
 states itself (except for a  possible  outline, which shouldn't normally be
 affected by further redraws after  the  initial  one, since it lies outside
 the actual object area).

