genericservices/s60compatibilityheaders/commonengine/src/textresolver.cpp
changeset 0 e4d67989cc36
child 44 97b0fb8a2cc2
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 <barsread.h>    // TResourceReader
       
    19 #include <bautils.h>     // BaflUtils
       
    20 #include "textresolver.h"
       
    21 #include <errorres.rsg>
       
    22 #include <uikon/eikdefconst.h>
       
    23 
       
    24 
       
    25 const TInt KUnknownError( 0 );
       
    26 const TInt KBlankError( -2 );
       
    27 
       
    28 const TInt KRIMask(0x00000fff);
       
    29 _LIT(KErrorResResourceFileName, "z:\\resource\\errors\\ERRORRES.RSC"); 
       
    30 _LIT(KRDSupport, "c:\\resource\\ErrRD");
       
    31 _LIT(KTextResolverPanic,   "TextResolver");
       
    32 
       
    33 
       
    34 GLDEF_C void Panic(TInt aPanic)
       
    35 	{
       
    36     User::Panic(KTextResolverPanic, aPanic);
       
    37 	}
       
    38 
       
    39 
       
    40 CTextResolver::CTextResolver()
       
    41     {
       
    42     }
       
    43 
       
    44 CTextResolver::CTextResolver(CCoeEnv& aEnv)
       
    45     :iCoe(&aEnv)
       
    46     {
       
    47     }
       
    48 /**
       
    49  * Two-phase constructor method that is used to create a new instance
       
    50  * of the CTextResolver class. The implementation uses the passed 
       
    51  * CCoeEnv instance to access the resource files.
       
    52  *
       
    53  * @param aEnv the CCoeEnv instance to be used to access the resource
       
    54  * files.
       
    55  * @return a pointer to a new instance of the CTextResolver class.
       
    56  */
       
    57 EXPORT_C CTextResolver* CTextResolver::NewL(CCoeEnv& aEnv)
       
    58     {
       
    59     CTextResolver* self = CTextResolver::NewLC(aEnv);
       
    60     CleanupStack::Pop(self);
       
    61     return self;
       
    62     }
       
    63 
       
    64  /**
       
    65  * Constructor creates a new instance of CTextResolver. The 
       
    66  * implementation uses the passed CCoeEnv instance to access the 
       
    67  * resource files. Leaves the object on the cleanup stack.
       
    68  *
       
    69  * @param aEnv the CCoeEnv instance to be used to access the resource
       
    70  * files.
       
    71  * @return a pointer to a new instance of the CTextResolver class.
       
    72  */
       
    73 EXPORT_C CTextResolver* CTextResolver::NewLC(CCoeEnv& aEnv)
       
    74     {
       
    75     CTextResolver* self = new (ELeave) CTextResolver(aEnv);
       
    76     CleanupStack::PushL(self);
       
    77     self->ConstructL();
       
    78     return self;
       
    79     }
       
    80 
       
    81  /**
       
    82  * Constructor creates a new instance of CTextResolver. Resource files 
       
    83  * are accessed through the RResourceFile API.
       
    84  *
       
    85  * @return a pointer to a new instance of the CTextResolver class.
       
    86  */
       
    87 EXPORT_C CTextResolver* CTextResolver::NewL()
       
    88     {
       
    89     CTextResolver* self = CTextResolver::NewLC();
       
    90     CleanupStack::Pop(self);
       
    91     return self;
       
    92     }
       
    93 
       
    94  /**
       
    95  * Constructor creates a new instance of CTextResolver.Resource files 
       
    96  * are accessed through the RResourceFile API. Leaves the object on 
       
    97  * the cleanup stack.
       
    98  *
       
    99  * @return a pointer to a new instance of the CTextResolver class.
       
   100  */
       
   101 EXPORT_C CTextResolver* CTextResolver::NewLC()
       
   102     {
       
   103     CTextResolver* self = new (ELeave) CTextResolver();
       
   104     CleanupStack::PushL(self);
       
   105     self->ConstructL();
       
   106     return self;
       
   107     }
       
   108 
       
   109 //
       
   110 // ---------------------------------------------------------
       
   111 // CTextResolver::ConstructL
       
   112 //
       
   113 // Symbian OS default constructor, initializes variables and cache 
       
   114 // ---------------------------------------------------------
       
   115 //
       
   116 void CTextResolver::ConstructL()
       
   117     {
       
   118     // if no coe is present, connect new filesession.
       
   119     if (!iCoe)
       
   120     	{
       
   121         User::LeaveIfError(iFs.Connect());    
       
   122 
       
   123 		TFileName resFile(KErrorResResourceFileName);
       
   124 		BaflUtils::NearestLanguageFile(iFs, resFile);
       
   125 		iResFile.OpenL(iFs, resFile);
       
   126     	}
       
   127 
       
   128     iRDSupport = BaflUtils::FileExists(iCoe ? iCoe->FsSession() : iFs, KRDSupport);     
       
   129     }
       
   130 
       
   131 /** 
       
   132 * Destructor 
       
   133 */
       
   134 EXPORT_C CTextResolver::~CTextResolver()
       
   135     {
       
   136     Reset();
       
   137     iResFile.Close();
       
   138 
       
   139     // if no coe is present, close filesession.
       
   140     if (!iCoe)
       
   141         iFs.Close();   
       
   142     
       
   143     delete iTitleText;
       
   144     delete iTextBuffer;
       
   145     delete iContextSeparator;
       
   146     }
       
   147 
       
   148 /**
       
   149 * Resolves the given error code and returns the error text for the
       
   150 * resolved error. Resolved text can be of any length. This version 
       
   151 * is for "normal" use.
       
   152 *
       
   153 * @param aError The error code to be resolved.
       
   154 * @param aContext Optional context for error numbers. If the aContext 
       
   155 * parameter is not passed to the function, it uses the default value
       
   156 * ECtxAutomatic. 
       
   157 * @return the error text for the resolved error. "System error" (in 
       
   158 * English localisation) is returned when error code is not known. For 
       
   159 * unknown errors blank error flag (flags are defined in 
       
   160 * textresolver.hrh) is also set to hide errors without proper 
       
   161 * explanation. There is no limit on how long the resolved string
       
   162 * can be.
       
   163 */
       
   164 EXPORT_C const TDesC& CTextResolver::ResolveErrorString(TInt aError, TErrorContext aContext)
       
   165     {
       
   166     TUint flags(0);
       
   167     TInt id(0);
       
   168 	return ResolveErrorString(aError,id,flags,aContext);
       
   169 	}
       
   170 
       
   171 /**
       
   172 * Resolves the given error code and returns the error text for the
       
   173 * resolved error. Resolved text can be of any length. This version
       
   174 * is for advanced use
       
   175 *
       
   176 * @param aError The error code to be resolved.
       
   177 * @param aTextId ID of the returned text.
       
   178 * @param aFlags The priority of the returned error. The priority is 
       
   179 * defined by the this module! Flags are defined in textresolver.hrh.
       
   180 * @param aContext Optional context for error numbers. If the aContext 
       
   181 * parameter is not passed to the function, it uses the default value
       
   182 * ECtxAutomatic. 
       
   183 * @return the error text for the resolved error. "System error" (in 
       
   184 * English localisation) is returned when error code is not known. For 
       
   185 * unknown errors blank error flag (flags are defined in 
       
   186 * textresolver.hrh) is also set to hide errors without proper 
       
   187 * explanation. There is no limit on how long the resolved string 
       
   188 * can be.
       
   189 */
       
   190 EXPORT_C const TDesC& CTextResolver::ResolveErrorString(TInt aError, TInt& aTextId, TUint& aFlags, TErrorContext aContext)
       
   191     {
       
   192     aFlags = 0;
       
   193     if (iCoe)	// Use the resource loaded using the CCoeEnv to read the resource file
       
   194     	{
       
   195 	    TRAPD(err, DoResolveErrorStringL(aError, aTextId, aFlags));
       
   196 		if (err)
       
   197 			{
       
   198 			if ((!AddContextAndSeparator(aContext)))
       
   199 				{
       
   200 				// Even the resource file opening failed, return OOM flag
       
   201 				aFlags |= EErrorResOOMFlag;
       
   202 				return KNullDesC;
       
   203 				}
       
   204 			return *iTextBuffer;
       
   205 			}            
       
   206 
       
   207 		if(aFlags&ETextResolverUnknownErrorFlag)	// Error code not supported. No error text found.
       
   208 	        {
       
   209 	        // Error is not recognised 
       
   210 	        aTextId = R_ERROR_RES_GENERAL;	// Read and return an "unknown error" text from the
       
   211 	        								// Nokia-specific version of the errorres.rss file
       
   212 	      	TPtr appTextPtr = iTitleText->Des();
       
   213 	      	TPtr textPtr = iTextBuffer->Des();
       
   214 	      	iCoe->ReadResource(appTextPtr, R_BASE);
       
   215 	      	iCoe->ReadResource(textPtr, R_ERROR_RES_GENERAL);
       
   216 	        }
       
   217 		}
       
   218 	else	// No CCoeEnv available
       
   219 		{
       
   220 		aTextId = 0;
       
   221         TRAPD(err, DoRawReadOfSystemErrorResourcesToArraysL(aError, aTextId));
       
   222         if(err)
       
   223             {
       
   224             // Cleaning needed since object not destroyed
       
   225             Reset();
       
   226             
       
   227             if (aTextId != R_ERROR_RES_NO_MEMORY || !AddContextAndSeparator(aContext))
       
   228                 {
       
   229                 // Even the resource file opening failed, return OOM flag
       
   230                 aFlags |= EErrorResOOMFlag;
       
   231                 return KNullDesC;
       
   232                 }
       
   233 
       
   234             return *iTextBuffer;
       
   235             }            
       
   236         
       
   237         aTextId = ResourceForError(aError);
       
   238         switch (aTextId)
       
   239             {
       
   240             case KBlankError:
       
   241                 {
       
   242                 aFlags |= ETextResolverBlankErrorFlag;
       
   243                 break;
       
   244                 }
       
   245             case KUnknownError:
       
   246                 {
       
   247                 // Error is not recognised 
       
   248                 aTextId = R_ERROR_RES_GENERAL;
       
   249 
       
   250 				delete iTitleText;
       
   251                 iTitleText = AllocReadUnicodeString(iResFile, R_BASE);
       
   252                 aFlags |= ETextResolverUnknownErrorFlag;
       
   253                 // No break here; Fall through to default case to resolve text for the general error
       
   254                 }
       
   255             default:    
       
   256                 {
       
   257                 // --- Error recognised by the resolver, so get the text ---
       
   258 				delete iTextBuffer;
       
   259                 iTextBuffer = AllocReadUnicodeString(iResFile, aTextId);
       
   260                 break;
       
   261                 }
       
   262             };       
       
   263         }       
       
   264 
       
   265 	if(aFlags&ETextResolverBlankErrorFlag)	// Error code supported, but no error text found.
       
   266 		{
       
   267 		delete iTextBuffer;
       
   268 		iTextBuffer = NULL;				// Return no error text at all	
       
   269 		}
       
   270 
       
   271     if (!AddContextAndSeparator(aContext))
       
   272 		{
       
   273 		aFlags |= EErrorResOOMFlag;
       
   274 		return KNullDesC;
       
   275 		}
       
   276 
       
   277     if (iRDSupport && iTextBuffer) 
       
   278         {
       
   279         HBufC* tempBuffer = iTextBuffer->ReAlloc(iTextBuffer->Length()+14);
       
   280 
       
   281         // if allocation succeeds, append error id. Otherwise iTextBuffer stays as it is
       
   282         if (tempBuffer)
       
   283             {
       
   284             iTextBuffer = tempBuffer;
       
   285             iTextBuffer->Des().Append(' ');
       
   286             iTextBuffer->Des().Append('(');
       
   287             iTextBuffer->Des().AppendNum(aError);
       
   288             iTextBuffer->Des().Append(')');
       
   289             }
       
   290         }
       
   291 	else if (aFlags & ETextResolverUnknownErrorFlag)
       
   292 		{ // We hide the errors we cannot give proper explanation, 
       
   293 		  //i.e. "System Error" will not be shown.
       
   294 		aFlags |= ETextResolverBlankErrorFlag;	
       
   295         }
       
   296 
       
   297     if (iTextBuffer)
       
   298         return *iTextBuffer;
       
   299     else
       
   300         return KNullDesC;
       
   301     }
       
   302 
       
   303 TInt CTextResolver::ResourceForError(TInt aError)
       
   304     {
       
   305     ASSERT(!iCoe);
       
   306     const TInt errorCount = iStartError->Count();
       
   307             
       
   308     delete iTitleText;
       
   309     iTitleText = NULL;
       
   310     
       
   311     for (TInt cc = 0; cc < errorCount; ++cc)
       
   312         {
       
   313         const TInt starterror = (*iStartError)[cc];
       
   314         const TInt endError = starterror-(*iErrorTexts)[cc]->Count()+1;
       
   315         
       
   316         if (aError >= endError && aError <= starterror)
       
   317         	{
       
   318 	        ASSERT(!iTitleText);
       
   319 	        iTitleText = AllocReadUnicodeString(iResFile, (*iAppTexts)[cc]);
       
   320 
       
   321 	        const TInt errorIndex = -(aError-starterror);
       
   322 	        const TInt flags = (*iFlags)[cc]->At(errorIndex);
       
   323 	        
       
   324 	        if (flags & ETextResolverPanicErrorFlag)
       
   325 	            {
       
   326 	            // --- Some errors are never meant to get to the UI level ---
       
   327 	            // --- Those of them that do, result in a panic ---
       
   328 	            Panic(aError);
       
   329 	            }
       
   330 	        
       
   331 	        else if (flags & ETextResolverBlankErrorFlag)
       
   332 	            {
       
   333 	            // --- Error code can be ignored from the users' perspective ---
       
   334 	            // --- Return blank error text ---
       
   335 	            return KBlankError;
       
   336 	            }
       
   337 
       
   338 	        else if (flags & ETextResolverUnknownErrorFlag)
       
   339 	            {
       
   340 	            // --- Error not recognised by TextResolver ---
       
   341 	            // --- Will be passed on to UIKON for interpretation ---
       
   342 	            return KUnknownError;
       
   343 	            }
       
   344 	            
       
   345 	        return (*iErrorTexts)[cc]->At(errorIndex); 
       
   346         	}
       
   347         }
       
   348         
       
   349    return KUnknownError;     
       
   350    }
       
   351     
       
   352 
       
   353 /**
       
   354 Read the system error texts from errorres.rss only, without using the Uikon CEikErrorResolver.
       
   355 This will not pick up any appliation specific errors.
       
   356 */
       
   357 void CTextResolver::DoRawReadOfSystemErrorResourcesToArraysL(TInt& aError, TInt& aTextId)
       
   358     {
       
   359     ASSERT(!iCoe);
       
   360     TResourceReader reader;
       
   361     ReadLocalizedSeparatorCharacterFromResourceAndPrepareResourceReaderLC(reader);
       
   362 
       
   363     // Lets handle KErrNoMemory as a special case, this this way we can maybe avoid extra "Resolving Errors"
       
   364     if (aError == KErrNoMemory) 
       
   365         {
       
   366         ASSERT(!iTextBuffer && !iTitleText);
       
   367 		aTextId = R_ERROR_RES_NO_MEMORY;
       
   368 		iTextBuffer = AllocReadUnicodeString(iResFile, aTextId);
       
   369 		iTitleText = AllocReadUnicodeString(iResFile, R_BASE);
       
   370         User::Leave(KErrNoMemory);
       
   371         }
       
   372    
       
   373 	if(iStartError && iErrorTexts && iFlags && iAppTexts)
       
   374 		{
       
   375 		CleanupStack::PopAndDestroy(); // rBuffer
       
   376 		return;	// Already all done
       
   377 		}
       
   378         
       
   379 	// The resource data is used differenciate between the old and new resource formats 
       
   380 	// (i.e, resources using title text and one's without using title text)
       
   381 	// This API only support the new format, so just check that it is on the new format
       
   382     const TInt dummy = reader.ReadInt16();
       
   383     const TInt version = reader.ReadInt16();
       
   384     __ASSERT_ALWAYS(dummy == 0 && version == 2, User::Leave(KErrNotSupported));
       
   385 
       
   386     // Read into the error arrays
       
   387     const TInt arrayCount = reader.ReadInt16();
       
   388     
       
   389     ASSERT(!iStartError && !iErrorTexts && !iFlags && !iAppTexts);
       
   390     iStartError = new(ELeave) CArrayFixFlat<TInt>(arrayCount);
       
   391     iErrorTexts = new(ELeave) CArrayPtrSeg<CErrorResourceIdArray>(arrayCount);
       
   392     iFlags = new(ELeave) CArrayPtrSeg<CErrorResourceFlagArray>(arrayCount);
       
   393     iAppTexts = new(ELeave) CArrayFixFlat<TInt>(arrayCount);
       
   394     
       
   395     for (TInt cc = 0; cc < arrayCount; ++cc)
       
   396         {
       
   397         // Read in error array
       
   398         iAppTexts->AppendL(reader.ReadInt32()); // Application indicators  
       
   399         iStartError->AppendL(reader.ReadInt32());
       
   400 
       
   401         const TInt listId = reader.ReadInt32();
       
   402         
       
   403         TResourceReader reader2;
       
   404         HBufC8* rBuffer = iResFile.AllocReadL(listId & KRIMask); // Remove offset from id
       
   405         reader2.SetBuffer(rBuffer);
       
   406         CleanupStack::PushL(rBuffer);
       
   407 
       
   408         const TInt count = reader2.ReadInt16();
       
   409         CArrayFixFlat<TInt>* array = new(ELeave) CErrorResourceIdArray(count);
       
   410         CleanupStack::PushL(array);
       
   411         
       
   412         CArrayFixFlat<TInt>* flagarray = new(ELeave) CErrorResourceFlagArray(count);
       
   413         CleanupStack::PushL(flagarray);
       
   414     
       
   415         for (TInt dd = 0; dd < count; ++dd)
       
   416             {                   
       
   417             const TInt flags = reader2.ReadInt8();
       
   418             flagarray->AppendL(flags);
       
   419             // Append resource id for this error text
       
   420             array->AppendL(reader2.ReadInt32());
       
   421             }
       
   422     
       
   423         iFlags->AppendL(flagarray);
       
   424         CleanupStack::Pop(flagarray); 
       
   425 
       
   426         iErrorTexts->AppendL(array);
       
   427         CleanupStack::Pop(array);
       
   428 
       
   429         CleanupStack::PopAndDestroy(rBuffer);
       
   430         }
       
   431     
       
   432     CleanupStack::PopAndDestroy(); // reader's rBuffer
       
   433     }
       
   434 
       
   435 // ---------------------------------------------------------
       
   436 // CTextResolver::Reset()
       
   437 //
       
   438 // Reset the member variables
       
   439 // ---------------------------------------------------------
       
   440 //
       
   441 void CTextResolver::Reset()
       
   442     {
       
   443     if (iBaseResourceFileOffset)
       
   444         {
       
   445         iCoe->DeleteResourceFile(iBaseResourceFileOffset);
       
   446         iBaseResourceFileOffset = 0;
       
   447         }
       
   448         
       
   449     if (iErrorTexts)
       
   450         {
       
   451         iErrorTexts->ResetAndDestroy();
       
   452         delete iErrorTexts;
       
   453         iErrorTexts = NULL;
       
   454         }
       
   455     
       
   456     if (iFlags)
       
   457         {
       
   458         iFlags->ResetAndDestroy();
       
   459         delete iFlags;
       
   460         iFlags = NULL;
       
   461         }
       
   462                 
       
   463     delete iStartError;
       
   464     iStartError = NULL;
       
   465     
       
   466     delete iAppTexts;   
       
   467     iAppTexts = NULL;
       
   468     }
       
   469 
       
   470 /**
       
   471 ErrorResolver resource files in the ?:/resource/errors/ folder must always begin with
       
   472 an array of error texts. The Nokia-specific version of the errorres.rss file also 
       
   473 contains the localized titel/text separator character at the end of the file.
       
   474 This method reads the separator character from file using the CCoeEnv provided.
       
   475 */
       
   476 void CTextResolver::ReadLocalizedSeparatorCharacterFromResourceL(CCoeEnv& aCoeEnv)
       
   477 	{
       
   478 	ASSERT(&aCoeEnv);
       
   479 	
       
   480 	if (!iBaseResourceFileOffset)
       
   481     	{
       
   482     	TFileName filename(KErrorResResourceFileName);
       
   483     	BaflUtils::NearestLanguageFile(aCoeEnv.FsSession(), filename);
       
   484     
       
   485     	iBaseResourceFileOffset = aCoeEnv.AddResourceFileL(filename);
       
   486 		
       
   487 		ASSERT(!iContextSeparator);
       
   488 		iContextSeparator = aCoeEnv.AllocReadResourceL(R_LOCALIZED_CONTEXT_SEPARATOR);
       
   489 		}
       
   490 	}
       
   491 
       
   492 /**
       
   493 ErrorResolver resource files in the ?:/resource/errors/ folder must always begin with
       
   494 an array of error texts. The Nokia-specific version of the errorres.rss file also 
       
   495 contains the localized titel/text separator character at the end of the file.
       
   496 This method reads the separator character from file WITHOUT using a CCoeEnv.
       
   497 */
       
   498 void CTextResolver::ReadLocalizedSeparatorCharacterFromResourceAndPrepareResourceReaderLC(TResourceReader& aResReader)
       
   499     {
       
   500     ASSERT(!iCoe);
       
   501     ASSERT(!iBaseResourceFileOffset);
       
   502 
       
   503     HBufC8* rBuffer = iResFile.AllocReadL(R_ERROR_RES_BASE_LIST & KRIMask); // Remove offset from id
       
   504     aResReader.SetBuffer(rBuffer);        
       
   505     CleanupStack::PushL(rBuffer);
       
   506     
       
   507     if(!iContextSeparator)
       
   508     	iContextSeparator = AllocReadUnicodeString(iResFile, R_LOCALIZED_CONTEXT_SEPARATOR);
       
   509     
       
   510     // Leave rBuffer on CleanupStack
       
   511     }
       
   512 
       
   513 // returns NULL if out of memory
       
   514 HBufC* CTextResolver::AllocReadUnicodeString(RResourceFile& aResFile, TInt aTextId)
       
   515     { 
       
   516     // Reading Unicode string w/o CCoe
       
   517     HBufC8* tempBuffer = NULL;
       
   518     HBufC* retBuffer = NULL;
       
   519 
       
   520     TRAPD(err, tempBuffer = aResFile.AllocReadL((KRIMask & aTextId))); // Remove offset from id
       
   521     if (!err)
       
   522         {
       
   523         __ASSERT_DEBUG((tempBuffer->Length()%2)==0,Panic(aTextId));
       
   524 
       
   525         // do bitwise shift to halve the length for mapping the tempBuffer to unicode.
       
   526         TInt newLen = tempBuffer->Length()>>1;
       
   527         TPtrC tempPointer((TText*)tempBuffer->Ptr(), newLen);
       
   528 
       
   529         retBuffer = tempPointer.Alloc();
       
   530         delete tempBuffer;
       
   531         }
       
   532 
       
   533     return retBuffer;
       
   534     }
       
   535 
       
   536 TBool CTextResolver::AddContextAndSeparator(TErrorContext aContext)
       
   537     {
       
   538     TBool retval(EFalse); 
       
   539     
       
   540     if (iTextBuffer && iTitleText && iContextSeparator) // If we got all the parts we need...
       
   541         {
       
   542         //... then put them together according to the aContext argument
       
   543         
       
   544         // Context checked after validity of string buffers is checked, 
       
   545         // because EFalse return value is required if any of those is NULL.
       
   546         if (aContext == ECtxNoCtxNoSeparator)
       
   547             retval = ETrue;
       
   548         else
       
   549             {
       
   550             HBufC* tempBuffer = iTextBuffer->ReAlloc(iTextBuffer->Length()+iContextSeparator->Length()+iTitleText->Length()+1);
       
   551 
       
   552             // If allocation succeeds, insert context. Otherwise iTextBuffer stays as it is.
       
   553             if (tempBuffer)
       
   554                 {
       
   555                 iTextBuffer = tempBuffer;
       
   556 				
       
   557 				// Add the title ("context") text and separator before the error text
       
   558 
       
   559                	_LIT(KNewLineChar, "\n");
       
   560                 iTextBuffer->Des().Insert(0, KNewLineChar);            
       
   561                 iTextBuffer->Des().Insert(0, *iContextSeparator);
       
   562 
       
   563                 if (aContext != ECtxNoCtx)
       
   564                     iTextBuffer->Des().Insert(0,*iTitleText);
       
   565 
       
   566                 retval = ETrue;
       
   567                 }
       
   568             }
       
   569         }
       
   570     return retval;
       
   571     }
       
   572 
       
   573 void CTextResolver::AllocBuffersL()
       
   574 	{
       
   575 	delete iTitleText;
       
   576 	iTitleText = NULL;
       
   577 	delete iTextBuffer;
       
   578 	iTextBuffer = NULL;
       
   579 
       
   580 	iTitleText = HBufC::NewL(KEikErrorResolverMaxTextLength);
       
   581     iTextBuffer = HBufC::NewL(KEikErrorResolverMaxTextLength);
       
   582 	}
       
   583 	
       
   584 void CTextResolver::DoResolveErrorStringL(TInt aError, TInt& aTextId, TUint& aFlags)
       
   585 	{
       
   586 	ASSERT(iCoe);
       
   587 	AllocBuffersL();
       
   588     
       
   589    	TPtr errTextPtr = iTextBuffer->Des();
       
   590 	TPtr errTitlePtr = iTitleText->Des();
       
   591     
       
   592     CEikonEnv::TErrorValidity errValidity = static_cast<CEikonEnv*>(iCoe)->DoGetErrorTextAndTitle(errTextPtr, aError, aTextId, aFlags, errTitlePtr, ETrue);
       
   593 
       
   594     if (errValidity == CEikonEnv::EErrorNumInvalid)
       
   595     	Panic(aError);
       
   596 
       
   597 	// If either the iTextBuffer or iTitleText buffers were too small, 
       
   598 	// they will contain the required length coded as digits into the buffer
       
   599 	TLex sizeRealloc(*iTextBuffer);
       
   600     TInt sizeRequiredForTextBuffer = 0;
       
   601     TInt sizeRequiredForTitleBuffer = 0;
       
   602     
       
   603     // Try reading the size required, if any
       
   604     sizeRealloc.Val(sizeRequiredForTextBuffer);
       
   605     sizeRealloc = *iTitleText;
       
   606     sizeRealloc.Val(sizeRequiredForTitleBuffer);
       
   607     
       
   608     // If sizes were found, realloc and get the error text again
       
   609     if (sizeRequiredForTextBuffer || sizeRequiredForTitleBuffer)	
       
   610     	{	
       
   611 		if (sizeRequiredForTextBuffer)
       
   612 			{
       
   613 			delete iTextBuffer;
       
   614 			iTextBuffer = NULL;
       
   615 			iTextBuffer = HBufC::NewL(sizeRequiredForTextBuffer);
       
   616 			}
       
   617 			
       
   618 		if (sizeRequiredForTitleBuffer)
       
   619 			{
       
   620 			delete iTitleText;
       
   621 			iTitleText = NULL;
       
   622 			iTitleText = HBufC::NewL(sizeRequiredForTitleBuffer);
       
   623 			}
       
   624 
       
   625 	   	TPtr errTextPtr(iTextBuffer->Des());
       
   626 		TPtr errTitlePtr(iTitleText->Des());
       
   627 		errValidity = static_cast<CEikonEnv*>(iCoe)->DoGetErrorTextAndTitle(errTextPtr, aError, aTextId, aFlags, errTitlePtr, ETrue);
       
   628 		if (!iTextBuffer->Length())
       
   629 			{
       
   630 			delete iTextBuffer;
       
   631 			iTextBuffer = NULL;
       
   632 			}
       
   633     	}
       
   634     	
       
   635     ReadLocalizedSeparatorCharacterFromResourceL(*iCoe);
       
   636 	}
       
   637 
       
   638 //  End of File
       
   639 
       
   640