********************************************************************************
*                                                                              *
* ScriptEdit v1.0 - Design document for Foundation's script-driven editor.     *
*                                                                              *
* This document is proprietary and confidental property of Jim Murphy and      *
*  Lunar Productions.                                                          *
*                                                                              *
* Copyright (C) 1991 Jim Murphy and Lunar Productions                          *
* All Rights Reserved.                                                         *
*                                                                              *
* Last modifications - 11/11/91 - jcm                                          *
*                                                                              *
********************************************************************************

     ========
     Overview
     ========

     ScriptEdit is a generic editor that provides the ability to define resource
definition scripts for any resource type. These can be either Apple-defined or
custom resource types. ScriptEdit performs its editing actions based on a custom
resource, the remScriptRes. This resource defines a simple interpretive command
descriptor structure. The remScriptRes resource includes a header, followed by a
one or more command descriptor records. These records will be defined below.

     When a resource (source resource) is to be opened for editing with
ScriptEdit, it initially searches for an appropriate remScriptRes resource
within the HexScriptREM resource file. It identifies the proper resource by
using the type of the target resource as the resource ID of remScriptRes. If it
cannot find a match the complete action will be determined later, but it will
generally allow for the creation of a new script.

     One note is in order. At this moment it can safely be assumed that the
remScriptRes is well-formed and syntactically correct. By making this assumption
we can hope to proceed rather quickly with the parsing process itself. We can
make this assumption since remScriptRes resource should only be created with the
dialog or script builder portions of ScriptEdit. These two functions properly
check the syntax of the script after it has been built. Since they will not
allow a 'dirty' script to be written to the resource file, this assumption
is quite reasonable. We should also note that Jim would probably have to write
two complete syntax checkers due to the way the world is going to work. One is
plenty, thank-you. :-)

     =================
     Script Conversion
     =================

     The script converter portion of ScriptEdit uses a single-pass script
assembly process. As the assembler walks the script, it builds a table of all
resolved label references which includes the label text and the final
OpRelReference value.

     At the same time it is attemting to resolve all command references from
this table. If the reference can be found in the OpRelReference table, then the
command descriptor record is completely resolved. If it cannot be found, the
unresolved reference is accumulated into a seperate table which holds absolute
addresses of all unresolved references. The command descriptor at this time is
partially built, with the obvious exception of the reference.

     After the entire script has been walked, the assembler attempts to find the
remaining unresolved references in the OpRelReference table. If it is successful
it fills in the references in the unfinished command descriptor records using
the absolute addresses that were accumulated into the unresolved reference
table.

+==============+
| remScriptRes |
+==============+

     A remScriptRes resource consists of a header (one word, must be zero),
followed by a series of variable-length Command Descriptor Records. These
records are comprised of five fields. The fields are as follows:

$00 - OpWord         Word - This command or specifier's token. Defined below.
$02 - OpData1        Long - OpWord-defined miscellaneous data. Defined below.
$06 - OpData2        Long - OpWord-defined miscellaneous data. Defined below.
$0A - OpRelReference Long - Byte offset from script start to the CDR referenced.
$0E - OpCommentStr   Var  - Optional string which is displayed to the left of a
                            dialog field. A practical length of 32 characters is
                            recommended since the string will be clipped.

     ======
     OpWord
     ======

     OpWord is a token representing either a data-type specifier or a script
language command. The OpWord can be broken down into three distinct fields.
The first field, commandLength, encompasses bits 15-8. This field defines the
size of the data that this OpWord operates on. It can be any value from 0-255.
Zero is a value which has special meaning. It indicates that the data type or
command should expand to its maximum possible length. For Pascal strings this
indicates that there should be a maximal limit of 255 characters on string
entry. For char or hex types, this represents a length of 'fill'. This length
includes all of the remaining data in the resource.

     The second field, commandGroup, provides for eight logical command or data-
type groupings. It is described by bits 7-5. There are currently four such
groups; simple data-type specifiers, complex data-type specifiers, branching
script language commands, and special script language commands.

     The third and final field, commandCode, is the data-type or command opcode
itself. Within each command group there are 32 possible values for a total of
256 from all groups. This field is described by bits 4-0.


     Data-Type Specifiers
     --------------------

     Data-type specifiers define the format of a script dialog entry field.
These fields are the means by which a resource can be modified using a script.
In the following tables 'xy' represents a variable value whose range is 0-255.


     - Simple Data-Type Specifiers -

     There are five simple data-type specifiers. These specifiers define their
