                Tutorial for writing Special icons for Megaboard
                ------------------------------------------------
----------------
- Introduction -
----------------
This file explains in a step-by-step manner how to create a special icon that
displays the current time, it will only be of interest to programmers, other
users should refer to the "Guide" file for information on general use.
For a full technical description of special icons see the ProgGuide file.
Note: the icon defined here serves no practical use as it simply duplicates
an icon already supplied with MegaBoard, but it is a good example of a
typical special icon.

----------------------------------
- Part 1: Writing the definition -
----------------------------------
Open the !MegaBoard application directory, locate the file 'Cstm_Scrpt', and
load it into a text editor.
Now add the following command to the end of the file:

  Start_Icon

This notifies MegaBoard that an icon definition begins here. The following
lines must contain the commands descried in the 'ProgGuide' file i.e:

  Name: TutTime
To specify the name of the icon

  Purpose: Display the current time
  Author: Your Name
  Version: 0.00
These will be displayed in the special info dialogue box.

  Width: 150
This sets the initial width of the icon to 150 OS units

  Height: 40
This sets the initial height of the icon to 150 OS units

  Worksize: 1024
Reserves 1024 bytes of workspace for the icon when it is created

  Update: Second
Informs Megaboard that the icon requires updating every second

  Mouse_State: Off
  Keypress_State: Off
  Message_State: Off
  Menu_State: Off
The icon does not respond to mouse clicks, keypresses or Wimp messages and
does not have a menu associated with it.

  Start_Parameters
  Format: %z24:%mi:%se
  End_Parameters
States that the icon has one user-definable parameter called "Format" with
the default value "%z24:%mi:%se".

  End_Icon
Terminates the icon definition.

The icon definition should now look like this:
  Start_Icon
  Name: TutTime
  Purpose: Display the current time
  Author: Your Name
  Version: 0.00
  Width: 150
  Height: 40
  Worksize: 1024
  Mouse_State: Off
  Keypress_State: Off
  Message_State: Off
  Menu_State: Off
  End_Icon

Now save the file and if it is not already running, run MegaBoard. The
Special icon submenu should now contain an additional item, namely "TutTime".
DO NOT CHOOSE THIS ITEM YET!!!


-----------------------------------
- Part 2: Writing the code blocks -
-----------------------------------
The BASIC file 'Skeleton' in this directory contains the source code of a
"blank" special icon i.e. one that neither display anything nor responds to
any events. Run this file, it will save the code file in the current
directory.
Open the directory !MegaBoard.Special and create a new diretory called
"TutTime" (the same as the icon name) then locate the code file previously
saved and copy it into this direcory.
Now the icon's menu item in the 'Special icon' submenu can be chosen, but
take care to note the location of the pointer when Menu was originally
clicked or you will have difficulty locating the icon. An invisible icon will
then be placed on MegaBoard, you can verify this by dragging Seelect or
Adjust over the pointer position where menu was clicked, which should allow
the icon represented by a 'rotating dash' box to to dragged around MegaBoard.

In order for the icon to do something meaningful the relevant code blocks
will have to be written. Load the "Skeleton" file into a BASIC editor

A Code block in the skeleton file looks something like this:
  REM initialise
  EQUD init_end-P%
  MOV PC,R14
 .init_end

The file line after the REM inserts a word conatining the length of the
block. Following this is the actual code, in this case it is simply a return
instruction terminated by the label referred to in the EQUD.

1. Initialise
-------------
In our example the initialisation code must simply copy the parameter string
into the icon's own workspace, encoding is not necessary:

  .init       MOV    R7,#0          :REM set the offset to 0
  .stringloop LDRB   R6,[R5],#1     :REM load a character into R6 and
                                     REM increment R5
              STRB   R6,[R4,R7]     :REM store the character in R4+R7
              ADD    R7,R7,#1       :REM increment R7
              CMP    R6,#32         :REM check if the character was a
                                     REM terminator
              BGE    stringloop     :REM if not then copy the next character
              MOV    R6,#0          :REM replace the control terminator with
              STRB   R6,[R4,R7]     :REM a null.

Next we have to read the curent time in a 5-byte format:

   ADD    R1,R4,#256   :REM the 5 bytes are stored at workspace offset 256
   MOV    R0,#3
   STR    R0,[R1]
   MOV    R0,#14
   SWI"OS_Word"

This 5-byte time information now needs to be converted ino a string:

   MOV      R0,R1                    :REM R0 points to the 5-byte time
   ADD      R1,R0,#8                 :REM R1 points to the buffer for the
                                      REM string at workspace offset 264
                                      REM (i.e. 256+8)
   MOV      R2,#240                  :REM buffer size
   MOV      R3,R4                    :REM R3 points to the format string
   STMFD    R13!,{R0-R3}             :REM push these registers to the stack
                                     :REM because we need them later
   SWI      "XOS_ConvertDateAndTime" :REM do not generate errors

