aknlayoutcompiler/src/LayCdl2InstO.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     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 	}