|
1 /* |
|
2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // disable "identifier was truncated to '255' characters in the browser information" warning |
|
21 #pragma warning (disable:4786) |
|
22 |
|
23 #include "LayCdl2InstO.h" |
|
24 #include "LayoutCompilerErr.h" |
|
25 #include "LayoutParse.h" |
|
26 #include "CppWriter.h" |
|
27 #include "Lay2Cdl.h" |
|
28 #include "CodeGenConsts.h" |
|
29 #include <fstream> |
|
30 #include <algorithm> |
|
31 #include <iostream> |
|
32 using namespace std; |
|
33 using namespace CdlCompilerToolkit; |
|
34 |
|
35 #define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte); |
|
36 #include "AknLayoutByteCodes.h" |
|
37 |
|
38 |
|
39 extern string KMultiLine("Multiline_"); |
|
40 typedef LayoutProcessArgsErr<LayoutCdlInstanceOpt> LayoutCdlInstanceOptArgsErr; |
|
41 |
|
42 |
|
43 /** |
|
44 * gTheFuncs |
|
45 * This is a collection of all SImplFunc objects that a layout instance needs, initialised |
|
46 * so that there are up to four integer parameters per API type. |
|
47 */ |
|
48 CAllFuncs gTheFuncs(4); |
|
49 |
|
50 const string KDefinitionNotSet("Layout definition not found"); |
|
51 |
|
52 |
|
53 CAllFuncs::CAllFuncs(int aMaxParams) |
|
54 { |
|
55 for (int ii=0; ii<=aMaxParams; ii++) |
|
56 { |
|
57 for (int jj=0; jj<2; jj++) |
|
58 { |
|
59 bool useParent = (jj == 1); |
|
60 AddLineFunc(SImplFunc::EWindowLine, ii, useParent, KTypeWindowLineLayout, "WindowLine"); |
|
61 AddLineFunc(SImplFunc::ETextLine, ii, useParent, KTypeTextLineLayout, "TextLine"); |
|
62 AddLineFunc(SImplFunc::EMultilineTextLine, ii, useParent, KTypeMultiLineTextLayout, "MultiLineTextLine"); |
|
63 AddTableFunc(SImplFunc::EWindowTable, ii, useParent, KTypeWindowLineLayout, "WindowTable"); |
|
64 AddTableFunc(SImplFunc::ETextTable, ii, useParent, KTypeTextLineLayout, "TextTable"); |
|
65 } |
|
66 } |
|
67 SImplFunc limits( |
|
68 SImplFunc::ETableLimits, 0, false, |
|
69 KTypeLayoutTableLimits + " Limits() { return AknLayoutDecode::TableLimits(KDataLookup); }", |
|
70 "&Limits"); |
|
71 push_back(limits); |
|
72 } |
|
73 |
|
74 void CAllFuncs::AddLineFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName) |
|
75 { |
|
76 // create a function of this form: |
|
77 //TAknWindowLineLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES) |
|
78 // { |
|
79 // return AknLayoutDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES); |
|
80 // } |
|
81 string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f"); |
|
82 string defn = aReturn + " " + funcName + "("; |
|
83 string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData"; |
|
84 |
|
85 if (aParent) |
|
86 { |
|
87 defn += KTypeRect + " " + KParamParentRect; |
|
88 body += ", " + KParamParentRect; |
|
89 } |
|
90 |
|
91 for (int ii=0; ii<aParams; ii++) |
|
92 { |
|
93 if (aParent || ii>0) |
|
94 defn += ","; |
|
95 defn += string(KTypeInt + " aParam") + CdlTkUtil::IntToString(ii); |
|
96 body += string(", aParam") + CdlTkUtil::IntToString(ii); |
|
97 } |
|
98 |
|
99 defn += body + "); }"; |
|
100 |
|
101 string ptrRef = string("&") + funcName; |
|
102 |
|
103 SImplFunc func(aType, aParams, aParent, defn, ptrRef); |
|
104 push_back(func); |
|
105 } |
|
106 |
|
107 void CAllFuncs::AddTableFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName) |
|
108 { |
|
109 //Create a function of this form: |
|
110 //TAknWindowLineLayout WindowTable$NUM$PARENT(TInt aLineIndex, $PARAMS_TYPES_AND_NAMES) |
|
111 // { |
|
112 // return AknLayoutDecode::WindowTable$NUM$PARENT(&KImplData, aLineIndex, $PARAM_NAMES); |
|
113 // } |
|
114 |
|
115 string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f"); |
|
116 string defn = aReturn + " " + funcName + "(" + KTypeInt + " " + KParamLineIndex; |
|
117 string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData, " + KParamLineIndex; |
|
118 |
|
119 if (aParent) |
|
120 { |
|
121 defn += ", " + KTypeRect + " " + KParamParentRect; |
|
122 body += ", " + KParamParentRect; |
|
123 } |
|
124 |
|
125 for (int ii=0; ii<aParams; ii++) |
|
126 { |
|
127 defn += string(", " + KTypeInt + " aParam") + CdlTkUtil::IntToString(ii); |
|
128 body += string(", aParam") + CdlTkUtil::IntToString(ii); |
|
129 } |
|
130 |
|
131 defn += body + "); }"; |
|
132 |
|
133 string ptrRef = string("&") + funcName; |
|
134 |
|
135 SImplFunc func(aType, aParams, aParent, defn, ptrRef); |
|
136 push_back(func); |
|
137 } |
|
138 |
|
139 |
|
140 class CLayoutInstOptImpl |
|
141 { |
|
142 public: |
|
143 CLayoutInstOptImpl(TLayoutLine* aLine, CCdlTkImplementation* aImpl); |
|
144 TLayoutLine* iLine; |
|
145 CCdlTkImplementation* iImpl; |
|
146 int iByteCodeIndex; |
|
147 string iComment; |
|
148 vector<char> iBytes; |
|
149 }; |
|
150 |
|
151 CLayoutInstOptImpl::CLayoutInstOptImpl(TLayoutLine* aLine, CCdlTkImplementation* aImpl) |
|
152 : iLine(aLine), iImpl(aImpl) |
|
153 { |
|
154 } |
|
155 |
|
156 |
|
157 class CLayoutInstOpt |
|
158 { |
|
159 public: |
|
160 CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr<TLayout>& aLayout, const string& aInstName); |
|
161 ~CLayoutInstOpt(); |
|
162 |
|
163 void Process(); |
|
164 void WriteInstance(); |
|
165 |
|
166 CCdlTkInstance& Inst() { return *iInstance; } |
|
167 |
|
168 private: |
|
169 void ProcessTable(TLayoutTable& aTable); |
|
170 void ProcessLine(TLayoutLine& aLine); |
|
171 void ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl); |
|
172 void ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl); |
|
173 |
|
174 void SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar); |
|
175 void SetNewLineData(CLayoutInstOptImpl& aImpl); |
|
176 bool HasApi(const string& aName); |
|
177 CCdlTkImplementation& FindImp(const string& aName); |
|
178 void SetLineFunc(CLayoutInstOptImpl& aImpl); |
|
179 |
|
180 void CountApiParams(CCdlTkImplementation& aApi, int& aParams, bool& aParent); |
|
181 SImplFunc& AddImplFunc(SImplFunc::TFuncType aType, int iParams, bool aParent); |
|
182 |
|
183 void SetExtraCpp(); |
|
184 |
|
185 void AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum); |
|
186 void AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable); |
|
187 void AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub); |
|
188 |
|
189 void EncodeValue(vector<char>& aBytes, string aValue); |
|
190 |
|
191 void MirrorParamName(string& aParamName); |
|
192 |
|
193 private: |
|
194 LayoutCdlInstanceOpt& iInstances; |
|
195 TLayout* iLayout; |
|
196 string iName; |
|
197 CCdlTkInterface& iInterface; |
|
198 CCdlTkInstance* iInstance; |
|
199 CLayoutInstOptImpls iImpls; |
|
200 typedef vector<SImplFunc*> CImplFuncs; |
|
201 CImplFuncs iFuncs; |
|
202 }; |
|
203 |
|
204 CLayoutInstOpt::CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr<TLayout>& aLayout, const string& aInstName) |
|
205 : iInstances(aInstances), iName(aInstName), iInterface(iInstances.Interface()) |
|
206 { |
|
207 iLayout = aLayout.get(); |
|
208 aLayout.release(); |
|
209 |
|
210 iInstance = new CCdlTkInstance(iInterface); |
|
211 iInstance->SetName(aInstName); |
|
212 |
|
213 // Initially set definitions that will not compile in the resulting code. |
|
214 // This will alert the programmer to missing layout data. |
|
215 CCdlTkImplementations& impl = iInstance->Impl(); |
|
216 for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl) |
|
217 (*pImpl)->SetDefinition(KDefinitionNotSet); |
|
218 } |
|
219 |
|
220 CLayoutInstOpt::~CLayoutInstOpt() |
|
221 { |
|
222 delete iLayout; |
|
223 delete iInstance; |
|
224 for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
225 delete *pImpl; |
|
226 } |
|
227 |
|
228 void CLayoutInstOpt::Process() |
|
229 { |
|
230 for (TLayout::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab) |
|
231 ProcessTable(**pTab); |
|
232 SetExtraCpp(); |
|
233 } |
|
234 |
|
235 void CLayoutInstOpt::WriteInstance() |
|
236 { |
|
237 CCdlTkWriteInstance writer(*iInstance); |
|
238 writer.Process(); |
|
239 } |
|
240 |
|
241 void CLayoutInstOpt::ProcessTable(TLayoutTable& aTable) |
|
242 { |
|
243 for (TLayoutTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) |
|
244 ProcessLine(**pLine); |
|
245 |
|
246 int tableNum = 0; |
|
247 for (TLayoutTable::TLayoutSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub) |
|
248 { |
|
249 TLayoutTable::TLayoutSubTable& sub = **pSub; |
|
250 AddTableToInstance(aTable, sub, tableNum); |
|
251 tableNum++; |
|
252 } |
|
253 } |
|
254 |
|
255 void CLayoutInstOpt::ProcessLine(TLayoutLine& aLine) |
|
256 { |
|
257 string apiName = LayoutToCdl::LineApiName(aLine); |
|
258 if (!HasApi(apiName)) |
|
259 return; |
|
260 |
|
261 ProcessLineApi(aLine, FindImp(apiName)); |
|
262 |
|
263 string multilineApiName = KFuncMultiline + apiName; |
|
264 if (aLine.iTable->iType == TLayoutTable::ETextTable && |
|
265 aLine["B"].size() > 1 && |
|
266 HasApi(multilineApiName)) |
|
267 ProcessMultiLineApi(aLine, FindImp(multilineApiName)); |
|
268 } |
|
269 |
|
270 void CLayoutInstOpt::ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl) |
|
271 { |
|
272 CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl); |
|
273 iImpls.push_back(newImpl); |
|
274 |
|
275 // always set the new line data |
|
276 SetNewLineData(*newImpl); |
|
277 |
|
278 // if we can find the new line data in the aggregated data, point to that instead |
|
279 int foundIndex = iInstances.FindSimilarBytes(newImpl); |
|
280 if(foundIndex >= 0) |
|
281 { |
|
282 newImpl->iByteCodeIndex = foundIndex; |
|
283 newImpl->iBytes.clear(); |
|
284 } |
|
285 |
|
286 SetLineFunc(*newImpl); |
|
287 iInstances.AddImpl(newImpl); |
|
288 newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(newImpl->iByteCodeIndex) + ",\t// " + LayoutToCdl::LineApiName(aLine)); |
|
289 } |
|
290 |
|
291 void CLayoutInstOpt::ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl) |
|
292 { |
|
293 CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl); |
|
294 iImpls.push_back(newImpl); |
|
295 |
|
296 CCdlTkImplementation& textImpl = FindImp(LayoutToCdl::LineApiName(aLine)); |
|
297 |
|
298 // locate the position of the "aIndex_B" paramters in the text API parameter list |
|
299 // and the position of the "aNumberOfLinesShown" parameter in the multiline API |
|
300 // parmeter list. This is all the info needed to implement multiline APIs in terms |
|
301 // of the corresponding text API |
|
302 int bPos = 4, lPos = 0; |
|
303 const CCdlTkApiParams& mParams = aImpl.Api().AsFunc().Params(); |
|
304 const CCdlTkApiParams& tParams = textImpl.Api().AsFunc().Params(); |
|
305 CCdlTkApiParams::const_iterator pMParam = mParams.begin(); |
|
306 CCdlTkApiParams::const_iterator pTParam = tParams.begin(); |
|
307 int ii=0; |
|
308 while (pMParam != mParams.end() || pTParam != tParams.end()) |
|
309 { |
|
310 if (pTParam != tParams.end()) |
|
311 { |
|
312 if (pTParam->Name() == KParamNameB) |
|
313 bPos = ii; |
|
314 ++pTParam; |
|
315 } |
|
316 if (pMParam != mParams.end()) |
|
317 { |
|
318 if (pMParam->Name() == KParamNameNumberOfLinesShown) |
|
319 lPos = ii; |
|
320 ++pMParam; |
|
321 } |
|
322 ii++; |
|
323 } |
|
324 |
|
325 SetLineFunc(*newImpl); |
|
326 iInstances.AddImpl(newImpl); |
|
327 newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString((bPos<<8)|lPos) + ",\t// " + aImpl.Name()); |
|
328 } |
|
329 |
|
330 |
|
331 void CLayoutInstOpt::SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar) |
|
332 { |
|
333 aImpl.iByteCodeIndex = aSimilar.iByteCodeIndex; |
|
334 } |
|
335 |
|
336 void CLayoutInstOpt::SetNewLineData(CLayoutInstOptImpl& aImpl) |
|
337 { |
|
338 TLayoutLine& line = *aImpl.iLine; |
|
339 |
|
340 // set comment |
|
341 aImpl.iComment = string("for ") + LayoutToCdl::LineApiName(line); |
|
342 |
|
343 const string* outputOrder = KWindowOutputOrder; |
|
344 int outputSize = KWindowOutputOrderSize; |
|
345 if (line.iTable->iType == TLayoutTable::ETextTable) |
|
346 { |
|
347 outputOrder = KTextOutputOrder; |
|
348 outputSize = KTextOutputOrderSize; |
|
349 } |
|
350 |
|
351 // encode parameters |
|
352 const CCdlTkApiParams& params = aImpl.iImpl->Api().AsFunc().Params(); |
|
353 for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam) |
|
354 { |
|
355 const CCdlTkApiParam& param = *pParam; |
|
356 if (param.Type() == KTypeInt) // is it a cell index parameter |
|
357 { |
|
358 string paramName = param.Name(); |
|
359 if (line.iIsMirroredHorizontally) |
|
360 MirrorParamName(paramName); |
|
361 char cells = 0; // bit field for cells that this parameter applies to |
|
362 char maxVal = 0; |
|
363 char nextCell = 1; // bit flag for the next cell |
|
364 for (int ii=0; ii<outputSize; ii++) |
|
365 { |
|
366 TValues& values = line[outputOrder[ii]]; |
|
367 if (values.iNeedsIndex && values.ParamName() == paramName) |
|
368 { |
|
369 if (maxVal == 0) |
|
370 maxVal = values.size(); |
|
371 else if (maxVal != values.size()) |
|
372 throw CdlTkAssert(string("param range mismatch ") + line.Name() + " " + param.Name()); |
|
373 cells |= nextCell; |
|
374 } |
|
375 nextCell = nextCell << 1; |
|
376 } |
|
377 aImpl.iBytes.push_back(cells); |
|
378 aImpl.iBytes.push_back(maxVal); |
|
379 } |
|
380 } |
|
381 |
|
382 // encode data |
|
383 for (int ii=0; ii<outputSize; ii++) |
|
384 { |
|
385 TValues& values = line[outputOrder[ii]]; |
|
386 for (TValues::iterator pVal = values.begin(); pVal != values.end(); ++pVal) |
|
387 EncodeValue(aImpl.iBytes, *pVal); |
|
388 } |
|
389 } |
|
390 |
|
391 void CLayoutInstOpt::CountApiParams(CCdlTkImplementation& aApi, int& aParams, bool& aParent) |
|
392 { |
|
393 aParams = 0; |
|
394 aParent = false; |
|
395 const CCdlTkApiParams& params = aApi.Api().AsFunc().Params(); |
|
396 for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam) |
|
397 { |
|
398 if (pParam->Type() == KTypeInt) // is it a cell index parameter |
|
399 aParams++; |
|
400 else |
|
401 aParent = true; |
|
402 } |
|
403 } |
|
404 |
|
405 void CLayoutInstOpt::SetLineFunc(CLayoutInstOptImpl& aImpl) |
|
406 { |
|
407 int nParams; |
|
408 bool hasParent; |
|
409 CountApiParams(*aImpl.iImpl, nParams, hasParent); |
|
410 |
|
411 SImplFunc::TFuncType type = SImplFunc::EWindowLine; |
|
412 if (aImpl.iLine->iTable->iType == TLayoutTable::ETextTable) |
|
413 { |
|
414 type = SImplFunc::ETextLine; |
|
415 string name = aImpl.iImpl->Name(); |
|
416 if (name.size() > KFuncMultiline.size() && name.substr(0,KFuncMultiline.size()) == KFuncMultiline) |
|
417 type = SImplFunc::EMultilineTextLine; |
|
418 } |
|
419 |
|
420 SImplFunc& func = AddImplFunc(type, nParams, hasParent); |
|
421 aImpl.iImpl->SetPointerReference(func.iPtrRef); |
|
422 } |
|
423 |
|
424 CCdlTkImplementation& CLayoutInstOpt::FindImp(const string& aName) |
|
425 { |
|
426 CCdlTkImplementation* impl = iInstance->Impl().Find(aName); |
|
427 if (!impl) |
|
428 throw NotFoundErr(aName + " in interface " + iInterface.FileName()); |
|
429 return *impl; |
|
430 } |
|
431 |
|
432 bool CLayoutInstOpt::HasApi(const string& aName) |
|
433 { |
|
434 return iInterface.ApiList().Find(aName) != 0; |
|
435 } |
|
436 |
|
437 SImplFunc& CLayoutInstOpt::AddImplFunc(SImplFunc::TFuncType aType, int aParams, bool aParent) |
|
438 { |
|
439 for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) |
|
440 { |
|
441 SImplFunc& func = **pFunc; |
|
442 if (func.iType == aType && func.iParams == aParams && func.iParent == aParent) |
|
443 return func; |
|
444 } |
|
445 |
|
446 int count = gTheFuncs.size(); |
|
447 for (int ii=0; ii<count; ii++) |
|
448 { |
|
449 SImplFunc* func = &gTheFuncs[ii]; |
|
450 if (func->iType == aType && func->iParams == aParams && func->iParent == aParent) |
|
451 { |
|
452 iFuncs.push_back(func); |
|
453 return *func; |
|
454 } |
|
455 } |
|
456 |
|
457 throw NotFoundErr("implementation function"); |
|
458 return gTheFuncs[0]; |
|
459 } |
|
460 |
|
461 // The following strings and the SetExtraCpp() function build the gross structure of |
|
462 // the C++ customisation instance. |
|
463 // So far, the implementations are actually just 16-bit values, typically indexes into |
|
464 // the data lookup table. These need to be turned into an array by adding declarations |
|
465 // and brackets to the first and last implementations. Extra support functions are also |
|
466 // added. |
|
467 extern string KExtraCpp = "\ |
|
468 #include \"aknlayout2decode.h\"\n\ |
|
469 namespace $INTERFACE_NS { extern const TUint8 KByteCodedData[]; }\n"; |
|
470 |
|
471 extern string KInitialCpp ="\ |
|
472 extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\ |
|
473 const SImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData };\n\ |
|
474 \n\ |
|
475 $FUNCTIONS\ |
|
476 \n\ |
|
477 const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\ |
|
478 \t{\n"; |
|
479 |
|
480 void CLayoutInstOpt::SetExtraCpp() |
|
481 { |
|
482 // The "extra cpp" field is written to the top of the cpp file. |
|
483 iInstance->SetExtraCpp(CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KExtraCpp)); |
|
484 |
|
485 // add headers & fwd declarations |
|
486 string init = CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KInitialCpp); |
|
487 |
|
488 // add decode functions |
|
489 string functions; |
|
490 for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) |
|
491 { |
|
492 CdlTkUtil::AppendString(functions, (*pFunc)->iDefn); |
|
493 CdlTkUtil::AppendString(functions, "\n"); |
|
494 } |
|
495 init = CdlTkUtil::Replace("$FUNCTIONS", functions, init); |
|
496 CCdlTkImplementation& first = **(iInstance->Impl().begin()); |
|
497 first.SetDefinition(init + first.Definition()); |
|
498 |
|
499 // add end of data table |
|
500 CCdlTkImplementation& last = **(iInstance->Impl().end() - 1); |
|
501 last.SetDefinition(last.Definition() + "\n};"); |
|
502 } |
|
503 |
|
504 void CLayoutInstOpt::AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum) |
|
505 { |
|
506 string tableName = LayoutToCdl::TableApiName(aTable, aSub, aTableNum); |
|
507 if (HasApi(tableName)) |
|
508 { |
|
509 AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub); |
|
510 AddTableImpl(tableName, aTable, aSub); |
|
511 } |
|
512 } |
|
513 |
|
514 void CLayoutInstOpt::AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable) |
|
515 { |
|
516 // code up table limits as a pair of byte values, the first byte is the first table |
|
517 // index, the second is the last table index. |
|
518 CCdlTkImplementation& impl = FindImp(aApiName); |
|
519 int first = (*aSubTable.begin()) & 0xff; |
|
520 int last = (*aSubTable.rbegin()) & 0xff; |
|
521 impl.SetDefinition(CdlTkUtil::ShortToHexString((first<<8)|last) + ","); |
|
522 impl.SetPointerReference(AddImplFunc(SImplFunc::ETableLimits, 0, false).iPtrRef); |
|
523 } |
|
524 |
|
525 void CLayoutInstOpt::AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub) |
|
526 { |
|
527 CCdlTkImplementation& impl = FindImp(aApiName); |
|
528 |
|
529 int nParams; |
|
530 bool hasParent; |
|
531 CountApiParams(impl, nParams, hasParent); |
|
532 nParams--; // don't count the aLineIndex param |
|
533 SImplFunc::TFuncType type = SImplFunc::EWindowTable; |
|
534 if (aTable.iType == TLayoutTable::ETextTable) |
|
535 type = SImplFunc::ETextTable; |
|
536 |
|
537 SImplFunc& func = AddImplFunc(type, nParams, hasParent); |
|
538 |
|
539 impl.SetDefinition(string("(TUint16)") + iInterface.NamespaceName() + "::EApiId_" + LayoutToCdl::LineApiName(*aTable[0]) + ","); |
|
540 impl.SetPointerReference(func.iPtrRef); |
|
541 } |
|
542 |
|
543 struct SIdToInt |
|
544 { |
|
545 int iInt; |
|
546 char* iStr; |
|
547 }; |
|
548 |
|
549 #include <avkon.hrh> |
|
550 const int KScalableFontIdOffset(0x1000); |
|
551 extern SIdToInt gIdToIntTable[] = |
|
552 { |
|
553 { ELayoutAlignLeft, "ELayoutAlignLeft" }, |
|
554 { ELayoutAlignRight, "ELayoutAlignRight" }, |
|
555 { ELayoutAlignCenter, "ELayoutAlignCenter" }, |
|
556 { ELayoutAlignBidi, "ELayoutAlignBidi" }, |
|
557 { ELatinBold19, "ELatinBold19" }, |
|
558 { ELatinBold17, "ELatinBold17" }, |
|
559 { ELatinBold13, "ELatinBold13" }, |
|
560 { ELatinBold12, "ELatinBold12" }, |
|
561 { ELatinPlain12, "ELatinPlain12" }, |
|
562 { ELatinClock14, "ELatinClock14" }, |
|
563 { EApacPlain12, "EApacPlain12" }, |
|
564 { EApacPlain16, "EApacPlain16" }, |
|
565 { ENumberPlain5, "ENumberPlain5" }, |
|
566 { ELatinBold16, "ELatinBold16" }, |
|
567 |
|
568 { ELatinBold19+KScalableFontIdOffset, "ELatinBold19_Scaled" }, |
|
569 { ELatinBold17+KScalableFontIdOffset, "ELatinBold17_Scaled" }, |
|
570 { ELatinBold13+KScalableFontIdOffset, "ELatinBold13_Scaled" }, |
|
571 { ELatinBold12+KScalableFontIdOffset, "ELatinBold12_Scaled" }, |
|
572 { ELatinPlain12+KScalableFontIdOffset, "ELatinPlain12_Scaled" }, |
|
573 { ELatinClock14+KScalableFontIdOffset, "ELatinClock14_Scaled" }, |
|
574 { EApacPlain12+KScalableFontIdOffset, "EApacPlain12_Scaled" }, |
|
575 { EApacPlain16+KScalableFontIdOffset, "EApacPlain16_Scaled" }, |
|
576 { ENumberPlain5+KScalableFontIdOffset, "ENumberPlain5_Scaled" }, |
|
577 { ELatinBold16+KScalableFontIdOffset, "ELatinBold16_Scaled" }, |
|
578 |
|
579 { 100, "qfn_latin_plain_17" }, // fonts that appear in app laf |
|
580 { ECalcBold21, "ECalcBold21" }, |
|
581 { ECalcOperBold21, "ECalcOperBold21" }, |
|
582 { ECalcOperBold13, "ECalcOperBold13" }, |
|
583 { 100, "gfn_latin_bold_13" }, |
|
584 { 100, "gfn_latin_plain_12" }, |
|
585 { 100, "qfn_clock_plain_5" }, |
|
586 |
|
587 { 100, "qfn_latin_plain_17_Scaled" }, |
|
588 { ECalcBold21+KScalableFontIdOffset, "ECalcBold21_Scaled" }, |
|
589 { ECalcOperBold21+KScalableFontIdOffset, "ECalcOperBold21_Scaled" }, |
|
590 { ECalcOperBold13+KScalableFontIdOffset, "ECalcOperBold13_Scaled" }, |
|
591 { 100, "gfn_latin_bold_13_Scaled" }, |
|
592 { 100, "gfn_latin_plain_12_Scaled" }, |
|
593 { 100, "qfn_clock_plain_5_Scaled" } |
|
594 |
|
595 }; |
|
596 extern const int gIdToIntTableCount = sizeof(gIdToIntTable)/sizeof(SIdToInt); |
|
597 |
|
598 extern void TranslateValue(string& aValue) |
|
599 { |
|
600 int count = gIdToIntTableCount; |
|
601 for (int ii=0; ii<count; ii++) |
|
602 { |
|
603 SIdToInt& trans = gIdToIntTable[ii]; |
|
604 if (aValue == trans.iStr) |
|
605 { |
|
606 aValue = CdlTkUtil::IntToString(trans.iInt); |
|
607 return; |
|
608 } |
|
609 } |
|
610 } |
|
611 |
|
612 void CLayoutInstOpt::EncodeValue(vector<char>& aBytes, string aValue) |
|
613 { |
|
614 int pos; |
|
615 TranslateValue(aValue); |
|
616 |
|
617 if (aValue == "") |
|
618 { |
|
619 aBytes.push_back(KByteEmpty); |
|
620 } |
|
621 else if ((pos = aValue.find('p')) != string::npos) |
|
622 { |
|
623 if (pos != 0) |
|
624 throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue); |
|
625 int val = CdlTkUtil::ParseInt(aValue.substr(1)); |
|
626 if (-128 <= val && val <= 127) |
|
627 { |
|
628 aBytes.push_back(KByteP1); |
|
629 aBytes.push_back(val); |
|
630 } |
|
631 else |
|
632 { |
|
633 aBytes.push_back(KByteP2); |
|
634 aBytes.push_back((val & 0xff00) >> 8); |
|
635 aBytes.push_back(val); |
|
636 } |
|
637 } |
|
638 else |
|
639 { |
|
640 int val = CdlTkUtil::ParseInt(aValue); |
|
641 if (0 <= val && val <= KMaxSingleByteValue) |
|
642 { |
|
643 aBytes.push_back(val); |
|
644 } |
|
645 else |
|
646 { |
|
647 aBytes.push_back(KByteWord); |
|
648 aBytes.push_back((val & 0xff00) >> 8); |
|
649 aBytes.push_back(val); |
|
650 } |
|
651 } |
|
652 } |
|
653 |
|
654 void CLayoutInstOpt::MirrorParamName(string& aParamName) |
|
655 { |
|
656 if (aParamName == KParamNameL) |
|
657 aParamName = KParamNameR; |
|
658 else if (aParamName == KParamNameR) |
|
659 aParamName = KParamNameL; |
|
660 } |
|
661 |
|
662 |
|
663 |
|
664 // |
|
665 // CInstanceList |
|
666 // |
|
667 |
|
668 void CInstanceList::ProcessOptions(vector<string>& aArgs) |
|
669 { |
|
670 bool instanceFileOk = false; |
|
671 iLoaded = false; |
|
672 string instFile; |
|
673 for(vector<string>::iterator pArg = aArgs.begin(); pArg != aArgs.end(); ++pArg) |
|
674 { |
|
675 string& arg = *pArg; |
|
676 if (arg.size() >= 2 && arg.substr(0,2) == "-i") |
|
677 { |
|
678 instFile = arg.substr(2); |
|
679 aArgs.erase(pArg); |
|
680 instanceFileOk = true; |
|
681 break; |
|
682 } |
|
683 } |
|
684 if(!instanceFileOk) |
|
685 throw LayoutCdlInstanceOptArgsErr(); |
|
686 ifstream in; |
|
687 CdlTkUtil::OpenInput(in, instFile); |
|
688 iLoaded = true; |
|
689 string line; |
|
690 while (!in.eof()) |
|
691 { |
|
692 getline(in, line); |
|
693 iInstances.insert(line); |
|
694 } |
|
695 in.close(); |
|
696 } |
|
697 |
|
698 bool CInstanceList::IsInstanceOk(const string& aInstance) const |
|
699 { |
|
700 return (!iLoaded || iInstances.find(aInstance) != iInstances.end()); |
|
701 } |
|
702 |
|
703 |
|
704 // |
|
705 // LayoutCdlInstanceOpt |
|
706 // |
|
707 |
|
708 int LayoutCdlInstanceOpt::Process(vector<string>& args) |
|
709 { |
|
710 CInstanceList instList; |
|
711 instList.ProcessOptions(args); |
|
712 |
|
713 int extraArgs = args.size() - 5; |
|
714 if (extraArgs < 0 || extraArgs%2 == 1) |
|
715 throw LayoutCdlInstanceOptArgsErr(); |
|
716 |
|
717 string cdlName = args[2]; |
|
718 CCdlTkCdlFileParser parser(cdlName); |
|
719 auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true)); |
|
720 |
|
721 LayoutCdlInstanceOpt process(*iface); |
|
722 |
|
723 TLayout* base = NULL; |
|
724 for (int arg = 3; arg < args.size(); arg += 2) |
|
725 { |
|
726 string layoutName = args[arg]; |
|
727 string instName = args[arg+1]; |
|
728 if (!instList.IsInstanceOk(instName)) |
|
729 continue; |
|
730 |
|
731 auto_ptr<TLayParseLayout> layoutParse = TLayParseLayout::Parse(layoutName); |
|
732 auto_ptr<TLayout> layout(layoutParse.get()); |
|
733 layoutParse.release(); |
|
734 if (base) |
|
735 { |
|
736 auto_ptr<TLayout> newLayout(new TLayout(*base)); |
|
737 newLayout->Merge(TLayout::KMergeModeVariant, *layout); |
|
738 layout = newLayout; |
|
739 } |
|
740 else |
|
741 { |
|
742 base = layout.get(); |
|
743 } |
|
744 process.AddLayout(layout, instName); |
|
745 } |
|
746 |
|
747 if (base) |
|
748 { |
|
749 process.Process(); |
|
750 process.WriteInstances(); |
|
751 } |
|
752 |
|
753 return 0; |
|
754 } |
|
755 |
|
756 void LayoutCdlInstanceOpt::ShowHelp(ostream& stream) |
|
757 { |
|
758 stream << "LayCdl2InstO [-i<instanceList>] <cdlName> (<layoutName> <instanceName>)+ " << endl; |
|
759 stream << " Creates optimised CDL instances containing the layout data." << endl; |
|
760 stream << " All layout instances must conform to the CDL interface." << endl; |
|
761 stream << " If more than one layout is supplies, subsequent ones are treated as" << endl; |
|
762 stream << " variants of the first." << endl; |
|
763 stream << " If -i<instanceList> is specified, then only instances whose name" << endl; |
|
764 stream << " appears in the file <instanceList> will be processed" << endl; |
|
765 } |
|
766 |
|
767 LayoutCdlInstanceOpt::LayoutCdlInstanceOpt(CCdlTkInterface& aInterface) |
|
768 : iInterface(aInterface), iByteCodeIndex(0) |
|
769 { |
|
770 } |
|
771 |
|
772 LayoutCdlInstanceOpt::~LayoutCdlInstanceOpt() |
|
773 { |
|
774 for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) |
|
775 delete *pLayout; |
|
776 } |
|
777 |
|
778 void LayoutCdlInstanceOpt::AddLayout(auto_ptr<TLayout>& aLayout, const string& aInstName) |
|
779 { |
|
780 auto_ptr<CLayoutInstOpt> p(new CLayoutInstOpt(*this, aLayout, aInstName)); |
|
781 iLayouts.push_back(p.get()); |
|
782 p.release(); |
|
783 } |
|
784 |
|
785 void LayoutCdlInstanceOpt::Process() |
|
786 { |
|
787 for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) |
|
788 (*pLayout)->Process(); |
|
789 ProcessCommonImpl(); |
|
790 } |
|
791 |
|
792 void LayoutCdlInstanceOpt::WriteInstances() |
|
793 { |
|
794 for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) |
|
795 (*pLayout)->WriteInstance(); |
|
796 } |
|
797 |
|
798 CCdlTkInterface& LayoutCdlInstanceOpt::Interface() |
|
799 { |
|
800 return iInterface; |
|
801 } |
|
802 |
|
803 const string KCommonImplStart = "\ |
|
804 #include \"aknlayout2decode.h\"\n\ |
|
805 namespace $NAMESPACENAME { extern TUint8 const KByteCodedData[] = {\n"; |
|
806 |
|
807 const string KCommonImplImpl = "\ |
|
808 // $INDEX $COMMENT\n\ |
|
809 $BYTES\n"; |
|
810 |
|
811 void LayoutCdlInstanceOpt::ProcessCommonImpl() |
|
812 { |
|
813 string bytecode = CdlTkUtil::Replace("$NAMESPACENAME", iInterface.NamespaceName(), KCommonImplStart); |
|
814 |
|
815 for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
816 { |
|
817 vector<char>& bytes = (*pImpl)->iBytes; |
|
818 if (bytes.size()) |
|
819 { |
|
820 string byteString; |
|
821 for (vector<char>::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar) |
|
822 { |
|
823 CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar)); |
|
824 CdlTkUtil::AppendString(byteString, ","); |
|
825 } |
|
826 |
|
827 CdlTkUtil::CReplaceSet implSet; |
|
828 implSet.Add("$INDEX", CdlTkUtil::ShortToHexString((*pImpl)->iByteCodeIndex)); |
|
829 implSet.Add("$COMMENT", (*pImpl)->iComment); |
|
830 implSet.Add("$BYTES", byteString); |
|
831 CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl)); |
|
832 } |
|
833 } |
|
834 CdlTkUtil::AppendString(bytecode, "};\n}"); |
|
835 |
|
836 CCdlTkInstance& firstInst = iLayouts[0]->Inst(); |
|
837 firstInst.SetExtraCpp(bytecode); |
|
838 } |
|
839 |
|
840 LayoutCdlInstanceOpt::CLayouts& LayoutCdlInstanceOpt::Layouts() |
|
841 { |
|
842 return iLayouts; |
|
843 } |
|
844 |
|
845 CLayoutInstOptImpl* LayoutCdlInstanceOpt::FindSimilarImpl(TLayoutLine& aLine) |
|
846 { |
|
847 for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
848 { |
|
849 CLayoutInstOptImpl* impl = *pImpl; |
|
850 if (LinesAreEqual(*impl->iLine, aLine)) |
|
851 { |
|
852 return impl; |
|
853 } |
|
854 } |
|
855 return NULL; |
|
856 } |
|
857 |
|
858 int LayoutCdlInstanceOpt::FindSimilarBytes(CLayoutInstOptImpl* aImpl) |
|
859 { |
|
860 int index = -1; |
|
861 vector<char>::iterator found = std::search( |
|
862 iBytesAggregated.begin(), |
|
863 iBytesAggregated.end(), |
|
864 aImpl->iBytes.begin(), |
|
865 aImpl->iBytes.end()); |
|
866 if(found != iBytesAggregated.end()) |
|
867 { |
|
868 index = std::distance(iBytesAggregated.begin(), found); |
|
869 } |
|
870 return index; |
|
871 } |
|
872 |
|
873 void LayoutCdlInstanceOpt::AddImpl(CLayoutInstOptImpl* aImpl) |
|
874 { |
|
875 iImpls.push_back(aImpl); |
|
876 int bytesAdded = aImpl->iBytes.size(); |
|
877 if (bytesAdded) |
|
878 { |
|
879 aImpl->iByteCodeIndex = iByteCodeIndex; |
|
880 iByteCodeIndex += bytesAdded; |
|
881 iBytesAggregated.insert( |
|
882 iBytesAggregated.end(), |
|
883 aImpl->iBytes.begin(), |
|
884 aImpl->iBytes.end()); |
|
885 } |
|
886 } |
|
887 |
|
888 bool LayoutCdlInstanceOpt::LinesAreEqual(TLayoutLine& aLine1, TLayoutLine& aLine2) |
|
889 { |
|
890 TLayoutLine::iterator pValues1 = aLine1.begin(); |
|
891 TLayoutLine::iterator pValues2 = aLine2.begin(); |
|
892 for (; pValues1 != aLine1.end() && pValues2 != aLine2.end(); ++pValues1, ++pValues2) |
|
893 { |
|
894 if (TLayoutTable::IsValueColumn(pValues1->first) && *pValues1 != *pValues2) |
|
895 return false; |
|
896 } |
|
897 return true; |
|
898 } |