
 writeflash 0.22
 ===============
 writeflash creates Flash 3 files from simple (or not so simple)
 script-files.
 !MakeFlash is a simple frontend for writeflash.


 Copyright
 =========
 The program is copyright  Henrik Bjerregaard Pedersen, 2000-2001
 and is released under the GPL (any version).

 writeflash uses ZLIB by Jean-loup Gailly and Mark Adler.


 About writeflash
 ================
 writeflash is a command-line program and may be run from a task-window,
 shell or obey-file or from another program.

 writeflash [switches] <input> [<output>]

 If no output file is specified, the result will be output to the
 standard output stream - either the screen (bad idea) or a file,
 depending on redirection.

 Switches:
    -pl                       print lines as they are being read
                              by the parser; this is very useful if
                              the parser reports an error, as it
                              allows you to easily find which line
                              contains the error

    -define <name> <value>    defines a macro; if the value includes
                              spaces, it should be enclosed in ""

    -defines <name> <value>   defines a macro; if the value includes
                              spaces, it should be enclosed in ""

 The difference between -define and -defines:

 -define COLOUR ff00ff            defines a macro with the value
                                  ff00ff
 -define TEXT "Hello there"       defines a macro with the value
                                  Hello there

 -defines COLOUR ff00ff           defines a macro with the value
                                  "ff00ff"
 -defines TEXT "Hello there"      defines a macro with the value
                                  "Hello there"


 Porting writeflash
 ==================
 writeflash is written in ANSI C, and should hopefully compile without
 any major problems on most platforms.

 Notice that 'char' is assumed to be unsigned, but 'char' is only used
 for strings and data-pointers, it is not used for arithmetics, so it
 should not cause any trouble.


 Using !MakeFlash
 ================
 MakeFlash is a simple frontend for writeflash. When run, it installs
 itself on the iconbar, and you may then drag a script-file to its
 icon - a save-box will then pop up allowing you to save the Flash-file.


 Compatibility
 =============
 I've tried to keep new versions of writeflash compatible with the
 older versions, but every now and then, some changes result in
 incompatibility:

 Version 0.16       - no longer supports pre-compressed ADPCM audio;
                      the meaning of "ADPCM2", "ADPCM3", "ADPCM4" and
                      "ADPCM5" sound formats have changed

 Version 0.17       - the file FlashFonts:IDs is no longer used or
                      included; this means that scripts that #include
                      that file cannot be compiled using v0.17 unless
                      the #include-line is removed or the FlashFonts:IDs
                      is copied from an older version
                    - some font-IDs have changed; as long as you've used
                      the pre-defined macros for specifying the fonts,
                      old scripts should still work


 Script file syntax
 ==================
 A script-file is a text file containing a textual description of the
 flash file you want to create.
 The script-file may also contain commands for the script-processor;
 the script-processor greatly simplifies many trivial operation when
 creating the script-file.

 The script-file is read line by line but is parsed one token at a time.
 A token is either a tag (eg. "FileVersion" or "DefineShape") or a
 fieldname (eg. "id" or "matrix") or a value or left or right curly
 brackets. Tokens must be seperated by a white-space (space, linefeed,
 carriage-return or TAB).

 Tags and fieldnames are case-insensitive.

 Comments may be included in a script-file:  // indicates that the rest
 of the line is a comment.
 Lines starting with # are used by the pre-processor.
 Lines starting with : are used by the script-processor.

 All tags except FileVersion, FrameRate and BackgroundColour require a
 structure as argument.
 A structure contains a number of fieldnames/values.
 A structure starts with a "{"  (left curly bracket), then follows
 pairs of fieldnames and values (values may be structures themselves,
 although in that case there are no fieldnames in the structure) and
 the list is terminated by a "}" (right curly bracket); eg.:

          PlaceObject {
            depth  1
            id     1
            matrix {
               65536 65536
               0     0
               0     0
            }
          }


 Coordinates
 ===========
 Coordinates are specified in twips, 1 twip = 1/20th of a pixel.


 Types
 =====
 The following data types are supported:

 U8                 unsigned 8 bit integer
 S8                 signed 8 bit integer
 U16                unsigned 16 bit integer
 S16                signed 16 bit integer
 U32                unsigned 32 bit integer
 S32                signed 32 bit integer
 bbox               { S32 S32 S32 S32 }
 matrix             { S32 S32 S32 S32 S32 S32 }
 cxform             { S16 S16 S16 S16 S16 S16 S16 S16}
 RGB                { U8 U8 U8 }
              or    24 bit integer      (written as hex: BBGGRR)
 RGBA               { U8 U8 U8 U8 }
              or    32 bit integer      (written as hex: AABBGGRR)
 gradient           1..8 pairs of U8 RGBA
 string             string, enclosed in " "
 file               string
              or    array of byte-values
                    (see the section 'Inline files')


 RGBA
 ====
 RGBA values are specified as either 

 A) a structure with 3 or 4 values { R G B A }, eg.
    { 0 128 64 255 }   for    R (red)   = 0          (0%)
                              G (green) = 128        (50%)
                              B (blue)  = 64         (25%)
                              A (alpha) = 255        (100%)

   if only 3 values are specified, A is set to 255

 or

 B) an 8 digit hexadecimal value, eg  00446688
     for      A (alpha) = 0   (0x00)  (0%)
              B (blue)  = 68  (0x44)  (26%)
              G (green) = 102 (0x66)  (40%)
              R (red)   = 136 (0x88)  (53%)

 An alpha value of 0 means completely transparent, 255 (0xff) means
 completely opaque.


 Matrix
 ======
 Often matrices only contain scaling or scaling/translation. To make
 entry of these easier, you may specify less than the usual 6 values
 in a matrix. The remaining values are set to their default values,
 which are:
          scalex              65536
          scaley              65536
          rotate0             0
          rotate1             0
          translatex          0
          translatey          0

 no. of values      treated as

     0              (default values)
     1              scaling (both scalex and scaley)
     2              scalex , scaley
     3              scaling, translatex, translatey
     4              scalex, scaley, translatex, translatey
     5              NOT ALLOWED


 Colour Transforms (cxform)
 ==========================
 A colour-transform transform RGBA values in a shape, using the formulaes

          R = R*MULR/255 + ADDR
          G = G*MULG/255 + ADDG
          B = B*MULB/255 + ADDB
          A = A*MULA/255 + ADDA

 The format of a colourtransform is

          { MULR MULG MULB MULA ADDR ADDG ADDB ADDA }


 IDs
 ===
 Flash uses 16 bit IDs to reference objects, characters, bitmaps, fonts
 etc. IDs should be unique within a Flash-file.

 writeflash will assume that IDs from 20000 to 49999 are reserved for
 future use by writeflash, IDs from 50000 to 59999 are reserved for
 fonts and IDs from 60000 to 65535 are reserved for other pre-defined
 shapes.


 Supported tags
 ==============
 The following tags are supported:

                              aliases

          FileVersion
          FrameArea
          FrameRate
          BackgroundColour    BgColour
          DefineShape         Shape
          PlaceObject         Place
          RemoveObject        Remove
          DefineSound         Sound
          PlaySound
          ShowFrame
          DoAction
          Protect
          Text
          Font
          JPEG
          Bitmat
          Button
          ButtonSound
          End


 Tags
 ====

 FileVersion
 -----------
 Defines the version of the file. There should only be one "FileVersion"
 tag in a script.

 Argument:          U8

 Example:           FileVersion 1


 FrameArea
 ---------
 Specifies the size of the display area for the Flash file; also
 defines the scaling factors for all coordinates in the script-file.

 Argument:          framearea-structure

 Example:           FrameArea {
                      width  5000
                      height 4000
                      scalex 2000
                    }

 The framearea-structure may include any of the following fields:

                    name                argumenttype

                    width               U16
                    height              U16
                    scalex              S32
                    scaley              S32

 The default value for 'scalex' and 'scaley' is 1000 (100%).
 The scale/rotateskew values in a matrix cannot be scaled using
 scalex and scaley; instead, they are all scaled using
 SQRT(ABS(scalex*scaley)).

 You may include more than one FrameArea tag in a script-file.


 FrameRate
 ----------
 Specifies the framerate for the Flash file, in frames per secon.
 Default is 10.0 fps.

 Argument:          U8.U8

 Example:           FrameRate 10.0


 BackgroundColour  /  BGColour
 -----------------------------
 Specifies the background colour for the Flash file.

 Argument:          RGB

 Examples:          BackgroundColour ff0000       // blue
                    BackgroundColour { 0 0 255 }  // blue


 DefineShape  /  Shape
 ---------------------
 Defines a shape which is added to the dictionary of defined characters.

 Argument:          shape-structure

 Example:           DefineShape {
                      id 1
                      fillstyle {
                        solid ff00ff00            // fillestyle #1
                        linear {                  // fillestyle #2
                          matrix { 65536 65536 0 0 0 0 }
                          gradient { 0 00ff00  255 008000 }
                        }
                      }
                      linestyle { 80 ffff0000     // define linestyle#1
                                  80 ff000000 }   // define linestyle#2
                      selectlinestyle 1           // default is 0, which
                      fill0 2                     // means "don't draw"
                      fill1 1
                      moveby { 200 200 }
                      lineby { 200 0 }
                    }

 Possible fields in the shape-structure:

                    name                argumenttype

                    id                  U16     (required)
                    bbox                bbox    (only used in v0.02)
                    linestyle           linestyle-structure
                    fillstyle           fillstyle-structure
                    selectlinestyle     U32
           selectfillstyle0   fill0     U32
           selectfillstyle1   fill1     U32
                    moveto              { S32 S32 }
                    moveby              { S32 S32 }
                    lineby              { S32 S32 }
                    curveby             { S32 S32 S32 S32 }


 Each fillstyle/linestyle structure defines a number of fill- or
 line-styles. You may have multiple fillstyle/linestyle structures.
 The first fillstyle is no. #1 and is thus selected by
 'selectfillstyle0 1' or 'selectfillstyle1 1'. To draw an un-filled
 shape, select fillstyle #0.


 A linestyle-structure one or more pairs of linestyle-values - first
 value is the linewidth (U16), second value is the colour (RGBA).

 A fillstyle-structure contains any combination of the following fields:

                    name                argumenttype

                    solid               RGBA
                    linear              gradient-fill-structure
                    radial              gradient-fill-structure
                    tiled               bitmap-fill-structure
                    clipped             bitmap-fill-structure

 A gradient-fill-structure contains the following fields:

                    name                argumenttype

                    matrix              matrix
                    gradient            gradient

 A bitmap-fill-structure contains the following fields:

                    name                argumenttype

                    id                  U16
                    matrix              matrix

 Scaling a bitmap by 100% (ie. setting scale in the
 bitmap-fill-structure to 65536) means that the bitmap is scaled so
 that 1 pixel in the bitmap equals 1 twip. Therefore, you should
 normally scale bitmaps by 2000% (20x), to make 1 pixel in the bitmap
 equal in pixel on the screen.


 PlaceObject  /  Place
 ---------------------
 Places a character (a shape from from the dictionary) on the screen.

 Argument:          place-object-structure

 Example:           PlaceObject {
                      id 1
                      depth 1
                      matrix {
                        32768 32768
                        0 0
                        0 0
                      }
                    }

 The place-object-structure must contain the following fields:

                    name                argumenttype

                    depth               U16

 and may also contain:

                    id                  U16
                    matrix              matrix
                    cxform              cxform
                    clip                U16
                    frame               U16

 Only one object can exist at a given depth.
 If no id is given in the place-object-structure, it is assumed that
 the matrix (and cxform) modify the object at the specified depth.

 Notice, you cannot place bitmaps (eg. JPEGs) on the screen this way.
 You have to create a shape which uses the bitmap for filling and then
 place that object.

 If a frame number is given in the structure, the object will be placed
 in the specified frame; you can only address previously defined frames
 this way.

 'clip' allows a shape to mask out shapes on lower levels.


 RemoveObject  /  Remove
 -----------------------
 Removes an object (a character) from the screen.

 Argument:          remove-object-structure

 Example:           RemoveObject {
                      id 5              // not needed, ignored
                      depth 5
                    }

 The remove-object structure must contain the following fields:

                    name                argumenttype

                    depth               U16

 and may also contain the following fields:

                    frame               U16


 If a frame number is given in the structure, the object will be removed
 from the screen at the specified frame; you can only address previously
 defined frames this way.


 ShowFrame
 ---------
 Displays the frame.

 Argument:          an empty structure

 Example:           ShowFrame {
                    }


 Protect
 -------
 Protect the file from editing in editors.

 Argument:          an empty structure

 Example:           Protect {
                    }


 DoAction
 --------
 Adds a number of actions to the current frame.

 Argument:          action-list structure

 Examples:          DoAction {
                      gotoframe 0
                      play
                    }

                    DoAction {
                      geturl {
                        url     "http://www.hanseman-luchter.net"
                        target  "__new"  // or whatever...
                      }
                    }

 The action-list structure contains a list of actions; each action
 starts with the actionname and is followed by the arguments (if any)
 to the action. Currently supported actions are:

                    name                argumenttype

                    gotoframe           U16       (frame no.)
                    play                -
                    stop                -
                    nextframe           -
                    previousframe       -
                    stopsounds          -
                    geturl              geturl-structure

 The geturl-structure must include the following fields:

                    url                 string

 and may optionlly also include the following fields:

                    target              string

 Action-list structures are also used when defining buttons.


 JPEG
 ----
 Adds a JPEG to the dictionary, for use as fill-style for a shape.

 Argument:          JPEG-structure

 Example:           JPEG {
                      id 54
                      file "test2.jpg"
                      alphafile "test2.alpha"
                      alphatype "uncompressed"
                    }

 The JPEG-structure must include the following fields:

                    name                argumenttype

                    id                  U16
                    file                file

 and may also include the following fields:

                    alphafile           file
                    alphatype           string

 If the alphafile field is included, the file is assumed to contain an
 8 bits-per-pixel image (the alpha-channel bitmap) with the same
 dimensions as the JPEG.
 alphatype specifies the format of the alpha-channel bitmap; this can
 be either of the following:

          "compressed"    ZLIB compressed (default)
          "uncompressed"  uncompressed

 Notice that JPEGs cannot be displayed on their own, using PlaceObject.
 They have to be used as the fillstyle (eg. 'tiled' or 'clipped') for
 a shape.


 Bitmap
 ------
 Adds a bitmap to the dictionary, for use as fill-style for a shape.

 Argument:          Bitmap-structure

 Example:           Bitmap {
                      id 53
                      file "test3"
                      width 100
                      height 80
                      type "32"
                    }

 The Bitmap-structure must include the following fields:

                    name                argumenttype

                    id                  U16
                    file                file
                    width               U16
                    height              U16
                    type                string

 type specifies the format of the bitmap. Currently, this can be
          "8"             256 colours (compressed)
          "16"            32k colours (compressed)
          "32"            16M colours (compressed)
          "RAW8"          256 colours (uncompressed)
          "RAW16"         32k colours (uncompressed)
          "RAW32"         16M colours (uncompressed)
          "spritefile"    uncompressed spritefile

 Notice that bitmaps cannot be displayed on their own, using
 PlaceObject. They have to be used as the fillstyle (eg. 'tiled' or
 'clipped') for a shape.

 If type is one of the compressed formats, the file must contain
 previously zlib-compressed data.

 For 256 colours bitmaps, the data contains both the palette and the
 image data. The first 768 bytes (before compression!) hold the
 256 palette-entries; each palette-entry is 3 bytes, red in byte 0,
 green in byte 1 and blue in byte 2; then follows the image data.
 The format of a 32k colours pixel is not known...
 For 16M colours bitmaps, the format of a pixel is:
          byte 0    0
          byte 1    red
          byte 2    green
          byte 3    blue

 For real-world images, you should use JPEG instead of Bitmap.

 Sprites must be 4, 8, 16 or 32bpp. 4 and 8bpp sprites must have a
 palette; 8bpp sprites must have a 256-entry palette. Masks are
 ignored.
 The unused 4th byte in each pixel in 32bpp sprites is used as an
 alpha channel. Set the byte to 255 to make the pixel transparent.


 Button
 ------
 Creates a button.

 Argument:          button-structure

 Example:           Button {
                      id 9
                      up {
                        id 6
                        depth 6   // not quite sure what this does
                      }
                      actions {
                        gotoframe 15
                        play
                      }
                    }

 The button-structure must contain the following fields:

                    name                argumenttype

                    id                  U16
                    up                  buttonstate structure
                    actions             action-list structure
                                        (see DoAction)

 and may also contain these fields:

                    over                buttonstate structure
                    down                buttonstate structure
                    activearea          buttonstate structure


 The buttonstate structures must contain the following fields:

                    id                  U16
                    depth               U16

 and may also include the following fields:

                    matrix              matrix

 The various buttonstate structures define which character (which must
 also be defined in the script-file) to use for the various states
 of the button. The activearea structure defines which character to
 use to detect when the mouse is over the button.

 You may include multiple up/over/down/activearea structure in a
 button. The over/down/activearea structures default to the same
 as the up structure.

 Use ButtonSound to attach sounds to a button.

 If the the two (or more) buttonstates use the same buttonstate-
 structure, you may define it by specifying eg.:

          Button {
            id 9
            up:down:activearea { id 6
                                 depth 6
            }
          }



 ButtonSound
 -----------
 Defines which sounds to play when a button changes state.

 Argument:          buttonsound-structure

 Example:           ButtonSound {
                      buttonid 123
                      enter { 121 3 } // play '121' 3 times
                      leave { 121 0 } // stop '121'
                    }

 The buttonsound-structure must contain the following fields:

                    name                argumenttype

                    buttonid            U16

 and must also contain at least one of the following fields:

                    down                { U16 U16 }
                    up                  { U16 U16 }
                    enter               { U16 U16 }
                    leave               { U16 U16 }

 up/down/enter/leave defines the sound to play when the button
 changes state from down to up, up to down, idle to over and over to
 idle. The first value is the id of the sound (as defined by
 DefineSound) and the second value is the number of times to loop.
 If the loop-count is set to 0, the sound will not be played, instead
 any instance of the specified sound will be stopped.


 Font
 ----
 Defines a font.

 Argument:          font-structure

 Example:           Font {
                      id 55
                      name "My Font"
                      glyph {
                        char "A"
                        moveby { 100 1000 }
                        curveby { 1000 1000 1000 -1000 }
                        lineby { -1000 -1000 }
                        lineby { -1000 1000 }
                      }
                      glyph {
                        char "x"
                        moveby { 100 1000 }
                        curveby { 1000 1000 1000 -1000 }
                        lineby { -1000 -1000 }
                        lineby { -1000 1000 }
                      }
                      scale { 46200 45600 }
                      spacing 100
                    }

 The font-structure must contain the 'id' field, and a least one
 glyph structure:

                    name                argumenttype

                    char                string (one char) or U8

 A glyph-structure must also contains a shape, in the form of a
 sequence of moveto { }, moveby { }, lineby { }  and curveby { }
 structures.

 The font-structure may also include the following fields:

                    scale               { S32 S32 }
                    spacing             S16
                    name                string

 The scale field specifies how to scale the coordinates in the
 glyph-shapes. The glyph-coordinates should be scaled so that all
 glyphs fit inside a 1024x1024 box (the EM square).

 The spacing is inserted between each char/letter.

 A font-defintion for all letters, numbers etc. may take up several
 kbytes; therefore writeflash doesn't save a glyph (the shape defining
 a letter or number or sign) if it isn't being used by any of the
 text-objects in the file; eg. if you define a font with 100 glyphs,
 but only use the glyphs for the letters in the word 'Hello', then only
 the glyphs for the letters 'H', 'e', 'l', and 'o' will be saved.
 However, this can be disabled by defining the macro INCLUDE_ALL_GLYPHS,
 ie. by including the line  '#define INCLUDE_ALL_GLYPHS'  in the script.

 If the name field is included, a fontinfo record for the font is
 included in the output; used with INCLUDE_ALL_GLYPHS it allows for
 easier manipulation of the generated flash file.


 DefineSound / Sound
 -------------------
 Adds a sound to the dictionary.

 Argument:          sound-structure

 Example:           Sound {
                      id 123
                      file "$.samplefile"
                      format "LIN8"
                      channels 1
                      freq 22
                    }

 The sound-structure must include the following fields:

                    name                argumenttype

                    id                  U16
                    file                file
                    format              string
                    channels            U16
                    freq                U16

 format must be either
          "LIN8"              8 bit linear signed
          "LIN16"             16 bit linear signed
          "ADPCM2"            8 bit lin signed, output as 2 bit ADPCM
          "ADPCM3"            8 bit lin signed, output as 3 bit ADPCM
          "ADPCM4"            8 bit lin signed, output as 4 bit ADPCM
          "ADPCM5"            8 bit lin signed, output as 5 bit ADPCM
          "ADPCM2-16"         16 bit lin signed, output as 2 bit ADPCM
          "ADPCM3-16"         16 bit lin signed, output as 3 bit ADPCM
          "ADPCM4-16"         16 bit lin signed, output as 4 bit ADPCM
          "ADPCM5-16"         16 bit lin signed, output as 5 bit ADPCM

 The value of the channels field must be either 1 (mono) or 2 (stereo).
 The freq field specifies the sample rate. It must be either
 5 (5.5kHz), 11 (11kHz), 22 (22kHz) or 44 (44kHz).

 If any of the "ADPCM" formats are specified, the samples will be
 converted from 8/16 bit linear signed to the specified ADPCM format.

 stereo and 16 bit formats have not been tested.


 PlaySound
 ---------
 Starts (or stops) a sound.

 Argument:          playsound-structure

 Example:           PlaySound {
                      id 123
                      loops 3
                      frame 45
                    }

 The playsound-structure must contain the id field, and may also contain
