Icons, Icons everywhere....

A program without interaction is not very interesting. Fine, you don't need icons if all you're detecting is a keypress or a mouse entering or leaving a window or a mouse click, but for most purposes you need icons, be they display icons, button icons or any other form of icon as described in the Style Guide. According to the PRMs, an icon is a "rectangular area of a window's workspace".

Style guide?

There is some debate as to the usefulness of the Acorn style guide. While it shows how to make all RISC OS applications follow the same format for the likes of icons and hot keys (for instance no matter which application you use, F3 will always save) and provide a framework for application to use to attain this level of "sameness" it must be stressed that it is only a guide. If you have a need to use an icon which is non style guide compliant, that's up to you.

The icon block

As with the window block, defining an icon also requires a block of memory to create the icon.

Again, this should be defined in a header file and included in the standard way (see the icon.h file in this months source code on the cover disc).

Creating an icon

Icons are always associated with the parent window (the window handle at offset 0). You can have a large number of icons in a window. When you create an icon, it will be given it's own unique icon handle. This handle will start at 0 for any particular window.

It is possible to create an icon in one of two ways. Either is it defined at the end of the create window block or you define it using the SWI Wimp_CreateIcon.

If you were to use the method of inclusion at the end of the window creation routine, then the same icon block would need to be appended to the end of the window block for each icon to be created. While this may be alright for an application containing one window with just one icon, imagine trying to do this with something as complex as a spreadsheet where you can have many hundreds (if not thousands) of icons for a window. The WIMP also needs to be told inside of the window creation the number of icons in that window (this is at offset 84 of the window block, in the window.h file, this is defined as int no_icons). Using the extra data at the end of the window creation block will also not return icon handles, instead the icons are numbered upwards from zero.

It is far more convenient to separate the two creations.

The application supplied (!Part5a) demonstrates how the creation is performed. I will explain it though. Before that, I need to explain the indirection.

While in most cases it is okay to place the text in directly to redirect.text (12 characters is currently the maximum size required to store a sprite name), there are occasions when this is of no use. For instance, if I have an icon with a validation string (this tells the WIMP what characters are and are not allowed within a writable icon - I will cover validation strings in the next instalment), this data has to be placed somewhere. This is when the indirection comes into play. Here you are able to store the sprite name, validation and the length of any text associated with the sprite.

As with the window creation, certain flags can be set when creating an icon. As with the WIMP poll mask, this is an 32 bit value which can be set in the same way as for masking the poll routine.

If you recall from the icon block definition, there are three words used for the indirection. To confuse matters further, there are three methods of indirection available.

If bit 8 of the icon flags is set, indirection is used. Depending on how bits 0 and 1 of the icon flags are also set, depends on the form of indirection. The three sets of indirection are shown to the right. For the moment, you need not worry about indirection as I will return to them at a later date. I have explained it as the !Part5a application (and most subsequent code) includes code for coping with indirection.

And now, the code....

Let's have a look at the way the code is called in !Part5a (the creation function is called from c.main with the actual function being held in create.c)

(from c.main)

int ihandle;

icon_block *icons; /* this is malloc'd when setting up */

from int main(void)

make_icon(whandle,32,-100,160,48,0x700303d,"Test icon",0,0,0);

(from c.create)


void make_icon (int whandle,int minx,int miny,int maxx,int maxy,int
                flags,char *mess,char *redirect,char *valid,int text_len)
{
  _kernel_oserror *er;
  icons->window_handle=whandle;
  icons->min_x_bound_box=minx;
  icons->min_y_bound_box=miny;
  icons->max_x_bound_box=maxx+minx;
  icons->max_y_bound_box=maxy+miny;
  icons->icon_flags=flags;
  if (strlen(mess)!=0) 
    strcpy(icons->redirect.text,mess);
  else
  {
    icons->redirect.indirected.pointer_text=redirect;
    icons->redirect.indirected.pointer_validation=valid;
    icons->redirect.indirected.text_len=text_len;
  }

  er=_swix(Wimp_CreateIcon,_IN(1)|_OUT(0),icons,&ihandle);
  E(er);
}

All pretty straight forward, but let have a look at the call to the routine.

make_icon(whandle,32,-100,160,48,0x700303d,"Test icon",0,0,0);

Here, we are sending across the window handle the icons are to be created on and the size of the icon. The flags (0x700303d) translates as 111000000000011000000111101 in binary which says that the icon has text, has a border, contents are vertically and horizontally centred and also has a filled background, defines the button type and the icon colour. Bit 8 is unset (0), therefore the contents are not indirected.

Okay, that's enough for now. Next time, I'll cover more on icons. Examine the code supplied (!Part5a) which is on the cover disc or if you've bought it, the rather excellent Archive CD which also includes 2 free compilers, the majority of the source code used in the tutorials and a front end which makes GCC a great deal simpler to use.