Merge RCL_3 fixes to Bug 1543,Bug 1860.
/*
* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Implements the characterconversion plug-in
* for ISCII characterset.
*
*/
#include <e32std.h>
#include <charconv.h>
#include <convgeneratedcpp.h>
#include <convutils.h>
//The maximum length of any intermediate buffer allocated for conversion.
const TInt KMaximumLengthOfIntermediateBuffer=5;
//The ISCII ATR code point, used for ISCII script switching mechanism.
const TUint KControlCharacterEscape=0xef;
//The number of Indic scripts supported by the plug-in.
//ISCII in general addresses all the Indic character sets.
const TUint KNumberOfIndicCharactersetsSupported = 1;
//The common reason for panic for all panics raised by the iscii plug-in
_LIT16(KPanicReason,"ISCII Plug-in Panic");
//The escape sequence for ISCII (ATR) is 0xEF and immidiate byte following
//that is the script selection code for Devanagari.
_LIT8(KEscapeSequenceDevanagari,"\xef\x42");
//The sequence for Explicit Halant, in unicode it gets converted to VIRAMA+ZWNJ
_LIT8(KExplicitHalant,"\xe8\xe8");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForExplicitHalant,"\xe8\xfc");
//The sequence for Soft Halant, in unicode it gets converted to VIRAMA+ZWJ
_LIT8(KSoftHalant,"\xe8\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForSoftHalant,"\xe8\xfd");
//Devanagari character Om
_LIT8(KOm,"\xa1\xe9");
////For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForOm,"\xfe");
//Devanagari character Avagraha
_LIT8(KAvagraha,"\xea\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForAvagraha,"\xff");
//Devanagari character VOCALIC RR
_LIT8(KVocalicRr,"\xaa\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicRr,"\x80");
//Devanagari character VOCALIC LL
_LIT8(KVocalicLl,"\xa7\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicLl,"\x81");
//Devanagari character VOCALIC L SIGN
_LIT8(KVocalicLSign,"\xdb\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicLSign,"\x82");
//Devanagari character VOCALIC LL SIGN
_LIT8(KVocalicLlSign,"\xdc\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicLlSign,"\x83");
//Devanagari character VOCALIC L
_LIT8(KVocalicL,"\xa6\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicL,"\x84");
//Devanagari character VOCALIC RR SIGN
_LIT8(KVocalicRrSign,"\xdf\xe9");
//For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
//sequence is converted to intermediate unused iscii code point.
_LIT8(KReplacementForVocalicRrSign,"\x85");
//Unconvertible ISCII character
_LIT8(KIsciiUnconvertibleCharacter,"\xeb");
enum TPanic
{
//The panic raised by ConvertToUnicodeFromModalForeign_Internal() if the input
//conversion flag is CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter
EPanicBadInputConversionFlags=1,
//Panic raised if the buffer does not start with the escape sequence 0xEF
EPanicBadRemainderOfForeign,
//Panic is raised if the length of the search buffer is greater than the length of the
//replacement buffer
EPanicBadReplacementBuffer,
//If the offset of start of the escape sequence is not an unsigned number.
EPanicBadStartOfNextEscapeSequence
};
//The dummy datastructure for the dummy conversion data i.e. used for conversion if the
//script selection code is not supported.
#define ARRAY_LENGTH(aArray) (sizeof(aArray)/sizeof((aArray)[0]))
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_foreignToUnicode_1[]=
{
{
0xa0,
0xfffd
}
};
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_unicodeToForeign_1[]=
{
{
0xfffd,
0xa0
}
};
LOCAL_D const SCnvConversionData::SVariableByteData::SRange foreignVariableByteDataRanges[]=
{
{
0x00,
0xff,
0,
0
}
};
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange foreignToUnicodeDataRanges[]=
{
{
0x00,
0x7f,
SCnvConversionData::SOneDirectionData::SRange::EDirect,
0,
0,
{
0
}
},
{
0xa0,
0xff,
SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616,
0,
0,
{
UData_SKeyedTable1616(keyedTable1616_foreignToUnicode_1)
}
}
};
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange unicodeToForeignDataRanges[]=
{
{
0x0000,
0x007f,
SCnvConversionData::SOneDirectionData::SRange::EDirect,
1,
0,
{
0
}
},
{
0x00a0,
0xffff,
SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616,
1,
0,
{
UData_SKeyedTable1616(keyedTable1616_unicodeToForeign_1)
}
}
};
//The dummy conversion data to be used for conversion if the iscii code sequence is not
//Devanagari (i.e. the script selection code is not 0x42 and something else.
//In this case the ISCII characters are converted to unconvertible characters.
LOCAL_D const SCnvConversionData conversionDataDummy=
{
SCnvConversionData::EFixedBigEndian,
{
ARRAY_LENGTH(foreignVariableByteDataRanges),
foreignVariableByteDataRanges
},
{
ARRAY_LENGTH(foreignToUnicodeDataRanges),
foreignToUnicodeDataRanges
},
{
ARRAY_LENGTH(unicodeToForeignDataRanges),
unicodeToForeignDataRanges
},
NULL,
NULL
};
#ifdef EKA2
///////////////////////////////////////////////////////////////
// 3.1 Code
// INCLUDES
#include <ecom/implementationproxy.h>
#include <charactersetconverter.h>
/**
* The character conversion plug-in implementation for Iscii.
*
* @lib ecom.lib
* @since Series 60 3.1
*/
class CIsciiImplementation : public CCharacterSetConverterPluginInterface
{
public:
//From CCharacterSetConverterPluginInterface
virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters();
//From CCharacterSetConverterPluginInterface
virtual TInt ConvertFromUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
TDes8& aForeign,
const TDesC16& aUnicode,
CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters );
//From CCharacterSetConverterPluginInterface
virtual TInt ConvertToUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aForeign,
TInt&,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter );
//From CCharacterSetConverterPluginInterface
virtual TBool IsInThisCharacterSetL(
TBool& aSetToTrue,
TInt& aConfidenceLevel,
const TDesC8& );
static CIsciiImplementation* NewL();
virtual ~CIsciiImplementation();
private:
CIsciiImplementation();
};
//Checks if a descriptor starts with another descriptor at the begining.
LOCAL_C TBool IsStartOf(const TDesC8& aEscapeSequence, const TDesC8& aBuffer)
{
const TInt lengthOfStart=aEscapeSequence.Length();
return (aBuffer.Length()>=lengthOfStart) && (aBuffer.Left(lengthOfStart)==aEscapeSequence);
}
// -----------------------------------------------------------------------------
// MatchesEscapeSequence()
//If the remainder of the foreign text starts with the passed escapesequence, modifies the remainder of the foreign text
//and sets the homogeneous run buffer that uses the same conversion data.
//The homogeneous run buffer is the buffer that will use a single conversion data, it doesn't contain the attribute code
// neither it contains the script switching code.
//The aRemainderOfForeign buffer
// Returns: ETrue: If the sequence contains the escape sequence
// EFalse: If the sequence does not contain the escape sequence
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool MatchesEscapeSequence(TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun,
TPtrC8& aRemainderOfForeign, const TDesC8& aEscapeSequence)
{
const TInt lengthOfEscapeSequence=aEscapeSequence.Length();
if (IsStartOf(aEscapeSequence, aRemainderOfForeign))
{
aRemainderOfForeign.Set(aRemainderOfForeign.Mid(lengthOfEscapeSequence));
const TInt startOfNextEscapeSequence=aRemainderOfForeign.Locate(KControlCharacterEscape);
if (startOfNextEscapeSequence==KErrNotFound)
{
aHomogeneousRun.Set(aRemainderOfForeign);
aRemainderOfForeign.Set(NULL, 0);
}
else
{
aHomogeneousRun.Set(aRemainderOfForeign.Left(startOfNextEscapeSequence));
aRemainderOfForeign.Set(aRemainderOfForeign.Mid(startOfNextEscapeSequence));
}
aNumberOfForeignBytesConsumed+=lengthOfEscapeSequence;
return ETrue;
}
return EFalse;
}
// -----------------------------------------------------------------------------
// NextHomogeneousForeignRun()
//Matches the escape sequence of each of the elements of the SState array with the remainder of
//foreign text and if the escape sequence matches with the start of remainder of the foreign text,
//then the conversion data is set to the conversion data corresponding to the escape sequence
//Also the homogeneous foreign text for conversion with the same escape sequence is set.
// Returns: ETrue: If length of the remainder of foreign buffer is nonzero.
// EFalse: If length of the remainder of foreign buffer is zero.
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool NextHomogeneousForeignRun(const SCnvConversionData*& aConversionData, TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TArray<CnvUtilities::SState>& aArrayOfStates, TUint& aOutputConversionFlags)
{
TBool returnValue = EFalse;
TBool foundState = EFalse;
__ASSERT_DEBUG((aRemainderOfForeign.Length()==0) || (aRemainderOfForeign[0]==KControlCharacterEscape), User::Panic(KPanicReason,EPanicBadRemainderOfForeign));
if (aRemainderOfForeign.Length()==0)
{
return returnValue;
}
const TInt numberOfStates=aArrayOfStates.Count();
TInt i;
for (i=0; i<numberOfStates; ++i)
{
const CnvUtilities::SState& state=aArrayOfStates[i];
if (MatchesEscapeSequence(aNumberOfForeignBytesConsumed, aHomogeneousRun, aRemainderOfForeign, *state.iEscapeSequence))
{
aConversionData=state.iConversionData;
foundState = ETrue;
}
}
if(!foundState)
{
for (i=0; i<numberOfStates; ++i)
{
if (IsStartOf(aRemainderOfForeign, *aArrayOfStates[i].iEscapeSequence))
{
// aRemainderOfForeign ends with a truncated escape sequence, so ConvertToUnicode cannot convert any more
aOutputConversionFlags|=CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated;
break;
}
}
MatchesEscapeSequence(aNumberOfForeignBytesConsumed,aHomogeneousRun,aRemainderOfForeign,aRemainderOfForeign.Left(2));
aConversionData = &conversionDataDummy;
returnValue = ETrue;
}
if (aHomogeneousRun.Length()>0)
{
returnValue = ETrue;
}
return returnValue;
}
// -----------------------------------------------------------------------------
// ConvertFromUnicodeIntermediateBufferInPlace()
//Default implementation for conversion to the intermediate buffer
//It modifies the unicode buffer before it is converted back to iscii.
//The current implementation of iscii plug-in doesn't require any
//modification to the default implementation
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void ConvertFromUnicodeIntermediateBufferInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
{
CnvUtilities::ConvertFromIntermediateBufferInPlace(aStartPositionInDescriptor, aDescriptor, aNumberOfCharactersThatDroppedOut, KEscapeSequenceDevanagari, 1);
}
// -----------------------------------------------------------------------------
// DoFindAndModifyBuffer()
//Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
//Introduced for handling multibyte iscii sequence.
//Takes the search buffer array and the replacement buffer arrays as input to it and replaces all
//the occurances of the search buffer with the corresponding replace buffer.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void DoFindAndModifyBuffer(TDes8& aModifyBuffer,const TDesC8& aSearchBuffer,const TDesC8& aReplaceBuffer)
{
FOREVER
{
TInt offset;
__ASSERT_ALWAYS((aSearchBuffer.Length()>= aReplaceBuffer.Length()),User::Panic(KPanicReason,EPanicBadReplacementBuffer));
if((offset = aModifyBuffer.Find(aSearchBuffer)) != KErrNotFound)
{
TUint8 *pointerToBuffer = const_cast<TUint8*> (aModifyBuffer.Ptr());
Mem::Copy(pointerToBuffer+offset,aReplaceBuffer.Ptr(),aReplaceBuffer.Length());
Mem::Copy(pointerToBuffer+offset+aReplaceBuffer.Length(),pointerToBuffer+offset+aSearchBuffer.Length(),aModifyBuffer.Length()-aSearchBuffer.Length()-offset);
aModifyBuffer.SetLength(aModifyBuffer.Length() - aSearchBuffer.Length() + aReplaceBuffer.Length());
}
else
break;
}
}
// -----------------------------------------------------------------------------
// FindAndModifyBuffer()
//Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
//Calls DoFindAndModifyBuffer() and supplies the search buffer and replacement buffer.
//Introduced for handling multibyte iscii sequence.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void FindAndModifyBuffer(TDes8& aModifyBuffer)
{
RArray<TPtrC8> searchBuffer;
RArray<TPtrC8> replaceBuffer;
//If the passed buffer contains the replacement buffer,
//Then it should not get converted to respective Unicode
//buffer rather it should get converted to replacement for
//unconvertible character.
searchBuffer.Append(KReplacementForExplicitHalant().Right(1));
searchBuffer.Append(KReplacementForSoftHalant().Right(1));
searchBuffer.Append(KReplacementForOm().Right(1));
searchBuffer.Append(KReplacementForAvagraha().Right(1));
searchBuffer.Append(KReplacementForVocalicRr().Right(1));
searchBuffer.Append(KReplacementForVocalicLl().Right(1));
searchBuffer.Append(KReplacementForVocalicLSign().Right(1));
searchBuffer.Append(KReplacementForVocalicLlSign().Right(1));
searchBuffer.Append(KReplacementForVocalicL().Right(1));
searchBuffer.Append(KReplacementForVocalicRrSign().Right(1));
//All normal search buffers
searchBuffer.Append(KExplicitHalant().Mid(0));
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
searchBuffer.Append(KVocalicRr().Mid(0));
searchBuffer.Append(KVocalicLl().Mid(0));
searchBuffer.Append(KVocalicLSign().Mid(0));
searchBuffer.Append(KVocalicLlSign().Mid(0));
searchBuffer.Append(KVocalicL().Mid(0));
searchBuffer.Append(KVocalicRrSign().Mid(0));
//The replacement buffer for the odd cases to restrict the
//replacement buffers not to get converted to the corresponding
//unicode buffer
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
//All normal replace buffers
replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
replaceBuffer.Append(KReplacementForOm().Mid(0));
replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
replaceBuffer.Append(KReplacementForVocalicRr().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLl().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLSign().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLlSign().Mid(0));
replaceBuffer.Append(KReplacementForVocalicL().Mid(0));
replaceBuffer.Append(KReplacementForVocalicRrSign().Mid(0));
for(TInt counter=0;counter<searchBuffer.Count();counter++)
{
DoFindAndModifyBuffer(aModifyBuffer,searchBuffer[counter],replaceBuffer[counter]);
}
searchBuffer.Reset();
replaceBuffer.Reset();
}
// -----------------------------------------------------------------------------
// DoNormalizeReturnValue()
//Modifies the return value(Number of bytes did not get converted) according to the modified
//intermediate buffer. Takes the modified intermediate buffer, return value, search and replace
//buffers. Searches for the replace buffer in the intermediate buffer and if found, it looks for
//the actual buffer corresponding to the replace buffer and adds the difference of the lengths
//of the actual to replace buffer to the return value.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void DoNormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer,RArray<TPtrC8>& anArrayOfSearches,RArray<TPtrC8>& anArrayOfReplaces)
{
TPtr8 buffer(const_cast<TUint8*>(aBuffer.Ptr()),aBuffer.Length(),aBuffer.Length());
TUint count = anArrayOfSearches.Count();
FOREVER
{
TBool flag = EFalse;
for(TUint i=0;i<count;i++)
{
TPtrC8 searchBufferForComparison(buffer.Right(anArrayOfReplaces[i].Length()));
TInt returnCompare = searchBufferForComparison.Compare(anArrayOfReplaces[i]);
if(returnCompare == 0)
{
flag =ETrue;
aReturnValue += (anArrayOfSearches[i].Length() - anArrayOfReplaces[i].Length());
buffer=buffer.MidTPtr(0,buffer.Length()-anArrayOfReplaces[i].Length());
break;
}
}
if(buffer.Length() == 0)
{
break;
}
if(!flag)
{
buffer=buffer.MidTPtr(0,buffer.Length()-1);
}
}
}
// -----------------------------------------------------------------------------
// NormalizeReturnValue()
//Modifies the return value(Number of bytes did not get converted) according to the
//replacements done to the iscii buffer before conversion.
//Internally calls DoNormalizeReturnValue() by suppling the search and replacement
//buffers.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void NormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer)
{
RArray<TPtrC8> searchBuffer;
RArray<TPtrC8> replaceBuffer;
searchBuffer.Append(KExplicitHalant().Mid(0));
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
searchBuffer.Append(KVocalicRr().Mid(0));
searchBuffer.Append(KVocalicLl().Mid(0));
searchBuffer.Append(KVocalicLSign().Mid(0));
searchBuffer.Append(KVocalicLlSign().Mid(0));
searchBuffer.Append(KVocalicL().Mid(0));
searchBuffer.Append(KVocalicRrSign().Mid(0));
replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
replaceBuffer.Append(KReplacementForOm().Mid(0));
replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
replaceBuffer.Append(KReplacementForVocalicRr().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLl().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLSign().Mid(0));
replaceBuffer.Append(KReplacementForVocalicLlSign().Mid(0));
replaceBuffer.Append(KReplacementForVocalicL().Mid(0));
replaceBuffer.Append(KReplacementForVocalicRrSign().Mid(0));
DoNormalizeReturnValue(aReturnValue,aBuffer,searchBuffer,replaceBuffer);
searchBuffer.Reset();
replaceBuffer.Reset();
}
// -----------------------------------------------------------------------------
// HandleHomogeneousRun()
//Handles a homogeneous foreign buffer and converts the foreign buffer to unicode
//On return the aUnicode argument contains the converted unicode data.
//Also it sets the return value, returned from the conversion. The return value also
//takes into account if there is any buffer modification done before passing it to
//CCnvCharacterSetConverter::DoConvertToUnicode()
//buffers.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void HandleHomogeneousRun(const SCnvConversionData*& aConversionData,
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aHomogeneousForeign,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
TUint& aOutputConversionFlags,
TUint aInputConversionFlags,TInt& aNumberOfForeignBytesConsumed,
TInt& aReturnValue)
{
TInt numberOfUnconvertibleCharacters;
TInt indexOfFirstByteOfFirstUnconvertibleCharacter;
TUint noOfConsumedBytes = 0;
if(aConversionData == NULL)
{
aReturnValue = CCnvCharacterSetConverter::EErrorIllFormedInput;
return;
}
aReturnValue = CCnvCharacterSetConverter::DoConvertToUnicode(*aConversionData,aDefaultEndiannessOfForeignCharacters,
aUnicode,aHomogeneousForeign,numberOfUnconvertibleCharacters,
indexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,
//The numberOfUnconvertibleCharacters and indexOfFirstByteOfFirstUnconvertibleCharacter are the values with
//respect to the intermediate iscii buffer and original values aIndexOfFirstByteOfFirstUnconvertibleCharacter and
//aNumberOfUnconvertibleCharacters need to be adjusted accordingly.
aInputConversionFlags);
if(numberOfUnconvertibleCharacters>0)
{
if(aNumberOfUnconvertibleCharacters == 0)
{
aIndexOfFirstByteOfFirstUnconvertibleCharacter = aNumberOfForeignBytesConsumed + indexOfFirstByteOfFirstUnconvertibleCharacter;
}
aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters;
}
noOfConsumedBytes = aHomogeneousForeign.Length();
//To Check whether it is really required.
NormalizeReturnValue(noOfConsumedBytes,aHomogeneousForeign);
aNumberOfForeignBytesConsumed+=noOfConsumedBytes;
if(aReturnValue>0)
{
TUint normalizedReturnValue = aReturnValue;
//There original iscii buffer copied to an intermediate iscii buffer and then modified
//and is then passed for conversion. Now, after conversion, the return value needs to
//be adjusted according to the original buffer. NormalizeReturnValue() does the
//same thing.
NormalizeReturnValue(normalizedReturnValue,aHomogeneousForeign);
aNumberOfForeignBytesConsumed-=normalizedReturnValue;
aReturnValue=normalizedReturnValue;
}
//The HandleHomogeneousRun() method is called in a loop and once there is some
//iscii codes converted to unicode, the ConvertToUnicode() should not return
//CCnvCharacterSetConverter::EErrorIllFormedInput even though the conversion
//method does not convert any of the iscii codes ppassed. To ensure that once the
//first non-zero number of iscii codes are converted, the internal input conversion
//flag is set to EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable.
if(aNumberOfForeignBytesConsumed>0)
{
aInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable;
}
return;
}
// -----------------------------------------------------------------------------
// IsTruncatedDoubleByteIsciiSequence()
//Checks if anIsciiBuffer is a part of multi byte iscii sequence truncated in the middle.
//If it is a truncated sequence, then returns ETrue else returns EFalse.
//
// Returns: ETrue: If the intermediate input iscii buffer is truncated
// EFalse: If the intermediate input iscii buffer is not truncated
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool IsTruncatedDoubleByteIsciiSequence(const TDesC8& anIsciiBuffer)
{
RArray<TPtrC8> searchBuffer;
if(anIsciiBuffer.Length () == 0)
return EFalse;
if(anIsciiBuffer[anIsciiBuffer.Length()-1] == 0xEF)
return ETrue;
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
searchBuffer.Append(KExplicitHalant().Mid(0));
TBool ret = EFalse;
TBool isNotTruncated =EFalse;
//First check if the intermediate iscii buffer is ending with a complete multi byte sequence.
//If it ends with a complete multi byte sequence, no need to check if the last character of
//intermediate iscii is same as first character of multi byte iscii sequence. And return EFalse.
for(TUint counter = 0;counter<searchBuffer.Count();counter++)
{
if(searchBuffer[counter].Compare(anIsciiBuffer.Right(searchBuffer[counter].Length())) == 0)
{
isNotTruncated = ETrue;
break;
}
}
//If the intermediate iscii buffer is not ending with a complete multi byte sequence, and the
//last code of the iscii buffer is a part of the multibyte sequence, then the iscii buffer is a
//truncated sequence and in that case return ETrue.
for(TUint counter = 0;counter<searchBuffer.Count();counter++)
{
if(isNotTruncated)
break;
else if( (anIsciiBuffer[anIsciiBuffer.Length()-1] == searchBuffer[counter][0]))
{
ret =ETrue;
break;
}
}
searchBuffer.Reset();
return ret;
}
// -----------------------------------------------------------------------------
// ReplacementForUnconvertibleUnicodeCharacters()
//Returns the replacement character for unconvertible unicode character.
//In the current implementation it is 0x1a (ASCII Substitute character)
//The default implementation calls ReplacementForUnconvertibleUnicodeCharacters_internal()
//in turn which is generated by cnvtool.
//
// Returns: Replacemt for unconvertible unicode characters (0x1a)
//
// -----------------------------------------------------------------------------
//
const TDesC8& CIsciiImplementation::ReplacementForUnconvertibleUnicodeCharacters()
{
return ReplacementForUnconvertibleUnicodeCharacters_internal();
}
// -----------------------------------------------------------------------------
// ConvertFromUnicode()
//The main conversion function for converting from unicode to iscii
//Loaded and called by the character conversion framework.
//In turn calls CnvUtilities::ConvertFromUnicode() which is Symbian provide
//utility method for converting unicode to modal character codes.
//
// Returns: The numbet of unicode codes it could not convert.
//
// -----------------------------------------------------------------------------
//
TInt CIsciiImplementation::ConvertFromUnicode(
CCnvCharacterSetConverter::TEndianness
aDefaultEndiannessOfForeignCharacters,
const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
TDes8& aForeign,
const TDesC16& aUnicode,
CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters )
{
TFixedArray<CnvUtilities::SCharacterSet,KNumberOfIndicCharactersetsSupported> aArrayOfCharacterSets;
aArrayOfCharacterSets[0].iConversionData = &conversionData;
aArrayOfCharacterSets[0].iConvertFromIntermediateBufferInPlace = ConvertFromUnicodeIntermediateBufferInPlace;
aArrayOfCharacterSets[0].iEscapeSequence = &KEscapeSequenceDevanagari();
return CnvUtilities::ConvertFromUnicode(
aDefaultEndiannessOfForeignCharacters,
aReplacementForUnconvertibleUnicodeCharacters,
aForeign,
aUnicode,
aIndicesOfUnconvertibleCharacters,
aArrayOfCharacterSets.Array());
}
// -----------------------------------------------------------------------------
// ConvertToUnicode()
//The main conversion function for converting from iscii to unicode
//Loaded and called by the character conversion framework.
//To support some of the iscii characters, the input forign buffer is
//copied to an intermediate buffer and then is then modified and
//CCnvCharactersetConverter::DoConvertToUnicode() is called with
//the modified buffer. For extensibility of iscii to other Indic languages
//it uses CnvUtilities::SState datastructure. CnvUtilities::SState is a
//Symbian defined class for modal charactersets. The escape sequence
//is specified to ATR followed by the script selection code and the conversion
//data is specified to be the conversion for the particular script. For the time
//being only Devanagari with script selection code 0x42 is supported. If
//any of the other script codes are used the conversion leads to unconvertible
//character i.e. 0xFFFD.
// Returns: The numbet of iscii codes it could not convert.
//
// -----------------------------------------------------------------------------
//
TInt CIsciiImplementation::ConvertToUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aForeign,
TInt& aState,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter )
{
aNumberOfUnconvertibleCharacters = 0;
TUint aOutputConversionFlags;
aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
TUint internalInputConversionFlags = 0;
TInt numberOfForeignBytesConsumed=0;
TPtrC8 remainderOfForeign(aForeign);
TInt returnValue;
TBool flag = EFalse;
TBool isSkipMatchSequence = EFalse;
const SCnvConversionData* convData;
//Set the iscii conversion data and escape sequence for Devanagari.
TFixedArray<CnvUtilities::SState,KNumberOfIndicCharactersetsSupported> modals;
modals[0].iConversionData = &conversionData;
modals[0].iEscapeSequence = &KEscapeSequenceDevanagari();
aUnicode.SetLength(0);
//The internal input conversion flag for conversion is set to CCnvCharacterSetConverter::EInputConversionFlagAppend
//so that for each conversion in the conversion loop, the generated conversion buffer is appened to the aUnicode buffer.
internalInputConversionFlags |= CCnvCharacterSetConverter::EInputConversionFlagAppend;
if (aForeign.Length()==0)
{
return 0;
}
//Get the conversion data from the previous call else the conversion data is set to the default
//conversion data, i.e. Devanagari.
convData=(aState!=CCnvCharacterSetConverter::KStateDefault)? REINTERPRET_CAST(const SCnvConversionData*, aState): modals[0].iConversionData;
FOREVER
{
TBuf8<KMaximumLengthOfIntermediateBuffer> intermediateBuffer;
TUint numberOfForeignBytesConsumedThisTime = 0;
if((remainderOfForeign.Length() >=KMaximumLengthOfIntermediateBuffer) && (aUnicode.MaxLength()-aUnicode.Length() >=KMaximumLengthOfIntermediateBuffer))
{
numberOfForeignBytesConsumedThisTime = KMaximumLengthOfIntermediateBuffer;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
//If the intermediate buffer is a part of truncated buffer sequence but the
//actual input buffer is not truncated then truncated sequence is not converted.
//The intermediate buffer is modified so as not to contain the truncated sequence.
flag = IsTruncatedDoubleByteIsciiSequence(intermediateBuffer);
if(flag)
{
numberOfForeignBytesConsumedThisTime --;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
}
else
{
flag = IsTruncatedDoubleByteIsciiSequence(remainderOfForeign.Left(aUnicode.MaxLength()-aUnicode.Length()));
if(!flag)
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
else
{
if(aForeign.Length()>(numberOfForeignBytesConsumed+aUnicode.Length()))
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length()-1;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
break;
}
else
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
}
}
//The input intermediate iscii buffer is modified with the search and replace
//buffers. It is required for supporting multibyte iscii sequences.
FindAndModifyBuffer(intermediateBuffer);
TPtrC8 remainderOfForeignInternal(intermediateBuffer);
TPtrC8 homogeneousRun;
const TInt startOfNextEscapeSequence=intermediateBuffer.Locate(KControlCharacterEscape);
if (startOfNextEscapeSequence!=0)
{
if (startOfNextEscapeSequence==KErrNotFound)
{
homogeneousRun.Set(remainderOfForeignInternal);
remainderOfForeignInternal.Set(NULL, 0);
}
else
{
__ASSERT_DEBUG(startOfNextEscapeSequence>0, User::Panic(KPanicReason,EPanicBadStartOfNextEscapeSequence));
homogeneousRun.Set(remainderOfForeignInternal.Left(startOfNextEscapeSequence));
remainderOfForeignInternal.Set(remainderOfForeignInternal.Mid(startOfNextEscapeSequence));
}
isSkipMatchSequence = ETrue;
}
FOREVER
{
if(!isSkipMatchSequence)
{
if (!NextHomogeneousForeignRun(convData, numberOfForeignBytesConsumed, homogeneousRun,
remainderOfForeignInternal, modals.Array(), aOutputConversionFlags))
{
break;
}
}
HandleHomogeneousRun( convData, aDefaultEndiannessOfForeignCharacters, aUnicode, homogeneousRun, aNumberOfUnconvertibleCharacters,
aIndexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,internalInputConversionFlags,
numberOfForeignBytesConsumed,returnValue);
if(returnValue<0)
{
return returnValue;
}
isSkipMatchSequence = EFalse;
}
if(returnValue > 0)
break;
if ((!flag && (numberOfForeignBytesConsumedThisTime != KMaximumLengthOfIntermediateBuffer)) || (flag && (numberOfForeignBytesConsumedThisTime != (KMaximumLengthOfIntermediateBuffer-1) )))
break;
remainderOfForeign.Set(aForeign.Mid(numberOfForeignBytesConsumed));
}
//If the number of iscii bytes consumed by the conversion is zero also the output conversion
//flag is not set to EOutputConversionFlagInputIsTruncated, then return EErrorIllFormedInput.
if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated))
{
return CCnvCharacterSetConverter::EErrorIllFormedInput;
}
//Set the conversion data sothat next time when ConvertToUnicode() is called,
//will use the previous conversion data.
aState=REINTERPRET_CAST(TInt, convData);
return aForeign.Length()-numberOfForeignBytesConsumed;
}
// -----------------------------------------------------------------------------
// IsInThisCharacterSetL()
//The method tells how probable it is that a sample piece of text is encoded in this character set.
//On return aConfidenceLevel, indicates how confident the function is about its return value. For
//iscii it is the default implementation and it does not implement the autodetect functionality.
//Loaded and called by the character conversion framework.
//
// Returns: EFalse: To tell CCnvCharacterSetConverter::AutoDetectCharacterSetL() that the plug-in DLL
// is not implementing a function of this signature and is therefore empty.
//
// -----------------------------------------------------------------------------
//
//Default implementation for IsInThisCharacterSetL()
TBool CIsciiImplementation::IsInThisCharacterSetL(
TBool& aSetToTrue,
TInt& aConfidenceLevel,
const TDesC8& )
{
aSetToTrue = EFalse;
aConfidenceLevel = 0;
return EFalse;
}
// -----------------------------------------------------------------------------
// NewL()
//Factory function for CIsciiImplementation(). Instantiates a CIsciiImplementation object on heap
//and returns the pointer to it.
//
// Returns: CIsciiImplementation*
//
// -----------------------------------------------------------------------------
//
CIsciiImplementation* CIsciiImplementation::NewL()
{
CIsciiImplementation* self = new(ELeave) CIsciiImplementation;
return self;
}
// -----------------------------------------------------------------------------
// CIsciiImplementation()
//default constructor, does nothing
//
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
CIsciiImplementation::CIsciiImplementation()
{
}
// -----------------------------------------------------------------------------
// ~CIsciiImplementation()
//default desstructor, does nothing
//
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
CIsciiImplementation::~CIsciiImplementation()
{
}
// ECOM CREATION FUNCTION
const TImplementationProxy ImplementationTable[] =
{
// Used also in 0x1027508E.rss ( implementation_uid )
IMPLEMENTATION_PROXY_ENTRY( 0x1027508E, CIsciiImplementation::NewL )
};
// -----------------------------------------------------------------------------
// ImplementationGroupProxy()
//Returns a pointer to TImplementationProxy object which contains the implementation uid vs factory
//function table. Also on return sets the aTableCount to the number of entries in the table.
//
// Returns: TImplementationProxy*
//
// -----------------------------------------------------------------------------
//
EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount )
{
aTableCount = sizeof( ImplementationTable ) / sizeof(TImplementationProxy);
return ImplementationTable;
}
#else
#include <convplug.h>
#ifndef EKA2
// -----------------------------------------------------------------------------
// E32Dll()
//For EKA1 this is the entry point for the DLL.
//
// Returns: KErrNone
//
// -----------------------------------------------------------------------------
//
GLDEF_C TInt E32Dll(TDllReason)
{
return KErrNone;
}
#endif
//Checks if a descriptor starts with another descriptor at the begining.
LOCAL_C TBool IsStartOf(const TDesC8& aEscapeSequence, const TDesC8& aBuffer)
{
const TInt lengthOfStart=aEscapeSequence.Length();
return (aBuffer.Length()>=lengthOfStart) && (aBuffer.Left(lengthOfStart)==aEscapeSequence);
}
// -----------------------------------------------------------------------------
// MatchesEscapeSequence()
//If the remainder of the foreign text starts with the passed escapesequence, modifies the remainder of the foreign text
//and sets the homogeneous run buffer that uses the same conversion data.
//The homogeneous run buffer is the buffer that will use a single conversion data, it doesn't contain the attribute code
// neither it contains the script switching code.
//The aRemainderOfForeign buffer
// Returns: ETrue: If the sequence contains the escape sequence
// EFalse: If the sequence does not contain the escape sequence
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool MatchesEscapeSequence(TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun,
TPtrC8& aRemainderOfForeign, const TDesC8& aEscapeSequence)
{
const TInt lengthOfEscapeSequence=aEscapeSequence.Length();
if (IsStartOf(aEscapeSequence, aRemainderOfForeign))
{
aRemainderOfForeign.Set(aRemainderOfForeign.Mid(lengthOfEscapeSequence));
const TInt startOfNextEscapeSequence=aRemainderOfForeign.Locate(KControlCharacterEscape);
if (startOfNextEscapeSequence==KErrNotFound)
{
aHomogeneousRun.Set(aRemainderOfForeign);
aRemainderOfForeign.Set(NULL, 0);
}
else
{
aHomogeneousRun.Set(aRemainderOfForeign.Left(startOfNextEscapeSequence));
aRemainderOfForeign.Set(aRemainderOfForeign.Mid(startOfNextEscapeSequence));
}
aNumberOfForeignBytesConsumed+=lengthOfEscapeSequence;
return ETrue;
}
return EFalse;
}
// -----------------------------------------------------------------------------
// NextHomogeneousForeignRun()
//Matches the escape sequence of each of the elements of the SState array with the remainder of
//foreign text and if the escape sequence matches with the start of remainder of the foreign text,
//then the conversion data is set to the conversion data corresponding to the escape sequence
//Also the homogeneous foreign text for conversion with the same escape sequence is set.
// Returns: ETrue: If length of the remainder of foreign buffer is nonzero.
// EFalse: If length of the remainder of foreign buffer is zero.
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool NextHomogeneousForeignRun(const SCnvConversionData*& aConversionData, TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TArray<CnvUtilities::SState>& aArrayOfStates, TUint& aOutputConversionFlags)
{
TBool returnValue = EFalse;
TBool foundState = EFalse;
__ASSERT_DEBUG((aRemainderOfForeign.Length()==0) || (aRemainderOfForeign[0]==KControlCharacterEscape), User::Panic(KPanicReason,EPanicBadRemainderOfForeign));
if (aRemainderOfForeign.Length()==0)
{
return returnValue;
}
const TInt numberOfStates=aArrayOfStates.Count();
TInt i;
for (i=0; i<numberOfStates; ++i)
{
const CnvUtilities::SState& state=aArrayOfStates[i];
if (MatchesEscapeSequence(aNumberOfForeignBytesConsumed, aHomogeneousRun, aRemainderOfForeign, *state.iEscapeSequence))
{
aConversionData=state.iConversionData;
foundState = ETrue;
}
}
if(!foundState)
{
for (i=0; i<numberOfStates; ++i)
{
if (IsStartOf(aRemainderOfForeign, *aArrayOfStates[i].iEscapeSequence))
{
// aRemainderOfForeign ends with a truncated escape sequence, so ConvertToUnicode cannot convert any more
aOutputConversionFlags|=CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated;
break;
}
}
MatchesEscapeSequence(aNumberOfForeignBytesConsumed,aHomogeneousRun,aRemainderOfForeign,aRemainderOfForeign.Left(2));
aConversionData = &conversionDataDummy;
returnValue = ETrue;
}
if (aHomogeneousRun.Length()>0)
{
returnValue = ETrue;
}
return returnValue;
}
// -----------------------------------------------------------------------------
// ConvertFromUnicodeIntermediateBufferInPlace()
//Default implementation for conversion to the intermediate buffer
//It modifies the unicode buffer before it is converted back to iscii.
//The current implementation of iscii plug-in doesn't require any
//modification to the default implementation
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void ConvertFromUnicodeIntermediateBufferInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
{
CnvUtilities::ConvertFromIntermediateBufferInPlace(aStartPositionInDescriptor, aDescriptor, aNumberOfCharactersThatDroppedOut, KEscapeSequenceDevanagari, 1);
}
// -----------------------------------------------------------------------------
// DoFindAndModifyBuffer()
//Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
//Introduced for handling multibyte iscii sequence.
//Takes the search buffer array and the replacement buffer arrays as input to it and replaces all
//the occurances of the search buffer with the corresponding replace buffer.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void DoFindAndModifyBuffer(TDes8& aModifyBuffer,const TDesC8& aSearchBuffer,const TDesC8& aReplaceBuffer)
{
FOREVER
{
TInt offset;
__ASSERT_ALWAYS((aSearchBuffer.Length()>= aReplaceBuffer.Length()),User::Panic(KPanicReason,EPanicBadReplacementBuffer));
if((offset = aModifyBuffer.Find(aSearchBuffer)) != KErrNotFound)
{
TUint8 *pointerToBuffer = const_cast<TUint8*> (aModifyBuffer.Ptr());
Mem::Copy(pointerToBuffer+offset,aReplaceBuffer.Ptr(),aReplaceBuffer.Length());
Mem::Copy(pointerToBuffer+offset+aReplaceBuffer.Length(),pointerToBuffer+offset+aSearchBuffer.Length(),aModifyBuffer.Length()-aSearchBuffer.Length()-offset);
aModifyBuffer.SetLength(aModifyBuffer.Length() - aSearchBuffer.Length() + aReplaceBuffer.Length());
}
else
break;
}
}
// -----------------------------------------------------------------------------
// FindAndModifyBuffer()
//Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
//Calls DoFindAndModifyBuffer() and supplies the search buffer and replacement buffer.
//Introduced for handling multibyte iscii sequence.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void FindAndModifyBuffer(TDes8& aModifyBuffer)
{
RArray<TPtrC8> searchBuffer;
RArray<TPtrC8> replaceBuffer;
searchBuffer.Append(KExplicitHalant().Mid(0));
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
replaceBuffer.Append(KReplacementForOm().Mid(0));
replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
for(TInt counter=0;counter<searchBuffer.Count();counter++)
{
DoFindAndModifyBuffer(aModifyBuffer,searchBuffer[counter],replaceBuffer[counter]);
}
searchBuffer.Reset();
replaceBuffer.Reset();
}
// -----------------------------------------------------------------------------
// DoNormalizeReturnValue()
//Modifies the return value(Number of bytes did not get converted) according to the modified
//intermediate buffer. Takes the modified intermediate buffer, return value, search and replace
//buffers. Searches for the replace buffer in the intermediate buffer and if found, it looks for
//the actual buffer corresponding to the replace buffer and adds the difference of the lengths
//of the actual to replace buffer to the return value.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void DoNormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer,RArray<TPtrC8>& anArrayOfSearches,RArray<TPtrC8>& anArrayOfReplaces)
{
TPtr8 buffer(const_cast<TUint8*>(aBuffer.Ptr()),aBuffer.Length(),aBuffer.Length());
TUint count = anArrayOfSearches.Count();
FOREVER
{
TBool flag = EFalse;
for(TUint i=0;i<count;i++)
{
TPtrC8 searchBufferForComparison(buffer.Right(anArrayOfReplaces[i].Length()));
TInt returnCompare = searchBufferForComparison.Compare(anArrayOfReplaces[i]);
if(returnCompare == 0)
{
flag =ETrue;
aReturnValue += (anArrayOfSearches[i].Length() - anArrayOfReplaces[i].Length());
buffer=buffer.MidTPtr(0,buffer.Length()-anArrayOfReplaces[i].Length());
break;
}
}
if(buffer.Length() == 0)
{
break;
}
if(!flag)
{
buffer=buffer.MidTPtr(0,buffer.Length()-1);
}
}
}
// -----------------------------------------------------------------------------
// NormalizeReturnValue()
//Modifies the return value(Number of bytes did not get converted) according to the
//replacements done to the iscii buffer before conversion.
//Internally calls DoNormalizeReturnValue() by suppling the search and replacement
//buffers.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void NormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer)
{
RArray<TPtrC8> searchBuffer;
RArray<TPtrC8> replaceBuffer;
searchBuffer.Append(KExplicitHalant().Mid(0));
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
replaceBuffer.Append(KReplacementForOm().Mid(0));
replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
DoNormalizeReturnValue(aReturnValue,aBuffer,searchBuffer,replaceBuffer);
searchBuffer.Reset();
replaceBuffer.Reset();
}
// -----------------------------------------------------------------------------
// HandleHomogeneousRun()
//Handles a homogeneous foreign buffer and converts the foreign buffer to unicode
//On return the aUnicode argument contains the converted unicode data.
//Also it sets the return value, returned from the conversion. The return value also
//takes into account if there is any buffer modification done before passing it to
//CCnvCharacterSetConverter::DoConvertToUnicode()
//buffers.
// Returns: Nothing
//
// -----------------------------------------------------------------------------
//
LOCAL_C void HandleHomogeneousRun(const SCnvConversionData*& aConversionData,
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aHomogeneousForeign,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
TUint& aOutputConversionFlags,
TUint aInputConversionFlags,TInt& aNumberOfForeignBytesConsumed,
TInt& aReturnValue)
{
TInt numberOfUnconvertibleCharacters;
TInt indexOfFirstByteOfFirstUnconvertibleCharacter;
TUint noOfConsumedBytes = 0;
if(aConversionData == NULL)
{
aReturnValue = CCnvCharacterSetConverter::EErrorIllFormedInput;
return;
}
aReturnValue = CCnvCharacterSetConverter::DoConvertToUnicode(*aConversionData,aDefaultEndiannessOfForeignCharacters,
aUnicode,aHomogeneousForeign,numberOfUnconvertibleCharacters,
indexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,
//The numberOfUnconvertibleCharacters and indexOfFirstByteOfFirstUnconvertibleCharacter are the values with
//respect to the intermediate iscii buffer and original values aIndexOfFirstByteOfFirstUnconvertibleCharacter and
//aNumberOfUnconvertibleCharacters need to be adjusted accordingly.
aInputConversionFlags);
if(numberOfUnconvertibleCharacters>0)
{
if(aNumberOfUnconvertibleCharacters == 0)
{
aIndexOfFirstByteOfFirstUnconvertibleCharacter = aNumberOfForeignBytesConsumed + indexOfFirstByteOfFirstUnconvertibleCharacter;
}
aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters;
}
noOfConsumedBytes = aHomogeneousForeign.Length();
//To Check whether it is really required.
NormalizeReturnValue(noOfConsumedBytes,aHomogeneousForeign);
aNumberOfForeignBytesConsumed+=noOfConsumedBytes;
if(aReturnValue>0)
{
TUint normalizedReturnValue = aReturnValue;
//There original iscii buffer copied to an intermediate iscii buffer and then modified
//and is then passed for conversion. Now, after conversion, the return value needs to
//be adjusted according to the original buffer. NormalizeReturnValue() does the
//same thing.
NormalizeReturnValue(normalizedReturnValue,aHomogeneousForeign);
aNumberOfForeignBytesConsumed-=normalizedReturnValue;
aReturnValue=normalizedReturnValue;
}
//The HandleHomogeneousRun() method is called in a loop and once there is some
//iscii codes converted to unicode, the ConvertToUnicode() should not return
//CCnvCharacterSetConverter::EErrorIllFormedInput even though the conversion
//method does not convert any of the iscii codes ppassed. To ensure that once the
//first non-zero number of iscii codes are converted, the internal input conversion
//flag is set to EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable.
if(aNumberOfForeignBytesConsumed>0)
{
aInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable;
}
return;
}
// -----------------------------------------------------------------------------
// IsTruncatedDoubleByteIsciiSequence()
//Checks if anIsciiBuffer is a part of multi byte iscii sequence truncated in the middle.
//If it is a truncated sequence, then returns ETrue else returns EFalse.
//
// Returns: ETrue: If the intermediate input iscii buffer is truncated
// EFalse: If the intermediate input iscii buffer is not truncated
//
// -----------------------------------------------------------------------------
//
LOCAL_C TBool IsTruncatedDoubleByteIsciiSequence(const TDesC8& anIsciiBuffer)
{
RArray<TPtrC8> searchBuffer;
if(anIsciiBuffer.Length () == 0)
return EFalse;
if(anIsciiBuffer[anIsciiBuffer.Length()-1] == 0xEF)
return ETrue;
searchBuffer.Append(KSoftHalant().Mid(0));
searchBuffer.Append(KOm().Mid(0));
searchBuffer.Append(KAvagraha().Mid(0));
searchBuffer.Append(KExplicitHalant().Mid(0));
TBool ret = EFalse;
TBool isNotTruncated =EFalse;
//First check if the intermediate iscii buffer is ending with a complete multi byte sequence.
//If it ends with a complete multi byte sequence, no need to check if the last character of
//intermediate iscii is same as first character of multi byte iscii sequence. And return EFalse.
for(TUint counter = 0;counter<searchBuffer.Count();counter++)
{
if(searchBuffer[counter].Compare(anIsciiBuffer.Right(searchBuffer[counter].Length())) == 0)
{
isNotTruncated = ETrue;
break;
}
}
//If the intermediate iscii buffer is not ending with a complete multi byte sequence, and the
//last code of the iscii buffer is a part of the multibyte sequence, then the iscii buffer is a
//truncated sequence and in that case return ETrue.
for(TUint counter = 0;counter<searchBuffer.Count();counter++)
{
if(isNotTruncated)
break;
else if( (anIsciiBuffer[anIsciiBuffer.Length()-1] == searchBuffer[counter][0]))
{
ret =ETrue;
break;
}
}
searchBuffer.Reset();
return ret;
}
// -----------------------------------------------------------------------------
// ReplacementForUnconvertibleUnicodeCharacters()
//Returns the replacement character for unconvertible unicode character.
//In the current implementation it is 0x1a (ASCII Substitute character)
//The default implementation calls ReplacementForUnconvertibleUnicodeCharacters_internal()
//in turn which is generated by cnvtool.
//
// Returns: Replacemt for unconvertible unicode characters (0x1a)
//
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters()
{
return ReplacementForUnconvertibleUnicodeCharacters_internal();
}
// -----------------------------------------------------------------------------
// ConvertFromUnicode()
//The main conversion function for converting from unicode to iscii
//Loaded and called by the character conversion framework.
//In turn calls CnvUtilities::ConvertFromUnicode() which is Symbian provide
//utility method for converting unicode to modal character codes.
//
// Returns: The numbet of unicode codes it could not convert.
//
// -----------------------------------------------------------------------------
//
EXPORT_C TInt ConvertFromUnicode(
CCnvCharacterSetConverter::TEndianness
aDefaultEndiannessOfForeignCharacters,
const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
TDes8& aForeign,
const TDesC16& aUnicode,
CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters )
{
TFixedArray<CnvUtilities::SCharacterSet,KNumberOfIndicCharactersetsSupported> aArrayOfCharacterSets;
aArrayOfCharacterSets[0].iConversionData = &conversionData;
aArrayOfCharacterSets[0].iConvertFromIntermediateBufferInPlace = ConvertFromUnicodeIntermediateBufferInPlace;
aArrayOfCharacterSets[0].iEscapeSequence = &KEscapeSequenceDevanagari();
return CnvUtilities::ConvertFromUnicode(
aDefaultEndiannessOfForeignCharacters,
aReplacementForUnconvertibleUnicodeCharacters,
aForeign,
aUnicode,
aIndicesOfUnconvertibleCharacters,
aArrayOfCharacterSets.Array());
}
// -----------------------------------------------------------------------------
// ConvertToUnicode()
//The main conversion function for converting from iscii to unicode
//Loaded and called by the character conversion framework.
//To support some of the iscii characters, the input forign buffer is
//copied to an intermediate buffer and then is then modified and
//CCnvCharactersetConverter::DoConvertToUnicode() is called with
//the modified buffer. For extensibility of iscii to other Indic languages
//it uses CnvUtilities::SState datastructure. CnvUtilities::SState is a
//Symbian defined class for modal charactersets. The escape sequence
//is specified to ATR followed by the script selection code and the conversion
//data is specified to be the conversion for the particular script. For the time
//being only Devanagari with script selection code 0x42 is supported. If
//any of the other script codes are used the conversion leads to unconvertible
//character i.e. 0xFFFD.
// Returns: The numbet of iscii codes it could not convert.
//
// -----------------------------------------------------------------------------
//
EXPORT_C TInt ConvertToUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aForeign,
TInt& aState,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter )
{
aNumberOfUnconvertibleCharacters = 0;
TUint aOutputConversionFlags;
aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
TUint internalInputConversionFlags = 0;
TInt numberOfForeignBytesConsumed=0;
TPtrC8 remainderOfForeign(aForeign);
TInt returnValue;
TBool flag = EFalse;
TBool isSkipMatchSequence = EFalse;
const SCnvConversionData* convData;
//Set the iscii conversion data and escape sequence for Devanagari.
TFixedArray<CnvUtilities::SState,KNumberOfIndicCharactersetsSupported> modals;
modals[0].iConversionData = &conversionData;
modals[0].iEscapeSequence = &KEscapeSequenceDevanagari();
aUnicode.SetLength(0);
//The internal input conversion flag for conversion is set to CCnvCharacterSetConverter::EInputConversionFlagAppend
//so that for each conversion in the conversion loop, the generated conversion buffer is appened to the aUnicode buffer.
internalInputConversionFlags |= CCnvCharacterSetConverter::EInputConversionFlagAppend;
if (aForeign.Length()==0)
{
return 0;
}
//Get the conversion data from the previous call else the conversion data is set to the default
//conversion data, i.e. Devanagari.
convData=(aState!=CCnvCharacterSetConverter::KStateDefault)? REINTERPRET_CAST(const SCnvConversionData*, aState): modals[0].iConversionData;
FOREVER
{
TBuf8<KMaximumLengthOfIntermediateBuffer> intermediateBuffer;
TUint numberOfForeignBytesConsumedThisTime = 0;
if((remainderOfForeign.Length() >=KMaximumLengthOfIntermediateBuffer) && (aUnicode.MaxLength()-aUnicode.Length() >=KMaximumLengthOfIntermediateBuffer))
{
numberOfForeignBytesConsumedThisTime = KMaximumLengthOfIntermediateBuffer;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
//If the intermediate buffer is a part of truncated buffer sequence but the
//actual input buffer is not truncated then truncated sequence is not converted.
//The intermediate buffer is modified so as not to contain the truncated sequence.
flag = IsTruncatedDoubleByteIsciiSequence(intermediateBuffer);
if(flag)
{
numberOfForeignBytesConsumedThisTime --;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
}
else
{
flag = IsTruncatedDoubleByteIsciiSequence(remainderOfForeign.Left(aUnicode.MaxLength()-aUnicode.Length()));
if(!flag)
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
else
{
if(aForeign.Length()>(numberOfForeignBytesConsumed+aUnicode.Length()))
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length()-1;
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
break;
}
else
{
numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
}
}
}
//The input intermediate iscii buffer is modified with the search and replace
//buffers. It is required for supporting multibyte iscii sequences.
FindAndModifyBuffer(intermediateBuffer);
TPtrC8 remainderOfForeignInternal(intermediateBuffer);
TPtrC8 homogeneousRun;
const TInt startOfNextEscapeSequence=intermediateBuffer.Locate(KControlCharacterEscape);
if (startOfNextEscapeSequence!=0)
{
if (startOfNextEscapeSequence==KErrNotFound)
{
homogeneousRun.Set(remainderOfForeignInternal);
remainderOfForeignInternal.Set(NULL, 0);
}
else
{
__ASSERT_DEBUG(startOfNextEscapeSequence>0, User::Panic(KPanicReason,EPanicBadStartOfNextEscapeSequence));
homogeneousRun.Set(remainderOfForeignInternal.Left(startOfNextEscapeSequence));
remainderOfForeignInternal.Set(remainderOfForeignInternal.Mid(startOfNextEscapeSequence));
}
isSkipMatchSequence = ETrue;
}
FOREVER
{
if(!isSkipMatchSequence)
{
if (!NextHomogeneousForeignRun(convData, numberOfForeignBytesConsumed, homogeneousRun,
remainderOfForeignInternal, modals.Array(), aOutputConversionFlags))
{
break;
}
}
HandleHomogeneousRun( convData, aDefaultEndiannessOfForeignCharacters, aUnicode, homogeneousRun, aNumberOfUnconvertibleCharacters,
aIndexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,internalInputConversionFlags,
numberOfForeignBytesConsumed,returnValue);
if(returnValue<0)
{
return returnValue;
}
isSkipMatchSequence = EFalse;
}
if(returnValue > 0)
break;
if ((!flag && (numberOfForeignBytesConsumedThisTime != KMaximumLengthOfIntermediateBuffer)) || (flag && (numberOfForeignBytesConsumedThisTime != (KMaximumLengthOfIntermediateBuffer-1) )))
break;
remainderOfForeign.Set(aForeign.Mid(numberOfForeignBytesConsumed));
}
//If the number of iscii bytes consumed by the conversion is zero also the output conversion
//flag is not set to EOutputConversionFlagInputIsTruncated, then return EErrorIllFormedInput.
if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated))
{
return CCnvCharacterSetConverter::EErrorIllFormedInput;
}
//Set the conversion data sothat next time when ConvertToUnicode() is called,
//will use the previous conversion data.
aState=REINTERPRET_CAST(TInt, convData);
return aForeign.Length()-numberOfForeignBytesConsumed;
}
// -----------------------------------------------------------------------------
// IsInThisCharacterSetL()
//The method tells how probable it is that a sample piece of text is encoded in this character set.
//On return aConfidenceLevel, indicates how confident the function is about its return value. For
//iscii it is the default implementation and it does not implement the autodetect functionality.
//Loaded and called by the character conversion framework.
//
// Returns: EFalse: To tell CCnvCharacterSetConverter::AutoDetectCharacterSetL() that the plug-in DLL
// is not implementing a function of this signature and is therefore empty.
//
// -----------------------------------------------------------------------------
//
//Default implementation for IsInThisCharacterSetL()
EXPORT_C TBool IsInThisCharacterSetL(
TBool& aSetToTrue,
TInt& aConfidenceLevel,
const TDesC8& )
{
aSetToTrue = EFalse;
aConfidenceLevel = 0;
return EFalse;
}
EXPORT_C void Reserved_2()
{
}
EXPORT_C void Reserved_3()
{
}
EXPORT_C void Reserved_4()
{
}
EXPORT_C void Reserved_5()
{
}
EXPORT_C void Reserved_6()
{
}
EXPORT_C void Reserved_7()
{
}
EXPORT_C void Reserved_8()
{
}
#endif //EKA2