This section describes how 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.