/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    MsgTrans.h
    Author:  Copyright  1994 Tony Houghton, 1996 Julian Smith
    Version: 1.10 (12 Jun 1996)
    Purpose: Interface to some of the most useful MessageTrans routines
	History:
		1.02 (05 Nov 1994) TH
		1.10 (12 Jun 1996) JS	Added:
					Desk_MessageTrans_LookupGetSize
					Desk_MessageTrans_LookupIntoBuffer
    					Desk_MessageTrans_LookupIntoBufferPos
    					Desk_MessageTrans_LookupIntoBufferCat
    					Desk_MessageTrans_OpenLookupCloseIntoBufferPos
    					Desk_MessageTrans_OpenLookupCloseIntoBuffer
    					Desk_MessageTrans_OpenLookupCloseIntoBufferCat
    		1.11 (05 Jul 1996) JS	Added
					Desk_MessageTrans_OpenFileRMA
					Desk_MessageTrans_CloseFileRMA
		
		12 Sep 1996 JS		Ammended docs for Desk_MessageTrans_Lookup
					- clarified what to do when not wanting
					data to be copied.

    NOTE: This is a veneer for the OS 'MsgTrans' system. An analogue of
          this system is provided by the 'Msgs' sublibrary (Msgs.h).
          Note that each system has advantages and disavantages compared
          to the other...
*/

#ifndef __Desk_MsgTrans_h
#define __Desk_MsgTrans_h

