Object types in MagiC
---------------------

Andreas Kromke
7.2.98
Last change: English translation: Peter West, April 99

Tabulator width: 5


1. Introduction
===============

Due to the constant extensions of the GEM object structure, as well as
partly differing concepts of MagiC and MultiTOS, it is time to specify
all object types and structures in an orderly manner, and also to keep 
them at the latest position in the future.

This file is intended to describe the diverse variants as well as their 
availability on various systems.


2. The OBJECT structure
=======================

In all TOS-compatible operating systems the actual object structure 
is identical:

typedef struct {
     WORD      ob_next;       /* index of next sibling */
     WORD      ob_head;       /* -1 or index of the first child */
     WORD      ob_tail;       /* -1 or index of the last child */
     WORD      ob_type;       /* object type */
     WORD      ob_flags;      /* flags */
     WORD      ob_state;      /* further flags */
     LONG      ob_spec;       /* depending on object type */
     WORD      ob_x;          /* x-position relative to parent */
     WORD      ob_y;          /* y-position relative to parent */
     WORD      ob_width;      /* width */
     WORD      ob_height;     /* height */
} OBJECT;

ob_type
-------

The high byte is used by the AES only for submenus. If the highest bit 
of ob_type (0x8000) as well as bit SUBMENU is set in ob_flags, then 
bits 8..14 specify which submenu is linked with the menu entry. This 
means that every application can have a maximum of 128 submenus.
MagiC always reads only the low byte from ob_type, except for submenu 
handling.
TOS reacts "cleanly" to unknown object types (e.g. the pure MagiC-types 
G_SWBUTTON etc.), meaning that the objects will not be drawn.

ob_flags
--------

SELECTABLE (0x0001)

This flag is evaluated only by form_do() and form_button() and indicates 
that the object is selectable, i.e. when clicked on the flag SELECTED in 
ob_state is toggled.

DEFAULT (0x0002)

This flag is evaluated by form_do() and form_keybd() and indicates that 
this object is the one that will be selected by pressing [Return]. Only 
one object at most in a tree should be the default object.
Furthermore, with the object type G_BUTTON it draws an additional border 
one pixel wide on the outside of the object (i.e. together with EXIT 
there are then 3 pixels).

EXIT (0x0004)

This flag is evaluated by form_do() and form_keybd() and indicates that 
when this object is selected the dialog will be exited and control will 
be returned to the caller.
Furthermore, with the object type G_BUTTON it draws an additional border 
one pixel wide on the outside of the object (i.e. together with DEFAULT
there are then 3 pixels).

EDITABLE (0x0008)

This flag is evaluated by form_do(), form_keybd() and form_button() and 
indicates that the cursor can be positioned in this field by clicking 
on it, or using the cursor-up/down or Tab/Shift-Tab keys.

RBUTTON (0x0010)

With RBUTTON, only one of all sibling objects must be in the selected 
state (ob_state SELECTED) at any given time. Hence this flag is 
evaluated by form_do() and form_button() to ensure that at the 
selection of an object all sibling objects that also have the RBUTTON 
set are reset.
The flag is _NOT_ evaluated by objc_change(), therefore this reset has  
to be performed manually.

LASTOB (0x0020)

This flag identifies the last object of the tree. The flag is required 
by form_keybd() and form_do() in order to search the object tree 
linearly (e.g. for the next editable input field, or in MagiC also for 
an object with a keyboard shortcut).

TOUCHEXIT (0x0040)

As EXIT, though the dialog will be exited immediately rather than after 
releasing the mouse button. Thus one can also recognise double-clicks. 
When TOUCHEXIT is set, the flag EXIT is without meaning.

HIDETREE (0x0080)

When this flag is set, the object and all sub-objects will be hidden 
for objc_draw() and objc_find(). Furthermore this flag is also 
evaluated from MagiC 5.20 onwards by form_keybd() when objects for 
keyboard shortcuts are being searched for.
An input into hidden objects (i.e. when the object or any of its 
parent or grandparent objects is hidden) is however still possible. 
To prevent this, EDITABLE has to be cleared.

