Symbian3/SDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita
changeset 0 89d6a7a84779
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita	Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-E180D222-CC4F-5007-93FC-C339BBE708BC" xml:lang="en"><title>Client
+MTM</title><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>Client MTMs provide a client-side API to functionality provided by the
+Server MTM, mainly for message manipulation and transport. It acts as the
+interface between the internal representation of a message’s data and the
+User Interface (UI) MTM. This architecture provides certain advantages; for
+example, a UI MTM can offer a user interface to enter message addresses without
+knowing the address storage format. Message client applications that do not
+require a user interface can use these client-side functions directly for
+automated message handling. </p>
+<p>The Message Server entry with which Client MTMs currently work is referred
+to as the context. UI MTMs always operate on the contexts set through Client
+MTMs. </p>
+<p>Client MTMs offer some or all of the following capabilities: </p>
+<ul>
+<li id="GUID-4327B533-04C0-5110-B8AD-90EC90C73D32"><p>Address list manipulation </p> </li>
+<li id="GUID-FC4908FC-5958-5815-90EB-D601B4710247"><p>Creation of forward
+and response messages </p> </li>
+<li id="GUID-CF8196EB-1C40-50D0-86AA-0F2C954CBC5D"><p>Message subject access </p> </li>
+<li id="GUID-51B25D57-A577-5375-9DD6-D398C8B860A8"><p>Message validation </p> </li>
+<li id="GUID-4345AB18-2096-5312-955D-EACE72DCA52F"><p>Internalising and externalising
+MTM-specific data to the Message Store </p> </li>
+</ul>
+<section id="GUID-BCFBE2C5-2C90-5E43-9B21-0D80A469CEAB"><title>Client MTM
+base class</title> <p>The base class for Client MTMs is <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm</apiname></xref> which
+provides a high-level interface for accessing and manipulating a Message Server
+entry </p> <p>The following are some significant functions in <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm</apiname></xref>.
+Some functions are implemented by the base class, and others must be implemented
+in a derived class: </p> <ul>
+<li id="GUID-8E6AB26D-BDD2-5D5E-BEDD-5371EE86834D"><p> <b>Context functions</b>  </p> <p>The <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-00C140DE-012F-3785-A628-E8D1330438B8"><apiname>CBaseMtm::SetCurrentEntryL</apiname></xref> <codeph>(CMsvEntry                 *)</codeph> and <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-016A5DFD-5C88-3531-A5F3-456884CAC041"><apiname>CBaseMtm::SwitchCurrentEntryL</apiname></xref> <codeph>(TMsvId)</codeph> functions
+change the Message Server entry (the context) on which later actions are performed.
+After creating a new Client MTM object, a message client application must
+set an initial context before using other functions. </p> </li>
+<li id="GUID-1E3E98F7-FBBF-5594-A7EF-93D7106FD3D3"><p> <b>Store and restore
+entry data functions</b>  </p> <p>The changes that a message client application
+makes to a message context through Client MTM functions, such as altering
+the body text obtained through <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-072E627F-8AB4-3C90-AD48-A5AF6A39581B"><apiname>CBaseMtm::Body()</apiname></xref>, are, for
+efficiency, cached in memory by a Client MTM. The message store (<xref href="GUID-A0F2B215-C453-3CB8-A659-29CB0B4CF0A7.dita"><apiname>SaveMessageL()</apiname></xref>)and
+restore (<xref href="GUID-DF6E56F8-3B05-3D34-8500-BDA77BABD05D.dita"><apiname>LoadMessageL()</apiname></xref>), functions are concerned with
+transferring data between that cache and committed storage. </p> <p> <b>Note:</b> Unlike
+message contexts, message client applications are not expected to manipulate
+directly contexts for message services. Instead, the corresponding <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita"><apiname>User</apiname></xref> Interface
+MTM provides a dialog to allow the user to alter service settings, and calls
+Client MTM functions to handle their retrieval and storage. </p> </li>
+<li id="GUID-A0FDCB02-3C4E-5CB0-A374-61C89889621B"><p> <b>Store and restore
+body text functions</b>  </p> <p>The base class maintains a private <xref href="GUID-39945DA4-B362-3DF6-BF9E-DD079EEA7934.dita"><apiname>CRichText</apiname></xref> object
+cache to store the body text for the current context. This can be accessed
+for reading and writing by message client applications through <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-072E627F-8AB4-3C90-AD48-A5AF6A39581B"><apiname>CBaseMtm::Body()</apiname></xref>.
+The <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-A036C34A-EFB9-3E98-983B-0DFF1EE8CD85"><apiname>CBaseMtm::StoreBodyL()</apiname></xref> <codeph>(CMsvStore &amp;)</codeph> and <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-43AF1C02-C435-3450-A549-8AECE9F6CAB0"><apiname>CBaseMtm::RestoreBodyL()</apiname></xref> <codeph>(CMsvStore
+&amp;)</codeph> functions encapsulate the retrieval and storage of this <xref href="GUID-39945DA4-B362-3DF6-BF9E-DD079EEA7934.dita"><apiname>CRichText</apiname></xref> object
+to a <xref href="GUID-8CB90FA2-A6CF-3FA2-81FF-7D22EFD9C2CE.dita"><apiname>CMsvStore</apiname></xref>. </p> </li>
+<li id="GUID-B44CFD8D-DB97-5A4D-B876-EA04D464A5B1"><p> <b>Address list functions</b>  </p> <p>The
+format and storage of message addresses is MTM-specific. The <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-51A8768D-684A-3668-98BF-AB88D676DEB5"><apiname>CBaseMtm::AddresseeList()</apiname></xref> <codeph>const</codeph>, <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-D3DFE444-DB84-331C-BC3F-AB12E148CD00"><apiname>CBaseMtm::AddAddresseeL</apiname></xref> <codeph>(const TDesC &amp;)</codeph>, and <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-770E749C-BA7F-3F31-B7B8-F2C21F4F06A1"><apiname>CBaseMtm::RemoveAddressee</apiname></xref> <codeph>(TInt)</codeph> allow
+clients to access address information in a generic way without having MTM-specific
+knowledge. </p> </li>
+<li id="GUID-F1E2AAD3-41E0-522A-B7AC-7090EE823807"><p> <b>MTM-specific client
+functions</b>  </p> <p>MTM components can offer protocol-specific functionality
+not provided by base class interface functions. MTM components define IDs
+that correspond to each protocol-specific operation offered, and implement
+the <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-A5B6CDAC-7C02-35F4-840E-35932B438FD8"><apiname>CBaseMtm::InvokeSyncFunctionL()</apiname></xref> and <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita#GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D/GUID-05327221-98A9-35FA-BD28-D6323BE449D1"><apiname>CBaseMtm::InvokeAsyncFunctionL()</apiname></xref> functions
+to allow clients to access these operations by passing in the appropriate
+ID. These functions are provided to allow the MTM component to offer both
+synchronous and asynchronous functionality. Message client applications can
+dynamically add user-interface features for these operations using <xref href="GUID-899C6D87-5712-34A7-902C-EA452894700C.dita#GUID-899C6D87-5712-34A7-902C-EA452894700C/GUID-75DE35D7-4738-38C0-9BFA-A066F67B114B"><apiname>CBaseMtmUiData::MtmSpecificFunctions()</apiname></xref>. </p> </li>
+<li id="GUID-A4A3ED85-EAC5-58BC-BB40-E40949A84B66"><p> <b>Query function</b>  </p> <p>The
+Client MTM <xref href="GUID-E32E2F1C-62C5-3635-BA60-3E547C32DB9C.dita"><apiname>QueryCapability()</apiname></xref> function is used to inquire
+whether an MTM supports a given feature. The first argument is a UID defined
+to correspond to a particular capability. The function returns a system error
+code and the response (whether the MTM supports the queried capability) is
+passed back through the second (by-reference)<codeph>aResponse</codeph> parameter.
+This value can be an integer or a bit set, depending on the capability. </p> <p>The
+UIDs for the different types of query are as follows: </p> <table id="GUID-6ADE624E-8B18-58F9-9386-79A75E72E0C7">
+<tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
+<thead>
+<row>
+<entry>UID</entry>
+<entry>Capability</entry>
+</row>
+</thead>
+<tbody>
+<row>
+<entry><p> <codeph>KUidMsvMtmQueryMaxBodySize</codeph>  </p> </entry>
+<entry><p>Maximum message body size </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQueryMaxTotalMsgSize</codeph>  </p> </entry>
+<entry><p>Maximum total size of message. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMtmQuerySupportedBody</codeph>  </p> </entry>
+<entry><p>Character widths supported by message type. The returned value is
+the sum of the appropriate values. The return type is either of KMtm7BitBody,
+KMtm8BitBody, KMtm16BitBody, and KMtmBinaryBody) </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMtmQuerySupportAttachments</codeph>  </p> </entry>
+<entry><p>To check if the attachments are supported </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQuerySupportSubject</codeph>  </p> </entry>
+<entry><p>Does the MTM message type have a subject field </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMtmQuerySupportsFolder</codeph>  </p> </entry>
+<entry><p>Does the MTM support folders </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMtmQueryOffLineAllowed</codeph>  </p> </entry>
+<entry><p>Off-line operation allowed </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQueryCanSendMsg</codeph>  </p> </entry>
+<entry><p>Can send the message </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQueryCanReceiveMsg</codeph>  </p> </entry>
+<entry><p>Can receive the message </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQueryMaxRecipientCount</codeph>  </p> </entry>
+<entry><p>Maximum number of recipients (-1 indicates unlimited numbers). </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQuerySendAsRequiresRenderedImage</codeph>  </p> </entry>
+<entry><p>When using the MTM in Send As, does a rendered image have to be
+prepared. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMtmQuerySendAsRenderingUid</codeph>  </p> </entry>
+<entry><p>Printer driver UID for rendering the fax image. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMsvMtmQueryEditorUid</codeph>  </p> </entry>
+<entry><p>UID of default message editor. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMsvQuerySupportsBioMsg</codeph>  </p> </entry>
+<entry><p>Does the MTM support BIO messages </p> </entry>
+</row>
+<row>
+<entry><p> <codeph> KUidMsvQuerySupportsScheduling</codeph>  </p> </entry>
+<entry><p>Does the MTM support scheduled sending. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQuerySupportsRecipientType</codeph>  </p> </entry>
+<entry><p>Does the MTM support the use of recipient type. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>KUidMtmQuerySendAsMessageSendSupport</codeph>  </p> </entry>
+<entry><p>Support for Sending messages using SendAs. </p> <p>If this is supported,
+then the MTM supports sending messages created through the SendAs API. </p> </entry>
+</row>
+</tbody>
+</tgroup>
+</table> <p>The following example is a snapshot of the Text MTM example. For
+more implementation details, see <xref href="GUID-5B9F2EEE-A5F6-5833-BFC4-3B063EA7EDF2.dita">Messaging
+Text MTM example code</xref>. </p> <codeblock id="GUID-375C5493-8DAA-5B2D-B371-B7FD7DC2CCD1" xml:space="preserve">TInt CTextMtmClient::QueryCapability(TUid aCapability, TInt&amp; aResponse)
+    {
+    TInt error = KErrNone;
+    switch (aCapability.iUid)
+        {
+        case KUidMtmQueryMaxBodySizeValue:
+        case KUidMtmQueryMaxTotalMsgSizeValue:
+            aResponse = KMaxTextMessageSize;
+            break;
+        case KUidMtmQuerySupportedBodyValue:
+            aResponse = KMtm8BitBody + KMtm7BitBody;
+            break;
+        case KUidMtmQueryOffLineAllowedValue:
+        case KUidMtmQueryCanReceiveMsgValue:
+            aResponse = ETrue;
+            break;
+        case KUidMtmQuerySupportAttachmentsValue:
+        default:
+            return KErrNotSupported;
+        }
+    return error;
+    }
+</codeblock> </li>
+</ul> <p>The <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm</apiname></xref> class provides the virtual functions
+for overriding in derived classes. </p> </section>
+<section id="GUID-6DD0912E-1E82-5BAD-889C-5FA79E5E800C"><title>Client-side
+operations</title> <p>Many Messaging tasks can take a long time to complete.
+For example, sending all items from the Outbox or downloading a large number
+of items from a POP3 server. In these situations, the use of active objects
+to wait for the completion of the task is inadequate, since applications also
+require to obtain progress information while the task is running (for example,
+to update a progress dialog). To solve this problem, most asynchronous functions
+in Messaging create a <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref> object and return a
+pointer to it, as well as taking a <codeph>TRequestStatus&amp;</codeph> parameter.
+The <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref> class is derived from <xref href="GUID-067293BF-B28C-3CEC-92F4-1351A795EA7F.dita"><apiname>CActive</apiname></xref> and
+is used to obtain progress information about a long-running task. </p> <p>The
+base class for all client-side Messaging operations is <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref>.
+The asynchronous methods in the <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm </apiname></xref> interface all
+return a pointer to a <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref> object. When you implement
+an MTM, you will have to provide your own custom operations, derived from <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref>,
+and return those polymorphically from your implementations of the asynchronous
+APIs. </p> <p><b>Example</b> </p> <p>The forward operation of the Text MTM
+is explained in the following example. </p> <p>The forward operation is an
+active object state machine that runs a series of asynchronous tasks one after
+another and waits for each to complete before moving on to the next. After
+the operation has been completed, an active object is notified through its <codeph>TRequestStatus</codeph> passed
+into the operation at construction. </p> <p>The forward operation is constructed
+using standard two-phase construction. The <xref href="GUID-93132FF9-512F-30EC-8AB0-BD3E98F668E6.dita"><apiname>NewL()</apiname></xref> function
+takes two arguments of a <xref href="GUID-A4B1F874-27C0-3BB6-9D29-C35C75A5DB98.dita"><apiname>TMsvId</apiname></xref> (source message and destination
+folder) type, a <xref href="GUID-2DA04D96-F0AD-3FDC-9E36-1C27D889AF4B.dita"><apiname>CMsvSession</apiname></xref> reference, and the observer’s <codeph>TRequestStatus</codeph>,
+which is notified on completion. The active object is constructed and added
+to the scheduler, and then <xref href="GUID-C8E0575D-5A7F-3D00-9BE5-AD8D6DBCF2F7.dita"><apiname>ConstructL()</apiname></xref> is called: </p> <codeblock id="GUID-C046D5BB-A157-5F5D-9702-C9ED271B89E8" xml:space="preserve">void CTxtMtmForwardOperation::ConstructL()
+    {
+    iObserverRequestStatus = KRequestPending;
+    SetActive();
+    TRequestStatus* stat = &amp;iStatus;
+    User::RequestComplete(stat, KErrNone);
+    }
+</codeblock> <p>This has the effect of marking this stage of the operation
+as complete and means that <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> is called at the next
+opportunity. This simplifies the state machine because it means that all states
+and tasks are started in <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> and not in <xref href="GUID-C8E0575D-5A7F-3D00-9BE5-AD8D6DBCF2F7.dita"><apiname>ConstructL()</apiname></xref>. </p> <p>The <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> function
+starts each task and receives a notification when it completes. The current
+task being executed is stored in <xref href="GUID-51087246-DDFF-384B-9DB6-2525F8C73CA5.dita"><apiname>iProgress</apiname></xref> and <xref href="GUID-A36DDD59-6236-3549-9DEB-8BE1F402CB16.dita"><apiname>iState</apiname></xref>,
+as are the errors and the ID of the new forwarded message, once complete.
+The default state for <xref href="GUID-A36DDD59-6236-3549-9DEB-8BE1F402CB16.dita"><apiname>iState</apiname></xref> on construction is <codeph>EInit</codeph>. </p> <codeblock id="GUID-B223CED8-8391-5825-BAC7-E81ED08C7E7E" xml:space="preserve">void CTxtMtmForwardOperation::RunL()
+    {
+    User::LeaveIfError(iStatus.Int());
+    switch(iProgress.iState)
+        {        
+        case TTxtMtmForwardOpProgress::EInit:
+            iProgress.iState =
+               TTxtMtmForwardOpProgress::ECreateMessage;
+            CreateMessageL();
+            break;
+
+        case TTxtMtmForwardOpProgress::ECreateMessage:
+            iProgress.iState =
+               TTxtMtmForwardOpProgress::EFormatBodyText;
+            FormatBodyTextL();
+            break;
+
+        case TTxtMtmForwardOpProgress::EFormatBodyText:
+            iProgress.iState =
+               TTxtMtmForwardOpProgress::EFinished;
+        
+        default:
+            break;
+        }
+    if(!IsActive())
+        {
+        TRequestStatus* stat = &amp;iObserverRequestStatus;
+        User::RequestComplete(stat, KErrNone);
+        }
+    }
+</codeblock> <p>If the state is <codeph>EInit</codeph>, the <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> changes
+state to <codeph>ECreateMessage</codeph> and then calls <xref href="GUID-E1D580C2-8B05-3A9E-8157-A3F849811AAB.dita"><apiname>CreateMessageL()</apiname></xref> to
+start the process of creating a message asynchronously. </p> <codeblock id="GUID-69C1C1DB-8813-56DC-8BDF-BF8B13D43583" xml:space="preserve">void CTxtMtmForwardOperation::CreateMessageL()
+    {
+</codeblock> <p>The function constructs a <xref href="GUID-85BBE389-81F7-3E2F-A789-446D9BE2CC49.dita"><apiname>CMsvEntry</apiname></xref> for
+the source entry and then retrieves its index entry. </p> <codeblock id="GUID-5E1A2C12-832E-54BF-91A4-9755348FD298" xml:space="preserve">delete iMsvEntry;
+    iMsvEntry = NULL;
+    iMsvEntry = iMsvSession.GetEntryL(iSourceMessage);
+        
+    // Get the entry to be forwarded    
+    TMsvEntry forwardEntry = iMsvEntry-&gt;Entry();
+</codeblock> <p>The context of <xref href="GUID-55F14844-0FCB-380C-B797-956CA2B2CFE2.dita"><apiname>iMsvEntry</apiname></xref> is changed to
+the destination folder and an entry is created. </p> <codeblock id="GUID-ECBE0131-DCC1-5182-B8D9-DBA35F4FD42A" xml:space="preserve">// Set the context to the destination folder
+    iMsvEntry-&gt;SetEntryL(iDestinationFolder);
+</codeblock> <p>The index entry’s date is updated to reflect the current date. </p> <codeblock id="GUID-B7156135-805B-509E-8778-EA17E5B69AE6" xml:space="preserve">// Create the forwarded index entry
+    forwardEntry.iDate.HomeTime();
+    iMsvEntry-&gt;CreateL(forwardEntry);
+</codeblock> <p>The <xref href="GUID-CAE27183-B48C-3B02-A88D-98CC51475DC0.dita"><apiname>iFinalMsgId</apiname></xref> member of the progress
+is updated to reflect the newly created entry. </p> <codeblock id="GUID-2C15F0E2-64C9-507B-8997-D257DACE0EEB" xml:space="preserve">iProgress.iFinalMsgId = forwardEntry.Id();
+
+    // schedules the active object to complete so that this 
+    // class's RunL method
+    // will be called by the active scheduler
+    SetActive();
+</codeblock> <p>The operation’s <codeph>TRequestStatus</codeph> is then flagged
+to cause <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref>. </p> <codeblock id="GUID-971DFF4A-E78F-5EBD-8DFB-616DA421E521" xml:space="preserve">TRequestStatus* stat = &amp;iStatus;
+    User::RequestComplete(stat, KErrNone);
+     }
+</codeblock> <p>When this happens,<codeph> iProgress.iState</codeph> is set
+to <codeph>ECreateMessage</codeph>, so the following code is executed: </p> <codeblock id="GUID-1AA9893A-2CAA-5E64-A09A-E20689B38BAF" xml:space="preserve">case TTxtMtmForwardOpProgress::ECreateMessage:
+    iProgress.iState =        TTxtMtmForwardOpProgress::EFormatBodyText;
+    FormatBodyTextL();
+    break;</codeblock> <p>The state is set to <codeph>EFormatBodyText</codeph> and
+the <xref href="GUID-FC4144F7-9D46-3D30-8316-ED22170E37B0.dita"><apiname>FormatBodyTextL()</apiname></xref> function is called. </p> <codeblock id="GUID-51C72DF8-9F39-51EA-BFFC-E4793A7B6621" xml:space="preserve">
+void CTxtMtmForwardOperation::FormatBodyTextL()
+   { 
+</codeblock> <p>The function constructs a <xref href="GUID-C5A6B3D4-1BDE-35B4-AC6B-DF517A4D4147.dita"><apiname>CParaFormatLayer</apiname></xref>,
+a <xref href="GUID-7BEFAAD5-15C3-35A0-BDEF-BC56380D6CE5.dita"><apiname>CCharFormatLayer</apiname></xref>, and a <xref href="GUID-39945DA4-B362-3DF6-BF9E-DD079EEA7934.dita"><apiname>CRichText</apiname></xref> object.
+These objects are required to store the body text of the forwarded message. </p> <codeblock id="GUID-D02202DB-9E19-5873-86D6-6B0DCF035B74" xml:space="preserve">CParaFormatLayer* paraLayer = CParaFormatLayer::NewL();
+   CleanupStack::PushL(paraLayer);
+   CCharFormatLayer* charLayer = CCharFormatLayer::NewL();
+   CleanupStack::PushL(charLayer);
+   CRichText* body = CRichText::NewL(paraLayer, charLayer);
+   CleanupStack::PushL(body);
+</codeblock> <p>Then the context of <codeph>iMsvEntry</codeph> is changed
+to point at the source message and a read-only <xref href="GUID-8CB90FA2-A6CF-3FA2-81FF-7D22EFD9C2CE.dita"><apiname>CMsvStore</apiname></xref> is
+opened for that entry. </p> <codeblock id="GUID-F3B582CD-867C-54FD-ACAB-0F50319601BC" xml:space="preserve">// Get the message store from the source entry
+   iMsvEntry-&gt;SetEntryL(iSourceMessage);
+   CMsvStore* readStore = iMsvEntry-&gt;ReadStoreL();
+   CleanupStack::PushL(readStore);</codeblock> <p>The context of the <xref href="GUID-55F14844-0FCB-380C-B797-956CA2B2CFE2.dita"><apiname>iMsvEntry</apiname></xref> object
+is changed to point at the newly created entry and a <xref href="GUID-8CB90FA2-A6CF-3FA2-81FF-7D22EFD9C2CE.dita"><apiname>CMsvStore</apiname></xref> is
+opened for that entry. </p> <codeblock id="GUID-097EC5DB-9FCB-5D45-8B94-8E7DB5256005" xml:space="preserve">// Get the message store from the newly created destination 
+   // entry
+   iMsvEntry-&gt;SetEntryL(iProgress.iFinalMsgId);
+   CMsvStore* writeStore = iMsvEntry-&gt;EditStoreL();
+   CleanupStack::PushL(writeStore);
+
+   // Get the body text from the source entry and write it
+   // to the destination entry, prepending the forward 
+   // prefix
+   readStore-&gt;RestoreBodyTextL(*body);
+   body-&gt;InsertL(0, KTxtMtmFwdPrefix);
+
+     // this method performs a commit for us
+   writeStore-&gt;StoreBodyTextL(*body);
+ 
+   CleanupStack::PopAndDestroy(5, paraLayer); 
+
+   // schedules the active object to complete so that this 
+   // class's RunL method
+   // will be called by the active scheduler
+   SetActive();
+   TRequestStatus* stat = &amp;iStatus;
+   User::RequestComplete(stat, KErrNone);
+   }
+</codeblock> <p>The <codeph>iProgress.iState</codeph> is set to <codeph>EFinished</codeph>,
+and because the object has not been activated the following conditional statement
+evaluates true: </p> <codeblock id="GUID-9CC7BAD3-B185-59F4-8CED-7BE23886661A" xml:space="preserve">if(!IsActive())
+    {
+    TRequestStatus* stat = &amp;iObserverRequestStatus;
+    User::RequestComplete(stat, KErrNone);
+    }
+</codeblock> <p>The observer active object’s <codeph>TRequestStatus</codeph> is
+flagged to let it know that the operation is complete. </p> <p>To return progress
+from the operation, implement the <xref href="GUID-E13013FF-09B9-3A9A-B471-0A9AE90E49EC.dita"><apiname>ProgressL()</apiname></xref> and <xref href="GUID-890A4968-EAD6-30F5-97D8-E6C07BA28B37.dita"><apiname>FinalProgress()</apiname></xref> functions. <xref href="GUID-E13013FF-09B9-3A9A-B471-0A9AE90E49EC.dita"><apiname>ProgressL()</apiname></xref> must
+be used to return progress information on the operation during processing,
+and <xref href="GUID-890A4968-EAD6-30F5-97D8-E6C07BA28B37.dita"><apiname>FinalProgress()</apiname></xref> is guaranteed to return the status
+of a completed operation. <xref href="GUID-E13013FF-09B9-3A9A-B471-0A9AE90E49EC.dita"><apiname>ProgressL()</apiname></xref> must be implemented
+to leave with <codeph>KErrNotReady</codeph> if the operation is not in progress,
+and <xref href="GUID-890A4968-EAD6-30F5-97D8-E6C07BA28B37.dita"><apiname>FinalProgress()</apiname></xref> must panic if the operation is not
+complete. </p> <codeblock id="GUID-4EAE052A-F445-589E-8B6A-983A579FBAE6" xml:space="preserve">const TDesC8&amp; CTxtMtmForwardOperation::ProgressL()
+            {
+            if (!IsActive())
+                        {
+                        User::Leave(KErrNotReady);
+                        }
+   iProgressBuf() = iProgress;
+   return iProgressBuf;
+   }
+
+const TDesC8&amp; CTxtMtmForwardOperation::FinalProgress()
+            {
+    __ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCPanic,
+                            ETxtcOperationIsActive));
+            iProgressBuf() = iProgress;
+   return iProgressBuf;
+   }</codeblock> <p>The <xref href="GUID-189483E6-31EA-32DF-8CD5-ECE58592DB3E.dita"><apiname>RunError()</apiname></xref> function must also be
+implemented to get any leaves in <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref>. </p> <codeblock id="GUID-D41E3F81-83E2-5F9C-BDB0-A97A4D9920A6" xml:space="preserve">TInt CTxtMtmForwardOperation::RunError(TInt aError)
+    {
+    iProgress.iError = aError;    
+    TRequestStatus* stat = &amp;iObserverRequestStatus;
+    User::RequestComplete(stat, aError);
+    return KErrNone;
+    }</codeblock> </section>
+</conbody><related-links>
+<link href="GUID-59217FA7-3078-53CA-88B3-78D6FB788271.dita"><linktext>MTM overview</linktext>
+</link>
+<link href="GUID-BAD138D5-2914-5C6E-9FA4-F7A3CCB85E6D.dita"><linktext>MTM Capabilities</linktext>
+</link>
+<link href="GUID-1E2DB50A-D8D7-595D-8448-77F057655E82.dita"><linktext>Writing a
+Client MTM</linktext></link>
+</related-links></concept>
\ No newline at end of file