; These three lines catch attempts to run this file as a script.
message("This is a help file, not a script!")
selfexec("%Filer_Run")
terminate()


This file has been converted from the StrongHelp guide. It has only had VERY
MINOR reformatting (ie, page numbers and titles removed, etc). This is
intended as a basic textual reference version of the main script guide. The
main guide is properly laid out, cross-referenced, looks nicer, etc. If you
do not have it, you may obtain it from the Teletext website at:
  http://www.heyrick.co.uk/software/ttx/
The examples have also been omitted to keep the size down. Also, without the
different fonts, it gets harder to determine what is what...
The entries are, possibly, in alphabetical order. I'm not entirely sure, I
just know the order is a bit strange. Sorry.





                         T e l e t e x t   S c r i p t
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          ( v e r s i o n   1 . 0 5 )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ----------------------------------------------------------------------------

  Introduction
  ~~~~~~~~~~~~
    Overview
    Script execution

    Frame basics
    Frame layout


  Script basics
  ~~~~~~~~~~~~~
    Variables

    Branches
    Conditionals
    Looping

    File handling

    Debugging

    Polling


  Maths operations
  ~~~~~~~~~~~~~~~~
    Variables A-P are integers, and Q-Z are floats.

    Numbers
    Real maths
    Logical maths


  Script commands
  ~~~~~~~~~~~~~~~
    ;                     filetype         mul              setchar
    .                     fileupdate       nop              showcachelist
    abs                   filewrite        not              showcontrols
    add                   filewritebyte    omitline         showpreferred
    and                   filewritefloat   or               showviewer
    appendframe           filewritestring  oscall           sign
    appendframes          filewritevar     poll_disable     smartclear
    appendgivenframe      find             poll_enable      sqr
    appendline            findend          poll_message     [status; via set]
    /cache_flush/         flatten          poll_nomessages  storeframe
    /cache_insertfile/    getframe         poll_now         sub
    /cache_loaddirectory/ getframes        quit             terminate
    channel               go               readvalue        userchoice
    channelid             if               /report_var/     version
    [char; via set]       lsl              roundcast        ++
    div                   lsr              selectframe      --
    eor                   /lvar/           selectframes
    error                 message          /selfexec/
    fileclose             mod              set

    Entries in /italic/ are classed as undocumented.
    Entries in [square brackets] are only available via the set command.


  Miscellany
  ~~~~~~~~~~
    Cache utilisation
    Cache index format

    Differences between script versions

    Known bugs
    Reporting problems

    Suggestions and comments

    Contact information


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


  One final thing...

  Documentation version 0.05, 12th May 2003
  Script interpreter version 1.05, 9th May 2003
  Copyright  2003 Richard Murray
  ============================================================================


                                   a b s (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: abs( <variable>, <number> )

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

    This sets <variable> to the absolute value of <number>, so -47 would
    become 47.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================



                                   a d d (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: add( <variable>, <number> )

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

    This adds the number (or variable) given to the variable specified.

    A shorthand version of add(<var>, 1) is <var>++ which is useful when you
    need to increment something.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   a n d (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: and( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> AND <number2> and places the
    result in the specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                           a p p e n d f r a m e (   )
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: appendframe( <page>, <type> )

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

    This appends the first frame of the specified page to the output file, in
    the given type.

    The available types are:
      1 Teletext
      2 ASCII

    If the file type is ASCII and the frame has no header (line 1), then all
    blank lines will be removed as the file is copied out.

    The commands appendframes and appendgivenframe are closely related to
    this command.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                          a p p e n d f r a m e s (   )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: appendframes( <page>, <type> )

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

    This appends the all frames of the specified page to the output file, in
    the given type, in numerical order.

    The available types are:
      1 Teletext
      2 ASCII

    If the file type is ASCII and the frame has no header (line 1), then all
    blank lines will be removed as the file is copied out.
    This does not multitask, so may freeze the computer for a few moments
    while the frames are saved.
    Subframes that do not exist are simply skipped over. If the entire page
    does not exist, results are undefined. :-)


    The commands appendframe and appendgivenframe are closely related to this
    command.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                      a p p e n d g i v e n f r a m e (   )
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: appendgivenframe( <page>, <subframe>, <type> )

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

    This appends the specified frame of the specified page to the output
    file, in the given type.

    The available types are:
      1 Teletext
      2 ASCII

    If the file type is ASCII and the frame has no header (line 1), then all
    blank lines will be removed as the file is copied out.


    The commands appendframe and appendframes are closely related to this
    command.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            a p p e n d l i n e (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: appendline( <line>, <type> )

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

    Appends a line to the currently open output file. Please note that this
    is different to the appendframe commands in that it will take the
    specified line from the currently loaded frame. You do not need to
    specify a frame/subframe.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                           c a c h e _ f l u s h (   )
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: cache_flush()

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

    This command erases the cache contents. Totally. Everything. Forever.

    It is designed as a debugging aid. Do not use it liberally in scripts you
    used by others, they may not appreciate their cache being nuked.

    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                      c a c h e _ i n s e r t f i l e (   )
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: cache_insertfile( <"path">, <frame>, <subframe> )

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

    This command loads a teletext frame from disc and inserts it into the
    cache as if it had been fetched. You can specify frame/subframe numbers,
    or set both to -1 in order to use the number stored within the frame.

    This is a useful debugging aid for scripts that fetch a number of pages
    and then process them. If the processing part needs debugging, you can
    simply fetch the pages manually and store them on disc. Then simply amend
    your script to temporarily load the frames from disc instead of off-air.
    Instant speed saving!

    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2001 Richard Murray
    ==========================================================================


                   c a c h e _ l o a d d i r e c t o r y (   )
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: cache_loaddirectory( <"path"> )

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

    This is like a souped up version of cache_insertfile(), where it will
    scan an entire directory and load every teletext frame (type &112) that
    it finds, storing them into the cache with their internal page numbers.
    An hourglass will appear, the percentage counter reflecting how many
    files have been checked (not a true percentage!).
    This command does not poll, and is not very fast.
    Scanning does not recurse into subdirectories.

    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               c h a n n e l (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: channel( <channel> )

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

    This command selects a given channel. The channel range is 1 to 9.

    Typical channel settings:
      1  BBC 1
      2  BBC 2
      3  Local ITV
      4  Channel 4
      5  Channel 5
      8  AV device, like set-top-box or satellite unit

    My settings, as I cannot receive Channel 5 off-air, are:
      1  BBC 1
      2  BBC 2
      3  Meridian
      4  Channel 4
      5  Satellite

    There is no way to set a channel's tuning in script, but one of the
    status options will return the UHF tuning, so you can check it if you
    desire.

    If you have a device that shares several 'channels' on one tune value,
    such as a satellite receiver, then you could use the channelid() command
    to read the identity value of the channel. This is broadcast by most
    stations. Use the "Channel ID" menu option to check the broadcast channel
    name and identity.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~
                                 s t a t u s (   )
                                 ~~~~~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      Syntax: status( <parameter> )

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

      Note that the status parameters are macros, not strings. Therefore they
      are not enclosed in quotes.

      This command returns the status of the requested parameter.

      This is a function, not a command. Therefore it must be used with the
      set command, like:
        set <variable> to status( <parameter> )



      cachesize
        This returns the number of frames currently cached. This is old
        frames, expired frames, script frames, the lot...


      channel
        This returns the currently selected channel, in the range 1-9. This
        could be useful for restoring previous context after running a script
        that changes channel.


      file
        This returns the file handle of the user file (the one opened with
        filewrite()), or 0 if no file is open.


      framenum
        This returns the true frame number, in the form &pppssss. There is
        practically no use for this whatsoever, but it was useful for me
        during script testing to check the denary<->hex translations were
        working correctly...


      frames
        This interrogates the cache and returns the highest subframe number
        available for the currently loaded frame, or 0 if no frames exist.
        Between retrieving the frame and using this status, you should
        selectframe() the desired page to fix the current frame, otherwise
        you may get a report for the wrong frame!
        For example:
          ; to see if page 123 is cached
          selectframe(123)
          set A to status(frames)
          if(A=0) error("Frame`123`not`cached!")


        pagefound
        Returns 1 if the requested page has been found and cached, or 0 if
        the getframe()/getframes() command timed out.


      pagenum
        Returns the page number of the current page (100-999), or 0 if
        nothing is current. You can use this like status(frames) in the
        example above.


      progver
        This returns the version of the program multiplied by 100. Therefore
        !Teletext version 1.48 is returned as 148.


      scriptver
        This returns the version of the script interpreter in use, multiplied
        by 100. Currently this will return '105'.
        If you use newer features, you should first ensure that the script
        interpreter in use can parse your features.
        You are guaranteed that the following will always work:
          set A to status(scriptver)
          if(A < <whatever version>) error("Parser too old!")


      ttxon
        Returns 1 if adaptor is on, else 0.
        It isn't really possible to execute a script with the adaptor off, as
        !Teletext won't open the viewer in this state, so this is mostly
        superfluous.


      uhftune
        This returns the UHF tuning (21-69) of the current channel.

      ------------------------------------------------------------------------
      Index

      Copyright  2003 Richard Murray
      ========================================================================





                             c h a n n e l i d (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: channelid( <variable> )

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

    Sets the specified variable to the current channel ID.
    For example, CNN is &804F.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   s e t (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: set <variable> to <value>

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

    This command assigns a value to a specified variable.
    Please note that this command is different to others in that it has no
    brackets, it has a 'to' instead.

    You can set the variable to another variable ( set A to B ) or to a
    constant value ( set A to 123 ), which may be expressed in denary, hex,
    or binary.

    There are also two functions at your disposal:
      char( <x>, <y> )
        char() will return the value of the specified character. The X value
        is in the range 1 to 40, and the Y value is in the range 1 to 25.
        setchar() is the logical opposite of this.

      status( <status> )
        status() provides a report on miscellanous things which may be of
        some use to you. As a script coder, things like 'pagefound' are
        useful, while things like 'file' probably are not so useful. :-).
        You can read full details on the status parameters here.


    When 'casting' a float to an integer, the set command rounds down, so 1.9
    would become 1. If you would prefer a round to nearest, use the
    roundcast() command.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================





                                   d i v (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: div( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> / <number2> and places the result
    in the specified variable.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   e o r (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: eor( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> EOR <number2> and places the
    result in the specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                 e r r o r (   )
                                 ~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: error( <"message"> )

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

    This command reports an error message to the user, and then aborts script
    processing.

    As with all string parameters, you can use '`' instead of spaces in your
    message.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================



                             f i l e c l o s e (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: fileclose()

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

    This closes the output file. As only one file handle is valid, no
    parameter needs to be specified.

    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                              f i l e t y p e (   )
                              ~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filetype( <"filename">, <type> )

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

    This sets the specified file to the specified type. Type is usually &FFF
    for ASCII text files.

    A side-effect of this command is the output file, if open, will be closed.


    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            f i l e u p d a t e (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: fileupdate( <"filename"> )

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

    This opens the specified file for update. You can only have one file open
    at any given time. If the file exists, it is opened and the file pointer
    set to the end of the file so your output is appended to the end of the
    file. If the file does not exist, it is created.
    This has the same behaviour as BASIC's OPENUP command (OS_Find &Cx).

    If you want to create a new file, overwriting previous contents, refer to
    filewrite().

    If another file is already open, an error will be generated and script
    processing terminated.

    The logical location to place your files is in <Teletext$Temp> or,
    failing that, <Wimp$Scrap>.


    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             f i l e w r i t e (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filewrite( <"filename"> )

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

    This opens the specified file for output. You can only have one file open
    at any given time, and if the file already exists, it's contents are
    erased. This has the same behaviour as BASIC's OPENOUT command (OS_Find
    &8x).

    If you want to update an existing file, refer to fileupdate().

    If another file is already open, an error will be generated and script
    processing terminated.

    The logical location to place your files is in <Teletext$Temp> or,
    failing that, <Wimp$Scrap>.


    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                         f i l e w r i t e b y t e (   )
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filewritebyte( <byte> )

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

    This outputs the byte given to the specified file. For example...

    filewrite("<Teletext$Temp>.temp")
    set A to 0
    .loop
      filewritebyte(A)
      A++
      if (A [ 255) go("loop")
    fileclose()
    filetype("<Teletext$Temp>.temp", &FFF)
    oscall("Filer_Run`<Teletext$Temp>.temp")

    ...would open a file and write 256 bytes, incremental through the
    character set.
    A more useful use for this is to output newline characters (10) between
    frames to space things out better.


    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                        f i l e w r i t e f l o a t (   )
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filewritefloat( <variable>, <number1>, <number2> )

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

    This writes the specified floating point variable to the file.

    <number1> specifies how many digits are on the LEFT of the decimal place.
    If there are fewer present, the number is padded with spaces on the left.
    If there are more, the leftmost numbers are truncated and replaced with a
    '' character.
    <number2> specifies how many digits are on the RIGHT of the decimal
    place. If there are fewer, the number is zero-tail-padded. If there are
    more, the number is truncated.

    If you pass an integer variable, it is displayed in the same way.


    Example:
      If Z is 1234.5678, then:
       filewritefloat(Z,4,2) outputs "1234.56".
       filewritefloat(Z,2,2) outputs "4.56".
       filewritefloat(Z,3,3) outputs "34.567".

      If A is 123, then:
       filewritefloat(A,4,2) outputs " 123.00".
       filewritefloat(A,2,2) outputs "3.00".
       filewritefloat(A,3,3) outputs "23.000".

    It may seem as if the truncated-left values are incorrect, but remember
    the '' character is counted as a digit for the purposes of allowing
    proper alignment.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                       f i l e w r i t e s t r i n g (   )
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filewritestring( <byte> )

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

    This outputs the given string to the specified file. For example...

    filewrite("<Teletext$Temp>.temp")
    filewritestring("CNN news headlines")
    filewritestring("==================")
    filewritebyte(10)

    ...commands to output news pages previously fetched...

    fileclose()
    filetype("<Teletext$Temp>.temp", &FFF)
    oscall("Filer_Run`<Teletext$Temp>.temp")

    would create a file beginning:

    CNN news headlines
    ==================

    ...data from fetched pages would begin here...



    Refer to file handling for further information.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                          f i l e w r i t e v a r (   )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: filewritevar( <variable>, <number> )

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

    This writes the specified variable to the file.

    Float variables... The <number> specifies how many decimal places the
    output is written as. For example, if Z is 0.123456, then
    filewritevar(Z,2) outputs 0.12.

    Integer variables... The <number> specifies an alignment. The output is
    padded to this size, with spaces on the left. For example, if A to 47,
    then filewritevar(A,5) then the output will be "   47".

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               f l a t t e n (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: flatten( <variable>, <number> )

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

    This 'flattens' a floating point variable (specified) to <number> decimal
    places.

    Sometimes a calculation can result in an annoying recursive number, for
    example '15 / 9' results in 1.66666667. To keep things sane, you can
    flatten to two decimal places to convert that into 1.66. Note that this
    simply chops off the end of the variable, no rounding is performed.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                              g e t f r a m e (   )
                              ~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: getframe( <page> )

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

    This command gets the next broadcast frame of the specified page. The
    frame, when retrieved, is stored in the cache.

    Frame searching will time out after sixty seconds, if nothing is found.


    If you want to retrieve all the frames of a cycling page (ie, TV guide or
    'letters'), you'll want to use getframes() instead.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             g e t f r a m e s (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: getframes( <page> )

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

    This command gets all frames of the specified page. The frame, when
    retrieved, is stored in the cache. A check is kept on the first found
    frame, and when it is found again, it is assumed that all frames are now
    stored.

    This command does not currently work with channels that broadcast each
    frame in the sequence twice.

    Frame searching will time out after sixty seconds, if nothing is found.
    This, obviously, is reset each time a frame is found.

    If you only want to retrieve a static page (ie, a news page), you'll want
    to use getframe() instead.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                    g o (   )
                                    ~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: go( <"label"> )

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

    This command branches to the specified label.
    You can branch to any label.

    The following shows a simple loop:
    set A to 0
    .loop
      A++
      go("loop")

    This also works, branching forward:
    set A to 0
    .loop
      A++
      ; we do something here
      if (A = 128) go("continue")
      go("loop")

    .continue
      terminate()

    You may also wish to refresh your memory on branches and looping.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================






                                    i f (   )
                                    ~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: if( <variable> <conditional> <value> ) <command>

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

    If you have not already done so, please read the help on conditionals.

    In an if() statement, the clause given is evaluated. If it evaluates to
    be true then the command is executed, otherwise script processing picks
    up on the next line.

         <variable> is any valid variable (A to Z)

         <conditional> is the comparison to perform

         <value> is the value to compare the variable with. This may be a
          constant number, or it may be another variable.

    The available comparisons are:
      =  Equal
      !  Not equal
      <  Less than
      >  Greater than
      [  Less than or equal to
      ]  Greater than or equal to

    You can chain if() statements, if necessary:
      set A to 1
      set B to 2
      set C to 3
      if(A = 1) if(B = 2) if(C = 3) message("Three times a lady!")
      terminate()

    The way that processing is performed for matching clauses is that the
    original line is butchered to remove the if() that was just executed,
    then it is passed back to the parser in a re-entrant fashion. No polling
    is performed between evaluation and reparsing, and the handler is capable
    of picking up on script errors.

    The maximum permissable line length of a script command is 255
    characters, and you can nest as many if()s as will fit into that space,
    though if you need that many if statements, you might be better off
    looking for an alternative way to do your comparisons!

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   l s l (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: lsl( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> << <number2> and places the
    result in the specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   l s r (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: lsr( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> >> <number2> and places the
    result in the specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   l v a r ( )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: lvar( )

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

    This command will generate a 'report' on the state of the script
    environment, and write it out to the logfile (refer to debugging for
    information on the logfile).

    This is an example, taken from the end of a successful execution of the
    "movietest" script:

    LVAR (weathrtest)
    =================

    Integer variables:
      A = 0
      B = 0
      C = 0
      D = 0
      E = 0
      F = 3
      G = 4
      H = 0
      I = 0
      J = 0
      K = 0
      L = 25
      M = 15
      N = 0
      O = 0
      P = 0

    Float variables:
      Q = 0
      R = 0
      S = 0
      T = 0
      U = 0
      V = 0
      W = 0
      X = 0
      Y = 0
      Z = 59

    Branch positions:
      frameloop,                           266; 17
      lineloop,                            315; 21

    Miscellany:
      Script file handle   254
      User file handle     253
      Current line number  50


    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               m e s s a g e (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: message( <"message"> )

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

    This command pops up a message for the user to read. Processing continues
    when the user clicks on the 'OK' icon.

    As with all string parameters, you can use '`' instead of ' ' if you
    prefer.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================




                                   m o d (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: mod( <variable>, <number1>, <number2> )

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

    This calculates the modulus of <number1> / <number2> and places the
    result in the specified variable.

    There is no corresponding 'DIV' to get the divisor only. The simple way
    to do this is to perform the division and direct the result to an integer
    variable.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   m u l (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: mul( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> * <number2> and places the result
    in the specified variable.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   n o p (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: nop( )

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

    This command does absolutely nothing, hence Null OPeration.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================





                                   n o t (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: not( <variable>, <number> )

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

    This calculates the result of NOT <number1> and places the result in the
    specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                              o m i t l i n e (   )
                              ~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: omitline( <"omitline"> )

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

    This command blanks out the specified line in the current frame. Valid
    lines are 1 to 25.

    Refer to frame layout for more details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                    o r (   )
                                    ~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: or( <variable>, <number1>, <number2> )

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

    This calculates the result of <number1> OR <number2> and places the
    result in the specified variable.

    Please refer to Logical Maths for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                o s c a l l (   )
                                ~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: oscall( <"call"> )

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

    This command executes the specified *command.
    Note that commands are not vetted, and error messages are reported and
    treated as script errors.

    You can use '`' instead of spaces in your command, if you wish.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                          p o l l _ d i s a b l e (   )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: poll_disable()

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

    This command switches the script interpreter to singletasking mode.

    Use poll_enable() to revert to the default multitasking mode.

    Refer to the information on polling for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                           p o l l _ e n a b l e (   )
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: poll_enable()

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

    This command reverts back to the default multitasking mode, after a call
    to poll_disable().

    Refer to the information on polling for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                          p o l l _ m e s s a g e (   )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: poll_message( <"message text"> )

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

    This writes the given message to the status window, clipping it if too
    large.

    As a side effect, if messages were previously disabled with
    poll_nomessages(), they will now be re-enabled.

    Refer to the information on polling for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                       p o l l _ n o m e s s a g e s (   )
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: poll_nomessages()

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

    Disable the output of status messages to the status window (bottom left
    of screen).

    Use the command poll_message() to re-enable status messages.

    Refer to the information on polling for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                              p o l l _ n o w (   )
                              ~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: poll_now()

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

    If in singletasking mode, this command will cause a wimp poll. It has no
    effect in the default multitasking mode.

    Refer to the information on polling for further details.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                  q u i t (   )
                                  ~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: quit( )

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

    Quits !Teletext. Use with care!

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             r e a d v a l u e (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: readvalue( <variable>, <number1>, <number2> )

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

    <number1> is the X position (column), <number2> is the Y position (row).
    The script interpreter will attempt to read a value, integer or float,
    and write the output to the specified variable.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            r e p o r t _ v a r (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: report_var( <"variable"> )

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

    This command pops up a message informing you of the current value of the
    specified variable. This is useful when debugging your scripts.
    The message is The value of variable '<var>' is '<value>', where <var>
    and <value> are set appropriately.

    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             r o u n d c a s t (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: roundcast( <variable>, <number> )

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

    This converts the number specified (which should be floating point), into
    the variable specified (which should be integer), rounding to the nearest
    whole number.

    This command was added because 'set A to Z' rounds down, so 1.9 would
    become 1.

    Other behaviour:
      If you cast a float to a float, 0.5 is added.
      If you cast an integer to an integer, nothing happens.
      If you cast an integer to a float, 0.5 is added.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                           s e l e c t f r a m e (   )
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: selectframe( <page> )

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

    This command makes the first located frame of the specified page the
    current frame.

    If you wish to specify a particular subframe to load, then use
    selectframes.

    If the frame cannot be loaded for any reason, the current frame number
    will be set to zero. Script processing will continue. You should check
    the status to see if the frame was reloaded from the cache or not.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================




                          s e l e c t f r a m e s (   )
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: selectframes( <page>, <subframe> )

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

    This command loads the requested subframe of the specified page and makes
    it the current frame.

    If the frame cannot be loaded for any reason, the current frame number
    will be set to zero. Script processing will continue. You should check
    the status to see if the frame was reloaded from the cache or not.


    If you do not wish to specify a particular subframe to load, then use
    selectframe to load the first found.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                              s e l f e x e c (   )
                              ~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: selfexec( <"command"> )

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

    This command will pass the command specified to the OS, with the filename
    of the current script appended.

    The use of this is demonstrated at the top of the textual helpfile, where
    the command:
      selfexec("%Filer_Run")
    will Filer_Run the help file, so if you try to execute the help as a
    script, it'll load itself into an editor after giving you a message.

    The lines in question are:
    ; This catches attempts to run this file as a script.
    message("This is a help file, not a script!")
    selfexec("%Filer_Run")
    terminate()


    Please note that this command is classed as undocumented.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================



                               s e t c h a r (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: setchar( <x>, <y>, <value> )

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

    This command sets the given character (X = 1 to 40, Y = 1 to 25) to the
    specified value (0 to 255).


    There is a macro that states if a null byte (value = 0) is encountered
    when exporting the file as ASCII, then the sequence <10><32> will be
    output. This is supposed to write a newline followed by a space, however
    it seems to output a newline too many and I've not gotten around to
    fixing this.
    The space, incidentally, is so you can replace a colour code (which would
    be converted to a space) with this macro, and preserve text alignment.


    You can use the set <variable> to char(<x>, <y>) command to read the
    value of a given character, the logical opposite to setchar().


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                  s i g n (   )
                                  ~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: sign( <variable>, <number> )

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

    This sets the variable specified to the sign of the given number.

    If the number is negative, the result is -1.
    If the number is zero, the result is 0.
    If the number is positive, the result is +1.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            s m a r t c l e a r (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: smartclear( <y> )

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

    This command is indended to replace potentially convoluted code involving
    lots of loops and calls to setchar(). What this command does is it looks
    at the line specified, and blanks out everything that is marked as
    'graphics', no matter where in the line. This, effectively, allows you to
    strip out graphical logos and 'clean' the page.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                   s q r (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: sqr( <variable>, <number> )

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

    This sets the variable specified to the square root of the number given.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            s t o r e f r a m e (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: storeframe()

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

    When you have finished altering a frame (ie, omitline() et al), you
    should use this command to push the frame back into the cache so that it
    is available for further processing.
    If you do not, then next time you select or otherwise reload the frame,
    it will pull what would seem to be the old copy from the cache!

    There is no parameter.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================





                                   s u b (   )
                                   ~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: sub( <variable>, <number> )

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

    This adds the number (or variable) given to the variable specified.

    A shorthand version of sub(<var>, 1) is <var>-- which is useful when you
    need to deccrement something.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             t e r m i n a t e (   )
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: terminate()

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

    This command ends script processing.
    You are warned if the user file is still open.
    You can terminate anywhere, in loops, as if() conditional commands,
    whenever.

    There is no parameter.


    Reaching the end of the script file is an implicit terminate(), but this
    is not the correct way to finish, so you will be given a warning in this
    instance.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            u s e r c h o i c e (   )
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: userchoice( <variable>, <"message"> )

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

    This command opens the standard 'errorbox' displaying the message given,
    and waiting for the user to choose OK or Cancel.

    If the user chooses OK, then <variable> is set to 1, else it is zero.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               v e r s i o n (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: version( <variable> )

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

    This sets the variable specified to the script version multiplied by 100.
    It is exactly the same as:
      set <variable> to status(scriptver)

    You should use this to ensure that your script will work correctly on
    this version of !Teletext. The minimum script version which should be
    supported at this time (May 2003) is 1.05. All previous script versions
    should be considered obsolete.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                D e b u g g i n g
                                ~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    There are no debugging commands provided in the proper script definition.

    However, judicial use of if() and two 'undocumented' commands can assist
    you in debugging your programs.

    report_var(var)
      This command will pop up a message box telling you what the value if
      the specified variable is.

    lvar()
      This command will insert a variables list into the debug log.

    If you have a RAMdisc defined, then the script interpreter will create a
    file called "ttxscrplog". Everything on line 2 of the report window will
    be written to this log. Ensure your disc is large enough, as running out
    of space for the log is classed as a script error (not intentionally, the
    script error handler picks it up). To give you an idea, "movietest"
    generated a 66K log.
    Line one (the upper line) is not logged, so you are spared loads of lines
    saying "Executing script - 69% (64)".


    One thing to note, the line number reporting is not totally accurate. I
    patched this facility into the existing script interpreter to aid me in
    debugging (as percentages were a pain to figure out). It can get confused
    by lots of branching. :-)

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                 B r a n c h e s
                                 ~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    You have the ability to branch. In this version of the script
    interpreter, you may have up to sixteen branches. You may branch from any
    part of the script to any part of the script. This makes it simple to
    construct loops and multi-line IF style structures.

    Branches are written as a period followed by the branch name, like:
      .branchpoint
    and:
      .herewegoroundthemulberrybush

    All labels are read when the script begins. You use the go() command to
    branch to a label.

    For example:
      .begin
        A++
        go("begin")


    This example simply increments A, then goes back to the start. Forever.

    Please refer to the examples, as branches are used quite a lot in the
    examples.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             C o n d i t i o n a l s
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    In BASIC, you can do things like:

       IF ( (A = 1) AND (B = 2) AND (C = 3) ) THEN ...do something...

    You can do this in script by knowing that the if() syntax is:
      if( <var> <condition> <number> ) <command>

    If the condition evaluates to be true, then the 'command' is executed.
    There is no reason why the 'command' cannot be another if() command.

    So, first, the conditions:
      ! Not equal
      = Equal
      < Less than
      > Greater than
      [ Less than or equal to
      ] Greater than or equal to

    All of the following examples evaluate to TRUE, so the command would be
    executed.
      set A to 123
      if(A = 123) ...
      if(A ! 0) ...
      if(A > 12) ...
      if(A < 1973) ...
      if(A [ 123) ...
      if(A ] 123) ...

    All of the following evaluate to FALSE. Remember, A is zero at script
    start.
      if(A = 123) ...
      if(A ! 0) ...
      if(A > 12) ...

    You get the idea.


    So, that line of BASIC at the very start could be written as:

       if(A = 1) if(B = 3) if(C = 3) ...do something...



    Now let's assume you have read some data from a teletext frame, and you'd
    like to convert it. We shall invent an algorythm, where:
      result = ( (((input << 3 ) / 4) >> 1) * 5 )
    We only want to do this to numbers over 100, but we may be called with
    numbers less than 100. What we need is an 'if()' spanning several lines.
    There are two ways to do this:

      The wrong way...
      if(Q ] 100) lsl(Q, 3)
      if(Q ] 100) div(Q, Q, 4)
      if(Q ] 100) lsr(Q, 2)
      if(Q ] 100) mul(Q, Q, 5)

      The right way...
      if(Q < 100) go("skipthisstuff")
        lsl(Q, 3)
        div(Q, Q, 4)
        lsr(Q, 2)
        mul(Q, Q, 5)
       .skipthisstuff

    Note that you can compare a float with an integer. 99.4 is less than 100,
    103.2 is more...

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================






                         S c r i p t   e x e c u t i o n
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Running scripts

    Scripts are run, simply, by clicking MENU in the viewer window, following
    the Script option, then picking a script to run.


    As the script executes, a little window will pop up in the lower left
    corner. It provides two lines of output. The first is a positional line,
    it tracks the part of the script being executed (as a percentage) and it
    also provides an approximate line count.
    The lower line gives you status report on major commands that were
    executed, to help you follow through the script.

    The script coder may opt to disable this little status window.


    Previous versions of !Teletext was able to run the script in a
    multitasking mode or a single-tasking mode (by holding ALT when selecting
    which script to execute).
    This is no longer supported, as the script author has the ability to
    control how and when the script polls - if permitted in the !Teletext
    configuration.
    Because most of the time is likely to be taken waiting for pages to
    arrive, it is strongly suggested that your scripts multitask while
    awaiting pages. Polling can then be disabled during calculations, if
    required.


    Abandoning scripts

    Click on the !Teletext iconbar icon. A message will pop up asking if you
    want to abandon or carry on.

    If the script is running in single-tasking mode (ie, if the iconbar click
    has no effect), pressing ESCape will ask if you wish to abandon script
    processing.



    Script execution - from the point of view of the script

    Scripts begin executing at the first line, and then continues until:
         A terminate() command is reached.          
         A script error (or error() command) occurs.
         The file ends.                             
      Please note that end-of-file is not the proper way to end a script, and
      a warning will be generated.

    You have rudimentary control over program execution, you have the if()
    instruction which can provide conditional tests, you have a way to branch
    to a previous line, and from that you can build loops.

    Lines beginning with an egg ('') character are control commands (and are
    ignored by the script interpreter) and lines beginning with a semicolon
    (';') are for your comments (and, also, are ignored).

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~
                              C o n d i t i o n a l s
                              ~~~~~~~~~~~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      In BASIC, you can do things like:

         IF ( (A = 1) AND (B = 2) AND (C = 3) ) THEN ...do something...

      You can do this in script by knowing that the if() syntax is:
        if( <var> <condition> <number> ) <command>

      If the condition evaluates to be true, then the 'command' is executed.
      There is no reason why the 'command' cannot be another if() command.

      So, first, the conditions:
        ! Not equal
        = Equal
        < Less than
        > Greater than
        [ Less than or equal to
        ] Greater than or equal to

      All of the following examples evaluate to TRUE, so the command would be
      executed.
        set A to 123
        if(A = 123) ...
        if(A ! 0) ...
        if(A > 12) ...
        if(A < 1973) ...
        if(A [ 123) ...
        if(A ] 123) ...

      All of the following evaluate to FALSE. Remember, A is zero at script
      start.
        if(A = 123) ...
        if(A ! 0) ...
        if(A > 12) ...

      You get the idea.


      So, that line of BASIC at the very start could be written as:

         if(A = 1) if(B = 3) if(C = 3) ...do something...



      Now let's assume you have read some data from a teletext frame, and
      you'd like to convert it. We shall invent an algorythm, where:
        result = ( (((input << 3 ) / 4) >> 1) * 5 )
      We only want to do this to numbers over 100, but we may be called with
      numbers less than 100. What we need is an 'if()' spanning several
      lines. There are two ways to do this:

        The wrong way...
        if(Q ] 100) lsl(Q, 3)
        if(Q ] 100) div(Q, Q, 4)
        if(Q ] 100) lsr(Q, 2)
        if(Q ] 100) mul(Q, Q, 5)

        The right way...
        if(Q < 100) go("skipthisstuff")
          lsl(Q, 3)
          div(Q, Q, 4)
          lsr(Q, 2)
          mul(Q, Q, 5)
         .skipthisstuff

      Note that you can compare a float with an integer. 99.4 is less than
      100, 103.2 is more...

      ------------------------------------------------------------------------
      Index

      Copyright  2003 Richard Murray
      ========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~
                                  B r a n c h e s
                                  ~~~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      You have the ability to branch. In this version of the script
      interpreter, you may have up to sixteen branches. You may branch from
      any part of the script to any part of the script. This makes it simple
      to construct loops and multi-line IF style structures.

      Branches are written as a period followed by the branch name, like:
        .branchpoint
      and:
        .herewegoroundthemulberrybush

      All labels are read when the script begins. You use the go() command to
      branch to a label.

      For example:
        .begin
          A++
          go("begin")


      This example simply increments A, then goes back to the start. Forever.

      Please refer to the examples, as branches are used quite a lot in the
      examples.

      ------------------------------------------------------------------------
      Index

      Copyright  2003 Richard Murray
      ========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~




                                   L o o p i n g
                                   ~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      There are no such things as FOR...NEXT loops or DO...WHILE or the like.
      Instead, you have an if() clause which can control how you move around
      the script.

      For example:

         FOR a% = 1 TO 20
           ...do something...
         NEXT

      This can also be expressed, in BASIC, as:

         a% = 1
         REPEAT
           ...do something...
           a% += 1
         UNTIL a% > 20

      So using this concept, we can write it in our script as:

         set A to 1
         .comebackhere
           ...do something...
           A++
           if (A [ 20) go("comebackhere")

      ------------------------------------------------------------------------
      Index

      Copyright  2003 Richard Murray
      ========================================================================


                            F i l e   h a n d l i n g
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    In the script, you may output to a file.

    You open the file with:
      filewrite(...)
    or
      fileupdate(...)
    The former creates a 'new' file, replacing anything currently there. The
    latter appends output to an existing file (the file pointer will be set
    to the end of the file automatically). If there is no previously existing
    file for fileupdate(), one will be created.


    Then you use:
      appendframe(...)
    or:
      appendframes(...)
    to write output to the file.

    If you only want to output a single line, you can use:
      appendline(...)


    You can also use:
      filewritebyte(...)
    if you need to write a single byte (such as a newline code) to the file.

      filewritestring(...)
    if you need to write a string to the file.

      filewritevar(...)
    if you need to write the value of a variable to the file.


    Finally, you close the file with:
      fileclose()

    You can, if you want, set the filetype with:
      filetype()


    You can open and use as many files as you like. But only one may be open
    and in use at any given time.

    There is no checking to see if the file currently exists.
    If the file cannot be opened, the script will abort with an error.

    You may use status() to read the file handle, though there is little real
    reason to actually know this...

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                             F r a m e   b a s i c s
                             ~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    You have frames 100 to 999, in decimal only. There is no way to access
    hex. frames.

    That, pretty much, is all you need to know.
    If you need to know why you need to know this (!), read on...


    Those of you with experience in teletext will be aware that 'true' frame
    numbers are hex, in the form: &PPPSSSS, where PPP is the page number we
    know (ie, 102) and SSSS is the subframe number. Therefore, the news index
    on BBC 1 is not frame 102, it is frame &102000x.

    Okay. Now that you know that, forget it!
    It simply helps justify this explanation. :-)

    In the script, frame numbers are always provided in a 'sensible' form.

    Frame numbers are expressed in the range 100 to 999. No hex frames are
    allowed. You should NOT try commands like:
      getframe(&102)
    As you will end up fetching page 258.

    You can use the status() command to find out things such as the current
    frame number (in friendly form) or the current subframe number/count.
    You can use the frame_number() or frame_subnumber() commands if you want
    to know the actual frame number, in denary or hex. Again, this is mainly
    for information.

    Pages are in the following sequence:
      100 - 199, 200 - 299, 300 - 399, etc.
    You cannot select the out-of-range pages (ie, 29A - 2FF).

    --------------------------------------------------------------------------
    Frame layout

    Index

    Copyright  2003 Richard Murray
    ==========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~
                              F r a m e   l a y o u t
                              ~~~~~~~~~~~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      The top-left of the frame is location 1,1.
      The bottom right is location 40,25.


      The first line is the header.
      Then follow twenty three lines of page data.
      Finally, the twenty fifth line is usually used for FastText links.

      Each line is forty characters wide.

      In the frame, there is no end-of-line marker, everything is padded with
      spaces. In the script, the notional end-of-line is at horizontal offset
      forty.

      ------------------------------------------------------------------------
      Frame basics

      Index

      Copyright  2003 Richard Murray
      ========================================================================


                                 O v e r v i e w
                                 ~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    !Teletext incorporates a script interpreter which allows you to process
    teletext frames. You may fetch frames, perform various operations on them
    and then store them back in the cache and/or output them in a variety of
    formats.

    For example, one of the scripts provided reads the "Movies at 9pm this
    week on Channel 5". It pulls out the list of movies, formats the frames
    to remove advertising and the like, and then outputs the frames to a file
    in text format.
    A slightly more complex script reads the temperature in Nantes, from CNN.
    It reports the temperature in degrees celcius. However, instead of simply
    reading the farenheit temperature, it calculates it from the celcius
    temperature.
    Finally, another example script reads the pound/dollar/euro exchange
    rates from CNN, and outputs an equivalence chart.

    These are the sorts of things that can be achieved with the Teletext
    script language.

    The script language itself is fairly simple, tailored to exactly what it
    has been designed for. Thus, it provides a way to pass messages to the
    user but there is no provision for, say, drawing on the screen. Such a
    facility would not be useful in processing teletext frames!

    The script interpreter does not execute quickly. It is designed to poll
    fairly regularly. The teletext system in use loads the system between 15%
    and 60% (depending on what it is doing), with an average loading of
    around twenty-thirty percent. When the script is running, this may go up
    to around forty percent (again depending on what is happening). Some
    scripts may take in the order of ten minutes to execute.
    If you think this is slow, please remember that in the 'movies at 9'
    script, most of the time taken will be in waiting for the pages to arrive.
    The system is designed to be used multitasking, where you start a script
    and then forget about it for a while.

    Please note that the timings were taken on my RiscPC700 with Ran Mokady's
    !Usage, and is subjective to the other tasks running on your system, and
    the system itself.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                V a r i a b l e s
                                ~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    You have sixteen integer variables, A to P. You can set these to any
    integer values that you like, perform basic maths, or use them in
    conditional statements and as parameters to commands.

    You have ten float variables, Q to Z. You can set these to any floating
    point number you like, so long as there are not more than nine digits
    (not including decimal point). For example:
      set Q to 1.12345678901234567890 would set Q to 1.123456789.
      set Q to 123.123456789012345678 would set Q to 123.1234567.
      set Q to 1234567.12345678901234 would set Q to 1234567.123.
      set Q to 123456789.123456789012 would set Q to 123456789.
    There is sufficient accuracy for all sorts of money calculations.

    All variables are set to zero when script execution begins.

    Wherever a command states that it requires a variable as input, then you
    must give a variable.

    Wherever a command states that it requires a number as input, you may
    provide either a constant number or a variable. Your choice.

    To cast from an integer to a float, or vice versa, simply specify the
    desired variable as the destination. For example:
      set A to 14
      set B to 15
      div(Z, A, B)
    The result of two integers divided, is written to a float variable, as
    0.933333333.

    You can cast directly, like set Z to A.
    When casting an integer to a float, the value is simply copied.
    When casting a float to an integer, anything after the decimal point is
    discarded. This means the default casting method rounds towards zero. You
    may prefer to 'round to nearest', in which case you should use the
    roundcast() command.

    If you are comparing floating point values in an if() statement, be aware
    that the following will fail:
      set A to 14
      set B to 15
      div(Z, A, B)
      if (Z = 0.93) message("division successful!")
    The reason for the failure is simple. 0.933333333 is not the same as
    0.93. To make this work, you need to lose a little bit of the accuracy.
    The flatten() command will do this for you, and so the following will
    work:
      set A to 14
      set B to 15
      div(Z, A, B)
      flatten(Z, 2)        ; flatten Z to two decimal places
      if (Z = 0.93) message("division successful!")

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                  N u m b e r s
                                  ~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    The script understands only integer numbers, ie whole numbers (1, 2, 3).
    You cannot specify fractions or decimal points (ie, 2.5).

    You can set variables to chosen values using:
      set <var> to <num>

    Alternatively, you can provide numbers as arguments to many functions.

    Normally, numbers are expressed in denary, ie base 10, the normal way.

    Sometimes it is preferable to give numbers in hex (base 16) or binary
    (base 2).

    To specify a number in hex, preceed it with '&'.
    To specify a number in binary, preceed it with '%'.

    These examples all set the chosen variable to 123:

      set A to 123
      set B to &7B
      set C to %1111011

    Alternatively, you can fetch the news index page 102 on BBC 1 using
    something like:

      channel(1)
      getframe(102)

    But if you were perverse, the following would work:

      A++
      channel(A)
      getframe(&66)

    The above works only as the start of a script, as all variables are set
    to zero when the script begins. Later on, A might not be zero.


    You can set a number to be negative simply by prefixing it with a '-'.
    For example:

      set A to -123
      set B to -&7B
      set C to -%01111011

    --------------------------------------------------------------------------
    Real maths
    Logical maths

    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               R e a l   m a t h s
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Maths plays a part in all scripting when you get beyond the really basic
    things.

    Before we start, remember that "<var>" means a variable is required, and
    "<num>" means either a number OR a variable may be given.

    You have the following mathematical possibilities with the script:

    Operation                   Command(s)

    Addition

      <var> = <var> + <num>     add(<var>, <num>)

      <var> = <var> + 1         add(<var>, 1)  [see below]

      <var> = <num1> + <num2>   set <var> to <num1>
                                add(<var>, <num2>)

    Subtraction

      <var> = <var> - <num>     sub(<var>, <num>)

      <var> = <var> - 1         sub(<var>, 1)  [see below]

      <var> = <num1> - <num2>   set <var> to <num1>
                                sub(<var>, <num2>)


    As a shorthand, you can use:
          <var>++   instead of  add(<var>,1)
    and
          <var>--   instead of  sub(<var>,1)


    Multiplication

      <var> = <num1> * <num2>   mul(<var>, <num1>, <num2>)


    Division
      If output is to an integer, it is rounded down, so 3 / 2 = 1.

      <var> = <num1> / <num2>   div(<var>, <num1>, <num2>)

      To calculate a modulus:
      <var> = <num1> MOD <num2> mod(<var>, <num1>, <num2>)


    More complicated maths

      To convert a number to absolute form:
      <var> = ABS(<num>)        abs(<var>, <num>)

      To determine the sign of a number:
      <var> = SGN(<num>)        sign(<var>, <num>)
      (returns -1 for negative, 0 for 0, +1 for positive)

      Square root:
      <var> = SQR(<num>)        sqr(<var>, <num>)


    --------------------------------------------------------------------------
    Numbers
    Logical maths

    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                            L o g i c a l   m a t h s
                            ~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Logic

      <var> = <num1> AND <num2>   and(<var>, <num1>, <num2>)

      <var> = <num1> EOR <num2>   eor(<var>, <num1>, <num2>)

      <var> = NOT <num>           not(<var>, <num>)

      <var> = <num1> OR <num2>    or(<var>, <num1>, <num2>)

      <var> = <num1> << <num2>    lsl(<var>, <num1>, <num2>)

      <var> = <num1> >> <num2>    lsr(<var>, <num1>, <num2>)


    Following is a brief introduction to logic. If, however, you are familiar
    with AND and OR and the like, you can use these links.

    --------------------------------------------------------------------------
    Numbers
    Real maths

    Index

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

    A brief introduction to logic

    Logic operations are bitwise operations. That is, they do not treat a
    number as a number, they treat it as a series of bits which may be
    manipulated.

    Binary values are base two. Thus, %100110 is 32 + 4 + 2 which is 38. In
    binary, the rightmost
    number is 1, and each number to the left is twice the value of the number
    before.

    Typically, you will come across some terms, a byte and a word. The term
    byte
    is defined as being eight bits. Thus, it can have the values 0 to 255.
    Here's how...

      128 + 64 + 32 + 16 + 8 + 4 + 2 + 1

    Thus, %01011010 is 64 + 16 + 8 + 2, so %01011010 is 90.


    There is a lot of confusion as to the precise meaning of word. Usually, a
    word is the width of the data path of the processor. Early words were 16
    bits (and Acorn assembler
    supports this with the EQUW instruction), though these are now often
    referred to as half-word. Now, words are 32 bits (they used to be
    double-word, hence EQUD in Acorn assembler). No doubt in the future when
    64 or 128 bit processors are commonplace, they'll look at our 32bit word
    with affection and nostalgia. You know, remember those days when people
    actually bought MicroSoft products and didn't get instantly dismissed!
    For what it's worth, I consider a word to be 32 bits. But then, I
    pronounce ADFS as four letters, so who am I to be paid attention to? :-)


    and
      AND sets the bit if the source and the corresponding mask are both set.

        <num1 bit>    <num2 bit>    <result>
        0             0             0
        0             1             0
        1             0             0
        1             1             1

      AND is a way to constrain values to a given boundary. To take any
      number and make it a byte, simply AND with 255.


    eor
      Exclusive OR is the opposite of OR, in that the bit is set if the
      source and the mask bits are different.

        <num1 bit>    <num2 bit>    <result>
        0             0             0
        0             1             1
        1             0             1
        1             1             0


    not
      NOT simply inverts the bits.

        <num>  = %10101100 (172)
        Result = %01010011 (83)

      Note that all 32 bits will be inverted, so the number may be something
      odd (ie, NOT 1 is -2). If you are dealing with bytes, you should then
      AND the result with 255 to get the correct result, 254.


    or
      OR will set the bit if either the source OR the mask are set.

        <num1 bit>    <num2 bit>    <result>
        0             0             0
        0             1             1
        1             0             1
        1             1             1


    lsl
      Logical shift left. This shifts the bits <num> places to the left.

      For example:
        lsl(A, 12, 2)

        On entry, the bits are %00001100 (12).
        They get shifted two places to the left.
      The result, the value placed in A, is thus %00110000 (48).

      This could be used as primative (!) multiplication.


    lsr
      Logical shift right. This shifts the bits <num> places to the right.

      For example:
        lsl(A, 12, 2)

        On entry, the bits are %00001100 (12).
        They get shifted two places to the right.
      The result, the value placed in A, is thus %00000011 (3).

      This could be used as primative (!) division.

      Shifts to the right are always treated as unsigned.

    --------------------------------------------------------------------------
    Numbers
    Real maths

    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                        C a c h e   u t i l i s a t i o n
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    The script interpreter uses the cache. It ignores references to expiry
    times. If no cache is defined, you will receive a message and the script
    will not run.

    The script interpreter builds a virtual cache within your existing cache
    setup. It does this by simply setting bit 7 of the "Request count" in the
    cache index. It will ONLY respond to this bit, if set. Anything
    previously in the cache will be ignored.

    When the script is started, the cache is scanned and ALL frames with bit
    7 set are deleted.
    Any frames fetched from the script are pushed into the cache with this
    bit 7 set. Any frames required are loaded if they have bit 7 set.
    Basically, the script interpreter will not touch what is already present
    in the cache, unless it was put there by the script interpreter...

    However, the main viewer cache facility has no such discrimination, so if
    you happen to load a newer frame in a script, the viewer will recall it.

    Everything fetched is pushed to the cache.

    You need to selectframe() to reload a frame and make it current. In this
    version of the script interpreter, the last fetched frame is 'current',
    but this behaviour should not be relied upon.

    Once you have finished with the frame, if you have modified it then use
    storeframe() to write it back into the cache.

    Frames are not deleted when the script terminates, only when a new one is
    started (or your cache is expired and/or deleted by !Teletext as part of
    your normal chosen cache configuration).

    --------------------------------------------------------------------------
    Cache index format

    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                       C a c h e   i n d e x   f o r m a t
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    The cache index is a series of 20 byte entries as follows:

          Byte        0 : Channel.

          Bytes  1 -  4 : Frame and subframe number, in
                          hex.
                          If 'deleted', bytes 6-10 are zero.

          Byte        5 : Currently unused.

          Bytes  6 - 10 : RISC OS 5-byte time value when
                          frame written to cache. If bytes
                          7-10 are zero, the page is
                          flagged as to be deleted).

          Bytes 11 - 14 : Word giving offset into data file.

          Byte       15 : 128 (bit 7 set)

          Bytes 16 - 19 : Reserved for future expansion.

    This is the same as the original index, the only difference being ?15 set
    to 128.
    If you use the cache list option, then the "Rqs" column will say 128.
    This means it is a script-cached-frame.

    Everything fetched is pushed to the cache.

    --------------------------------------------------------------------------
    Cache utilisation

    Index

    Copyright  2003 Richard Murray
    ==========================================================================

                                  Teletext Script
                                  ~~~~~~~~~~~~~~~
                         C a c h e   u t i l i s a t i o n
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ------------------------------------------------------------------------

      The script interpreter uses the cache. It ignores references to expiry
      times. If no cache is defined, you will receive a message and the
      script will not run.

      The script interpreter builds a virtual cache within your existing
      cache setup. It does this by simply setting bit 7 of the "Request
      count" in the cache index. It will ONLY respond to this bit, if set.
      Anything previously in the cache will be ignored.

      When the script is started, the cache is scanned and ALL frames with
      bit 7 set are deleted.
      Any frames fetched from the script are pushed into the cache with this
      bit 7 set. Any frames required are loaded if they have bit 7 set.
      Basically, the script interpreter will not touch what is already
      present in the cache, unless it was put there by the script
      interpreter...

      However, the main viewer cache facility has no such discrimination, so
      if you happen to load a newer frame in a script, the viewer will recall
      it.

      Everything fetched is pushed to the cache.

      You need to selectframe() to reload a frame and make it current. In
      this version of the script interpreter, the last fetched frame is
      'current', but this behaviour should not be relied upon.

      Once you have finished with the frame, if you have modified it then use
      storeframe() to write it back into the cache.

      Frames are not deleted when the script terminates, only when a new one
      is started (or your cache is expired and/or deleted by !Teletext as
      part of your normal chosen cache configuration).

      ------------------------------------------------------------------------
      Cache index format

      Index

      Copyright  2003 Richard Murray
      ========================================================================





                                     i f ( )
                                     ~~~~~~~
    --------------------------------------------------------------------------

    Syntax: if( <variable> <conditional> <value> )

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

    If you have not already done so, please read the help on conditionals.



    --------------------------------------------------------------------------
    Index

    Copyright  2001 Richard Murray
    ==========================================================================


                                        ;
                                        ~
    --------------------------------------------------------------------------

    Syntax: ; <"text">

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

    The semi-colon ';' at the start of any line defines that line as a
    comment. The line is ignored.

    You could also put comments on the right hand side of executed lines, as
    the script interpreter only scans as far as it needs to.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                        .
                                        ~
    --------------------------------------------------------------------------

    Syntax: .<label name>

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

    This command defines a 'label'. A go() command later may return to this
    position.

    You can define up to sixteen branches.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                   f i n d (   )   a n d   f i n d e n d (   )
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: find( <number1>, "<string>", <number2> )
            findend( <number1>, "<string>", <number2> )

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

    <number2> specifies the line in which to search for "<string>>". If it is
    found, the offset is written to <number1>. You can then use commands such
    as readvalue() to read numerical values.

    The difference between the two is find() sets the offset to the exact
    position where the string is found. findend() sets the offset to the
    location found, plus the length of the string. This is better for finding
    values following keywords. For example:

    We are looking for "precipitation:":

      Average precipitation: 57mm

              |             |
              |             '--- findend() points here
              '-- find() points here


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               s h o w X X X (   )
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Syntax: showcachelist( )
            showcontrols( )
            showpreferred( )
            showviewer( )

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

    This opens the cache list, the control panel, the preferred pages list,
    or the viewer window. You can use some, or all, of these to open windows
    prior to terminating the script, so !Teletext pops back with the windows
    you normally have open.

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================






                    U n d o c u m e n t e d   c o m m a n d s
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    There are other several commands available which fall into the
    'undocumented'  category (shown in the main index in italics).
    These are mainly development and test commands. You can use them in this
    version of the script interpreter, though there is no guarantee they will
    be present, or the same, in other versions.

    You might think it is a bit of a weird thing to document commands and
    call them 'undocumented'. Well, originally none of these were going to be
    documented, and little of it was to remain in the parser. However I
    decided that if it is this useful to me, then maybe these commands will
    be useful to you too.

    These are the 'undocumented' commands:
      cache_flush()
        Flushes the cache, completely.


      cache_insertdirectory()
        Inserts the contents of an entire directory into the script cache.
        This command is likely to be removed from the next major release of
        the script interpreter - email me if you require it be left in.


      cache_insertfile()
        Inserts the frame specified into the script cache.


      lvar()
        Generates a report of the interpreter status and outputs it to the
        log file. If no log file is open, this command has no effect.


      report_var()
        Gives you an on-screen message informing you of the contents of a
        chosen variable.


      selfexec()
        Designed purely for the textual help, this simply calls the given
        *command, with the full filename of the currently executing script
        tacked onto the end. This is so the help can Filer_Run itself (and,
        thus, pop up in a text editor!).


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                               K n o w n   b u g s
                               ~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    At time of writing (!Teletext v1.48, 9th May 2003), the only bugs I'm
    aware of are...


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

    Script bug 001 !Teletext v1.35
    Reported by Richard Murray (support@heyrick.co.uk)
    suggested priority: Low

    In the setchar() command, the null byte macro seems to put too many
    newlines in the output file.

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

    Script bug 002 !Teletext v1.48
    Reported by Richard Murray (support@heyrick.co.uk)
    suggested priority: Medium

    Not strictly a bug... Some channels refresh each page twice, so
    getframes() does not work correctly.

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


    If you discover a possible problem, please read this to know how to
    report it to me.
    Thank you.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                       R e p o r t i n g   p r o b l e m s
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    If you encounter a problem in the script interpreter that you feel is a
    possible anomoly in the interpreter itself, than please send in a bug
    report.

    First, check the teletext website at
    http://www.heyrick.co.uk/software/ttx/ to see if a newer version of the
    software is available. If it is, maybe your problem has been corrected?
    Download the newer version and try it.

    Please try to send me an email. It may take a while (like, six months!),
    but I should eventually read it. Or, if you know my address (or somebody
    who does), you'll get quicker with the ironically-named 'snail mail'.

    When reporting a bug, please do not say something like "it crashed".
    Sadly, many people do say just that, and I have to drop such reports into
    the electronic equivalent of the wastepaper basket. There are many many
    reasons why something could 'crash'.

    Is the problem repeatable, or was it a one-off?

    If a one-off, try restarting your computer with a minimal boot (hold down
    SHIFT as it reboots) and see if it works okay then. This usually points
    to a clash with another software package, rather than a fault in the
    interpreter itself.

    If the problem was repeatable, what steps caused the problem? Can you
    provide some example code?

    How serious would you gauge the problem? A typo in a report message is
    'trivial', a total system freeze is 'extremely serious'. This helps me to
    prioritise things.

    Also, don't forget to tell me which version of !Teletext you are using.


    Note that by reporting a bug, you agree to allow me to include a bug
    report both in this documentation (if necessary) and/or on the website.
    It's basically your name and an email link (refer to bug report for an
    example.


    Please submit your bug report to support@heyrick.co.uk


    Thank you.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                 S u g g e s t i o n s   a n d   c o m m e n t s
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Feel free to email me your comments and suggestions. Anything useful will
    be taken on board for future versions. Do you have an command that can be
    implemented? Do you have an idea for expanding an existing command?


    Please send your comments and suggestions to my address. Additionally, I
    enjoy reading about things you've done with my software, or about
    different hardware you've got it running under.

    Thank you.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                      C o n t a c t   i n f o r m a t i o n
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    The !Teletext website...
        http://www.heyrick.co.uk/software/ttx/

    Email (not read very often):
        support@heyrick.co.uk


    Sorry, I don't like having my name and address publically available.

    Until the end of April 2004, you can send me post via:
        Mr. Richard T Murray
        16 Elm View
        Ash
        Aldershot
        Hampshire
        GU12 6AN

    Please write it exactly as shown, do not write 'Rick Murray'.
    I say this because the post goes through the Royal Mail International
    Redirection Service, and for some reason 'Rick Murray' was never added.
    I'd hope they consider Rick to be Richard, one and the same, but I don't
    want to trust it as any mail that isn't properly redirected will never
    reach me. Ever.


    Note, if your StrongHelp gives messages like Manual '#URL mailto:' is not
    installed, then you'll need to upgrade your version of StrongHelp.


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                       O n e   f i n a l   t h i n g . . .
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Thank you for using !Teletext, and for using my script interpreter.

    This is your host, Richard Murray, bidding you farewell.
    Until next time!


    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================


                                  P o l l i n g
                                  ~~~~~~~~~~~~~
    --------------------------------------------------------------------------

    Early versions of the script interpreter offered two modes of operation.
    The usual mode was multitasking, where the script interpreter would
    regularly poll the wimp so the system kept running fairly smoothly; or a
    singletasking mode where all wimp operations were suspended and full
    attention was given to the script.

    These systems are both inefficient. In multitasking, you can take a speed
    hit while doing things that involve a lot of repetive processing.
    Likewise with singletasking, waiting for a page to arrive is simply a
    waste of processor cycles, the script isn't doing anything and neither
    are you.

    The way around this is to allow the script to have some control over it's
    own polling rate...

    When scripts are started, they are entered in a multitasking mode. If
    this is acceptable, you need do nothing.

    Otherwise:

       poll_disable()
          Switch to singletasking mode.

       poll_enable()
          Switch back to multitasking mode.

       poll_now()
          If you are in singletasking mode and you don't want to block the
          system completely, you can poll yourself at regular points in your
          script. This command has no effect in multitasking mode.

    Additionally, you can control that little status window that pops up:

       poll_nomessages()
          Disable the output of status messages, and close the window.

       poll_message( <"message text"> )
          Output a message to the status window. If output was disabled, this
          will cause it to be re-enabled and the window reopened.


    For example:
       ; script started - multitasking mode

       ; stuff to do with frame fetching, much time is spent
       ; waiting, so we'll poll normally...
       .getframe_loop
         ...getframe...
         go(getframe_loop)

       ; now we come to do some processing, so we will jump
       ; to singletasking mode to speed it up
       poll_nomessages()
       poll_disable()

       .process_loop
         ...do stuff...
         go(process_loop)

       terminate()

    --------------------------------------------------------------------------
    Index

    Copyright  2003 Richard Murray
    ==========================================================================




                       S c r i p t   d i f f e r e n c e s
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --------------------------------------------------------------------------


    1.00 [software release 1.38]

       This version identifies itself as version '1'.

       Basic script interpreter.



    1.01 [software release 1.41]

       This version incorrectly identifies itself as version '1'.

       New commands:
         poll_disable()
         poll_enable()
         poll_now()
         poll_message()
         poll_nomessages()



    1.02 [software release 1.43]

       This version incorrectly identifies itself as version '1'.

       Bugfix:
         setchar()

       New command:
         filewritestring()



    [ the following was done after I left the UK, so releases are few and far
    between. ]



    1.03 [software version 1.44]

       This version incorrectly identifies itself as version '1'.

       Some internal modifications, a few bits recoded (optimised).
       No changes to the API.



    1.04 [software versions 1.46 and 1.47]

       Added float variables Q to Z.
       Script returns a true version now, instead of just '1'.
       go() can branch to ANY location in the script, from any location.

       New commands:
         abs()
         appendline()
         channelid()
         fileupdate()
         filewritevar()
         find()
         findend()
         flatten()
         mod()
         quit()
         readvalue()
         roundcast()
         showcachelist()
         showcontrols()
         showpreferred()
         showviewer()
         sign()
         sqr()
         userchoice()
         version() - duplicates "set <var> to status(scriptver)"



    1.05 [software version 1.48]

       New commands:
         cache_loadnextentry()
         frame_number()       - more flexible than "set <var> to
       status(pagenum)"
         frame_subnumber()    - more flexible than "set <var> to
       status(pagenum)"
         frame_language()
         frame_linkedto()



    It is recommended that all scripts begin...

      version(A)
      if (A < 105) error("Script interpreter is too old, please upgrade your
    !Teletext...")

    ...at the very least, as version 1.05 is now to be considered the 'base'
    script interpreter version to support (version 1.04 is the actual base,
    but there was no public release between 1.04 and 1.05).

    Interpreter versions prior to this should be considered obsolete.

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

    Index

    Copyright  2003 Richard Murray
    ==========================================================================
