Implementation notes for the !Misc CSE of !ResEd
================================================

Contents
--------

1  Generic object handling
  1.1  Object definitions - ObjectDefRecs
  1.2  Relocation specifications - RefDefRecs
  1.3  Field/icon relationships - FieldDefRecs
  1.4  Mouse click specifications - ClickDefRecs
  1.5  Drag-n-drop specifications - DropDefRecs
  1.6 Treatment of OK and Cancel buttons
  1.7 How to add a new object class
  1.8 Unknown object classes
2  Responding to HelpRequest messages
  2.1  Object properties dialogue box
  2.2  Other dialogue box
  2.3  Menu


1 Generic object handling
-------------------------

At present, there are 12 different miscellaneous object classes which have to
be handled. There is much code common to all, although each class has its own
properties dialogue box. To keep the amount of code to a minimum, each class
is described by a data-structure which is interpreted by generic functions in
object.c.

This approach is similar to that adopted for different gadget types in the
Windows CSE.


1.1  Object definitions - ObjectDefRecs
---------------------------------------

The data structure which defines an object class is called an ObjectDefRec
and is created statically: see c.objdefs for examples. The fields are as
follows:

  class        - the object's class - eg 0x82980 for ColourMenu objects.

  version      - !Misc will save object templates in a particular format,
                 and this number identifies that format; normally 100.

  templatename - the name of the template for the object's properties
                 dialogue box; this will be found in !Misc.Templates.

  proto        - this is filled in when the template is loaded; it addresses
                 the dbox' prototype.

  protosize    - this is filled in when the template is loaded; it is the
                 size of the dbox' prototype in bytes.

  body         - this is a BodyDefRec which describes the structure of the
                 object's body: how big it is, and which fields inside it
                 need relocating. It contains the following fields:

        size           - the size of the object's template in bytes
        refs           - the address of an array of RefDefRecs, each of which
                         describes a field within the object's body that
                         requires relocation

  fields       - this addresses an array of FieldDefRecs; each one describes
                 the relationship between one or more fields in the object
                 and one or more icons in the object's properties dbox.

  clicks       - this addresses an array of ClickDefRecs; each one describes
                 the action to be taken when mouse clicks on icons in the
                 object's properties dbox occur.

  drops        - this addresses an array of DropDefRecs; each one describes
                 what action to take when the user drops an object into the
                 object's properties dbox.

  icons        - this is a sub-record that gives the handles of icons that
                 are common to all object properties dbox's:

        firstwritable  - the icon to which the caret should be given when
                         the dbox is first opened
        ok             - the OK button
        cancel         - the Cancel button

  specialstartup
               - if special action has to be taken at program start-up,
                 this field contains the address of the funcion to call;
                 otherwise it is NULL. This function is called after all
                 templates have been loaded - see
                 load_prototypes_and_create_menus(..) in c.main.

  specialinit  - if special action has to be taken when the object's
                 properties dbox is initialised, this field contains the
                 address of the function to call; otherwise it is NULL.
                 The function is called *after* other icons have been filled
                 in as specified by the 'fields' array above.

  specialapply - if special action has to be taken when the object's
                 properties dbox is applied, this field contains the address
                 of the function to call; otherwise it is NULL. The function
                 is called *before* other fields of the object are filled
                 in as specified by the 'fields' array above.


When an object arrives from the Shell, its corresponding ObjectDefRec is
located; this makes it possible to create an empty ObjectRec of the correct
size, and to store a pointer to its definition inside it. object_load(..) is
then called to initialise this object record from the template.


1.2  Relocation specifications - RefDefRecs
-------------------------------------------

These fields describe how StringReference and MessageReference fields inside
an object are to be treated.

When an object template is loaded from the shell, it is relocated without
reference to these specifications, so that object_load(..) is presented
with a template in which every StringReference or MessageReference field
already contains either NULL or the address of a valid string. But these
strings are still part of the template itself, and copies must be made for
the ObjectRec before the template is deleted.

When a objectRec is "re-assembled" as a component of a window object template
in preparation for delivery back to the shell, the relocation tables must be
reconstructed; RefDefRecs are used then to determine which fields must be
relocated and into which tables the entries should be placed.

The fields of a RefDefRec are as follows:

  type        - possibilities are:

                   REF_STR      - describes a StringReference field
                   REF_MSG      - describes a MessageReference field
                   REF_END      - identifies the end of the RefDefRec array;
                                   other fields of this record are ignored.

  offset      - the offset of the field within the object's template.

  emptyisnull - if this is TRUE, any empty string value is replaced by a
                NULL value when the object is loaded (this does not have to
                be done when saving, because internal processing will ensure
                that no empty string value is ever stored for this field -
                see FieldDefRecs below).

