lafagnosticuifoundation/uigraphicsutils/tulsrc/tultextresourceutils.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 #include <tultextresourceutils.h>
       
    19 #include <tulpanics.h>
       
    20 #include "languagespecificnumberconverter.h"
       
    21 #include <coeutils.h>
       
    22 #include <bautils.h>
       
    23 #include <coemain.h>
       
    24 
       
    25 // CP1252 ellipsis character value.
       
    26 #define KEllipsis		0x2026  // cp1252=133
       
    27 
       
    28 // KIntSize and KKeySize define maximum number of characters
       
    29 // in input TInts and in keystring. KNumOfParams is maximum number of
       
    30 // parameters in the resource string.
       
    31 const TInt KIntSize(11); //Max 11 digits.
       
    32 const TInt KNumOfParams(20); //Max 20 parameters
       
    33 const TInt KKeySize (4); //Max 2 digits in index. For example %20U
       
    34 
       
    35 // Key strings for number and unicode data.
       
    36 _LIT(KNumKeyBuf, "%N"); //Number data
       
    37 _LIT(KStringKeyBuf, "%U"); //Unicode data
       
    38 
       
    39 // Key characters to format key strings.
       
    40 const TText KKeyPrefix('%');
       
    41 const TText KNumKey('N');
       
    42 const TText KStringKey('U');
       
    43 const TText KSubStringSeparator(0x0001);	// pipe ('|') character
       
    44 const TText KDirNotFound( 0x0002 );
       
    45 
       
    46 const TInt KNoIndex(-1); //No index- code in Format-method.
       
    47 
       
    48 //Panic category
       
    49 _LIT(KPanicCategory, "TulTextResourceUtils");
       
    50 
       
    51 const TInt KExtraSpaceForMainStringDirMarker = 1;
       
    52 const TInt KExtraSpaceForSubStringDirMarkers = 2;
       
    53 const TText KLRMarker = 0x200E;
       
    54 const TText KRLMarker = 0x200F;
       
    55 
       
    56 // KUnknownCount is used as default value for param count in FormatStringL
       
    57 const TInt KUnknownCount(-99);
       
    58 
       
    59 //
       
    60 // class TulTextResourceUtils
       
    61 //
       
    62 
       
    63 /**
       
    64 Reads a resource string without memory allocation. The loaded string is stored in the 
       
    65 destination TDes&. Because this method doesn't allocate memory the destination 
       
    66 descriptor must be long enough.
       
    67 
       
    68 @param aResourceId The numeric ID of the resource string to be read.
       
    69 @param aDest Reference to the descriptor where the resource string is loaded.
       
    70 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
    71                    give this, CCoeEnv::Static is called to get it.
       
    72 
       
    73 @panic ECCoeEnvNotInitialized Parameter aLoaderEnv is NULL and CCoeEnv::Static returned NULL.
       
    74 */
       
    75 EXPORT_C void TulTextResourceUtils::Load(TDes& aDest, TInt aResourceId, CCoeEnv* aLoaderEnv)
       
    76     {
       
    77     if (!aLoaderEnv)
       
    78         {
       
    79         aLoaderEnv=CCoeEnv::Static();
       
    80         if (!aLoaderEnv)
       
    81             User::Panic(KPanicCategory, ECCoeEnvNotInitialized);
       
    82         }
       
    83 
       
    84     //If aDes is too small, this function causes CCoeEnv::HandleError() to be called.
       
    85     TInt ignore(KErrNone); // To avoid compiler warning.
       
    86     // Trapped because ReadResource() is deprecated and method cannot leave.
       
    87     TRAP(ignore, aLoaderEnv->ReadResourceL(aDest, aResourceId));
       
    88 	}
       
    89 
       
    90 /**
       
    91 Reads a resource string with memory allocation. 
       
    92 
       
    93 @param aResourceId The numeric ID of the resource string to be read.
       
    94 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
    95                    give this, CCoeEnv::Static is called to get it.
       
    96 @return Pointer to a heap descriptor containing the resource
       
    97          string. The calling program must destroy the heap descriptor
       
    98          when it is no longer needed.
       
    99 
       
   100 @leave KErrNotSupported Parameter aLoaderEnv is NULL and CCoeEnv::Static returned NULL.
       
   101 */
       
   102 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, CCoeEnv* aLoaderEnv)
       
   103     {
       
   104     if (!aLoaderEnv)
       
   105         {
       
   106         aLoaderEnv=CCoeEnv::Static();
       
   107         if (!aLoaderEnv)
       
   108             User::Leave(KErrNotSupported);
       
   109         }
       
   110     return aLoaderEnv->AllocReadResourceL(aResourceId);
       
   111 	}
       
   112 
       
   113 /**
       
   114 Reads a resource string with memory allocation and replaces the first \%N-string in it 
       
   115 with replacement TInt. In debug builds the Symbian OS panic mechanism is used to 
       
   116 notify programming errors.
       
   117  
       
   118 @param aResourceId The numeric ID of the resource string to be read.
       
   119 @param aInt The replacing TInt.
       
   120 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   121         			give this, CCoeEnv::Static is called to get it.
       
   122 @return Pointer to a heap descriptor containing the formatted
       
   123         resource string. The calling program must destroy the heap 
       
   124         descriptor when it is no longer needed.
       
   125 
       
   126 @panic EKeyStringNotFound In debug build if the key string 'N' wasn't
       
   127                            found in formatting.
       
   128 @leave KErrNotSupported Parameter aLoaderEnv is NULL and CCoeEnv::Static returned NULL.
       
   129 */
       
   130 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, TInt aInt, CCoeEnv* aLoaderEnv)
       
   131     {
       
   132     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   133     TPtr retptr = resbuf->Des();
       
   134     //
       
   135     //Converting input TInt to a descriptor. This way the size
       
   136     //of the return string can be controlled.
       
   137     //
       
   138     TBuf<KIntSize> intbuf;
       
   139     intbuf.Num(aInt);
       
   140 
       
   141     if (LanguageSpecificNumberConverter::IsConversionNeeded())
       
   142         LanguageSpecificNumberConverter::Convert(intbuf);
       
   143     //
       
   144     // Get number of sub strings
       
   145     TInt count = GetSubStringCount(retptr); 
       
   146     TBool marker(EFalse); 
       
   147     
       
   148     if (count >= 1)
       
   149         {
       
   150         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   151         CleanupStack::PushL(buffer);
       
   152         
       
   153         TBool found(EFalse);
       
   154         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   155         
       
   156         //Adding int    
       
   157         HBufC* retbuf = FormatStringL(*buffer, KNumKeyBuf, intbuf, mainDir);
       
   158         
       
   159         CleanupStack::PopAndDestroy(buffer);
       
   160         CleanupStack::PopAndDestroy(resbuf);
       
   161                         
       
   162         if (marker && retbuf->Length())
       
   163             {
       
   164             TPtr ptr = retbuf->Des();
       
   165             RemoveNoDirMarkers(ptr);
       
   166             } 
       
   167         __ASSERT_DEBUG(retbuf->Length(), 
       
   168                     User::Panic(KPanicCategory, EKeyStringNotFound));
       
   169         return retbuf;
       
   170         }
       
   171      else
       
   172         {
       
   173         CleanupStack::PopAndDestroy(resbuf);
       
   174         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   175         __ASSERT_DEBUG(retbuf->Length(), 
       
   176                     User::Panic(KPanicCategory, EKeyStringNotFound));
       
   177         return retbuf;
       
   178         }
       
   179    	}
       
   180 
       
   181 /**
       
   182 Reads a resource string with memory allocation and replaces the first \%U-string in it 
       
   183 with replacement string. In debug builds the Symbian OS panic mechanism is used to 
       
   184 notify programming errors.
       
   185 
       
   186 @param aResourceId The numeric ID of the resource string to be read.
       
   187 @param aString Reference to the replacing string.
       
   188 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   189                    give this, CCoeEnv::Static is called to get it.
       
   190 @return Pointer to a heap descriptor containing the formatted
       
   191          resource string. The calling program must destroy the heap 
       
   192          descriptor when it is no longer needed.
       
   193 
       
   194 @panic EKeyStringNotFound In debug build if the key string 'U' wasn't
       
   195                            found in formatting.
       
   196 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   197                          CCoeEnv::Static returned NULL.
       
   198 */
       
   199 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, const TDesC& aString, CCoeEnv* aLoaderEnv)
       
   200     {
       
   201     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   202     TPtr retptr(resbuf->Des());
       
   203         
       
   204     // Get number of sub strings
       
   205     TInt count = GetSubStringCount(retptr); 
       
   206     TBool marker(EFalse); 
       
   207     
       
   208     if (count >= 1)
       
   209         {
       
   210         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   211         CleanupStack::PushL(buffer);
       
   212         
       
   213         TBool found(EFalse);
       
   214         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   215         
       
   216         //Formating the return string with FormatStringL.
       
   217         HBufC* retbuf = FormatStringL(*buffer, KStringKeyBuf, aString, mainDir);
       
   218         
       
   219         CleanupStack::PopAndDestroy(buffer);
       
   220         CleanupStack::PopAndDestroy(resbuf);
       
   221                         
       
   222         if (marker && retbuf->Length())
       
   223             {
       
   224             TPtr ptr = retbuf->Des();
       
   225             RemoveNoDirMarkers(ptr);
       
   226             } 
       
   227             
       
   228         __ASSERT_DEBUG(retbuf->Length(), 
       
   229                     User::Panic(KPanicCategory, EKeyStringNotFound));    
       
   230         return retbuf;
       
   231         }
       
   232      else
       
   233         {
       
   234         CleanupStack::PopAndDestroy(resbuf);
       
   235         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   236         __ASSERT_DEBUG(retbuf->Length(), 
       
   237                     User::Panic(KPanicCategory, EKeyStringNotFound));
       
   238         return retbuf;
       
   239         }
       
   240    	}
       
   241 
       
   242 /**
       
   243 Reads a resource string with memory allocation, replaces the first \%N-string in it with
       
   244 replacement TInt and the first \%U-string in it with replacement string. 
       
   245 In debug builds the Symbian OS panic mechanism is used to 
       
   246 notify programming errors.
       
   247 
       
   248 @param aResourceId The numeric ID of the resource string to be read.
       
   249 @param aString Reference to the replacing string.
       
   250 @param aInt The replacing TInt.
       
   251 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   252                    give this, CCoeEnv::Static is called to get it.
       
   253 @return Pointer to a heap descriptor containing the formatted
       
   254          resource string. The calling program must destroy the heap
       
   255          descriptor when it is no longer needed.
       
   256 
       
   257 @panic EKeyStringNotFound In debug build if the key string 'N' or 'U'
       
   258                            wasn't found in formatting.
       
   259 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   260                          CCoeEnv::Static returned NULL.
       
   261 */
       
   262 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, const TDesC& aString, TInt aInt, CCoeEnv* aLoaderEnv)
       
   263     {
       
   264     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   265     TPtr retptr = resbuf->Des();
       
   266             
       
   267     //Converting input TInt to a descriptor. This way the size
       
   268     //of the return string can be controlled.
       
   269     TBuf<KIntSize> intbuf;
       
   270     intbuf.Num(aInt);
       
   271     
       
   272     if (LanguageSpecificNumberConverter::IsConversionNeeded())
       
   273         LanguageSpecificNumberConverter::Convert(intbuf);
       
   274  
       
   275     // Get number of sub strings
       
   276     TInt count = GetSubStringCount(retptr); 
       
   277     TBool marker(EFalse); 
       
   278     
       
   279     if (count >= 1)
       
   280         {
       
   281         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   282         CleanupStack::PushL(buffer);
       
   283         
       
   284         TBool found(EFalse);
       
   285         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   286         
       
   287         //Adding int    
       
   288         HBufC* cacbuf = FormatStringL(*buffer, KNumKeyBuf, intbuf, mainDir);
       
   289         CleanupStack::PushL(cacbuf);
       
   290         
       
   291         // Resolve directionality of the modified text and 
       
   292         // forward information to Formater().
       
   293         mainDir = DirectionalityL(*cacbuf, &found);
       
   294       
       
   295         //Adding string.
       
   296         HBufC* retbuf = FormatStringL(*cacbuf, KStringKeyBuf, aString, mainDir);
       
   297         __ASSERT_DEBUG(retbuf->Length(), 
       
   298                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   299         
       
   300         CleanupStack::PopAndDestroy(cacbuf);
       
   301         CleanupStack::PopAndDestroy(buffer);
       
   302         CleanupStack::PopAndDestroy(resbuf);
       
   303         
       
   304         if (marker && retbuf->Length())
       
   305             {
       
   306             TPtr ptr = retbuf->Des();
       
   307             RemoveNoDirMarkers(ptr);
       
   308             }   
       
   309 
       
   310         __ASSERT_DEBUG(retbuf->Length(), 
       
   311                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   312         return retbuf;
       
   313         }
       
   314     else
       
   315         {
       
   316         CleanupStack::PopAndDestroy(resbuf);
       
   317         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   318         __ASSERT_DEBUG(retbuf->Length(), 
       
   319                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   320         return retbuf;
       
   321         }
       
   322    	}
       
   323 
       
   324 /**
       
   325 Reads a resource string with memory allocation and replaces the \%(index)N-strings 
       
   326 in it with replacement TInts from an array. In debug builds the Symbian OS 
       
   327 panic mechanism is used to notify programming errors.
       
   328 
       
   329 @param aResourceId The numeric ID of the resource string to be read.
       
   330 @param aInts Reference to the array including the replacing TInts.
       
   331 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   332                    give this, CCoeEnv::Static is called to get it.
       
   333 @return Pointer to a heap descriptor containing the formatted
       
   334          resource string. The calling program must destroy the heap
       
   335          descriptor when it is no longer needed.
       
   336 
       
   337 @panic ETooManyArguments In debug build if too many replacing 
       
   338                          elements in aInts array.
       
   339 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   340                         CCoeEnv::Static returned NULL.
       
   341 */
       
   342 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, const CArrayFix<TInt>& aInts, CCoeEnv* aLoaderEnv)
       
   343     {
       
   344     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   345     TPtr retptr(resbuf->Des());
       
   346     TInt max = aInts.Count(); //Number of keystrings in resource string
       
   347     __ASSERT_DEBUG(max <= KNumOfParams, 
       
   348                     User::Panic(KPanicCategory, ETooManyArguments));
       
   349     
       
   350     TInt count = GetSubStringCount(retptr); 
       
   351     TBool marker(EFalse); 
       
   352     
       
   353     if (count >= 1)
       
   354         {
       
   355         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   356         CleanupStack::PushL(buffer);
       
   357         
       
   358         TBool found(EFalse);
       
   359         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   360         
       
   361         //Formating the return string with FormatStringL. 
       
   362         HBufC* retbuf = FormatStringL(*buffer, aInts, max, mainDir);
       
   363         
       
   364         CleanupStack::PopAndDestroy(buffer);
       
   365         CleanupStack::PopAndDestroy(resbuf);
       
   366                         
       
   367         if (marker && retbuf->Length())
       
   368             {
       
   369             TPtr ptr = retbuf->Des();
       
   370             RemoveNoDirMarkers(ptr);
       
   371             } 
       
   372             
       
   373         __ASSERT_DEBUG(retbuf->Length(), 
       
   374                     User::Panic(KPanicCategory, EKeyStringNotFound));    
       
   375         return retbuf;
       
   376         }
       
   377      else
       
   378         {
       
   379         CleanupStack::PopAndDestroy(resbuf);
       
   380         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   381         __ASSERT_DEBUG(retbuf->Length(), 
       
   382                     User::Panic(KPanicCategory, EKeyStringNotFound));
       
   383         return retbuf;
       
   384         }
       
   385     }
       
   386 
       
   387 /**
       
   388 Reads a resource string with memory allocation and replaces the \%(index)U-strings 
       
   389 in it with replacement strings from an array. In debug builds the Symbian OS 
       
   390 panic mechanism is used to notify programming errors.
       
   391 
       
   392 @param aResourceId The numeric ID of the resource string to be read.
       
   393 @param aStrings Reference to the array  including pointers to the
       
   394                 replacing strings.
       
   395 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   396                   give this, CCoeEnv::Static is called to get it.
       
   397 @return Pointer to a heap descriptor containing the formatted
       
   398          resource string. The calling program must destroy the heap
       
   399          descriptor when it is no longer needed.        
       
   400         
       
   401 @panic ETooManyArguments In debug build if too many replacing 
       
   402                           elements in aStrings 
       
   403                           array.
       
   404 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   405                          CCoeEnv::Static returned NULL.
       
   406 */
       
   407 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, const MDesCArray& aStrings, CCoeEnv* aLoaderEnv)
       
   408     {
       
   409     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   410     TPtr retptr(resbuf->Des());
       
   411     
       
   412     TInt max = aStrings.MdcaCount(); //Number of keystrings in resource string
       
   413     __ASSERT_DEBUG(max <= KNumOfParams, 
       
   414                     User::Panic(KPanicCategory, ETooManyArguments));
       
   415                     
       
   416     TInt count = GetSubStringCount(retptr); 
       
   417     TBool marker(EFalse); 
       
   418     
       
   419     if (count >= 1)
       
   420         {
       
   421         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   422         CleanupStack::PushL(buffer);
       
   423         
       
   424         TBool found(EFalse);
       
   425         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   426         
       
   427         //Formating the return string with FormatStringL. 
       
   428         HBufC* retbuf = FormatStringL(*buffer, aStrings, max, mainDir);
       
   429     
       
   430         CleanupStack::PopAndDestroy(buffer);
       
   431         CleanupStack::PopAndDestroy(resbuf);
       
   432                         
       
   433         if (marker && retbuf->Length())
       
   434             {
       
   435             TPtr ptr = retbuf->Des();
       
   436             RemoveNoDirMarkers(ptr);
       
   437             } 
       
   438             
       
   439         __ASSERT_DEBUG(retbuf->Length(), 
       
   440                     User::Panic(KPanicCategory, EKeyStringNotFound));    
       
   441         return retbuf;
       
   442         }
       
   443      else
       
   444         {
       
   445         CleanupStack::PopAndDestroy(resbuf);
       
   446         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   447         __ASSERT_DEBUG(retbuf->Length(), 
       
   448                     User::Panic(KPanicCategory, EKeyStringNotFound));
       
   449         return retbuf;
       
   450         }
       
   451     }
       
   452 
       
   453 /**
       
   454 Reads a resource string with memory allocation and replaces the
       
   455 \%(index)U-strings in it with replacement strings from an array and
       
   456 the \%(index)N-strings in it with replacement TInts from another
       
   457 array. In debug builds the Symbian OS panic mechanism is used to 
       
   458 notify programming errors.
       
   459 
       
   460 @param aResourceId The numeric ID of the resource string to be read.
       
   461 @param aStrings Reference to the array including pointers to the
       
   462                  replacing strings.
       
   463 @param aInts Reference to the array including the replacing TInts.
       
   464 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   465                    give this, CCoeEnv::Static is called to get it.
       
   466 @return Pointer to a heap descriptor containing the formatted
       
   467          resource string. The calling program must destroy the heap
       
   468          descriptor when it is no longer needed.        
       
   469         
       
   470 @panic ETooManyArguments In debug build if too many replacing 
       
   471                           elements in aStrings and/or aInts arrays.
       
   472 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   473                          CCoeEnv::Static returned NULL.
       
   474 */
       
   475 EXPORT_C HBufC* TulTextResourceUtils::LoadL(TInt aResourceId, const MDesCArray& aStrings, const CArrayFix<TInt>& aInts, CCoeEnv* aLoaderEnv)
       
   476     {
       
   477     HBufC* resbuf = LoadLC(aResourceId, aLoaderEnv);
       
   478     TPtr retptr(resbuf->Des());
       
   479     
       
   480     //Number of keystrings in resource string.
       
   481     TInt max = (aInts.Count() + aStrings.MdcaCount()); 
       
   482     __ASSERT_DEBUG(max <= KNumOfParams, User::Panic(KPanicCategory,
       
   483                     ETooManyArguments));
       
   484     
       
   485     // Get number of sub strings
       
   486     TInt count = GetSubStringCount(retptr); 
       
   487     TBool marker(EFalse); 
       
   488     
       
   489     if (count >= 1)
       
   490         {
       
   491         HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
   492         CleanupStack::PushL(buffer);
       
   493         
       
   494         TBool found(EFalse);
       
   495         TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
       
   496         
       
   497         //Adding int    
       
   498         HBufC* cacbuf = FormatStringL(*buffer, aInts, max, mainDir); //Adding ints
       
   499         CleanupStack::PushL(cacbuf);
       
   500         
       
   501         // Resolve directionality of the modified text and 
       
   502         // forward information to Formater().
       
   503         mainDir = DirectionalityL(*cacbuf, &found);
       
   504       
       
   505         //Adding string.
       
   506         HBufC* retbuf = FormatStringL(*cacbuf, aStrings, max, mainDir); //Adding strings
       
   507         __ASSERT_DEBUG(retbuf->Length(), 
       
   508                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   509         
       
   510         CleanupStack::PopAndDestroy(cacbuf);
       
   511         CleanupStack::PopAndDestroy(buffer);
       
   512         CleanupStack::PopAndDestroy(resbuf);
       
   513         
       
   514         if (marker && retbuf->Length())
       
   515             {
       
   516             TPtr ptr = retbuf->Des();
       
   517             RemoveNoDirMarkers(ptr);
       
   518             }   
       
   519 
       
   520         __ASSERT_DEBUG(retbuf->Length(), 
       
   521                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   522         return retbuf;
       
   523         }
       
   524     else
       
   525         {
       
   526         CleanupStack::PopAndDestroy(resbuf);
       
   527         HBufC* retbuf = HBufC::NewL(0); // return empty buffer
       
   528         __ASSERT_DEBUG(retbuf->Length(), 
       
   529                         User::Panic(KPanicCategory, EKeyStringNotFound));
       
   530         return retbuf;
       
   531         }
       
   532     }
       
   533 
       
   534 /**
       
   535 Reads a resource string with memory allocation and pushes the string 
       
   536 onto the cleanup stack.
       
   537 
       
   538 @param aResourceId The numeric ID of the resource string to be read.
       
   539 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   540                    give this, CCoeEnv::Static is called to get it.
       
   541 @return Pointer to a heap descriptor containing the resource
       
   542          string. This pointer is in the cleanup stack. The calling 
       
   543          program should pop and destroy the heap descriptor when it is
       
   544          no longer needed.
       
   545         
       
   546 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   547                          CCoeEnv::Static returned NULL.
       
   548 */
       
   549 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, CCoeEnv* aLoaderEnv)
       
   550     {
       
   551     if (!aLoaderEnv)
       
   552         {
       
   553         aLoaderEnv=CCoeEnv::Static();
       
   554         if (!aLoaderEnv)
       
   555             User::Leave(KErrNotSupported);
       
   556         }
       
   557 
       
   558     return aLoaderEnv->AllocReadResourceLC(aResourceId);
       
   559 	}
       
   560 
       
   561 /**
       
   562 Reads a resource string with memory allocation, replaces the first \%N-string 
       
   563 in it with replacement TInt and pushes the string onto the cleanup stack. In debug builds
       
   564 the Symbian OS panic mechanism is used to notify programming errors.
       
   565 
       
   566 @param aResourceId The numeric ID of the resource string to be read.
       
   567 @param aInt the replacing TInt.
       
   568 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   569                    give this, CCoeEnv::Static is called to get it.
       
   570 @return pointer to a heap descriptor containing the formatted
       
   571          resource string. This pointer is in the cleanup stack. 
       
   572          The calling program should pop and destroy the heap 
       
   573          descriptor when it is no longer needed.
       
   574 
       
   575 @panic EKeyStringNotFound In debug build if the key string 'N' wasn't
       
   576                            found in formatting.
       
   577 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   578                          CCoeEnv::Static returned NULL.
       
   579 */
       
   580 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, TInt aInt, CCoeEnv* aLoaderEnv)
       
   581     {
       
   582     HBufC* retbuf = LoadL(aResourceId, aInt, aLoaderEnv);
       
   583     CleanupStack::PushL(retbuf);
       
   584     return retbuf;
       
   585    	}
       
   586 
       
   587 /**
       
   588 Reads a resource string with memory allocation, replaces the first \%U-string 
       
   589 in it with replacement string and pushes the string onto the cleanup stack. 
       
   590 In debug builds the Symbian OS panic mechanism is used to notify programming errors.
       
   591 
       
   592 @param aResourceId The numeric ID of the resource string to be read.
       
   593 @param aString Reference to the replacing string.
       
   594 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   595                    give this, CCoeEnv::Static is called to get it.
       
   596 @return Pointer to a heap descriptor containing the formatted
       
   597          resource string. This pointer is in the cleanup stack.
       
   598          The calling program should pop and destroy the heap 
       
   599          descriptor when it is no longer needed.
       
   600 
       
   601 @panic EKeyStringNotFound In debug build if the key string 'U' wasn't
       
   602                            found in formatting.
       
   603 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   604                          CCoeEnv::Static returned NULL.
       
   605 */
       
   606 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, const TDesC& aString, CCoeEnv* aLoaderEnv)
       
   607     {
       
   608     HBufC* retbuf = LoadL(aResourceId, aString, aLoaderEnv);
       
   609     CleanupStack::PushL(retbuf);
       
   610     return retbuf;
       
   611    	}
       
   612 
       
   613 /**
       
   614 Reads a resource string with memory allocation, replaces the first \%N-string 
       
   615 in it with replacement TInt and the first \%U-string in it with replacement
       
   616 string and pushes the string onto the cleanup stack. In debug builds
       
   617 the Symbian OS panic mechanism is used to notify programming errors.
       
   618 
       
   619 @param aResourceId The numeric ID of the resource string to be
       
   620                     read.
       
   621 @param aString Reference to the replacing string.
       
   622 @param aInt The replacing TInt.
       
   623 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   624                    give this, CCoeEnv::Static is called to get it.
       
   625 @return Pointer to a heap descriptor containing the formatted
       
   626          resource string. This pointer is in the cleanup stack.
       
   627          The calling program should pop and destroy the heap 
       
   628          descriptor when it is no longer needed.
       
   629 
       
   630 @panic EKeyStringNotFound In debug build if the key string 'N' or 'U'
       
   631                            wasn't found in formatting.
       
   632 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   633                          CCoeEnv::Static returned NULL.
       
   634 */
       
   635 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, const TDesC& aString, TInt aInt, CCoeEnv* aLoaderEnv)
       
   636     {
       
   637     HBufC* retbuf = LoadL(aResourceId, aString, aInt, aLoaderEnv);
       
   638     CleanupStack::PushL(retbuf);
       
   639     return retbuf;
       
   640    	}
       
   641 
       
   642 /**
       
   643 Reads a resource string with memory allocation, replaces the \%(index)N-strings in it with
       
   644 replacement TInts from an array and pushes the string onto the
       
   645 cleanup stack. In debug builds the Symbian OS panic mechanism is 
       
   646 used to notify programming errors.
       
   647 
       
   648 @param aResourceId The numeric ID of the resource string to be
       
   649                    read.
       
   650 @param aInts Reference to the array including the replacing TInts.
       
   651 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   652                    give this, CCoeEnv::Static is called to get it.
       
   653 @return Pointer to a heap descriptor containing the formatted
       
   654          resource string. This pointer is in the cleanup stack.
       
   655          The calling program should pop and destroy the heap 
       
   656          descriptor when it is no longer needed.
       
   657 
       
   658 @panic ETooManyArguments In debug build if too many replacing 
       
   659                           elements in aInts array.
       
   660 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   661 *                         CCoeEnv::Static returned NULL.
       
   662 */
       
   663 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, const CArrayFix<TInt>& aInts, CCoeEnv* aLoaderEnv)
       
   664     {
       
   665     HBufC* retbuf = LoadL(aResourceId, aInts, aLoaderEnv);
       
   666     CleanupStack::PushL(retbuf);
       
   667     return retbuf;
       
   668     }
       
   669 
       
   670 
       
   671 /**
       
   672 Reads a resource string with memory allocation, replaces the \%(index)U-strings 
       
   673 in it with replacement strings from an array and pushes the string onto the
       
   674 cleanup stack. In debug builds the Symbian OS panic mechanism is 
       
   675 used to notify programming errors.
       
   676 
       
   677 @param aResourceId The numeric ID of the resource string to be read.
       
   678 @param aStrings Reference to the array  including pointers to the
       
   679                  replacing strings.
       
   680 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   681                    give this, CCoeEnv::Static is called to get it.
       
   682 @return Pointer to a heap descriptor containing the formatted
       
   683          resource string. This pointer is in the cleanup stack.
       
   684          The calling program should pop and destroy the heap 
       
   685          descriptor when it is no longer needed.
       
   686 
       
   687 @panic ETooManyArguments In debug build if too many replacing 
       
   688                           elements in aStrings array.
       
   689 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   690                          CCoeEnv::Static returned NULL.
       
   691 */
       
   692 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, const MDesCArray& aStrings, CCoeEnv* aLoaderEnv)
       
   693     {
       
   694     HBufC* retbuf = LoadL(aResourceId, aStrings, aLoaderEnv);
       
   695     CleanupStack::PushL(retbuf);
       
   696     return retbuf;
       
   697     }
       
   698 
       
   699 /**
       
   700 Reads a resource string with memory allocation, replaces the \%(index)U-strings 
       
   701 in it with replacement strings from an array. Replaces
       
   702 the \%(index)N-strings with replacement TInts from another
       
   703 array. Pushes the string onto the cleanup stack. In debug builds
       
   704 the Symbian OS panic mechanism is used to notify programming errors.
       
   705 
       
   706 @param aResourceId The numeric ID of the resource string to be read.
       
   707 @param aStrings Reference to the array including pointers to the
       
   708                  replacing strings.
       
   709 @param aInts Reference to the array including the replacing TInts.
       
   710 @param aLoaderEnv Pointer to the control environment. If user doesn't
       
   711                    give this, CCoeEnv::Static is called to get it.
       
   712 @return Pointer to a heap descriptor containing the formatted
       
   713          resource string. This pointer is in the cleanup stack.
       
   714          The calling program should pop and destroy the heap 
       
   715          descriptor when it is no longer needed.
       
   716         
       
   717 @panic ETooManyArguments In debug build if too many replacing 
       
   718                           elements in aStrings and/or aInts arrays.
       
   719 @leave KErrNotSupported Parameter aLoaderEnv is NULL and 
       
   720                          CCoeEnv::Static returned NULL.
       
   721 */
       
   722 EXPORT_C HBufC* TulTextResourceUtils::LoadLC(TInt aResourceId, const MDesCArray& aStrings, const CArrayFix<TInt>& aInts, CCoeEnv* aLoaderEnv)
       
   723     {
       
   724     HBufC* retbuf = LoadL(aResourceId, aStrings, aInts, aLoaderEnv); 
       
   725     CleanupStack::PushL(retbuf);
       
   726     return retbuf;
       
   727     }
       
   728 
       
   729 /**
       
   730 Formats a resource string without memory allocation. The formatted string 
       
   731 is stored in the destination TDes&. Since this method doesn't allocate memory the 
       
   732 destination descriptor must be long enough. In aPosition -1 means 
       
   733 that there is no index in the key string and all \%U-strings in the
       
   734 original string are replaced with aSubs. In debug builds the 
       
   735 Symbian OS panic mechanism is used to notify programming errors.
       
   736 
       
   737 @param aDest Reference to the descriptor where the resource string
       
   738               is formatted.
       
   739 @param aSource Reference to the original string.
       
   740 @param aPosition The index of the key string.
       
   741 @param aSubs Reference to the replacing string.
       
   742        
       
   743 @panic EInvalidIndex In debug build if the index of the key string 
       
   744                       is invalid.
       
   745 @panic EDescriptorTooSmall In debug build if the length of the 
       
   746                             destination descriptor is too small.
       
   747 @panic EKeyStringNotFound In debug build if the key string 'U' wasn't
       
   748                            found, aDest is empty.
       
   749 
       
   750 One small sample describing the usage of the method.
       
   751 @code
       
   752  // Load example string "%0U %1U" defined in rss- and loc-files.
       
   753  // %0U stands for weekday string and %1U for date string.
       
   754  HBufC* timeFormat = TulTextResourceUtils::LoadLC(R_TIME_FORMAT, iEikonEnv);
       
   755 
       
   756  // The replacing string.
       
   757  _LIT(dateString, "02/10/2006");
       
   758 
       
   759  TulTextResourceUtils::Format(destBuf, timeFormat, 
       
   760                        1, // %1U stands for date string
       
   761                        dateString);
       
   762 
       
   763  // After returning destBuf contains string "%0U 02/10/2006".
       
   764  @endcode
       
   765 */
       
   766 EXPORT_C void TulTextResourceUtils::Format(TDes& aDest, const TDesC& aSource, TInt aPosition, const TDesC& aSubs)
       
   767     {
       
   768     //Checking the index.
       
   769     __ASSERT_DEBUG((aPosition >= KNoIndex && aPosition <=KNumOfParams), 
       
   770                     User::Panic(KPanicCategory, EInvalidIndex));
       
   771     //
       
   772     //Formating the keystring.
       
   773     //
       
   774     TBuf<KKeySize> keybuf;
       
   775     KeyStringFormater(keybuf, KStringKey, aPosition, KStringKeyBuf);
       
   776 
       
   777 #ifdef _RD_COMMONENGINE_DETAILED_TRACE
       
   778     TInt paramCount = GetParamCount(aSource, aPosition);
       
   779     #ifdef _DEBUG
       
   780     TInt checklength(0);
       
   781     #endif
       
   782     TInt subslength(aSubs.Length() * paramCount);
       
   783     TInt keylength(keybuf.Length() * paramCount);
       
   784     if (subslength > keylength)
       
   785         {
       
   786         #ifdef _DEBUG
       
   787         checklength = 
       
   788         #endif
       
   789         aSource.Length()+subslength-keylength;
       
   790         }
       
   791     else
       
   792         {
       
   793         #ifdef _DEBUG
       
   794         checklength = 
       
   795         #endif
       
   796         aSource.Length();
       
   797         }
       
   798 
       
   799     //Checking the length of the destination descriptor.
       
   800     __ASSERT_DEBUG(checklength <= aDest.MaxLength(), User::Panic(
       
   801                    KPanicCategory, EDescriptorTooSmall));
       
   802 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
   803 
       
   804     TRAPD( err, FormatL( aDest, aSource, keybuf, aSubs ) );
       
   805     
       
   806     if ( err != KErrNone )
       
   807         {
       
   808         aDest.Zero();
       
   809         aDest.Copy(aSource);
       
   810         TBool found(EFalse);
       
   811         TBidiText::TDirectionality dir = ResolveDirectionality(aDest, &found);
       
   812         aDest.Zero();
       
   813 
       
   814         //Formating the resource string.
       
   815 	    Formater(aDest, aSource, keybuf, aSubs, dir);
       
   816         }
       
   817     
       
   818     //If the key string wasn't found, aDest is empty.
       
   819     __ASSERT_DEBUG( aDest.Length(), User::Panic( KPanicCategory,
       
   820                     EKeyStringNotFound ) );
       
   821     }
       
   822 
       
   823 /**
       
   824 Formats a resource string without memory allocation. The formatted string is stored 
       
   825 in the destination TDes&. Since this method doesn't allocate memory the destination 
       
   826 descriptor must be long enough. In aPosition -1 means that there is
       
   827 no index in the key string and all \%N-strings in the original string 
       
   828 are replaced with aSubs. In debug builds the Symbian OS panic 
       
   829 mechanism is used to notify programming errors.
       
   830 
       
   831 @param aDest Reference to the descriptor where the resource string
       
   832               is formatted.
       
   833 @param aSource Reference to the original string.
       
   834 @param aPosition The index of the key string.
       
   835 @param aSubs The replacing TInt.
       
   836 
       
   837 @panic EInvalidIndex In debug build if the index of the key string 
       
   838                       is invalid.
       
   839 @panic EDescriptorTooSmall In debug build if the length of the 
       
   840                             destination descriptor is too small.
       
   841 @panic EKeyStringNotFound In debug build if the key string 'N' wasn't
       
   842                            found, aDest is empty.
       
   843 
       
   844 One small sample describing the usage of the method.
       
   845  @code
       
   846  // Load example string "%0N %1N" defined in rss- and loc-files.
       
   847  // %0N stands for area code and %1N for phone number.
       
   848  HBufC* telFormat = TulTextResourceUtils::LoadLC(R_TEL_FORMAT, iEikonEnv);
       
   849 
       
   850  // The replacing number.
       
   851  TInt areaCode(123);
       
   852 
       
   853  TulTextResourceUtils::Format(destBuf, telFormat, 
       
   854                        0, // %0N stands for area code
       
   855                        areaCode);
       
   856 
       
   857  // After returning destBuf contains string "123 %1N".
       
   858 */
       
   859 EXPORT_C void TulTextResourceUtils::Format(TDes& aDest, const TDesC& aSource, TInt aPosition, TInt aSubs)
       
   860     {
       
   861     //Checking the index.
       
   862     __ASSERT_DEBUG((aPosition >= KNoIndex && aPosition <=KNumOfParams), 
       
   863                     User::Panic(KPanicCategory, EInvalidIndex));
       
   864     //
       
   865     //Formating the keystring.
       
   866     //
       
   867     TBuf<KKeySize> keybuf;
       
   868     KeyStringFormater(keybuf, KNumKey, aPosition, KNumKeyBuf);
       
   869     TBuf<KIntSize> intbuf;
       
   870     intbuf.Num(aSubs);
       
   871     
       
   872     if (LanguageSpecificNumberConverter::IsConversionNeeded())
       
   873         LanguageSpecificNumberConverter::Convert(intbuf);
       
   874 
       
   875 #ifdef _RD_COMMONENGINE_DETAILED_TRACE
       
   876     TInt paramCount = GetParamCount(aSource, aPosition);
       
   877     #ifdef _DEBUG
       
   878     TInt checklength(0);
       
   879     #endif
       
   880     TInt subslength(intbuf.Length() * paramCount);
       
   881     TInt keylength(keybuf.Length() * paramCount);
       
   882     
       
   883     if (subslength > keylength)
       
   884         {
       
   885         #ifdef _DEBUG
       
   886         checklength = 
       
   887         #endif
       
   888         aSource.Length()+subslength-keylength;
       
   889         }
       
   890     else
       
   891         {
       
   892         #ifdef _DEBUG
       
   893         checklength = 
       
   894         #endif
       
   895         aSource.Length();
       
   896         }
       
   897 
       
   898     //Checking the length of the destination descriptor.
       
   899     __ASSERT_DEBUG(checklength <= aDest.MaxLength(), User::Panic(
       
   900                    KPanicCategory, EDescriptorTooSmall));
       
   901 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
   902      TRAPD(err, FormatL(aDest, aSource, keybuf, intbuf));
       
   903      
       
   904      if(err != KErrNone)
       
   905         {
       
   906         aDest.Zero();
       
   907         aDest.Copy(aSource);
       
   908         TBool found(EFalse);
       
   909         TBidiText::TDirectionality dir = ResolveDirectionality(aDest, &found);
       
   910         aDest.Zero();
       
   911 
       
   912 	    //Formating the resource string.
       
   913 	    Formater(aDest, aSource, keybuf, intbuf, dir);
       
   914         }
       
   915     //
       
   916     //If the key string wasn't found, aDest is empty.
       
   917     //
       
   918     __ASSERT_DEBUG(aDest.Length(), User::Panic(KPanicCategory,
       
   919                    EKeyStringNotFound));
       
   920     }
       
   921 
       
   922 /**
       
   923 Finds the keystring from the source string and replaces it with the
       
   924 replacement string.
       
   925 */
       
   926 HBufC* TulTextResourceUtils::FormatStringL(const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs,TBidiText::TDirectionality aDir)
       
   927     {
       
   928     TInt paramCount(KUnknownCount); // variable needed as it may be updated
       
   929     return FormatStringL(aSource, aKey, aSubs, aDir, paramCount, KUnknownCount);
       
   930     }
       
   931 
       
   932 /**
       
   933 Finds the keystring from the source string and replaces it with the
       
   934 replacement string.
       
   935 */
       
   936 HBufC* TulTextResourceUtils::FormatStringL(const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs, TBidiText::TDirectionality aDirectionality,
       
   937     TInt& aParamCount, TInt aSubCount)
       
   938     {
       
   939     if (aParamCount == KUnknownCount)
       
   940         aParamCount = GetParamCount(aSource);
       
   941 
       
   942     if (aSubCount == KUnknownCount)
       
   943         aSubCount = GetSubStringCount(aSource);
       
   944 
       
   945     // determine lenght of needed buffer 
       
   946     TInt sourcelength(aSource.Length()); 
       
   947     TInt keylength(aKey.Length());
       
   948     TInt subslength(aSubs.Length());
       
   949     TInt destlength = 0;
       
   950     if (subslength >= keylength)
       
   951         {
       
   952         destlength = sourcelength + ((subslength - keylength) * aParamCount);
       
   953         }
       
   954     else
       
   955         {
       
   956         destlength = sourcelength;
       
   957         }
       
   958 
       
   959     destlength += KExtraSpaceForMainStringDirMarker * aSubCount;
       
   960     destlength += KExtraSpaceForSubStringDirMarkers * aParamCount;
       
   961     //
       
   962     // Allocating heap buffer for return string.
       
   963     //
       
   964 
       
   965     HBufC* retbuf = HBufC::NewL(destlength);
       
   966     TPtr retptr(retbuf->Des());
       
   967 
       
   968     // Formating the resource string. Don't bother with format, 
       
   969     // if parameter count is not above zero
       
   970     if (aParamCount > 0)
       
   971         {
       
   972         aParamCount -= Formater(retptr, aSource, aKey, aSubs, aDirectionality);
       
   973         __ASSERT_DEBUG(aParamCount >= 0, User::Invariant());
       
   974         }
       
   975 
       
   976     //
       
   977     // If the key string wasn't found, retbuf is empty.
       
   978     //
       
   979     return retbuf; 
       
   980     }
       
   981 
       
   982 /**
       
   983 Finds the \%(index)N-keystrings from the source string and replaces it with the
       
   984 replacement TInts.
       
   985 */
       
   986 HBufC* TulTextResourceUtils::FormatStringL(TDesC& aSource, const CArrayFix<TInt>& aInts, TInt aMax, TBidiText::TDirectionality aDir)
       
   987     {
       
   988     TInt numbers = aInts.Count(); //Number of input TInts.
       
   989     //
       
   990     //Allocating heap buffer for return string.
       
   991     //
       
   992     TInt paramCount = GetParamCount(aSource);
       
   993     TInt subCount = GetSubStringCount(aSource);
       
   994     HBufC* retbuf = HBufC::NewLC(
       
   995         aSource.Length() + 
       
   996         paramCount * KIntSize +
       
   997         paramCount * KExtraSpaceForSubStringDirMarkers +
       
   998         subCount * KExtraSpaceForMainStringDirMarker);
       
   999     TPtr retptr(retbuf->Des());
       
  1000 
       
  1001     TBidiText::TDirectionality mainDir = aDir;
       
  1002         
       
  1003 
       
  1004     //The input TInt is converted to a descriptor. This way the size
       
  1005     //of the return string can be controlled.
       
  1006     TBuf<KIntSize> intbuf;
       
  1007 
       
  1008     //The key string must be formated again in the for-loop every round.
       
  1009     TBuf<KKeySize> keybuf;
       
  1010 
       
  1011     //intcount keeps track of used TInts from aInts.
       
  1012     TInt intcount(0);
       
  1013 
       
  1014     //loopcount counts the loops in the while loop.
       
  1015     TInt loopcount(0);
       
  1016 
       
  1017     //The resource string is read from retptr and formatted in retbuf 
       
  1018     //in every round.
       
  1019     retptr.Append(aSource);
       
  1020 
       
  1021     while (loopcount <= aMax && paramCount > 0)
       
  1022         {
       
  1023         //Formating key string.
       
  1024         keybuf.Zero();
       
  1025         keybuf.Append(KKeyPrefix);
       
  1026         keybuf.AppendNum(loopcount);
       
  1027         keybuf.Append(KNumKey);
       
  1028 
       
  1029         //If all the TInts from aInts are used, the resource string is checked
       
  1030         //for unsolved parameters.
       
  1031         if (intcount == numbers)
       
  1032             {
       
  1033 #ifdef _RD_COMMONENGINE_DETAILED_TRACE	// debug build
       
  1034             HBufC* checkbuf = FormatStringL(retptr, keybuf, keybuf, mainDir, 
       
  1035                                              paramCount, subCount);
       
  1036             __ASSERT_DEBUG(!checkbuf->Length(), User::Panic(
       
  1037                            KPanicCategory, ETooFewArguments));
       
  1038             delete checkbuf;
       
  1039 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
  1040             }
       
  1041         else if (loopcount == aMax)
       
  1042             {
       
  1043 #ifdef _RD_COMMONENGINE_DETAILED_TRACE	// debug build
       
  1044             HBufC* checkbuf = FormatStringL(retptr, keybuf, keybuf, mainDir, 
       
  1045                                              paramCount, subCount);
       
  1046             __ASSERT_DEBUG(!checkbuf->Length(), User::Panic(
       
  1047                            KPanicCategory, EInvalidIndex));
       
  1048             delete checkbuf;
       
  1049 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
  1050             }
       
  1051         else
       
  1052             {
       
  1053             //Converting TInt.
       
  1054             intbuf.Zero();
       
  1055             intbuf.Num(aInts[intcount]);
       
  1056             
       
  1057             if (LanguageSpecificNumberConverter::IsConversionNeeded())
       
  1058                 LanguageSpecificNumberConverter::Convert(intbuf);
       
  1059 
       
  1060             //Formating the return string.
       
  1061             HBufC* cacbuf = FormatStringL(retptr, keybuf, intbuf, mainDir, paramCount, subCount);
       
  1062             TPtr cacptr(cacbuf->Des());
       
  1063 
       
  1064             //If the cacbuf is empty, the key string with this round's
       
  1065             //index was a string variable. If there are no string 
       
  1066             //variables in this resource string, it's an error.
       
  1067             //
       
  1068             if (cacptr.Length())
       
  1069                 {
       
  1070                 retptr = cacptr;
       
  1071                 intcount++;
       
  1072                 }
       
  1073             else
       
  1074                 __ASSERT_DEBUG(numbers != aMax, User::Panic(KPanicCategory,
       
  1075                                                              EInvalidIndex));
       
  1076             delete cacbuf;
       
  1077             }
       
  1078 
       
  1079         loopcount++;
       
  1080         }
       
  1081     __ASSERT_DEBUG(intcount == numbers, User::Panic(KPanicCategory,
       
  1082                    ETooManyArguments));
       
  1083 
       
  1084     //Reallocating the return buffer to right size.
       
  1085     retbuf = retbuf->ReAllocL(retptr.Length());
       
  1086     CleanupStack::Pop(); //retbuf
       
  1087     return retbuf;
       
  1088     }
       
  1089 
       
  1090 /**
       
  1091 Finds the \%(index)U-keystrings from the source string and replaces it with the
       
  1092 replacement strings.
       
  1093 */
       
  1094 HBufC* TulTextResourceUtils::FormatStringL(TDesC& aSource, const MDesCArray& aStrings, TInt aMax, TBidiText::TDirectionality aDir)
       
  1095     {
       
  1096     TInt strings(aStrings.MdcaCount()); //Number of input strings.
       
  1097 
       
  1098     //Counting the overall length of input strings.
       
  1099     TInt maxSubsLength(0);
       
  1100     for (TInt i(0); i < strings; i++)
       
  1101         {
       
  1102         if (maxSubsLength < aStrings.MdcaPoint(i).Length())
       
  1103             maxSubsLength = aStrings.MdcaPoint(i).Length();
       
  1104         }
       
  1105 
       
  1106     //Allocating heap buffer for return string.
       
  1107     TInt paramCount = GetParamCount(aSource);
       
  1108     TInt subCount = GetSubStringCount(aSource);
       
  1109     HBufC* retbuf = HBufC::NewLC(
       
  1110         aSource.Length() + 
       
  1111         paramCount * maxSubsLength +   // worst case scenario; more accurate alloc 
       
  1112                                        // would require complex analysis
       
  1113         paramCount * KExtraSpaceForSubStringDirMarkers +
       
  1114         subCount * KExtraSpaceForMainStringDirMarker);
       
  1115     TPtr retptr(retbuf->Des());
       
  1116 
       
  1117     TBidiText::TDirectionality mainDir = aDir;
       
  1118     
       
  1119     //The key string must be formated again in the for-loop every round.
       
  1120     TBuf<KKeySize> keybuf;
       
  1121 
       
  1122     //descount keeps track of used HBufC*'s from aStrings.
       
  1123     TInt descount(0);
       
  1124 
       
  1125     //loopcount counts the loops in the while loop.
       
  1126     TInt loopcount(0);
       
  1127 
       
  1128     //The resource strings is read from retptr and formatted in retbuf every round.
       
  1129     retptr.Append(aSource);
       
  1130 
       
  1131     while (loopcount <= aMax && paramCount > 0)
       
  1132         {
       
  1133         //Formating key string.
       
  1134         keybuf.Zero();
       
  1135         keybuf.Append(KKeyPrefix);
       
  1136         keybuf.AppendNum(loopcount);
       
  1137         keybuf.Append(KStringKey);
       
  1138 
       
  1139         //If all the strings from aStrings are used, the resource string is 
       
  1140         //checked for unsolved parameters.
       
  1141         if (descount == strings)
       
  1142             {
       
  1143 #ifdef _RD_COMMONENGINE_DETAILED_TRACE	// debug build
       
  1144             HBufC* checkbuf = FormatStringL(retptr, keybuf, keybuf, mainDir, 
       
  1145                                              paramCount, subCount);
       
  1146             __ASSERT_DEBUG(!checkbuf->Length(), User::Panic(
       
  1147                            KPanicCategory, ETooFewArguments));
       
  1148             delete checkbuf;
       
  1149 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
  1150             }
       
  1151         else if (loopcount == aMax)
       
  1152             {
       
  1153 #ifdef _RD_COMMONENGINE_DETAILED_TRACE	// debug build
       
  1154             HBufC* checkbuf = FormatStringL(retptr, keybuf, keybuf, 
       
  1155                                              mainDir, paramCount, subCount);
       
  1156             __ASSERT_DEBUG(!checkbuf->Length(), User::Panic(
       
  1157                             KPanicCategory, EInvalidIndex));
       
  1158             delete checkbuf;
       
  1159 #endif // _RD_COMMONENGINE_DETAILED_TRACE
       
  1160             }
       
  1161         else
       
  1162             {
       
  1163             //Formating the return string.
       
  1164             HBufC* cacbuf = FormatStringL(retptr, keybuf, aStrings.MdcaPoint(descount), mainDir, paramCount, subCount);
       
  1165             TPtr cacptr(cacbuf->Des());
       
  1166 
       
  1167             //If the cacbuf is empty, the key string with this
       
  1168             //round's index was a number variable. If there are no
       
  1169             //number variables in this resource string, it's an error.
       
  1170             if (cacptr.Length())
       
  1171                 {
       
  1172                 retptr = cacptr;
       
  1173                 descount++;
       
  1174                 }
       
  1175             else
       
  1176                 __ASSERT_DEBUG(strings != aMax, User::Panic(KPanicCategory, EInvalidIndex));
       
  1177 
       
  1178             delete cacbuf;
       
  1179             }
       
  1180         loopcount++;
       
  1181         }
       
  1182         
       
  1183     __ASSERT_DEBUG(descount == strings, User::Panic(KPanicCategory, ETooManyArguments));
       
  1184 
       
  1185     //Reallocating the return buffer to right size.
       
  1186     retbuf = retbuf->ReAllocL(retptr.Length());
       
  1187     CleanupStack::Pop(); //retbuf
       
  1188     return retbuf;
       
  1189     }
       
  1190 
       
  1191 /**
       
  1192 Finds the keystring from the source string and replaces it with the
       
  1193 replacement string. The formated string is stored in the destination
       
  1194 descriptor.
       
  1195 */
       
  1196 TInt TulTextResourceUtils::Formater(TDes& aDest, const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs, TBidiText::TDirectionality aDirectionality)    
       
  1197     {
       
  1198     // substitute string must not contain KSubStringSeparator, 
       
  1199     // or results will be unpredictable 
       
  1200     __ASSERT_DEBUG(aSubs.Locate(KSubStringSeparator) == KErrNotFound, 
       
  1201         User::Panic(KPanicCategory, EInvalidSubstitute));
       
  1202 
       
  1203     TInt keylength(aKey.Length());
       
  1204 
       
  1205     //aDest must be empty.
       
  1206     aDest.Zero();
       
  1207 
       
  1208     // offset indicates end of last handled key in source
       
  1209     TInt offset(0);
       
  1210 
       
  1211     // offset in destination string
       
  1212     TInt desOffset(0);
       
  1213 
       
  1214     // Substring directionalities are adjusted after all changes are done.
       
  1215     TBool checkSubstringDirectionalities(EFalse);
       
  1216 
       
  1217     // count is the position in the source from which the substring starts
       
  1218     TInt count(0);
       
  1219 
       
  1220     // Replaced parameters count
       
  1221     TInt replaceCount(0);
       
  1222 
       
  1223     while (count != KErrNotFound)
       
  1224         {
       
  1225         // desCount is the position of the substring starts in destination.
       
  1226         TInt desCount(0);
       
  1227 
       
  1228         TPtrC remainder = aSource.Right(aSource.Length() - offset);
       
  1229         count = remainder.Find(aKey);
       
  1230 
       
  1231         TInt maxSubLength = -1;
       
  1232         if (count != KErrNotFound)
       
  1233             {
       
  1234             replaceCount++;
       
  1235             desOffset += count;
       
  1236             offset += count;
       
  1237             count = offset;
       
  1238             desCount = desOffset;
       
  1239 
       
  1240             // copy source to destination if first time
       
  1241             if (aDest.Length() == 0)
       
  1242                 aDest.Append(aSource);
       
  1243 
       
  1244             // delete found key from destination
       
  1245             aDest.Delete(desCount, keylength);
       
  1246 
       
  1247             offset += keylength; // increase offset by key length
       
  1248 
       
  1249             if (count + keylength < (aSource.Length()-1)) // aKey is not at the end of string
       
  1250                 {
       
  1251                 if (aSource[count+keylength] == '[') // Key includes max datalength
       
  1252                     {
       
  1253                     maxSubLength = 10*(aSource[count+keylength+1]-'0') 
       
  1254                                    + (aSource[count+keylength+2]-'0');
       
  1255                     aDest.Delete(desCount,4); // Length information stored->delete from descriptor
       
  1256                     offset += 4; // increase offset by max sub length indicator
       
  1257                     }
       
  1258                 }
       
  1259          
       
  1260             aDest.Insert(desCount, aSubs);
       
  1261         
       
  1262             desOffset = desCount + aSubs.Length();
       
  1263 
       
  1264             if (maxSubLength > 0 && aSubs.Length() > maxSubLength)
       
  1265                 {
       
  1266                 aDest.Delete(desCount+maxSubLength-1, aSubs.Length()+1-maxSubLength);     
       
  1267                 TText ellipsis(KEllipsis);
       
  1268                 aDest.Insert(desCount+maxSubLength-1, TPtrC(&ellipsis,1));
       
  1269                 desOffset = desCount + maxSubLength;
       
  1270                 }
       
  1271 
       
  1272             TBidiText::TDirectionality subsDir =
       
  1273                 TBidiText::TextDirectionality(aDest.Mid(desCount, desOffset - desCount));
       
  1274 
       
  1275             // If inserted string has different directionality,
       
  1276             // insert directionality markers so that bidi algorithm works in a desired way.
       
  1277             if (aDirectionality != subsDir)
       
  1278                 {
       
  1279                 checkSubstringDirectionalities = ETrue;
       
  1280 
       
  1281                 TInt freeSpace = aDest.MaxLength() - aDest.Length();
       
  1282 
       
  1283                 // Protect the directionality of the inserted string.
       
  1284                 if (freeSpace >= KExtraSpaceForSubStringDirMarkers)
       
  1285                     {
       
  1286                     TBuf<1> subsMarker;
       
  1287                     subsMarker.Append(subsDir == TBidiText::ELeftToRight ?
       
  1288                         KLRMarker : KRLMarker);
       
  1289 
       
  1290                     aDest.Insert(desOffset, subsMarker);
       
  1291                     aDest.Insert(desCount, subsMarker);
       
  1292                     desOffset += KExtraSpaceForSubStringDirMarkers;
       
  1293                     }
       
  1294                 }
       
  1295             }
       
  1296         }
       
  1297 
       
  1298     // Adjust substring directionality markers if necessary
       
  1299     // and if there is enough room in destination string
       
  1300     if (checkSubstringDirectionalities)
       
  1301         {
       
  1302         TText mainMarker = (aDirectionality == TBidiText::ELeftToRight ? 
       
  1303             KLRMarker : KRLMarker);
       
  1304 
       
  1305         TInt freeSpace = aDest.MaxLength() - aDest.Length();
       
  1306 
       
  1307         // If not already done, protect the directionality of the original string
       
  1308         // and all of the KSubStringSeparator separated substrings.
       
  1309         if (freeSpace > 0 
       
  1310             && aDest.Length()
       
  1311             && aDest[0] != mainMarker 
       
  1312             && aDest[0] != KSubStringSeparator
       
  1313             && aDest[0] != KDirNotFound)  
       
  1314             {
       
  1315             aDest.Insert(0, TPtrC(&mainMarker, 1));
       
  1316             freeSpace--;
       
  1317             }
       
  1318 
       
  1319         // Find and protect KSubStringSeparator separated substrings.
       
  1320         // Go through string backwards so that any changes will not affect indexes 
       
  1321         // that are not yet checked.
       
  1322         TInt j(aDest.Length()-1);
       
  1323         while (freeSpace > 0 && j >= 0) 
       
  1324             {
       
  1325             if (aDest[j] == KSubStringSeparator && j < (aDest.Length() - 1) 
       
  1326                 && aDest[j+1] != mainMarker && aDest[j+1] != KDirNotFound)
       
  1327                 {
       
  1328                 aDest.Insert(j+1, TPtrC(&mainMarker, 1));
       
  1329                 freeSpace--;
       
  1330                 }
       
  1331             j--;
       
  1332             }
       
  1333         }
       
  1334 
       
  1335     return replaceCount;
       
  1336     }
       
  1337 
       
  1338 /**
       
  1339 Formats the keystring from given parameters.
       
  1340 */
       
  1341 void TulTextResourceUtils::KeyStringFormater(TDes& aDest, const TText& aKey, TInt aPosition, const TDesC& aKeyString)
       
  1342     {
       
  1343     if (aPosition > KNoIndex)
       
  1344         {
       
  1345         aDest.Append(KKeyPrefix);
       
  1346         aDest.AppendNum(aPosition);
       
  1347         aDest.Append(aKey);
       
  1348         }
       
  1349     else
       
  1350         {
       
  1351         aDest.Append(aKeyString);
       
  1352         }
       
  1353     }
       
  1354 
       
  1355 /**
       
  1356 Resolves directionality of the given source text.
       
  1357 Place-holder strings are removed so that they don't affect the result.
       
  1358 */
       
  1359 TBidiText::TDirectionality TulTextResourceUtils::ResolveDirectionality(TDes& aText, TBool* aFound)
       
  1360     {
       
  1361     TInt i = 0;
       
  1362 
       
  1363     // Remove place-holders from string so they don't affect directionality
       
  1364     // length parameters e.g. "[29]" do not contain strongly directional
       
  1365     // characters so can ignore them.
       
  1366     while (i < aText.Length())
       
  1367         {
       
  1368         TPtrC remainder = aText.Right(aText.Length() - i);
       
  1369         TInt nextKey = remainder.Locate(KKeyPrefix);
       
  1370         i += nextKey;
       
  1371 
       
  1372         if (nextKey != KErrNotFound && i < aText.Length() - 1)
       
  1373             {
       
  1374             TInt lastCharInKey = i + 1;
       
  1375 
       
  1376             // skip possible key index
       
  1377             TText t = aText[lastCharInKey];
       
  1378             if (t >= '0' && t <= '9')
       
  1379                 {
       
  1380                 lastCharInKey++;
       
  1381 
       
  1382                 if (lastCharInKey < aText.Length())
       
  1383                     {
       
  1384                     t = aText[lastCharInKey];
       
  1385                     if (t >= '0' && t <= '9')
       
  1386                         {
       
  1387                         lastCharInKey++;
       
  1388                         }
       
  1389                     }
       
  1390                 }
       
  1391 
       
  1392             // lastCharInKey is now the index of 'N' or 'U' in the key
       
  1393 
       
  1394             if (lastCharInKey < aText.Length())
       
  1395                 {
       
  1396                 TText t = aText[lastCharInKey];
       
  1397                 if (t == 'U' || t == 'N')
       
  1398                     {
       
  1399                     // found key, delete it and continue loop to
       
  1400                     // search for the next key
       
  1401                     aText.Delete(i, lastCharInKey - i + 1);
       
  1402                     }
       
  1403                 // This was not a proper key - check the remaining string
       
  1404                 else
       
  1405                     {
       
  1406                     i = lastCharInKey + 1;
       
  1407                     }
       
  1408                 }
       
  1409             // end of string encountered - stop
       
  1410             else
       
  1411                 {
       
  1412                 break;
       
  1413                 }
       
  1414             }
       
  1415         // no key found - stop
       
  1416         else
       
  1417             {
       
  1418             break;
       
  1419             }
       
  1420         }
       
  1421 
       
  1422     return TBidiText::TextDirectionality(aText, aFound);
       
  1423     }
       
  1424 
       
  1425 /**
       
  1426 Counts the number of parameters in the text. 
       
  1427 Needed for correct memory allocations.
       
  1428 */
       
  1429 TInt TulTextResourceUtils::GetParamCount(const TDesC& aText, TInt aIndex)
       
  1430 	{
       
  1431     TInt paramCount(0);
       
  1432     TInt i(0);
       
  1433     TBool singleIndex((aIndex < 0) || (aIndex > KNumOfParams) ? EFalse : ETrue);
       
  1434 
       
  1435     while (i < aText.Length())
       
  1436         {
       
  1437         TPtrC remainder = aText.Right(aText.Length() - i);
       
  1438         TInt nextKey = remainder.Locate(KKeyPrefix);
       
  1439         i += nextKey;
       
  1440 
       
  1441         if (nextKey != KErrNotFound && i < aText.Length() - 1)
       
  1442             {
       
  1443             TInt lastCharInKey = i + 1;
       
  1444 
       
  1445             // skip possible key index
       
  1446             TText t = aText[lastCharInKey];
       
  1447             TInt foundIndex(-1);
       
  1448             
       
  1449             if (t >= '0' && t <= '9')
       
  1450                 {
       
  1451                 lastCharInKey++;
       
  1452                 foundIndex = t - '0';
       
  1453 
       
  1454                 if (lastCharInKey < aText.Length())
       
  1455                     {
       
  1456                     t = aText[lastCharInKey];
       
  1457                     if (t >= '0' && t <= '9')
       
  1458                         {
       
  1459                         foundIndex *= 10;
       
  1460                         foundIndex += t - '0';
       
  1461                         lastCharInKey++;
       
  1462                         }
       
  1463                     }
       
  1464                 }
       
  1465 
       
  1466             // lastCharInKey is now the index of 'N' or 'U' in the key
       
  1467 
       
  1468             if (lastCharInKey < aText.Length())
       
  1469                 {
       
  1470                 // Only count parameter, if index matches
       
  1471                 if (!singleIndex || (foundIndex == aIndex))
       
  1472                     {
       
  1473                     TText t = aText[lastCharInKey];
       
  1474                     if (t == 'U' || t == 'N')
       
  1475                         {
       
  1476                         // found legit key, count it
       
  1477                         paramCount++;
       
  1478                         // continue search after index
       
  1479                         i = lastCharInKey + 1;
       
  1480                         }
       
  1481                     else if (t == '%')
       
  1482                         i = lastCharInKey;
       
  1483                     else	// continue search after index
       
  1484                         i = lastCharInKey + 1;
       
  1485                     }
       
  1486                 else	// continue search after index
       
  1487                     i = lastCharInKey + 1;
       
  1488                 }
       
  1489             else	// end of string encountered - stop
       
  1490                 break;
       
  1491             }
       
  1492         else	 // no key found - stop
       
  1493             break;
       
  1494         }
       
  1495 
       
  1496     return paramCount;
       
  1497 	}
       
  1498 
       
  1499 /**
       
  1500 Counts the number of substrings (separated by KSubStringSeparators) in the text. 
       
  1501 Needed for correct memory allocations.
       
  1502 */
       
  1503 TInt TulTextResourceUtils::GetSubStringCount(const TDesC& aText)
       
  1504 	{
       
  1505     TInt subCount = 0;
       
  1506     TInt i = 0;
       
  1507 
       
  1508     while (i < aText.Length())
       
  1509         {
       
  1510         TPtrC remainder = aText.Right(aText.Length() - i);
       
  1511         TInt nextKey = remainder.Locate(KSubStringSeparator);
       
  1512         i += nextKey;
       
  1513 
       
  1514         // Always increase subcount, as a string without any separators counts as one substring.
       
  1515         // However, if string length is zero, then there are no substrings.
       
  1516         subCount++;
       
  1517 
       
  1518         if (nextKey != KErrNotFound && i < aText.Length() - 1)
       
  1519             {
       
  1520             i++; // skip separator
       
  1521             }
       
  1522         else
       
  1523             break;
       
  1524         }
       
  1525 
       
  1526     return subCount;
       
  1527 	}
       
  1528 
       
  1529 /**
       
  1530 Resolves sub strings. Uses ResolveSubStringL()
       
  1531 */
       
  1532 HBufC* TulTextResourceUtils::ResolveSubStringDirsL(TDes& aText, TInt aCount, TBool* aMarker)
       
  1533     {   
       
  1534     // Allocating heap buffer for return string.
       
  1535     TInt destlength(aText.Length());
       
  1536     destlength = destlength + (KExtraSpaceForMainStringDirMarker) * aCount;
       
  1537     HBufC* retbuf = HBufC::NewLC(destlength);
       
  1538     TPtr retptr(retbuf->Des());
       
  1539     TInt freeSpace(destlength); 
       
  1540     TInt i(0);
       
  1541     TInt j(0);
       
  1542     TBuf<1> subsMarker;
       
  1543     subsMarker.Append(KSubStringSeparator);
       
  1544     TInt count(aCount - 1);
       
  1545 
       
  1546     while (i  < aCount)
       
  1547         {
       
  1548         // Resolve sub string
       
  1549         HBufC* buffer = ResolveSubStringL(aText, aMarker);
       
  1550         TPtr ptr = buffer->Des();
       
  1551         CleanupStack::PushL(buffer); 
       
  1552         
       
  1553         // Restore sub string separators
       
  1554         if (freeSpace >= ptr.Length()) 
       
  1555             {
       
  1556             retptr.Insert(j, ptr);
       
  1557             freeSpace -= ptr.Length();
       
  1558             j += ptr.Length();
       
  1559             if (freeSpace > KExtraSpaceForMainStringDirMarker && i < count)
       
  1560                 {
       
  1561                 retptr.Append(subsMarker);
       
  1562                 j ++;
       
  1563                 }
       
  1564             }    
       
  1565         CleanupStack::PopAndDestroy(buffer);  
       
  1566         i++;                       
       
  1567         } 
       
  1568     
       
  1569     retbuf = retbuf->ReAllocL(retptr.Length());
       
  1570     CleanupStack::Pop(); //retbuf  
       
  1571     return retbuf;
       
  1572     }
       
  1573 
       
  1574 /**
       
  1575 Resolves sub string and directionality of the sub string.
       
  1576 Adds no dir marker if directionality of the string not found.
       
  1577 */
       
  1578 HBufC* TulTextResourceUtils::ResolveSubStringL(TDes& aText, TBool* aMarker)
       
  1579     {
       
  1580     // Allocating heap buffer for return string.
       
  1581     TInt destlength(aText.Length());
       
  1582     HBufC* retbuf = HBufC::NewLC(destlength + 1); // no dir marker
       
  1583     TPtr retptr(retbuf->Des());
       
  1584     
       
  1585     TBuf<1> marker;
       
  1586     marker.Append(KDirNotFound);
       
  1587         
       
  1588     TPtrC remainder = aText.Right(aText.Length());
       
  1589     TInt nextKey = remainder.Locate(KSubStringSeparator);
       
  1590     
       
  1591     if (nextKey == 0)
       
  1592         {
       
  1593         remainder.Set(remainder.Mid(1));
       
  1594         nextKey = remainder.Locate(KSubStringSeparator);
       
  1595         if (nextKey != KErrNotFound)
       
  1596             {
       
  1597             retptr.Insert(0, aText.Mid(1, nextKey));           
       
  1598             // Remove string from aText
       
  1599             aText.Delete(0, nextKey + 1);
       
  1600             }
       
  1601         else
       
  1602             {
       
  1603             TInt length = aText.Length();
       
  1604             retptr.Insert(0, aText.Mid(1, length - 1));
       
  1605             // Remove string from aText
       
  1606             aText.Delete(0, length);
       
  1607             }
       
  1608         }
       
  1609     else if (nextKey == KErrNotFound)
       
  1610         {
       
  1611         retptr.Insert(0, aText); 
       
  1612         // Remove string from aText
       
  1613         aText.Delete(0, aText.Length());
       
  1614         }
       
  1615     else
       
  1616         {
       
  1617         retptr.Insert(0, aText.Mid(0, nextKey));
       
  1618         // Remove string from aText
       
  1619         aText.Delete(0, nextKey);
       
  1620         }
       
  1621      
       
  1622     // Resolve directionality of sub string
       
  1623     HBufC* dirbuf = retbuf->AllocL();
       
  1624     TPtr dirptr = dirbuf->Des();
       
  1625     TBool found(EFalse);
       
  1626     TBidiText::TDirectionality mainDir = ResolveDirectionality(dirptr, &found);
       
  1627     delete dirbuf;
       
  1628     
       
  1629     if (!found)
       
  1630         {
       
  1631         retptr.Insert(0, marker);
       
  1632         *aMarker = ETrue;
       
  1633         }
       
  1634     else
       
  1635         {
       
  1636         *aMarker = EFalse;
       
  1637         }
       
  1638         
       
  1639     retbuf = retbuf->ReAllocL(retptr.Length());
       
  1640     CleanupStack::Pop(); //retbuf
       
  1641     // If the key string wasn't found, retbuf is empty.
       
  1642     return retbuf;     
       
  1643     }
       
  1644     
       
  1645 TBidiText::TDirectionality TulTextResourceUtils::DirectionalityL(const TDesC& aText, TBool* aFound)
       
  1646     {
       
  1647     // Resolve directionality of sub string
       
  1648     HBufC* dirbuf = aText.AllocL();
       
  1649     TPtr dirptr = dirbuf->Des();
       
  1650     TBidiText::TDirectionality dir = ResolveDirectionality(dirptr, aFound);
       
  1651     delete dirbuf;
       
  1652     return dir;
       
  1653     }
       
  1654     
       
  1655 /**
       
  1656 Removes no dir markers from source text.
       
  1657 */
       
  1658 void TulTextResourceUtils::RemoveNoDirMarkers(TDes& aText)
       
  1659     {
       
  1660     TInt nextkey(0);
       
  1661     while (nextkey < aText.Length())
       
  1662         {
       
  1663         nextkey = aText.Locate(KDirNotFound);
       
  1664         if (nextkey != KErrNotFound)
       
  1665             {
       
  1666             aText.Delete(nextkey, 1);
       
  1667             nextkey++;    
       
  1668             }
       
  1669         else
       
  1670             {
       
  1671             break;
       
  1672             }     
       
  1673         }
       
  1674     }
       
  1675     
       
  1676 /**
       
  1677 Used by exported Format methods.
       
  1678 */
       
  1679 void TulTextResourceUtils::FormatL(TDes& aDest, const TDesC& aSource, const TDesC& aKeybuf, const TDesC& aSubs)
       
  1680 {
       
  1681     // Get number of sub strings 
       
  1682     TInt count = GetSubStringCount(aSource); 
       
  1683     
       
  1684     if (count >= 1)
       
  1685         {
       
  1686         HBufC* retbuf = retbuf = aSource.AllocLC();
       
  1687         
       
  1688         TPtr retptr(retbuf->Des());
       
  1689         TBool marker(EFalse); 
       
  1690         HBufC* buffer = buffer = ResolveSubStringDirsL(retptr, count, &marker);
       
  1691         
       
  1692         CleanupStack::PushL(buffer);
       
  1693         
       
  1694         TBool found(EFalse);
       
  1695         TBidiText::TDirectionality dir = DirectionalityL(*buffer, &found);
       
  1696         
       
  1697         if (!marker)
       
  1698             {
       
  1699             //Formating the resource string.
       
  1700             Formater(aDest, aSource, aKeybuf, aSubs, dir);
       
  1701             //If the key string wasn't found, aDest is empty.
       
  1702             __ASSERT_DEBUG(aDest.Length(), User::Panic(KPanicCategory,
       
  1703                             EKeyStringNotFound));
       
  1704             }
       
  1705         else            
       
  1706             {
       
  1707             // length of input string.
       
  1708             TInt maxSubsLength = aSubs.Length();
       
  1709             TInt subCount = GetSubStringCount(aSource);
       
  1710             HBufC* destbuf = HBufC::NewLC(
       
  1711                        aSource.Length() + 
       
  1712                        count * maxSubsLength +   // worst case scenario; more accurate alloc 
       
  1713                                                       // would require complex analysis
       
  1714                        count * KExtraSpaceForSubStringDirMarkers +
       
  1715                        subCount * KExtraSpaceForMainStringDirMarker + 
       
  1716                        subCount * KExtraSpaceForMainStringDirMarker); // no dir markers             
       
  1717             TPtr destptr(destbuf->Des());
       
  1718             //Formating the resource string.
       
  1719             Formater(destptr, *buffer, aKeybuf, aSubs, dir);
       
  1720             
       
  1721             if (destptr.Length())
       
  1722                 {
       
  1723                 RemoveNoDirMarkers(destptr);
       
  1724                 }
       
  1725                 
       
  1726             aDest.Zero();
       
  1727             aDest.Append(destptr);
       
  1728             //If the key string wasn't found, aDest is empty.
       
  1729             __ASSERT_DEBUG(aDest.Length(), User::Panic(KPanicCategory,EKeyStringNotFound));               
       
  1730             CleanupStack::PopAndDestroy(destbuf);  
       
  1731             }
       
  1732         CleanupStack::PopAndDestroy(buffer);
       
  1733         CleanupStack::PopAndDestroy(retbuf);
       
  1734         }
       
  1735     
       
  1736     __ASSERT_DEBUG(aDest.Length(), User::Panic(KPanicCategory, EKeyStringNotFound));
       
  1737 	}