
                  GEM PROGRAMMING by Jonathan White

                               ARTICLE 9

Hello and welcome to this month's GEM article.

This time we are going to start into our look at GEM resources, one of the 
more complex but most useful parts of GEM. This month I am going to talk a 
little about the different parts of a resource (NOTE: a resource and a resource 
FILE are not the same thing. A resource file can and usually does contain 
several resources).

But what exactly IS a resource? The answer is mostly anything. The file selector 
is a resource. Menus are resources. And the GEM desktop is a resource. So is any 
dialogue box you use when you use a GEM program. Basically, a resource is a 
collection of boxes, lines and pieces of text (all these are called OBJECTS) 
that prompt the user for some sort of input. Much beyond that, and you are 
getting too specific to cover them all.

So, a typical dialogue box is a resource. It is a also a collection of objects. 
That is a resource is constructed from the objects. Take a typical dialogue 
box..

                          <insert snapshot.img>

We can see that it is a box, which contains several smaller boxes, which 
themselves contain other things. Some of them are marked out from the others by 
having thicker lines or by being inverted. This also helps to show us how a 
typical dialogue box is organised. Resources are drawn from the back objects to 
the front objects. That way things never overlap where they shouldn't.

The first thing to be drawn is the main box. This is known as the ROOT object. 
After that (below it in the 'tree'). Are several objects. Each of these (the two 
boxes on the left BUT NOT the contents of the bottom one, the two 'exit' 
buttons, the two 'edit' lines and the 'dialogue 2' box) are all drawn at the 
same time and are all one step down the list from the root box. The root box is 
known as the PARENT of all these objects, and they are SIBLINGS, since they all 
have the same 'parent'. They are also the CHILDREN of the root box. Below this 
level we have the two 'radio' boxes. Each objects PARENT is the object that 
completely surrounds it, so the two RADIO boxes and the EXIT boxes are NOT 
siblings, as they do not have the same parent. All these relationships will 
become important later, as we look at the particulars of how a resource - 
otherwise called an object tree - is organised. If you want an idea of how it is 
organised, imagine a directory on a disk, say C:. This has the top directory 
(C:\) - the ROOT directory. All the directories and files in the root directory 
are the CHILDREN of C:\ and the SIBLINGS of each other. These directories might 
have files in them and each file (or directory) in that directory is the child 
of that directory and are siblings of each other and so on down the 'directory 
tree'.

For now we will not concern ourselves too greatly with organising objects, as 
that will all become clear soon. For now, we shall look at the data objects 
containing several C STRUCTS.

All objects have a common main structure, defined as the OBJECT type, in one of 
your C compilers GEM include files (you should check to find which one). It has 
the following structure

{
        WORD  ob_next;
        WORD  ob_head;
        WORD  ob_tail;
        UWORD ob_type;
        UWORD ob_flags;
        UWORD ob_state;
        VOID  *ob_spec;
        WORD  ob_x;
        WORD  ob_y;
        WORD  ob_width;
        WORD  ob_height;
} OBJECT;

Some of these are self explanatory - ob_x,ob_y,ob_width and ob_height define the 
position and size of the object on the screen. The rest need a closer inspection.

ob_next, ob_head and ob_tail are used to define the tree structure of the dialog. 
Each object in the dialog is given a particular number, starting from the root 
object of 0 on downwards, and going down and right to find the next one. ob_next 
gives the number of the next object to draw after this one. Therefore, siblings 
have numbers in sequence, unless one of the siblings has children, in which case 
they get the next number, and so on down. A typical tree might look like this.. 

                                        0(root)
                                        |
                                        |
                                -----------------
                                |       |       |
                                1       2       5
                                        |
                                    ---------
                                    |        |
                                    3        4

These numbers are used in the fields ob_next, ob_head and ob_tail. ob_next 
points to the next object in the tree that is a sibling. The final sibling of 
any 'level' has an ob_next that points to his parent. The root object requires 
an ob_next of -1, which signifies it as the root, because by definition it can 
have no siblings. If an object has children, the ob_head contains the number of 
its first child, and ob_tail, the last. If an object has no children, their 
values are -1. Therefore, our tree has values as follows...

        object          ob_next         ob_head         ob_tail
          0                -1              1               5
          1                2              -1              -1
          2                3               3               4
          3                4              -1              -1
          4                2              -1              -1
          5                0              -1              -1
          
These values allow the system to draw the tree in the correct order, back to 
front, so that objects are properly visible. Basically, if ob_head contains 
other than -1, draw that number object, otherwise draw ob_next. ob_tail tells it 
where to go  back to to carry on when it has drawn one 'branch' of the tree. 

