Introduction
Configure is the desktop application through which the user alters the configuration of the machine: the choices that are stored in CMOS RAM, the files within the Choices boot structure, and the settings of other components of the system. Each area of configuration is presented in its own window, and each of those windows is provided by a separate plug-in application. Configure itself provides the main window from which the plug-ins are opened, decides whether the machine is in a state where its configuration may be changed, and manages the closing of plug-ins.
This chapter describes the interface between Configure and its plug-ins. It is intended for those who write a plug-in for a piece of hardware or software, for those who write a group of related plug-ins which are presented together, and for those who write installation tools which add resources to the boot structure. It defines the user interface that a plug-in must present, the resources that a plug-in supplies, the way in which a plug-in is started and positioned, the Wimp messages exchanged with the plug-in, and the commands which are provided by the Installer module.
The content of the individual configuration windows (the choice of options on the Mouse window, for example) belongs to the plug-ins which provide them and is not described here. The use of the Toolbox to build a plug-in's window is likewise outside the scope of this chapter.
Overview
Structure
A configuration system is made up of the following parts:
- The root (or controlling) application, which displays the main window containing one icon for each top-level plug-in.
- Plug-ins, which are applications whose directories are placed within a configuration directory. Each plug-in opens a single window, which is used to alter one aspect of the configuration.
- Group plug-ins, which are plug-ins whose window shows a further collection of plug-ins, in the same way that the main window does. The members of a group are second-level plug-ins. Groups may be nested to further levels. A generic shell application, CPIShell, provides the behaviour of a group, so that a group need consist only of the shell, a messages file and a directory of children.
- The Installer module, which merges files and entries into the boot structure, keeping backups and logs of what it has done. It is used by the windows which install new resources.
Plug-ins are separate tasks. They communicate with the root application (or with the group which controls them) through a small number of Wimp messages, described in Wimp Messages. A plug-in which does not know about the protocol can still be used, but will not position its window consistently and cannot object to being closed; see Protocol-ignorant applications.
Purpose of plug-ins
Separating the configuration windows into individual applications allows parts of Configure to be added or removed without altering the rest. Third-party hardware, such as a SCSI interface, can supply its own configuration window which appears alongside the standard ones, and each plug-in can be maintained, upgraded and distributed by its own author. A system administrator may remove the plug-ins for areas which users must not alter (the network configuration, for example) without preventing them from changing others, such as the mouse speed.
Groups of plug-ins
Where there are many related configuration windows, they are collected under a single icon in the main window. Opening that icon opens a window which presents the members of the group as icons, in the manner of the main window. The group is the controlling plug-in for its members: it broadcasts the quit messages for them, and it passes on to them the class that identifies the group (see Plug-in classes).
The members of a group may be hidden or faded according to the configuration of the machine, or the version of the operating system, so that the same group can be shared between several versions of the system. The conditions are described in Group shell.
Locking
The root application is responsible for deciding whether the machine is in a state in which it may be configured. That decision depends upon whether the machine was booted locally or remotely, the access permissions of Choices$Write, and the state of FSLock. When configuration is not possible, the icons of the main window are faded, and the plug-ins cannot be started from it. The details are in Locking and failed writes.
Protocol-ignorant applications
An existing configuration application which does not implement the
protocol can be included as a plug-in. In that case the root application
takes the name of the application, without the leading !,
as the text of its icon; the name of the application, including the
!, as the name of its sprite; and a generic string as its
help text. These defaults are a fallback only. An application which is
written to be used as a plug-in must supply its own text, sprite and
help, as described in Plug-in resources.
The only message which such an application must handle is . Without the remainder of the protocol the window of the application will not be positioned beside the icon that opened it, and the application will not be reopened at the front of the window stack when its icon is clicked a second time.
User Interface
General principles
Every configuration window is a dialogue box presented in the standard RISC OS style. All gadgets must comply with the Style Guide. Each window has separate action buttons at the bottom, rather than instant-effect gadgets and a close icon. Because a window has a Cancel button, it has no close icon.
The windows normally provide the following action buttons. Where a Default button is present it restores the factory defaults for the system, which may differ from the defaults of the same components when they are soft-loaded on an earlier system.
| Button | Click | Action |
|---|---|---|
| Set | Select | Configures the current selections and closes the window. |
| Set | Adjust | Configures the current selections, and leaves the window open. |
| Cancel | Select | Closes the window without configuring the selections. The next time that the window is opened it will show the configured values. |
| Cancel | Adjust | Resets the selections to the configured values; that is, to the values when the window was opened or last Adjust-clicked on Set, whichever is more recent. |
| Default | Adjust | Resets the selections to the factory defaults without configuring them. |
| Default | Select | As for Adjust. Selecting the defaults and then closing the window would only duplicate Cancel, so the button does not close the window. |
A window may also provide a Try button, for settings whose effect can be sampled (the system beep, or a screen saver), so that the user can test them without configuring them.
A window which is opened gains the input focus, so that Return and Escape can be acted upon. If the window has no writable icons it must place an invisible caret. The Set button, or its equivalent, must always be a default action button (with the 3D border of a cream well), to show that it is the action taken on Return.
When the user clicks on the icon of a plug-in whose window is already open, the window is reopened at the front of the window stack in the same position, without changing any of its selections. The root application does this by sending . A click with Adjust does not close the main window.
Where a plug-in is used within a group, the group's Cancel closes all of the open windows of its members, and its Set does the same after telling them to save any data which they have modified. Unless Adjust was used, the group's own window then closes as well. A member whose data has been modified, and which has not been told to set it, asks the user whether to discard, cancel or set it; see Quit protocol.
Interactive help
Interactive help text is standardised across plug-ins. Only one help
message can be given to each gadget (which may consist of several icons
and, for a string set, a menu), and gadgets provide no help while they are
faded. In the table below, *** is replaced by text
appropriate to the circumstances, and |M is the sequence
which makes the Help application insert a line break. Wherever possible,
the help text of a gadget takes one of these forms:
| Gadget | Help text |
|---|---|
| Plug-in activation icon (main window) | Click SELECT to open the *** configuration window. |
| Plug-in work area | This window allows you to configure various aspects of the ***. |
| Preceding labels | This is the ***. |
| Numeric range (writable) | You can adjust the *** using either the keyboard or the arrows. |
| Numeric range (display) | You can adjust the *** using the arrows. |
| Writable icons | You can enter the *** here. |
| String sets | You can choose a *** from the menu. |
| Sliders | You can adjust the *** using the slider. |
| Following labels | The *** is measured in ***. The non-abbreviated name of the unit is used, followed by any necessary explanation of the unit, in brackets if that is brief. |
| Option buttons | This indicates if ***.|MClick SELECT to select or deselect this option. |
| Radio buttons | This indicates if ***.|MClick SELECT to select this alternative. |
| Drop zones | You can drop a *** here. |
| Try action buttons | Click SELECT to sample the selected ***. |
| Default action buttons | Click SELECT to reset the selections to the factory defaults. |
| Cancel action buttons | Click SELECT to close this window without configuring the selections.|MClick ADJUST to reset the selections to the configured settings. |
| Set action buttons | Click SELECT to configure the selections and close this window.|MClick ADJUST to configure the selections without closing this window. |
Main window
The main window contains one icon for each plug-in, sorted alphabetically by the descriptive text of the plug-in. The window initially has room for up to five columns and four rows of icons; if there are more, the work area extends beyond the visible area. The window can be resized in the manner of a directory display. The text, sprite and help of each icon come from the plug-in, as described in Plug-in resources.
The menu of the main window has no Quit item. It contains:
- , which leads to a submenu offering an information box for the application and for each top-level plug-in.
- , which saves the contents of the CMOS RAM to <Choices$Write>.CMOS.
- , which restores the CMOS RAM from that file.
- , which starts interactive help.
- , which loads the CMOS RAM from Choices:ResetCMOS.
The three CMOS items are faded when the reading or writing of the files they use is not possible, for example because FSLock is active. When Choices$Write is on a locked filing system, or when the machine has been booted remotely and Choices$Write is not publicly writable, every icon in the work area is faded. If FSLock is active, the icon of the Lock plug-in is not faded, so that the user can unlock the machine.
The help text for the work area of the main window changes with the state of the machine.
| Item | Help text |
|---|---|
| Work area | Configure allows you to control various preferences of operation and startup.|MClick SELECT on the icons to open the individual configuration windows. |
| Work area (disc locked) | Configure allows you to control various preferences of operation and startup.|MThe icons are faded because the hard disc is locked.|MClick SELECT on the Lock icon if you wish to unlock the hard disc. |
| Work area (no permission) | Configure allows you to control various preferences of operation and startup.|MThe icons are faded because you do not have permission to save your choices on the remote machine. |
| Info | Move the pointer right to view information about the configuration system. |
| Save CMOS | Click SELECT to save all the CMOS RAM as a file, from where you can restore it later. |
| Save CMOS (locked) | You cannot save the CMOS RAM while FSLock is active. |
| Load CMOS | Click SELECT to load all the CMOS RAM from your saved CMOS file. |
| Load CMOS (no file) | You do not have a CMOS RAM file to load from. |
| Load CMOS (locked) | You cannot load the CMOS RAM while FSLock is active. |
| Help... | Click SELECT to load interactive help, for guidance on the use of Configure. |
| Default CMOS | Click SELECT to restore all the CMOS RAM to the factory default settings. |
Installation windows
Three windows install resources into the boot structure, and share both their user interface and the Installer module that does the work:
- System, which merges a !System directory into System$Dir.
- Fonts (the Install fonts... button of the Fonts window), which merges a !Fonts directory into the font directory.
- Boot (the Install button of the Boot window), which merges a !Boot directory into Boot$Dir.
The Fonts and Boot windows are second-level plug-ins, opened by their parent through its group. The window of each is dragged to by a directory display; the dropped directory must be named and structured in the same way as the one it is to be merged into. The merge is described in terms of the objects and operations defined in Installer module.
The window has three states. In the initial state it asks for a directory to be dropped on it; it returns to this state whenever Cancel is clicked with Adjust. When a suitably named directory is dropped (even after a preview has been calculated), the window shows the name of the source and offers Quick merge, which starts the merge at once, and Preview. The preview examines all of the files concerned, determines the necessary operations, and presents them as a list of option buttons. The user may deselect any operation which they do not wish to perform; All and None select and deselect every operation. If an error occurs during the merge the user may cancel or continue; the window stays in the preview state, with the operations that completed successfully deselected.
The operations offered are the addition, update or removal of each file, as determined from the state of the destination before and after the operation. A font face is treated as a single item, so that the operations are of the form Update face Homerton.Medium. Paths are shown relative to the destination directory. The System and Boot windows also offer a Synchronise !System operation, generated whenever the contents of System$Dir are altered, which runs *Install_CheckSystem.
Directories of load and execution address &DEADDEAD (known as
corpses) are requests for the object at the equivalent position
of the destination to be removed. An empty directory is created at the
destination with *CDir.
| Window | Destination | Differences |
|---|---|---|
| System | System$Dir | Looks for modules, corpses, empty directories and miscellaneous files. The search starts from any subdirectory, whether or not it is an application, except Backup. Backups and the log are kept in the Backup and Log objects of System$Dir. Synchronises !System at the end. |
| Fonts | The third-last directory on Font$Path | Looks for fonts and corpses. The search starts from any subdirectory excluding applications. Backups and the log are kept in the Backup and Log objects of Boot$Dir. Runs *FontInstall at the end. |
| Boot | Boot$Dir | Looks for any file or font, together with corpses and empty directories. The search starts from the source directory itself, excluding Backup and Log. Backups and the log are kept in Boot$Dir, unless the destination is within System$Dir, when the System locations are used. Synchronises !System only if the contents of System$Dir were changed. The Boot.PreDesktop and Boot.Desktop files in Choices$Write are merged with *Install_Merge rather than updated. |
The interactive help for the merge windows follows the standard forms. For the System window:
| Gadget | Help text |
|---|---|
| Merge | Click SELECT to close the dialogue box and start the merging process.|MClick ADJUST to do the same, but keep the dialogue box open. |
| Cancel | Click SELECT to cancel this dialogue box.|MClick ADJUST to forget about the !System directory that has been dropped on to this window. |
| Agenda | Click SELECT to view a list of all the operations that will be performed during the merge. |
| All | Click SELECT to select all the operations. |
| None | Click SELECT to deselect all the operations. |
| Pane icons | This is one of the operations that will be performed as part of the merge process.|MClick SELECT to disable or re-enable the operation. |
Lists of boot items
Plug-ins which edit an ordered list of files, such as the items to be run or booted at startup, present the list in a scrolling pane. The list contains leafnames; a directory refers to the objects within it, to which the action is applied in turn. The list accepts files, applications and directories dropped on to it, drags within it (with autoscrolling) to change the order, and the Remove, Select all and Clear selection buttons. Entries in the file which were not written by the plug-in are shown faded; they cannot be selected or edited, and new items cannot be placed before or between the faded entries which come first, or after the faded entries which come last. Items which can be edited are shown with fully canonicalised names, and are stored relative to Boot: or Boot:^ where that is possible. The entries are written to the boot files with *Install_Merge; see Merging obeyfiles.
| Gadget | Help text |
|---|---|
| Remove selection | Click SELECT to remove all the selected files, applications and directories from this window. |
| Select all | Click SELECT to select all the files, applications and directories. |
| Clear selection | Click SELECT to deselect all the selected files, applications and directories. |
| Pane work area | Drag files, applications and directories to this window to add them to the list. |
| Un-faded items in pane | Drag this around within the window to change its position within the sequence.|MDrag other files, applications and directories to this window to add them to the list. |
Technical Details
Plug-in resources
A plug-in is an application directory located within a configuration directory. For the root application this is BootResources:Configure; for a group it is the directory given by the -dir option of the shell (see *CPIShell). The root application scans its directory when it starts. The information about each plug-in is read from the Messages file in the plug-in's application directory, using the following tokens.
| Token | Meaning |
|---|---|
| _ConfigText | The brief text of the icon in the window of the controlling application, and the key by which the icons are sorted. Defaults to the name of the application without the leading !. |
| _ConfigHelp | The interactive help text of the icon. It should follow the form given in Interactive help. A generic string is used if the token is absent. |
| _ConfigSprite | The name of the sprite for the icon. The sprite is taken from the Wimp sprite pool. Defaults to the name of the application including the !. |
To make the sprite available, the controlling application runs
*IconSprites on the file CoSprite within the
plug-in (or CoSprite22 and so on, following the
usual conventions for sprite files). To avoid clashes with other sprites
in the pool, the names of sprites within these files begin with the three
characters co_.
A plug-in will normally also have a !Sprites (or
!Sprites22 and so on) file and, optionally, a
!Boot file, for the case where it is used as a
stand-alone application. Plug-ins are not normally booted by the Filer
unless a directory display is opened for the configuration directory,
which saves time and space in the sprite pool. The sprite for the
application in !Sprites should differ from that in
CoSprite, as the latter is not constrained to
68×68 OS units. If no better sprite is available the
!configure sprite can be used.
A plug-in which is a group controlled by CPIShell may also use the tokens described in Group shell.
Starting a plug-in
The controlling application starts a plug-in with
Wimp_StartTask, passing the command line described by
*ConfigurePlugIn. The
-openat option gives the preferred position of the
top-left corner of the window, in decimal OS units, relative to the
screen; a typical command ends
!InetSetup -openat 120 844. A plug-in which is started
without that option (for example, because its application was
double-clicked in a directory display) must centre its window on the
screen. A plug-in which was started without -openat
must also ignore , as it
will not subsequently receive a .
When the user clicks on the icon of a plug-in which is still running, the controlling application sends it instead of starting it again. The plug-in must reopen its window at the front of the window stack, in the same position, and must make no other change, equivalent to an Adjust-click on Cancel that leaves its state alone.
A plug-in is launched on behalf of a group with -class naming the plug-in class of the group that controls it; see Plug-in classes.
Opening a particular plug-in directly, rather than the group as a whole, is done by starting the group's shell with -openwith. If the shell is already running, the same information is passed to it in , as described there.
Plug-in classes
Each plug-in system is identified by a plug-in system descriptor, a 32-bit number. The descriptor identifies the group of plug-ins to which the messages in Quit protocol apply, so that a message intended for the plug-ins of one group is ignored by the plug-ins of another.
A plug-in has a class, the descriptor of the group of which it is a member, which it receives with the -class option. A group, in addition, has a control class, the descriptor of the plug-ins which it controls, which it receives with the -control option. The group sends the control class in the messages that it broadcasts for its members, and passes it to each of them as their class. The root application is the controller of the main plug-in system, and uses the descriptor &50DBF as its control class.
Descriptors are allocated within the same chunk of numbers as the Wimp messages of the protocol, which starts at &50D80. The values in use are:
| Descriptor | Plug-in system |
|---|---|
| &50DBF | The main Configure plug-in system (the root application) |
| &50DBE | Boot configuration |
| &50DBD | Fonts configuration, and the font merge dialogue |
| &50DBC | Network configuration |
| &50DBB | Sound configuration |
| &50DBA | Disc configuration |
| &50DB9 | Display configuration |
| &50DB7 | Extension configuration |
| &50DB5 | Window configuration |
| &50DB4 | User configuration |
| &50DB3 | Input configuration |
Other values may be used for new groups, but must be kept within the range of numbers allocated for Configure. The same descriptor field is used in the messages so that the quit messages may be used by tasks which are not plug-ins of Configure: a task which does not recognise the descriptor must ignore the message.
Locking and failed writes
Only the root application tests whether the machine is in a state which allows its configuration to be changed. A plug-in does not repeat that test. Since plug-ins are normally reached only through the root application, which will not start them if the machine cannot be configured, this is sufficient.
A plug-in can also be started directly, by double-clicking its application. For that case a plug-in must not report an error if it fails to write to disc or to CMOS RAM. It must, however, still apply the settings for the current session. This allows a knowledgeable user to alter the operation of a locked machine, for example the mouse speed or the filename width of the Filer, when no other interface is available.
The Lock plug-in cooperates with the root application to change the state of FSLock, using the messages described in Lock protocol.
Quit protocol
The root application must close its plug-ins when its main window is closed, or when FSLock is activated. A plug-in whose selections would be difficult or time-consuming to repeat, such as an editor for the boot sequence, should be able to object. The existing mechanism cannot be used to warn these plug-ins, because it can only close a single task or the entire desktop and cannot restart the closing process if the user decides to proceed. The quit protocol is used instead, and is also used between a group and its members.
The sequence is as follows.
- The controller receives a request to close its window, a from a plug-in that has finished its confirmation, or (for the root application) a for lock status 2. It broadcasts , using event type 18 (recorded delivery), with its control class in the plug-in system descriptor.
- A plug-in which has the same class, has modified data and has
not yet been told to proceed, claims the message so that it is not
returned to the sender, and asks the user whether to discard, cancel or
set the data. This may take several calls to
Wimp_Poll. - If the user chooses to discard or to set, the plug-in sends to the task which sent , and will no longer object. The controller then repeats step 1, so that other plug-ins have their turn.
- If the user chooses to cancel, the plug-in broadcasts . Every plug-in which receives the message with a matching descriptor sets its objection state ready for the next time. The quit process stops.
- If no plug-in claims the message, the Wimp returns it to the controller. The controller then sends to each of its plug-ins individually. The Lock plug-in is not sent the message when the closure was the result of locking.
When the closure was caused by a group, rather than the root application, the process is the same, except that the group sends with a flags word, which says whether the user clicked Set or Cancel. A plug-in told that Set was clicked can assume that the user wants its data set, and so does not need to display the dialogue box asking whether to discard, cancel or set it. A group which has been asked to close, and which has members that object, is responsible for itself objecting in the same manner, and for forwarding the quit to its members once they have no further objection.
A plug-in which wishes to be able to object must, in addition to handling in the usual way, behave as shown in Handling the quit protocol.
When a plug-in is closed with and flag bit 0 is set (a closure of the single task, for example from the Task Manager), a group which has members still open claims the message and tells its members to quit as if Cancel had been clicked. The group's own closure is then the result of the which follows. A closure of the entire desktop is not intercepted.
Lock protocol
The Lock plug-in and the root application have a private protocol, used to change the state of FSLock; other tasks must ignore these messages. The Lock plug-in broadcasts with the new lock status (0, 1 or 2). If the new status is 2, the root application quits all of the other plug-ins, using the quit protocol, and fades their icons in the main window. If none of them objects, the root application broadcasts to the Lock plug-in, which then applies the new status. The confirmation is never sent if one of the plug-ins objected to being closed. The Lock plug-in announces the completed change to every instance of itself with , so that their windows can be updated.
The status values are 0 (permanently unlocked), 1 (temporarily unlocked) and 2 (locked).
Handling the quit protocol
A plug-in which can object to being quit maintains two flags: a complain flag, which is set when the plug-in is initialised, and a modified flag, which is set when its selections differ from the configured values. It responds to the messages as follows.
When Message_PlugInQuit is received with a descriptor equal to our class:
If complain and modified are both set:
Acknowledge the message, so that it is not returned to the sender
Ask the user whether to Discard, Cancel or Set the data
If Discard or Set was chosen:
Clear complain
Send Message_PlugInQuitContinue to the sender of Message_PlugInQuit
Otherwise (Cancel was chosen):
Broadcast Message_PlugInQuitAbort
When Message_PlugInQuitAbort is received with a descriptor equal to our class:
Set complain, ready for the next time
The message is acknowledged by sending it back to the task which sent it
as a Wimp user message acknowledgement (event type 19), with the
your_ref field set to the my_ref of the message.
A plug-in which is told that the user clicked Set, in the flags
word, sets its data without displaying the dialogue box, and objects
only if it cannot do so; it reports that error itself. If the plug-in was
started without -openat it ignores the message.
Group shell
CPIShell is the application which implements a group of plug-ins. A group consists of the shell and a directory containing the application directories of its members. The shell displays the members in a window in the manner of the main window, starts them in the way that the root application does and takes part in the quit protocol on their behalf. It is started with the command line described in *CPIShell.
The messages file of the application which uses the shell (the directory named by -msgdir) may supply the following tokens.
| Token | Meaning |
|---|---|
| _ConfigWindowTitle | The title of the window of the group. |
| _ConfigSetMessage | A message which is displayed when the Set button is clicked. It may be used to give a warning about the details that have been configured. |
In addition to the tokens in Plug-in resources, the messages file of a member may supply the following tokens.
| Token | Meaning |
|---|---|
| _FadeIfVariable | The plug-in is faded depending on the state of a system variable. The value is a name preceded by + (fade if the variable is set) or - (fade if the variable is not set). |
| _FadeIfModule | As for _FadeIfVariable, but the plug-in is faded depending on whether a module is present (+) or absent (-). |
| _FadeIfPodule | As for _FadeIfVariable, but the value is the product type of a podule, and the plug-in is faded if the podule is present (+) or absent (-). |
| _FadeIfFile | As for _FadeIfVariable, but the plug-in is faded depending on whether a file is present (+) or absent (-). |
| _ConfigHelpFaded | The help message of the icon of a plug-in which has been faded. |
| _ConfigHidden | If the token is present, with any value, the plug-in is not included in the list. A hidden plug-in is not shown at all, unlike a faded plug-in. It is only useful to hide configuration which would otherwise conflict with a later version of the operating system. |
| _ConfigMaxOSVersion | A three-digit version of the operating system. If the version given by Boot$OSVersion exceeds this value, the plug-in is hidden. The final digit of the system variable is always zero, so a component which applies to RISC OS 4.00 only has the value 400. |
| _ConfigOSVersion | The three-digit operating system version to which a plug-in applies. It determines the directory into which the plug-in is installed; see Installing a plug-in. |
The values of _FadeIfVariable and _FadeIfModule may combine several
conditions with the conjunctions & (logical AND) and
| (logical OR). The conjunctions must be separated from the
conditions by spaces, and cannot be nested. For example,
_FadeIfModule:-SCSI & -SCSIFS
fades the plug-in if neither the SCSI module nor the SCSIFS module is present.
Installing a plug-in
A new plug-in can be added to a group by dragging its application
directory to the window of the group. An application is accepted as a
plug-in only if its messages file contains a _ConfigSprite
token. If it does not, the user is told that the application cannot be
installed, or is warned that installation may have undefined results.
The destination within the configuration structure depends upon the
_ConfigOSVersion token in the messages file of the plug-in.
If the token is absent the plug-in is installed into the
RO400Hook directory, for compatibility with earlier
versions of the operating system. Most commonly the value is 420 or 400.
Installer module
The Installer module provides the operations used to install files into the boot structure, through a number of star commands, so that they can be used in an Obey file as an installation script. The module ensures that backups and logs are kept for every change, that modules are compared correctly, that the font messages files are updated, and that the version directories of !System are maintained.
The module recognises the following kinds of object. It installs one object at a time; it does not install an entire directory in a single command.
| Object | Meaning |
|---|---|
| Font | A compound object, consisting of all the files (of any file type) in one directory, one of which has a name beginning IntMet. The font is referred to by the directory, for example Resources:$.Fonts.Homerton.Medium. |
| Module | A file of type &FFA. |
| Obeyfile | A file of type &FEB (Obey), &FD7 (TaskObey) or &FEA (Desktop). |
| Datafile | Any other file, typed or untyped. |
Backups and logs. The commands which replace or remove a file
first copy it to a backup directory, and then append a record of the
operation to a log file. Both are held below the directory selected with
*Install_LogDir: the log file is called
Log, and a file which has the path
path relative to the log directory is backed up at
path relative to its Backup directory.
The log directory must therefore be higher in the hierarchy than any
file to be installed, or the file cannot be backed up. When no log
directory is defined the log data is written to the screen. For a module,
the version number multiplied by 100 is appended to the name of the file
in the backup directory, and the version is given in the log.
Newness. *Install_Update replaces a file only if the source is newer than the destination. If both files are modules, the version numbers are compared, and if they are equal, the datestamps of the files. Otherwise the datestamps of the files are compared, with the following special cases: an untyped file has the datestamp of the beginning of time; a font has the most recent datestamp of the files in its directory (not recursively); a directory has the most recent datestamp of the files within it (recursively); and where there is nothing at the destination, but it is located below a file rather than a directory, the datestamp of that file is used.
When fonts are installed or removed, the messages files in the first !Fonts directory above the destination are updated. For each new font family a default face is selected, in order of preference: none (regular), Medium, Book, Light, Demi, Bold, Heavy and Black, followed by the Oblique and then the Italic versions of the same.
When files in the Encodings directory of a fonts directory are changed the messages files are not updated, as the module cannot know that the files are within a fonts directory. To rebuild them, the caller should wipe !Fonts.Messages# and then install a font, which causes a new messages file for the current territory to be built, including the encodings. Aliases in the messages file of a source font are not copied to the destination file. When a complete !Fonts directory is removed, the backup copies of the messages files may be incomplete, because the file is updated as each font is removed. A font face which has been removed as a font directory is no longer recognised as a font by a later request to remove it, which then removes the hierarchy below it as well.
Obeyfile entries. An obeyfile which can be merged is made up of entries, each of which has the form:
|Start company application version section
...assorted * commands...
|End
Only the first word of the section name is significant. The company,
application and section are matched without regard to case. A non-empty
entry must always have a version number of at least 0.01. The comment
|Variable, within an entry, causes an existing entry of the
same version to be overwritten.
Merging obeyfiles
*Install_Merge combines the entries of a base obeyfile and a changes obeyfile into a destination file. The entries of the changes file are merged into the base file one by one:
- The base file is scanned for the first entry with the same
section. If there is none, the first applicable rule is used to decide
where the new section is placed. If no rule applies, the default
rule
*>*is used. - The consecutive entries with that section are scanned for the first with the same company, and if none is found the rules are used in the same way.
- The consecutive entries with that section and company are scanned for one with the same application. If none is found, the rules are used again. If there is one, the version numbers are compared: if the new entry has a matching or earlier version, the entry of the base file is kept, and otherwise the entry from the changes file is used.
The changes file may contain positioning rules. A rule is a one-line
entry beginning with |Section, |Company or
|App, with the form
|[Section|Company|App] rule [rule [rule ...]]
where each rule is either specifier>specifier,
meaning that the item on the left is created after the item on the
right, or specifier<specifier, meaning that it is created
before it. There must be no spaces within a rule. A specifier
is a single word naming a section, company or application, without regard
to case, or *. On the left, * means any
specifier, and on the right it means all of them. The rules are applied
from the first appropriate line of the file to the last, and from left to
right within each line.
*Install_DeMerge performs the reverse operation, removing entries from the base file.
Wimp Messages
The messages of the protocol have numbers in the chunk starting at &50D80. In every message the plug-in system descriptor is a number identifying the plug-in system for which the message is intended; see Plug-in classes. A task which receives a message and does not recognise the descriptor must ignore the message.
Commands
The first two commands are the command lines with which the applications
of the plug-in system are run. They are not star commands; they are
given to Wimp_StartTask or the Run command,
in the form
<directory>.!Run options. The remainder are star commands
provided by the Installer module.
-openat <x y> | - | Position of the top-left corner of the window, in decimal OS units. |
-class <class> | - | The plug-in system descriptor of the group of which the plug-in is a member, in hexadecimal. |
-openwith <component> | - | Name of a component to open when the plug-in is a group. The parameters for that component may follow, separated by a space. |
The controlling application runs a plug-in in this way. A plug-in which does not receive -openat must centre its window on the screen, and must not respond to . The positions are measured from the origin of the screen. A plug-in which does not receive -class has no class, and ignores the messages of the quit protocol.
-dir <directory> | - | Directory in which to search for the plug-ins to display. |
-msgdir <messages directory> | - | Directory containing the messages file for this group; see Group shell. |
-openat <x y> | - | Position of the top-left corner of the window; see *ConfigurePlugIn. |
-control <control class> | - | The plug-in system descriptor of the plug-ins which the group controls, in hexadecimal. This is the descriptor sent in the quit messages for the members, and is passed to them as their class. Defaults to &50DBF. |
-class <our class> | - | The plug-in system descriptor of the group of which this group is a member, in hexadecimal. |
-openwith <component> | - | Open with a particular component displayed. The name is that of the application directory of the member, optionally followed by a dot and the name of one of its own members, for example ScrnSetup.SvrSetup to open the screen saver plug-in. |
-openwithparams <parameters> | - | Parameters to use when opening the component named by -openwith; for example -from ADFS::$.Some.Path.!Boot to give the Boot installation plug-in a source directory. |
-root | - | Run as the root application, using the configuration directory BootResources:Configure. |
The shell presents the plug-ins found in the directory as a window of icons, which can be opened in the same way as those of the root application. Only one instance of the root application may run at any time. If the root application is already running when a second is started, the second sends to the first, with the component given by -openwith and its parameters, and then exits.
<directory> | - | The new log directory. |
Defines the directory into which the Installer module writes the log
file, called Log, and builds the backup tree. Backed-up
files have the same path relative to directory.Backup as they
had relative to directory. The directory must therefore be
higher up the hierarchy than any file which is to be installed or
removed, or the file cannot be backed up.
The log directory is undefined by default, so the command is normally used at the beginning of an installation script. If no argument is given the current log directory is printed.
Undefines the log directory. The command is normally used at the end of an installation script. While there is no log directory, the data for the log file is written to the screen.
<source_file> | - | The file to install. |
<dest_file> | - | The file to be replaced. |
Copies source_file to dest_file if the source is
newer than the destination. The rules which determine newness are given
in Installer module. A file which is
overwritten is first copied into the backup directory, and the details
of the operation are appended to the log file. For a font, the messages
files in the first application directory above dest_file are
updated to include the new font.
<file> | - | The file or directory to remove. |
Moves the file to its backup directory, and appends the details of the operation to the log file. A file of the same name which is already in the backup directory is first deleted. For a module, the version number multiplied by 100 is appended to the name of the file in the backup directory, and the version is mentioned in the log. For a font, the messages files in the first fonts directory above the file are updated to reflect its removal.
<base_file> | - | The base source file. |
<changes_file> | - | The changes source file. |
<dest_file> | - | The destination file. This may be the same as one of the source files. |
Combines the entries of two obeyfiles, placing the result in the destination file. The entries of the changes file are merged one by one into the base file, using the rules given in Merging obeyfiles. If the destination file is overwritten it is first copied into the backup directory. Each successful entry update is listed separately in the log file, with its new version number and any old version number.
Adding an application to those which are seen at startup, with a changes
file which contains the line |App Configure>*:
The section ResApps and company Acorn are assumed to exist already, as part of the default file; all the other Acorn ResApps entries come first.
Creating the section Run after the section Boot, or after Auto if Boot
does not yet exist, using a changes file which contains the line
|Section Run>Boot Run>Auto:
<base_file> | - | The base source file. |
<changes_file> | - | The file whose entries identify those to be removed. |
<dest_file> | - | The destination file. |
Removes from the base file any entry whose section, company and application match an entry in the changes file, unless the version number of the entry in the base file is newer than that in the changes file. The result is placed in the destination file. The changes file must therefore include at least the entry headers of the most recent version of each entry to be removed. If the destination file is overwritten or deleted it is first copied into the backup directory, and the details of the operation are appended to the log file.
Ensures that the versions of modules in the OS-version subdirectories of System$Dir are not older than those in previous-version subdirectories, or in the root Modules subdirectory. Any which are older are removed in the manner of *Install_Remove.
Examples
Handling a request to quit
A plug-in which edits a list of items checks, when it receives a request to quit, whether its data has been modified, and asks the user what to do. Only when the user chooses to cancel does it prevent the closure.
static int complain = 1;
int message_plugin_quit(WimpMessage *message, void *handle)
{
if (message->data.words[0] != plugin_class)
return 1; /* not for us */
if (complain && modified)
{
/* Claim the message so that the quit is stopped for now */
message->hdr.your_ref = message->hdr.my_ref;
wimp_send_message(Wimp_EUserMessageAcknowledge, message,
message->hdr.sender, 0, NULL);
/* Ask the user to Discard, Cancel or Set; for Cancel, abort */
/* the quit for everyone, otherwise let the sender continue */
...
}
return 1;
}
Opening a plug-in within a group
To open the screen saver plug-in of the Display group and set a source directory for it, the shell of the group is started with the name of the component. If the shell is already running, it receives the name in instead.
Run <ConfigPluginShell$Dir>.!Run -root -openwith ScrnSetup.SvrSetup
Placing an entry before others
To ensure that an entry for a company is placed before all of the others in a section, whether or not the section exists already, the changes file contains positioning rules. The first line states that the section Installation is created after the section Comments, if it does not exist, and the second that the company Acorn is created before all of the other companies.
|Section Installation>Comments
|Company Acorn<*
A later installer which needs to place an entry after one which may not yet
be present can first install an empty entry such as
Acorn Wimp 0.00 Installation. If a genuine entry already
exists the empty one is ignored; if it is installed later, the position of
the empty entry overrides the default rule. This is why non-empty entries
must always have a version number of at least 0.01.