Symbian3/SDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita
changeset 7 51a74ef9ed63
parent 0 89d6a7a84779
equal deleted inserted replaced
6:43e37759235e 7:51a74ef9ed63
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-E180D222-CC4F-5007-93FC-C339BBE708BC" xml:lang="en"><title>Client
       
    13 MTM</title><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>Client MTMs provide a client-side API to functionality provided by the
       
    15 Server MTM, mainly for message manipulation and transport. It acts as the
       
    16 interface between the internal representation of a message’s data and the
       
    17 User Interface (UI) MTM. This architecture provides certain advantages; for
       
    18 example, a UI MTM can offer a user interface to enter message addresses without
       
    19 knowing the address storage format. Message client applications that do not
       
    20 require a user interface can use these client-side functions directly for
       
    21 automated message handling. </p>
       
    22 <p>The Message Server entry with which Client MTMs currently work is referred
       
    23 to as the context. UI MTMs always operate on the contexts set through Client
       
    24 MTMs. </p>
       
    25 <p>Client MTMs offer some or all of the following capabilities: </p>
       
    26 <ul>
       
    27 <li id="GUID-4327B533-04C0-5110-B8AD-90EC90C73D32"><p>Address list manipulation </p> </li>
       
    28 <li id="GUID-FC4908FC-5958-5815-90EB-D601B4710247"><p>Creation of forward
       
    29 and response messages </p> </li>
       
    30 <li id="GUID-CF8196EB-1C40-50D0-86AA-0F2C954CBC5D"><p>Message subject access </p> </li>
       
    31 <li id="GUID-51B25D57-A577-5375-9DD6-D398C8B860A8"><p>Message validation </p> </li>
       
    32 <li id="GUID-4345AB18-2096-5312-955D-EACE72DCA52F"><p>Internalising and externalising
       
    33 MTM-specific data to the Message Store </p> </li>
       
    34 </ul>
       
    35 <section id="GUID-BCFBE2C5-2C90-5E43-9B21-0D80A469CEAB"><title>Client MTM
       
    36 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
       
    37 provides a high-level interface for accessing and manipulating a Message Server
       
    38 entry </p> <p>The following are some significant functions in <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm</apiname></xref>.
       
    39 Some functions are implemented by the base class, and others must be implemented
       
    40 in a derived class: </p> <ul>
       
    41 <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
       
    42 change the Message Server entry (the context) on which later actions are performed.
       
    43 After creating a new Client MTM object, a message client application must
       
    44 set an initial context before using other functions. </p> </li>
       
    45 <li id="GUID-1E3E98F7-FBBF-5594-A7EF-93D7106FD3D3"><p> <b>Store and restore
       
    46 entry data functions</b>  </p> <p>The changes that a message client application
       
    47 makes to a message context through Client MTM functions, such as altering
       
    48 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
       
    49 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
       
    50 restore (<xref href="GUID-DF6E56F8-3B05-3D34-8500-BDA77BABD05D.dita"><apiname>LoadMessageL()</apiname></xref>), functions are concerned with
       
    51 transferring data between that cache and committed storage. </p> <p> <b>Note:</b> Unlike
       
    52 message contexts, message client applications are not expected to manipulate
       
    53 directly contexts for message services. Instead, the corresponding <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita"><apiname>User</apiname></xref> Interface
       
    54 MTM provides a dialog to allow the user to alter service settings, and calls
       
    55 Client MTM functions to handle their retrieval and storage. </p> </li>
       
    56 <li id="GUID-A0FDCB02-3C4E-5CB0-A374-61C89889621B"><p> <b>Store and restore
       
    57 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
       
    58 cache to store the body text for the current context. This can be accessed
       
    59 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>.
       
    60 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
       
    61 &amp;)</codeph> functions encapsulate the retrieval and storage of this <xref href="GUID-39945DA4-B362-3DF6-BF9E-DD079EEA7934.dita"><apiname>CRichText</apiname></xref> object
       
    62 to a <xref href="GUID-8CB90FA2-A6CF-3FA2-81FF-7D22EFD9C2CE.dita"><apiname>CMsvStore</apiname></xref>. </p> </li>
       
    63 <li id="GUID-B44CFD8D-DB97-5A4D-B876-EA04D464A5B1"><p> <b>Address list functions</b>  </p> <p>The
       
    64 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
       
    65 clients to access address information in a generic way without having MTM-specific
       
    66 knowledge. </p> </li>
       
    67 <li id="GUID-F1E2AAD3-41E0-522A-B7AC-7090EE823807"><p> <b>MTM-specific client
       
    68 functions</b>  </p> <p>MTM components can offer protocol-specific functionality
       
    69 not provided by base class interface functions. MTM components define IDs
       
    70 that correspond to each protocol-specific operation offered, and implement
       
    71 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
       
    72 to allow clients to access these operations by passing in the appropriate
       
    73 ID. These functions are provided to allow the MTM component to offer both
       
    74 synchronous and asynchronous functionality. Message client applications can
       
    75 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>
       
    76 <li id="GUID-A4A3ED85-EAC5-58BC-BB40-E40949A84B66"><p> <b>Query function</b>  </p> <p>The
       
    77 Client MTM <xref href="GUID-E32E2F1C-62C5-3635-BA60-3E547C32DB9C.dita"><apiname>QueryCapability()</apiname></xref> function is used to inquire
       
    78 whether an MTM supports a given feature. The first argument is a UID defined
       
    79 to correspond to a particular capability. The function returns a system error
       
    80 code and the response (whether the MTM supports the queried capability) is
       
    81 passed back through the second (by-reference)<codeph>aResponse</codeph> parameter.
       
    82 This value can be an integer or a bit set, depending on the capability. </p> <p>The
       
    83 UIDs for the different types of query are as follows: </p> <table id="GUID-6ADE624E-8B18-58F9-9386-79A75E72E0C7">
       
    84 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
       
    85 <thead>
       
    86 <row>
       
    87 <entry>UID</entry>
       
    88 <entry>Capability</entry>
       
    89 </row>
       
    90 </thead>
       
    91 <tbody>
       
    92 <row>
       
    93 <entry><p> <codeph>KUidMsvMtmQueryMaxBodySize</codeph>  </p> </entry>
       
    94 <entry><p>Maximum message body size </p> </entry>
       
    95 </row>
       
    96 <row>
       
    97 <entry><p> <codeph>KUidMtmQueryMaxTotalMsgSize</codeph>  </p> </entry>
       
    98 <entry><p>Maximum total size of message. </p> </entry>
       
    99 </row>
       
   100 <row>
       
   101 <entry><p> <codeph> KUidMtmQuerySupportedBody</codeph>  </p> </entry>
       
   102 <entry><p>Character widths supported by message type. The returned value is
       
   103 the sum of the appropriate values. The return type is either of KMtm7BitBody,
       
   104 KMtm8BitBody, KMtm16BitBody, and KMtmBinaryBody) </p> </entry>
       
   105 </row>
       
   106 <row>
       
   107 <entry><p> <codeph> KUidMtmQuerySupportAttachments</codeph>  </p> </entry>
       
   108 <entry><p>To check if the attachments are supported </p> </entry>
       
   109 </row>
       
   110 <row>
       
   111 <entry><p> <codeph>KUidMtmQuerySupportSubject</codeph>  </p> </entry>
       
   112 <entry><p>Does the MTM message type have a subject field </p> </entry>
       
   113 </row>
       
   114 <row>
       
   115 <entry><p> <codeph> KUidMtmQuerySupportsFolder</codeph>  </p> </entry>
       
   116 <entry><p>Does the MTM support folders </p> </entry>
       
   117 </row>
       
   118 <row>
       
   119 <entry><p> <codeph> KUidMtmQueryOffLineAllowed</codeph>  </p> </entry>
       
   120 <entry><p>Off-line operation allowed </p> </entry>
       
   121 </row>
       
   122 <row>
       
   123 <entry><p> <codeph>KUidMtmQueryCanSendMsg</codeph>  </p> </entry>
       
   124 <entry><p>Can send the message </p> </entry>
       
   125 </row>
       
   126 <row>
       
   127 <entry><p> <codeph>KUidMtmQueryCanReceiveMsg</codeph>  </p> </entry>
       
   128 <entry><p>Can receive the message </p> </entry>
       
   129 </row>
       
   130 <row>
       
   131 <entry><p> <codeph>KUidMtmQueryMaxRecipientCount</codeph>  </p> </entry>
       
   132 <entry><p>Maximum number of recipients (-1 indicates unlimited numbers). </p> </entry>
       
   133 </row>
       
   134 <row>
       
   135 <entry><p> <codeph>KUidMtmQuerySendAsRequiresRenderedImage</codeph>  </p> </entry>
       
   136 <entry><p>When using the MTM in Send As, does a rendered image have to be
       
   137 prepared. </p> </entry>
       
   138 </row>
       
   139 <row>
       
   140 <entry><p> <codeph> KUidMtmQuerySendAsRenderingUid</codeph>  </p> </entry>
       
   141 <entry><p>Printer driver UID for rendering the fax image. </p> </entry>
       
   142 </row>
       
   143 <row>
       
   144 <entry><p> <codeph>KUidMsvMtmQueryEditorUid</codeph>  </p> </entry>
       
   145 <entry><p>UID of default message editor. </p> </entry>
       
   146 </row>
       
   147 <row>
       
   148 <entry><p> <codeph>KUidMsvQuerySupportsBioMsg</codeph>  </p> </entry>
       
   149 <entry><p>Does the MTM support BIO messages </p> </entry>
       
   150 </row>
       
   151 <row>
       
   152 <entry><p> <codeph> KUidMsvQuerySupportsScheduling</codeph>  </p> </entry>
       
   153 <entry><p>Does the MTM support scheduled sending. </p> </entry>
       
   154 </row>
       
   155 <row>
       
   156 <entry><p> <codeph>KUidMtmQuerySupportsRecipientType</codeph>  </p> </entry>
       
   157 <entry><p>Does the MTM support the use of recipient type. </p> </entry>
       
   158 </row>
       
   159 <row>
       
   160 <entry><p> <codeph>KUidMtmQuerySendAsMessageSendSupport</codeph>  </p> </entry>
       
   161 <entry><p>Support for Sending messages using SendAs. </p> <p>If this is supported,
       
   162 then the MTM supports sending messages created through the SendAs API. </p> </entry>
       
   163 </row>
       
   164 </tbody>
       
   165 </tgroup>
       
   166 </table> <p>The following example is a snapshot of the Text MTM example. For
       
   167 more implementation details, see <xref href="GUID-5B9F2EEE-A5F6-5833-BFC4-3B063EA7EDF2.dita">Messaging
       
   168 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)
       
   169     {
       
   170     TInt error = KErrNone;
       
   171     switch (aCapability.iUid)
       
   172         {
       
   173         case KUidMtmQueryMaxBodySizeValue:
       
   174         case KUidMtmQueryMaxTotalMsgSizeValue:
       
   175             aResponse = KMaxTextMessageSize;
       
   176             break;
       
   177         case KUidMtmQuerySupportedBodyValue:
       
   178             aResponse = KMtm8BitBody + KMtm7BitBody;
       
   179             break;
       
   180         case KUidMtmQueryOffLineAllowedValue:
       
   181         case KUidMtmQueryCanReceiveMsgValue:
       
   182             aResponse = ETrue;
       
   183             break;
       
   184         case KUidMtmQuerySupportAttachmentsValue:
       
   185         default:
       
   186             return KErrNotSupported;
       
   187         }
       
   188     return error;
       
   189     }
       
   190 </codeblock> </li>
       
   191 </ul> <p>The <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm</apiname></xref> class provides the virtual functions
       
   192 for overriding in derived classes. </p> </section>
       
   193 <section id="GUID-6DD0912E-1E82-5BAD-889C-5FA79E5E800C"><title>Client-side
       
   194 operations</title> <p>Many Messaging tasks can take a long time to complete.
       
   195 For example, sending all items from the Outbox or downloading a large number
       
   196 of items from a POP3 server. In these situations, the use of active objects
       
   197 to wait for the completion of the task is inadequate, since applications also
       
   198 require to obtain progress information while the task is running (for example,
       
   199 to update a progress dialog). To solve this problem, most asynchronous functions
       
   200 in Messaging create a <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref> object and return a
       
   201 pointer to it, as well as taking a <codeph>TRequestStatus&amp;</codeph> parameter.
       
   202 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
       
   203 is used to obtain progress information about a long-running task. </p> <p>The
       
   204 base class for all client-side Messaging operations is <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref>.
       
   205 The asynchronous methods in the <xref href="GUID-177AF50B-14EF-3C45-AE22-1FEE5678261D.dita"><apiname>CBaseMtm </apiname></xref> interface all
       
   206 return a pointer to a <xref href="GUID-AF724192-6580-3DE3-9287-3A005C0AA932.dita"><apiname>CMsvOperation</apiname></xref> object. When you implement
       
   207 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>,
       
   208 and return those polymorphically from your implementations of the asynchronous
       
   209 APIs. </p> <p><b>Example</b> </p> <p>The forward operation of the Text MTM
       
   210 is explained in the following example. </p> <p>The forward operation is an
       
   211 active object state machine that runs a series of asynchronous tasks one after
       
   212 another and waits for each to complete before moving on to the next. After
       
   213 the operation has been completed, an active object is notified through its <codeph>TRequestStatus</codeph> passed
       
   214 into the operation at construction. </p> <p>The forward operation is constructed
       
   215 using standard two-phase construction. The <xref href="GUID-93132FF9-512F-30EC-8AB0-BD3E98F668E6.dita"><apiname>NewL()</apiname></xref> function
       
   216 takes two arguments of a <xref href="GUID-A4B1F874-27C0-3BB6-9D29-C35C75A5DB98.dita"><apiname>TMsvId</apiname></xref> (source message and destination
       
   217 folder) type, a <xref href="GUID-2DA04D96-F0AD-3FDC-9E36-1C27D889AF4B.dita"><apiname>CMsvSession</apiname></xref> reference, and the observer’s <codeph>TRequestStatus</codeph>,
       
   218 which is notified on completion. The active object is constructed and added
       
   219 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()
       
   220     {
       
   221     iObserverRequestStatus = KRequestPending;
       
   222     SetActive();
       
   223     TRequestStatus* stat = &amp;iStatus;
       
   224     User::RequestComplete(stat, KErrNone);
       
   225     }
       
   226 </codeblock> <p>This has the effect of marking this stage of the operation
       
   227 as complete and means that <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> is called at the next
       
   228 opportunity. This simplifies the state machine because it means that all states
       
   229 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
       
   230 starts each task and receives a notification when it completes. The current
       
   231 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>,
       
   232 as are the errors and the ID of the new forwarded message, once complete.
       
   233 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()
       
   234     {
       
   235     User::LeaveIfError(iStatus.Int());
       
   236     switch(iProgress.iState)
       
   237         {        
       
   238         case TTxtMtmForwardOpProgress::EInit:
       
   239             iProgress.iState =
       
   240                TTxtMtmForwardOpProgress::ECreateMessage;
       
   241             CreateMessageL();
       
   242             break;
       
   243 
       
   244         case TTxtMtmForwardOpProgress::ECreateMessage:
       
   245             iProgress.iState =
       
   246                TTxtMtmForwardOpProgress::EFormatBodyText;
       
   247             FormatBodyTextL();
       
   248             break;
       
   249 
       
   250         case TTxtMtmForwardOpProgress::EFormatBodyText:
       
   251             iProgress.iState =
       
   252                TTxtMtmForwardOpProgress::EFinished;
       
   253         
       
   254         default:
       
   255             break;
       
   256         }
       
   257     if(!IsActive())
       
   258         {
       
   259         TRequestStatus* stat = &amp;iObserverRequestStatus;
       
   260         User::RequestComplete(stat, KErrNone);
       
   261         }
       
   262     }
       
   263 </codeblock> <p>If the state is <codeph>EInit</codeph>, the <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> changes
       
   264 state to <codeph>ECreateMessage</codeph> and then calls <xref href="GUID-E1D580C2-8B05-3A9E-8157-A3F849811AAB.dita"><apiname>CreateMessageL()</apiname></xref> to
       
   265 start the process of creating a message asynchronously. </p> <codeblock id="GUID-69C1C1DB-8813-56DC-8BDF-BF8B13D43583" xml:space="preserve">void CTxtMtmForwardOperation::CreateMessageL()
       
   266     {
       
   267 </codeblock> <p>The function constructs a <xref href="GUID-85BBE389-81F7-3E2F-A789-446D9BE2CC49.dita"><apiname>CMsvEntry</apiname></xref> for
       
   268 the source entry and then retrieves its index entry. </p> <codeblock id="GUID-5E1A2C12-832E-54BF-91A4-9755348FD298" xml:space="preserve">delete iMsvEntry;
       
   269     iMsvEntry = NULL;
       
   270     iMsvEntry = iMsvSession.GetEntryL(iSourceMessage);
       
   271         
       
   272     // Get the entry to be forwarded    
       
   273     TMsvEntry forwardEntry = iMsvEntry-&gt;Entry();
       
   274 </codeblock> <p>The context of <xref href="GUID-55F14844-0FCB-380C-B797-956CA2B2CFE2.dita"><apiname>iMsvEntry</apiname></xref> is changed to
       
   275 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
       
   276     iMsvEntry-&gt;SetEntryL(iDestinationFolder);
       
   277 </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
       
   278     forwardEntry.iDate.HomeTime();
       
   279     iMsvEntry-&gt;CreateL(forwardEntry);
       
   280 </codeblock> <p>The <xref href="GUID-CAE27183-B48C-3B02-A88D-98CC51475DC0.dita"><apiname>iFinalMsgId</apiname></xref> member of the progress
       
   281 is updated to reflect the newly created entry. </p> <codeblock id="GUID-2C15F0E2-64C9-507B-8997-D257DACE0EEB" xml:space="preserve">iProgress.iFinalMsgId = forwardEntry.Id();
       
   282 
       
   283     // schedules the active object to complete so that this 
       
   284     // class's RunL method
       
   285     // will be called by the active scheduler
       
   286     SetActive();
       
   287 </codeblock> <p>The operation’s <codeph>TRequestStatus</codeph> is then flagged
       
   288 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;
       
   289     User::RequestComplete(stat, KErrNone);
       
   290      }
       
   291 </codeblock> <p>When this happens,<codeph> iProgress.iState</codeph> is set
       
   292 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:
       
   293     iProgress.iState =        TTxtMtmForwardOpProgress::EFormatBodyText;
       
   294     FormatBodyTextL();
       
   295     break;</codeblock> <p>The state is set to <codeph>EFormatBodyText</codeph> and
       
   296 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">
       
   297 void CTxtMtmForwardOperation::FormatBodyTextL()
       
   298    { 
       
   299 </codeblock> <p>The function constructs a <xref href="GUID-C5A6B3D4-1BDE-35B4-AC6B-DF517A4D4147.dita"><apiname>CParaFormatLayer</apiname></xref>,
       
   300 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.
       
   301 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();
       
   302    CleanupStack::PushL(paraLayer);
       
   303    CCharFormatLayer* charLayer = CCharFormatLayer::NewL();
       
   304    CleanupStack::PushL(charLayer);
       
   305    CRichText* body = CRichText::NewL(paraLayer, charLayer);
       
   306    CleanupStack::PushL(body);
       
   307 </codeblock> <p>Then the context of <codeph>iMsvEntry</codeph> is changed
       
   308 to point at the source message and a read-only <xref href="GUID-8CB90FA2-A6CF-3FA2-81FF-7D22EFD9C2CE.dita"><apiname>CMsvStore</apiname></xref> is
       
   309 opened for that entry. </p> <codeblock id="GUID-F3B582CD-867C-54FD-ACAB-0F50319601BC" xml:space="preserve">// Get the message store from the source entry
       
   310    iMsvEntry-&gt;SetEntryL(iSourceMessage);
       
   311    CMsvStore* readStore = iMsvEntry-&gt;ReadStoreL();
       
   312    CleanupStack::PushL(readStore);</codeblock> <p>The context of the <xref href="GUID-55F14844-0FCB-380C-B797-956CA2B2CFE2.dita"><apiname>iMsvEntry</apiname></xref> object
       
   313 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
       
   314 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 
       
   315    // entry
       
   316    iMsvEntry-&gt;SetEntryL(iProgress.iFinalMsgId);
       
   317    CMsvStore* writeStore = iMsvEntry-&gt;EditStoreL();
       
   318    CleanupStack::PushL(writeStore);
       
   319 
       
   320    // Get the body text from the source entry and write it
       
   321    // to the destination entry, prepending the forward 
       
   322    // prefix
       
   323    readStore-&gt;RestoreBodyTextL(*body);
       
   324    body-&gt;InsertL(0, KTxtMtmFwdPrefix);
       
   325 
       
   326      // this method performs a commit for us
       
   327    writeStore-&gt;StoreBodyTextL(*body);
       
   328  
       
   329    CleanupStack::PopAndDestroy(5, paraLayer); 
       
   330 
       
   331    // schedules the active object to complete so that this 
       
   332    // class's RunL method
       
   333    // will be called by the active scheduler
       
   334    SetActive();
       
   335    TRequestStatus* stat = &amp;iStatus;
       
   336    User::RequestComplete(stat, KErrNone);
       
   337    }
       
   338 </codeblock> <p>The <codeph>iProgress.iState</codeph> is set to <codeph>EFinished</codeph>,
       
   339 and because the object has not been activated the following conditional statement
       
   340 evaluates true: </p> <codeblock id="GUID-9CC7BAD3-B185-59F4-8CED-7BE23886661A" xml:space="preserve">if(!IsActive())
       
   341     {
       
   342     TRequestStatus* stat = &amp;iObserverRequestStatus;
       
   343     User::RequestComplete(stat, KErrNone);
       
   344     }
       
   345 </codeblock> <p>The observer active object’s <codeph>TRequestStatus</codeph> is
       
   346 flagged to let it know that the operation is complete. </p> <p>To return progress
       
   347 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
       
   348 be used to return progress information on the operation during processing,
       
   349 and <xref href="GUID-890A4968-EAD6-30F5-97D8-E6C07BA28B37.dita"><apiname>FinalProgress()</apiname></xref> is guaranteed to return the status
       
   350 of a completed operation. <xref href="GUID-E13013FF-09B9-3A9A-B471-0A9AE90E49EC.dita"><apiname>ProgressL()</apiname></xref> must be implemented
       
   351 to leave with <codeph>KErrNotReady</codeph> if the operation is not in progress,
       
   352 and <xref href="GUID-890A4968-EAD6-30F5-97D8-E6C07BA28B37.dita"><apiname>FinalProgress()</apiname></xref> must panic if the operation is not
       
   353 complete. </p> <codeblock id="GUID-4EAE052A-F445-589E-8B6A-983A579FBAE6" xml:space="preserve">const TDesC8&amp; CTxtMtmForwardOperation::ProgressL()
       
   354             {
       
   355             if (!IsActive())
       
   356                         {
       
   357                         User::Leave(KErrNotReady);
       
   358                         }
       
   359    iProgressBuf() = iProgress;
       
   360    return iProgressBuf;
       
   361    }
       
   362 
       
   363 const TDesC8&amp; CTxtMtmForwardOperation::FinalProgress()
       
   364             {
       
   365     __ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCPanic,
       
   366                             ETxtcOperationIsActive));
       
   367             iProgressBuf() = iProgress;
       
   368    return iProgressBuf;
       
   369    }</codeblock> <p>The <xref href="GUID-189483E6-31EA-32DF-8CD5-ECE58592DB3E.dita"><apiname>RunError()</apiname></xref> function must also be
       
   370 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)
       
   371     {
       
   372     iProgress.iError = aError;    
       
   373     TRequestStatus* stat = &amp;iObserverRequestStatus;
       
   374     User::RequestComplete(stat, aError);
       
   375     return KErrNone;
       
   376     }</codeblock> </section>
       
   377 </conbody><related-links>
       
   378 <link href="GUID-59217FA7-3078-53CA-88B3-78D6FB788271.dita"><linktext>MTM overview</linktext>
       
   379 </link>
       
   380 <link href="GUID-BAD138D5-2914-5C6E-9FA4-F7A3CCB85E6D.dita"><linktext>MTM Capabilities</linktext>
       
   381 </link>
       
   382 <link href="GUID-1E2DB50A-D8D7-595D-8448-77F057655E82.dita"><linktext>Writing a
       
   383 Client MTM</linktext></link>
       
   384 </related-links></concept>