NOTE: by fooling around with these values and using special objects (which we 
will come to later) many special effects can be produced. Although, obviously, 
unless you are REALLY sure of what you are doing, the effects are likely to be 
disastrous.

ob_type defines the type of object with the dialog, surprise surprise. The 
possible values are as follows..

 
ob_type value   Name
        20      G_BOX           (An opaque box, possibly with a border)
        21      G_TEXT          (A formatted text string - colour, font size..)
        22      G_BOXTEXT       (G_TEXT inside a G_BOX)
        23      G_IMAGE         (A monochrome bitmap image)
        24      G_PROGDEF       (An object with a userdefined drawing routine)
        25      G_IBOX          (An 'invisible box. Used to group objects)
        26      G_BUTTON        (A string with a box around it)
        27      G_BOXCHAR       (A single letter in a G_BOX)
        28      G_STRING        (A string of system font text, unformatted)
        29      G_FTEXT         (A user editable string of formatted text)
        30      G_FBOXTEXT      (A G_FTEXT in a G_BOX)
        31      G_ICON          (A monochrome icon (different from a G_IMAGE))
        32      G_TITLE         (A special object form used for menu titles)
        33      G_CICON         (A NEW AES colour icon)
        
Each of these objects are modified by three other fields- ob_flags, ob_state and 
the information pointed to by *ob_spec.  The first two are the same for any 
object, so we can look at them first. Both are a set of binary flags which 
define certain properties of the object..

ob_flags..

BIT     NAME            FUNCTION
0       SELECTABLE      Clicking on this object with the mouse inverts it
1       DEFAULT         When drawn, this object has a bold border. If the return 
                        key is pressed, this object is automatically selected, 
                        and the dialog exits. No more than one object in any 
                        dialog can have this attribute set. 
2       EXIT            Clicking on this object caused the dialog to exit. It 
                        also has a bold border. An object which is both DEFAULT 
                        and EXIT will be double bold. For example, in the 
                        standard file selector, both OK and CANCEL are 'EXIT', 
                        with OK also being 'DEFAULT'
3       EDITABLE        This is usually used for text, allowing the user to 
                        change it. In the example, the path and the area right 
                        of 'SELECTION' are editable.
4       RBUTTON         This object is a radio button. If several objects at the 
                        same level have RBUTTON on, selecting one of them 
                        deselects the others. Note they also need 'selectable' 
                        set. RBUTTONS are usually set as siblings by making them 
                        the children of a small G_IBOX.
5       LASTOB          The object is the last in its particular tree. You can 
                        use this bit to temporarily remove part of the tree from 
                        view.
6       TOUCHEXIT       Similar to the EXIT flag, this has one important 
                        difference. With a normal EXIT object the dialog always 
                        quits when the button is clicked over it AND RELEASED 
                        (try it and see). With touchexit, it quits immediately 
                        the mouse button is pressed. This allows for rapid 
                        changes in the dialog box, and for draggable objects, 
                        by using the data from the dialog then quickly redrawing 
                        it. For example, the up and down arrows and vbar in the 
                        standard file selector are touchexit. When one is 
                        pressed, the list of files in the box is recalculated 
                        and redrawn instantaneously, allowing the user to scroll 
                        through lists.
7       HIDETREE        This object and all its children are not to be shown. 
                        This allows for 'expanding' or changing dialog boxes. 
                        The easiest example of this is the copy / format dialog 
                        in the desktop. Depending on which of the buttons are 
                        selected (touchexit selectable rbuttons, yes?  You see, 
                        it's easy when you know how..) a part of the dialog is 
                        hidden and the other unhidden. In this case they DO  
                        overlap, but as long as only one is visble at once, this 
                        is not a problem. 
8       INDIRECT        This one allows for more data to be stored than the 
                        STRUCT could normally hold. Normally, the ob_spec field 
                        holds a struct of data. If INDIRECT is set, it instead 
                        holds a POINTER to a struct of data.
                        
9       FL3DIND
10      FL3DACT
        These help define the object's appearance in terms of the NEW AES 3D 
        dialog boxes, seen on the Falcon and the MultiTOS desktop. THe object is 
        shaded according to the following plan..
        
        9       10      Action
        0       1       This object is a 3D actuator. Suitable for EXIT objects
        1       0       This object is a 3D indicator. Suitable for radio / 
                        toggle buttons
        1       1       This object is part of the 3D background. If its colour 
                        is set to white and fill 0, it will inherit the default 
                        3D background colour.

11      SUBMENU         This object has a submenu associated with it. These are 
                        also part of the NEW AES, and are somewhat beyond the 
                        scope of a beginners article.
                        

ob_state functions in a similar way. It too represents a set of binary flags 
which show the current appearance of the object, as follows..

BIT     NAME            FUNCTION
0       SELECTED        The object is highlighted -inverted usually, unless new 
                        AES, when its 'highlighted' appearance depends upon 
                        its type.
                        
1       CROSSED         For box objects, an X is drawn in the box. Note a 
                        touchexit box is required so a mouseclick can be 
                        responded to by setting this option.

2       CHECKED         For menu items, on=having a tick mark next to it. There 
                        is a specific function ( menu_icheck() ) to toggle this 
                        bit.

3       DISABLED        Greyed out by masking off every other bit. THe AES will 
                        not allow the user to click on it. NOTE: A disabled 
                        object can still be selected by return if it is DEFAULT.

4       OUTLINED        An outline is drawn round a box object. A truly 
                        invisible box would be a G_IBOX with a fill of 0 and 
                        OUTLINED set to 0.
                        
5       SHADOWED        A 'drop shadow' of the object is drawn.

 
Between these two flag maps, a large part of the appearance of the object can be 
set. Other parts of the parameters for the object are set by the values in the 
ob_spec field. Since these are specific for each object type, we will now go on 
to discuss them in detail.

G_BOX, G_IBOX and G_BOXCHAR (the box objects) all share the same parameters. 
Their size is fixed by members of the OBJECT structure, but further attributes 
are set by ob_spec. In this case, the field directly contains (rather than 
points to) the data. The two WORDS are split as follows..

        The lower WORD contains information as to the colour of the object as 
        follows..
        
        BITS    Function
        0-3     Interior colour (0-15)
        4-6     Interior fill
                        0       Background colour (IP_HOLLOW)
                        1-6     Dithered (IP_1PATT to IP_6PATT)
                        7       Foreground (IP_SOLID)
        7       Writing mode 0=transparent, 1=overwrite
        8-11    Border colour (0-15)
        12-15   Text colour (0-15)
        
        The lower byte of the upper word is a signed byte representing the 
        thickness of the border.
                -127 to -1      Outside thickness away from border in pixels
                0               No border
                1 to 128        Inside thickness away from edge inwards in 
                                pixels
        
        The high byte of the high word is used only by G_BOXCHAR and holds the 
        ASCII value of the character to be shown.
        
G_STRING, G_BUTTON and G_TITLE (the text objects) all share ob_spec parameters 
too. In this case, ob_spec contains a pointer to the text string to be 
displayed. This is in standard C format.
                
The next group (the formatted text objects) includes G_TEXT, G_BOXTEXT, G_FTEXT 
and G_FBOXTEXT. In these cases, ob_spec points to a defined GEM structure, 
called a TEDINFO structure..

        {
                char *te_ptext;         (pointer to the actual text string)
                char *te_ptmplt;        (pointer to the format template)
                char *te_pvalid;        (pointer to the validation string)
                WORD te_font;           (font info)
                WORD te_fontid;         (which font to use)
                WORD te_just;           (font justification)
                WORD te_color;          (color information - as boxes)
                WORD te_fontsize;       (font size to use)
                WORD te_thickness;      (border thickness of boxed objects)
                WORD te_txtlen;         (length of text string)
                WORD te_tmplen;         (length of template string)
        }TEDINFO;
        
Taking the font information first, the first consideration is te_font. This can 
have the following values..

        BIT     Name            Function
        0       GDOS_PROP       Use SpeedoGDOS font
        1       GDOS_MONO       Use SpeedoGDOS font, force monospacing
        2       GDOS_BITM       Use GDOS bitmap font
        3       IBM             Use standard system font
        5       SMALL           use small system font

Note that values of 1 and 2 will be ignored if the AES version is <4.1 and or 
SpeedoGDOS is not installed. 0 will be ignored if the AES version < 4.0 and 
SpeedoGDOS is not installed.  In these cases, 3 will be used.

If Speedo fonts CAN be used, te_fontid specifies which font is used and 
te_fontsize specifies how big. Otherwise these too are ignored.

te_hjust has a value of 0 selects left justified text, 1 specified right and 2 
centered.

The values of te_txtlen and te_tmplen MUST include the terminating character 
(ASCII 0).

The most complicated parts of the structure are the first three. te_ptext points 
to the actual string initially shown. A special case is if the first character 
is @, then the entire string is presumed to be filled wth spaces.

te_pvalid tells the system what characters are allowed in the string. for each 
character in te_ptext, there must be one in t_pvalid, defined as follows

        te_pvalid char          Character allowed
                9               numbers only (0-9)
                a               lower and upper case alphanumerics and space
                n               digits, alphabetic (upper and lower), and space
                p               all chars valid in a filepath
                A               uppercase only alphabetics and space
                N               uppercase alphabetics, digits and space
                F               all valid filename characters, including 
                                wildcards but NOT \
                P               all valid filepath characters (including 
                                wildcards and \ )
                X               anything whatsoever
                
Thus you can limit the name of a file output only to characters that are a valid 
filename etc.
                
te_ptmplt points to a string which defines the static (uneditable) characters 
in the string. This can, in fact be larger than the editable string and the 
system will align it correctly. Any character being overwritten by an editable 
one must be defined as a '_'.

We can look at several examples below

A filename with the extension not as a wildcard)
                te_ptext        ***********
                te_pvalid       FFFFFFFFppp
                te_ptmplt       FILENAME: ________.___
                
        would appear as 
                'FILENAME: ********.***'

a bank sorting code, two digits, followed by a minus sign, followed by 
four digits.      

                te_ptext        111111
                te_pvalid       999999
                te_ptmplt       CODE __-____
                
        would appear as
                'CODE 11-1111'
                
a telephone number, a four letter code in brackets, followed three digits, then 
a minus, then three digits

                te_ptext        1234567890
                te_pvalid       9999999999
                te_ptmplt       Phone: (____)___-____

        would appear as
                'Phone: (1234)567-890'

Obviously, a lot of the time you would fill te_ptext with spaces or underline 
characters.

These are the most basic means a user has to enter data into a dialog box.

The next type of object is the monochrome image, or G_IMAGE. This is distinct 
from a monochrome icon in that it is not meant to be selectable. This allows 
its structure to be simpler. In this case, the value of ob_spec is again 
indirect, and it is a pointer to a structure known as a BITBLK, which has the 
following definition..

{
        WORD *bi_pdata;         // pointer to bit image data
        WORD bi_wb;             // bit image width (in bytes - must be even)
        WORD bi_hl;             // height of image in lines
        WORD bi_x;              // X offset from start of data block
        WORD bi_y;              // Y offset from start of data block
        WORD bi_color;          // Image foreground color
}BITBLK;

Some of these (b_color, wb, hl, and pdata) are clear. The two that require 
explanation are bi_x and bi_y. These, along with bi_wb and bi_hl allow you to 
'pick' an icon form out of the pdata area, which might contain several images in 
one bitmap.

The pdata map itself is a simple bit array, which must be WORD aligned. Each 1 
bit is drawn in the foreground colour.

The next most sophisticated object is similar, the G_ICON. This is different 
from G_IMAGE in that it is meant to be selectable and has a particular 
behaviour when it is. The ob_spec field of a G_ICON type points to a data 
structure called an ICONBLK. This is defined as follows..

{
        WORD *ib_pmask; // pointer to the image mask data
        WORD *ib_pdata; //   "     "  "    "   data
        char *ptext;    // pointer to the object's text string
        WORD ib_char;   // low byte = ASCII character drawn on icon
                        // high byte = foreground and background colours
        WORD ib_xchar;  // x offset of that character
        WORD ib_ychar;  // y offset of that character
        WORD ib_xicon;  // X coordinate of the icon (in image data)
        WORD ib_yicon;  // y coordinate of the icon (in image data)
        WORD ib_wicon;  // width of the icon (pixels)
        WORD ib_hicon;  // height of the icon (in pixels)
        WORD ib_xtext;  // the x offset of the text string (from icon top)
        WORD ib_ytext;  // the y offset  "  "    "     "   (from icon left)
        WORD ib_wtext;  // the width of the text in pixels
        WORD ib_htext;  // the height of the text in pixels
}ICONBLK;

Most of this will be set up by the resource editor you use. The main thing to 
note is the way the AES draws the icon. First, it takes the bitmap of the mask, 
and colours pixels which are '1' in the mask to the background color. It leaves 
the '0' pixels alone. Then it colours all the pixels that are '1' in the data 
bitmap to the foreground colour. When the icon is selected, it uses the data for 
the mask and vice versa. Note that both bitmaps must be a multiple of 16 pixels 
wide.
        However, it is important to know this stuff in case you come across a 
situation where your program would wish to modify the icon as it was running. 
Personally, in these cases, I tend to have two ICONS and swap between them, but 
it's not as memory efficient, nor can you do some of the geewizz stuff (I once 
saw a program that had a milkbottle filling up as a progress indicator for a 
download process by realtime altering the mask. Very nice, but the time that bit 
took to figure out might have been better spent fixing some serious bugs in the 
program.).

