Home Products Documents links News Events Tech Info

The comp.sys.acorn Application Writer's Guide

The following document was taken from the usenet newsgroup comp.sources.acorn on 22nd June 1992

Newsgroups: comp.sources.acorn
Subject: The CSA App. Writers' Guide
From: jwil1@cs.aukuni.ac.nz (TMOTA)
Date: Mon, 22 Jun 1992 00:41:55 GMT

The comp.sys.acorn Application Writer's Guide

This guide contains a lot of small hints from some of the gurus on comp.sys.acorn. Most of them are pet hates - things that many applications do that really annoy us. When writing applications, please read through this list and check that your application conforms to as many as possible of the items...

Many of these things might seem complicated at first, but they are all very simple when you know what you are doing. All the information needed can be found in the Programmers Reference Manuals, or ask someone for some help!

This guide is kept by Jason Williams (jwil1@cs.aukuni.ac.nz), so please email any new suggestions for the guide to him. Any suggestions made on comp.sys.acorn should also be caught and included...

"Public Domain"

Public Domain means that everything in the application can be used, changed, copied, etc. exactly as the user wishes. They can even include portions of your application in their own (commercial) programs if they so wish.

Public Domain and Copyright are MUTUALLY EXCLUSIVE!

If you wish to place distribution conditions on your software, then call it FREEware, and clearly state your conditions. Using this term, you can also claim copyright on your software.

Legally, if you choose to use the term 'Public Domain', then you don't have a leg to stand on, even if you stated that the software was copyright, etc.

Icon sprites/Screen modes

Never include additional sprites (eg your own definitions of system sprites) in the !Sprites file of your application.

Always include small icons as well as large ones in your sprite files.
Regardless of how hard the things are to design, you can always do a better job than the automatic scaling of the large icons.

Always include a !Sprites22 (Mode 20) and !Sprites23 (Mode 23) file as well as !Sprites (Mode 12) - even if you can't display multisync sprites on your monitor, you can still create & edit them provided you use at least 2x magnification.

Make sure all your sprites have a core RISC OS 2 ROM mode number (Sprites should be defined in mode 0, 12, 20, or 23). Be very careful about this if you start using screen snapshots to help you design sprites. Similarly make sure you remove the sprite's palette after doing a screen shot to create an icon.

Always try your !Sprites in MODEs 8 and 0 (4 and 2 colour) to make sure they don't disappear. Careful choice of colours will ensure they don't Similarly aways try !Sprites22 in MODEs 19 and 18 as well as Mode 20. Your !Sprites23 should look similar to your !Sprites22 in MODE 18, but some difference is reasonable since you can hand stipple !Sprites23 as they are for monochrome display only.

RUN your program in ALL screen modes you can lay your hands on. Do all your icons dissapear due to colourtransing in mode 0? Do your 256-colour icons go SPLAT in mode 12?

