libraries/ltkutils/src/rez.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/ltkutils/src/rez.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,178 @@
+// rez.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#include <fshell/ltkutils.h>
+#include <f32file.h>
+#include <bautils.h>
+#include <barsc.h>
+
+// Horrible variadic macro to avoid leaving from within a variadic function, because GCCE doesn't like that
+#define LeaveIfErr(err, errBuf, fmt...) \
+	do \
+		{ \
+		TInt __err = (err); \
+		if (__err < 0 && errBuf) \
+			{ \
+			*errBuf = HBufC::NewL(512); \
+			FormatIntoBuf(*errBuf, fmt); \
+			} \
+		User::LeaveIfError(__err); \
+		} \
+		while (0)
+
+
+void FormatIntoBuf(HBufC* aErrBuf, TRefByValue<const TDesC> aFmt, ...)
+	{
+	VA_LIST list;
+	VA_START(list, aFmt);
+
+	TPtr ptr = aErrBuf->Des();
+	ptr.FormatList(aFmt, list);
+	VA_END(list);
+	}
+
+
+EXPORT_C HBufC8* LtkUtils::Rez8L(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
+	{
+	TPtrC id(aIdentifier);
+	if (aIdentifier.Left(2) != _L("R:"))
+		{
+		// Just return the string as-is, ie unlocalised
+		HBufC8* result = HBufC8::NewL(aIdentifier.Length());
+		result->Des().Copy(aIdentifier);
+		return result;
+		}
+
+	RFs stackfs;
+	if (!aFs)
+		{
+		CleanupClosePushL(stackfs);
+		LeaveIfErr(stackfs.Connect(), aErrBuf, _L("Couldn't connect to RFs"));
+		aFs = &stackfs;
+		}
+	else
+		{
+		CleanupStack::PushL((CBase*)NULL); // Just so the cleanup stack is the same depth in both cases - this is ok to destroy
+		}
+	RFs& fs = *aFs;
+
+	id.Set(id.Mid(2));
+	TInt colon = id.Locate(':');
+	if (colon == KErrNotFound || colon == 0)
+		{
+		LeaveIfErr(KErrArgument, aErrBuf, _L("Resource identifier must include a resource id - R:FILENAME:ID[:OFFSET]"));
+		}
+
+	TPtrC resname(id.Left(colon));
+	id.Set(id.Mid(colon+1));
+
+	colon = id.Locate(':');
+	TPtrC offset;
+	if (colon != KErrNotFound)
+		{
+		offset.Set(id.Mid(colon+1));
+		id.Set(id.Left(colon));
+		}
+
+	TFileName resFileName = resname;
+	resFileName.Insert(0, _L("\\Resource\\"));
+	resFileName.Append(_L(".rsc")); // Seems daft but you have to have this to keep Bafl happy
+	BaflUtils::NearestLanguageFile(fs, resFileName);
+
+	RResourceFile resFile;
+	CleanupClosePushL(resFile);
+	TRAPD(err, resFile.OpenL(fs, resFileName));
+	LeaveIfErr(err, aErrBuf, _L("Couldn't open resource file %S"), &resFileName);
+
+	TRAP(err, resFile.ConfirmSignatureL());
+	LeaveIfErr(err,  aErrBuf, _L("Failed to confirm signature"));
+
+	TBool hex = EFalse;
+	if (id.Left(2) == _L("0x"))
+		{
+		id.Set(id.Mid(2));
+		hex = ETrue;
+		}
+	TUint resourceId;
+	TLex lex(id);
+	LeaveIfErr(lex.Val(resourceId, hex ? EHex : EDecimal), aErrBuf, _L("Couldn't parse resource id from %S"), &id);
+
+	HBufC8* resdata = NULL;
+	TRAP(err, resdata = resFile.AllocReadL(resourceId));
+	LeaveIfErr(err, aErrBuf, _L("Couldn't read resource %d from %S"), resourceId, &resFileName);
+	CleanupStack::PushL(resdata);
+
+	TPtrC8 result(*resdata);
+	if (offset.Length())
+		{
+		char last = (char)offset[offset.Length() - 1];
+		if (last != 'd' && last != 'D')
+			{
+			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);
+			}
+		TResourceReader reader;
+		reader.SetBuffer(resdata);
+		TLex lex(offset);
+		while (!lex.Eos())
+			{
+			TChar ch = lex.Get();
+			if (ch == 'd')
+				{
+				result.Set(reader.ReadTPtrC8());
+				}
+			else if (ch == 'D')
+				{
+				TPtrC16 wptr = reader.ReadTPtrC16();
+				result.Set(TPtrC8((TUint8*)wptr.Ptr(), wptr.Size()));
+				}
+			else
+				{
+				lex.UnGet();
+				TInt amountToSkip;
+				LeaveIfErr(lex.Val(amountToSkip), aErrBuf, _L("Error lexing offset"));
+				reader.Advance(amountToSkip);
+				}
+			}
+		}
+
+	HBufC8* resultBuf = result.AllocL();
+	CleanupStack::PopAndDestroy(3); // resData, resFile, fs
+	return resultBuf;
+	}
+
+EXPORT_C HBufC* LtkUtils::RezL(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
+	{
+	if (aIdentifier.Left(2) != _L("R:"))
+		{
+		// Just return the string as-is, ie unlocalised
+		return aIdentifier.AllocL();
+		}
+	HBufC8* buf8 = Rez8L(aIdentifier, aFs, aErrBuf);
+	CleanupStack::PushL(buf8);
+	TPtrC16 wptr((TUint16*)buf8->Ptr(), buf8->Size()/2);
+	HBufC* result = wptr.AllocL();
+	CleanupStack::PopAndDestroy(buf8);
+	return result;
+	}
+
+EXPORT_C HBufC* LtkUtils::RezLC(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
+	{
+	HBufC* res = RezL(aIdentifier, aFs, aErrBuf);
+	CleanupStack::PushL(res);
+	return res;
+	}
+
+EXPORT_C HBufC8* LtkUtils::Rez8LC(const TDesC& aIdentifier, RFs* aFs, HBufC** aErrBuf)
+	{
+	HBufC8* res = Rez8L(aIdentifier, aFs, aErrBuf);
+	CleanupStack::PushL(res);
+	return res;
+	}