-------------------------------------------------------------------------------
History
=======

NB Don't forget to keep the 'Notes' version of this file updated in parallel!

03/10/97 (ADH): Created from programmer notes file.

14/10/97 (ADH): Ready for CVS.

04/12/97 (ADH): Put in information on using a local proxy server as a cache
                (i.e. basically controlling WebServe from the browser!) and
                added to the descriptions of keyboard modifiers.
-------------------------------------------------------------------------------

Contents
========

Multiple application name support - system variable dependencies
Other system variables

Using a local proxy server as a cache

User interface features: Toolbars
  Merging toolbars - an overview
  Operational 'modes'
  Dialler display
  Merged URL writable and status display
  Menu items
User interface features: Keyboard modifiers
  Mouse clicks with Shift held down
  Mouse clicks with Control held down
User interface features: Save dialogues
  Save File
  Save Object
User interface features: Icon scripting

External control of the browser
  Starting with a given URL
  Remote hotlists
  Home page


Multiple application name support - system variable dependencies
================================================================

When the browser starts, it reads where it ran from using argv[0]. This means that the actual application name is not important. However, the !Run file *must* execute !RunImage, and not any other binary name. For ROM builds, though, the assumption of 'Resources:$.Resources.Browse' pointing to the resources directory has to be made.

The cases of special system variables - e.g. to point to an alternative choices or controls file, etc. - is a tricky one. In the end, some have to maintain the same name - so they'll be Browse$... regardless of the application name. These are:

Variable name                When it/they is/are used

Browse$IssueDesktopCommand   On startup only, for AcornURI or TaskModule.

Browse$CurrentPage,          Set for every fetch, read only as part of
Browse$CurrentFetch,         post-crash recovery when restarted with an
Browse$PreviousPage          appropriate internal URL.

Browse$CookieFile            The HTTP module uses this, which if set, and a
                             cookie file cannot be found in
                             Choices:WWW.AcornHTTP.Cookies, will be used to
                             load a cookie file.

Browse$CookieFileFormat      HTTP module again; takes '1' or '2', defaults
                             to '2' and best left unset.

Browse$AcceptAllCookies      'on' or 'off', if 'off' the browser is required
                             to notice when cookies are in the pending
                             queue and tell the HTTP module to accept them
                             (perhaps with user intervention). At present,
                             best set to 'on'. It is, once more, the HTTP
                             module that reads this.

Others are prefixed by the application name ('_TaskName' token in the Messages file). These are:

Variable name                When it/they is/are used

<App>$HotlistURL,            Used only if set, to override Choices. The first
<App>$HotlistURIFile;        in the pair is tried to get a URL to fetch a
<App>$HomeURL,               hotlist (REMOTE_HOTLIST builds only) or find the
<App>$HomeURIFile            home page URL; if this is unset, the second is
                             tried to get to a URI file containing the same
                             information. If neither exist, the relevant
                             Choices entry is used instead. These are
                             described in more detail later.

<App>$ChoicesFile,           Used to load Choices or Controls if set, else
<App>$ControlsFile           if unset, use <from argv[0]>.[name].

<App>$ChoicesSave,           Used to save Choices or Controls if set, else
<App>$ControlsSave           if unset, use <from argv[0]>.[name].

So it is safe to have Browse$Dir and Browse$Path unset (or used under a different name), but other variables are needed / will be set as described above. If you do this, though, don't forget to alter any Messages, Controls or Choices entries which might describe paths with those variables (e.g. Hotlist or History file locations), and things such as the IconBar object in the Res file, which may reference !browse as a sprite.


Other system variables
======================

The primary scrap file is Wimp$Scrap (can be changed at compile-time).

Alias$@RunType_FFF is used, if set, to launch an external editor to view document source, if one isn't already running. This can be unset without anything bad happening.

Alias$@PrintType_FF4 must be set for printing to work correctly on RISC OS 3.1 or higher.

The browser will of course load a variety of file formats, and the relevant Alias$@RunType_xxx variables may be set or left alone as required. Files that may be loaded by double-click are URI (0xf91), HTML (0xfaf), GIF (0x695), JPEG (0xc85), PNG (0xb60), and TIFF (0xff0). Text (0xfff) and URL files (0xb28 - from the ANT suite) can be loaded by dragging to the browser. Setting an Alias$@RunType_B28 for URL files will work; setting an Alias$@RunType_FFF for Text files will cause big problems with the View Source button, for obvious reasons. Recommended settings are just for HTML and URI files (the latter being used only if the URI handler module is not present).


