> net#arf:$.a500.RiscOS+.doc.SaveDesk Author: Neil Raine
Status: Draft proposal, not agreed yet
History:
20-Sep-89 0.01 First draft.
20-Sep-89 0.02 TinyDirs section added.
20-Sep-89 0.03 Desktop_PreSavingDesktop stuff deleted.
*SetMemorySize -next <n>k added
Comment about *Desktop_SetPalette added.
Comment about printer drivers saving choices added.
20-Sep-89 0.04 /<Edit$Dir>.!Edit changed to /<Edit$Dir>
Comment about junking Filer=>Display=>Save added.
20-Sep-89 0.05 Section about "shared resources" replaces "!System"
21-Sep-89 0.06 Simplified according to WStoye's comments
26-Sep-89 0.07 Added stuff about !Alarm
Added 'Outline' section
Added 'Work done in Desktop module' section
29-Sep-89 0.08 Correct section about dbox
Enlarged section on Filer
4-Oct-89 0.09 Message_SavingDesktop changed to Message_SaveDesktop
Example code segment for C application added
6-Oct-89 0.10 Stuff about not acknowledging Message_SaveDesktop
19-Oct-89 0.11 Stuff about desktop auto-saving removed
Aside about save dbox not being a menu removed
"Work done in the Desktop module" section removed
GStark 27-Oct-89 0.12 Added Service_WimpSaveDesktop (in resident modules

                         section)
        27-Oct-89  0.13  Corrected Service_WimpSaveDesktop
        31-Oct-89  0.14  Put auto-save icon into description of dbox
GStark 03-Jan-89 0.15 Changed Ram Disc and other slot size stuff to the new spec.

This document describes the Task Manager facility that allows a user to save and restore the current state of his desktop, thus obviating the need for a separate !SetDeskWorld utility.

Outline

The Task Manager menu provides an option to save the current state of the desktop world into a Desktop file, which can be used to restart the desktop in its original state.

There will also be facilities to save the Desktop file as a !Boot file (on ADFS) or !ArmBoot file (on NetFS), whereby the necessary configuration commands to get the system to reboot via this file are automatically carried out by the Task Manager.

In general the boot file will not return the desktop to precisely the state it was in, because:

(a) Applications which have not been specially written to deal with

        desktop saving will not be restarted.

(b) Apart from Filer directory viewers, applications will not re-open

        all the windows that were open when the desktop was saved.  In
        particular, this means that editors will not re-open the files that
        were being edited.

Work done by Task Manager

Task Manager will have the following options:

        Save state to a given file, without exitting
        Exit to supervisor
        Shutdown machine

The menu therefore contains:

        New task        => (writeable buffer)
        Task display
        *Commands (f12)
        Desktop boot    => (boot dbox)
        Exit
        Shutdown

Note that the menu option says "Desktop boot" rather than "Save desktop" in order not to raise the user's expectations too high, since it will not in general be possible to return to precisely the same state as the desktop was in.

The boot file save dbox would look like this:

        <file icon>
        [ !Boot ]  [OK]
        [ ] Auto boot
        [ ] Auto save

If auto boot is enabled, then the effect of SHIFT being pressed on reset is reversed: ie. if it is not pressed, the boot file will be executed, and if
it is pressed, the boot file will not be executed. The icon is initially set up to reflect the current state of the auto-boot CMOS RAM bit.

The auto save icon is always turned off by default - if it is enabled when the file is saved, the file will be marked as an auto-save file, so that when the user selects Exit or Shutdown from the iconbar menu, the desktop state will be automatically saved in that file.

The filename is initialised to "!Boot" or "!ArmBoot" when the Task Manager starts up, depending on whether adfs or net is the configured filing system. The user can change this if he wishes, and then click on OK or drag the file into a directory viewer.

        net:
            If directory name is net#<fsname>:&
                *opt 4,2 executed on the appropriate fileserver
                *configure filesystem net
                *configure fs <fsname>
                *configure boot/noboot
        other:
            If directory name is <fs>::<discname>.$
                *opt 4,2 executed on the appropriate disc
                *configure filesystem <fs>
                *configure boot/noboot
            If <fs> is adfs
                *configure drive <drive containing appropriate disc>

