The PCA support module is designed to facilitate use of the PCA protocol. For PCA-2 applications its status moves from 'recommended' to 'required' as the applet registration system relies on it.
If "<PCA$Path>"="" Then Error Please locate PCA resources. rmensure PCASupport 0.30 run PCA:KickPCA rmensure PCASupport 0.30 Error Version 0.30 or later of the PCA support module is required.
*PCA_Debug
*PCA_Register <AppletID> <Filetypes> <Flags> <sprites> <RunCommand>This command is central to the PCA-2 applet registration system. It is used to add an applet to the list of those known about by the module. Typically, this is done in an applets !Boot and !Run files so that the applet becomes available as soon as it is 'seen' by the filer. Parameters:
AppletID
The applet ID is used by SWI PCA_AppletStarted to recognise the applet and add one to its counter of running copies.
The suggested format is Appletname.version*100.Publisher.year_released
Case sensitive.
The Appletname is used for building textual menus and should be <31 characters with no spaces. Hard spaces (ASCII 160) can be used if necessary.
Filetypes
A comma seperated list of object types we are interested in.
Limited to a maximum of 8 filetypes.
NB. The applet can still fail to use an object when started up. For example, if the applet only works with sprites of a particular bit-depth. In this case it will report why it cannot work with the object to the user and send Message_UnHook back to the Local task to terminate the PCA link.
Flags
Binary flags for Message_ImHere
NB. An unresolved (minor) problem here where an applet can have configurable flags for things like inplace editing but as these options are best left with the Local task no action has been taken.
Sprites
pcaspritename,!spritename
Comma seperated PCA and RISC OS application spritenames.
NB. a 'pressed' version of the PCA sprite should also exist with the prefix 'p'. Applets which want to can also use a 'd' version of their icon for the *PCA_Register command so that applets which are on disc are displayed in the PCA dialogue 'dimmed'.
An example:
!drawt is the standard RISC OS application sprite.
pcadrawt is the normal, running but not selected PCA icon. Its name is passed back to the support module by the applet with Message_ImHere.
dpcadrawt is the 'dimmed' version of the above. It is passed in the *PCA_Register command and is used by the support module when building a dialogue to indicate an applet that is available, but is still on disc.
ppcadrawt is the 'pressed' version of the normal PCA icon. It is used to indicate that the applet is selected and editing an object. Either automatically by the Wimp when an icon in the PCA dialogue is selected or by the Local task using SWI PCA_DialogueState
The pca sprites should be 32x32 square pixels, preferably 256 colour (or greater) and with borders that match the style of existing applets as shown above. An archive of example sprites (including blanks) is available here
Currently the RISC OS application spritename is not used by any of the dialogue types supported by this version of the PCA module. You should still include it.
RunCommand
Rest of line
The string which will be passed to Wimp_StartTask to start the applet. If the applet wants to know if it has been started by the PCA module as opposed to being run by the user then it can append a flag to this string (eg. '-autobootpca') and parse its command string using OS_GetEnv in the usual way.
An example of this *Command may help...
*PCA_Register Composition.115.Clares.1998 ff9,aff 111011 pcacompo,!compo <Compo$Dir>.!Run
SWI PCA_CreateTag on entry - R1 = address of base R2 = Offset to object R3 = size of object (optional) R4 = flags and extension data b0-15 (bytes required+4) Multiple of 4 bytes b16-31 reserved (0)on exit -
R0 = address of tag (R1-R4 are written into the tag from tag+0 to tag+12 as initial values.)All other registers preserved.
NOTE: PCASupport relies on the first value of a valid tag not being &FFFFFFFF (-1). NEVER write this value into the base field of the tag as the next call to PCA_CreateTag will probably map your tag to another object - causing chaos. So don't do it, okay? ;-)
Extension data in R4 allows variable size tags to be created which hold extra data. In such cases, immediately write an 'extension id' into tag+16. Values 0-&FFF are reserved for general PCA. All other values are allocated in line with SWI block allocations. Please think carefully before creating your own extension id - there may be a better way of passing extra information around between your applications. Some extensions defined by Clares follow...
R4 b0-15=8 tag+16 extension id: &FFF simple text tag+20 buffer size R4 b0-15=16 tag+16 extension id: &FFE split text tag+20 len first bit tag+24 offset to second bit tag+28 length of second bit R4 b0-15=16 tag+16 extension id: &FF9 Extended sprite (NCPaint) tag+20 pointer to undo image or -1 tag+24 pointer to clipboard or -1 tag+28 pointer to 8bpp mask or -1 NB: Undo and clipboard _must_ be normal single sprites in a sprite area with the pointers being to the start of the sprite area (ie sprite is at foo+foo!8)If an applet can make use of extension data it should first check that the tag is extended (b0-15 of tag+12 will be <>0) and then check the tag extension id at tag+16. If this matches an extension you know about you can then make use of the extra tag data.
SWI PCA_DeleteTag on entry - R0 = ptr to tagon exit all registers preserved. Errors returnable: "Bad tag passed to PCASupport."
SWI PCA_DeleteAndKill on entry - R0 = ptr to tag R1 = filetype of objecton exit all registers preserved. As well as the functionality of the above SWI this also broadcasts Message_Deselect for you.
Called by the object owning (Local) task when the user asks to initiate a
PCA session or when a currently open pca dialogue needs updating.
This is basically the same as broadcasting Message_WhosAbout, collecting ImHere replies and building a dialogue box (what PCA version one tasks had to do) but this call also adds the applets which have registered but are not running to the dialogue for you (depending on the scope given in block+12 of course).
It can also be used by a task which wants to present the PCA system to the
user in a different manner to gain information about the available applets. For example,
NCPaint.
Notes:
The EOR and Clear words at +20 and +24 are used in a similar way to SWI
Wimp_SetIconState to filter the flags word in the ImHere messages collected
by this call. The Local task can use these words to disable inplace editing
for example. To do this, you would set bits 4 and 5 in the Clear word, and
have a null EOR word (b4 is the inplace flag, and b5 is PCA-inplace v2).
The clear word indicates which bits to alter and the EOR word holds the new
value(s). You should not clear or set bits willy-nilly, only with a definite
purpose for flags which are well defined in the standard (don't clear
reserved bits for example).
To avoid all sorts of nasty problems the windows created by the above
calls include no user graphics. The wimp can redraw them by itself.
SWI PCA_BuildDialogueAddr TO code_address%
You should then call the code address with R0 pointing to a block:
+0 filetype of object
+4 pointer to object tag
+8 WhosAbout_flags
b0 reserved
b1 reserved
b2 Local supports undo extension protocol
b3 Local is using new (v2) user interface
b4 Local supports help extension protocol
all other bits clear and reserved
+12 search scope
0 all PCA apps known (those running and those registered but not running)
1 PCA apps running
2 PCA apps registered but not running
3 PCA apps registered (running or not)
+16 b0-7 return info format
0 return a RISC OS menu handle
1 NCOS menu (same as above but no titlebar)
2 window definition - RISC OS (buttonbox from below + a titlebar 'Applets')
3 window definition - NCOS 'buttonbox' (buttonbox with no titlebar)
4-254 reserved for expansion
255 raw data (see format given below)
b8-15 sorting method
subdivided:
b8-9
%00 no sorting
%01 Alphabetic sort
%10 reserved
%11 reserved
b10-15
## All values reserved (0).
b16-23
If return info format is =2 or =3 then this is the
desired width of the dialogue box in items. Valid value range 1-255
Suggest you stick to 1,2,3 or 5 or allow user control.
Otherwise reserved and zero.
b24-31 More flags:
b30 (for button dialogues) when set don't make icons depress (no R5)
b31 set add an 'unhook' tool (+28 has validity)
+20 Clear word
+24 EOR word
+28 (if +16 bit 31 is set)
pointer to a series of null terminated strings for the 'Unhook tool'
or zero for module defaults.
if you opt for other than the default then the format must be as follows:
.default_menu
EQUS "Unhook"+CHR$0:REM textual tool name
EQUS "pcaunhook"+CHR$0:REM tool sprite name
EQUS "spcaunhook,ppcaunhook;R5"+CHR$0:REM icon button definition
On exit, if R0=0 then no PCA applets are available (for the object type passed) otherwise R0 is a pointer to a menu definition, window definition or raw data depending on the return info format specified in block+16 on entry.
If no sorting is specified, there are disc and memory based applets selected,
and a menu style dialogue is requested then a dashed line will be inserted
into the menu between the memory based and disc based applets (memory based applets appear first on the menu).
If the requested return type is a window dialogue you will need to call
Wimp_CreateWindow and use the window handle. You should include code to delete
any PCA dialogue window created previously to avoid filling up the wimps workspace with old windows. If using popup PCA you should then open the dialogue as a menu with Wimp_CreateMenu or put it into your menu tree (create the dialogue when opening the menu and either thread it in then, or use Message_MenuWarning and use Wimp_CreateSubMenu). If you want to impliment Dynamic PCA then call your toolpane redraw code to display the newly created pca toolbar at a suitable position next to the document window or your existing toolpane. The PCA Support module maintains dialogue data for each calling task (the memory used for each application is freed automatically by the module when the task quits). Currently, only one dialogue per calling application is supported by the module - for dynamic PCA we suggest you either provide a 'pca here' button on your own toolpane or simply move the dialogue with the wimp input focus (and rebuild if the selected object changes). |
If a dialogue type of 'Window' is asked for then the window definition returned by R0 on exit may be copied to the tasks workspace and icons added etc. if desired before the window is created. If you do this then you must ensure that any icons you add are handled by your task and are not passed to SWI PCA_ActionDialogue.
If a menu is asked for, and you thread this into your menu tree you should move the wimp block pointer to that of the sub-menu before calling SWI PCA_ActionDialogueAddr as the module cannot know the menu depth at which you have included the PCA menu. ie. The value passed in block+8 to PCA_ActionDialogue should be windowblock+sub_menu_depth*4 where zero is the first level of the menu tree. |
Raw data format
This is a null terminated list of pointers to Message_ImHere blocks.
You should make no assumptions about the position of these memory blocks in
memory. Always access them via the list.
(The PCA module will shuffle the items in this list according to the input sort criteria - this saves it having to move the ImHere blocks around).
The Message_ImHere Wimp message blocks with two exceptions (noted below) are standard, see this messages definition in the original protocol for details.
The first difference to note is that, for applets still on disc this is a 'fake' message block - the task handle in block +4 will be zero and block +12 is a pointer to the run command string. The position of the run command in memory will be safe - raw data format users can remember it and use it later to start an applet with SWI Wimp_StartTask.
The second difference is that directly after the spritename at block +60 is
an indirection definition for the dialogue type icons. ie.
+60 "spritename"+CHR$0 +60+n "sspritename,pspritename;r5"+CHR$0This is added automatically by the PCA module and the size of the message block at block+0 updated, for both disc based and memory based applets.
If -1 is returned then the special 'unhook' tool has been chosen and message_deselect has been broadcast on your behalf. You should unset any variables associated with active tools, delete any trap icons and (if using Dynamic PCA) clear the 'selected' state of any tool icons that were in use by calling SWI PCA_DialogueState.
This SWI is usually called by the local task whenever the user chooses a menu entry or icon in the dialogue produced with PCA_BuildDialogue. It activates the
appropriate applet and passes a task handle or message block back to the local
task which it must then use to talk to and recognise messages from the applet.
Similar to calling Message_DoYourStuff but it automatically starts the applet
first. The rest of the PCA protocol continues as normal - if the applet selected wants to do inplace editing it will send the local task Message_HookMe the reply to which should be Message_ObjectPosition. All other messages used in the standard should be recognised and delt with correctly by the local application.
The SWI can also be used to select a tool by task handle or by tool name which allows (for example) tools to be automatically selected by the local task. Because PCA is an open system you should always be prepared for this swi to return zero (no tool selected) if the tool asked for is not available.
If the applet chosen wants to 'own' the object (b3 of ImHere flags word)
a Message_Deselect is broadcast before the DoYourStuff is sent.
You should not terminate any previous inplace editing session until you actually get a Message_HookMe from the newly selected applet even if its flags word indicates that it can do inplace editing.
It is important that the Local task be able to handle more than one
(non-inplace) applet working on the object at the same time. Ideally, it
should function correctly with several non-inplace applets and one inplace
applet, be able to add and remove non-inplace applets and change the inplace
applet without disturbing any of the others working on the object.
(Thou shalt not send Message_UnHook or broadcast Message_Deselect unless necessary)
To select the tool when it is chosen (after ActionDialogue returns >0)
You should also call this swi to select tools with a complete list of the tools which are editing the object immediately after a successful BuildDialogue as this resets the icon/menu states (the order and number of tools may be different anyway). Use this SWI in preference to any other method as it allows for the different dialogue types available.
This SWI must be called immediately after an applet successfully Wimp_Initialises so that the PCA module knows it is running.
SWI PCA_DialogueInfo TO infoblock%
On exit, if R0=0 then no dialogue has been built for this application
otherwise, R0= a pointer to a useful block of information:
R0+0 Applets Total applets returned by the last build dialogue
R0+4 Mem_applets Total number of memory based applets returned
R0+8 Disc_applets Total number of disc based applets returned
R0+12 copied from block+0 of BuildDialogue (filetype)
R0+16 copied from block+4 of BuildDialogue (tag)
R0+20 copied from block+8 of BuildDialogue (flgs)
R0+24 copied from block12 of BuildDialogue (search scope)
R0+28 copied from block16 of BuildDialogue (return format, sorting, flags)
R0+32 Pointer_raw Pointer to the start of the raw data structure
[list of message pointers]
R0+36 Pointer_dlog Pointer to the start of the dialogue definition
or zero if raw data was asked for.
R0+40 Safe_flag
=1 no PCA apps registered, started or quit since the build *began*
=0 PCA apps have registered, started or quit since the build *began*
R0+44 TaskHandle - your task handle.
SWI PCA_ActionDialogueAddr TO action_address%
This SWI is called by the Local (object owning) task when the user selects
an item in a PCA menu or dialogue box. After calling this SWI you should then call the action code address returned with R0 pointing to a block:
+0 Object tag
+4 Pointer to a string, which is the objects textual name.
This could be a leaf-name or a full filepath as appropriate.
A null name (NB. A pointer to a null string NOT a null pointer!)
is allowed in which case the recieving applet should choose
something suitable.
+8 Input data [see block+28 bits 8-15]
+12 Object type (eg. &ff9 for sprites)
+16 Local tasks flags for Message_DoYourStuff/WhosAbout:
b0 reserved
b1 reserved
b2 Local supports undo extension protocol
b3 Local is using NC user interface
b4 Local supports help extension protocol
b5 Local task is a colour history provider
b6 Local task would like to inplace redraw if possible
b7-12 reserved - set to zero.
bits 13-15 Local task request action flags:
b13 Initiate clipboard paste please
b14
b15
bits 16-31 reserved - set to zero.
all other bits clear and reserved
+20 reserved (0)
+24 handle of the Local tasks window (the one the object is in)
+28 swi flags
b0-7 return info format
0=Task handle
1=ImHere block
other values reserved
b8-15 Input format - affects interpretation of block+8
0=R0+8 is a pointer to a wimp poll block mouse click or menu sel.
1=R0+8 contains the task handle of the tool to select
2=R0+8 contains a pointer to a null terminated tool name to select
other values reserved
On exit, R0 is either the RISC OS task handle of the applet chosen, a pointer to a Message_ImHere block , -1 or zero. If greater than zero then a pca editing session has started and the selected applet has been sent Message_DoYourStuff on your behalf, you should record the task handle (in the case of a return type of ImHere block the task handle will be at block+4) and recognise other PCA messages from this task as documented in the official PCA specification and given in summary form below.SWI PCA_DialogueState
on entry:
R0 bits 0-7 format of task list
= 0 Single task handle in R2
= 1 List of task handles in R2 [R3 holds length of buffer]
other values reserved
bit 8 clear = deselect task(s)
set = select task(s)
all other bits reserved and clear
R1 Window or menu handle of dialogue
R2 depending on bits 0-7 of R0 is either a task handle,
a pointer to a word aligned list of task handles or zero.
If zero, then all of the tools in the dialogue or menu are
set or cleared according to the state of R0 bit 8.
R3 = length of list pointed to by R2 if R0 b0=1 in bytes (multiple of four)
This swi is used by the local task to set or clear the 'selected' state of those tools in use. It should be used to keep the dialogue state up to date with the tools which are editing objects. For example:
To deselect the tool when it sends an unhook message to the local task
When the object tool(s) are editing is deleted (Msg_Deselect is broadcast)SWI PCA_DialogueToolNameFromIcon
on entry -
R0 =item/icon number (as returned from Wimp_PointerInfo etc)
on exit
R0 = 0 or,
R0 = pointer to a null terminated tool name
This swi is used in the creation of a suitable line of help text for the PCA dialogue box. eg. 'Click here to select the Painting tool.'SWI PCA_AppletStarted
on entry -
R0 = pointer to null terminated Applet id (as *PCA_Register)
R1 = task handle of applet
R2 = 0 (!expansion!)
SWI PCA_ColourTableAddress,table TO address
This SWI returns the address of the colour table in R0. On entry, specify zero for the main palette of 256 colours, -1 for the temporary palette of 16 colours.
The colour table format is currently very simple, a 16 byte header with the number of colours-1 in the table at header+4 and the maximum number of colours-1 in header+8. The colour data starts at +16 and is in the form of bbggrr00 colour words.
Generally, you won't need to access the colour table directly and should use the SWIs provided. Exceptions are loading and saving the colour table as SWIs are not provided for this function yet.SWI PCA_ResetColourTable
This resets the global and temporary colour tables to a set of hardwired defaults. Generally, you won't want to use this SWI. :-)SWI PCA_WriteColour
on entry:
R0 = bbggrr00 colour to write
R1 = index into colour table to write to:
(0-255) write to location specified
-1 rotate palette right (fifo) and write to first location
-2 check that colour isn't alreay there, and if not, fifo and write to first location
R2 = colour table to write to: 0,-1 or ptr to user tableSWI PCA_ReadColour
on entry:
R0 = index to read from (0-255)
R1 = colour table to read from: 0,-1 or ptr to user
on exit:
R0 is the colour at this index bbggrr00.