PinboardServer

Early on in RISC OS times there were a lot of 'desktop sillies'. Actually there were quite a few for other systems as well, of which some were ported, or reproduced on RISC OS by people who thought 'that's cool'. Many of them were very pointless, but they showed off little things and were quite pretty. There were so many aquarium implementations that it was quite silly.

I remember I put together my own - quite a few years later - which was entirely based on Pinboard icons. Each fish animation frame was a filetype which meant that the sprite could be different when pinned to the screen. There was seaweed as well which was placed in such a way that a number of files one above the other would make a continuous section of weed. Using the Pinboard gradient background, the bottom of the background could be dark blue, and the top a light blue. There might even have been some icons for sand along the bottom as well. A little application would issue new *Pin commands regularly to make the fish move.

Ah, such memories... but that's not what I wanted to talk about. Prior to that - by about 5 years - I wanted to allow the desktop sillies to coexist in a harmonious way where they would not interfere with one another. Part of the problem with the sillies was that - when they worked with the background they would either replace the Pinboard as the background window, or they would create a small window around their animated object, which had a grey background, thus hiding anything that they covered but looking like they were part of the Pinboard background, which was also grey. The sillies which took over the whole background - aquariums and the like - would either not work or would look silly with other sillies.

Setting aside the fact that these generally are sillies, I thought that there must be an easy way to make them play nicely together. If they worked through the Pinboard, they could perform their job alongside others. So, the PinboardServer came into being. It was a patch on to Pinboard which would allow a selection of new messages to be supported by the task. The idea was that instead if doing the operations (creating icons, moving them, deleting them) themselves, the applications would send messages to Pinboard requesting that it do that.

Not only did this allow them to work with Pinboard, but also it meant that because the interface was simple and easy to implement it could be added to other backdrop applications. For example !StickyBD, or !Larger could have supported the API. They didn't, but they could have been updated to do so. This was all long before I knew you were meant to use particular message ranges, and that you should register them, so all the Wimp messages were &80 upwards.

Each desktop silly would broadcast a request for the version of the PinboardServer, which would also indicate that it was present. If no response was received, the application could terminate, reporting that it couldn't work without the PinboardServer. The response explicitly specified that the version returned was that of the command set, not of the implementation - which I think was pretty forward thinking for me, as this was back in 1994.

Applications could request the creation of icons on the background, and could request that they be moved. Because sprite areas could not be shared between the backdrop application and the silly application, any sprites used had to be shared in the Wimp Sprite pool - a particularly bad failing. These days I think I'd probably suggest that sprites be held in a dynamic area, or that the server provide a means to load sprites into its common pool. Either way you have to be careful not to leak, or to destroy a sprite pool when the application exited, whilst the PinboardServer was still using it.

Speaking of leaking, because of the way that I implemented the server (that is, badly), applications had to delete all their icons when they exited. If they crashed, the icons which had been created by the application would remain, but become completely inactive. A special message would be used if a user clicked on an icon which was created by applications, and this wouldn't be delivered. If the application was still alive, it could act on those clicks - either to offer a menu or perform an action.

I started with a couple of pretty neat little sillies that I liked, which I rewrote to use the new PinboardServer protocol. !Neko is pretty well known, and had been ported by Michael Bankstahl. I took the sprites and examined the way that !Neko worked to create a new version which worked with the protocol. Because I wasn't as clever as the original author, I couldn't work out how to detect the edges of windows - so !Neko just ran underneath everything, rather then clawing at the sides of windows.

Having made this work, I started on !DeskDuck2 in the same way. This was a simpler little application that swam a duck back and forth along the top of the IconBar. Until you clicked on it, that is, at which point it played a gunshot and the bird died. Rather sad, but this is a silly, after all. I don't condone the shooting of ducks except on the desktop.

I created a couple of original sillies as well. Once was a spotlight that would bounced around the backdrop until it found the cursor, which it highlighted as a escaped prisoner who would then be unceremoniously gunned down. The prisoner's chalk outline would be left behind, and like all good Naked Guns some of these looked silly - one had the prisoner cut in two, another had a tutu on (all very badly drawn by me).

