Icons V - The remainder (at last!)

Before I start, here is the answer to the problem at the end of C the WIMP 17 when I asked what the error in the code was and what the fix should be. The answer was that I had omitted the handler code for disallowed characters entered into the writable icon. This is simple to fix.

In poll.c add inside the switch condition

case 8 : key_press(wb->poll.key_pressed.code);
         break;

This will intercept the disallowed characters. There are a couple of ways of adding in the handler (such as that used in !Part4). A solution is on the cover disc.

You will need to add the line

extern void key_press(int key);

into the mouse_key.h header file.

Sprite Icons

Up until now all of the icons created have been text only. It is also possible to use sprites inside of icons as either just sprites or as sprites with text. To do this, bit 0 and 1 has to be set in the icon flags (for just a sprite, bit 1 needs to be set). Either type of icon can be either directed or indirected (though non-indirected text plus sprite icons are pretty useless; both the sprite name and icon text must be the same as they occupy the same space in the icon block!)

There are two areas where icons can be drawn : the WIMP sprite pool (contains all of the sprites incorporated into the OS ROM combined with sprite files which have been subject to the IconSprites command) or from a sprite area set up by the program.

It is vitally important that if you use a sprite in an icon that the WIMP is told where to find the sprite. In the case of a non-indirected sprite icon (and also a text plus sprite indirected icon), the WIMP will look at the sprite area pointer for the window definition block (window->sprite_area_ctrl_block). If the value is 1, the WIMP pool is used otherwise the pointer should point to a sprite area used by the program - I'll cover this in a moment.

For an indirected sprite-only icon, a pointer to the sprite area is provided at icons->redirect.indirected.pointer_text. The same rule as before applies here. 1 means use the WIMP pool.

The name of the sprite (for non-indirected icons) sits at icons->redirect.text (as the text did before). If the icon is indirected, the location of the name depends on if it a sprite only or text plus sprite. If it's a sprite only, a pointer to the name is given at icons->redirect.indirected.pointer_text with the length of the buffer at icons->redirect.indirected.text_len.

If the icon is text plus sprite, the sprite name must be included in the validation string prefaced by the S command.

Your very own sprite area

The recommended method of using your own sprites is to create an area in memory for your sprites and loading your sprites into the area.

The sprite area could be set up like this

#include <stdio.h>
#include <stdlib.h>
#include "kernel.h"
#include "swis.h"

int *sprite_area;

int setup_spritearea(void)
{
  _kernel_oserror *er;
  int file_size;
  er = _swix(OS_File,_INR(0,1)|_OUT(4),5,
             "<MyApp$Dir>.Sprites",&file_size);
  if (er != 0)
    return -1;
  file_size += 4;
  sprite_area = calloc(1,file_size);
  if (!sprite_area)
    return -1;
  sprite_area[0] = file_size;
  sprite_area[2] = 16;
  er = _swix(OS_SpriteOp",_INR(0,2),0x10a,sprite_area,
             "<MyApp$Dir>.Sprites")
  if (er != 0)
    return -1;
  return 0;
}

Provided that the sprite area pointers in your window and/or icon definition blocks point to sprite_area, then any sprites from the file which are used in sprite icons will be displayed. For more information on OS_SpriteOp, see the PRM CD from RISCOS Ltd or the StrongHelp OS manual.

Bringing it together

We can now bring what we have seen together by looking at !Part5g. In int main(void) we have both a validation string and a sprite from the wimp pool (a floppy disc drive) as well as an error icon (the red triangle) which is non-indirected. As both sprites are from the wimp pool, inside of the window definition function, window->sprite_area_ctrl_block has been set to equal 1.

The full range of wimp pool sprites can be obtained by running this short program

SYS "Wimp_BaseOfSprites" TO r%
SYS "OS_SpriteOp",268,r%,"ROMSprites"

A file will be created called ROMSprites which will contain all of the current wimp pool sprites.

Finally here, we'll have a look at !Part5h. In this, we create a set of radio icons using indirected text plus sprite icons. All of the other icons have been removed. The code for generating these inside of int main(void) needs some explanation though.

char *valid="Sradiooff,radioon",*text_1="Fahrenheit";
char *text_2="Celcius",*text_3="Kelvin";
make_icon(whandle,32,-100,240,44,0x1722b113,"",text_1,valid,21,0);
make_icon(whandle,32,-148,240,44,0x1702b113,"",text_2,valid,21,1);
make_icon(whandle,32,-196,240,44,0x1702b113,"",text_3,valid,21,2);

We have three char pointers for the text and another one for the validation string. Note that the validation string defines how the radio icons are set in the window - they are all off to start with. Two sprites are required for a radio icon, therefore the radioon icon is included in the validation string. This is simple enough. The icon flags aren't.

When using text plus sprite icons, the state of the horizontal, vertical and right justfied flags determines where the text and sprite appear relative to each other. For radio icons, the vertical flag (bit 4) needs to be set which results in the sprite being on the left with the text alongside.

And finally .... The Iconbar

Up until this point, all of the code supplied produces a window on screen. The application quits when the window is closed. This is fine, but what we really want is an iconbar sprite. !Part5i gives you just that!

It is very simple to do as well - you create an icon as you would normally, but instead of giving a window_handle, you pass in -1 for the icon to go on the right hand side or -2 for the left. Remember what is stored on the iconbar in those positions when you decide. The left has all the physical devices (disc drives etc) while the right has applications.

The icon is normally sprite only, non indirected. It is usual to have the icon used for the application to be the same one as on the iconbar, it is therefore in the sprite pool. There are rules to say where on the iconbar the icon is positioned. The WIMP will decided where to place the icon horizontally but the vertical position must be 0 (i.e. the iconbar's work area origin). The height should be 68 OS units with the width being any reasonable size, though it is normally 68 OS units for an application sprite. The button type is normally 3.

We have also had to change the code so that the window now no longer opens until the icon bar icon is clicked. To do this a new function, void iconbar(int button) has been added. This is called via void mouse_click(int button) which contains one line - if the the value passed to the function is -2, call the iconbar function. It does not differentiate between the mouse click being either Adjust or Select. Now when you compile and run the code, you will see what looks to be a more traditional RISC OS application.