messagingfw/msgsrvnstore/server/src/CMsvPlainBodyText.cpp
changeset 22 bde600d88860
parent 0 8e480a14352b
child 36 e7635922c074
child 39 e5b3a2155e1a
equal deleted inserted replaced
21:08008ce8a6df 22:bde600d88860
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // CMsvPlainBodyText.cpp
       
    15 //
       
    16 
       
    17 #include <cmsvplainbodytext.h>
       
    18 #include "cmsvbodytext.h"
       
    19 #include <mmsvstoremanager.h>
       
    20 #include "MSVPANIC.H"
       
    21 #include <txtrich.h>
       
    22 #include <utf.h>
       
    23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
       
    24 #include "msvconsts.h"
       
    25 #endif
       
    26 
       
    27 /**
       
    28 The number of characters that will be converted to Unicode at any one time.
       
    29 */
       
    30 const TInt KMaxDecodeUnicodeLength = 20;
       
    31 
       
    32 /**
       
    33 The NewL factory function for Write operation.
       
    34 @param aMsvStoreManager	 The MMsvStoreManager reference to call Store related RFile APIs
       
    35 @param aStore 			 The CMsvStore object.
       
    36 @param aIs8Bit			 TBool indicating whether to store bdy text as 8/16 bit.
       
    37 @param aCharsetId		 The charset of the body part.
       
    38 @param aDefaultCharsetId The default charset of the system.
       
    39 @param aMessageId		 The Id of the message that is to be stored.
       
    40 @param aFs				 The RFs for handling RFile related operations.
       
    41 @return CMsvPlainBodyText.
       
    42 */
       
    43 CMsvPlainBodyText* CMsvPlainBodyText::NewL(MMsvStoreManager& aMsvStoreManager, CMsvStore& aStore, TBool aIs8Bit, TUint aCharsetId, TUint aDefaultCharsetId, TMsvId aMessageId, RFs& aFs)
       
    44 	{
       
    45 	CMsvPlainBodyText* self = new(ELeave)CMsvPlainBodyText(aMsvStoreManager, aStore, aIs8Bit, aCharsetId, aDefaultCharsetId, aMessageId, aFs);
       
    46 	CleanupStack::PushL(self);
       
    47 	self->ConstructWriteL();
       
    48 	CleanupStack::Pop(self);
       
    49 	return self;
       
    50 	}
       
    51 
       
    52 /**
       
    53 Overloaded NewL for Read operation.
       
    54 @param aMsvStoreManager	 The MMsvStoreManager reference to call Store related RFile APIs
       
    55 @param aStore			 The CMsvStore object.
       
    56 @param aMessageId		 The Id of the message that is to be stored.
       
    57 @param aFs				 The RFs for handling RFile related operations.
       
    58 @param aChunkLength		 The length of the chunk that will be stored/restored in single operaion
       
    59 @return CMsvPlainBodyText.
       
    60 */
       
    61 CMsvPlainBodyText* CMsvPlainBodyText::NewL(MMsvStoreManager& aMsvStoreManager, CMsvStore& aStore, TMsvId aMessageId, RFs& aFs, TInt aChunkLength)
       
    62 	{
       
    63 	CMsvPlainBodyText* self = new(ELeave)CMsvPlainBodyText(aMsvStoreManager, aStore, aMessageId, aFs, aChunkLength);
       
    64 	CleanupStack::PushL(self);
       
    65 	self->ConstructReadL();
       
    66 	CleanupStack::Pop(self);
       
    67 	return self;
       
    68 	}
       
    69 
       
    70 /**
       
    71 Default Constructor for write operation.
       
    72 */
       
    73 CMsvPlainBodyText::CMsvPlainBodyText(MMsvStoreManager& aMsvStoreManager, CMsvStore& aStore, TBool aIs8Bit, TUint aCharsetId, TUint aDefaultCharsetId, TMsvId aMessageId,RFs& aFs)
       
    74 : CMsgActive(EPriorityNormal), iMsvStoreManager(aMsvStoreManager), iStore(aStore), iIs8Bit(aIs8Bit), iCharsetId(aCharsetId), iDefaultCharsetId(aDefaultCharsetId), 
       
    75   iMessageId(aMessageId), iFSession(aFs), iMsvFileStatus(EMsvFileWriting)
       
    76   	{
       
    77   	iAvailable = CCnvCharacterSetConverter::ENotAvailable;
       
    78     CActiveScheduler::Add(this);
       
    79 	}
       
    80 
       
    81 /**
       
    82 Default Constructor called for Read operation..
       
    83 */
       
    84 CMsvPlainBodyText::CMsvPlainBodyText(MMsvStoreManager& aMsvStoreManager, CMsvStore& aStore, TMsvId aMessageId, RFs& aFs, TInt aChunkLength)
       
    85 : CMsgActive(EPriorityNormal), iMsvStoreManager(aMsvStoreManager), iStore(aStore), iMessageId(aMessageId), iFSession(aFs), iPos(0), iChunkMaxLength(aChunkLength), 
       
    86    iStartPosOfNextChunk(0),  iMsvFileStatus(EMsvFileReading)
       
    87 	{
       
    88 	iAvailable = CCnvCharacterSetConverter::ENotAvailable;
       
    89 	CActiveScheduler::Add(this);
       
    90 	}
       
    91 
       
    92 /**
       
    93 ConstructWriteL for creating and writing to the plain bodytext file.
       
    94 */
       
    95 void CMsvPlainBodyText::ConstructWriteL()
       
    96 	{
       
    97 	RMsvWriteStream out;
       
    98 
       
    99 	if(iIs8Bit)
       
   100 		{
       
   101 		out.AssignLC(iStore, KMsvPlainBodyText8);
       
   102 		out.WriteUint32L(iCharsetId);
       
   103 		out.WriteUint32L(iDefaultCharsetId);
       
   104 		}
       
   105 	else
       
   106 		{
       
   107 		out.AssignLC(iStore, KMsvPlainBodyText16);
       
   108 		}
       
   109 	// 	iIsCommitted will be EFalse at this point.
       
   110 	out.WriteUint32L(iIsCommitted);
       
   111 
       
   112     TBuf<KFileNameFixedWidth> fileName;
       
   113 	fileName.NumFixedWidth(iMessageId, EHex, KFileNameFixedWidth);
       
   114 	
       
   115 	out << (TDes&)fileName;
       
   116 	out.CommitL();
       
   117 	out.Close();
       
   118 	iStore.CommitL();
       
   119 
       
   120 	iMsvStoreManager.CreatePlainTextFileL(iFile, iMessageId);
       
   121 	
       
   122 	iRemainingConvertedData.Create(KMaxDecodeUnicodeLength);
       
   123 	CleanupStack::PopAndDestroy(&out);
       
   124 	}
       
   125 
       
   126 /**
       
   127 ConstructL for Read operation.
       
   128 */
       
   129 void CMsvPlainBodyText::ConstructReadL()
       
   130 	{
       
   131 	// Check whether the data is stored in old-style non-chunk storage mechanism.
       
   132 	if(iStore.IsPresentL(KMsvEntryRichTextBody) || iStore.IsPresentL(KMsv8BitEncodedBodyData))
       
   133 		{
       
   134 		iParaLayer = CParaFormatLayer::NewL();
       
   135 		iCharLayer = CCharFormatLayer::NewL();
       
   136 		iRichText = CRichText::NewL(iParaLayer, iCharLayer);
       
   137 		iStore.RestoreBodyTextL(*iRichText);
       
   138 		}
       
   139 	else // Data is stored using the new chunk storage mechanism.
       
   140 		{
       
   141 		RMsvReadStream in;
       
   142 		if(iStore.IsPresentL(KMsvPlainBodyText8))
       
   143 			{
       
   144 			in.OpenLC(iStore, KMsvPlainBodyText8);
       
   145 			iCharsetId = in.ReadUint32L();
       
   146 			iDefaultCharsetId = in.ReadUint32L();
       
   147 			iIs8Bit = ETrue;
       
   148 			}
       
   149 		else if(iStore.IsPresentL(KMsvPlainBodyText16))
       
   150 			{
       
   151 			in.OpenLC(iStore, KMsvPlainBodyText16);
       
   152 			}
       
   153 		else
       
   154 			{
       
   155 			// The stream is not found.
       
   156 			User::Leave(KErrNotFound);
       
   157 			}
       
   158 		iIsCommitted = in.ReadUint32L();
       
   159 		HBufC* filename = HBufC::NewLC(in,KMaxFileName);
       
   160 		iFilePath = HBufC::NewL(KMaxFileName);
       
   161 		
       
   162 		TPtr16 fileNamePtr = iFilePath->Des();
       
   163 		iMsvStoreManager.BodyTextFilePathL(iMessageId, fileNamePtr);
       
   164 		fileNamePtr.Append(*filename);
       
   165 		iMsvStoreManager.OpenBodyTextFileForReadL(iFile, iMessageId, *iFilePath);
       
   166 		
       
   167 		iRemainingConvertedData.Create(KMaxDecodeUnicodeLength);
       
   168 		CleanupStack::PopAndDestroy(2,&in);// filename, in
       
   169 		}
       
   170 	}
       
   171 
       
   172 /**
       
   173 Destructor
       
   174 */
       
   175 EXPORT_C CMsvPlainBodyText::~CMsvPlainBodyText()
       
   176 	{
       
   177 	delete iConverter;
       
   178 	delete iParaLayer;
       
   179 	delete iCharLayer;
       
   180 	delete iRichText;
       
   181 	delete iFilePath;
       
   182 	iTempChunk16.Close();
       
   183 	iRemainingConvertedData.Close();
       
   184 
       
   185 	iStartPosOfEachChunkInFile.Close();
       
   186 	iRfileReadBuf8.Close();
       
   187 	
       
   188 	// Cannot leave in destructor, so ignore any error.
       
   189 	// iFile will be closed by a call to RevertL method.
       
   190 	TRAP_IGNORE(RevertL());
       
   191 	}
       
   192 
       
   193 /**
       
   194 Store the plain body text part in chunks.
       
   195 @param aChunk. 				The 8 bit chunk that is to be stored.
       
   196 @param aStatus. 			The TRequestStatus parameter for this request.
       
   197 @leave KErrAccessDenied.	If CMsvStore was opened in Read mode or
       
   198 							If CommitL is already called.
       
   199 @leave Other 				Standard system-wide error codes.
       
   200 @return void.
       
   201 */
       
   202 EXPORT_C void CMsvPlainBodyText::StoreChunkL(const TDesC8& aChunk, TRequestStatus& aStatus)
       
   203 	{
       
   204 	iTempChunk16.Close();
       
   205 	if(iIsCommitted || iMsvFileStatus == EMsvFileReading)
       
   206 		{
       
   207 		// Leave if CommitL is already called or CMsvStore is opened in Read mode.
       
   208 		User::Leave(KErrAccessDenied);
       
   209 		}
       
   210 
       
   211 	if(iIs8Bit)
       
   212 		{
       
   213 		iFile.Write(aChunk, aStatus);
       
   214 		}
       
   215 	// convert to 16..........
       
   216 	else
       
   217 		{
       
   218 		ConvertChunkToUnicodeForStoreL(aChunk);
       
   219 		iFile.Write(iRfileWritePtr8, aStatus);
       
   220 		}
       
   221 	}
       
   222 
       
   223 /**
       
   224 Store the plain body text part in chunks,synchronous version.
       
   225 @param aChunk. 				The 8 bit chunk that is to be stored.
       
   226 @leave KErrAccessDenied.	If CMsvStore was opened in Read mode or
       
   227 							If CommitL is already called.
       
   228 @leave Other 				Standard system-wide error codes.
       
   229 @return void.
       
   230 */
       
   231 EXPORT_C void CMsvPlainBodyText::StoreChunkL(const TDesC8& aChunk)
       
   232 	{
       
   233 	iTempChunk16.Close();
       
   234 	if(iIsCommitted || iMsvFileStatus == EMsvFileReading)
       
   235 		{
       
   236 		// Leave if CommitL is already called or CMsvStore is opened in Read mode.
       
   237 		User::Leave(KErrAccessDenied);
       
   238 		}
       
   239 	if(iIs8Bit)
       
   240 		{
       
   241 		User::LeaveIfError(iFile.Write(aChunk));
       
   242 		}
       
   243 	else
       
   244 		{
       
   245 		ConvertChunkToUnicodeForStoreL(aChunk);
       
   246 		User::LeaveIfError(iFile.Write(iRfileWritePtr8));
       
   247 		}
       
   248 	}
       
   249 
       
   250 /**
       
   251 Converts the 8 bit chunk to Unicode.
       
   252 @param aChunk The 8bit chunk to be converted.
       
   253 @return void.
       
   254 */
       
   255 void CMsvPlainBodyText::ConvertChunkToUnicodeForStoreL(const TDesC8& aChunk)
       
   256 	{
       
   257 	TInt chunkLength = aChunk.Length();
       
   258 	TPtrC8 chunkPtr8(aChunk);
       
   259 
       
   260 	iTempChunk16.Create(chunkLength);
       
   261 
       
   262 	PrepareToConvertL();
       
   263 	TInt charsetState = CCnvCharacterSetConverter::KStateDefault;
       
   264 
       
   265 	if (iAvailable == CCnvCharacterSetConverter::ENotAvailable)
       
   266 		{
       
   267 		// Copy data if character convertor not available
       
   268 		iTempChunk16.Copy(chunkPtr8);
       
   269 		}
       
   270 	else
       
   271 		{
       
   272 		TInt rem = iConverter->ConvertToUnicode(iTempChunk16, chunkPtr8, charsetState);
       
   273 		if (rem < 0)
       
   274 			{
       
   275 			// Copy the data without conversion,if there was error while converting.
       
   276 			iTempChunk16.Copy(aChunk);
       
   277 			}
       
   278 		else if(rem > 0)
       
   279 			{
       
   280 			// Some of the characters were not converted because the output buffer
       
   281 			// was not long enough, so reallocate the output buffer.
       
   282 			do
       
   283 				{
       
   284 				TBuf<KMaxDecodeUnicodeLength> buf;
       
   285 				chunkPtr8.Set(chunkPtr8.Right(rem));
       
   286 				rem = iConverter->ConvertToUnicode(buf, chunkPtr8, charsetState);
       
   287 				if(iTempChunk16.Length() + buf.Length() > iTempChunk16.MaxLength())
       
   288 					{
       
   289 					iTempChunk16.ReAllocL(iTempChunk16.Length() + buf.Length());
       
   290 					}
       
   291 				iTempChunk16.Append(buf);
       
   292 				}while(rem > 0);
       
   293 			}
       
   294 		}
       
   295 		TPtrC8 convertedChunk8((TUint8*)(iTempChunk16.Ptr()), iTempChunk16.Length()*2);
       
   296 		iRfileWritePtr8.Set(convertedChunk8);
       
   297 	}
       
   298 
       
   299 /**
       
   300 Store the body part in chunks(16 bit version).
       
   301 @param aChunk 			 The 16 bit chunk that is to be stored.
       
   302 @param aStatus	 		 The TRequestStatus parameter for this request.
       
   303 @leave KErrNotSupported  If the 8-bit storage was enabled.
       
   304 @leave KErrAccessDenied  If CMsvStore was opened in Read mode or
       
   305 						 IfCommitL is already called.
       
   306 @leave Other 			 Standard system-wide error codes.
       
   307 @return void
       
   308 */
       
   309 EXPORT_C void CMsvPlainBodyText::StoreChunkL(const TDesC16& aChunk, TRequestStatus& aStatus)
       
   310 	{
       
   311 	if(iIs8Bit)	
       
   312 		{
       
   313 		User::Leave(KErrNotSupported);
       
   314 		}
       
   315 	if(iIsCommitted || iMsvFileStatus == EMsvFileReading)
       
   316 		{
       
   317 		// Leave if CommitL is already called or CMsvStore is opened in Read mode.
       
   318 		User::Leave(KErrAccessDenied);
       
   319 		}	
       
   320 
       
   321 	TPtrC8 inFileBuf8((TUint8*)(aChunk.Ptr()), aChunk.Length()*2);
       
   322 	iFile.Write(inFileBuf8, aStatus);
       
   323 	}
       
   324 
       
   325 /**
       
   326 Store the body part in chunks(16 bit synchronous version).
       
   327 @param aChunk 			 The 16 bit chunk that is to be stored.
       
   328 @leave KErrNotSupported  If the 8-bit storage was enabled.						 
       
   329 @leave KErrAccessDenied  If CMsvStore was opened in Read mode or
       
   330 						 If CommitL is already called.
       
   331 @leave Other 			 Standard system-wide error codes.
       
   332 @return void
       
   333 */
       
   334 EXPORT_C void CMsvPlainBodyText::StoreChunkL(const TDesC16& aChunk)
       
   335 	{
       
   336 	if(iIs8Bit)	
       
   337 		{
       
   338 		User::Leave(KErrNotSupported);
       
   339 		}
       
   340 	if(iIsCommitted || iMsvFileStatus == EMsvFileReading)
       
   341 		{
       
   342 		// Leave if CommitL is already called or CMsvStore is opened in Read mode.
       
   343 		User::Leave(KErrAccessDenied);
       
   344 		}
       
   345 
       
   346 	TPtrC8 inFileBuf8((TUint8*)(aChunk.Ptr()), aChunk.Length()*2);
       
   347 	User::LeaveIfError(iFile.Write(inFileBuf8));
       
   348 	}
       
   349 
       
   350 /**
       
   351 Returns the size of body text in bytes.
       
   352 @param None.
       
   353 @return TInt  The size of the plain body text stored in bytes.
       
   354 */
       
   355 EXPORT_C TInt CMsvPlainBodyText::Size()
       
   356 	{
       
   357 	TInt size=0;
       
   358 	if(iRichText)
       
   359 		{
       
   360 		size = iRichText->DocumentLength() * 2;// Since Unicode multiply by 2.
       
   361 		}
       
   362 	else
       
   363 		{
       
   364 		iFile.Size(size);
       
   365 		}
       
   366 	return size;
       
   367 	}
       
   368 
       
   369 /**
       
   370 Converts and stores the CRichText contents to a plain text.
       
   371 @param aRichText 		 The CRichText object that will be stored as plain body text.
       
   372 @leave KErrNotSupported  If CMsvStore was opened in Read mode or
       
   373 						 If CommitL is already called.
       
   374 @leave Other 			 Standard system-wide error codes.
       
   375 @return void.
       
   376 */
       
   377 EXPORT_C void CMsvPlainBodyText::StoreRichTextAsPlainTextL(CRichText& aRichText)
       
   378 	{
       
   379 	if(iIs8Bit)	
       
   380 		{
       
   381 		User::Leave(KErrNotSupported);
       
   382 		}
       
   383 	if(iIsCommitted || iMsvFileStatus == EMsvFileReading)
       
   384 		{
       
   385 		// Leave if CommitL is already called or CMsvStore is opened in Read mode.
       
   386 		User::Leave(KErrAccessDenied);
       
   387 		}
       
   388   	// create a buffer of 512 bytes to extract data from a rich text instead of extracting
       
   389   	// the entire richtext so that 2 copies of the mail is not created in RAM.
       
   390 	TBuf<KMsvDecodeChunkLength> richBuf;
       
   391 	TInt currentPos = 0;
       
   392 	TInt richTextLen = aRichText.DocumentLength();
       
   393 	TInt lengthToExtract = richTextLen;
       
   394 	while(richTextLen > 0)
       
   395 	 	{
       
   396 	 	if(lengthToExtract > KMsvDecodeChunkLength)
       
   397 	 		{
       
   398 	 		lengthToExtract = KMsvDecodeChunkLength;
       
   399 	 		}
       
   400 	 	aRichText.Extract(richBuf,currentPos,lengthToExtract);
       
   401 	 	TPtrC8 richTextPtr1((TUint8*)(richBuf.Ptr()), richBuf.Length() * 2);
       
   402 	 	User::LeaveIfError(iFile.Write(richTextPtr1));
       
   403 	  	currentPos += lengthToExtract;
       
   404 	  	richTextLen -=lengthToExtract;
       
   405 	   	if(richTextLen <= lengthToExtract)
       
   406 	 		{
       
   407 	 		lengthToExtract = richTextLen;
       
   408 	 		}
       
   409 	 	 }
       
   410 	}
       
   411 
       
   412 /**
       
   413 Retrieve the next chunk of the plain body text.
       
   414 @param aChunk 			 The output parameter contains the requested chunk.
       
   415 @param aStatus.			 The TRequestStatus for this request.
       
   416 @leave KErrAccessDenied  If CMsvStore was opened in Write mode.
       
   417 @leave KErrNotSupported  If 16-bit storage is enabled.
       
   418 @leave KErrUnderflow 	 If aChunk MaxLength is less than iChunkMaxLength.
       
   419 @leave Other 				Standard system-wide error codes.
       
   420 @return void
       
   421 */
       
   422 EXPORT_C void CMsvPlainBodyText::NextChunkL(TDes8& aChunk, TRequestStatus& aStatus)
       
   423 	{
       
   424 	if(!iIs8Bit)
       
   425 		{
       
   426 		// If 16-bit storage is enabled.
       
   427 		User::Leave(KErrNotSupported);
       
   428 		}
       
   429 	if(iMsvFileStatus == EMsvFileWriting)
       
   430 		{
       
   431 		// Leave if CMsvStore is opened in Write mode.
       
   432 		User::Leave(KErrAccessDenied);
       
   433 		}	
       
   434 	if(aChunk.MaxLength() < iChunkMaxLength)
       
   435 		{
       
   436 		User::Leave(KErrUnderflow);
       
   437 		}
       
   438 	
       
   439 	iChunk8 = &aChunk;	
       
   440 	iChunk8->SetLength(0);
       
   441 	
       
   442 	iRetrieving8bit = ETrue;
       
   443 	
       
   444 	//store the current position of the file so that if request cancels and for next 
       
   445 	// call to NextChunkL() will attempt to read the same chunk that was cancelled
       
   446 	iCurrentFilePos = 0;
       
   447 	User::LeaveIfError(iFile.Seek(ESeekCurrent, iCurrentFilePos));
       
   448 	
       
   449 	Queue(aStatus);
       
   450 	iFile.Read(aChunk, iChunkMaxLength, iStatus);
       
   451 	SetActive();
       
   452 	}
       
   453 
       
   454 /**
       
   455 Retrieve the next chunk of the plain body text.
       
   456 @param aChunk 			 The output parameter contains the requested chunk.
       
   457 @leave KErrNotSupported  If CMsvStore was opened in Write mode.
       
   458 @leave KErrNotSupported  If 16-bit storage is enabled.
       
   459 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   460 @leave Other 			 Standard system-wide error codes.
       
   461 @return void
       
   462 */
       
   463 EXPORT_C void CMsvPlainBodyText::NextChunkL(TDes8& aChunk)
       
   464 	{
       
   465 	if(!iIs8Bit)
       
   466 		{
       
   467 		// If 16-bit storage is enabled.
       
   468 		User::Leave(KErrNotSupported);
       
   469 		}
       
   470 	if(iMsvFileStatus == EMsvFileWriting)
       
   471 		{
       
   472 		// Leave if CMsvStore is opened in Write mode.
       
   473 		User::Leave(KErrAccessDenied);
       
   474 		}
       
   475 	if(aChunk.MaxLength() < iChunkMaxLength)
       
   476 		{
       
   477 		User::Leave(KErrUnderflow);
       
   478 		}
       
   479 	aChunk.SetLength(0);
       
   480 	User::LeaveIfError(iFile.Read(aChunk, iChunkMaxLength));
       
   481 
       
   482 	if(aChunk.Length()>0)
       
   483 		{
       
   484 		iReadChunkLength = aChunk.Length();
       
   485 		}
       
   486 	}
       
   487 
       
   488 /**
       
   489 Retrieve  the next chunk of the plain body text. If body is stored as 8bit, the chunk is
       
   490 converted to unicode.Unconverted bytes will be converted while reading the next chunk.
       
   491 @param aChunk 			 The output parameter contains the requested chunk.If no more data is in Store this
       
   492 						 contains NULL descriptor.
       
   493 @param aStatus  		 The TRequestStatus for this request.
       
   494 @leave KErrAccessDenied  If CMsvStore was opened in Write mode.
       
   495 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   496 @leave Other 			 Standard system-wide error codes.
       
   497 @return void
       
   498 */
       
   499 EXPORT_C void CMsvPlainBodyText::NextChunkL(TDes16& aChunk, TRequestStatus& aStatus)
       
   500 	{
       
   501 	if(iMsvFileStatus == EMsvFileWriting)
       
   502 		{
       
   503 		// Leave if CMsvStore is opened in Write mode.
       
   504 		User::Leave(KErrAccessDenied);
       
   505 		}
       
   506 
       
   507 	if(aChunk.MaxLength() < iChunkMaxLength)
       
   508 		{
       
   509 		User::Leave(KErrUnderflow);
       
   510 		}
       
   511 
       
   512 	if(iRichText)
       
   513  		{
       
   514  		ExtractNextChunkFromRichText(aChunk);
       
   515 	 	TRequestStatus *status=&aStatus;
       
   516 		User::RequestComplete(status, KErrNone);
       
   517  		}
       
   518 	else
       
   519 		{
       
   520 		iRfileReadBuf8.Close();
       
   521 		iChunk16 = &aChunk;	
       
   522 		iChunk16->SetLength(0);
       
   523 		
       
   524 		//store the current position of the file so that if request cancels and for next 
       
   525 		// call to NextChunkL() will attempt to read the same chunk that was cancelled
       
   526 		iCurrentFilePos = 0;
       
   527 		User::LeaveIfError(iFile.Seek(ESeekCurrent, iCurrentFilePos));
       
   528 	
       
   529 		Queue(aStatus);
       
   530 		if(iIs8Bit)
       
   531 			{
       
   532 			// if there is any converted data then append to aChunk
       
   533 			if(iRemainingConvertedData.Length() != 0)
       
   534 				{
       
   535 				iChunk16->Append(iRemainingConvertedData);
       
   536 				iRemainingConvertedData.SetLength(0);
       
   537 				}
       
   538 				
       
   539 			iRfileReadBuf8.Create(iChunkMaxLength);
       
   540 			// 8-bit data read will be converted to Unicode in DoRunL.
       
   541 			iFile.Read(iRfileReadBuf8, iChunkMaxLength, iStatus);
       
   542 			SetActive();
       
   543 			}
       
   544 		else
       
   545 			{
       
   546 			iRfileReadBuf8.Create(iChunkMaxLength*2);
       
   547 			iFile.Read(iRfileReadBuf8, iChunkMaxLength*2, iStatus);
       
   548 			SetActive();
       
   549 			}
       
   550 		}
       
   551 	}
       
   552 	
       
   553 /**
       
   554 Retrieve the next chunk of the plain body text. If body is stored as 8bit, convert the chunk to Unicode.
       
   555 Unconverted bytes will be converted while reading the next chunk.
       
   556 @param aChunk			 The output parameter contains the requested chunk.If no more data is in Store this
       
   557 						 contains NULL descriptor.
       
   558 @leave KErrAccessDenied  If CMsvStore was opened in Write mode.
       
   559 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   560 @leave Other 			 Standard system-wide error codes.
       
   561 @return void
       
   562 */
       
   563 EXPORT_C void CMsvPlainBodyText::NextChunkL(TDes16& aChunk)
       
   564 	{
       
   565 	if(iMsvFileStatus == EMsvFileWriting)
       
   566 		{
       
   567 		// Leave if CMsvStore is opened in Write mode.
       
   568 		User::Leave(KErrAccessDenied);
       
   569 		}
       
   570 
       
   571 	if(aChunk.MaxLength() < iChunkMaxLength)
       
   572 		{
       
   573 		User::Leave(KErrUnderflow);
       
   574 		}
       
   575 
       
   576 	if(iRichText)
       
   577  		{
       
   578  		ExtractNextChunkFromRichText(aChunk);
       
   579  		}
       
   580  	else if(iIs8Bit)
       
   581  		{
       
   582  		iRfileReadBuf8.Close();
       
   583  		iChunk16 = &aChunk;	
       
   584 	
       
   585  		iChunk16->SetLength(0);
       
   586  		
       
   587 		TInt numOfBytesInCurrentChunk = 0;
       
   588 		// if there is any converted data then append to aChunk
       
   589 		if(iRemainingConvertedData.Length() != 0)
       
   590 			{
       
   591 			iChunk16->Append(iRemainingConvertedData);
       
   592 			iRemainingConvertedData.SetLength(0);
       
   593 			}
       
   594 
       
   595 	 	PrepareToConvertL();
       
   596 	 	if(iAvailable != CCnvCharacterSetConverter::EAvailable)
       
   597 	 		{
       
   598 	 		User::Leave(KErrNotSupported);
       
   599 	 		}
       
   600 
       
   601  		iIsLastChunk = EFalse;
       
   602  		while(iChunk16->Length() < iChunkMaxLength && !iIsLastChunk)
       
   603 			{
       
   604 			iRfileReadBuf8.Create(iChunkMaxLength);
       
   605 			iFile.Read(iRfileReadBuf8, iChunkMaxLength);
       
   606 			// iRfileReadBuf8 will be closed when ConvertChunkToUnicodeForRestoreL returns.
       
   607  			numOfBytesInCurrentChunk = ConvertChunkToUnicodeForRestoreL();
       
   608 			}
       
   609 
       
   610 		// Push start position of current chunk in to the stack.
       
   611 		iStartPosOfEachChunkInFile.Append(iStartPosOfNextChunk);
       
   612 		iStartPosOfNextChunk += numOfBytesInCurrentChunk;
       
   613 		iReadChunkLength = numOfBytesInCurrentChunk;
       
   614 		}
       
   615 	else // KMsvPlainBodyText16
       
   616 		{
       
   617 		HBufC8* inBuffer = HBufC8::NewLC(iChunkMaxLength * 2);
       
   618 		TPtr8 inPtr16(inBuffer->Des());
       
   619 		iFile.Read(inPtr16, iChunkMaxLength * 2); // Multiply by 2 to get no of bytes.
       
   620 		TPtrC16 ptr16((TUint16*)(inBuffer->Ptr()), inBuffer->Length() / 2);
       
   621 		aChunk.Copy(ptr16);
       
   622 		CleanupStack::PopAndDestroy(inBuffer);
       
   623 		if(aChunk.Length())
       
   624 			{
       
   625 			iReadChunkLength = aChunk.Length();
       
   626 			}
       
   627 		
       
   628 		}
       
   629 	}
       
   630 
       
   631 /**
       
   632 Extracts a chunk of iChunkMaxLength or less, from the CRichText object.
       
   633 */
       
   634 void CMsvPlainBodyText::ExtractNextChunkFromRichText(TDes16& aChunk)
       
   635 	{
       
   636 	TInt docLength = iRichText->DocumentLength();
       
   637 	// If we are at the end of the body text.
       
   638 	if(iPos >= docLength)
       
   639 		{
       
   640 		aChunk.Copy(KNullDesC16);
       
   641 		}
       
   642 	else
       
   643 		{
       
   644 		if(iPos+iChunkMaxLength <= docLength)
       
   645 			{
       
   646 			iRichText->Extract(aChunk, iPos, iChunkMaxLength);
       
   647 			iPos += iChunkMaxLength;
       
   648 			iReadChunkLength = iChunkMaxLength;
       
   649 			}
       
   650 		else // If it is the last chunk.
       
   651 			{
       
   652 			iRichText->Extract(aChunk, iPos, docLength-iPos);
       
   653 			iReadChunkLength = docLength-iPos;
       
   654 			iPos = docLength;
       
   655 			}
       
   656 		}
       
   657 	}
       
   658 
       
   659 /**
       
   660 Retrieve the previous chunk of the plain body text asynchronously.
       
   661 @param aChunk 			 The output parameter containing the requested chunk on completion.
       
   662 @param aStatus  		 The TRequestStatus for this request.
       
   663 @leave KErrNotSupported  If 16-bit storage is enabled.
       
   664 @leave KErrAccessDenied  If CMsvStore was opened in Write mode.
       
   665 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   666 @leave Other 			 Standard system-wide error codes.
       
   667 @return void
       
   668 */
       
   669 EXPORT_C void CMsvPlainBodyText::PreviousChunkL(TDes8& aChunk, TRequestStatus& aStatus)
       
   670 	{
       
   671 	TInt currentPos = 0;
       
   672 	User::LeaveIfError(iFile.Seek(ESeekCurrent, currentPos));
       
   673 	
       
   674 	// point to the position from where previous chunk was read.
       
   675 	currentPos -= iReadChunkLength;
       
   676 	// point to the position from where the new chunk is to be read.
       
   677 	currentPos -= iChunkMaxLength;
       
   678 
       
   679 	if(currentPos >= 0)
       
   680 		{
       
   681 		iFile.Seek(ESeekStart, currentPos);
       
   682 		NextChunkL(aChunk, aStatus);
       
   683 		}
       
   684 	else
       
   685 		{
       
   686 		aChunk.Copy(KNullDesC8);
       
   687 		TRequestStatus *status = &aStatus;
       
   688 		User::RequestComplete(status, KErrNone);
       
   689 		}
       
   690 	}
       
   691 
       
   692 /**
       
   693 Retrieve the previous chunk of the plain body text.
       
   694 @param aChunk 			 The output parameter containing the requested chunk.
       
   695 @leave KErrNotSupported  If 16-bit storage is enabled.
       
   696 @leave KErrAccessDenied  If CMsvStore was opened in Write mode. 
       
   697 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   698 @leave Other 			 Standard system-wide error codes.
       
   699 @return void
       
   700 */
       
   701 EXPORT_C void CMsvPlainBodyText::PreviousChunkL(TDes8& aChunk)
       
   702 	{
       
   703 	TInt currentPos = 0;
       
   704 	iFile.Seek(ESeekCurrent, currentPos);
       
   705 
       
   706 	// point to the position from where previous chunk was read.
       
   707 	currentPos -= iReadChunkLength;
       
   708 	 // point to the position from where the new chunk is to be read.
       
   709 	currentPos -= iChunkMaxLength;
       
   710 
       
   711 	if(currentPos >= 0)
       
   712 		{
       
   713 		iFile.Seek(ESeekStart, currentPos );
       
   714 		NextChunkL(aChunk);
       
   715 		}
       
   716 	else
       
   717 		{
       
   718 		aChunk.Copy(KNullDesC8);
       
   719 		}
       
   720 	}
       
   721 
       
   722 /**
       
   723 Retrieve the previous chunk of the plain body text asynchronously.DoRunl converts the chunk to unicode.
       
   724 @param aChunk 			 The output parameter containing the requested chunk on completion.
       
   725 @param aStatus  		 The TRequestStatus for this request.
       
   726 @leave KErrNotSupported  If CMsvStore was opened in Write mode.
       
   727 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   728 @leave Other 			 Standard system-wide error codes.
       
   729 @return void
       
   730 */
       
   731 EXPORT_C void CMsvPlainBodyText::PreviousChunkL(TDes16& aChunk, TRequestStatus& aStatus)
       
   732 	{
       
   733 	iPrevChunk = ETrue;
       
   734 	if(iRichText)
       
   735  		{
       
   736  		ExtractPreviousChunkFromRichText(aChunk);
       
   737  		TRequestStatus *status = &aStatus;
       
   738 		User::RequestComplete(status, KErrNone);
       
   739  		}
       
   740 	else 
       
   741 		{
       
   742 		if(iIs8Bit && iStartPosOfEachChunkInFile.Count() >= 2)
       
   743 			{
       
   744 			delete iRemainingUnConvertedData;
       
   745 			iRemainingUnConvertedData = NULL;
       
   746 			TInt count = iStartPosOfEachChunkInFile.Count() - 1;
       
   747 			TInt numOfBytes = iStartPosOfEachChunkInFile[count] - iStartPosOfEachChunkInFile[count - 1];
       
   748 			iFile.Seek(ESeekStart, iStartPosOfEachChunkInFile[count - 1] );
       
   749 			iReadChunkLength = numOfBytes;
       
   750 			NextChunkL(aChunk,aStatus);	
       
   751 			}
       
   752 		else
       
   753 			{
       
   754 			TInt startPos = 0;
       
   755 			TInt currentPos = 0;
       
   756 			User::LeaveIfError(iFile.Seek(ESeekCurrent, currentPos));
       
   757 			TInt prevChunkPos = 0;
       
   758 			if(currentPos > 0)
       
   759 				{
       
   760 				startPos = currentPos - iReadChunkLength * 2;
       
   761 				if(startPos > 0)
       
   762 					{
       
   763 					prevChunkPos = startPos - iChunkMaxLength * 2;
       
   764 					if(prevChunkPos >= 0)
       
   765 						{
       
   766 						iFile.Seek(ESeekStart, prevChunkPos);
       
   767 						NextChunkL(aChunk,aStatus);	
       
   768 						}
       
   769 					else
       
   770 						{
       
   771 						iChunk16->Copy(KNullDesC16);
       
   772 						TRequestStatus *status = &aStatus;
       
   773 						User::RequestComplete(status, KErrNone);
       
   774 						}
       
   775 					}
       
   776 				else
       
   777 					{
       
   778 					aChunk.Copy(KNullDesC16);
       
   779 					TRequestStatus *status = &aStatus;
       
   780 					User::RequestComplete(status, KErrNone);
       
   781 					}
       
   782 				}
       
   783 			else
       
   784 				{
       
   785 				aChunk.Copy(KNullDesC16);
       
   786 				TRequestStatus *status = &aStatus;
       
   787 				User::RequestComplete(status, KErrNone);
       
   788 				}
       
   789 			}
       
   790 		}	
       
   791 	}
       
   792 
       
   793 /**
       
   794 Retrieve the Previouschunk of the plain body text. If body is stored as 8bit, convert the chunk to Unicode.
       
   795 @param aChunk 			 The output parameter contains the requested chunk.
       
   796 @leave KErrNotSupported  If CMsvStore was opened in Write mode.
       
   797 @leave KErrUnderflow	 If aChunk MaxLength is less than iChunkMaxLength.
       
   798 @leave Other 			 Standard system-wide error codes.
       
   799 @return void
       
   800 */
       
   801 EXPORT_C void CMsvPlainBodyText::PreviousChunkL(TDes16& aChunk)
       
   802 	{
       
   803 	if(iRichText)
       
   804  		{
       
   805  		ExtractPreviousChunkFromRichText(aChunk);
       
   806  		}
       
   807 	else 
       
   808 		{
       
   809 		if(iIs8Bit && iStartPosOfEachChunkInFile.Count() >= 2)
       
   810 			{
       
   811 			delete iRemainingUnConvertedData;
       
   812 			iRemainingUnConvertedData = NULL;
       
   813 
       
   814 			TInt count = iStartPosOfEachChunkInFile.Count() - 1;
       
   815 
       
   816 			iFile.Seek(ESeekStart, iStartPosOfEachChunkInFile[count - 1] );
       
   817 			TInt numOfBytes = iStartPosOfEachChunkInFile[count] - iStartPosOfEachChunkInFile[count - 1];
       
   818 			iReadChunkLength = numOfBytes;
       
   819 			// Pop one position from iStartPosOfEachChunkInFile
       
   820 			iStartPosOfNextChunk = iStartPosOfEachChunkInFile[count];
       
   821 			iStartPosOfEachChunkInFile.Remove(count);
       
   822 			NextChunkL(aChunk);
       
   823 			}
       
   824 		else
       
   825 			{
       
   826 			TInt startPos = 0;
       
   827 			TInt currentPos = 0;
       
   828 			iFile.Seek(ESeekCurrent, currentPos);
       
   829 			TInt prevChunkPos = 0;
       
   830 
       
   831 			if(currentPos > 0)
       
   832 				{
       
   833 				startPos = currentPos - iReadChunkLength * 2;// Multiply by 2 to get no of bytes.
       
   834 				if(startPos > 0)
       
   835 					{
       
   836 					prevChunkPos = startPos - iChunkMaxLength * 2;// Multiply by 2 to get no of bytes.
       
   837 					if(prevChunkPos >= 0)
       
   838 						{
       
   839 						iFile.Seek(ESeekStart, prevChunkPos );
       
   840 						NextChunkL(aChunk);
       
   841 						}
       
   842 					else
       
   843 						{
       
   844 						aChunk.Copy(KNullDesC16);
       
   845 						}
       
   846 					}
       
   847 				}
       
   848 			}
       
   849 		}	
       
   850 	}
       
   851 
       
   852 /**
       
   853 Extracts a chunk of iChunkMaxLength or less, from the CRichText object.
       
   854 */
       
   855 void CMsvPlainBodyText::ExtractPreviousChunkFromRichText(TDes16& aChunk)
       
   856 	{
       
   857 	iPos -= iReadChunkLength;
       
   858 	if(iPos > 0)
       
   859 		{
       
   860 		iPos -= iChunkMaxLength;
       
   861 		if(iPos >= 0)
       
   862 			{
       
   863 			iRichText->Extract(aChunk, iPos, iChunkMaxLength);
       
   864 			iPos += iChunkMaxLength;
       
   865 			iReadChunkLength = iChunkMaxLength;
       
   866 			}
       
   867 		}
       
   868 	}
       
   869 
       
   870 /**
       
   871 Asynchronously retrives the body text chunks.If body is stored as 8bit, converts the chunk to Unicode.
       
   872 @param None.
       
   873 @return
       
   874 */
       
   875 void CMsvPlainBodyText::DoRunL()
       
   876 	{
       
   877 	User::LeaveIfError(iStatus.Int());
       
   878 	if(iRetrieving8bit)
       
   879 		{
       
   880 		if(iChunk8->Length())
       
   881 			{
       
   882 			iReadChunkLength = iChunk8->Length();
       
   883 			}
       
   884 		Complete(iStatus.Int());
       
   885 		iRetrieving8bit = EFalse;
       
   886 		}
       
   887 	else
       
   888 		{
       
   889 		iIsLastChunk = EFalse;
       
   890 		if (iIs8Bit)
       
   891 	 		{
       
   892 	 		PrepareToConvertL();
       
   893 		 	if(iAvailable != CCnvCharacterSetConverter::EAvailable)
       
   894 		 		{
       
   895 		 		User::Leave(KErrNotSupported);
       
   896 		 		}
       
   897 	 		TInt numOfBytesInCurrentChunk = ConvertChunkToUnicodeForRestoreL();
       
   898 	 		if(iChunk16->Length() < iChunkMaxLength && !iIsLastChunk)
       
   899 				{
       
   900 				// iRfileReadBuf8 will be closed when ConvertChunkToUnicodeForRestoreL returns.
       
   901 				iRfileReadBuf8.Create(iChunkMaxLength);
       
   902 				//store the current position of the file so that if request cancels and for next 
       
   903 				// call to NextChunkL() will attempt to read the same chunk that was cancelled
       
   904 				iCurrentFilePos = 0;
       
   905 				User::LeaveIfError(iFile.Seek(ESeekCurrent, iCurrentFilePos));
       
   906 				iFile.Read(iRfileReadBuf8, iChunkMaxLength, iStatus);
       
   907 				SetActive();
       
   908 				}
       
   909 			else
       
   910 				{
       
   911 				if(iPrevChunk)
       
   912 					{
       
   913 					//Pop one position from iStartPosOfEachChunkInFile
       
   914 					TInt count = iStartPosOfEachChunkInFile.Count() - 1;
       
   915 					iStartPosOfNextChunk = iStartPosOfEachChunkInFile[count];
       
   916 					iStartPosOfEachChunkInFile.Remove(count);
       
   917 					iPrevChunk = EFalse;
       
   918 					}
       
   919 				else
       
   920 					{
       
   921 					// Push Start position of current chunk in to the stack.
       
   922 					iStartPosOfEachChunkInFile.Append(iStartPosOfNextChunk);
       
   923 					iStartPosOfNextChunk += numOfBytesInCurrentChunk;
       
   924 					}
       
   925 				iReadChunkLength = numOfBytesInCurrentChunk;
       
   926 				Complete(iStatus.Int());
       
   927 				}
       
   928 			}
       
   929 		else
       
   930 			{
       
   931 			TPtrC16 ptr16((TUint16*)(iRfileReadBuf8.Ptr()), iRfileReadBuf8.Length()/2);
       
   932 			iChunk16->Copy(ptr16);
       
   933 			iRfileReadBuf8.Close();
       
   934 			Complete(iStatus.Int());
       
   935 			iReadChunkLength = ptr16.Length();
       
   936 			}
       
   937 		}
       
   938 	}
       
   939 
       
   940 /**
       
   941 Converts the 8 bit chunk to unicode.When this is called iRfileReadBuf8 will have the 8-bit  
       
   942 data that needs to be converted to unicode.8 bit data that is not converted is copied to 
       
   943 iRemainingUnConvertedData, which is used in conversion when this is called again.
       
   944 @param  None.
       
   945 @return TInt Number of bytes in Current Chunk.
       
   946 */
       
   947 TInt CMsvPlainBodyText::ConvertChunkToUnicodeForRestoreL()
       
   948 	{
       
   949 	TBufC16<KMaxDecodeUnicodeLength> outBuf;
       
   950 	TPtr16 outPtr = outBuf.Des();
       
   951  	TInt charsetState = CCnvCharacterSetConverter::KStateDefault;
       
   952 
       
   953  	TInt numOfBytesInCurrentChunk = 0;
       
   954 	TInt bytesUnconverted = 0;
       
   955 	// Check if we are processing the last chunk.
       
   956 	if(iRfileReadBuf8.Length() == 0)
       
   957 		{
       
   958 		iIsLastChunk = ETrue;
       
   959 		}
       
   960 	// Check if there are data that are yet to be converted.
       
   961 	if(iRemainingUnConvertedData)
       
   962 		{
       
   963 		if(iIsLastChunk)
       
   964 			{
       
   965 			TPtrC8 remPtr(*iRemainingUnConvertedData);
       
   966 			// If it is the lastchunk then convert the data, need not insert to input buffer.
       
   967 			if(iIsLastChunk)
       
   968 				{
       
   969 				while(remPtr.Length() > 0)
       
   970 					{
       
   971 					bytesUnconverted = iConverter->ConvertToUnicode(outPtr, remPtr, charsetState);
       
   972 					User::LeaveIfError(bytesUnconverted);
       
   973 					iChunk16->Append(outPtr);
       
   974 					remPtr.Set(remPtr.Right(bytesUnconverted));
       
   975 					}
       
   976 				}
       
   977 			}
       
   978 		else // If there are data that are yet to be converted insert it at the front of the input buffer.
       
   979 			{
       
   980 			iRfileReadBuf8.ReAllocL(iRfileReadBuf8.Length() + iRemainingUnConvertedData->Length());
       
   981 			iRfileReadBuf8.Insert(0, *iRemainingUnConvertedData);
       
   982 			}
       
   983 		delete iRemainingUnConvertedData;
       
   984 		iRemainingUnConvertedData = NULL;
       
   985 		}
       
   986 	
       
   987 	TPtrC8 remainingUnconvertedData(iRfileReadBuf8);
       
   988 	// This loop will convert the data to unicode till iChunk16 is filled with the converted data.
       
   989 	while(remainingUnconvertedData.Length() >= KMaxDecodeUnicodeLength || (iIsLastChunk && remainingUnconvertedData.Length() > 0))
       
   990 		{
       
   991 		bytesUnconverted = iConverter->ConvertToUnicode(outPtr, remainingUnconvertedData, charsetState);
       
   992 		User::LeaveIfError(bytesUnconverted);
       
   993 		TInt bytesConverted = remainingUnconvertedData.Length()-bytesUnconverted;
       
   994 
       
   995 		if (iChunk16->Length() + outPtr.Length() <= iChunk16->MaxLength())
       
   996 			{
       
   997 			iChunk16->Append(outPtr);
       
   998 			numOfBytesInCurrentChunk += bytesConverted;
       
   999 			}
       
  1000 		else
       
  1001 			{
       
  1002 			// Copy remaining unconverted data to iRemainingConvertedData,
       
  1003 			// if outBuf.Length() is greater than the space remains in aChunk
       
  1004 			TInt availableSpaceOnChunk = iChunk16->MaxLength() - iChunk16->Length();
       
  1005 			iChunk16->Append(outPtr.Left(availableSpaceOnChunk));
       
  1006 			
       
  1007 			numOfBytesInCurrentChunk += bytesConverted - iRemainingConvertedData.Length();
       
  1008 			iRemainingConvertedData.Append(outPtr.Mid(availableSpaceOnChunk));
       
  1009 			remainingUnconvertedData.Set(remainingUnconvertedData.Right(bytesUnconverted));
       
  1010 			break;
       
  1011 			}
       
  1012 		remainingUnconvertedData.Set(remainingUnconvertedData.Right(bytesUnconverted));
       
  1013 		}
       
  1014 
       
  1015 	// Copy remaining unconverted data to iRemainingUnConvertedData
       
  1016 	if(remainingUnconvertedData.Length())
       
  1017 		{
       
  1018 		__ASSERT_DEBUG(iRemainingUnConvertedData == NULL, PanicServer(EMsvBufferNotEmpty));
       
  1019 		iRemainingUnConvertedData = remainingUnconvertedData.AllocL();
       
  1020 		}
       
  1021 	iRfileReadBuf8.Close();	
       
  1022 	return numOfBytesInCurrentChunk;
       
  1023 	}
       
  1024 
       
  1025 /**
       
  1026 Creates the character converter and specifies the character set to convert to or from.
       
  1027 Leaves if the specified or default character set is not available.
       
  1028 @param   None.
       
  1029 @return  void.
       
  1030 */
       
  1031 void CMsvPlainBodyText::PrepareToConvertL()
       
  1032 	{
       
  1033 	if(!iConverter)
       
  1034 		{
       
  1035 		iConverter = CCnvCharacterSetConverter::NewL();
       
  1036 	 	if (iCharsetId != 0)
       
  1037 		 	{
       
  1038 		 	iAvailable = iConverter->PrepareToConvertToOrFromL(iCharsetId, iFSession);
       
  1039 		 	}
       
  1040 		if (iAvailable == CCnvCharacterSetConverter::ENotAvailable)
       
  1041 			{
       
  1042 			iAvailable = iConverter->PrepareToConvertToOrFromL(iDefaultCharsetId, iFSession);
       
  1043 			}
       
  1044 		}
       
  1045  	}
       
  1046 
       
  1047 /**
       
  1048 Set iCharsetId to aCharset if body text of the message was downloaded as 8 bit.
       
  1049 This can be used to override the charset with which a message was downloaded, when
       
  1050 the body text is opened for reading.
       
  1051 @param aCharset		The new charset with which it needs to be converted.
       
  1052 @return void.
       
  1053 */
       
  1054 EXPORT_C void CMsvPlainBodyText::SetCharacterSetL(const TUint aCharset)
       
  1055 	{
       
  1056 	if(iStore.IsPresentL(KMsvPlainBodyText8))
       
  1057 		{
       
  1058 		iCharsetId = aCharset;
       
  1059 		}
       
  1060 	}
       
  1061 
       
  1062 /**
       
  1063 Returns the charset for the plain text part
       
  1064 @param  None.
       
  1065 @return TUint
       
  1066 */
       
  1067 EXPORT_C TUint CMsvPlainBodyText::CharacterSet()
       
  1068 	{
       
  1069 	return iCharsetId ;
       
  1070 	}
       
  1071 
       
  1072 /**
       
  1073 Returns the default charset for the plain text part
       
  1074 @param  None.
       
  1075 @return TUint
       
  1076 */
       
  1077 EXPORT_C TUint CMsvPlainBodyText::DefaultCharacterSet()
       
  1078 	{
       
  1079 	return iDefaultCharsetId;
       
  1080 	}
       
  1081 
       
  1082 /**
       
  1083 Commit the file and the store after it is written and and also closes the file.
       
  1084 @param
       
  1085 @return void
       
  1086 */
       
  1087 EXPORT_C void CMsvPlainBodyText::CommitL()
       
  1088 	{
       
  1089 	iFile.Close();
       
  1090 	RMsvWriteStream out;
       
  1091 	if(iIs8Bit)
       
  1092 		{
       
  1093 		out.AssignLC(iStore, KMsvPlainBodyText8);
       
  1094 		out.WriteUint32L(iCharsetId);
       
  1095 		out.WriteUint32L(iDefaultCharsetId);
       
  1096 		}
       
  1097 	else
       
  1098 		{
       
  1099 		out.AssignLC(iStore, KMsvPlainBodyText16);
       
  1100 		}
       
  1101 	iIsCommitted = ETrue;
       
  1102 	out.WriteUint32L(iIsCommitted);
       
  1103 
       
  1104 	TBuf<KFileNameFixedWidth> fileName;
       
  1105 	fileName.NumFixedWidth(iMessageId, EHex, KFileNameFixedWidth);
       
  1106 	out << (TDes&)fileName;
       
  1107 
       
  1108 	out.CommitL();
       
  1109 	out.Close();
       
  1110 	iStore.CommitL();
       
  1111 	iMsvStoreManager.ReplacePlainTextFileL(iMessageId);
       
  1112 	CleanupStack::PopAndDestroy(&out);
       
  1113 	}
       
  1114 
       
  1115 /**
       
  1116 Revert/Delete the file if it is not committed.
       
  1117 @param  None.
       
  1118 @return void.
       
  1119 */
       
  1120 void CMsvPlainBodyText::RevertL()
       
  1121 	{
       
  1122 	iFile.Close();
       
  1123 	if(!iIsCommitted)
       
  1124 		{
       
  1125 		iMsvStoreManager.DeletePlainTextFileL(iMessageId);
       
  1126 		}
       
  1127 	}
       
  1128 	
       
  1129 /**
       
  1130 Cancel the file read operation and set the filepointer to the current position of the file 
       
  1131 so that next call to NextChunkL() will attempt to read the same chunk that was cancelled
       
  1132 @param  None.
       
  1133 @return void.
       
  1134 */	
       
  1135 void CMsvPlainBodyText::DoCancel()
       
  1136 	{
       
  1137 	if(iMsvFileStatus == EMsvFileReading)
       
  1138 		{
       
  1139 		iFile.ReadCancel();
       
  1140 		iFile.Seek(ESeekStart, iCurrentFilePos);
       
  1141 		}
       
  1142 	CMsgActive::DoCancel();
       
  1143 	}