Using a local proxy server as a cache
=====================================

The browser has no local cache in the conventional sense. It instead relies on a local server of some kind to cache for it - the browser is set to proxy to http://127.0.0.1/ (say) and cacheing is done there. This arises originally from its multiuser history, where the proxy server (aka cache) may reside on a central server on the local network, which several clients access. It so happens that this behaviour is also useful for Plug-ins, which can use the same server as a cache - this saves each component implementing a cache independently.

The browser has been designed towards a proxy server called WebServe, and in the absence of the various Messages file tokens described below will default to values suitable for this software. Later versions of WebServe (v0.33 upwards) have the capability to turn on and off their icon bar icon and respond to message Wimp_MAppControl (21) with a reason code of 4 (Wimp_MAppControl_Configure), opening the WebServe configuration dialogue if it is received. The browser can send this message to the server.

The server task name is held in the Messages file, as token 'ProxyName'. This is used by the browser to obtain the task handle of the server (or determine that it is not running). To send the message, raise event 0x10005, or a generic Menu_Selection event from component ID 0x10005. This means a menu item 0x10005 may exist which raises a default event *or* event 0x10005, or alternatively some button may raise the custom event, etc. This is an example of a case where a generic event may be used, but the definition of a custom event increases flexibility considerably. At present, the browser will grey or ungrey menu item component 0x10005 in a menu which raises event 0x101ff before being shown (these numbers are all in the icon bar (main) menu numberspace - see later) depending on whether or not the proxy server seems to be running.

A menu item can thus be used within the browser that seamlessly opens the proxy server's configuration dialogue. Since WebServe may be configured not to show an icon bar icon, WebServe can start up with no icon bar presence and be controlled through the browser, allowing the local proxy server to appear as part of the browser itself. The browser thus seems to have an inbuilt local cache from the user perspective.

As part of this, the Choices file item 'StartProxy' may be set to 'yes'. In this case, if the local proxy server does not seem to be running, the browser will issue a Wimp_StartTask SWI pointing to a command described in the Messages file as token 'ProxyComm' on startup. Errors directly returning from the SWI are not reported but the command itself may of course report an error. The browser may thus automatically start a local proxy server if one is not running already. This behaviour is not really useful for multiuser environments, where the proxy would normally be running continuously on a remote machine.


User interface features: Toolbars
=================================

The browser toollbars are highly configurable, operating as two split bars at the top and bottom of the window or one merged bar at the top. You can also swap the bars around, so that the toolbar at the top of the window goes to the bottom and vice versa. Only a limited control is available at run-time, though different operational modes are permitted in different windows running under the same browser. This is how the 'small fetch' windows for saving out objects with a Shift+Click on a link work - they are browsers with one merged toolbar, to allow the fetch status to sit alongside a stop button.

This section first describes the merged modes (one toolbar holding everything) in overview form, then describes all possible toolbar modes in detail. There then follows a description of more subtle controls that are available.


* Merging toolbars - an overview
  ------------------------------

The browser's normal operational mode is to have an upper and a lower toolbar present. The upper toolbar contains a URL writable, a history menu, a series of buttons and possibly a dialler display; the lower toolbar holds an animation, a status display and a byte counter.

The upper toolbar can be notionally split into a button bar and URL bar. This gives the user the impression of three toolbars, which may be freely switched on and off if the relevant menu items are present in the Res file (see below). This is *not* the same as actually deleting toolbars. The toolbar heights are notionally set by invisible gadgets placed on the bars marking the extent of the bars. The URL bar height is defined by component 0x300 (URLBarSpacer), the button bar height by 0x100 (ButtonBarSpacer), and the status bar height by 0x500 (StatusBarSpacer). The URL bar and button bar markers may overlap to define a commonly visible region between the two (usually for aesthetics). These may be seen in ResEd by selecting all items in the toolbar - the red bounding boxes will highlight where the spacing gadgets are.

Either toolbar may be deleted, remembering to change the attached toolbar settings of the main Browser object to account for the deletion, with this action allowing certain items to be merged into dual action gadgets. This is described further below. At present, a merged toolbar may not be turned off either partially or in full, and only the height marker with component ID 0x300 (URLBarSpacer) is required.