any of the following fields:

                    name                argumenttype

                    loops               U16
                    frame               U16

 If a frame number is given in the structure, the sound will be played
 at the specified frame; you can only address previously defined frames
 this way.

 If loops is set to 0, the sound will not be played, instead any
 instance of the sound specified by id will be stopped.

 Sounds may also be played when a button changes state; see ButtonSound.


 Text
 ----
 Defines a text-string.

 Argument:          text-structure

 Example:           Text {
                      id 56              // to be used by PlaceObject {}
                      matrix { }         // default matrix

                      style {
                        font 55          // font id
                        size 48*20       // text size in twips
                        colour ffffff00  // text colour
                        move { 10261 0 } // where to display the text
                      }
                      text "Hello, world!"
                    }

 The text-structure must include the 'id' field, and may also include
 a transformation matrix. Besides that, the text-structure must also
 contain at least one style- and one text-field.

                    name                argumenttype

                    text                string
                    style               textstyle-structure

 There must be a style-field before the first text-field, otherwise
 the player will not know which font/fontsize/colour/position to
 use.

 The textstyle-structure may contain any of these fields (the first
 textstyle-structure in a text-structure must contain all fields):

                    name                argumenttype

                    font                U16
                    size                U16
                    colour              RGBA
                    move                { S16 S16 }


 Preprocessor/Script-processor
 ==============================
 The script-processor provides both a simple one-pass preprocessor
 and allows you to do things like looped and conditional parsing.

 Preprocessor
 ------------
 Lines starting with the character '#' are considered
 preprocessor-directives and are processed when the script-file is read
 into memory before parsing.
 That the pre-processor is 'one-pass' means that macros may refer to
 other macros that have been define earlier in the file, but they may
 not refer to macros that are defined later on in the file.

 The following preprocessor-directives are supported:

 #include <filename>
 -------------------
 Inserts the specified file in the script; this allows you to build
 a library of commonly used shapes (eg. fonts or logos) and reuse them
 in any script-file.

 Example:           #include FlashLibrary:Fonts.Homerton.Medium

 #define <macroname> [<value>]
 -----------------------------
 Defines a macro, and optionally assignes a value to it. Whenever
 the script-file parser finds a reference to the macro, it is replaced
 with the value of the macro.
 It may also be used together with #ifdef and #ifndef to force the
 parser to ignore parts of the script-file.

 Examples:          #define INCLUDE_LOGO
                    #define FONTSIZE    900
                    #define FILLSTYLE3 { solid ff00ff00 }

 Macronames must start with a letter or the character '_', and may only
 include letters, numbers and the character '_'.

 #ifdef <macroname>
 ------------------
 The script-file lines following the #ifdef lines (until an #endif) are
 only parsed if the macro has been defined. 
 #ifdef .. #endif may be nested.

 Example:           #ifdef INCLUDE_LOGO
                    PlaceObject { id LOGOID
                                  depth LOGODEPTH 
                                  matrix { } }
                    #endif

 #ifndef <macroname>
 -------------------
 Similar to #ifdef, except the lines are only parsed if the macro
 hasn't been defined.

 #else
 -----
 Used between #ifdef .. #endif or between #ifndef .. #endif 

 Example:           #ifdef USE_UPPER_CASE
                          text "HELLO WORLD"
                    #else
                          text "Hello world"
                    #endif

 #undef <macroname>
 ------------------
 Un-defines a macro.


 Script-file processor
 ---------------------
 Whereas the preprocessor is used when the script-file is loaded into
 memory, the script-file processor is used when the parser reads a line
 from the file in memory.

 Lines starting with the character ':' are executed by the script-file
 processor, rather than being parsed by the parser.

 The script-file processor recognises the following statements and
 keywords:

 :for <variable> = <expression> to <expression>
 :next

 :if <expression>
 :endif

 :print "string"

 :print <expression>

 Variables can be declared and assigned values using the following
 syntax:
 :var <variable> [,<variable>]
 :<variable> = <expression>
 :<variable> += <expression>
 :<variable> -= <expression>
 :<variable> *= <expression>
 :<variable> /= <expression>

 Variablenames have the following restrictions:
          * max 15 chars
          * must start with a letter (A..Z or a..z) or '_'
          * may only include letters, digits and '_'

 Variables must be declared (using ':var <variable>') before they can
 be used. The exception is the variables used for :for .. :next  loops.
 The loop-variable is created automatically and ceases to exist when
 the loop has finished.


 Whenever you specify a value in eg. a matrix or shape-definition etc.,
 you may use an expression instead; expressions are terminated by
 a space or when there are the same number of ( and ) in an expression;
 thus
          x*12+43             is legal
          x*12 + 43           is illegal
          (x*12 + 43)         is legal

 The following functions and operators are available:

                    + - * /

                    sin(<expression>)
                    cos(<expression>)
                    tan(<expression>)
                    log(<expression>)
                    exp(<expression>)
                    abs(<expression>)
                    sqr(<expression>)
                    rnd(<expression>)

 Comparisons        ==   <=   >=   !=   <   >  &&  ||

 The comparisions will return 1 if true or 0 if false.

 Notice that expressions are evaluated using floating point, but the
 value returned is always an integer.

 The variable 'frameno' always contains the number of frames defined
 so far; the variables 'framesizex' and 'framesizey' are set when the
 parser encounters a 'FrameArea { }' tag.


 The following example demonstrates how to use loops and expressions:

  #define FRAMES     4

  :for i = 1 to FRAMES
    PlaceObject {
      depth i+1
      id CIRCLE_ID
      matrix { 23000*i+4560 } // one value -> scaling
    }
  // do something here...
  :if i == 2
  // do something here
  :endif
  :next
  ShowFrame { }


 Inline files
 ============
 Fields of the type 'file' (used by eg DefineSound and JPEG) can either
 hold the name of the file to use, or a sequence of byte-values.
 For example, a JPEG may be included either as:

          jpeg {
            id 54
            file "test2.jpg"
          }

 or as
          jpeg {
            id 54
            file { ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 64
                   00 64 00 00 ff db 00 43 00 09 06 07 08 07 06 09
       //            etc etc etc etc etc
       //            etc etc etc etc etc
                   49 83 a1 24 7f ff d9 
                 }
          }

 This is called an inline file, and is especially useful when the
 script is program-generated.
 The parser ignores everything between the { } except hexadecimal
 digits, so the sequence '12345 6 7 8ab' is treated just like
 '12 34 56 78 ab' or '12 xxxx *&*&* 3456 78 a ooppsss b'.


 Missing features, known bugs, etc.
 ==================================
 * not all features have been tested


 Creating fonts etc.
 ===================
 The directory !Flash.Tools contains a few command-line tools that may