There was a simple application which would scroll a message across the screen. And a little clock that could place itself on the backdrop and would just show the time.

I also wanted to show that you could do useful things with the protocol, so I created a simple mode utility. This would show a small number in the bottom right of the Pinboard for the mode number, and a pair of up/down icons which would control the resolution when clicked, immediately changing to a higher or lower resolution, and a pair of +/- icons which would control the number of colours when clicked.

I think I sent it to Acorn User but I'm not certain what response I got back - my reply letters were all thrown out a few years ago. I have a vague recollection that they were concerned about the reproducing of the Pinboard module as part of the patch, although it's entirely possible that's all just a figment of my imagination.

Neko chases the pointer, and the prisoner tries to escape... whilst there's a duck in need of shooting
The PinboardServer running a few clients. (Animated version (168K))
(No ducks, prisoners or cats were harmed in the making of this patch)

NoCoverIB

One of the early modules that I wrote was really based on a little information from one of the OSLib header files - which were always interesting reading to help populate !StrongHelp. The headers listed some undocumented CMOS flags for the Wimp, one of which was to prevent full size windows covering the IconBar. I thought this was quite a neat idea, and so I turned it on. Unfortunately I didn't understand it as meaning what it actually said; I had read it to mean that the option would mean that windows didn't cover the IconBar. The important bit is 'full size windows' - it only meant that the action of making windows full size would avoid the IconBar.

