libraries/ltkutils/src/rez.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // rez.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 #include <fshell/ltkutils.h>
       
    13 #include <f32file.h>
       
    14 #include <bautils.h>
       
    15 #include <barsc.h>
       
    16 
       
    17 // Horrible variadic macro to avoid leaving from within a variadic function, because GCCE doesn't like that
       
    18 #define LeaveIfErr(err, errBuf, fmt...) \
       
    19 	do \
       
    20 		{ \
       
    21 		TInt __err = (err); \
       
    22 		if (__err < 0 && errBuf) \
       
    23 			{ \
       
    24 			*errBuf = HBufC::NewL(512); \
       
    25 			FormatIntoBuf(*errBuf, fmt); \
       
    26 			} \
       
    27 		User::LeaveIfError(__err); \
       
    28 		} \
       
    29 		while (0)
       
    30 
       
    31 
       
    32 void FormatIntoBuf(HBufC* aErrBuf, TRefByValue<const TDesC> aFmt, ...)
       
    33 	{
       
    34 	VA_LIST list;
       
    35 	VA_START(list, aFmt);
       
    36 
       
    37 	TPtr ptr = aErrBuf->Des();
       
    38 	ptr.FormatList(aFmt, list);
       
    39 	VA_END(list);
       
    40 	}
       
    41 
       
    42 
       
    43 EXPORT_C HBufC8* LtkUtils::Rez8L(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
       
    44 	{
       
    45 	TPtrC id(aIdentifier);
       
    46 	if (aIdentifier.Left(2) != _L("R:"))
       
    47 		{
       
    48 		// Just return the string as-is, ie unlocalised
       
    49 		HBufC8* result = HBufC8::NewL(aIdentifier.Length());
       
    50 		result->Des().Copy(aIdentifier);
       
    51 		return result;
       
    52 		}
       
    53 
       
    54 	RFs stackfs;
       
    55 	if (!aFs)
       
    56 		{
       
    57 		CleanupClosePushL(stackfs);
       
    58 		LeaveIfErr(stackfs.Connect(), aErrBuf, _L("Couldn't connect to RFs"));
       
    59 		aFs = &stackfs;
       
    60 		}
       
    61 	else
       
    62 		{
       
    63 		CleanupStack::PushL((CBase*)NULL); // Just so the cleanup stack is the same depth in both cases - this is ok to destroy
       
    64 		}
       
    65 	RFs& fs = *aFs;
       
    66 
       
    67 	id.Set(id.Mid(2));
       
    68 	TInt colon = id.Locate(':');
       
    69 	if (colon == KErrNotFound || colon == 0)
       
    70 		{
       
    71 		LeaveIfErr(KErrArgument, aErrBuf, _L("Resource identifier must include a resource id - R:FILENAME:ID[:OFFSET]"));
       
    72 		}
       
    73 
       
    74 	TPtrC resname(id.Left(colon));
       
    75 	id.Set(id.Mid(colon+1));
       
    76 
       
    77 	colon = id.Locate(':');
       
    78 	TPtrC offset;
       
    79 	if (colon != KErrNotFound)
       
    80 		{
       
    81 		offset.Set(id.Mid(colon+1));
       
    82 		id.Set(id.Left(colon));
       
    83 		}
       
    84 
       
    85 	TFileName resFileName = resname;
       
    86 	resFileName.Insert(0, _L("\\Resource\\"));
       
    87 	resFileName.Append(_L(".rsc")); // Seems daft but you have to have this to keep Bafl happy
       
    88 	BaflUtils::NearestLanguageFile(fs, resFileName);
       
    89 
       
    90 	RResourceFile resFile;
       
    91 	CleanupClosePushL(resFile);
       
    92 	TRAPD(err, resFile.OpenL(fs, resFileName));
       
    93 	LeaveIfErr(err, aErrBuf, _L("Couldn't open resource file %S"), &resFileName);
       
    94 
       
    95 	TRAP(err, resFile.ConfirmSignatureL());
       
    96 	LeaveIfErr(err,  aErrBuf, _L("Failed to confirm signature"));
       
    97 
       
    98 	TBool hex = EFalse;
       
    99 	if (id.Left(2) == _L("0x"))
       
   100 		{
       
   101 		id.Set(id.Mid(2));
       
   102 		hex = ETrue;
       
   103 		}
       
   104 	TUint resourceId;
       
   105 	TLex lex(id);
       
   106 	LeaveIfErr(lex.Val(resourceId, hex ? EHex : EDecimal), aErrBuf, _L("Couldn't parse resource id from %S"), &id);
       
   107 
       
   108 	HBufC8* resdata = NULL;
       
   109 	TRAP(err, resdata = resFile.AllocReadL(resourceId));
       
   110 	LeaveIfErr(err, aErrBuf, _L("Couldn't read resource %d from %S"), resourceId, &resFileName);
       
   111 	CleanupStack::PushL(resdata);
       
   112 
       
   113 	TPtrC8 result(*resdata);
       
   114 	if (offset.Length())
       
   115 		{
       
   116 		char last = (char)offset[offset.Length() - 1];
       
   117 		if (last != 'd' && last != 'D')
       
   118 			{
       
   119 			LeaveIfErr(KErrArgument, aErrBuf, _L("Offset '%S' does not end in a 'd' or a 'D'. This is needed to indicate whether the actual target is 8-bit or 16-bit"), &offset);
       
   120 			}
       
   121 		TResourceReader reader;
       
   122 		reader.SetBuffer(resdata);
       
   123 		TLex lex(offset);
       
   124 		while (!lex.Eos())
       
   125 			{
       
   126 			TChar ch = lex.Get();
       
   127 			if (ch == 'd')
       
   128 				{
       
   129 				result.Set(reader.ReadTPtrC8());
       
   130 				}
       
   131 			else if (ch == 'D')
       
   132 				{
       
   133 				TPtrC16 wptr = reader.ReadTPtrC16();
       
   134 				result.Set(TPtrC8((TUint8*)wptr.Ptr(), wptr.Size()));
       
   135 				}
       
   136 			else
       
   137 				{
       
   138 				lex.UnGet();
       
   139 				TInt amountToSkip;
       
   140 				LeaveIfErr(lex.Val(amountToSkip), aErrBuf, _L("Error lexing offset"));
       
   141 				reader.Advance(amountToSkip);
       
   142 				}
       
   143 			}
       
   144 		}
       
   145 
       
   146 	HBufC8* resultBuf = result.AllocL();
       
   147 	CleanupStack::PopAndDestroy(3); // resData, resFile, fs
       
   148 	return resultBuf;
       
   149 	}
       
   150 
       
   151 EXPORT_C HBufC* LtkUtils::RezL(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
       
   152 	{
       
   153 	if (aIdentifier.Left(2) != _L("R:"))
       
   154 		{
       
   155 		// Just return the string as-is, ie unlocalised
       
   156 		return aIdentifier.AllocL();
       
   157 		}
       
   158 	HBufC8* buf8 = Rez8L(aIdentifier, aFs, aErrBuf);
       
   159 	CleanupStack::PushL(buf8);
       
   160 	TPtrC16 wptr((TUint16*)buf8->Ptr(), buf8->Size()/2);
       
   161 	HBufC* result = wptr.AllocL();
       
   162 	CleanupStack::PopAndDestroy(buf8);
       
   163 	return result;
       
   164 	}
       
   165 
       
   166 EXPORT_C HBufC* LtkUtils::RezLC(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
       
   167 	{
       
   168 	HBufC* res = RezL(aIdentifier, aFs, aErrBuf);
       
   169 	CleanupStack::PushL(res);
       
   170 	return res;
       
   171 	}
       
   172 
       
   173 EXPORT_C HBufC8* LtkUtils::Rez8LC(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
       
   174 	{
       
   175 	HBufC8* res = Rez8L(aIdentifier, aFs, aErrBuf);
       
   176 	CleanupStack::PushL(res);
       
   177 	return res;
       
   178 	}