www.riscos.com Technical Support: |
|
The MessageTrans module provides facilities for you to separate text messages from the main body of an application. The messages are held in a text file, and the application refers to them using tokens.
Using this module makes it much easier to prepare versions of your program to supply to different international markets. Changing your application's textual output becomes a simple matter of editing its messages file using your favourite text editor.
MessageTrans is not available in RISC OS 2.
The module provides SWIs to
It also provides a service call to ease the handling of message files over (for example) a module reinitialisation.
MessageTrans uses a file descriptor to refer to message files. A file descriptor consists of a 4-word data structure. A file descriptor is always passed to MessageTrans as a pointer to this data structure.
We recommend that when your application stores a file descriptor, it uses a fifth word to keep a record of the file's status (ie whether or not it is open).
If MessageTrans is passed a null pointer to a file descriptor, it uses a file of global messages, held in Resources:$.Resources.Global.Messages. Obviously, if any of these messages are suitable for your application, you should use them; this will save on RAM usage, and on any future effort in translating these messages.
Message files contain a series of one-line token / value pairs, terminated by character 10 (an ASCII linefeed).
<file> | ::= | { <line> }* |
<line> | ::= | <tokline> | '#' <comment><nl> | <nl> |
<tokline> | ::= | <token> { '/'<token> | <nl><token> }* : <value><nl> |
<token> | ::= | <tokchar> { <tokchar> }* |
<tokchar> | ::= | <char> | <wildcard> |
<char> | ::= | any character > ' 'except ',', ')', ':', '?' or '/' |
<wildcard> | ::= | '?' (matches any character) |
<comment> | ::= | { <anychar> }* |
<anychar> | ::= | any character except <nl> |
<nl> | ::= | character code 10 |
<value> | ::= | { <anychar> | '%0' | '%1' | '%2' | '%3' | '%%' }* |
Note that the spaces in the above description are purely to improve readability - in fact spaces are significant inside tokens, so should only really appear in <comment> and <value>.
Alternative tokens are separated by '/' or <nl>. If any of the alternative tokens before the next ':' in the file match the token supplied in a call, the value after the next ':' up to the following <nl> is returned.
The '?' character in a token in the file matches any character in the token supplied to be matched.
Case is significant.
Most MessageTrans SWIs support parameter substitution. If R2 is not 0 on entry, '%0', '%1', '%2' and '%3' are substituted with the parameters supplied in R4...R7, except where the relevant register is 0, in which case the text is left alone. '%%' is converted to '%'; otherwise if no parameter substitution occurs the text is left alone. No other substitution is performed on the string.
# This is an example message file TOK1:This value is obtained only for "TOK1". TOK2 TOK3/TOK4:This value is obtained for "TOK2","TOK3" or "TOK4" TOK?:This value is obtained for "TOK<not 1,2,3 or 4>" ANOTHER:Parameter in R4 = %0, parameter in R5 = %1. MENUTITLE:Title of menu MENUITEM1:First item in menu MENUITEM2:Second item in menu MENUITEM3:Third item in menu
There are a number of actions MessageTrans may take if it fails to find a match in the specified file. In order they are:
Whenever you have to supply MessageTrans with a token to be matched, you can also supply a default string to be used if MessageTrans is unable to match the token. The syntax is:
token:default
That is, the token and its default value are separated by a ':'. The default value must be null terminated.
MessageTrans generates the error 'Message token xxx not found' if it is totally unable to supply any string equivalent to a token. This error is also given if the string to be returned is on the last line of the file, and does not have a terminating ASCII linefeed.
Since MessageTrans does not close message files on a soft reset, applications that do not wish their message files to be open once they leave the desktop should call MessageTrans_CloseFile for all their open files at this point. However, it is perfectly legal for message files to be left open over a soft reset.
R0 = 0, or - under RISC OS 3 (version 3.00) only - the 4-word data structure passed to MessageTrans_OpenFile
R1 = &5E (reason code)
All registers are preserved
This call is issued by MessageTrans as a broadcast to warn that all message files have been closed. You must not claim it.
If your application has any direct pointers into message data, it should re-initialise itself by calling MessageTrans_OpenFile again to re-open the file, and recache its pointers. If it has used MessageTrans_MakeMenus, it should call Wimp_GetMenuState to see if its menu tree is open, and delete it using Wimp_CreateMenu (-1) if so.
You only need to act on this service call if you are using direct pointers into the message file data. Otherwise, the MessageTrans module will make a note in the file descriptor that the file has been closed, and simply re-open it when you next call MessageTrans_Lookup or MessageTrans_MakeMenus on that file.
We recommended that you don't use direct pointers into message file data (eg indirected icons with MessageTrans_MakeMenus) if your application cannot trap service calls. You can still use such indirected icons, if you provide a buffer pointer in R2 on entry to MessageTrans_OpenFile (so that the message file data is copied into the buffer).
Under RISC OS 3 (version 3.00) this service call is instead issued for each open message file that is not held in the user's own buffer. It tells the application that its file data has been thrown away, for example if the file is held inside a module which is then reloaded. The file is identified by the 4-word data structure passed to MessageTrans_OpenFile. If you recognise this value, you should claim the service call and act accordingly.
R1 = pointer to filename
R0 = flag word:
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call gives information about a message file, telling you if it is held in memory, and the size of buffer that is required to hold the file. If the file is held in memory, and you require read-only access, you need not use a buffer to access it.
None
R0 = pointer to file descriptor, held in the RMA if R2=0 on entry
R1 = pointer to filename, held in the RMA if R2=0 on entry
R2 = pointer to buffer to hold file data
--
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call opens a message file for subsequent use by the MessageTrans module.
The error 'Message file already open' is generated if R0 points to a structure already known to MessageTrans (ie already open).
An application may decide that it would like to buffer the file in its own workspace (rather than the RMA) if it needs to be loaded, or use the file directly if it is already in memory. To do this:
SYS "MessageTrans_FileInfo",,filename$ TO flags%,,size% IF flags% AND 1 THEN buffer%=0 ELSE buffer%=FNalloc(size%) SYS "OS_Module",6,,,17+LENfilename$ TO ,,filedesc% $(filedesc%+16)=filename$ SYS "MessageTrans_OpenFile",filedesc%,filedesc%+16,buffer%
where FNalloc() allocates a buffer of a given size, by using the Wimp_SlotSize or 'END=' command. Note that in fact the filename and file descriptor only need to be in the RMA if R2=0 on entry to MessageTrans_OpenFile.
Furthermore, if R2=0 on entry to this SWI, and the application uses direct pointers into the file (rather than copying the messages out) or uses MessageTrans_MakeMenus, it should also trap Service_MessageFileClosed, in case the file is unloaded.
R0 = pointer to file descriptor passed to MessageTrans_OpenFile, or 0 to use global messages file
R1 = pointer to token, terminated by character 0, 10 or 13
R2 = pointer to buffer to hold result (0 don't copy it)
R3 = size of buffer (if R2 non-zero)
R4 = pointer to parameter 0 (0 don't substitute for '%0')
R5 = pointer to parameter 1 (0 don't substitute for '%1')
R6 = pointer to parameter 2 (0 don't substitute for '%2')
R7 = pointer to parameter 3 (0 don't substitute for '%3')
R0 preserved
R1 = pointer to terminator of token
R2 = pointer to result string (read-only with no substitution if R2=0 on entry)
R3 = size of result before terminator
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call translates a message token into a string, with optional parameter substitution. If the token is not found in the given message file, it is then looked up in the global messages file; see the chapter entitled Global messages.
Your application must have previously called MessageTrans_OpenFile, although you can still call this SWI if the file has been automatically closed by the system, because the system will also automatically re-open the file.
See the chapter entitled Message file format for further details of the file format used to hold message tokens and their corresponding strings.
Sets up a menu structure from a definition containing references to tokens
R0 = pointer to file descriptor passed to MessageTrans_OpenFile, or 0 to use global messages file
R1 = pointer to menu definition (see below)
R2 = pointer to buffer to hold menu structure
R3 = size of buffer
R0, R1 preserved
R2 = pointer to end of constructed menu structure
R3 = bytes remaining in buffer (0 if call was successful)
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call sets up a menu structure from a definition containing references to tokens, and also sets up appropriate widths for the menu and any submenus. Parameter substitution is not allowed.
The menu structure created can then be passed directly to Wimp_CreateMenu.
Your application must have previously called MessageTrans_OpenFile, although you can still call this SWI if the file has been automatically closed by the system, because the system will also automatically re-open the file.
A 'Buffer overflow' error is generated if the buffer provided for the menu structure is too small.
The menu definition consists of one or more submenu definitions, terminated by a null byte. Each submenu definition consists of a title definition followed by one or more menu item definitions. A title definition has the following structure:
Bytes | Meaning |
---|---|
n | token for menu title, terminated by character 0, 10 or 13 |
1 | menu title foreground and frame colour |
1 | menu title background colour |
1 | menu work area foreground colour |
1 | menu work area background colour |
1 | height of following menu items |
1 | vertical gap between items |
and a menu item definition has this structure:
Bytes | Meaning |
---|---|
m | token for menu item, terminated by character 0, 10 or 13 |
word-align to here (addr := (addr+3) AND (NOT 3)) | |
4 | menu flags (bit 7 set last item) |
4 | offset from RAM menu start to RAM submenu start (0 no submenu) |
4 | icon flags |
If the icon flags have bit 8 clear (ie they are not indirected), the message text for the icon will be read into the 12-byte block that forms the icon data; otherwise the icon data will be set up to point to the message text inside the file data. In the latter case they are read-only.
If the menu item flags bit 2 is set (writable) and the icon is indirected, the 3 words of the icondata in the RAM buffer are assumed to have already been set up by the calling program. The result of looking up the message token is copied into the buffer indicated by the first word of the icon data (truncated if it gets bigger than the buffer size indicated in [icondata,#8]).
See the chapter entitled Message file format for further details of the file format used to hold message tokens and their corresponding strings.
For a more complete definition of the flags etc used in the menu definition, see the definition of Wimp_CreateMenu.
None
R0 = pointer to file descriptor passed to MessageTrans_OpenFile
--
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call closes a message file.
None
R0 = pointer to file descriptor passed to MessageTrans_OpenFile
R1 = pointer to (wildcarded) token, terminated by character 0, 10, 13 or ':'
R2 = pointer to buffer to hold result
R3 = size of buffer
R4 = index (zero for first call)
R0, R1 preserved
R2 preserved, or zero if no further matching tokens found
R3 = length of result excluding terminator (if R2 0)
R4 = index for next call (non-zero)
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call successively enumerates tokens that match a wildcarded token. Each successive call places a token in the buffer pointed to by R2, with the same terminator as that used for the wildcarded token that it matches. To enumerate all matching tokens, you should set R4 to zero, and repeatedly call this SWI until R2 is zero on exit.
Valid wildcards in the supplied token are:
Wildcard | Meaning |
---|---|
? | match 1 character |
* | match 0 or more characters |
See the chapter entitled Message file format for further details of the file format used to hold message tokens and their corresponding strings.
You cannot pass R0 = 0 to enumerate the global message tokens.
None
R0 = pointer to error block (word aligned)
R1 = pointer to file descriptor passed to MessageTrans_OpenFile, or 0 to use global messages file
R2 = pointer to buffer to hold result (0 use internal buffer)
R3 = buffer size (if R2 non-zero)
R4 = pointer to parameter 0 (0 don't substitute for '%0')
R5 = pointer to parameter 1 (0 don't substitute for '%1')
R6 = pointer to parameter 2 (0 don't substitute for '%2')
R7 = pointer to parameter 3 (0 don't substitute for '%3')
R0 = pointer to error buffer used
V flag set
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call translates a message token within an error block, with optional parameter substitution. If the token is not found in the given message file, it is then looked up in the global messages file; see the chapter entitled Global messages.
On entry the error block must contain:
Offset | Contents |
---|---|
0 | error number |
4 | null terminated token |
On exit the token is translated to the corresponding string. To test for successful error lookup, you should check the error number returned in the error block.
If R2 is 0 on entry, MessageTrans will use one of its internal buffers for the result. There are 10 buffers for foreground processes and 2 for calls made from within IRQ processes. MessageTrans will cycle between these buffers.
Your application must have previously called MessageTrans_OpenFile, although you can still call this SWI if the file has been automatically closed by the system, because the system will also automatically re-open the file.
See the chapter entitled Message file format for further details of the file format used to hold message tokens and their corresponding strings.
MessageTrans_Lookup, MessageTrans_GSLookup, MessageTrans_CopyError
Translates a message token into a string, GSTrans'ing it
R0 = pointer to file descriptor passed to MessageTrans_OpenFile, or 0 to use global messages file
R1 = pointer to token, terminated by character 0, 10 or 13
R2 = pointer to buffer to hold result (0 don't copy it)
R3 = size of buffer (if R2 non-zero)
R4 = pointer to parameter 0 (0 don't substitute for '%0')
R5 = pointer to parameter 1 (0 don't substitute for '%1')
R6 = pointer to parameter 2 (0 don't substitute for '%2')
R7 = pointer to parameter 3 (0 don't substitute for '%3')
R0, R1 preserved
R2 = pointer to result string (read-only with no substitution if R2=0 on entry)
R3 = size of result before terminator
Interrupts are enabled
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant
This call translates a message token into a string, with optional parameter substitution. If the token is not found in the given message file, it is then looked up in the global messages file; see the chapter entitled Global messages. The string is GSTrans'd after parameter substitution; this needs an intermediate buffer, and so will fail if one cannot be allocated from the RMA.
Your application must have previously called MessageTrans_OpenFile, although you can still call this SWI if the file has been automatically closed by the system, because the system will also automatically re-open the file.
See the chapter entitled Message file format for further details of the file format used to hold message tokens and their corresponding strings.
Calling this SWI with R2=0 is exactly equivalent to calling MessageTrans_Lookup with R2=0
R0 = pointer to error block (word aligned)
R0 = pointer to error buffer used
Interrupt status is unaltered
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant
This call copies an error to one of the MessageTrans internal buffers. There are 10 buffers for foreground processes and 2 for calls made from within IRQ processes. MessageTrans will cycle between these buffers.