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