===========================================================================
 VX-REXX Tech Note #11

                                      The VX-REXX Window File (.VRW) Format

                                                          February 15, 1995

                                         Applies to all versions of VX-REXX

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

                                                       WATCOM International
                                                          tech@watcom.on.ca

============================================================================


Abstract
--------

(The material here is aimed at advanced programmers.)

VX-REXX uses a binary format to describe a Window and the objects on
the window.  This binary format is used by VX-REXX in the .VRY files
that are stored with a project and in the .VRW files that are created
when you make a macro from your project.  This Tech Note describes
the simplest version of the VRW/VRY format as used and understood by
all versions of VX-REXX.  Once you understand how window files are
laid out, you can use this information along with the code in the
accompanying file WRITEVRW.VRX to write your own VRW files, which can
then be loaded by your programs as if the window files were bound to
the executable.

Note: This Tech Note does not describe how files are bound to VX-REXX
executables.  It also does not describe the more advanced form of
VRW/VRY file used by VX-REXX.


Using VRW Files
---------------

To load a VRW file you can simply use the VRLoad routine as described
in the VX-REXX online reference, with one caveat:  when you are building
an executable, VX-REXX adds an internal VRLoad routine which redirects
calls to VRLoad to another routine which knows how to read window files
out of the executable.  If you want to load a VRW file from disk, you
have to call VRLoad with the function name in quotes, as in:

      handle = 'VRLoad'( parent, filename )

If the file loaded successfully, VRLoad will return you a handle
(an internal name) to the window that was loaded, a null string
otherwise.


VRW File Outline
----------------

The VRW file format is actually quite simple, looking something like
this:

         ----------
         VRW Header     --> identifies version of VX-REXX
         ----------
         Window
         ----------
         Object 1
         ----------
         Object 2
         ----------
            etc.
         ----------
         Terminator     --> 2-byte zero value
         ----------

The objects are laid out sequentially in a depth-first, right-to-left
sequence.  In other words, if you have a Window that looks like this:

                          Window
                            |
                  ---------------------
                  |                   |
              PushButton           GroupBox
                                      |
                                DescriptiveText

In the VRW file you'd see this layout:

           Window
           GroupBox
           DescriptiveText
           PushButton

Each object has a "level" associated with it, with the Window being
at level 1.  In the example above, the PushButton and GroupBox are
at level 2, the DescriptiveText at level 3.


Object Layout
-------------

The Window object and its child objects are each laid out as follows:

             ----------------------
             level                      2 bytes
             ----------------------
             length of classname        1 byte
             ----------------------
             classname                  variable
             ----------------------
             create-time properties     variable
             ----------------------
             marker (zero)              1 byte
             ----------------------
             other properties           variable
             ----------------------
             marker (zero)              1 byte
             ----------------------

Note that the level (as all numeric values used in the VRW file) is
stored as an lo/hi byte pair (Intel format).

A create-time property is a property that can only be set at design
time and not at runtime using VRSet.  Most properties are not
create-time properties and should be listed in the "other properties"
section.  If you are unsure, you can use the ListProperties method
on an object to list its create-time properties.

Note: Events are really just properties!  If you want to set a "Click"
event to call the section "PB_1_Click", just set the "Click" property
to "call PB_1_Click".


Property Layout
---------------

Finally, each property is laid out as follows:

        -----------------------
        length of property name      1 byte
        -----------------------
        property name                variable
        -----------------------
        length of data               2 bytes
        -----------------------
        data (property value)        variable
        -----------------------

The type of data stored depends on the property.  Most properties
are stored either as 4-byte values (numeric properties such as Left,
Top, Visible, etc.) or strings (such as Name and Caption).


Numeric Values
--------------

Numeric values are stored in Intel format.  So the number 1 gets stored
as:

              01    1 byte
           01 00    2 bytes
     01 00 00 00    4 bytes

The accompanying file WRITEVRW.VRX includes the routines VRStringToByte,
VRStringToShort and VRStringToLong to convert numeric values into
the appropriate byte sequences.


An Example
----------

Accompanying this Tech Note is the file WRITEVRW.VRX, which are
routines you can use in your VX-REXX programs to create VRW files.
Here is how you can use those routines to create a VRW file with
a Window and a single PushButton:

    /* Path... change as appropriate */

    file = "d:\tmp\foo.vrw"

    /* Open the file for writing and write the header, marking
       it as a 2.0c file (2.0 = 2.00, 2.0a = 2.01, etc.) */

    call VRCreateVRW file, '2.03'

    /* Level 1 */

    call VRWriteShort file, 1
    call VRWriteClassName file, "Window"
    call VRWriteByte file, 0
    call VRWriteProperty file, "Left", VRStringToLong( 1000 )
    call VRWriteProperty file, "Top", VRStringToLong( 1000 )
    call VRWriteProperty file, "Height", VRStringToLong( 2000 )
    call VRWriteProperty file, "Width", VRStringToLong( 2000 )
    call VRWriteProperty file, "Visible", VRStringToLong( 1 ) 
    call VRWriteProperty file, "Name", "Test"
    call VRWriteProperty file, "Click", "say 'hello'"
    call VRWriteProperty file, "Caption", "A window"
    call VRWriteByte file, 0

    /* Level 2 */

    call VRWriteShort file, 2
    call VRWriteClassName file, "PushButton"
    call VRWriteByte file, 0
    call VRWriteProperty file, "Visible", VRStringToLong( 1 )
    call VRWriteProperty file, "Autosize", VRStringToLong( 1 )
    call VRWriteProperty file, "Top", VRStringToLong( 50 )
    call VRWriteProperty file, "Left", VRStringToLong( 50 )
    call VRWriteProperty file, "Click", "say 'hi!'"
    call VRWriteProperty file, "Caption", "A button"
    call VRWriteByte file, 0

    /* Finish it */

    call VRWriteShort file, 0
    call VRCloseVRW file


Final Notes
-----------

When writing out VRW files it is not necessary to include an entry for
every property or event an object supports.  If a property is not listed,
it simply defaults to the same value that it defaults to in design
mode.

Note that there is no way outside of the design environment to actually
take an existing window and save it out as a VRW file using a single
function call.  You can simulate this capability by traversing the
parent-child tree (using the FirstChild and Sibling properties of
objects) and writing out the necessary data using the given routines.