be useful.
     * Draw2Flash   creates library-files or full script-files
                    from Draw files
     * MakeFont     creates library-files from an outline font
     * readflash    deconstructs a Flash file


 Draw2Flash
 ----------
 Syntax:   *Draw2Flash [switches] <drawfile> <scriptfile>
 Switches: -v        verbose
           -s        split grouped paths
           -c        center objects around 0,0
           -b        include bitmaps
           -t        include text
           -full     output full scriptfile
           -id <id>  id of first object
 Example:  *Draw2Flash -s -c -id 400 -full $.drawfile $.script

 -s     split grouped paths:
        Flash and Draw uses very different and not always compatible
        rules for path-filling; this affects grouped paths with
        different fill-styles; use the -s switch to ungroup paths

 -full  output fill scriptfile
        Draw2Flash can either output a file containing just the
        shapes/objects (for including in your own scriptfile or for
        use a library) or it can output a full scriptfile which may
        then be passed to writeflash directly

 -id    id of first object
        this sets the id of the first shape/object output by
        Draw2Flash; at the end of each shape/object, the id is
        incremented so the next shape/object will have another id


 MakeFont
 --------
 Syntax:   *MakeFont [switches] <fontname> <macro> <id>
 Switches: -v        verbose
           -nosave   don't save anything
 Example:  *MakeFont -v Homerton.Medium HOMERTON_MEDIUM 50075

 fontname  name of the RISC OS font

 macro     name of the macro that should be used to define the
           ID of the font

 id        the id to use for the font

 The font will be saved as 'FlashFonts:<fontname>'.

 Notice that some fonts may need manual adjustment afterwards.
 RISCOS fonts and Flash-files use different types of Bezier-curves;
 MakeFont uses a very primitive algorithm to convert the Bezier-curves.


 readflash
 ---------
 Syntax:   *readflash [switches] <flashfile>
 Switches: -t        display only tag-id/size

 readflash can output quite a lot of information, so it is usually
 a good idea to redirect the output to a file.


 History
 =======

 0.22     2001-05-06
          * a fontdefinition may include the name of the font
          * if a fontdefinition includes a name, a fontinfo
            record is written
          * fixed action-parsing bug in readflash

 0.21     2001-05-01
          * fixed bug relating to 8/16/32 bpp sprites
          * no longer checks if a depth is used when placing an
            object
          * the unused 4th byte in each pixel in 32bpp sprites
            is now used as alpha channel; this doesn't work with
            !Flash 0.49c

 0.20     2000-10-14
          * changed a few things in button-parsing/writing, to allow
            multiple states to be defined in one go
          * improved readflash a bit

 0.19     2000-08-02
          * changed almost all 'int' and 'short' to S32/U32/S16/U16.

 0.18     2000-07-09
          * bug in bracket-matching fixed

 0.17     2000-07-05
          * font-IDs have been reorganized; MakeFont changed a bit and
            you no longer need to   #include FlashFonts:IDs
          * fixed bug in sound-format parsing

 0.16     2000-06-25
          * added support for ADPCM-compression - no longer supports
            loading of pre-compressed ADPCM samples

 0.15     2000-06-23
          * added support for compression of JPEG-alpha-channel - this
            also means that zcomp no longer has any use and so has been
            removed from the Tools directory
          * Draw2Flash now supports text (although not text-areas)

 0.14     2000-06-15
          * fixed bug in define_macro()
          * added (not-quite-working-yet) text-support to Draw2Flash

 0.13     2000-06-14
          * added support for bitmap-compression
          * added support for loading of spritefiles (4,8,16,32 bpp)
          * fixed bugs in Draw2Flash (-id was required, other minor bugs)
            and added support for JPEG/sprites

 0.12     2000-06-12
          * added -define and -defines switches
          * added support for lossless bitmaps
          * changed a few things in preprocess.c and elsewhere

 0.11     2000-06-11
          * extended readflash to support sound
          * support for ButtonSound
          * added check for 'id 0'
          * support for inline files
          * fixed bug in bitmap.c (JPEG with alpha-channel didn't work)

 0.10     2000-06-04
          * support for DefineSound and PlaySound
          * improved Draw2Flash
          * tidied a few things

 0.09     2000-04-25
          * minor cosmetic changes
          * improved the bezier-conversion in Draw2Flash and MakeFont

 0.08     2000-04-24
          * tidied the handling of the dictionary
          * fonttext.c now calculates and writes the no. of bits
            required to store a glyph-index and advance-value
          * now always includes a matrix in PlaceObject - the GPL
            player appears to require this

 0.07     2000-04-21
          * improved the script-processor
          * implemented bracket-matching in expressions

 0.06     2000-04-20
          * tidied a few things
          * fixed serious bug in shape.c
          * the bit-bucket is now being flushed before writing
            a matrix or cxform
          * aliases for selectfillstyle0 and selectfillstyle1

 0.05     2000-04-19
          * fixed a few bugs in evaluate.c and preprocess.c
          * aliases for DefineShape, PlaceObject, RemoveObject and
            BackgroundColour
          * cxform's are now parsed correctly

 0.04     2000-04-18
          * :for .. next loop extended to allow expressions
          * added :print to the script-processor (for script-debugging)
          * added -pl commandline switches (for script-debugging)
          * fixed bug in the parsing of 'moveby { }'
          * added 'moveto { }' to shape-structures
          * allowed RGBA values to be specifed as { R G B A }
          * changed 'letter' field in glyph-structure to 'char'
          * added more helpful error-messages

 0.03     2000-04-17
          * added support for buttons
          * added support for fonts/text (not sure if it works 100%)
          * script-processor added
          * now allows multiple line/fillstyles in a single structure
          * automatically calculates the bbox of shapes
          * objects may be placed in and removed from previous frames
          * tidied the code

 0.02     2000-04-09
          * first release