The new form of colour icon, seen in the new falcon and multiTOS desktops (and 
available to any programs which use them - and I think Geneva and MagiC / EASE 
use them too) are known as G_CICONS. In this case, the ob_spec field points to a 
CICON_BLK structure. This has the following form..

{
        ICONBLK monblk;         // as above - the mono form of the icon
        CICON  *mainlist;       // see below
}CICON_BLK;

The CICON structure is a structure which defines a set of images for various 
colour scemes. Although, I have yet to see any 256 or truecolour icons, in 
theory such things are possible. They would possibly lead to VERY large .RSC 
files though. For those of you who haven't seen them, they have the distinction 
from standard icons that the selected form can be an entirely different icon 
from the normal form. They have the following format..

typedef struct cicon_data
{
        WORD numplanes;         //number of bitplanes in this form
        WORD *col_data;         // icon image data in device independant form
        WORD *col_mask;         // icon mask data; same format
        WORD *sel_data;         // selected form image data
        WORD *sel_mask;         // selected form mask data
        struct cicon_data *next;// pointer to next icon (i.e same icon, 
                                // different number of colour planes
}CICON;

Thus to look its best in any colour resolution a G_CICON would need 4, 16, 256, 
16 bit and 24 bit forms. An AWFUL lot of data for one icon. Note that if the 
*sel items = NULL, the icon will be shaded (dithered with midgrey) when 
selected.

