messagingappbase/smsmtm/clientmtm/src/SMSCLNT.CPP
changeset 25 84d9eb65b26f
parent 23 238255e8b033
child 27 e4592d119491
child 37 518b245aa84c
child 79 2981cb3aa489
equal deleted inserted replaced
23:238255e8b033 25:84d9eb65b26f
     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 // SMSCLNT.CPP
       
    15 //
       
    16 
       
    17 #include <txtrich.h>	// CRichText
       
    18 
       
    19 #include <msvuids.h>	// KUidMsvRootEntry etc.
       
    20 #include <mtmdef.hrh>	// KUidMtmQuerySupports etc.
       
    21 #include <mtmdef.h>		// KMsvMessagePartRecipient	etc.
       
    22 #include <msvids.h>		// KMsvGlobalOutBoxIndexEntryId etc.
       
    23 #include <msvftext.h>	// CMsvFindText
       
    24 #include <biodb.h>		// CBIODatabase
       
    25 #include <SMSS.rsg>
       
    26 #include <barsc.h>
       
    27 #include <barsread.h>
       
    28 
       
    29 #include "SMSCLNT.H"	// smsclntmtm
       
    30 #include "SMCMMAIN.H"	// panics
       
    31 #include "smscmds.h"	// ESmsMtmCommandReadServiceCenter etc.
       
    32 #include "smut.h"		// TSmsUtilities
       
    33 #include "SMUTHDR.H"	// CSmsHeader
       
    34 #include "SMUTSET.H"	// CSmsSettings
       
    35 #include <smutsimparam.h>
       
    36 #include <csmsemailfields.h>
       
    37 #include <csmsaccount.h>
       
    38 #include "csmssendmessageoperation.h"
       
    39 
       
    40 #include <msvenhancesearchsortutil.h>
       
    41 
       
    42 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
       
    43 #include "msvconsts.h"
       
    44 #include <mtmuidsdef.hrh>
       
    45 #include <tmsvsmsentry.h>
       
    46 #endif
       
    47 
       
    48 
       
    49 
       
    50 /**
       
    51 The maximum number of SMS PDUs allowed in a concatenated SMS message.
       
    52 Together with KSmcmMaxCharsInMessageConcatenated7Bit, this is the response to
       
    53 the query for the KUidMtmQueryMaxTotalMsgSizeValue capability.
       
    54 @see	CSmsClientMtm::QueryCapability
       
    55 @see	KSmcmMaxCharsInMessageConcatenated7Bit
       
    56 */
       
    57 const TInt KSmcmMaxMessageNumber=0x32;
       
    58 
       
    59 /**
       
    60 The maximum number of characters in a concatenated SMS PDU.
       
    61 Together with KSmcmMaxMessageNumber, this is the response to the query for the
       
    62 KUidMtmQueryMaxTotalMsgSizeValue capability.
       
    63 @see	CSmsClientMtm::QueryCapability
       
    64 @see	KSmcmMaxCharsInMessageConcatenated7Bit
       
    65 */
       
    66 const TInt KSmcmMaxCharsInMessageConcatenated7Bit=0x99;
       
    67 
       
    68 /**
       
    69 The maximum number of characters in a non-concatenated SMS PDU.
       
    70 This is the response to the query for the KUidMtmQueryMaxBodySizeValue
       
    71 capability.
       
    72 @see	CSmsClientMtm::QueryCapability
       
    73 */
       
    74 const TInt KSmcmMaxTotalMsgSize=160;
       
    75 
       
    76 /**
       
    77 The granularity of the in-memory buffer for CRichText objects.
       
    78 @see	CRichText::NewL
       
    79 */
       
    80 const TInt KSmcmRichTextConstant=256;
       
    81 
       
    82 
       
    83 // These default subject formats are used if the resource field has not been
       
    84 // migrated to include a localised set of subject formats.
       
    85 _LIT(KSmsDefaultForwardSubjectFormat,	"Fw: %S");
       
    86 _LIT(KSmsDefaultReplySubjectFormat,		"Re: %S");
       
    87 
       
    88 /**
       
    89 Static factory constuctor.
       
    90 
       
    91 @param	aRegisteredMtmDll
       
    92 The registry information for the SMS MTM.
       
    93 
       
    94 @param	aSession
       
    95 The message server session
       
    96 
       
    97 @leave KErrArgument
       
    98 Invalid data read from the SMS resource file
       
    99 
       
   100 @internalTechnology
       
   101 
       
   102 @see	CRegisteredMtmDll
       
   103 */
       
   104 EXPORT_C CSmsClientMtm* CSmsClientMtm::NewL(CRegisteredMtmDll& aRegisteredMtmDll,CMsvSession& aSession)
       
   105 	{
       
   106 	CSmsClientMtm* self=new(ELeave) CSmsClientMtm(aRegisteredMtmDll,aSession);
       
   107 	CleanupStack::PushL(self);
       
   108 	self->ConstructL();
       
   109 	CleanupStack::Pop(self);
       
   110 	return self;
       
   111 	}
       
   112 
       
   113 /**
       
   114 Destructor.
       
   115 */
       
   116 CSmsClientMtm::~CSmsClientMtm()
       
   117 	{
       
   118 	delete iServiceSettings;
       
   119 	delete iSmsHeader;
       
   120 	delete iEmailForwardSubjectFormat;
       
   121 	delete iEmailReplySubjectFormat;
       
   122 	}
       
   123 
       
   124 void CSmsClientMtm::HandleEntryEvent(enum MMsvEntryObserver::TMsvEntryEvent /*aEvent*/,TAny* ,TAny* ,TAny* )
       
   125 	{
       
   126 	}
       
   127 
       
   128 /**
       
   129 Reads SMS parameters from the SIM.
       
   130 
       
   131 It starts a new CSmsSimParamOperation, which uses the SMS Server MTM to read the 
       
   132 SMS parameters from the SIM. 
       
   133 
       
   134 If the phone is unable to supply the SMS parameters from the SIM, then the progress
       
   135 information of the CSmsSimParamOperation operation will contain an error. 
       
   136 
       
   137 @param	aObserverRequestStatus
       
   138 The request status to be completed when the read operation has completed.
       
   139 
       
   140 @return
       
   141 A SIM parameter reader operation. The read SIM parameters are stored in
       
   142 CSmsSimParamOperation::iSimParams. 
       
   143 */
       
   144 EXPORT_C CSmsSimParamOperation* CSmsClientMtm::ReadSimParamsL(TRequestStatus& aObserverRequestStatus)
       
   145 	{
       
   146 	RestoreServiceAndSettingsL();
       
   147 
       
   148 	CMsvEntry* entry = Session().GetEntryL(iServiceId);
       
   149 	CleanupStack::PushL(entry);
       
   150 
       
   151 	CSmsSimParamOperation* op = CSmsSimParamOperation::ReadSimParamsL(entry->Entry().iMtm, iServiceId, Session(), aObserverRequestStatus);
       
   152 
       
   153 	CleanupStack::PopAndDestroy(entry);
       
   154 	return op;
       
   155 	}
       
   156 
       
   157 /**
       
   158 Writes SMS parameters to the SIM.
       
   159 
       
   160 It starts a new CSmsSimParamOperation, which uses the SMS Server to write the 
       
   161 specified SIM parameters to the SIM.
       
   162 
       
   163 If the phone is unable to write the SMS parameters to the SIM, then the progress
       
   164 information of the CSmsSimParamOperation operation will contain an error.
       
   165 
       
   166 @param	aList
       
   167 The SIM parameters to be written.
       
   168 
       
   169 @param	aObserverRequestStatus
       
   170 The request status to be completed when the write operation has completed.
       
   171 
       
   172 @return
       
   173 A SIM parameter writer operation.
       
   174 */
       
   175 EXPORT_C CSmsSimParamOperation* CSmsClientMtm::WriteSimParamsL(const CMobilePhoneSmspList& aList, TRequestStatus& aObserverRequestStatus)
       
   176 	{
       
   177 	RestoreServiceAndSettingsL();
       
   178 
       
   179 	CMsvEntry* entry = Session().GetEntryL(iServiceId);
       
   180 	CleanupStack::PushL(entry);
       
   181 
       
   182 	CSmsSimParamOperation* op = CSmsSimParamOperation::WriteSimParamsL(aList, entry->Entry().iMtm, iServiceId, Session(), aObserverRequestStatus);
       
   183 
       
   184 	CleanupStack::PopAndDestroy(entry);
       
   185 
       
   186 	return op;
       
   187 	}
       
   188 
       
   189 /**
       
   190 Restores the SMS service ID and SMS service settings.
       
   191 
       
   192 The SMS service ID is obtained. The service settings for the obtained ID are 
       
   193 restored from the message server. The SMS service ID can be obtained using the
       
   194 CSmsClientMtm::ServiceId API and the SMS settings are accessed via the two
       
   195 CSmsClientMtm::ServiceSettings API overloads.
       
   196 
       
   197 This API should be used before using any of the other APIs that required the SMS
       
   198 service ID and SMS service settings to be set.
       
   199 
       
   200 @see	CSmsClientMtm::ServiceId
       
   201 @see	CSmsClientMtm::ServiceSettings
       
   202 */
       
   203 EXPORT_C void CSmsClientMtm::RestoreServiceAndSettingsL()
       
   204 	{
       
   205 	if (iServiceSettings == NULL)
       
   206 		{
       
   207 		iServiceSettings = CSmsSettings::NewL();
       
   208 		}
       
   209 
       
   210 	// Let's find the right service entry!
       
   211 	TSmsUtilities::ServiceIdL(Session(), iServiceId, KUidMsgTypeSMS);
       
   212 
       
   213 	CSmsAccount* account = CSmsAccount::NewLC();
       
   214 	// just v2
       
   215 	account->LoadSettingsL(*iServiceSettings);
       
   216 	CleanupStack::PopAndDestroy(account);    
       
   217 	}
       
   218 
       
   219 
       
   220 CSmsClientMtm::CSmsClientMtm(CRegisteredMtmDll& aRegisteredMtmDll,CMsvSession& aSession)
       
   221 : CBaseMtm(aRegisteredMtmDll,aSession)
       
   222 	{
       
   223 	}
       
   224 
       
   225 void CSmsClientMtm::ConstructL()
       
   226 	{
       
   227 	SwitchCurrentEntryL(KMsvRootIndexEntryId);  //  Creates rich text
       
   228 	
       
   229 	RFs& fileSession = Session().FileSession();
       
   230 
       
   231 	iSmsHeader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body(),fileSession);
       
   232 
       
   233 	TRAPD(err, RestoreServiceAndSettingsL());
       
   234 
       
   235 	if (err)
       
   236 		{
       
   237 		if (err != KErrNotFound)
       
   238 			{
       
   239 			User::Leave(err);
       
   240 			}
       
   241 
       
   242 		TMsvEntry entry;
       
   243 		entry.iMtm = KUidMsgTypeSMS;
       
   244 		entry.iType = KUidMsvServiceEntry;
       
   245 		entry.SetReadOnly(EFalse);
       
   246 		entry.SetVisible(EFalse);
       
   247 		entry.iDate.UniversalTime();
       
   248 		entry.iDetails.Set(_L("Default SMS Message"));
       
   249     
       
   250 		CMsvEntry* root = Session().GetEntryL(KMsvRootIndexEntryId);
       
   251 		root->CreateL(entry);
       
   252 		iServiceId = entry.Id();
       
   253 		delete root;
       
   254 		}
       
   255 
       
   256 	//Initialise iRealAddressOpen and iRealAddressClose from the SMS resouce file
       
   257 	RResourceFile resFile = TSmsUtilities::OpenResourceFileL(fileSession);
       
   258 	CleanupClosePushL(resFile);
       
   259 	TBuf<4> buf;
       
   260 	TSmsUtilities::ReadResourceStringL(resFile, R_ADDRESSEE_TELEPHONE_OPEN, buf);
       
   261 	if (buf.Length() > 0)
       
   262 		{
       
   263 		iRealAddressOpen = buf[0];
       
   264 		}
       
   265 	else
       
   266 		{
       
   267 		User::Leave(KErrArgument); 
       
   268 		}
       
   269 	
       
   270 	TSmsUtilities::ReadResourceStringL(resFile, R_ADDRESSEE_TELEPHONE_CLOSE, buf);
       
   271 	if (buf.Length() > 0)
       
   272 		{
       
   273 		iRealAddressClose = buf[0];
       
   274 		}
       
   275 	else
       
   276 		{
       
   277 		User::Leave(KErrArgument); 
       
   278 		}
       
   279 	iEmailForwardSubjectFormat	= ReadEmailSubjectFormatL(resFile, R_SMS_EMAIL_FORWARD_SUBJECT_FORMAT, KSmsDefaultForwardSubjectFormat);
       
   280 	iEmailReplySubjectFormat	= ReadEmailSubjectFormatL(resFile, R_SMS_EMAIL_REPLY_SUBJECT_FORMAT, KSmsDefaultReplySubjectFormat);
       
   281 
       
   282 	CleanupStack::PopAndDestroy(&resFile);
       
   283 	}
       
   284 	
       
   285 HBufC* CSmsClientMtm::ReadEmailSubjectFormatL(RResourceFile& aResourceFile, TInt aResourceId, const TDesC& aDefaultFormat)
       
   286 	{
       
   287 	HBufC* format = NULL;
       
   288 	if( aResourceFile.OwnsResourceId(aResourceId) )
       
   289 		{
       
   290 		HBufC8* buf = aResourceFile.AllocReadLC(aResourceId);
       
   291 		TResourceReader reader;
       
   292 		reader.SetBuffer(buf);
       
   293 		format = (reader.ReadTPtrC()).AllocL();
       
   294 		CleanupStack::PopAndDestroy(buf);	
       
   295 		}
       
   296 	else
       
   297 		{
       
   298 		format = aDefaultFormat.AllocL();
       
   299 		}
       
   300 	return format;
       
   301 	}
       
   302 
       
   303 CMsvOperation* CSmsClientMtm::CreateNewEntryL(TMsvEntry& aNewEntry, TMsvId aDestination,CSmsHeader& aSmsHeader,const CRichText& aBody,TRequestStatus& aCompletionStatus)
       
   304 	{
       
   305 	RestoreServiceAndSettingsL();
       
   306 
       
   307 	CMsvEntry* cEntry = CMsvEntry::NewL(Session(), aDestination, TMsvSelectionOrdering());
       
   308 	CleanupStack::PushL(cEntry);
       
   309 
       
   310 	cEntry->CreateL(aNewEntry);
       
   311 
       
   312 	const TMsvId msvid = aNewEntry.Id();
       
   313 	Session().CleanupEntryPushL(msvid);
       
   314 
       
   315 	// switch context to the new entry
       
   316 	cEntry->SetEntryL(msvid);
       
   317 	aNewEntry = cEntry->Entry(); //for the description and details fields
       
   318 
       
   319 	aSmsHeader.SetSmsSettingsL(*iServiceSettings);
       
   320 
       
   321 	// service centre was not being set 
       
   322 	//If we haven't been provided with a service centre address then use the default one
       
   323 	if(!aSmsHeader.ReplyPathProvided())
       
   324 		{
       
   325 		TInt defaultSC = iServiceSettings->DefaultServiceCenter();
       
   326 		if(defaultSC > -1)
       
   327 			{
       
   328 			aSmsHeader.SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );	
       
   329 			}
       
   330 		}
       
   331 
       
   332 	// Check the context header to see an email message...
       
   333 	if( iSmsHeader->EmailFields().Length() > 0 )
       
   334 		{
       
   335 		// Yep - update the message as follows
       
   336 		// 1. Add the email <-> SMS gateway as the recipient of the new message.
       
   337 		// 2. Set the PID for interworking with email.
       
   338 		// 3. Set the entry description to be the email subject (if there is one).
       
   339 		// 4. Set the entry details to be the email address (if there is one).
       
   340 		DoAddRecipientL(&aSmsHeader, iSmsHeader->FromAddress(), KNullDesC);
       
   341 
       
   342 		CSmsPDU& pdu = aSmsHeader.Message().SmsPDU();
       
   343 		if( pdu.ProtocolIdentifierPresent() )
       
   344 			{
       
   345 			pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
       
   346 			pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
       
   347 			pdu.SetTelematicDeviceType(TSmsProtocolIdentifier::ESmsInternetElectronicMail);
       
   348 			}
       
   349 		
       
   350 		const CSmsEmailFields& fields = aSmsHeader.EmailFields();
       
   351 		if( fields.Subject().Length() > 0 )
       
   352 			{
       
   353 			// There is a subject - use this as the description
       
   354 			aNewEntry.iDescription.Set(fields.Subject());
       
   355 			}
       
   356 		if( fields.HasAddress() )
       
   357 			{
       
   358 			// There is an address - use first address as the details.
       
   359 			aNewEntry.iDetails.Set(fields.Addresses().MdcaPoint(0));			
       
   360 			}
       
   361 		}
       
   362 
       
   363 
       
   364 	CMsvStore* msvstore=cEntry->EditStoreL();
       
   365 	CleanupStack::PushL(msvstore);
       
   366 
       
   367 	aSmsHeader.StoreL(*msvstore);
       
   368 	msvstore->StoreBodyTextL(aBody);
       
   369 	msvstore->CommitL();
       
   370 
       
   371 	aNewEntry.iSize = msvstore->SizeL();
       
   372 	cEntry->ChangeL(aNewEntry);
       
   373 
       
   374 	CleanupStack::PopAndDestroy(msvstore);
       
   375 
       
   376 
       
   377 	TPckg<TMsvId> prog(msvid);
       
   378 	CMsvOperation* op = CMsvCompletedOperation::NewL(Session(), KUidMsgTypeSMS, prog, aNewEntry.iServiceId, aCompletionStatus);
       
   379 
       
   380 	// Now safe to pop the entry off the message server cleanup stack, and any
       
   381 	// other remaining resources.
       
   382 	Session().CleanupEntryPop();
       
   383 	CleanupStack::PopAndDestroy(cEntry);
       
   384 
       
   385 	return op;
       
   386 	}
       
   387 
       
   388 TBool CSmsClientMtm::ValidRecipients() const
       
   389 	{
       
   390 	TInt numrecipients = iSmsHeader->Recipients().Count();
       
   391 	TBool valid=numrecipients;
       
   392 
       
   393 	while (numrecipients-- && valid)
       
   394 		valid=ValidNumber(iSmsHeader->Recipients()[numrecipients]->Address());
       
   395 
       
   396 	return valid;
       
   397 	}
       
   398 
       
   399 TBool CSmsClientMtm::ValidNumber(const TDesC& aNumber) const
       
   400 	{
       
   401 	TBool valid=EFalse;
       
   402 	for (TInt i=0; i<aNumber.Length() && !valid; i++)  //  valid if at least one number in string
       
   403 		valid=(aNumber[i]>='0') && (aNumber[i]<='9');
       
   404 	return valid;
       
   405 	}
       
   406 
       
   407 void CSmsClientMtm::DoAddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias)
       
   408 	{
       
   409 	if (aAlias.Length())
       
   410 		{
       
   411 		HBufC* buf=HBufC::NewLC(aAlias.Length()+aRealAddress.Length()+3);
       
   412 		TPtr ptr = buf->Des();
       
   413 		ptr.Copy(aAlias);
       
   414 		ptr.Append(_L(" "));
       
   415 		ptr.Append(iRealAddressOpen);
       
   416 		ptr.Append(aRealAddress);
       
   417 		ptr.Append(iRealAddressClose);
       
   418 		iAddresseeList->AppendL(ptr);
       
   419 		CleanupStack::PopAndDestroy(buf);
       
   420 		}
       
   421 	else
       
   422 		iAddresseeList->AppendL(aRealAddress);
       
   423 	}
       
   424 
       
   425 void CSmsClientMtm::AddRecipientL(const TDesC& aRealAddress, const TDesC& aAlias)
       
   426 	{
       
   427 	DoAddRecipientL(iSmsHeader, aRealAddress, aAlias);
       
   428 	}
       
   429 
       
   430 void CSmsClientMtm::DoAddRecipientL(CSmsHeader* aSmsHeader, const TDesC& aRealAddress, const TDesC& aAlias)
       
   431 	{
       
   432 	CSmsNumber* recipient=CSmsNumber::NewL();
       
   433 	CleanupStack::PushL(recipient);
       
   434 	if ( aRealAddress.Locate('@') != KErrNotFound )
       
   435         {
       
   436         CSmsEmailFields* emailFields = NULL;
       
   437         if ( aSmsHeader->EmailFields().Length() > 0 )
       
   438             {
       
   439             emailFields = CSmsEmailFields::NewL( aSmsHeader->EmailFields() );
       
   440             }
       
   441         else
       
   442             {
       
   443             emailFields = CSmsEmailFields::NewL();
       
   444             }
       
   445         CleanupStack::PushL( emailFields );
       
   446        
       
   447 		recipient->SetEmailAddressL(aRealAddress, emailFields, aAlias);
       
   448        
       
   449         // Clears the CSmsHeaders EmailFields for non Email addresses
       
   450         aSmsHeader->SetEmailFieldsL( *emailFields );
       
   451         CleanupStack::PopAndDestroy( emailFields );
       
   452         }
       
   453 	else
       
   454 	    {
       
   455 	    recipient->SetAddressL(aRealAddress);
       
   456 	    if (aAlias.Length() > 0)
       
   457 	    	{	
       
   458 	        recipient->SetNameL(aAlias);
       
   459 	    	}
       
   460 	    }
       
   461     aSmsHeader->Recipients().AppendL(recipient);
       
   462     CleanupStack::Pop(recipient);
       
   463 	}
       
   464 
       
   465 void CSmsClientMtm::ResetHeader()
       
   466 	{
       
   467 	if (iSmsHeader)
       
   468 		iSmsHeader->Recipients().ResetAndDestroy();
       
   469 
       
   470 	if (iAddresseeList)
       
   471 		iAddresseeList->Reset();
       
   472 	}
       
   473 
       
   474 void CSmsClientMtm::FindInBodyL(const TDesC& aTextToFind, const TMsvPartList& aFoundList, TMsvPartList& aResult)
       
   475 	{
       
   476 	CMsvFindText* text=CMsvFindText::NewL();
       
   477 	CleanupStack::PushL(text);
       
   478 	if (text->FindRichTextL(aTextToFind,Body(),aFoundList))
       
   479 		aResult|=KMsvMessagePartBody;
       
   480 	CleanupStack::PopAndDestroy(text);
       
   481 	}
       
   482 
       
   483 void CSmsClientMtm::FindL(const TDesC& aTextToFind, const TMsvPartList aPartList, TMsvPartList& aFoundList)
       
   484 	{
       
   485 	
       
   486 	CMsvFindText* text=CMsvFindText::NewL();
       
   487 	CleanupStack::PushL(text);
       
   488 
       
   489 	// Enhance search and sort
       
   490   	// The setting variables are accessed by getting an instance to TMsvEnhanceSearchSortUtil  class
       
   491   	// This is accessed here by using GetExtensionData() defined in CBaseMtm which refers 
       
   492   	// to iExtensionData member variable
       
   493  	TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
       
   494 		
       
   495 	if(searchsortutil != NULL)
       
   496 		{
       
   497 		// For callees other than CMsvSearchsortOpOnHeaderBody class, searchsortutil pointer will be NULL	
       
   498 		
       
   499 		TInt index=0;
       
   500 		TBool foundinname = EFalse;
       
   501 		TBool foundinaddress = EFalse;
       
   502 
       
   503 		// Retrieve the search sort setting flags
       
   504 		TUint32 searchsortsetting=searchsortutil->GetSearchSortSetting();
       
   505 		
       
   506 		if(aPartList & KMsvMessagePartTo)
       
   507 			{
       
   508 			TInt count=iSmsHeader->Recipients().Count();
       
   509 			/* 
       
   510 			Search for the To field in the the SMS header
       
   511 			First it looks in the Senders name
       
   512 			if not found, it tries to find it in the senders numbers
       
   513 			*/
       
   514 			
       
   515 			for(TInt i=0;i<count;i++)
       
   516 				{
       
   517 				if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Name(),aPartList)))
       
   518 					{
       
   519 					aFoundList|=KMsvMessagePartTo;
       
   520 					foundinname = ETrue;
       
   521 					index = i;
       
   522 					}
       
   523 				if(!foundinname)
       
   524 					{
       
   525 					if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Address(),aPartList)))
       
   526 						{
       
   527 						aFoundList|=KMsvMessagePartTo;
       
   528 						foundinaddress = ETrue;
       
   529 						index = i;
       
   530 						}
       
   531 					}
       
   532 				}
       
   533 			}
       
   534 			// Search for the From field
       
   535 		else if(aPartList & KMsvMessagePartFrom)
       
   536 			{
       
   537 			if ((text->FindTextL(aTextToFind,iSmsHeader->FromAddress(),aPartList)) 
       
   538 		 	|| (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDetails,aPartList)))
       
   539 				{
       
   540 				aFoundList|=KMsvMessagePartFrom;
       
   541 				}
       
   542 			}
       
   543 			// Search for the Subject
       
   544 		else if (aPartList & KMsvMessagePartSubject)
       
   545 			{
       
   546 			if (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDescription,aPartList))
       
   547 				{
       
   548 				aFoundList|=KMsvMessagePartDescription;
       
   549 				}
       
   550 			}
       
   551 		/* Copy the sort data if sorting is specified.
       
   552 		 The operations being performed could be only be sort or it could be search and sort
       
   553 		 If the operation is search and sort than copy the sort data only if the
       
   554 		 search operation succeeded	*/
       
   555 					
       
   556 		if ((aPartList & EMessagePartSort ) || ((aPartList & EMessagePartSearchSort) && (aPartList & EMessagePartLastQueryOption) && aFoundList)) 
       
   557 			{
       
   558 			if (aPartList & EMessagePartToSort )
       
   559    				{
       
   560    				if(foundinname) // Copy the sort data form the senders name
       
   561    					{
       
   562    					TPtrC ptr((iSmsHeader->Recipients()).operator[](index)->Name());
       
   563    					SetExtensionData(&ptr);
       
   564    					}
       
   565    				if(foundinaddress) // Copy data from senders Address
       
   566    					{
       
   567    					TPtrC ptr((iSmsHeader->Recipients()).operator[](index)->Address());	
       
   568    					SetExtensionData(&ptr);
       
   569    					}
       
   570    				}
       
   571 			else if(aPartList & EMessagePartFromSort )
       
   572    				{
       
   573    				SetExtensionData((TAny*)(iSmsHeader->FromAddress().Ptr()));
       
   574    				}
       
   575    			else if(aPartList & EMessagePartSubjectSort )
       
   576    				{
       
   577    				SetExtensionData((TAny*)&iMsvEntry->Entry().iDescription);
       
   578 				}
       
   579 			else 
       
   580    				// Fix for DEF124605. If a different sort field is specified than
       
   581    				// sets setting flag to EMessagePartInvalidSortField
       
   582    				{
       
   583    				searchsortutil->SetSearchSortSetting(EMessagePartInvalidSortField);
       
   584    				}
       
   585 			}
       
   586 		}
       
   587 	else
       
   588 		{
       
   589 	
       
   590 		// Implementation prior to PREQ1667
       
   591 		if (aPartList & KMsvMessagePartRecipient) 		
       
   592 			{
       
   593 			TInt count=iSmsHeader->Recipients().Count();
       
   594 	
       
   595 			for(TInt i=0;i<count;i++)
       
   596 				{
       
   597 				if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Name(),aPartList))
       
   598 			 	|| (text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Address(),aPartList)))
       
   599 					{
       
   600 					aFoundList|=KMsvMessagePartRecipient;
       
   601 					}
       
   602 				}
       
   603 			}
       
   604 		else if(aPartList & KMsvMessagePartOriginator)
       
   605 			{
       
   606 			if((text->FindTextL(aTextToFind,iSmsHeader->FromAddress(),aPartList)) 
       
   607 			 || (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDetails,aPartList)))
       
   608 				{
       
   609 				aFoundList|=KMsvMessagePartOriginator;
       
   610 				}
       
   611 			}
       
   612 		else if (aPartList & KMsvMessagePartDescription)
       
   613 			{
       
   614 			if (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDescription,aPartList))
       
   615 				{
       
   616 				aFoundList|=KMsvMessagePartDescription;
       
   617 				}
       
   618 			}
       
   619 		}
       
   620 	CleanupStack::PopAndDestroy(text);
       
   621 	}
       
   622 
       
   623 
       
   624 TMsvPartList CSmsClientMtm::DoFindL(const TDesC& aTextToFind, TMsvPartList aPartList)
       
   625 	{
       
   626 	__ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
       
   627 
       
   628 	TMsvPartList retList = 0;
       
   629 
       
   630 	// Enhance search and sort
       
   631   	// The setting variables are accessed by getting an instance to TMsvEnhanceSearchSortUtil  class
       
   632   	// This is accessed here by using GetExtensionData() defined in CBaseMtm which refers 
       
   633   	// to iExtensionData member variable
       
   634 	
       
   635  	TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
       
   636 	
       
   637 	// For callees other than CMsvSearchsortOpOnHeaderBody class, searchsortutil pointer will be NULL	
       
   638 	if(searchsortutil !=NULL)
       
   639 		{
       
   640 		TUint32 searchsortsetting=searchsortutil->GetSearchSortSetting();
       
   641 		if ((aPartList & KMsvMessagePartBody) && !(searchsortsetting & EMessagePartBodyLoaded))
       
   642 			{
       
   643 			CMsvStore* msvstore=iMsvEntry->ReadStoreL();
       
   644 			CleanupStack::PushL(msvstore);
       
   645 			msvstore->RestoreBodyTextL(Body());			
       
   646 			FindInBodyL(aTextToFind,aPartList,retList); // Find in body	
       
   647 			CleanupStack::PopAndDestroy(msvstore);
       
   648 			
       
   649 			// The message body is loaded.Set the setting variable to specify that the body is loaded
       
   650 			// If the next search is also on body, than it wont be loaded next time around
       
   651 			
       
   652 			searchsortutil->SetSearchSortSetting(EMessagePartBodyLoaded); 
       
   653 			}
       
   654 		else if( (aPartList & KMsvMessagePartTo ) || (aPartList & KMsvMessagePartFrom ) || (aPartList & KMsvMessagePartSubject))
       
   655 			{
       
   656 			// Search for To, From and Subject
       
   657 			FindL(aTextToFind,aPartList,retList); // Find in header	
       
   658 			}
       
   659 		}
       
   660 	else
       
   661 		{
       
   662 		// Search implementation Prior to PREQ1667
       
   663 		if( (aPartList & KMsvMessagePartRecipient) || (aPartList & KMsvMessagePartOriginator) || (aPartList & KMsvMessagePartDescription))
       
   664 			{
       
   665 			FindL(aTextToFind,aPartList,retList); // Find in header	
       
   666 			}
       
   667 		else if(aPartList & KMsvMessagePartBody)
       
   668 			{
       
   669 			FindInBodyL(aTextToFind,aPartList,retList); // Find in body	
       
   670 			}
       
   671 
       
   672 		}
       
   673 	return retList;
       
   674 	}
       
   675 
       
   676 /*
       
   677 Used by ForwardL() and ReplyL() for initialising the contents of the new message
       
   678 */
       
   679 void CSmsClientMtm::BasicReplyForwardEntry(TMsvEntry& aNewEntry) const
       
   680 	{
       
   681 	aNewEntry.iMtm = KUidMsgTypeSMS;
       
   682  	// Fix for DEF000924: Need to be able to send/cancel an sms while another is being sent
       
   683  	aNewEntry.iRelatedId = Entry().Entry().iServiceId;
       
   684  	aNewEntry.iServiceId = KMsvLocalServiceIndexEntryId;
       
   685  	// End of fix
       
   686  	aNewEntry.iType = KUidMsvMessageEntry;
       
   687 	aNewEntry.iDate.UniversalTime();
       
   688 	}
       
   689 
       
   690 /*
       
   691  *	Methods from CBaseMtm
       
   692  */
       
   693 
       
   694 /** 
       
   695 Commits cached changes to the current message context to the message store.
       
   696 
       
   697 The current context must be set to a message entry with type KUidMsvServiceEntryValue,
       
   698 KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
       
   699 not set, or is set to an entry with a type that is not supported by this function
       
   700 then a panic will occur.
       
   701 
       
   702 Both the SMS service ID and SMS service settings must have been set or a panic
       
   703 will occur. The CSmsClientMtm::RestoreServiceAndSettingsL API can restore both
       
   704 of these items.
       
   705 
       
   706 @panic	SMCM	1
       
   707 The current context has not been set (debug only).
       
   708 
       
   709 @panic	SMCM	4
       
   710 The type of the current context is not supported.
       
   711 
       
   712 @panic	SMCM	11
       
   713 The SMS Service settings have not been set (debug only).
       
   714 
       
   715 @panic	SMCM	12
       
   716 The ID for SMS Service has not been set (debug only).
       
   717 
       
   718 @see	CSmsClientMtm::RestoreServiceAndSettingsL
       
   719 */
       
   720 void CSmsClientMtm::SaveMessageL()
       
   721 	{
       
   722 	__ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
       
   723 
       
   724 	CMsvStore* msvstore=iMsvEntry->EditStoreL();
       
   725 	CleanupStack::PushL(msvstore);
       
   726 	
       
   727 	TMsvEntry entry(iMsvEntry->Entry());
       
   728 	TBool entryChanged = EFalse;
       
   729 	
       
   730 	switch (iMsvEntry->Entry().iType.iUid)
       
   731 		{
       
   732 		case KUidMsvServiceEntryValue:
       
   733 			{
       
   734 			__ASSERT_DEBUG(iServiceSettings, Panic(ESmscSettingsNotSet));
       
   735 			__ASSERT_DEBUG(iServiceId, Panic(ESmscServiceIdNotSet));
       
   736 
       
   737 			CSmsAccount* account = CSmsAccount::NewLC();
       
   738 			//just v2
       
   739 			account->SaveSettingsL(*iServiceSettings);
       
   740 			CleanupStack::PopAndDestroy(account);    
       
   741 			break;
       
   742 			}
       
   743 		case KUidMsvFolderEntryValue:
       
   744 			{
       
   745 			break;
       
   746 			}
       
   747 		case KUidMsvMessageEntryValue:
       
   748 			{
       
   749 			// since CreateMessageL creates message as in preparation and non-visible, the SaveMessageL
       
   750 			// must now make it visible and not in preparation
       
   751 
       
   752 			// If iDetails is empty, set it to be the first recipient in the header
       
   753 			if ((0 >= entry.iDetails.Length()) && (iSmsHeader->Recipients().Count() > 0))
       
   754 				{
       
   755 				CSmsNumber* recipient = iSmsHeader->Recipients().At(0);
       
   756 				if(recipient->Name().Length() > 0)
       
   757 					entry.iDetails.Set(recipient->Name());
       
   758 				else
       
   759 					entry.iDetails.Set(recipient->Address());
       
   760 				}
       
   761 			
       
   762 			// If iDescription is empty, set it to be the first part of the body text
       
   763 			if(Body().DocumentLength()>0 && 0 >= entry.iDescription.Length())
       
   764 				{
       
   765 				entry.iDescription.Set(Body().Read(0,iServiceSettings->DescriptionLength()));	
       
   766 				}
       
   767 			entry.SetVisible(ETrue);
       
   768 			entry.SetInPreparation(EFalse);	
       
   769 			entry.SetMultipleRecipients(iSmsHeader->Recipients().Count() > 1);
       
   770 			entryChanged = ETrue;
       
   771 
       
   772 			iSmsHeader->StoreL(*msvstore);
       
   773 			StoreBodyL(*msvstore);
       
   774 			break;
       
   775 			}
       
   776 		default:
       
   777 			Panic(ESmscUnrecognizedEntryType);
       
   778 		}
       
   779 	msvstore->CommitL();
       
   780 
       
   781  	// Set the iSize member of the TMsvEntry
       
   782  	if (iMsvEntry->HasStoreL())
       
   783  		{
       
   784  		const TInt size = msvstore->SizeL();		
       
   785  		if (entry.iSize != size)
       
   786  			{
       
   787  			entry.iSize = size; 			
       
   788  			entryChanged = ETrue;
       
   789  			}
       
   790  		}
       
   791 
       
   792 	CleanupStack::PopAndDestroy(msvstore);
       
   793 
       
   794 	if ( entryChanged )
       
   795 		{
       
   796 		// The entry info has been updated - commit to the store.		
       
   797 		iMsvEntry->ChangeL(entry);
       
   798 		}
       
   799 	}
       
   800 
       
   801 /**
       
   802 Loads the cache with the message data for the current context.
       
   803 
       
   804 The current context must be set to a message entry with type KUidMsvServiceEntryValue,
       
   805 KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
       
   806 not set, or is set to an entry with a type that is not supported by this function
       
   807 then a panic will occur.
       
   808 
       
   809 If the current context is of type KUidMsvServiceEntryValue then the SMS service
       
   810 settings are restore from the context. The SMS service settings can be accessed
       
   811 using the overloaded CSmsClientMtm::ServiceSettings APIs .
       
   812 
       
   813 If the current context is of type KUidMsvMessageEntryValue then the SMS message
       
   814 object is restore from the context. This can be accessed using the overloaded 
       
   815 CSmsClientMtm::SmsHeader APIs.
       
   816 
       
   817 If the current context is of type KUidMsvFolderEntryValue then this function 
       
   818 does nothing.
       
   819 
       
   820 @panic	SMCM	1
       
   821 The current context has not been set (debug only).
       
   822 
       
   823 @panic	SMCM	4
       
   824 The entry type of the current context was not recognised.
       
   825 
       
   826 @see	CSmsClientMtm::SmsHeader
       
   827 @see	CSmsClientMtm::ServiceSettings
       
   828 */
       
   829 void CSmsClientMtm::LoadMessageL()
       
   830 	{
       
   831 	__ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
       
   832 
       
   833 	CMsvStore* msvstore=iMsvEntry->ReadStoreL();
       
   834 	CleanupStack::PushL(msvstore);
       
   835 	switch (iMsvEntry->Entry().iType.iUid)
       
   836 		{
       
   837 		case KUidMsvServiceEntryValue:
       
   838 			{
       
   839 			RestoreServiceAndSettingsL();
       
   840 			break;
       
   841 			}
       
   842 		case KUidMsvFolderEntryValue:
       
   843 			{
       
   844 			break;
       
   845 			}
       
   846 		case KUidMsvMessageEntryValue:
       
   847 			{
       
   848 			ResetHeader();
       
   849 			Body().Reset();
       
   850 			CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
       
   851 			CleanupStack::PushL(smsheader);
       
   852 			
       
   853 			smsheader->RestoreL(*msvstore);
       
   854 			// the following part inserts the recipients from header also to the smsclient
       
   855 			// the recipients are restored inside the csmsheader already
       
   856 			if (smsheader->Type()==CSmsPDU::ESmsSubmit)
       
   857 				{
       
   858 				for (TInt i=0; i<smsheader->Recipients().Count(); ++i)
       
   859 					{
       
   860 					CSmsNumber* recipient=smsheader->Recipients()[i];
       
   861 					DoAddAddresseeL(recipient->Address(),recipient->Name());
       
   862 					}
       
   863 				}
       
   864 				
       
   865 		// Get a reference to TMsvEnhanceSearchSortUtil  instance set by CMsvSearchsortOpOnHeaderBody class
       
   866 		// If advanced search and sort is being performed than do not load the body here
       
   867 		// For API's other than CMsvSearchsortOpOnHeaderBody-> FindInHeaderBodyL(), a call to LoadMessageL()
       
   868 		// loads the body.
       
   869 	
       
   870 			TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
       
   871 			if ( searchsortutil == NULL )
       
   872 				{
       
   873 				msvstore->RestoreBodyTextL(Body()); // Restore Body text
       
   874 				}
       
   875 			CleanupStack::Pop(smsheader); 
       
   876 			delete iSmsHeader;
       
   877 			iSmsHeader=smsheader;
       
   878 			break;
       
   879 			}
       
   880 		default:
       
   881 			Panic(ESmscUnrecognizedEntryType);
       
   882 		}
       
   883 	CleanupStack::PopAndDestroy(msvstore);
       
   884 	}
       
   885 /** 
       
   886 Validates the current message context.
       
   887 
       
   888 The addresses for the message are checked to be well-formed SMS addresses.
       
   889 
       
   890 The current context must be set. If the current context is not set then a panic
       
   891 will occur.
       
   892 
       
   893 @param	aPartList
       
   894 Indicates the message parts for which the validation has been requested.
       
   895 
       
   896 @return
       
   897 If valid KErrNone is returned. If invalid, the invalid parts of the message are
       
   898 identified. The return error value is the bitmask of the TMsvPartList IDs for
       
   899 each invalid part
       
   900 
       
   901 @panic	SMCM	1
       
   902 The current context has not been set (debug only).
       
   903 
       
   904 @panic	SMCM	6
       
   905 The addressee list and recipient list do not match (debug only).
       
   906 */
       
   907 TMsvPartList CSmsClientMtm::ValidateMessage(TMsvPartList aPartList)
       
   908 	{
       
   909 	__ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
       
   910 	__ASSERT_DEBUG(iSmsHeader->Recipients().Count()==iAddresseeList->Count(), Panic(ESmscRecpAddresseeMiscount));
       
   911 
       
   912 	TMsvPartList partlist=TMsvPartList(0);
       
   913 	if (aPartList&KMsvMessagePartRecipient)
       
   914 		if (!ValidRecipients())  
       
   915 			partlist|=KMsvMessagePartRecipient;
       
   916 
       
   917 	return partlist;
       
   918 	}
       
   919 
       
   920 /**
       
   921 Searches the specified message part(s) for the plain-text version of the text 
       
   922 to be found.
       
   923 
       
   924 @param	aTextToFind
       
   925 The plain-text version of the text to be found. 
       
   926 
       
   927 @param	aPartList
       
   928 Indicates the message parts which should be searched. 
       
   929 
       
   930 @return
       
   931 If the text was not found, or searching is unsupported, 0. If the text was found,
       
   932 a bitmask of the TMsvPartList IDs for each part in which the text was present.
       
   933 */
       
   934 TMsvPartList CSmsClientMtm::Find(const TDesC& aTextToFind,TMsvPartList aPartList)
       
   935 	{
       
   936 	TMsvPartList retList = 0;
       
   937 	TRAP_IGNORE(retList = DoFindL(aTextToFind, aPartList));
       
   938 	return retList;
       
   939 	}
       
   940 
       
   941 /**
       
   942 Creates a new SMS message as a reply to the current message context.
       
   943 
       
   944 The SMS in the current context must be of type SMS-DELIVER, indicating a mobile
       
   945 terminated message.
       
   946 
       
   947 The current context must be set to a message entry with type KUidMsvMessageEntryValue.
       
   948 If the current context is not set, or is set to an entry not of type
       
   949 KUidMsvMessageEntryValuethen a panic will occur.
       
   950 
       
   951 The new SMS message has the recipient set to the sender of the message in the
       
   952 current context. It has a type SMS-SUBMIT, indicating a mobile originated meesage.
       
   953 If the SMS service settings CSmsSettings::ReplyQuoted is true then the reply
       
   954 message will contain the body of the original message, including any EMS elements.
       
   955 
       
   956 @param	aDestination
       
   957 The message entry (folder) under which to create the new message.
       
   958 
       
   959 @param	aPartList
       
   960 Ignored.
       
   961 
       
   962 @param	aCompletionStatus
       
   963 The request status to be completed when the operation has finished.
       
   964 
       
   965 @return
       
   966 An operation object. If the relpy email is successful created, the operation will
       
   967 complete with KErrNone. The operation's progress information is a TPckg<TMsvId>,
       
   968 containing the TMsvId of the new SMS message. If the reply message fails to be 
       
   969 created, the operation completes with the relevant error code.
       
   970 
       
   971 @leave	KErrNotSupported
       
   972 The current context does not have a PDU type of SMS-DELIVER.
       
   973 
       
   974 @panic	SMCM	1
       
   975 The current context has not been set (debug only).
       
   976 
       
   977 @panic	SMCM	2
       
   978 The current context was not of type KUidMsvMessageEntry (debug only).
       
   979 */
       
   980 CMsvOperation* CSmsClientMtm::ReplyL(TMsvId aDestination,TMsvPartList /*aPartList*/, TRequestStatus& aCompletionStatus)
       
   981 	{
       
   982 	LoadMessageL();
       
   983 
       
   984 	__ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
       
   985 	__ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
       
   986 
       
   987 	if (iSmsHeader->Type()!=CSmsPDU::ESmsDeliver)
       
   988 		{
       
   989 		User::Leave(KErrNotSupported);
       
   990 		}
       
   991 
       
   992 	CRichText* body = CRichText::NewL(iParaFormatLayer, iCharFormatLayer,CEditableText::EFlatStorage,KSmcmRichTextConstant);
       
   993 	CleanupStack::PushL(body);
       
   994 
       
   995 	CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
       
   996 	CleanupStack::PushL(smsheader);
       
   997 
       
   998 	// Check to see if we are copying the contents of the original message
       
   999 	if(iServiceSettings->ReplyQuoted() && iMsvEntry->Entry().iBioType==NULL)
       
  1000 		{
       
  1001 		// Copy original rich text
       
  1002 		body->AppendTakingSolePictureOwnershipL(Body());
       
  1003 		// Copy ems elements from original message to new message
       
  1004 		iSmsHeader->Message().CopyEmsElementsL(smsheader->Message());
       
  1005 		}
       
  1006 		
       
  1007 	if( iSmsHeader->EmailFields().Length() > 0 )
       
  1008 		{
       
  1009 		// The context message is an email message - set the email fields for
       
  1010 		// the new message.
       
  1011 		smsheader->SetReplyEmailFieldsL(iSmsHeader->EmailFields(), *iEmailReplySubjectFormat);
       
  1012 		}
       
  1013 	else
       
  1014 		{
       
  1015 		// Get the reply to address if there is one else the from address.
       
  1016 		DoAddRecipientL(smsheader, iSmsHeader->ReplyAddressL(), iMsvEntry->Entry().iDetails);
       
  1017 		}
       
  1018 
       
  1019 	if(iSmsHeader->Deliver().ReplyPath())
       
  1020 		{
       
  1021 		smsheader->Submit().SetServiceCenterAddressL(iSmsHeader->Deliver().ServiceCenterAddress());
       
  1022 		smsheader->SetReplyPathProvided(ETrue);
       
  1023 		}
       
  1024 	else smsheader->SetReplyPathProvided(EFalse);
       
  1025 	
       
  1026 	TMsvEntry entry;
       
  1027 	BasicReplyForwardEntry(entry);
       
  1028 
       
  1029 	CMsvOperation* operation = CreateNewEntryL(entry, aDestination, *smsheader, *body, aCompletionStatus);
       
  1030 
       
  1031 	CleanupStack::PopAndDestroy(2, body);
       
  1032 	return operation;
       
  1033 	}
       
  1034 
       
  1035 /** 
       
  1036 Creates a SMS forwarded message from the current message context.
       
  1037 
       
  1038 The SMS in the current context must be of type SMS-DELIVER, a mobile terminated 
       
  1039 message, or SMS-SUBMIT, a mobile originated message. 
       
  1040 
       
  1041 The current context must be set to a message entry with type KUidMsvMessageEntryValue.
       
  1042 If the current context is not set, or is set to an entry not of type
       
  1043 KUidMsvMessageEntryValuethen a panic will occur.
       
  1044 
       
  1045 The new SMS message will have type SMS-SUBMIT, a mobile originated message. The 
       
  1046 recipient is left blank. The contents that are copied to the new message include
       
  1047 the message body, iBioType and description. Also, any EMS components are also
       
  1048 copied.
       
  1049 
       
  1050 @param	aDestination
       
  1051 The message entry (folder) under which to create the new message.
       
  1052 
       
  1053 @param	aPartList
       
  1054 Ignored.
       
  1055 
       
  1056 @param	aCompletionStatus
       
  1057 The request status to be completed when the operation has finished.
       
  1058 
       
  1059 @return
       
  1060 An operation object. If the forward email is successful created, the operation
       
  1061 will complete with KErrNone. The operation's progress information is a 
       
  1062 TPckg<TMsvId>, containing the TMsvId of the new SMS message. If the forward 
       
  1063 message fails to be created, the operation completes with the relevant error code.
       
  1064 
       
  1065 @leave	KErrNotSupported
       
  1066 The current context has a PDU type that is neither SMS-SUBMIT nor SMS-DELIVER.
       
  1067 
       
  1068 @panic	SMCM	1
       
  1069 The current context has not been set (debug only).
       
  1070 
       
  1071 @panic	SMCM	2
       
  1072 The current context was not of type KUidMsvMessageEntry (debug only).
       
  1073 */
       
  1074 CMsvOperation* CSmsClientMtm::ForwardL(TMsvId aDestination,TMsvPartList /*aPartList*/, TRequestStatus& aCompletionStatus)
       
  1075 	{
       
  1076 	LoadMessageL();
       
  1077 
       
  1078 	__ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
       
  1079 	__ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
       
  1080 
       
  1081 	// Only forwarding of Submitted or Delivered Messages is supported - ie only
       
  1082 	// SMS messages that either been sent or received. 
       
  1083 	CSmsPDU::TSmsPDUType smsType = iSmsHeader->Type();
       
  1084 	if (smsType!=CSmsPDU::ESmsSubmit && smsType!=CSmsPDU::ESmsDeliver)
       
  1085 		User::Leave(KErrNotSupported);
       
  1086 
       
  1087 	CRichText* body = CRichText::NewL(iParaFormatLayer, iCharFormatLayer,CEditableText::EFlatStorage,KSmcmRichTextConstant);
       
  1088 	CleanupStack::PushL(body);
       
  1089 	body->AppendTakingSolePictureOwnershipL(Body());
       
  1090 
       
  1091 	CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
       
  1092 	CleanupStack::PushL(smsheader);
       
  1093 
       
  1094 	smsheader->SetReplyPathProvided(EFalse);
       
  1095 
       
  1096 	// Copy any EMS elements
       
  1097 	iSmsHeader->Message().CopyEmsElementsL(smsheader->Message());
       
  1098 	
       
  1099 	if( iSmsHeader->EmailFields().Length() > 0 )
       
  1100 		{
       
  1101 		// The context message is an email message - set the email fields for
       
  1102 		// the new message.
       
  1103 		smsheader->SetForwardEmailFieldsL(iSmsHeader->EmailFields(), *iEmailForwardSubjectFormat);
       
  1104 		}
       
  1105 	
       
  1106 	// Set the contents of the new TMsvEntry
       
  1107 	const TMsvEntry& originalEntry = Entry().Entry();
       
  1108 	TMsvEntry entry;
       
  1109 	BasicReplyForwardEntry(entry);
       
  1110 	entry.iBioType = originalEntry.iBioType; // added since 6.1
       
  1111 	entry.iDescription.Set(originalEntry.iDescription); // added since 6.1		
       
  1112 
       
  1113 	CMsvOperation* operation = CreateNewEntryL(entry, aDestination,*smsheader,*body,aCompletionStatus);
       
  1114 
       
  1115 	CleanupStack::PopAndDestroy(2, body);
       
  1116 	return operation;
       
  1117 	}
       
  1118 
       
  1119 /**
       
  1120 Adds an addressee to the current context.
       
  1121 
       
  1122 The current context must be an SMS messge of type SMS-SUBMIT, indicating a 
       
  1123 mobile originated message. The address is added to the recipient list for the 
       
  1124 message.
       
  1125 
       
  1126 For SMS an address is a telephone number. There is no validation done on the 
       
  1127 input argument aRealAddress to ensure that it is a valid telephone number.
       
  1128 
       
  1129 The TSmsUtilities::GetDetails API can be used prior to this API to find the if
       
  1130 a unique alias exists in the contacts database for this particular telephone 
       
  1131 number.
       
  1132 
       
  1133 The current context must be set to a message entry with type KUidMsvMessageEntryValue.
       
  1134 If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
       
  1135 a panic will occur.
       
  1136 
       
  1137 The SMS MTM maintains an addressee list that matches the recipient list in the 
       
  1138 SMS message header object. If the two list cannot be maintained together then
       
  1139 this function will leave and both lists are unchanged.
       
  1140 
       
  1141 @param	aRealAddress
       
  1142 A string representing the address to be added to the recipient list for the
       
  1143 current context.
       
  1144 
       
  1145 @leave	KErrNotSupported
       
  1146 The current contxt PDU type is not SMS-SUBMIT.
       
  1147 
       
  1148 @panic	SMCM	2
       
  1149 The current context was not of type KUidMsvMessageEntry (debug only).
       
  1150 
       
  1151 @panic	SMCM	6
       
  1152 The addressee list and recipient list do not match (debug only).
       
  1153 */
       
  1154 void CSmsClientMtm::AddAddresseeL(const TDesC& aRealAddress)
       
  1155 	{
       
  1156 	__ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
       
  1157 	if (iSmsHeader->Type()!=CSmsPDU::ESmsSubmit)
       
  1158 		User::Leave(KErrNotSupported);
       
  1159 	__ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
       
  1160 	TPtr ptr(NULL,0);
       
  1161 	DoAddAddresseeL(aRealAddress,ptr);
       
  1162 	TRAPD(ret,AddRecipientL(aRealAddress,ptr));
       
  1163 	if (ret!=KErrNone)
       
  1164 		{
       
  1165 		iAddresseeList->Delete(iAddresseeList->Count()-1);
       
  1166 		User::Leave(ret);
       
  1167 		}
       
  1168 	}
       
  1169 
       
  1170 /** 
       
  1171 Adds an addressee with an alias to the current context.
       
  1172 
       
  1173 The SMS message in the current context must be of type SMS-SUBMIT, indicating a
       
  1174 mobile originated message. The address is added to the recipient list for the 
       
  1175 message.
       
  1176 
       
  1177 For SMS an address is a telephone number. There is no validation done on the 
       
  1178 input argument aRealAddress to ensure that it is a valid telephone number.
       
  1179 
       
  1180 The TSmsUtilities::GetDetails API can be used prior to this API to find the if
       
  1181 a unique alias exists in the contacts database for this particular telephone 
       
  1182 number.
       
  1183 
       
  1184 The current context must be set to a message entry with type KUidMsvMessageEntryValue.
       
  1185 If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
       
  1186 a panic will occur.
       
  1187 
       
  1188 The SMS MTM maintains an addressee list that matches the recipient list in the 
       
  1189 SMS message header object. If the two list cannot be maintained together then
       
  1190 this function will leave and both lists are unchanged.
       
  1191 
       
  1192 @param	aRealAddress
       
  1193 A string representing the address to be added to the recipient list for the 
       
  1194 current message.
       
  1195 
       
  1196 @param	aAlias
       
  1197 The alias information for the address.
       
  1198 
       
  1199 @leave	KErrNotSupported
       
  1200 The current contxt PDU type is not SMS-SUBMIT.
       
  1201 
       
  1202 @panic	SMCM	2
       
  1203 The current context was not of type KUidMsvMessageEntry (debug only).
       
  1204 
       
  1205 @panic	SMCM	6
       
  1206 The addressee list and recipient list do not match (debug only).
       
  1207 */
       
  1208 void CSmsClientMtm::AddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias)
       
  1209 	{
       
  1210 	__ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
       
  1211 	if (iSmsHeader->Type()!=CSmsPDU::ESmsSubmit)
       
  1212 		User::Leave(KErrNotSupported);
       
  1213 	__ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
       
  1214 	DoAddAddresseeL(aRealAddress,aAlias);
       
  1215 	TRAPD(ret,AddRecipientL(aRealAddress,aAlias));
       
  1216 	if (ret!=KErrNone)
       
  1217 		{
       
  1218 		iAddresseeList->Delete(iAddresseeList->Count()-1);
       
  1219 		User::Leave(ret);
       
  1220 		}
       
  1221 	}
       
  1222 
       
  1223 /** 
       
  1224 Removes a recipient from the current address list.
       
  1225 
       
  1226 The recipient to be removed is specified by its index in the list of recipients.
       
  1227 This function can only be used when the current context is a mobile-originated
       
  1228 message (is a SMS-SUBMIT type message).
       
  1229 
       
  1230 The index must be valid or a panic will occur. A valid index is not negative and
       
  1231 does not exceed the upper bounds of the list.
       
  1232 
       
  1233 The current context must be set to a message entry with type KUidMsvMessageEntryValue.
       
  1234 If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
       
  1235 a panic will occur.
       
  1236 
       
  1237 The SMS MTM maintains an addressee list that matches the recipient list in the 
       
  1238 SMS message header object. The address is removed from both lists.
       
  1239 
       
  1240 @param aIndex
       
  1241 The index of recipient to be removed.
       
  1242 
       
  1243 @panic	SMCM	0
       
  1244 The current contxt PDU type is not SMS-SUBMIT (debug only).
       
  1245 
       
  1246 @panic	SMCM	2
       
  1247 The current context was not a mesasge type context (debug only).
       
  1248 
       
  1249 @panic	SMCM	5
       
  1250 The specified index exceeds the recipient list range (debug only).
       
  1251 
       
  1252 @panic	SMCM	6
       
  1253 The addressee list and recipient list do not match (debug only).
       
  1254 */
       
  1255 void CSmsClientMtm::RemoveAddressee(TInt aIndex)
       
  1256 	{
       
  1257 	__ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
       
  1258 	__ASSERT_DEBUG(iSmsHeader->Type() == CSmsPDU::ESmsSubmit, Panic(ESmutPanicUnsupportedMsgType));
       
  1259 	__ASSERT_DEBUG((aIndex>=0) && (aIndex<iAddresseeList->Count()),Panic(ESmscAddresseeIndexOutOfRange));
       
  1260 	__ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
       
  1261 	delete iSmsHeader->Recipients()[aIndex];
       
  1262 	iSmsHeader->Recipients().Delete(aIndex);
       
  1263 	iAddresseeList->Delete(aIndex);
       
  1264 	}
       
  1265 
       
  1266 /**
       
  1267 Queries if the MTM supports the capability specified by the supplied UID.
       
  1268 
       
  1269 @param	aCapability
       
  1270 The UID of capability to be queried.
       
  1271 
       
  1272 @param	aResponse
       
  1273 An output argument for the response value. The format of the response varies
       
  1274 according to the capability. 
       
  1275 
       
  1276 @return
       
  1277 A value of KErrNone if the specified capability is recognised and a response
       
  1278 is returned. KErrNotSupported indicates that the capability is not recognised.
       
  1279 
       
  1280 @see	mtmuids.h
       
  1281 */
       
  1282 TInt CSmsClientMtm::QueryCapability(TUid aCapability, TInt& aResponse)
       
  1283 	{
       
  1284 	TInt error=KErrNone;
       
  1285 	aResponse=ETrue;
       
  1286 	switch (aCapability.iUid)
       
  1287 		{
       
  1288 		case KUidMtmQueryMaxBodySizeValue:
       
  1289 			{
       
  1290 			aResponse=KSmcmMaxTotalMsgSize;
       
  1291 			break;
       
  1292 			}
       
  1293 		case KUidMtmQueryMaxTotalMsgSizeValue:
       
  1294 			{
       
  1295 			aResponse = KSmcmMaxMessageNumber*KSmcmMaxCharsInMessageConcatenated7Bit;
       
  1296 			break;
       
  1297 			}
       
  1298 		case KUidMtmQuerySupportedBodyValue:
       
  1299 			{
       
  1300 			aResponse = KMtm7BitBody + KMtm8BitBody + KMtm16BitBody;
       
  1301 			break;
       
  1302 			}
       
  1303 		case KUidMtmQueryCanSendMsgValue:
       
  1304 		case KUidMtmQueryCanReceiveMsgValue:
       
  1305 		case KUidMtmQuerySupportsBioMsgValue:
       
  1306 		case KUidMtmQuerySupportsSchedulingValue:
       
  1307 		case KUidMtmQuerySendAsMessageSendSupportValue:
       
  1308 			break;
       
  1309 		case KUidMtmQueryMaxRecipientCountValue:
       
  1310 			{
       
  1311 			aResponse=KErrNotFound;	// not limited
       
  1312 			break;
       
  1313 			}
       
  1314 		case KUidMsvMtmQueryEditorUidValue:
       
  1315 			{
       
  1316 			aResponse=KUidMsgSmsEditorAppVal;
       
  1317 			break;
       
  1318 			}
       
  1319 		case KUidMtmQuerySupportAttachmentsValue:
       
  1320 		case KUidMtmQueryOffLineAllowedValue:
       
  1321 		case KUidMtmQuerySupportSubjectValue:
       
  1322 		case KUidMtmQuerySendAsRequiresRenderedImageValue:
       
  1323 		case KUidMtmQuerySendAsRenderingUidValue:
       
  1324 		case KUidMtmQuerySupportsFolderValue:
       
  1325 		case KUidMtmQuerySupportsRecipientTypeValue:
       
  1326 		default:
       
  1327 			error=KErrNotSupported;
       
  1328 		}
       
  1329 	return error;
       
  1330 	}
       
  1331 
       
  1332 /**
       
  1333 Unused for SMS.
       
  1334 
       
  1335 This function should not be used as it will cause a panic.
       
  1336 
       
  1337 @param aFunctionId
       
  1338 Unused.
       
  1339 
       
  1340 @param aSelection
       
  1341 Unused.
       
  1342 
       
  1343 @param aParameter
       
  1344 Unused. 
       
  1345 
       
  1346 @panic	SMCM	3
       
  1347 This command is not supported in SMS and should not be used.
       
  1348 
       
  1349 @internalComponent
       
  1350 */
       
  1351 void CSmsClientMtm::InvokeSyncFunctionL(TInt /*aFunctionId*/,const CMsvEntrySelection& /*aSelection*/, TDes8& /*aParameter*/)
       
  1352 	{
       
  1353 	Panic(ESmscPanicUnexpectedCommand);
       
  1354 	}
       
  1355 
       
  1356 /**
       
  1357 Invokes asynchronous SMS-specific operations.
       
  1358 
       
  1359 The specified operation is performed by the SMS server MTM.
       
  1360 
       
  1361 If the requested command is not supported then a panic will occur. The list of
       
  1362 supported commands is given by TSmsMtmCommand.
       
  1363 
       
  1364 The current context must be set. If the current context is not set then a panic
       
  1365 will occur.
       
  1366 
       
  1367 @param	aFunctionId
       
  1368 The ID of the operation to perform. The specific operations are defined by the
       
  1369 TSmsMtmCommand enumeration.
       
  1370 
       
  1371 @param	aSelection
       
  1372 A selection of messages, the use of which is specific to the selected operation.
       
  1373 
       
  1374 @param	aParameter
       
  1375 A packaged object, the use of which is specific to the selected operation.
       
  1376 
       
  1377 @param	aCompletionStatus
       
  1378 The request status to be notified when the operation completes. 
       
  1379 
       
  1380 @return
       
  1381 An object encapsulating the requested operation if the specified operation was
       
  1382 successfully started. If the operation failed to be started an completing 
       
  1383 operation is returned with its status set to the relevant error code.
       
  1384 
       
  1385 @see	TSmsMtmCommand 
       
  1386 
       
  1387 @panic	SMCM	1
       
  1388 The message entry has not been set (debug only).
       
  1389 
       
  1390 @panic	SMCM	3
       
  1391 The specified operation is not supported in SMS.
       
  1392 */
       
  1393 CMsvOperation* CSmsClientMtm::InvokeAsyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection, TDes8& aParameter, TRequestStatus& aCompletionStatus)
       
  1394 	{
       
  1395 	__ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
       
  1396 	switch (aFunctionId)
       
  1397 		{
       
  1398 		case KMTMStandardFunctionsSendMessage:
       
  1399 			// perform a regular send with standardised progress information for SendAs2
       
  1400 			return CSmsSendMessageOperation::NewL(Session(), aSelection, aParameter, aCompletionStatus);
       
  1401 		case ESmsMtmCommandScheduleCopy:
       
  1402 		case ESmsMtmCommandScheduleMove:
       
  1403 		case ESmsMtmCommandDeleteSchedule:
       
  1404 		case ESmsMtmCommandCheckSchedule:
       
  1405 		case ESmsMtmCommandSendScheduledCopy:
       
  1406 		case ESmsMtmCommandSendScheduledMove:
       
  1407 		case ESmsMtmCommandEnumeratePhoneStores:
       
  1408 		case ESmsMtmCommandDeleteFromPhoneStore:
       
  1409 		case ESmsMtmCommandCopyFromPhoneStore:
       
  1410 		case ESmsMtmCommandMoveFromPhoneStore:
       
  1411 		case ESmsMtmCommandCopyToPhoneStore:
       
  1412 		case ESmsMtmCommandMoveToPhoneStore:
       
  1413 			break;
       
  1414 		default:
       
  1415 			Panic(ESmscPanicUnexpectedCommand);
       
  1416 		}
       
  1417 	return Session().TransferCommandL(aSelection,aFunctionId,(TDesC8&)aParameter, aCompletionStatus);
       
  1418 	}
       
  1419 
       
  1420 
       
  1421 /**
       
  1422 Informs the MTM that the context's BIO field is being changed.
       
  1423 
       
  1424 The change is as a result of a call to CSendAs::SetBioTypeL(). This function is
       
  1425 used by CSendAs::CreateMessageL to create a new outgoing SMS message
       
  1426 
       
  1427 @param	aBioTypeUid
       
  1428 The new value for the BIO field.
       
  1429 
       
  1430 @panic	SMCM	10
       
  1431 The BIO field contains the wrong value (debug only).
       
  1432 */
       
  1433 EXPORT_C void CSmsClientMtm::BioTypeChangedL(TUid aBioTypeUid)
       
  1434 	{
       
  1435 	// Looks up the default send bearer and sets the
       
  1436 	// character encoding of the Submit() accordingly.
       
  1437 	RestoreServiceAndSettingsL();
       
  1438 
       
  1439 	CBIODatabase* bdb = CBIODatabase::NewLC(Session().FileSession());
       
  1440 	TBioMsgId bioMsgId;
       
  1441 	bdb->GetDefaultSendBearerL(aBioTypeUid, bioMsgId);
       
  1442 
       
  1443 	CSmsSettings* settings = CSmsSettings::NewL();
       
  1444 	CleanupStack::PushL(settings);
       
  1445 
       
  1446 	settings->CopyL(*iServiceSettings);
       
  1447 
       
  1448 	iSmsHeader->SetBioMsgIdType(bioMsgId.iType);
       
  1449 
       
  1450 	TSmsDataCodingScheme::TSmsAlphabet alpha = TSmsDataCodingScheme::ESmsAlphabet8Bit;
       
  1451 
       
  1452 	// Set the SMS Data Encoding Scheme
       
  1453 	switch (bioMsgId.iType)
       
  1454 		{
       
  1455 		case EBioMsgIdNbs:
       
  1456 			{
       
  1457 			switch (bioMsgId.iCharacterSet.iUid)
       
  1458 				{
       
  1459 //				case KCharacterSetIdentifierIso88591:
       
  1460 				case KCharacterSetIdentifierCodePage1252:
       
  1461 					{
       
  1462 					alpha = TSmsDataCodingScheme::ESmsAlphabet8Bit;
       
  1463 					break;
       
  1464 					}
       
  1465 				case KCharacterSetIdentifierSms7Bit:
       
  1466 					{
       
  1467 					alpha = TSmsDataCodingScheme::ESmsAlphabet7Bit;
       
  1468 					break;
       
  1469 					}
       
  1470 				default:
       
  1471 					{
       
  1472 					alpha = TSmsDataCodingScheme::ESmsAlphabetUCS2;
       
  1473 					break;
       
  1474 					}
       
  1475 				}
       
  1476 			break;
       
  1477 			}
       
  1478 		case EBioMsgIdWap:
       
  1479 		case EBioMsgIdWapSecure:
       
  1480 		default:
       
  1481 			{
       
  1482 			//ESmsAlphabet8Bit;
       
  1483 			break;
       
  1484 			}
       
  1485 		};
       
  1486 
       
  1487 	settings->SetCharacterSet(alpha);
       
  1488 	iSmsHeader->SetSmsSettingsL(*settings);
       
  1489 
       
  1490 	// service centre was not being set 
       
  1491 	TInt defaultSC = iServiceSettings->DefaultServiceCenter();
       
  1492 	if(defaultSC > -1)
       
  1493 		{
       
  1494 		iSmsHeader->SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );	
       
  1495 		}
       
  1496 
       
  1497 	__ASSERT_DEBUG(iSmsHeader->BioMsgIdType() == bioMsgId.iType, Panic(ESmscBioMsgIdTypeError));
       
  1498 
       
  1499 	CleanupStack::PopAndDestroy(2, bdb);
       
  1500 	}
       
  1501 
       
  1502 /** 
       
  1503 Creates a new outgoing SMS message entry as a child of the current context.
       
  1504 
       
  1505 Used by CSendAs::CreateMessageL to create an outgoing SMS message.
       
  1506 
       
  1507 @param	aServiceId
       
  1508 The ID of the service to own the entry (not used).
       
  1509 
       
  1510 @see	CSendAs::CreateMessageL
       
  1511 */
       
  1512 EXPORT_C void CSmsClientMtm::CreateMessageL(TMsvId /*aServiceId*/)
       
  1513 	{
       
  1514 	RestoreServiceAndSettingsL();
       
  1515 
       
  1516  	// Fix for DEF000924: Need to be able to send/cancel an sms while another 
       
  1517 	// is being sent create an invisible blank entry.
       
  1518  	TMsvEntry entry;
       
  1519  	entry.iType = KUidMsvMessageEntry;
       
  1520  	entry.iRelatedId = iServiceId;
       
  1521  	entry.iServiceId = KMsvLocalServiceIndexEntryId;
       
  1522  	entry.iMtm = Type();
       
  1523  	entry.SetVisible(EFalse);
       
  1524  	entry.SetInPreparation(ETrue);
       
  1525  	
       
  1526  	// Fix for DEF061945: Need to initialise the iDate member of the new entry
       
  1527  	entry.iDate.UniversalTime();
       
  1528  	// store entry in folder
       
  1529  	iMsvEntry->CreateL(entry);
       
  1530  	SwitchCurrentEntryL(entry.Id());
       
  1531  	// End of fix
       
  1532 
       
  1533 	delete iSmsHeader;
       
  1534 	iSmsHeader=NULL;
       
  1535 	iSmsHeader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
       
  1536 	iSmsHeader->SetSmsSettingsL(*iServiceSettings);
       
  1537 
       
  1538 	// service centre was not being set 
       
  1539 	TInt defaultSC = iServiceSettings->DefaultServiceCenter();
       
  1540 	if(defaultSC > -1)
       
  1541 		{
       
  1542 		if (iServiceSettings->ServiceCenterCount() > defaultSC )
       
  1543 			{
       
  1544 			iSmsHeader->SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );	
       
  1545 			}
       
  1546 		}
       
  1547  	}
       
  1548 
       
  1549 
       
  1550 
       
  1551 
       
  1552 
       
  1553 /** 
       
  1554 Creates a new outgoing SMS message entry as a child of the current context.
       
  1555 
       
  1556 Used by CSendAs::CreateMessageL to create an outgoing SMS message.
       
  1557 
       
  1558 @param	
       
  1559 The entry with the required fields set.
       
  1560 
       
  1561 */
       
  1562 EXPORT_C void CSmsClientMtm::CreateMessageL(TMsvEntry& aEntry)
       
  1563 	{
       
  1564 	RestoreServiceAndSettingsL();
       
  1565 
       
  1566  	aEntry.SetVisible(EFalse);
       
  1567  	aEntry.SetInPreparation(ETrue);
       
  1568  	aEntry.iDate.UniversalTime();
       
  1569  	
       
  1570  	// store entry in folder
       
  1571  	iMsvEntry->CreateL(aEntry);
       
  1572  	SwitchCurrentEntryL(aEntry.Id());
       
  1573  	// End of fix
       
  1574 
       
  1575 	delete iSmsHeader;
       
  1576 	iSmsHeader=NULL;
       
  1577 	iSmsHeader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
       
  1578 	iSmsHeader->SetSmsSettingsL(*iServiceSettings);
       
  1579 
       
  1580 	// service centre was not being set 
       
  1581 	TInt defaultSC = iServiceSettings->DefaultServiceCenter();
       
  1582 	if(defaultSC > -1)
       
  1583 		{
       
  1584 		if (iServiceSettings->ServiceCenterCount() > defaultSC )
       
  1585 			{
       
  1586 			iSmsHeader->SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );	
       
  1587 			}
       
  1588 		}
       
  1589  	}
       
  1590 
       
  1591 
       
  1592 
       
  1593 /**
       
  1594 Resets the current SMS message.
       
  1595 
       
  1596 The recipient list in the SMS message header object is emptied. As the SMS MTM 
       
  1597 maintains an addressee list that matches the recipient list in the SMS message 
       
  1598 header object, this addressee list is also emptied.
       
  1599 */
       
  1600 void CSmsClientMtm::ContextEntrySwitched()
       
  1601 	{
       
  1602 	ResetHeader();
       
  1603 	}
       
  1604 
       
  1605 /** 
       
  1606 This method is from CBaseMtm, The default implementation is available in CBaseMtm. 
       
  1607 The implementation of this function assumes that the new service for setting the 
       
  1608 charset encoding value for a SMS message is supported.
       
  1609 TAny* is equivalent to void*.
       
  1610 @param	a0				 			The collective parameters of TAny*
       
  1611 @param	a1				 			The collective parameters of TAny*,Charset encoding value is actually extracted from a1.
       
  1612 @param aExtensionId 	 			Uid of the extension interface.
       
  1613 @return KErrNone					If charset is changed successfully in SMS settings for a message.
       
  1614 @return KErrExtensionNotSupported 	If the message is other than SMS.					
       
  1615 @return Other 			 			Standard system-wide error codes.
       
  1616 */
       
  1617 
       
  1618 EXPORT_C TInt CSmsClientMtm::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
  1619 	{
       
  1620 	TInt ret=KErrNone;
       
  1621 	switch(aExtensionId)
       
  1622 		{
       
  1623 		case KUIDCharacterSet:
       
  1624 			{
       
  1625 	    	TSmsDataCodingScheme::TSmsAlphabet tsmsAlphabet = (TSmsDataCodingScheme::TSmsAlphabet)(TUint)*(TUint*)a1;
       
  1626 	    	TRAP(ret,SetMessageCharacterSetL(tsmsAlphabet));
       
  1627 			return ret;
       
  1628 			}
       
  1629 		default:
       
  1630 			{
       
  1631 			// Chain to base class
       
  1632 			return CBaseMtm::Extension_(aExtensionId, a0, a1);
       
  1633 			}
       
  1634 		}
       
  1635 	}
       
  1636 
       
  1637 /**
       
  1638 This is the actual functionality for setting the character encoding value other than 7-bit ASCII.
       
  1639 TSmsDataCodingScheme is used for collecting the encoding value for setting the charset for a message.
       
  1640 This setting is for per-message basis.
       
  1641 @param aTsmsAlphabet 	 			Enum of Sms datacoding scheme for the character encoding value.
       
  1642 @return void.
       
  1643 */
       
  1644    
       
  1645 void CSmsClientMtm::SetMessageCharacterSetL(TSmsDataCodingScheme::TSmsAlphabet aTsmsAlphabet)
       
  1646 	{
       
  1647 	CSmsSettings* settings = CSmsSettings::NewL();
       
  1648 	CleanupStack::PushL(settings);
       
  1649 
       
  1650 	settings->CopyL(*iServiceSettings);
       
  1651 	settings->SetCharacterSet(aTsmsAlphabet);
       
  1652 	iSmsHeader->SetSmsSettingsL(*settings);
       
  1653 	CleanupStack::PopAndDestroy(settings);
       
  1654 	}
       
  1655 
       
  1656 /** 
       
  1657 Commits cached changes to the current message context to the message store.
       
  1658 
       
  1659 The current context must be set to a message entry with type KUidMsvServiceEntryValue,
       
  1660 KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
       
  1661 not set, or is set to an entry with a type that is not supported by this function
       
  1662 then a panic will occur.
       
  1663 
       
  1664 Both the SMS service ID and SMS service settings must have been set or a panic
       
  1665 will occur. The CSmsClientMtm::RestoreServiceAndSettingsL API can restore both
       
  1666 of these items.
       
  1667 
       
  1668 @panic  SMCM    1
       
  1669 The current context has not been set (debug only).
       
  1670 
       
  1671 @panic  SMCM    4
       
  1672 The type of the current context is not supported.
       
  1673 
       
  1674 @panic  SMCM    11
       
  1675 The SMS Service settings have not been set (debug only).
       
  1676 
       
  1677 @panic  SMCM    12
       
  1678 The ID for SMS Service has not been set (debug only).
       
  1679 
       
  1680 @see    CSmsClientMtm::RestoreServiceAndSettingsL
       
  1681 */
       
  1682 EXPORT_C void CSmsClientMtm::SaveMessageL(CMsvStore& aEditStore, TMsvEntry& aEntry)
       
  1683     {
       
  1684     switch (aEntry.iType.iUid)
       
  1685         {
       
  1686         case KUidMsvServiceEntryValue:
       
  1687             {
       
  1688             __ASSERT_DEBUG(iServiceSettings, Panic(ESmscSettingsNotSet));
       
  1689             __ASSERT_DEBUG(iServiceId, Panic(ESmscServiceIdNotSet));
       
  1690             CSmsAccount* account = CSmsAccount::NewLC();
       
  1691             account->SaveSettingsL(*iServiceSettings);
       
  1692             CleanupStack::PopAndDestroy(account);    
       
  1693             break;
       
  1694             }
       
  1695         case KUidMsvFolderEntryValue:
       
  1696             {
       
  1697             break;
       
  1698             }
       
  1699         case KUidMsvMessageEntryValue:
       
  1700             {
       
  1701             if ((0 >= aEntry.iDetails.Length()) && (iSmsHeader->Recipients().Count() > 0))
       
  1702                 {
       
  1703                 CSmsNumber* recipient = iSmsHeader->Recipients().At(0);
       
  1704                 if(recipient->Name().Length() > 0)
       
  1705                     aEntry.iDetails.Set(recipient->Name());
       
  1706                 else
       
  1707                     aEntry.iDetails.Set(recipient->Address());
       
  1708                 }
       
  1709             if(Body().DocumentLength()>0 && 0 >= aEntry.iDescription.Length())
       
  1710                 {
       
  1711                 aEntry.iDescription.Set(Body().Read(0,iServiceSettings->DescriptionLength()));   
       
  1712                 }
       
  1713             aEntry.SetVisible(ETrue);
       
  1714             aEntry.SetInPreparation(EFalse);           
       
  1715             aEntry.SetMultipleRecipients(iSmsHeader->Recipients().Count() > 1);
       
  1716             iSmsHeader->StoreL(aEditStore);
       
  1717             StoreBodyL(aEditStore);
       
  1718             break;
       
  1719             }
       
  1720         default:
       
  1721             Panic(ESmscUnrecognizedEntryType);
       
  1722         }
       
  1723     
       
  1724     const TInt size = aEditStore.SizeL();        
       
  1725     if (aEntry.iSize != size)
       
  1726         {
       
  1727         aEntry.iSize = size;             
       
  1728         }
       
  1729     }