INDIRECT (0x0100)

This flag is only useful for object types for which ob_spec is a pointer.
It indicates that the pointer is indirect, i.e. points to a pointer which 
in turn points to the data.

FL3DIND (0x0200)

This flag under MultiTOS creates a three-dimensional object. Under 
MagiC (from version 3.0 onwards) this applies only with 16 colours or 
more and when the 3D effect has not been switched off.
For this purpose a hollow, white-filled object will be drawn in light 
grey and supplemented by a 3D border. This border lies outside the 
object in MultiTOS and therefore enlarges it. In MagiC the object size 
remains unchanged.
For all 3D objects in MagiC, G_(BOX)TEXT with opaque text is converted 
to transparent text. This is necessary because, due to a design weakness 
of the VDI, opaque text always has a white background. 

The INDICATOR objects should be regarded as "latching" switches, i.e. 
on selection the object will not only appear "depressed" but will also 
be accentuated by colour.

When selecting an INDICATOR object, the box colour is changed from light
grey to dark grey. Furthermore any text that may be present will be drawn 
in a different colour.

Under MultiTOS this works in the following way:

     0    <=>  1
     2    <=>  13
     3    <=>  15
     4    <=>  14
     5    <=>  10
     6    <=>  12
     7    <=>  11
     8    <=>  9

In MultiTOS however this does _NOT_ work with G_BUTTON, G_TITLE and 
G_STRING, where the text colour remains unchanged. One can also not 
recognised any system in the way the colours are allocated, except that 
light grey and dark grey as well as black and white are swapped over.

MagiC therefore has the following transposition:

     0    <=>  1
     8    <=>  9
     otherwise: Toggle bit 3, i.e. darken/lighten the colour

In MagiC this colour transposition naturally also works for G_BUTTON, 
G_TITLE and G_STRING.
objc_change() always redraws the object at selection and deselection. 

FL3DBAK (0x0400)

In principle as FL3DIND, but should create a "background object", say  
a dialog background.
Actually the only difference lies in the fact that on selection the 
object is modified via an XOR mask.
objc_change() for (de-)selection also draws an XOR mask.

FL3DACT (0x0600)

As a 3D object can not be simultaneously INDICATOR and BACKGROUND, this 
bit combination is used to create an ACTIVATOR object. In principle 
this works like FL3DIND, but creates an object which "springs back" and 
does not latch when activated.
On selection any border present will be "inverted" (to represent the 
depression), and any text present will be moved right and down by 1 pixel.
objc_change() always redraws the object at selection and deselection. 

SUBMENU (0x0800)

This flag is used in MultiTOS and in MagiC from 5.10 onwards to 
identify hierarchical submenus. menu_attach() sets this bit in a menu 
entry to mark the fact that a submenu is attached here. The high byte 
of ob_type then contains the submenu number (128..255), i.e. bit 15 of 
ob_type is always set together with SUBMENU.

ob_state
--------

SELECTED (0x0001)

This flag shows that an object is "selected", generally by changing its
appearance. Thus 2D buttons become black, 3D objects appear depressed.
The effect of this flag therefore depends on the object type. For 
G_USERDEF, if the drawing routine does not itself evaluate the flag,
a black rectangle will be drawn in XOR mode over the object.

CROSSED (0x0002)

This flag when set draws a black 'X' in XOR mode over the object. 
Therefor it is only  sensible for rectangular objects (G_BOXTEXT, 
G_BOX, G_BUTTON), if at all, because it is only used very seldomly. If 
an object is to be identified as non-selectable, it is better to use 
DISABLED.

CHECKED (0x0004)

This flag when set draws the ASCII character 8 (tick) in black and in 
transparent mode at far left in the object. It is used mainly for menu 
entries, but also for switches that can be clicked on and off in 
dialogs because it doesn't look as heavy as a button. In MagiC a 
crossed check-button (see below) is preferable in dialogs.

DISABLED (0x0008)