Does your code fall over in mode 66, 78, 120? (Not checking the size of the screen is a very common fault. DO NOT assume that the screen other people are using is identical to the one you use!

Get the size of the iconbar icon RIGHT! If in the program you declare the iconbar icon bounds as 0,0;68,68 then make the sprite you use 34x17 in mode 12/0 or 34x34 in mode 20/23! Try 'dabbing' at the edges of your icons with a window or menu and see if you can cause bits of the icon to be 'rubbed out' and not correctly redrawn.

Info windows like those used by BASS are pretty with all their sprites, but how much memory does this take? Place these sprites into a file we can edit (don't compact them in with the !RunImage), and preferably give an option that stops unnecessary sprites being loaded/displayed.

!Boot & !Run files

Only include a !Boot file if it is absolutely necessary. Remember that other users may not appreciate an unnecessary !Boot file, particularly if they are Econet users.

If a !Boot file is missing, then the equivalent of
IconSprites <Obey$Dir>.!Sprites
will be done automatically for you.

ALWAYS put an IconSprites <Obey$Dir>.!Sprites into your !Run file. If the application is launched with !Menon or similar, the sprites will not have been loaded by your app. dir. being 'seen'.

Suggestion: rather than having a !Run file which goes "Obey <foo$Dir>. !Boot", include the contents of the !Boot file in line in the !Run file. This way the application starts up quicker over Econet, as the !Boot file doesn't have to be loaded.

Never have anything (not even blank lines) after the "Run <foo$Dir>. !RunImage" in your !Run file, otherwise the !Run file stays open while your application is running and only gets closed when it quits.

Don't make your program auto-run in a !Boot file. If you want people to have the option of this, give them a file they can rename to !boot...

Help files

Always include a !Help file. This should be a plain text file, and never one of these !Help applications which are springing up.

IF you MUST use a non-text !Help file, then use an Obey file that checks if the application your Helpfile needs is loaded, and reverts to just RUNning the text version of the help if the special application is not found.

Always call the help file '!Help', not 'ReadMe' or other names. This allows help to be offered on the filer menu.

Always include your name in the !Help file, as well as the application. You don't have to include your address, but without a name, it can be very difficult to identify pieces of software. DON'T include your name if you are re-releasing somebody else's work - passing off someone else's program as your own is bad, and could get you into a lot of trouble.

Always credit other people for any help/code they supplied you for your application.

A nice option is to check if your help file exists from within the application, and offer a 'help' option on your main menu, which simply RUNs the text file...

Always include an indication of the legal status of the software, and whether or not it may be freely distributed.

Other files/resources

Don't put lots of subdirectories inside the application if it can be helped. People with hard drives typically lose 14k for each directory you bung in, which often wastes more space than the total size of a small PD application... :-(

Get all your resources with <App$Dir>.Name, where Name is the filename of the resource, and App is the name of your application. Set this variable (*Set App$Dir <Obey$Dir>) in your !Run file.
DON'T use <Obey$Dir>.Name inside your main program!
DON'T use "$.!app.file" or "adfs::Mydisc.$.!app.file" - Even though this is convenient, it is bad form, and may cause problems for anyone who adds functionality to your program later. Do it right the first time!

Alternatively do "*Set App$Path <Obey$Dir>." (note the trailing period character) and reference files as App:Name. This only works for reading though.
RISC OS 3 applications tend to have both a $Dir and a $Path. The path is used for reading reasource files, so they can be in several places (and indeed some of them are - see Alarm$Path). $Dir is used for writing configuration files etc.

Preferably, use a SEPARATE variable for your config. files, so that someone else can easily move your config. data to a central place and then rename your variable to point there instead. This can allow your program to be run from read-only filing systems (e.g. on econet, etc)

Always use <Wimp$Scrap> and <Wimp$ScrapDir> for storing temporary files in. Never store them inside your own application's directory. In this way the user is free to put temporary files where he wants them, rather than ending up with them spread over 4 different floppy discs with attendant unecessary disc swapping. The disc with <Wimp$ScrapDir> on it is probably already in the drive.
On RISC OS 2 you need to be careful about <Wimp$ScrapDir> as it doesn't always exist. It is suggested that you supply a !Scrap application with your software if you make use of <Wimp$ScrapDir>

Windows

Even if you only have an info window, make sure you process OPENWINDOW requests, or your windows won't be movable.

Info windows that go away when you move the pointer out of them are *incredibly* annoying! Likewise, Info windows that limit the pointer (BASS!) are a hassle. (Especially in Protracker where the limit is a window *behind* the one you are looking at... I *hate* that!)

Always open windows as defined in the templates file. Reposition them if you like, but don't change their size! Some people have bigger screen modes than you and they like to have bigger windows when they are first opened!

Open windows centered in the *current* screen mode, or over a parent window. I hate windows appearing as squitty little things in the corner of large multisync modes. I also hate windows appearing off the top/side of mode 12...

Preferably, check the window position when things happen - if the window is fullsized, or if the screen mode changes, check if you need to 'bump' the window back onto the screen. At least the titlebar should be available so it can be dragged back onto the screen! Preferably also allow your windows to be dragged off the screen (This means if fullsize is clicked, you must ensure that the window doesn't get bigger than the current screen mode)

Window Templates

If you get memory for templates, DON'T trim down the allocated memory to the exact byte needed for *your* templates. Add a few hundred bytes so we can alter/add to templates without your program crashing. This is especially a good idea when you are only using half of the WIMPSLOT memory anyway... (Acorn, do you hear me? ;-)
If this is a big problem and you are supplying source, give a constant./variable that is easily found to change the allocation.

In RISC OS 3.00, there is a call to tell you how much memory is needed for your Templates to be loaded.

3-d 'plinthy' windows look nice. Some people don't think so, though, and it would be very nice if you supply two sets of templates, one for 3-d and one for 2-d icons.

Note that 'Interface' is incompatible with RISC OS 3.00's way of redrawing 3-d icons, so your application will look really crappy in RISC OS 3.00.

Menus

Put your menu 96 OS units above the menu bar (40% of PD apps. fail this one, and it is a right pain!). The TOP menu item of your iconbar menu should be INFO, and the bottom one should be QUIT. This calculation is:
y = 96 + (number_of_items * 44) + (number_of_dotted_lines * 24)

Menu items should be 44 OS units high, and the item gap should be 0.
Menu items should be left justified (DON'T center them!)

Don't put dangerous items next to innocuous one ins menus. A very bad example of brain-dead design lies over your floppy :0 drive icon - notice how dismount, format, verify, are all bunched together? How many times have *you* hit format instead of dismount?

Fonts

Go to the command-line. Type *FX25 . Go back to the desktop. Do all of the symbols used in your program look right still? Good. (If you have really been screwing around in the system, you may need a *alphabet bfont as well)

If using outline fonts, AT LEAST put an easy to find option or variable that can be set to allocate enough room for the font menu... most people seem to make their programs to use their 5 fonts, and don't realise some people have around 300 fonts on their hard drives! It is in fact possible to count the number of available fonts, and allocate enough memory to read them all.

If replacing BFONT with an outline font, remember these points:

  • 14 point is usually about the best size - not too big to fit, roughly the same size as BFONT, and not so small as to look 'grubby' in low res modes (12, 15)
  • Use ONE font (family) consistently throughout the app.
  • Use ONE (or maybe 2) font size consistently throughout. (More sizes means heavy font cache usage - thrashing off disc and more memory needed, which are bad things)
  • Use Trinity, Homerton, (or Porterhouse) unless you are providing the font with the application- these fonts are available to everyone, and the first two are in ROM in RO3.
  • Give an OPTION to use BFONT.
  • Preferably check that there is at least 16k allocated to the font cache and drop back to BFONT if this is not the case

Filing systems

Don't leave files open.
Don't close open files with CLOSE#0 !!!

DON'T assume anything about the FS you are run from.
Or the Drive number.
Don't even assume that you can write to the Filing System if it can be helped.

Don't set the CSD or library or alter any FS paths. Don't alter the current filing system.

If doing file operations in C, try using setvbuf. I found in CBAdecode that a 150% speed improvement resulted off floppies (using 16k buffers in place of OS 4k buffers), and seeking was drastically reduced on my hard drive.

Configuration

If your program alters the machine in any way (eg redefines system beep, or changes mouse pointer), make sure that they are restored when it finally terminates. Be especially careful to make this work when the program crashes! (And don't assume that it won't crash!)

Don't use *CONFIGURE commands in your applications. They are NOT needed for anything you should be doing.

Don't *UNPLUG modules you want to kill- *RMKILL them. Never include a *RMCLEAR command in your programs.

Make sure that your program doesn't use any unusual modules or screen modes, unless they are included with the application.

If you need to RMEnsure modules from !System, try to check for the earliest possible version which will work with your software.

If your program uses a module, make sure that if the module is RMCLEARed, the application will quit cleanly, rather than going into an infinite loop.

Make sure that the memory you ask for in the WimpSlot command in your !Run file is equal to the actual amount displayed in the task manager window when the program starts running. 4 Megabyte machine will give you 32kB of memory even if you only ask for 8kB, but a 1MB machine will only give you 8kB! This causes lots of programs to fail to run on 1/2MB machines.

Bearing the above in mind, trim down the WIMPSLOT size to a safe minimum.

Miscellanea

CTRL-Break your machine and then hold down SHIFT so it doesn't autoboot. THis should give you a reasonably 'clean' machine, with no strange modules, screen modes, etc. Does your program still run fine on this 'bare' machine?

If a program will not allow users to return to the desktop, display a warning giving them the chance to return to the desktop before the program starts running.

Use % in front of any *commands you use, and specify ALL options e.g. "%wipe file ~v ~c r f"
This should get around aliases that do unexpected things and odd wipe options configurations that you didn't expect.

Get a program that protects zero page and run it. Now run your application. If you get "Abort on data transfer" errors, you are writing to places you shouldn't.

When files are saved to you from another app., you first get a DataSave message including a suggested leafname. REMEMBER THIS LEAFNAME. When you subsequently get a <Wimp$Scrap> or similar transfer, you can then use the remembered leafname as the filename instead of <Wimp$Scrap>.
I *hate* the way Edit gets this wrong.

MASK OUT NULL POLLS while you aren't using them!
If you need nulls, then use Wimp_PollIdle.
Clocks only need updating every second or so... If only minutes are displayed then an update every 10 seconds is close enough. Thus, use PollIdle to give you 1 null poll every 10 secs, and save a lot of desktop bandwidth to make drags, etc. smoother.

When doing long operations, multitask in the background. This is not difficult to do, and doesn't affect the speed of your program much.
(I found that with 20cs timeslices for processing, there was not a noticable (to the centisecond, at least) time difference in processing that took 90 or so seconds... 5 polls in a second just don't take a noticable time.
This allows people to abort things quickly and allow them to do low-bandwidth operations such as editing textfiles while doing stuff in the background.

Oh, and while multitasking, don't use the hourglass!

-- 
_________________  "I'd like to answer this question in two ways:
  /____ _ _/_ __       First in my normal voice, and then
 // / //_//_ /_/       in a silly, high-pitched whine." (Monty Python)

poppy@poppyfields.net