represented data size implicitly. That is, they fully define the amount of data
that they represent without the need for a commandLength, although the string
types optionally provide for this field. The hexadecimal number is the OpWord
token value for the defined specifier. All of these specifiers are group zero
commands.

     $0000 - point   - Standard QuickDraw II point.

     $0001 - rect    - Standard QuickDraw II rectangle.

     $xy02 - pstring - Pascal-type string. Length byte followed by a string.

     $xy03 - cstring - C-type string. A string followed by a NULL byte.

     $xy04 - wstring - A word string. Length word followed by a string.


     - Complex Data-Type Specifiers -

     There are eleven complex data-type specifiers. These specifiers require a
valid commandLength field to define the length of the represented data. These
specifiers belong to group one.

     $xy20 - unsigned  - An unsigned decimal integer.

     $xy21 - signed    - A signed decimal integer.

     $xy22 - hex       - A hexadecimal integer.

     $xy23 - char      - An 8-bit ASCII character.

     $xy24 - boolean   - A logical true or false.

     $xy25 - bitarray  - An array of flag bits.

     $0026 - bit       - An individual bit within a bitarray. Can be either a
                         single bit or a range of bits.

     $0027 - bitzero   - An individual bit within a bitarray. Can be either a
                         single bit or a range of bits. This data-type provides
                         for simple type-checking of an individual bit or bits.
                         When a resource data bit referenced by a bitzero data-
                         type specifier is non-zero, it can be flagged as
                         improperly formatted data.

     $0028 - bitone    - An individual bit within a bitarray. Can be either a
                         single bit or a range of bits. This data-type provides
                         for simple type-checking of an individual bit or bits.
                         When a resource data bit referenced by a bitone data-
                         type specifier is zero, it can be flagged as improperly
                         formatted data.

     $xy29 - enumarray - This command signals that the following 'enum'
                         specifiers should be added to a pop-up menu. This
                         provides a means to select from a list of items that
                         represent a normally unintelligible value. This is
                         useful for such situations as the countryCode in an
                         rVersion resource.

     $002A - enum      - These specify the item string and corresponding value
                         of the 'enumarray' pop-up menu items.


     Script Language Commands
     ------------------------

     A script language command is operator that either explicitly performs a
defined action such as a branch, or it can set into motion a background action
as is the case with pcount or loop commands.

     There are twelve script language commands. Each of these commands rely on
either an OpData1 and/or an OpData2 fields to further define their action. The
first nine belong to group two.


     - Branching Script Language Commands -

     $xy40 - switch - This provides for the ability to interpret variant
                      resource structures such as control templates. It signals
                      the resource data field that will be the target of
                      subsequent 'case' commands. This must be immediately
                      followed by one or more 'case' commands. During parsing,
                      ScriptEdit builds a pop-up menu for each 'switch' command
                      that contains subsequent 'case' commands as menu items.
                      This is useful in a situation such as the procRef field in
                      a control template.

     $xy41 - case   - This command allows for variable execution branch points
                      based on specific values of a previously defined 'switch'
                      field. At least one case command must immediately follow a
                      'switch' command. All possible values for the referenced
                      resource data field need not be provided. After all case
                      commands are parsed, execution falls through to the next
                      command. A series of commands which displays the remaining
                      resource data in a generic format should be located here.

     $xy42 - goto   - This command transfers template parsing to the referenced
                      Command Descriptor Record.

     $xy43 - ifeq   - These commands are all variants of a simple comparison-
     $xy44 - ifne     then-branch command. If the result of a comparison with
     $xy45 - iflt     the referenced resource data is logically true, a branch
     $xy46 - ifgt     is taken to the referenced Command Descriptor Record.
     $xy47 - ifle
     $xy48 - ifge


     - Special Script Language Commands -

There are three instructions that belong to group three. These instructions
have special meaning to the script language parser.

     $xy60 - pcount - This command is used with variable-length resources
                      such as control templates. This command indicates to
                      the template parser that it should constrain the number of
                      displayed fields. When the internal parsed field count
                      reaches the value present in the corresponding data field
                      of the resource, script parsing ceases.

     $xy61 - loop   - The loop command has two variants. The first allows for
                      a count reference to be provided. Through each iteration
                      of the loop the count value will be decremented by one.
                      A logical 'if' command should be placed at the end of the
                      loop to test for an exit condition, such as the count
                      reaching zero. This loop type can be used with resources
                      such as rStringList where a count word is provided.

                      The second variant is a controlled version of an
                      infinite loop. A reference is provided that specifies
                      the field to watch through each loop iteration. A logical
                      'if' command should be placed at the end of the loop to
                      test for an exit condition. When the test value appears at
                      the reference location the loop will be exited. This loop
                      type can be used with resources such as an rControlList
                      where the test condition is for a long NULL.

     $0062 - end    - This signifies to the script parser that all of the
                      resource data should have been used in prior parsing. This
                      provides for notification if a source resource has been
                      corrupted.

     =======
     OpData1
     =======

     Of the twenty-nine currently defined data-type specifiers and script