Where references are made to components in upper or lower toolbars, this implicitly means whatever toolbar components are visible when the toolbars are merged.


* Operational 'modes'
  -------------------

1   Normal
2   Reversed
3   Merged upper
4   Merged lower

What they mean and required state of Controls file 'SwapBars' entry:

1   Combined URL/Button bar at top, status bar at bottom   SwapBars=no
2   Combined URL/Button bar at bottom, status bar at top   SwapBars=yes
3   Combined URL/Button/Status bar at top                  SwapBars=no
4   Combined URL/Button/Status bar at bottom               SwapBars=no

To fix the size of a normal or reversed toolbar (1, 2):

    URL bar height by URLBarSpacer (0x300)
    Button bar height by ButtonBarSpacer (0x100) (may overlap URLSpacer)
    Status bar height by StatusBarSpacer (0x500)

To fix the size of a merged upper toolbar (3):

    Whole bar height by URLBarSpacer (0x300)

To fix the size of a merged lower toolbar (4):

    Whole bar height by URLBarSpacer (0x500)

To turn toolbars on/off for normal or reversed toolbar (1, 2):

    Three menu entries for URL, button and status bar
    Component IDs 0x11601, 0x11602 and 0x11603 respectively
    (UtilsURLBar, UtilsButtonBar, UtilsStatusBar)
    Makes assumption that URL and button bars are merged into one. The
        URL bar should be above the button bar; the height and overlap
        of the two is indicated by the components as described above
    The status bar should be a separate item

To turn toolbars on/off for a merged upper toolbar (3):

    Only one menu entry, no assumptions made about toolbar layout
    Component ID 0x11601 (UtilsURLBar)

To turn toolbars on/off for a merged lower toolbar (4);

    Only one menu entry, no assumptions made about toolbar layout
    Component ID 0x11603 (UtilsStatusBar)

Note that a merged toolbar is expected to have a URL writable, though it doesn't have to have any buttons. Small fetch windows, which effectively (usually) have a status line with a stop button merged in, will need to have such a gadget moved out of the visible area on the page. Note also that the Choices file MoveGadgets item is ignored for small fetch windows - nothing is ever moved (as it is assumed that the windows cannot resize).


* Dialler display
  ---------------

If the dialler display field (component ID 0x204, URLBarDiallerStatus) is present in the upper toolbar, it will be used to report the dialler status (provided the dialler module is loaded, of course). It may have an associated border / cover gadget with ID 0x206 (URLBarDiallerStatusCover) and a label 0x205 (URLBarDiallerStatusLabel). The label will have two states to indicate that the associated display is showing dialler status or online time.


* Merged URL writable and status display
  --------------------------------------

If the toolbars are merged, and the URL writable and status bar status display may be merged. To do this, place one exactly over the other. The default state will be to show the status display; clicking on this (or generating event 0xd, EButtonBarGoTo) will swap this to a writable, allowing entry of a URL. Pressing Return (or generating event 0xe, EButtonBarGo) accepts this URL, changes back to a status display and starts a fetch. Generating event 0xf (EButtonBarCancel) cancels the changes and changes back to a status display, without interrupting any current fetch, format or other activity.


* Menu items
  ----------

Certain menu items may instruct the browser to show or hide toolbars as mentioned in the overview. They should be present in a menu which, before being shown, raises event 0x1201 - this queues the browser to tick or untick items in the menu before showing it.

To turn the URL bar on and off, include component 0x11601 (UtilsURLBar).
To turn the button bar on and off, include component 0x11602 (UtilsButtonBar).
To turn the status bar on and off, include component 0x11603 (UtilsStatusBar).