If OS_ConvertDateAndTime detected an error in the format string it will
return with the V flag set this must now be checked for and handled. If an
error occurred the time and format strings will be replaced with the word
"ERROR".

   MOV     R5,R0             :REM these registers will be needed if there was
   MOV     R6,R1             :REM no error
   LDMFD   R13!,{R0-R3}      :REM pull the registers from the stack that were
                              REM stored above.

   REM the following is only executed if there was an error
   LDRVS   R2,error1         :REM load the first 4 bytes of the word "ERROR"
                              REM into R2
   STRVS   R2,[R1]           :REM replace both the format string and the time
   STRVS   R2,[R3]           :REM string with the word "ERROR"
   LDRVS   R2,error2         :REM copy the second
   STRVS   R2,[R1,#4]        :REM 4 bytes
   STRVS   R2,[R3,#4]        :REM (actually only 2)
   SUBVC   R1,R6,R5          :REM if there was no error set R1 to the length
                              REM of the time string +1
   MOVVS   R1,#6             :REM if there was an error set R1 to the length
                              REM of "ERROR" +1 i.e. 6

Finally BASIC's C% variable must be modifed to the width of the of the string
in OS units.

          SUB    R1,R1,#1        :REM subtract 1 from R1 to obtain the number
                                  REM of characters
          MOV R1,R1,LSL# 4       :REM multiply R1 by 16 (the width of system
                                  REM font text under the WIMP.
          STR R1,pointer_stuff-8 :REM use it as the new icon width
          MOV PC,R14             :REM return


This code should be entered between the "EQUD init_end-P%" and the
".init_end" label.

2. Null
-------
This entry point simply reads the current time then converts it to a string
using the stored format string:

   .null ADD   R1,R4,#256           :REM read the
         MOV   R0,#3                :REM current time
         STR   R0,[R1]              :REM and store it
         MOV   R0,#14               :REM at workspace
         SWI   "OS_Word"            :REM offset 256

         MOV R0,R1                  :REM and
         ADD R1,R0,#8               :REM convert
         MOV R2,#248                :REM it
         MOV R3,R4                  :REM to
         SWI"OS_ConvertDateAndTime" :REM a string

         MOV PC,R14                 :REM return to BASIC

3. Redraw
---------
Here it is first necessary to move the cursor to
[x_coord-icon_width/2,ycoord-icon_height/2+36]:

   SUB R3,R1,R3,LSR #1  :REM subtract half the icon height from the Y
                         REM coordinate and store the result in R3
   ADD R3,R3,#36        :REM add 36 to this value
   SUB R1,R0,R2,LSR #1  :REM subtract half the icon width from the X
                         REM coordinate and store the result in R1
   MOV R2,R3            :REM copy the calculated Y coordinate into R2
   MOV R0,#68           :REM plot code 68 to move cursor
   SWI "OS_Plot"        :REM execute the move

Next the colour must be set to black:

   MOV R5,R4                  :REM copy the workspace pointer to R5 as it is
                               REM needed later
   MOV R0,#0                  :REM the palette entry for black
   MOV R3,#0                  :REM flags all 0
   MOV R4,#0                  :REM GCOL action 0
   SWI "ColourTrans_SetGCOL"  :REM set the colour

4. Finish
---------
This entry point can be left empty, there is no finishing up necessary.

5. Save
-------
The only string that needs saving is the unencoded format string but first
the header "1: " must be output:

                MOV R1,R5           :REM copy the file handle to R1
                ADR R2,header       :REM point R2 at the header
  .save_loop1   LDRB R0,[R2],#1     :REM load a character
                CMP R0,#32          :REM check if it's a terminator
                SWIGE "OS_BPut"     :REM if not ouput it to the file
                BGE save_loop1      :REM then get the next character

Now we can output the format string:

  .save_loop2   LDRB R0,[R4],#1     :REM load a character and increment R4
                CMP R0,#32          :REM check if it's a terminator
                MOVLT R0,#10        :REM if it is output a newline instead
                SWI "OS_BPut"       :REM output the character
                BGE save_loop2      :REM if it was not a terminator then get
                                     REM the next character

One parameter has been saved, so the ntry returns with a R0 set to 0

                MOV    R0,#1
                MOV    PC,R14

  .header       EQUS "  1: "+CHR$(0):ALIGN

5. Load
-------
As only one parameter was saved, load will only be called once. All that has
to be done is to copy that string to the icon's workspace:

                MOV     R1,R4        :REM Copy R4 to R1 as it is needed later
  .load_loop    LDRB    R0,[R6],#1   :REM load the first character into R0
                                      REM and increment R6
                CMP     R0,#32       :REM check if it's a terminator
                MOVLT   R0,#0        :REM if it is replace it with a null
                STRB    R0,[R1],#1   :REM store the character and increment
                                      REM R1
                BGE     load_loop    :REM if it was not a termintor get the
                                      REM next character

Immediately after this call redraw will be called, however there will not
be a valid time string in the buffer for it to display, therefore one must
be generated here, this is achieved by simply calling null.

   STMFD     R13!,{R14}  :REM push R14 as the BL instruction will corrupt it
   BL        null        :REM call null
   LDMFD     R13!,{PC}   :REM return to BASIC



All other entry points can remain empty.

Once these code segments have been entered into the skeleton file run it
again and copy the created code file into the TutTime directory as described
above. The special icon is now complete and can be placed on MegaBoard just
like the ones provided with the package.
