smsprotocols/smsstack/gsmu/src/Gsmuelem.cpp
changeset 0 3553901f7fa8
child 5 7ef16719d8cb
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This file implements the different PDU elements
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20 */
       
    21 
       
    22 #include <gsmuelem.h>
       
    23 #include <gsmumsg.h>
       
    24 #include "Gsmumain.h"
       
    25 #include <gsmusar.h>
       
    26 #include "gsmupriv.h"
       
    27 #include <s32strm.h>
       
    28 #include <etelmm.h>
       
    29 #include <gsmuetel.h>
       
    30 #include <exterror.h>
       
    31 #include <emsinformationelement.h>
       
    32 #include <emsformatie.h>
       
    33 #include <charconv.h>
       
    34 
       
    35 /**
       
    36  *  Question Mark character.
       
    37  */
       
    38 const TInt  KReplacementCharacter = 0x003f;
       
    39 
       
    40 
       
    41 /**
       
    42  *  Constructs the object with a descriptor. The extraction mark and next character members are initialised to point to the start of the string.
       
    43  *  
       
    44  *  @param aSource Descriptor to be assigned by reference
       
    45  */
       
    46 TGsmuLex8::TGsmuLex8(const TDesC8& aSource): TLex8(aSource)
       
    47 	{
       
    48 	//NOP
       
    49 	} // TGsmuLex8::TGsmuLex8
       
    50 
       
    51 
       
    52 /**
       
    53  *  Gets the next character in the string and increments the next character position.
       
    54  *  
       
    55  *  @return The next character in the string
       
    56  *  @leave Leaves with KErrGsmuDecoding if at end of string
       
    57  */
       
    58 TUint8 TGsmuLex8::GetL()
       
    59 	{
       
    60 	if (Eos())
       
    61 		LeaveL();
       
    62 
       
    63 	return static_cast<TUint8>(Get());
       
    64 	} // TGsmuLex8::GetL
       
    65 
       
    66 
       
    67 /**
       
    68  *  Increments the next character position by aNumber
       
    69  *  
       
    70  *  @param aNumber The number of characters to increment the next character position by.
       
    71  *  @leave If the increment puts the next character position before the start or beyond the end of the string, the function leaves with KErrGsmuDecoding.
       
    72  */
       
    73 void TGsmuLex8::IncL(TInt aNumber)
       
    74 	{
       
    75 	if (aNumber != 0)
       
    76 		{
       
    77 		if (aNumber < 0 || Eos() || Remainder().Length() < aNumber)
       
    78 			LeaveL();
       
    79 		else
       
    80 			Inc(aNumber);
       
    81 		}
       
    82 	} // TGsmuLex8::IncL
       
    83 
       
    84 
       
    85 /**
       
    86  *  Checks there are enough remaining characters, then returns a TPtrC containing the next aLength characters. Does not increment the current position.
       
    87  *  
       
    88  *  @param aLength Number of characters to return
       
    89  *  @return Remainder().Left(aLength)
       
    90  *  @leave Leaves with KErrGsmuDecoding if there are insufficient characters remaining
       
    91  */
       
    92 TPtrC8 TGsmuLex8::NextWithNoIncL(TInt aLength) const
       
    93 	{
       
    94 	return NextWithNoIncL(aLength, EFalse);
       
    95 	}
       
    96 
       
    97 /**
       
    98  * Checks there are enough remaining characters, then returns a TPtrC containing the next aLength characters. Does not increment the current position.
       
    99  *
       
   100  * @param aLength Number of characters to return
       
   101  * @param aAcceptTruncation ETrue if a mismatch between length indicator and actual length is acceptable. EFalse otherwise.
       
   102  * @return Remainder().Left(aLength) if aAcceptTruncation is EFalse. Remainder() otherwise.
       
   103  * @leave Leaves with KErrGsmuDecoding if there are insufficient characters remaining, unless aAcceptTruncation is ETrue.
       
   104  */
       
   105 TPtrC8 TGsmuLex8::NextWithNoIncL(TInt aLength, TBool aAcceptTruncation) const
       
   106 	{
       
   107 	const TPtrC8 remainder(Remainder());
       
   108 
       
   109 	if ( (aLength < 0) || (remainder.Length()< aLength && !aAcceptTruncation) )
       
   110 		{
       
   111 		LeaveL();
       
   112 		}
       
   113 	
       
   114   if (!aAcceptTruncation)
       
   115 		{
       
   116 		return Remainder().Left(aLength);
       
   117 		}
       
   118 	// aAcceptTruncation is ETrue
       
   119 	else if (remainder.Length() < aLength)
       
   120 		{
       
   121 		return Remainder();
       
   122 		}
       
   123 	// otherwise, no need for truncation:
       
   124   
       
   125 	return Remainder().Left(aLength);
       
   126 	}
       
   127 
       
   128 
       
   129 /**
       
   130  *  Calls TGsmuLeax8::NextWithNoIncL then increments the next character position by aLength
       
   131  *  
       
   132  *  @param aLength Number of characters to return and increment the next character position
       
   133  *  @return Remainder().Left(aLength)
       
   134  *  @leave If the increment puts the next character position before the start or beyond the end of the string, the function leaves with KErrGsmuDecoding.
       
   135  */
       
   136 TPtrC8 TGsmuLex8::NextAndIncL(TInt aLength)
       
   137 	{
       
   138 	const TPtrC8 next(NextWithNoIncL(aLength));
       
   139 	IncL(aLength);
       
   140 	return next;
       
   141 	} // TGsmuLeax8::NextWithNoIncL
       
   142 
       
   143 
       
   144 const TSmsOctet& TSmsOctet::operator = (TInt aValue)
       
   145 	{
       
   146 	iValue = static_cast<TUint8>(aValue);
       
   147 	return *this;
       
   148 	} // TSmsOctet::operator
       
   149 
       
   150 
       
   151 TUint8* TSmsOctet::EncodeL(TUint8* aPtr) const
       
   152 	{
       
   153 	*aPtr=iValue;
       
   154 	return aPtr+1;
       
   155 	} // TSmsOctet::EncodeL
       
   156 
       
   157 
       
   158 TSmsFirstOctet::TSmsFirstOctet(TInt aValue):
       
   159 	TSmsOctet(aValue)
       
   160 	{
       
   161 	} // TSmsFirstOctet::TSmsFirstOctet
       
   162 
       
   163 
       
   164 const TSmsFirstOctet& TSmsFirstOctet::operator = (TInt aValue)
       
   165 	{
       
   166 	TSmsOctet::operator = (aValue);
       
   167 	return *this;
       
   168 	} // TSmsFirstOctet::operator
       
   169 
       
   170 
       
   171 TSmsFailureCause::TSmsFailureCause():
       
   172 	TSmsOctet(ESmsErrorUnspecified)
       
   173 	{
       
   174 	} // TSmsFailureCause::TSmsFailureCause
       
   175 
       
   176 
       
   177 TSmsStatus::TSmsStatus():
       
   178 	TSmsOctet(ESmsShortMessageReceivedBySME)
       
   179 	{
       
   180 	} // TSmsStatus::TSmsStatus
       
   181 
       
   182 
       
   183 CSmsCommandData* CSmsCommandData::NewL(TSmsFirstOctet& aFirstOctet)
       
   184 	{
       
   185 	LOGGSMU1("CSmsCommandData::NewL()");
       
   186 
       
   187 	CSmsCommandData* commanddata=new(ELeave) CSmsCommandData(aFirstOctet);
       
   188 	CleanupStack::PushL(commanddata);
       
   189 	TPtrC8 ptr;
       
   190 	commanddata->SetDataL(ptr);
       
   191 	CleanupStack::Pop();
       
   192 	return commanddata;
       
   193 	} // CSmsCommandData::NewL
       
   194 
       
   195 
       
   196 CSmsCommandData::~CSmsCommandData()
       
   197 	{
       
   198 	iInformationElementArray.ResetAndDestroy();
       
   199 	delete iBuffer;
       
   200 	} // CSmsCommandData::NewL
       
   201 
       
   202 
       
   203 /**
       
   204  *  Duplicates this CSmsCommandData object.
       
   205  * 
       
   206  *  @return  Pointer to the newly created CSmsCommandData object.
       
   207  */
       
   208 CSmsCommandData* CSmsCommandData::DuplicateL() const
       
   209 	{
       
   210 	LOGGSMU1("CSmsCommandData::DuplicateL()");
       
   211 
       
   212 	CSmsCommandData*  smsCommandData = CSmsCommandData::NewL(iFirstOctet);
       
   213 	CleanupStack::PushL(smsCommandData);
       
   214 
       
   215 	smsCommandData->SetDataL(Data());
       
   216 
       
   217 	for (TInt ie = 0;  ie < iInformationElementArray.Count();  ie++)
       
   218 		{
       
   219 		smsCommandData->AddInformationElementL(iInformationElementArray[ie]->Identifier(),
       
   220 											   iInformationElementArray[ie]->Data());
       
   221 		}
       
   222 
       
   223 	CleanupStack::Pop(smsCommandData);
       
   224 
       
   225 	return smsCommandData;
       
   226 	} // CSmsCommandData::DuplicateL
       
   227 
       
   228 
       
   229 CSmsInformationElement& CSmsCommandData::InformationElement(TInt aIndex) const
       
   230 	{
       
   231 	LOGGSMU1("CSmsCommandData::InformationElement()");
       
   232 
       
   233 	CSmsInformationElement* ie=iInformationElementArray[aIndex];
       
   234 	return *ie;
       
   235 	} // CSmsCommandData::InformationElement
       
   236 
       
   237 
       
   238 CSmsInformationElement*& CSmsCommandData::InformationElementPtr(TInt aIndex)
       
   239     {
       
   240     // Ignore in code coverage - not used in SMS stack and not exported
       
   241     // but cannot be removed as impacts public header.
       
   242     BULLSEYE_OFF    
       
   243     LOGGSMU1("CSmsCommandData::InformationElementPtr()");
       
   244     return iInformationElementArray[aIndex];
       
   245     BULLSEYE_RESTORE
       
   246     }
       
   247 
       
   248 TBool CSmsCommandData::InformationElementIndex(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier,
       
   249 		TInt& aIndex) const
       
   250 	{
       
   251 	LOGGSMU1("CSmsCommandData::InformationElementIndex()");
       
   252 
       
   253 	TBool found=EFalse;
       
   254 	TInt count=NumInformationElements();
       
   255 	for (TInt i=0; (!found) && (i<count); i++)
       
   256 		if (InformationElement(i).Identifier()==aIdentifier)
       
   257 			{
       
   258 			found=ETrue;
       
   259 			aIndex=i;
       
   260 			}
       
   261 	return found;
       
   262 	} // CSmsCommandData::InformationElementIndex
       
   263 
       
   264 
       
   265 void CSmsCommandData::AddInformationElementL(const TSmsId aIdentifier,const TDesC8& aData)
       
   266 	{
       
   267 	LOGGSMU1("CSmsCommandData::AddInformationElementL()");
       
   268 
       
   269 	//
       
   270 	// Currently there is no restriction on how many instances of an information element can be
       
   271 	// placed in the collection.
       
   272 	// No restriction will be placed on the number of Special SMS Message Indications that can be
       
   273 	// added in order to maintain FC.
       
   274 	// (cf CSmsUserData::AddInformationElementL(const TSmsId aIdentifier,const TDesC8& aData);
       
   275 	//
       
   276 	CSmsInformationElement* informationelement=CSmsInformationElement::NewL(aIdentifier,aData);
       
   277 	CleanupStack::PushL(informationelement);
       
   278 	iInformationElementArray.AppendL(informationelement);
       
   279 	CleanupStack::Pop();
       
   280 	if (NumInformationElements()>=1)
       
   281 		SetHeaderPresent(ETrue);
       
   282 	} // CSmsCommandData::AddInformationElementL
       
   283 
       
   284 
       
   285 void CSmsCommandData::RemoveInformationElement(TInt aIndex)
       
   286 	{
       
   287 	LOGGSMU1("CSmsCommandData::RemoveInformationElement()");
       
   288 	// Since iInformationElementArray[aIndex] is removed from iInformationElementArray, no double free issue.
       
   289 	// coverity[double_free]
       
   290 	delete iInformationElementArray[aIndex];
       
   291 	iInformationElementArray[aIndex] = NULL;
       
   292 	iInformationElementArray.Delete(aIndex);
       
   293 
       
   294 	if (NumInformationElements()==0)
       
   295 		{
       
   296 		SetHeaderPresent(EFalse);
       
   297 		}
       
   298 	} // CSmsCommandData::RemoveInformationElement
       
   299 
       
   300 
       
   301 TPtrC8 CSmsCommandData::Data() const
       
   302 	{
       
   303 	LOGGSMU1("CSmsCommandData::Data()");
       
   304 
       
   305 	TPtrC8 ptr;
       
   306 	ptr.Set(iBuffer->Des());
       
   307 	return ptr;
       
   308 	} // CSmsCommandData::Data
       
   309 
       
   310 
       
   311 void CSmsCommandData::SetDataL(const TDesC8& aData)
       
   312 	{
       
   313 	LOGGSMU1("CSmsCommandData::SetDataL()");
       
   314 
       
   315 	TInt length=aData.Length();
       
   316 	__ASSERT_DEBUG(length<=KSmsMaxDataSize,Panic(KGsmuPanicCommandDataLengthTooLong));
       
   317 	HBufC8* buffer=HBufC8::NewL(length);
       
   318 	delete iBuffer;
       
   319 	iBuffer=buffer;
       
   320 	iBuffer->Des().SetLength(length);
       
   321 	iBuffer->Des().Copy(aData);
       
   322 	} // CSmsCommandData::SetDataL
       
   323 
       
   324 
       
   325 TUint8* CSmsCommandData::EncodeL(TUint8* aPtr) const
       
   326 	{
       
   327 	LOGGSMU1("CSmsCommandData::EncodeL()");
       
   328 
       
   329 	__ASSERT_DEBUG(iBuffer->Length()<=MaxDataLength(),Panic(KGsmuPanicCommandDataBufferTooLong));
       
   330 	TSmsOctet datalength=iBuffer->Length()+TSmsOctet(TotalHeaderLengthInUDLUnits());
       
   331 	aPtr=datalength.EncodeL(aPtr);
       
   332 	TPtr8 ptr((TUint8*) aPtr,datalength);
       
   333 
       
   334     if (HeaderPresent())
       
   335         {
       
   336 		TSmsOctet headerLength(HeaderLength());
       
   337 		aPtr=headerLength.EncodeL(aPtr);
       
   338 		for (TInt i=0; i<NumInformationElements(); i++)
       
   339 		    {
       
   340 			aPtr=iInformationElementArray[i]->EncodeL(aPtr);
       
   341 		    }
       
   342         }
       
   343 
       
   344 	ptr.Copy(iBuffer->Des());
       
   345 	aPtr+=TInt(iBuffer->Length());
       
   346 	return aPtr;
       
   347 	} // CSmsCommandData::EncodeL
       
   348 
       
   349 
       
   350 void CSmsCommandData::DecodeL(TGsmuLex8& aPdu)
       
   351 	{
       
   352 	LOGGSMU1("CSmsCommandData::DecodeL()");
       
   353 
       
   354 	iInformationElementArray.ResetAndDestroy();
       
   355 	const TBool headerPresent=HeaderPresent();
       
   356 	TSmsOctet dataLength;
       
   357 	dataLength.DecodeL(aPdu);
       
   358 
       
   359 	if (headerPresent)
       
   360 		{
       
   361 		TSmsOctet headerLength;
       
   362 		headerLength.DecodeL(aPdu);
       
   363 		if ((1+headerLength)>KSmsMaxDataSize)
       
   364 			User::Leave(KErrGsmSMSTpduNotSupported);
       
   365 		while (HeaderLength()<headerLength)
       
   366 			{
       
   367 			CSmsInformationElement* informationElement=CSmsInformationElement::NewL();
       
   368 			CleanupStack::PushL(informationElement);
       
   369 			informationElement->DecodeL(aPdu);
       
   370 			iInformationElementArray.AppendL(informationElement);
       
   371 			CleanupStack::Pop(informationElement);
       
   372 			}
       
   373 		if (HeaderLength()!=headerLength)
       
   374 			User::Leave(KErrGsmSMSTpduNotSupported);
       
   375 		}
       
   376 	const TInt totalHeaderLength=TotalHeaderLengthInUDLUnits();
       
   377 	const TInt totalDataLength=dataLength-totalHeaderLength;
       
   378 	const TPtrC8 next(aPdu.NextAndIncL(totalDataLength));
       
   379 	SetDataL(next);
       
   380 	} // CSmsCommandData::DecodeL
       
   381 
       
   382 
       
   383 void CSmsCommandData::InternalizeL(RReadStream& aStream)
       
   384 	{
       
   385 	iInformationElementArray.ResetAndDestroy();
       
   386 	TInt numInformationElements=aStream.ReadInt32L();
       
   387 	for (TInt i=0; i<numInformationElements; i++)
       
   388 		{
       
   389 		CSmsInformationElement* informationElement=CSmsInformationElement::NewL();
       
   390 		CleanupStack::PushL(informationElement);
       
   391 		aStream >> *informationElement;
       
   392 		iInformationElementArray.AppendL(informationElement);
       
   393 		CleanupStack::Pop();
       
   394 		}
       
   395 	HBufC8* buffer=HBufC8::NewL(aStream,KSmsMaxDataSize);
       
   396 	delete iBuffer;
       
   397 	iBuffer=buffer;
       
   398 	} // CSmsCommandData::InternalizeL
       
   399 
       
   400 
       
   401 void CSmsCommandData::ExternalizeL(RWriteStream& aStream) const
       
   402 	{
       
   403 	TInt numInformationElements=iInformationElementArray.Count();
       
   404 	aStream.WriteInt32L(numInformationElements);
       
   405 	for (TInt i=0; i<numInformationElements; i++)
       
   406 		aStream << *iInformationElementArray[i];
       
   407 	aStream << *iBuffer;
       
   408 	} // CSmsCommandData::ExternalizeL
       
   409 
       
   410 
       
   411 CSmsCommandData::CSmsCommandData(TSmsFirstOctet& aFirstOctet):
       
   412 	iFirstOctet(aFirstOctet),
       
   413 	iInformationElementArray(8)
       
   414 	{
       
   415 	} // CSmsCommandData::CSmsCommandData
       
   416 
       
   417 
       
   418 TInt CSmsCommandData::HeaderLength() const
       
   419 	{
       
   420 	LOGGSMU1("CSmsCommandData::HeaderLength()");
       
   421 
       
   422 	TInt headerLength=0;
       
   423 	for (TInt i=0; i<NumInformationElements(); i++)
       
   424 		headerLength+=iInformationElementArray[i]->Length();
       
   425 	return headerLength;
       
   426 	} // CSmsCommandData::HeaderLength
       
   427 
       
   428 
       
   429 TInt CSmsCommandData::TotalHeaderLengthInUDLUnits() const
       
   430 	{
       
   431 	LOGGSMU1("CSmsCommandData::TotalHeaderLengthInUDLUnits()");
       
   432 
       
   433 	if (iInformationElementArray.Count()==0)
       
   434 		return 0;
       
   435 	else
       
   436 		return (HeaderLength()+1);   // +1 stands for  UDHL
       
   437 	} // CSmsCommandData::TotalHeaderLengthInUDLUnits
       
   438 
       
   439 
       
   440 TBool CSmsCommandData::HeaderPresent() const
       
   441 	{
       
   442 	LOGGSMU1("CSmsCommandData::HeaderPresent()");
       
   443 
       
   444 	return (iFirstOctet&TSmsFirstOctet::ESmsUDHIMask)==TSmsFirstOctet::ESmsUDHIHeaderPresent;
       
   445 	} // CSmsCommandData::HeaderPresent
       
   446 
       
   447 
       
   448 void CSmsCommandData::SetHeaderPresent(TBool aHeaderPresent)
       
   449 	{
       
   450 	LOGGSMU1("CSmsCommandData::SetHeaderPresent()");
       
   451 
       
   452 	iFirstOctet=aHeaderPresent? (iFirstOctet&(~TSmsFirstOctet::ESmsUDHIMask))|TSmsFirstOctet::ESmsUDHIHeaderPresent: (iFirstOctet&(~TSmsFirstOctet::ESmsUDHIMask))|TSmsFirstOctet::ESmsUDHIHeaderNotPresent;
       
   453 	} // CSmsCommandData::SetHeaderPresent
       
   454 
       
   455 
       
   456 TSmsParameterIndicator::TSmsParameterIndicator():
       
   457 	TSmsOctet(ESmsPIDProtocolIdentifierPresent|ESmsPIDUserDataPresent|ESmsPIDDataCodingSchemePresent)
       
   458 	{
       
   459 	} // TSmsParameterIndicator::TSmsParameterIndicator
       
   460 
       
   461 
       
   462 TSmsCommandType::TSmsCommandType():
       
   463 	TSmsOctet(ESmsCommandTypeEnquiry)
       
   464 	{
       
   465 	} // TSmsCommandType::TSmsCommandType
       
   466 
       
   467 
       
   468 TSmsProtocolIdentifier::TSmsProtocolIdentifier():
       
   469 	TSmsOctet((TInt)ESmsPIDTelematicInterworking|(TInt)ESmsNoTelematicDevice)
       
   470 	{
       
   471 	} // TSmsProtocolIdentifier::TSmsProtocolIdentifier
       
   472 
       
   473 
       
   474 TSmsProtocolIdentifier::TSmsTelematicDeviceIndicator TSmsProtocolIdentifier::TelematicDeviceIndicator() const
       
   475 	{
       
   476 	__ASSERT_DEBUG(PIDType()==ESmsPIDTelematicInterworking,Panic(KGsmuPanicNoTelematicInterworking));
       
   477 	return (TSmsTelematicDeviceIndicator) (iValue&EPIDTelematicDeviceIndicatorMask);
       
   478 	} // TSmsProtocolIdentifier::TSmsTelematicDeviceIndicator
       
   479 
       
   480 
       
   481 void TSmsProtocolIdentifier::SetTelematicDeviceIndicator(TSmsTelematicDeviceIndicator aIndicator)
       
   482 	{
       
   483 	LOGGSMU1("TSmsProtocolIdentifier::SetTelematicDeviceIndicator()");
       
   484 
       
   485 	__ASSERT_DEBUG(PIDType()==ESmsPIDTelematicInterworking,Panic(KGsmuPanicNoTelematicInterworking));
       
   486 
       
   487 	//iValue=(TUint8) ((iValue&ESmsPIDTypeMask)|aIndicator);
       
   488 	iValue=(TUint8) ((iValue&(~EPIDTelematicDeviceIndicatorMask))|aIndicator);
       
   489 	} // TSmsProtocolIdentifier::SetTelematicDeviceIndicator
       
   490 
       
   491 
       
   492 TSmsProtocolIdentifier::TSmsTelematicDeviceType TSmsProtocolIdentifier::TelematicDeviceType() const
       
   493 	{
       
   494 	__ASSERT_DEBUG(TelematicDeviceIndicator()==ESmsTelematicDevice,Panic(KGsmuPanicNoTelematicDevice));
       
   495 	return (TSmsTelematicDeviceType) (iValue&ESmsTelematicDeviceTypeMask);
       
   496 	} // TSmsProtocolIdentifier::TSmsTelematicDeviceType
       
   497 
       
   498 
       
   499 void TSmsProtocolIdentifier::SetTelematicDeviceType(TSmsTelematicDeviceType aDeviceType)
       
   500 	{
       
   501 	LOGGSMU1("TSmsProtocolIdentifier::SetTelematicDeviceType()");
       
   502 
       
   503 	__ASSERT_DEBUG(TelematicDeviceIndicator()==ESmsTelematicDevice,Panic(KGsmuPanicNoTelematicDevice));
       
   504 	iValue=(TUint8) ((iValue&(~ESmsTelematicDeviceTypeMask))|aDeviceType);
       
   505 	} // TSmsProtocolIdentifier::SetTelematicDeviceType
       
   506 
       
   507 
       
   508 TInt TSmsProtocolIdentifier::ShortMessageALProtocol() const
       
   509     {
       
   510     // Ignore in code coverage - not used in SMS stack and not exported
       
   511     // but cannot be removed as impacts public header.
       
   512     BULLSEYE_OFF    
       
   513     LOGGSMU1("TSmsProtocolIdentifier::ShortMessageALProtocol()");
       
   514     
       
   515     __ASSERT_DEBUG(TelematicDeviceIndicator()==ESmsNoTelematicDevice,Panic(KGsmuPanicNoTelematicDevice));
       
   516     return (TSmsShortMessageALProtocol) (iValue&ESmsShortMessageALProtocolMask);
       
   517     BULLSEYE_RESTORE
       
   518     }
       
   519 
       
   520 void TSmsProtocolIdentifier::SetShortMessageALProtocol(TSmsShortMessageALProtocol aProtocol)
       
   521     {
       
   522     // Ignore in code coverage - not used in SMS stack and not exported
       
   523     // but cannot be removed as impacts public header.
       
   524     BULLSEYE_OFF    
       
   525     LOGGSMU1("TSmsProtocolIdentifier::SetShortMessageALProtocol()");
       
   526     
       
   527     __ASSERT_DEBUG(TelematicDeviceIndicator()==ESmsNoTelematicDevice,Panic(KGsmuPanicNoTelematicDevice));
       
   528     iValue=(TUint8) ((iValue&(~ESmsShortMessageALProtocolMask))|aProtocol);
       
   529     BULLSEYE_RESTORE
       
   530     }
       
   531 
       
   532 TInt TSmsProtocolIdentifier::ShortMessageType() const
       
   533 	{
       
   534 	LOGGSMU1("TSmsProtocolIdentifier::ShortMessageType()");
       
   535 
       
   536 	__ASSERT_DEBUG(PIDType()==ESmsPIDShortMessageType,Panic(KGsmuPanicNoShortMessageType));
       
   537 	return (TSmsShortMessageType) (iValue&ESmsShortMessageTypeMask);
       
   538 	} // TSmsProtocolIdentifier::ShortMessageType
       
   539 
       
   540 
       
   541 void TSmsProtocolIdentifier::SetShortMessageType(TSmsShortMessageType aShortMessageType)
       
   542 	{
       
   543 	LOGGSMU1("TSmsProtocolIdentifier::SetShortMessageType()");
       
   544 
       
   545 	__ASSERT_DEBUG(PIDType()==ESmsPIDShortMessageType,Panic(KGsmuPanicNoShortMessageType));
       
   546 	//iValue=(TUint8) ((iValue&(~ESmsPIDTypeMask))|aShortMessageType);
       
   547 	iValue=(TUint8) ((iValue&(~ESmsShortMessageTypeMask))|aShortMessageType);
       
   548 	} // TSmsProtocolIdentifier::SetShortMessageType
       
   549 
       
   550 
       
   551 TSmsDataCodingScheme::TSmsDataCodingScheme():
       
   552 	TSmsOctet((TInt)ESmsDCSTextUncompressedWithNoClassInfo|(TInt)ESmsAlphabet7Bit|(TInt)ESmsClass0)
       
   553 	// Constructor is expected to set the octet = 0, This is needed by
       
   554 	// CSmsDeliverReport::DecodeL, CSmsSubmitReport::DecodeL and CSmsStatusReport::DecodeL, per
       
   555 	// 23.040 v6.5.0 section 9.2.3.27.
       
   556 	{
       
   557 	} // CSmsDeliverReport::DecodeL
       
   558 
       
   559 
       
   560 TBool TSmsDataCodingScheme::TextCompressed() const
       
   561 	{
       
   562 	LOGGSMU1("TSmsDataCodingScheme::TextCompressed()");
       
   563 
       
   564 	TInt bits7to4=Bits7To4();
       
   565 	return (bits7to4==ESmsDCSTextCompressedWithNoClassInfo)    || (bits7to4==ESmsDCSTextCompressedWithClassInfo)      ||
       
   566            (bits7to4==ESmsDCSAutoDelNoClassInfoCompressedText) || (bits7to4==ESmsDCSAutoDelClassInfoTextCompressedText);
       
   567 	} // TSmsDataCodingScheme::TextCompressed
       
   568 
       
   569 
       
   570 void TSmsDataCodingScheme::SetTextCompressed(TBool aCompressed)
       
   571 	{
       
   572 	LOGGSMU1("TSmsDataCodingScheme::SetTextCompressed()");
       
   573 
       
   574 	TInt bits7to4=Bits7To4();
       
   575 	if (aCompressed)
       
   576 		{
       
   577 		switch (bits7to4)
       
   578 			{
       
   579 			case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   580 				{
       
   581 				iValue=(TUint8) (ESmsDCSTextCompressedWithNoClassInfo|(iValue&(~ESmsDCSBits7To4Mask)));
       
   582 				break;
       
   583 				}
       
   584 			case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   585 				{
       
   586 				iValue=(TUint8) (ESmsDCSAutoDelNoClassInfoCompressedText|(iValue&(~ESmsDCSBits7To4Mask)));
       
   587 				break;
       
   588 				}
       
   589 			case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   590 				{
       
   591 				iValue=(TUint8) (ESmsDCSAutoDelClassInfoTextCompressedText|(iValue&(~ESmsDCSBits7To4Mask)));
       
   592 				break;
       
   593 				}
       
   594 			case (ESmsDCSTextUncompressedWithClassInfo):
       
   595 			case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   596 				{
       
   597 				iValue=(TUint8) (ESmsDCSTextCompressedWithClassInfo|(iValue&(~ESmsDCSBits7To4Mask)));
       
   598 				break;
       
   599 				}
       
   600 			case (ESmsDCSTextCompressedWithNoClassInfo):
       
   601 			case (ESmsDCSTextCompressedWithClassInfo):
       
   602 			case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   603 			case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   604 				break;
       
   605 			default:
       
   606                 break;
       
   607                 // has to be tested, what happens in this default case
       
   608 				//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   609 			}
       
   610 		}
       
   611 	else
       
   612 		{
       
   613 		switch (bits7to4)
       
   614 			{
       
   615 			case (ESmsDCSTextCompressedWithNoClassInfo):
       
   616 				{
       
   617 				iValue=(TUint8) (ESmsDCSTextUncompressedWithNoClassInfo|(iValue&(~ESmsDCSBits7To4Mask)));
       
   618 				break;
       
   619 				}
       
   620 			case (ESmsDCSTextCompressedWithClassInfo):
       
   621 				{
       
   622 				iValue=(TUint8) (ESmsDCSTextUncompressedWithClassInfo|(iValue&(~ESmsDCSBits7To4Mask)));
       
   623 				break;
       
   624 				}
       
   625 			case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   626 				{
       
   627 				iValue=(TUint8) (ESmsDCSAutoDelNoClassInfoUncompressedText|(iValue&(~ESmsDCSBits7To4Mask)));
       
   628 				break;
       
   629 				}
       
   630 			case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   631 				{
       
   632 				iValue=(TUint8) ( ESmsDCSAutoDelClassInfoUncompressedText|(iValue&(~ESmsDCSBits7To4Mask)));
       
   633 				break;
       
   634 				}
       
   635 			case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   636 			case (ESmsDCSTextUncompressedWithClassInfo):
       
   637             case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   638             case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   639 			case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   640 			default:
       
   641 				{
       
   642 				}
       
   643 			}
       
   644 		}
       
   645 	} // TSmsDataCodingScheme::SetTextCompressed
       
   646 
       
   647 
       
   648 TSmsDataCodingScheme::TSmsAlphabet TSmsDataCodingScheme::Alphabet() const
       
   649 	{
       
   650 	LOGGSMU1("TSmsDataCodingScheme::TSmsAlphabet()");
       
   651 
       
   652 	TInt bits7to4=Bits7To4();
       
   653 	TInt alphabet=ESmsAlphabet7Bit;
       
   654 	switch (bits7to4)
       
   655 		{
       
   656 		case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   657 		case (ESmsDCSTextUncompressedWithClassInfo):
       
   658 		case (ESmsDCSTextCompressedWithNoClassInfo):  //  Alphabet not used in these cases
       
   659 		case (ESmsDCSTextCompressedWithClassInfo):
       
   660 		case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   661 		case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   662 		case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   663 		case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   664 			{
       
   665 			alphabet=iValue&ESmsAlphabetMask;
       
   666 			break;
       
   667 			}
       
   668 		case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   669 			{
       
   670 			alphabet=iValue&ESmsAlphabet8Bit;  //  N.B. only one bit used to code alphabet
       
   671 			break;
       
   672 			}
       
   673 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   674 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   675 			{
       
   676 			alphabet=ESmsAlphabet7Bit;
       
   677 			break;
       
   678 			}
       
   679 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   680 			{
       
   681 			alphabet=ESmsAlphabetUCS2;
       
   682 			break;
       
   683 			}
       
   684 		default:
       
   685             break;
       
   686             // TODO - ahe - Never Panic GSMU !!!
       
   687             // has to be tested, what happens in this default case
       
   688             // Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   689 		}
       
   690 	return (TSmsAlphabet) alphabet;
       
   691 	} // TSmsDataCodingScheme::TSmsAlphabet
       
   692 
       
   693 
       
   694 void TSmsDataCodingScheme::SetAlphabet(TSmsAlphabet aAlphabet)
       
   695 	{
       
   696 	LOGGSMU1("TSmsDataCodingScheme::SetAlphabet()");
       
   697 
       
   698 	TInt bits7to4=Bits7To4();
       
   699 	switch (bits7to4)
       
   700 		{
       
   701 		case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   702 		case (ESmsDCSTextUncompressedWithClassInfo):
       
   703 		case (ESmsDCSTextCompressedWithNoClassInfo):  //  Alphabet not used in these cases
       
   704 		case (ESmsDCSTextCompressedWithClassInfo):
       
   705 		case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   706 		case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   707 		case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   708 		case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   709 			{
       
   710 			iValue=(TUint8) ((iValue&(~ESmsAlphabetMask))|aAlphabet);
       
   711 			break;
       
   712 			}
       
   713 		case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   714 			{
       
   715 			if ((aAlphabet==ESmsAlphabet7Bit) || (aAlphabet==ESmsAlphabet8Bit))
       
   716 				{
       
   717 				iValue=(TUint8) ((iValue&(~ESmsAlphabet8Bit))|aAlphabet);  //  N.B. only one bit used to code alphabet
       
   718 				}
       
   719 			break;
       
   720 			}
       
   721 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   722 			{
       
   723             // TODO - ahe - Never Panic GSMU !!!
       
   724             // has to be tested, what happens in this default case
       
   725 			//if (aAlphabet!=ESmsAlphabet7Bit)
       
   726 				//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   727 			break;
       
   728 			}
       
   729 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   730 			{
       
   731             // TODO - ahe - Never Panic GSMU !!!
       
   732             // has to be tested, what happens in this default case
       
   733 			//if (aAlphabet==ESmsAlphabet8Bit)
       
   734 				//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   735 			if (aAlphabet==ESmsAlphabetUCS2)
       
   736 				iValue=(TUint8) (ESmsDCSMessageWaitingIndicationUCS2|(iValue&(~ESmsDCSBits7To4Mask)));
       
   737 			break;
       
   738 			}
       
   739 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   740 			{
       
   741             // TODO - ahe - Never Panic GSMU !!!
       
   742             // has to be tested, what happens in this default case
       
   743 			//if (aAlphabet==ESmsAlphabet8Bit)
       
   744 				//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   745 			if (aAlphabet==ESmsAlphabet7Bit)
       
   746 				iValue=(TUint8) (ESmsDCSMessageWaitingIndication7Bit|(iValue&(~ESmsDCSBits7To4Mask)));
       
   747 			break;
       
   748 			}
       
   749 		default:
       
   750             break;
       
   751             // TODO - ahe - Never Panic GSMU !!!
       
   752             // has to be tested, what happens in this default case
       
   753 			//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   754 		}
       
   755 	} // TSmsDataCodingScheme::SetAlphabet
       
   756 
       
   757 
       
   758 TBool TSmsDataCodingScheme::Class(TSmsClass& aClass) const
       
   759 	{
       
   760 	LOGGSMU1("TSmsDataCodingScheme::Class()");
       
   761 
       
   762 	switch (Bits7To4())
       
   763 		{
       
   764 		case (ESmsDCSTextUncompressedWithClassInfo):
       
   765 		case (ESmsDCSTextCompressedWithClassInfo):
       
   766 		case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   767 		case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   768 		case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   769 			aClass=(TSmsClass) (iValue&ESmsClassMask);
       
   770 			return ETrue;
       
   771 		default:
       
   772 			return EFalse;
       
   773 		}
       
   774 	} // TSmsDataCodingScheme::Class
       
   775 
       
   776 
       
   777 void TSmsDataCodingScheme::SetClass(TBool aClassDefined,TSmsDataCodingScheme::TSmsClass aClass)
       
   778 	{
       
   779 	LOGGSMU1("TSmsDataCodingScheme::SetClass()");
       
   780 
       
   781 	TInt bits7to4=Bits7To4();
       
   782 	if (aClassDefined)
       
   783 		{
       
   784 		switch (bits7to4)
       
   785 			{
       
   786 			case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   787 				{
       
   788 				iValue=(TUint8) (ESmsDCSTextUncompressedWithClassInfo|(iValue&ESmsAlphabetMask|aClass));
       
   789 				break;
       
   790 				}
       
   791 			case (ESmsDCSTextCompressedWithNoClassInfo):
       
   792 				{
       
   793 				iValue=(TUint8) (ESmsDCSTextCompressedWithClassInfo|(iValue&ESmsAlphabetMask|aClass));
       
   794 				break;
       
   795 				}
       
   796 			case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   797 				{
       
   798 				iValue=(TUint8) (ESmsDCSAutoDelClassInfoUncompressedText|(iValue&ESmsAlphabetMask|aClass));
       
   799 				break;
       
   800 				}
       
   801 			case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   802 				{
       
   803 				iValue=(TUint8) (ESmsDCSAutoDelClassInfoTextCompressedText|(iValue&ESmsAlphabetMask|aClass));
       
   804 				break;
       
   805 				}
       
   806 			case (ESmsDCSTextUncompressedWithClassInfo):
       
   807 			case (ESmsDCSTextCompressedWithClassInfo):
       
   808 			case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   809 			case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   810 			case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   811 
       
   812 				{
       
   813 				iValue=(TUint8) (iValue&(~ESmsClassMask)|aClass);
       
   814 				break;
       
   815 				}
       
   816 			default:
       
   817                 break;
       
   818             // TODO - ahe - Never Panic GSMU !!!
       
   819             // has to be tested, what happens in this default case
       
   820 				//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   821 			}
       
   822 		}
       
   823 	else
       
   824 		{
       
   825 		switch (bits7to4)
       
   826 			{
       
   827 			case (ESmsDCSTextUncompressedWithClassInfo):
       
   828 				{
       
   829 				iValue=(TUint8) (ESmsDCSTextUncompressedWithNoClassInfo|(iValue&ESmsAlphabetMask)|aClass);
       
   830 				break;
       
   831 				}
       
   832 			case (ESmsDCSTextCompressedWithClassInfo):
       
   833 				{
       
   834 				iValue=(TUint8) (ESmsDCSTextCompressedWithNoClassInfo|(iValue&ESmsAlphabetMask)|aClass);
       
   835 				break;
       
   836 				}
       
   837 			case (ESmsDCSAutoDelClassInfoUncompressedText):
       
   838 				{
       
   839 				iValue=(TUint8) (ESmsDCSAutoDelNoClassInfoUncompressedText|(iValue&ESmsAlphabetMask)|aClass);
       
   840 				break;
       
   841 				}
       
   842 			case (ESmsDCSAutoDelClassInfoTextCompressedText):
       
   843 				{
       
   844 				iValue=(TUint8) (ESmsDCSAutoDelNoClassInfoCompressedText|(iValue&ESmsAlphabetMask)|aClass);
       
   845 				break;
       
   846 				}
       
   847 			case (ESmsDCSTextUncompressed7BitOr8Bit):
       
   848 				{
       
   849 				iValue=(TUint8) (ESmsDCSTextUncompressedWithNoClassInfo|(iValue&ESmsAlphabetMask)|aClass);
       
   850 				break;
       
   851 				}
       
   852 			case (ESmsDCSTextUncompressedWithNoClassInfo):
       
   853 			case (ESmsDCSTextCompressedWithNoClassInfo):
       
   854 			case (ESmsDCSAutoDelNoClassInfoUncompressedText):
       
   855 			case (ESmsDCSAutoDelNoClassInfoCompressedText):
       
   856 			case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   857 			case (ESmsDCSMessageWaitingIndication7Bit):
       
   858 			case (ESmsDCSMessageWaitingIndicationUCS2):
       
   859 			default:
       
   860 				{
       
   861 				}
       
   862 			}
       
   863 		}
       
   864 	} // TSmsDataCodingScheme::SetClass
       
   865 
       
   866 
       
   867 TSmsDataCodingScheme::TSmsIndicationState TSmsDataCodingScheme::IndicationState() const
       
   868 	{
       
   869 	LOGGSMU1("TSmsDataCodingScheme::IndicationState()");
       
   870 
       
   871 	TInt bits7to4=Bits7To4();
       
   872 	TSmsIndicationState state=ESmsIndicationInactive;
       
   873 	switch (bits7to4)
       
   874 		{
       
   875 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   876 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   877 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   878 			{
       
   879 			state=(TSmsIndicationState) (iValue&ESmsIndicationStateMask);
       
   880 			break;
       
   881 			}
       
   882 		default:
       
   883             break;
       
   884             // TODO - ahe - Never Panic GSMU !!!
       
   885             // has to be tested, what happens in this default case
       
   886 			//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   887 		}
       
   888 	return state;
       
   889 	} // TSmsDataCodingScheme::TSmsIndicationState
       
   890 
       
   891 
       
   892 void TSmsDataCodingScheme::SetIndicationState(TSmsIndicationState aState)
       
   893 	{
       
   894 	LOGGSMU1("TSmsDataCodingScheme::SetIndicationState()");
       
   895 
       
   896 	TInt bits7to4=Bits7To4();
       
   897 	switch (bits7to4)
       
   898 		{
       
   899 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   900 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   901 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   902 			{
       
   903 			iValue=(TUint8) (aState | (iValue&(~ESmsIndicationStateMask)));
       
   904 			break;
       
   905 			}
       
   906 		default:
       
   907             break;
       
   908             // TODO - ahe - Never Panic GSMU !!!
       
   909             // has to be tested, what happens in this default case
       
   910 			//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   911 		}
       
   912 	} // TSmsDataCodingScheme::SetIndicationState
       
   913 
       
   914 
       
   915 TSmsDataCodingScheme::TSmsIndicationType TSmsDataCodingScheme::IndicationType() const
       
   916 	{
       
   917 	LOGGSMU1("TSmsDataCodingScheme::IndicationType()");
       
   918 
       
   919 	TInt bits7to4=Bits7To4();
       
   920 	TSmsIndicationType type=ESmsVoicemailMessageWaiting;
       
   921 	switch (bits7to4)
       
   922 		{
       
   923 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   924 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   925 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   926 			{
       
   927 			type=(TSmsIndicationType) (iValue&ESmsIndicationTypeMask);
       
   928 			break;
       
   929 			}
       
   930 		default:
       
   931             break;
       
   932             // TODO - ahe - Never Panic GSMU !!!
       
   933             // has to be tested, what happens in this default case
       
   934 			//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   935 		}
       
   936 	return type;
       
   937 	} // TSmsDataCodingScheme::TSmsIndicationType
       
   938 
       
   939 
       
   940 void TSmsDataCodingScheme::SetIndicationType(TSmsIndicationType aType)
       
   941 	{
       
   942 	LOGGSMU1("TSmsDataCodingScheme::SetIndicationType()");
       
   943 
       
   944 	TInt bits7to4=Bits7To4();
       
   945 	switch (bits7to4)
       
   946 		{
       
   947 		case (ESmsDCSMessageWaitingIndicationDiscardMessage):
       
   948 		case (ESmsDCSMessageWaitingIndication7Bit):
       
   949 		case (ESmsDCSMessageWaitingIndicationUCS2):
       
   950 			{
       
   951 			iValue=(TUint8) (aType | (iValue&(~ESmsIndicationTypeMask)));
       
   952 			break;
       
   953 			}
       
   954 		default:
       
   955             break;
       
   956             // TODO - ahe - Never Panic GSMU !!!
       
   957             // has to be tested, what happens in this default case
       
   958 			//Panic(KGsmuPanicNotSupportedWithDCSBits7To4);
       
   959 		}
       
   960 	} // TSmsDataCodingScheme::SetIndicationType
       
   961 
       
   962 
       
   963 /**
       
   964  *  Allocates and creates a CSmsAlphabetConverter object, specifying an Alphabet
       
   965  *  Coding scheme and a Binary flag.
       
   966  *  
       
   967  *  @param aCharacterSetConverter Pre-initialised character set converter
       
   968  *  @param aFs File system handle
       
   969  *  @param aSmsAlphabet Data coding scheme alphabet
       
   970  *  @param aIsBinary Set to true for WAP or compressed data
       
   971  *  @return New CSmsAlphabetConverter object
       
   972  *  @capability None
       
   973  */
       
   974 EXPORT_C CSmsAlphabetConverter* CSmsAlphabetConverter::NewLC(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs,TSmsDataCodingScheme::TSmsAlphabet aSmsAlphabet,TBool aIsBinary)
       
   975 	{
       
   976 	LOGGSMU1("CSmsAlphabetConverter::NewLC()");
       
   977 
       
   978 	CSmsAlphabetConverter* converter=new (ELeave)CSmsAlphabetConverter(aCharacterSetConverter,aFs,aSmsAlphabet,aIsBinary);
       
   979 	CleanupStack::PushL(converter);
       
   980 	converter->ConstructL();
       
   981 	return converter;
       
   982 	} // CSmsAlphabetConverter::NewLC
       
   983 
       
   984 
       
   985 /**
       
   986  *  Destructor.
       
   987  *  @capability None
       
   988  */
       
   989 EXPORT_C CSmsAlphabetConverter::~CSmsAlphabetConverter()
       
   990     {
       
   991     delete iConvertedNativeCharacters;
       
   992     delete iConvertedUDElements;
       
   993     delete iUnconvertedNativeCharacters;
       
   994     delete iUnconvertedUDElements;
       
   995     } // CSmsAlphabetConverter::NewLC
       
   996 
       
   997 
       
   998 //
       
   999 // C'tor - standard stuff
       
  1000 //
       
  1001 CSmsAlphabetConverter::CSmsAlphabetConverter(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs,TSmsDataCodingScheme::TSmsAlphabet aSmsAlphabet,TBool aIsBinary)
       
  1002     : iCharacterSetConverter(aCharacterSetConverter),
       
  1003     iFs(aFs),
       
  1004     iSmsAlphabet(aSmsAlphabet),
       
  1005     iIsBinary(aIsBinary),
       
  1006     iUnconvertedNativeCharactersPtr(NULL,0),
       
  1007     iUnconvertedUDElementsPtr(NULL,0)
       
  1008     {
       
  1009     } // CSmsAlphabetConverter::CSmsAlphabetConverter
       
  1010 
       
  1011 
       
  1012 //
       
  1013 // Ensures this is a supported character set if not binary conversion
       
  1014 //
       
  1015 void CSmsAlphabetConverter::ConstructL()
       
  1016 	{
       
  1017 	LOGGSMU1("CSmsAlphabetConverter::ConstructL()");
       
  1018 
       
  1019 
       
  1020 	if (!iIsBinary)
       
  1021 		{
       
  1022 		switch (iSmsAlphabet)
       
  1023 			{
       
  1024 			case TSmsDataCodingScheme::ESmsAlphabet7Bit:
       
  1025 			case TSmsDataCodingScheme::ESmsAlphabet8Bit:
       
  1026 			case TSmsDataCodingScheme::ESmsAlphabetUCS2:
       
  1027 				{
       
  1028 				// Supported
       
  1029 				break;
       
  1030 				}
       
  1031 			default:
       
  1032 				{
       
  1033 				// Not supported
       
  1034 				User::Leave(KErrGsmSMSDataCodingSchemeNotSupported);
       
  1035 				break;
       
  1036 				}
       
  1037 			}
       
  1038 		}
       
  1039 	} // CSmsAlphabetConverter::ConstructL
       
  1040 
       
  1041 
       
  1042 //
       
  1043 // Returns whether the character set converter is invoked.  Provided to allow
       
  1044 // clients to provided efficient converted length calculation where no
       
  1045 // conversion is required.
       
  1046 //
       
  1047 void CSmsAlphabetConverter::ConversionPropertiesL(TSmsAlphabetConversionProperties& aConversionProperties) const
       
  1048 	{
       
  1049 	LOGGSMU1("CSmsAlphabetConverter::ConversionPropertiesL()");
       
  1050 
       
  1051 
       
  1052 	// Set defaults
       
  1053 	aConversionProperties.iWidthConversion=ESmsAlphabetWidthConversionFixed;
       
  1054 	aConversionProperties.iUDElementsPerNativeCharacter=1;
       
  1055 	// Modify if different
       
  1056 	if (iIsBinary)
       
  1057 		return;
       
  1058 	switch (iSmsAlphabet)
       
  1059 		{
       
  1060 		case TSmsDataCodingScheme::ESmsAlphabet7Bit:
       
  1061 		case TSmsDataCodingScheme::ESmsAlphabet8Bit:
       
  1062 			{
       
  1063 			aConversionProperties.iWidthConversion=ESmsAlphabetWidthConversionVariable;
       
  1064 			break;
       
  1065 			}
       
  1066 		case TSmsDataCodingScheme::ESmsAlphabetUCS2:
       
  1067 			{
       
  1068 			aConversionProperties.iUDElementsPerNativeCharacter=sizeof(TText);
       
  1069 			break;
       
  1070 			}
       
  1071 		default:
       
  1072 			{
       
  1073 			User::Leave(KErrGsmSMSDataCodingSchemeNotSupported);
       
  1074 			}
       
  1075 		}
       
  1076 	} // CSmsAlphabetConverter::ConversionPropertiesL
       
  1077 
       
  1078 
       
  1079 /**
       
  1080  *  Converts from the native character set to unpacked user data elements of the
       
  1081  *  desired character set.
       
  1082  *  
       
  1083  *  The function stores the converted data internally.
       
  1084  *  
       
  1085  *  @param aNativeCharacters The native character set data (Unicode only)
       
  1086  *  @return Converted characters
       
  1087  *  @capability None
       
  1088  */
       
  1089 EXPORT_C TPtrC8 CSmsAlphabetConverter::ConvertFromNativeL(const TDesC& aNativeCharacters)
       
  1090 	{
       
  1091 	LOGGSMU1("CSmsAlphabetConverter::ConvertFromNativeL()");
       
  1092 
       
  1093 	TInt  numberOfUnconvertibleCharacters, numberOfDowngradedCharacters;
       
  1094 
       
  1095 	return ConvertFromNativeL(aNativeCharacters, ESmsEncodingNone,
       
  1096 			                  numberOfUnconvertibleCharacters,
       
  1097 			                  numberOfDowngradedCharacters);
       
  1098 	} // CSmsAlphabetConverter::ConvertFromNativeL
       
  1099 
       
  1100 
       
  1101 /**
       
  1102  *  Converts from the native character set to unpacked user data elements of the
       
  1103  *  desired character set.
       
  1104  *  
       
  1105  *  The function stores the converted data internally.
       
  1106  *  
       
  1107  *  @param aNativeCharacters                 The native character set data (Unicode only)
       
  1108  *  @param aNumberOfUnconvertibleCharacters  Number of characters unconverted
       
  1109  *  @param aNumberOfDowngradedCharacters     Number of characters downgraded
       
  1110  *  @param aEncoding                         Alternative 7bit encoding to used (if needed)
       
  1111  * 
       
  1112  *  @return Converted characters
       
  1113  * 
       
  1114  *  @capability None
       
  1115  */
       
  1116 EXPORT_C TPtrC8 CSmsAlphabetConverter::ConvertFromNativeL(const TDesC& aNativeCharacters,
       
  1117                                                           TSmsEncoding aEncoding,
       
  1118                                                           TInt& aNumberOfUnconvertibleCharacters,
       
  1119 			                                              TInt& aNumberOfDowngradedCharacters)
       
  1120 	{
       
  1121 	LOGGSMU2("CSmsAlphabetConverter::ConvertFromNativeL(): aEncoding=%d", aEncoding);
       
  1122 	
       
  1123 	aNumberOfUnconvertibleCharacters = 0;
       
  1124 	aNumberOfDowngradedCharacters    = 0;
       
  1125 
       
  1126 	// Check for some shortcuts
       
  1127 	if (iIsBinary ||  iSmsAlphabet == TSmsDataCodingScheme::ESmsAlphabet8Bit)
       
  1128 		{
       
  1129 		// Binary data stored as padded unicode
       
  1130 		TPtr8 outputPtr=CheckAllocBufferL(&iConvertedUDElements,aNativeCharacters.Length(),0);
       
  1131 		outputPtr.Copy(aNativeCharacters);
       
  1132 		iUnconvertedNativeCharactersPtr.Zero();
       
  1133 		return outputPtr;
       
  1134 		}
       
  1135 	else if (iSmsAlphabet==TSmsDataCodingScheme::ESmsAlphabetUCS2)
       
  1136 		{
       
  1137 		TInt nativeCharactersLength = aNativeCharacters.Length();
       
  1138 		// 16-bit copy with possible endianess correction
       
  1139 		TInt elementCount=nativeCharactersLength*2;
       
  1140 		TPtr8 outputPtr(CheckAllocBufferL(&iConvertedUDElements,elementCount,elementCount));
       
  1141 	    for (TInt i=0;i<nativeCharactersLength;i++)
       
  1142 		    {
       
  1143 		    outputPtr[2*i]=(TUint8)(aNativeCharacters[i]>>8);
       
  1144 		    outputPtr[2*i+1]=(TUint8)aNativeCharacters[i];
       
  1145 		    }
       
  1146 		iUnconvertedNativeCharactersPtr.Zero();
       
  1147 		return outputPtr;
       
  1148 		}
       
  1149 	else // No shortcuts, do proper conversion
       
  1150 		{
       
  1151 		PrepareForConversionFromNativeL(aEncoding);
       
  1152 		
       
  1153 		// Create input buffer
       
  1154 		TInt newInputLength=iUnconvertedNativeCharactersPtr.Length()+aNativeCharacters.Length();
       
  1155 		iUnconvertedNativeCharactersPtr.Set(CheckAllocBufferL(&iUnconvertedNativeCharacters,newInputLength,iUnconvertedNativeCharactersPtr.Length()));
       
  1156 		iUnconvertedNativeCharactersPtr.Append(aNativeCharacters);
       
  1157 
       
  1158 		// Ensure buffer is at least the length of the input buffer
       
  1159 		TPtr8 outputPtr=CheckAllocBufferL(&iConvertedUDElements,iUnconvertedNativeCharactersPtr.Length(),0);
       
  1160 
       
  1161 		TInt retryCount=0;
       
  1162 		TInt unconvertedCount=iUnconvertedNativeCharactersPtr.Length();
       
  1163 		while (unconvertedCount)
       
  1164 			{
       
  1165 			TInt  tempNumberOfUnconvertibleCharacters = 0;
       
  1166 			TInt  tempNumberOfDowngradedCharacters    = 0;
       
  1167 			
       
  1168 			// Get a pointer to unfilled area of output buffer
       
  1169 			TPtr8 fillPtr((TUint8*)outputPtr.Ptr()+outputPtr.Length(),0,outputPtr.MaxLength()-outputPtr.Length());
       
  1170 			// Try the conversion & get number of unconverted characters
       
  1171 			TInt newUnconvertedCount=iCharacterSetConverter.ConvertFromUnicode(fillPtr,iUnconvertedNativeCharactersPtr);
       
  1172 			if (newUnconvertedCount<0)
       
  1173 				break;
       
  1174 
       
  1175 			// Compare what is converted with the original, to get downgrade count
       
  1176 			TPtr  tempBufPtr((TUint16*)iUnconvertedNativeCharactersPtr.Ptr(), 0, fillPtr.Length());
       
  1177 			TInt  offset      = aNativeCharacters.Length() - unconvertedCount;
       
  1178 			TInt  state       = CCnvCharacterSetConverter::KStateDefault;
       
  1179 			TInt  notRestored = iCharacterSetConverter.ConvertToUnicode(tempBufPtr, fillPtr, state);
       
  1180 			
       
  1181 			if (notRestored > 0)
       
  1182 				{
       
  1183 				tempNumberOfUnconvertibleCharacters += notRestored;
       
  1184 				}
       
  1185 			
       
  1186 			for (TInt pos = 0;  pos < tempBufPtr.Length();  pos++)
       
  1187 				{
       
  1188 				if (tempBufPtr[pos] != aNativeCharacters[offset + pos])
       
  1189 					{
       
  1190 					if (tempBufPtr[pos] != KReplacementCharacter)
       
  1191 						{
       
  1192 						tempNumberOfDowngradedCharacters++;
       
  1193 						}
       
  1194 					else
       
  1195 						{
       
  1196 						tempNumberOfUnconvertibleCharacters++;
       
  1197 						}
       
  1198 					}
       
  1199 				}
       
  1200 
       
  1201 			//
       
  1202 			// If characters were downgraded or unconverted then replace them
       
  1203 			// with downgrades from the PREQ2090 converter.
       
  1204 			//
       
  1205 			if (tempNumberOfUnconvertibleCharacters > 0  &&
       
  1206 				aEncoding != ESmsEncodingNone)
       
  1207 				{
       
  1208 				HBufC8*  downgradesBuf = HBufC8::NewLC(iUnconvertedNativeCharactersPtr.Length());
       
  1209 				HBufC*  nativeBuf = HBufC::NewLC(iUnconvertedNativeCharactersPtr.Length());
       
  1210 				TPtr8  downgradesPtr = downgradesBuf->Des();
       
  1211 				TPtr  nativePtr = nativeBuf->Des();
       
  1212 
       
  1213 				PrepareForConversionFromNativeL(ESmsEncodingNone);
       
  1214 
       
  1215 				// Attempt to convert the text
       
  1216 	 			TInt ret = iCharacterSetConverter.ConvertFromUnicode(downgradesPtr, iUnconvertedNativeCharactersPtr);
       
  1217 		 		if (ret >= 0)
       
  1218 		 			{
       
  1219 					// Compare what is converted with the original...
       
  1220 					state       = CCnvCharacterSetConverter::KStateDefault;
       
  1221 					notRestored = iCharacterSetConverter.ConvertToUnicode(nativePtr, downgradesPtr, state);
       
  1222 						
       
  1223 					if (notRestored >= 0)
       
  1224 						{
       
  1225 						// Merge in the downgrades
       
  1226 						TInt  pos;
       
  1227 						
       
  1228 						for (pos = 0;  pos < tempBufPtr.Length();  pos++)
       
  1229 							{
       
  1230 							if (tempBufPtr[pos] != aNativeCharacters[offset + pos])
       
  1231 								{
       
  1232 								if (tempBufPtr[pos] != KReplacementCharacter)
       
  1233 									{
       
  1234 									tempBufPtr[pos] = nativePtr[pos];
       
  1235 									}
       
  1236 								}
       
  1237 							}
       
  1238 
       
  1239 						// Reconvert...
       
  1240 						PrepareForConversionFromNativeL(aEncoding);
       
  1241 
       
  1242 						newUnconvertedCount=iCharacterSetConverter.ConvertFromUnicode(fillPtr,iUnconvertedNativeCharactersPtr);
       
  1243 						if (newUnconvertedCount<0)
       
  1244 							break;
       
  1245 
       
  1246 						// Recount the changed characters...
       
  1247 						tempNumberOfUnconvertibleCharacters = 0;
       
  1248 						tempNumberOfDowngradedCharacters    = 0;
       
  1249 
       
  1250 						for (pos = 0;  pos < tempBufPtr.Length();  pos++)
       
  1251 							{
       
  1252 							if (tempBufPtr[pos] != aNativeCharacters[offset + pos])
       
  1253 								{
       
  1254 								if (tempBufPtr[pos] != KReplacementCharacter)
       
  1255 									{
       
  1256 									tempNumberOfDowngradedCharacters++;
       
  1257 									}
       
  1258 								else
       
  1259 									{
       
  1260 									tempNumberOfUnconvertibleCharacters++;
       
  1261 									}
       
  1262 								}
       
  1263 							}
       
  1264 		 				}
       
  1265 					}
       
  1266 				
       
  1267 				CleanupStack::PopAndDestroy(2, downgradesBuf);
       
  1268 				}
       
  1269 
       
  1270 			//
       
  1271 			// Store these downgraded/unconvertible character counts...
       
  1272 			//
       
  1273 			aNumberOfDowngradedCharacters    += tempNumberOfDowngradedCharacters;
       
  1274 			aNumberOfUnconvertibleCharacters += tempNumberOfUnconvertibleCharacters;
       
  1275 			
       
  1276 			// Update original buffer length, check retry count and realloc if req'd
       
  1277 			outputPtr.SetLength(outputPtr.Length()+fillPtr.Length());
       
  1278 			if (newUnconvertedCount==unconvertedCount)
       
  1279 				{
       
  1280 				if (++retryCount>KMaxSmsAlphabetConversionRetries)
       
  1281 					{
       
  1282 					__ASSERT_DEBUG(EFalse,Panic(KGsmuPanicConversionRetriedOut));
       
  1283 					break;
       
  1284 					}
       
  1285 				}
       
  1286 			else
       
  1287 				{
       
  1288 				iUnconvertedNativeCharactersPtr.Delete(0,unconvertedCount-newUnconvertedCount);
       
  1289 				retryCount=0;
       
  1290 				}
       
  1291 			unconvertedCount=newUnconvertedCount;
       
  1292 			// Check for realloc
       
  1293 			if (unconvertedCount)
       
  1294 				outputPtr.Set(CheckAllocBufferL(&iConvertedUDElements,iConvertedUDElements->Length()+Max(unconvertedCount,KMinSmsAlphabetConversionAllocIncrement),outputPtr.Length()));
       
  1295 			}
       
  1296 
       
  1297 		return outputPtr;
       
  1298 		}
       
  1299 	} // CSmsAlphabetConverter::ConvertFromNativeL
       
  1300 
       
  1301 
       
  1302 /**
       
  1303  *  Converts the user data elements of the specified character set to the native
       
  1304  *  character set.
       
  1305  *  
       
  1306  *  @param aUDElements The converted character set data
       
  1307  * 
       
  1308  *  @return Native character set data (Unicode only)
       
  1309  * 
       
  1310  *  @capability None
       
  1311  */
       
  1312 EXPORT_C TPtrC CSmsAlphabetConverter::ConvertToNativeL(const TDesC8& aUDElements)
       
  1313 	{
       
  1314 	LOGGSMU1("CSmsAlphabetConverter::ConvertToNativeL()");
       
  1315 
       
  1316 	return ConvertToNativeL(aUDElements, ESmsEncodingNone);
       
  1317 	} // CSmsAlphabetConverter::ConvertToNativeL
       
  1318 
       
  1319 
       
  1320 /**
       
  1321  *  Converts the user data elements of the specified character set to the native
       
  1322  *  character set.
       
  1323  *  
       
  1324  *  @param aUDElements The converted character set data
       
  1325  *  @param aEncoding   Alternative 7bit encoding to used (if needed)
       
  1326  * 
       
  1327  *  @return Native character set data (Unicode only)
       
  1328  * 
       
  1329  *  @capability None
       
  1330  */
       
  1331 EXPORT_C TPtrC CSmsAlphabetConverter::ConvertToNativeL(const TDesC8& aUDElements,
       
  1332 													   TSmsEncoding aEncoding)
       
  1333 	{
       
  1334 	LOGGSMU2("CSmsAlphabetConverter::ConvertToNativeL(): aEncoding=%d", aEncoding);
       
  1335 
       
  1336 	// Check for some shortcuts
       
  1337 	if (iIsBinary ||  iSmsAlphabet == TSmsDataCodingScheme::ESmsAlphabet8Bit)
       
  1338 		{
       
  1339 		// Binary data stored as padded unicode
       
  1340 		TPtr16 outputPtr=CheckAllocBufferL(&iConvertedNativeCharacters,aUDElements.Length(),0);
       
  1341 		outputPtr.Copy(aUDElements);
       
  1342 		iUnconvertedUDElementsPtr.Zero();
       
  1343 		return outputPtr;
       
  1344 		}
       
  1345 	else if (iSmsAlphabet==TSmsDataCodingScheme::ESmsAlphabetUCS2)
       
  1346 		{
       
  1347 		// 16-bit copy with possible endianess correction
       
  1348 		TInt charCount=aUDElements.Length()/2;
       
  1349 		TPtr16 outputPtr=CheckAllocBufferL(&iConvertedNativeCharacters,charCount,charCount);
       
  1350 	    for (TInt i=0; i<charCount; i++)
       
  1351 		    {
       
  1352 		    outputPtr[i]=(TText)(aUDElements[2*i]<<8);
       
  1353 		    outputPtr[i]=(TText)(outputPtr[i]+(aUDElements[2*i+1]));
       
  1354 		    }
       
  1355 		iUnconvertedUDElementsPtr.Zero();
       
  1356 		return outputPtr;
       
  1357 		}
       
  1358 	else
       
  1359 		{
       
  1360 		PrepareForConversionToNativeL(aEncoding);
       
  1361 
       
  1362 		// Create input buffer with unconverted characters prepended
       
  1363 		TInt newInputLength=iUnconvertedUDElementsPtr.Length()+aUDElements.Length();
       
  1364 		iUnconvertedUDElementsPtr.Set(CheckAllocBufferL(&iUnconvertedUDElements,newInputLength,iUnconvertedUDElementsPtr.Length()));
       
  1365 		iUnconvertedUDElementsPtr.Append(aUDElements);
       
  1366 
       
  1367 		// Ensure buffer is at least the length of the input buffer
       
  1368 		TPtr outputPtr=CheckAllocBufferL(&iConvertedNativeCharacters,iUnconvertedUDElementsPtr.Length(),0);
       
  1369 
       
  1370 		TInt retryCount=0;
       
  1371 		TInt unconvertedCount=iUnconvertedUDElementsPtr.Length();
       
  1372 		TInt state=CCnvCharacterSetConverter::KStateDefault;
       
  1373 		while (unconvertedCount)
       
  1374 			{
       
  1375 			// Get a pointer to unfilled area of output buffer
       
  1376 			TPtr16 fillPtr((TUint16*)outputPtr.Ptr()+outputPtr.Length(),0,outputPtr.MaxLength()-outputPtr.Length());
       
  1377 			// Try the conversion & get number of unconverted characters
       
  1378 			TInt newUnconvertedCount=iCharacterSetConverter.ConvertToUnicode(fillPtr,iUnconvertedUDElementsPtr,state);
       
  1379 			if (newUnconvertedCount<0)
       
  1380 				break;
       
  1381 			// Update original buffer length & check retry count
       
  1382 			outputPtr.SetLength(outputPtr.Length()+fillPtr.Length());
       
  1383 			if (newUnconvertedCount==unconvertedCount)
       
  1384 				{
       
  1385 				if (++retryCount>KMaxSmsAlphabetConversionRetries)
       
  1386 					{
       
  1387 					__ASSERT_DEBUG(EFalse,Panic(KGsmuPanicConversionRetriedOut));
       
  1388 					break;
       
  1389 					}
       
  1390 				}
       
  1391 			else
       
  1392 				{
       
  1393 				iUnconvertedUDElementsPtr.Delete(0,unconvertedCount-newUnconvertedCount);
       
  1394 				retryCount=0;
       
  1395 				}
       
  1396 			unconvertedCount=newUnconvertedCount;
       
  1397 			// Check for realloc
       
  1398 			if (unconvertedCount)
       
  1399 				outputPtr.Set(CheckAllocBufferL(&iConvertedNativeCharacters,iConvertedNativeCharacters->Length()+Max(unconvertedCount,KMinSmsAlphabetConversionAllocIncrement),outputPtr.Length()));
       
  1400 			}
       
  1401 		return outputPtr;
       
  1402 		}
       
  1403 	} // CSmsAlphabetConverter::ConvertToNativeL
       
  1404 
       
  1405 
       
  1406 /**
       
  1407  *  Tests if the character is supported by the current character set.
       
  1408  *  This function can be used with 7bit and 8bit alphabets.
       
  1409  * 
       
  1410  *  @param aChar  Character to investigate.
       
  1411  * 
       
  1412  *  @return  ETrue if the character is supported.
       
  1413  * 
       
  1414  *  @note Since the function is based on the old behaviour (pre-PREQ2090)
       
  1415  *        it does not accept a downgraded character or alternative encoding
       
  1416  *        as being supported.
       
  1417  */
       
  1418 TBool CSmsAlphabetConverter::IsSupportedL(TChar aChar)
       
  1419 	{
       
  1420 	LOGGSMU2("[1] CSmsAlphabetConverter::IsSupportedL(aChar=0x%04x)", (TUint) aChar);
       
  1421 
       
  1422 	TBool isDowngrade, isRequiresAlternativeEncoding;
       
  1423 
       
  1424     TBool  supported = IsSupportedL(aChar, ESmsEncodingNone,
       
  1425             isDowngrade, isRequiresAlternativeEncoding);
       
  1426 	
       
  1427 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): supported=%d.", supported);
       
  1428 
       
  1429 	return supported;
       
  1430 	} // CSmsAlphabetConverter::IsSupportedL
       
  1431 
       
  1432 
       
  1433 /**
       
  1434  *  Tests if the descriptor text is supported by the current character set.
       
  1435  *  This function can be used with 7bit and 8bit alphabets.
       
  1436  * 
       
  1437  *  @param aDes                                 Text string to check.
       
  1438  *  @param aNumberOfUnconvertibleCharacters     Exit param for the number of
       
  1439  *                                              characters unconvertible.
       
  1440  *  @param aIndexOfFirstUnconvertibleCharacter  Exit param for the first
       
  1441  *                                              unconverted character.
       
  1442  * 
       
  1443  *  @return  ETrue if the character is supported.
       
  1444  */
       
  1445 TBool CSmsAlphabetConverter::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
       
  1446                                           TInt& aIndexOfFirstUnconvertibleCharacter)
       
  1447 	{
       
  1448 	LOGGSMU2("[2] CSmsAlphabetConverter::IsSupportedL(aDes=\"%S\")", &aDes);
       
  1449 
       
  1450 	TInt desLength = aDes.Length();
       
  1451 	//
       
  1452 	// Initialise the exit params...
       
  1453 	//
       
  1454 	aNumberOfUnconvertibleCharacters    = 0;
       
  1455 	aIndexOfFirstUnconvertibleCharacter = desLength;
       
  1456 
       
  1457     //
       
  1458     // Create buffers for the input converted to 7Bit and a buffer for it once
       
  1459     // converted back again...
       
  1460     //
       
  1461     HBufC8* encodedBuf       = HBufC8::NewLC(desLength*2); // worse case
       
  1462     HBufC*  backToUnicodeAfterStdBuf = HBufC::NewLC(desLength);
       
  1463     TPtr8  encoded(encodedBuf->Des());
       
  1464     TPtr  backToUnicodeAfterStd(backToUnicodeAfterStdBuf->Des());
       
  1465 
       
  1466     //
       
  1467     // Convert the input string to standard 7bit (with downgrades if needed)...
       
  1468     // 
       
  1469     PrepareForConversionFromNativeL(ESmsEncodingNone);
       
  1470 
       
  1471     TInt  notConverted = iCharacterSetConverter.ConvertFromUnicode(encoded, aDes);
       
  1472 
       
  1473     if (notConverted > 0)
       
  1474         {
       
  1475         aNumberOfUnconvertibleCharacters += notConverted;
       
  1476         }
       
  1477     else if (notConverted < 0)
       
  1478         {
       
  1479         aNumberOfUnconvertibleCharacters = desLength;
       
  1480         }
       
  1481     
       
  1482     //
       
  1483     // Convert it back again to the native format...
       
  1484     //
       
  1485     TInt  state       = CCnvCharacterSetConverter::KStateDefault;
       
  1486     TInt  notRestored = iCharacterSetConverter.ConvertToUnicode(backToUnicodeAfterStd, encoded, state);
       
  1487 
       
  1488     if (notRestored > 0)
       
  1489         {
       
  1490         aNumberOfUnconvertibleCharacters += notRestored;
       
  1491         }
       
  1492     else if (notRestored < 0)
       
  1493         {
       
  1494         aNumberOfUnconvertibleCharacters = desLength;
       
  1495         }
       
  1496 
       
  1497     //
       
  1498     // Work out if the string is acceptable as it is (e.g. no unconvertible
       
  1499     // and no downgrades). We only need do this if the previous conversions were
       
  1500     // complete with no issues.
       
  1501     //
       
  1502     for (TInt pos = desLength-1;  pos >= 0;  --pos)
       
  1503         {
       
  1504         if (backToUnicodeAfterStd[pos] != aDes[pos])
       
  1505             {
       
  1506             aNumberOfUnconvertibleCharacters++;
       
  1507             aIndexOfFirstUnconvertibleCharacter = pos;
       
  1508             }
       
  1509         }
       
  1510     
       
  1511     CleanupStack::PopAndDestroy(backToUnicodeAfterStdBuf);
       
  1512     CleanupStack::PopAndDestroy(encodedBuf);
       
  1513 	
       
  1514 	//
       
  1515 	// Useful logging...
       
  1516 	//
       
  1517 	TBool  supported = (aNumberOfUnconvertibleCharacters == 0);
       
  1518 
       
  1519 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aNumberOfUnconvertibleCharacters=%d.", aNumberOfUnconvertibleCharacters);
       
  1520 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aIndexOfFirstUnconvertibleCharacter=%d.", aIndexOfFirstUnconvertibleCharacter);
       
  1521 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): supported=%d.", supported);
       
  1522 
       
  1523 	return supported;
       
  1524 	} // CSmsAlphabetConverter::IsSupportedL
       
  1525 
       
  1526 
       
  1527 /**
       
  1528  *  Tests if the character is supported by the current character set.
       
  1529  *  This function can be used with 7bit and 8bit alphabets.
       
  1530  * 
       
  1531  *  @param aChar                         Character to investigate.
       
  1532  *  @param aEncoding                     Alternative 7bit encoding (if used).
       
  1533  *  @param aIsDowngrade                  Exit param set to ETrue if the
       
  1534  *                                       character has to be downgraded.
       
  1535  *  @param aRequiresAlternativeEncoding  Exit param set to ETrue if the
       
  1536  *                                       alternative encoding has to be
       
  1537  *                                       used to encode it.
       
  1538  * 
       
  1539  *  @return  ETrue if the character is supported.
       
  1540  */
       
  1541 TBool CSmsAlphabetConverter::IsSupportedL(TChar aChar, TSmsEncoding aEncoding,
       
  1542 		                                  TBool& aIsDowngrade,
       
  1543                                           TBool& aRequiresAlternativeEncoding)
       
  1544 	{
       
  1545 	LOGGSMU2("[3] CSmsAlphabetConverter::IsSupportedL(aChar=0x%04x)", (TUint) aChar);
       
  1546 
       
  1547 	//
       
  1548 	// Convert the character...
       
  1549 	//
       
  1550 	TInt  numberOfUnconvertibleCharacters, numberOfDowngradedCharacters, 
       
  1551             numberRequiringAlternativeEncoding, indexOfFirstUnconvertibleCharacter;
       
  1552 	TBuf<4>   toEncode;
       
  1553 
       
  1554 	toEncode.SetLength(1);
       
  1555 	toEncode[0]=(TText)aChar;
       
  1556 
       
  1557 	TBool supported = IsSupportedL(toEncode, aEncoding, 
       
  1558 	        numberOfUnconvertibleCharacters,
       
  1559 	        numberOfDowngradedCharacters,
       
  1560 	        numberRequiringAlternativeEncoding,
       
  1561 	        indexOfFirstUnconvertibleCharacter);
       
  1562 
       
  1563 	//
       
  1564 	// Calculate the exit params...
       
  1565 	//
       
  1566 	aIsDowngrade                 = (numberOfDowngradedCharacters > 0);
       
  1567 	aRequiresAlternativeEncoding = (numberRequiringAlternativeEncoding > 0);
       
  1568 	    
       
  1569 	//
       
  1570 	// Useful logging...
       
  1571 	//
       
  1572 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aIsDowngrade=%d.", aIsDowngrade);
       
  1573 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aRequiresAlternativeEncoding=%d.", aRequiresAlternativeEncoding);
       
  1574 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): supported=%d.", supported);
       
  1575 
       
  1576 	return supported;
       
  1577 	} // CSmsAlphabetConverter::IsSupportedL
       
  1578 
       
  1579 
       
  1580 /**
       
  1581  *  Tests if the descriptor text is supported by the current character set.
       
  1582  *  This function can be used with 7bit and 8bit alphabets.
       
  1583  * 
       
  1584  *  @param aDes                                 Text string to check.
       
  1585  *  @param aEncoding                            Alternative 7bit encoding (if used).
       
  1586  *  @param aNumberOfUnconvertibleCharacters     Exit param for the number of
       
  1587  *                                              characters unconvertible.
       
  1588  *  @param aNumberOfDowngradedCharacters        Exit param for the number of
       
  1589  *                                              downgraded characters.
       
  1590  *  @param aNumberRequiringAlternativeEncoding  Exit param for the number of
       
  1591  *                                              characters requiring use of
       
  1592  *                                              the alternative encoder.
       
  1593  *  @param aIndexOfFirstUnconvertibleCharacter  Exit param for the first
       
  1594  *                                              unconverted character.
       
  1595  * 
       
  1596  *  @return  ETrue if the character is supported.
       
  1597  */
       
  1598 TBool CSmsAlphabetConverter::IsSupportedL(const TDesC& aDes, TSmsEncoding aEncoding,
       
  1599 										  TInt& aNumberOfUnconvertibleCharacters,
       
  1600                                           TInt& aNumberOfDowngradedCharacters,
       
  1601                                           TInt& aNumberRequiringAlternativeEncoding,
       
  1602                                           TInt& aIndexOfFirstUnconvertibleCharacter)
       
  1603 	{
       
  1604 	LOGGSMU2("[4] CSmsAlphabetConverter::IsSupportedL(aDes=\"%S\")", &aDes);
       
  1605 
       
  1606 	TInt desLength = aDes.Length();
       
  1607 	//
       
  1608 	// Initialise the exit params...
       
  1609 	//
       
  1610 	aNumberOfUnconvertibleCharacters    = 0;
       
  1611 	aNumberOfDowngradedCharacters       = 0;
       
  1612 	aNumberRequiringAlternativeEncoding = 0;
       
  1613 	aIndexOfFirstUnconvertibleCharacter = desLength;
       
  1614 	
       
  1615 	//
       
  1616 	// Create buffers for the input converted to 7Bit and a buffer for it once
       
  1617 	// converted back again...
       
  1618 	//
       
  1619     HBufC8* encodedBuf       = HBufC8::NewLC(desLength*2); // worse case
       
  1620     HBufC*  backToUnicodeAfterStdBuf = HBufC::NewLC(desLength);
       
  1621     TPtr8  encoded(encodedBuf->Des());
       
  1622     TPtr  backToUnicodeAfterStd(backToUnicodeAfterStdBuf->Des());
       
  1623 
       
  1624     //
       
  1625     // Convert the input string to standard 7bit (with downgrades if needed)...
       
  1626     // 
       
  1627     PrepareForConversionFromNativeL(ESmsEncodingNone);
       
  1628 
       
  1629     TInt  notConverted = iCharacterSetConverter.ConvertFromUnicode(encoded, aDes);
       
  1630 
       
  1631     if (notConverted > 0)
       
  1632         {
       
  1633         aNumberOfUnconvertibleCharacters += notConverted;
       
  1634         }
       
  1635     else if (notConverted < 0)
       
  1636         {
       
  1637         aNumberOfUnconvertibleCharacters = desLength;
       
  1638         }
       
  1639     
       
  1640     //
       
  1641     // Convert it back again to the native format...
       
  1642     //
       
  1643     TInt  state       = CCnvCharacterSetConverter::KStateDefault;
       
  1644     TInt  notRestored = iCharacterSetConverter.ConvertToUnicode(backToUnicodeAfterStd, encoded, state);
       
  1645 
       
  1646     if (notRestored > 0)
       
  1647         {
       
  1648         aNumberOfUnconvertibleCharacters += notRestored;
       
  1649         }
       
  1650     else if (notRestored < 0)
       
  1651         {
       
  1652         aNumberOfUnconvertibleCharacters = desLength;
       
  1653         }
       
  1654 
       
  1655     //
       
  1656     // Work out if the string is acceptable as it is (e.g. no unconvertible
       
  1657     // and no downgrades).
       
  1658     //
       
  1659     for (TInt pos = desLength-1;  pos >= 0;  --pos)
       
  1660         {
       
  1661         if (backToUnicodeAfterStd[pos] != aDes[pos])
       
  1662             {
       
  1663             if (backToUnicodeAfterStd[pos] != KReplacementCharacter)
       
  1664                 {
       
  1665                 aNumberOfDowngradedCharacters++;
       
  1666                 }
       
  1667             else
       
  1668                 {
       
  1669                 aNumberOfUnconvertibleCharacters++;
       
  1670                 aIndexOfFirstUnconvertibleCharacter = pos;
       
  1671                 }
       
  1672             }
       
  1673         }
       
  1674 
       
  1675     TInt  totalCharFaultsSoFar = aNumberOfUnconvertibleCharacters + 
       
  1676                                     aNumberOfDowngradedCharacters;
       
  1677     
       
  1678     //
       
  1679     // If the total unconvertible plus downgrades is zero, then there is nothing
       
  1680     // more to do as the string can be converted to 7bit with no issues and no
       
  1681     // other encoder is needed.
       
  1682     //
       
  1683     // Otherwise we have to look at the alternative encoder...
       
  1684     //
       
  1685     if (totalCharFaultsSoFar == 0)
       
  1686         {
       
  1687         //
       
  1688         // We are done (the return counts are already zero and therefore
       
  1689         // correct at this point too!).
       
  1690         //
       
  1691         }
       
  1692     else if (iSmsAlphabet != TSmsDataCodingScheme::ESmsAlphabet7Bit  ||
       
  1693              aEncoding == ESmsEncodingNone)
       
  1694         {
       
  1695         //
       
  1696         // The string was not perfectly converted, but there is no alternative
       
  1697         // encoder to try.  We are done.
       
  1698         //
       
  1699         }
       
  1700     else
       
  1701         {
       
  1702         //
       
  1703         // Initialise the params...
       
  1704         //
       
  1705         TInt  tmpDowngradedCharacters        = 0;
       
  1706         TInt  tmpUnconvertibleCharacters     = 0;
       
  1707         TInt  tmpIndexOfFirstUnconvertibleCharacter = desLength;
       
  1708 		
       
  1709         //
       
  1710         // Convert the input string to the alternative encoding...
       
  1711         //
       
  1712         PrepareForConversionFromNativeL(aEncoding);
       
  1713 
       
  1714         notConverted = iCharacterSetConverter.ConvertFromUnicode(encoded, aDes);
       
  1715         if (notConverted > 0)
       
  1716             {
       
  1717             tmpUnconvertibleCharacters = notConverted;
       
  1718             }
       
  1719         else if (notConverted < 0)
       
  1720             {
       
  1721             tmpUnconvertibleCharacters = desLength;
       
  1722             }
       
  1723 
       
  1724         //
       
  1725         // Convert it back again to the native format...
       
  1726         //
       
  1727         HBufC*  backToUnicodeAfterAltBuf = HBufC::NewLC(desLength);
       
  1728         TPtr  backToUnicodeAfterAlt(backToUnicodeAfterAltBuf->Des());
       
  1729         TInt  state       = CCnvCharacterSetConverter::KStateDefault;
       
  1730         TInt  notRestored = iCharacterSetConverter.ConvertToUnicode(backToUnicodeAfterAlt, encoded, state);
       
  1731 
       
  1732         if (notRestored > 0)
       
  1733             {
       
  1734             tmpUnconvertibleCharacters += notRestored;
       
  1735             }
       
  1736         else if (notRestored < 0)
       
  1737             {
       
  1738             tmpUnconvertibleCharacters = desLength;
       
  1739             }
       
  1740 
       
  1741         //
       
  1742         // Now work out which characters are downgrades, require alternative encoding
       
  1743         // or are unsupported.
       
  1744         //
       
  1745         for (TInt pos = desLength-1;  pos >= 0;  --pos)
       
  1746             {
       
  1747             if (backToUnicodeAfterStd[pos] != aDes[pos])
       
  1748                 {
       
  1749                 // Not supported by standard encoder...
       
  1750                 if (backToUnicodeAfterAlt[pos] == aDes[pos])
       
  1751                     {
       
  1752                     // Supported by alternative encoder...
       
  1753                     aNumberRequiringAlternativeEncoding++;
       
  1754                     }
       
  1755                 else if (backToUnicodeAfterStd[pos] != KReplacementCharacter)
       
  1756                     {
       
  1757                     // Downgraded by standard encoder...
       
  1758                     tmpDowngradedCharacters++;
       
  1759                     }
       
  1760                 else if (backToUnicodeAfterAlt[pos] != KReplacementCharacter)
       
  1761                     {
       
  1762                     // Downgraded by alternative encoder...
       
  1763                     tmpDowngradedCharacters++;
       
  1764                     aNumberRequiringAlternativeEncoding++;
       
  1765                     }
       
  1766                 else
       
  1767                     {
       
  1768                     // Unconvertible...
       
  1769                     tmpUnconvertibleCharacters++;
       
  1770                     tmpIndexOfFirstUnconvertibleCharacter = pos;
       
  1771                     }
       
  1772                 }
       
  1773             }
       
  1774 
       
  1775         // Is this better?  
       
  1776         if ( totalCharFaultsSoFar >= (tmpUnconvertibleCharacters + tmpDowngradedCharacters) )
       
  1777             {
       
  1778             // Best conversion is the alternative conversion
       
  1779             aNumberOfUnconvertibleCharacters     = tmpUnconvertibleCharacters;
       
  1780             aNumberOfDowngradedCharacters        = tmpDowngradedCharacters;
       
  1781             aIndexOfFirstUnconvertibleCharacter  = tmpIndexOfFirstUnconvertibleCharacter;
       
  1782             }
       
  1783         else
       
  1784             {
       
  1785             // Best conversion is the standard conversion
       
  1786             aNumberRequiringAlternativeEncoding = 0;
       
  1787             }
       
  1788         
       
  1789         CleanupStack::PopAndDestroy(backToUnicodeAfterAltBuf);
       
  1790         }
       
  1791     
       
  1792     CleanupStack::PopAndDestroy(backToUnicodeAfterStdBuf);
       
  1793     CleanupStack::PopAndDestroy(encodedBuf);
       
  1794 
       
  1795 	//
       
  1796 	// Useful logging...
       
  1797 	//
       
  1798 	TBool  supported = (aNumberOfUnconvertibleCharacters == 0);
       
  1799 
       
  1800 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aNumberOfUnconvertibleCharacters=%d.", aNumberOfUnconvertibleCharacters);
       
  1801 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aNumberOfDowngradedCharacters=%d.", aNumberOfDowngradedCharacters);
       
  1802 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aNumberRequiringAlternativeEncoding=%d.", aNumberRequiringAlternativeEncoding);
       
  1803 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): aIndexOfFirstUnconvertibleCharacter=%d.", aIndexOfFirstUnconvertibleCharacter);
       
  1804 	LOGGSMU2("CSmsAlphabetConverter::IsSupportedL(): supported=%d.", supported);
       
  1805 
       
  1806 	return supported;
       
  1807 	} // CSmsAlphabetConverter::IsSupportedL
       
  1808 
       
  1809 
       
  1810 /**
       
  1811  *  Given a piece of text and an alternative encoding, this function works out
       
  1812  *  which encoding is best to use and returns the ID of that converter.
       
  1813  * 
       
  1814  *  @param aNativeCharacters      Text to use as a sample.
       
  1815  *  @param aEncoding              Suggested alternative 7bit encoding method.
       
  1816  * 
       
  1817  *  @return Encoding that should be used.
       
  1818  */
       
  1819 TSmsEncoding CSmsAlphabetConverter::FindBestAlternativeEncodingL(const TDesC& aNativeCharacters,
       
  1820 									                     		 TSmsEncoding aSuggestedEncoding)
       
  1821 	{
       
  1822 	LOGGSMU2("CSmsAlphabetConverter::FindBestAlternativeEncodingL(): aSuggestedEncoding=%d",
       
  1823 			 aSuggestedEncoding);
       
  1824 
       
  1825 	TSmsEncoding  encodingToUse = ESmsEncodingNone;
       
  1826 
       
  1827 	//
       
  1828 	// If this is not 7bit or the alternative encoding is not set then do
       
  1829 	// nothing...
       
  1830 	//
       
  1831 	if (aSuggestedEncoding != ESmsEncodingNone  &&
       
  1832 		iSmsAlphabet == TSmsDataCodingScheme::ESmsAlphabet7Bit)
       
  1833 		{
       
  1834 		TInt  numberOfUnconvertibleCharacters, numberOfDowngradedCharacters;
       
  1835 		TInt  numberRequiringAlternativeEncoding, indexOfFirstUnconvertibleCharacter;
       
  1836 		
       
  1837 		//
       
  1838 		// First try the default encoding (but in this case treat downgrades
       
  1839 		// as unconverted, since later encoders might do better)...
       
  1840 		//
       
  1841 		IsSupportedL(aNativeCharacters, ESmsEncodingNone,
       
  1842 					 numberOfUnconvertibleCharacters,
       
  1843                      numberOfDowngradedCharacters,
       
  1844                      numberRequiringAlternativeEncoding,
       
  1845                      indexOfFirstUnconvertibleCharacter);
       
  1846 
       
  1847 		TInt leastUnconvertibleCharacters = numberOfUnconvertibleCharacters + numberOfDowngradedCharacters;
       
  1848 
       
  1849 		//
       
  1850 		// Create a list of alternative encodings to try...
       
  1851 		//
       
  1852 		TSmsEncoding  encodingList[8];
       
  1853 		TInt          encodingCount = 0;
       
  1854 		
       
  1855 		if (aSuggestedEncoding == ESmsEncodingTurkishLockingAndSingleShift)
       
  1856 			{
       
  1857 			encodingList[encodingCount++] = ESmsEncodingTurkishSingleShift;
       
  1858 			encodingList[encodingCount++] = ESmsEncodingTurkishLockingShift;
       
  1859 			}
       
  1860 		else if (aSuggestedEncoding == ESmsEncodingPortugueseLockingAndSingleShift)
       
  1861 			{
       
  1862 			encodingList[encodingCount++] = ESmsEncodingPortugueseSingleShift;
       
  1863 			encodingList[encodingCount++] = ESmsEncodingPortugueseLockingShift;
       
  1864 			}
       
  1865 
       
  1866 		encodingList[encodingCount++] = aSuggestedEncoding;
       
  1867 		encodingList[encodingCount++] = ESmsEncodingNone;
       
  1868 
       
  1869 		//
       
  1870 		// Now try the all the alternatives...
       
  1871 		//
       
  1872 		for (TInt  encoder = 0;  encoder < encodingCount;  encoder++)
       
  1873 			{
       
  1874 			IsSupportedL(aNativeCharacters, encodingList[encoder],
       
  1875 						 numberOfUnconvertibleCharacters,
       
  1876 	                     numberOfDowngradedCharacters,
       
  1877 	                     numberRequiringAlternativeEncoding,
       
  1878 	                     indexOfFirstUnconvertibleCharacter);
       
  1879 			if (numberOfUnconvertibleCharacters + numberOfDowngradedCharacters < leastUnconvertibleCharacters)
       
  1880 				{
       
  1881 				encodingToUse = encodingList[encoder];
       
  1882 				leastUnconvertibleCharacters = numberOfUnconvertibleCharacters + numberOfDowngradedCharacters;
       
  1883 				}
       
  1884 			}
       
  1885 		}
       
  1886 
       
  1887 	LOGGSMU2("CSmsAlphabetConverter::FindBestAlternativeEncodingL(): encodingToUse=%d", encodingToUse);
       
  1888 
       
  1889 	return encodingToUse;
       
  1890 	} // CSmsAlphabetConverter::FindBestAlternativeEncoding
       
  1891 
       
  1892 
       
  1893 /**
       
  1894  *  Confirms that the requested encoding method is present (e.g. the converter
       
  1895  *  plug-in can be loaded).
       
  1896  * 
       
  1897  *  @param aEncoding  Alternative 7bit encoding method.
       
  1898  * 
       
  1899  *  @leave KErrNotSupported if the encoder is not available.
       
  1900  */
       
  1901 void CSmsAlphabetConverter::ConfirmAlternativeEncoderL(TSmsEncoding aEncoding) const
       
  1902 	{
       
  1903 	//
       
  1904 	// Check the ID for the encoder exists...
       
  1905 	//
       
  1906 	if (aEncoding != ESmsEncodingNone)
       
  1907 		{
       
  1908 		TUint  encoderID;
       
  1909 		
       
  1910 		GetAlternativeEncoderIDL(aEncoding, encoderID);
       
  1911 		
       
  1912 		//
       
  1913 		// Confirm it can be loaded...
       
  1914 		//
       
  1915 		if (iCharacterSetConverter.PrepareToConvertToOrFromL(encoderID, iFs) != CCnvCharacterSetConverter::EAvailable)
       
  1916 			{
       
  1917 			User::Leave(KErrNotSupported);
       
  1918 			}
       
  1919 		}
       
  1920 	} // CSmsAlphabetConverter::ConfirmAlternativeEncoderL
       
  1921 
       
  1922 
       
  1923 /**
       
  1924  *  Prepares the converted for conversion from native charset.
       
  1925  *  Character set specific preparation is performed here.
       
  1926  * 
       
  1927  *  @param aEncoding  Alternative 7bit encoding to use if required.
       
  1928  */
       
  1929 void CSmsAlphabetConverter::PrepareForConversionFromNativeL(TSmsEncoding aEncoding)
       
  1930 	{
       
  1931 	LOGGSMU2("CSmsAlphabetConverter::PrepareForConversionFromNativeL(): aEncoding=%d",
       
  1932 			 aEncoding);
       
  1933 
       
  1934 	__ASSERT_DEBUG(iIsBinary==EFalse,Panic(KGsmuPanicUnsupportedAlphabet));
       
  1935 	switch (iSmsAlphabet)
       
  1936 		{
       
  1937 		case TSmsDataCodingScheme::ESmsAlphabet7Bit:
       
  1938 			{
       
  1939 			//
       
  1940 			// If an alternative encoding has been specified then try and
       
  1941 			// load that converter...
       
  1942 			//
       
  1943 			if (aEncoding != ESmsEncodingNone)
       
  1944 				{
       
  1945 				TUint  alternativeEncoderID;
       
  1946 				
       
  1947 				GetAlternativeEncoderIDL(aEncoding, alternativeEncoderID);
       
  1948 				if (alternativeEncoderID != 0)
       
  1949 					{
       
  1950 					CCnvCharacterSetConverter::TAvailability  availability;
       
  1951 		
       
  1952 					LOGGSMU2("CSmsAlphabetConverter::PrepareForConversionFromNativeL(): Converter 0x%08x",
       
  1953 							 alternativeEncoderID);
       
  1954 					
       
  1955 					availability = iCharacterSetConverter.PrepareToConvertToOrFromL(alternativeEncoderID, iFs);
       
  1956 					if (availability == CCnvCharacterSetConverter::EAvailable)
       
  1957 						{
       
  1958 			 			// Force unicode line termination characters to simple line feed
       
  1959 			 			iCharacterSetConverter.SetDowngradeForExoticLineTerminatingCharacters(
       
  1960 				 				CCnvCharacterSetConverter::EDowngradeExoticLineTerminatingCharactersToJustLineFeed);
       
  1961 					
       
  1962 						// Job done, return
       
  1963 			 			return;
       
  1964 						}
       
  1965 					
       
  1966 					// Plug-in could not be loaded, so drop through and load the default!
       
  1967 					}
       
  1968 				}
       
  1969 			
       
  1970 			//
       
  1971 			// Check for the PREQ2090 7bit converter with Eastern European
       
  1972 			// downgrade support first, otherwise if the plug-in is not found
       
  1973 			// use the standard internal converter.
       
  1974 			//
       
  1975 			CCnvCharacterSetConverter::TAvailability  availability;
       
  1976 			
       
  1977 			availability = iCharacterSetConverter.PrepareToConvertToOrFromL(KCharacterSetIdentifierExtendedSms7Bit, iFs);
       
  1978 			if (availability == CCnvCharacterSetConverter::ENotAvailable)
       
  1979 				{
       
  1980 				availability = iCharacterSetConverter.PrepareToConvertToOrFromL(KCharacterSetIdentifierSms7Bit, iFs);
       
  1981 				if (availability == CCnvCharacterSetConverter::ENotAvailable)
       
  1982 					{
       
  1983 					User::Leave(KErrNotFound);
       
  1984 					}
       
  1985 				}
       
  1986 
       
  1987  			// Force unicode line termination characters to simple line feed
       
  1988  			iCharacterSetConverter.SetDowngradeForExoticLineTerminatingCharacters(
       
  1989  				CCnvCharacterSetConverter::EDowngradeExoticLineTerminatingCharactersToJustLineFeed);
       
  1990 			break;
       
  1991 			}
       
  1992 		case TSmsDataCodingScheme::ESmsAlphabet8Bit:
       
  1993 			{
       
  1994 			CCnvCharacterSetConverter::TAvailability availability=iCharacterSetConverter.PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252,iFs);
       
  1995 			if (availability==CCnvCharacterSetConverter::ENotAvailable)
       
  1996 				{
       
  1997 				User::Leave(KErrNotFound);
       
  1998 				}
       
  1999 
       
  2000  			// Force unicode line termination characters to simple line feed
       
  2001  			iCharacterSetConverter.SetDowngradeForExoticLineTerminatingCharacters(
       
  2002  				CCnvCharacterSetConverter::EDowngradeExoticLineTerminatingCharactersToJustLineFeed);
       
  2003 			break;
       
  2004 			}
       
  2005 		case TSmsDataCodingScheme::ESmsAlphabetUCS2:
       
  2006 		default:
       
  2007 			{
       
  2008             User::Leave(KErrNotSupported);
       
  2009 			}
       
  2010 		}
       
  2011 	} // CSmsAlphabetConverter::PrepareForConversionFromNativeL
       
  2012 
       
  2013 
       
  2014 /**
       
  2015  *  Prepares the converted for conversion to unicode.  Character set
       
  2016  *  specific preparation is performed here.
       
  2017  * 
       
  2018  *  @param aEncoding  Alternative 7bit encoding to use if required.
       
  2019  */
       
  2020 void CSmsAlphabetConverter::PrepareForConversionToNativeL(TSmsEncoding aEncoding)
       
  2021 	{
       
  2022 	LOGGSMU2("CSmsAlphabetConverter::PrepareForConversionToNativeL(): aEncoding=%d",
       
  2023 			 aEncoding);
       
  2024 
       
  2025 	switch (iSmsAlphabet)
       
  2026 		{
       
  2027 		case TSmsDataCodingScheme::ESmsAlphabet7Bit:
       
  2028 			{
       
  2029 			//
       
  2030 			// If an alternative encoding has been specified then try and
       
  2031 			// load that converter...
       
  2032 			//
       
  2033 			if (aEncoding != ESmsEncodingNone)
       
  2034 				{
       
  2035 				TUint  alternativeEncoderID;
       
  2036 				
       
  2037 				GetAlternativeEncoderIDL(aEncoding, alternativeEncoderID);
       
  2038 				if (alternativeEncoderID != 0)
       
  2039 					{
       
  2040 					CCnvCharacterSetConverter::TAvailability  availability;
       
  2041 		
       
  2042 					LOGGSMU2("CSmsAlphabetConverter::PrepareForConversionFromNativeL(): Converter 0x%08x",
       
  2043 							 alternativeEncoderID);
       
  2044 					
       
  2045 					availability = iCharacterSetConverter.PrepareToConvertToOrFromL(alternativeEncoderID, iFs);
       
  2046 					if (availability == CCnvCharacterSetConverter::EAvailable)
       
  2047 						{
       
  2048 						// Job done, return
       
  2049 			 			return;
       
  2050 						}
       
  2051 					
       
  2052 					// Plug-in could not be loaded, so drop through and load the default!
       
  2053 					}
       
  2054 				}
       
  2055 			
       
  2056 			//
       
  2057 			// Always use the internal converter, as it is quicker to prepare
       
  2058 			// and the PREQ2090 7bit converter with Eastern European downgrade
       
  2059 			// offers no benefit when converting to native.
       
  2060 			//
       
  2061 			CCnvCharacterSetConverter::TAvailability availability=iCharacterSetConverter.PrepareToConvertToOrFromL(KCharacterSetIdentifierSms7Bit,iFs);
       
  2062 			if (availability==CCnvCharacterSetConverter::ENotAvailable)
       
  2063 				{
       
  2064 				User::Leave(KErrNotFound);
       
  2065 				}
       
  2066 			break;
       
  2067 			}
       
  2068 		case TSmsDataCodingScheme::ESmsAlphabet8Bit:
       
  2069 			{
       
  2070 			CCnvCharacterSetConverter::TAvailability availability=iCharacterSetConverter.PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252,iFs);
       
  2071 			if (availability==CCnvCharacterSetConverter::ENotAvailable)
       
  2072 				{
       
  2073 				User::Leave(KErrNotFound);
       
  2074 				}
       
  2075 			break;
       
  2076 			}
       
  2077 		case TSmsDataCodingScheme::ESmsAlphabetUCS2:
       
  2078 		default:
       
  2079 			{
       
  2080 			User::Leave(KErrNotSupported);
       
  2081 			}
       
  2082 		}
       
  2083 	} // CSmsAlphabetConverter::PrepareForConversionToNativeL
       
  2084 
       
  2085 
       
  2086 /**
       
  2087  *  This function returns the alternative encoding converters that are used
       
  2088  *  incase the default GSM encoding cannot encode the message completely
       
  2089  *  without data loss.
       
  2090  * 
       
  2091  *  @param aEncoding   Encoding to obtain the converter for.
       
  2092  *  @param aEncoderID  Returned converter UID if present.
       
  2093  * 
       
  2094  *  @leave KErrArgument if the encoding enum is invalid or
       
  2095  */
       
  2096 void CSmsAlphabetConverter::GetAlternativeEncoderIDL(TSmsEncoding aEncoding, TUint& aEncoderID) const
       
  2097 	{
       
  2098 	LOGGSMU2("CSmsAlphabetConverter::GetAlternativeEncoderIDL(%d)", aEncoding);
       
  2099 
       
  2100 	aEncoderID = 0;
       
  2101 	
       
  2102 	//
       
  2103 	// Decide on appropriate encoders.
       
  2104 	//
       
  2105 	switch (aEncoding)
       
  2106 		{
       
  2107 		case ESmsEncodingNone:
       
  2108 			{
       
  2109 			// Nothing to set.
       
  2110 			}
       
  2111 			break;
       
  2112 		
       
  2113 		case ESmsEncodingTurkishSingleShift:
       
  2114 			{
       
  2115 			aEncoderID = KCharacterSetIdentifierTurkishSingleSms7Bit;
       
  2116 			}
       
  2117 			break;
       
  2118 		
       
  2119 		case ESmsEncodingTurkishLockingShift:
       
  2120 			{
       
  2121 			aEncoderID = KCharacterSetIdentifierTurkishLockingSms7Bit;
       
  2122 			}
       
  2123 			break;
       
  2124 		
       
  2125 		case ESmsEncodingTurkishLockingAndSingleShift:
       
  2126 			{
       
  2127 			aEncoderID = KCharacterSetIdentifierTurkishLockingAndSingleSms7Bit;
       
  2128 			}
       
  2129 			break;
       
  2130 		
       
  2131 		case ESmsEncodingSpanishSingleShift:
       
  2132 			{
       
  2133 			aEncoderID = KCharacterSetIdentifierSpanishSingleSms7Bit;
       
  2134 			}
       
  2135 			break;
       
  2136 		
       
  2137 		case ESmsEncodingPortugueseSingleShift:
       
  2138 			{
       
  2139 			aEncoderID = KCharacterSetIdentifierPortugueseSingleSms7Bit;
       
  2140 			}
       
  2141 			break;
       
  2142 		
       
  2143 		case ESmsEncodingPortugueseLockingShift:
       
  2144 			{
       
  2145 			aEncoderID = KCharacterSetIdentifierPortugueseLockingSms7Bit;
       
  2146 			}
       
  2147 			break;
       
  2148 		
       
  2149 		case ESmsEncodingPortugueseLockingAndSingleShift:
       
  2150 			{
       
  2151 			aEncoderID = KCharacterSetIdentifierPortugueseLockingAndSingleSms7Bit;
       
  2152 			}
       
  2153 			break;
       
  2154 
       
  2155 		default:
       
  2156 			{
       
  2157 			//
       
  2158 			// Invalid encoder method!
       
  2159 			//
       
  2160 			User::Leave(KErrArgument);
       
  2161 			}
       
  2162 		};
       
  2163 	} // CSmsAlphabetConverter::GetAlternativeEncoderIDL
       
  2164 
       
  2165 
       
  2166 //
       
  2167 // Ensures the allocated 16 bit buffer is at least of the specified length
       
  2168 //
       
  2169 TPtr16 CSmsAlphabetConverter::CheckAllocBufferL(HBufC16** aBuffer,TInt aMaxLength,TInt aUsedLength)
       
  2170 	{
       
  2171 	LOGGSMU1("CSmsAlphabetConverter::CheckAllocBufferL()");
       
  2172 
       
  2173 	if (*aBuffer!=NULL)
       
  2174 		{
       
  2175 		if ((*aBuffer)->Length()<aMaxLength)
       
  2176 			{
       
  2177 			*aBuffer=(*aBuffer)->ReAllocL(aMaxLength);
       
  2178 			(*aBuffer)->Des().SetLength(aMaxLength);
       
  2179 			}
       
  2180 		}
       
  2181 	else
       
  2182 		{
       
  2183 		*aBuffer=HBufC16::NewMaxL(aMaxLength);
       
  2184 		}
       
  2185 	return TPtr16((TUint16*)(*aBuffer)->Des().Ptr(),aUsedLength,(*aBuffer)->Length());
       
  2186 	} // CSmsAlphabetConverter::CheckAllocBufferL
       
  2187 
       
  2188 
       
  2189 //
       
  2190 // Ensures the allocated 8 bit buffer is at least of the specified length
       
  2191 //
       
  2192 TPtr8 CSmsAlphabetConverter::CheckAllocBufferL(HBufC8** aBuffer,TInt aMaxLength,TInt aUsedLength)
       
  2193 	{
       
  2194 	LOGGSMU1("CSmsAlphabetConverter::CheckAllocBufferL()");
       
  2195 
       
  2196 	if (*aBuffer!=NULL)
       
  2197 		{
       
  2198 		if ((*aBuffer)->Length()<aMaxLength)
       
  2199 			{
       
  2200 			*aBuffer=(*aBuffer)->ReAllocL(aMaxLength);
       
  2201 			(*aBuffer)->Des().SetLength(aMaxLength);
       
  2202 			}
       
  2203 		}
       
  2204 	else
       
  2205 		{
       
  2206 		*aBuffer=HBufC8::NewMaxL(aMaxLength);
       
  2207 		}
       
  2208 	return TPtr8((TUint8*)(*aBuffer)->Des().Ptr(),aUsedLength,(*aBuffer)->Length());
       
  2209 	} // CSmsAlphabetConverter::CheckAllocBufferL
       
  2210 
       
  2211 
       
  2212 /**
       
  2213  *  @internalComponent
       
  2214  *  
       
  2215  *  Determines whether the address format matches the specified type.
       
  2216  *  
       
  2217  *  @param aType Specifies an indicator type, as defined in the Common PCN Handset Specification
       
  2218  *  @return returns ETrue if address is of specified type, EFalse otherwise 
       
  2219  */
       
  2220 EXPORT_C TBool TGsmSmsTelNumber::IsInstanceOf(TTypeOfIndicator aType)
       
  2221     {
       
  2222     LOGGSMU1("TGsmSmsTelNumber::IsInstanceOf()");
       
  2223 
       
  2224     TBool rc = EFalse;
       
  2225 
       
  2226     (void) aType;
       
  2227 
       
  2228     if((aType == EVoiceMessageWaitingIndicator)
       
  2229      && ((iTypeOfAddress & TGsmSmsTypeOfAddress::EGsmSmsTONMask)==EGsmSmsTONAlphaNumeric)
       
  2230      && (iTelNumber.Length()==ECPHSSizeOfAddressField)
       
  2231      && ((iTelNumber[ECPHSAddressIndicatorType] & ECPSHIndicatorTypeBitMask) == ECPSHVoiceMailId)
       
  2232      && ((iTelNumber[ECPHSAddressIndicatorId] & ECPSHIndicatorIdBitMask) == ECPSHIndicatorId ))
       
  2233       rc = ETrue;
       
  2234 
       
  2235     return rc;
       
  2236     } // TGsmSmsTelNumber::IsInstanceOf
       
  2237 
       
  2238 
       
  2239 //
       
  2240 // CSmsAddress
       
  2241 //
       
  2242 
       
  2243 CSmsAddress* CSmsAddress::NewL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
       
  2244 	{
       
  2245 	LOGGSMU1("CSmsAddress::NewL()");
       
  2246 
       
  2247 	CSmsAddress* address=new(ELeave) CSmsAddress(aCharacterSetConverter,aFs);
       
  2248 	CleanupStack::PushL(address);
       
  2249 	TPtrC ptr;
       
  2250 	address->SetAddressL(ptr);
       
  2251 	CleanupStack::Pop();
       
  2252 	return address;
       
  2253 	} // CSmsAddress::NewL
       
  2254 
       
  2255 
       
  2256 CSmsAddress::~CSmsAddress()
       
  2257     {
       
  2258     delete iBuffer;
       
  2259     } // CSmsAddress::NewL
       
  2260 
       
  2261 
       
  2262 /**
       
  2263  *  Duplicates this CSmsAddress object.
       
  2264  * 
       
  2265  *  @return  Pointer to the newly created CSmsAddress object.
       
  2266  */
       
  2267 CSmsAddress* CSmsAddress::DuplicateL() const
       
  2268 	{
       
  2269 	LOGGSMU1("CSmsAddress::DuplicateL()");
       
  2270 
       
  2271 	CSmsAddress*  address = CSmsAddress::NewL(iCharacterSetConverter, iFs);
       
  2272 	CleanupStack::PushL(address);
       
  2273 
       
  2274 	address->SetRawAddressL(iTypeOfAddress, *iBuffer);
       
  2275 	
       
  2276 	CleanupStack::Pop();
       
  2277 
       
  2278 	return address;
       
  2279 	} // CSmsAddress::DuplicateL
       
  2280 
       
  2281 
       
  2282 TPtrC CSmsAddress::Address() const
       
  2283 	{
       
  2284 	LOGGSMU1("CSmsAddress::Address()");
       
  2285 
       
  2286 	TPtrC ptr;
       
  2287 	if (iBuffer)
       
  2288 		ptr.Set(iBuffer->Des());
       
  2289 	return ptr;
       
  2290 	} // CSmsAddress::Address
       
  2291 
       
  2292 
       
  2293 void CSmsAddress::SetRawAddressL(TGsmSmsTypeOfAddress aTypeOfAddress, TPtrC aBufferPtr)
       
  2294     {
       
  2295     LOGGSMU1("CSmsAddress::SetRawAddressL()");
       
  2296 
       
  2297     iTypeOfAddress = aTypeOfAddress;
       
  2298 
       
  2299     NewBufferL(aBufferPtr.Length());
       
  2300 
       
  2301 	*iBuffer=aBufferPtr;
       
  2302     } // CSmsAddress::SetRawAddressL
       
  2303 
       
  2304 
       
  2305 TGsmSmsTypeOfAddress& CSmsAddress::TypeOfAddress()
       
  2306     {
       
  2307     LOGGSMU1("CSmsAddress::TypeOfAddress()");
       
  2308 
       
  2309     return iTypeOfAddress;
       
  2310     } // CSmsAddress::TypeOfAddress
       
  2311 
       
  2312 
       
  2313 void CSmsAddress::SetAddressL(const TDesC& aAddress)
       
  2314 	{
       
  2315 	LOGGSMU1("CSmsAddress::SetAddressL()");
       
  2316 
       
  2317 	TInt length=aAddress.Length();
       
  2318 	NewBufferL(length);
       
  2319 	iBuffer->Des().Copy(aAddress);
       
  2320 
       
  2321 	const TGsmSmsTypeOfNumber typeofnumber=length && (iBuffer->Des()[0]=='+')? EGsmSmsTONInternationalNumber: EGsmSmsTONUnknown;
       
  2322 	iTypeOfAddress.SetTON(typeofnumber);
       
  2323 	} // CSmsAddress::SetAddressL
       
  2324 
       
  2325 
       
  2326 void CSmsAddress::ParsedAddress(TGsmSmsTelNumber& aParsedAddress) const
       
  2327 	{
       
  2328 	aParsedAddress.iTypeOfAddress = iTypeOfAddress;
       
  2329 
       
  2330 	TInt maxparsedlength=aParsedAddress.iTelNumber.MaxLength();
       
  2331 
       
  2332 	if (iTypeOfAddress.TON()==EGsmSmsTONAlphaNumeric)
       
  2333 		{
       
  2334 		TInt parsedlength=Address().Length();
       
  2335 		if (parsedlength>maxparsedlength)
       
  2336 			parsedlength=maxparsedlength;
       
  2337 		aParsedAddress.iTelNumber.Copy(Address().Mid(0,parsedlength));
       
  2338 		}
       
  2339 	else
       
  2340 		{
       
  2341 		aParsedAddress.iTelNumber.SetLength(maxparsedlength);
       
  2342 
       
  2343 		TInt length=iBuffer->Des().Length();
       
  2344 		TInt parsedlength=0;
       
  2345 		for (TInt i=0; (i<length) && (parsedlength<maxparsedlength); i++)
       
  2346 			{
       
  2347 			TText ch=iBuffer->Des()[i];
       
  2348             switch(ch)
       
  2349                 {
       
  2350                 case '*':
       
  2351                 case '#':
       
  2352                 case 'a':
       
  2353                 case 'b':
       
  2354                 case 'c':
       
  2355                     aParsedAddress.iTelNumber[parsedlength]=(TUint8) ch;
       
  2356                     parsedlength++;
       
  2357                     break;                    
       
  2358                 default:
       
  2359                     if ((ch>='0') && (ch<='9'))
       
  2360                         {
       
  2361                         aParsedAddress.iTelNumber[parsedlength]=(TUint8) ch;
       
  2362                         parsedlength++;
       
  2363                         }
       
  2364                     break;
       
  2365                 }			
       
  2366 			}
       
  2367 
       
  2368 		aParsedAddress.iTelNumber.SetLength(parsedlength);
       
  2369 		}
       
  2370 	}
       
  2371 
       
  2372 
       
  2373 void CSmsAddress::SetParsedAddressL(const TGsmSmsTelNumber& aParsedAddress)
       
  2374 	{
       
  2375 	LOGGSMU1("CSmsAddress::SetParsedAddressL()");
       
  2376 
       
  2377 	iTypeOfAddress=aParsedAddress.iTypeOfAddress;
       
  2378 	DoSetParsedAddressL(aParsedAddress.iTelNumber);
       
  2379 	} // CSmsAddress::SetParsedAddressL
       
  2380 
       
  2381 
       
  2382 TUint8 CSmsAddress::SizeL()
       
  2383     {
       
  2384     LOGGSMU1("CSmsAddress::SizeL()");
       
  2385 
       
  2386     TUint8 size = 0;
       
  2387 
       
  2388     TBuf8<KSmsAddressMaxAddressLength> testBuffer;
       
  2389     testBuffer.SetLength(KSmsAddressMaxAddressLength);
       
  2390     TUint8* startPtr = &testBuffer[0];
       
  2391     TUint8* endPtr = NULL;
       
  2392 
       
  2393     TRAPD(err,endPtr = EncodeL(startPtr));
       
  2394 
       
  2395     if (err != KErrNone)
       
  2396         {
       
  2397         User::Leave(KErrArgument);
       
  2398         }
       
  2399     else
       
  2400         {
       
  2401         // handle architectures whose address space increments or whose address space decrements.
       
  2402         (endPtr > startPtr) ? (size = endPtr - startPtr) : (size = startPtr - endPtr);
       
  2403         }
       
  2404 
       
  2405 	return size;
       
  2406     } // CSmsAddress::SizeL
       
  2407 
       
  2408 
       
  2409 TUint8* CSmsAddress::EncodeL(TUint8* aPtr) const
       
  2410 	{
       
  2411 	TGsmSmsTelNumber parsedaddress;
       
  2412 	ParsedAddress(parsedaddress);
       
  2413 
       
  2414 	switch (iTypeOfAddress.TON())
       
  2415 		{
       
  2416 		case EGsmSmsTONAlphaNumeric:
       
  2417 			{
       
  2418 			// Mark buffer for length encoding after conversion
       
  2419 			TUint8* lengthPtr=aPtr++;
       
  2420 			// Encode type
       
  2421 			aPtr=iTypeOfAddress.EncodeL(aPtr);
       
  2422 			// 7-bit conversion
       
  2423 			TPtrC address=Address();
       
  2424 			TInt convertedNumUDUnits=0;
       
  2425 			TPtr8 packedPtr(aPtr,0,KSmsAddressMaxAddressValueLength);
       
  2426 			TSmsAlphabetPacker packer(TSmsDataCodingScheme::ESmsAlphabet7Bit,EFalse,0);
       
  2427 			aPtr+=packer.ConvertAndPackL(iCharacterSetConverter,iFs,packedPtr,address,convertedNumUDUnits);
       
  2428 			// Now encode length
       
  2429 			TSmsOctet length=(convertedNumUDUnits*7+3)/4;
       
  2430 			length.EncodeL(lengthPtr);
       
  2431 			break;
       
  2432 			}
       
  2433 		case EGsmSmsTONInternationalNumber:
       
  2434 		default:
       
  2435 			{
       
  2436 			TSmsOctet length=parsedaddress.iTelNumber.Length();
       
  2437 			if (length > KSmsAddressMaxAddressValueLength * 2)
       
  2438 			// each address value occupies one nibble.
       
  2439                 {
       
  2440                 User::Leave(KErrArgument);
       
  2441                 }
       
  2442 			aPtr=length.EncodeL(aPtr);
       
  2443 			aPtr=iTypeOfAddress.EncodeL(aPtr);
       
  2444 			TSmsOctet octet;
       
  2445 			for (TInt i=0; i<length; i++)
       
  2446 				{
       
  2447                 if ((i%2)==0)  //  even
       
  2448                     {
       
  2449                     switch(parsedaddress.iTelNumber[i])
       
  2450                         {
       
  2451                         case '*':
       
  2452                             {
       
  2453                             octet=10; // 1010 as a binary, according to 23.040 …
       
  2454                             }
       
  2455                             break;
       
  2456 
       
  2457                         case '#':
       
  2458                             {
       
  2459                             octet=11; // 1011 as a binary, according to 23.040…
       
  2460                             }
       
  2461                             break; 
       
  2462 
       
  2463                         case 'a':
       
  2464                             {
       
  2465                             octet=12; // 1100 as a binary, according to 23.040...
       
  2466                             }
       
  2467                             break;
       
  2468 
       
  2469                         case 'b':
       
  2470                             {
       
  2471                             octet=13; // 1101 as a binary, according to 23.040…
       
  2472                             }
       
  2473                             break;
       
  2474 
       
  2475                         case 'c':
       
  2476                             {
       
  2477                             octet=14; // 1110 as a binary, according to 23.040…
       
  2478                             }
       
  2479                             break;
       
  2480 
       
  2481                         default:
       
  2482                             octet=(parsedaddress.iTelNumber[i])-'0';
       
  2483                             break;
       
  2484                         }
       
  2485                     } 
       
  2486                 else
       
  2487                     {
       
  2488                     TInt tempOctet = 0;
       
  2489        
       
  2490                     switch(parsedaddress.iTelNumber[i])
       
  2491                         {
       
  2492                         case '*':
       
  2493                             {
       
  2494                             tempOctet=10; // 1010 as a binary, according to 23.040…
       
  2495                             }
       
  2496                             break;
       
  2497 
       
  2498                         case '#':
       
  2499                             {
       
  2500                             tempOctet=11; // 1011 as a binary, according to 23.040…
       
  2501                             }
       
  2502                             break;
       
  2503 
       
  2504                         case 'a':
       
  2505                             {
       
  2506                             tempOctet=12; // 1100 as a binary, according to 23.040…
       
  2507                             }
       
  2508                             break;
       
  2509 
       
  2510                         case 'b':
       
  2511                             {
       
  2512                             tempOctet=13; // 1101 as a binary, according to 23.040…
       
  2513                             }
       
  2514                             break;
       
  2515 
       
  2516                         case 'c':
       
  2517                             {
       
  2518                             tempOctet=14; // 1110 as a binary, according to 23.040…
       
  2519                             }
       
  2520                             break;
       
  2521 
       
  2522                         default:
       
  2523                             tempOctet=(parsedaddress.iTelNumber[i])-'0';
       
  2524                             break;
       
  2525                         }
       
  2526                     octet=octet|tempOctet<<4;
       
  2527                     aPtr=octet.EncodeL(aPtr);				
       
  2528 				    }
       
  2529                 
       
  2530 			    } // end for loop
       
  2531 
       
  2532 			if (length%2)   // odd number of semioctets
       
  2533 				{
       
  2534 				octet=octet|0xF0;
       
  2535 				aPtr=octet.EncodeL(aPtr);
       
  2536 				}
       
  2537 						
       
  2538 		    } // end default case
       
  2539 	    }
       
  2540 	return aPtr;
       
  2541 	}
       
  2542 
       
  2543 
       
  2544 void CSmsAddress::DecodeL(TGsmuLex8& aPdu)
       
  2545 	{
       
  2546 	TSmsOctet length;  //represents the number of valid semi-octets
       
  2547 	length.DecodeL(aPdu);
       
  2548 	iTypeOfAddress.DecodeL(aPdu);
       
  2549 
       
  2550 	switch (iTypeOfAddress.TON())
       
  2551 		{
       
  2552 		case EGsmSmsTONAlphaNumeric:
       
  2553 			{
       
  2554 			const TUint cphs1 = aPdu.GetL();
       
  2555 			const TUint cphs2 = aPdu.GetL();
       
  2556 			aPdu.UnGet();
       
  2557 			aPdu.UnGet();
       
  2558 
       
  2559 			const TPtrC8 remainder(aPdu.Remainder());
       
  2560 			// we assume that it is a cphs message waiting indicator
       
  2561             // we might want to do further tests tobe sure that it is a CPHS message
       
  2562 			if(    (length==4)
       
  2563 				&& ((cphs1 & 0x7E) == 0x10) // x001 000x constant value
       
  2564 				&& ((cphs2 & 0x7E) == 0x00) // x000 000x constant value
       
  2565 			  )
       
  2566 				{
       
  2567 				TGsmSmsTelNumber parsedaddress;
       
  2568 				parsedaddress.iTelNumber.SetLength(length);
       
  2569 				//Copy the two bytes of the cphs message waiting address into the parsed address
       
  2570 				parsedaddress.iTelNumber[0]=(TUint8)length;
       
  2571 				parsedaddress.iTelNumber[1]= (TUint8)iTypeOfAddress;
       
  2572 				parsedaddress.iTelNumber[2]= (TUint8)aPdu.GetL();
       
  2573 				parsedaddress.iTelNumber[3]= (TUint8)aPdu.GetL();
       
  2574 				DoSetParsedAddressL(parsedaddress.iTelNumber);
       
  2575 				}
       
  2576 			else if(length==11 && remainder.Left(6).CompareF(KMOSES) ==KErrNone ) //check for MOSES
       
  2577 				{
       
  2578 					DoSetParsedAddressL(KNETWORK);
       
  2579 					aPdu.IncL(6);
       
  2580 				}
       
  2581 			else
       
  2582 				{
       
  2583 				// Encoded length is number of semi-octets used to store address using
       
  2584 				// 7-bit char set - determine number of user data units required
       
  2585 				const TInt numUDUnits=length*4/7;
       
  2586 				// Unpack the data - assume max converted length twice the unconverted length
       
  2587 				// VEP Why this assumption, the length will be doubled at the client because of that??
       
  2588 				// EXT-568BMW
       
  2589 				// Fix is not to multiply by 2
       
  2590 				//NewBufferL(2*numUDUnits);
       
  2591 				NewBufferL(numUDUnits);
       
  2592 				TPtr unpackedPtr((TText*)iBuffer->Des().Ptr(),0,iBuffer->Length());
       
  2593 
       
  2594 				if (remainder.Length() < KSmsAddressMaxAddressValueLength)
       
  2595 					User::Leave(KErrGsmuDecoding);
       
  2596 
       
  2597 				TPtrC8 packedPtr(remainder.Ptr(), KSmsAddressMaxAddressValueLength);
       
  2598 				TSmsAlphabetPacker unpacker(TSmsDataCodingScheme::ESmsAlphabet7Bit,EFalse,0);
       
  2599 				unpacker.UnpackAndConvertL(iCharacterSetConverter,iFs,packedPtr,unpackedPtr,numUDUnits);
       
  2600 				aPdu.IncL(length / 2);
       
  2601 				if ((length % 2) != 0)
       
  2602 					aPdu.IncL();
       
  2603 				}
       
  2604 			break;
       
  2605 			}
       
  2606 		case EGsmSmsTONInternationalNumber:
       
  2607 		default:
       
  2608 			{
       
  2609 			TGsmSmsTelNumber parsedaddress;
       
  2610 			if (length>parsedaddress.iTelNumber.MaxLength())
       
  2611 				User::Leave(KErrGsmuDecoding);
       
  2612 			parsedaddress.iTelNumber.SetLength(length);
       
  2613 			TSmsOctet octet;
       
  2614 			for (TInt i=0; i<length; i++)
       
  2615 				{
       
  2616 				if ((i%2)==0)  //  even
       
  2617 					{
       
  2618                     TUint8 tempOctet = 0;
       
  2619                     octet.DecodeL(aPdu);
       
  2620                     tempOctet = (TUint8)octet&0x0F; // four topmost bits set to zero
       
  2621                     
       
  2622                     switch(tempOctet)
       
  2623                         {
       
  2624                         case 10: // 1010
       
  2625                             {
       
  2626                             parsedaddress.iTelNumber[i] = '*';
       
  2627                             }
       
  2628                             break;
       
  2629 
       
  2630                         case 11: // 1011
       
  2631                             {
       
  2632                             parsedaddress.iTelNumber[i] = '#';
       
  2633                             }
       
  2634                             break; 
       
  2635 
       
  2636                         case 12: // 1100
       
  2637                             {
       
  2638                             parsedaddress.iTelNumber[i] = 'a';
       
  2639                             }
       
  2640                             break;
       
  2641 
       
  2642                         case 13: //1101
       
  2643                             {
       
  2644                             parsedaddress.iTelNumber[i] = 'b'; 
       
  2645                             }
       
  2646                             break;
       
  2647 
       
  2648                         case 14: //1110
       
  2649                             {
       
  2650                             parsedaddress.iTelNumber[i] = 'c';
       
  2651                             }
       
  2652                             break;
       
  2653 
       
  2654                         case 15: 
       
  2655                             // Skip if 1111 is received 
       
  2656                             break;
       
  2657 
       
  2658                         default:
       
  2659                             parsedaddress.iTelNumber[i]=(TUint8) (tempOctet+'0');
       
  2660                             break;
       
  2661                         }
       
  2662 					}
       
  2663 				else
       
  2664                     {
       
  2665                     TUint8 tempOctet = 0;
       
  2666                     octet&0xF0; // four least significant bits…
       
  2667                     tempOctet = (TUint8)octet>>4;
       
  2668 
       
  2669                     switch(tempOctet)
       
  2670                         {
       
  2671                         case 10: // 1010
       
  2672                             {
       
  2673                             parsedaddress.iTelNumber[i] = '*';
       
  2674                             }
       
  2675                             break;
       
  2676 
       
  2677                         case 11: // 1011
       
  2678                             {
       
  2679                             parsedaddress.iTelNumber[i] = '#';
       
  2680                             }
       
  2681                             break;
       
  2682 
       
  2683                         case 12: // 1100
       
  2684                             {
       
  2685                             parsedaddress.iTelNumber[i] = 'a';
       
  2686                             }
       
  2687                             break;
       
  2688 
       
  2689                         case 13: // 1101
       
  2690                             {
       
  2691                             parsedaddress.iTelNumber[i] = 'b';
       
  2692                             }
       
  2693                             break;
       
  2694 
       
  2695                         case 14: // 1110
       
  2696                             {
       
  2697                             parsedaddress.iTelNumber[i] = 'c';
       
  2698                             }
       
  2699                             break;
       
  2700 
       
  2701                         case 15: 
       
  2702                             // Skip if 1111 is received 
       
  2703                             break;
       
  2704 
       
  2705                         default:
       
  2706                             parsedaddress.iTelNumber[i]=(TUint8) (tempOctet+'0'); 
       
  2707                             // unwanted bits zeroed in the beginning
       
  2708        
       
  2709                             break;
       
  2710                         }
       
  2711                     }
       
  2712 				}
       
  2713 			DoSetParsedAddressL(parsedaddress.iTelNumber);
       
  2714 			}
       
  2715 		}
       
  2716 	}
       
  2717 
       
  2718 void CSmsAddress::InternalizeL(RReadStream& aStream)
       
  2719 	{
       
  2720 	aStream >> iTypeOfAddress;
       
  2721 	HBufC* buffer=HBufC::NewL(aStream,256);
       
  2722 	delete iBuffer;
       
  2723 	iBuffer=buffer;
       
  2724 	} // CSmsAddress::InternalizeL
       
  2725 
       
  2726 
       
  2727 void CSmsAddress::ExternalizeL(RWriteStream& aStream) const
       
  2728 	{
       
  2729 	aStream << iTypeOfAddress;
       
  2730 	aStream << *iBuffer;
       
  2731 	} // CSmsAddress::ExternalizeL
       
  2732 
       
  2733 
       
  2734 CSmsAddress::CSmsAddress(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs):
       
  2735 	iCharacterSetConverter(aCharacterSetConverter),
       
  2736 	iFs(aFs),
       
  2737 	iTypeOfAddress(EGsmSmsTONUnknown, EGsmSmsNPIISDNTelephoneNumberingPlan)
       
  2738 	{
       
  2739 	} // CSmsAddress::CSmsAddress
       
  2740 
       
  2741 
       
  2742 void CSmsAddress::NewBufferL(TInt aLength)
       
  2743 	{
       
  2744 	LOGGSMU1("CSmsAddress::NewBufferL()");
       
  2745 
       
  2746 	HBufC* buffer=HBufC::NewL(aLength);
       
  2747 	delete iBuffer;
       
  2748 	iBuffer=buffer;
       
  2749 	iBuffer->Des().SetLength(aLength);
       
  2750 	iBuffer->Des().FillZ();
       
  2751 	} // CSmsAddress::NewBufferL
       
  2752 
       
  2753 
       
  2754 void CSmsAddress::DoSetParsedAddressL(const TDesC& aAddress)
       
  2755 	{
       
  2756 	LOGGSMU1("CSmsAddress::DoSetParsedAddressL()");
       
  2757 
       
  2758 	TInt length=aAddress.Length();
       
  2759 	if ((iTypeOfAddress.TON()==EGsmSmsTONInternationalNumber) &&
       
  2760 	    (length && (aAddress[0]!='+')))
       
  2761 		{
       
  2762 		NewBufferL(length+1);
       
  2763 		iBuffer->Des()[0]='+';
       
  2764 		TPtr ptr((TText*) (iBuffer->Des().Ptr()+1),length,length);
       
  2765 		ptr.Copy(aAddress);
       
  2766 		}
       
  2767 	else
       
  2768 		{
       
  2769 		NewBufferL(length);
       
  2770 		iBuffer->Des().Copy(aAddress);
       
  2771 		}
       
  2772 	} // CSmsAddress::DoSetParsedAddressL
       
  2773 
       
  2774 
       
  2775 TSmsServiceCenterTimeStamp::TSmsServiceCenterTimeStamp()
       
  2776 	{
       
  2777 	iTimeZoneNumQuarterHours = 0;
       
  2778 	} // TSmsServiceCenterTimeStamp::TSmsServiceCenterTimeStamp
       
  2779 
       
  2780 
       
  2781 void TSmsServiceCenterTimeStamp::SetTimeOffset(TInt aNumQuarterHours)
       
  2782 	{
       
  2783 	__ASSERT_DEBUG((aNumQuarterHours>=-KSmsMaxTimeZoneNumQuarterHours) && (aNumQuarterHours<=KSmsMaxTimeZoneNumQuarterHours),Panic(KGsmuPanicNumQuarterHoursOutOfRange));
       
  2784 	iTimeZoneNumQuarterHours=aNumQuarterHours;
       
  2785 	} // TSmsServiceCenterTimeStamp::SetTimeOffset
       
  2786 
       
  2787 
       
  2788 TUint8* TSmsServiceCenterTimeStamp::EncodeL(TUint8* aPtr) const
       
  2789     {
       
  2790     LOGGSMU1("TSmsServiceCenterTimeStamp::EncodeL()");
       
  2791 
       
  2792     TInt numquarterhours=iTimeZoneNumQuarterHours;
       
  2793 
       
  2794     TInt timeZoneOffsetInSeconds = numquarterhours * CSmsMessage::E15MinutesRepresentedInSeconds;
       
  2795     TTimeIntervalSeconds offsetFromUTCToLocal(timeZoneOffsetInSeconds);
       
  2796 
       
  2797     TTime time = iTime;
       
  2798     time += offsetFromUTCToLocal;
       
  2799 
       
  2800     TDateTime datetime=time.DateTime();
       
  2801 
       
  2802     TSmsOctet octet;
       
  2803     octet.FillSemiOctets(datetime.Year()%100);
       
  2804     aPtr=octet.EncodeL(aPtr);
       
  2805     octet.FillSemiOctets(datetime.Month()+1);
       
  2806     aPtr=octet.EncodeL(aPtr);
       
  2807     octet.FillSemiOctets(datetime.Day()+1);
       
  2808     aPtr=octet.EncodeL(aPtr);
       
  2809     octet.FillSemiOctets(datetime.Hour());
       
  2810     aPtr=octet.EncodeL(aPtr);
       
  2811     octet.FillSemiOctets(datetime.Minute());
       
  2812     aPtr=octet.EncodeL(aPtr);
       
  2813     octet.FillSemiOctets(datetime.Second());
       
  2814     aPtr=octet.EncodeL(aPtr);
       
  2815 
       
  2816     TInt signbit=ESmsTimeZonePositive;
       
  2817     if (numquarterhours<0)
       
  2818         {
       
  2819         numquarterhours=-numquarterhours;
       
  2820         signbit=ESmsTimeZoneNegative;
       
  2821         }
       
  2822 
       
  2823     TSmsOctet timezone;
       
  2824     timezone.FillSemiOctets(numquarterhours);
       
  2825     timezone=timezone|signbit;
       
  2826     return timezone.EncodeL(aPtr);
       
  2827     } // TSmsServiceCenterTimeStamp::EncodeL
       
  2828 
       
  2829 
       
  2830 void TSmsServiceCenterTimeStamp::DecodeL(TGsmuLex8& aPdu, TInt& aTimeError)
       
  2831 	{
       
  2832 	LOGGSMU1("TSmsServiceCenterTimeStamp::DecodeL()");
       
  2833 
       
  2834 	TSmsOctet octet;
       
  2835 	octet.DecodeL(aPdu);
       
  2836 	TInt year=octet.SemiOctetsToNum();
       
  2837 	if (year>95)
       
  2838 		year+=1900;
       
  2839 	else
       
  2840 		year+=2000;
       
  2841 	octet.DecodeL(aPdu);
       
  2842 	TInt month=octet.SemiOctetsToNum();
       
  2843 	octet.DecodeL(aPdu);
       
  2844 
       
  2845 	TInt day=octet.SemiOctetsToNum();
       
  2846 	octet.DecodeL(aPdu);
       
  2847 	TInt hour=octet.SemiOctetsToNum();
       
  2848 	octet.DecodeL(aPdu);
       
  2849 	TInt minute=octet.SemiOctetsToNum();
       
  2850 	octet.DecodeL(aPdu);
       
  2851 	TInt second=octet.SemiOctetsToNum();
       
  2852 
       
  2853     TDateTime datetime;
       
  2854     aTimeError = datetime.Set(year,(TMonth) (month-1),day-1,hour,minute,second,0);
       
  2855 
       
  2856     TSmsOctet timezone;
       
  2857     timezone.DecodeL(aPdu);
       
  2858 
       
  2859     TInt signBit = (timezone&ESmsTimeZoneSignBitMask) ?  ESmsTimeZoneNegative : ESmsTimeZonePositive;
       
  2860     timezone=timezone &(~ESmsTimeZoneSignBitMask); // clear sign bit
       
  2861 
       
  2862     TInt offsetToUTCInSeconds = 0;
       
  2863     if (timezone.SemiOctetsToNum() <= KSmsMaxTimeZoneNumQuarterHours)
       
  2864         {
       
  2865         offsetToUTCInSeconds = ((TInt) timezone.SemiOctetsToNum()) * CSmsMessage::E15MinutesRepresentedInSeconds;
       
  2866         if (signBit == ESmsTimeZoneNegative)    
       
  2867             {
       
  2868             offsetToUTCInSeconds = -offsetToUTCInSeconds;
       
  2869             }
       
  2870 
       
  2871         TTimeIntervalSeconds offsetToUTC(offsetToUTCInSeconds) ;      
       
  2872 
       
  2873         if (aTimeError == KErrNone)
       
  2874             {
       
  2875             TTime time = datetime;    	
       
  2876             time -= offsetToUTC;
       
  2877             iTime = time;
       
  2878     	
       
  2879             iTimeZoneNumQuarterHours=(signBit == ESmsTimeZonePositive) ? timezone.SemiOctetsToNum(): -timezone.SemiOctetsToNum();
       
  2880             }
       
  2881             
       
  2882         }
       
  2883     else // Time zone out of range, set to 0 per 23.040 4.4.0 Section 9.2.3.11
       
  2884         {
       
  2885     	if (aTimeError == KErrNone)
       
  2886             {    		
       
  2887             iTime = datetime;    	
       
  2888     	    iTimeZoneNumQuarterHours=0;
       
  2889     	    }            
       
  2890         }
       
  2891 	} // TSmsServiceCenterTimeStamp::DecodeL
       
  2892 
       
  2893 
       
  2894 void TSmsServiceCenterTimeStamp::InternalizeL(RReadStream& aStream)
       
  2895 	{
       
  2896 	TInt64 time;
       
  2897 	aStream >> time;
       
  2898 	iTime=time;
       
  2899 	iTimeZoneNumQuarterHours=aStream.ReadInt32L();
       
  2900 	} // TSmsServiceCenterTimeStamp::InternalizeL
       
  2901 
       
  2902 
       
  2903 void TSmsServiceCenterTimeStamp::ExternalizeL(RWriteStream& aStream) const
       
  2904 	{
       
  2905 	aStream << iTime.Int64();
       
  2906 	aStream.WriteInt32L(iTimeZoneNumQuarterHours);
       
  2907 	} // TSmsServiceCenterTimeStamp::ExternalizeL
       
  2908 
       
  2909 
       
  2910 TSmsValidityPeriod::TSmsValidityPeriod(TSmsFirstOctet& aFirstOctet):
       
  2911 	iFirstOctet(aFirstOctet),
       
  2912 	iTimeIntervalMinutes(EOneDayUnitInMinutes)
       
  2913 	{
       
  2914 	} // TSmsValidityPeriod::TSmsValidityPeriod
       
  2915 
       
  2916 
       
  2917 TTime TSmsValidityPeriod::Time() const
       
  2918 	{
       
  2919 	LOGGSMU1("TSmsValidityPeriod::Time()");
       
  2920 
       
  2921 	TTime time;
       
  2922 	time.UniversalTime();
       
  2923 	time+=iTimeIntervalMinutes;
       
  2924 	return time;
       
  2925 	} // TSmsValidityPeriod::Time
       
  2926 
       
  2927 
       
  2928 TUint8* TSmsValidityPeriod::EncodeL(TUint8* aPtr) const
       
  2929 	{
       
  2930 	LOGGSMU1("TSmsValidityPeriod::EncodeL()");
       
  2931 
       
  2932 	TInt validityperiodformat=ValidityPeriodFormat();
       
  2933 	switch (validityperiodformat)
       
  2934 		{
       
  2935 		case (TSmsFirstOctet::ESmsVPFNone):
       
  2936 			break;
       
  2937 		case (TSmsFirstOctet::ESmsVPFInteger):
       
  2938 			{
       
  2939 			TInt timeintervalminutes=iTimeIntervalMinutes.Int();
       
  2940 			__ASSERT_DEBUG((timeintervalminutes>=EFiveMinuteUnitInMinutes) && (timeintervalminutes<=63*EOneWeekUnitLimitInMinutes),Panic(KGsmuPanicValidityPeriodOutOfRange));
       
  2941 			TSmsOctet octet;
       
  2942 			if (timeintervalminutes<=EFiveMinuteUnitLimitInMinutes)
       
  2943                 octet=((timeintervalminutes/EFiveMinuteUnitInMinutes)-1);
       
  2944 			else if (timeintervalminutes<=EHalfHourUnitLimitInMinutes)
       
  2945                 octet=(((timeintervalminutes-(EHalfHourUnitLimitInMinutes/2))/EHalfHourUnitInMinutes)+EFiveMinuteUnitLimit);
       
  2946 
       
  2947 			else if (timeintervalminutes<=EOneDayUnitLimitInMinutes)
       
  2948                 octet=((timeintervalminutes/EOneDayUnitInMinutes)+166);
       
  2949 			else
       
  2950                 octet=((timeintervalminutes/EOneWeekUnitInMinutes)+192);
       
  2951 
       
  2952 			aPtr=octet.EncodeL(aPtr);
       
  2953 			break;
       
  2954 			}
       
  2955 		case (TSmsFirstOctet::ESmsVPFSemiOctet):
       
  2956 			{
       
  2957 			TSmsServiceCenterTimeStamp timestamp;
       
  2958 			timestamp.SetTime(Time());
       
  2959 
       
  2960 	 		TTimeIntervalSeconds timeIntervalInSeconds(User::UTCOffset());
       
  2961 			timestamp.SetTimeOffset(timeIntervalInSeconds.Int() / CSmsMessage::E15MinutesRepresentedInSeconds);
       
  2962 
       
  2963 			aPtr=timestamp.EncodeL(aPtr);
       
  2964 			break;
       
  2965 			}
       
  2966 		default:
       
  2967             __ASSERT_DEBUG(EFalse,Panic(KGsmuPanicUnsupportedValidityPeriodFormat));
       
  2968 			User::Leave(KErrGsmSMSTPVPFNotSupported);
       
  2969             break;
       
  2970 		};
       
  2971 	return aPtr;
       
  2972 	} // TSmsValidityPeriod::EncodeL
       
  2973 	
       
  2974 TUint8* TSmsValidityPeriod::EncodeL(TUint8* aPtr, const TEncodeParams* aEncodeParams) const
       
  2975 	{
       
  2976 	LOGGSMU1("TSmsValidityPeriod::EncodeL()");
       
  2977 
       
  2978 	TInt validityperiodformat=ValidityPeriodFormat();
       
  2979 	switch (validityperiodformat)
       
  2980 		{
       
  2981 		case (TSmsFirstOctet::ESmsVPFNone):
       
  2982 			break;
       
  2983 		case (TSmsFirstOctet::ESmsVPFInteger):
       
  2984 			{
       
  2985 			TInt timeintervalminutes=iTimeIntervalMinutes.Int();
       
  2986 			__ASSERT_DEBUG((timeintervalminutes>=EFiveMinuteUnitInMinutes) && (timeintervalminutes<=63*EOneWeekUnitLimitInMinutes),Panic(KGsmuPanicValidityPeriodOutOfRange));
       
  2987 			TSmsOctet octet;
       
  2988 			if (timeintervalminutes<=EFiveMinuteUnitLimitInMinutes)
       
  2989                 octet=((timeintervalminutes/EFiveMinuteUnitInMinutes)-1);
       
  2990 			else if (timeintervalminutes<=EHalfHourUnitLimitInMinutes)
       
  2991                 octet=(((timeintervalminutes-(EHalfHourUnitLimitInMinutes/2))/EHalfHourUnitInMinutes)+EFiveMinuteUnitLimit);
       
  2992 
       
  2993 			else if (timeintervalminutes<=EOneDayUnitLimitInMinutes)
       
  2994                 octet=((timeintervalminutes/EOneDayUnitInMinutes)+166);
       
  2995 			else
       
  2996                 octet=((timeintervalminutes/EOneWeekUnitInMinutes)+192);
       
  2997 
       
  2998 			aPtr=octet.EncodeL(aPtr);
       
  2999 			break;
       
  3000 			}
       
  3001 		case (TSmsFirstOctet::ESmsVPFSemiOctet):
       
  3002 			{			
       
  3003 			//The reason TSmsValidityPeriod::EncodeL(TUint8* aPtr, const TEncodeParams* aEncodeParams) was
       
  3004 			//created was to allow the CSmsMessage's time stamp to be used when generating the validity time.
       
  3005 			//The CSmsMessage's time stamp is typically created when the message is constructed by the SMS Stack client.
       
  3006 			//This means the validity time is based from the point the SMS Stack client actually sends the message, rather
       
  3007 			//than the SMS Stack encodes it
       
  3008 						
       
  3009 			TSmsServiceCenterTimeStamp timestamp;
       
  3010 			timestamp.SetTime( *aEncodeParams->iTimeStamp + iTimeIntervalMinutes ); 									    		    		    		    		    
       
  3011 
       
  3012 	 		TTimeIntervalSeconds timeIntervalInSeconds( *aEncodeParams->iTimeIntervalInSeconds );
       
  3013 			timestamp.SetTimeOffset(timeIntervalInSeconds.Int() / CSmsMessage::E15MinutesRepresentedInSeconds);
       
  3014 
       
  3015 			aPtr=timestamp.EncodeL(aPtr);
       
  3016 			break;
       
  3017 			}
       
  3018 		default:
       
  3019             __ASSERT_DEBUG(EFalse,Panic(KGsmuPanicUnsupportedValidityPeriodFormat));
       
  3020 			User::Leave(KErrGsmSMSTPVPFNotSupported);
       
  3021             break;
       
  3022 		};
       
  3023 	return aPtr;
       
  3024 	} // TSmsValidityPeriod::EncodeL	
       
  3025 
       
  3026 void TSmsValidityPeriod::DecodeL(TGsmuLex8& aPdu)
       
  3027 	{
       
  3028 	LOGGSMU1("TSmsValidityPeriod::DecodeL()");
       
  3029 
       
  3030 	TInt validityperiodformat=ValidityPeriodFormat();
       
  3031 	switch (validityperiodformat)
       
  3032 		{
       
  3033 		case (TSmsFirstOctet::ESmsVPFNone):
       
  3034 			break;
       
  3035 		case (TSmsFirstOctet::ESmsVPFInteger):
       
  3036 			{
       
  3037 			TSmsOctet octet;
       
  3038 			octet.DecodeL(aPdu);
       
  3039             if (octet<=EFiveMinuteUnitLimit)
       
  3040                 iTimeIntervalMinutes=(octet+1)*EFiveMinuteUnitInMinutes;
       
  3041 			else if (octet<=EHalfHourUnitLimit)
       
  3042                 iTimeIntervalMinutes=((EOneDayUnitInMinutes/2)+((octet-EFiveMinuteUnitLimit)*EHalfHourUnitInMinutes));
       
  3043 			else if (octet<=EOneDayUnitLimit)
       
  3044                 iTimeIntervalMinutes=(octet-166)*EOneDayUnitInMinutes;
       
  3045 			else
       
  3046                 iTimeIntervalMinutes=(octet-192)*EOneWeekUnitInMinutes;
       
  3047 			break;
       
  3048 			}
       
  3049 		case (TSmsFirstOctet::ESmsVPFSemiOctet):
       
  3050 			{
       
  3051 			TSmsServiceCenterTimeStamp timestamp;
       
  3052 			TInt timeError;
       
  3053 			timestamp.DecodeL(aPdu, timeError);
       
  3054 			User::LeaveIfError(timeError);
       
  3055 			TTime time;
       
  3056 			time.UniversalTime();
       
  3057 			timestamp.Time().MinutesFrom(time,iTimeIntervalMinutes);
       
  3058 			break;
       
  3059 			}
       
  3060 		default:
       
  3061             __ASSERT_DEBUG(EFalse,Panic(KGsmuPanicUnsupportedValidityPeriodFormat));
       
  3062 			User::Leave(KErrGsmSMSTPVPFNotSupported);
       
  3063             break;
       
  3064 		};
       
  3065 	} // TSmsValidityPeriod::DecodeL
       
  3066 
       
  3067 
       
  3068 void TSmsValidityPeriod::InternalizeL(RReadStream& aStream)
       
  3069 	{
       
  3070 	TInt timeintervalinminutes=aStream.ReadInt32L();
       
  3071 	iTimeIntervalMinutes=timeintervalinminutes;
       
  3072 	} // TSmsValidityPeriod::InternalizeL
       
  3073 
       
  3074 
       
  3075 void TSmsValidityPeriod::ExternalizeL(RWriteStream& aStream) const
       
  3076 	{
       
  3077 	aStream.WriteInt32L(iTimeIntervalMinutes.Int());
       
  3078 	} // TSmsValidityPeriod::ExternalizeL
       
  3079 
       
  3080 
       
  3081 CSmsInformationElement* CSmsInformationElement::NewL(TSmsInformationElementIdentifier aIdentifier,const TDesC8& aData)
       
  3082 	{
       
  3083 	LOGGSMU1("CSmsInformationElement::NewL()");
       
  3084 
       
  3085 	CSmsInformationElement* informationelement=new(ELeave) CSmsInformationElement(aIdentifier);
       
  3086 	CleanupStack::PushL(informationelement);
       
  3087 	informationelement->ConstructL(aData);
       
  3088 	CleanupStack::Pop();
       
  3089 	return informationelement;
       
  3090 	} // CSmsInformationElement::NewL
       
  3091 
       
  3092 
       
  3093 CSmsInformationElement* CSmsInformationElement::NewL()
       
  3094 	{
       
  3095 	LOGGSMU1("CSmsInformationElement::NewL()");
       
  3096 
       
  3097 	CSmsInformationElement* informationelement=new(ELeave) CSmsInformationElement(ESmsIEIConcatenatedShortMessages8BitReference);
       
  3098 	CleanupStack::PushL(informationelement);
       
  3099 	TPtrC8 data;
       
  3100 	informationelement->ConstructL(data);
       
  3101 	CleanupStack::Pop();
       
  3102 	return informationelement;
       
  3103 	} // CSmsInformationElement::NewL
       
  3104 
       
  3105 
       
  3106 /**
       
  3107  *  Destructor.
       
  3108  */
       
  3109 CSmsInformationElement::~CSmsInformationElement()
       
  3110 	{
       
  3111 	delete iData;
       
  3112 	} // CSmsInformationElement::NewL
       
  3113 
       
  3114 
       
  3115 /**
       
  3116  *  Gets the Information Element data.
       
  3117  *  
       
  3118  *  @return Information Element data
       
  3119  *  @capability None
       
  3120  */
       
  3121 EXPORT_C TPtr8 CSmsInformationElement::Data()
       
  3122 	{
       
  3123 	LOGGSMU1("CSmsInformationElement::Data()");
       
  3124 
       
  3125 	return iData->Des();
       
  3126 	} // CSmsInformationElement::Data
       
  3127 
       
  3128 
       
  3129 /**
       
  3130  *  Gets the (const) Information Element data.
       
  3131  *  
       
  3132  *  @return Information Element data
       
  3133  *  @capability None
       
  3134  */
       
  3135 EXPORT_C const TDesC8& CSmsInformationElement::Data() const
       
  3136 	{
       
  3137 	LOGGSMU1("CSmsInformationElement::Data()");
       
  3138 
       
  3139 	return *iData;
       
  3140 	} // CSmsInformationElement::Data
       
  3141 
       
  3142 
       
  3143 /**
       
  3144  *  Gets the Information Element Identifier.
       
  3145  *  
       
  3146  *  @return Information Element Identifier
       
  3147  *  @capability None
       
  3148  */
       
  3149 EXPORT_C CSmsInformationElement::TSmsInformationElementIdentifier CSmsInformationElement::Identifier() const
       
  3150 	{
       
  3151 	return TSmsId(TInt(iIdentifier));
       
  3152 	} // CSmsInformationElement::TSmsInformationElementIdentifier
       
  3153 
       
  3154 
       
  3155 TUint8* CSmsInformationElement::EncodeL(TUint8* aPtr) const
       
  3156 	{
       
  3157 	LOGGSMU1("CSmsInformationElement::EncodeL()");
       
  3158 
       
  3159 	TSmsOctet id=iIdentifier;
       
  3160 	aPtr=id.EncodeL(aPtr);
       
  3161 	TSmsOctet informationelementlength=iData->Des().Length();
       
  3162 	aPtr=informationelementlength.EncodeL(aPtr);
       
  3163 	Mem::Copy(aPtr,iData->Des().Ptr(),informationelementlength);
       
  3164 	aPtr+=TInt(informationelementlength);
       
  3165 	return aPtr;
       
  3166 	} // CSmsInformationElement::EncodeL
       
  3167 
       
  3168 
       
  3169 void CSmsInformationElement::DecodeL(TGsmuLex8& aPdu)
       
  3170 	{
       
  3171 	LOGGSMU1("CSmsInformationElement::DecodeL()");
       
  3172 
       
  3173 	TSmsOctet id;
       
  3174 	id.DecodeL(aPdu);
       
  3175 	iIdentifier=static_cast<TSmsInformationElementIdentifier>((TInt)id);
       
  3176 
       
  3177 	TSmsOctet informationelementlength;
       
  3178 	informationelementlength.DecodeL(aPdu);
       
  3179 
       
  3180  	switch(iIdentifier)
       
  3181  	{
       
  3182  	case (ESmsIEIConcatenatedShortMessages8BitReference):
       
  3183  		if(informationelementlength !=3)
       
  3184  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3185  		break;
       
  3186  	case (ESmsIEISpecialSMSMessageIndication):
       
  3187  		if(informationelementlength !=2)
       
  3188  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3189  		break;
       
  3190  	case (ESmsIEIApplicationPortAddressing8Bit):
       
  3191  		if(informationelementlength !=2)
       
  3192  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3193  		break;
       
  3194  	case (ESmsIEIApplicationPortAddressing16Bit):
       
  3195  		if(informationelementlength !=4)
       
  3196  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3197  		break;
       
  3198  	case (ESmsIEISMSCControlParameters):
       
  3199  		if(informationelementlength !=1)
       
  3200  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3201  		break;
       
  3202  	case (ESmsIEIUDHSourceIndicator):
       
  3203  		if(informationelementlength !=1)
       
  3204  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3205  		break;
       
  3206  	case (ESmsIEIConcatenatedShortMessages16BitReference):
       
  3207  		if(informationelementlength !=4)
       
  3208  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3209  		break;
       
  3210  	case (ESmsIEIRFC822EmailHeader):
       
  3211  		if(informationelementlength !=1)
       
  3212  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3213  		break;
       
  3214   	case (ESmsHyperLinkFormat):
       
  3215  		if(informationelementlength !=4)
       
  3216  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3217  		break;
       
  3218   	case (ESmsNationalLanguageSingleShift):
       
  3219  		if(informationelementlength != 1)
       
  3220  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3221  		break;
       
  3222   	case (ESmsNationalLanguageLockingShift):
       
  3223  		if(informationelementlength != 1)
       
  3224  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3225  		break;
       
  3226  	case (ESmsIEISIMToolkitSecurityHeaders1):
       
  3227  	case (ESmsIEISIMToolkitSecurityHeaders2):
       
  3228  	case (ESmsIEISIMToolkitSecurityHeaders3):
       
  3229  	case (ESmsIEISIMToolkitSecurityHeaders4):
       
  3230  	case (ESmsIEISIMToolkitSecurityHeaders5):
       
  3231  	case (ESmsIEISIMToolkitSecurityHeaders6):
       
  3232  	case (ESmsIEISIMToolkitSecurityHeaders7):
       
  3233  	case (ESmsIEISIMToolkitSecurityHeaders8):
       
  3234  	case (ESmsIEISIMToolkitSecurityHeaders9):
       
  3235  	case (ESmsIEISIMToolkitSecurityHeaders10):
       
  3236  	case (ESmsIEISIMToolkitSecurityHeaders11):
       
  3237  	case (ESmsIEISIMToolkitSecurityHeaders12):
       
  3238  	case (ESmsIEISIMToolkitSecurityHeaders13):
       
  3239  	case (ESmsIEISIMToolkitSecurityHeaders14):
       
  3240  	case (ESmsIEISIMToolkitSecurityHeaders15):
       
  3241  	case (ESmsIEISIMToolkitSecurityHeaders16):
       
  3242  	if(informationelementlength !=0)
       
  3243  			User::Leave(KErrGsmSMSTpduNotSupported);
       
  3244  		break;
       
  3245  	default:
       
  3246  		break;
       
  3247  	}
       
  3248 
       
  3249 	const TPtrC8 data(aPdu.NextAndIncL(informationelementlength));
       
  3250 	NewDataL(informationelementlength);
       
  3251 	TPtr8 ptr(iData->Des());
       
  3252 	ptr.Copy(data);
       
  3253 	} // CSmsInformationElement::DecodeL
       
  3254 
       
  3255 
       
  3256 void CSmsInformationElement::InternalizeL(RReadStream& aStream)
       
  3257 	{
       
  3258 	TSmsOctet id;
       
  3259 	aStream >> id;
       
  3260 	iIdentifier=static_cast<TSmsInformationElementIdentifier>((TInt)id);
       
  3261 	delete iData;
       
  3262 	iData=NULL;
       
  3263 	iData=HBufC8::NewL(aStream,CSmsUserData::KSmsMaxUserDataSize);
       
  3264 	} // CSmsInformationElement::InternalizeL
       
  3265 
       
  3266 
       
  3267 void CSmsInformationElement::ExternalizeL(RWriteStream& aStream) const
       
  3268 	{
       
  3269 	TSmsOctet id;
       
  3270 	id=(TInt)iIdentifier;
       
  3271 	aStream << id;
       
  3272 	aStream << *iData;
       
  3273 	} // CSmsInformationElement::ExternalizeL
       
  3274 
       
  3275 
       
  3276 void CSmsInformationElement::ConstructL(const TDesC8& aData)
       
  3277 	{
       
  3278 	LOGGSMU1("CSmsInformationElement::ConstructL()");
       
  3279 
       
  3280 	NewDataL(aData.Length());
       
  3281 	iData->Des().Copy(aData);
       
  3282 	} // CSmsInformationElement::ConstructL
       
  3283 
       
  3284 
       
  3285 void CSmsInformationElement::NewDataL(TInt aLength)
       
  3286 	{
       
  3287 	LOGGSMU1("CSmsInformationElement::NewDataL()");
       
  3288 
       
  3289 	HBufC8* data=HBufC8::NewL(aLength);
       
  3290 	delete iData;
       
  3291 	iData=data;
       
  3292 	iData->Des().SetLength(aLength);
       
  3293 	} // CSmsInformationElement::NewDataL
       
  3294 
       
  3295 
       
  3296 TUint CSmsInformationElement::Length()const
       
  3297 	{
       
  3298 	LOGGSMU1("CSmsInformationElement::Length()");
       
  3299 
       
  3300 	return 2+iData->Length();  // 2 stands for IEID and IEDL
       
  3301 	} // CSmsInformationElement::Length
       
  3302 
       
  3303 
       
  3304 /**
       
  3305  *  @internalComponent
       
  3306  *  
       
  3307  *  This method maps an information element to an index into an array of categories.
       
  3308  *  
       
  3309  *  @param aId
       
  3310  *  The information Element Identifier.
       
  3311  *  @param aIndex
       
  3312  *  The index into the array of categories
       
  3313  *  @return
       
  3314  *  True if the information element can be mapped.
       
  3315  *  False otherwise.
       
  3316  */
       
  3317 TBool TSmsInformationElementCategories::TranslateCategoryToIndex(TInformationElementId aId, TInt& aIndex)
       
  3318     {
       
  3319     LOGGSMU1("CSmsMessage::TranslateCategoryToIndex");
       
  3320 
       
  3321     TBool rc = ETrue;
       
  3322 
       
  3323     if (aId < CSmsInformationElement::ESmsIEMaximum)
       
  3324         {
       
  3325         switch (aId)
       
  3326             {
       
  3327             case CSmsInformationElement::ESmsIEIConcatenatedShortMessages8BitReference:
       
  3328             case CSmsInformationElement::ESmsIEIConcatenatedShortMessages16BitReference:
       
  3329             case CSmsInformationElement::ESmsIEISMSCControlParameters:
       
  3330             case CSmsInformationElement::ESmsIEIRFC822EmailHeader:
       
  3331                 {
       
  3332                 aIndex = EIndexCtrlMandatoryInEveryPDUButWithValueSpecificToPDU;
       
  3333                 break;
       
  3334                 }
       
  3335             case CSmsInformationElement::ESmsIEISpecialSMSMessageIndication:
       
  3336                 {
       
  3337                 aIndex = EIndexCtrlMandatoryInEveryPDUMultipleInstancesPerPDU;
       
  3338                 break;
       
  3339                 }
       
  3340             case CSmsInformationElement::ESmsHyperLinkFormat:
       
  3341                 {
       
  3342                 aIndex = EIndexCtrlMultipleInstancesAllowed;
       
  3343                 break;
       
  3344                 }
       
  3345             case CSmsInformationElement::ESmsNationalLanguageSingleShift:
       
  3346             case CSmsInformationElement::ESmsNationalLanguageLockingShift:
       
  3347                 {
       
  3348                 aIndex = EIndexCtrlOptionalInEveryPDUWithValueSpecificToPDU;
       
  3349                 break;
       
  3350                 }
       
  3351             case CSmsInformationElement::ESmsReplyAddressFormat:
       
  3352                 {
       
  3353                 aIndex = EIndexCtrlMandatoryIn1stPDUOnly;
       
  3354                 break;
       
  3355                 }
       
  3356             case CSmsInformationElement::ESmsEnhanceVoiceMailInformation:
       
  3357                 {
       
  3358                 aIndex = EIndexCtrlSingleInstanceOnly;
       
  3359                 break;
       
  3360                 }
       
  3361             case CSmsInformationElement::ESmsEnhancedTextFormatting:
       
  3362             case CSmsInformationElement::ESmsEnhancedPredefinedSound:
       
  3363             case CSmsInformationElement::ESmsEnhancedUserDefinedSound:
       
  3364             case CSmsInformationElement::ESmsEnhancedPredefinedAnimation:
       
  3365             case CSmsInformationElement::ESmsEnhancedLargeAnimation:
       
  3366             case CSmsInformationElement::ESmsEnhancedSmallAnimation:
       
  3367             case CSmsInformationElement::ESmsEnhancedLargePicture:
       
  3368             case CSmsInformationElement::ESmsEnhancedSmallPicture:
       
  3369             case CSmsInformationElement::ESmsEnhancedVariablePicture:
       
  3370             case CSmsInformationElement::ESmsEnhancedUserPromptIndicator:
       
  3371             case CSmsInformationElement::ESmsEnhancedExtendedObject:
       
  3372             case CSmsInformationElement::ESmsEnhancedReusedExtendedObject:
       
  3373             case CSmsInformationElement::ESmsEnhancedCompressionControl:
       
  3374             case CSmsInformationElement::ESmsEnhancedODI:
       
  3375             case CSmsInformationElement::ESmsEnhancedStandardWVG:
       
  3376             case CSmsInformationElement::ESmsEnhancedCharacterSizeWVG:
       
  3377             case CSmsInformationElement::ESmsEnhancedextendedObjectDataRequest:
       
  3378                 {
       
  3379                 aIndex = EIndexEmsInformationElement;
       
  3380                 break;
       
  3381                 }
       
  3382             case CSmsInformationElement::ESmsIEIReserved:
       
  3383             case CSmsInformationElement::ESmsIEIValueNotUsed:
       
  3384                 {
       
  3385                 rc = EFalse;
       
  3386                 break;
       
  3387                 }
       
  3388             default:
       
  3389                 {
       
  3390                 aIndex = EIndexCtrlMandatoryInEveryPDUAndWithIdenticalValues;
       
  3391                 break;
       
  3392                 }
       
  3393             }
       
  3394         }
       
  3395     else
       
  3396         {
       
  3397         rc = EFalse;
       
  3398         LOGGSMU3("CSmsMessage::TranslateCategoryToIndex id = %d, found = %d", aId, rc);
       
  3399         }
       
  3400     return rc;
       
  3401     } // TSmsInformationElementCategories::TranslateCategoryToIndex
       
  3402 
       
  3403 
       
  3404 /**
       
  3405  *  @internalComponent
       
  3406  *  
       
  3407  *  This method gets an information element identifier's category.
       
  3408  *  
       
  3409  *  @param aId
       
  3410  *  The information Element Identifier.
       
  3411  *  @param aCategory
       
  3412  *  The category of information element.
       
  3413  *  @return
       
  3414  *  ETrue if successful, EFalse if an information identifier is unknown or cannot
       
  3415  *  be mapped.
       
  3416  */
       
  3417 TBool TSmsInformationElementCategories::GetCategoryDefinition(TInformationElementId aId, TInformationElementCategory& aCategory)
       
  3418     {
       
  3419     LOGGSMU1("TSmsInformationElementCategories::GetCategoryDefinition");
       
  3420     TInt index;
       
  3421 
       
  3422     if (TranslateCategoryToIndex(aId,index))
       
  3423         {
       
  3424         aCategory = categories[index];
       
  3425         }
       
  3426     else
       
  3427         {
       
  3428         LOGGSMU2("TSmsInformationElementCategories::GetCategoryDefinition, Failure, aId = %d", aId);
       
  3429         return EFalse;
       
  3430         }
       
  3431 
       
  3432     return ETrue;
       
  3433     } // TSmsInformationElementCategories::GetCategoryDefinition
       
  3434 
       
  3435 
       
  3436 const TSmsInformationElementCategories::TInformationElementCategory TSmsInformationElementCategories::categories[TSmsInformationElementCategories::ENumberOfIndices] =
       
  3437     {
       
  3438     TSmsInformationElementCategories::EEmsInformationElement,                           // EDefaultEMSIndex
       
  3439     TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues,   // EDefaultControlIndex
       
  3440     TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU,  // EIndexForSpecialSMSMessageIndication, Concatenated Short Messages
       
  3441     TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU,// EIndexForIRFC822EmailHeader, Application Port Addresses
       
  3442     TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly,                       // EIndexReplyAddressFormat
       
  3443     TSmsInformationElementCategories::ECtrlSingleInstanceOnly,                          // EIndexEnhanceVoiceMailInformation
       
  3444     TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed                     // EIndexForHyperLinkFormat
       
  3445     };
       
  3446 
       
  3447 
       
  3448 CSmsUserData* CSmsUserData::NewL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs,TSmsFirstOctet& aFirstOctet,const TSmsDataCodingScheme& aDataCodingScheme)
       
  3449 	{
       
  3450 	LOGGSMU1("CSmsUserData::NewL()");
       
  3451 
       
  3452 	CSmsUserData* userdata=new(ELeave) CSmsUserData(aCharacterSetConverter,aFs,aFirstOctet,aDataCodingScheme);
       
  3453 	CleanupStack::PushL(userdata);
       
  3454 	userdata->ConstructL();
       
  3455 	CleanupStack::Pop();
       
  3456 	return userdata;
       
  3457 	} // CSmsUserData::NewL
       
  3458 
       
  3459 
       
  3460 /**
       
  3461  *  Destructor.
       
  3462  */
       
  3463 CSmsUserData::~CSmsUserData()
       
  3464     {
       
  3465     iInformationElementArray.ResetAndDestroy();
       
  3466     delete iBody;
       
  3467     } // CSmsUserData::NewL
       
  3468 
       
  3469 
       
  3470 /**
       
  3471  *  Gets an information element by index.
       
  3472  *  
       
  3473  *  @param aIndex Index of the information element within the User Data
       
  3474  *  @return Information element
       
  3475  *  @capability None
       
  3476  */
       
  3477 EXPORT_C  CSmsInformationElement& CSmsUserData::InformationElement(TInt aIndex) const
       
  3478 	{
       
  3479 	LOGGSMU1("CSmsUserData::InformationElement()");
       
  3480 
       
  3481 	return *iInformationElementArray[aIndex];
       
  3482 	} // CSmsUserData::InformationElement
       
  3483 
       
  3484 
       
  3485 CSmsInformationElement*& CSmsUserData::InformationElementPtr(TInt aIndex)
       
  3486     {
       
  3487     LOGGSMU1("CSmsUserData::InformationElementPtr()");
       
  3488 
       
  3489     return iInformationElementArray[aIndex];
       
  3490     } // CSmsUserData::InformationElementPtr
       
  3491 
       
  3492 
       
  3493 /**
       
  3494  *  Gets the index of an information element.
       
  3495  *  
       
  3496  *  @param aIdentifier An information element Identifier to search for
       
  3497  *  @param aIndex The index within the User Data of the information element (if
       
  3498  *  found). If more than 1 instance of this information element exists, then
       
  3499  *  the 1st instance will be returned.
       
  3500  *  
       
  3501  *  Use InformationELementIndexL to get all elements.
       
  3502  *  @return True if aIdentifier is found in the User Data
       
  3503  *  @capability None
       
  3504  */
       
  3505 EXPORT_C TBool CSmsUserData::InformationElementIndex(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier,TInt& aIndex) const
       
  3506 	{
       
  3507 	LOGGSMU1("CSmsUserData::InformationElementIndex()");
       
  3508 
       
  3509 	TBool found=EFalse;
       
  3510 	TInt count=NumInformationElements();
       
  3511 	for (TInt i=0; (!found) && (i<count); i++)
       
  3512 		if (InformationElement(i).Identifier()==aIdentifier)
       
  3513 			{
       
  3514 			found=ETrue;
       
  3515 			aIndex=i;
       
  3516 			}
       
  3517 	return found;
       
  3518 	} // CSmsUserData::InformationElementIndex
       
  3519 
       
  3520 
       
  3521 /**
       
  3522  *  Gets the last index of an information element.
       
  3523  *  
       
  3524  *  @param aIdentifier An information element Identifier to search for
       
  3525  *  @param aIndex The index within the User Data of the information element (if
       
  3526  *  found). If more than 1 instance of this information element exists, then
       
  3527  *  the last instance will be returned.
       
  3528  *  
       
  3529  *  Use InformationELementIndexL to get all elements.
       
  3530  *  @return True if aIdentifier is found in the User Data
       
  3531  *  @capability None
       
  3532  */
       
  3533 EXPORT_C TBool CSmsUserData::InformationElementLastIndex(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier,TInt& aIndex) const
       
  3534 	{
       
  3535 	LOGGSMU1("CSmsUserData::InformationElementLastIndex()");
       
  3536 
       
  3537 	TBool found=EFalse;
       
  3538 	TInt count=NumInformationElements();
       
  3539 	for (TInt i=count-1; (!found) && (i>=0); i--)
       
  3540 		if (InformationElement(i).Identifier()==aIdentifier)
       
  3541 			{
       
  3542 			found=ETrue;
       
  3543 			aIndex=i;
       
  3544 			}
       
  3545 	return found;
       
  3546 	} // CSmsUserData::InformationElementLastIndex
       
  3547 
       
  3548 
       
  3549 /**
       
  3550  *  @internalComponent
       
  3551  *  
       
  3552  *  Locates every information element of type aIdentifier and
       
  3553  *  stores its location index in the output array aIndices.
       
  3554  *  
       
  3555  *  @param aIdentifer
       
  3556  *  The information element Identifier to search for
       
  3557  *  @param aIndices
       
  3558  *  A collection containing the location index for each information element of this type.
       
  3559  */
       
  3560 void CSmsUserData::InformationElementIndicesL(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier, CArrayFixFlat<TInt>& aIndices) const
       
  3561     {
       
  3562     LOGGSMU1("CSmsUserData::InformationElementIndicesL()");
       
  3563 
       
  3564     aIndices.Reset();
       
  3565     
       
  3566 	TInt count=NumInformationElements();
       
  3567 	for (TInt i=0; i<count; i++)
       
  3568 	    {
       
  3569     	if (InformationElement(i).Identifier()==aIdentifier)
       
  3570             {
       
  3571             aIndices.AppendL(i);
       
  3572             }
       
  3573         }
       
  3574     } // CSmsUserData::InformationElementIndicesL
       
  3575 
       
  3576 
       
  3577 /**
       
  3578  *  Note that whilst a pointer to the aIe is passed as an
       
  3579  *  input argument, the information element is still owned
       
  3580  *  by the calling function, regardless of the return code.
       
  3581  *  @param aInformationElement An EMS Information Element
       
  3582  */
       
  3583 TBool CSmsUserData::EmsInformationElementWillFitL(CEmsInformationElement* aIe,CSmsEMSBufferSegmenter& aSeg,TUint& aCharsAddedToCurrentPDU)
       
  3584 	{
       
  3585 	LOGGSMU1("CSmsUserData::EmsInformationElementWillFitL()");
       
  3586 
       
  3587 	// Before using an EmsInformationElement polymorphically as an SmsIE,
       
  3588 	// we need to make sure that the IE has been encoded
       
  3589 	aIe->EncodeInformationElementL();
       
  3590 	iInformationElementArray.AppendL(aIe);
       
  3591 
       
  3592 	TInt sizeLeft=MaxPackedUDUnitsInBodyRemaining();
       
  3593 	iInformationElementArray.Delete(iInformationElementArray.Count()-1);
       
  3594 	if(sizeLeft==0 && iBody && (iBody->Length() > 0) && (*iBody)[iBody->Length()-1] == KSms7BitAlphabetEscapeChar)
       
  3595 	{
       
  3596 		--aCharsAddedToCurrentPDU;
       
  3597 		--aSeg.iElementsExtracted;
       
  3598 		TPtr8 ptr(iBody->Des());
       
  3599 		ptr.Delete(iBody->Length()-1,1);
       
  3600 		--sizeLeft;
       
  3601 	}
       
  3602 	return sizeLeft>=0;
       
  3603 	} // CSmsUserData::EmsInformationElementWillFitL
       
  3604 
       
  3605 
       
  3606 /**
       
  3607  *  Tests whether the control information element will fit in the current PDU.
       
  3608  *  
       
  3609  *  Note that whilst a pointer to the aIe is passed as an
       
  3610  *  input argument, the information element is still owned
       
  3611  *  by the calling function, regardless of the return code.
       
  3612  *  
       
  3613  *  @param aInformationElement A pointer to an information Element
       
  3614  *  @capability None
       
  3615  */
       
  3616 TBool CSmsUserData::ControlInformationElementWillFitL(CSmsInformationElement* aIe)
       
  3617     {
       
  3618     LOGGSMU1("CSmsUserData::ControlInformationElementWillFitL()");
       
  3619 
       
  3620     if (aIe == NULL)
       
  3621         {
       
  3622         User::Leave(KErrGeneral);
       
  3623         }
       
  3624 
       
  3625     TSmsInformationElementCategories::TInformationElementCategory category;
       
  3626 
       
  3627     if (TSmsInformationElementCategories::GetCategoryDefinition(aIe->Identifier(), category) == EFalse  ||
       
  3628     	category == TSmsInformationElementCategories::EEmsInformationElement)
       
  3629         {
       
  3630         User::Leave(KErrArgument);
       
  3631         }
       
  3632 
       
  3633     iInformationElementArray.AppendL(aIe);
       
  3634 
       
  3635     TInt sizeLeft=MaxPackedUDUnitsInBodyRemaining();
       
  3636     iInformationElementArray.Delete(iInformationElementArray.Count()-1);
       
  3637 
       
  3638     // Not considering whether escape characters exist in the buffer
       
  3639     // as control information elements do not add text to the buffer.
       
  3640 
       
  3641     return sizeLeft>=0;
       
  3642     } // CSmsUserData::ControlInformationElementWillFitL
       
  3643 
       
  3644 
       
  3645 /**
       
  3646  *  Adds an information element.
       
  3647  *  This method can be used to create information elements in the range:
       
  3648  *  00 - 09 - i.e. Control Information Elements
       
  3649  *  It can be used to create information elements in the following ranges
       
  3650  *  (on the assumption that the information element is intended to be encoded into
       
  3651  *  every PDU):
       
  3652  *  24 - 25 - i.e. National Language Encodings
       
  3653  *  70 - 7F - i.e. SIM Tool Kit Security Headers
       
  3654  *  80 - 9F - i.e  SMS to SME specific use
       
  3655  *  C0 - CF - i.e. SC specific use
       
  3656  *  
       
  3657  *  Information elements in the following ranges should not be
       
  3658  *  added using this interface. Instead they should be added using
       
  3659  *  the following identified interfaces:
       
  3660  *  0A-1F - Use the interfaces provided to support EMS Elements
       
  3661  *  20 - Use the interfaces provided for Email in CSmsMessage
       
  3662  *  21 - Use the interface provided by CSmsHyperLinkOperations
       
  3663  *  22 - Use the interface provided by CSmsReplyAddressOperations
       
  3664  *  23 - Use the interface provided by CSmsEnhancedVoiceMailOperations
       
  3665  *  
       
  3666  *  This interface should not be used for information element in the following
       
  3667  *  ranges, these are reserved for future use in TS23.040 V6.5.0 and their
       
  3668  *  characteristics and repeatability have not yet been defined.
       
  3669  *  26-6F
       
  3670  *  A0-BF
       
  3671  *  E0-FF
       
  3672  *  
       
  3673  *  @param aIdentifier An information element Identifier for aData
       
  3674  *  @param aData The information element to add to the User Data
       
  3675  *  @leave
       
  3676  *  KErrNotSupported if the information element is not supported via this interface.
       
  3677  *  @capability None
       
  3678  */
       
  3679 EXPORT_C void CSmsUserData::AddInformationElementL(TSmsId aIdentifier,const TDesC8& aData)
       
  3680     {
       
  3681     LOGGSMU1("CSmsUserData::AddInformationElementL");
       
  3682 
       
  3683     if  ((aIdentifier >= 0x21) && (aIdentifier <= 0x23) ||
       
  3684          (aIdentifier >= 0x26) && (aIdentifier <= 0x6F) ||
       
  3685          (aIdentifier >= 0xA0) && (aIdentifier <= 0xBF) ||
       
  3686          (aIdentifier >= 0xE0) && (aIdentifier <= 0xFF))
       
  3687         {
       
  3688         User::Leave(KErrNotSupported);
       
  3689         }
       
  3690     UpdateInformationElementArrayL(aIdentifier, aData);
       
  3691 
       
  3692     } // CSmsUserData::AddInformationElementL
       
  3693 
       
  3694 
       
  3695 /**
       
  3696  *  @internalComponent
       
  3697  *  
       
  3698  *  Either adds an information element to
       
  3699  *  iInformationElementArray.
       
  3700  *  
       
  3701  *  @param aIdentifier An information element Identifier for aData
       
  3702  *  @param aData The information element to add to the User Data
       
  3703  */
       
  3704 void CSmsUserData::UpdateInformationElementArrayL(TSmsId aIdentifier,const TDesC8& aData)
       
  3705     {
       
  3706     LOGGSMU1("CSmsUserData::UpdateInformationElementsL");
       
  3707 
       
  3708     TInt count=NumInformationElements();
       
  3709     if(!CEmsFactory::Supported(aIdentifier))
       
  3710         {
       
  3711         for (TInt i=0; i<count; i++)
       
  3712             {
       
  3713  	        if (InformationElement(i).Identifier()==aIdentifier)
       
  3714                 {
       
  3715                 TSmsInformationElementCategories::TInformationElementCategory category;
       
  3716                 
       
  3717                 if (TSmsInformationElementCategories::GetCategoryDefinition(aIdentifier, category) == EFalse)
       
  3718                 	{
       
  3719                 	User::Leave(KErrArgument);
       
  3720                 	}
       
  3721 
       
  3722                 switch (category)
       
  3723                     {
       
  3724                     case TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUMultipleInstancesPerPDU:
       
  3725                         {
       
  3726                         if (InformationElement(i).Identifier() == CSmsInformationElement::ESmsIEISpecialSMSMessageIndication)
       
  3727                             {
       
  3728                             LOGGSMU3("CSmsUserData::AddInformationElementL1 category = %d, identifier = %d",category,aIdentifier);
       
  3729 
       
  3730                             //if Msg type is the same, swap with the most recent value
       
  3731                             if ((InformationElement(i).Data()[0] & ((TUint8) EGsmSmsSpecialMessageIndicationTypeMask)) ==
       
  3732                                 (aData[0] & ((TUint8) EGsmSmsSpecialMessageIndicationTypeMask)))
       
  3733                                 {
       
  3734                                 User::Leave(KErrAlreadyExists);
       
  3735                                 }
       
  3736                             }
       
  3737                         else
       
  3738                             {
       
  3739                             LOGGSMU4("CSmsUserData::AddInformationElementL3 category = %d, identifier = %d, data = %S",category,aIdentifier, &aData);
       
  3740                             User::Leave(KErrArgument);
       
  3741                             }
       
  3742                         break;
       
  3743                         }
       
  3744                     case TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUAndWithIdenticalValues:
       
  3745                     case TSmsInformationElementCategories::ECtrlMandatoryIn1stPDUOnly:
       
  3746                     case TSmsInformationElementCategories::ECtrlSingleInstanceOnly:
       
  3747                         {
       
  3748                         LOGGSMU3("CSmsUserData::AddInformationElementL4 category = %d, identifier = %d",category,aIdentifier);
       
  3749                         User::Leave(KErrAlreadyExists);
       
  3750                         break;
       
  3751                         }
       
  3752                     case TSmsInformationElementCategories::ECtrlMultipleInstancesAllowed:
       
  3753                         {
       
  3754                         LOGGSMU3("CSmsUserData::AddInformationElementL5 category = %d, identifier = %d",category,aIdentifier);
       
  3755                         break;
       
  3756                         }
       
  3757                     case TSmsInformationElementCategories::ECtrlMandatoryInEveryPDUButWithValueSpecificToPDU:
       
  3758                         {
       
  3759                         LOGGSMU3("CSmsUserData::AddInformationElementL6 category = %d, identifier = %d",category,aIdentifier);
       
  3760                         User::Leave(KErrAlreadyExists);
       
  3761                         // currently the email header is updated in:
       
  3762                         // void CSmsMessage::DecodeBufferL(CArrayPtr<CSmsPDU>& aSmsPDUArray,CSmsBufferBase& aBuffer)
       
  3763                         break;
       
  3764                         }
       
  3765                     default:
       
  3766                         {
       
  3767                         LOGGSMU3("CSmsUserData::AddInformationElementL8 category = %d, identifier = %d",category,aIdentifier);
       
  3768                         User::Leave(KErrNotSupported);
       
  3769                         break;
       
  3770                         }
       
  3771                     }
       
  3772                 }
       
  3773             }
       
  3774         }
       
  3775 
       
  3776     	CSmsInformationElement* informationElement=CSmsInformationElement::NewL(aIdentifier,aData);
       
  3777     	CleanupStack::PushL(informationElement);
       
  3778     	iInformationElementArray.AppendL(informationElement);
       
  3779     	CleanupStack::Pop();
       
  3780     	SetHeaderPresent(ETrue);
       
  3781     } // CSmsUserData::UpdateInformationElementArrayL
       
  3782 
       
  3783 
       
  3784 void CSmsUserData::AddEmsInformationElementL(CEmsInformationElement* aIe)
       
  3785 	{
       
  3786 	LOGGSMU1("CSmsUserData::AddEmsInformationElementL()");
       
  3787 
       
  3788 	// Before using an EmsInformationElement polymorphically as an SmsIE,
       
  3789 	// we need to make sure that the IE has been encoded
       
  3790 	aIe->EncodeInformationElementL();
       
  3791 	iInformationElementArray.AppendL(aIe);
       
  3792 	SetHeaderPresent(ETrue);
       
  3793 	} // CSmsUserData::AddEmsInformationElementL
       
  3794 
       
  3795 
       
  3796 /**
       
  3797  *  Removes an information element at the specified index.
       
  3798  *  
       
  3799  *  @param aIndex Information element index
       
  3800  *  @capability None
       
  3801  */
       
  3802 EXPORT_C void CSmsUserData::RemoveInformationElement(TInt aIndex)
       
  3803 	{
       
  3804 	LOGGSMU1("CSmsUserData::RemoveInformationElement()");
       
  3805 	// Since iInformationElementArray[aIndex] pointer is removed from iInformationElementArray, there is no double free issue.
       
  3806 	// coverity[double_free]
       
  3807 	delete iInformationElementArray[aIndex];
       
  3808 	iInformationElementArray[aIndex] = NULL;
       
  3809 	iInformationElementArray.Delete(aIndex);
       
  3810 
       
  3811 	if (NumInformationElements()==0)
       
  3812 		{
       
  3813 		SetHeaderPresent(EFalse);
       
  3814 		}
       
  3815 	} // CSmsUserData::RemoveInformationElement
       
  3816 
       
  3817 
       
  3818 TInt CSmsUserData::MaxPackedUDUnitsInBodyRemaining() const
       
  3819 	{
       
  3820 	LOGGSMU1("CSmsUserData::MaxPackedUDUnitsInBodyRemaining()");
       
  3821 
       
  3822 	TInt totalHeaderLengthInUDLUnits=TotalHeaderLengthInUDLUnits();
       
  3823 	TInt maxPackedUDUnitsInBody=0;
       
  3824 	if (iDataCodingScheme.TextCompressed()||(iDataCodingScheme.Alphabet()!=TSmsDataCodingScheme::ESmsAlphabet7Bit))
       
  3825 		{
       
  3826 		maxPackedUDUnitsInBody=KSmsMaxUserDataSize-totalHeaderLengthInUDLUnits;
       
  3827 		if (iDataCodingScheme.Alphabet()==TSmsDataCodingScheme::ESmsAlphabetUCS2)
       
  3828 			{
       
  3829 			// Cannot split unicode character across PDU boundary
       
  3830 			maxPackedUDUnitsInBody&=~1;
       
  3831 			}
       
  3832 		}
       
  3833 	else // 7-bit
       
  3834 		{
       
  3835 		maxPackedUDUnitsInBody=(8*KSmsMaxUserDataSize)/7-totalHeaderLengthInUDLUnits;
       
  3836 		}
       
  3837 
       
  3838 	if (iBody)
       
  3839 		return maxPackedUDUnitsInBody-=iBody->Length();
       
  3840 	return maxPackedUDUnitsInBody;
       
  3841 	} // CSmsUserData::MaxPackedUDUnitsInBodyRemaining
       
  3842 
       
  3843 
       
  3844 TInt CSmsUserData::MaxPackedUDUnitsInBodyRemaining(TUint aIELen) const
       
  3845 	{
       
  3846 	LOGGSMU1("CSmsUserData::MaxPackedUDUnitsInBodyRemaining()");
       
  3847 
       
  3848 	TInt totalHeaderLengthInUDLUnits=TotalHeaderLengthInUDLUnits(aIELen);
       
  3849 	TInt maxPackedUDUnitsInBody=0;
       
  3850 	if (iDataCodingScheme.TextCompressed()||(iDataCodingScheme.Alphabet()!=TSmsDataCodingScheme::ESmsAlphabet7Bit))
       
  3851 		{
       
  3852 		maxPackedUDUnitsInBody=KSmsMaxUserDataSize-totalHeaderLengthInUDLUnits;
       
  3853 		if (iDataCodingScheme.Alphabet()==TSmsDataCodingScheme::ESmsAlphabetUCS2)
       
  3854 			{
       
  3855 			// Cannot split unicode character across PDU boundary
       
  3856 			maxPackedUDUnitsInBody&=~1;
       
  3857 			}
       
  3858 		}
       
  3859 	else // 7-bit
       
  3860 		{
       
  3861 		maxPackedUDUnitsInBody=(8*KSmsMaxUserDataSize)/7-totalHeaderLengthInUDLUnits;
       
  3862 		}
       
  3863 
       
  3864 	if (iBody)
       
  3865 		return maxPackedUDUnitsInBody-=iBody->Length();
       
  3866 	return maxPackedUDUnitsInBody;
       
  3867 	} // CSmsUserData::MaxPackedUDUnitsInBodyRemaining
       
  3868 
       
  3869 
       
  3870 /**
       
  3871  *  @capability None
       
  3872  */
       
  3873 EXPORT_C TInt CSmsUserData::MaxBodyLengthInChars() const
       
  3874 	{
       
  3875 	LOGGSMU1("CSmsUserData::MaxBodyLengthInChars()");
       
  3876 
       
  3877 	TInt totalheaderlengthinudlunits=TotalHeaderLengthInUDLUnits();
       
  3878 	TInt maxbodylengthinchars=0;
       
  3879 	if (iDataCodingScheme.TextCompressed())
       
  3880 		{
       
  3881 		maxbodylengthinchars=KSmsMaxUserDataSize-totalheaderlengthinudlunits;
       
  3882 		}
       
  3883 	else
       
  3884 		{
       
  3885 		switch (iDataCodingScheme.Alphabet())
       
  3886 			{
       
  3887 			case (TSmsDataCodingScheme::ESmsAlphabet7Bit):
       
  3888 				{
       
  3889 				maxbodylengthinchars=(8*KSmsMaxUserDataSize)/7-totalheaderlengthinudlunits;
       
  3890 				break;
       
  3891 				}
       
  3892 			case (TSmsDataCodingScheme::ESmsAlphabet8Bit):
       
  3893 				{
       
  3894 				maxbodylengthinchars=KSmsMaxUserDataSize-totalheaderlengthinudlunits;
       
  3895 				break;
       
  3896 				}
       
  3897 			case (TSmsDataCodingScheme::ESmsAlphabetUCS2):
       
  3898 				{
       
  3899 				maxbodylengthinchars=(KSmsMaxUserDataSize-totalheaderlengthinudlunits)/2;
       
  3900 				break;
       
  3901 				}
       
  3902 			default:
       
  3903                 break;
       
  3904             // TODO - ahe - Never Panic GSMU !!!
       
  3905             // has to be tested, what happens in this default case
       
  3906 				//Panic(KGsmuPanicUnsupportedAlphabet);
       
  3907 			}
       
  3908 		}
       
  3909 	return maxbodylengthinchars;
       
  3910 	} // CSmsUserData::MaxBodyLengthInChars
       
  3911 
       
  3912 
       
  3913 /**
       
  3914  *  Gets the unpacked User Data Elements.
       
  3915  *  
       
  3916  *  @return Unpacked User Data Elements
       
  3917  *  @capability None
       
  3918  */
       
  3919 EXPORT_C TPtrC8 CSmsUserData::Body() const
       
  3920 	{
       
  3921 	LOGGSMU1("CSmsUserData::Body()");
       
  3922 
       
  3923 	return iBody->Des();
       
  3924 	} // CSmsUserData::Body
       
  3925 
       
  3926 
       
  3927 /**
       
  3928  *  Sets the User Data (unpacked).
       
  3929  *  
       
  3930  *  @param aBody Unpacked User Data Elements
       
  3931  *  @capability None
       
  3932  */
       
  3933 EXPORT_C void CSmsUserData::SetBodyL(const TDesC8& aBody)
       
  3934 	{
       
  3935 	LOGGSMU1("CSmsUserData::SetBodyL()");
       
  3936 
       
  3937 	//Some tests fail with this line in, despite it being a valid condition!
       
  3938 	//__ASSERT_DEBUG(aBody.Length() <= MaxBodyLengthInChars(), User::Leave(KErrTooBig));
       
  3939 
       
  3940 	NewBodyL(aBody.Length());
       
  3941 	iBody->Des().Copy(aBody);
       
  3942 	} // CSmsUserData::SetBodyL
       
  3943 
       
  3944 
       
  3945 void CSmsUserData::AppendBodyL(const TDesC8& aBody)
       
  3946 	{
       
  3947 	LOGGSMU1("CSmsUserData::AppendBodyL()");
       
  3948 
       
  3949 	if (iBody)
       
  3950 		{
       
  3951 		//Some tests fail with this line in, despite it being a valid condition!
       
  3952 		//__ASSERT_DEBUG(aBody.Length() + iBody->Length() <= MaxBodyLengthInChars(), User::Leave(KErrTooBig));
       
  3953 
       
  3954 		iBody = iBody->ReAllocL(aBody.Length()+iBody->Length());
       
  3955 		iBody->Des().Append(aBody);
       
  3956 		}
       
  3957 	else
       
  3958 		{
       
  3959 		SetBodyL(aBody);
       
  3960 		}
       
  3961 	} // CSmsUserData::AppendBodyL
       
  3962 
       
  3963 
       
  3964 /**
       
  3965  *  Tests if the character is supported by the current character set.
       
  3966  *  This function can be used with 7bit and 8bit alphabets.
       
  3967  * 
       
  3968  *  @param aChar  Character to investigate.
       
  3969  * 
       
  3970  *  @return  ETrue if the character is supported.
       
  3971  * 
       
  3972  *  @note Since the function is based on the old behaviour (pre-PREQ2090)
       
  3973  *        it does not accept a downgraded character or alternative encoding
       
  3974  *        as being supported.
       
  3975  *
       
  3976  *  @capability None
       
  3977  */
       
  3978 EXPORT_C TBool CSmsUserData::IsSupportedL(TChar aChar)
       
  3979 	{
       
  3980 	LOGGSMU1("CSmsUserData::IsSupportedL()");
       
  3981 
       
  3982 	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(iCharacterSetConverter,iFs,iDataCodingScheme.Alphabet(),IsBinaryData());
       
  3983 	TBool result=converter->IsSupportedL(aChar);
       
  3984 	CleanupStack::PopAndDestroy();
       
  3985 
       
  3986 	return result;
       
  3987 	} // CSmsUserData::IsSupportedL
       
  3988 
       
  3989 
       
  3990 /**
       
  3991  *  Tests if the descriptor text is supported by the current character set.
       
  3992  *  This function can be used with 7bit and 8bit alphabets.
       
  3993  * 
       
  3994  *  @param aDes                                 Text string to check.
       
  3995  *  @param aNumberOfUnconvertibleCharacters     Exit param for the number of
       
  3996  *                                              characters unconvertible.
       
  3997  *  @param aIndexOfFirstUnconvertibleCharacter  Exit param for the first
       
  3998  *                                              unconverted character.
       
  3999  * 
       
  4000  *  @return  ETrue if the character is supported.
       
  4001  *
       
  4002  *  @capability None
       
  4003  */
       
  4004 EXPORT_C TBool CSmsUserData::IsSupportedL(const TDesC& aDes, TInt& aNumberOfUnconvertibleCharacters,
       
  4005                                           TInt& aIndexOfFirstUnconvertibleCharacter) const
       
  4006 	{
       
  4007 	LOGGSMU1("[1] CSmsUserData::IsSupportedL()");
       
  4008 
       
  4009 	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(iCharacterSetConverter,iFs,iDataCodingScheme.Alphabet(),IsBinaryData());
       
  4010 	TBool result=converter->IsSupportedL(aDes, aNumberOfUnconvertibleCharacters,
       
  4011 			                             aIndexOfFirstUnconvertibleCharacter);
       
  4012 	CleanupStack::PopAndDestroy();
       
  4013 
       
  4014 	return result;
       
  4015 	} // CSmsUserData::IsSupportedL
       
  4016 
       
  4017 
       
  4018 /**
       
  4019  *  Tests if the descriptor text is supported by the current character set.
       
  4020  *  This function can be used with 7bit and 8bit alphabets.
       
  4021  * 
       
  4022  *  @param aDes                                 Text string to check.
       
  4023  *  @param aEncoding                            Alternative encoding method.
       
  4024  *  @param aNumberOfUnconvertibleCharacters     Exit param for the number of
       
  4025  *                                              characters unconvertible.
       
  4026  *  @param aNumberOfDowngradedCharacters        Exit param for the number of
       
  4027  *                                              downgraded characters.
       
  4028  *  @param aNumberRequiringAlternativeEncoding  Exit param for the number of
       
  4029  *                                              characters requiring use of
       
  4030  *                                              the alternative encoder.
       
  4031  *  @param aIndexOfFirstUnconvertibleCharacter  Exit param for the first
       
  4032  *                                              unconverted character.
       
  4033  * 
       
  4034  *  @return  ETrue if the character is supported.
       
  4035  *
       
  4036  *  @capability None
       
  4037  */
       
  4038 EXPORT_C TBool CSmsUserData::IsSupportedL(const TDesC& aDes, TSmsEncoding aEncoding,
       
  4039 										  TInt& aNumberOfUnconvertibleCharacters,
       
  4040                                           TInt& aNumberOfDowngradedCharacters,
       
  4041                                           TInt& aNumberRequiringAlternativeEncoding,
       
  4042                                           TInt& aIndexOfFirstUnconvertibleCharacter) const
       
  4043 	{
       
  4044 	LOGGSMU1("[2] CSmsUserData::IsSupportedL()");
       
  4045 
       
  4046 	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(iCharacterSetConverter,iFs,iDataCodingScheme.Alphabet(),IsBinaryData());
       
  4047 	TBool result=converter->IsSupportedL(aDes, aEncoding,
       
  4048 			                             aNumberOfUnconvertibleCharacters,
       
  4049 			                             aNumberOfDowngradedCharacters,
       
  4050 			                             aNumberRequiringAlternativeEncoding,
       
  4051 			                             aIndexOfFirstUnconvertibleCharacter);
       
  4052 	CleanupStack::PopAndDestroy();
       
  4053 
       
  4054 	return result;
       
  4055 	} // CSmsUserData::IsSupportedL
       
  4056 
       
  4057 
       
  4058 TUint8* CSmsUserData::EncodeL(TUint8* aPtr) const
       
  4059 	{
       
  4060 	LOGGSMU1("CSmsUserData::EncodeL()");
       
  4061 
       
  4062 	__ASSERT_DEBUG(0<=MaxPackedUDUnitsInBodyRemaining(),Panic(KGsmuPanicUserDataBodyTooLong));
       
  4063 	// Encode the user data length
       
  4064 	TInt totalHeaderLengthInUDLUnits=TotalHeaderLengthInUDLUnits();
       
  4065 	TSmsOctet userDataLength=totalHeaderLengthInUDLUnits+TSmsOctet(BodyLengthInUDLUnits());
       
  4066 	aPtr=userDataLength.EncodeL(aPtr);
       
  4067 	// Encode any user data header
       
  4068 	if (HeaderPresent())
       
  4069 		{
       
  4070 		TSmsOctet headerLength=HeaderLength();
       
  4071 		aPtr=headerLength.EncodeL(aPtr);
       
  4072 		TInt numInformationElements=NumInformationElements();
       
  4073 		for (TInt i=0; i<numInformationElements; i++)
       
  4074 			aPtr=iInformationElementArray[i]->EncodeL(aPtr);
       
  4075 		}
       
  4076 	// Pack the user data body
       
  4077 	TInt startBit=0;
       
  4078 	if (iDataCodingScheme.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit)
       
  4079 		startBit=(totalHeaderLengthInUDLUnits*7)%8;
       
  4080 	TSmsAlphabetPacker packer(iDataCodingScheme.Alphabet(),IsBinaryData(),startBit);
       
  4081 	TPtr8 ptr((TUint8*)aPtr,0,packer.PackedOctetsRequiredL(Body().Length()));
       
  4082 	aPtr+=packer.PackL(ptr,Body());
       
  4083 	return aPtr;
       
  4084 	} // CSmsUserData::EncodeL
       
  4085 
       
  4086 
       
  4087 void CSmsUserData::DecodeL(TGsmuLex8& aPdu)
       
  4088 	{
       
  4089 	DecodeL(aPdu, EFalse);
       
  4090 	}
       
  4091 
       
  4092 void CSmsUserData::DecodeL(TGsmuLex8& aPdu, TBool aAcceptTruncation)
       
  4093 	{	
       
  4094 	LOGGSMU1("CSmsUserData::DecodeL()");
       
  4095 
       
  4096 	// Reset current data
       
  4097 	iInformationElementArray.ResetAndDestroy();
       
  4098 	// Decode the user data
       
  4099 	TSmsOctet userDataLength;
       
  4100 	userDataLength.DecodeL(aPdu);
       
  4101 	TSmsOctet headerLength;
       
  4102 	// Decode any user data header
       
  4103 	TBool headerPresent=HeaderPresent();
       
  4104 	/*
       
  4105 	if (headerPresent || IsHeaderPresent(aPtr,dataLength))
       
  4106 	*/
       
  4107 	if (headerPresent)
       
  4108 		{
       
  4109 		headerLength.DecodeL(aPdu);
       
  4110 		if ((1+headerLength)>KSmsMaxUserDataSize)
       
  4111 			User::Leave(KErrGsmSMSTpduNotSupported);
       
  4112 		while (HeaderLength()<headerLength)
       
  4113 			{
       
  4114 			CSmsInformationElement* informationelement=CSmsInformationElement::NewL();
       
  4115 			CleanupStack::PushL(informationelement);
       
  4116 			informationelement->DecodeL(aPdu);
       
  4117 			iInformationElementArray.AppendL(informationelement);
       
  4118 			CleanupStack::Pop(informationelement);
       
  4119 			}
       
  4120 		if (HeaderLength()!=headerLength)
       
  4121 			User::Leave(KErrGsmSMSTpduNotSupported);
       
  4122 		}
       
  4123 	// Decode the body - make sure we have enough buffer
       
  4124 	TInt headerLengthInUDLUnits=TotalHeaderLengthInUDLUnits();
       
  4125 	TInt bodyLengthInUDLUnits=userDataLength-headerLengthInUDLUnits;
       
  4126 
       
  4127 	if(bodyLengthInUDLUnits <=0)
       
  4128 	{
       
  4129 		NewBodyL(0);
       
  4130 		return;
       
  4131 	}
       
  4132 
       
  4133 	NewBodyL(bodyLengthInUDLUnits);
       
  4134 
       
  4135 	// Unpack the body
       
  4136 	TInt startBit=0;
       
  4137 	if (iDataCodingScheme.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit)
       
  4138 		startBit=(headerLengthInUDLUnits*7)%8;
       
  4139 	TSmsAlphabetPacker unpacker(iDataCodingScheme.Alphabet(),IsBinaryData(),startBit);
       
  4140 	TInt bodyLengthInOctets=unpacker.PackedOctetsRequiredL(bodyLengthInUDLUnits);
       
  4141 	TPtr8 destPtr((TUint8*)iBody->Des().Ptr(),0,bodyLengthInUDLUnits);
       
  4142 
       
  4143 	const TPtrC8 sourcePtr(aPdu.NextWithNoIncL(bodyLengthInOctets,aAcceptTruncation));
       
  4144 	if ( aAcceptTruncation && sourcePtr.Length() < bodyLengthInOctets)
       
  4145 		{
       
  4146 		// field was truncated in an acceptable situation (User Data in Status Report PDU)
       
  4147 		bodyLengthInUDLUnits = unpacker.NumUDUnitsL(sourcePtr.Length());
       
  4148 		}
       
  4149 	unpacker.UnpackL(sourcePtr,destPtr,bodyLengthInUDLUnits);
       
  4150 
       
  4151 	//@note No need to call aPdu.IncL() because CSmsUserData is always at the end of a PDU
       
  4152 	} // CSmsUserData::DecodeL
       
  4153 
       
  4154 
       
  4155 void CSmsUserData::InternalizeL(RReadStream& aStream)
       
  4156 	{
       
  4157 	iInformationElementArray.ResetAndDestroy();
       
  4158 	TInt numiformationelements=aStream.ReadInt32L();
       
  4159 	// The "header present" flag must mirror whether information elements are present, and
       
  4160 	// the parental iFirstOctet should already be set by its InternalizeL()
       
  4161 	__ASSERT_DEBUG(((!HeaderPresent() && numiformationelements == 0) || (HeaderPresent() && numiformationelements > 0)), Panic(KGsmuPanicInformationElementIndexOutOfRange));
       
  4162 	for (TInt i=0; i<numiformationelements; i++)
       
  4163 		{
       
  4164 		CSmsInformationElement* informationelement=CSmsInformationElement::NewL();
       
  4165 		CleanupStack::PushL(informationelement);
       
  4166 		aStream >> *informationelement;
       
  4167 		iInformationElementArray.AppendL(informationelement);
       
  4168 		CleanupStack::Pop();
       
  4169 		}
       
  4170 	delete iBody;
       
  4171 	iBody=NULL;
       
  4172 	iBody=HBufC8::NewL(aStream,KSmsMaxUserDataLengthInChars);
       
  4173 	} // CSmsUserData::InternalizeL
       
  4174 
       
  4175 
       
  4176 void CSmsUserData::ExternalizeL(RWriteStream& aStream) const
       
  4177 	{
       
  4178 	TInt numiformationelements=iInformationElementArray.Count();
       
  4179 	aStream.WriteInt32L(numiformationelements);
       
  4180 	for (TInt i=0; i<numiformationelements; i++)
       
  4181 		aStream << *iInformationElementArray[i];
       
  4182 	aStream << *iBody;
       
  4183 	} // CSmsUserData::ExternalizeL
       
  4184 
       
  4185 
       
  4186 CSmsUserData::CSmsUserData(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs,TSmsFirstOctet& aFirstOctet,const TSmsDataCodingScheme& aDataCodingScheme):
       
  4187     iCharacterSetConverter(aCharacterSetConverter),
       
  4188     iFs(aFs),
       
  4189     iFirstOctet(aFirstOctet),
       
  4190     iDataCodingScheme(aDataCodingScheme),
       
  4191     iInformationElementArray(8)
       
  4192     {
       
  4193     } // CSmsUserData::CSmsUserData
       
  4194 
       
  4195 
       
  4196 void CSmsUserData::ConstructL()
       
  4197 	{
       
  4198 	LOGGSMU1("CSmsUserData::ConstructL()");
       
  4199 
       
  4200 	NewBodyL(0);
       
  4201 	} // CSmsUserData::ConstructL
       
  4202 
       
  4203 
       
  4204 /**
       
  4205  *  Duplicates this CSmsUserData object.
       
  4206  * 
       
  4207  *  @return  Pointer to the newly created CSmsUserData object.
       
  4208  */
       
  4209 CSmsUserData* CSmsUserData::DuplicateL(TSmsFirstOctet& aFirstOctet,
       
  4210 									   const TSmsDataCodingScheme& aDataCodingScheme) const
       
  4211 	{
       
  4212 	LOGGSMU1("CSmsUserData::DuplicateL()");
       
  4213 
       
  4214 	CSmsUserData*  userdata = CSmsUserData::NewL(iCharacterSetConverter, iFs,
       
  4215 	                                             aFirstOctet, aDataCodingScheme);
       
  4216 	CleanupStack::PushL(userdata);
       
  4217 
       
  4218 	userdata->SetBodyL(Body());
       
  4219 
       
  4220 	for (TInt ie = 0;  ie < iInformationElementArray.Count();  ie++)
       
  4221 		{
       
  4222 		CSmsInformationElement*  oldIE = iInformationElementArray[ie];
       
  4223 
       
  4224 		if (CEmsFactory::Supported(oldIE->Identifier()))
       
  4225 			{
       
  4226 			CEmsInformationElement*  newIE = static_cast<CEmsInformationElement*>(oldIE)->DuplicateL();
       
  4227 			
       
  4228 			CleanupStack::PushL(newIE);
       
  4229 			userdata->AddEmsInformationElementL(newIE);
       
  4230 			CleanupStack::Pop(newIE);
       
  4231 			}
       
  4232 		else
       
  4233 			{
       
  4234 			userdata->UpdateInformationElementArrayL(oldIE->Identifier(), oldIE->Data());
       
  4235 			}
       
  4236 		}
       
  4237 
       
  4238 	CleanupStack::Pop();
       
  4239 
       
  4240 	return userdata;
       
  4241 	} // CSmsUserData::DuplicateL
       
  4242 
       
  4243 
       
  4244 TInt CSmsUserData::HeaderLength() const
       
  4245 	{
       
  4246 	LOGGSMU1("CSmsUserData::HeaderLength()");
       
  4247 
       
  4248 	TInt numinformationelements=NumInformationElements();
       
  4249 	TInt headerlength=0;
       
  4250 	for (TInt i=0; i<numinformationelements; i++)
       
  4251 		headerlength+=iInformationElementArray[i]->Length();
       
  4252 	return headerlength;
       
  4253 	} // CSmsUserData::HeaderLength
       
  4254 
       
  4255 
       
  4256 TInt CSmsUserData::TotalHeaderLengthInUDLUnits() const
       
  4257 	{
       
  4258 	LOGGSMU1("CSmsUserData::TotalHeaderLengthInUDLUnits()");
       
  4259 
       
  4260 	TInt totalheaderlengthinudlunits=0;
       
  4261 	if (iInformationElementArray.Count()>0)
       
  4262 		{
       
  4263 		TInt totalheaderlength=1+HeaderLength();
       
  4264 		if (iDataCodingScheme.TextCompressed())
       
  4265 			{
       
  4266 			totalheaderlengthinudlunits=totalheaderlength;
       
  4267 			}
       
  4268 		else
       
  4269 			{
       
  4270 			switch(iDataCodingScheme.Alphabet())
       
  4271 				{
       
  4272 				case (TSmsDataCodingScheme::ESmsAlphabet7Bit):
       
  4273 					{
       
  4274 					totalheaderlengthinudlunits=((8*totalheaderlength)+6)/7; //  Rounds up
       
  4275 					break;
       
  4276 					}
       
  4277 				case (TSmsDataCodingScheme::ESmsAlphabet8Bit):
       
  4278 				case (TSmsDataCodingScheme::ESmsAlphabetUCS2):
       
  4279 					{
       
  4280 					totalheaderlengthinudlunits=totalheaderlength;
       
  4281 					break;
       
  4282 					}
       
  4283 				default:
       
  4284                     break;
       
  4285                 // TODO - ahe - Never Panic GSMU !!!
       
  4286                 // has to be tested, what happens in this default case
       
  4287 					//Panic(KGsmuPanicUnsupportedAlphabet);
       
  4288 				}
       
  4289 			}
       
  4290 		}
       
  4291 	return totalheaderlengthinudlunits;
       
  4292 	} // CSmsUserData::TotalHeaderLengthInUDLUnits
       
  4293 
       
  4294 
       
  4295 TInt CSmsUserData::TotalHeaderLengthInUDLUnits(TInt aIElen) const
       
  4296 	{
       
  4297 	LOGGSMU1("CSmsUserData::TotalHeaderLengthInUDLUnits()");
       
  4298 
       
  4299 		TInt totalheaderlengthinudlunits=0;
       
  4300 		TInt totalheaderlength=aIElen;
       
  4301 
       
  4302 		if (iInformationElementArray.Count()>0)
       
  4303 			totalheaderlength+=HeaderLength();
       
  4304 
       
  4305 		if(totalheaderlength)totalheaderlength+=1; //UDHL
       
  4306 
       
  4307 		if (iDataCodingScheme.TextCompressed())
       
  4308 			{
       
  4309 			totalheaderlengthinudlunits=totalheaderlength;
       
  4310 			}
       
  4311 		else
       
  4312 			{
       
  4313 			switch(iDataCodingScheme.Alphabet())
       
  4314 				{
       
  4315 				case (TSmsDataCodingScheme::ESmsAlphabet7Bit):
       
  4316 					{
       
  4317 					totalheaderlengthinudlunits=((8*totalheaderlength)+6)/7; //  Rounds up
       
  4318 					break;
       
  4319 					}
       
  4320 				case (TSmsDataCodingScheme::ESmsAlphabet8Bit):
       
  4321 				case (TSmsDataCodingScheme::ESmsAlphabetUCS2):
       
  4322 					{
       
  4323 					totalheaderlengthinudlunits=totalheaderlength;
       
  4324 					break;
       
  4325 					}
       
  4326 				default:
       
  4327                     break;
       
  4328 				}
       
  4329 			}
       
  4330 		return totalheaderlengthinudlunits;
       
  4331 	} // CSmsUserData::TotalHeaderLengthInUDLUnits
       
  4332 
       
  4333 
       
  4334 TInt CSmsUserData::BodyLengthInUDLUnits() const
       
  4335 	{
       
  4336 	LOGGSMU1("CSmsUserData::BodyLengthInUDLUnits()");
       
  4337 
       
  4338 	return iBody->Des().Length();
       
  4339 	} // CSmsUserData::BodyLengthInUDLUnits
       
  4340 
       
  4341 
       
  4342 void CSmsUserData::NewBodyL(TInt aLength)
       
  4343 	{
       
  4344 	LOGGSMU1("CSmsUserData::NewBodyL()");
       
  4345 
       
  4346 
       
  4347 		HBufC8* body=HBufC8::NewL(aLength);
       
  4348 		delete iBody;
       
  4349 		iBody=body;
       
  4350 		iBody->Des().SetLength(aLength);
       
  4351 
       
  4352 	} // CSmsUserData::NewBodyL
       
  4353 
       
  4354 
       
  4355 TBool CSmsUserData::HeaderPresent() const
       
  4356 	{
       
  4357 	LOGGSMU1("CSmsUserData::HeaderPresent()");
       
  4358 
       
  4359 	return (iFirstOctet&TSmsFirstOctet::ESmsUDHIMask)==TSmsFirstOctet::ESmsUDHIHeaderPresent;
       
  4360 	} // CSmsUserData::HeaderPresent
       
  4361 
       
  4362 
       
  4363 void CSmsUserData::SetHeaderPresent(TBool aHeaderPresent)
       
  4364 	{
       
  4365 	LOGGSMU1("CSmsUserData::SetHeaderPresent()");
       
  4366 
       
  4367 	iFirstOctet=aHeaderPresent? (iFirstOctet&(~TSmsFirstOctet::ESmsUDHIMask))|TSmsFirstOctet::ESmsUDHIHeaderPresent: (iFirstOctet&(~TSmsFirstOctet::ESmsUDHIMask))|TSmsFirstOctet::ESmsUDHIHeaderNotPresent;
       
  4368 	} // CSmsUserData::SetHeaderPresent
       
  4369 
       
  4370 
       
  4371 TBool CSmsUserData::IsBinaryData() const
       
  4372 	{
       
  4373 	LOGGSMU1("CSmsUserData::IsBinaryData()");
       
  4374 
       
  4375 	TInt index=0;
       
  4376 	return (iDataCodingScheme.TextCompressed()) ||
       
  4377 			((iDataCodingScheme.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet8Bit) &&
       
  4378 			(InformationElementIndex(CSmsInformationElement::ESmsIEIApplicationPortAddressing8Bit,index) ||
       
  4379 	        InformationElementIndex(CSmsInformationElement::ESmsIEIApplicationPortAddressing16Bit,index)));
       
  4380 	} // CSmsUserData::IsBinaryData
       
  4381 
       
  4382 
       
  4383 /**
       
  4384  *  Converts type of number and numbering plan identification information
       
  4385  *  from the type of address parameter to the NMobilePhone::TMobileTON
       
  4386  *  and NMobilePhone::TMobileNPI format.
       
  4387  *  
       
  4388  *  @return aTon The number type
       
  4389  *  @return aNpi The numbering plan
       
  4390  *  
       
  4391  *  @capability None
       
  4392  */
       
  4393 EXPORT_C void TGsmSmsTypeOfAddress::ConvertToETelMM(NMobilePhone::TMobileTON& aTon,NMobilePhone::TMobileNPI& aNpi) const
       
  4394     {
       
  4395     LOGGSMU1("TGsmSmsTypeOfAddress::ConvertToETelMM()");
       
  4396 
       
  4397     switch (TON())
       
  4398     {
       
  4399 		case EGsmSmsTONInternationalNumber:
       
  4400             {
       
  4401             aTon = (NMobilePhone::EInternationalNumber);
       
  4402             break;
       
  4403             }
       
  4404         case EGsmSmsTONNationalNumber:
       
  4405             {
       
  4406             aTon = (NMobilePhone::ENationalNumber);
       
  4407             break;
       
  4408             }
       
  4409         case EGsmSmsTONNetworkSpecificNumber:
       
  4410             {
       
  4411             aTon = (NMobilePhone::ENetworkSpecificNumber);
       
  4412             break;
       
  4413             }
       
  4414         case EGsmSmsTONSubscriberNumber:
       
  4415             {
       
  4416             aTon = (NMobilePhone::ESubscriberNumber);
       
  4417             break;
       
  4418             }
       
  4419         case EGsmSmsTONAlphaNumeric:
       
  4420             {
       
  4421             aTon = (NMobilePhone::EAlphanumericNumber);
       
  4422             break;
       
  4423             }
       
  4424         case EGsmSmsTONAbbreviatedNumber:
       
  4425             {
       
  4426             aTon = (NMobilePhone::EAbbreviatedNumber);
       
  4427             break;
       
  4428             }
       
  4429 
       
  4430         default:
       
  4431             {
       
  4432             aTon = (NMobilePhone::EUnknownNumber);
       
  4433             break;
       
  4434             }
       
  4435 		}
       
  4436 
       
  4437     switch (NPI())
       
  4438 		{
       
  4439         case EGsmSmsNPIISDNTelephoneNumberingPlan:
       
  4440             {
       
  4441             aNpi = (NMobilePhone::EIsdnNumberPlan);
       
  4442             break;
       
  4443             }
       
  4444         case EGsmSmsNPIDataNumberingPlan:
       
  4445             {
       
  4446             aNpi = (NMobilePhone::EDataNumberPlan);
       
  4447             break;
       
  4448             }
       
  4449         case EGsmSmsNPITelexNumberingPlan:
       
  4450             {
       
  4451             aNpi = (NMobilePhone::ETelexNumberPlan);
       
  4452             break;
       
  4453             }
       
  4454         case EGsmSmsNPINationalNumberingPlan:
       
  4455             {
       
  4456             aNpi = (NMobilePhone::ENationalNumberPlan);
       
  4457             break;
       
  4458             }
       
  4459         case EGsmSmsNPIPrivateNumberingPlan:
       
  4460             {
       
  4461             aNpi = (NMobilePhone::EPrivateNumberPlan);
       
  4462             break;
       
  4463             }
       
  4464         case EGsmSmsNPIERMESNumberingPlan:
       
  4465             {
       
  4466             aNpi = (NMobilePhone::EERMESNumberPlan);
       
  4467             break;
       
  4468             }
       
  4469 
       
  4470         default:
       
  4471             {
       
  4472             aNpi = (NMobilePhone::EUnknownNumberingPlan);
       
  4473             break;
       
  4474             }
       
  4475 		}
       
  4476 	} // NMobilePhone::TMobileNPI
       
  4477 
       
  4478 
       
  4479 /**
       
  4480  *  Converts type of number and numbering plan identification information
       
  4481  *  from the NMobilePhone::TMobileTON and NMobilePhone::TMobileNPI format
       
  4482  *  to the type of address parameter.
       
  4483  *  
       
  4484  *  @param aTon The number type
       
  4485  *  @param aNpi The numbering plan
       
  4486  *  
       
  4487  *  @capability None
       
  4488  */
       
  4489 EXPORT_C void TGsmSmsTypeOfAddress::SetFromETelMM(NMobilePhone::TMobileTON aTon,NMobilePhone::TMobileNPI aNpi)
       
  4490     {
       
  4491     LOGGSMU1("TGsmSmsTypeOfAddress::SetFromETelMM()");
       
  4492 
       
  4493     switch (aTon)
       
  4494     {
       
  4495 		case NMobilePhone::EInternationalNumber:
       
  4496             {
       
  4497             SetTON( EGsmSmsTONInternationalNumber );
       
  4498             break;
       
  4499             }
       
  4500         case NMobilePhone::ENationalNumber:
       
  4501             {
       
  4502             SetTON( EGsmSmsTONNationalNumber );
       
  4503             break;
       
  4504             }
       
  4505         case NMobilePhone::ENetworkSpecificNumber:
       
  4506             {
       
  4507             SetTON( EGsmSmsTONNetworkSpecificNumber );
       
  4508             break;
       
  4509             }
       
  4510         case NMobilePhone::ESubscriberNumber:
       
  4511             {
       
  4512             SetTON( EGsmSmsTONSubscriberNumber );
       
  4513             break;
       
  4514             }
       
  4515         case NMobilePhone::EAlphanumericNumber:
       
  4516             {
       
  4517             SetTON( EGsmSmsTONAlphaNumeric );
       
  4518             break;
       
  4519             }
       
  4520         case NMobilePhone::EAbbreviatedNumber:
       
  4521             {
       
  4522             SetTON( EGsmSmsTONAbbreviatedNumber );
       
  4523             break;
       
  4524             }
       
  4525 
       
  4526         default:
       
  4527             {
       
  4528             SetTON( EGsmSmsTONUnknown );
       
  4529             break;
       
  4530             }
       
  4531 		}
       
  4532 
       
  4533     switch (aNpi)
       
  4534 		{
       
  4535         case NMobilePhone::EIsdnNumberPlan:
       
  4536             {
       
  4537             SetNPI( EGsmSmsNPIISDNTelephoneNumberingPlan );
       
  4538             break;
       
  4539             }
       
  4540         case NMobilePhone::EDataNumberPlan:
       
  4541             {
       
  4542             SetNPI( EGsmSmsNPIDataNumberingPlan );
       
  4543             break;
       
  4544             }
       
  4545         case NMobilePhone::ETelexNumberPlan:
       
  4546             {
       
  4547             SetNPI( EGsmSmsNPITelexNumberingPlan );
       
  4548             break;
       
  4549             }
       
  4550         case NMobilePhone::ENationalNumberPlan:
       
  4551             {
       
  4552             SetNPI( EGsmSmsNPINationalNumberingPlan );
       
  4553             break;
       
  4554             }
       
  4555         case NMobilePhone::EPrivateNumberPlan:
       
  4556             {
       
  4557             SetNPI( EGsmSmsNPIPrivateNumberingPlan );
       
  4558             break;
       
  4559             }
       
  4560         case NMobilePhone::EERMESNumberPlan:
       
  4561             {
       
  4562             SetNPI( EGsmSmsNPIERMESNumberingPlan );
       
  4563             break;
       
  4564             }
       
  4565 
       
  4566         default:
       
  4567             {
       
  4568             SetNPI( EGsmSmsNPIUnknown );
       
  4569             break;
       
  4570             }
       
  4571 		}
       
  4572 	} // NMobilePhone::TMobileTON
       
  4573 
       
  4574 
       
  4575 /**
       
  4576  *  @publishedAll
       
  4577  *  
       
  4578  *  Indicates whether this message is a Voice Mail Notification
       
  4579  *  or a Voice Mail Deletion Confirmation.
       
  4580  *  
       
  4581  *  @return
       
  4582  *  TVoiceMailInfoType, indicating whether this message is a Voice Mail
       
  4583  *  Notification or a Voice Mail Deletion Confirmation.
       
  4584  *  
       
  4585  *  @capability None
       
  4586  */
       
  4587 EXPORT_C TVoiceMailInfoType CEnhancedVoiceMailBoxInformation::Type() const
       
  4588 	{
       
  4589 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::Type()");
       
  4590 
       
  4591 	return iType;
       
  4592 	} // CEnhancedVoiceMailBoxInformation::Type
       
  4593 
       
  4594 
       
  4595 /**
       
  4596  *  @publishedAll
       
  4597  *  
       
  4598  *  Sets the subscriber profile per 23.040 v6.5 Section 9.2.3.24.13.1.
       
  4599  *  
       
  4600  *  @param aProfile
       
  4601  *  The required subscriber profile
       
  4602  *  
       
  4603  *  @capability None
       
  4604  */
       
  4605 EXPORT_C void CEnhancedVoiceMailBoxInformation::SetProfile(TSmsMessageProfileType aProfile)
       
  4606 	{
       
  4607 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetProfile()");
       
  4608 
       
  4609 	iProfile = aProfile;
       
  4610 	} // CEnhancedVoiceMailBoxInformation::SetProfile
       
  4611 
       
  4612 
       
  4613 /**
       
  4614  *  @publishedAll
       
  4615  *  
       
  4616  *  Gets the subscriber profile per 23.040 v6.5 Section 9.2.3.24.13.1.
       
  4617  *  
       
  4618  *  @param aProfile
       
  4619  *  The current subscriber profile
       
  4620  *  
       
  4621  *  @capability None
       
  4622  */
       
  4623 EXPORT_C TSmsMessageProfileType CEnhancedVoiceMailBoxInformation::Profile() const
       
  4624 	{
       
  4625 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::Profile()");
       
  4626 
       
  4627 	return iProfile;
       
  4628 	} // CEnhancedVoiceMailBoxInformation::Profile
       
  4629 
       
  4630 
       
  4631 /**
       
  4632  *  @publishedAll
       
  4633  *  
       
  4634  *  Configures the storage directive
       
  4635  *  
       
  4636  *  @param aIsStored
       
  4637  *  Set to True if the SM is to be stored in the ME or USIM,
       
  4638  *  False is the SM is to be discarded.
       
  4639  *  
       
  4640  *  @capability None
       
  4641  */
       
  4642 EXPORT_C void CEnhancedVoiceMailBoxInformation::SetStorage(TBool aIsStored)
       
  4643 	{
       
  4644 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetStorage()");
       
  4645 
       
  4646 	iStorage = aIsStored;
       
  4647 	} // CEnhancedVoiceMailBoxInformation::SetStorage
       
  4648 
       
  4649 
       
  4650 /**
       
  4651  *  @publishedAll
       
  4652  *  
       
  4653  *  Indicates whether the SM is to be stored or discarded
       
  4654  *  
       
  4655  *  @return
       
  4656  *  True if the SM is to be stored in the ME or USIM,
       
  4657  *  False is the SM is to be discarded.
       
  4658  *  
       
  4659  *  @capability None
       
  4660  */
       
  4661 EXPORT_C TBool CEnhancedVoiceMailBoxInformation::Store() const
       
  4662 	{
       
  4663 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::Store()");
       
  4664 
       
  4665 	return iStorage;
       
  4666 	} // CEnhancedVoiceMailBoxInformation::Store
       
  4667 
       
  4668 
       
  4669 /**
       
  4670  *  @publishedAll
       
  4671  *  
       
  4672  *  Used to set or reset the voice mail status to almost full.
       
  4673  *  
       
  4674  *  @param aIsStored
       
  4675  *  Set to True the voice mail system is almost full.
       
  4676  *  Set to False otherwise.
       
  4677  *  
       
  4678  *  @capability None
       
  4679  */
       
  4680 EXPORT_C void CEnhancedVoiceMailBoxInformation::SetAlmostMaximumCapacity(TBool aIsAlmostFull)
       
  4681 	{
       
  4682 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetAlmostMaximumCapacity()");
       
  4683 
       
  4684 	iAlmostFull = aIsAlmostFull;
       
  4685 	} // CEnhancedVoiceMailBoxInformation::SetAlmostMaximumCapacity
       
  4686 
       
  4687 
       
  4688 /**
       
  4689  *  @publishedAll
       
  4690  *  
       
  4691  *  Indicates whether the voice mail system is almost at full capacity.
       
  4692  *  
       
  4693  *  @return
       
  4694  *  True, if the voice mail system is almost full.
       
  4695  *  False otherwise.
       
  4696  *  
       
  4697  *  @capability None
       
  4698  */
       
  4699 EXPORT_C TBool CEnhancedVoiceMailBoxInformation::AlmostMaximumCapacity() const
       
  4700 	{
       
  4701 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::AlmostMaximumCapacity()");
       
  4702 
       
  4703 	return iAlmostFull;
       
  4704 	} // CEnhancedVoiceMailBoxInformation::AlmostMaximumCapacity
       
  4705 
       
  4706 
       
  4707 /**
       
  4708  *  @publishedAll
       
  4709  *  
       
  4710  *  Used to set or reset the voice mail status to full.
       
  4711  *  
       
  4712  *  @param aIsStored
       
  4713  *  Set to True the voice mail system is full.
       
  4714  *  Set to False otherwise.
       
  4715  *  
       
  4716  *  @capability None
       
  4717  */
       
  4718 EXPORT_C void CEnhancedVoiceMailBoxInformation::SetMaximumCapacity(TBool aIsFull)
       
  4719 	{
       
  4720 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetMaximumCapacity()");
       
  4721 
       
  4722 	iFull = aIsFull;
       
  4723 	} // CEnhancedVoiceMailBoxInformation::SetMaximumCapacity
       
  4724 
       
  4725 
       
  4726 /**
       
  4727  *  @publishedAll
       
  4728  *  
       
  4729  *  Indicates whether the voice mail status is full.
       
  4730  *  
       
  4731  *  @return
       
  4732  *  True if the voice mail system is almost full.
       
  4733  *  False otherwise.
       
  4734  *  
       
  4735  *  @capability None
       
  4736  */
       
  4737 EXPORT_C TBool CEnhancedVoiceMailBoxInformation::MaximumCapacity() const
       
  4738 	{
       
  4739 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::MaximumCapacity()");
       
  4740 
       
  4741 	return iFull;
       
  4742 	} // CEnhancedVoiceMailBoxInformation::MaximumCapacity
       
  4743 
       
  4744 
       
  4745 /**
       
  4746  *  @publishedAll
       
  4747  *  
       
  4748  *  Indicates whether the message contains extension bytes
       
  4749  *  
       
  4750  *  @return
       
  4751  *  True if the message contains extension bytes.
       
  4752  *  False otherwise.
       
  4753  *  
       
  4754  *  @capability None
       
  4755  */
       
  4756 EXPORT_C TBool CEnhancedVoiceMailBoxInformation::ExtensionIndicator() const
       
  4757 	{
       
  4758 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::ExtensionIndicator()");
       
  4759 
       
  4760 	return iExtensionIndicator;
       
  4761 	} // CEnhancedVoiceMailBoxInformation::ExtensionIndicator
       
  4762 
       
  4763 
       
  4764 void CEnhancedVoiceMailBoxInformation::NewBufferL(TInt aLength)
       
  4765 	{
       
  4766 	LOGGSMU2("CEnhancedVoiceMailBoxInformation::NewBufferL, length = %d",aLength);
       
  4767 
       
  4768 	HBufC* buffer=HBufC::NewL(aLength);
       
  4769 	delete iAccessAddress;
       
  4770 	iAccessAddress=buffer;
       
  4771 	iAccessAddress->Des().SetLength(aLength);
       
  4772 	iAccessAddress->Des().FillZ();
       
  4773 	} // CEnhancedVoiceMailBoxInformation::NewBufferL
       
  4774 
       
  4775 
       
  4776 /**
       
  4777  *  @publishedAll
       
  4778  *  
       
  4779  *  Used to set the voice mail box number, overwriting any pre-existing number.
       
  4780  *  
       
  4781  *  @param aAddress
       
  4782  *  The voice mail box address.
       
  4783  *  
       
  4784  *  @capability None
       
  4785  */
       
  4786 EXPORT_C void  CEnhancedVoiceMailBoxInformation::SetAccessAddressL(const TDesC& aAddress)
       
  4787 	{
       
  4788 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetAccessAddressL()");
       
  4789 
       
  4790 	TInt length=aAddress.Length();
       
  4791 	NewBufferL(length);
       
  4792 	iAccessAddress->Des().Copy(aAddress);
       
  4793 
       
  4794 	const TGsmSmsTypeOfNumber typeofnumber=length && (iAccessAddress->Des()[0]=='+')? EGsmSmsTONInternationalNumber: EGsmSmsTONUnknown;
       
  4795 	iTypeOfAddress.SetTON(typeofnumber);
       
  4796 	} // CEnhancedVoiceMailBoxInformation::SetAccessAddressL
       
  4797 
       
  4798 
       
  4799 /**
       
  4800  *  @publishedAll
       
  4801  *  
       
  4802  *  Retrieves the voice mail box number.
       
  4803  *  
       
  4804  *  @return
       
  4805  *  A pointer to the voice mail box number.
       
  4806  *  
       
  4807  *  @capability None
       
  4808  */
       
  4809 EXPORT_C TPtrC CEnhancedVoiceMailBoxInformation::AccessAddress() const
       
  4810 	{
       
  4811 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::AccessAddress()");
       
  4812 
       
  4813 	TPtrC ptr;
       
  4814 	if (iAccessAddress)
       
  4815 	    ptr.Set(iAccessAddress->Des());
       
  4816 	return ptr;
       
  4817 	} // CEnhancedVoiceMailBoxInformation::AccessAddress
       
  4818 
       
  4819 
       
  4820 /**
       
  4821  *  @publishedAll
       
  4822  *  
       
  4823  *  Used to set the voice mail box number as a parsed address
       
  4824  *  
       
  4825  *  @param aParsedAddress
       
  4826  *  The parsed address to be used as the voice mail box number.
       
  4827  *  
       
  4828  *  @capability None
       
  4829  */
       
  4830 EXPORT_C void  CEnhancedVoiceMailBoxInformation::SetParsedAccessAddressL(const TGsmSmsTelNumber& aParsedAddress)
       
  4831 	{
       
  4832 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetParsedAccessAddressL()");
       
  4833 
       
  4834    	iTypeOfAddress=aParsedAddress.iTypeOfAddress;
       
  4835 	DoSetParsedAddressL(aParsedAddress.iTelNumber);
       
  4836 	} // CEnhancedVoiceMailBoxInformation::SetParsedAccessAddressL
       
  4837 
       
  4838 
       
  4839 /**
       
  4840  *  @publishedAll
       
  4841  *  
       
  4842  *  Used to get the voice mail box number as a parsed address.
       
  4843  *  
       
  4844  *  @param aParsedAddress
       
  4845  *  An output parameter which is set to the parsed address.
       
  4846  *  
       
  4847  *  @capability None
       
  4848  */
       
  4849 EXPORT_C void  CEnhancedVoiceMailBoxInformation::ParsedAccessAddress(TGsmSmsTelNumber& aParsedAddress) const
       
  4850 	{
       
  4851 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::ParsedAccessAddress()");
       
  4852 
       
  4853 	aParsedAddress.iTypeOfAddress = iTypeOfAddress;
       
  4854 
       
  4855 	TInt maxparsedlength=aParsedAddress.iTelNumber.MaxLength();
       
  4856 
       
  4857 	if (iTypeOfAddress.TON()==EGsmSmsTONAlphaNumeric)
       
  4858 		{
       
  4859 		TInt parsedlength=AccessAddress().Length();
       
  4860 		if (parsedlength>maxparsedlength)
       
  4861 			parsedlength=maxparsedlength;
       
  4862 		aParsedAddress.iTelNumber.Copy(AccessAddress().Mid(0,parsedlength));
       
  4863 		}
       
  4864 	else
       
  4865 		{
       
  4866 		aParsedAddress.iTelNumber.SetLength(maxparsedlength);
       
  4867 
       
  4868 		TInt length=iAccessAddress->Des().Length();
       
  4869 		TInt parsedlength=0;
       
  4870 		for (TInt i=0; (i<length) && (parsedlength<maxparsedlength); i++)
       
  4871 			{
       
  4872 			TText ch=iAccessAddress->Des()[i];
       
  4873 			if ((ch>='0') && (ch<='9'))
       
  4874 				{
       
  4875 				aParsedAddress.iTelNumber[parsedlength]=(TUint8) ch;
       
  4876 				parsedlength++;
       
  4877 				}
       
  4878 			}
       
  4879 
       
  4880 		aParsedAddress.iTelNumber.SetLength(parsedlength);
       
  4881 		}
       
  4882 	} // CEnhancedVoiceMailBoxInformation::ParsedAccessAddress
       
  4883 
       
  4884 
       
  4885 void CEnhancedVoiceMailBoxInformation::DoSetParsedAddressL(const TDesC& aAddress)
       
  4886 	{
       
  4887 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::DoSetParsedAddressL()");
       
  4888 
       
  4889 	TInt length=aAddress.Length();
       
  4890 	if ((iTypeOfAddress.TON()==EGsmSmsTONInternationalNumber) &&
       
  4891 	    (length && (aAddress[0]!='+')))
       
  4892 		{
       
  4893 		NewBufferL(length+1);
       
  4894 		iAccessAddress->Des()[0]='+';
       
  4895 		TPtr ptr((TText*) (iAccessAddress->Des().Ptr()+1),length,length);
       
  4896 		ptr.Copy(aAddress);
       
  4897 		}
       
  4898 	else
       
  4899 		{
       
  4900 		NewBufferL(length);
       
  4901 		iAccessAddress->Des().Copy(aAddress);
       
  4902 		}
       
  4903 	} // CEnhancedVoiceMailBoxInformation::DoSetParsedAddressL
       
  4904 
       
  4905 
       
  4906 /**
       
  4907  *  @publishedAll
       
  4908  *  
       
  4909  *  Sets the number of voice messages to a value in the range 0 to 255.
       
  4910  *  
       
  4911  *  @param aNumber
       
  4912  *  The number of voice messages.
       
  4913  *  
       
  4914  *  @capability None
       
  4915  */
       
  4916 EXPORT_C void   CEnhancedVoiceMailBoxInformation::SetNumberOfVoiceMessages(TUint8 aNumber)
       
  4917 	{
       
  4918 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::SetNumberOfVoiceMessages()");
       
  4919 
       
  4920 	iNumberOfVoiceMessages=aNumber;
       
  4921 	} // CEnhancedVoiceMailBoxInformation::SetNumberOfVoiceMessages
       
  4922 
       
  4923 
       
  4924 /**
       
  4925  *  @publishedAll
       
  4926  *  
       
  4927  *  Retrieves the number of voice messages that are unread.
       
  4928  *  
       
  4929  *  @return
       
  4930  *  The number of unread voice messages.
       
  4931  *  
       
  4932  *  @capability None
       
  4933  */
       
  4934 EXPORT_C TUint8 CEnhancedVoiceMailBoxInformation::NumberOfVoiceMessages() const
       
  4935 	{
       
  4936 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::NumberOfVoiceMessages()");
       
  4937 
       
  4938 	return iNumberOfVoiceMessages;
       
  4939 	} // CEnhancedVoiceMailBoxInformation::NumberOfVoiceMessages
       
  4940 
       
  4941 
       
  4942 TUint8* CEnhancedVoiceMailBoxInformation::EncodeL(TUint8* aPtr, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) const
       
  4943 	{
       
  4944 	*aPtr =  (((TUint8) iType)       & EMask1Bit )       +
       
  4945 	        ((((TUint8) iProfile)    & EMask2Bits) << 2) +
       
  4946 	        ((((TUint8) iStorage)    & EMask1Bit ) << 4) +
       
  4947 	        ((((TUint8) iAlmostFull) & EMask1Bit ) << 5) +
       
  4948 	        ((((TUint8) iFull)       & EMask1Bit ) << 6) +
       
  4949 	         (((TUint8) iExtensionIndicator      ) << 7);
       
  4950 
       
  4951 	LOGGSMU2("CEnhancedVoiceMailBoxInformation::EncodeL 1st byte = %d",*aPtr);
       
  4952 	aPtr++;
       
  4953 
       
  4954 	// Create an address object to encode the mail box access address into the
       
  4955 	// format required by 23.040 v6.5.0 section 9.1.2.5.
       
  4956 	CSmsAddress* address = CSmsAddress::NewL(aCharacterSetConverter,aFs);
       
  4957 	CleanupStack::PushL(address);
       
  4958 	TPtrC accessAddressPtr;
       
  4959 	if (iAccessAddress)
       
  4960 	    {
       
  4961 		accessAddressPtr.Set(iAccessAddress->Des());
       
  4962 	    }
       
  4963 	address->SetRawAddressL(iTypeOfAddress,accessAddressPtr);
       
  4964 	aPtr = address->EncodeL(aPtr);
       
  4965 	CleanupStack::PopAndDestroy(address);
       
  4966 
       
  4967 	*aPtr = (TUint8) iNumberOfVoiceMessages;
       
  4968 	aPtr++;
       
  4969 
       
  4970 	return aPtr;
       
  4971 	} // CEnhancedVoiceMailBoxInformation::EncodeL
       
  4972 
       
  4973 
       
  4974 void CEnhancedVoiceMailBoxInformation::DecodeL(TGsmuLex8& aVoiceMailInfo, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
       
  4975 	{
       
  4976 	TUint8 Byte1 = aVoiceMailInfo.GetL();
       
  4977 
       
  4978 	iType               = (TVoiceMailInfoType)       (Byte1       & EMask1Bit);
       
  4979 	iProfile            = (TSmsMessageProfileType ) ((Byte1 >> 2) & EMask2Bits);
       
  4980 	iStorage            = (TBool)                   ((Byte1 >> 4) & EMask1Bit);
       
  4981 	iAlmostFull         = (TBool)                   ((Byte1 >> 5) & EMask1Bit);
       
  4982 	iFull               = (TBool)                   ((Byte1 >> 6) & EMask1Bit);
       
  4983 	iExtensionIndicator = (TBool)                   ((Byte1 >> 7) & EMask1Bit);
       
  4984 
       
  4985 	LOGGSMU2("CEnhancedVoiceMailBoxInformation::DecodeL 1st byte = %d", Byte1);
       
  4986 
       
  4987 	// Create an address object to deccode the mail box access address from the
       
  4988 	// format required by 23.040 v6.5.0 section 9.1.2.5.
       
  4989 	CSmsAddress* decodedAddress = CSmsAddress::NewL(aCharacterSetConverter,aFs);
       
  4990 	CleanupStack::PushL(decodedAddress);
       
  4991 
       
  4992 	// CSmsAddress::DecodeL is also used to decode source and destination addresses.
       
  4993 	// CSmsAddress::DecodeL expects internally that alphanumeric addresses will be size
       
  4994 	// CSmsAddress::KSmsAddressMaxAddressValueLength=10.
       
  4995 	// Need to add padding bytes to bring the address field up to the maximum size.
       
  4996 	const TPtrC8 remainder(aVoiceMailInfo.Remainder());
       
  4997 
       
  4998 	if (remainder.Length() < CSmsAddress::KSmsAddressMaxAddressLength)
       
  4999 	    {
       
  5000 	    TBuf8<CSmsAddress::KSmsAddressMaxAddressLength> data;
       
  5001 	    data = remainder;
       
  5002 	    TInt actualLength = data.Length();
       
  5003 	    data.SetLength(CSmsAddress::KSmsAddressMaxAddressLength);
       
  5004 
       
  5005 	    for (TUint8 j = actualLength; j < CSmsAddress::KSmsAddressMaxAddressLength; j++)
       
  5006 	        {
       
  5007 	        data[j] = 0;
       
  5008 	        }
       
  5009 
       
  5010 	    TGsmuLex8 encodedAddress(data);
       
  5011 	    decodedAddress->DecodeL(encodedAddress);
       
  5012 	    // might want to check that aVoiceMailInfo can be incremented
       
  5013 	    // by encodedAddress.Offset.
       
  5014 	    aVoiceMailInfo.Inc(encodedAddress.Offset());
       
  5015 	    }
       
  5016 	else
       
  5017 	    {
       
  5018 	    decodedAddress->DecodeL(aVoiceMailInfo);
       
  5019 	    }
       
  5020 
       
  5021 	TInt length=(decodedAddress->Address()).Length();
       
  5022 	NewBufferL(length);
       
  5023 	iAccessAddress->Des().Copy((decodedAddress->Address().Ptr()),length);
       
  5024 
       
  5025 	iTypeOfAddress = decodedAddress->TypeOfAddress();
       
  5026 
       
  5027 	CleanupStack::PopAndDestroy(decodedAddress);
       
  5028 
       
  5029 	iNumberOfVoiceMessages = aVoiceMailInfo.GetL();
       
  5030 	LOGGSMU2("CEnhancedVoiceMailBoxInformation::DecodeL iNumberOfVoiceMessages = %d", iNumberOfVoiceMessages);
       
  5031 	} // CEnhancedVoiceMailBoxInformation::DecodeL
       
  5032 
       
  5033 
       
  5034 CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation()
       
  5035 	{
       
  5036 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation()");
       
  5037 
       
  5038 	// Consider changing this over to a Panic.
       
  5039 	iType               = EGsmSmsVoiceMailNotification;
       
  5040 	iOctet1Bit1         = EFalse;
       
  5041 	iProfile            = EGsmSmsProfileId1;
       
  5042 	iStorage            = EFalse;
       
  5043 	iAlmostFull         = EFalse;
       
  5044 	iFull               = EFalse;
       
  5045 	iExtensionIndicator = EFalse;
       
  5046 	iTypeOfAddress      = 0;
       
  5047 	} // CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation
       
  5048 
       
  5049 
       
  5050 CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation(TVoiceMailInfoType aTVoiceMailInfoType)
       
  5051 	{
       
  5052 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation()");
       
  5053 
       
  5054 	iType               = aTVoiceMailInfoType;
       
  5055 	iOctet1Bit1         = EFalse;
       
  5056 	iProfile            = EGsmSmsProfileId1;
       
  5057 	iStorage            = EFalse;
       
  5058 	iAlmostFull         = EFalse;
       
  5059 	iFull               = EFalse;
       
  5060 	iExtensionIndicator = EFalse;
       
  5061 	iTypeOfAddress      = 0;
       
  5062 	} // CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation
       
  5063 
       
  5064 
       
  5065 /**
       
  5066  *  @internalComponent
       
  5067  *  
       
  5068  *  Prevent clients from using the copy constructor by including it in the class definition
       
  5069  *  but making it protected and not exporting it.
       
  5070  *  
       
  5071  *  @capability None
       
  5072  */
       
  5073 CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation(const CEnhancedVoiceMailBoxInformation&)
       
  5074     {
       
  5075     // Ignore in code coverage - not intended to be used
       
  5076     BULLSEYE_OFF    
       
  5077     LOGGSMU1("CEnhancedVoiceMailBoxInformation::CEnhancedVoiceMailBoxInformation");
       
  5078     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5079     BULLSEYE_RESTORE
       
  5080     }
       
  5081 
       
  5082 /**
       
  5083  *  @internalComponent
       
  5084  *  
       
  5085  *  Prevent clients from using the equality operator by including it in the class definition
       
  5086  *  but making it protected and not exporting it.
       
  5087  *  
       
  5088  *  @capability None
       
  5089  */
       
  5090 TBool CEnhancedVoiceMailBoxInformation::operator==(const CEnhancedVoiceMailBoxInformation&)
       
  5091     {
       
  5092     // Ignore in code coverage - not intended to be used
       
  5093     BULLSEYE_OFF    
       
  5094     LOGGSMU1("CEnhancedVoiceMailBoxInformation::operator==");
       
  5095     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5096     return EFalse;
       
  5097     BULLSEYE_RESTORE
       
  5098     }
       
  5099 
       
  5100 /**
       
  5101  *  @internalComponent
       
  5102  *  
       
  5103  *  Prevent clients from using the assignment operator by including it in the class definition
       
  5104  *  but making it protected and not exporting it.
       
  5105  *  
       
  5106  *  @capability None
       
  5107  */
       
  5108 void CEnhancedVoiceMailBoxInformation::operator=(const CEnhancedVoiceMailBoxInformation&)
       
  5109     {
       
  5110     // Ignore in code coverage - not intended to be used
       
  5111     BULLSEYE_OFF    
       
  5112     LOGGSMU1("CEnhancedVoiceMailBoxInformation::operator=");
       
  5113     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5114     BULLSEYE_RESTORE
       
  5115     }
       
  5116 
       
  5117 void CEnhancedVoiceMailBoxInformation::ConstructL()
       
  5118 	{
       
  5119 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::ConstructL()");
       
  5120 
       
  5121 	NewBufferL(0);
       
  5122 	} // CEnhancedVoiceMailBoxInformation::ConstructL
       
  5123 
       
  5124 
       
  5125 CEnhancedVoiceMailBoxInformation::~CEnhancedVoiceMailBoxInformation()
       
  5126 	{
       
  5127 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::~CEnhancedVoiceMailBoxInformation");
       
  5128 	delete iAccessAddress;
       
  5129 	} // CEnhancedVoiceMailBoxInformation::ConstructL
       
  5130 
       
  5131 
       
  5132 CEnhancedVoiceMailBoxInformation* CEnhancedVoiceMailBoxInformation::NewL()
       
  5133 	{
       
  5134 	LOGGSMU1("CEnhancedVoiceMailBoxInformation::NewL()");
       
  5135 
       
  5136 	CEnhancedVoiceMailBoxInformation* aCEnhancedVoiceMailBoxInformation=new(ELeave) CEnhancedVoiceMailBoxInformation();
       
  5137 	CleanupStack::PushL(aCEnhancedVoiceMailBoxInformation);
       
  5138 	aCEnhancedVoiceMailBoxInformation->ConstructL();
       
  5139 	CleanupStack::Pop(aCEnhancedVoiceMailBoxInformation);
       
  5140 	return aCEnhancedVoiceMailBoxInformation;
       
  5141 	} // CEnhancedVoiceMailBoxInformation::NewL
       
  5142 
       
  5143 
       
  5144 /**
       
  5145  *  @publishedAll
       
  5146  *  
       
  5147  *  Sets the message id to a value between 0 and 65535.
       
  5148  *  
       
  5149  *  @param aNumber
       
  5150  *  The message id
       
  5151  *  
       
  5152  *  @capability None
       
  5153  */
       
  5154 EXPORT_C void CVoiceMailNotification::SetMessageId(TUint16 aMessageId)
       
  5155 	{
       
  5156 	LOGGSMU1("CVoiceMailNotification::SetMessageId()");
       
  5157 
       
  5158 	iMessageId = aMessageId;
       
  5159 	} // CVoiceMailNotification::SetMessageId
       
  5160 
       
  5161 
       
  5162 /**
       
  5163  *  @publishedAll
       
  5164  *  
       
  5165  *  Retrieves the message id, a value in the range 0 to 65535.
       
  5166  *  
       
  5167  *  @return
       
  5168  *  The message id,
       
  5169  *  
       
  5170  *  @capability None
       
  5171  */
       
  5172 EXPORT_C TUint16 CVoiceMailNotification::MessageId() const
       
  5173 	{
       
  5174 	LOGGSMU1("CVoiceMailNotification::MessageId()");
       
  5175 
       
  5176 	return iMessageId;
       
  5177 	} // CVoiceMailNotification::MessageId
       
  5178 
       
  5179 
       
  5180 /**
       
  5181  *  @publishedAll
       
  5182  *  
       
  5183  *  Sets the voice mail message length to a value between 0 and 255
       
  5184  *  
       
  5185  *  @param aLength
       
  5186  *  The voice mail message length.
       
  5187  *  
       
  5188  *  @capability None
       
  5189  */
       
  5190 EXPORT_C void CVoiceMailNotification::SetMessageLength(TUint8 aLength)
       
  5191 	{
       
  5192 	LOGGSMU1("CVoiceMailNotification::SetMessageLength()");
       
  5193 
       
  5194 	iMessageLength=aLength;
       
  5195 	} // CVoiceMailNotification::SetMessageLength
       
  5196 
       
  5197 
       
  5198 /**
       
  5199  *  @publishedAll
       
  5200  *  
       
  5201  *  Retrieves the voice mail message length, a value in the range 0 to 255.
       
  5202  *  
       
  5203  *  @return
       
  5204  *  The voice mail message length.
       
  5205  *  
       
  5206  *  @capability None
       
  5207  */
       
  5208 EXPORT_C TUint8 CVoiceMailNotification::MessageLength() const
       
  5209 	{
       
  5210 	LOGGSMU1("CVoiceMailNotification::MessageLength()");
       
  5211 
       
  5212 	return iMessageLength;
       
  5213 	} // CVoiceMailNotification::MessageLength
       
  5214 
       
  5215 
       
  5216 /**
       
  5217  *  @publishedAll
       
  5218  *  
       
  5219  *  Sets the number of days that the voice message will be retained to
       
  5220  *  a value between 0 and 31. Values in excess of 31 will be capped at
       
  5221  *  31.
       
  5222  *  
       
  5223  *  @param aDays
       
  5224  *  The number of retention days.
       
  5225  *  
       
  5226  *  @capability None
       
  5227  */
       
  5228 EXPORT_C void CVoiceMailNotification::SetRetentionDays(TUint8 aDays)
       
  5229 	{
       
  5230 	LOGGSMU1("CVoiceMailNotification::SetRetentionDays()");
       
  5231 
       
  5232 	if (aDays > 31)
       
  5233 	    {
       
  5234 	    iRetentionDays = 31;
       
  5235 	    }
       
  5236 	else
       
  5237 	    {
       
  5238 	    iRetentionDays = aDays;
       
  5239 	    }
       
  5240 	} // CVoiceMailNotification::SetRetentionDays
       
  5241 
       
  5242 
       
  5243 /**
       
  5244  *  @publishedAll
       
  5245  *  
       
  5246  *  Retrieves the number of days the voice message will be retained.
       
  5247  *  
       
  5248  *  @return
       
  5249  *  The number of days the voice message will be retained.
       
  5250  *  
       
  5251  *  @capability None
       
  5252  */
       
  5253 EXPORT_C TUint8 CVoiceMailNotification::RetentionDays() const
       
  5254 	{
       
  5255 	LOGGSMU1("CVoiceMailNotification::RetentionDays()");
       
  5256 
       
  5257 	return iRetentionDays;
       
  5258 	} // CVoiceMailNotification::RetentionDays
       
  5259 
       
  5260 
       
  5261 /**
       
  5262  *  @publishedAll
       
  5263  *  
       
  5264  *  Sets the message priority to urgent
       
  5265  *  
       
  5266  *  @param aPriority
       
  5267  *  Set to True if the priority is urgent,
       
  5268  *  Otherwise set to False.
       
  5269  *  
       
  5270  *  @capability None
       
  5271  */
       
  5272 EXPORT_C void CVoiceMailNotification::SetPriorityIndication(TBool aPriority)
       
  5273 	{
       
  5274 	LOGGSMU1("CVoiceMailNotification::SetPriorityIndication()");
       
  5275 
       
  5276 	iPriorityIndication=aPriority;
       
  5277 	} // CVoiceMailNotification::SetPriorityIndication
       
  5278 
       
  5279 
       
  5280 /**
       
  5281  *  @publishedAll
       
  5282  *  
       
  5283  *  Retrieves the priority indication.
       
  5284  *  
       
  5285  *  @return
       
  5286  *  True if the priority is urgent,
       
  5287  *  False otherwise.
       
  5288  *  
       
  5289  *  @capability None
       
  5290  */
       
  5291 EXPORT_C TBool CVoiceMailNotification::PriorityIndication() const
       
  5292 	{
       
  5293 	LOGGSMU1("CVoiceMailNotification::PriorityIndication()");
       
  5294 
       
  5295 	return iPriorityIndication;
       
  5296 	} // CVoiceMailNotification::PriorityIndication
       
  5297 
       
  5298 
       
  5299 /**
       
  5300  *  @publishedAll
       
  5301  *  
       
  5302  *  Indicates whether the voice mail notification contains extension bytes.
       
  5303  *  
       
  5304  *  @return
       
  5305  *  True if the voice mail notification contains extension bytes.
       
  5306  *  False otherwise.
       
  5307  *  
       
  5308  *  @capability None
       
  5309  */
       
  5310 EXPORT_C TBool CVoiceMailNotification::MessageExtensionIndication() const
       
  5311 	{
       
  5312 	LOGGSMU1("CVoiceMailNotification::MessageExtensionIndication()");
       
  5313 
       
  5314 	return iMessageExtensionIndicator;
       
  5315 	} // CVoiceMailNotification::MessageExtensionIndication
       
  5316 
       
  5317 
       
  5318 void CVoiceMailNotification::NewBufferL(TInt aLength)
       
  5319 	{
       
  5320 	LOGGSMU1("CVoiceMailNotification::NewBufferL()");
       
  5321 
       
  5322 	HBufC* buffer=HBufC::NewL(aLength);
       
  5323 	delete iCallingLineIdentity;
       
  5324 	iCallingLineIdentity=buffer;
       
  5325 	iCallingLineIdentity->Des().SetLength(aLength);
       
  5326 	iCallingLineIdentity->Des().FillZ();
       
  5327 	} // CVoiceMailNotification::NewBufferL
       
  5328 
       
  5329 
       
  5330 /**
       
  5331  *  @publishedAll
       
  5332  *  
       
  5333  *  Used to set the calling line idenity
       
  5334  *  
       
  5335  *  @param aLineIdentity
       
  5336  *  
       
  5337  *  @capability None
       
  5338  */
       
  5339 EXPORT_C void  CVoiceMailNotification::SetCallingLineIdentityL(TDesC& aLineIdentity)
       
  5340 	{
       
  5341 	LOGGSMU1("CVoiceMailNotification::SetCallingLineIdentityL()");
       
  5342 
       
  5343 	TInt length=aLineIdentity.Length();
       
  5344 	NewBufferL(length);
       
  5345 	iCallingLineIdentity->Des().Copy(aLineIdentity);
       
  5346 
       
  5347 	const TGsmSmsTypeOfNumber typeofnumber=length && (iCallingLineIdentity->Des()[0]=='+')? EGsmSmsTONInternationalNumber: EGsmSmsTONUnknown;
       
  5348 	iTypeOfAddress.SetTON(typeofnumber);
       
  5349 	} // CVoiceMailNotification::SetCallingLineIdentityL
       
  5350 
       
  5351 
       
  5352 /**
       
  5353  *  @publishedAll
       
  5354  *  
       
  5355  *  Retrieves the Calling Line Identity
       
  5356  *  
       
  5357  *  @return
       
  5358  *  A pointer to the Calling Line Identity.
       
  5359  *  
       
  5360  *  @capability None
       
  5361  */
       
  5362 EXPORT_C TPtrC CVoiceMailNotification::CallingLineIdentity() const
       
  5363 	{
       
  5364 	LOGGSMU1("CVoiceMailNotification::CallingLineIdentity()");
       
  5365 
       
  5366 	TPtrC ptr;
       
  5367 	if (iCallingLineIdentity)
       
  5368 	    ptr.Set(iCallingLineIdentity->Des());
       
  5369 	return ptr;
       
  5370 	} // CVoiceMailNotification::CallingLineIdentity
       
  5371 
       
  5372 
       
  5373 /**
       
  5374  *  @publishedAll
       
  5375  *  
       
  5376  *  Set the Calling Line Id as a parsed address.
       
  5377  *  
       
  5378  *  @param aParsedAddress
       
  5379  *  The Calling Line Id as a parsed address.
       
  5380  *  
       
  5381  *  @capability None
       
  5382  */
       
  5383 EXPORT_C void CVoiceMailNotification::SetParsedCallingLineIdentityL(TGsmSmsTelNumber& aParsedAddress)
       
  5384 	{
       
  5385 	LOGGSMU1("CVoiceMailNotification::SetParsedCallingLineIdentityL()");
       
  5386 
       
  5387 	iTypeOfAddress=aParsedAddress.iTypeOfAddress;
       
  5388 	DoSetParsedAddressL(aParsedAddress.iTelNumber);
       
  5389 	} // CVoiceMailNotification::SetParsedCallingLineIdentityL
       
  5390 
       
  5391 
       
  5392 /**
       
  5393  *  @publishedAll
       
  5394  *  
       
  5395  *  Gets the Calling Line Id as a parsed address.
       
  5396  *  
       
  5397  *  @param aParsedAddress
       
  5398  *  An output parameter which is to be set to the parsed calling line ID.
       
  5399  *  
       
  5400  *  @capability None
       
  5401  */
       
  5402 EXPORT_C void CVoiceMailNotification::ParsedCallingLineIdentity(TGsmSmsTelNumber& aParsedAddress) const
       
  5403 	{
       
  5404 	LOGGSMU1("CVoiceMailNotification::ParsedCallingLineIdentity()");
       
  5405 
       
  5406 	aParsedAddress.iTypeOfAddress = iTypeOfAddress;
       
  5407 
       
  5408 	TInt maxparsedlength=aParsedAddress.iTelNumber.MaxLength();
       
  5409 
       
  5410 	if (iTypeOfAddress.TON()==EGsmSmsTONAlphaNumeric)
       
  5411 		{
       
  5412 		TInt parsedlength=CallingLineIdentity().Length();
       
  5413 		if (parsedlength>maxparsedlength)
       
  5414 			parsedlength=maxparsedlength;
       
  5415 		aParsedAddress.iTelNumber.Copy(CallingLineIdentity().Mid(0,parsedlength));
       
  5416 		}
       
  5417 	else
       
  5418 		{
       
  5419 		aParsedAddress.iTelNumber.SetLength(maxparsedlength);
       
  5420 
       
  5421 		TInt length=iCallingLineIdentity->Des().Length();
       
  5422 		TInt parsedlength=0;
       
  5423 		for (TInt i=0; (i<length) && (parsedlength<maxparsedlength); i++)
       
  5424 			{
       
  5425 			TText ch=iCallingLineIdentity->Des()[i];
       
  5426 			if ((ch>='0') && (ch<='9'))
       
  5427 				{
       
  5428 				aParsedAddress.iTelNumber[parsedlength]=(TUint8) ch;
       
  5429 				parsedlength++;
       
  5430 				}
       
  5431 			}
       
  5432 
       
  5433 		aParsedAddress.iTelNumber.SetLength(parsedlength);
       
  5434 		}
       
  5435 	} // CVoiceMailNotification::ParsedCallingLineIdentity
       
  5436 
       
  5437 
       
  5438 void CVoiceMailNotification::NewExtensionL(TInt aLength)
       
  5439 	{
       
  5440 	LOGGSMU1("CVoiceMailNotification::NewExtensionL()");
       
  5441 
       
  5442 	HBufC* buffer=HBufC::NewL(aLength);
       
  5443 	delete iExtension;
       
  5444 	iExtension=buffer;
       
  5445 	iExtension->Des().SetLength(aLength);
       
  5446 	iExtension->Des().FillZ();
       
  5447 	} // CVoiceMailNotification::NewExtensionL
       
  5448 
       
  5449 
       
  5450 /*void CVoiceMailNotification::SetExtension(TDesC& aExtension)
       
  5451 	{
       
  5452 	LOGGSMU1("CVoiceMailNotification::SetExtension()");
       
  5453 
       
  5454 	TInt length=aExtension.Length();
       
  5455 	NewExtensionL(length);
       
  5456 	iExtension->Des().Copy(aExtension);
       
  5457 	} // CVoiceMailNotification::SetExtension
       
  5458 
       
  5459 TPtrC CVoiceMailNotification::Extension() const
       
  5460 	{
       
  5461 	LOGGSMU1("CVoiceMailNotification::Extension()");
       
  5462 
       
  5463 	TPtrC ptr;
       
  5464 	if (iExtension)
       
  5465 	    ptr.Set(iExtension->Des());
       
  5466 	return ptr;
       
  5467 	}*/
       
  5468 
       
  5469 
       
  5470 /**
       
  5471  *  @internalComponent
       
  5472  *  
       
  5473  *  Determines the size of the encoded Voice Mail Notification.
       
  5474  *  
       
  5475  *  @param aCharacterSetConverter  A reference to a character set converter.
       
  5476  *  @param aFs  A reference to the file server.
       
  5477  *  @return The size of the encoded Voice Mail Notification
       
  5478  *  
       
  5479  *  @capability None
       
  5480  */
       
  5481 TUint8 CVoiceMailNotification::SizeL(CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
       
  5482 	{
       
  5483 	LOGGSMU1("CVoiceMailNotification::SizeL()");
       
  5484 
       
  5485 	const TUint8 KTotalSizeOfFixedLengthAttributes = 4;
       
  5486 	TUint8 size = KTotalSizeOfFixedLengthAttributes;
       
  5487 
       
  5488 	// need to find the size of the calling line ID.
       
  5489 	CSmsAddress* address = CSmsAddress::NewL(aCharacterSetConverter,aFs);
       
  5490 	CleanupStack::PushL(address);
       
  5491 
       
  5492 	TPtrC callingLineIdentityPtr;
       
  5493 	if (iCallingLineIdentity)
       
  5494 	    {
       
  5495 		callingLineIdentityPtr.Set(iCallingLineIdentity->Des());
       
  5496 	    }
       
  5497 
       
  5498 	address->SetRawAddressL(iTypeOfAddress,callingLineIdentityPtr);
       
  5499 
       
  5500 	size += address->SizeL();
       
  5501 	CleanupStack::PopAndDestroy(address);
       
  5502 
       
  5503 	return size;
       
  5504 	} // CVoiceMailNotification::SizeL
       
  5505 
       
  5506 
       
  5507 TUint8* CVoiceMailNotification::EncodeL(TUint8* aPtr, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) const
       
  5508 	{
       
  5509 	// When changes are made to this function that affect the
       
  5510 	// number of bytes that are encoded, this should be reflected in
       
  5511 	// CVoiceMailNotification::SizeL()
       
  5512 	LOGGSMU1("CVoiceMailNotification::EncodeL");
       
  5513 
       
  5514 
       
  5515 	*aPtr =   (TUint8)  (iMessageId                         >> 8);  // Message Id MSB
       
  5516 	aPtr++;
       
  5517 	*aPtr =   (TUint8)   iMessageId;                                // Message Id LSB
       
  5518 	aPtr++;
       
  5519 	*aPtr =   (TUint8)   iMessageLength;
       
  5520 	aPtr++;
       
  5521 	*aPtr =   ((TUint8)  (iRetentionDays & EMask5Bits))             +
       
  5522 	         (((TUint8)   iPriorityIndication)               << 6)  +
       
  5523 	         (((TUint8)   iMessageExtensionIndicator)        << 7);
       
  5524 	aPtr++;
       
  5525 
       
  5526 	CSmsAddress* address = CSmsAddress::NewL(aCharacterSetConverter,aFs);
       
  5527 	CleanupStack::PushL(address);
       
  5528 
       
  5529 	TPtrC callingLineIdentityPtr;
       
  5530 	if (iCallingLineIdentity)
       
  5531 	    {
       
  5532 		callingLineIdentityPtr.Set(iCallingLineIdentity->Des());
       
  5533 	    }
       
  5534 
       
  5535 	address->SetRawAddressL(iTypeOfAddress,callingLineIdentityPtr);
       
  5536 
       
  5537 	aPtr = address->EncodeL(aPtr);
       
  5538 	CleanupStack::PopAndDestroy(address);
       
  5539 
       
  5540 	return aPtr;
       
  5541 	} // CVoiceMailNotification::EncodeL
       
  5542 
       
  5543 
       
  5544 void CVoiceMailNotification::DecodeL(TGsmuLex8& aVoiceMailInfo, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
       
  5545 	{
       
  5546 	LOGGSMU1("CVoiceMailNotification::DecodeL");
       
  5547 
       
  5548 	iMessageId = (((TUint16) aVoiceMailInfo.GetL()) << 8);
       
  5549 	iMessageId += ((TUint16) aVoiceMailInfo.GetL());
       
  5550 
       
  5551 	iMessageLength=aVoiceMailInfo.GetL();
       
  5552 
       
  5553 	TUint8 currentByte = aVoiceMailInfo.GetL();
       
  5554 
       
  5555 	iRetentionDays             =   currentByte       & EMask5Bits;
       
  5556 	iPriorityIndication        = ((currentByte >> 6) & EMask1Bit);
       
  5557 	iMessageExtensionIndicator = ((currentByte >> 7) & EMask1Bit);
       
  5558 
       
  5559 	CSmsAddress* decodedAddress = CSmsAddress::NewL(aCharacterSetConverter,aFs);
       
  5560 	CleanupStack::PushL(decodedAddress);
       
  5561 
       
  5562 	const TPtrC8 remainder(aVoiceMailInfo.Remainder());
       
  5563 	// The address information element makes an assumption that aVoiceMail must
       
  5564 	// be of size CSmsAddress::KSmsAddressMaxAddressLength
       
  5565 	// Provide padding to ensure that this is the case.
       
  5566 	if (remainder.Length() < CSmsAddress::KSmsAddressMaxAddressLength)
       
  5567 	    {
       
  5568 	    TBuf8<CSmsAddress::KSmsAddressMaxAddressLength> data;
       
  5569 	    data = remainder;
       
  5570 	    TInt actualLength = data.Length();
       
  5571 	    data.SetLength(CSmsAddress::KSmsAddressMaxAddressLength);
       
  5572 
       
  5573 	    for (TUint8 j = actualLength; j < CSmsAddress::KSmsAddressMaxAddressLength; j++)
       
  5574 	        {
       
  5575 	        data[j] = 0;
       
  5576 	        }
       
  5577 
       
  5578 	    TGsmuLex8 encodedAddress(data);
       
  5579 	    decodedAddress->DecodeL(encodedAddress);
       
  5580 	    // Should be the last piece of data to be decoded
       
  5581 	    // The next line is included for completeness.
       
  5582 	    aVoiceMailInfo.Inc(encodedAddress.Offset());
       
  5583 	    }
       
  5584 	else
       
  5585 	    {
       
  5586 	    decodedAddress->DecodeL(aVoiceMailInfo);
       
  5587 	    }
       
  5588 
       
  5589 	TInt length=(decodedAddress->Address()).Length();
       
  5590 	NewBufferL(length);
       
  5591 	iCallingLineIdentity->Des().Copy((decodedAddress->Address().Ptr()),length);
       
  5592 
       
  5593 	iTypeOfAddress = decodedAddress->TypeOfAddress();
       
  5594 
       
  5595 	CleanupStack::PopAndDestroy(decodedAddress);
       
  5596 
       
  5597 	if (iMessageExtensionIndicator)
       
  5598 	    {
       
  5599 	    TUint8 extensionLength = aVoiceMailInfo.GetL();
       
  5600 	    aVoiceMailInfo.Inc(extensionLength);
       
  5601 	    }
       
  5602 	} // CVoiceMailNotification::DecodeL
       
  5603 
       
  5604 
       
  5605 /**
       
  5606  *  @internalComponent
       
  5607  *  
       
  5608  *  Prevent clients from using the copy constructor by including it in the class definition
       
  5609  *  but making it protected and not exporting it.
       
  5610  *  
       
  5611  *  @capability None
       
  5612  */
       
  5613 CVoiceMailNotification::CVoiceMailNotification(const CVoiceMailNotification&)
       
  5614     {
       
  5615     // Ignore in code coverage - not intended to be used
       
  5616     BULLSEYE_OFF    
       
  5617     LOGGSMU1("CVoiceMailNotification::CVoiceMailNotification");
       
  5618     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5619     BULLSEYE_RESTORE
       
  5620     }
       
  5621 
       
  5622 /**
       
  5623  *  @internalComponent
       
  5624  *  
       
  5625  *  Prevent clients from using the equality operator by including it in the class definition
       
  5626  *  but making it protected and not exporting it.
       
  5627  *  
       
  5628  *  @capability None
       
  5629  */
       
  5630 TBool CVoiceMailNotification::operator==(const CVoiceMailNotification&)
       
  5631     {
       
  5632     // Ignore in code coverage - not intended to be used
       
  5633     BULLSEYE_OFF    
       
  5634     LOGGSMU1("CVoiceMailNotification::operator==");
       
  5635     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5636     return EFalse;
       
  5637     BULLSEYE_RESTORE
       
  5638     }
       
  5639 
       
  5640 /**
       
  5641  *  @internalComponent
       
  5642  *  
       
  5643  *  Prevent clients from using the assignment operator by including it in the class definition
       
  5644  *  but making it protected and not exporting it.
       
  5645  *  
       
  5646  *  @capability None
       
  5647  */
       
  5648 void CVoiceMailNotification::operator=(const CVoiceMailNotification&)
       
  5649     {
       
  5650     // Ignore in code coverage - not intended to be used
       
  5651     BULLSEYE_OFF    
       
  5652     LOGGSMU1("CVoiceMailNotification::operator=");
       
  5653     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5654     BULLSEYE_RESTORE
       
  5655     }
       
  5656 
       
  5657 CVoiceMailNotification::CVoiceMailNotification()
       
  5658 	{
       
  5659 	LOGGSMU1("CVoiceMailNotification::CVoiceMailNotification()");
       
  5660 
       
  5661 	iMessageId                 = 0;
       
  5662 	iMessageLength             = 0;
       
  5663 	iRetentionDays             = 0;
       
  5664 	iOctetN8Bit1               = EFalse;
       
  5665 	iPriorityIndication        = EFalse;
       
  5666 	iMessageExtensionIndicator = EFalse;
       
  5667 	iTypeOfAddress             = 0;
       
  5668 	} // CVoiceMailNotification::CVoiceMailNotification
       
  5669 
       
  5670 
       
  5671 /**
       
  5672  *  @publishedAll
       
  5673  *  
       
  5674  *  Class Destructor
       
  5675  *  
       
  5676  *  @capability None
       
  5677  */
       
  5678 EXPORT_C CVoiceMailNotification::~CVoiceMailNotification()
       
  5679 	{
       
  5680 	LOGGSMU1("CVoiceMailNotification::~CVoiceMailNotification");
       
  5681 	delete iCallingLineIdentity;
       
  5682 	delete iExtension;
       
  5683 	} // CVoiceMailNotification::CVoiceMailNotification
       
  5684 
       
  5685 
       
  5686 void CVoiceMailNotification::ConstructL()
       
  5687 	{
       
  5688 	LOGGSMU1("CVoiceMailNotification::ConstructL()");
       
  5689 
       
  5690 	NewBufferL(0);
       
  5691 	NewExtensionL(0);
       
  5692 	} // CVoiceMailNotification::ConstructL
       
  5693 
       
  5694 
       
  5695 /**
       
  5696  *  @publishedAll
       
  5697  *  
       
  5698  *  Class construction method.
       
  5699  *  
       
  5700  *  @capability None
       
  5701  */
       
  5702 EXPORT_C CVoiceMailNotification* CVoiceMailNotification::NewL()
       
  5703 	{
       
  5704 	LOGGSMU1("CVoiceMailNotification::NewL()");
       
  5705 
       
  5706 	CVoiceMailNotification* aCVoiceMailNotification=new(ELeave) CVoiceMailNotification();
       
  5707 	CleanupStack::PushL(aCVoiceMailNotification);
       
  5708 	aCVoiceMailNotification->ConstructL();
       
  5709 	CleanupStack::Pop(aCVoiceMailNotification);
       
  5710 	return aCVoiceMailNotification;
       
  5711 	} // CVoiceMailNotification::NewL
       
  5712 
       
  5713 
       
  5714 void CVoiceMailNotification::DoSetParsedAddressL(const TDesC& aAddress)
       
  5715 	{
       
  5716 	LOGGSMU1("CVoiceMailNotification::DoSetParsedAddressL()");
       
  5717 
       
  5718 	TInt length=aAddress.Length();
       
  5719 	if ((iTypeOfAddress.TON()==EGsmSmsTONInternationalNumber) &&
       
  5720 	    (length && (aAddress[0]!='+')))
       
  5721 		{
       
  5722 		NewBufferL(length+1);
       
  5723 		iCallingLineIdentity->Des()[0]='+';
       
  5724 		TPtr ptr((TText*) (iCallingLineIdentity->Des().Ptr()+1),length,length);
       
  5725 		ptr.Copy(aAddress);
       
  5726 		}
       
  5727 	else
       
  5728 		{
       
  5729 		NewBufferL(length);
       
  5730 		iCallingLineIdentity->Des().Copy(aAddress);
       
  5731 		}
       
  5732 	} // CVoiceMailNotification::DoSetParsedAddressL
       
  5733 
       
  5734 
       
  5735 /**
       
  5736  *  @publishedAll
       
  5737  *  
       
  5738  *  Retrieves the number of voice message notifications contained in
       
  5739  *  this information. The range is 0 to 15.
       
  5740  *  
       
  5741  *  @return
       
  5742  *  The number of voice message notifications in this information element.
       
  5743  *  
       
  5744  *  @capability None
       
  5745  */
       
  5746 EXPORT_C TUint8 CEnhancedVoiceMailNotification::NumberOfVoiceMails()
       
  5747 	{
       
  5748 	LOGGSMU1("CEnhancedVoiceMailNotification::NumberOfVoiceMails()");
       
  5749 
       
  5750 	return (TUint8) iNotifications->Count();
       
  5751 	} // CEnhancedVoiceMailNotification::NumberOfVoiceMails
       
  5752 
       
  5753 
       
  5754 /*void CEnhancedVoiceMailNotification::SetExtension(TDesC& aExtension)
       
  5755 	{
       
  5756 	LOGGSMU1("CEnhancedVoiceMailNotification::SetExtension()");
       
  5757 
       
  5758 	TInt length=aExtension.Length();
       
  5759 	NewExtensionL(length);
       
  5760 	iExtension->Des().Copy(aExtension);
       
  5761 	} // CEnhancedVoiceMailNotification::SetExtension
       
  5762 
       
  5763 TPtrC CEnhancedVoiceMailNotification::Extension() const
       
  5764 	{
       
  5765 	LOGGSMU1("CEnhancedVoiceMailNotification::Extension()");
       
  5766 
       
  5767 	TPtrC ptr;
       
  5768 	if (iExtension)
       
  5769 	    ptr.Set(iExtension->Des());
       
  5770 	return ptr;
       
  5771 	}*/
       
  5772 
       
  5773 
       
  5774 /**
       
  5775  *  @publishedAll
       
  5776  *  
       
  5777  *  Provides a reference to the collection that is used to contain the Voice Mail Notifications.
       
  5778  *  A maximum of 15 voice mail confirmations is supported. If more that 15 voice mails notifications are added
       
  5779  *  the CEnhancedVoiceMailNotification will not be added to the CSmsMessage by the CSmsEnhancedVoiceMailOperations
       
  5780  *  class.
       
  5781  *  
       
  5782  *  @return
       
  5783  *  A reference to the collection that is used to contain the Voice Mail Notifications.
       
  5784  *  
       
  5785  *  @capability None
       
  5786  */
       
  5787 EXPORT_C RPointerArray<CVoiceMailNotification>& CEnhancedVoiceMailNotification::GetVoiceMailNotifications()
       
  5788 	{
       
  5789 	LOGGSMU1("CEnhancedVoiceMailNotification::GetVoiceMailNotifications()");
       
  5790 
       
  5791 	return *iNotifications;
       
  5792 	} // CEnhancedVoiceMailNotification::GetVoiceMailNotifications
       
  5793 
       
  5794 
       
  5795 void CEnhancedVoiceMailNotification::NewExtensionL(TInt aLength)
       
  5796 	{
       
  5797 	LOGGSMU1("CEnhancedVoiceMailNotification::NewExtensionL()");
       
  5798 
       
  5799 	HBufC* buffer=HBufC::NewL(aLength);
       
  5800 	delete iExtension;
       
  5801 	iExtension=buffer;
       
  5802 	iExtension->Des().SetLength(aLength);
       
  5803 	iExtension->Des().FillZ();
       
  5804 	} // CEnhancedVoiceMailNotification::NewExtensionL
       
  5805 
       
  5806 
       
  5807 /**
       
  5808  *  @publishedAll
       
  5809  *  
       
  5810  *  Class construction method.
       
  5811  *  
       
  5812  *  @capability None
       
  5813  */
       
  5814 EXPORT_C  CEnhancedVoiceMailNotification* CEnhancedVoiceMailNotification::NewL()
       
  5815 	{
       
  5816 	LOGGSMU1("CEnhancedVoiceMailNotification::NewL()");
       
  5817 
       
  5818 	CEnhancedVoiceMailNotification* aCEnhancedVoiceMailNotification=new(ELeave) CEnhancedVoiceMailNotification();
       
  5819 	CleanupStack::PushL(aCEnhancedVoiceMailNotification);
       
  5820 	aCEnhancedVoiceMailNotification->CEnhancedVoiceMailBoxInformation::ConstructL();
       
  5821 	aCEnhancedVoiceMailNotification->ConstructL();
       
  5822 	CleanupStack::Pop(aCEnhancedVoiceMailNotification);
       
  5823 	return aCEnhancedVoiceMailNotification;
       
  5824 	} // CEnhancedVoiceMailNotification::NewL
       
  5825 
       
  5826 
       
  5827 CEnhancedVoiceMailNotification::CEnhancedVoiceMailNotification() : CEnhancedVoiceMailBoxInformation(EGsmSmsVoiceMailNotification)
       
  5828 	{
       
  5829 	} // CEnhancedVoiceMailNotification::CEnhancedVoiceMailNotification
       
  5830 
       
  5831 
       
  5832 /**
       
  5833  *  @internalComponent
       
  5834  *  
       
  5835  *  Prevent clients from using the copy constructor by including it in the class definition
       
  5836  *  but making it protected and not exporting it.
       
  5837  *  
       
  5838  *  @capability None
       
  5839  */
       
  5840 CEnhancedVoiceMailNotification::CEnhancedVoiceMailNotification(const CEnhancedVoiceMailNotification&)
       
  5841     {
       
  5842     // Ignore in code coverage - not intended to be used
       
  5843     BULLSEYE_OFF    
       
  5844     LOGGSMU1("CEnhancedVoiceMailNotification::CEnhancedVoiceMailNotification");
       
  5845     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5846     BULLSEYE_RESTORE
       
  5847     }
       
  5848 
       
  5849 /**
       
  5850  *  @internalComponent
       
  5851  *  
       
  5852  *  Prevent clients from using the equality operator by including it in the class definition
       
  5853  *  but making it protected and not exporting it.
       
  5854  *  
       
  5855  *  @capability None
       
  5856  */
       
  5857 TBool CEnhancedVoiceMailNotification::operator==(const CEnhancedVoiceMailNotification&)
       
  5858     {
       
  5859     // Ignore in code coverage - not intended to be used
       
  5860     BULLSEYE_OFF    
       
  5861     LOGGSMU1("CEnhancedVoiceMailNotification::operator==");
       
  5862     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5863     return EFalse;
       
  5864     BULLSEYE_RESTORE
       
  5865     }
       
  5866 
       
  5867 /**
       
  5868  *  @internalComponent
       
  5869  *  
       
  5870  *  Prevent clients from using the assignment operator by including it in the class definition
       
  5871  *  but making it protected and not exporting it.
       
  5872  *  
       
  5873  *  @capability None
       
  5874  */
       
  5875 void CEnhancedVoiceMailNotification::operator=(const CEnhancedVoiceMailNotification&)
       
  5876     {
       
  5877     // Ignore in code coverage - not intended to be used
       
  5878     BULLSEYE_OFF    
       
  5879     LOGGSMU1("CEnhancedVoiceMailNotification::operator=");
       
  5880     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  5881     BULLSEYE_RESTORE
       
  5882     }
       
  5883 
       
  5884 /**
       
  5885  *  @publishedAll
       
  5886  *  
       
  5887  *  Class destructor.
       
  5888  *  
       
  5889  *  @capability None
       
  5890  */
       
  5891 EXPORT_C  CEnhancedVoiceMailNotification::~CEnhancedVoiceMailNotification()
       
  5892 	{
       
  5893 	LOGGSMU1("CEnhancedVoiceMailNotification::~CEnhancedVoiceMailNotification");
       
  5894 	delete iExtension;
       
  5895 	iNotifications->ResetAndDestroy();
       
  5896 	iNotifications->Close();
       
  5897 	delete iNotifications;
       
  5898 	} // CEnhancedVoiceMailNotification::operator
       
  5899 
       
  5900 
       
  5901 void CEnhancedVoiceMailNotification::ConstructL()
       
  5902 	{
       
  5903 	LOGGSMU1("CEnhancedVoiceMailNotification::ConstructL()");
       
  5904 
       
  5905 	NewExtensionL(0);
       
  5906 	iNotifications = new (ELeave) RPointerArray<CVoiceMailNotification>(KMaxNumberOfNotifications);
       
  5907 	} // CEnhancedVoiceMailNotification::ConstructL
       
  5908 
       
  5909 
       
  5910 TUint8* CEnhancedVoiceMailNotification::EncodeL(TUint8* aCurrentPtr, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) const
       
  5911 	{
       
  5912 	LOGGSMU1("CEnhancedVoiceMailNotification::EncodeL");
       
  5913 
       
  5914 	TUint8* startPtr   = aCurrentPtr;
       
  5915 
       
  5916 	aCurrentPtr = CEnhancedVoiceMailBoxInformation::EncodeL(aCurrentPtr, aCharacterSetConverter, aFs);
       
  5917 
       
  5918 	TUint8 count = (TUint8)  iNotifications->Count();
       
  5919 	if (count > KMaxNumberOfNotifications)
       
  5920 	    {
       
  5921 	    User::Leave(KErrArgument);
       
  5922 	    }
       
  5923 
       
  5924 	*aCurrentPtr = (count & KSmsNotificationBitMask);
       
  5925 	aCurrentPtr++;
       
  5926 
       
  5927 	TInt16 spaceAlreadyAllocated = 0; // handle architectures whose address space increments and whose address space decrements.
       
  5928 	(aCurrentPtr > startPtr) ? (spaceAlreadyAllocated = aCurrentPtr - startPtr) : (spaceAlreadyAllocated = startPtr - aCurrentPtr);
       
  5929 
       
  5930 	TInt16 remainingSize = (TInt16)(CEnhancedVoiceMailNotification::KSmsMaxEnhancedVoiceMailSize - spaceAlreadyAllocated);
       
  5931 	for (TUint i = 0; i < count; i++)
       
  5932 	    {
       
  5933 	    remainingSize -= (TInt16)(*iNotifications)[i]->SizeL(aCharacterSetConverter,aFs);
       
  5934 	    if (remainingSize < 0)
       
  5935 	        {
       
  5936 	        User::Leave(KErrArgument);
       
  5937 	        }
       
  5938 
       
  5939 	    aCurrentPtr = (*iNotifications)[i]->EncodeL(aCurrentPtr, aCharacterSetConverter, aFs);
       
  5940 	    }
       
  5941 
       
  5942 	return aCurrentPtr;
       
  5943 	} // CEnhancedVoiceMailNotification::EncodeL
       
  5944 
       
  5945 
       
  5946 void CEnhancedVoiceMailNotification::DecodeL(TGsmuLex8& aVoiceMailInfo, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
       
  5947 	{
       
  5948 	LOGGSMU1("CEnhancedVoiceMailNotification::DecodeL");
       
  5949 
       
  5950 	CEnhancedVoiceMailBoxInformation::DecodeL(aVoiceMailInfo, aCharacterSetConverter, aFs);
       
  5951 
       
  5952 	TUint8 numberOfNotifications = (aVoiceMailInfo.GetL() & KSmsNotificationBitMask);
       
  5953 
       
  5954 	if (iExtensionIndicator)
       
  5955 	    {
       
  5956 	    TUint8 extensionLength = aVoiceMailInfo.GetL();
       
  5957 	    aVoiceMailInfo.Inc(extensionLength);
       
  5958 	    }
       
  5959 
       
  5960 	for (TUint8 i = 0; i < numberOfNotifications; i++)
       
  5961 	    {
       
  5962 	    CVoiceMailNotification* voiceMailNotification = CVoiceMailNotification::NewL();
       
  5963 	    CleanupStack::PushL(voiceMailNotification);
       
  5964 	    voiceMailNotification->DecodeL(aVoiceMailInfo, aCharacterSetConverter, aFs);
       
  5965 	    iNotifications->AppendL(voiceMailNotification);
       
  5966 	    CleanupStack::Pop(voiceMailNotification);
       
  5967 	    }
       
  5968 	} // CEnhancedVoiceMailNotification::DecodeL
       
  5969 
       
  5970 
       
  5971 /**
       
  5972  *  @publishedAll
       
  5973  *  
       
  5974  *  Sets the message ID of the specific Voice Mail message
       
  5975  *  whose deletion is being confirmed.
       
  5976  *  
       
  5977  *  @param aMessageId
       
  5978  *  The message ID of the specific voice mail message whose deletion
       
  5979  *  is being confirmed.
       
  5980  *  
       
  5981  *  @capability None
       
  5982  */
       
  5983 EXPORT_C void CVoiceMailDeletion::SetMessageId(TUint16 aMessageId)
       
  5984 	{
       
  5985 	LOGGSMU1("CVoiceMailDeletion::SetMessageId()");
       
  5986 
       
  5987 	iMessageId=aMessageId;
       
  5988 	} // CVoiceMailDeletion::SetMessageId
       
  5989 
       
  5990 
       
  5991 /**
       
  5992  *  @publishedAll
       
  5993  *  
       
  5994  *  Retrieves the message ID of the Voice Mail message
       
  5995  *  whose deletion is being confirmed, range 0 to 65535.
       
  5996  *  
       
  5997  *  @return
       
  5998  *  The message ID of the Voice Mail message whose deletion
       
  5999  *  is being confirmed, range 0 to 65535.
       
  6000  *  
       
  6001  *  @capability None
       
  6002  */
       
  6003 EXPORT_C TUint16 CVoiceMailDeletion::MessageId() const
       
  6004 	{
       
  6005 	LOGGSMU1("CVoiceMailDeletion::MessageId()");
       
  6006 
       
  6007 	return iMessageId;
       
  6008 	} // CVoiceMailDeletion::MessageId
       
  6009 
       
  6010 
       
  6011 /**
       
  6012  *  @publishedAll
       
  6013  *  
       
  6014  *  Indicates whether the voice mail deletion contains extension bytes.
       
  6015  *  
       
  6016  *  @return
       
  6017  *  True if the voice mail deletion contains extension bytes.
       
  6018  *  False otherwise.
       
  6019  *  
       
  6020  *  @capability None
       
  6021  */
       
  6022 EXPORT_C TBool CVoiceMailDeletion::MessageExtensionIndication() const
       
  6023 	{
       
  6024 	LOGGSMU1("CVoiceMailDeletion::MessageExtensionIndication()");
       
  6025 
       
  6026 	return iExtensionIndicator;
       
  6027 	} // CVoiceMailDeletion::MessageExtensionIndication
       
  6028 
       
  6029 
       
  6030 TUint8 CVoiceMailDeletion::SizeL()
       
  6031 	{
       
  6032 	LOGGSMU1("CVoiceMailDeletion::SizeL()");
       
  6033 
       
  6034 	const TUint8 KSizeOfVoiceMailDeletion = 3;
       
  6035 	return KSizeOfVoiceMailDeletion;
       
  6036 	} // CVoiceMailDeletion::SizeL
       
  6037 
       
  6038 
       
  6039 TUint8* CVoiceMailDeletion::EncodeL(TUint8* aPtr) const
       
  6040 	{
       
  6041 	// When changes are made which affect the
       
  6042 	// number of bytes encoded, this should be
       
  6043 	// reflected in VoiceMailDeletion::SizeL()
       
  6044 	LOGGSMU1("CVoiceMailDeletion::EncodeL");
       
  6045 
       
  6046 	*aPtr =  (TUint8) (iMessageId >> 8);
       
  6047 	aPtr++;
       
  6048 	*aPtr =  (TUint8) iMessageId;
       
  6049 	aPtr++;
       
  6050 	*aPtr = ((TUint8) iExtensionIndicator) << 7;
       
  6051 	aPtr++;
       
  6052 	return aPtr;
       
  6053 	} // CVoiceMailDeletion::EncodeL
       
  6054 
       
  6055 
       
  6056 void CVoiceMailDeletion::DecodeL(TGsmuLex8& aVoiceMailInfo)
       
  6057 	{
       
  6058 	LOGGSMU1("CVoiceMailDeletion::DecodeL");
       
  6059 
       
  6060 	iMessageId = (((TUint16) aVoiceMailInfo.GetL()) << 8) +
       
  6061 	              ((TUint16) aVoiceMailInfo.GetL());
       
  6062 	iExtensionIndicator =    (aVoiceMailInfo.GetL() >> 7);
       
  6063 
       
  6064 	if (iExtensionIndicator)
       
  6065 	    {
       
  6066 	    TUint8 extensionLength = aVoiceMailInfo.GetL();
       
  6067 	    aVoiceMailInfo.Inc(extensionLength);
       
  6068 	    }
       
  6069 	} // CVoiceMailDeletion::DecodeL
       
  6070 
       
  6071 
       
  6072 CVoiceMailDeletion::CVoiceMailDeletion()
       
  6073 	{
       
  6074 	iMessageId = 0;
       
  6075 	iExtensionIndicator = EFalse;
       
  6076 	} // CVoiceMailDeletion::CVoiceMailDeletion
       
  6077 
       
  6078 
       
  6079 /**
       
  6080  *  @internalComponent
       
  6081  *  
       
  6082  *  Prevent clients from using the copy constructor by including it in the class definition
       
  6083  *  but making it protected and not exporting it.
       
  6084  *  
       
  6085  *  @capability None
       
  6086  */
       
  6087 CVoiceMailDeletion::CVoiceMailDeletion(const CVoiceMailDeletion&)
       
  6088     {
       
  6089     // Ignore in code coverage - not intended to be used
       
  6090     BULLSEYE_OFF    
       
  6091     LOGGSMU1("CVoiceMailDeletion::CVoiceMailDeletion");
       
  6092     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6093     BULLSEYE_RESTORE
       
  6094     }
       
  6095 
       
  6096 /**
       
  6097  *  @internalComponent
       
  6098  *  
       
  6099  *  Prevent clients from using the equality operator by including it in the class definition
       
  6100  *  but making it protected and not exporting it.
       
  6101  *  
       
  6102  *  @capability None
       
  6103  */
       
  6104 TBool CVoiceMailDeletion::operator==(const CVoiceMailDeletion&)
       
  6105     {
       
  6106     // Ignore in code coverage - not intended to be used
       
  6107     BULLSEYE_OFF    
       
  6108     LOGGSMU1("CVoiceMailDeletion::operator==");
       
  6109     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6110     return EFalse;
       
  6111     BULLSEYE_RESTORE
       
  6112     }
       
  6113 
       
  6114 /**
       
  6115  *  @internalComponent
       
  6116  *  
       
  6117  *  Prevent clients from using the assignment operator by including it in the class definition
       
  6118  *  but making it protected and not exporting it.
       
  6119  *  
       
  6120  *  @capability None
       
  6121  */
       
  6122 void CVoiceMailDeletion::operator=(const CVoiceMailDeletion&)
       
  6123     {
       
  6124     // Ignore in code coverage - not intended to be used
       
  6125     BULLSEYE_OFF    
       
  6126     LOGGSMU1("CVoiceMailDeletion::operator=");
       
  6127     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6128     BULLSEYE_RESTORE
       
  6129     }
       
  6130 
       
  6131 /**
       
  6132  *  @publishedAll
       
  6133  *  
       
  6134  *  Class destructor.
       
  6135  *  
       
  6136  *  @capability None
       
  6137  */
       
  6138 EXPORT_C CVoiceMailDeletion::~CVoiceMailDeletion()
       
  6139 	{
       
  6140 	LOGGSMU1("CVoiceMailDeletion::~CVoiceMailDeletion");
       
  6141 
       
  6142 	delete iExtension;
       
  6143 	} // CVoiceMailDeletion::operator
       
  6144 
       
  6145 
       
  6146 void CVoiceMailDeletion::ConstructL()
       
  6147 	{
       
  6148 	LOGGSMU1("CVoiceMailDeletion::ConstructL()");
       
  6149 
       
  6150 	NewBufferL(0);
       
  6151 	} // CVoiceMailDeletion::ConstructL
       
  6152 
       
  6153 
       
  6154 void CVoiceMailDeletion::NewBufferL(TInt aLength)
       
  6155 	{
       
  6156 	LOGGSMU1("CVoiceMailDeletion::NewBufferL()");
       
  6157 
       
  6158 	HBufC* buffer=HBufC::NewL(aLength);
       
  6159 	delete iExtension;
       
  6160 	iExtension=buffer;
       
  6161 	iExtension->Des().SetLength(aLength);
       
  6162 	iExtension->Des().FillZ();
       
  6163 	} // CVoiceMailDeletion::NewBufferL
       
  6164 
       
  6165 
       
  6166 /**
       
  6167  *  @publishedAll
       
  6168  *  
       
  6169  *  Class constructor
       
  6170  *  
       
  6171  *  @capability None
       
  6172  */
       
  6173 EXPORT_C CVoiceMailDeletion* CVoiceMailDeletion::NewL()
       
  6174 	{
       
  6175 	LOGGSMU1("CVoiceMailDeletion::NewL()");
       
  6176 
       
  6177 	CVoiceMailDeletion* voiceMailDeletion=new(ELeave) CVoiceMailDeletion();
       
  6178 	CleanupStack::PushL(voiceMailDeletion);
       
  6179 	voiceMailDeletion->ConstructL();
       
  6180 	CleanupStack::Pop(voiceMailDeletion);
       
  6181 	return voiceMailDeletion;
       
  6182 	} // CVoiceMailDeletion::NewL
       
  6183 
       
  6184 
       
  6185 /*
       
  6186 void CVoiceMailDeletion::SetExtension(TDesC& aExtension)
       
  6187 	{
       
  6188 	LOGGSMU1("CVoiceMailDeletion::SetExtension()");
       
  6189 
       
  6190 	TInt length=aExtension.Length();
       
  6191 	NewBufferL(length);
       
  6192 	iExtension->Des().Copy(aExtension);
       
  6193 	} // CVoiceMailDeletion::SetExtension
       
  6194 
       
  6195 
       
  6196 TPtrC CVoiceMailDeletion::Extension() const
       
  6197 	{
       
  6198 	LOGGSMU1("CVoiceMailDeletion::Extension()");
       
  6199 
       
  6200 	TPtrC ptr;
       
  6201 	if (iExtension)
       
  6202 	    ptr.Set(iExtension->Des());
       
  6203 	return ptr;
       
  6204 	}*/
       
  6205 
       
  6206 
       
  6207 void CEnhancedVoiceMailDeleteConfirmations::NewExtensionL(TInt aLength)
       
  6208 	{
       
  6209 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::NewExtensionL()");
       
  6210 
       
  6211 	HBufC* buffer=HBufC::NewL(aLength);
       
  6212 	delete iExtension;
       
  6213 	iExtension=buffer;
       
  6214 	iExtension->Des().SetLength(aLength);
       
  6215 	iExtension->Des().FillZ();
       
  6216 	} // CEnhancedVoiceMailDeleteConfirmations::NewExtensionL
       
  6217 
       
  6218 
       
  6219 CEnhancedVoiceMailDeleteConfirmations::CEnhancedVoiceMailDeleteConfirmations() : CEnhancedVoiceMailBoxInformation(EGsmSmsVoiceMailDeleteConfirmation)
       
  6220 	{
       
  6221 	//NOP
       
  6222 	} // CEnhancedVoiceMailDeleteConfirmations::CEnhancedVoiceMailDeleteConfirmations
       
  6223 
       
  6224 
       
  6225 /**
       
  6226  *  @publishedAll
       
  6227  *  
       
  6228  *  Class destructor
       
  6229  *  
       
  6230  *  @capability None
       
  6231  */
       
  6232 EXPORT_C  CEnhancedVoiceMailDeleteConfirmations::~CEnhancedVoiceMailDeleteConfirmations()
       
  6233 	{
       
  6234 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::~CEnhancedVoiceMailDeleteConfirmations");
       
  6235 
       
  6236 	delete iExtension;
       
  6237 	iVoiceMailDeletions->ResetAndDestroy();
       
  6238 	iVoiceMailDeletions->Close();
       
  6239 	delete iVoiceMailDeletions;
       
  6240 	} // CEnhancedVoiceMailDeleteConfirmations::CEnhancedVoiceMailDeleteConfirmations
       
  6241 
       
  6242 
       
  6243 /**
       
  6244  *  @internalComponent
       
  6245  *  
       
  6246  *  Prevent clients from using the copy constructor by including it in the class definition
       
  6247  *  but making it protected and not exporting it.
       
  6248  *  
       
  6249  *  @capability None
       
  6250  */
       
  6251 CEnhancedVoiceMailDeleteConfirmations::CEnhancedVoiceMailDeleteConfirmations(const CEnhancedVoiceMailDeleteConfirmations&)
       
  6252     {
       
  6253     // Ignore in code coverage - not intended to be used
       
  6254     BULLSEYE_OFF    
       
  6255     LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::CEnhancedVoiceMailDeleteConfirmations");
       
  6256     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6257     BULLSEYE_RESTORE
       
  6258     }
       
  6259 
       
  6260 /**
       
  6261  *  @internalComponent
       
  6262  *  
       
  6263  *  Prevent clients from using the equality operator by including it in the class definition
       
  6264  *  but making it protected and not exporting it.
       
  6265  *  
       
  6266  *  @capability None
       
  6267  */
       
  6268 TBool CEnhancedVoiceMailDeleteConfirmations::operator==(const CEnhancedVoiceMailDeleteConfirmations&)
       
  6269     {
       
  6270     // Ignore in code coverage - not intended to be used
       
  6271     BULLSEYE_OFF    
       
  6272     LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::operator==");
       
  6273     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6274     return EFalse;
       
  6275     BULLSEYE_RESTORE
       
  6276     }
       
  6277 
       
  6278 /**
       
  6279  *  @internalComponent
       
  6280  *  
       
  6281  *  Prevent clients from using the assignment operator by including it in the class definition
       
  6282  *  but making it protected and not exporting it.
       
  6283  *  
       
  6284  *  @capability None
       
  6285  */
       
  6286 void CEnhancedVoiceMailDeleteConfirmations::operator=(const CEnhancedVoiceMailDeleteConfirmations&)
       
  6287     {
       
  6288     // Ignore in code coverage - not intended to be used
       
  6289     BULLSEYE_OFF    
       
  6290     LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::operator=");
       
  6291     Panic(KGsmuPanicMethodBodyNotImplemented);
       
  6292     BULLSEYE_RESTORE
       
  6293     }
       
  6294 
       
  6295 void CEnhancedVoiceMailDeleteConfirmations::ConstructL()
       
  6296 	{
       
  6297 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::ConstructL()");
       
  6298 
       
  6299 	NewExtensionL(0);
       
  6300 
       
  6301 	iVoiceMailDeletions = new (ELeave) RPointerArray<CVoiceMailDeletion>(15);
       
  6302 	} // CEnhancedVoiceMailDeleteConfirmations::ConstructL
       
  6303 
       
  6304 
       
  6305 /**
       
  6306  *  @publishedAll
       
  6307  *  
       
  6308  *  Class constructor
       
  6309  *  
       
  6310  *  @capability None
       
  6311  */
       
  6312 EXPORT_C  CEnhancedVoiceMailDeleteConfirmations* CEnhancedVoiceMailDeleteConfirmations::NewL()
       
  6313 	{
       
  6314 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::NewL()");
       
  6315 
       
  6316 	CEnhancedVoiceMailDeleteConfirmations* aCEnhancedVoiceMailDeleteConfirmations=new(ELeave) CEnhancedVoiceMailDeleteConfirmations();
       
  6317 	CleanupStack::PushL(aCEnhancedVoiceMailDeleteConfirmations);
       
  6318 	aCEnhancedVoiceMailDeleteConfirmations->CEnhancedVoiceMailBoxInformation::ConstructL();
       
  6319 	aCEnhancedVoiceMailDeleteConfirmations->ConstructL();
       
  6320 	CleanupStack::Pop(aCEnhancedVoiceMailDeleteConfirmations);
       
  6321 	return aCEnhancedVoiceMailDeleteConfirmations;
       
  6322 	} // CEnhancedVoiceMailDeleteConfirmations::NewL
       
  6323 
       
  6324 
       
  6325 /**
       
  6326  *  @publishedAll
       
  6327  *  
       
  6328  *  Indicates the number of message IDs that follow in this IE.
       
  6329  *  
       
  6330  *  @return
       
  6331  *  The number of message IDs that follow.
       
  6332  *  
       
  6333  *  @capability None
       
  6334  */
       
  6335 EXPORT_C TUint8  CEnhancedVoiceMailDeleteConfirmations::NumberOfDeletes()
       
  6336 	{
       
  6337 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::NumberOfDeletes()");
       
  6338 
       
  6339 	return iVoiceMailDeletions->Count();
       
  6340 	} // CEnhancedVoiceMailDeleteConfirmations::NumberOfDeletes
       
  6341 
       
  6342 
       
  6343 /**
       
  6344  *  @publishedAll
       
  6345  *  
       
  6346  *  Provides a reference to the collection that is used to contain the Voice Mail Deletion
       
  6347  *  notifications. Up to 31 instances of CVoiceMailDeletion can be stored. If more than
       
  6348  *  31 instances are added, the CEnhancedVoiceMailDeleteConfirmations will not be added to
       
  6349  *  the CSmsMessage.
       
  6350  *  
       
  6351  *  @return
       
  6352  *  A reference to the collection that is used to contain the Voice Mail Deletion
       
  6353  *  notifications.
       
  6354  *  
       
  6355  *  @capability None
       
  6356  */
       
  6357 EXPORT_C RPointerArray<CVoiceMailDeletion>& CEnhancedVoiceMailDeleteConfirmations::GetVoiceMailDeletions()
       
  6358 	{
       
  6359 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::GetVoiceMailDeletions()");
       
  6360 
       
  6361 	return *iVoiceMailDeletions;
       
  6362 	} // CEnhancedVoiceMailDeleteConfirmations::GetVoiceMailDeletions
       
  6363 
       
  6364 
       
  6365 /*
       
  6366 void CEnhancedVoiceMailDeleteConfirmations::SetExtension(TDesC& aExtension)
       
  6367 	{
       
  6368 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::SetExtension()");
       
  6369 
       
  6370 	TInt length=aExtension.Length();
       
  6371 	NewBufferL(length);
       
  6372 	iExtension->Des().Copy(aExtension);
       
  6373 	} // CEnhancedVoiceMailDeleteConfirmations::SetExtension
       
  6374 
       
  6375 
       
  6376 TPtrC CEnhancedVoiceMailDeleteConfirmations::Extension() const
       
  6377 	{
       
  6378 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::Extension()");
       
  6379 
       
  6380 	TPtrC ptr;
       
  6381 	if (iExtension)
       
  6382 		{
       
  6383 		ptr.Set(iExtension->Des());
       
  6384 		}
       
  6385 	return ptr;
       
  6386 	}*/
       
  6387 
       
  6388 
       
  6389 TUint8* CEnhancedVoiceMailDeleteConfirmations::EncodeL(TUint8* aCurrentPtr, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) const
       
  6390 	{
       
  6391 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::EncodeL");
       
  6392 
       
  6393 	TUint8* startPtr   = aCurrentPtr;
       
  6394 
       
  6395 	aCurrentPtr = CEnhancedVoiceMailBoxInformation::EncodeL(aCurrentPtr, aCharacterSetConverter, aFs);
       
  6396 
       
  6397 	TUint8 count = ((TUint8)iVoiceMailDeletions->Count());
       
  6398 
       
  6399 	if (count > KMaxNumberOfNotifications)
       
  6400 	    {
       
  6401 	    User::Leave(KErrArgument);
       
  6402 	    }
       
  6403 
       
  6404 	*aCurrentPtr= (count & KSmsNotificationBitMask);
       
  6405 	aCurrentPtr++;
       
  6406 
       
  6407 	TInt16 spaceAlreadyAllocated; // handle architectures whose address space increments and whose address space decrements.
       
  6408 	(aCurrentPtr > startPtr) ? (spaceAlreadyAllocated = aCurrentPtr - startPtr) : (spaceAlreadyAllocated = startPtr - aCurrentPtr);
       
  6409 
       
  6410 	// allow space for id and length bytes
       
  6411 	TInt16 remainingSize = (TInt16)(CEnhancedVoiceMailBoxInformation::KSmsMaxEnhancedVoiceMailSize - spaceAlreadyAllocated);
       
  6412 
       
  6413 	for (TUint i = 0; i < count; i++)
       
  6414 	    {
       
  6415 	    remainingSize -= (TInt16)(*iVoiceMailDeletions)[i]->SizeL();
       
  6416 	    if (remainingSize < 0)
       
  6417 	        {
       
  6418 	        User::Leave(KErrArgument);
       
  6419 	        }
       
  6420 
       
  6421 	    aCurrentPtr = (*iVoiceMailDeletions)[i]->EncodeL(aCurrentPtr);
       
  6422 	    }
       
  6423 
       
  6424 	return aCurrentPtr;
       
  6425 	} // CEnhancedVoiceMailDeleteConfirmations::EncodeL
       
  6426 
       
  6427 
       
  6428 void CEnhancedVoiceMailDeleteConfirmations::DecodeL(TGsmuLex8& aVoiceMailInfo, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
       
  6429 	{
       
  6430 	LOGGSMU1("CEnhancedVoiceMailDeleteConfirmations::DecodeL");
       
  6431 
       
  6432 	CEnhancedVoiceMailBoxInformation::DecodeL(aVoiceMailInfo, aCharacterSetConverter, aFs);
       
  6433 
       
  6434 	TUint numberOfVMDeletions = (aVoiceMailInfo.GetL() & KSmsNotificationBitMask);
       
  6435 
       
  6436 	if (iExtensionIndicator)
       
  6437 		{
       
  6438 		TUint8 extensionLength = aVoiceMailInfo.GetL();
       
  6439 		aVoiceMailInfo.Inc(extensionLength);
       
  6440 		}
       
  6441 
       
  6442 	for (TUint8 i = 0; i < numberOfVMDeletions; i++)
       
  6443 		{
       
  6444 		// Create a Voice Mail Deletion
       
  6445 		CVoiceMailDeletion* voiceMailDeletion = CVoiceMailDeletion::NewL();
       
  6446 		CleanupStack::PushL(voiceMailDeletion);
       
  6447 		voiceMailDeletion->DecodeL(aVoiceMailInfo);
       
  6448 		CleanupStack::Pop(voiceMailDeletion);
       
  6449 		iVoiceMailDeletions->Append(voiceMailDeletion);
       
  6450 		}
       
  6451 	} // CEnhancedVoiceMailDeleteConfirmations::DecodeL