This flag when set draws a grey (actually a fine b/w chequered) 
rectangular pattern (IP_4PATT) in transparent mode over the object.
In MagiC the pattern for 3D background objects is drawn in LWHITE 
(light grey).
In place of the rectangular pattern procedure, MagiC from 5.20 on when 
used in at least 16 colours draws G_STRING and G_TITLE in dark grey. 
Furthermore, a G_STRING consisting only of hyphens or minus characters 
is replaced in MagiC 5.20 and up by a dark grey unbroken line.

OUTLINED (0x0010)

This flag when set enlarges the object by three additional pixels in 
all directions. A 2-pixel-wide white border and a 1-pixel black border 
will be drawn.
In MagiC, 3D objects instead receive a 2-pixel inner and OUTLINED 
"ornamental border" for dialog boxes.

SHADOWED (0x0020)

This flag when set draws a black shadow at the right of and under the 
object, having twice the width of the object border.
With G_ICON and G_CICON this flag switches to a different font instead.

WHITEBAK (0x0040)

This flag when set causes the icon mask not to be drawn for G_ICON and 
G_CICON with a white background colour. This permits icons to be output 
faster on a white background.
From MagiC 3 onwards, this flag switches on special forms for G_BUTTON
(crossed check-buttons, round buttons, group frames, headings) as well as 
underlining of characters for keyboard shortcuts. This functionality can 
be inquired via appl_getinfo(), subfunction 13, fourth WORD, bit 2.

DRAW3D (0x0080)

With GEM 2.0 and MagiC 1.x and 2.x this flag when set causes the mask 
to be drawn three times, diagonally displaced, over a selected G_ICON 
to create a three-dimensional effect.

UNDERLINE (0x0f00)

From MagiC 2.0 on, only for G_STRING, G_TITLE and G_BUTTON and only in 
combination with WHITEBAK: Here the position and size of the underline 
are set.

XSTATE (0xf000)

From MagiC 2.0 on, only for G_STRING, G_TITLE and G_BUTTON and only in 
combination with WHITEBAK: Here one can switch between the various 
button types.


3. The TEDINFO structure
========================


For some object types:

     G_TEXT
     G_BOXTEXT
     G_FTEXT
     G_FBOXTEXT

<ob_spec> points to a TEDINFO (Text Edit Information) structure.
It describes the positioning, colour and size of the text to be output
(and underlying rectangle if appropriate). The structure looks like 
the following:

typedef struct
{
     char     *te_ptext;        /* pointer to text (must be 1st) */
     char     *te_ptmplt;       /* pointer to template           */
     char     *te_pvalid;       /* pointer to validation string  */
     WORD     te_font;          /* font                          */
     WORD     te_junk1;         /* junk int                      */
     WORD     te_just;          /* justification: left, right... */
     WORD     te_color;         /* colour information            */
     WORD     te_junk2;         /* junk int                      */
     WORD     te_thickness;     /* border thickness              */
     WORD     te_txtlen;        /* text string length            */
     WORD     te_tmplen;        /* template string length        */
} TEDINFO;

te_ptext
--------

Points to the actual text to be displayed. The pointer must always be 
valid, but it may point to a null-byte if so required.

te_ptmplt
---------

Points to the template (or mask). It is used only with G_FTEXT and 
G_FBOXTEXT, i.e. with G_TEXT and G_BOXTEXT it can be NULL.
During output, all the '_' characters in the template will be replaced 
successively by the characters in <te_ptext>, i.e. a mixed character 
string will be formed. So in general the template will contain as many 
'_'s as the length of the buffer for <te_ptext> (without the null-byte).


4. Object types
===============

G_BOX (20, 0x14)
----------------

This draws a rectangle.
ob_spec is a longword and contains the following information:
Bit 0..3:      fill colour (0..15)
Bit 4..6:      fill pattern (0=hollow .. 7=completely filled)
Bit 16..23:    border width (-128 .. 127)
               < 0: border within the object
               > 0: border outside the object
               0: no border


G_TEXT (21, 0x15)
-----------------

This draws a justified text in various colours and point sizes. 


G_BOXTEXT (22, 0x16)
--------------------