So, I liked the idea but wanted more. My NoCoverIconBar module was created to do just this. I wanted to patch the SWI Wimp_OpenWindow calls such that moving a window (or opening a new one) bounded the bottom of the window to the IconBar, essentially dragging a window downwards would only resize the top of the window. Someone had done a patch, a while earlier, that provided 'fvwm' style (well, that's how I knew it) sections around every window that would change the size of the window. They were nice but they were a bit invasive and they tended to have bad effects on panes.

I started out by providing a module with the same SWI base as the WindowManager, and trapping every SWI that applications issued for it. These were then modified, if necessary, and the base WindowManager instance would be called to perform the usual operation. This was fine, except it means that you cannot share the patching with anyone else on the system. Fortunately, Andrew Clover had the same idea and wrote WimpSWIve - a manager for Wimp SWI claimants - and he contacted me to let me know about this. I changed over the claim system so that it could work with other claimants, which meant that the two modules had to be supplied together, but this hugely simplified things.

The patching was very simple and merely changed the parameters to the SWI Wimp_OpenWindow call. Initially this was fine, but it caused problems if the parameter block was stored in ROM (which might be the case for some supplied applications), or where the contents were subsequently reused in other calls. Instead of just changing the data in the block, the block was copied and the copy was modified, rather than the original. This worked fine for many years until the extended nested Wimp calls were introduced, as these had additional parameters in the block.

TextCopy

I wrote the TextCopy module as a simple filter to allow drags to be performed on text input fields, and to allow text files to be dropped on to text input fields to insert their content. Whilst some of this could be done through filters, the dragging of text input fields wasn't supported - there were a few types of text input fields, most of which were the plain 'Click' format. These only notified the application (and thus filters) of single clicks, not drags. To allow these types of icons to be dragged there were two choices - either reimplement the drag detection in a wider filter, or convert all the plain writable icons to 'Click/Double-click/Drag' icons.

I tried the wider filter initially and found it to be a little too fiddly to make work properly. There were just too many little bits of the checking process that meant that my implementation and that in the Wimp felt different. So instead, I added WimpSWIve handling so that the icon creation calls (SWI Wimp_CreateWindow, SWI Wimp_CreateIcon) would force all the plain writables to be the draggable type. This worked very well, with very few applications being upset by it.

FunMenus

One of the sillier little tools that I included in the examples was a the FunMenus module. This wasn't all that clever really. It changed the background colour of the menus to be different random colours from the 8 defaults that RISC OS used. It filtered off the calls using WimpSWIve and replaced all the sub-menu handling with its own modified version so that it could manipulate the menus as they opened.

It appears to get upset with some windows on RISC OS 4 - probably because it relies on undocumented details about the structure of windows in memory, but mostly works fine.

A brightly coloured menu stack
Menus appeared in random colours as you traversed them

One thing it does show up is that the divider icon still assumes that the background will be grey, which isn't right. Since the divider is actually just a flag in the preceding item, it should either blend from one colour to the next row's colour, or maybe just use the preceding colour.

Activity

Back in the olden days I had a SCSI drive - I have a feeling I borrowed it from Chris, along with a SCSI card. It worked really well, except for the noise. Oh my was it noisy. Its spinning was so noisy that you couldn't actually hear when it was running. And being a SCSI drive, the activity light on the front of the machine wouldn't light up when it was running. So usually you couldn't tell if it was just accessing the disc a lot - or crashed.

So I knocked together a very simple little module that sat on all the filing system vectors. Whenever they were entered it would make the pointer a little bit lighter, and when they exited it would restore the pointer to its original colour. Obviously this may the filing operations a little slower, but compared to the time taken to get data from the disc it wasn't significant (lets ignore the fact that it was significant if the data was coming from memory, such as ResourceFS).

Initially I claimed all the vectors, which was nice as it meant that you would see all the operations, but as many of the operations were BGET and BPUT - especially on Obey files, and the overheads were high when the data was in memory, I removed them. This was before the Obey module was updated to cache the input file in memory.

In the final version it looks like I decided that it was useful to filter off the Load operations from FileV when they were not the 'load at address' forms. Reasonable, because they would never return, but it begs the question of why I didn't also filter off FSControlV calls to run things. Unless they always decomposed to FileV load calls, but I'm pretty certain they do not.

What should happen is that a command run through the normal 'run' interface should leave the pointer stuck in its light colour. That did happen sometimes but not as often as I'd have expected if the FSControlV problem was as I think it is. Oh well... anyhow, it was a really simple module but was one of the many cases where post trapping a vector was required, and that was always fun <smile>.

EE

The EE tool was a development of the work that I'd done on the External Edit protocol. Desktop tools could happily use the protocol, but a command line tool cannot. This means that if you need to get any large input for a command line tool you have to rely on a simple editor, or static file input. My own need for something like this stemmed from my !GMail tool - a small command line mail composing client, which had its own (very simple) line based editor. I wanted to make it easy to replace the editor with something else. The EE tool was what I came up with.

External Edit allowed other applications to perform the editing on your behalf. A client (like !GMail) requested an edit be performed by an editor and a suitable editor (hopefully the user's preferred editor) would perform the editing. The user then had access to the rich (and possibly complex) editing environment, and didn't have to be frustrated by yet another poorly implemented editing system being provided by an application. In the case of !GMail, this meant that you could launch your text editor (which might be !Zap or !StrongEd or whatever) to compose your email, rather than having to put up with its built in line input 'editor'.

It's a !JFPatch produced application, which is a little unusual in the first place, as usually I wouldn't write applications in assembler. In fact these days I discourage such use with scorn - especially those without a proper AIF header (which EE was). Anyhow, the tool would take a file from its command line and make that editable in the current external editor tool for the type of file. You could also override the filetype by using a command line option.

If you were outside the desktop (for example, at the F12 command line), it would start a new task and then perform the repeatedly poll until it was killed, or a flag was set. If you were inside the desktop (for example, in a TaskWindow), it just wait for a key to be pressed or for the flag to be set. In either case it would install a filter over the task, which was how all the communication was performed. Using a filter for both the 'real task' and the 'inside a desktop task' cases meant the code was in the same place. The filters would then do all the communication needed with the External Edit task.

The filters also detected the case where the task was terminated and forced these to be dealt with as a failure of the edit. Because the filter code lives inside the application space, the task has to still be paged in prior to the filter code being executed. This isn't a problem, and actually is required for most filters to work, because the user block into which the poll data is supplied to the filter comes from the application space. It's still a bit wrong, because the application shouldn't have such things in its application space. Oh well; it did the job.

The command line tool did a very nice job, but one of the goals of !GMail was to be a single executable which allowed you to send email through any transport you had available (another goal was for it to be under 32K, which for most of its life it achieved). Having a separate tool to edit text went against that goal, so I created a C-ified version, which I could link with the C code in !GMail.

I'm pretty sure I released both the little C library and command line tool for people to use. There's limited cases where you want to be able to edit things from the command line, though. One of the best, however, was the CVS tool, which allowed you to give you commit comment in an external edit session by just setting the CVS$Editor variable to be EE -t FFF .

The tool still works, although I've not used it in a while. As I don't send email from RISC OS anymore (or even have a way to), it's less useful. I would imagine that most other revision control systems could use the same interface for invoking an external editor. I think one of the main reasons that you see such atrocious commit messages (aside from laziness and an inability of developers to see value in such things) is that the editors do not encourage more than a couple of lines. It's possible that the tool's usefulness is more from my own practices writing mail and developing software.

SWPointer

As one of those 'fun' and 'exciting' evening projects whilst at RISCOS Ltd, I put together a simple software pointer module. Essentially this was because we'd found that some hardware just wasn't going to support the type of pointer that RISC OS was expecting, either because of the lack of colours (we expect 3 colours plus transparency), resolution (VIDC pointers can be any height), or support (some of the hardware we looked at had no support for hardware overlay).

A software pointer would also give us the ability to use full colour pointers, instead of the more limiting hardware pointers that were currently in use. There was the downside that the pointer programming code was an SWI OS_Word call which had limited breadth - it only supported a width of 32 pixels.

The operation is quite similar to that of the DragASprite module, although not as optimised. Unlike DragASprite, it has to do a lot of the work itself - DragASprite can rely on being called by the Wimp when it needs to do anything, but any software pointer needs to be able to function even when there is no WindowManager running.

In order to be flexible, the implementation uses only standard Sprite operations. The result is that it's a little slower, and has to take care that it doesn't get called at the wrong time - in particular it shouldn't do anything if output is being sent to the printer (VDU 2) or disabled (VDU 21), or a few other things. It also has to preserve the graphics rectangle which would otherwise cause the pointer plot to not work properly.

Each VSync, the code would check the pointer state and if it was active, and had moved, the background would be restored and the sprite moved (remembering the backing). Special traps were present on the Rectangle redraw and Post Rectangle redraw to ensure that Wimp redraws didn't interfere - any direct screen access might confuse the software pointer. Oddly I didn't trap the VDU vectors, nor redirection to sprite, which would mean that it'd fail abysmally in some circumstances, including if a font was being cached.

For a quick few hours mock up, it worked quite well, though. It'd have needed a bit more work to get right, but it certainly seemed interesting. Another little !JFPatch module that was, essentially, a prototype of what might be done <smile>.

Little things

There were a few little patches that got thrown together to try to address problems that I felt could be dealt with differently. Not all were particularly well thought out, or practical - and many were quite forgettable as they didn't really give enough useful functionality to the system.

AutoTopSave

AutoTopSave was a typical example of such a module. Based on a suggestion from the newsgroups, it would allow you to save files without dragging them around. The idea was relatively simple - instead of dragging the file (or entering a path into the save box), it would default to saving the file to the Filer window at the top of the stack. The rationale was that you were often working in a particular directory, which was at the top of the stack, and then you loaded your document, which might obscure that window.

So pressing Return in the save box would cause the file to be saved to that window. The patch would spot an error box being opened complaining about the file needing a path, and then try to save the file with the name of the top directory in the stack. It wasn't all that reliable, and as it needed the error box to have known text present, it didn't work with all applications.

I'm not sure I'd implement it that way if I were to try to do it again. On the other hand, I'm not certain of the best way to do it.

SpacedFiles

SpacedFiles was a small patch to allow you to use spaces in filenames. Any DataSave messages sent with spaces in the filename would be converted to hard spaces. This meant that whilst the spaces themselves wouldn't be accepted by the filesystem, the hard spaces would be. It worked a lot of the time, where the application allowed you to enter a space. However, many applications had their validation strings in the save boxes set to disallow spaces, so you couldn't enter the space in the first place.

I used almost exactly the same technique later in Filer itself, as part of the filter to allow spaces in filenames - and it had the same sort of problems there.

AllHelp

The AllHelp module was confusingly named. It was named after the fact that it caused every window to have help to redraw the backgrounds of its windows. It was also one of the modules I created prior to discovering WimpSWIve, so it replaced the SWIs that would be directed at the WindowManager by having the same SWI base and filtered every call itself.

The module provided a single command - *WimpBackground - which took a sprite file as an argument and would use the sprites found in that file as the background for all the windows. Every window which was created would be added to a list as it was created, and have the 'needs help to redraw' so that the window would be redrawn. The filter would take care of the actual redraw. If the flag was already set, the window would be ignored and the application would handle its own redraw.

Even loading it on a modern system, it still works. Windows that are created after it is loaded use its sprites, rather than (well, over the top of) the Wimp's own background. For a pre-RISC OS 3.5 system (or before Wimp 3.22), it was actually quite neat. I don't remember whether it ever got released - all the !JFPatch files have the old filetype, before I registered the application, and it is dated November '94, so I don't expect that I would have sent it anywhere.

FilerPlus Patch

FilerPlus was a patched version of the Filer that Jens Ovesen had produced - it gave quite a few neat little features that I liked. Different icons for directories, keyboard support, plug ins and a few other nice things. I patched it further to add a few other little bits that I wanted to do.

My patched version most visibly added slabs around the icons. Every object in the directory would appear on a raised slab (taken from Robin Watts' !Larger), and when selected would appear depressed instead of inverted. This made it more consistent with !Larger which I used instead of Pinboard. I also made the Filer use Alt-Click to take the input focus instead of just a plain click, which I later used (temporarily) in the Filer.

I wanted to have multiple lines of filename in the icons, so the code would split lines as a camel-case break in the filename, or could be forced to break the line when the backtick (`) character was used. The filename was also presented slightly differently - for example a comma would be replaced by a dot, so 'Source`1,00' would appear with 'Source' on the top line and '1.00' on the second line.

You could also change the font that the Filer used explicitly through a variable, independent of the desktop font (which wouldn't be used anyhow, because the handling of the line splitting was completely different to how the icons had been displayed before).

My patch was really nice, but obviously went when I upgraded the OS - I didn't update it to support the new Filer. I do miss the two line filenames though, in those rare times that I use RISC OS (that is, whilst I've been writing these rambles!)

WMCols

One of the last experiments on the A5000 was to make a small modification to the WindowManager's use of colours. This was back at the end of 1997, so probably influenced a little bit by the ability for Windows to modify the standard colours used by windows in different colour schemes. The patched version would change the colours of the window according to a colour scheme used by the application.

Each application could have a different scheme, selected based on the application's name, although the configuration of the schemes wasn't actually implemented, it seems - all the code to handle the selection of the schemes appears to be present, but only a default is provided. You would have to poke into the workspace to add a configured scheme, which is a bit odd. I presume that I got distracted by something, as it has limited appeal.

I do remember it being quite interesting to have different colours in the desktop per application, so I must have manually poked the configuration for my tests. I wanted to follow up the scheme configurations when we were doing work on the WindowManager's configuration, but it's actually quite hard to get in there in a useful way without making a mess or breaking things. As we were planning on introducing such things as the Alerter system for application configured notifications, and sound schemes, in a later Select version, I expect we'd have investigated this again then. On the other hand, with the use of furniture that didn't translate well to other colour schemes it probably wouldn't have worked out so well.