As far as I know, the only resource editor that handles this form of icon 
properly is InterFace distributed by Compo. Hisoft WERCS crashes when you load 
a file with them in, and the chances of it being updated any time soon is 
virtually nil (Hisoft seem to have more or less stopped developing their own 
software and have become a licensing agency..) and I can't see anyone putting 
the effort into a shareware product with a proper multicolour icon editor. A 
pity, because they do enhance the look of a program greatly. Perhaps if MagiC 
becomes the standard OS across all ST's they will gain in popularity...

The last, and potentially most complicated resource type is the userdefined 
resource, or G_PROGDEF. For these, the system basically hands a section of the 
resource over to your program to draw and maintain. This can be anything from a 
font preview box, to a different form of radio button, to a realtime scrolling 
message.. In this case, ob_spec points to a structure called an APPBLK..

{
        WORD (*ab_code) (PARMBLOCK *);
        LONG ab_parm;
}APPBLK:

Basically, ab_code is a pointer to a function which redraws the section of the 
resource. The parameters of this function MUST be a PARMBLOCK structure. ab_parm 
is anything you wish.

{
        OBJECT *tree;           // pointer to the tree that contains this object;
        WORD pb_obj;            // the objects index in the tree
        WORD pb_prevstate;      // the objects old state field
        WORD pb_currstate;      // the objects current state
        WORD pb_x;
        WORD pb_y;
        WORD pb_w;
        WORD pb_h;              // the current size and position of the object
        WORD pb_xc;
        WORD pb_yc;
        WORD pb_wc;
        WORD pb_hc;             // the objects clipping rectangle
        LONG pb_parm;           // holds a copy of the ab_parm field of the APPBLK
}

Basically, the user routine will do something like this...

user_draw (pb)
PARMBLK *pb
{
        Parse_parmblk(pb);
        do_redraw;
        return(0);      // your routine should ALWAYS return 0
}

If you are doing this, you should be aware that the AES is calling the function 
so you should avoid using long lists of parameters or recursion within it and 
you should NEVER call AES functions within it.

All this is a bit advanced for us, I know, but it fits here if anywhere. If you 
don't understand it, don't use it is the best advise I can give. To be honest, 
documentation on this type is scarce enough as it is, so that I couldn't skate 
over it in case you could find no other source.


Well, that's the structure of GEM resources dealt with. The question you are 
probably asking yourself now is WHY? If a decent resource editor will do all 
this for me, why do I have to know it. Well, apart from the fact that you are a 
conscientious and diligent programmer who wants to know as much about GEM as 
possible (just like me ;-) ), the main way you get information on the actions a 
user takes when the resource is displayed is by the changes in these structures. 
When a user clicks or edits an object, its structures and data flags are 
changed accordingly. The only way we can detect what those changes are is to 
examine the structures after the dialog has quit. We will go on to look at this 
next time, when we will look at displaying dialogs and retrieving responses from 
them.