G_IMAGE (23, 0x17)
------------------


G_USERDEF (24, 0x18)
--------------------


G_IBOX (25, 0x19)
-----------------


G_BUTTON (26, 0x1a)
-------------------

In MagiC from 2.00 on the following special buttons can be specified:

Underline for G_BUTTON. One letter will be underlined, which makes the 
object selectable by pressing [Alt] in conjunction with the underlined 
key; this also works with numerals. It is recommended that the object 
height be increased by one pixel:

  Set WHITEBAK in ob_state 
  (ob_state >> 8) & 0xf sets the position of the underlined character
  (ob_state >> 8) & 0xf0 is 0

Group frame:

  ob_type = G_BUTTON
  Set WHITEBAK in ob_state
  (ob_state >> 8) == 0xfe

Crossed check-button:

  ob_type = G_BUTTON
  In ob_flags _deactivate_  RADIOBUTTON
  Set WHITEBAK in ob_state
  (ob_state >> 8) == 0xff

Crossed check-button, with underline for keyboard operation:

  ob_type = G_BUTTON
  In ob_flags _deactivate_  RADIOBUTTON
  Set WHITEBAK in ob_state
  (ob_state >> 8) & 0xf sets the position of the underlined character
  (ob_state >> 8) & 0xf0 == 0x80

Round radio-button:

  ob_type = G_BUTTON
  In ob_flags _activate_  RADIOBUTTON
  Set WHITEBAK in ob_state
  (ob_state >> 8) == 0xff

Round radio-button, with underline for keyboard operation:

  ob_type = G_BUTTON
  In ob_flags _activate_  RADIOBUTTON
  Set WHITEBAK in ob_state
  (ob_state >> 8) & 0xf sets the position of the underlined character
  (ob_state >> 8) & 0xf0 == 0x80


G_BOXCHAR (27, 0x1b)
--------------------


G_STRING (28, 0x1c)
-------------------

In MagiC from 2.00 on the following special types can be specified:

Underline for G_STRING and G_TITLE. One letter will be underlined, 
which makes the object selectable by pressing [Alt] in conjunction with 
the underlined key; this also works for numerals:

  Set WHITEBAK in ob_state
  (ob_state >> 8) & 0xf sets the position of the underlined character
  (ob_state >> 8) & 0xf0 is 0

Heading (completely underlined G_STRING). It is recommended that the 
object height be increased by two to three pixels:

  Set WHITEBAK in ob_state
  (ob_state >> 8) == 0xff

The object type G_STRING is also used for menu entries. So that these 
entries look serviceable with proportional AES fonts as well, they are 
handled by MagiC in a special way if the following applies:

     1. The large AES font is proportional
     2. The object tree is a menu
     3. The G_STRING starts with two space characters

If now the G_STRING (apart from the two spaces) consists only of '-' 
and is DISABLED, then in place of the hyphens a solid dividing line 
will be drawn. Otherwise an attempt will be made to split up the 
character string into commands and keyboard shortcuts and output them 
correspondingly. As this automation does not always work, in cases of 
doubt one should use the special MagiC object type G_SHORTCUT.


G_FTEXT (29, 0x1d)
------------------

3D input field:

  ob_type = G_FTEXT
  3D-flags BACKGROUND
  Border: Outside 2 pixels


G_FBOXTEXT (30, 0x1e)
---------------------


G_ICON (31, 0x1f)
-----------------


G_TITLE (32, 0x20)
-------------------

In MagiC from 2.00 onwards the following special types can be specified:

Underline for G_TITLE. One character will be underlined:

  Set WHITEBAK in ob_state
  (ob_state >> 8) & 0xf sets the position of the underlined character
  (ob_state >> 8) & 0xf0 is 0


G_CICON (33, 0x21)
------------------

For G_CICON objects that do not contain a CICON (supposed to occur at 
times), -1L is entered as cib_mainlist pointer. If there is a NULL 
there, one can assume that CICONs will follow after it.


G_SWBUTTON (34, 0x22)
---------------------