#ifdef __cplusplus
	extern "C" {
#endif

#include <stdarg.h>

#ifndef __Desk_DeskMem_h
	#include "Desk.DeskMem.h"
#endif


/*K*************************************************************************

> MessageTrans

MessageTrans is Acorn's module for looking up messages in a text file; it
is standard with RISC OS 3 onwards. You may prefer to use it to DeskLib's
Msgs.h to avoid duplicating OS functionality or to gain access to system
Messages files, because Msgs.h has an incompatible token format.

A Messages file has the following structure:

  # Comment lines begin with a #
  Token:Text message with parameters %0 to %3
  Token1
  Token2/Token3:Message with more than one token
  Percent:Message with a percent sign - %%

The final line must have a terminating LF.

PARAMETER SUBSTITUTION: Parameter substitution can be carried out by passing
  up to 4 additional string parameters which are substituted for %0 to %3.

DEFAULT STRINGS: By supplying a token in the form "Token:Default string", if
  the token is not matched in the file, the supplied string is used instead.

WILDCARDED/MULTIPLE TOKENS: A '?' in a token in the file matches any
  character in the token supplied to be matched. A message can have more
  than one token separated by '/' or LF.

DeskLib's MessageTrans library provides low level interfaces to the most
essential of the module's SWIs. The others are unlikely to be useful in the
context of a program written with DeskLib. In addition, there are some
functions prefixed Desk_MsgTrans_ which provide higher level access to the calls.


****************************************************************************/


/*K*************************************************************************

> MsgTrans

A group of functions providing higher level access to MessageTrans SWI
functions. MsgTrans maintains a linked list of message files to allow it to find their
buffers in memory for freeing.


****************************************************************************/


typedef struct {
  int data[4];
} Desk_msgtrans_filedesc;
/*
  Purpose:  A file descriptor block for use with MessageTrans SWIs.
  Fields:   Not available to user.
  SeeAlso:  Desk_MessageTrans_OpenFile; Desk_MessageTrans_Lookup;
            Desk_MessageTrans_CloseFile
*/



extern void	Desk_MessageTrans_FileInfo( const char *filename, int *flags, int *size);
/*
  Purpose:  Get information about a Messages file prior to opening it
  Inputs:   filename - Messages file path name
  Outputs:  *flags   - bit 1 set indicates file is held in memory; all other
                       bits are reserved
            *size    - size of buffer necessary to hold file
  Returns:  Pointer to an error block or NULL if successful
  Errors:   -
  SeeAlso:  Desk_MessageTrans_OpenFile
*/



extern void	Desk_MessageTrans_OpenFile(Desk_msgtrans_filedesc *filedesc,
                                       const char *filename, char *buffer);
/*
  Purpose:  Open or load a Messages file ready for reading
  Inputs:   filedesc - Pointer to a file descriptor block which must be
                         held in the RMA if buffer is NULL on entry
            filename   - Messages file path name; string must be held in the
                         RMA if buffer is NULL on entry
            buffer     - Pointer to buffer to hold file or NULL; in the
                         latter case the file will be used directly if
                         possible, otherwise space will be allocated in the
                         RMA.
  Outputs:  -  
  Returns:  Pointer to an error block or NULL if successful
  Errors:   "Message file already open" if descriptor is in use
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MessageTrans_CloseFile
*/



extern void	Desk_MessageTrans_Lookup(Desk_msgtrans_filedesc *filedesc, const char *token,
                                     char **buffer, int *size,
                                     const char *p0, const char *p1, const char *p2, const char *p3);
/*
  Purpose:  Look up a token in an open Messages file and return its string
  Inputs:   filedesc - pointer to a file descriptor block
            token      - token to match
            *buffer    - a pointer to the buffer to copy the string or NULL
                         if the string is not to be copied
            *size      - size of the buffer
            p0 to p3   - optional parameters (NULL for no substitution)
            Note that 'buffer' and 'size' should both be the address of
            bona-fide variables. If the message is not to be copied, both
            of these variables should contain 0 (so 'buffer' and 'size' will
            both point to words which contain zero).
            
  Outputs:  *buffer    - now points to result string
            *size      - updated to size of result before terminator
  Returns:  Pointer to an error block or NULL if successful
  Errors:   -
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MessageTrans_OpenFile
*/



extern void	Desk_MessageTrans_CloseFile(Desk_msgtrans_filedesc *filedesc);
/*
  Purpose:  Close a Messages file
  Inputs:   filedesc - Pointer to the file descriptor block
  Outputs:  -  
  Returns:  Pointer to an error block or NULL if successful
  Errors:   -
  SeeAlso:  Desk_mesgtrans_filedesc; Desk_MessageTrans_OpenFile
*/





extern void	Desk_MsgTrans_LoadFile(Desk_msgtrans_filedesc **filedesc, const char *filename);
/*
  Purpose:  Allocate space for a Messages file and load it
  Inputs:   filename  - path name of Messages file
  Outputs:  *filedesc - points to file descriptor block
  Returns:  An error if one of the SWIs fails or NULL
  Errors:   As for Desk_MessageTrans_FileInfo and Desk_MessageTrans_OpenFile,
            or 'NoStore' from Resources:Global.Messages
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MessageTrans_FileInfo; Desk_MessageTrans_OpenFile;
              MsgTrans
*/



#define Desk_MsgTrans_Lookup(filedesc, token, buffer, bufflen) \
  Desk_MsgTrans_LookupPS((filedesc), (token), (buffer), (bufflen), \
                    NULL, NULL, NULL, NULL)
/*
  MACRO:    extern Desk_os_error *Desk_MsgTrans_Lookup(Desk_msgtrans_filedesc *filedesc,
                                             char *token,
                                             char *buffer, int bufflen);

  Purpose:  Copy the matched token's string to a buffer and ensure it is NULL
            terminated.
  Inputs:   filedesc - descriptor or NULL for Global messages
            token    - token to match
            buffer   - where to store result
            bufflen  - size of buffer available
  Outputs:  *buffer - result string is copied here
  Returns:  An error if Desk_MessageTrans_Lookup fails or NULL
  Errors:   As for Desk_MessageTrans_Lookup
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MessageTrans_Lookup; MsgTrans
*/



extern void	Desk_MsgTrans_LookupPS(Desk_msgtrans_filedesc *filedesc, const char *token,
                                   char *buffer, int bufflen,
                                   const char *p0, const char *p1, const char *p2, const char *p3);
/*
  Purpose:  Desk_MsgTrans_Lookup with parameter substitution
  Inputs:   filedesc - descriptor or NULL for Global messages
            token    - token to match
            buffer   - where to store result
            bufflen  - size of buffer available
            p0 to p3 - strings to substitute in result or NULL
  Outputs:  *buffer - result string is copied here
  Returns:  An error if Desk_MessageTrans_Lookup fails or NULL
  Errors:   As for Desk_MessageTrans_Lookup
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MessageTrans_Lookup; Desk_MsgTrans_Lookup; MsgTrans
*/



extern void	Desk_MsgTrans_LoseFile(Desk_msgtrans_filedesc *filedesc);
/*
  Purpose:  Closes a Messages file and frees memory used
  Inputs:   block - pointer to Desk_msgtrans_block for file
  Outputs:  -
  Returns:  Pointer to an error block or NULL if successful
  Errors:   As for Desk_MessageTrans_CloseFile
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MsgTrans_LoadFile; Desk_MessageTrans_CloseFile;
            MsgTrans
*/



#define Desk_MsgTrans_Report(filedesc, token, fatal) \
  Desk_MsgTrans_ReportPS((filedesc), (token), (fatal), 0, 0, 0, 0)
/*
  MACRO:    extern Desk_os_error *Desk_MsgTrans_Report(Desk_msgtrans_filedesc *filedesc,
                                             char *token, Desk_bool fatal);

  Purpose:  Looks up a message into an internal buffer and passes it to
            Desk_Error_Report or Desk_Error_ReportFatal
  Inputs:   filedesc - file descriptor
            token    - token to match
            fatal    - whether to call Desk_Error_Report or Desk_Error_ReportFatal
  Outputs:  -
  Returns:  Pointer to an error block or NULL if successful
  Errors:   As for Desk_MessageTrans_Lookup
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MsgTrans_Lookup; Desk_MsgTrans_ReportPS; MsgTrans;
            Desk_Error_Report; Desk_Error_ReportFatal
*/



extern void	Desk_MsgTrans_ReportPS(Desk_msgtrans_filedesc *filedesc, const char *token,
                                   Desk_bool fatal,
                                   const char *p0, const char *p1, const char *p2, const char *p3);
/*
  Purpose:  Looks up a message with parameter substitution into an
            internal buffer and passes it to Desk_Error_Report or Desk_Error_ReportFatal
  Inputs:   filedesc - file descriptor
            token    - token to match
            fatal    - whether to call Desk_Error_Report or Desk_Error_ReportFatal
  Outputs:  -
  Returns:  Pointer to an error block or NULL if successful
  Errors:   As for Desk_MessageTrans_Lookup
  SeeAlso:  Desk_msgtrans_filedesc; Desk_MsgTrans_LookupPS; Desk_MsgTrans_Report; MsgTrans;
            Desk_Error_Report; Desk_Error_ReportFatal
*/






int	Desk_MessageTrans_LookupGetSize( 
		Desk_msgtrans_filedesc*	filedesc, 
		const char*		token, 
		const char*		p0, 
		const char*		p1, 
		const char*		p2, 
		const char*		p3
		);
/*
Returns the length of the string that would be generated when 'token' is
expanded with p0-p3. This length excludes the terminating '\0'.

At the moment (12 Jun 1996), this works by trying temporary buffer sizes
of 32,64, 128, ... until the returned text doesn't fill the buffer.
 */


void	Desk_MessageTrans_LookupIntoBuffer( 
		Desk_deskmem_buffer*	buffer,
		Desk_msgtrans_filedesc*	filedesc,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
Expands token into buffer, ensuring buffer is large enough.
 */


void	Desk_MessageTrans_LookupIntoBufferPos( 
		Desk_deskmem_buffer*	buffer,
		int			pos,
		Desk_msgtrans_filedesc*	filedesc,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
Expands 'token' into 'buffer' starting at pos 'pos', after ensuring
'buffer' is large enough.
 */


void	Desk_MessageTrans_LookupIntoBufferCat( 
		Desk_deskmem_buffer*	buffer,
		Desk_msgtrans_filedesc*	filedesc,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
Appends expanded token to end of string in 'buffer'.
*/


void	Desk_MessageTrans_OpenLookupCloseIntoBufferPos( 
		Desk_deskmem_buffer*	buffer,
		int			pos,
		const char*		filename,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
As Desk_MessageTrans_LookupIntoBufferPos, except that the messages file
is opened, the lookup performed, and then closed again.
 */


void	Desk_MessageTrans_OpenLookupCloseIntoBuffer( 
		Desk_deskmem_buffer*	buffer,
		const char*		filename,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
As Desk_MessageTrans_LookupIntoBuffer, except that the messages file
is opened, the lookup performed, and then closed again.
 */




void	Desk_MessageTrans_OpenLookupCloseIntoBufferCat( 
		Desk_deskmem_buffer*	buffer,
		const char*		filename,
		const char*		token,
		const char*		p0,
		const char*		p1,
		const char*		p2,
		const char*		p3
		);
/*
As Desk_MessageTrans_LookupIntoBufferCat, except that the messages file
is opened, the lookup performed, and then closed again.
 */



typedef struct	{
	char*			filename;
	Desk_msgtrans_filedesc*	desc;
	}
	Desk_msgtrans_rmafiledesc;
/*
Used with Desk_MessageTrans_OpenFileRMA and
Desk_MessageTrans_CloseFileRMA.

For safety, you should initialise a Desk_msgtrans_rmafiledesc to NULLs
before use. Eg:

Desk_msgtrans_rmafiledesc	messages = { NULL, NULL};
 */


void	Desk_MessageTrans_OpenFileRMA( Desk_msgtrans_rmafiledesc* filedesc, const char* filename);
/*
Opens a message file, instructing MessageTrans to buffer the file
automatically in the RMA. For such use, MessageTrans requires that the
Desk_msgtrans_filedesc and filename are stored in the RMA (see PRMs
3-743), so 'filename' is copied into a block of RMA, and a
'Desk_msgtrans_filedesc' is also allocated in the RMA.

To use message file, call Desk_MessageTrans_Lookup etc with
'filedesc->desc'.
 */

void	Desk_MessageTrans_CloseFileRMA( Desk_msgtrans_rmafiledesc* filedesc);
/*
Closes and frees all RMA memory associated with 'filedesc'.
 */



int	Desk_MessageTrans_Lookupvf( char* buffer, Desk_msgtrans_filedesc *filedesc, const char *token, va_list va);
/*
As Desk_MessageTrans_Loopupf, accept takes a va_list rather than
variadic parameters directly.
 */


int	Desk_MessageTrans_Lookupf( char* buffer, Desk_msgtrans_filedesc *filedesc, const char *token, ...);
/*
Gets text corresponding to 'token' from 'filedesc' and does an vsprintf
into the specified buffer.

Important: The string corresponding to 'token' in the messages file must
be 0-terminated.

Returns the value returned by vsprintf().
 */


char*	Desk_MessageTrans_LookupvfStatic( Desk_msgtrans_filedesc *filedesc, const char *token, va_list va);
/*
As Desk_MessageTrans_Lookupf2, accept takes a va_list rather than
variadic parameters directly.
 */

char*	Desk_MessageTrans_LookupfStatic( Desk_msgtrans_filedesc *filedesc, const char *token, ...);
/*
As Desk_MessageTrans_Lookupf, except uses Desk_MessageTrans_LookupStatic
and its internal buffer.
 */


char*	Desk_MessageTrans_LookupStatic( 
		Desk_msgtrans_filedesc	*filedesc, 
		const char		*token, 
		const char*		p0, 
		const char*		p1, 
		const char*		p2, 
		const char*		p3
		);
/*
Uses internal 256-byte buffer. If the messages file's string for 'token'
expands to longer then 256 characters (including the terminating 0),
then memory will be corrupted.
 */


#ifdef __cplusplus
}
#endif


#endif
