smsprotocols/smsstack/gsmu/src/Gsmumsg.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 23 6b1d113cdff3
--- a/smsprotocols/smsstack/gsmu/src/Gsmumsg.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/gsmu/src/Gsmumsg.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,3770 +1,3770 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Contains the implementation of the CSmsMessage class
-// 
-//
-
-/**
- @file
-*/
-
-#include <gsmumsg.h>
-#include "Gsmumain.h"
-#include <gsmubuf.h>
-#include <gsmuset.h>
-#include <gsmusar.h>
-#include "gsmumsgadditionalattributes.h"
-#include <gsmuieoperations.h>
-#include <gsmunonieoperations.h>
-
-#include <logwrap.h> //  Used for KLogNullId only
-#include <e32uid.h>
-#include <etelmm.h>
-#include <logwraplimits.h>
-
-#include <emsinformationelement.h>
-#include <emsformatie.h>
-#include <emsuserpromptie.h>
-#include <emsobjectdistributionie.h>
-#include "smsstackutils.h"
-
-/**
- *  Allocates and creates a CSmsMessage instance from a TGsmSms.
- *  
- *  The type of SMS-XXXX message to construct is defined by the first byte of
- *  the TGsmSms TPDU header.
- *  
- *  @param aFs Reference handle to the file system
- *  @param aGsmSms Reference to TGsmSms
- *  @param aBuffer The Unicode text for the message. The object takes ownership
- *  of aBuffer.
- *  @param aIsRPError Set to true if the message contains Reply Path Error. Default
- *  is false.
- *  @param aIsMobileTerminated Set to True if the message is Mobile Terminated.
- *  Default is false.
- *  @return New CSmsMessage object
- *  @capability None
- */
-EXPORT_C CSmsMessage* CSmsMessage::NewL(RFs& aFs, const TGsmSms& aGsmSms,CSmsBufferBase* aBuffer, TBool aIsRPError,TBool aIsMobileTerminated)
-	{
-	LOGGSMU1("CSmsMessage::NewL()");
-	
-	CleanupStack::PushL(aBuffer);
-	CSmsMessage* smsmessage=new(ELeave) CSmsMessage(aFs, aBuffer);
-	CleanupStack::Pop();
-	CleanupStack::PushL(smsmessage);
-	smsmessage->ConstructL(aGsmSms, aIsRPError,aIsMobileTerminated);
-	CleanupStack::Pop();
-	return smsmessage;
-	} // CSmsMessage::NewL
-
-
-/**
- *  Allocates and creates a CSmsMessage, specifying the SMS-XXX message type with
- *  a CSmsPDU::TSmsPduType.
- *  
- *  @param aFs Reference handle to the file system
- *  @param aType The PDU type
- *  @param aBuffer The Unicode text for the message. The object takes ownership
- *  of aBuffer.
- *  @param aIsRPError Set to true if the message contains Reply Path Error. Default
- *  is false.
- *  @return New CSmsMessage object
- *  @capability None
- */
-EXPORT_C CSmsMessage* CSmsMessage::NewL(RFs& aFs, CSmsPDU::TSmsPDUType aType,CSmsBufferBase* aBuffer,TBool aIsRPError)
-	{
-	LOGGSMU1("CSmsMessage::NewL()");
-
-	CleanupStack::PushL(aBuffer);
-	CSmsMessage* smsmessage=new(ELeave) CSmsMessage(aFs, aBuffer);
-	CleanupStack::Pop();
-	CleanupStack::PushL(smsmessage);
-	smsmessage->ConstructL(aType,aIsRPError);
-	CleanupStack::Pop();
-	return smsmessage;
-	} // CSmsMessage::NewL
-
-
-/**
- *  Destructor, frees resources.
- *  @capability None
- */
-EXPORT_C CSmsMessage::~CSmsMessage()
-	{
-	LOGGSMU1("CSmsMessage::~CSmsMessage()");
-
-	delete iSmsPDU;
-	delete iBuffer;
-	delete iCharacterSetConverter;
-
-	if (iInformationElementArray)
-		{
-		iInformationElementArray->ResetAndDestroy();
-		delete iInformationElementArray;
-		}
-
-	delete iAdditionalInfo;
-	} // CSmsMessage::NewL
-
-
-/**
- *  Internalises all object data except for the CSmsBufferBase.
- *  
- *  This is used when the buffer is stored elsewhere.
- *  
- *  @param aStream Stream to read from
- *  @capability None
- */
-EXPORT_C void CSmsMessage::InternalizeWithoutBufferL(RReadStream& aStream)
-	{
-	LOGGSMU1("CSmsMessage::InternalizeWithoutBufferL()");
-
-	InternalizeWithoutBufferAndVersionL(aStream);
-	InternalizeVersionL(aStream);
-
-	iAdditionalInfo->ResetAttributesL();
-
-	if (iVersion > ESmsMessageV0)
-        {
-        iAdditionalInfo->InternalizeL(aStream, iVersion);
-		}
-	} // CSmsMessage::InternalizeWithoutBufferL
-
-
-/**
- *  Externalises all object data except for the CSmsBufferBase.
- *  
- *  This is used when the buffer is stored elsewhere.
- *  
- *  @param aStream Stream to write to
- *  @capability None
- */
-EXPORT_C void CSmsMessage::ExternalizeWithoutBufferL(RWriteStream& aStream) const
-	{
-	LOGGSMU1("CSmsMessage::ExternalizeWithoutBufferL()");
-
-	ExternalizeWithoutBufferAndVersionL(aStream);
-	ExternalizeVersionL(aStream);
-
-	if (iVersion > ESmsMessageV0)
-		{
-		iAdditionalInfo->ExternalizeL(aStream, iVersion);
-		}
-	} // CSmsMessage::ExternalizeWithoutBufferL
-
-
-/**
- *  Internalises all object data.
- *  
- *  @param aStream Stream to read from
- *  @capability None
- */
-EXPORT_C void CSmsMessage::InternalizeL(RReadStream& aStream)
-	{
-	LOGGSMU1("CSmsMessage::InternalizeL()");
-
-	InternalizeWithoutBufferAndVersionL(aStream);
-	InternalizeBufferL(aStream);
-	InternalizeVersionL(aStream);
-
-	iAdditionalInfo->ResetAttributesL();
-	if (iVersion > ESmsMessageV0)
-		{
-		iAdditionalInfo->InternalizeL(aStream, iVersion);
-		}
-	} // CSmsMessage::InternalizeL
-
-
-/**
- *  Externalises all object data.
- *  
- *  @param aStream Stream to write to
- *  @capability None
- */
-EXPORT_C void CSmsMessage::ExternalizeL(RWriteStream& aStream) const
-	{
-	LOGGSMU1("CSmsMessage::ExternalizeL()");
-
-	ExternalizeWithoutBufferAndVersionL(aStream);
-	ExternalizeBufferL(aStream);
-	ExternalizeVersionL(aStream);
-
-	if (iVersion > ESmsMessageV0)
-		{
-		iAdditionalInfo->ExternalizeL(aStream, iVersion);
-		}
-	} // CSmsMessage::ExternalizeL
-
-
-/**
- *  Tests if the message contains text.
- *  
- *  @return True if the message contains text
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::TextPresent() const
-	{
-	LOGGSMU1("CSmsMessage::TextPresent()");
-
-	CSmsPDU::TSmsPDUType pdutype=SmsPDU().Type();
-	return (pdutype==CSmsPDU::ESmsSubmit) ||
-	       (pdutype==CSmsPDU::ESmsDeliver) ||
-	     (((pdutype==CSmsPDU::ESmsSubmitReport) || (pdutype==CSmsPDU::ESmsDeliverReport) ||
-	      ((pdutype==CSmsPDU::ESmsStatusReport) && ((CSmsStatusReport&) SmsPDU()).ParameterIndicatorPresent())) &&
-	      SmsPDU().UserDataPresent());
-	} // CSmsMessage::TextPresent
-
-
-/**
- *  Gets the number of PDU's required to encode the complete message.
- *  
- *  @leave KErrOverflow Leaves if the number of required PDUs exceeds the maximum
- *  or the message cannot be encoded.
- *  @return Number of PDU's
- *  @capability None
- */
-EXPORT_C TInt CSmsMessage::NumMessagePDUsL()
-	{
-	LOGGSMU1("CSmsMessage::NumMessagePDUsL()");
-
-	TInt nummessagepdus=1;
-	if (IsDecoded())
-		{
-		if (TextPresent())
-			{
-			nummessagepdus=NumMessageEmsPDUsL();
-			TInt maxnummessagepdus=SmsPDU().TextConcatenated()? 0xFF: 1;
- 			if (nummessagepdus>maxnummessagepdus)
-				{
- 				User::Leave(KErrOverflow);
-				}
-			}
-
-		}
-	else if (TextPresent() && SmsPDU().TextConcatenated())
-		{
-		nummessagepdus=SmsPDU().NumConcatenatedMessagePDUs();
-		}
-
-	LOGGSMU2("CSmsMessage::NumMessagePDUsL() returns %d", nummessagepdus);
-
-	return nummessagepdus;
-	} // CSmsMessage::NumMessagePDUsL
-
-
-/**
- *  Gets the maximum message length possible with the current settings.
- *  
- *  If Text is compressed, this returns the maximum number of bytes available
- *  with text compressed.
- *  
- *  @return Maximum message length
- *  @capability None
- */
-EXPORT_C TInt CSmsMessage::MaxMessageLength() const
-	{
-	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
-	TInt maxmessagelength=SmsPDU().UserData().MaxBodyLengthInChars();
-	if (SmsPDU().TextConcatenated())
-		{
-		maxmessagelength=maxmessagelength*0xFF;
-		}
-
-	LOGGSMU2("CSmsMessage::MaxMessageLength() returns %d", maxmessagelength);
-
-	return maxmessagelength;
-	} // CSmsMessage::MaxMessageLength
-
-
-/**
- *  
- *  @return The converted buffer length
- *  @note Use with care - Expensive operation
- */
-TInt CSmsMessage::ConvertedBufferLengthL(const CSmsBufferBase& aBuffer)
-    {
-    // Ignore in code coverage - not used in SMS stack and not exported
-    // but cannot be removed as impacts public header.
-    BULLSEYE_OFF    
-    LOGGSMU1("CSmsMessage::ConvertedBufferLengthL()");
-    
-    TInt convertedBufferLength=0;
-    CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
-    CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aBuffer);
-    convertedBufferLength=segmenter->TotalConvertedLengthL(iAdditionalInfo->Alternative7bitEncoding());
-    CleanupStack::PopAndDestroy(2, converter);
-    
-    LOGGSMU2("CSmsMessage::ConvertedBufferLengthL() returns %d", convertedBufferLength);
-    
-    return convertedBufferLength;
-    BULLSEYE_RESTORE
-    }
-
-/**
- *  Gets the message length.
- *  
- *  In the case where the message is compressed, this function compresses the
- *  text and returns the number of bytes of the compressed buffer.
- *  
- *  The function calls ConvertedBufferLengthL(), and is therefore an expensive
- *  operation.
- *  
- *  @return Message length
- *  @capability None
- */
-EXPORT_C TInt CSmsMessage::MessageLengthL()
-	{
-	LOGGSMU1("CSmsMessage::MessageLengthL()");
-
-	TInt messagelength=0;
-	if (!SmsPDU().TextCompressed())
-		{
-		messagelength=iBuffer->Length();
-		if(SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabetUCS2)messagelength*=2 ;
-		}
-	else
-		{
-		User::Leave(KErrNotSupported);
-		}
-	return messagelength;
-	} // CSmsMessage::MessageLengthL
-
-
-EXPORT_C void CSmsMessage::GetEncodingInfoL(TInt& aPdus, TInt& aUnconvertedChars,
-		                                    TInt& aDowngradedChars, TInt& aFreeUDUnitsInLastPDU)
-	{
-	LOGGSMU1("CSmsMessage::GetEncodingInfoL()");
-
-	aPdus                 = 1;
-	aUnconvertedChars     = 0;
-	aDowngradedChars      = 0;
-	aFreeUDUnitsInLastPDU = 0;
-
-	if (TextPresent())
-		{
-		if (IsDecoded())
-			{
-			//
-			// Clear the concatenated flag, EncodeBufferL() will add it if needed.
-			//
-			SmsPDU().SetTextConcatenatedL(EFalse, EFalse);
-
-			//
-			// Attempt to encode to a single PDU, and if that fails then attempt to
-			// encode to a set of PDUs.
-			//
-			CArrayFixFlat<TGsmSms>*  tmpArray = new (ELeave) CArrayFixFlat<TGsmSms>(8);
-			CleanupStack::PushL(tmpArray);
-			
-			//
-			// Encode the message...
-			//
-			if (!EncodeIntoSinglePDUL(*tmpArray, aUnconvertedChars,
-                                      aDowngradedChars, aFreeUDUnitsInLastPDU))
-				{
-				EncodeBufferL(*tmpArray, 0, *iBuffer, aUnconvertedChars,
-						      aDowngradedChars, aFreeUDUnitsInLastPDU, EFalse);
-
-				aPdus = iAdditionalInfo->SmsPDUArray().Count();
-				if (aPdus > 255)
-					{
-	 				User::Leave(KErrOverflow);
-					}
-				}
-
-			CleanupStack::PopAndDestroy(tmpArray);
-			}
-		else if (SmsPDU().TextConcatenated())
-			{
-			aPdus                 = SmsPDU().NumConcatenatedMessagePDUs();
-			aUnconvertedChars     = 0;
-			aDowngradedChars      = 0;
-			aFreeUDUnitsInLastPDU = 0;
-			}
-		}
-
-	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aPdus=%d", aPdus);
-	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aUnconvertedChars=%d", aUnconvertedChars);
-	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aDowngradedChars=%d", aDowngradedChars);
-	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aFreeUDUnitsInLastPDU=%d", aFreeUDUnitsInLastPDU);
-	} // CSmsMessage::GetEncodingInfoL
-
-
-/**
- *  Gets the User Data Settings.
- *  
- *  @param aSettings User Data Settings
- *  @capability None
- */
-EXPORT_C void CSmsMessage::UserDataSettings(TSmsUserDataSettings& aSettings) const
-	{
-	LOGGSMU1("CSmsMessage::UserDataSettings()");
-
-	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
-	aSettings.SetAlphabet(SmsPDU().Alphabet());
-	aSettings.SetTextCompressed(SmsPDU().TextCompressed());
-	TBool is16bit;
-	TBool concatenated=SmsPDU().TextConcatenated(&is16bit);
-	aSettings.SetTextConcatenated(concatenated,is16bit);
-	} // CSmsMessage::UserDataSettings
-
-
-/**
- *  Sets the User Data Settings.
- *  
- *  @param aSettings User Data Settings
- *  @capability None
- */
-EXPORT_C void CSmsMessage::SetUserDataSettingsL(const TSmsUserDataSettings& aSettings)
-	{
-	LOGGSMU1("CSmsMessage::SetUserDataSettingsL()");
-
-	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
-	SmsPDU().SetAlphabet(aSettings.Alphabet());
-	SmsPDU().SetTextCompressed(aSettings.TextCompressed());
-	TBool is16bit;
-	TBool concatenated=aSettings.TextConcatenated(&is16bit);
-	SmsPDU().SetTextConcatenatedL(concatenated,is16bit);
-	} // CSmsMessage::SetUserDataSettingsL
-
-
-/**
- *  Optimizes the user data settings.
- *  
- *  The alphabet flag causes an alphabet to be chosen which preserves information
- *  in the message and makes the number of PDUs as small as possible.
- *  
- *  The compression settings flag is not supported.
- *  
- *  The compression flag causes compression to be switched on if the resultant
- *  number of PDUs is smaller.
- *  
- *  If user explicitly defines alphabet as UCS2 or 8-bit coding, this setting is preserved;
- *  otherwise, if 7-bit (default) alphabet can not support current text of message UCS2
- *  alphabet (Unicode) is used.
- *  
- *  The two concatenation flags are mutually exclusive as they deal with 8-bit
- *  and 16-bit referenced concatenation. Both flags cause compression to be switched
- *  off and if the message length is greater than the maximum message length,
- *  concatenation is switched on.
- *  
- *  @param aOptions Combination of TSmsOptimizationFlags
- *  @capability None
- */
-EXPORT_C void CSmsMessage::OptimizeSettingsL(TInt aOptions)
-	{
-	LOGGSMU1("CSmsMessage::OptimizeSettingsL()");
-
-	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
-	__ASSERT_DEBUG(IsDecoded(),Panic(KGsmuPanicNotDecoded));
-
-	if (aOptions&ESmsFlagOptimizeAlphabet && (SmsPDU().Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit))
-		{
-		TBool isSupported=ETrue;
-		TInt numOfUnconvertibleChars;
-		TInt indexOfFirstUnconvertibleChar;
-
-		TInt size=iBuffer->Length();
-		const TInt bufsize=128;
-		TBuf<bufsize> buf;
-		TInt extracted=0;
-		TInt remaining=0;
-		TInt toExtract=0;
-		TInt pos=0;
-
-		// Defect Fix. Previous for loop caused an access violation as extract size was set
-		// to size of ibuffer not bufsize and caused a access violation when over 128. Implemented
-		// fix copies the ibuffer in 128 chunks until its all done.
-
-		while((pos<size) && isSupported)
-			{
-			remaining=(size - extracted);
-
-			if(remaining>bufsize)
-				toExtract=bufsize;
-			else
-				toExtract=remaining;
-
-			iBuffer->Extract(buf,pos,toExtract);
-			isSupported=IsSupportedL(buf,numOfUnconvertibleChars,indexOfFirstUnconvertibleChar);
-			extracted=(extracted+toExtract);
-			pos=extracted;
-			}
-
-		if(!isSupported)
-			SmsPDU().SetAlphabet(TSmsDataCodingScheme::ESmsAlphabetUCS2);
-		}
-	} // CSmsMessage::OptimizeSettingsL
-
-
-/**
- *  This function returns the currently requested alternative encoding method.
- * 
- *  In the case of incoming SMS messages received on the device, it will often
- *  be TSmsEncodingNone unless the Information Elements imply that an
- *  alternative encoding has been used.
- * 
- *  @return The currently selected encoding method.
- * 
- *  @capability None
- */
-EXPORT_C TSmsEncoding CSmsMessage::Alternative7bitEncoding() const
-	{
-	LOGGSMU1("CSmsMessage::Alternative7bitEncoding()");
-
-	return iAdditionalInfo->Alternative7bitEncoding();
-	} // CSmsMessage::Alternative7bitEncoding
-
-
-/**
- *  This function allows the client to specify an alternative encoding method
- *  incase the default GSM encoding cannot encode the message completely
- *  without data loss.
- * 
- *  @param aEncoding  Encoding method to select.
- * 
- *  @return A Symbian system wide error code.  This function will return
- *          KErrArgument if the encoding enum is invalid and will return
- *          KErrNotSupported if the required plug-ins are not present.
- * 
- *  @capability None
- */
-EXPORT_C TInt CSmsMessage::SetAlternative7bitEncoding(TSmsEncoding aEncoding)
-	{
-	LOGGSMU2("CSmsMessage::SetAlternative7bitEncoding(%d)", aEncoding);
-
-	//
-	// Get the encoders that would be used for this encoding method.
-	// The function will also check that the required encoder is present.
-	//
-	TRAPD(err,
-		{
-		CSmsAlphabetConverter*  converter = CSmsAlphabetConverter::NewLC(*iCharacterSetConverter, iFs,
-																	     TSmsDataCodingScheme::ESmsAlphabet7Bit,
-																	     EFalse);
-		converter->ConfirmAlternativeEncoderL(aEncoding);
-		CleanupStack::PopAndDestroy(converter);
-		});
-	
-	//
-	// Set the variable if the encoders are available...
-	//
-	if (err == KErrNone)
-		{
-		iAdditionalInfo->SetAlternative7bitEncoding(aEncoding);
-		}
-	
-	return err;
-	} // CSmsMessage::SetAlternative7bitEncoding
-
-
-/**
- *  Takes an encoding setting (received from a PDU) and merges it into the
- *  current setting (where possible).
- *  
- *  @param aEncoding  Encoding setting to merge.
- */
-void CSmsMessage::MergeAlternative7bitEncoding(TSmsEncoding aEncoding) const
-	{
-	LOGGSMU3("CSmsMessage::MergeAlternative7bitEncoding(): aEncoding=%d (currently %d)",
-			 aEncoding, iAdditionalInfo->Alternative7bitEncoding());
-
-	switch (iAdditionalInfo->Alternative7bitEncoding())
-		{
-		case ESmsEncodingNone:
-			{
-			// Anything is can be merge with this...
-			iAdditionalInfo->SetAlternative7bitEncoding(aEncoding);
-			}
-			break;
-		
-		case ESmsEncodingTurkishSingleShift:
-			{
-			// Only Turkish locking shift can merge...
-			if (aEncoding == ESmsEncodingTurkishLockingShift)
-				{
-				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingTurkishLockingAndSingleShift);
-				}
-			}
-			break;
-		
-		case ESmsEncodingTurkishLockingShift:
-			{
-			// Only Turkish single shift can merge...
-			if (aEncoding == ESmsEncodingTurkishSingleShift)
-				{
-				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingTurkishLockingAndSingleShift);
-				}
-			}
-			break;
-		
-		case ESmsEncodingPortugueseSingleShift:
-			{
-			// Only Portuguese locking shift can merge...
-			if (aEncoding == ESmsEncodingPortugueseLockingShift)
-				{
-				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingPortugueseLockingAndSingleShift);
-				}
-			}
-			break;
-		
-		case ESmsEncodingPortugueseLockingShift:
-			{
-			// Only Portuguese single shift can merge...
-			if (aEncoding == ESmsEncodingPortugueseSingleShift)
-				{
-				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingPortugueseLockingAndSingleShift);
-				}
-			}
-			break;
-		
-		case ESmsEncodingTurkishLockingAndSingleShift:
-		case ESmsEncodingSpanishSingleShift:
-		case ESmsEncodingPortugueseLockingAndSingleShift:
-		default:
-			{
-			// NOP - Cannot merge anything into these...
-			}
-		};
-
-	LOGGSMU2("CSmsMessage::MergeAlternative7bitEncoding(): New encoding=%d",
-			 iAdditionalInfo->Alternative7bitEncoding());
-	} // CSmsMessage::MergeAlternative7bitEncoding
-
-
-/**
- *  Tests if a buffer can be encoded without loss of information.
- *  
- *  @param aDes                                 The buffer to test for encoding
- *  @param aNumberOfUnconvertibleCharacters     On return, the number of 
- *                                              unconvertible characters
- *  @param aIndexOfFirstUnconvertibleCharacter  On return, the index of the
- *                                              first unconvertible character
- * 
- *  @return True if aDes can be encoded without loss of information
- * 
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
-		                                 TInt& aIndexOfFirstUnconvertibleCharacter)
-	{
-	LOGGSMU1("[1] CSmsMessage::IsSupportedL()");
-
-	__ASSERT_DEBUG(TextPresent(), Panic(KGsmuPanicTextNotPresent));
-
-	aNumberOfUnconvertibleCharacters    = 0;
-	aIndexOfFirstUnconvertibleCharacter = aDes.Length();
-
-	if (SmsPDU().TextCompressed())
-		{
-		return EFalse;
-		}
-
-	return SmsPDU().UserData().IsSupportedL(aDes, aNumberOfUnconvertibleCharacters,
-                                            aIndexOfFirstUnconvertibleCharacter);
-	} // CSmsMessage::IsSupportedL
-
-
-/**
- *  Tests if a buffer can be encoded without loss of information.
- *  
- *  @param aDes                                 The buffer to test for encoding
- *  @param aNumberOfUnconvertibleCharacters     On return, the number of 
- *                                              unconvertible characters
- *  @param aNumberOfDowngradedCharacters        On return, the number of 
- *                                              characters downgraded
- *  @param aNumberRequiringAlternativeEncoding  On return, the number of 
- *                                              characters needing alternative
- *                                              encoding support
- *  @param aIndexOfFirstUnconvertibleCharacter  On return, the index of the
- *                                              first unconvertible character
- * 
- *  @return True if aDes can be encoded without loss of information
- * 
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
-		                                 TInt& aNumberOfDowngradedCharacters,
-		                                 TInt& aNumberRequiringAlternativeEncoding,
-		                                 TInt& aIndexOfFirstUnconvertibleCharacter) const
-	{
-	LOGGSMU1("[2] CSmsMessage::IsSupportedL()");
-
-	__ASSERT_DEBUG(TextPresent(), Panic(KGsmuPanicTextNotPresent));
-
-	aNumberOfUnconvertibleCharacters    = 0;
-	aNumberOfDowngradedCharacters       = 0;
-	aNumberRequiringAlternativeEncoding = 0;
-	aIndexOfFirstUnconvertibleCharacter = aDes.Length();
-
-	if (SmsPDU().TextCompressed())
-		{
-		return EFalse;
-		}
-
-	return SmsPDU().UserData().IsSupportedL(aDes, iAdditionalInfo->Alternative7bitEncoding(),
-											aNumberOfUnconvertibleCharacters,
-	                                        aNumberOfDowngradedCharacters,
-                                            aNumberRequiringAlternativeEncoding,
-                                            aIndexOfFirstUnconvertibleCharacter);
-	} // CSmsMessage::IsSupportedL
-
-
-/**
- *  Encodes message PDUs as an array of TGsmSms objects.
- *  
- *  Note, this function should only be called after EncodeIntoSinglePDUL() as EncodeBufferL() now
- *  automatically prepares PDUs for concatenation.
- *  
- *  @param aSmsArray (In) an empty array. On return, one or more encoded TGsmSms.
- *  @param aReference Sets a Concatenated Message Reference (default 0)
- *  @capability None
- */
-EXPORT_C void CSmsMessage::EncodeMessagePDUsL(CArrayFix<TGsmSms>& aSmsArray, TInt aReference)
-	{
-	LOGGSMU2("CSmsMessage::EncodeMessagePDUsL(): aReference=%d", aReference);
-
-	__ASSERT_DEBUG((aSmsArray.Count()==0),Panic(KGsmuPanicSmsArrayNotEmpty));
-	
-	if (TextPresent())
-		{
-		if (SmsPDU().TextCompressed())
-			{
-			User::Leave(KErrNotSupported);
-			}
-		else
-			{
-			TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
-				
-			EncodeBufferL(aSmsArray, aReference, *iBuffer, unconvertedChars,
-					      downgradedChars, freeUDUnitsInLastPDU);
-			}
-		}
-	else
-		{
-        if(SmsPDU().Type()==CSmsPDU::ESmsCommand)
-            {
-            //Commands never contain text, so commands only encoded
-            // in this branch.
-            //
-            // However  Commands don't support information
-            // elements (per 23.040 6.5) and the CSmsIEOperation class
-            // do not allow control information elements to be added
-            // to Commands, hence the next line is commented out.
-            // PrepareCommandMessageL();
-            }
-
- 		TGsmSms sms;
- 		SmsPDU().EncodeMessagePDUL(sms);
- 		aSmsArray.AppendL(sms);
-		}
-	} // CSmsMessage::EncodeMessagePDUsL
-
-
-/**
- *  @internalComponent
- *  
- *  This method copies information elements from the collections contained in
- *  CSmsMessageAdditionalAttributes into the working PDU.
- *  
- *  Command Messages comprise only 1 PDU. Therefore all information
- *  elements must be present in the working PDU when encoding takes place.
- *  If there is not enough space in the PDU, the message encoding will fail.
- *  
- *  The 23.040 has not defined any information elements that are contained in
- *  Command PDUs. This method has been provided to maintain consistency with
- *  previous GSMU implementations.
- *  
- *  @leave KErrAlreadyExists or KErrAlreadyExists
- */
-void CSmsMessage::PrepareCommandMessageL()
-    {
-    LOGGSMU1("CSmsMessage::PrepareCommandMessageL()");
-
-    if (SmsPDU().Type()==CSmsPDU::ESmsCommand)
-        {
-        CSmsCommand& command = static_cast<CSmsCommand&>(SmsPDU());
-
-        for (TUint8 category = 0; category < TSmsInformationElementCategories::ENumberOfCategories; category++)
-            {
-            switch(category)
-                {
-                case TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
-                case TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
-                case TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
-                    {
-                    for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
-                        {
-                        CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j);
-                        TPtr8 data = informationElement.Data();
-                        command.AddInformationElementL(informationElement.Identifier(), data);
-                        }
-                    break;
-                    }
-                default:
-                LOGGSMU2("CSmsMessage::PrepareCommandMessageL,default switch category = %d, id = %d", category);
-                    break;
-                }
-            }
-        }
-    } // CSmsMessage::PrepareCommandMessageL
-
-
-/**
- *  Decodes message PDUs from an array of TGsmSms objects.
- *  
- *  The array contains a concatenated message, and must have the correct number
- *  of PDUs.
- *  
- *  @param aSmsArray Concatenated message
- *  @capability None
- */
-EXPORT_C void CSmsMessage::DecodeMessagePDUsL(const CArrayFix<TGsmSms>& aSmsArray)
-	{
-    LOGGSMU2("CSmsMessage::DecodeMessagePDUsL(): PDUs=%d", aSmsArray.Count());
-
-	TInt count=aSmsArray.Count();
-	SetIsComplete(ETrue);
-	CArrayPtrFlat<CSmsPDU>* smspduarray=new(ELeave) CArrayPtrFlat<CSmsPDU>(8);
-	CleanupStack::PushL(smspduarray);
-	// With CleanupResetAndDestroyPushL, only ResetAndDestroy method of smspduarray is invoked. 
-	// smspduarray object is actually deleted with the first push. 
-	// coverity[double_push]
-	CleanupResetAndDestroyPushL(*smspduarray);  // Don't forget to destroy what the array elements point to.
-
-	TInt i=0;
-	TBool ismobileterminated=(Type()==CSmsPDU::ESmsDeliver) || (Type()==CSmsPDU::ESmsSubmitReport) || (Type()==CSmsPDU::ESmsStatusReport);
-	for (; i<count; i++)
-		{
-		CSmsPDU* smspdu=CSmsPDU::NewL(aSmsArray[i],*iCharacterSetConverter,iFs, EFalse,ismobileterminated);
-		CleanupStack::PushL(smspdu);
-		TInt j=0;
-		for (; (j<smspduarray->Count()) && (smspdu->ConcatenatedMessagePDUIndex()>(*smspduarray)[j]->ConcatenatedMessagePDUIndex()); j++)
-			{
-			}
-		smspduarray->InsertL(j,smspdu);
-		CleanupStack::Pop();
-		}
-	if (SmsPDU().TextCompressed())
-		User::Leave(KErrNotSupported);
-	else
-		DecodeBufferL(*smspduarray,*iBuffer);
-
-	CleanupStack::PopAndDestroy(2);  //  smspduarray elements (Reset and Destroy), smspduarray
-	SetIsDecoded(ETrue);
-	SmsPDU().UserData().SetBodyL(KNullDesC8);
-	} // CSmsMessage::DecodeMessagePDUsL
-
-/**
- *  Decodes partial complete message PDUs from an array of TGsmSms objects.
- *  
- *  The array contains a concatenated incomplete message, but the array of
- *  TGsmSms object must be in sequence.
- *  
- *	NOTE:
- *	It will not fully decode EMS and Control Information elements if it needs 
- *	to decode a partially complete class 0 SMS message. The assumption is that 
- *	it is necessary to display a partially complete message then only the raw 
- *	text will be displayed on the UI without any animation elements. The 
- *	rational for this design is that these information elements are normally 
- *	specified as being located at a specific position in a message. It will 
- *	complicate the design of client app if it has to re-calculate the position 
- *	of these elements when it receives a partially complete message under 
- *	Out Of Memory Conditions.
- 
- *  @param aSmsArray Concatenated message
- *	@param aLastPartialCompleteMsg boolean value indicating this is the last
- *			incomplete message for a particular concatenated message.
- *  @capability None
- */
-EXPORT_C void CSmsMessage::DecodePartialCompleteMessagePDUsL(const CArrayFix<TGsmSms>& aSmsArray, TBool aLastPartialCompleteMsg)
-	{
-	LOGGSMU2("CSmsMessage::DecodePartialCompleteMessagePDUsL(): PDUs=%d", aSmsArray.Count());
-
-	TInt count=aSmsArray.Count();
-	SetIsComplete(EFalse);
-	CArrayPtrFlat<CSmsPDU>* smspduarray=new(ELeave) CArrayPtrFlat<CSmsPDU>(8);
-	CleanupStack::PushL(smspduarray);
-	// With CleanupResetAndDestroyPushL, only ResetAndDestroy method of smspduarray is invoked. 
-	// smspduarray object is actually deleted with the first push. 
-	// coverity[double_push]
-	CleanupResetAndDestroyPushL(*smspduarray);  // Don't forget to destroy what the array elements point to.
-
-	TBool isMobileTerminated=(Type()==CSmsPDU::ESmsDeliver);
-	/*
-	The loop below goes through all the sms's received & check whether the received PDUs are of Class 0
-	or not. The number of PDUs received must be less than the number of concatenated PDUs constitute this message.
-	Then it order the PDUs in sequence for decoding purpose.
-	*/
-	for (TInt i=0; i<count; i++)
-		{
-		CSmsPDU* smspdu=CSmsPDU::NewL(aSmsArray[i],*iCharacterSetConverter,iFs, EFalse,isMobileTerminated);
-		CleanupStack::PushL(smspdu);
-
-		/*
-		Check all the PDUs must be class 0 messages & also the number of received PDUs
-		must be less than the number of concatenated PDUs constitute this message
-		*/
-		TSmsDataCodingScheme::TSmsClass  msgClass;
-		if (smspdu->DataCodingSchemePresent()  &&  smspdu->Class(msgClass))
-			{
-			if (msgClass != TSmsDataCodingScheme::ESmsClass0)
-				{
-				User::Leave(KErrNotSupported);
-				}
-			__ASSERT_DEBUG((count < smspdu->NumConcatenatedMessagePDUs()),Panic(KGsmuPanicWrongNumberOfMessagePDUs));
-			}
-		else
-			{
-			User::Leave(KErrNotSupported);
-			}
-		//The below for statement finds the position in smspduarray where the PDU should be inserted.
-		//The PDUs are put in sequence for decoding purpose.
-		TInt j;
-		for (j=0; (j<smspduarray->Count()) && (smspdu->ConcatenatedMessagePDUIndex()>(*smspduarray)[j]->ConcatenatedMessagePDUIndex()); j++)
-			{
-			}
-		smspduarray->InsertL(j,smspdu);
-		CleanupStack::Pop();
-		}
-
-	if (SmsPDU().TextCompressed())
-		{
-		User::Leave(KErrNotSupported);
-		}
-	else
-		{
-		DecodeOnlyTextL(*smspduarray,*iBuffer);
-		}
-
-	iVersion = CSmsMessage::ESmsIncompleteClass0MessageV;
-
-	TInt startPDU = smspduarray->At(0)->ConcatenatedMessagePDUIndex();
-	TInt endPDU = smspduarray->At(smspduarray->Count()-1)->ConcatenatedMessagePDUIndex();
-	AddIncompleteMessageInfoL(startPDU, endPDU, aLastPartialCompleteMsg);
-
-	CleanupStack::PopAndDestroy(2);  //  smspduarray elements (Reset and Destroy), smspduarray
-	SetIsDecoded(ETrue);
-	SmsPDU().UserData().SetBodyL(KNullDesC8);	
-	}
-
-CSmsMessage::CSmsMessage(RFs& aFs, CSmsBufferBase* aBuffer):
-    iFlags(0),
-    iStatus(NMobileSmsStore::EStoredMessageUnread),
-    iLogServerId(KLogNullId),
-    iBuffer(aBuffer),
-    iFs(aFs),
-	iSlotArray(8),
-	iVersion(ESmsMessageV4),
-	iAdditionalInfo(NULL)
-    {
-    iTime.UniversalTime();
-
-    TBool result = SetUTCOffset(User::UTCOffset());
-    __ASSERT_DEBUG(result, Panic(KGSMUPanicUserTimeZoneOffsetOutOfRange));
-    } // NMobileSmsStore::EStoredMessageUnread
-
-void CSmsMessage::ConstructL(const TGsmSms& aGsmSms, TBool aIsRPError,TBool aIsMobileTerminated)
-	{
-    LOGGSMU1("CSmsMessage::ConstructL()");
-
-	iCharacterSetConverter=CCnvCharacterSetConverter::NewL();
-	iInformationElementArray = new (ELeave) RPointerArray<CEmsInformationElement>(8);
-
-	iAdditionalInfo = CSmsMessageAdditionalAttributes::NewL();
-	CreateControlIEOperationsClassesL();
-	CreateControlNonIEOperationsClassesL();
-
-	iSmsPDU=CSmsPDU::NewL(aGsmSms,*iCharacterSetConverter,iFs, aIsRPError,aIsMobileTerminated);
-	SetIsComplete(NumMessagePDUsL()==1);
-	if (IsComplete() && TextPresent())
-		{
-		TSmsEncoding  encodingUsedInSegment = SmsPDU().NationalLanguageEncoding();
-		
-		CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
-		TPtrC nativeChars(converter->ConvertToNativeL(SmsPDU().UserData().Body(),
-													  encodingUsedInSegment));
-		MergeAlternative7bitEncoding(encodingUsedInSegment);
-		
-		if (SmsPDU().TextCompressed())
-			User::Leave(KErrNotSupported);
-		else
-			iBuffer->InsertL(iBuffer->Length(),nativeChars);
-		CleanupStack::PopAndDestroy(converter);
-		CSmsPDU::TSmsPDUType pdutype= SmsPDU().Type();
-		if(pdutype==CSmsPDU::ESmsCommand)
-			{
-			// This branch is never executed as TextPresent() never
-			// returns true when pduType == command
-            User::Leave(KErrArgument);
-			}
-		else if(SmsPDU().UserDataPresent())
-			{
-			TInt smscIndex(0);
-
-			if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
-				{
-				iAdditionalInfo->SetStatusReportSchemeL(EControlParametersScheme);
-				}
-			else
-				{
-				iAdditionalInfo->SetStatusReportSchemeL(EDefaultScheme);	
-				}
-				
-            InstallControlInformationElementsL(SmsPDU().UserData(), 0);
-			InstallEmsInformationElementsL(SmsPDU().UserData(),0);
-			UpdateUserPromptAndODIElementsStartPosition();
-			}
-		}
-	SetIsDecoded(IsComplete());
-
-	if (TextPresent())
-		SmsPDU().UserData().SetBodyL(KNullDesC8);
-	} // CSmsMessage::ConstructL
-
-
-void CSmsMessage::ConstructL(CSmsPDU::TSmsPDUType aType,TBool aIsRPError)
-	{
-    LOGGSMU3("CSmsMessage::ConstructL(): aType=%d, aIsRPError=%d", (TInt) aType,
-    		 aIsRPError);
-
-	iCharacterSetConverter=CCnvCharacterSetConverter::NewL();
-	iInformationElementArray = new (ELeave) RPointerArray<CEmsInformationElement>(2);
-
-	iAdditionalInfo = CSmsMessageAdditionalAttributes::NewL();
-	CreateControlIEOperationsClassesL();
-	CreateControlNonIEOperationsClassesL();
-
-	iSmsPDU=CSmsPDU::NewL(aType,*iCharacterSetConverter,iFs,aIsRPError);
-	SetIsComplete(ETrue);
-	SetIsDecoded(ETrue);
-	} // CSmsMessage::ConstructL
-
-
-/**
- *  Counts the number of PDUs that this message will take. To do this the
- *  message will attempt to be encoded into 1 message, and if not into
- *  multiple messages. Due to the processing, the function should be used
- *  sparingly.
- * 
- *  @return  Number of PDUs required.
- */
-TInt CSmsMessage::NumMessageEmsPDUsL()
-	{
-	LOGGSMU1("CSmsMessage::NumMessageEmsPDUsL()");
-
-	//
-	// Clear the concatenated flag, EncodeBufferL() will add it if needed.
-	//
-	SmsPDU().SetTextConcatenatedL(EFalse, EFalse);
-
-	//
-	// Attempt to encode to a single PDU, and if that fails then attempt to
-	// encode to a set of PDUs.
-	//
-	CArrayFixFlat<TGsmSms>*  tmpArray = new (ELeave) CArrayFixFlat<TGsmSms>(8);
-	CleanupStack::PushL(tmpArray);
-	TInt numMsgs = 1;
-	
-	if (!EncodeIntoSinglePDUL(*tmpArray))
-		{
-		TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
-		
-		EncodeBufferL(*tmpArray, 0, *iBuffer, unconvertedChars,
-			          downgradedChars, freeUDUnitsInLastPDU, EFalse);
-
-		numMsgs = iAdditionalInfo->SmsPDUArray().Count();
-		}
-
-	CleanupStack::PopAndDestroy(tmpArray);
-	
-    LOGGSMU2("CSmsMessage::NumMessageEmsPDUsL() returns %d", numMsgs);
-
-	return numMsgs;
-	} // CSmsMessage::NumMessageEmsPDUsL
-
-
-/**
- *  @internalComponent
- *  
- *  This method removes all non mandatory information elements from the
- *  working PDU.
- *  
- *  The working PDU is the PDU which is currently being encoded or decoded.
- *  
- *  @leave KErrAlreadyExists or KErrAlreadyExists
- */
-void CSmsMessage::ResetWorkingPDUL()
-	{
-	LOGGSMU1("CSmsMessage::ResetWorkingPDUL()");
-	
-	CSmsUserData& uData = SmsPDU().UserData();
-	//remove non-mandatory EMS information elements
-	for (TInt a=uData.NumInformationElements(); a>0; --a)
-        {
-        const CSmsInformationElement& ie = uData.InformationElement(a-1);
-
-         TSmsInformationElementCategories::TInformationElementCategory category;
-
-        if (TSmsInformationElementCategories::GetCategoryDefinition(ie.Identifier(), category)  &&
-        	(category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues)    &&
-            (category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU) &&
-            (category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU))
-            {
-            uData.RemoveInformationElement(a-1);
-            }
-        }
-    // reset user body
-    uData.SetBodyL(KNullDesC8);
-    } // CSmsMessage::ResetWorkingPDUL
-
-
-void CSmsMessage::CorrectFormattingL(TUint aCharsAddedToCurrentPDU,
-									 RPointerArray<CEmsInformationElement>& aCorrectedFormattingIEArray,
-									 TUint aCharsAlreadyAdded)
-	{
-	LOGGSMU3("CSmsMessage::CorrectFormattingL(): aCharsAddedToCurrentPDU=%d, aCharsAlreadyAdded=%d",
-			 aCharsAddedToCurrentPDU, aCharsAlreadyAdded);
-
-	CSmsUserData& uData = SmsPDU().UserData();
-	for (TInt a= 0; a < uData.NumInformationElements(); a++)
-		{
-		CSmsInformationElement& ie = uData.InformationElement(a);
-		if (CSmsInformationElement::ESmsEnhancedTextFormatting==ie.Identifier())
-			{
-			CEmsFormatIE& formatIE=static_cast<CEmsFormatIE&>(ie);
-
-			TUint oldFormatLen=formatIE.FormatLength(); //
-			if(aCharsAddedToCurrentPDU < formatIE.StartPosition() + oldFormatLen)
-				{
-				TUint newFormatLen=aCharsAddedToCurrentPDU - formatIE.StartPosition();
-				formatIE.SetFormatLength(newFormatLen);
-
-				// Now, re-encode the information element - this is because we have
-				// changed a message in the UserData which is using EMS elements as
-				// SMS IEs. Encoding is NOT automatic
-				formatIE.EncodeInformationElementL();
-
-				if((TInt)(aCharsAlreadyAdded+aCharsAddedToCurrentPDU) < iBuffer->Length())
-					{
-					CEmsFormatIE* newie=static_cast<CEmsFormatIE*>(formatIE.DuplicateL());
-					CleanupStack::PushL(newie);
-					newie->SetFormatLength(oldFormatLen - newFormatLen);
-					newie->SetStartPosition(aCharsAlreadyAdded+aCharsAddedToCurrentPDU);
-					LOGGSMU2("CSmsMessage::CorrectFormattingL",aCorrectedFormattingIEArray.Count());
-					aCorrectedFormattingIEArray.Append(newie);
-					CleanupStack::Pop(newie);
-					}
-				}
-			}
-		}
-	} // CSmsMessage::CorrectFormattingL
-
-
-void CSmsMessage::CorrectFormattingInSinglePDUL()
-	{
-	LOGGSMU1("CSmsMessage::CorrectFormattingInSinglePDUL()");
-
-	CSmsUserData& uData = SmsPDU().UserData();
-	for (TInt a= 0; a < uData.NumInformationElements(); a++)
-		{
-		CSmsInformationElement& ie = uData.InformationElement(a);
-		if (CSmsInformationElement::ESmsEnhancedTextFormatting==ie.Identifier())
-			{
-			CEmsFormatIE& formatIE=static_cast<CEmsFormatIE&>(ie);
-			TUint oldFormatLen=formatIE.FormatLength(); //
-			if(iBuffer->Length() < (TInt)(formatIE.StartPosition()+ oldFormatLen))
-				{
-				TUint newFormatLen=iBuffer->Length() - formatIE.StartPosition();
-				formatIE.SetFormatLength(newFormatLen);
-
-				// reencode
-				formatIE.EncodeInformationElementL();
-				}
-			}
-		}
-	} // CSmsMessage::CorrectFormattingInSinglePDUL
-
-
-/**
- *  Adds a copy of the current PDU to the PDU array used to record all the
- *  PDUs being encoded in a concatentated message.
- * 
- *  @param  aDoEncode  If true the PDU is added and updated. If false only a
- *                     NULL placeholder is stored. This allows the number of
- *                     PDUs to be quickly counted if the encoded PDUs are of
- *                     no further use.
- */
-void CSmsMessage::AddCurrentPDUToPDUArrayL(TBool aDoEncode)
-	{
-	LOGGSMU2("CSmsMessage::AddCurrentPDUToPDUArrayL(): Adding PDU number %d",
-			 iAdditionalInfo->SmsPDUArray().Count() + 1);
-	
-	//
-	// Maximum number of PDU is 255, so if we have that already then we cannot
-	// continue.
-	//
-	TInt  numPDUs = iAdditionalInfo->SmsPDUArray().Count();
-
-	if (numPDUs >= 255)
-		{
-		User::Leave(KErrOverflow);
-		}
-	
-	//
-	// We only do most of the work if we are actually encoding.
-	//
-	if (aDoEncode)
-		{
-		//
-		// Update the Concatenated Message PDU numbers in the current PDU. This
-		// means that at least the last PDU has the correct values (to update
-		// all PDUs when a new PDU is added would be too slow, so we do that
-		// only once at the end).
-		//
-		if (numPDUs > 0)
-			{
-			SmsPDU().SetConcatenatedMessagePDUIndex(numPDUs+1);
-			SmsPDU().SetNumConcatenatedMessagePDUs(numPDUs+1);
-			}
-	
-		//
-		// Create copy of the current PDU and store it in the array...
-		//
-		CSmsPDU*  newPDU = SmsPDU().DuplicateL();
-		CleanupStack::PushL(newPDU);
-		iAdditionalInfo->SmsPDUArray().AppendL(newPDU);
-		CleanupStack::Pop(newPDU);
-		}
-	else
-		{
-		//
-		// Otherwise just append a NULL value to allow the data PDUs to be
-		// counted...
-		//
-		iAdditionalInfo->SmsPDUArray().AppendL(NULL);
-		}
-	} // CSmsMessage::AddCurrentPDUToPDUArrayL
-
-
-TBool CSmsMessage::AddIEToUserDataL(CEmsInformationElement* aIE, TInt aCharsAlreadyAdded,TUint& aCharsAddedToCurrentPDU,CSmsEMSBufferSegmenter& aSeg)
-	{
-	LOGGSMU1("CSmsMessage::AddIEToUserDataL()");
-
-	TBool ieAdded=EFalse;
-	if (SmsPDU().UserData().EmsInformationElementWillFitL(aIE,aSeg,aCharsAddedToCurrentPDU))
-		{
-		CEmsInformationElement* newIE=aIE->DuplicateL();
-		newIE->SetStartPosition(newIE->StartPosition()-aCharsAlreadyAdded);
-	    CleanupStack::PushL(newIE);
-		SmsPDU().UserData().AddEmsInformationElementL(newIE);
-		CleanupStack::Pop(newIE);
-		ieAdded=ETrue;
-		}
-	return ieAdded;
-	} // CSmsMessage::AddIEToUserDataL
-
-
-/**
- *  Fills the current PDU with the number of specified native chars.
- *  
- *  @param aSeg Buffer containing the native chars
- *  @param aNumChars number of native characters to add.
- *  @param aEncoding  SMS Encoding if required.
- * 
- *  @return TInt Number of native characters added
- */
-TInt CSmsMessage::FillPduL(CSmsEMSBufferSegmenter& aSeg, TInt aNumChars, TSmsEncoding aEncoding)
-	{
-	LOGGSMU1("CSmsMessage::FillPduL()");
-
-	TUint maxUDUnitsREmaining=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-
-	if (aNumChars==0 || maxUDUnitsREmaining==0)
-		{
-		return 0;
-		}
-
-	HBufC8* buf=HBufC8::NewMaxLC(2*aNumChars);
-	TPtr8 ptr(buf->Des());
-	TInt numberOfUnconvertibleCharacters(0); 
-	TInt numberOfDowngradedCharacters(0);
-
-	TInt nativeLength = aSeg.SegmentL(ptr, aNumChars, maxUDUnitsREmaining,
-			                          numberOfUnconvertibleCharacters,
-			                          numberOfDowngradedCharacters,
-			                          aEncoding);
-
-	SmsPDU().UserData().AppendBodyL(ptr);
-
-	CleanupStack::PopAndDestroy(buf);
-	return nativeLength;
-	} // CSmsMessage::FillPduL
-
-
-/**
- *  This method copies control information elements from the specified
- *  collection into the working PDU.
- *  
- *  @param aCategory        The category of control information element to be
- *                          added to the PDU.
- *  @param aMandatoryInPDU  Specifies whether the specified category of information
- *                          element must be added to this PDU.
- *  @param aDoEncode        Flag indicating if encoding is really wanted, or just the
- *                          calculation of the number of PDUs.
- *
- *  @leave KErrArgument     If the category is mandatory but one or more elements
- *                          cannot be added then the encoding will fail.
- *  @leave KErrOverFlow     If the information element is too big to be encoded into
- *                          a PDU that contains only the mandatory elements.
- */
-void CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::TInformationElementCategory aCategory,
-			                                                          TBool aMandatoryInPDU, TBool aDoEncode)
-    {
-    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL()");
-
-    TUint numberOfInformationElements = iAdditionalInfo->NumberOfControlInformationElements(aCategory);
-
-    for (TInt i = 0; i < numberOfInformationElements; i++)
-        {
-        CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( aCategory, i);
-
-        CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(informationElement.Identifier(),informationElement.Data());
-        CleanupStack::PushL(cloneInformationElement);
-
-        if (SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement))
-            {
-            SmsPDU().UserData().UpdateInformationElementArrayL(informationElement.Identifier(),informationElement.Data());
-            }
-        else if (aMandatoryInPDU)
-                {
-                // Error Scenario, cannot fit the mandatory PDU into the User Data
-                User::Leave(KErrArgument);
-                }
-             else
-                {
-                // Close off PDU and transfer to output array
-                AddCurrentPDUToPDUArrayL(aDoEncode);
-                ResetWorkingPDUL();
-
-                // Now test whether the information element will fit into a PDU at all.
-                // It is possible to make Enhanced Voice Mail Information Elements
-                // bigger than the available space in the PDU.
-                TBool canFit = SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement);
-                if (canFit == EFalse)
-                    {
-                    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessage, IE too bit to fit in any PDUL");
-                    User::Leave(KErrArgument);
-                    }
-                i--;
-                }
-
-        CleanupStack::PopAndDestroy(cloneInformationElement);
-        }
-    } // CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL
-
-
-/**
- *  This method copies control information elements from the collections of
- *  control information elements contained in CSmsAdditionalAttributes into the
- *  working PDU.
- *  
- *  @param aDoEncode  Flag indicating if encoding is really wanted, or just the
- *                    calculation of the number of PDUs.
- *
- *  @leave KErrArgument  If the category is mandatory but one or more elements
- *                       cannot be added then the encoding will fail.
- */
-void CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL(TBool aDoEncode)
-    {
-    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL() 1");
-
-    TBool mandatoryInEachPDU = ETrue;
-    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly,
-    													mandatoryInEachPDU, aDoEncode);
-    mandatoryInEachPDU = EFalse;
-    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlSingleInstanceOnly,
-    													mandatoryInEachPDU, aDoEncode);
-    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed,
-    													mandatoryInEachPDU, aDoEncode);
-    } // CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL
-
-
-/**
- *  Attempts to add EMS IE to the current PDU.
- *  
- *  @param aSegmenter                  Reference to buffer segmenter.
- *  @param aCharsAddedToCurrentPDU     Returned number of characters added to current PDU.
- *  @param aDoEncode                   Flag indicating if encoding is really wanted,
- *                                     or just the calculation of the number of PDUs.
- *  @param aEncoding                   SMS 7bit encoding if appropriate.
- *  @param aCorrectedFormatingIEArray  Array of IEs that have to be placed in following
- *                                     PDUs (e.g. corrected).
- *  @param aCurrEMSIEno                Current IE number.
- *  @param aCharsAlreadyAdded          Returned number of characters added.
- *
- *  @return Whether EMS IE has beenn added, in singleMode returns true if there are no more than one PDU.
- */
-TBool CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL(CSmsEMSBufferSegmenter& aSegmenter,
-																   TUint& aCharsAddedToCurrentPDU,
-																   TBool aDoEncode,
-																   TSmsEncoding& aEncoding,
-																   RPointerArray<CEmsInformationElement>& aCorrectedFormatingIEArray,
-																   TUint& aCurrEMSIEno,
-																   TUint& aCharsAlreadyAdded)
-	{
-	LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL()");
-
-	TUint startPosition=0;
-
-	 // number of chars added to the current PDU
-	TUint no=iInformationElementArray->Count();
-	LOGGSMU2("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL no of IE %d",no);
-	CEmsInformationElement* ie = NULL;
-	TUint msgLen=iBuffer->Length();
-	TUint filledChars=0;
-
-	while(aCurrEMSIEno < no || aCorrectedFormatingIEArray.Count() > 0)
-	{
-		ie = NULL;
-		TBool correction=EFalse;
-		if(aCurrEMSIEno < no)
-			{
-			ie = (*iInformationElementArray)[aCurrEMSIEno];
-			startPosition=ie->StartPosition();
-			}
-
-		if(ie == NULL || ( startPosition != aCharsAlreadyAdded) )
-		{
-			if(aCorrectedFormatingIEArray.Count() > 0)
-			{
-				correction=ETrue;
-				ie = aCorrectedFormatingIEArray[0];
-				startPosition=ie->StartPosition();
-			}
-		}
-
-		__ASSERT_ALWAYS(ie !=NULL, User::Leave(KErrCorrupt));
-
-		if(startPosition <= msgLen)
-			{
-			__ASSERT_DEBUG(startPosition>=aCharsAlreadyAdded, User::Leave(KErrUnderflow));
-			startPosition -= aCharsAlreadyAdded; // startPosition now relative to current PDU.
-
-			// Add all chars upto startposition.
-			filledChars=0;
-
-			if(startPosition > aCharsAddedToCurrentPDU)
-				{
-				filledChars = FillPduL(aSegmenter, startPosition-aCharsAddedToCurrentPDU, aEncoding);
-				aCharsAddedToCurrentPDU+=filledChars;
-				}
-
-			LOGGSMU2("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: filled %d chars", filledChars);
-
-			if (aCharsAddedToCurrentPDU==startPosition)
-				{
-				// Try adding the IE.
-				if (AddIEToUserDataL(ie, aCharsAlreadyAdded,aCharsAddedToCurrentPDU,aSegmenter))
-					{
-					if(correction)
-					{
-						aCorrectedFormatingIEArray.Remove(0);
-						// aCorrectedFormatingIEArray[0] has been removed. In next loop, ie will point another element. So there is no double free.
-						// coverity[double_free]
-						delete ie;
-						correction=EFalse;
-					}
-					else aCurrEMSIEno++;
-					}
-				else
-					{
-					// Information Element will not fit send PDU
-					LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: ie will not fit send Message");
-					CorrectFormattingL(aCharsAddedToCurrentPDU,aCorrectedFormatingIEArray,aCharsAlreadyAdded);
-
-					aCharsAlreadyAdded += aCharsAddedToCurrentPDU;
-					aCharsAddedToCurrentPDU=0;
-
-					AddCurrentPDUToPDUArrayL(aDoEncode);
-					ResetWorkingPDUL();
-
-					//
-					// Find the encoding method for the next segment...
-					//
-					//aEncoding = ESmsEncodingNone;
-					//TRAP_IGNORE(aEncoding = aSegmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
-					//												                   maxBodyLength));
-					SmsPDU().SetNationalLanguageEncodingL(aEncoding);
-					}
-				}
-			else
-				{
-				// native chars upto start position will not fit send PDu.
-				LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: PDU is filled with chars sending");
-
-				CorrectFormattingL(aCharsAddedToCurrentPDU,aCorrectedFormatingIEArray,aCharsAlreadyAdded);
-
-				aCharsAlreadyAdded += aCharsAddedToCurrentPDU;
-				aCharsAddedToCurrentPDU=0;
-
-				AddCurrentPDUToPDUArrayL(aDoEncode);
-				ResetWorkingPDUL();
-
-				//
-				// Find the encoding method for the next segment...
-				//
-				//aEncoding = ESmsEncodingNone;
-				//TRAP_IGNORE(aEncoding = aSegmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
-				//												                   maxBodyLength));
-				SmsPDU().SetNationalLanguageEncodingL(aEncoding);
-				}
-			}
-		else
-			{
-			aCurrEMSIEno++;
-			}
-		}		// end of while loop for all IEs
-
-	return ETrue;
-	} // CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL
-
-
-/**
- *  Attempts to add EMS IE to the current PDU
- *  
- *  @param aSegmenter
- *  @return TBool whether EMS IEs have been added to segment
- */
-TBool CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL(CSmsEMSBufferSegmenter& aSegmenter,
-																	TSmsEncoding aEncoding)
-	{
-	LOGGSMU1("CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL()");
-
-	TUint charsAddedToCurrentPDU=0;
-	TUint numOfEmsIE=iInformationElementArray->Count();
-	TUint currEmsIEindex=0;
-	CEmsInformationElement* ie = NULL;
-	TUint startPosition=0;
-	TUint filledChars=0;
-
-	while(currEmsIEindex < numOfEmsIE)
-		{
-		ie = (*iInformationElementArray)[currEmsIEindex];
-		startPosition=ie->StartPosition();
-
-		if (startPosition > charsAddedToCurrentPDU)
-			{
-			filledChars = FillPduL(aSegmenter, startPosition-charsAddedToCurrentPDU, aEncoding);
-			charsAddedToCurrentPDU+=filledChars;
-			}
-
-		if (charsAddedToCurrentPDU != startPosition ||
-			!AddIEToUserDataL(ie, 0,charsAddedToCurrentPDU,aSegmenter))
-			{
-			return EFalse;
-			}
-
-		++currEmsIEindex;
-		}
-
-	return ETrue;
-	} // CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL
-
-
-/**
- *  Encode the PDU into an TGsmSms array. The Text and the EMS objects are
- *  laid out with respect to start position locations and encoded into the
- *  correct TGsmSms object.
- *  
- *  @leave KErrUnderflow if the Ems objects are not in Start position order.
- *
- *  @param aSmsArray               Returned array of newly created TSms objects
- *                                 containing the encoded message.
- *  @param aReference              Unique reference number to be given to the
- *                                 TGsmSms objects.
- *  @param aBuffer                 Body Text buffer of the message.
- *  @param aUnconvertedChars       Exit param for the number of characters not converted.
- *  @param aDowngradedChars        Exit param for the number of characters downgraded.
- *  @param aFreeUDUnitsInLastPDU   Exit param for the number of characters free
- *                                 in the last PDU.
- *  @param aDoEncode               Flag indicating if encoding is really wanted,
- *                                 or just the calculation of the number of PDUs.
- */
-void CSmsMessage::EncodeBufferL(CArrayFix<TGsmSms>& aSmsArray, TInt aReference,
-								const CSmsBufferBase& aBuffer,
-								TInt& aUnconvertedChars, TInt& aDowngradedChars,
-						        TInt& aFreeUDUnitsInLastPDU, TBool aDoEncode)
-	{
-	LOGGSMU1("CSmsMessage::EncodeBufferL()");
-
-	aUnconvertedChars     = 0;
-	aDowngradedChars      = 0;
-	aFreeUDUnitsInLastPDU = 0;
-	
-	//
-	// Reset the working array of PDUs...
-	//
-	iAdditionalInfo->SmsPDUArray().ResetAndDestroy();
-
-	TUint currEMSIEno(0);
-	
-	TInt smscIndex(0);
-	TBool smscPresent(EFalse);
-	
-	TInt emailOverallHeaderLength(0);
-	TInt emailIndex(0);
-	TBool emailPresent(EFalse);
-	
-	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
-		{
-		smscPresent=ETrue;
-		}
-	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
-		{
-		emailPresent=ETrue;
-		emailOverallHeaderLength=SmsPDU().UserData().InformationElement(emailIndex).Data()[0];
-		}
-
-	//
-	// Create Array for corrected format elements. These will be elements that
-	// have to be moved into subsequent PDUs due to lack of space in the
-	// current PDU.
-	//
-	RPointerArray<CEmsInformationElement>  correctedFormatingIEArray(2);
-	CleanupResetAndDestroyPushL(correctedFormatingIEArray);
-
-	//
-	// Reset the working PDU. This safes time be keeping fields we need and
-	// droping any data from previous PDUs.
-	//
-	ResetWorkingPDUL();
-
-	//
-	// Automatically prepare for concatenation (any single PDU messages would
-	// have been handled by EncodeIntoSinglePDUL() previously).
-	//
-	SmsPDU().SetTextConcatenatedL(ETrue,iIs16BitConcatenation);
-
-	TInt maxBodyLength=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-
-	//
-	// Add any elements that are required to be present, and ensure they
-	// have correct data stored (for example if we are recycling the working PDU).
-	//
-	AddControlInformationElementsToMultiSegmentMessageL(aDoEncode);
-
-	//
-	// Create EMS Segmenter and Buffer Converter...
-	//
-	CSmsAlphabetConverter*  converter = CSmsAlphabetConverter::NewLC(*iCharacterSetConverter, iFs,SmsPDU().Alphabet(),
-			                                                         BinaryData());
-	CSmsEMSBufferSegmenter*  segmenter = CSmsEMSBufferSegmenter::NewLC(*converter, aBuffer, maxBodyLength);
-	TBool  isUnicode = (SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabetUCS2);
-
-	TBool informationToSend     = ETrue;
-	TUint charsAdded2CurrentPDU = 0;
-	TUint charsAlreadyAdded     = 0;
-
-	//
-	// Find the best alternative encoding for the current segment. This will be
-	// set at the beginning of each PDU using the list of encoders.
-	//
-	TSmsEncoding  encodingToUse = ESmsEncodingNone;
-
-	TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->Alternative7bitEncoding(),
-													                    aBuffer.Length()));
-	SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
-	
-	//
-	// If there are information elements to add, add them to the first PDU (or
-	// to the correct formatting array for later PDUs if more appropriate).
-	//
-	if(iInformationElementArray->Count() >0)
-		{
-		AddEMSInformationElementsToMultiSegmentMessageL(*segmenter, charsAdded2CurrentPDU,
-														aDoEncode, encodingToUse,
-														correctedFormatingIEArray,
-														currEMSIEno, charsAlreadyAdded);
-		}
-
-	//
-	// Allocate a temporary buffer to work with...
-	//
-	HBufC8* buf=HBufC8::NewMaxLC(maxBodyLength);
-	TPtr8 ptr(buf->Des());
-
-	//
-	// While there is still data to encode see how much space is left in this
-	// PDU and attempt to encode something into it...
-	//
-	while (segmenter->MoreL())
-			{
-			LOGGSMU1("CSmsMessage::EncodeBufferL - there is MoreL");
-			
-			//
-			// Calculate the space left to use in this PDU...
-			//
-			TInt size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-			LOGGSMU2("CSmsMessage::EncodeBufferL - remaining size in PDU is %d",size);
-
-			//
-			// While there is no space, correct the formatting (which may
-			// introduce any un-placed EMS Elements into the corrected format
-			// array) and then start a new PDU...
-			//
-			while (size==0)
-				{
-				//
-				// Store any elements not yet placed into the array for later...
-				//
-				CorrectFormattingL(charsAdded2CurrentPDU, correctedFormatingIEArray, charsAlreadyAdded);
-
-				//
-				// Store this PDU, reset the working PDU and get ready to
-				// continue with the next PDU...
-				//
-				aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-				AddCurrentPDUToPDUArrayL(aDoEncode);
-				ResetWorkingPDUL();
-				informationToSend=EFalse;
-				charsAlreadyAdded+=charsAdded2CurrentPDU;
-				charsAdded2CurrentPDU=0;
-
-				//
-				// Find the encoding method for the next segment...
-				//
-				//encodingToUse = ESmsEncodingNone;
-				//TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
-				//												                    maxBodyLength));
-				SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
-
-				//
-				// Add any elements that can be placed now (from previous
-				// PDUs and above)... 
-				//
-				LOGGSMU3("CSmsMessage::EncodeBufferL: IE count  %d corrected  count %d",iInformationElementArray->Count(),correctedFormatingIEArray.Count() );
-				if ((TUint)iInformationElementArray->Count() > currEMSIEno  ||
-					correctedFormatingIEArray.Count() > 0)
-					{
-					AddEMSInformationElementsToMultiSegmentMessageL(*segmenter,charsAdded2CurrentPDU,
-																	aDoEncode, encodingToUse,
-																	correctedFormatingIEArray,
-																	currEMSIEno,charsAlreadyAdded);
-					}
-
-				//
-				// Calculate the space left remaining in this new PDU...
-				//
-				size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-				LOGGSMU2("CSmsMessage::EncodeBufferL - remaining size in PDU is %d",size);
-				}
-			
-			//
-			// We have space in this PDU and no elements to place, so obtain
-			// the next peice of text that can fit and append it.
-			//
-			segmenter->SegmentNextL(ptr, size, aUnconvertedChars, aDowngradedChars, encodingToUse);
-			SmsPDU().UserData().AppendBodyL(ptr);
-
-			TUint charsInSegment= isUnicode ? ptr.Length()/2 : ptr.Length();
-			LOGGSMU2("CSmsMessage::EncodeBufferL: segmenting added %d chars", charsInSegment);
-
-			//
-			// At this point the working PDU is either full (e.g. we filled the
-			// remaining space with a chuck of text, or the is some space as we
-			// stored the last part of the text.
-			//
-			// If there are any elements not yet stored, add them to the
-			// formatting array...
-			//
-			charsAdded2CurrentPDU+=charsInSegment;
-			CorrectFormattingL(charsAdded2CurrentPDU, correctedFormatingIEArray, charsAlreadyAdded);
-			charsAlreadyAdded+=charsAdded2CurrentPDU;
-			LOGGSMU2("CSmsMessage::EncodeBufferL(): charsAlreadyAdded=%d", charsAlreadyAdded);
-			
-			//
-			// Now store this PDU and reset the working PDU...
-			//
-			aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-			AddCurrentPDUToPDUArrayL(aDoEncode);
-			ResetWorkingPDUL();
-			informationToSend=EFalse;
-			charsAdded2CurrentPDU=0;
-			
-			//
-			// Find the encoding method for the next segment...
-			//
-			//encodingToUse = ESmsEncodingNone;
-			//TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
-			//												                    maxBodyLength));
-			SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
-
-			//
-			// Add any elements that can be placed now given we have a new
-			// empty PDU... 
-			//
-			LOGGSMU3("CSmsMessage::EncodeBufferL: IE count  %d corrected  count %d",
-			         iInformationElementArray->Count(), correctedFormatingIEArray.Count() );
-			if ((TUint)iInformationElementArray->Count() > currEMSIEno  ||
-				correctedFormatingIEArray.Count() > 0)
-				{
-				AddEMSInformationElementsToMultiSegmentMessageL(*segmenter, charsAdded2CurrentPDU,
-																aDoEncode, encodingToUse,
-																correctedFormatingIEArray,
-																currEMSIEno, charsAlreadyAdded);
-				}
-			LOGGSMU1("CSmsMessage::EncodeBufferL end Moreloop");
-			}
-	CleanupStack::PopAndDestroy(buf);
-
-	LOGGSMU1("CSmsMessage::EncodeBufferL - last PDU");
-	
-	//
-	// This is the last PDU. We need to check if there is a partial PDU left over
-	// and add it if needed.
-	//
-	if (informationToSend)
-		{
-		aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-		AddCurrentPDUToPDUArrayL(aDoEncode);
-		ResetWorkingPDUL();
-		}
-
-	//
-	// At this point the segmenting and layouts of PDU is complete, so if we
-	// find any more data something is wrong...
-	//
-	if (segmenter->MoreL()  ||  correctedFormatingIEArray.Count() > 0)
-		{
-		User::Leave(KErrCorrupt);
-		}
-
-	CleanupStack::PopAndDestroy(3, &correctedFormatingIEArray); // segmenter, converter & correctedFormatingIEArray
-
-	//
-	// By now the PDUs are segmented and correctly setup for encoding.
-	// They have not been encoded yet, as this requires the PDU total to be known.
-	// So we go through the array setting the final PDU number/total PDUs and
-	// perform the encoding from CSmsPDU to the TGsmPdu object.
-	//
-	// Note: In the case were aDoEncode is EFalse, iSmsPDUArray will be full
-	//       of NULL pointers as it is only the count that we need in that case.
-	//
-	TInt  numPDUs = iAdditionalInfo->SmsPDUArray().Count();
-
-	LOGGSMU2("CSmsMessage::EncodeBufferL number of PDUs: %d", iAdditionalInfo->SmsPDUArray().Count());
-	
-	if (aDoEncode)
-		{
-		CSmsMessageAdditionalAttributes::CSmsStatusReportScheme&  scheme = iAdditionalInfo->GetStatusReportScheme();
-		TGsmSms  gsmSms;
-		
-		for (TInt pdu = 0;  pdu < numPDUs;  pdu++)
-			{
-			if(scheme.Id() == EControlParametersScheme)
-				{
-				if(smscPresent)				
-					{
-					CSmsSMSCCtrlParameterOperations&  ieOp = (CSmsSMSCCtrlParameterOperations&)GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters);
-					TUint8 octet(0);
-
-					if (ieOp.GetStatusReport(pdu, octet) == KErrNone)
-						{					
-						iAdditionalInfo->SmsPDUArray()[pdu]->UpdateSMSCCtrlParameterL(octet);
-						}
-					}
-				else
-					{
-					User::Leave(KErrNotFound);
-					}
-				}
-			else if(scheme.Id() == ETPSRRScheme)
-				{
-				TSmsFirstOctet smsReportRequest;
-				CSmsTPSRROperations& nonIEOp = (CSmsTPSRROperations&)GetOperationsForNonIEL(ESmsTPSRRParameter);
-				smsReportRequest = nonIEOp.GetStatusReport(pdu);
-								
-				iAdditionalInfo->SmsPDUArray()[pdu]->UpdateTPSRRL(smsReportRequest);
-				}
-
-			if(emailPresent)				
-				{
-				iAdditionalInfo->SmsPDUArray()[pdu]->UpdateEmailHeaderDataL(emailOverallHeaderLength);
-				}
-
-			//
-			// Set the concatenation Message Reference number and PDU numbers...
-			//
-			iAdditionalInfo->SmsPDUArray()[pdu]->UpdateConcatenationDataL(aReference, pdu+1, numPDUs);
-
-			//
-			// Encode this PDU...
-			//
-			
-			TEncodeParams encodeParams;
-			encodeParams.iTimeStamp = &Time();
-			
-			TTimeIntervalSeconds interval = UTCOffset();
-			encodeParams.iTimeIntervalInSeconds = &interval;
-						
-			iAdditionalInfo->SmsPDUArray()[pdu]->EncodeMessagePDUL(gsmSms, &encodeParams);
-	 		aSmsArray.AppendL(gsmSms);
-			}
-
-		//
-		// Since the working PDU has been reset the data in it does not match
-		// the data of the last PDU. Some tests in SMS Stack assume it does
-		// and therefore to retain compatibility we decode the last PDU back
-		// over the working PDU.
-		//
-		TGsmuLex8 lex(gsmSms.Pdu());
-		SmsPDU().DecodeL(lex);
-		}
-	} // CSmsMessage::EncodeBufferL
-
-
-/**
- *  Attempts to encode into the single PDU. This function is the private version
- *  to the public EncodeIntoSinglePDUL() function. It performs the work and also
- *  returns more information regarding the characters encoded.
- *  
- *  The Text and the EMS objects are laid out with respect to start position
- *  locations.
- *  
- *  @leave KErrUnderflow if the Ems objects are not in Start position order.
- *
- *  @param aSmsArray               Returned array of newly created TSms objects
- *                                 containing the encoded message.
- *  @param aUnconvertedChars       Exit param for the number of characters not converted.
- *  @param aDowngradedChars        Exit param for the number of characters downgraded.
- *  @param aFreeUDUnitsInLastPDU   Exit param for the number of characters free
- *                                 in the last PDU.
- */
-TBool CSmsMessage::EncodeIntoSinglePDUL(CArrayFix<TGsmSms>& aSmsArray, TInt& aUnconvertedChars,
-		                                TInt& aDowngradedChars, TInt& aFreeUDUnitsInLastPDU)
-	{
-	LOGGSMU1("CSmsMessage::EncodeIntoSinglePDUL()");
-
-	__ASSERT_DEBUG((aSmsArray.Count()==0),Panic(KGsmuPanicSmsArrayNotEmpty));
-
-	aUnconvertedChars     = 0;
-	aDowngradedChars      = 0;
-	aFreeUDUnitsInLastPDU = 0;
-
-	iAdditionalInfo->SmsPDUArray().ResetAndDestroy();
-
-	if (!TextPresent())
-		{
-        if(SmsPDU().Type()==CSmsPDU::ESmsCommand)
-            {
-            // Commands don't contain text, so commands
-            // are only encoded in this branch.
-            PrepareCommandMessageL();
-            }
-
-		TGsmSms sms;
-		SmsPDU().EncodeMessagePDUL(sms);
-		aSmsArray.AppendL(sms);
-		return ETrue;
-		}
-
-	ResetWorkingPDUL();
-
-    // find the length of all the control information elements
-    TUint ieLength=0;
-    for (TUint8 category = 0; category <  TSmsInformationElementCategories::ENumberOfCategories; category++)
-        {
-        switch (category)
-            {
-            case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
-            case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
-            case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
-                {
-                for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
-                    {
-                    ieLength += iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j).Length();
-                    }
-                break;
-                }
-            default:
-                break;
-            }
-        }
-    LOGGSMU2("CSmsMessage::EncodeIntoSinglePDUL, ctrl elem len = %d", ieLength);
-
-	CEmsInformationElement* emsIE =NULL;
-	for (TInt num=0; num<iInformationElementArray->Count();num++)
-		{
-		emsIE = (*iInformationElementArray)[num];
-        ieLength+=emsIE->Length();
-		}
-
-	TInt remainInBody=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining(ieLength);
-
-	TInt msgLength=MessageLengthL(); // in octets
-
-	if( msgLength > remainInBody) return EFalse;
-
-    LOGGSMU4("CSmsMessage::EncodeIntoSinglePDUL, ie len = %d, remainInBody = %d, msgLength = %d", ieLength, msgLength, remainInBody);
-    //  add all control information elements into working PDU.
-    //
-    for (TUint8 category = 0; category <  TSmsInformationElementCategories::ENumberOfCategories; category++)
-        {
-        switch (category)
-            {
-            case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
-            case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
-            case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
-                {
-                for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
-                    {
-                    CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j);
-
-                    CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(informationElement.Identifier(),informationElement.Data());
-                    CleanupStack::PushL(cloneInformationElement);
-                    TBool willFit = SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement);
-                    CleanupStack::PopAndDestroy(cloneInformationElement);
-
-                    if (willFit)
-                        {
-                        SmsPDU().UserData().UpdateInformationElementArrayL(informationElement.Identifier(),informationElement.Data());
-                        }
-                    else
-                        {
-                        ResetWorkingPDUL();
-                        return EFalse;
-                        }
-                    }
-                break;
-                }
-            default:
-                break;
-            }
-        }
-		
-	EncodingTPSRRFromSchemesIntoSinglePDUL();
-
-	TInt maxBodyLength=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
-	CSmsEMSBufferSegmenter* segmenter=CSmsEMSBufferSegmenter::NewLC(*converter,*iBuffer, maxBodyLength);
-
-	//
-	// Find the best alternative encoding for the current segment. This will be
-	// set at the beginning of each PDU using the list of encoders.
-	//
-	TSmsEncoding  encodingToUse = ESmsEncodingNone;
-
-	TRAP_IGNORE(encodingToUse= segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->Alternative7bitEncoding(),
-													                   maxBodyLength));
-	SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
-	
-	if(!AddEMSInformationElementsToSingleSegmentMessageL(*segmenter, encodingToUse))
-		{
-		aSmsArray.Reset();
-		CleanupStack::PopAndDestroy(2, converter);
-		return EFalse;
-		}
-
-	if(segmenter->MoreL())
-			{
-			TInt size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-			// Defensive code to prevent SegmentNextL being called with size of zero
-			if (size == 0)
-				{
-				CleanupStack::PopAndDestroy(2, converter);
-				aSmsArray.Reset();
-				return EFalse;
-				}
-			HBufC8* buf=HBufC8::NewMaxLC(maxBodyLength);
-			TPtr8 ptr(buf->Des());
-			segmenter->SegmentNextL(ptr, size, aUnconvertedChars, aDowngradedChars, encodingToUse);
-			SmsPDU().UserData().AppendBodyL(ptr);
-			CleanupStack::PopAndDestroy(buf);
-			}
-	CorrectFormattingInSinglePDUL();
-
-	if (segmenter->MoreL())
-		{
-		CleanupStack::PopAndDestroy(2, converter);
-		aSmsArray.Reset();
-		return EFalse;
-		}
-	CleanupStack::PopAndDestroy(2, converter);
-
-	aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
-
-	//
-	// Encode the PDU...
-	//
-	TGsmSms  gsmSms;
-		
-	TEncodeParams encodeParams;
-	encodeParams.iTimeStamp = &Time();
-		
-	TTimeIntervalSeconds interval = UTCOffset();
-	encodeParams.iTimeIntervalInSeconds = &interval;
-		
-	SmsPDU().EncodeMessagePDUL(gsmSms, &encodeParams);
-	aSmsArray.AppendL(gsmSms);
-
-	return ETrue;
-	} // CSmsMessage::EncodeIntoSinglePDUL
-
-
-/**
- *  Attempts to encode into the single PDU
- *  The Text and the EMS objects are layed out with respect to start position locations and encoded into the correct Tsms object.
- *  Ensure this function is called before EncodeMessagePDUsL to properly process single PDU messages
- *  
- *  @return KErrUnderflow if the Ems objects are not in Start position order.
- *  @param aSmsArray returned array of newly created TSms objects containing the encoded message
- *  
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::EncodeIntoSinglePDUL(CArrayFix<TGsmSms>& aSmsArray)
-	{
-	LOGGSMU1("CSmsMessage::EncodeIntoSinglePDUL()");
-	
-	TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
-	
-	return EncodeIntoSinglePDUL(aSmsArray, unconvertedChars,
-                                downgradedChars, freeUDUnitsInLastPDU);
-	} // CSmsMessage::EncodeIntoSinglePDUL
-
-
-void CSmsMessage::EncodingTPSRRFromSchemesIntoSinglePDUL()
-	{
-	TInt smscIndex(0);
-	TBool smscPresent(EFalse);
-	
-	CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();	
-	if(scheme.Id() == EControlParametersScheme)
-		{
-		if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
-			{
-			smscPresent=ETrue;
-			}
-		if(smscPresent)				
-			{
-			TUint8 octet(0);
-
-			CSmsSMSCCtrlParameterOperations& ieOp = (CSmsSMSCCtrlParameterOperations&)GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters);
-			
-			if (ieOp.GetStatusReport(0, octet) == KErrNone)
-				{
-				if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
-					{
-					SmsPDU().UserData().InformationElement(smscIndex).Data()[0] = octet;
-					if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
-						{
-						((CSmsSubmit&)SmsPDU()).SetStatusReportRequest(ETrue);	
-						}
-					else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
-						{
-						((CSmsDeliver&)SmsPDU()).SetStatusReportIndication(ETrue);
-						}
-					}
-				else
-					{
-					User::Leave(KErrCorrupt);	
-					}	
-				}
-			}
-		else
-			{
-			User::Leave(KErrNotFound);
-			}	
-		}
-	else if(scheme.Id() == ETPSRRScheme)
-		{
-		TSmsFirstOctet smsReportRequest;
-		CSmsTPSRROperations& nonIEOp = (CSmsTPSRROperations&)GetOperationsForNonIEL(ESmsTPSRRParameter);
-		smsReportRequest = nonIEOp.GetStatusReport(0);
-		
-		if(smsReportRequest>=0)
-			{
-			if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
-				{
-				((CSmsSubmit&)SmsPDU()).SetStatusReportRequest(smsReportRequest);	
-				}
-			else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
-				{
-				((CSmsDeliver&)SmsPDU()).SetStatusReportIndication(smsReportRequest);
-				}	
-			}
-		}	
-	} // CSmsMessage::EncodingTPSRRFromSchemesIntoSinglePDUL
-
-
-/**
- *  Decode CSmsMessage
- *  
- *  @param aUserData Object containing the EMS objects.
- *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
- *  of the UserData.
- */
-void CSmsMessage::DecodeBufferL(CArrayPtr<CSmsPDU>& aSmsPDUArray,
-								CSmsBufferBase& aBuffer)
-	{
-	LOGGSMU1("CSmsMessage::DecodeBufferL()");
-
-	iInformationElementArray->ResetAndDestroy();
-
-	TSmsStatusReportScheme schemeId = FindSchemeL(aSmsPDUArray);
-	
-	TInt emailLen(0);
-	for (TInt i=0; i<aSmsPDUArray.Count(); i++)
-		{
-		CSmsUserData& usrData = (aSmsPDUArray)[i]->UserData();
-		InstallControlInformationElementsL(usrData, i);
-		InstallEmsInformationElementsL(usrData, aBuffer.Length());
-        // Possible refactoring opportunity:
-        // This would be a good place to add a method which provides processing for control information
-        // elements which contain values specific to the pdu (as opposed to being constant in every PDU.
-        InstallEmailHeaderInformationElementL(usrData,emailLen);
-        if(schemeId == ETPSRRScheme)
-        	{
-        	InstallTPSRRInformationL(aSmsPDUArray, i);
-        	}
-        
-		CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,aSmsPDUArray[i]->Alphabet(),BinaryData());
-		TSmsBufferReassembler reassembler(*converter,aBuffer);
-        TSmsEncoding  encodingUsedInSegment = aSmsPDUArray[i]->NationalLanguageEncoding();
-		
-        reassembler.ReassembleNextL(usrData.Body(),
-									encodingUsedInSegment,
-									i==(aSmsPDUArray.Count()-1));
-        
-		CleanupStack::PopAndDestroy(converter);		
-		MergeAlternative7bitEncoding(encodingUsedInSegment);
-		}
-
-    // Possible refactoring opportunity:
-    // This would be a good place to add a method which provides processing for control information
-    // elements which contain values specific to the pdu (as opposed to being constant in every PDU.
-    if(emailLen>0)
-		{
-		if(emailLen>255)
-			User::Leave(KErrTooBig);
-		TBuf8<1> data;
-		data.SetLength(1);
-		data[0]=static_cast<TUint8>(emailLen);
-		TInt emailIndex;
-		if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
-			SmsPDU().UserData().InformationElement(emailIndex).Data()[0]=static_cast<TInt8>(emailLen);
-		else
-			SmsPDU().UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIRFC822EmailHeader,data);
-		}
-	UpdateUserPromptAndODIElementsStartPosition();
-	} // CSmsMessage::DecodeBufferL
-
-/**
- *  It decodes only raw text data.
- *  
- *  @param aSmsPDUArray Object containing PDUs.
- *  @param aBuffer where the decoded data will be stored.
- *
- */
-void CSmsMessage::DecodeOnlyTextL(CArrayPtr<CSmsPDU>& aSmsPDUArray,
-								CSmsBufferBase& aBuffer)
-	{
-	LOGGSMU1("CSmsMessage::DecodeOnlyTextL()");
-
-	for (TInt i=0; i<aSmsPDUArray.Count(); i++)
-		{
-        CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,aSmsPDUArray[i]->Alphabet(),BinaryData());
-        TSmsBufferReassembler reassembler(*converter,aBuffer);
-		TSmsEncoding  encodingUsedInSegment = aSmsPDUArray[i]->NationalLanguageEncoding();
-        
-		reassembler.ReassembleNextL(aSmsPDUArray[i]->UserData().Body(),
-									encodingUsedInSegment,
-									i==(aSmsPDUArray.Count()-1));
-		
-		CleanupStack::PopAndDestroy(converter);
-		MergeAlternative7bitEncoding(encodingUsedInSegment);
-		}
-	} // CSmsMessage::DecodeBufferL
-
-/**
- *  It adds the incomplete message info in additional attribute field.
- *  
- *  @param aStartPDU starting PDU index of incomplete message.
- *  @param aEndPDU end PDU index of incomplete message.
- *  @param aLastPartialCompleteMsg boolean value indicating whether 
- 				this message is the last incomplete message sent to client.
- */
-void CSmsMessage::AddIncompleteMessageInfoL(TInt aStartPDU, TInt aEndPDU, TBool aLastPartialCompleteMsg)
-	{
-	LOGGSMU1("CSmsMessage::AddIncompleteMessageInfoL()");
-
-	CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo&) iAdditionalInfo->GetNonIEOperationL(ESmsIncompleteClass0MessageParameter);
-	incompleteClass0MsgInfo.SetVersion(CIncompleteClass0MessageInfo::ESmsIncompleteClass0MessageV0);
-	incompleteClass0MsgInfo.SetIncompleteMessageInfoL(aStartPDU, aEndPDU, aLastPartialCompleteMsg);
-	}
-
-/**
- *  This method copies control information elements from the user data (passed as an
- *  input argument) into either the CSmsMessage's user data (working pdu) OR one of the
- *  collection of control information elements (sorted by category) which is contained
- *  in CSmsMessage::iAdditionalInfo.
- *  
- *  @param aUserData
- *  The user data which is currently being processed, and whose elements may be copied
- *  into the appropriate collection belonging to the CSmsMessage.
- *  @leave
- *  KErrArgument if an information element's type is unknown
- *  
- *  @internalComponent
- */
-void CSmsMessage::InstallControlInformationElementsL(CSmsUserData& aUserData, TInt aSegmentSequenceNum)
-    {
-	// Installs all the information elements within the subsequent PDUs.
-	LOGGSMU1("CSmsMessage::InstallControlInformationElements()");
-
-    CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();
-    
-	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
-		{
-		const CSmsInformationElement& ie = aUserData.InformationElement(z);
-
-         TSmsInformationElementCategories::TInformationElementCategory category;
-
-        if (TSmsInformationElementCategories::GetCategoryDefinition(ie.Identifier(), category))
-        	{
-            switch (category)
-                {
-                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU: // e.g. Special SMS Message Indication
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements \
-                    ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU id = %d", ie.Identifier());
-
-                    if (ie.Identifier()== CSmsInformationElement::ESmsIEISpecialSMSMessageIndication)
-                        {
-                        TBool found = EFalse;
-                        CArrayFixFlat<TInt>* indices = new(ELeave) CArrayFixFlat<TInt>(4);
-                        CleanupStack::PushL(indices);
-                        SmsPDU().UserData().InformationElementIndicesL(ie.Identifier(), *indices);
-
-                        TInt count = indices->Count();
-		                for (TInt i=0; ((i<count) && (found==EFalse)); i++)
-		                    {
-		                    TUint index = indices->operator[](i);
-		                    CSmsInformationElement& ieAlreadyInWorkingPDU = SmsPDU().UserData().InformationElement(index);
-
-                            if (ieAlreadyInWorkingPDU.Data()[0] == ie.Data()[0])
-                                {
-                                ieAlreadyInWorkingPDU.Data()[1] = ie.Data()[1];
-                                found = ETrue;
-                                break;
-                                }
-		                    }
-                        CleanupStack::PopAndDestroy(indices);
-
-                        if (found == EFalse)
-                            {
-                            SmsPDU().UserData().UpdateInformationElementArrayL(ie.Identifier(),ie.Data());
-                            }
-                        }
-                    else
-                        {
-                        // Unknown category.
-                        LOGGSMU3("CSmsMessage::InstallControlInformationElementsL category = %d, id = %d", category, ie.Identifier());
-                        User::Leave(KErrArgument);
-                        }
-                    break;
-                case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
-                case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
-                    {
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryIn1stPDUOnly "
-                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier());
-
-                    TUint index = 0;
-                    if (iAdditionalInfo->Find1stInstanceOfControlInformationElement(ie.Identifier(), index))
-                        {
-                        iAdditionalInfo->DeleteControlInformationElement(category, index); //  might want to pass the
-                                                                                                //  id in as an additional check
-                                                                                                //  this should be an exception case
-                        CSmsInformationElement* newInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
-
-                    	CleanupStack::PushL(newInformationElement);
-                    	iAdditionalInfo->AddControlInformationElementL(category, newInformationElement);
-                        CleanupStack::Pop(newInformationElement);
-                        }
-                     else
-                        {
-                        CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
-                        CleanupStack::PushL(cloneInformationElement);
-                        iAdditionalInfo->AddControlInformationElementL(category, cloneInformationElement);
-                        CleanupStack::Pop(cloneInformationElement);
-                        }
-                    break;
-                    }
-                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues:
-                    {
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUAndWithIdenticalValues "
-                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier());
-                    TInt index = 0;
-                    if (SmsPDU().UserData().InformationElementIndex(ie.Identifier(),index))
-                        {
-                        CSmsInformationElement* newInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
-
-                    	CleanupStack::PushL(newInformationElement);
-                        CSmsInformationElement*& indexedPDU = SmsPDU().UserData().InformationElementPtr(index);
-                        CSmsInformationElement* oldInformationElement = indexedPDU;
-                        SmsPDU().UserData().InformationElementPtr(index) = newInformationElement;
-						// In next loop, oldInformationElement will point to the newly created information element. So double free is no case.
-						// coverity[double_free]
-                        delete oldInformationElement;
-                        CleanupStack::Pop(newInformationElement);
-                        }
-                    else
-                        {
-                        SmsPDU().UserData().UpdateInformationElementArrayL(ie.Identifier(),ie.Data());
-                        }
-                    break;
-                    }
-
-                case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
-                    {
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUAndWithIdenticalValues "
-                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
-
-                    CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL( ie.Identifier(),ie.Data() );
-                    CleanupStack::PushL(cloneInformationElement);
-                    iAdditionalInfo->AddControlInformationElementL( TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed, cloneInformationElement);
-                    CleanupStack::Pop(cloneInformationElement);
-                    break;
-                    }
-                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU:
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU "
-                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
-                    
-                    if (ie.Identifier() == CSmsInformationElement::ESmsIEISMSCControlParameters)
-                    	{
-                       	if(scheme.Id() == EControlParametersScheme)
-                    		{
-                    		CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
-                    		ctrlParamScheme.iDefaultStatusReport = 0x00;
-                    		
-	                       	const TUint8* octet(0);
-	                    	octet = ie.Data().Ptr();
-	                    	if(*octet)
-                    			{
-                    			CSmsMessageAdditionalAttributes::CControlParametersScheme::TSmsSMSCCtrlParameterStatus smscCtrlParameterStatus;
-								smscCtrlParameterStatus.iSegmentSequenceNum = aSegmentSequenceNum;
-								smscCtrlParameterStatus.iSelectiveStatus = *octet;
-								(ctrlParamScheme.iControlParametersStatusReport).AppendL(smscCtrlParameterStatus);
-                    			}
-                    		ctrlParamScheme.iNumOfPDUs++;
-	                    	}
-	                    }
-                
-                    // e.g  Email Header / Concatenation Elements.
-                    // Consider whether EMail Header should be ported here.
-                    // or left as is.
-                    break;
-                case  TSmsInformationElementCategories::EEmsInformationElement:
-                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU "
-                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
-                    // Will be handled in the method InstallEmsInformationElements, nothing to do here
-                    break;
-                default:
-                    LOGGSMU3("CSmsMessage::InstallControlInformationElementsToMultiSegmentMessageL, default switch, category = %d, id= %d", category, ie.Identifier() );
-                    break;
-                }
-            }
-    	}
-    } // CSmsMessage::InstallControlInformationElementsL
-
-
-/**
- *  Extracts all the EMS information objects out of the given UserData into the CSmsMessage IEArray.
- *  
- *  @param aUserData Object containing the EMS objects.
- *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
- *  of the UserData.
- */
-void  CSmsMessage::InstallEmsInformationElementsL(CSmsUserData& aUserData, TInt aCharsAlreadyAdded)
-	{
-	// Installs all the information elements within the subsequent PDUs.
-	LOGGSMU1("CSmsMessage::InstallEmsInformationElements()");
-
-	CSmsInformationElement::TSmsInformationElementIdentifier id;
-	CEmsInformationElement* newIE =NULL;
-
-	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
-		{
-		const CSmsInformationElement& ie = aUserData.InformationElement(z);
-
-		// is the ie an EMS information Element;
-		id = ie.Identifier();
-		if (CEmsFactory::Supported(id))
-			{
-			newIE=NULL;
-			TRAPD(ret,newIE = CEmsFactory::CreateReceivedEmsIEL(ie,aCharsAlreadyAdded));
-			if(newIE != NULL)
-				{
-				if(ret == KErrNone)
-					{
-					ret=AddReceivedEmsInformationElement(newIE);
-					if(ret==KErrNone)  // Remove the Information Element from the User Data.
-						aUserData.RemoveInformationElement(z--);
-					else
-						// newIE is made NULL in first place and then a new IE is created. so double free is no case
-						// coverity[double_free]
-						delete newIE;
-					}
-				else
-					delete newIE;
-				}
-			}
-		}
-	} // CSmsMessage::InstallEmsInformationElementsL
-
-
-/**
- *  Extracts all the EMS information objects out of the given Command into the CSmsMessage IEArray.
- *  
- *  @param aCommand Object containing the EMS objects.
- *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
- *  of the UserData.
- */
-void  CSmsMessage::InstallEmsInformationElementsL(CSmsCommand& aCommand, TInt aCharsAlreadyAdded)
-    {
-    // Ignore in code coverage - not used in SMS stack and not exported
-    // but cannot be removed as impacts public header.
-    BULLSEYE_OFF    
-    // Installs all the information elements within the subsequent PDUs.
-    LOGGSMU1("CSmsMessage::InstallEmsInformationElements()");
-    
-    CSmsInformationElement::TSmsInformationElementIdentifier id;
-    CEmsInformationElement* newIE=NULL;
-    
-    for (TInt z=0; z<aCommand.NumInformationElements(); z++)
-        {
-        const CSmsInformationElement& ie = aCommand.InformationElement(z);
-        // is the ie an EMS information Element;
-        id = ie.Identifier();
-        if (CEmsFactory::Supported(id))
-            {
-            newIE=NULL;
-            TRAPD(ret,newIE = CEmsFactory::CreateReceivedEmsIEL(ie,aCharsAlreadyAdded));
-            if(newIE != NULL )
-                {
-                    if(ret == KErrNone)
-                    {
-                        ret=AddReceivedEmsInformationElement(newIE);
-                        if(ret==KErrNone)  // Remove the Information Element from the User Data.
-                            aCommand.RemoveInformationElement(z--);
-                        else
-                            // newIE is made NULL in first place and then a new IE is created. so double free is no case.
-                            // coverity[double_free]
-                            delete newIE;
-                    }
-                    else
-                        delete newIE;
-                }
-            }
-        }
-    BULLSEYE_RESTORE
-    }
-
-TSmsStatusReportScheme CSmsMessage::FindSchemeL(const CArrayPtr<CSmsPDU>& aSmsPDUArray)
-	{
-	TInt smscIndex(0);
-	
-	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
-		{
-		iAdditionalInfo->SetStatusReportSchemeL(EControlParametersScheme);
-		return EControlParametersScheme;
-		}
-		
-	TSmsFirstOctet oldTpsrr;
-	TSmsFirstOctet tpsrr;
-	CSmsSubmit* smsSubmit;
-	CSmsDeliver* smsDeliver;
-	
-	if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
-		{
-		smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[0]);
-		oldTpsrr = smsSubmit->StatusReportRequest();
-		}
-	else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
-		{
-		smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[0]);
-		oldTpsrr = smsDeliver->StatusReportIndication();
-		}
-		
-	for (TInt ii=1; ii<aSmsPDUArray.Count(); ii++)
-		{
-		if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
-			{
-			smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[ii]);
-			tpsrr = smsSubmit->StatusReportRequest();
-			}
-		else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
-			{
-			smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[ii]);
-			tpsrr = smsDeliver->StatusReportIndication();
-			}
-		if(tpsrr != oldTpsrr)
-			{
-			iAdditionalInfo->SetStatusReportSchemeL(ETPSRRScheme);
-			return ETPSRRScheme;
-			}
-		}
-	
-	iAdditionalInfo->SetStatusReportSchemeL(EDefaultScheme);
-
-	return EDefaultScheme;
-	} // CSmsMessage::FindSchemeL
-
-	
-void CSmsMessage::InstallTPSRRInformationL(const CArrayPtr<CSmsPDU>& aSmsPDUArray, TInt aSegmentSequenceNum)
-	{
-    CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();
-    CSmsMessageAdditionalAttributes::CTPSRRScheme& tpsrrScheme = (CSmsMessageAdditionalAttributes::CTPSRRScheme&)scheme;
-    
-    tpsrrScheme.iDefaultStatusReport = TSmsFirstOctet::ESmsStatusReportNotRequested;
-    tpsrrScheme.iNumOfPDUs++;
-    
-    TSmsFirstOctet tpsrr;
-    
-    if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
-		{
-		CSmsSubmit* smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[aSegmentSequenceNum]);
-		tpsrr = smsSubmit->StatusReportRequest();
-		}
-	else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
-		{
-		CSmsDeliver* smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[aSegmentSequenceNum]);
-		tpsrr = smsDeliver->StatusReportIndication();
-		}
-    
-    if(tpsrr)
-    	{
-    	CSmsMessageAdditionalAttributes::CTPSRRScheme::TSmsTPSRRStatus tpsrrStatus;
-
-    	tpsrrStatus.iSegmentSequenceNum = aSegmentSequenceNum;
-		tpsrrStatus.iTPSRRStatus = TSmsFirstOctet::ESmsStatusReportRequested;
-		tpsrrScheme.iTPSRRStatusReport.AppendL(tpsrrStatus);	
-    	}
-	} // CSmsMessage::InstallTPSRRInformationL
-
-
-/**
- *  Adds EMS IE to a CSmsMessage
- *  
- *  @param aEmsIE EMS object to be added.
- *  
- *  @capability None
- */
-EXPORT_C void CSmsMessage::AddEMSInformationElementL(const CEmsInformationElement& aEmsIE)
-	{
-	LOGGSMU1("CSmsMessage::AddEMSInformationElementL()");
-
-	if(aEmsIE.StartPosition() > (TUint)iBuffer->Length())
-		{
-		User::Leave(KErrOverflow);
-		}
-
-	if(CSmsInformationElement::ESmsEnhancedTextFormatting == aEmsIE.Identifier() && aEmsIE.Length() ==0)
-		{
-		User::Leave(KErrUnderflow);
-		}
-
-	if(CSmsInformationElement::ESmsEnhancedUserPromptIndicator == aEmsIE.Identifier())
-		{
-		AddEmsUserPromptL(static_cast<const CEmsUserPrompt&>(aEmsIE));
-		}
-	else if(CSmsInformationElement::ESmsEnhancedODI == aEmsIE.Identifier())
-		{
-		AddEmsObjectDistributionL(static_cast<const CEmsObjectDistribution&>(aEmsIE));
-		}
-	else
-		{
-		TInt count=iInformationElementArray->Count();
-		TInt currNo=0;
-		const CEmsInformationElement* emsIE=NULL;
-
-		while(currNo < count)
-		{
-			emsIE=(*iInformationElementArray)[currNo];
-			if(emsIE->StartPosition() == aEmsIE.StartPosition() && (CSmsInformationElement::ESmsEnhancedUserPromptIndicator == emsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI == emsIE->Identifier()))
-				User::Leave(KErrArgument);
-			else if(emsIE->StartPosition() > aEmsIE.StartPosition())
-				break;
-			currNo++;
-		}
-		User::LeaveIfError(iInformationElementArray->Insert(aEmsIE.DuplicateL(),currNo));
-		}
-	} // CSmsMessage::AddEMSInformationElementL
-
-
-TBool CSmsMessage::CanBeRemoved(const CEmsInformationElement& aIE, const TUint aIEIndex)
-	{
-	LOGGSMU1("CSmsMessage::CanBeRemoved()");
-
-	TBool ret=ETrue;
-	if(CSmsInformationElement::ESmsEnhancedODI == aIE.Identifier())
-		return ret;
-
-	TUint ieStartPosition=aIE.StartPosition();
-	TUint count=iInformationElementArray->Count();
-	CEmsInformationElement* ie=NULL;
-
-	// is there a UserPrompt/ODI at the same position
-	for (TUint i=0; i < count && ret; ++i)
-		{
-		ie = (*iInformationElementArray)[i];
-		// Do not allow removal if start position matches a user prompt and it is not the user prompt itself being removed
-		if (ie->StartPosition() == ieStartPosition && ie->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator && aIE.Identifier() != CSmsInformationElement::ESmsEnhancedUserPromptIndicator)
-		    ret=EFalse;
-		if (ie->Identifier() == CSmsInformationElement::ESmsEnhancedODI)
-		    {
-		    // don't allow removal of IE if position inside object count of ODI
-		    if ((static_cast<CEmsObjectDistribution*>(ie)->ObjectCount()+i) >= aIEIndex || static_cast<CEmsObjectDistribution*>(ie)->ObjectCount() == 0)
-		        ret=EFalse;
-		    }
-		}
-
-	LOGGSMU2("CSmsMessage::CanBeRemoved() returns %d", ret);
-
-	return ret;
-	} // CSmsMessage::CanBeRemoved
-
-
-/**
- *  Adds EMS IE to a CSmsMessage
- *  
- *  @param aEmsIE EMS object to be added.
- */
-void CSmsMessage::AddEmsUserPromptL(const CEmsUserPrompt& aUserPromptIE)
-	{
-	LOGGSMU1("CSmsMessage::AddEmsUserPromptL()");
-
-		if(aUserPromptIE.ObjectCount() == 0 )User::Leave(KErrArgument);
-
-		TUint count=iInformationElementArray->Count();
-		TUint userPromptStartPosition=aUserPromptIE.StartPosition();
-
-		TSmsId id=aUserPromptIE.Identifier();
-		TBool allSameType=ETrue;
-		TUint countOnTheSamePos=0;
-		TUint firstIndex=0;
-
-		// collect all IEs on the same startPosition as the new User Prompt
-		CEmsInformationElement* ie=NULL;
-
-		for (TUint i=0; i < count ; i++)
-		{
-			ie = (*iInformationElementArray)[i];
-			if (ie->StartPosition() == userPromptStartPosition)
-			{
-				if(countOnTheSamePos==0)
-				{
-					firstIndex=i;
-					id = ie->Identifier();
-				}
-				else
-				{
-					if(allSameType && id != ie->Identifier())allSameType=EFalse;
-					else id = ie->Identifier();
-				}
-				++countOnTheSamePos;
-			}
-		}
-
-		if(countOnTheSamePos != aUserPromptIE.ObjectCount())
-			User::Leave(KErrArgument);
-
-
-	if( countOnTheSamePos == 1)
-	{
-		switch(id)
-		{
-		case CEmsInformationElement::ESmsEnhancedPredefinedAnimation:
-		case CEmsInformationElement::ESmsEnhancedLargeAnimation :
-		case CEmsInformationElement::ESmsEnhancedSmallAnimation	:
-		case CEmsInformationElement::ESmsEnhancedUserDefinedSound:
-		case CEmsInformationElement::ESmsEnhancedLargePicture:
-		case CEmsInformationElement::ESmsEnhancedSmallPicture:
-		case CEmsInformationElement::ESmsEnhancedVariablePicture:
-		User::LeaveIfError(iInformationElementArray->Insert(aUserPromptIE.DuplicateL(),firstIndex));
-			break;
-		default:
-		User::Leave(KErrCorrupt);
-			break;
-		}
-		return;
-	}
-
-	// stitching - more than one object
-	if(allSameType  && (id == CEmsInformationElement::ESmsEnhancedUserDefinedSound || id == CEmsInformationElement::ESmsEnhancedLargePicture || id == CEmsInformationElement::ESmsEnhancedSmallPicture || id == CEmsInformationElement::ESmsEnhancedVariablePicture))
-		{
-		User::LeaveIfError(iInformationElementArray->Insert(aUserPromptIE.DuplicateL(),firstIndex));
-		return;
-		}
-
-    //  not of the same type or not supported IE types
-	User::Leave(KErrCorrupt);
-	} // CSmsMessage::AddEmsUserPromptL
-
-
-/**
- *  Adds EMS IE to a CSmsMessage
- *  
- *  @param aEmsIE EMS object to be added.
- */
-void CSmsMessage::AddEmsObjectDistributionL(const CEmsObjectDistribution& aObjectDistributionIE)
-    {
-	LOGGSMU1("CSmsMessage::AddEmsObjectDistributionL()");
-
-    TUint count=iInformationElementArray->Count();
-    TUint objectDistributionStartPosition=aObjectDistributionIE.StartPosition();
-
-    TBool firstIndexFound=EFalse;
-    TUint firstIndex=0;
-    TUint countOnSameOrSubsequentPos=0;
-
-    // collect any IEs on the same or greater startPosition as the new Object Distribution Indicator
-    CEmsInformationElement* ie=NULL;
-
-    for (TUint i=0; i < count; i++)
-        {
-        ie = (*iInformationElementArray)[i];
-        if (ie->StartPosition() >= objectDistributionStartPosition)
-            {
-            // Only set index if at least one IE found at desired start position
-            if (!firstIndexFound)
-                {
-                firstIndex=i;
-                firstIndexFound=ETrue;
-                }
-            ++countOnSameOrSubsequentPos;
-            }
-        }
-    // check number of IEs present for desired ObjectCount
-    if(countOnSameOrSubsequentPos < aObjectDistributionIE.ObjectCount())
-        User::Leave(KErrArgument);
-
-    if (firstIndexFound)
-        {
-        User::LeaveIfError(iInformationElementArray->Insert(aObjectDistributionIE.DuplicateL(),firstIndex));
-        return;
-        }
-
-    //  no valid IE for ODI to apply to
-    User::Leave(KErrCorrupt);
-    } // CSmsMessage::AddEmsObjectDistributionL
-
-
-/**
- *  Removes first EMS IE that matches the criteria from the CSmsMessage
- *  
- *  @param aStartPosition of a EMS object to be removed.
- *  @param aEmsId type of a EMS object to be removed
- *  @return pointer EMS information element
- *  @capability
- *  @capability None
- */
-EXPORT_C CEmsInformationElement* CSmsMessage::RemoveEMSInformationElementL(const TUint aStartPosition,const TSmsId aEmsId)
-	{
-	LOGGSMU1("CSmsMessage::RemoveEMSInformationElementL()");
-
-	CEmsInformationElement* emsIE=NULL;
-	CEmsInformationElement* ie=NULL;
-
-	TUint count=iInformationElementArray->Count();
-
-	for (TInt i=--count; i >=0 ; --i)
-		{
-		ie = (*iInformationElementArray)[i];
-		if (ie->StartPosition() == aStartPosition && ie->Identifier() == aEmsId)
-			{
-				if(CanBeRemoved(*ie, i))
-				{
-					iInformationElementArray->Remove(i);
-					emsIE=ie;
-				}
-				else
-					emsIE=NULL;
-				break;
-			}
-
-		}
-	return emsIE;
-	} // CSmsMessage::RemoveEMSInformationElementL
-
-
-/**
- *  Removes all EMS IEs that matches the criteria from the CSmsMessage
- *  
- *  @param aStartPosition of a EMS object to be removed.
- *  @param aEmsId type of a EMS object to be removed
- *  @return pointer to array of EMS IE
- *  
- *  @capability None
- */
-EXPORT_C RPointerArray<CEmsInformationElement>* CSmsMessage::RemoveEMSInformationElementsL(const TUint aStartPosition,const TSmsId aEmsId)
-	{
-	LOGGSMU1("CSmsMessage::RemoveEMSInformationElementsL()");
-
-	CEmsInformationElement* ie=NULL;
-	RPointerArray<CEmsInformationElement>* selectedIEs = NULL;
-	TUint count=iInformationElementArray->Count();
-
-	for (TInt i=--count; i >= 0 ; --i)
-		{
-		ie = (*iInformationElementArray)[i];
-		if (ie->StartPosition() == aStartPosition && ie->Identifier() == aEmsId)
-			{
-				if(CanBeRemoved(*ie, i))
-				{
-					if(selectedIEs == NULL)selectedIEs=new (ELeave) RPointerArray<CEmsInformationElement>(8);
-					iInformationElementArray->Remove(i);
-					selectedIEs->Append(ie);
-				}
-			}
-
-		}
-	return selectedIEs;
-	} // CSmsMessage::RemoveEMSInformationElementsL
-
-/**
- *  Resets EMS IE from a CSmsMessage
- *  
- *  
- *  @capability None
- */
-EXPORT_C void  CSmsMessage::ResetEMSL()
-	{
-	LOGGSMU1("CSmsMessage::ResetEMSL()");
-
-	iInformationElementArray->ResetAndDestroy();
-	} // CSmsMessage::ResetEMSL
-
-/**
- *  Removes EMS IE from a CSmsMessage
- *  
- *  @return CArrayPtrFlat<const CEmsInformationElement>& of internal EMS array
- *  
- *  @capability None
- */
-EXPORT_C const RPointerArray<const CEmsInformationElement>& CSmsMessage::GetEMSInformationElementsL()const
-	{
-	LOGGSMU1("CSmsMessage::GetEMSInformationElementsL()");
-
-	 return (const RPointerArray<const CEmsInformationElement>&)(*iInformationElementArray);
-	} // CSmsMessage::GetEMSInformationElementsL
-
-
-void CSmsMessage::UpdateUserPromptAndODIElementsStartPosition()
-	{
-	LOGGSMU1("CSmsMessage::UpdateUserPromptAndODIElementsStartPosition()");
-
-		TUint num=iInformationElementArray->Count();
-		TInt startPosition=-1;
-		CEmsInformationElement* ie = NULL;
-
-
-		// is the ie an EMS information Element;
-
-		for(TInt i=num-1;i >=0; --i)
-		{
-			ie = (*iInformationElementArray)[i];
-			if(ie->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator || ie->Identifier() == CSmsInformationElement::ESmsEnhancedODI)
-			{
-				if(startPosition >=0)
-					ie->SetStartPosition(startPosition);
-				else
-					iInformationElementArray->Remove(i);
-			}
-			else
-				startPosition=ie->StartPosition();
-
-		}
-	} // CSmsMessage::UpdateUserPromptAndODIElementsStartPosition
-
-
-TInt CSmsMessage::AddReceivedEmsInformationElement(CEmsInformationElement* aEmsIE)
-	{
-	LOGGSMU1("CSmsMessage::AddReceivedEmsInformationElement()");
-
-	TInt ret=KErrNone;
-	if(CSmsInformationElement::ESmsEnhancedUserPromptIndicator == aEmsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI == aEmsIE->Identifier())
-		ret=iInformationElementArray->Append(aEmsIE);
-	else
-		{
-			TInt count=iInformationElementArray->Count();
-			TInt currNo=0;
-			const CEmsInformationElement* emsIE=NULL;
-			while(currNo < count)
-			{
-				emsIE=(*iInformationElementArray)[currNo];
-				if(emsIE->StartPosition() > aEmsIE->StartPosition() && (CSmsInformationElement::ESmsEnhancedUserPromptIndicator != emsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI != emsIE->Identifier()))
-					break;
-				currNo++;
-			}
-			ret=iInformationElementArray->Insert(aEmsIE,currNo);
-		}
-	return ret;
-	} // CSmsMessage::AddReceivedEmsInformationElement
-
-
-/**
- *  Updates the slot information for the given message as described in the supplied buffer
- *  
- *  @param aDesc buffer, layout: byte 0 store id, byte 1..n PDU slot indexes
- *  @leave KErrArgument
- *  
- *  @capability None
- */
-EXPORT_C void CSmsMessage::UpdateSlotsL(TDesC8& aDesc)
-    {
-	LOGGSMU1("CSmsMessage::UpdateSlotsL()");
-
-    TGsmSmsSlotEntry newSlot;
-
-    switch (aDesc[0])
-        {
-        case CSmsMessage::ESmsSIMStorage:
-            {
-            newSlot.iStore = KETelIccSmsStore;
-            break;
-            }
-        case CSmsMessage::ESmsPhoneStorage:
-            {
-            newSlot.iStore = KETelMeSmsStore;
-            break;
-            }
-        case CSmsMessage::ESmsCombinedStorage:
-            {
-            newSlot.iStore = KETelCombinedSmsStore;
-            break;
-            }
-        default:
-            User::Leave(KErrArgument);
-        }
-
-    for (TInt index = 1; index < aDesc.Size(); index++)
-        {
-        newSlot.iIndex = aDesc[index]; // point to PDU indexes
-        iSlotArray.AppendL(newSlot);
-        }
-    } // CSmsMessage::UpdateSlotsL
-
-/**
- *  Copy EMS elements to dest CSmsMessage
- *  Uses CSmsMessage extended EMS API
- *  Creates new CEmsInformationElement instance(s) and passes ownership to the dest CSmsMessage
- *  
- *  @return aToMessage  - Destination CSmsMessage
- *  
- *  @capability None
- */
-EXPORT_C void CSmsMessage::CopyEmsElementsL(CSmsMessage& aToMessage) const
-	{
-	LOGGSMU1("CSmsMessage::CopyEmsElementsL()");
-
-	// CSmsMessage extended EMS API method creates array of references to EMS elements in
-	// the source message
-	// Loop through the array copying each individual method using the CSmsMessage
-	// and CEmsInformationElement API's
-	CEmsInformationElement* dupl=NULL;
-	aToMessage.ResetEMSL();
-	for(TInt i = iInformationElementArray->Count()-1 ; i >=0; --i)
-		{
-		dupl = (*iInformationElementArray)[i]->DuplicateL();
-		CleanupStack::PushL(dupl);
-		aToMessage.AddEMSInformationElementL(*dupl);
-		CleanupStack::PopAndDestroy(dupl);
-		}
-	} // CSmsMessage::CopyEmsElementsL
-
-/**
- *  @capability None
- */
-EXPORT_C void CSmsMessage::AddSlotL(const TGsmSmsSlotEntry& aSlot)
-	{
-	LOGGSMU1("CSmsMessage::AddSlotL()");
-
-		TInt count = iSlotArray.Count();
-		TInt i(0);
-		TBool found(EFalse);
-		while(!found && i<count)
-		{
-			if(aSlot.iIndex == iSlotArray[i].iIndex)found=ETrue;
-			else ++i;
-		}
-		LOGGSMU3("CSmsMessage::AddSlotL current no in: %d, adds index %d", count,aSlot.iIndex );
-		LOGGSMU3("found %d at position %d",found,i);
-		iSlotArray.AppendL(aSlot);
-	} // CSmsMessage::AddSlotL
-
-/**
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::MatchSlots(const CArrayFixFlat<TGsmSmsSlotEntry>& aSlotArray)
-	{
-	LOGGSMU1("CSmsMessage::MatchSlots()");
-
-		TBool match = EFalse;
-		TInt count = aSlotArray.Count();
-		if(iSlotArray.Count() == count)
-		{
-			TInt i = 0;
-			match = ETrue;
-			while(match && i < count)
-				{
-				const TGsmSmsSlotEntry& newSlot=aSlotArray[i];
-				const TGsmSmsSlotEntry& slot =iSlotArray[i];
-				if ( ( slot.iIndex != newSlot.iIndex ) || ( slot.iStore != newSlot.iStore ) )
-						match = EFalse;
-				i++;
-				}
-
-		}
-		return match;
-	} // CSmsMessage::MatchSlots
-
-/**
- *  c'tor
- *  @capability None
- */
-EXPORT_C TGsmSmsSlotEntry::TGsmSmsSlotEntry()
-	{
-	} // TGsmSmsSlotEntry::TGsmSmsSlotEntry
-
-/**
- *  Internalize
- *  
- *  @param aStream For internalizing the data
- */
-void TGsmSmsSlotEntry::InternalizeL(RReadStream& aStream)
-	{
-	aStream >> iStore;
-	iIndex=aStream.ReadInt32L();
-	} // TGsmSmsSlotEntry::InternalizeL
-
-/**
- *  Externalize
- *  
- *  @param aStream For Externalizing the data
- */
-void TGsmSmsSlotEntry::ExternalizeL(RWriteStream& aStream) const
-	{
-	aStream << iStore;
-	aStream.WriteInt32L(iIndex);
-	} // TGsmSmsSlotEntry::ExternalizeL
-
- /**
-  *  Extracts all RFC 822 Email header information objects out of the given UserData into the CSmsMessage's iSmsEmailHeaderLength.
-  *  
-  *  @param aUserData Object containing the EmailHeader information element.
-  *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
-  *  of the UserData.
-  */
-void  CSmsMessage::InstallEmailHeaderInformationElementL(CSmsUserData& aUserData,TInt& aHeaderLength)
- 	{
- 	// Installs all the information elements within the subsequent PDUs.
- 	LOGGSMU1("CSmsMessage::InstallEmailHeaderInformationElementL()");
-
- 	CSmsInformationElement::TSmsInformationElementIdentifier id;
-
- 	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
- 		{
- 		const CSmsInformationElement& ie = aUserData.InformationElement(z);
- 		id = (CSmsInformationElement::TSmsInformationElementIdentifier)ie.Identifier();
- 		if (id == CSmsInformationElement::ESmsIEIRFC822EmailHeader)
- 			{
- 				const TDesC8& des = ie.Data();
- 				aHeaderLength+=des[0];
- 			}
- 		}
- 	} // CSmsMessage::InstallEmailHeaderInformationElementL
-
-/**
- *  Extracts all RFC 822 Email header information objects out of the given UserData into the CSmsMessage's iSmsEmailHeaderLength.
- *  
- *  @param aCommand Object containing the EmailHeader information element.
- *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
- *  of the UserData.
- */
-void CSmsMessage::InstallEmailHeaderInformationElementL(CSmsCommand& aCommand,TInt& aHeaderLength)
-    {
-    // Ignore in code coverage - not used in SMS stack and not exported
-    // but cannot be removed as impacts public header.
-    BULLSEYE_OFF    
-    // Installs all the information elements within the subsequent PDUs.
-    LOGGSMU1("CSmsMessage::InstallEmailHeaderInformationElementL()");
-    
-    CSmsInformationElement::TSmsInformationElementIdentifier id;
-    
-    for (TInt z=0; z<aCommand.NumInformationElements(); z++)
-        {
-        const CSmsInformationElement& ie = aCommand.InformationElement(z);
-        id = (CSmsInformationElement::TSmsInformationElementIdentifier)ie.Identifier();
-        if (id == CSmsInformationElement::ESmsIEIRFC822EmailHeader)
-            {
-            const TDesC8& des = ie.Data();
-            aHeaderLength+=des[0];
-            }
-        }
-    BULLSEYE_RESTORE
-    }
-
-// E-mail header methods
-
-/**
- *  Adds a header to an email body
- *  
- *  @param aEMailBody The buffer to which the header gets appended
- *  @param aEmailHeader The buffer which holds RFC 822 e-mail header
- *  @publishedAll
- *  @released
- *  
- *  @capability None
- */
-EXPORT_C void CSmsMessage::AddEmailHeaderL(const TDesC& aEmailHeader, const TDesC& aEmailBody)
- 	{
- 	LOGGSMU1("CSmsMessage::AddEmailHeaderL()");
-
- 	if(IsEmailHeader())
- 		User::Leave(KErrAlreadyExists);
-
- 	TInt len =aEmailHeader.Length();
- 	if(len <= 0)
- 		User::Leave(KErrCorrupt);
-
-	if(len >= 255 )
- 		User::Leave(KErrTooBig);
-
-
-	if(SmsPDU().UserData().NumInformationElements())
-		{
-		TBool is16bit = EFalse;
-		TBool concatenationIEPresent= SmsPDU().TextConcatenated( &is16bit );
-		if(concatenationIEPresent)
-			{
-			if(SmsPDU().UserData().NumInformationElements() >=2) // something more than concat IE
-				User::Leave(KErrAccessDenied);
-			}
-		else
-			User::Leave(KErrAccessDenied);
-		}
-
-
-	TBuf8<1> data;
-	data.SetLength(1);
-	data[0]=static_cast<TUint8>(len);
-	SmsPDU().UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIRFC822EmailHeader,data);
-
- 	iBuffer->Reset();
- 	iBuffer->InsertL(0,aEmailHeader);
- 	iBuffer->InsertL(iBuffer->Length(),aEmailBody);
- 	} // CSmsMessage::AddEmailHeaderL
-
- /**
-  *  Checks whether the SmsMessage contains an e-mail.
-  *  
-  *  @return ETrue if CSmsMessage contains e-mail ( e-mail header information element), otherwise EFalse
-  *  @publishedAll
-  *  @released
-  *  
-  *  @capability None
-  */
-EXPORT_C TBool CSmsMessage::IsEmailHeader() const
- 	{
- 	LOGGSMU1("CSmsMessage::IsEmailHeader()");
-
-	TInt emailIndex;
-	return SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex);
- 	} // CSmsMessage::IsEmailHeader
-
- /**
-  *  Extracts e-mail header and body from the SmsMessage
-  *  
-  *  @return aEMailHeader The buffer containing the extracted email header
-  *  @return aEMailBody The buffer containing the extracted email body
-  *  @return ETrue if extraction of e-mail header and body succeeds
-  *  @publishedAll
-  *  @released
-  *  
-  *  @capability None
-  */
-EXPORT_C TBool CSmsMessage::GetEmailHeaderL(HBufC** aEmailHeader,HBufC** aEmailBody)
- 	{
- 	LOGGSMU1("CSmsMessage::GetEmailHeaderL()");
-
- 	if(IsEmailHeader())
- 		{
- 			TInt bufLen=iBuffer->Length();
- 			TInt emailHeaderLen(0);
-			TInt emailIndex(0);
-			if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
-				emailHeaderLen=SmsPDU().UserData().InformationElement(emailIndex).Data()[0];
-			else
-				User::Leave(KErrCorrupt);
-
- 			TInt emailBodyLen=bufLen-emailHeaderLen;
-
- 			if(emailBodyLen<0)
- 				return EFalse;
-
- 			*aEmailHeader=HBufC::NewL(emailHeaderLen);
- 			CleanupStack::PushL(*aEmailHeader);
-
- 			*aEmailBody=HBufC::NewL(emailBodyLen);
- 			CleanupStack::PushL(*aEmailBody);
-
- 			TPtr headerPtr((*aEmailHeader)->Des());
- 			iBuffer->Extract(headerPtr,0,emailHeaderLen);
-
- 			TPtr bodyPtr((*aEmailBody)->Des());
- 			iBuffer->Extract(bodyPtr,emailHeaderLen,emailBodyLen);
-
- 			CleanupStack::Pop(2);
- 			return ETrue;
- 		}
- 	return EFalse;
- 	} // CSmsMessage::GetEmailHeaderL
-
-
- /**
-  *  Extracts the offset between universal time and local time in seconds.
-  *  If the value is > 0, local time is ahead of universal time.
-  *  If the value is < 0, local time is behind universal time.
-  *  
-  *  @return TTTimeIntervalSeconds The time zone offset in seconds.
-  *  @publishedAll
-  *  @capability None
-  */
-EXPORT_C TTimeIntervalSeconds CSmsMessage::UTCOffset() const
-    {
-    LOGGSMU1("CSmsMessage::UTCOffset()");
-
-    TUint timeZoneOffset = ((iFlags & ESmsUTCOffsetSecondGranularityMask) >> ESecondBitOffset);
-
-    if (iFlags & ESmsUTCOffsetSignBit)
-        {
-        timeZoneOffset = -timeZoneOffset;
-        }
-
-    return (TTimeIntervalSeconds(timeZoneOffset));
-    } // CSmsMessage::UTCOffset
-
-
- /**
-  *  Sets the offset between universal time and local time in seconds.
-  *  If the value is > 0, local time is ahead of universal time.
-  *  If the value is < 0, local time is behind universal time.
-  *  The CSmsMessage Time Zone Offset has the range +/- 71100 seconds. This is same range as
-  *  the Service Centre Time Stamp Time Zone Offset as specified in 23.040 V4.4.0 Sect 9.2.3.11.
-  *  
-  *  @return True if input value was set successfully (in range), False otherwise
-  *  @publishedAll
-  *  @capability None
-  */
-EXPORT_C TBool CSmsMessage::SetUTCOffset(const TTimeIntervalSeconds& aTimeOffset)
-    {
-    LOGGSMU1("CSmsMessage::SetUTCOffset()");
-
-    TBool rc = ETrue;
-
-    TInt timeOffset = aTimeOffset.Int();
-
-    if ((timeOffset <=  EMaximumSeconds) &&
-        (timeOffset >= -EMaximumSeconds))
-        {
-        // Clear the timezone offset bits
-        iFlags &= (~(ESmsUTCOffsetSecondGranularityMask   |
-                     ESmsUTCOffsetSignBit));
-
-        if (timeOffset < 0)
-            {
-            iFlags |= ESmsUTCOffsetSignBit;
-            timeOffset = -timeOffset;
-            }
-
-        iFlags |= (timeOffset << ESecondBitOffset);
-        }
-    else
-        {
-        LOGGSMU2("CSmsMessage::SetUTCOffset offset [out of range] = %d",timeOffset);
-        rc = EFalse;
-        }
-
-    return rc;
-} // CSmsMessage::SetUTCOffset
-
-
-/**
- *  Returns the message version number.
- *  @capability
- */
-EXPORT_C TInt CSmsMessage::Version()
- 	{
- 	LOGGSMU1("CSmsMessage::Version()");
-
- 	return iVersion;
- 	} // CSmsMessage::Version
-
-
-/**
- *  @internalComponent
- *  Validates and sets the message version number.
- *  
- *  @param aVersion version number to set.
- *  @return KErrNone if aVersion is valid and successfully set, KErrArgument otherwise.
- *  @capability None
- */
-EXPORT_C TInt CSmsMessage::SetVersion(TInt aVersion)
-	{
- 	LOGGSMU2("CSmsMessage::SetVersion()", aVersion);
-
-	if((aVersion>=ESmsMessageV0) && (aVersion<=ESmsMessageV4))
-		{
-		iVersion=aVersion;
-		return KErrNone;
-		}
-
-	return KErrArgument;
-	} // CSmsMessage::SetVersion
-
-
-/**
- *  @internalComponent
- *  Internalises all object data except for the CSmsBufferBase and the message version.
- *  
- *  This is used when the buffer is stored elsewhere.
- *  
- *  @param aStream Stream to read from
- *  @capability None
- */
-EXPORT_C void CSmsMessage::InternalizeWithoutBufferAndVersionL(RReadStream& aStream)
-	{
- 	LOGGSMU1("CSmsMessage::InternalizeWithoutBufferAndVersionL()");
-
-	iFlags=aStream.ReadInt32L();
-	iStatus=(NMobileSmsStore::TMobileSmsStoreStatus) aStream.ReadInt32L();
-	iLogServerId=aStream.ReadInt32L();
-	TInt64 time;
-	aStream >> time;
-	iTime=time;
-
-	CSmsPDU* smspdu=CSmsPDU::NewL(aStream,*iCharacterSetConverter,iFs);
-	delete iSmsPDU;
-	iSmsPDU=smspdu;
-	iIs16BitConcatenation=aStream.ReadInt32L();
-
-	iInformationElementArray->ResetAndDestroy();
-	CEmsFactory::InternalizeL(*iInformationElementArray, aStream);
-
-	TInt count=aStream.ReadInt32L();
-	iSlotArray.Reset();
-	TInt i=0;
-	TGsmSmsSlotEntry newSlot;
-	for (; i<count; i++)
-		{
-		newSlot.InternalizeL(aStream);
-		AddSlotL(newSlot);
-		}
-	} // CSmsMessage::InternalizeWithoutBufferAndVersionL
-
-
-/**
- *  @internalComponent
- *  Externalises all object data except for the CSmsBufferBase and the message version.
- *  
- *  This is used when the buffer is stored elsewhere.
- *  
- *  @param aStream Stream to write to
- *  @capability None
- */
-EXPORT_C void CSmsMessage::ExternalizeWithoutBufferAndVersionL(RWriteStream& aStream) const
-	{
- 	LOGGSMU1("CSmsMessage::ExternalizeWithoutBufferAndVersionL()");
-
-	aStream.WriteInt32L(iFlags);
-	aStream.WriteInt32L(iStatus);
-	aStream.WriteInt32L(iLogServerId);
-	aStream << Time().Int64();
-
-	SmsPDU().ExternalizeL(aStream);
-	aStream.WriteInt32L(iIs16BitConcatenation);
-
-	CEmsFactory::ExternalizeL(*iInformationElementArray, aStream);
-	TInt count=iSlotArray.Count();
-	aStream.WriteInt32L(count);
-	TInt i=0;
-	for (; i<count; i++)
-		{
-		iSlotArray[i].ExternalizeL(aStream);
-		}
-	} // CSmsMessage::ExternalizeWithoutBufferAndVersionL
-
-
-/**
- *  @internalComponent
- *  Internalises the CSmsBufferBase.
- *  
- *  @param aStream Stream to read from
- *  @capability None
- */
-EXPORT_C void CSmsMessage::InternalizeBufferL(RReadStream& aStream)
-	{
-	aStream >> *iBuffer;
-	} // CSmsMessage::InternalizeBufferL
-
-
-/**
- *  @internalComponent
- *  Externalises the CSmsBufferBase.
- *  
- *  @param aStream Stream to write to
- *  @capability None
- */
-EXPORT_C void CSmsMessage::ExternalizeBufferL(RWriteStream& aStream) const
-	{
-	aStream << *iBuffer;
-	} // CSmsMessage::ExternalizeBufferL
-
-
-/**
- *  @internalComponent
- *  Internalises the message version.
- *  
- *  @param aStream Stream to read from
- *  @capability None
- */
-EXPORT_C void CSmsMessage::InternalizeVersionL(RReadStream& aStream)
-	{
-	TInt32 versionNumber = ESmsMessageV0;
-	TRAPD(err,versionNumber=aStream.ReadInt32L());
-	if(err==KErrEof)
-		{
-		versionNumber=ESmsMessageV0;
-		}
-
-	iVersion=static_cast<TSmsMessageVersion> (versionNumber);
-	} // CSmsMessage::InternalizeVersionL
-
-
-/**
- *  @internalComponent
- *  Externalises the message version.
- *  
- *  @param aStream Stream to write to
- *  @capability None
- */
-EXPORT_C void CSmsMessage::ExternalizeVersionL(RWriteStream& aStream) const
-	{
-	aStream.WriteInt32L(iVersion);
-	} // CSmsMessage::ExternalizeVersionL
-
-
-/**
- *  @publishedAll
- *  
- *  Returns a reference to a specialisation of the class CSmsIEOperation. Clients can use this sub-class
- *  to access the attributes of a specific type of information element encapsulated inside the CSmsMessage.
- *  The ownership to the CSmsIEOperation class belongs to the CSmsMessage. When the CSmsMessage is deleted,
- *  the CSmsIEOperation will also be deleted and the reference will become stale.
- *  
- *  @param aId
- *  Specifies the sub class of CSmsIEOperation required.
- *  @leave KErrNotSupported
- *  When there is not accessor class available for the specified type of information element.
- *  @capability None
- */
-EXPORT_C CSmsIEOperation& CSmsMessage::GetOperationsForIEL(CSmsInformationElement::TSmsInformationElementIdentifier aId) const
-    {
-    LOGGSMU1("CSmsMessage::GetOperationsForIEL()");
-
-    if (iVersion < CSmsMessage::ESmsMessageV1)
-        {
-        LOGGSMU2("CSmsMessage::GetOperationsForIEL, Operation not supported, Msg Version %d", iVersion);
-        User::Leave(KErrNotSupported);
-        }
-
-    return iAdditionalInfo->GetIEOperationL(aId);
-    } // CSmsMessage::GetOperationsForIEL
-
-EXPORT_C CSmsNonIEOperation& CSmsMessage::GetOperationsForNonIEL(TSmsNonIEIdentifier aId) const
-	{
-	LOGGSMU1("CSmsMessage::GetOperationsForNonIEL");
-
-	if (iVersion < CSmsMessage::ESmsMessageV2)
-		{
-		LOGGSMU2("GetOperationsForNonIEL not supported, Msg Version %d", iVersion);
-		User::Leave(KErrNotSupported);
-		}
-
-	return iAdditionalInfo->GetNonIEOperationL(aId);
-	} // CSmsMessage::GetOperationsForNonIEL
-
-
-void CSmsMessage::CreateControlIEOperationsClassesL()
-    {
- 	LOGGSMU1("CSmsMessage::CreateControlIEOperationsClassesL()");
-
-    CSmsIEOperation* iEOperation = NULL;
-
-    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsHyperLinkFormat, *this,	*iCharacterSetConverter, iFs);
-    iAdditionalInfo->SetIEOperationL(iEOperation);
-
-    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsReplyAddressFormat, *this,	*iCharacterSetConverter, iFs);
-    iAdditionalInfo->SetIEOperationL(iEOperation);
-
-    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, *this,	*iCharacterSetConverter, iFs);
-    iAdditionalInfo->SetIEOperationL(iEOperation);
-
-    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication, *this,	*iCharacterSetConverter, iFs);
-    iAdditionalInfo->SetIEOperationL(iEOperation);
-    
-    iEOperation = CSmsIEOperation::NewL( CSmsInformationElement::ESmsIEISMSCControlParameters, *this,	*iCharacterSetConverter, iFs);
-    iAdditionalInfo->SetIEOperationL(iEOperation);
-    } // CSmsMessage::CreateControlIEOperationsClassesL
-
-    
-void CSmsMessage::CreateControlNonIEOperationsClassesL()
-    {
-    CSmsNonIEOperation* nonIEOperation = NULL;
-
-    nonIEOperation = CSmsNonIEOperation::NewL(ESmsTPSRRParameter, *this);
-    iAdditionalInfo->SetNonIEOperationL(nonIEOperation);
-
-	nonIEOperation = CSmsNonIEOperation::NewL(ESmsIncompleteClass0MessageParameter, *this);
-	iAdditionalInfo->SetNonIEOperationL(nonIEOperation);
-	} // CSmsMessage::CreateControlNonIEOperationsClassesL
-
-
-/**
- *  Gets the scheme of the status report.
- *  
- *  @return Staus Report Scheme 
- */
-EXPORT_C TSmsStatusReportScheme CSmsMessage::Scheme() const
-	{
-	return iAdditionalInfo->GetStatusReportScheme().Id();
-	}
-
-/**
- *  @publishedAll
- *  
- *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
- *  to be on the SIM. If the message's DCS byte is configured for automatic delete or the
- *  PID is set to Type 0, the message may subsequently have been deleted from the SIM during
- *  decoding in which case its storage status is unstored.
- *  
- *  @param aOnSim
- *  Used to indicate that the message was on the SIM when it was decoded.
- *  @capability None
- */
-EXPORT_C void  CSmsMessage::SetDecodedOnSIM(TBool aOnSim)
-    {
- 	LOGGSMU2("CSmsMessage::SetDecodedOnSIM(): %d", aOnSim);
-
-    if (aOnSim)
-        {
-        iFlags = iFlags | EDecodedOnSimBit;
-        }
-    else
-        {
-        iFlags = iFlags & ~EDecodedOnSimBit;
-        }
-    } // CSmsMessage::SetDecodedOnSIM
-
-
-/**
- *  @publishedAll
- *  
- *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
- *  to be on the SIM. If the message's DCS byte is configured for automatic delete or the
- *  PID is set to Type 0, the message may subsequently have been deleted from the SIM during
- *  decoding in which case its storage status is unstored.
- *  
- *  @return
- *  True if the message was on the SIM during decoding,
- *  False otherwise.
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::DecodedOnSim()
-    {
-    LOGGSMU1("CSmsMessage::DecodedOnSim()");
-
-    if (iFlags & EDecodedOnSimBit)
-        {
-        return ETrue;
-        }
-    else
-        {
-        return EFalse;
-        }
-    } // CSmsMessage::DecodedOnSim
-
-
-/**
- *  @publishedAll
- *  
- *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
- *  that it should be forwarded to the client. The message will not be forwarded to the
- *  client when the PID byte is set to type 0 (except by default for class 0 and class 2 messages).
- *  
- *  @param forward
- *  Used to indicate that the message needs to be forwarded to clients.
- *  @capability None
- */
-EXPORT_C void CSmsMessage::SetForwardToClient(TBool aForward)
-    {
- 	LOGGSMU2("CSmsMessage::SetForwardToClient(): %d", aForward);
-
-    if (aForward)
-        {
-        iFlags = iFlags | EForwardToClientBit;
-        }
-    else
-        {
-        iFlags = iFlags & ~EForwardToClientBit;
-        }
-    } // CSmsMessage::SetForwardToClient
-
-
-/**
- *  @publishedAll
- *  
- *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
- *  that is should be forwarded to the client. The message will not be forwarded to the client
- *  when the PID byte is set to type 0 (except by default for class 0 and class 2 messages).
- *  
- *  @return
- *  True if the message is to be forwarded to clients
- *  False otherwise.
- *  @capability None
- */
-EXPORT_C TBool CSmsMessage::ForwardToClient()
-    {
-    LOGGSMU1("CSmsMessage::ForwardToClient()");
-
-    if (iFlags & EForwardToClientBit)
-        {
-        return ETrue;
-        }
-    else
-        {
-        return EFalse;
-        }
-    } // CSmsMessage::ForwardToClient
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Contains the implementation of the CSmsMessage class
+// 
+//
+
+/**
+ @file
+*/
+
+#include <gsmumsg.h>
+#include "Gsmumain.h"
+#include <gsmubuf.h>
+#include <gsmuset.h>
+#include <gsmusar.h>
+#include "gsmumsgadditionalattributes.h"
+#include <gsmuieoperations.h>
+#include <gsmunonieoperations.h>
+
+#include <logwrap.h> //  Used for KLogNullId only
+#include <e32uid.h>
+#include <etelmm.h>
+#include <logwraplimits.h>
+
+#include <emsinformationelement.h>
+#include <emsformatie.h>
+#include <emsuserpromptie.h>
+#include <emsobjectdistributionie.h>
+#include "smsstackutils.h"
+
+/**
+ *  Allocates and creates a CSmsMessage instance from a TGsmSms.
+ *  
+ *  The type of SMS-XXXX message to construct is defined by the first byte of
+ *  the TGsmSms TPDU header.
+ *  
+ *  @param aFs Reference handle to the file system
+ *  @param aGsmSms Reference to TGsmSms
+ *  @param aBuffer The Unicode text for the message. The object takes ownership
+ *  of aBuffer.
+ *  @param aIsRPError Set to true if the message contains Reply Path Error. Default
+ *  is false.
+ *  @param aIsMobileTerminated Set to True if the message is Mobile Terminated.
+ *  Default is false.
+ *  @return New CSmsMessage object
+ *  @capability None
+ */
+EXPORT_C CSmsMessage* CSmsMessage::NewL(RFs& aFs, const TGsmSms& aGsmSms,CSmsBufferBase* aBuffer, TBool aIsRPError,TBool aIsMobileTerminated)
+	{
+	LOGGSMU1("CSmsMessage::NewL()");
+	
+	CleanupStack::PushL(aBuffer);
+	CSmsMessage* smsmessage=new(ELeave) CSmsMessage(aFs, aBuffer);
+	CleanupStack::Pop();
+	CleanupStack::PushL(smsmessage);
+	smsmessage->ConstructL(aGsmSms, aIsRPError,aIsMobileTerminated);
+	CleanupStack::Pop();
+	return smsmessage;
+	} // CSmsMessage::NewL
+
+
+/**
+ *  Allocates and creates a CSmsMessage, specifying the SMS-XXX message type with
+ *  a CSmsPDU::TSmsPduType.
+ *  
+ *  @param aFs Reference handle to the file system
+ *  @param aType The PDU type
+ *  @param aBuffer The Unicode text for the message. The object takes ownership
+ *  of aBuffer.
+ *  @param aIsRPError Set to true if the message contains Reply Path Error. Default
+ *  is false.
+ *  @return New CSmsMessage object
+ *  @capability None
+ */
+EXPORT_C CSmsMessage* CSmsMessage::NewL(RFs& aFs, CSmsPDU::TSmsPDUType aType,CSmsBufferBase* aBuffer,TBool aIsRPError)
+	{
+	LOGGSMU1("CSmsMessage::NewL()");
+
+	CleanupStack::PushL(aBuffer);
+	CSmsMessage* smsmessage=new(ELeave) CSmsMessage(aFs, aBuffer);
+	CleanupStack::Pop();
+	CleanupStack::PushL(smsmessage);
+	smsmessage->ConstructL(aType,aIsRPError);
+	CleanupStack::Pop();
+	return smsmessage;
+	} // CSmsMessage::NewL
+
+
+/**
+ *  Destructor, frees resources.
+ *  @capability None
+ */
+EXPORT_C CSmsMessage::~CSmsMessage()
+	{
+	LOGGSMU1("CSmsMessage::~CSmsMessage()");
+
+	delete iSmsPDU;
+	delete iBuffer;
+	delete iCharacterSetConverter;
+
+	if (iInformationElementArray)
+		{
+		iInformationElementArray->ResetAndDestroy();
+		delete iInformationElementArray;
+		}
+
+	delete iAdditionalInfo;
+	} // CSmsMessage::NewL
+
+
+/**
+ *  Internalises all object data except for the CSmsBufferBase.
+ *  
+ *  This is used when the buffer is stored elsewhere.
+ *  
+ *  @param aStream Stream to read from
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::InternalizeWithoutBufferL(RReadStream& aStream)
+	{
+	LOGGSMU1("CSmsMessage::InternalizeWithoutBufferL()");
+
+	InternalizeWithoutBufferAndVersionL(aStream);
+	InternalizeVersionL(aStream);
+
+	iAdditionalInfo->ResetAttributesL();
+
+	if (iVersion > ESmsMessageV0)
+        {
+        iAdditionalInfo->InternalizeL(aStream, iVersion);
+		}
+	} // CSmsMessage::InternalizeWithoutBufferL
+
+
+/**
+ *  Externalises all object data except for the CSmsBufferBase.
+ *  
+ *  This is used when the buffer is stored elsewhere.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::ExternalizeWithoutBufferL(RWriteStream& aStream) const
+	{
+	LOGGSMU1("CSmsMessage::ExternalizeWithoutBufferL()");
+
+	ExternalizeWithoutBufferAndVersionL(aStream);
+	ExternalizeVersionL(aStream);
+
+	if (iVersion > ESmsMessageV0)
+		{
+		iAdditionalInfo->ExternalizeL(aStream, iVersion);
+		}
+	} // CSmsMessage::ExternalizeWithoutBufferL
+
+
+/**
+ *  Internalises all object data.
+ *  
+ *  @param aStream Stream to read from
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::InternalizeL(RReadStream& aStream)
+	{
+	LOGGSMU1("CSmsMessage::InternalizeL()");
+
+	InternalizeWithoutBufferAndVersionL(aStream);
+	InternalizeBufferL(aStream);
+	InternalizeVersionL(aStream);
+
+	iAdditionalInfo->ResetAttributesL();
+	if (iVersion > ESmsMessageV0)
+		{
+		iAdditionalInfo->InternalizeL(aStream, iVersion);
+		}
+	} // CSmsMessage::InternalizeL
+
+
+/**
+ *  Externalises all object data.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::ExternalizeL(RWriteStream& aStream) const
+	{
+	LOGGSMU1("CSmsMessage::ExternalizeL()");
+
+	ExternalizeWithoutBufferAndVersionL(aStream);
+	ExternalizeBufferL(aStream);
+	ExternalizeVersionL(aStream);
+
+	if (iVersion > ESmsMessageV0)
+		{
+		iAdditionalInfo->ExternalizeL(aStream, iVersion);
+		}
+	} // CSmsMessage::ExternalizeL
+
+
+/**
+ *  Tests if the message contains text.
+ *  
+ *  @return True if the message contains text
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::TextPresent() const
+	{
+	LOGGSMU1("CSmsMessage::TextPresent()");
+
+	CSmsPDU::TSmsPDUType pdutype=SmsPDU().Type();
+	return (pdutype==CSmsPDU::ESmsSubmit) ||
+	       (pdutype==CSmsPDU::ESmsDeliver) ||
+	     (((pdutype==CSmsPDU::ESmsSubmitReport) || (pdutype==CSmsPDU::ESmsDeliverReport) ||
+	      ((pdutype==CSmsPDU::ESmsStatusReport) && ((CSmsStatusReport&) SmsPDU()).ParameterIndicatorPresent())) &&
+	      SmsPDU().UserDataPresent());
+	} // CSmsMessage::TextPresent
+
+
+/**
+ *  Gets the number of PDU's required to encode the complete message.
+ *  
+ *  @leave KErrOverflow Leaves if the number of required PDUs exceeds the maximum
+ *  or the message cannot be encoded.
+ *  @return Number of PDU's
+ *  @capability None
+ */
+EXPORT_C TInt CSmsMessage::NumMessagePDUsL()
+	{
+	LOGGSMU1("CSmsMessage::NumMessagePDUsL()");
+
+	TInt nummessagepdus=1;
+	if (IsDecoded())
+		{
+		if (TextPresent())
+			{
+			nummessagepdus=NumMessageEmsPDUsL();
+			TInt maxnummessagepdus=SmsPDU().TextConcatenated()? 0xFF: 1;
+ 			if (nummessagepdus>maxnummessagepdus)
+				{
+ 				User::Leave(KErrOverflow);
+				}
+			}
+
+		}
+	else if (TextPresent() && SmsPDU().TextConcatenated())
+		{
+		nummessagepdus=SmsPDU().NumConcatenatedMessagePDUs();
+		}
+
+	LOGGSMU2("CSmsMessage::NumMessagePDUsL() returns %d", nummessagepdus);
+
+	return nummessagepdus;
+	} // CSmsMessage::NumMessagePDUsL
+
+
+/**
+ *  Gets the maximum message length possible with the current settings.
+ *  
+ *  If Text is compressed, this returns the maximum number of bytes available
+ *  with text compressed.
+ *  
+ *  @return Maximum message length
+ *  @capability None
+ */
+EXPORT_C TInt CSmsMessage::MaxMessageLength() const
+	{
+	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
+	TInt maxmessagelength=SmsPDU().UserData().MaxBodyLengthInChars();
+	if (SmsPDU().TextConcatenated())
+		{
+		maxmessagelength=maxmessagelength*0xFF;
+		}
+
+	LOGGSMU2("CSmsMessage::MaxMessageLength() returns %d", maxmessagelength);
+
+	return maxmessagelength;
+	} // CSmsMessage::MaxMessageLength
+
+
+/**
+ *  
+ *  @return The converted buffer length
+ *  @note Use with care - Expensive operation
+ */
+TInt CSmsMessage::ConvertedBufferLengthL(const CSmsBufferBase& aBuffer)
+    {
+    // Ignore in code coverage - not used in SMS stack and not exported
+    // but cannot be removed as impacts public header.
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsMessage::ConvertedBufferLengthL()");
+    
+    TInt convertedBufferLength=0;
+    CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
+    CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aBuffer);
+    convertedBufferLength=segmenter->TotalConvertedLengthL(iAdditionalInfo->Alternative7bitEncoding());
+    CleanupStack::PopAndDestroy(2, converter);
+    
+    LOGGSMU2("CSmsMessage::ConvertedBufferLengthL() returns %d", convertedBufferLength);
+    
+    return convertedBufferLength;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  Gets the message length.
+ *  
+ *  In the case where the message is compressed, this function compresses the
+ *  text and returns the number of bytes of the compressed buffer.
+ *  
+ *  The function calls ConvertedBufferLengthL(), and is therefore an expensive
+ *  operation.
+ *  
+ *  @return Message length
+ *  @capability None
+ */
+EXPORT_C TInt CSmsMessage::MessageLengthL()
+	{
+	LOGGSMU1("CSmsMessage::MessageLengthL()");
+
+	TInt messagelength=0;
+	if (!SmsPDU().TextCompressed())
+		{
+		messagelength=iBuffer->Length();
+		if(SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabetUCS2)messagelength*=2 ;
+		}
+	else
+		{
+		User::Leave(KErrNotSupported);
+		}
+	return messagelength;
+	} // CSmsMessage::MessageLengthL
+
+
+EXPORT_C void CSmsMessage::GetEncodingInfoL(TInt& aPdus, TInt& aUnconvertedChars,
+		                                    TInt& aDowngradedChars, TInt& aFreeUDUnitsInLastPDU)
+	{
+	LOGGSMU1("CSmsMessage::GetEncodingInfoL()");
+
+	aPdus                 = 1;
+	aUnconvertedChars     = 0;
+	aDowngradedChars      = 0;
+	aFreeUDUnitsInLastPDU = 0;
+
+	if (TextPresent())
+		{
+		if (IsDecoded())
+			{
+			//
+			// Clear the concatenated flag, EncodeBufferL() will add it if needed.
+			//
+			SmsPDU().SetTextConcatenatedL(EFalse, EFalse);
+
+			//
+			// Attempt to encode to a single PDU, and if that fails then attempt to
+			// encode to a set of PDUs.
+			//
+			CArrayFixFlat<TGsmSms>*  tmpArray = new (ELeave) CArrayFixFlat<TGsmSms>(8);
+			CleanupStack::PushL(tmpArray);
+			
+			//
+			// Encode the message...
+			//
+			if (!EncodeIntoSinglePDUL(*tmpArray, aUnconvertedChars,
+                                      aDowngradedChars, aFreeUDUnitsInLastPDU))
+				{
+				EncodeBufferL(*tmpArray, 0, *iBuffer, aUnconvertedChars,
+						      aDowngradedChars, aFreeUDUnitsInLastPDU, EFalse);
+
+				aPdus = iAdditionalInfo->SmsPDUArray().Count();
+				if (aPdus > 255)
+					{
+	 				User::Leave(KErrOverflow);
+					}
+				}
+
+			CleanupStack::PopAndDestroy(tmpArray);
+			}
+		else if (SmsPDU().TextConcatenated())
+			{
+			aPdus                 = SmsPDU().NumConcatenatedMessagePDUs();
+			aUnconvertedChars     = 0;
+			aDowngradedChars      = 0;
+			aFreeUDUnitsInLastPDU = 0;
+			}
+		}
+
+	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aPdus=%d", aPdus);
+	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aUnconvertedChars=%d", aUnconvertedChars);
+	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aDowngradedChars=%d", aDowngradedChars);
+	LOGGSMU2("CSmsMessage::GetEncodingInfoL(): aFreeUDUnitsInLastPDU=%d", aFreeUDUnitsInLastPDU);
+	} // CSmsMessage::GetEncodingInfoL
+
+
+/**
+ *  Gets the User Data Settings.
+ *  
+ *  @param aSettings User Data Settings
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::UserDataSettings(TSmsUserDataSettings& aSettings) const
+	{
+	LOGGSMU1("CSmsMessage::UserDataSettings()");
+
+	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
+	aSettings.SetAlphabet(SmsPDU().Alphabet());
+	aSettings.SetTextCompressed(SmsPDU().TextCompressed());
+	TBool is16bit;
+	TBool concatenated=SmsPDU().TextConcatenated(&is16bit);
+	aSettings.SetTextConcatenated(concatenated,is16bit);
+	} // CSmsMessage::UserDataSettings
+
+
+/**
+ *  Sets the User Data Settings.
+ *  
+ *  @param aSettings User Data Settings
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::SetUserDataSettingsL(const TSmsUserDataSettings& aSettings)
+	{
+	LOGGSMU1("CSmsMessage::SetUserDataSettingsL()");
+
+	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
+	SmsPDU().SetAlphabet(aSettings.Alphabet());
+	SmsPDU().SetTextCompressed(aSettings.TextCompressed());
+	TBool is16bit;
+	TBool concatenated=aSettings.TextConcatenated(&is16bit);
+	SmsPDU().SetTextConcatenatedL(concatenated,is16bit);
+	} // CSmsMessage::SetUserDataSettingsL
+
+
+/**
+ *  Optimizes the user data settings.
+ *  
+ *  The alphabet flag causes an alphabet to be chosen which preserves information
+ *  in the message and makes the number of PDUs as small as possible.
+ *  
+ *  The compression settings flag is not supported.
+ *  
+ *  The compression flag causes compression to be switched on if the resultant
+ *  number of PDUs is smaller.
+ *  
+ *  If user explicitly defines alphabet as UCS2 or 8-bit coding, this setting is preserved;
+ *  otherwise, if 7-bit (default) alphabet can not support current text of message UCS2
+ *  alphabet (Unicode) is used.
+ *  
+ *  The two concatenation flags are mutually exclusive as they deal with 8-bit
+ *  and 16-bit referenced concatenation. Both flags cause compression to be switched
+ *  off and if the message length is greater than the maximum message length,
+ *  concatenation is switched on.
+ *  
+ *  @param aOptions Combination of TSmsOptimizationFlags
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::OptimizeSettingsL(TInt aOptions)
+	{
+	LOGGSMU1("CSmsMessage::OptimizeSettingsL()");
+
+	__ASSERT_DEBUG(TextPresent(),Panic(KGsmuPanicTextNotPresent));
+	__ASSERT_DEBUG(IsDecoded(),Panic(KGsmuPanicNotDecoded));
+
+	if (aOptions&ESmsFlagOptimizeAlphabet && (SmsPDU().Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit))
+		{
+		TBool isSupported=ETrue;
+		TInt numOfUnconvertibleChars;
+		TInt indexOfFirstUnconvertibleChar;
+
+		TInt size=iBuffer->Length();
+		const TInt bufsize=128;
+		TBuf<bufsize> buf;
+		TInt extracted=0;
+		TInt remaining=0;
+		TInt toExtract=0;
+		TInt pos=0;
+
+		// Defect Fix. Previous for loop caused an access violation as extract size was set
+		// to size of ibuffer not bufsize and caused a access violation when over 128. Implemented
+		// fix copies the ibuffer in 128 chunks until its all done.
+
+		while((pos<size) && isSupported)
+			{
+			remaining=(size - extracted);
+
+			if(remaining>bufsize)
+				toExtract=bufsize;
+			else
+				toExtract=remaining;
+
+			iBuffer->Extract(buf,pos,toExtract);
+			isSupported=IsSupportedL(buf,numOfUnconvertibleChars,indexOfFirstUnconvertibleChar);
+			extracted=(extracted+toExtract);
+			pos=extracted;
+			}
+
+		if(!isSupported)
+			SmsPDU().SetAlphabet(TSmsDataCodingScheme::ESmsAlphabetUCS2);
+		}
+	} // CSmsMessage::OptimizeSettingsL
+
+
+/**
+ *  This function returns the currently requested alternative encoding method.
+ * 
+ *  In the case of incoming SMS messages received on the device, it will often
+ *  be TSmsEncodingNone unless the Information Elements imply that an
+ *  alternative encoding has been used.
+ * 
+ *  @return The currently selected encoding method.
+ * 
+ *  @capability None
+ */
+EXPORT_C TSmsEncoding CSmsMessage::Alternative7bitEncoding() const
+	{
+	LOGGSMU1("CSmsMessage::Alternative7bitEncoding()");
+
+	return iAdditionalInfo->Alternative7bitEncoding();
+	} // CSmsMessage::Alternative7bitEncoding
+
+
+/**
+ *  This function allows the client to specify an alternative encoding method
+ *  incase the default GSM encoding cannot encode the message completely
+ *  without data loss.
+ * 
+ *  @param aEncoding  Encoding method to select.
+ * 
+ *  @return A Symbian system wide error code.  This function will return
+ *          KErrArgument if the encoding enum is invalid and will return
+ *          KErrNotSupported if the required plug-ins are not present.
+ * 
+ *  @capability None
+ */
+EXPORT_C TInt CSmsMessage::SetAlternative7bitEncoding(TSmsEncoding aEncoding)
+	{
+	LOGGSMU2("CSmsMessage::SetAlternative7bitEncoding(%d)", aEncoding);
+
+	//
+	// Get the encoders that would be used for this encoding method.
+	// The function will also check that the required encoder is present.
+	//
+	TRAPD(err,
+		{
+		CSmsAlphabetConverter*  converter = CSmsAlphabetConverter::NewLC(*iCharacterSetConverter, iFs,
+																	     TSmsDataCodingScheme::ESmsAlphabet7Bit,
+																	     EFalse);
+		converter->ConfirmAlternativeEncoderL(aEncoding);
+		CleanupStack::PopAndDestroy(converter);
+		});
+	
+	//
+	// Set the variable if the encoders are available...
+	//
+	if (err == KErrNone)
+		{
+		iAdditionalInfo->SetAlternative7bitEncoding(aEncoding);
+		}
+	
+	return err;
+	} // CSmsMessage::SetAlternative7bitEncoding
+
+
+/**
+ *  Takes an encoding setting (received from a PDU) and merges it into the
+ *  current setting (where possible).
+ *  
+ *  @param aEncoding  Encoding setting to merge.
+ */
+void CSmsMessage::MergeAlternative7bitEncoding(TSmsEncoding aEncoding) const
+	{
+	LOGGSMU3("CSmsMessage::MergeAlternative7bitEncoding(): aEncoding=%d (currently %d)",
+			 aEncoding, iAdditionalInfo->Alternative7bitEncoding());
+
+	switch (iAdditionalInfo->Alternative7bitEncoding())
+		{
+		case ESmsEncodingNone:
+			{
+			// Anything is can be merge with this...
+			iAdditionalInfo->SetAlternative7bitEncoding(aEncoding);
+			}
+			break;
+		
+		case ESmsEncodingTurkishSingleShift:
+			{
+			// Only Turkish locking shift can merge...
+			if (aEncoding == ESmsEncodingTurkishLockingShift)
+				{
+				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingTurkishLockingAndSingleShift);
+				}
+			}
+			break;
+		
+		case ESmsEncodingTurkishLockingShift:
+			{
+			// Only Turkish single shift can merge...
+			if (aEncoding == ESmsEncodingTurkishSingleShift)
+				{
+				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingTurkishLockingAndSingleShift);
+				}
+			}
+			break;
+		
+		case ESmsEncodingPortugueseSingleShift:
+			{
+			// Only Portuguese locking shift can merge...
+			if (aEncoding == ESmsEncodingPortugueseLockingShift)
+				{
+				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingPortugueseLockingAndSingleShift);
+				}
+			}
+			break;
+		
+		case ESmsEncodingPortugueseLockingShift:
+			{
+			// Only Portuguese single shift can merge...
+			if (aEncoding == ESmsEncodingPortugueseSingleShift)
+				{
+				iAdditionalInfo->SetAlternative7bitEncoding(ESmsEncodingPortugueseLockingAndSingleShift);
+				}
+			}
+			break;
+		
+		case ESmsEncodingTurkishLockingAndSingleShift:
+		case ESmsEncodingSpanishSingleShift:
+		case ESmsEncodingPortugueseLockingAndSingleShift:
+		default:
+			{
+			// NOP - Cannot merge anything into these...
+			}
+		};
+
+	LOGGSMU2("CSmsMessage::MergeAlternative7bitEncoding(): New encoding=%d",
+			 iAdditionalInfo->Alternative7bitEncoding());
+	} // CSmsMessage::MergeAlternative7bitEncoding
+
+
+/**
+ *  Tests if a buffer can be encoded without loss of information.
+ *  
+ *  @param aDes                                 The buffer to test for encoding
+ *  @param aNumberOfUnconvertibleCharacters     On return, the number of 
+ *                                              unconvertible characters
+ *  @param aIndexOfFirstUnconvertibleCharacter  On return, the index of the
+ *                                              first unconvertible character
+ * 
+ *  @return True if aDes can be encoded without loss of information
+ * 
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
+		                                 TInt& aIndexOfFirstUnconvertibleCharacter)
+	{
+	LOGGSMU1("[1] CSmsMessage::IsSupportedL()");
+
+	__ASSERT_DEBUG(TextPresent(), Panic(KGsmuPanicTextNotPresent));
+
+	aNumberOfUnconvertibleCharacters    = 0;
+	aIndexOfFirstUnconvertibleCharacter = aDes.Length();
+
+	if (SmsPDU().TextCompressed())
+		{
+		return EFalse;
+		}
+
+	return SmsPDU().UserData().IsSupportedL(aDes, aNumberOfUnconvertibleCharacters,
+                                            aIndexOfFirstUnconvertibleCharacter);
+	} // CSmsMessage::IsSupportedL
+
+
+/**
+ *  Tests if a buffer can be encoded without loss of information.
+ *  
+ *  @param aDes                                 The buffer to test for encoding
+ *  @param aNumberOfUnconvertibleCharacters     On return, the number of 
+ *                                              unconvertible characters
+ *  @param aNumberOfDowngradedCharacters        On return, the number of 
+ *                                              characters downgraded
+ *  @param aNumberRequiringAlternativeEncoding  On return, the number of 
+ *                                              characters needing alternative
+ *                                              encoding support
+ *  @param aIndexOfFirstUnconvertibleCharacter  On return, the index of the
+ *                                              first unconvertible character
+ * 
+ *  @return True if aDes can be encoded without loss of information
+ * 
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
+		                                 TInt& aNumberOfDowngradedCharacters,
+		                                 TInt& aNumberRequiringAlternativeEncoding,
+		                                 TInt& aIndexOfFirstUnconvertibleCharacter) const
+	{
+	LOGGSMU1("[2] CSmsMessage::IsSupportedL()");
+
+	__ASSERT_DEBUG(TextPresent(), Panic(KGsmuPanicTextNotPresent));
+
+	aNumberOfUnconvertibleCharacters    = 0;
+	aNumberOfDowngradedCharacters       = 0;
+	aNumberRequiringAlternativeEncoding = 0;
+	aIndexOfFirstUnconvertibleCharacter = aDes.Length();
+
+	if (SmsPDU().TextCompressed())
+		{
+		return EFalse;
+		}
+
+	return SmsPDU().UserData().IsSupportedL(aDes, iAdditionalInfo->Alternative7bitEncoding(),
+											aNumberOfUnconvertibleCharacters,
+	                                        aNumberOfDowngradedCharacters,
+                                            aNumberRequiringAlternativeEncoding,
+                                            aIndexOfFirstUnconvertibleCharacter);
+	} // CSmsMessage::IsSupportedL
+
+
+/**
+ *  Encodes message PDUs as an array of TGsmSms objects.
+ *  
+ *  Note, this function should only be called after EncodeIntoSinglePDUL() as EncodeBufferL() now
+ *  automatically prepares PDUs for concatenation.
+ *  
+ *  @param aSmsArray (In) an empty array. On return, one or more encoded TGsmSms.
+ *  @param aReference Sets a Concatenated Message Reference (default 0)
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::EncodeMessagePDUsL(CArrayFix<TGsmSms>& aSmsArray, TInt aReference)
+	{
+	LOGGSMU2("CSmsMessage::EncodeMessagePDUsL(): aReference=%d", aReference);
+
+	__ASSERT_DEBUG((aSmsArray.Count()==0),Panic(KGsmuPanicSmsArrayNotEmpty));
+	
+	if (TextPresent())
+		{
+		if (SmsPDU().TextCompressed())
+			{
+			User::Leave(KErrNotSupported);
+			}
+		else
+			{
+			TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
+				
+			EncodeBufferL(aSmsArray, aReference, *iBuffer, unconvertedChars,
+					      downgradedChars, freeUDUnitsInLastPDU);
+			}
+		}
+	else
+		{
+        if(SmsPDU().Type()==CSmsPDU::ESmsCommand)
+            {
+            //Commands never contain text, so commands only encoded
+            // in this branch.
+            //
+            // However  Commands don't support information
+            // elements (per 23.040 6.5) and the CSmsIEOperation class
+            // do not allow control information elements to be added
+            // to Commands, hence the next line is commented out.
+            // PrepareCommandMessageL();
+            }
+
+ 		TGsmSms sms;
+ 		SmsPDU().EncodeMessagePDUL(sms);
+ 		aSmsArray.AppendL(sms);
+		}
+	} // CSmsMessage::EncodeMessagePDUsL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  This method copies information elements from the collections contained in
+ *  CSmsMessageAdditionalAttributes into the working PDU.
+ *  
+ *  Command Messages comprise only 1 PDU. Therefore all information
+ *  elements must be present in the working PDU when encoding takes place.
+ *  If there is not enough space in the PDU, the message encoding will fail.
+ *  
+ *  The 23.040 has not defined any information elements that are contained in
+ *  Command PDUs. This method has been provided to maintain consistency with
+ *  previous GSMU implementations.
+ *  
+ *  @leave KErrAlreadyExists or KErrAlreadyExists
+ */
+void CSmsMessage::PrepareCommandMessageL()
+    {
+    LOGGSMU1("CSmsMessage::PrepareCommandMessageL()");
+
+    if (SmsPDU().Type()==CSmsPDU::ESmsCommand)
+        {
+        CSmsCommand& command = static_cast<CSmsCommand&>(SmsPDU());
+
+        for (TUint8 category = 0; category < TSmsInformationElementCategories::ENumberOfCategories; category++)
+            {
+            switch(category)
+                {
+                case TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
+                case TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
+                case TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
+                    {
+                    for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
+                        {
+                        CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j);
+                        TPtr8 data = informationElement.Data();
+                        command.AddInformationElementL(informationElement.Identifier(), data);
+                        }
+                    break;
+                    }
+                default:
+                LOGGSMU2("CSmsMessage::PrepareCommandMessageL,default switch category = %d, id = %d", category);
+                    break;
+                }
+            }
+        }
+    } // CSmsMessage::PrepareCommandMessageL
+
+
+/**
+ *  Decodes message PDUs from an array of TGsmSms objects.
+ *  
+ *  The array contains a concatenated message, and must have the correct number
+ *  of PDUs.
+ *  
+ *  @param aSmsArray Concatenated message
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::DecodeMessagePDUsL(const CArrayFix<TGsmSms>& aSmsArray)
+	{
+    LOGGSMU2("CSmsMessage::DecodeMessagePDUsL(): PDUs=%d", aSmsArray.Count());
+
+	TInt count=aSmsArray.Count();
+	SetIsComplete(ETrue);
+	CArrayPtrFlat<CSmsPDU>* smspduarray=new(ELeave) CArrayPtrFlat<CSmsPDU>(8);
+	CleanupStack::PushL(smspduarray);
+	// With CleanupResetAndDestroyPushL, only ResetAndDestroy method of smspduarray is invoked. 
+	// smspduarray object is actually deleted with the first push. 
+	// coverity[double_push]
+	CleanupResetAndDestroyPushL(*smspduarray);  // Don't forget to destroy what the array elements point to.
+
+	TInt i=0;
+	TBool ismobileterminated=(Type()==CSmsPDU::ESmsDeliver) || (Type()==CSmsPDU::ESmsSubmitReport) || (Type()==CSmsPDU::ESmsStatusReport);
+	for (; i<count; i++)
+		{
+		CSmsPDU* smspdu=CSmsPDU::NewL(aSmsArray[i],*iCharacterSetConverter,iFs, EFalse,ismobileterminated);
+		CleanupStack::PushL(smspdu);
+		TInt j=0;
+		for (; (j<smspduarray->Count()) && (smspdu->ConcatenatedMessagePDUIndex()>(*smspduarray)[j]->ConcatenatedMessagePDUIndex()); j++)
+			{
+			}
+		smspduarray->InsertL(j,smspdu);
+		CleanupStack::Pop();
+		}
+	if (SmsPDU().TextCompressed())
+		User::Leave(KErrNotSupported);
+	else
+		DecodeBufferL(*smspduarray,*iBuffer);
+
+	CleanupStack::PopAndDestroy(2);  //  smspduarray elements (Reset and Destroy), smspduarray
+	SetIsDecoded(ETrue);
+	SmsPDU().UserData().SetBodyL(KNullDesC8);
+	} // CSmsMessage::DecodeMessagePDUsL
+
+/**
+ *  Decodes partial complete message PDUs from an array of TGsmSms objects.
+ *  
+ *  The array contains a concatenated incomplete message, but the array of
+ *  TGsmSms object must be in sequence.
+ *  
+ *	NOTE:
+ *	It will not fully decode EMS and Control Information elements if it needs 
+ *	to decode a partially complete class 0 SMS message. The assumption is that 
+ *	it is necessary to display a partially complete message then only the raw 
+ *	text will be displayed on the UI without any animation elements. The 
+ *	rational for this design is that these information elements are normally 
+ *	specified as being located at a specific position in a message. It will 
+ *	complicate the design of client app if it has to re-calculate the position 
+ *	of these elements when it receives a partially complete message under 
+ *	Out Of Memory Conditions.
+ 
+ *  @param aSmsArray Concatenated message
+ *	@param aLastPartialCompleteMsg boolean value indicating this is the last
+ *			incomplete message for a particular concatenated message.
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::DecodePartialCompleteMessagePDUsL(const CArrayFix<TGsmSms>& aSmsArray, TBool aLastPartialCompleteMsg)
+	{
+	LOGGSMU2("CSmsMessage::DecodePartialCompleteMessagePDUsL(): PDUs=%d", aSmsArray.Count());
+
+	TInt count=aSmsArray.Count();
+	SetIsComplete(EFalse);
+	CArrayPtrFlat<CSmsPDU>* smspduarray=new(ELeave) CArrayPtrFlat<CSmsPDU>(8);
+	CleanupStack::PushL(smspduarray);
+	// With CleanupResetAndDestroyPushL, only ResetAndDestroy method of smspduarray is invoked. 
+	// smspduarray object is actually deleted with the first push. 
+	// coverity[double_push]
+	CleanupResetAndDestroyPushL(*smspduarray);  // Don't forget to destroy what the array elements point to.
+
+	TBool isMobileTerminated=(Type()==CSmsPDU::ESmsDeliver);
+	/*
+	The loop below goes through all the sms's received & check whether the received PDUs are of Class 0
+	or not. The number of PDUs received must be less than the number of concatenated PDUs constitute this message.
+	Then it order the PDUs in sequence for decoding purpose.
+	*/
+	for (TInt i=0; i<count; i++)
+		{
+		CSmsPDU* smspdu=CSmsPDU::NewL(aSmsArray[i],*iCharacterSetConverter,iFs, EFalse,isMobileTerminated);
+		CleanupStack::PushL(smspdu);
+
+		/*
+		Check all the PDUs must be class 0 messages & also the number of received PDUs
+		must be less than the number of concatenated PDUs constitute this message
+		*/
+		TSmsDataCodingScheme::TSmsClass  msgClass;
+		if (smspdu->DataCodingSchemePresent()  &&  smspdu->Class(msgClass))
+			{
+			if (msgClass != TSmsDataCodingScheme::ESmsClass0)
+				{
+				User::Leave(KErrNotSupported);
+				}
+			__ASSERT_DEBUG((count < smspdu->NumConcatenatedMessagePDUs()),Panic(KGsmuPanicWrongNumberOfMessagePDUs));
+			}
+		else
+			{
+			User::Leave(KErrNotSupported);
+			}
+		//The below for statement finds the position in smspduarray where the PDU should be inserted.
+		//The PDUs are put in sequence for decoding purpose.
+		TInt j;
+		for (j=0; (j<smspduarray->Count()) && (smspdu->ConcatenatedMessagePDUIndex()>(*smspduarray)[j]->ConcatenatedMessagePDUIndex()); j++)
+			{
+			}
+		smspduarray->InsertL(j,smspdu);
+		CleanupStack::Pop();
+		}
+
+	if (SmsPDU().TextCompressed())
+		{
+		User::Leave(KErrNotSupported);
+		}
+	else
+		{
+		DecodeOnlyTextL(*smspduarray,*iBuffer);
+		}
+
+	iVersion = CSmsMessage::ESmsIncompleteClass0MessageV;
+
+	TInt startPDU = smspduarray->At(0)->ConcatenatedMessagePDUIndex();
+	TInt endPDU = smspduarray->At(smspduarray->Count()-1)->ConcatenatedMessagePDUIndex();
+	AddIncompleteMessageInfoL(startPDU, endPDU, aLastPartialCompleteMsg);
+
+	CleanupStack::PopAndDestroy(2);  //  smspduarray elements (Reset and Destroy), smspduarray
+	SetIsDecoded(ETrue);
+	SmsPDU().UserData().SetBodyL(KNullDesC8);	
+	}
+
+CSmsMessage::CSmsMessage(RFs& aFs, CSmsBufferBase* aBuffer):
+    iFlags(0),
+    iStatus(NMobileSmsStore::EStoredMessageUnread),
+    iLogServerId(KLogNullId),
+    iBuffer(aBuffer),
+    iFs(aFs),
+	iSlotArray(8),
+	iVersion(ESmsMessageV4),
+	iAdditionalInfo(NULL)
+    {
+    iTime.UniversalTime();
+
+    TBool result = SetUTCOffset(User::UTCOffset());
+    __ASSERT_DEBUG(result, Panic(KGSMUPanicUserTimeZoneOffsetOutOfRange));
+    } // NMobileSmsStore::EStoredMessageUnread
+
+void CSmsMessage::ConstructL(const TGsmSms& aGsmSms, TBool aIsRPError,TBool aIsMobileTerminated)
+	{
+    LOGGSMU1("CSmsMessage::ConstructL()");
+
+	iCharacterSetConverter=CCnvCharacterSetConverter::NewL();
+	iInformationElementArray = new (ELeave) RPointerArray<CEmsInformationElement>(8);
+
+	iAdditionalInfo = CSmsMessageAdditionalAttributes::NewL();
+	CreateControlIEOperationsClassesL();
+	CreateControlNonIEOperationsClassesL();
+
+	iSmsPDU=CSmsPDU::NewL(aGsmSms,*iCharacterSetConverter,iFs, aIsRPError,aIsMobileTerminated);
+	SetIsComplete(NumMessagePDUsL()==1);
+	if (IsComplete() && TextPresent())
+		{
+		TSmsEncoding  encodingUsedInSegment = SmsPDU().NationalLanguageEncoding();
+		
+		CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
+		TPtrC nativeChars(converter->ConvertToNativeL(SmsPDU().UserData().Body(),
+													  encodingUsedInSegment));
+		MergeAlternative7bitEncoding(encodingUsedInSegment);
+		
+		if (SmsPDU().TextCompressed())
+			User::Leave(KErrNotSupported);
+		else
+			iBuffer->InsertL(iBuffer->Length(),nativeChars);
+		CleanupStack::PopAndDestroy(converter);
+		CSmsPDU::TSmsPDUType pdutype= SmsPDU().Type();
+		if(pdutype==CSmsPDU::ESmsCommand)
+			{
+			// This branch is never executed as TextPresent() never
+			// returns true when pduType == command
+            User::Leave(KErrArgument);
+			}
+		else if(SmsPDU().UserDataPresent())
+			{
+			TInt smscIndex(0);
+
+			if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+				{
+				iAdditionalInfo->SetStatusReportSchemeL(EControlParametersScheme);
+				}
+			else
+				{
+				iAdditionalInfo->SetStatusReportSchemeL(EDefaultScheme);	
+				}
+				
+            InstallControlInformationElementsL(SmsPDU().UserData(), 0);
+			InstallEmsInformationElementsL(SmsPDU().UserData(),0);
+			UpdateUserPromptAndODIElementsStartPosition();
+			}
+		}
+	SetIsDecoded(IsComplete());
+
+	if (TextPresent())
+		SmsPDU().UserData().SetBodyL(KNullDesC8);
+	} // CSmsMessage::ConstructL
+
+
+void CSmsMessage::ConstructL(CSmsPDU::TSmsPDUType aType,TBool aIsRPError)
+	{
+    LOGGSMU3("CSmsMessage::ConstructL(): aType=%d, aIsRPError=%d", (TInt) aType,
+    		 aIsRPError);
+
+	iCharacterSetConverter=CCnvCharacterSetConverter::NewL();
+	iInformationElementArray = new (ELeave) RPointerArray<CEmsInformationElement>(2);
+
+	iAdditionalInfo = CSmsMessageAdditionalAttributes::NewL();
+	CreateControlIEOperationsClassesL();
+	CreateControlNonIEOperationsClassesL();
+
+	iSmsPDU=CSmsPDU::NewL(aType,*iCharacterSetConverter,iFs,aIsRPError);
+	SetIsComplete(ETrue);
+	SetIsDecoded(ETrue);
+	} // CSmsMessage::ConstructL
+
+
+/**
+ *  Counts the number of PDUs that this message will take. To do this the
+ *  message will attempt to be encoded into 1 message, and if not into
+ *  multiple messages. Due to the processing, the function should be used
+ *  sparingly.
+ * 
+ *  @return  Number of PDUs required.
+ */
+TInt CSmsMessage::NumMessageEmsPDUsL()
+	{
+	LOGGSMU1("CSmsMessage::NumMessageEmsPDUsL()");
+
+	//
+	// Clear the concatenated flag, EncodeBufferL() will add it if needed.
+	//
+	SmsPDU().SetTextConcatenatedL(EFalse, EFalse);
+
+	//
+	// Attempt to encode to a single PDU, and if that fails then attempt to
+	// encode to a set of PDUs.
+	//
+	CArrayFixFlat<TGsmSms>*  tmpArray = new (ELeave) CArrayFixFlat<TGsmSms>(8);
+	CleanupStack::PushL(tmpArray);
+	TInt numMsgs = 1;
+	
+	if (!EncodeIntoSinglePDUL(*tmpArray))
+		{
+		TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
+		
+		EncodeBufferL(*tmpArray, 0, *iBuffer, unconvertedChars,
+			          downgradedChars, freeUDUnitsInLastPDU, EFalse);
+
+		numMsgs = iAdditionalInfo->SmsPDUArray().Count();
+		}
+
+	CleanupStack::PopAndDestroy(tmpArray);
+	
+    LOGGSMU2("CSmsMessage::NumMessageEmsPDUsL() returns %d", numMsgs);
+
+	return numMsgs;
+	} // CSmsMessage::NumMessageEmsPDUsL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  This method removes all non mandatory information elements from the
+ *  working PDU.
+ *  
+ *  The working PDU is the PDU which is currently being encoded or decoded.
+ *  
+ *  @leave KErrAlreadyExists or KErrAlreadyExists
+ */
+void CSmsMessage::ResetWorkingPDUL()
+	{
+	LOGGSMU1("CSmsMessage::ResetWorkingPDUL()");
+	
+	CSmsUserData& uData = SmsPDU().UserData();
+	//remove non-mandatory EMS information elements
+	for (TInt a=uData.NumInformationElements(); a>0; --a)
+        {
+        const CSmsInformationElement& ie = uData.InformationElement(a-1);
+
+         TSmsInformationElementCategories::TInformationElementCategory category;
+
+        if (TSmsInformationElementCategories::GetCategoryDefinition(ie.Identifier(), category)  &&
+        	(category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues)    &&
+            (category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU) &&
+            (category !=  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU))
+            {
+            uData.RemoveInformationElement(a-1);
+            }
+        }
+    // reset user body
+    uData.SetBodyL(KNullDesC8);
+    } // CSmsMessage::ResetWorkingPDUL
+
+
+void CSmsMessage::CorrectFormattingL(TUint aCharsAddedToCurrentPDU,
+									 RPointerArray<CEmsInformationElement>& aCorrectedFormattingIEArray,
+									 TUint aCharsAlreadyAdded)
+	{
+	LOGGSMU3("CSmsMessage::CorrectFormattingL(): aCharsAddedToCurrentPDU=%d, aCharsAlreadyAdded=%d",
+			 aCharsAddedToCurrentPDU, aCharsAlreadyAdded);
+
+	CSmsUserData& uData = SmsPDU().UserData();
+	for (TInt a= 0; a < uData.NumInformationElements(); a++)
+		{
+		CSmsInformationElement& ie = uData.InformationElement(a);
+		if (CSmsInformationElement::ESmsEnhancedTextFormatting==ie.Identifier())
+			{
+			CEmsFormatIE& formatIE=static_cast<CEmsFormatIE&>(ie);
+
+			TUint oldFormatLen=formatIE.FormatLength(); //
+			if(aCharsAddedToCurrentPDU < formatIE.StartPosition() + oldFormatLen)
+				{
+				TUint newFormatLen=aCharsAddedToCurrentPDU - formatIE.StartPosition();
+				formatIE.SetFormatLength(newFormatLen);
+
+				// Now, re-encode the information element - this is because we have
+				// changed a message in the UserData which is using EMS elements as
+				// SMS IEs. Encoding is NOT automatic
+				formatIE.EncodeInformationElementL();
+
+				if((TInt)(aCharsAlreadyAdded+aCharsAddedToCurrentPDU) < iBuffer->Length())
+					{
+					CEmsFormatIE* newie=static_cast<CEmsFormatIE*>(formatIE.DuplicateL());
+					CleanupStack::PushL(newie);
+					newie->SetFormatLength(oldFormatLen - newFormatLen);
+					newie->SetStartPosition(aCharsAlreadyAdded+aCharsAddedToCurrentPDU);
+					LOGGSMU2("CSmsMessage::CorrectFormattingL",aCorrectedFormattingIEArray.Count());
+					aCorrectedFormattingIEArray.Append(newie);
+					CleanupStack::Pop(newie);
+					}
+				}
+			}
+		}
+	} // CSmsMessage::CorrectFormattingL
+
+
+void CSmsMessage::CorrectFormattingInSinglePDUL()
+	{
+	LOGGSMU1("CSmsMessage::CorrectFormattingInSinglePDUL()");
+
+	CSmsUserData& uData = SmsPDU().UserData();
+	for (TInt a= 0; a < uData.NumInformationElements(); a++)
+		{
+		CSmsInformationElement& ie = uData.InformationElement(a);
+		if (CSmsInformationElement::ESmsEnhancedTextFormatting==ie.Identifier())
+			{
+			CEmsFormatIE& formatIE=static_cast<CEmsFormatIE&>(ie);
+			TUint oldFormatLen=formatIE.FormatLength(); //
+			if(iBuffer->Length() < (TInt)(formatIE.StartPosition()+ oldFormatLen))
+				{
+				TUint newFormatLen=iBuffer->Length() - formatIE.StartPosition();
+				formatIE.SetFormatLength(newFormatLen);
+
+				// reencode
+				formatIE.EncodeInformationElementL();
+				}
+			}
+		}
+	} // CSmsMessage::CorrectFormattingInSinglePDUL
+
+
+/**
+ *  Adds a copy of the current PDU to the PDU array used to record all the
+ *  PDUs being encoded in a concatentated message.
+ * 
+ *  @param  aDoEncode  If true the PDU is added and updated. If false only a
+ *                     NULL placeholder is stored. This allows the number of
+ *                     PDUs to be quickly counted if the encoded PDUs are of
+ *                     no further use.
+ */
+void CSmsMessage::AddCurrentPDUToPDUArrayL(TBool aDoEncode)
+	{
+	LOGGSMU2("CSmsMessage::AddCurrentPDUToPDUArrayL(): Adding PDU number %d",
+			 iAdditionalInfo->SmsPDUArray().Count() + 1);
+	
+	//
+	// Maximum number of PDU is 255, so if we have that already then we cannot
+	// continue.
+	//
+	TInt  numPDUs = iAdditionalInfo->SmsPDUArray().Count();
+
+	if (numPDUs >= 255)
+		{
+		User::Leave(KErrOverflow);
+		}
+	
+	//
+	// We only do most of the work if we are actually encoding.
+	//
+	if (aDoEncode)
+		{
+		//
+		// Update the Concatenated Message PDU numbers in the current PDU. This
+		// means that at least the last PDU has the correct values (to update
+		// all PDUs when a new PDU is added would be too slow, so we do that
+		// only once at the end).
+		//
+		if (numPDUs > 0)
+			{
+			SmsPDU().SetConcatenatedMessagePDUIndex(numPDUs+1);
+			SmsPDU().SetNumConcatenatedMessagePDUs(numPDUs+1);
+			}
+	
+		//
+		// Create copy of the current PDU and store it in the array...
+		//
+		CSmsPDU*  newPDU = SmsPDU().DuplicateL();
+		CleanupStack::PushL(newPDU);
+		iAdditionalInfo->SmsPDUArray().AppendL(newPDU);
+		CleanupStack::Pop(newPDU);
+		}
+	else
+		{
+		//
+		// Otherwise just append a NULL value to allow the data PDUs to be
+		// counted...
+		//
+		iAdditionalInfo->SmsPDUArray().AppendL(NULL);
+		}
+	} // CSmsMessage::AddCurrentPDUToPDUArrayL
+
+
+TBool CSmsMessage::AddIEToUserDataL(CEmsInformationElement* aIE, TInt aCharsAlreadyAdded,TUint& aCharsAddedToCurrentPDU,CSmsEMSBufferSegmenter& aSeg)
+	{
+	LOGGSMU1("CSmsMessage::AddIEToUserDataL()");
+
+	TBool ieAdded=EFalse;
+	if (SmsPDU().UserData().EmsInformationElementWillFitL(aIE,aSeg,aCharsAddedToCurrentPDU))
+		{
+		CEmsInformationElement* newIE=aIE->DuplicateL();
+		newIE->SetStartPosition(newIE->StartPosition()-aCharsAlreadyAdded);
+	    CleanupStack::PushL(newIE);
+		SmsPDU().UserData().AddEmsInformationElementL(newIE);
+		CleanupStack::Pop(newIE);
+		ieAdded=ETrue;
+		}
+	return ieAdded;
+	} // CSmsMessage::AddIEToUserDataL
+
+
+/**
+ *  Fills the current PDU with the number of specified native chars.
+ *  
+ *  @param aSeg Buffer containing the native chars
+ *  @param aNumChars number of native characters to add.
+ *  @param aEncoding  SMS Encoding if required.
+ * 
+ *  @return TInt Number of native characters added
+ */
+TInt CSmsMessage::FillPduL(CSmsEMSBufferSegmenter& aSeg, TInt aNumChars, TSmsEncoding aEncoding)
+	{
+	LOGGSMU1("CSmsMessage::FillPduL()");
+
+	TUint maxUDUnitsREmaining=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+
+	if (aNumChars==0 || maxUDUnitsREmaining==0)
+		{
+		return 0;
+		}
+
+	HBufC8* buf=HBufC8::NewMaxLC(2*aNumChars);
+	TPtr8 ptr(buf->Des());
+	TInt numberOfUnconvertibleCharacters(0); 
+	TInt numberOfDowngradedCharacters(0);
+
+	TInt nativeLength = aSeg.SegmentL(ptr, aNumChars, maxUDUnitsREmaining,
+			                          numberOfUnconvertibleCharacters,
+			                          numberOfDowngradedCharacters,
+			                          aEncoding);
+
+	SmsPDU().UserData().AppendBodyL(ptr);
+
+	CleanupStack::PopAndDestroy(buf);
+	return nativeLength;
+	} // CSmsMessage::FillPduL
+
+
+/**
+ *  This method copies control information elements from the specified
+ *  collection into the working PDU.
+ *  
+ *  @param aCategory        The category of control information element to be
+ *                          added to the PDU.
+ *  @param aMandatoryInPDU  Specifies whether the specified category of information
+ *                          element must be added to this PDU.
+ *  @param aDoEncode        Flag indicating if encoding is really wanted, or just the
+ *                          calculation of the number of PDUs.
+ *
+ *  @leave KErrArgument     If the category is mandatory but one or more elements
+ *                          cannot be added then the encoding will fail.
+ *  @leave KErrOverFlow     If the information element is too big to be encoded into
+ *                          a PDU that contains only the mandatory elements.
+ */
+void CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::TInformationElementCategory aCategory,
+			                                                          TBool aMandatoryInPDU, TBool aDoEncode)
+    {
+    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL()");
+
+    TUint numberOfInformationElements = iAdditionalInfo->NumberOfControlInformationElements(aCategory);
+
+    for (TInt i = 0; i < numberOfInformationElements; i++)
+        {
+        CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( aCategory, i);
+
+        CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(informationElement.Identifier(),informationElement.Data());
+        CleanupStack::PushL(cloneInformationElement);
+
+        if (SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement))
+            {
+            SmsPDU().UserData().UpdateInformationElementArrayL(informationElement.Identifier(),informationElement.Data());
+            }
+        else if (aMandatoryInPDU)
+                {
+                // Error Scenario, cannot fit the mandatory PDU into the User Data
+                User::Leave(KErrArgument);
+                }
+             else
+                {
+                // Close off PDU and transfer to output array
+                AddCurrentPDUToPDUArrayL(aDoEncode);
+                ResetWorkingPDUL();
+
+                // Now test whether the information element will fit into a PDU at all.
+                // It is possible to make Enhanced Voice Mail Information Elements
+                // bigger than the available space in the PDU.
+                TBool canFit = SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement);
+                if (canFit == EFalse)
+                    {
+                    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessage, IE too bit to fit in any PDUL");
+                    User::Leave(KErrArgument);
+                    }
+                i--;
+                }
+
+        CleanupStack::PopAndDestroy(cloneInformationElement);
+        }
+    } // CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL
+
+
+/**
+ *  This method copies control information elements from the collections of
+ *  control information elements contained in CSmsAdditionalAttributes into the
+ *  working PDU.
+ *  
+ *  @param aDoEncode  Flag indicating if encoding is really wanted, or just the
+ *                    calculation of the number of PDUs.
+ *
+ *  @leave KErrArgument  If the category is mandatory but one or more elements
+ *                       cannot be added then the encoding will fail.
+ */
+void CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL(TBool aDoEncode)
+    {
+    LOGGSMU1("CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL() 1");
+
+    TBool mandatoryInEachPDU = ETrue;
+    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly,
+    													mandatoryInEachPDU, aDoEncode);
+    mandatoryInEachPDU = EFalse;
+    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlSingleInstanceOnly,
+    													mandatoryInEachPDU, aDoEncode);
+    AddControlInformationElementsToMultiSegmentMessageL(TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed,
+    													mandatoryInEachPDU, aDoEncode);
+    } // CSmsMessage::AddControlInformationElementsToMultiSegmentMessageL
+
+
+/**
+ *  Attempts to add EMS IE to the current PDU.
+ *  
+ *  @param aSegmenter                  Reference to buffer segmenter.
+ *  @param aCharsAddedToCurrentPDU     Returned number of characters added to current PDU.
+ *  @param aDoEncode                   Flag indicating if encoding is really wanted,
+ *                                     or just the calculation of the number of PDUs.
+ *  @param aEncoding                   SMS 7bit encoding if appropriate.
+ *  @param aCorrectedFormatingIEArray  Array of IEs that have to be placed in following
+ *                                     PDUs (e.g. corrected).
+ *  @param aCurrEMSIEno                Current IE number.
+ *  @param aCharsAlreadyAdded          Returned number of characters added.
+ *
+ *  @return Whether EMS IE has beenn added, in singleMode returns true if there are no more than one PDU.
+ */
+TBool CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL(CSmsEMSBufferSegmenter& aSegmenter,
+																   TUint& aCharsAddedToCurrentPDU,
+																   TBool aDoEncode,
+																   TSmsEncoding& aEncoding,
+																   RPointerArray<CEmsInformationElement>& aCorrectedFormatingIEArray,
+																   TUint& aCurrEMSIEno,
+																   TUint& aCharsAlreadyAdded)
+	{
+	LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL()");
+
+	TUint startPosition=0;
+
+	 // number of chars added to the current PDU
+	TUint no=iInformationElementArray->Count();
+	LOGGSMU2("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL no of IE %d",no);
+	CEmsInformationElement* ie = NULL;
+	TUint msgLen=iBuffer->Length();
+	TUint filledChars=0;
+
+	while(aCurrEMSIEno < no || aCorrectedFormatingIEArray.Count() > 0)
+	{
+		ie = NULL;
+		TBool correction=EFalse;
+		if(aCurrEMSIEno < no)
+			{
+			ie = (*iInformationElementArray)[aCurrEMSIEno];
+			startPosition=ie->StartPosition();
+			}
+
+		if(ie == NULL || ( startPosition != aCharsAlreadyAdded) )
+		{
+			if(aCorrectedFormatingIEArray.Count() > 0)
+			{
+				correction=ETrue;
+				ie = aCorrectedFormatingIEArray[0];
+				startPosition=ie->StartPosition();
+			}
+		}
+
+		__ASSERT_ALWAYS(ie !=NULL, User::Leave(KErrCorrupt));
+
+		if(startPosition <= msgLen)
+			{
+			__ASSERT_DEBUG(startPosition>=aCharsAlreadyAdded, User::Leave(KErrUnderflow));
+			startPosition -= aCharsAlreadyAdded; // startPosition now relative to current PDU.
+
+			// Add all chars upto startposition.
+			filledChars=0;
+
+			if(startPosition > aCharsAddedToCurrentPDU)
+				{
+				filledChars = FillPduL(aSegmenter, startPosition-aCharsAddedToCurrentPDU, aEncoding);
+				aCharsAddedToCurrentPDU+=filledChars;
+				}
+
+			LOGGSMU2("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: filled %d chars", filledChars);
+
+			if (aCharsAddedToCurrentPDU==startPosition)
+				{
+				// Try adding the IE.
+				if (AddIEToUserDataL(ie, aCharsAlreadyAdded,aCharsAddedToCurrentPDU,aSegmenter))
+					{
+					if(correction)
+					{
+						aCorrectedFormatingIEArray.Remove(0);
+						// aCorrectedFormatingIEArray[0] has been removed. In next loop, ie will point another element. So there is no double free.
+						// coverity[double_free]
+						delete ie;
+						correction=EFalse;
+					}
+					else aCurrEMSIEno++;
+					}
+				else
+					{
+					// Information Element will not fit send PDU
+					LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: ie will not fit send Message");
+					CorrectFormattingL(aCharsAddedToCurrentPDU,aCorrectedFormatingIEArray,aCharsAlreadyAdded);
+
+					aCharsAlreadyAdded += aCharsAddedToCurrentPDU;
+					aCharsAddedToCurrentPDU=0;
+
+					AddCurrentPDUToPDUArrayL(aDoEncode);
+					ResetWorkingPDUL();
+
+					//
+					// Find the encoding method for the next segment...
+					//
+					//aEncoding = ESmsEncodingNone;
+					//TRAP_IGNORE(aEncoding = aSegmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
+					//												                   maxBodyLength));
+					SmsPDU().SetNationalLanguageEncodingL(aEncoding);
+					}
+				}
+			else
+				{
+				// native chars upto start position will not fit send PDu.
+				LOGGSMU1("CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL: PDU is filled with chars sending");
+
+				CorrectFormattingL(aCharsAddedToCurrentPDU,aCorrectedFormatingIEArray,aCharsAlreadyAdded);
+
+				aCharsAlreadyAdded += aCharsAddedToCurrentPDU;
+				aCharsAddedToCurrentPDU=0;
+
+				AddCurrentPDUToPDUArrayL(aDoEncode);
+				ResetWorkingPDUL();
+
+				//
+				// Find the encoding method for the next segment...
+				//
+				//aEncoding = ESmsEncodingNone;
+				//TRAP_IGNORE(aEncoding = aSegmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
+				//												                   maxBodyLength));
+				SmsPDU().SetNationalLanguageEncodingL(aEncoding);
+				}
+			}
+		else
+			{
+			aCurrEMSIEno++;
+			}
+		}		// end of while loop for all IEs
+
+	return ETrue;
+	} // CSmsMessage::AddEMSInformationElementsToMultiSegmentMessageL
+
+
+/**
+ *  Attempts to add EMS IE to the current PDU
+ *  
+ *  @param aSegmenter
+ *  @return TBool whether EMS IEs have been added to segment
+ */
+TBool CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL(CSmsEMSBufferSegmenter& aSegmenter,
+																	TSmsEncoding aEncoding)
+	{
+	LOGGSMU1("CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL()");
+
+	TUint charsAddedToCurrentPDU=0;
+	TUint numOfEmsIE=iInformationElementArray->Count();
+	TUint currEmsIEindex=0;
+	CEmsInformationElement* ie = NULL;
+	TUint startPosition=0;
+	TUint filledChars=0;
+
+	while(currEmsIEindex < numOfEmsIE)
+		{
+		ie = (*iInformationElementArray)[currEmsIEindex];
+		startPosition=ie->StartPosition();
+
+		if (startPosition > charsAddedToCurrentPDU)
+			{
+			filledChars = FillPduL(aSegmenter, startPosition-charsAddedToCurrentPDU, aEncoding);
+			charsAddedToCurrentPDU+=filledChars;
+			}
+
+		if (charsAddedToCurrentPDU != startPosition ||
+			!AddIEToUserDataL(ie, 0,charsAddedToCurrentPDU,aSegmenter))
+			{
+			return EFalse;
+			}
+
+		++currEmsIEindex;
+		}
+
+	return ETrue;
+	} // CSmsMessage::AddEMSInformationElementsToSingleSegmentMessageL
+
+
+/**
+ *  Encode the PDU into an TGsmSms array. The Text and the EMS objects are
+ *  laid out with respect to start position locations and encoded into the
+ *  correct TGsmSms object.
+ *  
+ *  @leave KErrUnderflow if the Ems objects are not in Start position order.
+ *
+ *  @param aSmsArray               Returned array of newly created TSms objects
+ *                                 containing the encoded message.
+ *  @param aReference              Unique reference number to be given to the
+ *                                 TGsmSms objects.
+ *  @param aBuffer                 Body Text buffer of the message.
+ *  @param aUnconvertedChars       Exit param for the number of characters not converted.
+ *  @param aDowngradedChars        Exit param for the number of characters downgraded.
+ *  @param aFreeUDUnitsInLastPDU   Exit param for the number of characters free
+ *                                 in the last PDU.
+ *  @param aDoEncode               Flag indicating if encoding is really wanted,
+ *                                 or just the calculation of the number of PDUs.
+ */
+void CSmsMessage::EncodeBufferL(CArrayFix<TGsmSms>& aSmsArray, TInt aReference,
+								const CSmsBufferBase& aBuffer,
+								TInt& aUnconvertedChars, TInt& aDowngradedChars,
+						        TInt& aFreeUDUnitsInLastPDU, TBool aDoEncode)
+	{
+	LOGGSMU1("CSmsMessage::EncodeBufferL()");
+
+	aUnconvertedChars     = 0;
+	aDowngradedChars      = 0;
+	aFreeUDUnitsInLastPDU = 0;
+	
+	//
+	// Reset the working array of PDUs...
+	//
+	iAdditionalInfo->SmsPDUArray().ResetAndDestroy();
+
+	TUint currEMSIEno(0);
+	
+	TInt smscIndex(0);
+	TBool smscPresent(EFalse);
+	
+	TInt emailOverallHeaderLength(0);
+	TInt emailIndex(0);
+	TBool emailPresent(EFalse);
+	
+	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+		{
+		smscPresent=ETrue;
+		}
+	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
+		{
+		emailPresent=ETrue;
+		emailOverallHeaderLength=SmsPDU().UserData().InformationElement(emailIndex).Data()[0];
+		}
+
+	//
+	// Create Array for corrected format elements. These will be elements that
+	// have to be moved into subsequent PDUs due to lack of space in the
+	// current PDU.
+	//
+	RPointerArray<CEmsInformationElement>  correctedFormatingIEArray(2);
+	CleanupResetAndDestroyPushL(correctedFormatingIEArray);
+
+	//
+	// Reset the working PDU. This safes time be keeping fields we need and
+	// droping any data from previous PDUs.
+	//
+	ResetWorkingPDUL();
+
+	//
+	// Automatically prepare for concatenation (any single PDU messages would
+	// have been handled by EncodeIntoSinglePDUL() previously).
+	//
+	SmsPDU().SetTextConcatenatedL(ETrue,iIs16BitConcatenation);
+
+	TInt maxBodyLength=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+
+	//
+	// Add any elements that are required to be present, and ensure they
+	// have correct data stored (for example if we are recycling the working PDU).
+	//
+	AddControlInformationElementsToMultiSegmentMessageL(aDoEncode);
+
+	//
+	// Create EMS Segmenter and Buffer Converter...
+	//
+	CSmsAlphabetConverter*  converter = CSmsAlphabetConverter::NewLC(*iCharacterSetConverter, iFs,SmsPDU().Alphabet(),
+			                                                         BinaryData());
+	CSmsEMSBufferSegmenter*  segmenter = CSmsEMSBufferSegmenter::NewLC(*converter, aBuffer, maxBodyLength);
+	TBool  isUnicode = (SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabetUCS2);
+
+	TBool informationToSend     = ETrue;
+	TUint charsAdded2CurrentPDU = 0;
+	TUint charsAlreadyAdded     = 0;
+
+	//
+	// Find the best alternative encoding for the current segment. This will be
+	// set at the beginning of each PDU using the list of encoders.
+	//
+	TSmsEncoding  encodingToUse = ESmsEncodingNone;
+
+	TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->Alternative7bitEncoding(),
+													                    aBuffer.Length()));
+	SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
+	
+	//
+	// If there are information elements to add, add them to the first PDU (or
+	// to the correct formatting array for later PDUs if more appropriate).
+	//
+	if(iInformationElementArray->Count() >0)
+		{
+		AddEMSInformationElementsToMultiSegmentMessageL(*segmenter, charsAdded2CurrentPDU,
+														aDoEncode, encodingToUse,
+														correctedFormatingIEArray,
+														currEMSIEno, charsAlreadyAdded);
+		}
+
+	//
+	// Allocate a temporary buffer to work with...
+	//
+	HBufC8* buf=HBufC8::NewMaxLC(maxBodyLength);
+	TPtr8 ptr(buf->Des());
+
+	//
+	// While there is still data to encode see how much space is left in this
+	// PDU and attempt to encode something into it...
+	//
+	while (segmenter->MoreL())
+			{
+			LOGGSMU1("CSmsMessage::EncodeBufferL - there is MoreL");
+			
+			//
+			// Calculate the space left to use in this PDU...
+			//
+			TInt size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+			LOGGSMU2("CSmsMessage::EncodeBufferL - remaining size in PDU is %d",size);
+
+			//
+			// While there is no space, correct the formatting (which may
+			// introduce any un-placed EMS Elements into the corrected format
+			// array) and then start a new PDU...
+			//
+			while (size==0)
+				{
+				//
+				// Store any elements not yet placed into the array for later...
+				//
+				CorrectFormattingL(charsAdded2CurrentPDU, correctedFormatingIEArray, charsAlreadyAdded);
+
+				//
+				// Store this PDU, reset the working PDU and get ready to
+				// continue with the next PDU...
+				//
+				aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+				AddCurrentPDUToPDUArrayL(aDoEncode);
+				ResetWorkingPDUL();
+				informationToSend=EFalse;
+				charsAlreadyAdded+=charsAdded2CurrentPDU;
+				charsAdded2CurrentPDU=0;
+
+				//
+				// Find the encoding method for the next segment...
+				//
+				//encodingToUse = ESmsEncodingNone;
+				//TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
+				//												                    maxBodyLength));
+				SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
+
+				//
+				// Add any elements that can be placed now (from previous
+				// PDUs and above)... 
+				//
+				LOGGSMU3("CSmsMessage::EncodeBufferL: IE count  %d corrected  count %d",iInformationElementArray->Count(),correctedFormatingIEArray.Count() );
+				if ((TUint)iInformationElementArray->Count() > currEMSIEno  ||
+					correctedFormatingIEArray.Count() > 0)
+					{
+					AddEMSInformationElementsToMultiSegmentMessageL(*segmenter,charsAdded2CurrentPDU,
+																	aDoEncode, encodingToUse,
+																	correctedFormatingIEArray,
+																	currEMSIEno,charsAlreadyAdded);
+					}
+
+				//
+				// Calculate the space left remaining in this new PDU...
+				//
+				size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+				LOGGSMU2("CSmsMessage::EncodeBufferL - remaining size in PDU is %d",size);
+				}
+			
+			//
+			// We have space in this PDU and no elements to place, so obtain
+			// the next peice of text that can fit and append it.
+			//
+			segmenter->SegmentNextL(ptr, size, aUnconvertedChars, aDowngradedChars, encodingToUse);
+			SmsPDU().UserData().AppendBodyL(ptr);
+
+			TUint charsInSegment= isUnicode ? ptr.Length()/2 : ptr.Length();
+			LOGGSMU2("CSmsMessage::EncodeBufferL: segmenting added %d chars", charsInSegment);
+
+			//
+			// At this point the working PDU is either full (e.g. we filled the
+			// remaining space with a chuck of text, or the is some space as we
+			// stored the last part of the text.
+			//
+			// If there are any elements not yet stored, add them to the
+			// formatting array...
+			//
+			charsAdded2CurrentPDU+=charsInSegment;
+			CorrectFormattingL(charsAdded2CurrentPDU, correctedFormatingIEArray, charsAlreadyAdded);
+			charsAlreadyAdded+=charsAdded2CurrentPDU;
+			LOGGSMU2("CSmsMessage::EncodeBufferL(): charsAlreadyAdded=%d", charsAlreadyAdded);
+			
+			//
+			// Now store this PDU and reset the working PDU...
+			//
+			aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+			AddCurrentPDUToPDUArrayL(aDoEncode);
+			ResetWorkingPDUL();
+			informationToSend=EFalse;
+			charsAdded2CurrentPDU=0;
+			
+			//
+			// Find the encoding method for the next segment...
+			//
+			//encodingToUse = ESmsEncodingNone;
+			//TRAP_IGNORE(encodingToUse = segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->iAlternative7bitEncoding,
+			//												                    maxBodyLength));
+			SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
+
+			//
+			// Add any elements that can be placed now given we have a new
+			// empty PDU... 
+			//
+			LOGGSMU3("CSmsMessage::EncodeBufferL: IE count  %d corrected  count %d",
+			         iInformationElementArray->Count(), correctedFormatingIEArray.Count() );
+			if ((TUint)iInformationElementArray->Count() > currEMSIEno  ||
+				correctedFormatingIEArray.Count() > 0)
+				{
+				AddEMSInformationElementsToMultiSegmentMessageL(*segmenter, charsAdded2CurrentPDU,
+																aDoEncode, encodingToUse,
+																correctedFormatingIEArray,
+																currEMSIEno, charsAlreadyAdded);
+				}
+			LOGGSMU1("CSmsMessage::EncodeBufferL end Moreloop");
+			}
+	CleanupStack::PopAndDestroy(buf);
+
+	LOGGSMU1("CSmsMessage::EncodeBufferL - last PDU");
+	
+	//
+	// This is the last PDU. We need to check if there is a partial PDU left over
+	// and add it if needed.
+	//
+	if (informationToSend)
+		{
+		aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+		AddCurrentPDUToPDUArrayL(aDoEncode);
+		ResetWorkingPDUL();
+		}
+
+	//
+	// At this point the segmenting and layouts of PDU is complete, so if we
+	// find any more data something is wrong...
+	//
+	if (segmenter->MoreL()  ||  correctedFormatingIEArray.Count() > 0)
+		{
+		User::Leave(KErrCorrupt);
+		}
+
+	CleanupStack::PopAndDestroy(3, &correctedFormatingIEArray); // segmenter, converter & correctedFormatingIEArray
+
+	//
+	// By now the PDUs are segmented and correctly setup for encoding.
+	// They have not been encoded yet, as this requires the PDU total to be known.
+	// So we go through the array setting the final PDU number/total PDUs and
+	// perform the encoding from CSmsPDU to the TGsmPdu object.
+	//
+	// Note: In the case were aDoEncode is EFalse, iSmsPDUArray will be full
+	//       of NULL pointers as it is only the count that we need in that case.
+	//
+	TInt  numPDUs = iAdditionalInfo->SmsPDUArray().Count();
+
+	LOGGSMU2("CSmsMessage::EncodeBufferL number of PDUs: %d", iAdditionalInfo->SmsPDUArray().Count());
+	
+	if (aDoEncode)
+		{
+		CSmsMessageAdditionalAttributes::CSmsStatusReportScheme&  scheme = iAdditionalInfo->GetStatusReportScheme();
+		TGsmSms  gsmSms;
+		
+		for (TInt pdu = 0;  pdu < numPDUs;  pdu++)
+			{
+			if(scheme.Id() == EControlParametersScheme)
+				{
+				if(smscPresent)				
+					{
+					CSmsSMSCCtrlParameterOperations&  ieOp = (CSmsSMSCCtrlParameterOperations&)GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters);
+					TUint8 octet(0);
+
+					if (ieOp.GetStatusReport(pdu, octet) == KErrNone)
+						{					
+						iAdditionalInfo->SmsPDUArray()[pdu]->UpdateSMSCCtrlParameterL(octet);
+						}
+					}
+				else
+					{
+					User::Leave(KErrNotFound);
+					}
+				}
+			else if(scheme.Id() == ETPSRRScheme)
+				{
+				TSmsFirstOctet smsReportRequest;
+				CSmsTPSRROperations& nonIEOp = (CSmsTPSRROperations&)GetOperationsForNonIEL(ESmsTPSRRParameter);
+				smsReportRequest = nonIEOp.GetStatusReport(pdu);
+								
+				iAdditionalInfo->SmsPDUArray()[pdu]->UpdateTPSRRL(smsReportRequest);
+				}
+
+			if(emailPresent)				
+				{
+				iAdditionalInfo->SmsPDUArray()[pdu]->UpdateEmailHeaderDataL(emailOverallHeaderLength);
+				}
+
+			//
+			// Set the concatenation Message Reference number and PDU numbers...
+			//
+			iAdditionalInfo->SmsPDUArray()[pdu]->UpdateConcatenationDataL(aReference, pdu+1, numPDUs);
+
+			//
+			// Encode this PDU...
+			//
+			
+			TEncodeParams encodeParams;
+			encodeParams.iTimeStamp = &Time();
+			
+			TTimeIntervalSeconds interval = UTCOffset();
+			encodeParams.iTimeIntervalInSeconds = &interval;
+						
+			iAdditionalInfo->SmsPDUArray()[pdu]->EncodeMessagePDUL(gsmSms, &encodeParams);
+	 		aSmsArray.AppendL(gsmSms);
+			}
+
+		//
+		// Since the working PDU has been reset the data in it does not match
+		// the data of the last PDU. Some tests in SMS Stack assume it does
+		// and therefore to retain compatibility we decode the last PDU back
+		// over the working PDU.
+		//
+		TGsmuLex8 lex(gsmSms.Pdu());
+		SmsPDU().DecodeL(lex);
+		}
+	} // CSmsMessage::EncodeBufferL
+
+
+/**
+ *  Attempts to encode into the single PDU. This function is the private version
+ *  to the public EncodeIntoSinglePDUL() function. It performs the work and also
+ *  returns more information regarding the characters encoded.
+ *  
+ *  The Text and the EMS objects are laid out with respect to start position
+ *  locations.
+ *  
+ *  @leave KErrUnderflow if the Ems objects are not in Start position order.
+ *
+ *  @param aSmsArray               Returned array of newly created TSms objects
+ *                                 containing the encoded message.
+ *  @param aUnconvertedChars       Exit param for the number of characters not converted.
+ *  @param aDowngradedChars        Exit param for the number of characters downgraded.
+ *  @param aFreeUDUnitsInLastPDU   Exit param for the number of characters free
+ *                                 in the last PDU.
+ */
+TBool CSmsMessage::EncodeIntoSinglePDUL(CArrayFix<TGsmSms>& aSmsArray, TInt& aUnconvertedChars,
+		                                TInt& aDowngradedChars, TInt& aFreeUDUnitsInLastPDU)
+	{
+	LOGGSMU1("CSmsMessage::EncodeIntoSinglePDUL()");
+
+	__ASSERT_DEBUG((aSmsArray.Count()==0),Panic(KGsmuPanicSmsArrayNotEmpty));
+
+	aUnconvertedChars     = 0;
+	aDowngradedChars      = 0;
+	aFreeUDUnitsInLastPDU = 0;
+
+	iAdditionalInfo->SmsPDUArray().ResetAndDestroy();
+
+	if (!TextPresent())
+		{
+        if(SmsPDU().Type()==CSmsPDU::ESmsCommand)
+            {
+            // Commands don't contain text, so commands
+            // are only encoded in this branch.
+            PrepareCommandMessageL();
+            }
+
+		TGsmSms sms;
+		SmsPDU().EncodeMessagePDUL(sms);
+		aSmsArray.AppendL(sms);
+		return ETrue;
+		}
+
+	ResetWorkingPDUL();
+
+    // find the length of all the control information elements
+    TUint ieLength=0;
+    for (TUint8 category = 0; category <  TSmsInformationElementCategories::ENumberOfCategories; category++)
+        {
+        switch (category)
+            {
+            case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
+            case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
+            case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
+                {
+                for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
+                    {
+                    ieLength += iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j).Length();
+                    }
+                break;
+                }
+            default:
+                break;
+            }
+        }
+    LOGGSMU2("CSmsMessage::EncodeIntoSinglePDUL, ctrl elem len = %d", ieLength);
+
+	CEmsInformationElement* emsIE =NULL;
+	for (TInt num=0; num<iInformationElementArray->Count();num++)
+		{
+		emsIE = (*iInformationElementArray)[num];
+        ieLength+=emsIE->Length();
+		}
+
+	TInt remainInBody=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining(ieLength);
+
+	TInt msgLength=MessageLengthL(); // in octets
+
+	if( msgLength > remainInBody) return EFalse;
+
+    LOGGSMU4("CSmsMessage::EncodeIntoSinglePDUL, ie len = %d, remainInBody = %d, msgLength = %d", ieLength, msgLength, remainInBody);
+    //  add all control information elements into working PDU.
+    //
+    for (TUint8 category = 0; category <  TSmsInformationElementCategories::ENumberOfCategories; category++)
+        {
+        switch (category)
+            {
+            case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
+            case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
+            case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
+                {
+                for (TUint j = 0; j < iAdditionalInfo->NumberOfControlInformationElements((CSmsMessageAdditionalAttributes::TCategory) category); j++)
+                    {
+                    CSmsInformationElement& informationElement = iAdditionalInfo->GetControlInformationElementL( ( (CSmsMessageAdditionalAttributes::TCategory) category), j);
+
+                    CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(informationElement.Identifier(),informationElement.Data());
+                    CleanupStack::PushL(cloneInformationElement);
+                    TBool willFit = SmsPDU().UserData().ControlInformationElementWillFitL(cloneInformationElement);
+                    CleanupStack::PopAndDestroy(cloneInformationElement);
+
+                    if (willFit)
+                        {
+                        SmsPDU().UserData().UpdateInformationElementArrayL(informationElement.Identifier(),informationElement.Data());
+                        }
+                    else
+                        {
+                        ResetWorkingPDUL();
+                        return EFalse;
+                        }
+                    }
+                break;
+                }
+            default:
+                break;
+            }
+        }
+		
+	EncodingTPSRRFromSchemesIntoSinglePDUL();
+
+	TInt maxBodyLength=SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,SmsPDU().Alphabet(),BinaryData());
+	CSmsEMSBufferSegmenter* segmenter=CSmsEMSBufferSegmenter::NewLC(*converter,*iBuffer, maxBodyLength);
+
+	//
+	// Find the best alternative encoding for the current segment. This will be
+	// set at the beginning of each PDU using the list of encoders.
+	//
+	TSmsEncoding  encodingToUse = ESmsEncodingNone;
+
+	TRAP_IGNORE(encodingToUse= segmenter->FindBestAlternativeEncodingL(iAdditionalInfo->Alternative7bitEncoding(),
+													                   maxBodyLength));
+	SmsPDU().SetNationalLanguageEncodingL(encodingToUse);
+	
+	if(!AddEMSInformationElementsToSingleSegmentMessageL(*segmenter, encodingToUse))
+		{
+		aSmsArray.Reset();
+		CleanupStack::PopAndDestroy(2, converter);
+		return EFalse;
+		}
+
+	if(segmenter->MoreL())
+			{
+			TInt size = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+			// Defensive code to prevent SegmentNextL being called with size of zero
+			if (size == 0)
+				{
+				CleanupStack::PopAndDestroy(2, converter);
+				aSmsArray.Reset();
+				return EFalse;
+				}
+			HBufC8* buf=HBufC8::NewMaxLC(maxBodyLength);
+			TPtr8 ptr(buf->Des());
+			segmenter->SegmentNextL(ptr, size, aUnconvertedChars, aDowngradedChars, encodingToUse);
+			SmsPDU().UserData().AppendBodyL(ptr);
+			CleanupStack::PopAndDestroy(buf);
+			}
+	CorrectFormattingInSinglePDUL();
+
+	if (segmenter->MoreL())
+		{
+		CleanupStack::PopAndDestroy(2, converter);
+		aSmsArray.Reset();
+		return EFalse;
+		}
+	CleanupStack::PopAndDestroy(2, converter);
+
+	aFreeUDUnitsInLastPDU = SmsPDU().UserData().MaxPackedUDUnitsInBodyRemaining();
+
+	//
+	// Encode the PDU...
+	//
+	TGsmSms  gsmSms;
+		
+	TEncodeParams encodeParams;
+	encodeParams.iTimeStamp = &Time();
+		
+	TTimeIntervalSeconds interval = UTCOffset();
+	encodeParams.iTimeIntervalInSeconds = &interval;
+		
+	SmsPDU().EncodeMessagePDUL(gsmSms, &encodeParams);
+	aSmsArray.AppendL(gsmSms);
+
+	return ETrue;
+	} // CSmsMessage::EncodeIntoSinglePDUL
+
+
+/**
+ *  Attempts to encode into the single PDU
+ *  The Text and the EMS objects are layed out with respect to start position locations and encoded into the correct Tsms object.
+ *  Ensure this function is called before EncodeMessagePDUsL to properly process single PDU messages
+ *  
+ *  @return KErrUnderflow if the Ems objects are not in Start position order.
+ *  @param aSmsArray returned array of newly created TSms objects containing the encoded message
+ *  
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::EncodeIntoSinglePDUL(CArrayFix<TGsmSms>& aSmsArray)
+	{
+	LOGGSMU1("CSmsMessage::EncodeIntoSinglePDUL()");
+	
+	TInt  unconvertedChars, downgradedChars, freeUDUnitsInLastPDU;
+	
+	return EncodeIntoSinglePDUL(aSmsArray, unconvertedChars,
+                                downgradedChars, freeUDUnitsInLastPDU);
+	} // CSmsMessage::EncodeIntoSinglePDUL
+
+
+void CSmsMessage::EncodingTPSRRFromSchemesIntoSinglePDUL()
+	{
+	TInt smscIndex(0);
+	TBool smscPresent(EFalse);
+	
+	CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();	
+	if(scheme.Id() == EControlParametersScheme)
+		{
+		if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+			{
+			smscPresent=ETrue;
+			}
+		if(smscPresent)				
+			{
+			TUint8 octet(0);
+
+			CSmsSMSCCtrlParameterOperations& ieOp = (CSmsSMSCCtrlParameterOperations&)GetOperationsForIEL(CSmsInformationElement::ESmsIEISMSCControlParameters);
+			
+			if (ieOp.GetStatusReport(0, octet) == KErrNone)
+				{
+				if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+					{
+					SmsPDU().UserData().InformationElement(smscIndex).Data()[0] = octet;
+					if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
+						{
+						((CSmsSubmit&)SmsPDU()).SetStatusReportRequest(ETrue);	
+						}
+					else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
+						{
+						((CSmsDeliver&)SmsPDU()).SetStatusReportIndication(ETrue);
+						}
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);	
+					}	
+				}
+			}
+		else
+			{
+			User::Leave(KErrNotFound);
+			}	
+		}
+	else if(scheme.Id() == ETPSRRScheme)
+		{
+		TSmsFirstOctet smsReportRequest;
+		CSmsTPSRROperations& nonIEOp = (CSmsTPSRROperations&)GetOperationsForNonIEL(ESmsTPSRRParameter);
+		smsReportRequest = nonIEOp.GetStatusReport(0);
+		
+		if(smsReportRequest>=0)
+			{
+			if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
+				{
+				((CSmsSubmit&)SmsPDU()).SetStatusReportRequest(smsReportRequest);	
+				}
+			else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
+				{
+				((CSmsDeliver&)SmsPDU()).SetStatusReportIndication(smsReportRequest);
+				}	
+			}
+		}	
+	} // CSmsMessage::EncodingTPSRRFromSchemesIntoSinglePDUL
+
+
+/**
+ *  Decode CSmsMessage
+ *  
+ *  @param aUserData Object containing the EMS objects.
+ *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
+ *  of the UserData.
+ */
+void CSmsMessage::DecodeBufferL(CArrayPtr<CSmsPDU>& aSmsPDUArray,
+								CSmsBufferBase& aBuffer)
+	{
+	LOGGSMU1("CSmsMessage::DecodeBufferL()");
+
+	iInformationElementArray->ResetAndDestroy();
+
+	TSmsStatusReportScheme schemeId = FindSchemeL(aSmsPDUArray);
+	
+	TInt emailLen(0);
+	for (TInt i=0; i<aSmsPDUArray.Count(); i++)
+		{
+		CSmsUserData& usrData = (aSmsPDUArray)[i]->UserData();
+		InstallControlInformationElementsL(usrData, i);
+		InstallEmsInformationElementsL(usrData, aBuffer.Length());
+        // Possible refactoring opportunity:
+        // This would be a good place to add a method which provides processing for control information
+        // elements which contain values specific to the pdu (as opposed to being constant in every PDU.
+        InstallEmailHeaderInformationElementL(usrData,emailLen);
+        if(schemeId == ETPSRRScheme)
+        	{
+        	InstallTPSRRInformationL(aSmsPDUArray, i);
+        	}
+        
+		CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,aSmsPDUArray[i]->Alphabet(),BinaryData());
+		TSmsBufferReassembler reassembler(*converter,aBuffer);
+        TSmsEncoding  encodingUsedInSegment = aSmsPDUArray[i]->NationalLanguageEncoding();
+		
+        reassembler.ReassembleNextL(usrData.Body(),
+									encodingUsedInSegment,
+									i==(aSmsPDUArray.Count()-1));
+        
+		CleanupStack::PopAndDestroy(converter);		
+		MergeAlternative7bitEncoding(encodingUsedInSegment);
+		}
+
+    // Possible refactoring opportunity:
+    // This would be a good place to add a method which provides processing for control information
+    // elements which contain values specific to the pdu (as opposed to being constant in every PDU.
+    if(emailLen>0)
+		{
+		if(emailLen>255)
+			User::Leave(KErrTooBig);
+		TBuf8<1> data;
+		data.SetLength(1);
+		data[0]=static_cast<TUint8>(emailLen);
+		TInt emailIndex;
+		if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
+			SmsPDU().UserData().InformationElement(emailIndex).Data()[0]=static_cast<TInt8>(emailLen);
+		else
+			SmsPDU().UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIRFC822EmailHeader,data);
+		}
+	UpdateUserPromptAndODIElementsStartPosition();
+	} // CSmsMessage::DecodeBufferL
+
+/**
+ *  It decodes only raw text data.
+ *  
+ *  @param aSmsPDUArray Object containing PDUs.
+ *  @param aBuffer where the decoded data will be stored.
+ *
+ */
+void CSmsMessage::DecodeOnlyTextL(CArrayPtr<CSmsPDU>& aSmsPDUArray,
+								CSmsBufferBase& aBuffer)
+	{
+	LOGGSMU1("CSmsMessage::DecodeOnlyTextL()");
+
+	for (TInt i=0; i<aSmsPDUArray.Count(); i++)
+		{
+        CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*iCharacterSetConverter,iFs,aSmsPDUArray[i]->Alphabet(),BinaryData());
+        TSmsBufferReassembler reassembler(*converter,aBuffer);
+		TSmsEncoding  encodingUsedInSegment = aSmsPDUArray[i]->NationalLanguageEncoding();
+        
+		reassembler.ReassembleNextL(aSmsPDUArray[i]->UserData().Body(),
+									encodingUsedInSegment,
+									i==(aSmsPDUArray.Count()-1));
+		
+		CleanupStack::PopAndDestroy(converter);
+		MergeAlternative7bitEncoding(encodingUsedInSegment);
+		}
+	} // CSmsMessage::DecodeBufferL
+
+/**
+ *  It adds the incomplete message info in additional attribute field.
+ *  
+ *  @param aStartPDU starting PDU index of incomplete message.
+ *  @param aEndPDU end PDU index of incomplete message.
+ *  @param aLastPartialCompleteMsg boolean value indicating whether 
+ 				this message is the last incomplete message sent to client.
+ */
+void CSmsMessage::AddIncompleteMessageInfoL(TInt aStartPDU, TInt aEndPDU, TBool aLastPartialCompleteMsg)
+	{
+	LOGGSMU1("CSmsMessage::AddIncompleteMessageInfoL()");
+
+	CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo&) iAdditionalInfo->GetNonIEOperationL(ESmsIncompleteClass0MessageParameter);
+	incompleteClass0MsgInfo.SetVersion(CIncompleteClass0MessageInfo::ESmsIncompleteClass0MessageV0);
+	incompleteClass0MsgInfo.SetIncompleteMessageInfoL(aStartPDU, aEndPDU, aLastPartialCompleteMsg);
+	}
+
+/**
+ *  This method copies control information elements from the user data (passed as an
+ *  input argument) into either the CSmsMessage's user data (working pdu) OR one of the
+ *  collection of control information elements (sorted by category) which is contained
+ *  in CSmsMessage::iAdditionalInfo.
+ *  
+ *  @param aUserData
+ *  The user data which is currently being processed, and whose elements may be copied
+ *  into the appropriate collection belonging to the CSmsMessage.
+ *  @leave
+ *  KErrArgument if an information element's type is unknown
+ *  
+ *  @internalComponent
+ */
+void CSmsMessage::InstallControlInformationElementsL(CSmsUserData& aUserData, TInt aSegmentSequenceNum)
+    {
+	// Installs all the information elements within the subsequent PDUs.
+	LOGGSMU1("CSmsMessage::InstallControlInformationElements()");
+
+    CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();
+    
+	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
+		{
+		const CSmsInformationElement& ie = aUserData.InformationElement(z);
+
+         TSmsInformationElementCategories::TInformationElementCategory category;
+
+        if (TSmsInformationElementCategories::GetCategoryDefinition(ie.Identifier(), category))
+        	{
+            switch (category)
+                {
+                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU: // e.g. Special SMS Message Indication
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements \
+                    ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU id = %d", ie.Identifier());
+
+                    if (ie.Identifier()== CSmsInformationElement::ESmsIEISpecialSMSMessageIndication)
+                        {
+                        TBool found = EFalse;
+                        CArrayFixFlat<TInt>* indices = new(ELeave) CArrayFixFlat<TInt>(4);
+                        CleanupStack::PushL(indices);
+                        SmsPDU().UserData().InformationElementIndicesL(ie.Identifier(), *indices);
+
+                        TInt count = indices->Count();
+		                for (TInt i=0; ((i<count) && (found==EFalse)); i++)
+		                    {
+		                    TUint index = indices->operator[](i);
+		                    CSmsInformationElement& ieAlreadyInWorkingPDU = SmsPDU().UserData().InformationElement(index);
+
+                            if (ieAlreadyInWorkingPDU.Data()[0] == ie.Data()[0])
+                                {
+                                ieAlreadyInWorkingPDU.Data()[1] = ie.Data()[1];
+                                found = ETrue;
+                                break;
+                                }
+		                    }
+                        CleanupStack::PopAndDestroy(indices);
+
+                        if (found == EFalse)
+                            {
+                            SmsPDU().UserData().UpdateInformationElementArrayL(ie.Identifier(),ie.Data());
+                            }
+                        }
+                    else
+                        {
+                        // Unknown category.
+                        LOGGSMU3("CSmsMessage::InstallControlInformationElementsL category = %d, id = %d", category, ie.Identifier());
+                        User::Leave(KErrArgument);
+                        }
+                    break;
+                case  TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
+                case  TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
+                    {
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryIn1stPDUOnly "
+                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier());
+
+                    TUint index = 0;
+                    if (iAdditionalInfo->Find1stInstanceOfControlInformationElement(ie.Identifier(), index))
+                        {
+                        iAdditionalInfo->DeleteControlInformationElement(category, index); //  might want to pass the
+                                                                                                //  id in as an additional check
+                                                                                                //  this should be an exception case
+                        CSmsInformationElement* newInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
+
+                    	CleanupStack::PushL(newInformationElement);
+                    	iAdditionalInfo->AddControlInformationElementL(category, newInformationElement);
+                        CleanupStack::Pop(newInformationElement);
+                        }
+                     else
+                        {
+                        CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
+                        CleanupStack::PushL(cloneInformationElement);
+                        iAdditionalInfo->AddControlInformationElementL(category, cloneInformationElement);
+                        CleanupStack::Pop(cloneInformationElement);
+                        }
+                    break;
+                    }
+                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues:
+                    {
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUAndWithIdenticalValues "
+                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier());
+                    TInt index = 0;
+                    if (SmsPDU().UserData().InformationElementIndex(ie.Identifier(),index))
+                        {
+                        CSmsInformationElement* newInformationElement = CSmsInformationElement::NewL(ie.Identifier(),ie.Data());
+
+                    	CleanupStack::PushL(newInformationElement);
+                        CSmsInformationElement*& indexedPDU = SmsPDU().UserData().InformationElementPtr(index);
+                        CSmsInformationElement* oldInformationElement = indexedPDU;
+                        SmsPDU().UserData().InformationElementPtr(index) = newInformationElement;
+						// In next loop, oldInformationElement will point to the newly created information element. So double free is no case.
+						// coverity[double_free]
+                        delete oldInformationElement;
+                        CleanupStack::Pop(newInformationElement);
+                        }
+                    else
+                        {
+                        SmsPDU().UserData().UpdateInformationElementArrayL(ie.Identifier(),ie.Data());
+                        }
+                    break;
+                    }
+
+                case  TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
+                    {
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUAndWithIdenticalValues "
+                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
+
+                    CSmsInformationElement* cloneInformationElement = CSmsInformationElement::NewL( ie.Identifier(),ie.Data() );
+                    CleanupStack::PushL(cloneInformationElement);
+                    iAdditionalInfo->AddControlInformationElementL( TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed, cloneInformationElement);
+                    CleanupStack::Pop(cloneInformationElement);
+                    break;
+                    }
+                case  TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU:
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU "
+                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
+                    
+                    if (ie.Identifier() == CSmsInformationElement::ESmsIEISMSCControlParameters)
+                    	{
+                       	if(scheme.Id() == EControlParametersScheme)
+                    		{
+                    		CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
+                    		ctrlParamScheme.iDefaultStatusReport = 0x00;
+                    		
+	                       	const TUint8* octet(0);
+	                    	octet = ie.Data().Ptr();
+	                    	if(*octet)
+                    			{
+                    			CSmsMessageAdditionalAttributes::CControlParametersScheme::TSmsSMSCCtrlParameterStatus smscCtrlParameterStatus;
+								smscCtrlParameterStatus.iSegmentSequenceNum = aSegmentSequenceNum;
+								smscCtrlParameterStatus.iSelectiveStatus = *octet;
+								(ctrlParamScheme.iControlParametersStatusReport).AppendL(smscCtrlParameterStatus);
+                    			}
+                    		ctrlParamScheme.iNumOfPDUs++;
+	                    	}
+	                    }
+                
+                    // e.g  Email Header / Concatenation Elements.
+                    // Consider whether EMail Header should be ported here.
+                    // or left as is.
+                    break;
+                case  TSmsInformationElementCategories::EEmsInformationElement:
+                    LOGGSMU2("CSmsMessage::InstallControlInformationElements ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU "
+                                 "ECtrlSingleInstanceOnly, id = %d", ie.Identifier() );
+                    // Will be handled in the method InstallEmsInformationElements, nothing to do here
+                    break;
+                default:
+                    LOGGSMU3("CSmsMessage::InstallControlInformationElementsToMultiSegmentMessageL, default switch, category = %d, id= %d", category, ie.Identifier() );
+                    break;
+                }
+            }
+    	}
+    } // CSmsMessage::InstallControlInformationElementsL
+
+
+/**
+ *  Extracts all the EMS information objects out of the given UserData into the CSmsMessage IEArray.
+ *  
+ *  @param aUserData Object containing the EMS objects.
+ *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
+ *  of the UserData.
+ */
+void  CSmsMessage::InstallEmsInformationElementsL(CSmsUserData& aUserData, TInt aCharsAlreadyAdded)
+	{
+	// Installs all the information elements within the subsequent PDUs.
+	LOGGSMU1("CSmsMessage::InstallEmsInformationElements()");
+
+	CSmsInformationElement::TSmsInformationElementIdentifier id;
+	CEmsInformationElement* newIE =NULL;
+
+	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
+		{
+		const CSmsInformationElement& ie = aUserData.InformationElement(z);
+
+		// is the ie an EMS information Element;
+		id = ie.Identifier();
+		if (CEmsFactory::Supported(id))
+			{
+			newIE=NULL;
+			TRAPD(ret,newIE = CEmsFactory::CreateReceivedEmsIEL(ie,aCharsAlreadyAdded));
+			if(newIE != NULL)
+				{
+				if(ret == KErrNone)
+					{
+					ret=AddReceivedEmsInformationElement(newIE);
+					if(ret==KErrNone)  // Remove the Information Element from the User Data.
+						aUserData.RemoveInformationElement(z--);
+					else
+						// newIE is made NULL in first place and then a new IE is created. so double free is no case
+						// coverity[double_free]
+						delete newIE;
+					}
+				else
+					delete newIE;
+				}
+			}
+		}
+	} // CSmsMessage::InstallEmsInformationElementsL
+
+
+/**
+ *  Extracts all the EMS information objects out of the given Command into the CSmsMessage IEArray.
+ *  
+ *  @param aCommand Object containing the EMS objects.
+ *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
+ *  of the UserData.
+ */
+void  CSmsMessage::InstallEmsInformationElementsL(CSmsCommand& aCommand, TInt aCharsAlreadyAdded)
+    {
+    // Ignore in code coverage - not used in SMS stack and not exported
+    // but cannot be removed as impacts public header.
+    BULLSEYE_OFF    
+    // Installs all the information elements within the subsequent PDUs.
+    LOGGSMU1("CSmsMessage::InstallEmsInformationElements()");
+    
+    CSmsInformationElement::TSmsInformationElementIdentifier id;
+    CEmsInformationElement* newIE=NULL;
+    
+    for (TInt z=0; z<aCommand.NumInformationElements(); z++)
+        {
+        const CSmsInformationElement& ie = aCommand.InformationElement(z);
+        // is the ie an EMS information Element;
+        id = ie.Identifier();
+        if (CEmsFactory::Supported(id))
+            {
+            newIE=NULL;
+            TRAPD(ret,newIE = CEmsFactory::CreateReceivedEmsIEL(ie,aCharsAlreadyAdded));
+            if(newIE != NULL )
+                {
+                    if(ret == KErrNone)
+                    {
+                        ret=AddReceivedEmsInformationElement(newIE);
+                        if(ret==KErrNone)  // Remove the Information Element from the User Data.
+                            aCommand.RemoveInformationElement(z--);
+                        else
+                            // newIE is made NULL in first place and then a new IE is created. so double free is no case.
+                            // coverity[double_free]
+                            delete newIE;
+                    }
+                    else
+                        delete newIE;
+                }
+            }
+        }
+    BULLSEYE_RESTORE
+    }
+
+TSmsStatusReportScheme CSmsMessage::FindSchemeL(const CArrayPtr<CSmsPDU>& aSmsPDUArray)
+	{
+	TInt smscIndex(0);
+	
+	if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+		{
+		iAdditionalInfo->SetStatusReportSchemeL(EControlParametersScheme);
+		return EControlParametersScheme;
+		}
+		
+	TSmsFirstOctet oldTpsrr;
+	TSmsFirstOctet tpsrr;
+	CSmsSubmit* smsSubmit;
+	CSmsDeliver* smsDeliver;
+	
+	if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
+		{
+		smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[0]);
+		oldTpsrr = smsSubmit->StatusReportRequest();
+		}
+	else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
+		{
+		smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[0]);
+		oldTpsrr = smsDeliver->StatusReportIndication();
+		}
+		
+	for (TInt ii=1; ii<aSmsPDUArray.Count(); ii++)
+		{
+		if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
+			{
+			smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[ii]);
+			tpsrr = smsSubmit->StatusReportRequest();
+			}
+		else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
+			{
+			smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[ii]);
+			tpsrr = smsDeliver->StatusReportIndication();
+			}
+		if(tpsrr != oldTpsrr)
+			{
+			iAdditionalInfo->SetStatusReportSchemeL(ETPSRRScheme);
+			return ETPSRRScheme;
+			}
+		}
+	
+	iAdditionalInfo->SetStatusReportSchemeL(EDefaultScheme);
+
+	return EDefaultScheme;
+	} // CSmsMessage::FindSchemeL
+
+	
+void CSmsMessage::InstallTPSRRInformationL(const CArrayPtr<CSmsPDU>& aSmsPDUArray, TInt aSegmentSequenceNum)
+	{
+    CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = iAdditionalInfo->GetStatusReportScheme();
+    CSmsMessageAdditionalAttributes::CTPSRRScheme& tpsrrScheme = (CSmsMessageAdditionalAttributes::CTPSRRScheme&)scheme;
+    
+    tpsrrScheme.iDefaultStatusReport = TSmsFirstOctet::ESmsStatusReportNotRequested;
+    tpsrrScheme.iNumOfPDUs++;
+    
+    TSmsFirstOctet tpsrr;
+    
+    if (SmsPDU().Type() == CSmsPDU::ESmsSubmit)
+		{
+		CSmsSubmit* smsSubmit = reinterpret_cast<CSmsSubmit*>((aSmsPDUArray)[aSegmentSequenceNum]);
+		tpsrr = smsSubmit->StatusReportRequest();
+		}
+	else if (SmsPDU().Type() == CSmsPDU::ESmsDeliver)
+		{
+		CSmsDeliver* smsDeliver = reinterpret_cast<CSmsDeliver*>((aSmsPDUArray)[aSegmentSequenceNum]);
+		tpsrr = smsDeliver->StatusReportIndication();
+		}
+    
+    if(tpsrr)
+    	{
+    	CSmsMessageAdditionalAttributes::CTPSRRScheme::TSmsTPSRRStatus tpsrrStatus;
+
+    	tpsrrStatus.iSegmentSequenceNum = aSegmentSequenceNum;
+		tpsrrStatus.iTPSRRStatus = TSmsFirstOctet::ESmsStatusReportRequested;
+		tpsrrScheme.iTPSRRStatusReport.AppendL(tpsrrStatus);	
+    	}
+	} // CSmsMessage::InstallTPSRRInformationL
+
+
+/**
+ *  Adds EMS IE to a CSmsMessage
+ *  
+ *  @param aEmsIE EMS object to be added.
+ *  
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::AddEMSInformationElementL(const CEmsInformationElement& aEmsIE)
+	{
+	LOGGSMU1("CSmsMessage::AddEMSInformationElementL()");
+
+	if(aEmsIE.StartPosition() > (TUint)iBuffer->Length())
+		{
+		User::Leave(KErrOverflow);
+		}
+
+	if(CSmsInformationElement::ESmsEnhancedTextFormatting == aEmsIE.Identifier() && aEmsIE.Length() ==0)
+		{
+		User::Leave(KErrUnderflow);
+		}
+
+	if(CSmsInformationElement::ESmsEnhancedUserPromptIndicator == aEmsIE.Identifier())
+		{
+		AddEmsUserPromptL(static_cast<const CEmsUserPrompt&>(aEmsIE));
+		}
+	else if(CSmsInformationElement::ESmsEnhancedODI == aEmsIE.Identifier())
+		{
+		AddEmsObjectDistributionL(static_cast<const CEmsObjectDistribution&>(aEmsIE));
+		}
+	else
+		{
+		TInt count=iInformationElementArray->Count();
+		TInt currNo=0;
+		const CEmsInformationElement* emsIE=NULL;
+
+		while(currNo < count)
+		{
+			emsIE=(*iInformationElementArray)[currNo];
+			if(emsIE->StartPosition() == aEmsIE.StartPosition() && (CSmsInformationElement::ESmsEnhancedUserPromptIndicator == emsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI == emsIE->Identifier()))
+				User::Leave(KErrArgument);
+			else if(emsIE->StartPosition() > aEmsIE.StartPosition())
+				break;
+			currNo++;
+		}
+		User::LeaveIfError(iInformationElementArray->Insert(aEmsIE.DuplicateL(),currNo));
+		}
+	} // CSmsMessage::AddEMSInformationElementL
+
+
+TBool CSmsMessage::CanBeRemoved(const CEmsInformationElement& aIE, const TUint aIEIndex)
+	{
+	LOGGSMU1("CSmsMessage::CanBeRemoved()");
+
+	TBool ret=ETrue;
+	if(CSmsInformationElement::ESmsEnhancedODI == aIE.Identifier())
+		return ret;
+
+	TUint ieStartPosition=aIE.StartPosition();
+	TUint count=iInformationElementArray->Count();
+	CEmsInformationElement* ie=NULL;
+
+	// is there a UserPrompt/ODI at the same position
+	for (TUint i=0; i < count && ret; ++i)
+		{
+		ie = (*iInformationElementArray)[i];
+		// Do not allow removal if start position matches a user prompt and it is not the user prompt itself being removed
+		if (ie->StartPosition() == ieStartPosition && ie->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator && aIE.Identifier() != CSmsInformationElement::ESmsEnhancedUserPromptIndicator)
+		    ret=EFalse;
+		if (ie->Identifier() == CSmsInformationElement::ESmsEnhancedODI)
+		    {
+		    // don't allow removal of IE if position inside object count of ODI
+		    if ((static_cast<CEmsObjectDistribution*>(ie)->ObjectCount()+i) >= aIEIndex || static_cast<CEmsObjectDistribution*>(ie)->ObjectCount() == 0)
+		        ret=EFalse;
+		    }
+		}
+
+	LOGGSMU2("CSmsMessage::CanBeRemoved() returns %d", ret);
+
+	return ret;
+	} // CSmsMessage::CanBeRemoved
+
+
+/**
+ *  Adds EMS IE to a CSmsMessage
+ *  
+ *  @param aEmsIE EMS object to be added.
+ */
+void CSmsMessage::AddEmsUserPromptL(const CEmsUserPrompt& aUserPromptIE)
+	{
+	LOGGSMU1("CSmsMessage::AddEmsUserPromptL()");
+
+		if(aUserPromptIE.ObjectCount() == 0 )User::Leave(KErrArgument);
+
+		TUint count=iInformationElementArray->Count();
+		TUint userPromptStartPosition=aUserPromptIE.StartPosition();
+
+		TSmsId id=aUserPromptIE.Identifier();
+		TBool allSameType=ETrue;
+		TUint countOnTheSamePos=0;
+		TUint firstIndex=0;
+
+		// collect all IEs on the same startPosition as the new User Prompt
+		CEmsInformationElement* ie=NULL;
+
+		for (TUint i=0; i < count ; i++)
+		{
+			ie = (*iInformationElementArray)[i];
+			if (ie->StartPosition() == userPromptStartPosition)
+			{
+				if(countOnTheSamePos==0)
+				{
+					firstIndex=i;
+					id = ie->Identifier();
+				}
+				else
+				{
+					if(allSameType && id != ie->Identifier())allSameType=EFalse;
+					else id = ie->Identifier();
+				}
+				++countOnTheSamePos;
+			}
+		}
+
+		if(countOnTheSamePos != aUserPromptIE.ObjectCount())
+			User::Leave(KErrArgument);
+
+
+	if( countOnTheSamePos == 1)
+	{
+		switch(id)
+		{
+		case CEmsInformationElement::ESmsEnhancedPredefinedAnimation:
+		case CEmsInformationElement::ESmsEnhancedLargeAnimation :
+		case CEmsInformationElement::ESmsEnhancedSmallAnimation	:
+		case CEmsInformationElement::ESmsEnhancedUserDefinedSound:
+		case CEmsInformationElement::ESmsEnhancedLargePicture:
+		case CEmsInformationElement::ESmsEnhancedSmallPicture:
+		case CEmsInformationElement::ESmsEnhancedVariablePicture:
+		User::LeaveIfError(iInformationElementArray->Insert(aUserPromptIE.DuplicateL(),firstIndex));
+			break;
+		default:
+		User::Leave(KErrCorrupt);
+			break;
+		}
+		return;
+	}
+
+	// stitching - more than one object
+	if(allSameType  && (id == CEmsInformationElement::ESmsEnhancedUserDefinedSound || id == CEmsInformationElement::ESmsEnhancedLargePicture || id == CEmsInformationElement::ESmsEnhancedSmallPicture || id == CEmsInformationElement::ESmsEnhancedVariablePicture))
+		{
+		User::LeaveIfError(iInformationElementArray->Insert(aUserPromptIE.DuplicateL(),firstIndex));
+		return;
+		}
+
+    //  not of the same type or not supported IE types
+	User::Leave(KErrCorrupt);
+	} // CSmsMessage::AddEmsUserPromptL
+
+
+/**
+ *  Adds EMS IE to a CSmsMessage
+ *  
+ *  @param aEmsIE EMS object to be added.
+ */
+void CSmsMessage::AddEmsObjectDistributionL(const CEmsObjectDistribution& aObjectDistributionIE)
+    {
+	LOGGSMU1("CSmsMessage::AddEmsObjectDistributionL()");
+
+    TUint count=iInformationElementArray->Count();
+    TUint objectDistributionStartPosition=aObjectDistributionIE.StartPosition();
+
+    TBool firstIndexFound=EFalse;
+    TUint firstIndex=0;
+    TUint countOnSameOrSubsequentPos=0;
+
+    // collect any IEs on the same or greater startPosition as the new Object Distribution Indicator
+    CEmsInformationElement* ie=NULL;
+
+    for (TUint i=0; i < count; i++)
+        {
+        ie = (*iInformationElementArray)[i];
+        if (ie->StartPosition() >= objectDistributionStartPosition)
+            {
+            // Only set index if at least one IE found at desired start position
+            if (!firstIndexFound)
+                {
+                firstIndex=i;
+                firstIndexFound=ETrue;
+                }
+            ++countOnSameOrSubsequentPos;
+            }
+        }
+    // check number of IEs present for desired ObjectCount
+    if(countOnSameOrSubsequentPos < aObjectDistributionIE.ObjectCount())
+        User::Leave(KErrArgument);
+
+    if (firstIndexFound)
+        {
+        User::LeaveIfError(iInformationElementArray->Insert(aObjectDistributionIE.DuplicateL(),firstIndex));
+        return;
+        }
+
+    //  no valid IE for ODI to apply to
+    User::Leave(KErrCorrupt);
+    } // CSmsMessage::AddEmsObjectDistributionL
+
+
+/**
+ *  Removes first EMS IE that matches the criteria from the CSmsMessage
+ *  
+ *  @param aStartPosition of a EMS object to be removed.
+ *  @param aEmsId type of a EMS object to be removed
+ *  @return pointer EMS information element
+ *  @capability
+ *  @capability None
+ */
+EXPORT_C CEmsInformationElement* CSmsMessage::RemoveEMSInformationElementL(const TUint aStartPosition,const TSmsId aEmsId)
+	{
+	LOGGSMU1("CSmsMessage::RemoveEMSInformationElementL()");
+
+	CEmsInformationElement* emsIE=NULL;
+	CEmsInformationElement* ie=NULL;
+
+	TUint count=iInformationElementArray->Count();
+
+	for (TInt i=--count; i >=0 ; --i)
+		{
+		ie = (*iInformationElementArray)[i];
+		if (ie->StartPosition() == aStartPosition && ie->Identifier() == aEmsId)
+			{
+				if(CanBeRemoved(*ie, i))
+				{
+					iInformationElementArray->Remove(i);
+					emsIE=ie;
+				}
+				else
+					emsIE=NULL;
+				break;
+			}
+
+		}
+	return emsIE;
+	} // CSmsMessage::RemoveEMSInformationElementL
+
+
+/**
+ *  Removes all EMS IEs that matches the criteria from the CSmsMessage
+ *  
+ *  @param aStartPosition of a EMS object to be removed.
+ *  @param aEmsId type of a EMS object to be removed
+ *  @return pointer to array of EMS IE
+ *  
+ *  @capability None
+ */
+EXPORT_C RPointerArray<CEmsInformationElement>* CSmsMessage::RemoveEMSInformationElementsL(const TUint aStartPosition,const TSmsId aEmsId)
+	{
+	LOGGSMU1("CSmsMessage::RemoveEMSInformationElementsL()");
+
+	CEmsInformationElement* ie=NULL;
+	RPointerArray<CEmsInformationElement>* selectedIEs = NULL;
+	TUint count=iInformationElementArray->Count();
+
+	for (TInt i=--count; i >= 0 ; --i)
+		{
+		ie = (*iInformationElementArray)[i];
+		if (ie->StartPosition() == aStartPosition && ie->Identifier() == aEmsId)
+			{
+				if(CanBeRemoved(*ie, i))
+				{
+					if(selectedIEs == NULL)selectedIEs=new (ELeave) RPointerArray<CEmsInformationElement>(8);
+					iInformationElementArray->Remove(i);
+					selectedIEs->Append(ie);
+				}
+			}
+
+		}
+	return selectedIEs;
+	} // CSmsMessage::RemoveEMSInformationElementsL
+
+/**
+ *  Resets EMS IE from a CSmsMessage
+ *  
+ *  
+ *  @capability None
+ */
+EXPORT_C void  CSmsMessage::ResetEMSL()
+	{
+	LOGGSMU1("CSmsMessage::ResetEMSL()");
+
+	iInformationElementArray->ResetAndDestroy();
+	} // CSmsMessage::ResetEMSL
+
+/**
+ *  Removes EMS IE from a CSmsMessage
+ *  
+ *  @return CArrayPtrFlat<const CEmsInformationElement>& of internal EMS array
+ *  
+ *  @capability None
+ */
+EXPORT_C const RPointerArray<const CEmsInformationElement>& CSmsMessage::GetEMSInformationElementsL()const
+	{
+	LOGGSMU1("CSmsMessage::GetEMSInformationElementsL()");
+
+	 return (const RPointerArray<const CEmsInformationElement>&)(*iInformationElementArray);
+	} // CSmsMessage::GetEMSInformationElementsL
+
+
+void CSmsMessage::UpdateUserPromptAndODIElementsStartPosition()
+	{
+	LOGGSMU1("CSmsMessage::UpdateUserPromptAndODIElementsStartPosition()");
+
+		TUint num=iInformationElementArray->Count();
+		TInt startPosition=-1;
+		CEmsInformationElement* ie = NULL;
+
+
+		// is the ie an EMS information Element;
+
+		for(TInt i=num-1;i >=0; --i)
+		{
+			ie = (*iInformationElementArray)[i];
+			if(ie->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator || ie->Identifier() == CSmsInformationElement::ESmsEnhancedODI)
+			{
+				if(startPosition >=0)
+					ie->SetStartPosition(startPosition);
+				else
+					iInformationElementArray->Remove(i);
+			}
+			else
+				startPosition=ie->StartPosition();
+
+		}
+	} // CSmsMessage::UpdateUserPromptAndODIElementsStartPosition
+
+
+TInt CSmsMessage::AddReceivedEmsInformationElement(CEmsInformationElement* aEmsIE)
+	{
+	LOGGSMU1("CSmsMessage::AddReceivedEmsInformationElement()");
+
+	TInt ret=KErrNone;
+	if(CSmsInformationElement::ESmsEnhancedUserPromptIndicator == aEmsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI == aEmsIE->Identifier())
+		ret=iInformationElementArray->Append(aEmsIE);
+	else
+		{
+			TInt count=iInformationElementArray->Count();
+			TInt currNo=0;
+			const CEmsInformationElement* emsIE=NULL;
+			while(currNo < count)
+			{
+				emsIE=(*iInformationElementArray)[currNo];
+				if(emsIE->StartPosition() > aEmsIE->StartPosition() && (CSmsInformationElement::ESmsEnhancedUserPromptIndicator != emsIE->Identifier() || CSmsInformationElement::ESmsEnhancedODI != emsIE->Identifier()))
+					break;
+				currNo++;
+			}
+			ret=iInformationElementArray->Insert(aEmsIE,currNo);
+		}
+	return ret;
+	} // CSmsMessage::AddReceivedEmsInformationElement
+
+
+/**
+ *  Updates the slot information for the given message as described in the supplied buffer
+ *  
+ *  @param aDesc buffer, layout: byte 0 store id, byte 1..n PDU slot indexes
+ *  @leave KErrArgument
+ *  
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::UpdateSlotsL(TDesC8& aDesc)
+    {
+	LOGGSMU1("CSmsMessage::UpdateSlotsL()");
+
+    TGsmSmsSlotEntry newSlot;
+
+    switch (aDesc[0])
+        {
+        case CSmsMessage::ESmsSIMStorage:
+            {
+            newSlot.iStore = KETelIccSmsStore;
+            break;
+            }
+        case CSmsMessage::ESmsPhoneStorage:
+            {
+            newSlot.iStore = KETelMeSmsStore;
+            break;
+            }
+        case CSmsMessage::ESmsCombinedStorage:
+            {
+            newSlot.iStore = KETelCombinedSmsStore;
+            break;
+            }
+        default:
+            User::Leave(KErrArgument);
+        }
+
+    for (TInt index = 1; index < aDesc.Size(); index++)
+        {
+        newSlot.iIndex = aDesc[index]; // point to PDU indexes
+        iSlotArray.AppendL(newSlot);
+        }
+    } // CSmsMessage::UpdateSlotsL
+
+/**
+ *  Copy EMS elements to dest CSmsMessage
+ *  Uses CSmsMessage extended EMS API
+ *  Creates new CEmsInformationElement instance(s) and passes ownership to the dest CSmsMessage
+ *  
+ *  @return aToMessage  - Destination CSmsMessage
+ *  
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::CopyEmsElementsL(CSmsMessage& aToMessage) const
+	{
+	LOGGSMU1("CSmsMessage::CopyEmsElementsL()");
+
+	// CSmsMessage extended EMS API method creates array of references to EMS elements in
+	// the source message
+	// Loop through the array copying each individual method using the CSmsMessage
+	// and CEmsInformationElement API's
+	CEmsInformationElement* dupl=NULL;
+	aToMessage.ResetEMSL();
+	for(TInt i = iInformationElementArray->Count()-1 ; i >=0; --i)
+		{
+		dupl = (*iInformationElementArray)[i]->DuplicateL();
+		CleanupStack::PushL(dupl);
+		aToMessage.AddEMSInformationElementL(*dupl);
+		CleanupStack::PopAndDestroy(dupl);
+		}
+	} // CSmsMessage::CopyEmsElementsL
+
+/**
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::AddSlotL(const TGsmSmsSlotEntry& aSlot)
+	{
+	LOGGSMU1("CSmsMessage::AddSlotL()");
+
+		TInt count = iSlotArray.Count();
+		TInt i(0);
+		TBool found(EFalse);
+		while(!found && i<count)
+		{
+			if(aSlot.iIndex == iSlotArray[i].iIndex)found=ETrue;
+			else ++i;
+		}
+		LOGGSMU3("CSmsMessage::AddSlotL current no in: %d, adds index %d", count,aSlot.iIndex );
+		LOGGSMU3("found %d at position %d",found,i);
+		iSlotArray.AppendL(aSlot);
+	} // CSmsMessage::AddSlotL
+
+/**
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::MatchSlots(const CArrayFixFlat<TGsmSmsSlotEntry>& aSlotArray)
+	{
+	LOGGSMU1("CSmsMessage::MatchSlots()");
+
+		TBool match = EFalse;
+		TInt count = aSlotArray.Count();
+		if(iSlotArray.Count() == count)
+		{
+			TInt i = 0;
+			match = ETrue;
+			while(match && i < count)
+				{
+				const TGsmSmsSlotEntry& newSlot=aSlotArray[i];
+				const TGsmSmsSlotEntry& slot =iSlotArray[i];
+				if ( ( slot.iIndex != newSlot.iIndex ) || ( slot.iStore != newSlot.iStore ) )
+						match = EFalse;
+				i++;
+				}
+
+		}
+		return match;
+	} // CSmsMessage::MatchSlots
+
+/**
+ *  c'tor
+ *  @capability None
+ */
+EXPORT_C TGsmSmsSlotEntry::TGsmSmsSlotEntry()
+	{
+	} // TGsmSmsSlotEntry::TGsmSmsSlotEntry
+
+/**
+ *  Internalize
+ *  
+ *  @param aStream For internalizing the data
+ */
+void TGsmSmsSlotEntry::InternalizeL(RReadStream& aStream)
+	{
+	aStream >> iStore;
+	iIndex=aStream.ReadInt32L();
+	} // TGsmSmsSlotEntry::InternalizeL
+
+/**
+ *  Externalize
+ *  
+ *  @param aStream For Externalizing the data
+ */
+void TGsmSmsSlotEntry::ExternalizeL(RWriteStream& aStream) const
+	{
+	aStream << iStore;
+	aStream.WriteInt32L(iIndex);
+	} // TGsmSmsSlotEntry::ExternalizeL
+
+ /**
+  *  Extracts all RFC 822 Email header information objects out of the given UserData into the CSmsMessage's iSmsEmailHeaderLength.
+  *  
+  *  @param aUserData Object containing the EmailHeader information element.
+  *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
+  *  of the UserData.
+  */
+void  CSmsMessage::InstallEmailHeaderInformationElementL(CSmsUserData& aUserData,TInt& aHeaderLength)
+ 	{
+ 	// Installs all the information elements within the subsequent PDUs.
+ 	LOGGSMU1("CSmsMessage::InstallEmailHeaderInformationElementL()");
+
+ 	CSmsInformationElement::TSmsInformationElementIdentifier id;
+
+ 	for (TInt z=0; z<aUserData.NumInformationElements(); z++)
+ 		{
+ 		const CSmsInformationElement& ie = aUserData.InformationElement(z);
+ 		id = (CSmsInformationElement::TSmsInformationElementIdentifier)ie.Identifier();
+ 		if (id == CSmsInformationElement::ESmsIEIRFC822EmailHeader)
+ 			{
+ 				const TDesC8& des = ie.Data();
+ 				aHeaderLength+=des[0];
+ 			}
+ 		}
+ 	} // CSmsMessage::InstallEmailHeaderInformationElementL
+
+/**
+ *  Extracts all RFC 822 Email header information objects out of the given UserData into the CSmsMessage's iSmsEmailHeaderLength.
+ *  
+ *  @param aCommand Object containing the EmailHeader information element.
+ *  @param aCharsAlreadyAdded The current, running, start position to be applied to the objects taken out
+ *  of the UserData.
+ */
+void CSmsMessage::InstallEmailHeaderInformationElementL(CSmsCommand& aCommand,TInt& aHeaderLength)
+    {
+    // Ignore in code coverage - not used in SMS stack and not exported
+    // but cannot be removed as impacts public header.
+    BULLSEYE_OFF    
+    // Installs all the information elements within the subsequent PDUs.
+    LOGGSMU1("CSmsMessage::InstallEmailHeaderInformationElementL()");
+    
+    CSmsInformationElement::TSmsInformationElementIdentifier id;
+    
+    for (TInt z=0; z<aCommand.NumInformationElements(); z++)
+        {
+        const CSmsInformationElement& ie = aCommand.InformationElement(z);
+        id = (CSmsInformationElement::TSmsInformationElementIdentifier)ie.Identifier();
+        if (id == CSmsInformationElement::ESmsIEIRFC822EmailHeader)
+            {
+            const TDesC8& des = ie.Data();
+            aHeaderLength+=des[0];
+            }
+        }
+    BULLSEYE_RESTORE
+    }
+
+// E-mail header methods
+
+/**
+ *  Adds a header to an email body
+ *  
+ *  @param aEMailBody The buffer to which the header gets appended
+ *  @param aEmailHeader The buffer which holds RFC 822 e-mail header
+ *  @publishedAll
+ *  @released
+ *  
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::AddEmailHeaderL(const TDesC& aEmailHeader, const TDesC& aEmailBody)
+ 	{
+ 	LOGGSMU1("CSmsMessage::AddEmailHeaderL()");
+
+ 	if(IsEmailHeader())
+ 		User::Leave(KErrAlreadyExists);
+
+ 	TInt len =aEmailHeader.Length();
+ 	if(len <= 0)
+ 		User::Leave(KErrCorrupt);
+
+	if(len >= 255 )
+ 		User::Leave(KErrTooBig);
+
+
+	if(SmsPDU().UserData().NumInformationElements())
+		{
+		TBool is16bit = EFalse;
+		TBool concatenationIEPresent= SmsPDU().TextConcatenated( &is16bit );
+		if(concatenationIEPresent)
+			{
+			if(SmsPDU().UserData().NumInformationElements() >=2) // something more than concat IE
+				User::Leave(KErrAccessDenied);
+			}
+		else
+			User::Leave(KErrAccessDenied);
+		}
+
+
+	TBuf8<1> data;
+	data.SetLength(1);
+	data[0]=static_cast<TUint8>(len);
+	SmsPDU().UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIRFC822EmailHeader,data);
+
+ 	iBuffer->Reset();
+ 	iBuffer->InsertL(0,aEmailHeader);
+ 	iBuffer->InsertL(iBuffer->Length(),aEmailBody);
+ 	} // CSmsMessage::AddEmailHeaderL
+
+ /**
+  *  Checks whether the SmsMessage contains an e-mail.
+  *  
+  *  @return ETrue if CSmsMessage contains e-mail ( e-mail header information element), otherwise EFalse
+  *  @publishedAll
+  *  @released
+  *  
+  *  @capability None
+  */
+EXPORT_C TBool CSmsMessage::IsEmailHeader() const
+ 	{
+ 	LOGGSMU1("CSmsMessage::IsEmailHeader()");
+
+	TInt emailIndex;
+	return SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex);
+ 	} // CSmsMessage::IsEmailHeader
+
+ /**
+  *  Extracts e-mail header and body from the SmsMessage
+  *  
+  *  @return aEMailHeader The buffer containing the extracted email header
+  *  @return aEMailBody The buffer containing the extracted email body
+  *  @return ETrue if extraction of e-mail header and body succeeds
+  *  @publishedAll
+  *  @released
+  *  
+  *  @capability None
+  */
+EXPORT_C TBool CSmsMessage::GetEmailHeaderL(HBufC** aEmailHeader,HBufC** aEmailBody)
+ 	{
+ 	LOGGSMU1("CSmsMessage::GetEmailHeaderL()");
+
+ 	if(IsEmailHeader())
+ 		{
+ 			TInt bufLen=iBuffer->Length();
+ 			TInt emailHeaderLen(0);
+			TInt emailIndex(0);
+			if(SmsPDU().UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
+				emailHeaderLen=SmsPDU().UserData().InformationElement(emailIndex).Data()[0];
+			else
+				User::Leave(KErrCorrupt);
+
+ 			TInt emailBodyLen=bufLen-emailHeaderLen;
+
+ 			if(emailBodyLen<0)
+ 				return EFalse;
+
+ 			*aEmailHeader=HBufC::NewL(emailHeaderLen);
+ 			CleanupStack::PushL(*aEmailHeader);
+
+ 			*aEmailBody=HBufC::NewL(emailBodyLen);
+ 			CleanupStack::PushL(*aEmailBody);
+
+ 			TPtr headerPtr((*aEmailHeader)->Des());
+ 			iBuffer->Extract(headerPtr,0,emailHeaderLen);
+
+ 			TPtr bodyPtr((*aEmailBody)->Des());
+ 			iBuffer->Extract(bodyPtr,emailHeaderLen,emailBodyLen);
+
+ 			CleanupStack::Pop(2);
+ 			return ETrue;
+ 		}
+ 	return EFalse;
+ 	} // CSmsMessage::GetEmailHeaderL
+
+
+ /**
+  *  Extracts the offset between universal time and local time in seconds.
+  *  If the value is > 0, local time is ahead of universal time.
+  *  If the value is < 0, local time is behind universal time.
+  *  
+  *  @return TTTimeIntervalSeconds The time zone offset in seconds.
+  *  @publishedAll
+  *  @capability None
+  */
+EXPORT_C TTimeIntervalSeconds CSmsMessage::UTCOffset() const
+    {
+    LOGGSMU1("CSmsMessage::UTCOffset()");
+
+    TUint timeZoneOffset = ((iFlags & ESmsUTCOffsetSecondGranularityMask) >> ESecondBitOffset);
+
+    if (iFlags & ESmsUTCOffsetSignBit)
+        {
+        timeZoneOffset = -timeZoneOffset;
+        }
+
+    return (TTimeIntervalSeconds(timeZoneOffset));
+    } // CSmsMessage::UTCOffset
+
+
+ /**
+  *  Sets the offset between universal time and local time in seconds.
+  *  If the value is > 0, local time is ahead of universal time.
+  *  If the value is < 0, local time is behind universal time.
+  *  The CSmsMessage Time Zone Offset has the range +/- 71100 seconds. This is same range as
+  *  the Service Centre Time Stamp Time Zone Offset as specified in 23.040 V4.4.0 Sect 9.2.3.11.
+  *  
+  *  @return True if input value was set successfully (in range), False otherwise
+  *  @publishedAll
+  *  @capability None
+  */
+EXPORT_C TBool CSmsMessage::SetUTCOffset(const TTimeIntervalSeconds& aTimeOffset)
+    {
+    LOGGSMU1("CSmsMessage::SetUTCOffset()");
+
+    TBool rc = ETrue;
+
+    TInt timeOffset = aTimeOffset.Int();
+
+    if ((timeOffset <=  EMaximumSeconds) &&
+        (timeOffset >= -EMaximumSeconds))
+        {
+        // Clear the timezone offset bits
+        iFlags &= (~(ESmsUTCOffsetSecondGranularityMask   |
+                     ESmsUTCOffsetSignBit));
+
+        if (timeOffset < 0)
+            {
+            iFlags |= ESmsUTCOffsetSignBit;
+            timeOffset = -timeOffset;
+            }
+
+        iFlags |= (timeOffset << ESecondBitOffset);
+        }
+    else
+        {
+        LOGGSMU2("CSmsMessage::SetUTCOffset offset [out of range] = %d",timeOffset);
+        rc = EFalse;
+        }
+
+    return rc;
+} // CSmsMessage::SetUTCOffset
+
+
+/**
+ *  Returns the message version number.
+ *  @capability
+ */
+EXPORT_C TInt CSmsMessage::Version()
+ 	{
+ 	LOGGSMU1("CSmsMessage::Version()");
+
+ 	return iVersion;
+ 	} // CSmsMessage::Version
+
+
+/**
+ *  @internalComponent
+ *  Validates and sets the message version number.
+ *  
+ *  @param aVersion version number to set.
+ *  @return KErrNone if aVersion is valid and successfully set, KErrArgument otherwise.
+ *  @capability None
+ */
+EXPORT_C TInt CSmsMessage::SetVersion(TInt aVersion)
+	{
+ 	LOGGSMU2("CSmsMessage::SetVersion()", aVersion);
+
+	if((aVersion>=ESmsMessageV0) && (aVersion<=ESmsMessageV4))
+		{
+		iVersion=aVersion;
+		return KErrNone;
+		}
+
+	return KErrArgument;
+	} // CSmsMessage::SetVersion
+
+
+/**
+ *  @internalComponent
+ *  Internalises all object data except for the CSmsBufferBase and the message version.
+ *  
+ *  This is used when the buffer is stored elsewhere.
+ *  
+ *  @param aStream Stream to read from
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::InternalizeWithoutBufferAndVersionL(RReadStream& aStream)
+	{
+ 	LOGGSMU1("CSmsMessage::InternalizeWithoutBufferAndVersionL()");
+
+	iFlags=aStream.ReadInt32L();
+	iStatus=(NMobileSmsStore::TMobileSmsStoreStatus) aStream.ReadInt32L();
+	iLogServerId=aStream.ReadInt32L();
+	TInt64 time;
+	aStream >> time;
+	iTime=time;
+
+	CSmsPDU* smspdu=CSmsPDU::NewL(aStream,*iCharacterSetConverter,iFs);
+	delete iSmsPDU;
+	iSmsPDU=smspdu;
+	iIs16BitConcatenation=aStream.ReadInt32L();
+
+	iInformationElementArray->ResetAndDestroy();
+	CEmsFactory::InternalizeL(*iInformationElementArray, aStream);
+
+	TInt count=aStream.ReadInt32L();
+	iSlotArray.Reset();
+	TInt i=0;
+	TGsmSmsSlotEntry newSlot;
+	for (; i<count; i++)
+		{
+		newSlot.InternalizeL(aStream);
+		AddSlotL(newSlot);
+		}
+	} // CSmsMessage::InternalizeWithoutBufferAndVersionL
+
+
+/**
+ *  @internalComponent
+ *  Externalises all object data except for the CSmsBufferBase and the message version.
+ *  
+ *  This is used when the buffer is stored elsewhere.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::ExternalizeWithoutBufferAndVersionL(RWriteStream& aStream) const
+	{
+ 	LOGGSMU1("CSmsMessage::ExternalizeWithoutBufferAndVersionL()");
+
+	aStream.WriteInt32L(iFlags);
+	aStream.WriteInt32L(iStatus);
+	aStream.WriteInt32L(iLogServerId);
+	aStream << Time().Int64();
+
+	SmsPDU().ExternalizeL(aStream);
+	aStream.WriteInt32L(iIs16BitConcatenation);
+
+	CEmsFactory::ExternalizeL(*iInformationElementArray, aStream);
+	TInt count=iSlotArray.Count();
+	aStream.WriteInt32L(count);
+	TInt i=0;
+	for (; i<count; i++)
+		{
+		iSlotArray[i].ExternalizeL(aStream);
+		}
+	} // CSmsMessage::ExternalizeWithoutBufferAndVersionL
+
+
+/**
+ *  @internalComponent
+ *  Internalises the CSmsBufferBase.
+ *  
+ *  @param aStream Stream to read from
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::InternalizeBufferL(RReadStream& aStream)
+	{
+	aStream >> *iBuffer;
+	} // CSmsMessage::InternalizeBufferL
+
+
+/**
+ *  @internalComponent
+ *  Externalises the CSmsBufferBase.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::ExternalizeBufferL(RWriteStream& aStream) const
+	{
+	aStream << *iBuffer;
+	} // CSmsMessage::ExternalizeBufferL
+
+
+/**
+ *  @internalComponent
+ *  Internalises the message version.
+ *  
+ *  @param aStream Stream to read from
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::InternalizeVersionL(RReadStream& aStream)
+	{
+	TInt32 versionNumber = ESmsMessageV0;
+	TRAPD(err,versionNumber=aStream.ReadInt32L());
+	if(err==KErrEof)
+		{
+		versionNumber=ESmsMessageV0;
+		}
+
+	iVersion=static_cast<TSmsMessageVersion> (versionNumber);
+	} // CSmsMessage::InternalizeVersionL
+
+
+/**
+ *  @internalComponent
+ *  Externalises the message version.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::ExternalizeVersionL(RWriteStream& aStream) const
+	{
+	aStream.WriteInt32L(iVersion);
+	} // CSmsMessage::ExternalizeVersionL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Returns a reference to a specialisation of the class CSmsIEOperation. Clients can use this sub-class
+ *  to access the attributes of a specific type of information element encapsulated inside the CSmsMessage.
+ *  The ownership to the CSmsIEOperation class belongs to the CSmsMessage. When the CSmsMessage is deleted,
+ *  the CSmsIEOperation will also be deleted and the reference will become stale.
+ *  
+ *  @param aId
+ *  Specifies the sub class of CSmsIEOperation required.
+ *  @leave KErrNotSupported
+ *  When there is not accessor class available for the specified type of information element.
+ *  @capability None
+ */
+EXPORT_C CSmsIEOperation& CSmsMessage::GetOperationsForIEL(CSmsInformationElement::TSmsInformationElementIdentifier aId) const
+    {
+    LOGGSMU1("CSmsMessage::GetOperationsForIEL()");
+
+    if (iVersion < CSmsMessage::ESmsMessageV1)
+        {
+        LOGGSMU2("CSmsMessage::GetOperationsForIEL, Operation not supported, Msg Version %d", iVersion);
+        User::Leave(KErrNotSupported);
+        }
+
+    return iAdditionalInfo->GetIEOperationL(aId);
+    } // CSmsMessage::GetOperationsForIEL
+
+EXPORT_C CSmsNonIEOperation& CSmsMessage::GetOperationsForNonIEL(TSmsNonIEIdentifier aId) const
+	{
+	LOGGSMU1("CSmsMessage::GetOperationsForNonIEL");
+
+	if (iVersion < CSmsMessage::ESmsMessageV2)
+		{
+		LOGGSMU2("GetOperationsForNonIEL not supported, Msg Version %d", iVersion);
+		User::Leave(KErrNotSupported);
+		}
+
+	return iAdditionalInfo->GetNonIEOperationL(aId);
+	} // CSmsMessage::GetOperationsForNonIEL
+
+
+void CSmsMessage::CreateControlIEOperationsClassesL()
+    {
+ 	LOGGSMU1("CSmsMessage::CreateControlIEOperationsClassesL()");
+
+    CSmsIEOperation* iEOperation = NULL;
+
+    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsHyperLinkFormat, *this,	*iCharacterSetConverter, iFs);
+    iAdditionalInfo->SetIEOperationL(iEOperation);
+
+    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsReplyAddressFormat, *this,	*iCharacterSetConverter, iFs);
+    iAdditionalInfo->SetIEOperationL(iEOperation);
+
+    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, *this,	*iCharacterSetConverter, iFs);
+    iAdditionalInfo->SetIEOperationL(iEOperation);
+
+    iEOperation = CSmsIEOperation::NewL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication, *this,	*iCharacterSetConverter, iFs);
+    iAdditionalInfo->SetIEOperationL(iEOperation);
+    
+    iEOperation = CSmsIEOperation::NewL( CSmsInformationElement::ESmsIEISMSCControlParameters, *this,	*iCharacterSetConverter, iFs);
+    iAdditionalInfo->SetIEOperationL(iEOperation);
+    } // CSmsMessage::CreateControlIEOperationsClassesL
+
+    
+void CSmsMessage::CreateControlNonIEOperationsClassesL()
+    {
+    CSmsNonIEOperation* nonIEOperation = NULL;
+
+    nonIEOperation = CSmsNonIEOperation::NewL(ESmsTPSRRParameter, *this);
+    iAdditionalInfo->SetNonIEOperationL(nonIEOperation);
+
+	nonIEOperation = CSmsNonIEOperation::NewL(ESmsIncompleteClass0MessageParameter, *this);
+	iAdditionalInfo->SetNonIEOperationL(nonIEOperation);
+	} // CSmsMessage::CreateControlNonIEOperationsClassesL
+
+
+/**
+ *  Gets the scheme of the status report.
+ *  
+ *  @return Staus Report Scheme 
+ */
+EXPORT_C TSmsStatusReportScheme CSmsMessage::Scheme() const
+	{
+	return iAdditionalInfo->GetStatusReportScheme().Id();
+	}
+
+/**
+ *  @publishedAll
+ *  
+ *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
+ *  to be on the SIM. If the message's DCS byte is configured for automatic delete or the
+ *  PID is set to Type 0, the message may subsequently have been deleted from the SIM during
+ *  decoding in which case its storage status is unstored.
+ *  
+ *  @param aOnSim
+ *  Used to indicate that the message was on the SIM when it was decoded.
+ *  @capability None
+ */
+EXPORT_C void  CSmsMessage::SetDecodedOnSIM(TBool aOnSim)
+    {
+ 	LOGGSMU2("CSmsMessage::SetDecodedOnSIM(): %d", aOnSim);
+
+    if (aOnSim)
+        {
+        iFlags = iFlags | EDecodedOnSimBit;
+        }
+    else
+        {
+        iFlags = iFlags & ~EDecodedOnSimBit;
+        }
+    } // CSmsMessage::SetDecodedOnSIM
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
+ *  to be on the SIM. If the message's DCS byte is configured for automatic delete or the
+ *  PID is set to Type 0, the message may subsequently have been deleted from the SIM during
+ *  decoding in which case its storage status is unstored.
+ *  
+ *  @return
+ *  True if the message was on the SIM during decoding,
+ *  False otherwise.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::DecodedOnSim()
+    {
+    LOGGSMU1("CSmsMessage::DecodedOnSim()");
+
+    if (iFlags & EDecodedOnSimBit)
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    } // CSmsMessage::DecodedOnSim
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
+ *  that it should be forwarded to the client. The message will not be forwarded to the
+ *  client when the PID byte is set to type 0 (except by default for class 0 and class 2 messages).
+ *  
+ *  @param forward
+ *  Used to indicate that the message needs to be forwarded to clients.
+ *  @capability None
+ */
+EXPORT_C void CSmsMessage::SetForwardToClient(TBool aForward)
+    {
+ 	LOGGSMU2("CSmsMessage::SetForwardToClient(): %d", aForward);
+
+    if (aForward)
+        {
+        iFlags = iFlags | EForwardToClientBit;
+        }
+    else
+        {
+        iFlags = iFlags & ~EForwardToClientBit;
+        }
+    } // CSmsMessage::SetForwardToClient
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Used by the SMS Stack to indicate that when the message was decoded, it was determined
+ *  that is should be forwarded to the client. The message will not be forwarded to the client
+ *  when the PID byte is set to type 0 (except by default for class 0 and class 2 messages).
+ *  
+ *  @return
+ *  True if the message is to be forwarded to clients
+ *  False otherwise.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsMessage::ForwardToClient()
+    {
+    LOGGSMU1("CSmsMessage::ForwardToClient()");
+
+    if (iFlags & EForwardToClientBit)
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    } // CSmsMessage::ForwardToClient