charconvfw/charconvplugins/src/plugins/iscii.cpp
changeset 0 1fb32624e06b
child 16 748ec5531811
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:     Implements the characterconversion plug-in
       
    15 *                for ISCII characterset.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 #include <e32std.h>
       
    24 #include <charconv.h>
       
    25 #include <convgeneratedcpp.h>
       
    26 #include <convutils.h>
       
    27 
       
    28 //The maximum length of any intermediate buffer allocated for conversion.
       
    29 const TInt KMaximumLengthOfIntermediateBuffer=5;
       
    30 //The ISCII ATR code point, used for ISCII script switching mechanism.
       
    31 const TUint KControlCharacterEscape=0xef;
       
    32 //The number of Indic scripts supported by the plug-in.
       
    33 //ISCII in general addresses all the Indic character sets.
       
    34 const TUint KNumberOfIndicCharactersetsSupported = 1;
       
    35 //The common reason for panic for all panics raised by the iscii plug-in
       
    36 _LIT16(KPanicReason,"ISCII Plug-in Panic"); 
       
    37 //The escape sequence for ISCII (ATR) is 0xEF and immidiate byte following 
       
    38 //that is the script selection code for Devanagari.
       
    39 _LIT8(KEscapeSequenceDevanagari,"\xef\x42");
       
    40 //The sequence for Explicit Halant, in unicode it gets converted to VIRAMA+ZWNJ
       
    41 _LIT8(KExplicitHalant,"\xe8\xe8");
       
    42 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    43 //sequence is converted to intermediate unused iscii code point.
       
    44 _LIT8(KReplacementForExplicitHalant,"\xe8\xfc");
       
    45 //The sequence for Soft Halant, in unicode it gets converted to VIRAMA+ZWJ
       
    46 _LIT8(KSoftHalant,"\xe8\xe9");
       
    47 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    48 //sequence is converted to intermediate unused iscii code point.
       
    49 _LIT8(KReplacementForSoftHalant,"\xe8\xfd");
       
    50 //Devanagari character Om
       
    51 _LIT8(KOm,"\xa1\xe9");
       
    52 ////For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    53 //sequence is converted to intermediate unused iscii code point.
       
    54 _LIT8(KReplacementForOm,"\xfe");
       
    55 //Devanagari character Avagraha
       
    56 _LIT8(KAvagraha,"\xea\xe9");
       
    57 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    58 //sequence is converted to intermediate unused iscii code point.
       
    59 _LIT8(KReplacementForAvagraha,"\xff");
       
    60 
       
    61 //Devanagari character VOCALIC RR
       
    62 _LIT8(KVocalicRr,"\xaa\xe9");
       
    63 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    64 //sequence is converted to intermediate unused iscii code point.
       
    65 _LIT8(KReplacementForVocalicRr,"\x80");
       
    66 //Devanagari character VOCALIC LL
       
    67 _LIT8(KVocalicLl,"\xa7\xe9");
       
    68 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    69 //sequence is converted to intermediate unused iscii code point.
       
    70 _LIT8(KReplacementForVocalicLl,"\x81");
       
    71 //Devanagari character VOCALIC L SIGN
       
    72 _LIT8(KVocalicLSign,"\xdb\xe9");
       
    73 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    74 //sequence is converted to intermediate unused iscii code point.
       
    75 _LIT8(KReplacementForVocalicLSign,"\x82");
       
    76 //Devanagari character VOCALIC LL SIGN
       
    77 _LIT8(KVocalicLlSign,"\xdc\xe9");
       
    78 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    79 //sequence is converted to intermediate unused iscii code point.
       
    80 _LIT8(KReplacementForVocalicLlSign,"\x83");
       
    81 //Devanagari character VOCALIC L
       
    82 _LIT8(KVocalicL,"\xa6\xe9");
       
    83 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    84 //sequence is converted to intermediate unused iscii code point.
       
    85 _LIT8(KReplacementForVocalicL,"\x84");
       
    86 //Devanagari character VOCALIC RR SIGN
       
    87 _LIT8(KVocalicRrSign,"\xdf\xe9");
       
    88 //For supportiing ISCII to Unicode conversion of multi byte ISCII sequences, the
       
    89 //sequence is converted to intermediate unused iscii code point.
       
    90 _LIT8(KReplacementForVocalicRrSign,"\x85");
       
    91 
       
    92 //Unconvertible ISCII character
       
    93 _LIT8(KIsciiUnconvertibleCharacter,"\xeb");
       
    94 
       
    95 enum TPanic
       
    96 {
       
    97 	//The panic raised by ConvertToUnicodeFromModalForeign_Internal() if the input
       
    98 	//conversion flag is CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter
       
    99 	EPanicBadInputConversionFlags=1,
       
   100 	//Panic raised if the buffer does not start with the escape sequence 0xEF
       
   101 	EPanicBadRemainderOfForeign,
       
   102 	//Panic is raised if the length of the search buffer is greater than the length of the 
       
   103 	//replacement buffer
       
   104 	EPanicBadReplacementBuffer,
       
   105 	//If the offset of start of the escape sequence is not an unsigned number.
       
   106 	EPanicBadStartOfNextEscapeSequence
       
   107 };
       
   108 
       
   109 //The dummy datastructure for the dummy conversion data i.e. used for conversion if the 
       
   110 //script selection code is not supported.
       
   111 #define ARRAY_LENGTH(aArray) (sizeof(aArray)/sizeof((aArray)[0]))
       
   112 
       
   113 LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_foreignToUnicode_1[]=
       
   114 	{
       
   115 		{
       
   116 		0xa0,
       
   117 		0xfffd
       
   118 		}
       
   119 	};
       
   120 
       
   121 LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_unicodeToForeign_1[]=
       
   122 	{
       
   123 		{
       
   124 		0xfffd,
       
   125 		0xa0
       
   126 		}
       
   127 	};
       
   128 
       
   129 LOCAL_D const SCnvConversionData::SVariableByteData::SRange foreignVariableByteDataRanges[]=
       
   130 	{
       
   131 		{
       
   132 		0x00,
       
   133 		0xff,
       
   134 		0,
       
   135 		0
       
   136 		}
       
   137 	};
       
   138 
       
   139 LOCAL_D const SCnvConversionData::SOneDirectionData::SRange foreignToUnicodeDataRanges[]=
       
   140 	{
       
   141 		{
       
   142 		0x00,
       
   143 		0x7f,
       
   144 		SCnvConversionData::SOneDirectionData::SRange::EDirect,
       
   145 		0,
       
   146 		0,
       
   147 			{
       
   148 			0
       
   149 			}
       
   150 		},
       
   151 		{
       
   152 		0xa0,
       
   153 		0xff,
       
   154 		SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616,
       
   155 		0,
       
   156 		0,
       
   157 			{
       
   158 			UData_SKeyedTable1616(keyedTable1616_foreignToUnicode_1)
       
   159 			}
       
   160 		}
       
   161 	};
       
   162 
       
   163 LOCAL_D const SCnvConversionData::SOneDirectionData::SRange unicodeToForeignDataRanges[]=
       
   164 	{
       
   165 		{
       
   166 		0x0000,
       
   167 		0x007f,
       
   168 		SCnvConversionData::SOneDirectionData::SRange::EDirect,
       
   169 		1,
       
   170 		0,
       
   171 			{
       
   172 			0
       
   173 			}
       
   174 		},
       
   175 		{
       
   176 		0x00a0,
       
   177 		0xffff,
       
   178 		SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616,
       
   179 		1,
       
   180 		0,
       
   181 			{
       
   182 			UData_SKeyedTable1616(keyedTable1616_unicodeToForeign_1)
       
   183 			}
       
   184 		}
       
   185 	};
       
   186 
       
   187 //The dummy conversion data to be used for conversion if the iscii code sequence is not
       
   188 //Devanagari (i.e. the script selection code is not 0x42 and something else.
       
   189 //In this case the ISCII characters are converted to unconvertible characters.
       
   190 
       
   191 LOCAL_D const SCnvConversionData conversionDataDummy=
       
   192 	{
       
   193 	SCnvConversionData::EFixedBigEndian,
       
   194 		{
       
   195 		ARRAY_LENGTH(foreignVariableByteDataRanges),
       
   196 		foreignVariableByteDataRanges
       
   197 		},
       
   198 		{
       
   199 		ARRAY_LENGTH(foreignToUnicodeDataRanges),
       
   200 		foreignToUnicodeDataRanges
       
   201 		},
       
   202 		{
       
   203 		ARRAY_LENGTH(unicodeToForeignDataRanges),
       
   204 		unicodeToForeignDataRanges
       
   205 		},
       
   206 	NULL,
       
   207 	NULL
       
   208 	};
       
   209 
       
   210 
       
   211 
       
   212 #ifdef EKA2
       
   213 
       
   214 ///////////////////////////////////////////////////////////////
       
   215 // 3.1 Code
       
   216 
       
   217 // INCLUDES
       
   218 #include <ecom/implementationproxy.h>
       
   219 #include <charactersetconverter.h>
       
   220 
       
   221 
       
   222 /**
       
   223 * The character conversion plug-in implementation for Iscii.
       
   224 *
       
   225 *  @lib ecom.lib
       
   226 *  @since Series 60 3.1
       
   227 */
       
   228 
       
   229 class CIsciiImplementation : public CCharacterSetConverterPluginInterface
       
   230 {
       
   231     public:
       
   232     	//From CCharacterSetConverterPluginInterface
       
   233         virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters();
       
   234 
       
   235 	//From CCharacterSetConverterPluginInterface
       
   236         virtual TInt ConvertFromUnicode(
       
   237             CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
       
   238             const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
       
   239             TDes8& aForeign, 
       
   240             const TDesC16& aUnicode, 
       
   241             CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters );
       
   242 
       
   243 	//From CCharacterSetConverterPluginInterface
       
   244         virtual TInt ConvertToUnicode(
       
   245             CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
       
   246             TDes16& aUnicode, 
       
   247             const TDesC8& aForeign, 
       
   248             TInt&, 
       
   249             TInt& aNumberOfUnconvertibleCharacters, 
       
   250             TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter );
       
   251 
       
   252 	//From CCharacterSetConverterPluginInterface
       
   253         virtual TBool IsInThisCharacterSetL(
       
   254             TBool& aSetToTrue, 
       
   255             TInt& aConfidenceLevel, 
       
   256             const TDesC8& );
       
   257 
       
   258         static CIsciiImplementation* NewL();
       
   259 
       
   260         virtual ~CIsciiImplementation();
       
   261     private:
       
   262         CIsciiImplementation();
       
   263 };
       
   264 
       
   265 //Checks if a descriptor starts with another descriptor at the begining.
       
   266 LOCAL_C TBool IsStartOf(const TDesC8& aEscapeSequence, const TDesC8& aBuffer)
       
   267 {
       
   268 	const TInt lengthOfStart=aEscapeSequence.Length();
       
   269 	return (aBuffer.Length()>=lengthOfStart) && (aBuffer.Left(lengthOfStart)==aEscapeSequence);
       
   270 }
       
   271 // -----------------------------------------------------------------------------
       
   272 // MatchesEscapeSequence()
       
   273 //If the remainder of the foreign text starts with the passed escapesequence, modifies the remainder of the foreign text
       
   274 //and  sets the homogeneous run buffer that uses the same conversion data.
       
   275 //The homogeneous run buffer is the buffer that will use a single conversion data, it doesn't contain the attribute code
       
   276 // neither it contains the script switching code.
       
   277 //The aRemainderOfForeign buffer 
       
   278 
       
   279 // Returns: ETrue: If the sequence contains the escape sequence
       
   280 //              EFalse: If the sequence does not contain the escape sequence
       
   281 //
       
   282 // -----------------------------------------------------------------------------
       
   283 //
       
   284 LOCAL_C TBool MatchesEscapeSequence(TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun,
       
   285 		TPtrC8& aRemainderOfForeign, const TDesC8& aEscapeSequence)
       
   286 {
       
   287 	const TInt lengthOfEscapeSequence=aEscapeSequence.Length();
       
   288 	if (IsStartOf(aEscapeSequence, aRemainderOfForeign))
       
   289 		{
       
   290 		aRemainderOfForeign.Set(aRemainderOfForeign.Mid(lengthOfEscapeSequence));
       
   291 		const TInt startOfNextEscapeSequence=aRemainderOfForeign.Locate(KControlCharacterEscape);
       
   292 		if (startOfNextEscapeSequence==KErrNotFound)
       
   293 			{
       
   294 			aHomogeneousRun.Set(aRemainderOfForeign);
       
   295 			aRemainderOfForeign.Set(NULL, 0);
       
   296 			}
       
   297 		else
       
   298 			{
       
   299 			aHomogeneousRun.Set(aRemainderOfForeign.Left(startOfNextEscapeSequence));
       
   300 			aRemainderOfForeign.Set(aRemainderOfForeign.Mid(startOfNextEscapeSequence));
       
   301 			}
       
   302 		aNumberOfForeignBytesConsumed+=lengthOfEscapeSequence;
       
   303 		return ETrue;
       
   304 		}
       
   305 	return EFalse;
       
   306 }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // NextHomogeneousForeignRun()
       
   310 //Matches the escape sequence of each of the elements of the SState array with the remainder of
       
   311 //foreign text and if the escape sequence matches with the start of remainder of the foreign text, 
       
   312 //then the conversion data is set to the conversion data corresponding to the escape sequence
       
   313 //Also the homogeneous foreign text for conversion with the same escape sequence is set.
       
   314 
       
   315 // Returns: ETrue: If length of the remainder of foreign buffer is nonzero.
       
   316 //              EFalse: If length of the remainder of foreign buffer is zero.
       
   317 //
       
   318 // -----------------------------------------------------------------------------
       
   319 //
       
   320 
       
   321 
       
   322 LOCAL_C TBool NextHomogeneousForeignRun(const SCnvConversionData*& aConversionData, TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TArray<CnvUtilities::SState>& aArrayOfStates, TUint& aOutputConversionFlags)
       
   323 {
       
   324 	TBool returnValue = EFalse;
       
   325 	TBool foundState = EFalse;
       
   326 	__ASSERT_DEBUG((aRemainderOfForeign.Length()==0) || (aRemainderOfForeign[0]==KControlCharacterEscape), User::Panic(KPanicReason,EPanicBadRemainderOfForeign));
       
   327 	if (aRemainderOfForeign.Length()==0)
       
   328 		{
       
   329 		return returnValue;
       
   330 		}
       
   331 	const TInt numberOfStates=aArrayOfStates.Count();
       
   332 	TInt i;
       
   333 	for (i=0; i<numberOfStates; ++i)
       
   334 		{
       
   335 		const CnvUtilities::SState& state=aArrayOfStates[i];
       
   336 		if (MatchesEscapeSequence(aNumberOfForeignBytesConsumed, aHomogeneousRun, aRemainderOfForeign, *state.iEscapeSequence))
       
   337 			{
       
   338 			aConversionData=state.iConversionData;
       
   339 			foundState = ETrue;
       
   340 			}
       
   341 		}
       
   342 	if(!foundState)
       
   343 		{
       
   344 		for (i=0; i<numberOfStates; ++i)
       
   345 			{
       
   346 			if (IsStartOf(aRemainderOfForeign, *aArrayOfStates[i].iEscapeSequence))
       
   347 				{
       
   348 				// aRemainderOfForeign ends with a truncated escape sequence, so ConvertToUnicode cannot convert any more
       
   349 				aOutputConversionFlags|=CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated;
       
   350 				break;
       
   351 				}
       
   352 			}
       
   353 
       
   354 		MatchesEscapeSequence(aNumberOfForeignBytesConsumed,aHomogeneousRun,aRemainderOfForeign,aRemainderOfForeign.Left(2));
       
   355 		aConversionData = &conversionDataDummy;	
       
   356 		returnValue = ETrue;
       
   357 		}
       
   358 		if (aHomogeneousRun.Length()>0)
       
   359 			{
       
   360 			returnValue = ETrue;
       
   361 			}
       
   362 		return returnValue;		
       
   363 }
       
   364 // -----------------------------------------------------------------------------
       
   365 // ConvertFromUnicodeIntermediateBufferInPlace()
       
   366 //Default implementation for conversion to the intermediate buffer
       
   367 //It modifies the unicode buffer before it is converted back to iscii.
       
   368 //The current implementation of iscii plug-in doesn't require any
       
   369 //modification to the default implementation
       
   370 // Returns: Nothing
       
   371 //
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 
       
   375 
       
   376 LOCAL_C void ConvertFromUnicodeIntermediateBufferInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
       
   377 {
       
   378 	CnvUtilities::ConvertFromIntermediateBufferInPlace(aStartPositionInDescriptor, aDescriptor, aNumberOfCharactersThatDroppedOut, KEscapeSequenceDevanagari, 1);
       
   379 }
       
   380 
       
   381 // -----------------------------------------------------------------------------
       
   382 // DoFindAndModifyBuffer()
       
   383 //Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
       
   384 //Introduced for handling multibyte iscii sequence.
       
   385 //Takes the search buffer array and the replacement buffer arrays as input to it and replaces all
       
   386 //the occurances of the search buffer with the corresponding replace buffer.
       
   387 // Returns: Nothing
       
   388 //
       
   389 // -----------------------------------------------------------------------------
       
   390 //
       
   391 
       
   392 LOCAL_C void DoFindAndModifyBuffer(TDes8& aModifyBuffer,const TDesC8& aSearchBuffer,const TDesC8& aReplaceBuffer)
       
   393 {
       
   394 	FOREVER
       
   395 	{
       
   396 		TInt offset;
       
   397 		__ASSERT_ALWAYS((aSearchBuffer.Length()>= aReplaceBuffer.Length()),User::Panic(KPanicReason,EPanicBadReplacementBuffer));
       
   398 		if((offset = aModifyBuffer.Find(aSearchBuffer)) != KErrNotFound)
       
   399 		{
       
   400 			TUint8 *pointerToBuffer = const_cast<TUint8*> (aModifyBuffer.Ptr());
       
   401 			Mem::Copy(pointerToBuffer+offset,aReplaceBuffer.Ptr(),aReplaceBuffer.Length());
       
   402 			Mem::Copy(pointerToBuffer+offset+aReplaceBuffer.Length(),pointerToBuffer+offset+aSearchBuffer.Length(),aModifyBuffer.Length()-aSearchBuffer.Length()-offset);
       
   403 			aModifyBuffer.SetLength(aModifyBuffer.Length() - aSearchBuffer.Length() + aReplaceBuffer.Length());
       
   404 		}
       
   405 		else
       
   406 			break;
       
   407 	}
       
   408 	
       
   409 }
       
   410 
       
   411 // -----------------------------------------------------------------------------
       
   412 // FindAndModifyBuffer()
       
   413 //Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
       
   414 //Calls DoFindAndModifyBuffer() and supplies the search buffer and replacement buffer.
       
   415 //Introduced for handling multibyte iscii sequence.
       
   416 // Returns: Nothing
       
   417 //
       
   418 // -----------------------------------------------------------------------------
       
   419 //
       
   420 
       
   421 LOCAL_C void FindAndModifyBuffer(TDes8& aModifyBuffer)
       
   422 {
       
   423 	RArray<TPtrC8> searchBuffer;
       
   424 	RArray<TPtrC8> replaceBuffer;
       
   425 	
       
   426 	//If the passed buffer contains the replacement buffer,
       
   427 	//Then it should not get converted to respective Unicode
       
   428 	//buffer rather it should get converted to replacement for
       
   429 	//unconvertible character.
       
   430 	
       
   431 	searchBuffer.Append(KReplacementForExplicitHalant().Right(1));
       
   432 	searchBuffer.Append(KReplacementForSoftHalant().Right(1));
       
   433 	searchBuffer.Append(KReplacementForOm().Right(1));
       
   434 	searchBuffer.Append(KReplacementForAvagraha().Right(1));
       
   435 	
       
   436 	searchBuffer.Append(KReplacementForVocalicRr().Right(1));
       
   437 	searchBuffer.Append(KReplacementForVocalicLl().Right(1));
       
   438 	searchBuffer.Append(KReplacementForVocalicLSign().Right(1));
       
   439 	searchBuffer.Append(KReplacementForVocalicLlSign().Right(1));
       
   440 	searchBuffer.Append(KReplacementForVocalicL().Right(1));
       
   441 	searchBuffer.Append(KReplacementForVocalicRrSign().Right(1));
       
   442 	
       
   443 	//All normal search buffers
       
   444 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
   445 	searchBuffer.Append(KSoftHalant().Mid(0));
       
   446 	searchBuffer.Append(KOm().Mid(0));
       
   447 	searchBuffer.Append(KAvagraha().Mid(0));
       
   448 	
       
   449 	searchBuffer.Append(KVocalicRr().Mid(0));
       
   450 	searchBuffer.Append(KVocalicLl().Mid(0));
       
   451 	searchBuffer.Append(KVocalicLSign().Mid(0));
       
   452 	searchBuffer.Append(KVocalicLlSign().Mid(0));
       
   453 	searchBuffer.Append(KVocalicL().Mid(0));
       
   454 	searchBuffer.Append(KVocalicRrSign().Mid(0));
       
   455 	
       
   456 	//The replacement buffer for the odd cases to restrict the 
       
   457 	//replacement buffers not to get converted to the corresponding 
       
   458 	//unicode buffer
       
   459 	
       
   460 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   461 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   462 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   463 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   464 	
       
   465 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   466 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   467 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   468 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   469 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   470 	replaceBuffer.Append(KIsciiUnconvertibleCharacter().Mid(0));
       
   471 	
       
   472 	//All normal replace buffers		
       
   473 	replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
       
   474 	replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
       
   475 	replaceBuffer.Append(KReplacementForOm().Mid(0));
       
   476 	replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
       
   477 	
       
   478 	
       
   479 	replaceBuffer.Append(KReplacementForVocalicRr().Mid(0));
       
   480 	replaceBuffer.Append(KReplacementForVocalicLl().Mid(0));
       
   481 	replaceBuffer.Append(KReplacementForVocalicLSign().Mid(0));
       
   482 	replaceBuffer.Append(KReplacementForVocalicLlSign().Mid(0));
       
   483 	replaceBuffer.Append(KReplacementForVocalicL().Mid(0));
       
   484 	replaceBuffer.Append(KReplacementForVocalicRrSign().Mid(0));
       
   485 	
       
   486 			
       
   487 	for(TInt counter=0;counter<searchBuffer.Count();counter++)
       
   488 	{
       
   489 		DoFindAndModifyBuffer(aModifyBuffer,searchBuffer[counter],replaceBuffer[counter]);
       
   490 	}
       
   491 	searchBuffer.Reset();
       
   492 	replaceBuffer.Reset();
       
   493 	
       
   494 }
       
   495 
       
   496 // -----------------------------------------------------------------------------
       
   497 // DoNormalizeReturnValue()
       
   498 //Modifies the return value(Number of bytes did not get converted) according to the modified
       
   499 //intermediate buffer. Takes the modified intermediate buffer, return value, search and replace
       
   500 //buffers. Searches for the replace buffer in the intermediate buffer and if found, it looks for
       
   501 //the actual buffer corresponding to the replace buffer and adds the difference of the lengths
       
   502 //of the actual to replace buffer to the return value.
       
   503 // Returns: Nothing
       
   504 //
       
   505 // -----------------------------------------------------------------------------
       
   506 //
       
   507 
       
   508 LOCAL_C void DoNormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer,RArray<TPtrC8>& anArrayOfSearches,RArray<TPtrC8>& anArrayOfReplaces)
       
   509 {
       
   510 	TPtr8 buffer(const_cast<TUint8*>(aBuffer.Ptr()),aBuffer.Length(),aBuffer.Length());
       
   511 	TUint count = anArrayOfSearches.Count();
       
   512 	FOREVER
       
   513 	{
       
   514 		TBool flag = EFalse;
       
   515 		for(TUint i=0;i<count;i++)
       
   516 		{
       
   517 			TPtrC8 searchBufferForComparison(buffer.Right(anArrayOfReplaces[i].Length()));
       
   518 			TInt returnCompare = searchBufferForComparison.Compare(anArrayOfReplaces[i]);
       
   519 			if(returnCompare == 0)
       
   520 			{
       
   521 				flag =ETrue;
       
   522 				aReturnValue += (anArrayOfSearches[i].Length() - anArrayOfReplaces[i].Length());
       
   523 				buffer=buffer.MidTPtr(0,buffer.Length()-anArrayOfReplaces[i].Length());
       
   524 				break;
       
   525 			}
       
   526 		}
       
   527 		
       
   528 		if(buffer.Length() == 0)
       
   529 		{
       
   530 			break;
       
   531 		}
       
   532 		
       
   533 		if(!flag)
       
   534 		{
       
   535 			buffer=buffer.MidTPtr(0,buffer.Length()-1);
       
   536 		}
       
   537 	}
       
   538 
       
   539 }
       
   540 
       
   541 // -----------------------------------------------------------------------------
       
   542 // NormalizeReturnValue()
       
   543 //Modifies the return value(Number of bytes did not get converted) according to the 
       
   544 //replacements done to the iscii buffer before conversion.
       
   545 //Internally calls DoNormalizeReturnValue() by suppling the search and replacement 
       
   546 //buffers.
       
   547 
       
   548 // Returns: Nothing
       
   549 //
       
   550 // -----------------------------------------------------------------------------
       
   551 //
       
   552 
       
   553 LOCAL_C void NormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer)
       
   554 {
       
   555 	RArray<TPtrC8> searchBuffer;
       
   556 	RArray<TPtrC8> replaceBuffer;
       
   557 	
       
   558 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
   559 	searchBuffer.Append(KSoftHalant().Mid(0));
       
   560 	searchBuffer.Append(KOm().Mid(0));
       
   561 	searchBuffer.Append(KAvagraha().Mid(0));
       
   562 	
       
   563 	searchBuffer.Append(KVocalicRr().Mid(0));
       
   564 	searchBuffer.Append(KVocalicLl().Mid(0));
       
   565 	searchBuffer.Append(KVocalicLSign().Mid(0));
       
   566 	searchBuffer.Append(KVocalicLlSign().Mid(0));
       
   567 	searchBuffer.Append(KVocalicL().Mid(0));
       
   568 	searchBuffer.Append(KVocalicRrSign().Mid(0));
       
   569 	
       
   570 	replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
       
   571 	replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
       
   572 	replaceBuffer.Append(KReplacementForOm().Mid(0));
       
   573 	replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
       
   574 	
       
   575 	replaceBuffer.Append(KReplacementForVocalicRr().Mid(0));
       
   576 	replaceBuffer.Append(KReplacementForVocalicLl().Mid(0));
       
   577 	replaceBuffer.Append(KReplacementForVocalicLSign().Mid(0));
       
   578 	replaceBuffer.Append(KReplacementForVocalicLlSign().Mid(0));
       
   579 	replaceBuffer.Append(KReplacementForVocalicL().Mid(0));
       
   580 	replaceBuffer.Append(KReplacementForVocalicRrSign().Mid(0));
       
   581 	
       
   582 	DoNormalizeReturnValue(aReturnValue,aBuffer,searchBuffer,replaceBuffer);
       
   583 	searchBuffer.Reset();
       
   584 	replaceBuffer.Reset();
       
   585 }
       
   586 
       
   587 // -----------------------------------------------------------------------------
       
   588 // HandleHomogeneousRun()
       
   589 //Handles a homogeneous foreign buffer and converts the foreign buffer to unicode
       
   590 //On return the aUnicode argument contains the converted unicode data.
       
   591 //Also it sets the return value, returned from the conversion. The return value also
       
   592 //takes into account if there is any buffer modification done before passing it to
       
   593 //CCnvCharacterSetConverter::DoConvertToUnicode()
       
   594 //buffers.
       
   595 
       
   596 // Returns: Nothing
       
   597 //
       
   598 // -----------------------------------------------------------------------------
       
   599 //
       
   600 
       
   601 LOCAL_C void HandleHomogeneousRun(const SCnvConversionData*& aConversionData, 
       
   602 							CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
       
   603 							TDes16& aUnicode,
       
   604 							const TDesC8& aHomogeneousForeign,
       
   605 							TInt& aNumberOfUnconvertibleCharacters,
       
   606 							TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
       
   607 							TUint& aOutputConversionFlags,
       
   608 							TUint aInputConversionFlags,TInt& aNumberOfForeignBytesConsumed,
       
   609 							TInt& aReturnValue)
       
   610 {
       
   611 	TInt numberOfUnconvertibleCharacters;
       
   612 	TInt indexOfFirstByteOfFirstUnconvertibleCharacter;
       
   613 	TUint noOfConsumedBytes = 0;
       
   614 	if(aConversionData == NULL)
       
   615 		{
       
   616 		aReturnValue = CCnvCharacterSetConverter::EErrorIllFormedInput;
       
   617 		return;
       
   618 		}
       
   619 	aReturnValue = CCnvCharacterSetConverter::DoConvertToUnicode(*aConversionData,aDefaultEndiannessOfForeignCharacters,
       
   620 															  aUnicode,aHomogeneousForeign,numberOfUnconvertibleCharacters,
       
   621 															  indexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,
       
   622 
       
   623 	//The numberOfUnconvertibleCharacters and indexOfFirstByteOfFirstUnconvertibleCharacter are the values with
       
   624 	//respect to the intermediate iscii buffer and original values aIndexOfFirstByteOfFirstUnconvertibleCharacter and 
       
   625 	//aNumberOfUnconvertibleCharacters need to be adjusted accordingly.
       
   626 	
       
   627 	aInputConversionFlags);
       
   628 	if(numberOfUnconvertibleCharacters>0)
       
   629 		{
       
   630 		if(aNumberOfUnconvertibleCharacters == 0)
       
   631 			{
       
   632 			aIndexOfFirstByteOfFirstUnconvertibleCharacter = aNumberOfForeignBytesConsumed + indexOfFirstByteOfFirstUnconvertibleCharacter;
       
   633 			}
       
   634 		aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters;
       
   635 		}
       
   636 	noOfConsumedBytes = aHomogeneousForeign.Length();
       
   637 	//To Check whether it is really required.
       
   638 	NormalizeReturnValue(noOfConsumedBytes,aHomogeneousForeign);
       
   639 	aNumberOfForeignBytesConsumed+=noOfConsumedBytes;
       
   640 	if(aReturnValue>0)
       
   641 		{
       
   642 		TUint normalizedReturnValue = aReturnValue;
       
   643 		
       
   644 		//There original iscii buffer copied to an intermediate iscii buffer and then modified 
       
   645 		//and is then passed for conversion. Now, after conversion, the return value needs to
       
   646 		//be adjusted according to the original buffer. NormalizeReturnValue() does the 
       
   647 		//same thing.
       
   648 		
       
   649 		NormalizeReturnValue(normalizedReturnValue,aHomogeneousForeign);
       
   650 		aNumberOfForeignBytesConsumed-=normalizedReturnValue;
       
   651 		aReturnValue=normalizedReturnValue;
       
   652 		}
       
   653 	
       
   654 	//The HandleHomogeneousRun() method is called in a loop and once there is some
       
   655 	//iscii codes converted to unicode, the ConvertToUnicode() should not return
       
   656 	//CCnvCharacterSetConverter::EErrorIllFormedInput even though the conversion
       
   657 	//method does not convert any of the iscii codes ppassed. To ensure that once the
       
   658 	//first non-zero number of iscii codes are converted, the internal input conversion
       
   659 	//flag is set to EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable.
       
   660 	
       
   661 	if(aNumberOfForeignBytesConsumed>0)
       
   662 		{
       
   663 		aInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable;
       
   664 		}
       
   665 	return;
       
   666 }
       
   667 
       
   668 // -----------------------------------------------------------------------------
       
   669 // IsTruncatedDoubleByteIsciiSequence()
       
   670 //Checks if anIsciiBuffer is a part of multi byte iscii sequence truncated in the middle.
       
   671 //If it is a truncated sequence, then returns ETrue else returns EFalse.
       
   672 //
       
   673 // Returns: ETrue: If the intermediate input iscii buffer is truncated
       
   674 //              EFalse: If the intermediate input iscii buffer is not truncated
       
   675 //
       
   676 // -----------------------------------------------------------------------------
       
   677 //
       
   678 
       
   679 LOCAL_C TBool IsTruncatedDoubleByteIsciiSequence(const TDesC8& anIsciiBuffer)
       
   680 {
       
   681 	RArray<TPtrC8> searchBuffer;
       
   682 	if(anIsciiBuffer.Length () == 0)
       
   683 		return EFalse;
       
   684 	if(anIsciiBuffer[anIsciiBuffer.Length()-1] == 0xEF)
       
   685 	return ETrue;
       
   686 	searchBuffer.Append(KSoftHalant().Mid(0));
       
   687 	searchBuffer.Append(KOm().Mid(0));
       
   688 	searchBuffer.Append(KAvagraha().Mid(0));
       
   689 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
   690 	TBool ret = EFalse;
       
   691 	TBool isNotTruncated =EFalse;
       
   692 	
       
   693 	//First check if the intermediate iscii buffer is ending with a complete multi byte sequence.
       
   694 	//If it ends with a complete multi byte sequence, no need to check if the last character of 
       
   695 	//intermediate iscii is same as first character of multi byte iscii sequence. And return EFalse.
       
   696 	for(TUint counter = 0;counter<searchBuffer.Count();counter++)
       
   697 		{
       
   698 		if(searchBuffer[counter].Compare(anIsciiBuffer.Right(searchBuffer[counter].Length())) == 0)
       
   699 			{
       
   700 			isNotTruncated = ETrue;
       
   701 			break;
       
   702 			}
       
   703 		}
       
   704 	//If the intermediate iscii buffer is not ending with a complete multi byte sequence, and the 
       
   705 	//last code of the iscii buffer is a part of the multibyte sequence, then the iscii buffer is a 
       
   706 	//truncated sequence and in that case return ETrue.
       
   707 	
       
   708 	for(TUint counter = 0;counter<searchBuffer.Count();counter++)
       
   709 		{
       
   710 		if(isNotTruncated)
       
   711 			break;
       
   712 		else if( (anIsciiBuffer[anIsciiBuffer.Length()-1] == searchBuffer[counter][0]))
       
   713 			{
       
   714 			ret =ETrue;
       
   715 			break;
       
   716 			}
       
   717 		}
       
   718 	searchBuffer.Reset();
       
   719 	return ret;
       
   720 }
       
   721 
       
   722 // -----------------------------------------------------------------------------
       
   723 // ReplacementForUnconvertibleUnicodeCharacters()
       
   724 //Returns the replacement character for unconvertible unicode character.
       
   725 //In the current implementation it is 0x1a (ASCII Substitute character)
       
   726 //The default implementation calls ReplacementForUnconvertibleUnicodeCharacters_internal()
       
   727 //in turn which is generated by cnvtool.
       
   728 //
       
   729 // Returns: Replacemt for unconvertible unicode characters (0x1a)
       
   730 //
       
   731 // -----------------------------------------------------------------------------
       
   732 //
       
   733 
       
   734 const TDesC8& CIsciiImplementation::ReplacementForUnconvertibleUnicodeCharacters()
       
   735 	{
       
   736     return ReplacementForUnconvertibleUnicodeCharacters_internal();
       
   737 	}
       
   738 
       
   739 // -----------------------------------------------------------------------------
       
   740 // ConvertFromUnicode()
       
   741 //The main conversion function for converting from unicode to iscii
       
   742 //Loaded and called by the character conversion framework.
       
   743 //In turn calls CnvUtilities::ConvertFromUnicode() which is Symbian provide
       
   744 //utility method for converting unicode to modal character codes.
       
   745 //
       
   746 // Returns: The numbet of unicode codes it could not convert.
       
   747 //
       
   748 // -----------------------------------------------------------------------------
       
   749 //
       
   750 
       
   751 TInt CIsciiImplementation::ConvertFromUnicode(
       
   752          CCnvCharacterSetConverter::TEndianness 
       
   753          aDefaultEndiannessOfForeignCharacters, 
       
   754          const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
       
   755          TDes8& aForeign, 
       
   756          const TDesC16& aUnicode, 
       
   757          CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters )
       
   758 	{
       
   759 	TFixedArray<CnvUtilities::SCharacterSet,KNumberOfIndicCharactersetsSupported> aArrayOfCharacterSets;
       
   760 	aArrayOfCharacterSets[0].iConversionData = &conversionData;
       
   761 	aArrayOfCharacterSets[0].iConvertFromIntermediateBufferInPlace = ConvertFromUnicodeIntermediateBufferInPlace;
       
   762 	aArrayOfCharacterSets[0].iEscapeSequence = &KEscapeSequenceDevanagari();
       
   763 
       
   764 		return CnvUtilities::ConvertFromUnicode(
       
   765 				aDefaultEndiannessOfForeignCharacters, 
       
   766 				aReplacementForUnconvertibleUnicodeCharacters, 
       
   767 				aForeign, 
       
   768 				aUnicode, 
       
   769 				aIndicesOfUnconvertibleCharacters, 
       
   770 				aArrayOfCharacterSets.Array());
       
   771 	}
       
   772 
       
   773 // -----------------------------------------------------------------------------
       
   774 // ConvertToUnicode()
       
   775 //The main conversion function for converting from iscii to unicode
       
   776 //Loaded and called by the character conversion framework.
       
   777 //To support some of the iscii characters, the input forign buffer is
       
   778 //copied to an intermediate buffer and then is then modified and 
       
   779 //CCnvCharactersetConverter::DoConvertToUnicode() is called with
       
   780 //the modified buffer. For extensibility of iscii to other Indic languages
       
   781 //it uses CnvUtilities::SState datastructure. CnvUtilities::SState is a
       
   782 //Symbian defined class for modal charactersets. The escape sequence 
       
   783 //is specified to ATR followed by the script selection code and the conversion
       
   784 //data is specified to be the conversion for the particular script. For the time
       
   785 //being only Devanagari with script selection code 0x42 is supported. If 
       
   786 //any of the other script codes are used the conversion leads to unconvertible
       
   787 //character i.e. 0xFFFD.
       
   788 // Returns: The numbet of iscii codes it could not convert.
       
   789 //
       
   790 // -----------------------------------------------------------------------------
       
   791 //
       
   792 
       
   793 TInt CIsciiImplementation::ConvertToUnicode(
       
   794          CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
       
   795          TDes16& aUnicode, 
       
   796          const TDesC8& aForeign, 
       
   797          TInt& aState, 
       
   798          TInt& aNumberOfUnconvertibleCharacters, 
       
   799          TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter )
       
   800 	{
       
   801 	aNumberOfUnconvertibleCharacters = 0;
       
   802 	TUint aOutputConversionFlags = CCnvCharacterSetConverter::KStateDefault;
       
   803 	aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
       
   804 	TUint internalInputConversionFlags = 0;
       
   805 	TInt numberOfForeignBytesConsumed=0;
       
   806 	TPtrC8 remainderOfForeign(aForeign);
       
   807 	TInt returnValue;
       
   808 	TBool flag = EFalse;
       
   809 	TBool isSkipMatchSequence = EFalse;
       
   810 	const SCnvConversionData* convData;
       
   811 	//Set the iscii conversion data and escape sequence for Devanagari.
       
   812 	TFixedArray<CnvUtilities::SState,KNumberOfIndicCharactersetsSupported> modals;
       
   813 	modals[0].iConversionData = &conversionData;
       
   814 	modals[0].iEscapeSequence = &KEscapeSequenceDevanagari();
       
   815 
       
   816 	aUnicode.SetLength(0);
       
   817 	
       
   818 	//The internal input conversion flag for conversion is set to CCnvCharacterSetConverter::EInputConversionFlagAppend
       
   819 	//so that for each conversion in the conversion loop, the generated conversion buffer is appened to the aUnicode buffer.
       
   820 	internalInputConversionFlags |= CCnvCharacterSetConverter::EInputConversionFlagAppend;
       
   821 	if (aForeign.Length()==0)
       
   822 	{
       
   823 		return 0;
       
   824 	}
       
   825 	//Get the conversion data from the previous call else the conversion data is set to the default 
       
   826 	//conversion data, i.e. Devanagari.
       
   827 	convData=(aState!=CCnvCharacterSetConverter::KStateDefault)? REINTERPRET_CAST(const SCnvConversionData*, aState): modals[0].iConversionData;
       
   828 	FOREVER
       
   829 	{
       
   830 		TBuf8<KMaximumLengthOfIntermediateBuffer> intermediateBuffer;
       
   831 		TUint numberOfForeignBytesConsumedThisTime = 0;
       
   832 		if((remainderOfForeign.Length() >=KMaximumLengthOfIntermediateBuffer) && (aUnicode.MaxLength()-aUnicode.Length() >=KMaximumLengthOfIntermediateBuffer))
       
   833 		{
       
   834 			numberOfForeignBytesConsumedThisTime = KMaximumLengthOfIntermediateBuffer;
       
   835 			intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
   836 			//If the intermediate buffer is a part of truncated buffer sequence but the
       
   837 			//actual input buffer is not truncated then truncated sequence is not converted.
       
   838 			//The intermediate buffer is modified so as not to contain the truncated sequence.
       
   839 			
       
   840 			flag = IsTruncatedDoubleByteIsciiSequence(intermediateBuffer);
       
   841 			if(flag)
       
   842 				{
       
   843 					numberOfForeignBytesConsumedThisTime --;
       
   844 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);					
       
   845 				}
       
   846 			
       
   847 		}
       
   848 		else
       
   849 		{
       
   850 			flag = IsTruncatedDoubleByteIsciiSequence(remainderOfForeign.Left(aUnicode.MaxLength()-aUnicode.Length()));
       
   851 			if(!flag)
       
   852 				{
       
   853 				numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
       
   854 				intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
   855 				}
       
   856 			else
       
   857 				{
       
   858 				if(aForeign.Length()>(numberOfForeignBytesConsumed+aUnicode.Length()))
       
   859 					{
       
   860 					numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length()-1;
       
   861 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
   862 					break;
       
   863 					}
       
   864 				else
       
   865 					{
       
   866 					numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
       
   867 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
   868 					}
       
   869 				}
       
   870 		}			
       
   871 		
       
   872 		//The input intermediate iscii buffer is modified with the search and replace
       
   873 		//buffers. It is required for supporting multibyte iscii sequences.		
       
   874 		FindAndModifyBuffer(intermediateBuffer);
       
   875 		TPtrC8 remainderOfForeignInternal(intermediateBuffer);
       
   876 		TPtrC8 homogeneousRun;
       
   877 		const TInt startOfNextEscapeSequence=intermediateBuffer.Locate(KControlCharacterEscape);
       
   878 		if (startOfNextEscapeSequence!=0) 
       
   879 			{
       
   880 			if (startOfNextEscapeSequence==KErrNotFound)
       
   881 				{
       
   882 				homogeneousRun.Set(remainderOfForeignInternal);
       
   883 				remainderOfForeignInternal.Set(NULL, 0);
       
   884 				}
       
   885 			else
       
   886 				{
       
   887 				__ASSERT_DEBUG(startOfNextEscapeSequence>0, User::Panic(KPanicReason,EPanicBadStartOfNextEscapeSequence));
       
   888 				homogeneousRun.Set(remainderOfForeignInternal.Left(startOfNextEscapeSequence));
       
   889 				remainderOfForeignInternal.Set(remainderOfForeignInternal.Mid(startOfNextEscapeSequence));
       
   890 				}
       
   891 			isSkipMatchSequence = ETrue;
       
   892 			}
       
   893 		FOREVER
       
   894 			{
       
   895 			if(!isSkipMatchSequence)
       
   896 				{
       
   897 				if (!NextHomogeneousForeignRun(convData, numberOfForeignBytesConsumed, homogeneousRun, 
       
   898 											remainderOfForeignInternal, modals.Array(), aOutputConversionFlags))
       
   899 					{
       
   900 					break;
       
   901 					}
       
   902 				}
       
   903 			HandleHomogeneousRun( convData, aDefaultEndiannessOfForeignCharacters, aUnicode, homogeneousRun, aNumberOfUnconvertibleCharacters, 
       
   904 								aIndexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,internalInputConversionFlags,
       
   905 								numberOfForeignBytesConsumed,returnValue);
       
   906 			if(returnValue<0)
       
   907 				{
       
   908 				return returnValue;
       
   909 				}
       
   910 			isSkipMatchSequence = EFalse;
       
   911 			}
       
   912 		if(returnValue > 0)
       
   913 			break;
       
   914 		if ((!flag && (numberOfForeignBytesConsumedThisTime != KMaximumLengthOfIntermediateBuffer)) || (flag && (numberOfForeignBytesConsumedThisTime != (KMaximumLengthOfIntermediateBuffer-1) )))
       
   915 			break;
       
   916 		remainderOfForeign.Set(aForeign.Mid(numberOfForeignBytesConsumed));				
       
   917 	}
       
   918 	//If the number of iscii bytes consumed by the conversion is zero also the output conversion
       
   919 	//flag is not set to EOutputConversionFlagInputIsTruncated, then return EErrorIllFormedInput.
       
   920 	if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated))
       
   921 		{
       
   922 		return CCnvCharacterSetConverter::EErrorIllFormedInput;
       
   923 		}
       
   924 	//Set the conversion data sothat next time when ConvertToUnicode() is called,
       
   925 	//will use the previous conversion data.
       
   926 	aState=REINTERPRET_CAST(TInt, convData);
       
   927 	return aForeign.Length()-numberOfForeignBytesConsumed;
       
   928     }
       
   929 
       
   930 // -----------------------------------------------------------------------------
       
   931 // IsInThisCharacterSetL()
       
   932 //The method tells how probable it is that a sample piece of text is encoded in this character set.
       
   933 //On return aConfidenceLevel, indicates how confident the function is about its return value. For
       
   934 //iscii it is the default implementation and it does not implement the autodetect functionality.
       
   935 //Loaded and called by the character conversion framework.
       
   936 //
       
   937 // Returns: EFalse: To tell CCnvCharacterSetConverter::AutoDetectCharacterSetL()  that the plug-in DLL
       
   938 //                          is not implementing a function of this signature and is therefore empty.
       
   939 //
       
   940 // -----------------------------------------------------------------------------
       
   941 //
       
   942 
       
   943 
       
   944 //Default implementation for IsInThisCharacterSetL()
       
   945 
       
   946 TBool CIsciiImplementation::IsInThisCharacterSetL(
       
   947          TBool& aSetToTrue, 
       
   948          TInt& aConfidenceLevel, 
       
   949          const TDesC8& )
       
   950 	{
       
   951     	aSetToTrue = EFalse;
       
   952 	aConfidenceLevel = 0;
       
   953 	return EFalse;
       
   954 	}
       
   955 
       
   956 // -----------------------------------------------------------------------------
       
   957 // NewL()
       
   958 //Factory function for CIsciiImplementation(). Instantiates a CIsciiImplementation object on heap
       
   959 //and returns the pointer to it.
       
   960 //
       
   961 // Returns: CIsciiImplementation*
       
   962 //
       
   963 // -----------------------------------------------------------------------------
       
   964 //
       
   965 	
       
   966 CIsciiImplementation* CIsciiImplementation::NewL()
       
   967     {
       
   968     CIsciiImplementation* self = new(ELeave) CIsciiImplementation;
       
   969     return self;
       
   970     }
       
   971 
       
   972 // -----------------------------------------------------------------------------
       
   973 // CIsciiImplementation()
       
   974 //default constructor, does nothing
       
   975 //
       
   976 // Returns: Nothing
       
   977 //
       
   978 // -----------------------------------------------------------------------------
       
   979 //
       
   980 CIsciiImplementation::CIsciiImplementation()
       
   981     {
       
   982     }
       
   983 
       
   984 // -----------------------------------------------------------------------------
       
   985 // ~CIsciiImplementation()
       
   986 //default desstructor, does nothing
       
   987 //
       
   988 // Returns: Nothing
       
   989 //
       
   990 // -----------------------------------------------------------------------------
       
   991 //
       
   992 
       
   993 CIsciiImplementation::~CIsciiImplementation()
       
   994     {
       
   995     }
       
   996 
       
   997 // ECOM CREATION FUNCTION
       
   998 const TImplementationProxy ImplementationTable[] = 
       
   999     {
       
  1000     // Used also in 0x1027508E.rss ( implementation_uid )
       
  1001     IMPLEMENTATION_PROXY_ENTRY( 0x1027508E, CIsciiImplementation::NewL )
       
  1002     };
       
  1003 
       
  1004 // -----------------------------------------------------------------------------
       
  1005 // ImplementationGroupProxy()
       
  1006 //Returns a pointer to TImplementationProxy object which contains the implementation uid vs factory
       
  1007 //function table. Also on return sets the aTableCount to the number of entries in the table.
       
  1008 //
       
  1009 // Returns: TImplementationProxy*
       
  1010 //
       
  1011 // -----------------------------------------------------------------------------
       
  1012 //
       
  1013 EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount )
       
  1014     {
       
  1015     aTableCount = sizeof( ImplementationTable ) / sizeof(TImplementationProxy);
       
  1016     return ImplementationTable;
       
  1017     }
       
  1018 #else
       
  1019 
       
  1020 #include <convplug.h>
       
  1021 
       
  1022 #ifndef EKA2
       
  1023 // -----------------------------------------------------------------------------
       
  1024 // E32Dll()
       
  1025 //For EKA1 this is the entry point for the DLL.
       
  1026 //
       
  1027 // Returns: KErrNone
       
  1028 //
       
  1029 // -----------------------------------------------------------------------------
       
  1030 //
       
  1031 GLDEF_C TInt E32Dll(TDllReason)
       
  1032 {
       
  1033 	return KErrNone;
       
  1034 }
       
  1035 #endif
       
  1036 
       
  1037 //Checks if a descriptor starts with another descriptor at the begining.
       
  1038 LOCAL_C TBool IsStartOf(const TDesC8& aEscapeSequence, const TDesC8& aBuffer)
       
  1039 {
       
  1040 	const TInt lengthOfStart=aEscapeSequence.Length();
       
  1041 	return (aBuffer.Length()>=lengthOfStart) && (aBuffer.Left(lengthOfStart)==aEscapeSequence);
       
  1042 }
       
  1043 // -----------------------------------------------------------------------------
       
  1044 // MatchesEscapeSequence()
       
  1045 //If the remainder of the foreign text starts with the passed escapesequence, modifies the remainder of the foreign text
       
  1046 //and  sets the homogeneous run buffer that uses the same conversion data.
       
  1047 //The homogeneous run buffer is the buffer that will use a single conversion data, it doesn't contain the attribute code
       
  1048 // neither it contains the script switching code.
       
  1049 //The aRemainderOfForeign buffer 
       
  1050 
       
  1051 // Returns: ETrue: If the sequence contains the escape sequence
       
  1052 //              EFalse: If the sequence does not contain the escape sequence
       
  1053 //
       
  1054 // -----------------------------------------------------------------------------
       
  1055 //
       
  1056 LOCAL_C TBool MatchesEscapeSequence(TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun,
       
  1057 		TPtrC8& aRemainderOfForeign, const TDesC8& aEscapeSequence)
       
  1058 {
       
  1059 	const TInt lengthOfEscapeSequence=aEscapeSequence.Length();
       
  1060 	if (IsStartOf(aEscapeSequence, aRemainderOfForeign))
       
  1061 		{
       
  1062 		aRemainderOfForeign.Set(aRemainderOfForeign.Mid(lengthOfEscapeSequence));
       
  1063 		const TInt startOfNextEscapeSequence=aRemainderOfForeign.Locate(KControlCharacterEscape);
       
  1064 		if (startOfNextEscapeSequence==KErrNotFound)
       
  1065 			{
       
  1066 			aHomogeneousRun.Set(aRemainderOfForeign);
       
  1067 			aRemainderOfForeign.Set(NULL, 0);
       
  1068 			}
       
  1069 		else
       
  1070 			{
       
  1071 			aHomogeneousRun.Set(aRemainderOfForeign.Left(startOfNextEscapeSequence));
       
  1072 			aRemainderOfForeign.Set(aRemainderOfForeign.Mid(startOfNextEscapeSequence));
       
  1073 			}
       
  1074 		aNumberOfForeignBytesConsumed+=lengthOfEscapeSequence;
       
  1075 		return ETrue;
       
  1076 		}
       
  1077 	return EFalse;
       
  1078 }
       
  1079 
       
  1080 // -----------------------------------------------------------------------------
       
  1081 // NextHomogeneousForeignRun()
       
  1082 //Matches the escape sequence of each of the elements of the SState array with the remainder of
       
  1083 //foreign text and if the escape sequence matches with the start of remainder of the foreign text, 
       
  1084 //then the conversion data is set to the conversion data corresponding to the escape sequence
       
  1085 //Also the homogeneous foreign text for conversion with the same escape sequence is set.
       
  1086 
       
  1087 // Returns: ETrue: If length of the remainder of foreign buffer is nonzero.
       
  1088 //              EFalse: If length of the remainder of foreign buffer is zero.
       
  1089 //
       
  1090 // -----------------------------------------------------------------------------
       
  1091 //
       
  1092 
       
  1093 
       
  1094 LOCAL_C TBool NextHomogeneousForeignRun(const SCnvConversionData*& aConversionData, TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TArray<CnvUtilities::SState>& aArrayOfStates, TUint& aOutputConversionFlags)
       
  1095 {
       
  1096 	TBool returnValue = EFalse;
       
  1097 	TBool foundState = EFalse;
       
  1098 	__ASSERT_DEBUG((aRemainderOfForeign.Length()==0) || (aRemainderOfForeign[0]==KControlCharacterEscape), User::Panic(KPanicReason,EPanicBadRemainderOfForeign));
       
  1099 	if (aRemainderOfForeign.Length()==0)
       
  1100 		{
       
  1101 		return returnValue;
       
  1102 		}
       
  1103 	const TInt numberOfStates=aArrayOfStates.Count();
       
  1104 	TInt i;
       
  1105 	for (i=0; i<numberOfStates; ++i)
       
  1106 		{
       
  1107 		const CnvUtilities::SState& state=aArrayOfStates[i];
       
  1108 		if (MatchesEscapeSequence(aNumberOfForeignBytesConsumed, aHomogeneousRun, aRemainderOfForeign, *state.iEscapeSequence))
       
  1109 			{
       
  1110 			aConversionData=state.iConversionData;
       
  1111 			foundState = ETrue;
       
  1112 			}
       
  1113 		}
       
  1114 	if(!foundState)
       
  1115 		{
       
  1116 		for (i=0; i<numberOfStates; ++i)
       
  1117 			{
       
  1118 			if (IsStartOf(aRemainderOfForeign, *aArrayOfStates[i].iEscapeSequence))
       
  1119 				{
       
  1120 				// aRemainderOfForeign ends with a truncated escape sequence, so ConvertToUnicode cannot convert any more
       
  1121 				aOutputConversionFlags|=CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated;
       
  1122 				break;
       
  1123 				}
       
  1124 			}
       
  1125 
       
  1126 		MatchesEscapeSequence(aNumberOfForeignBytesConsumed,aHomogeneousRun,aRemainderOfForeign,aRemainderOfForeign.Left(2));
       
  1127 		aConversionData = &conversionDataDummy;	
       
  1128 		returnValue = ETrue;
       
  1129 		}
       
  1130 		if (aHomogeneousRun.Length()>0)
       
  1131 			{
       
  1132 			returnValue = ETrue;
       
  1133 			}
       
  1134 		return returnValue;		
       
  1135 }
       
  1136 // -----------------------------------------------------------------------------
       
  1137 // ConvertFromUnicodeIntermediateBufferInPlace()
       
  1138 //Default implementation for conversion to the intermediate buffer
       
  1139 //It modifies the unicode buffer before it is converted back to iscii.
       
  1140 //The current implementation of iscii plug-in doesn't require any
       
  1141 //modification to the default implementation
       
  1142 // Returns: Nothing
       
  1143 //
       
  1144 // -----------------------------------------------------------------------------
       
  1145 //
       
  1146 
       
  1147 
       
  1148 LOCAL_C void ConvertFromUnicodeIntermediateBufferInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
       
  1149 {
       
  1150 	CnvUtilities::ConvertFromIntermediateBufferInPlace(aStartPositionInDescriptor, aDescriptor, aNumberOfCharactersThatDroppedOut, KEscapeSequenceDevanagari, 1);
       
  1151 }
       
  1152 
       
  1153 // -----------------------------------------------------------------------------
       
  1154 // DoFindAndModifyBuffer()
       
  1155 //Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
       
  1156 //Introduced for handling multibyte iscii sequence.
       
  1157 //Takes the search buffer array and the replacement buffer arrays as input to it and replaces all
       
  1158 //the occurances of the search buffer with the corresponding replace buffer.
       
  1159 // Returns: Nothing
       
  1160 //
       
  1161 // -----------------------------------------------------------------------------
       
  1162 //
       
  1163 
       
  1164 LOCAL_C void DoFindAndModifyBuffer(TDes8& aModifyBuffer,const TDesC8& aSearchBuffer,const TDesC8& aReplaceBuffer)
       
  1165 {
       
  1166 	FOREVER
       
  1167 	{
       
  1168 		TInt offset;
       
  1169 		__ASSERT_ALWAYS((aSearchBuffer.Length()>= aReplaceBuffer.Length()),User::Panic(KPanicReason,EPanicBadReplacementBuffer));
       
  1170 		if((offset = aModifyBuffer.Find(aSearchBuffer)) != KErrNotFound)
       
  1171 		{
       
  1172 			TUint8 *pointerToBuffer = const_cast<TUint8*> (aModifyBuffer.Ptr());
       
  1173 			Mem::Copy(pointerToBuffer+offset,aReplaceBuffer.Ptr(),aReplaceBuffer.Length());
       
  1174 			Mem::Copy(pointerToBuffer+offset+aReplaceBuffer.Length(),pointerToBuffer+offset+aSearchBuffer.Length(),aModifyBuffer.Length()-aSearchBuffer.Length()-offset);
       
  1175 			aModifyBuffer.SetLength(aModifyBuffer.Length() - aSearchBuffer.Length() + aReplaceBuffer.Length());
       
  1176 		}
       
  1177 		else
       
  1178 			break;
       
  1179 	}
       
  1180 	
       
  1181 }
       
  1182 
       
  1183 // -----------------------------------------------------------------------------
       
  1184 // FindAndModifyBuffer()
       
  1185 //Modifies the iscii buffer by replacing the search buffer with the replacement buffer.
       
  1186 //Calls DoFindAndModifyBuffer() and supplies the search buffer and replacement buffer.
       
  1187 //Introduced for handling multibyte iscii sequence.
       
  1188 // Returns: Nothing
       
  1189 //
       
  1190 // -----------------------------------------------------------------------------
       
  1191 //
       
  1192 
       
  1193 LOCAL_C void FindAndModifyBuffer(TDes8& aModifyBuffer)
       
  1194 {
       
  1195 	RArray<TPtrC8> searchBuffer;
       
  1196 	RArray<TPtrC8> replaceBuffer;
       
  1197 	
       
  1198 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
  1199 	searchBuffer.Append(KSoftHalant().Mid(0));
       
  1200 	searchBuffer.Append(KOm().Mid(0));
       
  1201 	searchBuffer.Append(KAvagraha().Mid(0));
       
  1202 	
       
  1203 	replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
       
  1204 	replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
       
  1205 	replaceBuffer.Append(KReplacementForOm().Mid(0));
       
  1206 	replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
       
  1207 	
       
  1208 	for(TInt counter=0;counter<searchBuffer.Count();counter++)
       
  1209 	{
       
  1210 		DoFindAndModifyBuffer(aModifyBuffer,searchBuffer[counter],replaceBuffer[counter]);
       
  1211 	}
       
  1212 	searchBuffer.Reset();
       
  1213 	replaceBuffer.Reset();
       
  1214 	
       
  1215 }
       
  1216 
       
  1217 // -----------------------------------------------------------------------------
       
  1218 // DoNormalizeReturnValue()
       
  1219 //Modifies the return value(Number of bytes did not get converted) according to the modified
       
  1220 //intermediate buffer. Takes the modified intermediate buffer, return value, search and replace
       
  1221 //buffers. Searches for the replace buffer in the intermediate buffer and if found, it looks for
       
  1222 //the actual buffer corresponding to the replace buffer and adds the difference of the lengths
       
  1223 //of the actual to replace buffer to the return value.
       
  1224 // Returns: Nothing
       
  1225 //
       
  1226 // -----------------------------------------------------------------------------
       
  1227 //
       
  1228 
       
  1229 LOCAL_C void DoNormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer,RArray<TPtrC8>& anArrayOfSearches,RArray<TPtrC8>& anArrayOfReplaces)
       
  1230 {
       
  1231 	TPtr8 buffer(const_cast<TUint8*>(aBuffer.Ptr()),aBuffer.Length(),aBuffer.Length());
       
  1232 	TUint count = anArrayOfSearches.Count();
       
  1233 	FOREVER
       
  1234 	{
       
  1235 		TBool flag = EFalse;
       
  1236 		for(TUint i=0;i<count;i++)
       
  1237 		{
       
  1238 			TPtrC8 searchBufferForComparison(buffer.Right(anArrayOfReplaces[i].Length()));
       
  1239 			TInt returnCompare = searchBufferForComparison.Compare(anArrayOfReplaces[i]);
       
  1240 			if(returnCompare == 0)
       
  1241 			{
       
  1242 				flag =ETrue;
       
  1243 				aReturnValue += (anArrayOfSearches[i].Length() - anArrayOfReplaces[i].Length());
       
  1244 				buffer=buffer.MidTPtr(0,buffer.Length()-anArrayOfReplaces[i].Length());
       
  1245 				break;
       
  1246 			}
       
  1247 		}
       
  1248 		
       
  1249 		if(buffer.Length() == 0)
       
  1250 		{
       
  1251 			break;
       
  1252 		}
       
  1253 		
       
  1254 		if(!flag)
       
  1255 		{
       
  1256 			buffer=buffer.MidTPtr(0,buffer.Length()-1);
       
  1257 		}
       
  1258 	}
       
  1259 
       
  1260 }
       
  1261 
       
  1262 // -----------------------------------------------------------------------------
       
  1263 // NormalizeReturnValue()
       
  1264 //Modifies the return value(Number of bytes did not get converted) according to the 
       
  1265 //replacements done to the iscii buffer before conversion.
       
  1266 //Internally calls DoNormalizeReturnValue() by suppling the search and replacement 
       
  1267 //buffers.
       
  1268 
       
  1269 // Returns: Nothing
       
  1270 //
       
  1271 // -----------------------------------------------------------------------------
       
  1272 //
       
  1273 
       
  1274 LOCAL_C void NormalizeReturnValue(TUint& aReturnValue,const TDesC8& aBuffer)
       
  1275 {
       
  1276 	RArray<TPtrC8> searchBuffer;
       
  1277 	RArray<TPtrC8> replaceBuffer;
       
  1278 	
       
  1279 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
  1280 	searchBuffer.Append(KSoftHalant().Mid(0));
       
  1281 	searchBuffer.Append(KOm().Mid(0));
       
  1282 	searchBuffer.Append(KAvagraha().Mid(0));
       
  1283 	
       
  1284 	replaceBuffer.Append(KReplacementForExplicitHalant().Mid(0));
       
  1285 	replaceBuffer.Append(KReplacementForSoftHalant().Mid(0));
       
  1286 	replaceBuffer.Append(KReplacementForOm().Mid(0));
       
  1287 	replaceBuffer.Append(KReplacementForAvagraha().Mid(0));
       
  1288 	DoNormalizeReturnValue(aReturnValue,aBuffer,searchBuffer,replaceBuffer);
       
  1289 	searchBuffer.Reset();
       
  1290 	replaceBuffer.Reset();
       
  1291 }
       
  1292 
       
  1293 // -----------------------------------------------------------------------------
       
  1294 // HandleHomogeneousRun()
       
  1295 //Handles a homogeneous foreign buffer and converts the foreign buffer to unicode
       
  1296 //On return the aUnicode argument contains the converted unicode data.
       
  1297 //Also it sets the return value, returned from the conversion. The return value also
       
  1298 //takes into account if there is any buffer modification done before passing it to
       
  1299 //CCnvCharacterSetConverter::DoConvertToUnicode()
       
  1300 //buffers.
       
  1301 
       
  1302 // Returns: Nothing
       
  1303 //
       
  1304 // -----------------------------------------------------------------------------
       
  1305 //
       
  1306 
       
  1307 LOCAL_C void HandleHomogeneousRun(const SCnvConversionData*& aConversionData, 
       
  1308 							CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
       
  1309 							TDes16& aUnicode,
       
  1310 							const TDesC8& aHomogeneousForeign,
       
  1311 							TInt& aNumberOfUnconvertibleCharacters,
       
  1312 							TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
       
  1313 							TUint& aOutputConversionFlags,
       
  1314 							TUint aInputConversionFlags,TInt& aNumberOfForeignBytesConsumed,
       
  1315 							TInt& aReturnValue)
       
  1316 {
       
  1317 	TInt numberOfUnconvertibleCharacters;
       
  1318 	TInt indexOfFirstByteOfFirstUnconvertibleCharacter;
       
  1319 	TUint noOfConsumedBytes = 0;
       
  1320 	if(aConversionData == NULL)
       
  1321 		{
       
  1322 		aReturnValue = CCnvCharacterSetConverter::EErrorIllFormedInput;
       
  1323 		return;
       
  1324 		}
       
  1325 	aReturnValue = CCnvCharacterSetConverter::DoConvertToUnicode(*aConversionData,aDefaultEndiannessOfForeignCharacters,
       
  1326 															  aUnicode,aHomogeneousForeign,numberOfUnconvertibleCharacters,
       
  1327 															  indexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,
       
  1328 
       
  1329 	//The numberOfUnconvertibleCharacters and indexOfFirstByteOfFirstUnconvertibleCharacter are the values with
       
  1330 	//respect to the intermediate iscii buffer and original values aIndexOfFirstByteOfFirstUnconvertibleCharacter and 
       
  1331 	//aNumberOfUnconvertibleCharacters need to be adjusted accordingly.
       
  1332 	
       
  1333 	aInputConversionFlags);
       
  1334 	if(numberOfUnconvertibleCharacters>0)
       
  1335 		{
       
  1336 		if(aNumberOfUnconvertibleCharacters == 0)
       
  1337 			{
       
  1338 			aIndexOfFirstByteOfFirstUnconvertibleCharacter = aNumberOfForeignBytesConsumed + indexOfFirstByteOfFirstUnconvertibleCharacter;
       
  1339 			}
       
  1340 		aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters;
       
  1341 		}
       
  1342 	noOfConsumedBytes = aHomogeneousForeign.Length();
       
  1343 	//To Check whether it is really required.
       
  1344 	NormalizeReturnValue(noOfConsumedBytes,aHomogeneousForeign);
       
  1345 	aNumberOfForeignBytesConsumed+=noOfConsumedBytes;
       
  1346 	if(aReturnValue>0)
       
  1347 		{
       
  1348 		TUint normalizedReturnValue = aReturnValue;
       
  1349 		
       
  1350 		//There original iscii buffer copied to an intermediate iscii buffer and then modified 
       
  1351 		//and is then passed for conversion. Now, after conversion, the return value needs to
       
  1352 		//be adjusted according to the original buffer. NormalizeReturnValue() does the 
       
  1353 		//same thing.
       
  1354 		
       
  1355 		NormalizeReturnValue(normalizedReturnValue,aHomogeneousForeign);
       
  1356 		aNumberOfForeignBytesConsumed-=normalizedReturnValue;
       
  1357 		aReturnValue=normalizedReturnValue;
       
  1358 		}
       
  1359 	
       
  1360 	//The HandleHomogeneousRun() method is called in a loop and once there is some
       
  1361 	//iscii codes converted to unicode, the ConvertToUnicode() should not return
       
  1362 	//CCnvCharacterSetConverter::EErrorIllFormedInput even though the conversion
       
  1363 	//method does not convert any of the iscii codes ppassed. To ensure that once the
       
  1364 	//first non-zero number of iscii codes are converted, the internal input conversion
       
  1365 	//flag is set to EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable.
       
  1366 	
       
  1367 	if(aNumberOfForeignBytesConsumed>0)
       
  1368 		{
       
  1369 		aInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable;
       
  1370 		}
       
  1371 	return;
       
  1372 }
       
  1373 
       
  1374 // -----------------------------------------------------------------------------
       
  1375 // IsTruncatedDoubleByteIsciiSequence()
       
  1376 //Checks if anIsciiBuffer is a part of multi byte iscii sequence truncated in the middle.
       
  1377 //If it is a truncated sequence, then returns ETrue else returns EFalse.
       
  1378 //
       
  1379 // Returns: ETrue: If the intermediate input iscii buffer is truncated
       
  1380 //              EFalse: If the intermediate input iscii buffer is not truncated
       
  1381 //
       
  1382 // -----------------------------------------------------------------------------
       
  1383 //
       
  1384 
       
  1385 LOCAL_C TBool IsTruncatedDoubleByteIsciiSequence(const TDesC8& anIsciiBuffer)
       
  1386 {
       
  1387 	RArray<TPtrC8> searchBuffer;
       
  1388 	if(anIsciiBuffer.Length () == 0)
       
  1389 		return EFalse;
       
  1390 	if(anIsciiBuffer[anIsciiBuffer.Length()-1] == 0xEF)
       
  1391 	return ETrue;
       
  1392 	searchBuffer.Append(KSoftHalant().Mid(0));
       
  1393 	searchBuffer.Append(KOm().Mid(0));
       
  1394 	searchBuffer.Append(KAvagraha().Mid(0));
       
  1395 	searchBuffer.Append(KExplicitHalant().Mid(0));
       
  1396 	TBool ret = EFalse;
       
  1397 	TBool isNotTruncated =EFalse;
       
  1398 	
       
  1399 	//First check if the intermediate iscii buffer is ending with a complete multi byte sequence.
       
  1400 	//If it ends with a complete multi byte sequence, no need to check if the last character of 
       
  1401 	//intermediate iscii is same as first character of multi byte iscii sequence. And return EFalse.
       
  1402 	for(TUint counter = 0;counter<searchBuffer.Count();counter++)
       
  1403 		{
       
  1404 		if(searchBuffer[counter].Compare(anIsciiBuffer.Right(searchBuffer[counter].Length())) == 0)
       
  1405 			{
       
  1406 			isNotTruncated = ETrue;
       
  1407 			break;
       
  1408 			}
       
  1409 		}
       
  1410 	//If the intermediate iscii buffer is not ending with a complete multi byte sequence, and the 
       
  1411 	//last code of the iscii buffer is a part of the multibyte sequence, then the iscii buffer is a 
       
  1412 	//truncated sequence and in that case return ETrue.
       
  1413 	
       
  1414 	for(TUint counter = 0;counter<searchBuffer.Count();counter++)
       
  1415 		{
       
  1416 		if(isNotTruncated)
       
  1417 			break;
       
  1418 		else if( (anIsciiBuffer[anIsciiBuffer.Length()-1] == searchBuffer[counter][0]))
       
  1419 			{
       
  1420 			ret =ETrue;
       
  1421 			break;
       
  1422 			}
       
  1423 		}
       
  1424 	searchBuffer.Reset();
       
  1425 	return ret;
       
  1426 }
       
  1427 
       
  1428 // -----------------------------------------------------------------------------
       
  1429 // ReplacementForUnconvertibleUnicodeCharacters()
       
  1430 //Returns the replacement character for unconvertible unicode character.
       
  1431 //In the current implementation it is 0x1a (ASCII Substitute character)
       
  1432 //The default implementation calls ReplacementForUnconvertibleUnicodeCharacters_internal()
       
  1433 //in turn which is generated by cnvtool.
       
  1434 //
       
  1435 // Returns: Replacemt for unconvertible unicode characters (0x1a)
       
  1436 //
       
  1437 // -----------------------------------------------------------------------------
       
  1438 //
       
  1439 
       
  1440 EXPORT_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters()
       
  1441 	{
       
  1442     return ReplacementForUnconvertibleUnicodeCharacters_internal();
       
  1443 	}
       
  1444 
       
  1445 // -----------------------------------------------------------------------------
       
  1446 // ConvertFromUnicode()
       
  1447 //The main conversion function for converting from unicode to iscii
       
  1448 //Loaded and called by the character conversion framework.
       
  1449 //In turn calls CnvUtilities::ConvertFromUnicode() which is Symbian provide
       
  1450 //utility method for converting unicode to modal character codes.
       
  1451 //
       
  1452 // Returns: The numbet of unicode codes it could not convert.
       
  1453 //
       
  1454 // -----------------------------------------------------------------------------
       
  1455 //
       
  1456 
       
  1457 EXPORT_C TInt ConvertFromUnicode(
       
  1458          CCnvCharacterSetConverter::TEndianness 
       
  1459          aDefaultEndiannessOfForeignCharacters, 
       
  1460          const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
       
  1461          TDes8& aForeign, 
       
  1462          const TDesC16& aUnicode, 
       
  1463          CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters )
       
  1464 	{
       
  1465 	TFixedArray<CnvUtilities::SCharacterSet,KNumberOfIndicCharactersetsSupported> aArrayOfCharacterSets;
       
  1466 	aArrayOfCharacterSets[0].iConversionData = &conversionData;
       
  1467 	aArrayOfCharacterSets[0].iConvertFromIntermediateBufferInPlace = ConvertFromUnicodeIntermediateBufferInPlace;
       
  1468 	aArrayOfCharacterSets[0].iEscapeSequence = &KEscapeSequenceDevanagari();
       
  1469 
       
  1470 		return CnvUtilities::ConvertFromUnicode(
       
  1471 				aDefaultEndiannessOfForeignCharacters, 
       
  1472 				aReplacementForUnconvertibleUnicodeCharacters, 
       
  1473 				aForeign, 
       
  1474 				aUnicode, 
       
  1475 				aIndicesOfUnconvertibleCharacters, 
       
  1476 				aArrayOfCharacterSets.Array());
       
  1477 	}
       
  1478 
       
  1479 // -----------------------------------------------------------------------------
       
  1480 // ConvertToUnicode()
       
  1481 //The main conversion function for converting from iscii to unicode
       
  1482 //Loaded and called by the character conversion framework.
       
  1483 //To support some of the iscii characters, the input forign buffer is
       
  1484 //copied to an intermediate buffer and then is then modified and 
       
  1485 //CCnvCharactersetConverter::DoConvertToUnicode() is called with
       
  1486 //the modified buffer. For extensibility of iscii to other Indic languages
       
  1487 //it uses CnvUtilities::SState datastructure. CnvUtilities::SState is a
       
  1488 //Symbian defined class for modal charactersets. The escape sequence 
       
  1489 //is specified to ATR followed by the script selection code and the conversion
       
  1490 //data is specified to be the conversion for the particular script. For the time
       
  1491 //being only Devanagari with script selection code 0x42 is supported. If 
       
  1492 //any of the other script codes are used the conversion leads to unconvertible
       
  1493 //character i.e. 0xFFFD.
       
  1494 // Returns: The numbet of iscii codes it could not convert.
       
  1495 //
       
  1496 // -----------------------------------------------------------------------------
       
  1497 //
       
  1498 
       
  1499 EXPORT_C TInt ConvertToUnicode(
       
  1500          CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
       
  1501          TDes16& aUnicode, 
       
  1502          const TDesC8& aForeign, 
       
  1503          TInt& aState, 
       
  1504          TInt& aNumberOfUnconvertibleCharacters, 
       
  1505          TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter )
       
  1506 	{
       
  1507 	aNumberOfUnconvertibleCharacters = 0;
       
  1508 	TUint aOutputConversionFlags = CCnvCharacterSetConverter::KStateDefault;
       
  1509 	aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
       
  1510 	TUint internalInputConversionFlags = 0;
       
  1511 	TInt numberOfForeignBytesConsumed=0;
       
  1512 	TPtrC8 remainderOfForeign(aForeign);
       
  1513 	TInt returnValue;
       
  1514 	TBool flag = EFalse;
       
  1515 	TBool isSkipMatchSequence = EFalse;
       
  1516 	const SCnvConversionData* convData;
       
  1517 	//Set the iscii conversion data and escape sequence for Devanagari.
       
  1518 	TFixedArray<CnvUtilities::SState,KNumberOfIndicCharactersetsSupported> modals;
       
  1519 	modals[0].iConversionData = &conversionData;
       
  1520 	modals[0].iEscapeSequence = &KEscapeSequenceDevanagari();
       
  1521 
       
  1522 	aUnicode.SetLength(0);
       
  1523 	
       
  1524 	//The internal input conversion flag for conversion is set to CCnvCharacterSetConverter::EInputConversionFlagAppend
       
  1525 	//so that for each conversion in the conversion loop, the generated conversion buffer is appened to the aUnicode buffer.
       
  1526 	internalInputConversionFlags |= CCnvCharacterSetConverter::EInputConversionFlagAppend;
       
  1527 	if (aForeign.Length()==0)
       
  1528 	{
       
  1529 		return 0;
       
  1530 	}
       
  1531 	//Get the conversion data from the previous call else the conversion data is set to the default 
       
  1532 	//conversion data, i.e. Devanagari.
       
  1533 	convData=(aState!=CCnvCharacterSetConverter::KStateDefault)? REINTERPRET_CAST(const SCnvConversionData*, aState): modals[0].iConversionData;
       
  1534 	FOREVER
       
  1535 	{
       
  1536 		TBuf8<KMaximumLengthOfIntermediateBuffer> intermediateBuffer;
       
  1537 		TUint numberOfForeignBytesConsumedThisTime = 0;
       
  1538 		if((remainderOfForeign.Length() >=KMaximumLengthOfIntermediateBuffer) && (aUnicode.MaxLength()-aUnicode.Length() >=KMaximumLengthOfIntermediateBuffer))
       
  1539 		{
       
  1540 			numberOfForeignBytesConsumedThisTime = KMaximumLengthOfIntermediateBuffer;
       
  1541 			intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
  1542 			//If the intermediate buffer is a part of truncated buffer sequence but the
       
  1543 			//actual input buffer is not truncated then truncated sequence is not converted.
       
  1544 			//The intermediate buffer is modified so as not to contain the truncated sequence.
       
  1545 			
       
  1546 			flag = IsTruncatedDoubleByteIsciiSequence(intermediateBuffer);
       
  1547 			if(flag)
       
  1548 				{
       
  1549 					numberOfForeignBytesConsumedThisTime --;
       
  1550 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);					
       
  1551 				}
       
  1552 			
       
  1553 		}
       
  1554 		else
       
  1555 		{
       
  1556 			flag = IsTruncatedDoubleByteIsciiSequence(remainderOfForeign.Left(aUnicode.MaxLength()-aUnicode.Length()));
       
  1557 			if(!flag)
       
  1558 				{
       
  1559 				numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
       
  1560 				intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
  1561 				}
       
  1562 			else
       
  1563 				{
       
  1564 				if(aForeign.Length()>(numberOfForeignBytesConsumed+aUnicode.Length()))
       
  1565 					{
       
  1566 					numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length()-1;
       
  1567 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
  1568 					break;
       
  1569 					}
       
  1570 				else
       
  1571 					{
       
  1572 					numberOfForeignBytesConsumedThisTime = aUnicode.MaxLength()-aUnicode.Length();
       
  1573 					intermediateBuffer = remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime);
       
  1574 					}
       
  1575 				}
       
  1576 		}			
       
  1577 		
       
  1578 		//The input intermediate iscii buffer is modified with the search and replace
       
  1579 		//buffers. It is required for supporting multibyte iscii sequences.		
       
  1580 		FindAndModifyBuffer(intermediateBuffer);
       
  1581 		TPtrC8 remainderOfForeignInternal(intermediateBuffer);
       
  1582 		TPtrC8 homogeneousRun;
       
  1583 		const TInt startOfNextEscapeSequence=intermediateBuffer.Locate(KControlCharacterEscape);
       
  1584 		if (startOfNextEscapeSequence!=0) 
       
  1585 			{
       
  1586 			if (startOfNextEscapeSequence==KErrNotFound)
       
  1587 				{
       
  1588 				homogeneousRun.Set(remainderOfForeignInternal);
       
  1589 				remainderOfForeignInternal.Set(NULL, 0);
       
  1590 				}
       
  1591 			else
       
  1592 				{
       
  1593 				__ASSERT_DEBUG(startOfNextEscapeSequence>0, User::Panic(KPanicReason,EPanicBadStartOfNextEscapeSequence));
       
  1594 				homogeneousRun.Set(remainderOfForeignInternal.Left(startOfNextEscapeSequence));
       
  1595 				remainderOfForeignInternal.Set(remainderOfForeignInternal.Mid(startOfNextEscapeSequence));
       
  1596 				}
       
  1597 			isSkipMatchSequence = ETrue;
       
  1598 			}
       
  1599 		FOREVER
       
  1600 			{
       
  1601 			if(!isSkipMatchSequence)
       
  1602 				{
       
  1603 				if (!NextHomogeneousForeignRun(convData, numberOfForeignBytesConsumed, homogeneousRun, 
       
  1604 											remainderOfForeignInternal, modals.Array(), aOutputConversionFlags))
       
  1605 					{
       
  1606 					break;
       
  1607 					}
       
  1608 				}
       
  1609 			HandleHomogeneousRun( convData, aDefaultEndiannessOfForeignCharacters, aUnicode, homogeneousRun, aNumberOfUnconvertibleCharacters, 
       
  1610 								aIndexOfFirstByteOfFirstUnconvertibleCharacter,aOutputConversionFlags,internalInputConversionFlags,
       
  1611 								numberOfForeignBytesConsumed,returnValue);
       
  1612 			if(returnValue<0)
       
  1613 				{
       
  1614 				return returnValue;
       
  1615 				}
       
  1616 			isSkipMatchSequence = EFalse;
       
  1617 			}
       
  1618 		if(returnValue > 0)
       
  1619 			break;
       
  1620 		if ((!flag && (numberOfForeignBytesConsumedThisTime != KMaximumLengthOfIntermediateBuffer)) || (flag && (numberOfForeignBytesConsumedThisTime != (KMaximumLengthOfIntermediateBuffer-1) )))
       
  1621 			break;
       
  1622 		remainderOfForeign.Set(aForeign.Mid(numberOfForeignBytesConsumed));				
       
  1623 	}
       
  1624 	//If the number of iscii bytes consumed by the conversion is zero also the output conversion
       
  1625 	//flag is not set to EOutputConversionFlagInputIsTruncated, then return EErrorIllFormedInput.
       
  1626 	if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated))
       
  1627 		{
       
  1628 		return CCnvCharacterSetConverter::EErrorIllFormedInput;
       
  1629 		}
       
  1630 	//Set the conversion data sothat next time when ConvertToUnicode() is called,
       
  1631 	//will use the previous conversion data.
       
  1632 	aState=REINTERPRET_CAST(TInt, convData);
       
  1633 	return aForeign.Length()-numberOfForeignBytesConsumed;
       
  1634     }
       
  1635 
       
  1636 // -----------------------------------------------------------------------------
       
  1637 // IsInThisCharacterSetL()
       
  1638 //The method tells how probable it is that a sample piece of text is encoded in this character set.
       
  1639 //On return aConfidenceLevel, indicates how confident the function is about its return value. For
       
  1640 //iscii it is the default implementation and it does not implement the autodetect functionality.
       
  1641 //Loaded and called by the character conversion framework.
       
  1642 //
       
  1643 // Returns: EFalse: To tell CCnvCharacterSetConverter::AutoDetectCharacterSetL()  that the plug-in DLL
       
  1644 //                          is not implementing a function of this signature and is therefore empty.
       
  1645 //
       
  1646 // -----------------------------------------------------------------------------
       
  1647 //
       
  1648 
       
  1649 
       
  1650 //Default implementation for IsInThisCharacterSetL()
       
  1651 
       
  1652 EXPORT_C TBool IsInThisCharacterSetL(
       
  1653          TBool& aSetToTrue, 
       
  1654          TInt& aConfidenceLevel, 
       
  1655          const TDesC8& )
       
  1656 	{
       
  1657     	aSetToTrue = EFalse;
       
  1658 	aConfidenceLevel = 0;
       
  1659 	return EFalse;
       
  1660 	}
       
  1661 
       
  1662 EXPORT_C void Reserved_2()
       
  1663 	{
       
  1664 	}
       
  1665 
       
  1666 EXPORT_C void Reserved_3()
       
  1667 	{
       
  1668 	}
       
  1669 
       
  1670 EXPORT_C void Reserved_4()
       
  1671 	{
       
  1672 	}
       
  1673 
       
  1674 EXPORT_C void Reserved_5()
       
  1675 	{
       
  1676 	}
       
  1677 
       
  1678 EXPORT_C void Reserved_6()
       
  1679 	{
       
  1680 	}
       
  1681 
       
  1682 EXPORT_C void Reserved_7()
       
  1683 	{
       
  1684 	}
       
  1685 
       
  1686 EXPORT_C void Reserved_8()
       
  1687 	{
       
  1688 	}
       
  1689 
       
  1690 #endif //EKA2