Note that the page display controls (Underline Links, Use Document's Colours, Show Foreground Images, Show Background Images) and the Full Screen control also expect to be in a menu raising event 0x117ff (EUtilsToBeShown) for the same reason as the toolbar controls - ticking of items. However, because the browser is tolerant (in non-TRACE builds) of items being missing in menus, it is quite possible to have these in two separate menus both raising the event, or grouped in one menu.


User interface features: Menu items
===================================

Menu items that define options, such as turning on or off tool bars or toggling page display options, may be deleted (the application will still try to set ticks in them if the submenu they used to be in is opened, but will fail silently).


User interface features: Keyboard modifiers
===========================================

In all cases below, there may be build-local restrictions. For example, a Full Screen browser will not be allowed to conduct external object fetches - it will raise an error explaining this. After all, on a STB-like device, having a little save dialogue pop up when you've got (conceptually) no storage devices or Filer interface to access them does not make a good UI!


* Mouse clicks with Shift held down
  ---------------------------------

On any link, open that link into a save dialogue. This may be done in new windows for multiple concurrent saves by adjust-clicking. If the Choices file item 'UseSmall' is set to 'yes', then any Shift+Click will open a small fetch window and the fetching will go into there, regardless of mouse button used.

Shift+Click on a browser window's toggle size icon will open the window to full size but not obscure the icon bar (or rather, do the reverse of whatever bit 4 of CMOS byte 28 says), as is the expected behaviour under RISC OS.


* Mouse clicks with Control held down
  -----------------------------------

On any image (link or otherwise), show that particular image. This forces the image to override any flags saying images should be hidden. Unfetched images will be fetched by this. (Shift used to give this behaviour, before it was reassigned as above).

Ctrl+Click on a toggle size icon of a browser window will open it to full height, but not full width, with Shift modifying whether or not it obscures the icon bar (as described above).


User interface features: Save dialogues
=======================================


* Save File
  ---------

The Save File dialogue is set to raise event 0x13ff (ESaveFileToBeShown) before it opens. Only one dialogue can be visible at a time (in the Res file, the object has its 'shared object' bit set, and the code assumes that this will always be the case); so no event is raised when closing - there is no need to deregister event handlers and so-forth.

When ESaveFileToBeShown is raised, the saveobject_to_be_shown function will fill in the contents of the dialogue in an appropriate fashion automatically. To do this, it has to know certain methods of generation. First, it expects to have an ancestor ID. This should point to a browser or hotlist window. If a browser window, the component ID of the menu entry generating the item is looked at. This will be (from Save.h):

FileSaveFrame            Save this frame as HTML
FileSaveParent           Save the parent frameset as HTML
FileSaveCurrentLocation  Save the current page location as a URI file
HotlistSaveHotlist       Save the hotlist
MiscHotlistSaveObject    Save an object from the hotlist (URI file, selection, directory)
ExportAsDraw             Export the page as a Drawfile
ExportAsText             Export the page as text
ExportLink               Export the link contents as a URI file
ExportPicture            Export the image as a sprite
ExportBackground         Export background image as a sprite

The use of component IDs rather than menu object IDs allows the various options to migrate around the menu structure. Export items could all be in a different menu, or the same menu, as the HTML save items, for example. The browser window Hotlist submenu can hold a 'Save hotlist' item, or the main hotlist menu could hold it. And so-on.

If a parent component ID of -1 is encountered, then FileSaveFrame is assumed. The ancestor object is used for the source, but if this shows there is a currently selected frame, then that will be used instead.


* Save Object
  -----------

This dialogue can exist many times; browser_data structures keep track of whether a dialogue is open for them. These are used entirely for spooling data to disc from a remote source (i.e. through the fetcher). The code is not intended to be especially extensible.

The dialogue raises event 0x15ff (ESaveObjectToBeShown) when it opens. It raises no event when closed, as it should not be opened in a transient form and the code should therefore have full control of when it does close. Appropriate action can therefore be taken directly.


User interface features: Icon scripting
=======================================

To support unusual user interface designs, and given that the Toolbox restricts the 'look and feel' of various items, it is possible for icons which take text values to have 'scripts' (a bit of a grand word for what this actually is) placed in them.

Scripts allow you to change certain icon flags for that icon. So, for example, a display field could be made to be borderless, white, with black text; a writable icon could me made to be borderless, white, with blue text.

Scripts must start with '@!', to make the chances of clashing with regular text negligable. There then follow, directly, comma separated command letters, some of which take single byte, upper case hex digit parameters. These are:

Command   What it changes

N         No border (forces no border for the icon)
H         Has border (forces a border for the icon)
B         Background colour (follow by Wimp colour, 0-9 and A-F)
F         Foreground colour (follow by Wimp colour, 0-9 and A-F)
C         Click (button) type (follow by button type number, 0-9 and A-F)

If an unrecognised command letter is met, it is skipped. The routine continues if, after reading a letter and possibly a command, if finds a comma; otherwise, it exists. It is this possible to follow a command directly with text of any sort, provided that text does not start with a comma. Note that incorrectly formatted script strings will give undefined results... Here are some examples:

Script         Action

@!N,B0,F8      No border, white background, blue foreground
@!H,B1,FF,C1   Has border, light grey background, cyan foreground, button
               type set to 'always' (1).
@!NHello       No border, and text seen by user will be 'Hello'.

The browser automatically scans for these strings in certain icons and removes the scripting text before showing the dialogue. The dialler status display, URL bar writable, main status display, Save File dialogue writable, Save Object dialogue writable, Open URL dialogue writable and Find dialogue writable fields are all scanned. The number range gadgets in the Print dialogue cannot take anything except numbers, but they can have scripts specified in the Controls file (see the AlterNumRanges and AlterWith entries).


External control of the browser
===============================

In the following, there are references to HTML files (which are obvious) and URI files. URI files are dealt with by the Acorn URI handler module or the browser - the former does not have to be present, but if it is, other applications may pick up URI files and either deal with them or modify the contents before passing them on. This, then, allows such things as mailto: to work, even though the browser does not handle such URIs itself. A description of the URI handler and the URI file format is in document 1307,206/FS (see the Acorn FTP site).Double-clicking on a URI file will always go through the URI handler, not the browser. If the browser is started without the URI handler, however, it will handle double-click events itself.


* Starting with a given URL
  -------------------------

The browser will normally start and install itself on the icon bar. No window will be opened until the user initiates this by actions defined through the Res file. To start the browser and open a window with a given URL in it, there are the following facilities:

1. A command line parameter '-url' followed by a single space and a URL
   to open.

2. A command line parameter '-html' followed by a RISC OS pathname pointing
   to an HTML file to load from local store.

3. A command line parameter '-uri' followed by a RISC OS pathname pointing
   to a URI file to read from local store.

URI and HTML files may be dragged to the icon bar icon, or to a browser window (where they will be loaded into a new window or the window they were dragged to respectively), or can be activated by double-clicking on them (in which case a new window is always opened, with the possible intervention of the URI handler for URI files, as described above).


* Remote hotlists
  ---------------

When the View Hotlist button (component ID 0x6, generating event 0x206, residing in the upper toolbar or a merged toolbar) is activated, the hotlist window is opened. Alternatively, on REMOTE_HOTLIST builds, the hotlist code (which is quite large) is not compiled in. Instead, the hotlist is fetched as an HTML file to be displayed in the browser window containing the button that was activated.

The URL used for this fetch is obtained in three ways:

1. If a system variable 'Browse$HotlistURL' is defined, this is expanded
   and the value within used as the URL to fetch (so it must contain a
   fully specified valid URL).

2. Failing that, if a system variable 'Browse$HotlistURIFile' is defined,
   this will be taken to hold a pathname of a URI file. This variable may
   itself include variable references, e.g. 'HotlistPath:URIfile', to
   allow a search path for the hotlist file if its local location is
   likely to change.

   If this file is not found, the browser will open with no URL (i.e. it
   fails silently).

3. If neither variable is defined, the token 'HotlistPath' is looked up in
   the Choices file. This is taken to contain a RISC OS pathname specifying
   a local HTML file. The pathname is converted to a URL for the File
   module to fetch through, so there are limitations on what may be used
   here; for example, '<Browse$Dir>.User.Hotlist' would fail due to the use
   of angle brackets, but 'BrowseUser:Hotlist' (referencing the variable
   'BrowseUser$Path', equivalent to '<Browse$Dir>.User.'), would work.
   This token must exist in the Choices file, or an error will be raised.


* Home page
  ---------

When a new window is opened, in the absence of any other action (see above) the following scheme is used to determine the starting URL to display in the window - this is very similar to the remote hotlist system described above:

1. If the system variable 'Browse$HomeURL' is defined, this is expanded and
   the URL contained with used for the fetch.

2. Failing that, the system variable 'Browse$HomeURIFile' is examined. It
   will be expanded if defined and taken to hold a pathname pointing to a
   URI file with the hotlist URL inside it. If this file is not found, the
   browser will open with no URL (i.e. a blank window).

3. Lastly, the token 'HomePage' is looked up in the Choices file. This
   should hold a fully specified URL for the home page (rather than, for
   example, a RISC OS path for a local file, as with the third method of
   finding the Hotlist file as described above). Again, this token must
   exist in the Choices file, or an error will be raised.