|
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 } |