------------------------------------------------------------------------------- History ======= NB Don't forget to keep the 'User' version of this file updated in parallel! 02/09/97 (ADH): Created and regularly maintained. 03/09/97 (ADH): Restructured a bit, added Contents; introduction renamed to Overview, to match other documentation. 05/09/97 (ADH): Merged in some UI stuff from the another UI notes file. 18/09/97 (ADH): Event code and component ID names and numbers updated to match new name and numberspacing scheme. This does mean that some sections in this document are now reduced to little more than repeated 'read the header file' statements...! Split off the Scratchpad to a separate file. Saving and loading section made much simpler; refers to PRMs and recommended source file starting points. 26/09/97 (ADH): Added 'Choices' and 'Controls' file location information. 11/11/97 (ADH): Added 'Key code behaviour' section. 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. 13/01/98 (ADH): ARROWS_MOVE_OUT compile time option for Forms.c mentioned. ------------------------------------------------------------------------------- Contents ======== Overview Key notes for coders (very important) Documentation Hard coded limits Compile-time options Lines and chunks - referencing Tying up loose ends Debugging Key code behaviour Multiple application name support - system variable dependencies Other system variables Choices file Entries in the user choices structure 'choices' Entries to read straight from the file or a dialogue box Controls file Entries in the fixed choices structure 'controls' Entries to read straight from the file or a dialogue box Component and event code numberspaces Miscellaneous Toolbars (Toolbars.h) Menus (TBEvents.h, Save.h) Save Object dialogue (SaveObject.h) Save File dialogue (SaveFile.h) Print Style dialogue (PrintStyle.h) Open URL writable (OpenURL.h) The Hotlist (Hotlist.h) Find dialogue (Find.h) Authorisation dialogue (Authorise.h) Debug functions 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 Saving and loading Saving Loading External control of the browser Starting with a given URL Remote hotlists Home page Overview ======== This file contains various general notes about the browser. If anything gets coded that seems obscure or puts some important restriction on something else, it should be mentioned here. Other notes include information on the user interface controls and so forth, and these will probably get split to another file at some stage. The text is designed for a dynamic wrap width. Most of it needs only 79 characters or greater, but some needs a wider display and mentions when this is the case. Key notes for coders (very important) ===================================== * Documentation ------------- All comments and related text files (such as this one) must be kept up to date! It is a fairly arduous task, but without doubt the best approach is to always modify as required at the moment an affecting change is made. Never let this sort of thing build up over time... * Hard coded limits ----------------- Coders must be aware that when using any predefined limits from Limits.h, all attempts must be made to ensure buffers currently flagged as (S)afe remain so. If existing (U)nsafe / (P)artly unsafe buffers can be made safe, that's great. For items where this (D)oesn't matter, it is desirable to leave things that way! * Compile-time options -------------------- If altering #defined values inside the compiler options, you *must* then recompile the whole project. Global options (some of which are not fully implemented) currently are: #define name Function ROM The ROM build !Mkxxxx files use this. TRACE Enable general debugging. STRICT_PARSER Gives more warnings at parse time. ALIAS_URLS E.g. instead of file://...hotlist, just say 'Hotlist'. HIDE_CGI Don't show the info after a '?' in URL displays. ANTI_TWITTER Use software anti-twitter. REMOTE_HOTLIST Use HTML files fetched to the page for hotlists, rather than compiling in the whole hotlist manager. CUSTOMER_SPECIAL Include hard coded JavaScript for www.customer.net. UNIFONT Multilingual support. Local options, for which only the mentioned files need recompiling, are: #define name Source file(s) Function DUMP_HEADERS FetchHTML.c Dump HTTP headers. URLveneer.c INCLUDE_HEAPGRAPH Main.c Allow heap graphing. INCLUDE_HIERPROF Main.c Allow hierarchical profiling. INCLUDE_MEMCHECK Main.c Allow memory checking. TRACE_FETCH_STORE Images.c Look at data as it is fetched. USE_TML svcprint.c See 'Debugging' below. ARROWS_MOVE_OUT Forms.c Up/Down arrows jump out of forms fields. * Lines and chunks - referencing ------------------------------ Lines are referenced only by number, as an array - as in ldata[number]. Line numbers start at 0 and go to nlines - 1. Lines do not contain a base chunk address, but a base array offset into the chunks. Array indices thus go from ldata[l].chunk to ldata[l].chunks + ldata[l].n - 1. Chunks are referenced only by number, and through cdata[number]. Numbers are between 0 and nchunks - 1. nchunks can only be worked out by looking at the last line that has some chunks, and doing ldata[lastline].chunks + ldata[lastline].n. (So this gets the number of chunks - subtract one to get the last chunk number). * Tying up loose ends ------------------- One method of tying up the many loose ends is to look for '//' comments. Keeping to this syntax - use '/* */' pairs for normal comments, use '//' comments for anything that needs further attention - is probably a good idea. * Debugging --------- In TRACE builds, a variety of four letter codes can be specified in a comma separated, case sensitive list after a '-debug' (or '-d' for short) command line parameter, usually placed in the browser !Run file. A summary of these codes is at the top of Global.c. New general areas of code which could require separate debugging should define the next logical code in the sequence, adding the appropriate recognition code to main() in Main.c, documenting the facility in Global.c, and wrapping all debug output in something like: #ifdef TRACE /* (At the time of writing, 29 is the next available */ /* trace level bit). */ if (tl & (1u<<29)) { ... } #endif The standard browser debugging runs through svcprint.c - i.e. uses a TML card (hardware) output to a second terminal with a similar card. It is possible to alter the appropriate compile-time option inside svcprint.c and change this to output to Pipe:$.TMLDebug, which can then be listed in a Task Window whilst the browser runs with something like: *Basic REPEAT:OSCLI "Type Pipe:$.TMLDebug":UNTIL FALSE The loop is needed as the PipeFS file is opened before, and closed after, writing any piece of debug information, so if the Task Window finishes listing the contents at a point where the file is closed it would stop there and PipeFS would remove the file. This is obviously quite slow, so it's also possible to output to Devices:Parallel by altering line 332 of the code. A second machine connected to the main station with a parallel cable can then be used to dump the information, and is somewhat faster than the PipeFS method, though even more prone to lock-up if one end sends whilst the other isn't listening (or vice versa) than TML cards themselves. Use a program such as: 10 MODE 31 20 x%=OPENIN("Devices:Parallel") 30 IF x%=0 THEN END 40 REPEAT 50 a%=BGET#x% 60 IF a%=10 OR a%=13 PRINT ELSE PRINT CHR$(a%); 70 UNTIL FALSE Be careful to run this *before* starting the other end with the browser. The debug function Printf is used to output to TML, which behaves syntactically just like printf, though fewer format specifiers are supported. In particular, %d will only output an int as unsigned. The PipeFS or Parallel debug methods discussed above use vfprintf, and thus support the full range of specifiers - this can be handy now and again even if you have a pair of TML cards. Colour output can be achieved by sending BBC-style VDU codes: Printf("This is in \0212Green, \0211Red, and \0217white.\n"); Of course, the actual colours depend on the palette of the debug station, though the existing browser debug routines expect a standard BBC-style 16 colour palette (so run TML debug out of a Task Window and the Desktop in, say, mode 31 - 800x600x16). * Key code behaviour ------------------ Certain behavioural aspects of various code components are relied upon throughout the browser code. There are probably more than listed here, but off the top of my head: 1. When a new browser is created, any caller who knows that the function called will lead to this result may rely on the global 'last_browser' pointing to the new item. 2. When lookup_token or related functions are called, the global buffer 'tokens' is always used. The return value from the functions will always point here and is bordering on deprecated. I may well go through all of the code and remove this assumption though, as clearly using the return value is the approach which *should* be taken, rather than relying on 'tokens' (also allows more rational signaling of a failed lookup). 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. Note, though, that some trace functions may rely on Browse$Dir (see 'Other system variables'). 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, which may reference !browse as a sprite. Other system variables ====================== The scrap file is defined in Save.h (usually, for Wimp$Scrap, but this can, then, be changed, even though it does require recompilation). The DUMP_HEADERS trace build option is hard coded to scrap; specifically, '<Wimp$ScrapDir>.Headers'. 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 'svcprint.c' function can be switched to a mode where PipeFS is used for output - slow, but can be useful if you don't have a TML card and really need the debug output. This is hard coded to 'Pipe:$.TMLDebug'. For the token dump functions in Trace.c, '<Browse$Dir>.Tokens-L' and '<Browse$Dir>.Tokens-S' are used for the by-line and by-stream token dumps respectively. This is #defined in the source, so it is easily changed for an unusually named trace build, if absolutely required. 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). Choices file ============ * Entries in the user choices structure 'choices' ----------------------------------------------- HomePage BackColour TextColour LinkColour UsedColour FollColour SeleColour FontSize SystemFont Encoding UnderlineLinks UseSourceCols ShowForeground ShowBackground LeftMargin RightMargin QuoteMargin Leading LeftIndent MaxImages ClientPull SaveHotlist AddHotlist HotlistType AutoOpenDelay AutoScrollDelay AutoScrollMargin GHistSize VHistSize ShowURLs SaveHistory URLbar ButtonBar StatusBar MoveGadgets Width Height OverrideX OverrideY SolidResize FullScreen HScroll VScroll RefoWait RefoHang RefoTime FixedPtr HighlightLks KeyboardCtl Clone UseProxy * Entries to read straight from the file or a dialogue ---------------------------------------------------- HotlistPath HistoryPath PrintCopies \ PrintStart | PrintEnd | Read by the Print dialogue PrintReform | PrintOrient / PrintBack \ Read by the Print Style dialogue PrintBlack / PrintPlain - Read by Print for Print Style PostIn [not implemented] PostOut [not implemented] Controls file ============= * Entries in the fixed choices structure 'controls' ------------------------------------------------- AnimSpeed AnimDrift DBoxAnims MinConvergence DontGrey SwapBars BackWindow ClaimHelp ShowHelpFor ShowDStatFor ShowLinksFor ShowMiscFor Quantise ProgressDelay AppendStatus UseBrackets ColourProgress MinFrmHeight MinFrmWidth KeepHighlight KeepCaret ClearFirst LockToLine IgnoreAdjust AppendURLs BrickWall StopWebServ BackOffAt [not implemented, but has entry] PtrLnkActvX PtrLnkActvY PtrMapActvX PtrMapActvY PtrUDActvX PtrUDActvY PtrLRActvX PtrLRActvY PtrUDLRActvX PtrUDLRActvY PtrNoRActvX PtrNoRActvY PtrToSActvX PtrToSActvY PtrScrActvX PtrScrActvY * Entries to read straight from the file or a dialogue ---------------------------------------------------- ProtocolMax ProtocolM1 ProtocolU1 . . . (to Mn and Un where n = ProtocolMax) ShowFHighFor AppendWith AlterNumranges AlterWith Component and event code numberspaces ===================================== This is the numberspace scheme employed for event numbers and component IDs in the various browser dialogues, toolbars and menus. There were some considerably historical complications with conventions therein, which have since been resolved. TBEvents.h contains full details. * Miscellaneous ------------- There is a small collection of miscellaneous event codes with a base number of 0x20000. These are defined in MiscEvents.h. Any event codes which really don't fit in anywhere else should go here, though obviously keeping things meaningfully categorised wherever possible is generally A Good Thing. * Toolbars (Toolbars.h) --------------------- Toolbars occupy a numberspace between 0x0001 and 0x00fff for event codes and component IDs. See the header file for more. * Menus (Menus.h) --------------- Menu items and related events used to be defined across several files, but are now collected in Menus.h. There is the possibility of splitting this in future, if Menus.c itself splits to form separate sources for specific menus or groups of menus. Menu items rarely raise events themselves, outside of ToBeShown-style events; usually, the dialogues or other objects that they show or alter raise the events themselves (again, usually dialogues raise ToBeShown-style events rather than menu items raising events best described as AboutToShow). It is possible to use default event codes and add code to the menus_item_selected function, but it may be desirable to use custom events within the menu numberspace if the same function may be driven elsewhere. (See the section on using a local proxy server as a cache for an example of this). * Save Object dialogue (SaveObject.h) ----------------------------------- The component ID base is 0x1400. Event codes are tied to component numbers where the two inter-relate or start at the top of the numberspace, 0x15ff, and work down where not connected. * Save File dialogue (SaveFile.h) ------------------------------- Similar to the SaveObject dialogue. The numberspace starts at 0x1200. * Print Style dialogue (PrintStyle.h) ----------------------------------- The numberspace starts at 0x2200. * Open URL writable (OpenURL.h) ----------------------------- The numberspace starts at 0x1800. There is a slight complication with this dialogue, where different events are raised if the dialogue is to be shown from a document menu as opposed to from anywhere else (allows the URL pointed to by a link that the menu was opened over, for example, to be placed in the dialogue). * The Hotlist (Hotlist.h) ----------------------- The Hotlist is relatively independent of the main browser and does not fully fit into the component ID and event code numberspace / namespace conventions established in TBEvents.h, except where core browser interaction is required. Typical 'conformant' event codes are at the top of Hotlist.h, with the more exotic definitions following towards the bottom of the file. * Find dialogue (Find.h) [unimplemented] -------------------------------------- The numberspace starts at 0x1600. * Authorisation dialogue (Authorise.h) ------------------------------------ Component IDs and associated event codes start at 0x1000. * Debug functions --------------- For TRACE builds, some extra menu items may be included to perform various debug actions. Event codes for these start at 0x30000. 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). Binaries compiled with TRACE defined in the compiler, however, will typically be considerably less tolerant of such changes, and will happily raise errors about missing items - purely as a warning. These errors are not fatal. 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. In trace builds, if it would appear that a given component is inappropriate - e.g. FileSaveFrame when there is no document source - an error will be raised. In non-trace builds, the function will fail silently, so *get it right* in the trace variants - menu items should be greyed if irrelevant! To add new save types, you need to add to the 'switch' statements in the following places: savefile_to_be_shown (remember to set 'ok') savefile_drag_ended savefile_save_file Transient dialogues can be opened near the pointer using savefile_show_for. Dialogues should only be forcibly shut with savefile_close or by collapsing the menu tree. * 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. A new dialogue may be created for a browser using saveobject_show_for. Ensure that any previous Save Object dialogue attached to the browser wishing to hold a new one is deleted first, using saveobject_close. 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 (calling saveobject_close, usually) 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). Saving and loading ================== * Saving ------ Although you tend to have to read them several times and in different orders to understand the big picture, the PRM section on application to application transfer is quite good. Pages 3-249 through to 3-256 are the relevant pages. The best approach here is to read the source files. Protocols.h is a good overview of the main messaging 'centre' for the browser, with SaveFile.c and Save.c feeding into it as the higher level interface. SaveObject uses a slightly different system running largely via. some special case conditions in the same functions. * Loading ------- As with saving, pages 3-249 through to 3-256 describe the messages involved, but note that loading also involves Message_DataOpen, which is stuck out on page 3-265 for some reason (after the iconise and printer protocol information). 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. 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.