The "switch-button" has been available since MagiC 1.00 onwards, but is 
not supported by other operating systems.  The presence of the object 
type can be inquired via appl_getinfo(), subfunction 13, fourth WORD, 
bit 0.

The "switch-button" can be used when a button has to have more than two 
states. A G_SWBUTTON looks like a G_BUTTON at first, but when clicked 
on changes its legend cyclically (a double-click cycles "backwards" 
through the states).

A G_SWBUTTON is simpler to program and, with a short selection list, 
also easier to use than a popup. But as it only exists under MagiC and 
becomes rather obscure with more than three states, it is better to use 
the more flexible popup solution.

For G_SWBUTTON <ob_spec> points to a SWINFO structure, which is defined 
in MT_AES.H:

typedef struct {
     char *string;           /* say "TOS|MSDOS|MAG!X"            */
     WORD num;               /* no. of current character string  */
     WORD maxnum;            /* maximum permitted <num>          */
     } SWINFO;


G_POPUP (35, 0x23)
------------------

The popup button has been available since MagiC 1.00 onwards, but is 
not supported by other operating systems.  The presence of the object 
type can be inquired via appl_getinfo(), subfunction 13, fourth WORD, 
bit 1.

With this object type it is very (!) easy to accommodate a popup for 
multiple selection within a (window) dialog. Under MultiTOS it would be 
necessary to define a button for this that has the status EXIT. When 
leaving form_do() one would have to call and evaluate a menu_popup().
In MagiC all this is achieved automatically with G_POPUP, which is why 
MagiC service programs make good use of this object type.

ob_spec points to a POPINFO structure, which is defined in MT_AES.H:

typedef struct {
     OBJECT *tree;           /* popup menu                    */
     WORD obnum;             /* current object of <tree>      */
     } POPINFO;

tree points to an object tree, which could perhaps serve as input for 
form_popup(). This means that the box should contain a G_BOX or G_IBOX 
as object 0 which is completely covered by other objects. Those objects 
that are not selectable should be given the status DISABLED, just as in 
a drop-down menu. All selectable objects must have the status SELECTABLE.
In addition, for use with G_POPUP all selectable objects have to be of 
the type G_STRING (or, better -> G_SHORTCUT) or G_BUTTON and start with 
two space characters, the latter because of the tick (ASCII 8) that is 
set automatically by form_button() or form_(x)do()! It is important 
that ob_x, ob_y of object 0 of the menu are specified relative to the 
G_POPUP object, i.e. mostly both will be 0.

It is recommended to specify a shadow and a border of -1 width.

G_POPUP looks like G_BUTTON, but the text string is not centered, in 
order to line up with the text strings in the menu if possible.


G_WINTITLE (36, 0x24)
---------------------

This object number is used by MagiC internally to display window 
titles. The structure of this object type may change at any time and 
is therefore not documented.


G_EDIT (37, 0x25)
-----------------

From MagiC 5.20 onwards a multi-line input object is available, 
implemented in a "shared library". For use of this object type, 
see EDITOB.TXT.
One should note that this object type is _NOT_ (yet) supported by 
form_(x)do(), form_button(), form_keybd(), objc_edit(), wdlg_evnt() and 
wdlg_do(). This means that the events (mouse and/or keyboard) have to 
be passed on to the object "by hand" via edit_evnt().


G_SHORTCUT (38, 0x26)
---------------------

This object type is only available under MagiC and only from version 6 
onwards. It is treated in a similar way to G_STRING (i.e. ob_spec 
points to the character string), but any keyboard shortcut present will 
be split off and output flushed right.

The presence of the object type can be inquired via appl_getinfo(), 
subfunction 13, fourth WORD, bit 3.

The introduction of proportional AES fonts with MagiC 6 made a new 
strategy for the justification of menu entries necessary. In order to 
be able to line up keyboard shortcuts flushed right, objects of the 
type G_STRING within a menu are split up correspondingly into commands 
and shortcuts. This strategy fails, however, for menus that are managed 
by the program itself, for instance within a window or a popup menu.
In order to achieve usable justification here as well it was necesary 
to introduce this new object type.
