aknlayoutcompiler/src/MLCompCdl2InstO.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     1 /*
       
     2 * Copyright (c) 2002-2008 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 // disable "identifier was truncated to '255' characters in the browser information" warning
       
    20 #pragma warning (disable:4786)
       
    21 
       
    22 // disable "decorated name length exceeded, name was truncated" warning	
       
    23 #pragma warning (disable:4503)
       
    24 
       
    25 #include "MLCompDataParse.h"
       
    26 #include "MLCompCdl2InstO.h"
       
    27 #include "ZoomLevelNames.h"
       
    28 #include "LayoutCompilerErr.h"
       
    29 #include "LayoutParse.h"
       
    30 #include "CppWriter.h"
       
    31 #include "MLCompData2Cdl.h"
       
    32 #include "LayCdl2InstO.h" // for common classes
       
    33 #include "MLAttributesParse.h"
       
    34 #include "MLAttributes.h"
       
    35 #include "CodeGenConsts.h"
       
    36 #include "UsefulDefinitions.h"
       
    37 
       
    38 #include <akndef.hrh>
       
    39 
       
    40 #include <fstream>
       
    41 #include <algorithm>
       
    42 #include <iostream>
       
    43 #include <numeric> // accumulate
       
    44 
       
    45 using namespace std;
       
    46 using namespace CdlCompilerToolkit;
       
    47 
       
    48 //
       
    49 // defines
       
    50 //
       
    51 
       
    52 #define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte);
       
    53 #include "AknLayoutByteCodes.h"
       
    54 
       
    55 typedef LayoutProcessArgsErr<MLCompDataCdlInstanceOpt> MLCompDataCdlInstanceOptArgsErr;
       
    56 
       
    57 
       
    58 //
       
    59 // constants
       
    60 //
       
    61 
       
    62 const string KDefinitionNotDefined("Layout not defined, this API must not be called for this instance");
       
    63 const string KDefinitionNotSet("Layout definition not found");
       
    64 extern string KMultiLine;
       
    65 const string KSpace = " ";
       
    66 const string KComma = ",";
       
    67 const string KTheWordBlank("blank");
       
    68 const string KParentRelativeMarker("Pp");
       
    69 const string KCellNameJustification("J");
       
    70 const string KCompDataFileNameSuffix("compData");
       
    71 const string KAttributesFileNameSuffix("attributes");
       
    72 
       
    73 // this is the addressable area for each instance, as the lookup table is 16bit
       
    74 const int KAddressableBytecodedData = 0xFFFF;
       
    75 
       
    76 /**
       
    77 *  SCompDataImplFunc
       
    78 *  This class represents a layout data decompression function local to a layout instance.
       
    79 *  These functions will call the corresponding DLL wide function for decompression.
       
    80 */
       
    81 struct SCompDataImplFunc
       
    82 	{
       
    83 	enum TFuncType
       
    84 		{ 
       
    85 		EWindowLine, 
       
    86 		ETextLine,
       
    87 		ETableLimits,
       
    88 		EWindowTable, 
       
    89 		ETextTable,
       
    90 		ELineParamLimits,
       
    91 		ETableParamLimits,
       
    92 		EGenericComponentType,
       
    93 		EGenericParamLimits,
       
    94 		EGenericWindowComponent,
       
    95 		EGenericTextComponent
       
    96 		};
       
    97 	TFuncType iType;
       
    98 	CCdlTkApiParams iParams;
       
    99 	string iDefn;
       
   100 	string iPtrRef;
       
   101 
       
   102 	SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef, CCdlTkApiParams& aParams)
       
   103 		: 
       
   104 		iType(aType), 
       
   105 		iDefn(aDefn), 
       
   106 		iPtrRef(aPtrRef),
       
   107 		iParams(aParams)
       
   108 		{
       
   109 			
       
   110 		}
       
   111 
       
   112 	SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef)
       
   113 		: 
       
   114 		iType(aType), 
       
   115 		iDefn(aDefn), 
       
   116 		iPtrRef(aPtrRef)
       
   117 		{
       
   118 			
       
   119 		}
       
   120 
       
   121 	bool IsSimilar(TFuncType aType, CCdlTkApiParams& aParams)
       
   122 		{
       
   123 		if(iType != aType) 
       
   124 			return false;
       
   125 		int size = iParams.size();
       
   126 		if(size != aParams.size())
       
   127 			return false;
       
   128 		for(int ii = 0; ii < size; ii++)
       
   129 			{
       
   130 			CCdlTkApiParam& thisParam = iParams[ii];
       
   131 			CCdlTkApiParam& otherParam = aParams[ii];
       
   132 			if(thisParam.Name() != otherParam.Name())
       
   133 				return false;
       
   134 			if(thisParam.Type() != otherParam.Type())
       
   135 				return false;
       
   136 			// don't compare the default value, as we're not interested in that for the implementation.
       
   137 			}
       
   138 		return true;
       
   139 		}
       
   140 	};
       
   141 
       
   142 
       
   143 /**
       
   144 *  CAllCompDataFuncs
       
   145 *  This represents a collection of all the SCompDataImplFunc objects that a layout instance may need
       
   146 */
       
   147 class CAllCompDataFuncs : public vector<SCompDataImplFunc>
       
   148 	{
       
   149 public:
       
   150 	CAllCompDataFuncs();
       
   151 
       
   152 private:
       
   153 	void AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation);
       
   154 	void AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody);
       
   155 	void AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody);
       
   156 	};
       
   157 
       
   158 
       
   159 
       
   160 /**
       
   161 *  gTheFuncs
       
   162 *  This is a collection of all SCompDataImplFunc objects that a layout instance needs, initialised
       
   163 *  so that there are up to four integer parameters per API type.
       
   164 */
       
   165 CAllCompDataFuncs gTheFuncs;
       
   166 
       
   167 //
       
   168 // CAllCompDataFuncs
       
   169 //
       
   170 
       
   171 CAllCompDataFuncs::CAllCompDataFuncs()
       
   172 	{
       
   173 	// need to generate all combinations of parameters
       
   174 	vector<string> paramNames;
       
   175 	paramNames.push_back(KParamOptionIndex);
       
   176 	paramNames.push_back(KParamColIndex);
       
   177 	paramNames.push_back(KParamRowIndex);
       
   178 
       
   179 	// all cominations of option, row, and column are possible, in any order
       
   180 	typedef vector<int> Seq;
       
   181 	Seq pattern;
       
   182 	set< Seq > subPatterns;
       
   183 
       
   184 	// for each of the available positions, there could be any available value, or it could be empty
       
   185 	const int numPlaces = paramNames.size();
       
   186 	for(int jj = 0; jj < numPlaces; jj++)
       
   187 		pattern.push_back(jj);
       
   188 
       
   189 	// for each permutation, copy all the possible positions
       
   190 	// into a separate set, which hence will be filled with the unique permutations
       
   191 	do
       
   192 		{
       
   193 		int numMasks = (1 << numPlaces); // eg for 3 places there are 8 masks
       
   194 		for(int mask = 0; mask < numMasks; mask++)
       
   195 			{
       
   196 			Seq subPattern;
       
   197 			int bit = 0;
       
   198 			// count down the bits
       
   199 			for(int bitCount = mask; bitCount != 0; bitCount >>= 1)
       
   200 				{
       
   201 				if(mask & (1 << bit))
       
   202 					subPattern.push_back(pattern[bit]);
       
   203 				bit++;
       
   204 				}
       
   205 			subPatterns.insert(subPattern);
       
   206 			}
       
   207 		}
       
   208 	while(next_permutation(pattern.begin(), pattern.end()));
       
   209 
       
   210 	for(set< Seq >::iterator pPattern = subPatterns.begin(); pPattern != subPatterns.end(); ++pPattern)
       
   211 		{
       
   212 		CCdlTkApiParams params;
       
   213 		for(Seq::iterator pParam = pPattern->begin(); pParam != pPattern->end(); ++pParam)
       
   214 			{
       
   215 			int& param = (*pParam);
       
   216 			string name = paramNames[param];
       
   217 			params.push_back(CCdlTkApiParam(KTypeInt, name));
       
   218 			}
       
   219 		AddFunc(SCompDataImplFunc::EWindowLine, params, KTypeWindowComponentLayout, KFuncWindowLine, true);
       
   220 		AddFunc(SCompDataImplFunc::ETextLine, params, KTypeTextComponentLayout, KFuncTextLine, true);
       
   221 
       
   222 		params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex));
       
   223 		AddFunc(SCompDataImplFunc::EWindowTable, params, KTypeWindowComponentLayout, KFuncWindowTable, true);
       
   224 		AddFunc(SCompDataImplFunc::ETextTable, params, KTypeTextComponentLayout, KFuncTextTable, true);
       
   225 		}
       
   226 
       
   227 	for(int ii = 0; ii < 2; ii++)
       
   228 		{
       
   229 		CCdlTkApiParams params;
       
   230 		if(ii)
       
   231 			{
       
   232 			params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex));
       
   233 			}
       
   234 		AddFunc(SCompDataImplFunc::ELineParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimits, true);
       
   235 		params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex));
       
   236 		AddFunc(SCompDataImplFunc::ETableParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimitsTable, true);
       
   237 		}
       
   238 
       
   239 	SCompDataImplFunc limits(
       
   240 		SCompDataImplFunc::ETableLimits, 
       
   241 		KTypeLayoutScalableTableLimits + " Limits() { return AknLayoutScalableDecode::TableLimits(KDataLookup); }",
       
   242 		"&Limits");
       
   243 	push_back(limits);
       
   244 
       
   245 	// finally, the generic APIs
       
   246 	CCdlTkApiParams params;
       
   247 	params.push_back(CCdlTkApiParam(KTypeInt, KParamComponentId));
       
   248 	AddFunc(SCompDataImplFunc::EGenericComponentType, params, KTypeLayoutScalableComponentType, KFuncGetComponentTypeById, false);
       
   249 
       
   250 	// param limits needs the variety index
       
   251 	params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex));
       
   252 	AddFunc(SCompDataImplFunc::EGenericParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncGetParamLimitsById, false);
       
   253 
       
   254 	// and getting the component by id requires all the params
       
   255 	params.push_back(CCdlTkApiParam(KTypeInt, KParamColIndex));
       
   256 	params.push_back(CCdlTkApiParam(KTypeInt, KParamRowIndex));
       
   257 	AddFunc(SCompDataImplFunc::EGenericWindowComponent, params, KTypeWindowComponentLayout, KFuncGetWindowComponentById, false);
       
   258 	AddFunc(SCompDataImplFunc::EGenericTextComponent, params, KTypeTextComponentLayout, KFuncGetTextComponentById, false);
       
   259 	}
       
   260 
       
   261 void CAllCompDataFuncs::AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation)
       
   262 	{
       
   263 	// create a function of this form:
       
   264 	//TAknWindowComponentLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES)
       
   265 	//	{
       
   266 	//	return AknLayoutScalableDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES);
       
   267 	//  }
       
   268 	string funcName = aFuncName;
       
   269 	if(aAppendAbbreviation)
       
   270 		for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam)
       
   271 			funcName += pParam->Name().substr(1, 1); // append the first character after the "a"
       
   272 
       
   273 	string defn = aReturn + " " + funcName + "(";
       
   274 	string body = string(") { return AknLayoutScalableDecode::") + funcName + "(&KImplData";
       
   275 	AddParamsToFunc(aParams, defn, body);
       
   276 	defn += body + "); }";
       
   277 
       
   278 	string ptrRef = string("&") + funcName;
       
   279 
       
   280 	SCompDataImplFunc func(aType, defn, ptrRef, aParams);
       
   281 	push_back(func);
       
   282 	}
       
   283 
       
   284 void CAllCompDataFuncs::AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody)
       
   285 	{
       
   286 	string filler = "";
       
   287 	for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam)
       
   288 		{
       
   289 		AddParamToFunc(filler, pParam->Name(), aDefn, aBody);
       
   290 		filler = KComma + KSpace;
       
   291 		}
       
   292 	}
       
   293 
       
   294 void CAllCompDataFuncs::AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody)
       
   295 	{
       
   296 	aDefn += aFiller + string(KTypeInt) + KSpace + aParamName;
       
   297 	aBody += KComma + KSpace + aParamName;
       
   298 	}
       
   299 
       
   300 
       
   301 //
       
   302 // CMLCompDataInstOptImpl
       
   303 //
       
   304 
       
   305 class CMLCompDataInstOptImpl
       
   306 	{
       
   307 public:
       
   308 	CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl);
       
   309 	virtual ~CMLCompDataInstOptImpl();
       
   310 public:
       
   311 	CCdlTkImplementation* iImpl;
       
   312 	int iByteCodeIndex;
       
   313 	string iComment;
       
   314 	string iName;
       
   315 	vector<char> iBytes;
       
   316 	bool iIsRedirectedToExactCopy;
       
   317 	};
       
   318 
       
   319 CMLCompDataInstOptImpl::CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl)
       
   320 	:
       
   321 	iImpl(aImpl),
       
   322 	iIsRedirectedToExactCopy(false)
       
   323 	{
       
   324 	}
       
   325 
       
   326 CMLCompDataInstOptImpl::~CMLCompDataInstOptImpl()
       
   327 	{
       
   328 	}
       
   329 
       
   330 //
       
   331 // CMLCompDataLineInstOptImpl
       
   332 //
       
   333 
       
   334 class CMLCompDataLineInstOptImpl : public CMLCompDataInstOptImpl
       
   335 	{
       
   336 public:
       
   337 	CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl);
       
   338 	virtual ~CMLCompDataLineInstOptImpl();
       
   339 public:
       
   340 	TMLCompDataLine* iLine;
       
   341 	};
       
   342 
       
   343 CMLCompDataLineInstOptImpl::CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl)
       
   344 	: 
       
   345 	CMLCompDataInstOptImpl(aImpl),
       
   346 	iLine(aLine)
       
   347 	{
       
   348 	}
       
   349 
       
   350 CMLCompDataLineInstOptImpl::~CMLCompDataLineInstOptImpl()
       
   351 	{
       
   352 	}
       
   353 
       
   354 
       
   355 //
       
   356 // CMLCompDataSubTableInstOptImpl
       
   357 //
       
   358 
       
   359 class CMLCompDataSubTableInstOptImpl : public CMLCompDataInstOptImpl
       
   360 	{
       
   361 public:
       
   362 	CMLCompDataSubTableInstOptImpl(
       
   363 		TMLCompDataTable* aTable,
       
   364 		TMLCompDataTable::TMLCompDataSubTable* aSubTable, 
       
   365 		CCdlTkImplementation* aImpl);
       
   366 	virtual ~CMLCompDataSubTableInstOptImpl();
       
   367 public:
       
   368 	TMLCompDataTable* iTable;
       
   369 	TMLCompDataTable::TMLCompDataSubTable* iSubTable;
       
   370 	};
       
   371 
       
   372 CMLCompDataSubTableInstOptImpl::CMLCompDataSubTableInstOptImpl(
       
   373 	TMLCompDataTable* aTable,
       
   374 	TMLCompDataTable::TMLCompDataSubTable* aSubTable, 
       
   375 	CCdlTkImplementation* aImpl)
       
   376 	:
       
   377 	iTable(aTable),
       
   378 	CMLCompDataInstOptImpl(aImpl),
       
   379 	iSubTable(aSubTable)
       
   380 	{
       
   381 	}
       
   382 
       
   383 CMLCompDataSubTableInstOptImpl::~CMLCompDataSubTableInstOptImpl()
       
   384 	{
       
   385 	}
       
   386 
       
   387 
       
   388 //
       
   389 // CMLCompDataInstOpt
       
   390 //
       
   391 
       
   392 class CMLCompDataInstOpt
       
   393 	{
       
   394 public:
       
   395 	CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance);
       
   396 	~CMLCompDataInstOpt();
       
   397 
       
   398 	void Process(const string& aFirstInstanceName);
       
   399 	void WriteInstance();
       
   400 
       
   401 	CCdlTkInstance& Inst() const { return *iInstance; }
       
   402 	string Name() const { return iName; }
       
   403 	string ZoomName() const { return iZoomName; }
       
   404 
       
   405 private:
       
   406 	typedef vector<int> ParamLimitVarieties;
       
   407 	typedef vector<ParamLimitVarieties> ParamLimits;
       
   408 	typedef map<int, int> IndexMap;
       
   409 
       
   410 private:
       
   411 	void ProcessLines(TMLCompDataTable& aTable);
       
   412 	void ProcessTables(TMLCompDataTable& aTable);
       
   413 	void ProcessLine(TMLCompDataLine& aLine);
       
   414 	void ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl);
       
   415 	void UpdateBaseOffset();
       
   416 	void UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta);
       
   417 	void UpdateLineImpls();
       
   418 	void UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl);
       
   419 	void UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl);
       
   420 
       
   421 	void SetNewLineData(CMLCompDataLineInstOptImpl& aImpl);
       
   422 	void SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties);
       
   423 	void OptimizeNewLineData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, vector<char>& aTempBytes, const vector<string>& aOutputOrder, bool aMirrored, int aTotalMax, int aNumVarieties);
       
   424 	void OptimizeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, TMLCompDataValues& aValues, unsigned int& aNextCell, int aTotalParams, int aNumVarieties, ParamLimitVarieties& aParamLimitVarieties, string cellName, bool aMirrorJustification);
       
   425 	void EncodeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, vector<string>& aValuesToEncode, unsigned int& aNextCell, int aTotalMax, bool aOptimizeVarieties, bool aOptimizeCalcs);
       
   426 
       
   427 	bool HasApi(const string& aName);
       
   428 	CCdlTkImplementation& FindImp(const string& aName);
       
   429 	CMLCompDataInstOptImpl* FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl);
       
   430 	string DefinitionString(int aByteCodeIndex, const string& aApiName);
       
   431 	bool CheckByteCodeIndexInRange(int aByteCodeIndex);
       
   432 
       
   433 	void SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType);
       
   434 	void SetLineFunc(CMLCompDataLineInstOptImpl& aImpl);
       
   435 	void SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl);
       
   436 	void SetParamLimits(CMLCompDataLineInstOptImpl& aImpl);
       
   437 
       
   438 	void ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow);
       
   439 	void CountApiParams(CCdlTkImplementation& aApi, int& aParams);
       
   440 	SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType);
       
   441 	SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams);
       
   442 
       
   443 	void SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName);
       
   444 	void SetExtraCpp(const string& aFirstInstanceName);
       
   445 	void OutputStats();
       
   446 
       
   447 	void AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int aTableNum);
       
   448 	void UpdateTables(TMLCompDataTable& aTable);
       
   449 	void AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions);
       
   450 	void UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex);
       
   451 	void AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable);
       
   452 	void AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl);
       
   453 	void AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub);
       
   454 	void AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions);
       
   455 	void UpdateParamLimits(const string& apiName);
       
   456 	void SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl);
       
   457 	void UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl);
       
   458 	void EncodeValue(vector<char>& aBytes, string aValue);
       
   459 	void EncodeValue(vector<char>& aBytes, int aValue);
       
   460 	void EncodeParentRelativeValue(vector<char>& aBytes, int aValue);
       
   461 	void MirrorParamName(string& aParamName);
       
   462 
       
   463 private:
       
   464 	MLCompDataCdlInstanceOpt& iInstances;
       
   465 	TMLCompData* iLayout;
       
   466 	string iName;
       
   467 	string iZoomName;
       
   468 	CCdlTkInterface& iInterface;
       
   469 	CCdlTkInstance* iInstance; // not owned
       
   470 	CMLCompDataInstOptImpls iImpls;
       
   471 	CMLCompDataInstOptImpls iTableImpls;
       
   472 	typedef vector<SCompDataImplFunc*> CImplFuncs;
       
   473 	CImplFuncs iFuncs;
       
   474 	int iZoomLevel;
       
   475 	bool iAllParams;
       
   476 	int iBaseOffset; // offset from the start of the main data table to the start of this instance's data
       
   477 	};
       
   478 
       
   479 CMLCompDataInstOpt::CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance)
       
   480 	: 
       
   481 	iInstances(aInstances), 
       
   482 	iLayout(aLayout),
       
   483 	iName(aInstName), 
       
   484 	iZoomName(aZoomName), 
       
   485 	iZoomLevel(aZoomLevel),
       
   486 	iInterface(iInstances.Interface()),
       
   487 	iAllParams(aAllParams),
       
   488 	iBaseOffset(0)
       
   489 	{
       
   490 	string zoomInstName = aInstName;
       
   491 	if(aZoomName.length() > 0)
       
   492 		zoomInstName += "_" + aZoomName;
       
   493 
       
   494 	iInstance = new CCdlTkInstance(iInterface);
       
   495 	iInstance->SetName(zoomInstName);
       
   496 
       
   497 	CCdlTkImplementations& impl = iInstance->Impl();
       
   498 	for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl)
       
   499 		{
       
   500 		const CCdlTkInterface& iface = (*pImpl)->Instance().Interface();
       
   501 		const CCdlTkApi& api = (*pImpl)->Api();
       
   502 		if(aLayout->iIsBaseInstance)
       
   503 			{
       
   504 			// for a base instance, need to set a default implementation
       
   505 			// even for missing data
       
   506 			(*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined);
       
   507 			
       
   508 			// preliminary implementation of "blank" implementation. cdl engine searches to ensure that
       
   509 			// all implementations are not NULL. So this will satisfy that test. However, if any of the 
       
   510 			// methods are called, there will be an access violation, which will cause a panic
       
   511 			// this will be a successful guide to implementers not to call the API when the wrong layout
       
   512 			// pack is installed.
       
   513 			string definition = "(" + iface.NamespaceName() + "::" + api.PointerType() + ")((void*)4), // LAYOUT NOT DEFINED FOR THIS INSTANCE";
       
   514 			(*pImpl)->SetPointerReference(definition); 
       
   515 			}
       
   516         else if(aNonCompleteInstance)
       
   517             {
       
   518 			// for a base instance, need to set a default implementation
       
   519 			// even for missing data
       
   520 			(*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined);
       
   521 
       
   522             // but we need the pointer to be null so that CdlEngine falls through the layer below
       
   523 			string definition =  "0, // " + iface.NamespaceName() + "::" + api.PointerType();
       
   524 			(*pImpl)->SetPointerReference(definition); 
       
   525             }
       
   526         else
       
   527 			{
       
   528 			// Initially set definition that will not compile in the resulting code.
       
   529 			// This will alert the programmer to missing layout data.
       
   530 			(*pImpl)->SetDefinition(KDefinitionNotSet);
       
   531 			}
       
   532 		}
       
   533 	}
       
   534 
       
   535 CMLCompDataInstOpt::~CMLCompDataInstOpt()
       
   536 	{
       
   537 	delete iInstance;
       
   538 	for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
       
   539 		delete *pImpl;
       
   540 	for (pImpl = iTableImpls.begin(); pImpl != iTableImpls.end(); ++pImpl)
       
   541 		delete *pImpl;
       
   542 	}
       
   543 
       
   544 void CMLCompDataInstOpt::Process(const string& aFirstInstName)
       
   545 	{
       
   546 	iLayout->Compile();
       
   547 
       
   548 	for (TMLCompData::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
       
   549 		{
       
   550 		ProcessLines(**pTab);
       
   551 		}
       
   552 
       
   553 	for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
       
   554 		{
       
   555 		ProcessTables(**pTab);
       
   556 		}
       
   557 
       
   558 	// update the base offset to include all the data added, including reserving space for the tables
       
   559 	UpdateBaseOffset();
       
   560 
       
   561 	// with the correct base offset, the definitions can be updated
       
   562 	UpdateLineImpls();
       
   563 
       
   564 	for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
       
   565 		{
       
   566 		// now that the rest of the data is stable, we can add the tables at the end
       
   567 		UpdateTables(**pTab);
       
   568 		}
       
   569 
       
   570 	SetGenericAPI(SCompDataImplFunc::EGenericComponentType, KFuncGetComponentTypeById);
       
   571 	SetGenericAPI(SCompDataImplFunc::EGenericParamLimits, KFuncGetParamLimitsById);
       
   572 	SetGenericAPI(SCompDataImplFunc::EGenericWindowComponent, KFuncGetWindowComponentById);
       
   573 	SetGenericAPI(SCompDataImplFunc::EGenericTextComponent, KFuncGetTextComponentById);
       
   574 	
       
   575 	SetExtraCpp(aFirstInstName);
       
   576 	OutputStats();
       
   577 	}
       
   578 
       
   579 void CMLCompDataInstOpt::WriteInstance()
       
   580 	{
       
   581 	CCdlTkWriteInstance writer(*iInstance);
       
   582 	writer.Process();
       
   583 	}
       
   584 
       
   585 void CMLCompDataInstOpt::ProcessLines(TMLCompDataTable& aTable)
       
   586 	{
       
   587 	for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
       
   588 		{
       
   589 		ProcessLine(**pLine);
       
   590 		}
       
   591 	}
       
   592 
       
   593 void CMLCompDataInstOpt::ProcessTables(TMLCompDataTable& aTable)
       
   594 	{
       
   595 	int line = 0;
       
   596 	for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
       
   597 		{
       
   598 		for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
       
   599 			{
       
   600 			TMLCompDataTable::TMLCompDataSubTable& sub = **pSub;
       
   601 			int last = *(sub.rbegin());
       
   602 			if(line == last)
       
   603 				AddTableToInstance(aTable, sub, 0);
       
   604 			}
       
   605 		line++;
       
   606 		}
       
   607 	}
       
   608 
       
   609 void CMLCompDataInstOpt::ProcessLine(TMLCompDataLine& aLine)
       
   610 	{
       
   611 	string apiName = MLCompDataToCdl::LineApiName(aLine);
       
   612 	if (!HasApi(apiName))
       
   613 		return;
       
   614 
       
   615 	ProcessLineApi(aLine, FindImp(apiName));
       
   616 	}
       
   617 
       
   618 void CMLCompDataInstOpt::ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl)
       
   619 	{
       
   620 	string lineName = MLCompDataToCdl::LineApiName(aLine);
       
   621 
       
   622 	CMLCompDataLineInstOptImpl* newImpl = new CMLCompDataLineInstOptImpl(&aLine, &aImpl);
       
   623 	iImpls.push_back(newImpl);
       
   624 
       
   625 	// always set the new line data
       
   626 	SetNewLineData(*newImpl);
       
   627 
       
   628 	// if we can find the new line data in the aggregated data, point to that instead
       
   629 	int foundIndex = iInstances.FindSimilarBytes(newImpl, iBaseOffset);
       
   630 	if(foundIndex >= 0)
       
   631 		{
       
   632 		newImpl->iByteCodeIndex = foundIndex;
       
   633 		newImpl->iIsRedirectedToExactCopy = true;
       
   634 		}
       
   635 	else
       
   636 		{
       
   637 		iInstances.AddImpl(newImpl);
       
   638 		}
       
   639 
       
   640 	SetLineFunc(*newImpl);
       
   641 
       
   642 	// only add parameter limits if the line is not simple
       
   643 	// and we must add the param limits after the actual impl, so that we can find it!
       
   644 	bool needsParamLimits = aLine.NeedsOptions() || aLine.NeedsCols() || aLine.NeedsRows();
       
   645 	if(needsParamLimits)
       
   646 		{
       
   647 		AddParamLimits(aLine, aLine.NeedsOptions());
       
   648 		}
       
   649 	}
       
   650 
       
   651 void CMLCompDataInstOpt::UpdateBaseOffset()
       
   652 	{
       
   653 	// have to account for this instance's tables
       
   654 	int tablesSize(0);
       
   655 	for(CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl)
       
   656 		{
       
   657 		CMLCompDataInstOptImpl* impl = *pTableImpl;
       
   658 		tablesSize += impl->iBytes.size();
       
   659 		}
       
   660 
       
   661 	int origByteStreamSize = iInstances.ByteStreamSize() + tablesSize;
       
   662 
       
   663 	// repeat until base offset stabilizes
       
   664 	iBaseOffset = max(0, origByteStreamSize - KAddressableBytecodedData);
       
   665 	int newBaseOffset = iBaseOffset;
       
   666 	int byteCodeSizeDelta(0);
       
   667 	do
       
   668 		{
       
   669 		iBaseOffset = newBaseOffset;
       
   670 		for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
       
   671 			UpdateLine(**pImpl, byteCodeSizeDelta);
       
   672 		newBaseOffset = max(0, origByteStreamSize + byteCodeSizeDelta - KAddressableBytecodedData);
       
   673 		}
       
   674 	while(iBaseOffset != newBaseOffset);
       
   675 	}
       
   676 
       
   677 void CMLCompDataInstOpt::UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta)
       
   678 	{
       
   679 	if(aImpl.iIsRedirectedToExactCopy && aImpl.iByteCodeIndex < iBaseOffset)
       
   680 		{
       
   681 		// when we encoded the impls, we found a match in an area which now
       
   682 		// turns out to be before the base offset (i.e. outside the addressable range).
       
   683 
       
   684 		// first of all check in case we've already made another copy close by
       
   685 		int foundIndex = iInstances.FindSimilarBytes(&aImpl, iBaseOffset);
       
   686 		if(foundIndex >= 0)
       
   687 			{
       
   688 			aImpl.iByteCodeIndex = foundIndex;
       
   689 			}
       
   690 		else
       
   691 			{
       
   692 			// add its bytecodes to the end
       
   693 			aImpl.iIsRedirectedToExactCopy = false;
       
   694 			iInstances.AddImpl(&aImpl);
       
   695 			aByteCodeSizeDelta += aImpl.iBytes.size();
       
   696 			}
       
   697 		}
       
   698 	}
       
   699 
       
   700 
       
   701 void CMLCompDataInstOpt::UpdateLineImpls()
       
   702 	{
       
   703 	for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
       
   704 		UpdateLineImplDefn(**pImpl);
       
   705 	}
       
   706 
       
   707 void CMLCompDataInstOpt::UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl)
       
   708 	{
       
   709 	if(!CheckByteCodeIndexInRange(aImpl.iByteCodeIndex))
       
   710 		throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName());
       
   711 	// the base offset has been updated, so all definitions must be refreshed
       
   712 	int adjustedIndex = aImpl.iByteCodeIndex - iBaseOffset;
       
   713 	aImpl.iImpl->SetDefinition(DefinitionString(aImpl.iByteCodeIndex, aImpl.iName));
       
   714 	UpdateParamLimits(aImpl.iName); 
       
   715 	}
       
   716 
       
   717 void CMLCompDataInstOpt::UpdateTables(TMLCompDataTable& aTable)
       
   718 	{
       
   719 	// regenerate the byte code indices, in case they have changed
       
   720 	int line = 0;
       
   721 	for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
       
   722 		{
       
   723 		for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
       
   724 			{
       
   725 			TMLCompDataTable::TMLCompDataSubTable& sub = **pSub;
       
   726 			int last = *(sub.rbegin());
       
   727 			if(line == last)
       
   728 				{
       
   729 				string tableName = MLCompDataToCdl::SubTableApiName(sub);
       
   730 				CMLCompDataInstOptImpl* impl = FindSimilarImpl(iTableImpls, FindImp(tableName));
       
   731 				UpdateTableInstance(aTable, sub, impl);
       
   732 				}
       
   733 			}
       
   734 		line++;
       
   735 		}
       
   736 	}
       
   737 
       
   738 void CMLCompDataInstOpt::SetNewLineData(CMLCompDataLineInstOptImpl& aImpl)
       
   739 	{
       
   740 	aImpl.iBytes.clear();	
       
   741 
       
   742 	TMLCompDataLine& line = *aImpl.iLine;
       
   743 	aImpl.iComment = string("for line: ");
       
   744 	aImpl.iName = MLCompDataToCdl::LineApiName(line);
       
   745 
       
   746 	// handle mirroring order
       
   747 	bool mirrored = false;
       
   748 	if(line.iParentTable) // we know top table can't be mirrored
       
   749 		mirrored = line.iParentTable->iTables->iCanBeMirror;
       
   750 	const string* outputOrder =  mirrored ? 
       
   751 		KCompDataGraphicOutputOrderMirrored : KCompDataGraphicOutputOrder;
       
   752 	int outputSize = KCompDataGraphicOutputOrderSize;
       
   753 	if (line.iType == TMLCompDataLine::ETextComponent)
       
   754 		{
       
   755 		outputOrder = mirrored ? 
       
   756 			KCompDataTextOutputOrderMirrored : KCompDataTextOutputOrder;
       
   757 		outputSize = KCompDataTextOutputOrderSize;
       
   758 		}
       
   759 	vector<string> cellOrder(outputOrder, outputOrder + outputSize);
       
   760 
       
   761 	// we are currently storing variety as max allowed value, but it's a zero based index
       
   762 	int numVarieties = line.MaxVariety() + 1;
       
   763 
       
   764 	// we will be storing all of the rows and cols, even if the rows and cols limits are lower
       
   765 	int totalMaxCols = numVarieties * line.NumCols();
       
   766 	int totalMaxRows = numVarieties * line.NumRows();
       
   767     int totalMax = totalMaxCols > totalMaxRows ? totalMaxCols : totalMaxRows;
       
   768 
       
   769 	// initialize the temporary bytestream, and the index map
       
   770 	vector<char> tempBytes;
       
   771 	IndexMap indexMap;
       
   772 
       
   773 	// fill in the temp byte stream and the index map for each cell
       
   774 	OptimizeNewLineData(aImpl, indexMap, tempBytes, cellOrder, mirrored, totalMax, numVarieties);
       
   775 
       
   776 	// encode the index map
       
   777 	SetNewLineParamData(aImpl, indexMap, totalMax, numVarieties);
       
   778 
       
   779 	// finally copy the temp byte stream onto the end of the real encoded byte stream
       
   780 	copy(tempBytes.begin(), tempBytes.end(), back_inserter(aImpl.iBytes));
       
   781 	}
       
   782 
       
   783 void CMLCompDataInstOpt::SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties)
       
   784 	{
       
   785 	// only set parameter data if the line is not simple
       
   786 	TMLCompDataLine& line = *aImpl.iLine;
       
   787 	
       
   788 	bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows();
       
   789 
       
   790 	int typeBitfield = line.iType << 1;
       
   791 	if(needsHeader)
       
   792 		{
       
   793 		typeBitfield |= 1;
       
   794 		}
       
   795 	
       
   796 	aImpl.iBytes.push_back(typeBitfield);
       
   797 
       
   798 	if(needsHeader)
       
   799 		{
       
   800 		// we can just dump the number of varieties, this will be used by the limits API
       
   801 		// and we can also them to calculate value indices within a cell when decoding
       
   802 		aImpl.iBytes.push_back(aNumVarieties);
       
   803 		}
       
   804 
       
   805 	//  count the number of cells that are complex
       
   806 	char numMultiValues = aIndexMap.size();
       
   807 	if(needsHeader)
       
   808 		{
       
   809 		aImpl.iBytes.push_back(numMultiValues);
       
   810 		}
       
   811 	else
       
   812 		{
       
   813 		// we didn't think we needed a header, so there should be no complex cells!
       
   814 		if (numMultiValues > 0)
       
   815 			throw GeneralErr("complex cells detected in simple line");
       
   816 		}
       
   817 
       
   818 	// for each complex cell, encode the bitfield and the count
       
   819 	for(IndexMap::iterator pIndex = aIndexMap.begin(); pIndex != aIndexMap.end(); ++pIndex)
       
   820 		{
       
   821 		int count = pIndex->first;
       
   822 		int index = pIndex->second;
       
   823 		EncodeValue(aImpl.iBytes, index);
       
   824 		EncodeValue(aImpl.iBytes, count);
       
   825 		}
       
   826 	}
       
   827 
       
   828 void CMLCompDataInstOpt::OptimizeNewLineData(
       
   829 	CMLCompDataLineInstOptImpl& aImpl, 
       
   830 	IndexMap& aIndexMap, 
       
   831 	vector<char>& aTempBytes,
       
   832 	const vector<string>& aOutputOrder,
       
   833 	bool aMirrored,
       
   834 	int aTotalMax, 
       
   835 	int aNumVarieties)
       
   836 	{
       
   837 	vector<ParamLimitVarieties> paramLimits;
       
   838 	TMLCompDataLine& line = *aImpl.iLine;
       
   839 
       
   840 	// start by extracting the row and column data. 
       
   841 	// we can optimize the stored format along with the rest of the data
       
   842 	// so no need to optimize it yet
       
   843 	for(int cell = 0; cell < 2; cell++)
       
   844 		{
       
   845 		string cellName = aOutputOrder[cell];
       
   846 		ParamLimitVarieties nextLimits;
       
   847 		TMLCompDataValues& values = line[cellName];
       
   848 		for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++)
       
   849 			{
       
   850 			TMLCompDataZoomLevels& zoomLevels = values[varietyIndex];
       
   851 			TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]);
       
   852 			if(!calcs->size())
       
   853 				calcs = &(zoomLevels[EAknUiZoomNormal]);
       
   854 			int value = CdlTkUtil::ParseInt((*calcs)[0]);
       
   855 			nextLimits.push_back(value);
       
   856 			}
       
   857 		paramLimits.push_back(nextLimits);
       
   858 		}
       
   859 
       
   860 	// calculate the number of values
       
   861 	bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows();
       
   862 	unsigned int nextCellFlag = 1;	// bit flag for the next cell, note it can get bigger than a char
       
   863 	for (cell = 0; cell < aOutputOrder.size(); cell++)
       
   864 		{
       
   865 		string cellName = aOutputOrder[cell];
       
   866 		TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName);
       
   867 		if(!needsHeader && type == TMLCompDataValues::ECellTypeParamLimit)
       
   868 			{
       
   869 			// if we don't need header, then don't output the param limits values
       
   870 			// although we'll still use them internally
       
   871 			continue;
       
   872 			}
       
   873 
       
   874 		int paramLimitsIndex = TMLCompDataValues::Type(cellName) == TMLCompDataValues::ECellTypeCol ? 0 : 1; // if it's not a row or col, it doesn't matter what param limits are used.
       
   875 		TMLCompDataValues& values = line[cellName];
       
   876 		int numValues = 0;
       
   877 		if(type == TMLCompDataValues::ECellTypeCol || type == TMLCompDataValues::ECellTypeRow)
       
   878 			{
       
   879 			ParamLimitVarieties& nextLimits = paramLimits[paramLimitsIndex];
       
   880 			numValues = std::accumulate(nextLimits.begin(), nextLimits.end(), 0);
       
   881 			}
       
   882 		else
       
   883 			{
       
   884 			numValues = aNumVarieties;
       
   885 			}
       
   886 
       
   887 		bool mirrorJustification = (aMirrored && cellName == KCellNameJustification);
       
   888 		OptimizeNewLineCellData(aIndexMap, aTempBytes, values, nextCellFlag, numValues, aNumVarieties, paramLimits[paramLimitsIndex], cellName, mirrorJustification);
       
   889 		}
       
   890 	}
       
   891 
       
   892 void CMLCompDataInstOpt::OptimizeNewLineCellData(
       
   893 	IndexMap& aIndexMap, 
       
   894 	vector<char>& aTempBytes, 
       
   895 	TMLCompDataValues& aValues, 
       
   896 	unsigned int& aNextCell, 
       
   897 	int aTotalParams,
       
   898 	int aNumVarieties, 
       
   899 	CMLCompDataInstOpt::ParamLimitVarieties& aParamLimitVarieties, 
       
   900 	string cellName,
       
   901 	bool aMirrorJustification)
       
   902 	{
       
   903 	// build up the values for each variety 
       
   904 	// if the valid values for each variety are the same, then we can store them once only
       
   905 	// in which case there will be as many values as the variety with the largest number of values
       
   906 	vector<string> optimizedValues; 
       
   907 
       
   908 	// also build up the found valid values in case we can't optimize
       
   909 	vector<string> foundValues; 
       
   910 
       
   911 	bool optimizeVarieties = true;
       
   912 	bool optimizeCalcs = true;
       
   913 	int numCalcs = 0;
       
   914 	int* largestParamLimitPtr = max_element(aParamLimitVarieties.begin(), aParamLimitVarieties.end());
       
   915 	int largestParamLimit = largestParamLimitPtr != aParamLimitVarieties.end() ? *largestParamLimitPtr : 0;
       
   916 	
       
   917 	// in the case of there being no calcs at all, we don't want to be optimizing,
       
   918 	// in order to avoid wasted flags.
       
   919 	if(largestParamLimit == 1)
       
   920 		optimizeCalcs = false;
       
   921 
       
   922 	TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName);
       
   923 	bool isColRow = (type == TMLCompDataValues::ECellTypeCol ||	type == TMLCompDataValues::ECellTypeRow);
       
   924 
       
   925 	// only go up to the max variety, as any data past that may be from a spurious merged instance
       
   926 	for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++)
       
   927 		{
       
   928 		TMLCompDataZoomLevels& zoomLevels = aValues[varietyIndex];
       
   929 		TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]);
       
   930 		if(!calcs->size())
       
   931 			calcs = &(zoomLevels[EAknUiZoomNormal]);
       
   932 		numCalcs = calcs->size();
       
   933 		string value;
       
   934 		vector<string> foundCalcs; 
       
   935 		int paramLimit = aParamLimitVarieties[varietyIndex];
       
   936 		if(numCalcs == 0)
       
   937 			{
       
   938 			if(varietyIndex == 0)
       
   939 				optimizedValues.push_back(value);
       
   940 			if(varietyIndex > 0 && !(optimizedValues[0].empty()))
       
   941 				optimizeVarieties = false;
       
   942 			foundCalcs.push_back(value);
       
   943 			}
       
   944 		else
       
   945 			{
       
   946 			for(int index = 0; index < numCalcs; index++)
       
   947 				{
       
   948 				bool needToCheckIndexValidity = !isColRow || (index < paramLimit);
       
   949 				value = (*calcs)[index];
       
   950 				value = aMirrorJustification ? TMLCompDataValues::MirrorJustificationValue(value) : value;
       
   951 
       
   952 				if(index >= optimizedValues.size() && index < largestParamLimit) // index is zero based, size is quantity
       
   953 					{
       
   954 					// store the first valid value for a given index that we find.
       
   955 					// note that this will pick up additional values in subsequent varieties
       
   956 					optimizedValues.push_back(value);
       
   957 					}
       
   958 				else if(needToCheckIndexValidity && value != optimizedValues[index]) 
       
   959 					{
       
   960 					// so if it doesn't match, we can't optimize
       
   961 					optimizeVarieties = false;
       
   962 					}
       
   963 
       
   964 				// collect the valid found values as we go, in case we aren't able to optimize
       
   965 				if(needToCheckIndexValidity)
       
   966 					{
       
   967 					foundCalcs.push_back(value);
       
   968 					}
       
   969 				}
       
   970 			}
       
   971 		if(isColRow)
       
   972 			{
       
   973 			int found = foundCalcs.size();
       
   974 			if(!found)
       
   975 				{
       
   976 				foundCalcs.push_back(string());
       
   977 				found++;
       
   978 				}
       
   979 			if(found > 1)
       
   980 				{
       
   981 				optimizeCalcs = false;
       
   982 				}
       
   983 			}
       
   984 		else
       
   985 			{
       
   986 			optimizeCalcs = false;
       
   987 			}
       
   988 		copy(foundCalcs.begin(), foundCalcs.end(), back_inserter(foundValues));
       
   989 		}
       
   990 
       
   991 	if(optimizeVarieties && isColRow)
       
   992 		{
       
   993 		// now that we know the optimized values, fill missing values by repeating the last one.
       
   994 		// but if we're optimizing the calcs, then we don't want to expand them after all
       
   995 		if(!optimizeCalcs)
       
   996 			{
       
   997 			int optimal = optimizedValues.size();
       
   998 			string value = optimal > 0 ? optimizedValues[optimal-1] : string();
       
   999 			for(; optimal < largestParamLimit; optimal++)
       
  1000 				{
       
  1001 				optimizedValues.push_back(value);
       
  1002 				}
       
  1003 			}
       
  1004 		}
       
  1005 
       
  1006 	if(optimizeVarieties && aNumVarieties == 1)
       
  1007 		{
       
  1008 		optimizeVarieties = false;
       
  1009 		}
       
  1010 
       
  1011 	vector<string>& valuesToEncode = optimizeVarieties ? optimizedValues : foundValues;
       
  1012 	EncodeNewLineCellData(aIndexMap, aTempBytes, valuesToEncode, aNextCell, aTotalParams, optimizeVarieties, optimizeCalcs);
       
  1013 	}
       
  1014 
       
  1015 void CMLCompDataInstOpt::EncodeNewLineCellData(
       
  1016 	IndexMap& aIndexMap, 
       
  1017 	vector<char>& aTempBytes, 
       
  1018 	vector<string>& aValuesToEncode, 
       
  1019 	unsigned int& aNextCell,
       
  1020 	int aTotalMax,
       
  1021 	bool aOptimizeVarieties,
       
  1022 	bool aOptimizeCalcs)
       
  1023 	{
       
  1024 	// encode the actual data into the temporary bytestream
       
  1025 	int numOptimizedVals = aValuesToEncode.size();
       
  1026 	if(numOptimizedVals > 0)
       
  1027 		{
       
  1028 		for(vector<string>::iterator pString = aValuesToEncode.begin(); pString != aValuesToEncode.end(); ++pString)
       
  1029 			{
       
  1030 			EncodeValue(aTempBytes, *pString);
       
  1031 			}
       
  1032 		}
       
  1033 	else
       
  1034 		{
       
  1035 		EncodeValue(aTempBytes, "");
       
  1036 		}
       
  1037 
       
  1038 	if(numOptimizedVals > aTotalMax)
       
  1039 		throw GeneralErr("bad index in indexMap");
       
  1040 	
       
  1041 	// if there is only one value stored, we can make a further optimization
       
  1042 	// as we know that all values must be the same, however they are stored
       
  1043 	// so in that case, don't store an index map entry
       
  1044 	if(numOptimizedVals > 1)
       
  1045 		{
       
  1046 		// update the index map, 
       
  1047 		// put the flags at the right hand side, to avoid it becoming multi-byte in general
       
  1048 		int optimizeVarietiesMask = (aOptimizeVarieties ? 1 : 0);
       
  1049 		int optimizeCalcsMask = (aOptimizeCalcs ? 1 : 0) << 1;
       
  1050 		int numValsMask = (numOptimizedVals) << 2;
       
  1051 		int indexField = (numValsMask | optimizeCalcsMask | optimizeVarietiesMask);
       
  1052 		aIndexMap[indexField] |= aNextCell;
       
  1053 		}
       
  1054 	aNextCell = aNextCell << 1;
       
  1055 	}
       
  1056 
       
  1057 void CMLCompDataInstOpt::CountApiParams(CCdlTkImplementation& aApi, int& aParams)
       
  1058 	{
       
  1059 	aParams = 0;
       
  1060 	const CCdlTkApiParams& params = aApi.Api().AsFunc().Params();
       
  1061 	for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam)
       
  1062 		{
       
  1063 		if (pParam->Type() == KTypeInt) // is it a cell index parameter
       
  1064 			aParams++;
       
  1065 		}
       
  1066 	}
       
  1067 
       
  1068 void CMLCompDataInstOpt::ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow)
       
  1069 	{
       
  1070 	// check that data matches api
       
  1071 	bool matches = true;
       
  1072 	matches &= ((aOption) == (aParams.FindByName(KParamOptionIndex) != aParams.end()));
       
  1073 	matches &= ((aColumn) == (aParams.FindByName(KParamColIndex) != aParams.end()));
       
  1074 	matches &= ((aRow) == (aParams.FindByName(KParamRowIndex) != aParams.end()));
       
  1075 	if(!matches)
       
  1076 		throw CdlTkAssert(string("layout data does not match CDL API : ") + aApiName);
       
  1077 	}
       
  1078 
       
  1079 void CMLCompDataInstOpt::SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType)
       
  1080 	{
       
  1081 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
       
  1082 	CCdlTkApiParams& params = api.Params();
       
  1083 
       
  1084 	SCompDataImplFunc& func = AddImplFunc(aType, params);
       
  1085 	aImpl.iImpl->SetPointerReference(func.iPtrRef);
       
  1086 	}
       
  1087 
       
  1088 void CMLCompDataInstOpt::SetLineFunc(CMLCompDataLineInstOptImpl& aImpl)
       
  1089 	{
       
  1090 	SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowLine;
       
  1091 	if (aImpl.iLine->iType == TMLCompDataLine::ETextComponent)
       
  1092 		{
       
  1093 		type = SCompDataImplFunc::ETextLine;
       
  1094 		}
       
  1095 	string name = aImpl.iImpl->Name();
       
  1096 
       
  1097 	// look up the api to see whether we need the params
       
  1098 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
       
  1099 	CCdlTkApiParams& params = api.Params();
       
  1100 	ValidateRequiredParams(
       
  1101 		name, 
       
  1102 		params, 
       
  1103 		iAllParams || aImpl.iLine->NeedsOptions(), 
       
  1104 		iAllParams || aImpl.iLine->NeedsCols(), 
       
  1105 		iAllParams || aImpl.iLine->NeedsRows());
       
  1106 	SCompDataImplFunc& func = AddImplFunc(type, params);
       
  1107 	aImpl.iImpl->SetPointerReference(func.iPtrRef);
       
  1108 	}
       
  1109 
       
  1110 void CMLCompDataInstOpt::SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl)
       
  1111 	{
       
  1112 	TMLCompDataTable& table = *(aImpl.iTable);
       
  1113 	TMLCompDataTable::TMLCompDataSubTable& subTable = *(aImpl.iSubTable);
       
  1114 	TMLCompDataLine& line= *(table[subTable[0]]);
       
  1115 
       
  1116 	SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable;
       
  1117 
       
  1118 	if (line.iType == TMLCompDataLine::ETextComponent)
       
  1119 		{
       
  1120 		type = SCompDataImplFunc::ETextTable;
       
  1121 		}
       
  1122 	string name = aImpl.iImpl->Name();
       
  1123 
       
  1124 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
       
  1125 	CCdlTkApiParams& params = api.Params();
       
  1126 
       
  1127 	string debug;
       
  1128 	for(CCdlTkApiParams::iterator pParam = params.begin(); pParam != params.end(); ++pParam)
       
  1129 		debug = pParam->Name();
       
  1130 
       
  1131 	ValidateRequiredParams(
       
  1132 		name, 
       
  1133 		params, 
       
  1134 		iAllParams || subTable.iNeedsOption, 
       
  1135 		iAllParams || subTable.iNeedsCol, 
       
  1136 		iAllParams || subTable.iNeedsRow);
       
  1137 	SCompDataImplFunc& func = AddImplFunc(type, params);
       
  1138 	aImpl.iImpl->SetPointerReference(func.iPtrRef);
       
  1139 	}
       
  1140 
       
  1141 bool CMLCompDataInstOpt::HasApi(const string& aName)
       
  1142 	{
       
  1143 	return iInterface.ApiList().Find(aName) != 0;
       
  1144 	}
       
  1145 
       
  1146 CCdlTkImplementation& CMLCompDataInstOpt::FindImp(const string& aName)
       
  1147 	{
       
  1148 	CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
       
  1149 	if (!impl)
       
  1150 		throw NotFoundErr(aName + " in interface " + iInterface.FileName());
       
  1151 	return *impl;
       
  1152 	}
       
  1153 
       
  1154 CMLCompDataInstOptImpl* CMLCompDataInstOpt::FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl)
       
  1155 	{
       
  1156 	for (CMLCompDataInstOptImpls::const_iterator pOptImpl = aImpls.begin(); pOptImpl != aImpls.end(); ++pOptImpl)
       
  1157 		{
       
  1158 		CMLCompDataInstOptImpl* optImpl = *pOptImpl;
       
  1159 		if (optImpl->iImpl == &aImpl)
       
  1160 			return optImpl;
       
  1161 		}
       
  1162 	return NULL;
       
  1163 	}
       
  1164 
       
  1165 string CMLCompDataInstOpt::DefinitionString(int aByteCodeIndex, const string& aApiName)
       
  1166 	{
       
  1167 	int adjustedIndex = aByteCodeIndex - iBaseOffset;
       
  1168 	return CdlTkUtil::ShortToHexString(adjustedIndex) + ",\t// (" + CdlTkUtil::IntToHexString(aByteCodeIndex) + ") " + aApiName;
       
  1169 	}
       
  1170 
       
  1171 bool CMLCompDataInstOpt::CheckByteCodeIndexInRange(int aByteCodeIndex)
       
  1172 	{
       
  1173 	int adjustedIndex = aByteCodeIndex - iBaseOffset;
       
  1174 	if(adjustedIndex > KAddressableBytecodedData)
       
  1175 		{
       
  1176 		cerr << "Error: Out of range: index = "  << CdlTkUtil::IntToHexString(aByteCodeIndex) << ", ";
       
  1177 		cerr << "baseOffset = " << CdlTkUtil::IntToHexString(iBaseOffset ) << endl;
       
  1178 		return false;
       
  1179 		}
       
  1180 	return true;
       
  1181 	}
       
  1182 
       
  1183 SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType)
       
  1184 	{
       
  1185 	CCdlTkApiParams params;
       
  1186 	return AddImplFunc(aType, params);
       
  1187 	}
       
  1188 
       
  1189 SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams)
       
  1190 	{
       
  1191 	for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
       
  1192 		{
       
  1193 		SCompDataImplFunc& func = **pFunc;
       
  1194 		if(func.IsSimilar(aType, aParams))
       
  1195 			return func;
       
  1196 		}
       
  1197 
       
  1198 	int count = gTheFuncs.size();
       
  1199 	for (int ii=0; ii<count; ii++)
       
  1200 		{
       
  1201 		SCompDataImplFunc* func = &gTheFuncs[ii];
       
  1202 		if(func->IsSimilar(aType, aParams)) 
       
  1203 			{
       
  1204 			iFuncs.push_back(func);
       
  1205 			return *func;
       
  1206 			}
       
  1207 		}
       
  1208 
       
  1209 	throw NotFoundErr("implementation function");
       
  1210 	return gTheFuncs[0];
       
  1211 	}
       
  1212 
       
  1213 void CMLCompDataInstOpt::SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName)
       
  1214 	{
       
  1215 	CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
       
  1216 
       
  1217 	// CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl);
       
  1218 	CMLCompDataInstOptImpl* newImpl = new CMLCompDataInstOptImpl(impl);
       
  1219 	iImpls.push_back(newImpl);
       
  1220 
       
  1221 	SetGenericFunc(*newImpl, aType);
       
  1222 	newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(0) + ","); // no specific data for generic apis
       
  1223 	}
       
  1224 
       
  1225 // The following strings and the SetExtraCpp() function build the gross structure of
       
  1226 // the C++ customisation instance.
       
  1227 // So far, the implementations are actually just 16-bit values, typically indexes into
       
  1228 // the data lookup table. These need to be turned into an array by adding declarations
       
  1229 // and brackets to the first and last implementations. Extra support functions are also
       
  1230 // added.
       
  1231 // extern string KScalableExtraCpp;
       
  1232 string KScalableExtraCpp = "\
       
  1233 #include \"aknlayout2scalabledecode.h\"\n\
       
  1234 namespace $INTERFACE_NS { extern const TUint8 KByteCodedData_$FIRSTINSTANCENAME[]; }\n";
       
  1235 
       
  1236 //extern string KScalableInitialCpp;
       
  1237 string KScalableInitialCpp ="\
       
  1238 extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\
       
  1239 const SCompDataImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData_$FIRSTINSTANCENAME + $THISINSTANCEBASEOFFSET };\n\
       
  1240 \n\
       
  1241 $FUNCTIONS\
       
  1242 \n\
       
  1243 const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\
       
  1244 \t{\n";
       
  1245 void CMLCompDataInstOpt::SetExtraCpp(const string& aFirstInstName)
       
  1246 	{
       
  1247 	// The "extra cpp" field is written to the top of the cpp file.
       
  1248 	CdlTkUtil::CReplaceSet cppSet;
       
  1249 	cppSet.Add("$INTERFACE_NS", iInterface.NamespaceName());
       
  1250 	cppSet.Add("$FIRSTINSTANCENAME", aFirstInstName);
       
  1251 	cppSet.Add("$THISINSTANCEBASEOFFSET", CdlTkUtil::IntToHexString(iBaseOffset)); // base offset can be longer than 16 bits
       
  1252 	iInstance->SetExtraCpp(CdlTkUtil::MultiReplace(cppSet, KScalableExtraCpp));
       
  1253 
       
  1254 	// add headers & fwd declarations
       
  1255 	string init = CdlTkUtil::MultiReplace(cppSet, KScalableInitialCpp);
       
  1256 
       
  1257 	// add decode functions
       
  1258 	string functions;
       
  1259 	for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
       
  1260 		{
       
  1261 		CdlTkUtil::AppendString(functions, (*pFunc)->iDefn);
       
  1262 		CdlTkUtil::AppendString(functions, "\n");
       
  1263 		}
       
  1264 	init = CdlTkUtil::Replace("$FUNCTIONS", functions, init);
       
  1265 	CCdlTkImplementation& first = **(iInstance->Impl().begin());
       
  1266 	first.SetDefinition(init + first.Definition());
       
  1267 
       
  1268 	// add end of data table
       
  1269 	CCdlTkImplementation& last = **(iInstance->Impl().end() - 1);
       
  1270 	last.SetDefinition(last.Definition() + "\n};");
       
  1271 	}
       
  1272 
       
  1273 void CMLCompDataInstOpt::OutputStats()
       
  1274 	{
       
  1275 	int optimizedBytes(0);
       
  1276 	int unoptimizedBytes(0);
       
  1277 	for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
       
  1278 		{
       
  1279 		int size = (*pImpl)->iBytes.size();
       
  1280 		if ((*pImpl)->iIsRedirectedToExactCopy)
       
  1281 			optimizedBytes += size;
       
  1282 		else
       
  1283 			unoptimizedBytes += size;
       
  1284 		}
       
  1285 	for (CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl)
       
  1286 		{
       
  1287 		int size = (*pTableImpl)->iBytes.size();
       
  1288 		if ((*pTableImpl)->iIsRedirectedToExactCopy)
       
  1289 			optimizedBytes += size;
       
  1290 		else
       
  1291 			unoptimizedBytes += size;
       
  1292 		}
       
  1293 
       
  1294 	float compress = (100.0 * (float)unoptimizedBytes) / ((float)optimizedBytes + (float)unoptimizedBytes);
       
  1295 	int compressInt = (int)(compress + 0.5);
       
  1296 	cout << "instance " << iName << " compressed to " << compressInt << "% of total (" << unoptimizedBytes<< " / " << optimizedBytes + unoptimizedBytes << ")" << endl;
       
  1297 	}
       
  1298 
       
  1299 void CMLCompDataInstOpt::AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int /*aTableNum*/)
       
  1300 	{
       
  1301 	string tableName = MLCompDataToCdl::SubTableApiName(aSub);
       
  1302 	string tableParamLimitsName = tableName + KFuncParamLimitsSuffix;
       
  1303 
       
  1304 	if (HasApi(tableName))
       
  1305 		{
       
  1306 		CCdlTkImplementation& impl = FindImp(tableName);
       
  1307 		CMLCompDataSubTableInstOptImpl* newImpl = new CMLCompDataSubTableInstOptImpl(&aTable, &aSub, &impl);
       
  1308 		iTableImpls.push_back(newImpl);
       
  1309 
       
  1310 		SetDummyTableData(aTable, aSub, *newImpl);
       
  1311 		SetSubTableFunc(*newImpl);
       
  1312 
       
  1313 		AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub);
       
  1314 		if (HasApi(tableParamLimitsName))
       
  1315 			{
       
  1316 			AddTableParamLimitsImpl(tableParamLimitsName, newImpl->iByteCodeIndex, SCompDataImplFunc::ETableParamLimits, aSub.iNeedsOption);
       
  1317 			}
       
  1318 		AddTableImpl(tableName, aTable, aSub);
       
  1319 		}
       
  1320 	}
       
  1321 
       
  1322 void CMLCompDataInstOpt::UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl)
       
  1323 	{
       
  1324 	string tableName = MLCompDataToCdl::SubTableApiName(aSub);
       
  1325 	UpdateTableData(aTable, aSub, *aImpl);
       
  1326 
       
  1327 	// if we can find the new table data in the aggregated data, point to that instead
       
  1328 	int foundIndex = iInstances.FindSimilarBytes(aImpl, iBaseOffset);
       
  1329 	if(foundIndex >= 0)
       
  1330 		{
       
  1331 		if(foundIndex != aImpl->iByteCodeIndex)
       
  1332 			{
       
  1333 			aImpl->iByteCodeIndex = foundIndex;
       
  1334 			aImpl->iIsRedirectedToExactCopy = true;
       
  1335 			}
       
  1336 		else
       
  1337 			{
       
  1338 			cerr << "Error: found same table already in bytestream: " << aImpl->iName << endl;
       
  1339 			}
       
  1340 		}
       
  1341 
       
  1342 	// now we've generated the bytecode, it will be added to the bytestream
       
  1343 	iInstances.AddImpl(aImpl);
       
  1344 	aImpl->iImpl->SetDefinition(DefinitionString(aImpl->iByteCodeIndex, tableName));
       
  1345 
       
  1346 	string tableParamLimitsName = tableName + KFuncParamLimitsSuffix;
       
  1347 	if (HasApi(tableParamLimitsName))
       
  1348 		{
       
  1349 		UpdateTableParamLimitsImpl(tableParamLimitsName, aImpl->iByteCodeIndex);
       
  1350 		}
       
  1351 	}
       
  1352 
       
  1353 void CMLCompDataInstOpt::AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions)
       
  1354 	{
       
  1355 	CCdlTkImplementation& impl = FindImp(aApiName);
       
  1356 
       
  1357 	// look up the api to see whether we need a variety params
       
  1358 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc());
       
  1359 	CCdlTkApiParams& params = api.Params();
       
  1360 	ValidateRequiredParams(
       
  1361 		aApiName, 
       
  1362 		params, 
       
  1363 		iAllParams || aNeedsOptions, 
       
  1364 		false, 
       
  1365 		false);
       
  1366 
       
  1367 	SCompDataImplFunc& func = AddImplFunc(aType, params);
       
  1368 
       
  1369 	impl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName));
       
  1370 	impl.SetPointerReference(func.iPtrRef);
       
  1371 	}
       
  1372 
       
  1373 void CMLCompDataInstOpt::UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex)
       
  1374 	{
       
  1375 	CCdlTkImplementation& paramLimitsImpl = FindImp(aApiName);
       
  1376 	paramLimitsImpl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName));
       
  1377 	}
       
  1378 
       
  1379 void CMLCompDataInstOpt::AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable)
       
  1380 	{
       
  1381 	CCdlTkImplementation& impl = FindImp(aApiName);
       
  1382 	AddTableLimitsImplDefn(aSubTable, impl);
       
  1383 	impl.SetPointerReference(AddImplFunc(SCompDataImplFunc::ETableLimits).iPtrRef);
       
  1384 	}
       
  1385 
       
  1386 void CMLCompDataInstOpt::AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl)
       
  1387 	{
       
  1388 	// code up table limits as a pair of byte values, the first byte is the first table
       
  1389 	// index, the second is the last table index.
       
  1390 	int first = (*aSubTable.begin()) & 0xff;
       
  1391 	int last = (*aSubTable.rbegin()) & 0xff;
       
  1392 
       
  1393 	// however, we want these APIs to be accessed zero based, so have to calculate the offset.
       
  1394 	int offset = last - first;
       
  1395 
       
  1396     int v = offset;
       
  1397 	if ( v > KAddressableBytecodedData )
       
  1398 	    {
       
  1399 	    std::cerr << "*** ERROR: Value " << v << "(unknown/3) of out range" << std::endl;
       
  1400 	    }
       
  1401 	    
       
  1402 	aImpl.SetDefinition(CdlTkUtil::ShortToHexString(offset) + KComma);
       
  1403 	}
       
  1404 
       
  1405 void CMLCompDataInstOpt::AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub)
       
  1406 	{
       
  1407 	CCdlTkImplementation& impl = FindImp(aApiName);
       
  1408 
       
  1409 	int nParams;
       
  1410 	CountApiParams(impl, nParams);
       
  1411 	nParams--;	// don't count the aLineIndex param
       
  1412 	SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable;
       
  1413 	TMLCompDataLine::TComponentType subTableType = aTable[aSub[0]]->iType;
       
  1414 	switch(subTableType)
       
  1415 		{
       
  1416 		case TMLCompDataLine::ETextComponent:
       
  1417 			{
       
  1418 			type = SCompDataImplFunc::ETextTable;
       
  1419 			break;
       
  1420 			}
       
  1421 		}
       
  1422 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc());
       
  1423 	CCdlTkApiParams& params = api.Params();
       
  1424 	ValidateRequiredParams(
       
  1425 		aApiName, 
       
  1426 		params, 
       
  1427 		iAllParams || aSub.iNeedsOption, 
       
  1428 		iAllParams || aSub.iNeedsCol, 
       
  1429 		iAllParams || aSub.iNeedsRow);
       
  1430 	SCompDataImplFunc& func = AddImplFunc(type, params);
       
  1431 	}
       
  1432 
       
  1433 void CMLCompDataInstOpt::AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions)
       
  1434 	{
       
  1435 	string apiName = MLCompDataToCdl::LineApiName(aLine) ;
       
  1436 	string paramLimitsApiName = apiName + KFuncParamLimitsSuffix;
       
  1437 	if (!HasApi(paramLimitsApiName))
       
  1438 		throw NotFoundErr(paramLimitsApiName + " in interface " + iInterface.FileName());
       
  1439 
       
  1440 	CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName);
       
  1441 
       
  1442 	// look up the api to see whether we need a variety params
       
  1443 	CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(paramLimitsImpl.Api().AsFunc());
       
  1444 	CCdlTkApiParams& params = api.Params();
       
  1445 	ValidateRequiredParams(
       
  1446 		paramLimitsApiName, 
       
  1447 		params, 
       
  1448 		iAllParams || aNeedsOptions, 
       
  1449 		false, 
       
  1450 		false);
       
  1451 
       
  1452 	SCompDataImplFunc& func = AddImplFunc(SCompDataImplFunc::ELineParamLimits, params);
       
  1453 	paramLimitsImpl.SetPointerReference(func.iPtrRef);
       
  1454 
       
  1455 	UpdateParamLimits(apiName);
       
  1456 	}
       
  1457 
       
  1458 void CMLCompDataInstOpt::UpdateParamLimits(const string& apiName)
       
  1459 	{
       
  1460 	string paramLimitsApiName = apiName + KFuncParamLimitsSuffix;
       
  1461 	if (HasApi(paramLimitsApiName))
       
  1462 		{
       
  1463 		CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName);
       
  1464 		CMLCompDataInstOptImpl* actualOptImpl = FindSimilarImpl(iImpls, FindImp(apiName));
       
  1465 		
       
  1466 		paramLimitsImpl.SetDefinition(DefinitionString(actualOptImpl->iByteCodeIndex, paramLimitsApiName));
       
  1467 		}
       
  1468 	}
       
  1469 
       
  1470 void CMLCompDataInstOpt::SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl)
       
  1471 	{
       
  1472 	aImpl.iBytes.clear();
       
  1473 	aImpl.iComment = string("for table: ");
       
  1474 	aImpl.iName = MLCompDataToCdl::SubTableApiName(aSubTable);
       
  1475 	EncodeValue(aImpl.iBytes, aSubTable.size());
       
  1476 	for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId)
       
  1477 		{
       
  1478 		aImpl.iBytes.push_back(0);
       
  1479 		aImpl.iBytes.push_back(0);
       
  1480 		}
       
  1481 	}
       
  1482 
       
  1483 void CMLCompDataInstOpt::UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl)
       
  1484 	{
       
  1485 	aImpl.iBytes.clear();
       
  1486 	EncodeValue(aImpl.iBytes, aSubTable.size());
       
  1487 	for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId)
       
  1488 		{
       
  1489 		// figure out the offset to the next line of the table
       
  1490 		TMLCompDataLine& line = *(aTable[*pLineId]);
       
  1491 		string lineName = MLCompDataToCdl::LineApiName(line) ;
       
  1492 		CMLCompDataInstOptImpl* lineImpl = FindSimilarImpl(iImpls, FindImp(lineName));
       
  1493 
       
  1494 		// we must store the adjusted index, ie relative to the base offset, in the definition, as that will be used 
       
  1495 		// in the main output, so check that the offset is in range, which it should be if we've updated the lines
       
  1496 		// correctly
       
  1497 		if(!CheckByteCodeIndexInRange(lineImpl->iByteCodeIndex))
       
  1498 			throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName());
       
  1499 		int adjustedIndex = lineImpl->iByteCodeIndex - iBaseOffset;
       
  1500 
       
  1501 		// make an assumption that data fits into 16 bits, and don't encode the lookups
       
  1502 		// that way, when decoding, we can jump forward by 2 bytes * index without decoding
       
  1503 		// all the values (since they're not encoded, we know they're all the same size)
       
  1504 		aImpl.iBytes.push_back((adjustedIndex & 0xff00) >> 8);
       
  1505 		aImpl.iBytes.push_back(adjustedIndex);
       
  1506 		}
       
  1507 	}
       
  1508 
       
  1509 struct SIdToInt
       
  1510 	{
       
  1511 	int iInt;
       
  1512 	char* iStr;
       
  1513 	};
       
  1514 
       
  1515 #include <avkon.hrh>
       
  1516 extern SIdToInt gIdToIntTable[];
       
  1517 extern const int gIdToIntTableCount;
       
  1518 extern void TranslateValue(string& aValue);
       
  1519 
       
  1520 void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, string aValue)
       
  1521 	{
       
  1522 	int pos = 0;
       
  1523 	TranslateValue(aValue);
       
  1524 	if (aValue == "")
       
  1525 		{
       
  1526 		aBytes.push_back(KByteEmpty);
       
  1527 		}
       
  1528 	else 
       
  1529 		{
       
  1530 		pos = aValue.find_first_of(KParentRelativeMarker);
       
  1531 		if(pos != string::npos)
       
  1532 			{
       
  1533 			if (pos != 0)
       
  1534 				throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue);
       
  1535 			int val = CdlTkUtil::ParseInt(aValue.substr(1));
       
  1536 			EncodeParentRelativeValue(aBytes, val);
       
  1537 			}
       
  1538 		else
       
  1539 			{
       
  1540 			int val = CdlTkUtil::ParseInt(aValue);
       
  1541 			EncodeValue(aBytes, val);
       
  1542 			}
       
  1543 		}
       
  1544 	}
       
  1545 
       
  1546 void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, int aValue)
       
  1547 	{
       
  1548 	if (0 <= aValue && aValue <= KMaxSingleByteValue)
       
  1549 		{
       
  1550 		aBytes.push_back(aValue);
       
  1551 		}
       
  1552 	else if (aValue > KMaxSingleByteValue && aValue <= KMaxDoubleByteValue)
       
  1553 		{
       
  1554 		aBytes.push_back(KByteWord);
       
  1555 		aBytes.push_back((aValue & 0xff00) >> 8);
       
  1556 		aBytes.push_back(aValue);
       
  1557 		}
       
  1558 	else
       
  1559 		{
       
  1560 		aBytes.push_back(KByteLong);
       
  1561 		aBytes.push_back((aValue & 0xff000000) >> 24);
       
  1562 		aBytes.push_back((aValue & 0x00ff0000) >> 16);
       
  1563 		aBytes.push_back((aValue & 0x0000ff00) >> 8);
       
  1564 		aBytes.push_back(aValue);
       
  1565 		}
       
  1566 	}
       
  1567 
       
  1568 void CMLCompDataInstOpt::EncodeParentRelativeValue(vector<char>& aBytes, int aValue)
       
  1569 	{
       
  1570 	if (KMinSingleByteParentRelativeValue <= aValue && aValue <= KMaxSingleByteParentRelativeValue)
       
  1571 		{
       
  1572 		aBytes.push_back(KByteP1);
       
  1573 		aBytes.push_back(aValue);
       
  1574 		}
       
  1575 	else
       
  1576 		{
       
  1577 		aBytes.push_back(KByteP2);
       
  1578 		aBytes.push_back((aValue & 0xff00) >> 8);
       
  1579 		aBytes.push_back(aValue);
       
  1580 		}
       
  1581 	}
       
  1582 
       
  1583 void CMLCompDataInstOpt::MirrorParamName(string& aParamName)
       
  1584 	{
       
  1585 	if (aParamName == KParamNameL)
       
  1586 		aParamName = KParamNameR;
       
  1587 	else if (aParamName == KParamNameR)
       
  1588 		aParamName = KParamNameL;
       
  1589 	}
       
  1590 
       
  1591 //
       
  1592 // MLCompDataCdlInstanceOpt
       
  1593 //
       
  1594 
       
  1595 MLCompDataCdlInstanceOpt::InstStruct::InstStruct(string aInstName, TMLCompData* aInst, TMLAttributes* aAttribs) 
       
  1596 	: 
       
  1597 	iInstName(aInstName), 
       
  1598 	iInst(aInst),
       
  1599 	iAttribs(aAttribs)
       
  1600 	{
       
  1601 	}
       
  1602 
       
  1603 MLCompDataCdlInstanceOpt::InstList::~InstList() 
       
  1604 	{
       
  1605 	for(InstList::iterator pNext = begin(); pNext != end(); ++pNext)
       
  1606 		{
       
  1607 		delete pNext->iInst;
       
  1608 		}
       
  1609 	}
       
  1610 
       
  1611 void MLCompDataCdlInstanceOpt::ProcessSeparators(vector<string>& args, vector<int>& aSeparators)
       
  1612 	{
       
  1613     for(int arg = 3; arg < args.size(); arg++)
       
  1614         {
       
  1615         if(args[arg] == "-a")
       
  1616             aSeparators.push_back(arg);
       
  1617         }
       
  1618 
       
  1619     aSeparators.push_back(args.size()); // add an implicit last separator
       
  1620     if(aSeparators.size() < 2)
       
  1621         throw MLCompDataCdlInstanceOptArgsErr();
       
  1622 
       
  1623     // check that the distance between each separator is not a multiple of 2 
       
  1624     // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> sep) is 3 steps
       
  1625     // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> xml -> inst -> sep) is 5 steps
       
  1626     for(int sep = 0; sep < aSeparators.size() - 1; sep++)
       
  1627         {
       
  1628         int delta = aSeparators[sep+1] - aSeparators[sep]; 
       
  1629 	    if (delta%2 == 0)
       
  1630 		    throw MLCompDataCdlInstanceOptArgsErr();
       
  1631         }
       
  1632 	}
       
  1633 
       
  1634 bool MLCompDataCdlInstanceOpt::CheckForUsedInstances(
       
  1635 	const CInstanceList& aUsedList, 
       
  1636 	const CZoomLevelNames& aZoomLevelNames,
       
  1637 	const vector<string>& aArgs, 
       
  1638 	const vector<int>& aSeparators, 
       
  1639 	int aSepIndex)
       
  1640 	{
       
  1641 	bool ok = false;
       
  1642 	for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
       
  1643 		{
       
  1644 		// check if any of these instances are used - skip this if none are used
       
  1645 		for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2)
       
  1646 			{
       
  1647 			string instName = aArgs[arg+1] + "_" + pZoomLevel->second;
       
  1648 			if (aUsedList.IsInstanceOk(instName))
       
  1649 				ok = true;
       
  1650 			}
       
  1651 		}
       
  1652 	return ok;
       
  1653 	}
       
  1654 
       
  1655 void MLCompDataCdlInstanceOpt::ParseInstances(const vector<string>& aArgs, const vector<int>& aSeparators, int aSepIndex, MLCompDataCdlInstanceOpt::InstList& aInstList)
       
  1656 	{
       
  1657 	for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2)
       
  1658 		{
       
  1659 		string layoutName = aArgs[arg];
       
  1660 		string instName = aArgs[arg+1];
       
  1661 		string attribsName = CdlTkUtil::Replace(KCompDataFileNameSuffix, KAttributesFileNameSuffix, layoutName);
       
  1662 
       
  1663 		auto_ptr<TMLCompDataParseLayout> layoutParse = TMLCompDataParseLayout::Parse(layoutName);
       
  1664 		auto_ptr<TMLCompData> layout(layoutParse.get());
       
  1665 		layoutParse.release();
       
  1666 
       
  1667 		auto_ptr<TMLAttributesParse> attribsParse = TMLAttributesParse::Parse(attribsName);
       
  1668 		auto_ptr<TMLAttributes> attribs(attribsParse.get());
       
  1669 		attribsParse.release();
       
  1670 
       
  1671 		InstStruct instStruct(instName, layout.get(), attribs.get());
       
  1672 		aInstList.push_back(instStruct);
       
  1673 		layout.release();
       
  1674 		attribs.release();
       
  1675 		}
       
  1676 	}
       
  1677 
       
  1678 void MLCompDataCdlInstanceOpt::MergeLayouts(CInstanceList& aInstUsedList, CZoomLevelNames& aZoomLevelNames, const InstList& aInstances, InstList& aMergedLayouts)
       
  1679 	{
       
  1680 	// start with the non-mirrored instances
       
  1681 	for(int count = 0; count < 2; count++)
       
  1682 		{
       
  1683 		bool isMirrored = (count != 0);
       
  1684 		// first iterate through the layouts, we will generate one instance per layout
       
  1685 		for(int instIndex = 0; instIndex < aInstances.size(); instIndex++)
       
  1686 			{
       
  1687 			const InstStruct& instStruct = aInstances[instIndex];
       
  1688 			string targetInstName = instStruct.iInstName;
       
  1689 			TMLCompData& targetLayout = *(instStruct.iInst);
       
  1690 			TMLAttributes& targetAttribs = *(instStruct.iAttribs);
       
  1691 
       
  1692 			bool required = false;
       
  1693 			for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
       
  1694 				{
       
  1695 				string zoomInstName = targetInstName + "_" + pZoomLevel->second;
       
  1696 				 if(aInstUsedList.IsInstanceOk(zoomInstName))
       
  1697 					required = true;
       
  1698 				}
       
  1699 
       
  1700 			// if this target is not required, or if it's the wrong sort of mirrored
       
  1701 			// for this iteration, skip it.
       
  1702 			if(targetLayout.iCanBeMirror != isMirrored || !required)
       
  1703 				continue;
       
  1704 
       
  1705 			// for each instance, we must merge all the other layouts
       
  1706 			auto_ptr<TMLCompData> mergedLayout(new TMLCompData());
       
  1707 			auto_ptr<TMLAttributes> mergedAttribs(new TMLAttributes());
       
  1708 			for (InstList::const_iterator pInst2 = aInstances.begin(); pInst2 != aInstances.end(); ++pInst2)
       
  1709 				{
       
  1710 				// merge in all the others
       
  1711 				const InstStruct& instStruct2 = *pInst2;
       
  1712 				if(instStruct2.iInstName != targetInstName)
       
  1713 					{
       
  1714 					TMLCompData& nextLayout = *(instStruct2.iInst);
       
  1715 					TMLAttributes& nextAttribs = *(instStruct2.iAttribs);
       
  1716 					// but only if it's the right kind of mirrored
       
  1717 					if(nextLayout.iCanBeMirror == isMirrored)
       
  1718 						{
       
  1719 						mergedLayout->Merge(nextLayout);
       
  1720 						mergedAttribs->Merge(nextAttribs);
       
  1721 						}
       
  1722 					}
       
  1723 				}
       
  1724 			// then end up merging in the one we want
       
  1725 			mergedLayout->Merge(targetLayout);
       
  1726 			mergedAttribs->Merge(targetAttribs);
       
  1727 			if(isMirrored)
       
  1728 				{
       
  1729 				// If we have just processed a mirrored layout, 
       
  1730 				// we need to do a mirror merge with the corresponding one.
       
  1731 				// The instances are ordered as on the command line, 
       
  1732 				// but the merged layouts are grouped toghether, unmirrored first.
       
  1733 				// So to convert between the two indexes: 1 -> 0, and 3 -> 1
       
  1734 				int unMirroredMergedLayoutIndex = (instIndex / 2);
       
  1735 				InstStruct& unMirroredInst = aMergedLayouts[unMirroredMergedLayoutIndex]; // this works as we have already added the unmirrored instance to the vector
       
  1736 				TMLCompData& unMirroredLayout = *(unMirroredInst.iInst);
       
  1737 				TMLAttributes& unMirroredAttribs = *(unMirroredInst.iAttribs);
       
  1738 				mergedLayout->Merge(unMirroredLayout);
       
  1739 				mergedAttribs->Merge(unMirroredAttribs);
       
  1740 				}
       
  1741 
       
  1742 			InstStruct mergedInstStruct(targetInstName, mergedLayout.get(), mergedAttribs.get());
       
  1743 			aMergedLayouts.push_back(mergedInstStruct);
       
  1744 			mergedLayout.release();
       
  1745 			mergedAttribs.release();
       
  1746 			}
       
  1747 		}
       
  1748 	}
       
  1749 
       
  1750 int MLCompDataCdlInstanceOpt::Process(vector<string>& args)
       
  1751 	{
       
  1752 	// parse the file containing the used instances list. only instances in this list 
       
  1753 	// will be generated, even if also mentioned on the command line
       
  1754 	CInstanceList instUsedList;
       
  1755 	instUsedList.ProcessOptions(args);
       
  1756 
       
  1757 	// extract the zoom level names, note that this consumes the argument if present
       
  1758 	CZoomLevelNames zoomLevelNames;
       
  1759 	zoomLevelNames.ProcessOptions(args);
       
  1760 
       
  1761 	// check that we have an acceptable number of arguments
       
  1762 	int extraArgs = args.size() - 3;
       
  1763 	if (extraArgs < 0)
       
  1764 		throw MLCompDataCdlInstanceOptArgsErr();
       
  1765 
       
  1766 	// check for optional flags
       
  1767     int arg = 2;
       
  1768 	bool allParams = false;
       
  1769 	if (args[arg] == "-allparams")
       
  1770 		{
       
  1771 		allParams = true;
       
  1772 		arg++;
       
  1773 		}
       
  1774 
       
  1775 	bool nonCompleteInstance = false;
       
  1776 	if(args[arg].substr(0,2) == "-d")
       
  1777         {
       
  1778 		arg++;
       
  1779         if (args[arg].size() >= 2)
       
  1780 		    {
       
  1781 		    nonCompleteInstance = true;
       
  1782 		    }
       
  1783         }
       
  1784 
       
  1785 	// parse the CDL interface
       
  1786 	string cdlName = args[arg];
       
  1787 	CCdlTkCdlFileParser parser(cdlName);
       
  1788 	auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true));
       
  1789 	MLCompDataCdlInstanceOpt process(*iface);
       
  1790 
       
  1791     // the separators divide the layout instances that are aggregated together
       
  1792     vector<int> separators;
       
  1793 	ProcessSeparators(args, separators);
       
  1794     for(int sep = 0; sep < separators.size() - 1; sep++)
       
  1795         {
       
  1796 		if(!CheckForUsedInstances(instUsedList, zoomLevelNames, args, separators, sep))
       
  1797 			continue;
       
  1798         // start from after the next separator, and continue until before the next one
       
  1799 	    InstList instances;
       
  1800 		ParseInstances(args, separators, sep, instances);
       
  1801 
       
  1802 		InstList mergedLayouts;
       
  1803 		MergeLayouts(instUsedList, zoomLevelNames, instances, mergedLayouts);
       
  1804 		for(InstList::iterator pMergedLayout = mergedLayouts.begin(); pMergedLayout != mergedLayouts.end(); )
       
  1805 			{
       
  1806 			process.AddInst(*pMergedLayout, zoomLevelNames, allParams, nonCompleteInstance); // pass ownership of mergedLayout
       
  1807 			pMergedLayout = mergedLayouts.erase(pMergedLayout);
       
  1808 			}
       
  1809         }
       
  1810 
       
  1811 	process.Process();
       
  1812 	process.WriteInstances();
       
  1813 	return 0;
       
  1814 	}
       
  1815 
       
  1816 void MLCompDataCdlInstanceOpt::ShowHelp(ostream& stream)
       
  1817 	{
       
  1818 	stream << "MLCompCdl2InstO [-i<instanceList>] [-z<zoomList>] [-allparams] [-d<deliveryType>] <interface.cdl> (-a ([-m]<layout.xml> <instanceName>)+ )+" << endl;
       
  1819 	stream << "  Creates optimised CDL instances containing the layout data." << endl;
       
  1820 	stream << "  Each -a flag is followed by a collection of xml and instance name pairs." << endl;
       
  1821 	stream << "  Each collection is aggregated separately." << endl;
       
  1822 	stream << "  The aggregation of the layout instances must conform to the CDL interface, " << endl;
       
  1823 	stream << "    but note any missing data in an instance may result in data being returned " << endl;
       
  1824 	stream << "    from a different instance, although duplicate implementations will be reused " << endl;
       
  1825 	stream << "    to reduce ROM usage." << endl;
       
  1826 	stream << "  A -m flag must precede an xml file that contains mirrored layout data." << endl;
       
  1827 	stream << "  An aggregated collection of layouts must contain interleaved" << endl;
       
  1828 	stream << "    elaf and the corresponding abrw instances." << endl;
       
  1829 	stream << "  If -i<instanceList> is specified, then only instances whose name" << endl;
       
  1830 	stream << "    appears in the file <instanceList> will be processed." << endl;
       
  1831 	stream << "  If -z<zoomList> is specified, then only instances whose zoom factor" << endl;
       
  1832 	stream << "   (in the form \"n,string\") appears in the file <zoomList> will be generated." << endl;
       
  1833 	stream << "  If -allparams is used, all processed APIs will have all available params added, " << endl;
       
  1834 	stream << "    otherwise only needed params are added." << endl;
       
  1835 	stream << "  If -d<deliveryType> is supplied with any value, any API that has a missing" << endl;
       
  1836 	stream << "    implementation will be filled in with NULL, allowing fall-through to an instance" << endl;
       
  1837 	stream << "    from a lower priority pack." << endl;
       
  1838 	}
       
  1839 
       
  1840 MLCompDataCdlInstanceOpt::MLCompDataCdlInstanceOpt(CCdlTkInterface& aInterface)
       
  1841 	: 
       
  1842 	iInterface(aInterface)
       
  1843 	{
       
  1844 	}
       
  1845 
       
  1846 MLCompDataCdlInstanceOpt::~MLCompDataCdlInstanceOpt()
       
  1847 	{
       
  1848 	for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
       
  1849 		{
       
  1850 		CCompDatas& compDatas = pZoomLevel->second;
       
  1851 		for (CCompDatas::iterator pInstOpt = compDatas.begin(); pInstOpt != compDatas.end(); ++pInstOpt)
       
  1852 			delete *pInstOpt;
       
  1853 		}
       
  1854 	for(CCompDataLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
       
  1855 		 delete *pLayout;
       
  1856 	}
       
  1857 
       
  1858 void MLCompDataCdlInstanceOpt::AddInst(const InstStruct& aInstStruct, CZoomLevelNames& aZoomLevelNames, bool aAllParams, bool aNonCompleteInstance)
       
  1859 	{
       
  1860 	TMLCompData* layout = aInstStruct.iInst;
       
  1861 	layout->iAttributes = aInstStruct.iAttribs; // transfer ownership
       
  1862 	iLayouts.push_back(aInstStruct.iInst);
       
  1863 	for(CZoomLevelNames::iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
       
  1864 		{
       
  1865 		auto_ptr<CMLCompDataInstOpt> p(new CMLCompDataInstOpt(*this, layout, aInstStruct.iInstName, pZoomLevel->second, pZoomLevel->first, aAllParams, aNonCompleteInstance));
       
  1866 		CCompDatas& compDatas = iZoomLevelDatas[pZoomLevel->first];
       
  1867 		compDatas.push_back(p.get());
       
  1868 		p.release();
       
  1869 		}
       
  1870 	}
       
  1871 
       
  1872 void MLCompDataCdlInstanceOpt::Process()
       
  1873 	{
       
  1874 	for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
       
  1875 		{
       
  1876 		CCompDatas& compDatas = pZoomLevel->second;
       
  1877 		if(compDatas.size() == 0)
       
  1878 			continue;
       
  1879 		CMLCompDataInstOpt* firstInstOpt = compDatas[0];
       
  1880 		cout << "processing instances for zoom level: " << firstInstOpt->ZoomName() << endl;
       
  1881 
       
  1882 		string firstInstName = firstInstOpt->Name();
       
  1883 		for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout)
       
  1884 			(*pLayout)->Process(firstInstName);
       
  1885 		}
       
  1886 	ProcessCommonImpl();
       
  1887 	}
       
  1888 
       
  1889 void MLCompDataCdlInstanceOpt::WriteInstances()
       
  1890 	{
       
  1891 	bool found = false;
       
  1892 	for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
       
  1893 		{
       
  1894 		CCompDatas& compDatas = pZoomLevel->second;
       
  1895 		if(!found && compDatas.size() > 0)
       
  1896 			{
       
  1897 			found = true;
       
  1898 			cout << "writing instances ... " << endl;
       
  1899 			}
       
  1900 		for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout)
       
  1901 			(*pLayout)->WriteInstance();
       
  1902 		}
       
  1903 	}
       
  1904 
       
  1905 CCdlTkInterface& MLCompDataCdlInstanceOpt::Interface()
       
  1906 	{
       
  1907 	return iInterface;
       
  1908 	}
       
  1909 
       
  1910 const string KCommonImplStart = "\
       
  1911 #include \"aknlayout2scalabledecode.h\"\n\
       
  1912 namespace $NAMESPACENAME { extern TUint8 const KByteCodedData_$FIRSTINSTANCENAME[] = {\n";
       
  1913 
       
  1914 const string KCommonImplImpl = "\
       
  1915 // $INDEX $COMMENT\n\
       
  1916 $BYTES\n";
       
  1917 
       
  1918 void MLCompDataCdlInstanceOpt::ProcessCommonImpl()
       
  1919 	{
       
  1920 	// use the first instance name of the first zoom level
       
  1921 	// it's not entirely accurate but it only needs to disambiguate
       
  1922 	CCompDatas& compDatas = iZoomLevelDatas[EAknUiZoomNormal];
       
  1923 	if(compDatas.size() == 0)
       
  1924 		return;
       
  1925 	CMLCompDataInstOpt* firstInstOpt = compDatas[0];
       
  1926 
       
  1927 	CdlTkUtil::CReplaceSet startImplSet;
       
  1928 	startImplSet.Add("$NAMESPACENAME", iInterface.NamespaceName());
       
  1929 	startImplSet.Add("$FIRSTINSTANCENAME", firstInstOpt->Name());
       
  1930 	string bytecode = CdlTkUtil::MultiReplace(startImplSet, KCommonImplStart);
       
  1931 	int byteCounter(0);
       
  1932 
       
  1933 	for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
       
  1934 		{
       
  1935 		vector<char>& bytes = (*pImpl)->iBytes;
       
  1936 		if (!(*pImpl)->iIsRedirectedToExactCopy && bytes.size())
       
  1937 			{
       
  1938 			string byteString;
       
  1939 			for (vector<char>::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar)
       
  1940 				{
       
  1941 				CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar));
       
  1942 				CdlTkUtil::AppendString(byteString, KComma);
       
  1943 				}
       
  1944 
       
  1945 			// in this case, we want to know the absolute index to help with debugging
       
  1946 			int index = (*pImpl)->iByteCodeIndex;
       
  1947 			if(byteCounter != index)
       
  1948 				{
       
  1949 				cerr << "Error: Data table mismatch for " << (*pImpl)->iName;
       
  1950 				cerr << ": Bytecode index = " << CdlTkUtil::ShortToHexString(index);
       
  1951 				cerr << "; byte counter = " << CdlTkUtil::ShortToHexString(byteCounter) << endl;
       
  1952 				throw GeneralErr((*pImpl)->iName + " in interface " + iInterface.FileName());
       
  1953 				}
       
  1954 			byteCounter += bytes.size();
       
  1955 
       
  1956 			CdlTkUtil::CReplaceSet implSet;
       
  1957 			implSet.Add("$INDEX", CdlTkUtil::IntToHexString(index));
       
  1958 			implSet.Add("$COMMENT", (*pImpl)->iComment + (*pImpl)->iName + " (" + CdlTkUtil::ShortToHexString(bytes.size()) + " bytes)");
       
  1959 			implSet.Add("$BYTES", byteString);
       
  1960 			CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl));
       
  1961 			}
       
  1962 		}
       
  1963 	CdlTkUtil::AppendString(bytecode, "};\n}");
       
  1964 	CCdlTkInstance& firstInst = firstInstOpt->Inst();
       
  1965 	firstInst.SetExtraCpp(bytecode);
       
  1966 	}
       
  1967 
       
  1968 int MLCompDataCdlInstanceOpt::FindSimilarBytes(CMLCompDataInstOptImpl* aImpl, int aBaseOffset)
       
  1969 	{
       
  1970 	int index = -1;
       
  1971 	vector<char>::iterator startOfAddressableBlock = iBytesAggregated.begin() + aBaseOffset;
       
  1972 	vector<char>::iterator found = std::search(
       
  1973 		startOfAddressableBlock, 
       
  1974 		iBytesAggregated.end(), 
       
  1975 		aImpl->iBytes.begin(), 
       
  1976 		aImpl->iBytes.end());
       
  1977 	if(found != iBytesAggregated.end())
       
  1978 		{
       
  1979 		index = std::distance(iBytesAggregated.begin(), found); // we return the absolute position
       
  1980 		}
       
  1981 	return index;
       
  1982 	}
       
  1983 
       
  1984 void MLCompDataCdlInstanceOpt::AddImpl(CMLCompDataInstOptImpl* aImpl)
       
  1985 	{
       
  1986 	if(!aImpl->iIsRedirectedToExactCopy)
       
  1987 		{
       
  1988 		CMLCompDataInstOptImpls::iterator found = std::find(iImpls.begin(), iImpls.end(), aImpl);
       
  1989 		if(found == iImpls.end())
       
  1990 			{
       
  1991 			iImpls.push_back(aImpl);
       
  1992 			}
       
  1993 		else
       
  1994 			{
       
  1995 			cerr << "Error: " << aImpl->iName << " already added to byte stream" << endl;
       
  1996 			throw GeneralErr(aImpl->iName + " in interface " + iInterface.FileName());
       
  1997 			}
       
  1998 		if (aImpl->iBytes.size())
       
  1999 			{
       
  2000 			aImpl->iByteCodeIndex = iBytesAggregated.size();
       
  2001 			iBytesAggregated.insert(
       
  2002 				iBytesAggregated.end(), 
       
  2003 				aImpl->iBytes.begin(), 
       
  2004 				aImpl->iBytes.end());
       
  2005 			}
       
  2006 		}
       
  2007 	}
       
  2008 
       
  2009 int MLCompDataCdlInstanceOpt::ByteStreamSize() const
       
  2010 	{
       
  2011 	return iBytesAggregated.size();
       
  2012 	}
       
  2013 
       
  2014 // end of file
       
  2015 
       
  2016