This section describes how to create a Charconv plug-in DLL.
The flowchart below shows the steps to create a Charconv plug-in DLL.
An example is used to explain the procedure for creating a Charconv plug-in DLL. This plug-in converts between the cp850 character set and Unicode.
Create a cnvtool source file using a text editor and save it as, for example d:\charconvfiles\data\cp850.txt
. This file contains pairs of hexadecimal numbers. The first number in each pair is the encoding of a character in cp850and the second is the Unicode encoding of the same character.
... 0x00 0x0000 #NULL 0x01 0x0001 #START OF HEADING 0x02 0x0002 #START OF TEXT 0x03 0x0003 #END OF TEXT 0x04 0x0004 #END OF TRANSMISSION 0x05 0x0005 #ENQUIRY 0x06 0x0006 #ACKNOWLEDGE ...
For more information about the syntax of a cnvtool source file, refer to Cnvtool Source File.
Create a cnvtool control file using a text editor and save it as, for example d:\charconvfiles\data\cp850.ctl
. This file specifies the conversion algorithms to convert both ways between ranges of characters, and other information.
Endianness FixedBigEndian ReplacementForUnconvertibleUnicodeCharacters 0x1a # ASCII "substitute" character - must be a single character, and must be little-endian if the "Endianness" above is "Unspecified", otherwise in the same endianness as specified StartForeignVariableByteData # FirstInitialByteValueInRange LastInitialByteValueInRange NumberOfSubsequentBytes 0x00 0xff 0 EndForeignVariableByteData StartForeignToUnicodeData # IncludePriority SearchPriority FirstInputCharacterCodeInRange LastInputCharacterCodeInRange Algorithm Parameters 2 2 0x00 0x7f Direct {} # ASCII 1 1 0x80 0xff KeyedTable16OfIndexedTables16 {} # CP850 EndForeignToUnicodeData StartUnicodeToForeignData # IncludePriority SearchPriority FirstInputCharacterCodeInRange LastInputCharacterCodeInRange Algorithm SizeOfOutputCharacterCodeInBytes Parameters 2 2 0x0000 0x007f Direct 1 {} # ASCII 1 1 0x00A0 0x25A0 KeyedTable1616 1 {} # CP850 EndUnicodeToForeignData
For more information about the syntax of a cnvtool control file, refer to Cnvtool Control File.
Start a command prompt to run cnvtool
on the source and control files as follows:
cd d:\Symbian\epoc32\tools
cnvtool.bat -generateSourceCode d:\charconvfiles\data\cp850.txt d:\charconvfiles\data\cp850.ctl d:\charconvfiles\data\g_cp850.cpp
This process generates a C++ source code file called g_cp850.cpp
. It is referred to as the cnvtool
-generated cpp file. It contains the SCnvConversionData
data structure.
#include <e32std.h> #include <CONVDATA.H> #include <CONVGENERATEDCPP.H> #define ARRAY_LENGTH(aArray) (sizeof(aArray)/sizeof((aArray)[0])) _LIT8(KLit8ReplacementForUnconvertibleUnicodeCharacters, "\x1a"); GLDEF_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters_internal() { return KLit8ReplacementForUnconvertibleUnicodeCharacters; } LOCAL_D const TUint16 keyedTables16OfIndexedTables16_indexedEntries_foreignToUnicode_1[]= { 0x00c7, 0x00fc, ... } LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry keyedTables16OfIndexedTables16_keyedEntries_foreignToUnicode_1[]= { { 0x80, 0xff, keyedTables16OfIndexedTables16_indexedEntries_foreignToUnicode_1 } }; LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_unicodeToForeign_1[]= { { 0x00a0, 0xff }, ... } LOCAL_D const SCnvConversionData::SVariableByteData::SRange foreignVariableByteDataRanges[]= { { 0x00, 0xff, 0, 0 } }; .... GLDEF_D const SCnvConversionData conversionData= { SCnvConversionData::EFixedBigEndian, { ARRAY_LENGTH(foreignVariableByteDataRanges), foreignVariableByteDataRanges }, { ARRAY_LENGTH(foreignToUnicodeDataRanges), foreignToUnicodeDataRanges }, { ARRAY_LENGTH(unicodeToForeignDataRanges), unicodeToForeignDataRanges }, NULL, NULL };
For more information about the command syntax of cnvtool, refer to Cnvtool Command Syntax.
Create a cpp file which implements the CCharacterSetConverterPluginInterface
class.
All of the functions defined in the interface must be implemented by the plug-in DLL. The implementations of ConvertFromUnicode()
and ConvertToUnicode()
must fulfil the following behavioural requirements:
They must return a negative error code (see CCnvCharacterSetConverter::TError
), or the number of elements remaining in the input descriptor which have not been converted.
They must not return an error when the output descriptor is too short or there is a truncated sequence at the end of the input descriptor.
If the output descriptor is full, the input descriptor cannot be fully converted.
If the input descriptor ends with a truncated sequence, such as the first half of a Unicode surrogate pair, the first byte of a multi-byte foreign character set character code, or a truncated escape sequence of a modal foreign character set, it cannot be fully converted.
If the input descriptor consists purely of a truncated sequence they must return CCnvCharacterSetConverter::EErrorIllFormedInput
.
For non-complex character sets, they can call CCnvCharacterSetConverter::DoConvertFromUnicode()
and CCnvCharacterSetConverter::DoConvertToUnicode()
functions respectively.
For complex character sets, for example JIS or Shift-JIS, the CnvUtilities
class provides some utility functions.
To access the two (const) global objects implemented in the cnvtool-generated cpp file, you must include the convgeneratedcpp.h
header file. The SCnvConversionData
object generated can then be used to implement the ConvertFromUnicode()
and ConvertToUnicode()
functions.
Example implementation
#include <e32std.h> #include <charconv.h> #include <convgeneratedcpp.h> #include <ecom/implementationproxy.h> #include <charactersetconverter.h> class CCP850ConverterImpl : public CCharacterSetConverterPluginInterface { public: virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters(); virtual TInt ConvertFromUnicode( CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters); virtual TInt ConvertToUnicode( CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, TDes16& aUnicode, const TDesC8& aForeign, TInt& aState, TInt& aNumberOfUnconvertibleCharacters, TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter); virtual TBool IsInThisCharacterSetL( TBool& aSetToTrue, TInt& aConfidenceLevel, const TDesC8& aSample); static CCP850ConverterImpl* NewL(); virtual ~CCP850ConverterImpl(); private: CCP850ConverterImpl(); }; const TDesC8& CCP850ConverterImpl::ReplacementForUnconvertibleUnicodeCharacters() { return ReplacementForUnconvertibleUnicodeCharacters_internal(); } TInt CCP850ConverterImpl::ConvertFromUnicode( CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters) { return CCnvCharacterSetConverter::DoConvertFromUnicode(conversionData, aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters); } TInt CCP850ConverterImpl::ConvertToUnicode( CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, TDes16& aUnicode, const TDesC8& aForeign, TInt& /*aState*/, TInt& aNumberOfUnconvertibleCharacters, TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter) { return CCnvCharacterSetConverter::DoConvertToUnicode(conversionData, aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter); } TBool CCP850ConverterImpl::IsInThisCharacterSetL( TBool& aSetToTrue, TInt& aConfidenceLevel, const TDesC8& /*aSample*/) { aSetToTrue=ETrue; aConfidenceLevel=0; return EFalse; } CCP850ConverterImpl* CCP850ConverterImpl::NewL() { CCP850ConverterImpl* self = new(ELeave) CCP850ConverterImpl(); return self; } CCP850ConverterImpl::~CCP850ConverterImpl() { } CCP850ConverterImpl::CCP850ConverterImpl() { } const TImplementationProxy ImplementationTable[] = { IMPLEMENTATION_PROXY_ENTRY(0x102825AD, CCP850ConverterImpl::NewL) }; EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) { aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); return ImplementationTable; }
Create an ECom registry resource file using a text editor.
102825ac.rss
#include "ecom/registryinfo.rh" RESOURCE REGISTRY_INFO theInfo { dll_uid = 0x102825AC; // UID acquired from Symbian interfaces = { INTERFACE_INFO { interface_uid = 0x101F7F1D; // fixed UID for Charconv plug-ins implementations = { IMPLEMENTATION_INFO { implementation_uid = 0x102825AD; // UID acquired from Symbian version_no = 1; display_name = "CP850"; default_data = "CP850"; opaque_data = ""; } }; } }; }
Create an mmp file which is used to build the plug-in DLL.
TARGET cp850.dll TARGETTYPE PLUGIN CAPABILITY All -Tcb UID 0x10009D8D 0x102825AC VENDORID 0x70000001 SYSTEMINCLUDE /epoc32/include SOURCEPATH ../src/plugins SOURCE cp850.cpp SOURCEPATH /epoc32/build/generatedcpp/charconv SOURCE g_cp850.cpp SOURCEPATH ../resource START RESOURCE cp850.rss TARGETPATH /resource/charconv LANG sc END START RESOURCE 102825ac.rss TARGET cp850.rsc END LIBRARY euser.lib LIBRARY charconv.lib LIBRARY ecom.lib
Build the plug-in DLL and install it into the \system\charconv\
directory. The DLL is then available to be loaded when CCnvCharacterSetConverter::PrepareToConvertToOrFromL()
is invoked.