These records are used by:

  object_load(..)     - to find out where the strings in the template are,
                        and how to copy them

  object_save(..)     - to find out which fields need to be relocated, and
                        in what way

  object_size(..)     - to determine the size of the object template

  copy_body(..)       - to find out where the strings are which need to be
                        copied

  object_free(..)     - to find out where the strings are which need to be
  compare_bodies(..)  - free'd


1.3  Field/icon relationships - FieldDefRecs
--------------------------------------------

Each FieldDefRec describes a property of the object; it includes information
about how this property is represented by fields in the object's template,
and how it is represented by icons in the object's properties dialogue box.

Each FieldDefRec consists of a 'type' field, and a 'def' field which points
to <type>FldRec; that is, the 'def' field is of type:

        "pointer-to-union-of <type1>FldRec, <type2>FldRec ..."

The possible types (many identical to those in !Window) are as follows:

  FLD_INTEGER        - as Window CSE

  FLD_MAND_ASS_STR   - as Window CSE

  FLD_OPT_ASS_STR    - as Window CSE

  FLD_TITLE          - this decribes a Title property. This is like an
                        "optional assignable" string property: NULL values
                        and empty strings have distinct meanings, and there
                        is an associated buffer.
                       It is represented by a MessageReference field at
                        'valoffset' and a Length field at 'lenoffset' in the
                        object template, and by a group of radio buttons, two
                        writables and a pair of adjusters in the object's
                        properties dialogue box.

    int dflticon   - the "use default title" radio button
    int othericon  - the "use other title" radio button
    int valicon    - the writable for the "other" title
    int lenicon    - the "length" writable
    int upicon     - its associated 'up' adjuster icon
    int downicon   - its associated 'down' adjuster icon
    int valoffset  - the offset of the title text field in the object
    int lenoffset  - the offset of its associated length field

  FLD_MAND_CONST_STR - as Window CSE

  FLD_OPT_CONST_STR  - as Window CSE

  FLD_FLAG           - as Window CSE

  FLD_OPT_EVENT      - as Window CSE

  FLD_FILETYPE       - this describes a "filetype" property. This is
                        represented in the object template by an integer
                        field, and in the properties dbox by a display icon
                        and associated pop-up menu icon.
                       The display icon displays both the filetype's value
                        (in hexadecimal) and any associated filetype name
                        (eg "DrawFile").
                       The pop-up menu allows the user to choose a filetype
                        from a pre-prepared list, or enter a new one either
                        by number or name.

    int valicon    - the display icon
    int offset     - the offset of the filetype field in the object

  FLD_END            - identifies the end of the FieldDefRec array.


Notes:

  All offsets are relative to the start of the object.

  An "opticon" value can identify a radio button icon as well as an option
  icon.

  Many of the functions which are used to initialise properties dboxes and
  to update object fields are in the module gui.c.

The FieldDefRecs list is used by:

  object_load(..)       - to identify any "length" fields and initialise them
                          to -1 where necessary (displayed as '*' in a dbox).

  object_save(..)       - to identify "length" fields and replace -1 ('*') by
                          the correct explicit value.

  object_init_dbox(..)  - to initialise the icons within the object's
                          properties dialogue box

  object_apply_dbox(..) - to set the fields of the object according to the
                          settings of the icons in the object's properties
                          dialogue box


1.4  Mouse click specifications - ClickDefRecs
----------------------------------------------

Each ClickDefRec describes how to respond to a user mouse click on some icon
in an object's properties dialogue box; its format is as follows:

  icon     - the icon of interest ("control icon")
  action   - the action desired
  params   - addresses a record containing additional parameters for the
             action; the form of this record varies according to the desired
             action.

Every mouse click gives input focus to the window, and the software ensures
that the caret is placed in a non-faded writable (or is "invisible" if no
such writables are present).

Possible actions are as follows, where the bracketted letters indicate
which mouse buttons are recognised ([SMA] = [Select, Menu, Adjust]); many of
these are identical to those in !Window:

  ACT_FADE [SA]       - as Window CSE

  ACT_UNFADE  [SA]    - as Window CSE

  ACT_TOGGLEFADE [SA] - as Window CSE

  ACT_RADIO [SA]      - as Window CSE

  ACT_ADJUST [SA]     - as Window CSE

  ACT_TITLE [SA]      - deals with clicks on any icon in the "Title" set:
                          Click on "default" radio button:
                            Switches it on.
                            Fades all other icons.
                          Click on "other" radio button:
                            Switches it on.
                            Unfades all other icons.
                            Places the caret in the writable for the title.
                          Click on adjuster icon:
                            Adjusts value of "length" writable in the usual
                             way.

    int dflticon   - "default" radio button
    int othericon  - "other title" radio button
    int valicon    - writable icon for title text
    int lenicon    - writable icon for associated "length" field
    int upicon     - 'up' adjuster arrow icon
    int downicon   - 'down' adjuster arrow icon

  ACT_SPECIAL [SMA]   - the escape mechanism: the function provided is called
                         to process the mouse click (note that, unlike the
                         Window CSE, the icon and mouse click information
                         are passed to the function).

    error * (*f) (ObjectPtr object, int icon, MouseClickPtr mouse)
                       - special function to process mouse-click.

  ACT_END [-]         - indicates the end of the list of ClickDefRecs; other
                         fields are ignored.