Filing systems other than the network are assumed to behave like adfs, ie. the boot filename is "!Boot" and it must be created in "$".

Aside: It was felt that it would be too much of a shock for the user if

            an error message was returned if the file was not saved in the
            root directory, so instead it just doesn't do the filesystem
            configuration etc.

The save protocol

Once the file to be saved is known, the save protocol can start:

These set the sizes of the 'Next' slot, the font and sprite area sizes, and the RAM disc size, as would be expected. It is not sensible to set the RMA size or the system stack in this way, as they are much more system-dependent than those described above. The screen size cannot be set as it is always reset to the size of the current screen mode by the Task Manager.

If there is not enough memory free to be allocated for a particular slot then, instead of giving errors, the largest amount of memory which is free will be allocated to the slot.

        *Set SaveDesk$File <Desktop$File>

What this does is to ensure that when the file is used to restart the desktop, the environment variable SaveDesk$File is set up to remember the name of the file. This works because the Desktop module has also been extended to set up Desktop$File to the name of the file passed to it.

When the user selects 'Exit' or 'Shutdown' from the task manager's menu, it looks to see if the variable SaveDesk$File is set up - if it is, it automatically saves the desktop state in this file before exitting.

        +16 Message_SaveDesktop (10)
        +20 (word) file handle of desktop file being written
        +24 flag word:
            bits 0..31  reserved (ignore them)

Note that this is a RISC OS rather than a C file handle, so fprintf() cannot be used. The RISC OS SWIs OS_BPut or OS_GBPB should be used instead.

The data is a sequence of *commands suitable for inclusion in a Desktop file, each terminated by a linefeed character (&0A). When the file is run to start the desktop, each command will be executed as a separate Wimp task.

A typical example for a C application follows:

        #include <os.h>
        #include <swis.h>
        os_error *save_desktop(int handle)
        {
          char *ptr;
          for (ptr=getenv ("Edit$Dir"); *ptr; ptr++) {
            os_error *error = os_swi2(OS_BPut, *ptr, handle);
            if (error) return error;
          }
          return os_swi2(OS_BPut, 10, handle);    /* line terminator */
        }
        (a) Tasks which don't understand desktop saving will not be saved in
            the desktop file, and the documentation should make it clear
            that this will happen with old applications.
        (b) If an application gets an error while writing to the file, it
            should acknowledge the message and report the error.  The Task
            Manager will detect that the message has been acknowledged, and
            will abort the save operation and remove the file.

Work done by applications

Normal applications:

The typical restart command for an application is a GSTrans-ed form of something like:

        /<Edit$Dir>

Note that since several copies of !Edit can be loaded at once, this GSTrans-ing operation should be done as soon as the application is loaded (and the result stored in a buffer), in case the value of Edit$Dir changes subsequently.

Resident modules:

Resident module tasks do not require a restart command of that form, since they are automatically started when the desktop is entered (by means of the Service_StartWimp protocol). However, if the modules are not stored in the ROM, they will probably be loaded by means of some form of *RMEnsure command in a !foo application, so the !foo application should be re-run instead.

There is a service call provided, though, for modules which need to save some state to the file, e.g. ColourTrans saves its calibration. This is as below:

Service_WimpSaveDesktop (&5C)
In R0 = flag word (as in Message_SaveDesktop)

        R1 = &5C (reason code)
        R2 = file handle of file to write *commands to
Out R0 -> Error, if necessary, else preserved
        R1 = 0 for error (i.e. claim), else preserved
        all other registers preserved

When a module receives this service code it should write out any * commands, to the specified file handle, which should be performed by a Desktop Boot file on entry to the Desktop.

