diff -r 000000000000 -r f58d6ec98e88 aknlayoutcompiler/src/LayCdl2InstO.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/aknlayoutcompiler/src/LayCdl2InstO.cpp Thu Dec 17 09:14:18 2009 +0200 @@ -0,0 +1,898 @@ +/* +* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + +// disable "identifier was truncated to '255' characters in the browser information" warning +#pragma warning (disable:4786) + +#include "LayCdl2InstO.h" +#include "LayoutCompilerErr.h" +#include "LayoutParse.h" +#include "CppWriter.h" +#include "Lay2Cdl.h" +#include "CodeGenConsts.h" +#include +#include +#include +using namespace std; +using namespace CdlCompilerToolkit; + +#define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte); +#include "AknLayoutByteCodes.h" + + +extern string KMultiLine("Multiline_"); +typedef LayoutProcessArgsErr LayoutCdlInstanceOptArgsErr; + + +/** +* gTheFuncs +* This is a collection of all SImplFunc objects that a layout instance needs, initialised +* so that there are up to four integer parameters per API type. +*/ +CAllFuncs gTheFuncs(4); + +const string KDefinitionNotSet("Layout definition not found"); + + +CAllFuncs::CAllFuncs(int aMaxParams) + { + for (int ii=0; ii<=aMaxParams; ii++) + { + for (int jj=0; jj<2; jj++) + { + bool useParent = (jj == 1); + AddLineFunc(SImplFunc::EWindowLine, ii, useParent, KTypeWindowLineLayout, "WindowLine"); + AddLineFunc(SImplFunc::ETextLine, ii, useParent, KTypeTextLineLayout, "TextLine"); + AddLineFunc(SImplFunc::EMultilineTextLine, ii, useParent, KTypeMultiLineTextLayout, "MultiLineTextLine"); + AddTableFunc(SImplFunc::EWindowTable, ii, useParent, KTypeWindowLineLayout, "WindowTable"); + AddTableFunc(SImplFunc::ETextTable, ii, useParent, KTypeTextLineLayout, "TextTable"); + } + } + SImplFunc limits( + SImplFunc::ETableLimits, 0, false, + KTypeLayoutTableLimits + " Limits() { return AknLayoutDecode::TableLimits(KDataLookup); }", + "&Limits"); + push_back(limits); + } + +void CAllFuncs::AddLineFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName) + { + // create a function of this form: + //TAknWindowLineLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES) + // { + // return AknLayoutDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES); + // } + string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f"); + string defn = aReturn + " " + funcName + "("; + string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData"; + + if (aParent) + { + defn += KTypeRect + " " + KParamParentRect; + body += ", " + KParamParentRect; + } + + for (int ii=0; ii0) + defn += ","; + defn += string(KTypeInt + " aParam") + CdlTkUtil::IntToString(ii); + body += string(", aParam") + CdlTkUtil::IntToString(ii); + } + + defn += body + "); }"; + + string ptrRef = string("&") + funcName; + + SImplFunc func(aType, aParams, aParent, defn, ptrRef); + push_back(func); + } + +void CAllFuncs::AddTableFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName) + { + //Create a function of this form: + //TAknWindowLineLayout WindowTable$NUM$PARENT(TInt aLineIndex, $PARAMS_TYPES_AND_NAMES) + // { + // return AknLayoutDecode::WindowTable$NUM$PARENT(&KImplData, aLineIndex, $PARAM_NAMES); + // } + + string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f"); + string defn = aReturn + " " + funcName + "(" + KTypeInt + " " + KParamLineIndex; + string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData, " + KParamLineIndex; + + if (aParent) + { + defn += ", " + KTypeRect + " " + KParamParentRect; + body += ", " + KParamParentRect; + } + + for (int ii=0; ii iBytes; + }; + +CLayoutInstOptImpl::CLayoutInstOptImpl(TLayoutLine* aLine, CCdlTkImplementation* aImpl) +: iLine(aLine), iImpl(aImpl) + { + } + + +class CLayoutInstOpt + { +public: + CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr& aLayout, const string& aInstName); + ~CLayoutInstOpt(); + + void Process(); + void WriteInstance(); + + CCdlTkInstance& Inst() { return *iInstance; } + +private: + void ProcessTable(TLayoutTable& aTable); + void ProcessLine(TLayoutLine& aLine); + void ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl); + void ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl); + + void SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar); + void SetNewLineData(CLayoutInstOptImpl& aImpl); + bool HasApi(const string& aName); + CCdlTkImplementation& FindImp(const string& aName); + void SetLineFunc(CLayoutInstOptImpl& aImpl); + + void CountApiParams(CCdlTkImplementation& aApi, int& aParams, bool& aParent); + SImplFunc& AddImplFunc(SImplFunc::TFuncType aType, int iParams, bool aParent); + + void SetExtraCpp(); + + void AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum); + void AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable); + void AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub); + + void EncodeValue(vector& aBytes, string aValue); + + void MirrorParamName(string& aParamName); + +private: + LayoutCdlInstanceOpt& iInstances; + TLayout* iLayout; + string iName; + CCdlTkInterface& iInterface; + CCdlTkInstance* iInstance; + CLayoutInstOptImpls iImpls; + typedef vector CImplFuncs; + CImplFuncs iFuncs; + }; + +CLayoutInstOpt::CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr& aLayout, const string& aInstName) +: iInstances(aInstances), iName(aInstName), iInterface(iInstances.Interface()) + { + iLayout = aLayout.get(); + aLayout.release(); + + iInstance = new CCdlTkInstance(iInterface); + iInstance->SetName(aInstName); + + // Initially set definitions that will not compile in the resulting code. + // This will alert the programmer to missing layout data. + CCdlTkImplementations& impl = iInstance->Impl(); + for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl) + (*pImpl)->SetDefinition(KDefinitionNotSet); + } + +CLayoutInstOpt::~CLayoutInstOpt() + { + delete iLayout; + delete iInstance; + for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) + delete *pImpl; + } + +void CLayoutInstOpt::Process() + { + for (TLayout::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab) + ProcessTable(**pTab); + SetExtraCpp(); + } + +void CLayoutInstOpt::WriteInstance() + { + CCdlTkWriteInstance writer(*iInstance); + writer.Process(); + } + +void CLayoutInstOpt::ProcessTable(TLayoutTable& aTable) + { + for (TLayoutTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) + ProcessLine(**pLine); + + int tableNum = 0; + for (TLayoutTable::TLayoutSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub) + { + TLayoutTable::TLayoutSubTable& sub = **pSub; + AddTableToInstance(aTable, sub, tableNum); + tableNum++; + } + } + +void CLayoutInstOpt::ProcessLine(TLayoutLine& aLine) + { + string apiName = LayoutToCdl::LineApiName(aLine); + if (!HasApi(apiName)) + return; + + ProcessLineApi(aLine, FindImp(apiName)); + + string multilineApiName = KFuncMultiline + apiName; + if (aLine.iTable->iType == TLayoutTable::ETextTable && + aLine["B"].size() > 1 && + HasApi(multilineApiName)) + ProcessMultiLineApi(aLine, FindImp(multilineApiName)); + } + +void CLayoutInstOpt::ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl) + { + CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl); + iImpls.push_back(newImpl); + + // always set the new line data + SetNewLineData(*newImpl); + + // if we can find the new line data in the aggregated data, point to that instead + int foundIndex = iInstances.FindSimilarBytes(newImpl); + if(foundIndex >= 0) + { + newImpl->iByteCodeIndex = foundIndex; + newImpl->iBytes.clear(); + } + + SetLineFunc(*newImpl); + iInstances.AddImpl(newImpl); + newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(newImpl->iByteCodeIndex) + ",\t// " + LayoutToCdl::LineApiName(aLine)); + } + +void CLayoutInstOpt::ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl) + { + CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl); + iImpls.push_back(newImpl); + + CCdlTkImplementation& textImpl = FindImp(LayoutToCdl::LineApiName(aLine)); + + // locate the position of the "aIndex_B" paramters in the text API parameter list + // and the position of the "aNumberOfLinesShown" parameter in the multiline API + // parmeter list. This is all the info needed to implement multiline APIs in terms + // of the corresponding text API + int bPos = 4, lPos = 0; + const CCdlTkApiParams& mParams = aImpl.Api().AsFunc().Params(); + const CCdlTkApiParams& tParams = textImpl.Api().AsFunc().Params(); + CCdlTkApiParams::const_iterator pMParam = mParams.begin(); + CCdlTkApiParams::const_iterator pTParam = tParams.begin(); + int ii=0; + while (pMParam != mParams.end() || pTParam != tParams.end()) + { + if (pTParam != tParams.end()) + { + if (pTParam->Name() == KParamNameB) + bPos = ii; + ++pTParam; + } + if (pMParam != mParams.end()) + { + if (pMParam->Name() == KParamNameNumberOfLinesShown) + lPos = ii; + ++pMParam; + } + ii++; + } + + SetLineFunc(*newImpl); + iInstances.AddImpl(newImpl); + newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString((bPos<<8)|lPos) + ",\t// " + aImpl.Name()); + } + + +void CLayoutInstOpt::SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar) + { + aImpl.iByteCodeIndex = aSimilar.iByteCodeIndex; + } + +void CLayoutInstOpt::SetNewLineData(CLayoutInstOptImpl& aImpl) + { + TLayoutLine& line = *aImpl.iLine; + + // set comment + aImpl.iComment = string("for ") + LayoutToCdl::LineApiName(line); + + const string* outputOrder = KWindowOutputOrder; + int outputSize = KWindowOutputOrderSize; + if (line.iTable->iType == TLayoutTable::ETextTable) + { + outputOrder = KTextOutputOrder; + outputSize = KTextOutputOrderSize; + } + + // encode parameters + const CCdlTkApiParams& params = aImpl.iImpl->Api().AsFunc().Params(); + for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam) + { + const CCdlTkApiParam& param = *pParam; + if (param.Type() == KTypeInt) // is it a cell index parameter + { + string paramName = param.Name(); + if (line.iIsMirroredHorizontally) + MirrorParamName(paramName); + char cells = 0; // bit field for cells that this parameter applies to + char maxVal = 0; + char nextCell = 1; // bit flag for the next cell + for (int ii=0; iiType() == KTypeInt) // is it a cell index parameter + aParams++; + else + aParent = true; + } + } + +void CLayoutInstOpt::SetLineFunc(CLayoutInstOptImpl& aImpl) + { + int nParams; + bool hasParent; + CountApiParams(*aImpl.iImpl, nParams, hasParent); + + SImplFunc::TFuncType type = SImplFunc::EWindowLine; + if (aImpl.iLine->iTable->iType == TLayoutTable::ETextTable) + { + type = SImplFunc::ETextLine; + string name = aImpl.iImpl->Name(); + if (name.size() > KFuncMultiline.size() && name.substr(0,KFuncMultiline.size()) == KFuncMultiline) + type = SImplFunc::EMultilineTextLine; + } + + SImplFunc& func = AddImplFunc(type, nParams, hasParent); + aImpl.iImpl->SetPointerReference(func.iPtrRef); + } + +CCdlTkImplementation& CLayoutInstOpt::FindImp(const string& aName) + { + CCdlTkImplementation* impl = iInstance->Impl().Find(aName); + if (!impl) + throw NotFoundErr(aName + " in interface " + iInterface.FileName()); + return *impl; + } + +bool CLayoutInstOpt::HasApi(const string& aName) + { + return iInterface.ApiList().Find(aName) != 0; + } + +SImplFunc& CLayoutInstOpt::AddImplFunc(SImplFunc::TFuncType aType, int aParams, bool aParent) + { + for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) + { + SImplFunc& func = **pFunc; + if (func.iType == aType && func.iParams == aParams && func.iParent == aParent) + return func; + } + + int count = gTheFuncs.size(); + for (int ii=0; iiiType == aType && func->iParams == aParams && func->iParent == aParent) + { + iFuncs.push_back(func); + return *func; + } + } + + throw NotFoundErr("implementation function"); + return gTheFuncs[0]; + } + +// The following strings and the SetExtraCpp() function build the gross structure of +// the C++ customisation instance. +// So far, the implementations are actually just 16-bit values, typically indexes into +// the data lookup table. These need to be turned into an array by adding declarations +// and brackets to the first and last implementations. Extra support functions are also +// added. +extern string KExtraCpp = "\ +#include \"aknlayout2decode.h\"\n\ +namespace $INTERFACE_NS { extern const TUint8 KByteCodedData[]; }\n"; + +extern string KInitialCpp ="\ +extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\ +const SImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData };\n\ +\n\ +$FUNCTIONS\ +\n\ +const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\ +\t{\n"; + +void CLayoutInstOpt::SetExtraCpp() + { + // The "extra cpp" field is written to the top of the cpp file. + iInstance->SetExtraCpp(CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KExtraCpp)); + + // add headers & fwd declarations + string init = CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KInitialCpp); + + // add decode functions + string functions; + for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) + { + CdlTkUtil::AppendString(functions, (*pFunc)->iDefn); + CdlTkUtil::AppendString(functions, "\n"); + } + init = CdlTkUtil::Replace("$FUNCTIONS", functions, init); + CCdlTkImplementation& first = **(iInstance->Impl().begin()); + first.SetDefinition(init + first.Definition()); + + // add end of data table + CCdlTkImplementation& last = **(iInstance->Impl().end() - 1); + last.SetDefinition(last.Definition() + "\n};"); + } + +void CLayoutInstOpt::AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum) + { + string tableName = LayoutToCdl::TableApiName(aTable, aSub, aTableNum); + if (HasApi(tableName)) + { + AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub); + AddTableImpl(tableName, aTable, aSub); + } + } + +void CLayoutInstOpt::AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable) + { + // code up table limits as a pair of byte values, the first byte is the first table + // index, the second is the last table index. + CCdlTkImplementation& impl = FindImp(aApiName); + int first = (*aSubTable.begin()) & 0xff; + int last = (*aSubTable.rbegin()) & 0xff; + impl.SetDefinition(CdlTkUtil::ShortToHexString((first<<8)|last) + ","); + impl.SetPointerReference(AddImplFunc(SImplFunc::ETableLimits, 0, false).iPtrRef); + } + +void CLayoutInstOpt::AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub) + { + CCdlTkImplementation& impl = FindImp(aApiName); + + int nParams; + bool hasParent; + CountApiParams(impl, nParams, hasParent); + nParams--; // don't count the aLineIndex param + SImplFunc::TFuncType type = SImplFunc::EWindowTable; + if (aTable.iType == TLayoutTable::ETextTable) + type = SImplFunc::ETextTable; + + SImplFunc& func = AddImplFunc(type, nParams, hasParent); + + impl.SetDefinition(string("(TUint16)") + iInterface.NamespaceName() + "::EApiId_" + LayoutToCdl::LineApiName(*aTable[0]) + ","); + impl.SetPointerReference(func.iPtrRef); + } + +struct SIdToInt + { + int iInt; + char* iStr; + }; + +#include +const int KScalableFontIdOffset(0x1000); +extern SIdToInt gIdToIntTable[] = + { + { ELayoutAlignLeft, "ELayoutAlignLeft" }, + { ELayoutAlignRight, "ELayoutAlignRight" }, + { ELayoutAlignCenter, "ELayoutAlignCenter" }, + { ELayoutAlignBidi, "ELayoutAlignBidi" }, + { ELatinBold19, "ELatinBold19" }, + { ELatinBold17, "ELatinBold17" }, + { ELatinBold13, "ELatinBold13" }, + { ELatinBold12, "ELatinBold12" }, + { ELatinPlain12, "ELatinPlain12" }, + { ELatinClock14, "ELatinClock14" }, + { EApacPlain12, "EApacPlain12" }, + { EApacPlain16, "EApacPlain16" }, + { ENumberPlain5, "ENumberPlain5" }, + { ELatinBold16, "ELatinBold16" }, + + { ELatinBold19+KScalableFontIdOffset, "ELatinBold19_Scaled" }, + { ELatinBold17+KScalableFontIdOffset, "ELatinBold17_Scaled" }, + { ELatinBold13+KScalableFontIdOffset, "ELatinBold13_Scaled" }, + { ELatinBold12+KScalableFontIdOffset, "ELatinBold12_Scaled" }, + { ELatinPlain12+KScalableFontIdOffset, "ELatinPlain12_Scaled" }, + { ELatinClock14+KScalableFontIdOffset, "ELatinClock14_Scaled" }, + { EApacPlain12+KScalableFontIdOffset, "EApacPlain12_Scaled" }, + { EApacPlain16+KScalableFontIdOffset, "EApacPlain16_Scaled" }, + { ENumberPlain5+KScalableFontIdOffset, "ENumberPlain5_Scaled" }, + { ELatinBold16+KScalableFontIdOffset, "ELatinBold16_Scaled" }, + + { 100, "qfn_latin_plain_17" }, // fonts that appear in app laf + { ECalcBold21, "ECalcBold21" }, + { ECalcOperBold21, "ECalcOperBold21" }, + { ECalcOperBold13, "ECalcOperBold13" }, + { 100, "gfn_latin_bold_13" }, + { 100, "gfn_latin_plain_12" }, + { 100, "qfn_clock_plain_5" }, + + { 100, "qfn_latin_plain_17_Scaled" }, + { ECalcBold21+KScalableFontIdOffset, "ECalcBold21_Scaled" }, + { ECalcOperBold21+KScalableFontIdOffset, "ECalcOperBold21_Scaled" }, + { ECalcOperBold13+KScalableFontIdOffset, "ECalcOperBold13_Scaled" }, + { 100, "gfn_latin_bold_13_Scaled" }, + { 100, "gfn_latin_plain_12_Scaled" }, + { 100, "qfn_clock_plain_5_Scaled" } + + }; +extern const int gIdToIntTableCount = sizeof(gIdToIntTable)/sizeof(SIdToInt); + +extern void TranslateValue(string& aValue) + { + int count = gIdToIntTableCount; + for (int ii=0; ii& aBytes, string aValue) + { + int pos; + TranslateValue(aValue); + + if (aValue == "") + { + aBytes.push_back(KByteEmpty); + } + else if ((pos = aValue.find('p')) != string::npos) + { + if (pos != 0) + throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue); + int val = CdlTkUtil::ParseInt(aValue.substr(1)); + if (-128 <= val && val <= 127) + { + aBytes.push_back(KByteP1); + aBytes.push_back(val); + } + else + { + aBytes.push_back(KByteP2); + aBytes.push_back((val & 0xff00) >> 8); + aBytes.push_back(val); + } + } + else + { + int val = CdlTkUtil::ParseInt(aValue); + if (0 <= val && val <= KMaxSingleByteValue) + { + aBytes.push_back(val); + } + else + { + aBytes.push_back(KByteWord); + aBytes.push_back((val & 0xff00) >> 8); + aBytes.push_back(val); + } + } + } + +void CLayoutInstOpt::MirrorParamName(string& aParamName) + { + if (aParamName == KParamNameL) + aParamName = KParamNameR; + else if (aParamName == KParamNameR) + aParamName = KParamNameL; + } + + + +// +// CInstanceList +// + +void CInstanceList::ProcessOptions(vector& aArgs) + { + bool instanceFileOk = false; + iLoaded = false; + string instFile; + for(vector::iterator pArg = aArgs.begin(); pArg != aArgs.end(); ++pArg) + { + string& arg = *pArg; + if (arg.size() >= 2 && arg.substr(0,2) == "-i") + { + instFile = arg.substr(2); + aArgs.erase(pArg); + instanceFileOk = true; + break; + } + } + if(!instanceFileOk) + throw LayoutCdlInstanceOptArgsErr(); + ifstream in; + CdlTkUtil::OpenInput(in, instFile); + iLoaded = true; + string line; + while (!in.eof()) + { + getline(in, line); + iInstances.insert(line); + } + in.close(); + } + +bool CInstanceList::IsInstanceOk(const string& aInstance) const + { + return (!iLoaded || iInstances.find(aInstance) != iInstances.end()); + } + + +// +// LayoutCdlInstanceOpt +// + +int LayoutCdlInstanceOpt::Process(vector& args) + { + CInstanceList instList; + instList.ProcessOptions(args); + + int extraArgs = args.size() - 5; + if (extraArgs < 0 || extraArgs%2 == 1) + throw LayoutCdlInstanceOptArgsErr(); + + string cdlName = args[2]; + CCdlTkCdlFileParser parser(cdlName); + auto_ptr iface(parser.LoadAndParse(true)); + + LayoutCdlInstanceOpt process(*iface); + + TLayout* base = NULL; + for (int arg = 3; arg < args.size(); arg += 2) + { + string layoutName = args[arg]; + string instName = args[arg+1]; + if (!instList.IsInstanceOk(instName)) + continue; + + auto_ptr layoutParse = TLayParseLayout::Parse(layoutName); + auto_ptr layout(layoutParse.get()); + layoutParse.release(); + if (base) + { + auto_ptr newLayout(new TLayout(*base)); + newLayout->Merge(TLayout::KMergeModeVariant, *layout); + layout = newLayout; + } + else + { + base = layout.get(); + } + process.AddLayout(layout, instName); + } + + if (base) + { + process.Process(); + process.WriteInstances(); + } + + return 0; + } + +void LayoutCdlInstanceOpt::ShowHelp(ostream& stream) + { + stream << "LayCdl2InstO [-i] ( )+ " << endl; + stream << " Creates optimised CDL instances containing the layout data." << endl; + stream << " All layout instances must conform to the CDL interface." << endl; + stream << " If more than one layout is supplies, subsequent ones are treated as" << endl; + stream << " variants of the first." << endl; + stream << " If -i is specified, then only instances whose name" << endl; + stream << " appears in the file will be processed" << endl; + } + +LayoutCdlInstanceOpt::LayoutCdlInstanceOpt(CCdlTkInterface& aInterface) +: iInterface(aInterface), iByteCodeIndex(0) + { + } + +LayoutCdlInstanceOpt::~LayoutCdlInstanceOpt() + { + for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) + delete *pLayout; + } + +void LayoutCdlInstanceOpt::AddLayout(auto_ptr& aLayout, const string& aInstName) + { + auto_ptr p(new CLayoutInstOpt(*this, aLayout, aInstName)); + iLayouts.push_back(p.get()); + p.release(); + } + +void LayoutCdlInstanceOpt::Process() + { + for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) + (*pLayout)->Process(); + ProcessCommonImpl(); + } + +void LayoutCdlInstanceOpt::WriteInstances() + { + for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) + (*pLayout)->WriteInstance(); + } + +CCdlTkInterface& LayoutCdlInstanceOpt::Interface() + { + return iInterface; + } + +const string KCommonImplStart = "\ +#include \"aknlayout2decode.h\"\n\ +namespace $NAMESPACENAME { extern TUint8 const KByteCodedData[] = {\n"; + +const string KCommonImplImpl = "\ +// $INDEX $COMMENT\n\ +$BYTES\n"; + +void LayoutCdlInstanceOpt::ProcessCommonImpl() + { + string bytecode = CdlTkUtil::Replace("$NAMESPACENAME", iInterface.NamespaceName(), KCommonImplStart); + + for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) + { + vector& bytes = (*pImpl)->iBytes; + if (bytes.size()) + { + string byteString; + for (vector::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar) + { + CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar)); + CdlTkUtil::AppendString(byteString, ","); + } + + CdlTkUtil::CReplaceSet implSet; + implSet.Add("$INDEX", CdlTkUtil::ShortToHexString((*pImpl)->iByteCodeIndex)); + implSet.Add("$COMMENT", (*pImpl)->iComment); + implSet.Add("$BYTES", byteString); + CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl)); + } + } + CdlTkUtil::AppendString(bytecode, "};\n}"); + + CCdlTkInstance& firstInst = iLayouts[0]->Inst(); + firstInst.SetExtraCpp(bytecode); + } + +LayoutCdlInstanceOpt::CLayouts& LayoutCdlInstanceOpt::Layouts() + { + return iLayouts; + } + +CLayoutInstOptImpl* LayoutCdlInstanceOpt::FindSimilarImpl(TLayoutLine& aLine) + { + for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) + { + CLayoutInstOptImpl* impl = *pImpl; + if (LinesAreEqual(*impl->iLine, aLine)) + { + return impl; + } + } + return NULL; + } + +int LayoutCdlInstanceOpt::FindSimilarBytes(CLayoutInstOptImpl* aImpl) + { + int index = -1; + vector::iterator found = std::search( + iBytesAggregated.begin(), + iBytesAggregated.end(), + aImpl->iBytes.begin(), + aImpl->iBytes.end()); + if(found != iBytesAggregated.end()) + { + index = std::distance(iBytesAggregated.begin(), found); + } + return index; + } + +void LayoutCdlInstanceOpt::AddImpl(CLayoutInstOptImpl* aImpl) + { + iImpls.push_back(aImpl); + int bytesAdded = aImpl->iBytes.size(); + if (bytesAdded) + { + aImpl->iByteCodeIndex = iByteCodeIndex; + iByteCodeIndex += bytesAdded; + iBytesAggregated.insert( + iBytesAggregated.end(), + aImpl->iBytes.begin(), + aImpl->iBytes.end()); + } + } + +bool LayoutCdlInstanceOpt::LinesAreEqual(TLayoutLine& aLine1, TLayoutLine& aLine2) + { + TLayoutLine::iterator pValues1 = aLine1.begin(); + TLayoutLine::iterator pValues2 = aLine2.begin(); + for (; pValues1 != aLine1.end() && pValues2 != aLine2.end(); ++pValues1, ++pValues2) + { + if (TLayoutTable::IsValueColumn(pValues1->first) && *pValues1 != *pValues2) + return false; + } + return true; + }