The ClickDefRec list is processed whenever a mouse click is received for an
object properties dialogue box; see the function object_dbox_mouse_click(..).


Notes:

  The whole array is scanned, and so a number of different actions can be
  associated with a single mouse click; they will be executed in the same
  order as they appear in the list.


1.5  Drag-n-drop specifications - DropDefRecs
---------------------------------------------

Each DropDefRec specifies what action to take when an object is dropped into
an object properties dialogue box. Each record has the following fields:

  icon     -  a)  A value of -2 identifies the end of the array of
                  DropDefRecs; such a record is otherwise ignored.

              b)  A value of -1 means that the record specifies an action to
                  be taken when a drop occurs anywhere within the dbox.

              c)  A value n >= 0 means that the record specifies an action to
                  be taken when a drop onto icon n occurs.

  details  -  addresses a sub-record containing the following fields:

    type    -  this field is ignored (and should always be given the value
               OBJECT_DROP - see Window CSE).

    class   -  this field identifies the class of object required. If its
               value is -1, then any class of object will be accepted;
               otherwise, only objects of the given class will cause the
               specified action to be carried out.

    action  -  this determines the kind of action to be carried out.

    params  -  this addresses a record which contains further parameters to
               describe the intended action; its format depends on the
               particular action.

Possibilities are:

  DROP_SET      - The name of the object is stored in the target writable
                   icon.

    int valicon      - the target icon
                     
  DROP_SETOPT   - The name of the object is stored in the target writable
                   icon, and the associated option icon is switched on.
                  If the option icon is unfaded, the target icon is unfaded.

    int valicon      - the target icon
    int opticon      - the associated option icon

  DROP_SETOPT2  - The name of the object is stored in the target writable
                   icon, and the associated option icon is switched on.
                  If the option icon is unfaded, the target icon and the
                   'othericon' are unfaded.

    int valicon      - the target icon
    int opticon      - the associated option icon
    int othericon    - another associated icon

  DROP_SETOPT3  - The name of the object is stored in the target writable
                   icon, and the associated option icon is switched on.
                  If the option icon is unfaded, the target icon and the two
                   other icons are all unfaded.

    int valicon      - the target icon
    int opticon      - the associated option icon
    int othericon1   - another associated icon
    int othericon2   - a further associated icon

It is the function object_object_drop(..) which scans the DropDefRecs array
whenever an object is dropped onto a dialogue box.


1.6 Treatment of OK and Cancel buttons
--------------------------------------

Every object properties dialogue box has OK and Cancel buttons which are
treated in the standard way:

  SELECT-click OK, or RETURN:
    object_apply_dbox(..)
    If the object has been altered, mark it with 'pendingclose = TRUE' and
     send it back to the shell; after a successful transfer the shell will
     respond with an OBJECT_LOADED message and the CSE will delete the dbox
     calling objedit_close_object(..); see Window CSE for details of this
     protocol.
    If the object has not been altered, objedit_close_object(..) is called
     immediately.

  ADJUST-click OK, or SHIFT-RETURN:
    object_apply_dbox(..)
    If the object has been altered, mark it with 'pendingclose = FALSE' and
     send it back to the shell; after a successful transfer the shell will
     respond with an OBJECT_LOADED message and the CSE will reinitialise the
     dbox by calling object_init_dbox(..); see Window CSE for details of
     this protocol.
    If the object has not been altered, object_init_dbox(..) is called
     immediately.

  SELECT-click Cancel, or ESCAPE:
    objedit_close_object(..)

  ADJUST-click Cancel, or SHIFT-ESCAPE:
    object_init_dbox(..)


1.7 How to add a new object class
---------------------------------