language commands, thirteen require modifier data to complete their function.
The following commands and specifiers are those that need this extra data.

     $0026 - bit     - The individual bits specify which bits in the value
                       that this data-type is to act upon.

     $0027 - bitzero - The individual bits specify which bits in the value
                       that this data-type is to act upon.

     $0028 - bitone  - The individual bits specify which bits in the value
                       that this data-type is to act upon.

     $xy41 - case    - This is the immediate value that must match for the
                       branch to be taken.

     $xy43 - ifeq    - This is the immediate value that is to be used in the
     $xy44 - ifne      comparison operation.
     $xy45 - iflt
     $xy46 - ifgt
     $xy47 - ifle
     $xy48 - ifge

     $xy60 - pcount  - The low word specifies the minimum value, and the high
                       word contains the maximum value.

     $xy61 - loop    - This is undergoing some radical changes, so it is
                       currently undefined.

     =======
     OpData1
     =======

     Currenly no data-type specifiers or script language commands use this
field. It will be used to hold data that needs to be back-referenced from a
subsequent Command Descriptor Record. This data is pulled directly from the
source resource and stored here.

     ==============
     OpRelReference
     ==============

     This field is used to reference a Command Descriptor Record as either a
branch target, or as part of an expression evaluation. This reference is a
long offset from the beginning of this remScriptRes resource. The following
commands and specifiers are those that currently use this field.

     $xy41 - case    - This is the destination Command Descriptor Record if this
                       comparison is true.

     $0042 - goto    - This is the destination Command Descriptor Record.

     $xy43 - ifeq    - This is the destination Command Descriptor Record if this
     $xy44 - ifne      comparison is logically true.
     $xy45 - iflt
     $xy46 - ifgt
     $xy47 - ifle
     $xy48 - ifge

     $xy61 - loop    - This is the destination Command Descriptor Record.

     ============
     OpCommentStr
     ============

     This field is a simple Pascal-type string. It is drawn to the left of a
script dialog's control as a comment or label string. It is optional for all
data-type specifiers and script language commands except 'case' and 'enum'. In
these two instances, it is required since it is used as the menu item string in
the corresponding pop-up menu.

********************************************************************************

     Enough with the icky data structure definition. I think a few notes on what
ScriptEdit actually does at this point are in order.

     - Currently, all of the 'bit' related commands are unimplemented. If they
       are used in a remScriptRes, they get interpreted as a hexadecimal value.

     - PCount is also not implemented. It too gets interpreted as a hexadecimal
       value.

     - The loop SLC is undergoing radical modifications, so it is currently
       simply ignored.

     At this time, I wouldn't suggest using the pop-up in control templates for
anything more than entertainment. It actually will change the type of the
control. This is not a good thing at present since the data may be bogus for the
newly selected type. Simply, it's not very useful yet.

     But the good news is that the 'enumarray' pop-up (currently used in the
rVersion script) does work quite well. Have as much fun as you can with those
countries. :-)

     When it comes to navigation, you can tab to move to the next control, and
shift-tab to move backwards. The scroll bar moves between logical groups of
'cards' (for lack of a better term). Controls are hidden and shown as required.
Eventually, tabbing will move to the next (or previous) card when the last (or
first) control is reached. For now, it simply wraps within the current card.

     The final bad news is that you cannot currently create new resources with
ScriptEdit. :( Marc's been asking for it lately, so you should see it in short
order. In fact, I'll be doing it tonight.

     Well, I hope this is of some use to you. If you'd like a script built for
any custom resource, I can help there. All of the included scripts thus far
have been built by hand. Uugh. The script complier is currently floating 'round
in my head, so it doesn't quite work yet.


Jim Murphy                              Internet: ujmurphy@mcs.drexel.edu
Apartment A-412                         GEnie:    J.MURPHY7
3500 Powelton Ave.                      AO:       Jim Murphy
Philadelphia, PA 19104                  Phone:    (215) 387-3521
