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