This section just lists the various steps to be taken - see the relevant
header and source files for details.

  Add a new section which decribes the object template to the "Miscellaneous
  object templates" section in h.format; this will include a #define for
  its class and for any object-specific flags, as well as a type definition
  for the structure; let's call this WidgetTemplateRec.

  Add "WidgetTemplateRec widget;" as a further entry to the union type
  ObjectTemplateBodyRec in the "Miscellaneous object templates" section of
  h.format.

  Use !WinEdit to edit the Templates file, and add a new template for the
  Widget properties dialogue box: remember to give a name to each icon which
  will be referenced when creating the object's definition (ObjectDefRec).
  Use other dialogue boxes as a guide to spacing, appropriate validation
  strings, and other conventions. Icon naming also controls how the dialogue
  box responds to interactive help - see the later for details.

  Add a new ObjectDefRec to the array objectdefs[] defined in the section
  "the array of all object class definitions" in c.objdefs; it's probably
  most sensible to insert this entry before the final {-1} entry which
  terminates the list.

  The entry above will refer to variables which define the RefDefRecs,
  FieldDefRecs, ClickDefRecs and DropDefRecs for the object class; these
  should be defined in a new section in c.objdefs headed "widget definition"
  and immediately preceding "the array of all object class definitions"
  section.

  If any special functionality is required, define the functions in the
  form "object_wf_...(..)"; declare them in the header h.object, and define
  them in the source file c.object.

  Where necessary, add new help message text to the Messages file: see later
  for more details.


1.8 Unknown object classes
--------------------------

Code for editing unknown object classes was added for Aquarius Update 1.

The approach is very similar to that adopted by the Window editor for editing
unknown gadget types.

Note that the "copy" of the object's body maintained during editing is held
in a field called "bodycopy" rather than in the "extension" record; this is
because objects do not have extension records, and so this pointer cannot be
reused!

The test to determine whether a definition is a dynamic one or not, is to
compare the definition's template name with that in unkobjectdef:

    def->templatename == unkobjectdef.templatename

New REF types REF_SPRITE and REF_OFFSET have also been added.

Object Offset values are not interpreted in any way by the editor; that is,
they are not relocated when an object is loaded and saved. This makes it
much easier to edit them.



2  Responding to HelpRequest messages
-------------------------------------

The following contexts are distinguished, each giving rise to a "base" help
token as shown. If there is no entry for the base token in the Messages file,
then simpler derived tokens are looked up until one is found to be present:
the priority order is as shown.


2.1  Object properties dialogue box
-----------------------------------

  Token:  Hlp.O.<object-class>.<icon-name>   - if pointer over named icon
          Hlp.O.<object-class>               - if pointer not over named icon

    where  <object-class> is the name of the template for the object
     properties dialogue box; possibilities are:

                 ColourMenu
                 ColourDbox
                 DCS
                 FileInfo
                 FontDbox
                 FontMenu
                 Iconbar
                 PrintDbox
                 ProgInfo
                 Quit
                 SaveAs
                 Scale

     and   <icon-name> is the name of the icon.

  Example:  Hlp.O.Scale.MINIMUM

  Lookup order:  Hlp.O.<object-class>.<icon-name>
                 Hlp.<icon-name>
                 Hlp.ADJ_UP       - if <icon-name> ends in ADJ_UP
                 Hlp.ADJ_DOWN     - if <icon-name> ends in ADJ_DOWN
                 Hlp.MAX          - if <icon-name> ends in MAX
                 Hlp.O.<object-class>
                 Hlp.O

  [ Note that there is a minor difference here from the analogous rules for
    the Window CSE - no search is made for "Hlp.O.<icon-name>". I think this
    is probably a historical accident: that is, I can see only one case in
    the !Window Messages file where a token of this kind is set, and that
    does not seem to be necessary - although it saves a little space. ]

 
2.2  Other dialogue box
-----------------------

  Token:  Hlp.W<n>.<icon-name>     - if pointer over named icon
          Hlp.W<n>                 - if pointer not over named icon

    where  <n> is the registered window type:

                 2  Filetype

     and   <icon-name> is the name of the icon.

  Lookup order:  Hlp.W<n>.<icon-name>
                 Hlp.<icon-name>
                 Hlp.ADJ_UP       - if <icon-name> ends in ADJ_UP
                 Hlp.ADJ_DOWN     - if <icon-name> ends in ADJ_DOWN
                 Hlp.MAX          - if <icon-name> ends in MAX
                 Hlp.W<n>


2.3  Menu
---------

  Token:  Hlp.M<n>.<h1>.<h2>...

    where  <n> is the registered menu type:

                 1  colour selection menu
                 2  filetype selection menu
                 3  licence type selection menu
                 4  iconbar icon position selection menu
                 5  font selection menu

     and   <h1>, <h2>, ... is the "hit list" which identifies the entry
            chosen from the menu (the first entry has index 0).

  Lookup order:  Hlp.M<n>.<h1>.<h2> ... <hn-1><hn>
                 Hlp.M<n>.<h1>.<h2> ... <hn-1>
                           ...
                 Hlp.M<n>.<h1>
                 Hlp.M<n>