If an error occurs (Disc full, Can't extend, or even a module specific error like 'Can't save desktop now because...' then the service should be claimed, and R0 should point to the error block.

This service call is performed before the task manager issues the Wimp broadcast message Message_SaveDesktop.

NetFiler:

Network logons must be regenerated, so that Filer windows referring to network directories can be re-opened. The NetFiler module must keep track of which username is in use on each fileserver, so that it knows the required username to put in the *command. These commands would not include the password - if the user id required a password, the Wimp's command window would appear with the *Logon command in the title and the prompt 'Password:' in the window. The current NetFiler would have to be changed so that the window title displayed the fileserver and username, so that the user knew which password to enter!

Filer:

As long as the appropriate logons are executed, the current state of the filer display can be saved by using the Filer's ability to generate *Filer_OpenDir commands for the directories currently open (already used in the Filer's Display => Save option).

The Filer must remember the full pathnames of any applications it sees (eliminating duplicates), and issue a "Filer_Boot" command for each application that contained a !Boot file (since these can set up aliases and load in icons for data filetypes).

The Filer must issue a Message_FileStarted broadcast after it has started all its children, which allows the TaskManager to 'renumber' the Filer in its list, so that its desktop saving will be done AFTER that of the individual filing systems. This is important so that the NetFiler can issue its logon commands before any net directories are opened.

Shared resources:

Environment variables pointing to shared resources are set up when the !Boot file of the relevant shared resource directory is run. This is therefore dealt with by the Filer.

PaletteUtil:

The Palette Utility is capable of saving the current palette in a file, but this would not be suitable for saving its current state into the saved desktop file. It would have to accept a new *command of the form:

        *Desktop_SetPalette RRGGBB RRGGBB RRGGBB etc. (times 20)

where 'RRGGBB' is a sequence of 6 hex digits defining colour (0..15, then the border colour and then the 3 mouse colours).

(The maximum length of a line in a Desktop file is 256 characters, and at 158 characters, this line is OK).

Printer drivers:

Similarly the printer drivers can set their current state from the 'PrData' file stored within themselves, but strictly speaking ought to save their state as a set of textual parameters on the command line, which could be re-asserted when the command was executed. The problem with simply saving the current state into the PrData file is that two different desktop save files with different printer setups would produce the same result if there was only one printer application, since both would cause the same PrData file to be loaded. However, it may be impractical to duplicate all the functionality of the modifiable parts of the PrData file as *commands.

If the state must be saved in the PrData file, then at least the printer drivers should behave like !Edit in that if you try to exit while you have unsaved choices, a dialogue box is presented.

!Alarm:

Applications such as !Alarm that live in DeskFS: cannot easily save data into their application directory (unless the user copies the directory onto a disc and runs it from there).

With the advent of desktop saving, it is probably better for applications like !Alarm to save small bits of configuration status in an environment variable, and then to output an appropriate *Set command when the desktop save occurs.

The ROM version of !Alarm will detect which filing system it was run from, and grey out the "Alarm=>Set" option if it detects that it has been run from DeskFS. It can do this as follows:

        handle% = OPENIN"Alarm:!Alarm"               :REM open alarm file
        SYS "OS_FSControl",21,handle% TO ,,fsword%   :REM read FS info word
        CLOSE #handle%
        IF (fsword% AND &FF)=21 THEN <grey out "set alarm">

!Alarm should use an environment variable to store the user format time string, eg.

        *Set Alarm$DateFormat %w3 %zdy %m3 %z12:%mi %pm

Another environment variable is also required:

        *Set Alarm$DateType Analogue
        *Set Alarm$DateType HoursMins
        *Set Alarm$DateType HoursMinsSecs

since Alarm$DateFormat is still used for the user date string even if (eg) analogue is initially selected.

In this way all the data concerning the display options is held in the desktop save file, rather than the application itself. CMOS RAM is not used, since (a) there is not enough to store the user format string, and (b) if the user format string is in a variable, then so should the display type be.

However, the alarms are stored in the application directory, but are not available if !Alarm is run from DeskFS.

ADFSFiler:

It is not necessary to 'log on' to discs - the user will automatically be prompted to insert the appropriate discs as required.

TinyDirs:

The TinyDirs module must return a *AddTinyDir command for each directory currently held on the iconbar, in left-to-right order. When re-executed, these commands would cause each new directory to be placed to the right of the previous one.