aknlayoutcompiler/src/MLCompData2Cdl.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aknlayoutcompiler/src/MLCompData2Cdl.cpp	Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,546 @@
+/*
+* Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+// disable "identifier was truncated to '255' characters in the browser information" warning
+#pragma warning (disable:4786)
+
+#include "MLCompData2Cdl.h"
+#include "MLCompDataParse.h"
+#include "MLAttributesParse.h"
+#include "LayoutCompilerErr.h"
+#include <cdlcompilertoolkit/cdltkprocess.h>
+#include <fstream>
+#include <iostream>
+#include <algorithm>
+#include "CppWriter.h"
+#include "CodeGenConsts.h"
+
+using namespace std;
+
+typedef LayoutProcessArgsErr<MLCompDataToCdl> MLCompDataToCdlArgsErr;
+
+// constants
+
+const int KGeneratedInterfaceMajorVer = 1;
+const int KGeneratedInterfaceMinorVer = 0;
+
+const string KCompDataFileNameSuffix("compData");
+const string KAttributesFileNameSuffix("attributes");
+
+
+// 
+// MLCompDataToCdl
+//
+MLCompDataToCdl::CApiNamesUsed MLCompDataToCdl::iInterfaceNamesUsed;
+
+string MLCompDataToCdl::InterfaceName(const string& aFileName)
+	{
+	return aFileName.substr(0,aFileName.find_last_of('.'));
+	}
+
+int MLCompDataToCdl::Process(const vector<string>& args)
+	{
+	iInterfaceNamesUsed.clear();
+
+	int numExpectedArgs = 4;
+	if(args.size() < numExpectedArgs)
+		throw MLCompDataToCdlArgsErr();
+
+    int arg = 2;
+	bool deletesAllowed = true;
+	if (args[arg] == "-nodeletes")
+		{
+		deletesAllowed = false;
+		arg++;
+		numExpectedArgs++;
+		}
+
+	bool allParams = false;
+	if (args[arg] == "-allparams")
+		{
+		allParams = true;
+		arg++;
+		numExpectedArgs++;
+		}
+
+	bool romOnly = false;
+	if (args[arg] == "-romonly")
+		{
+		romOnly = true;
+		arg++;
+		numExpectedArgs++;
+		}
+
+	int numLayouts = args.size() - numExpectedArgs;
+	if (numLayouts < 1)
+		throw MLCompDataToCdlArgsErr();
+
+	TMLCompData* mergedLayout = NULL;
+	TMLAttributes* mergedAttribs = NULL;
+    for(int ii = 0; ii < numLayouts; ii++)
+        {
+		string layoutName = args[arg++];
+		string attribsName = CdlTkUtil::Replace(KCompDataFileNameSuffix, KAttributesFileNameSuffix, layoutName);
+
+		auto_ptr<TMLCompDataParseLayout> layoutParse = TMLCompDataParseLayout::Parse(layoutName);
+		auto_ptr<TMLCompData> layout(layoutParse.get());
+		layoutParse.release();
+
+		auto_ptr<TMLAttributesParse> attribsParse = TMLAttributesParse::Parse(attribsName);
+		auto_ptr<TMLAttributes> attribs(attribsParse.get());
+		attribsParse.release();
+
+		if (mergedLayout || mergedAttribs)
+			{
+			// first we merge the components and the attributes
+			mergedLayout->MergeComponents(*layout);
+			mergedAttribs->Merge(*attribs);
+			}
+		else
+			{
+			// first time around
+			mergedLayout = layout.get();
+			mergedAttribs = attribs.get();
+			}
+        layout.release();
+		attribs.release();
+        }
+
+	mergedLayout->iAttributes = mergedAttribs; // transfer ownership
+
+	// once merged, we can compile the tables
+    mergedLayout->Compile();
+
+	string cdlName = args[arg++];
+	int uid = CdlTkUtil::ParseInt(args[arg++]);
+
+	auto_ptr<CCdlTkInterface> iface(new CCdlTkInterface);
+	CCdlTkCdlFileParser parser(cdlName);
+	try
+		{
+		iface = parser.LoadAndParse(true);
+		}
+	catch (const CdlTkFileOpenErr& aErr)
+		{
+		// there was no file, so presume that we are creating a new interface.
+		aErr.Show(cerr);
+		cout << "Creating new CDL API from scratch." << endl;
+		}
+
+	LayoutToInterface(*iface, *mergedLayout, deletesAllowed, allParams);
+
+	stringstream comment;
+	comment << "// Generated from ";
+
+	// ignore the args up to and including the app name, the mode name, and the optional flags, 
+    arg = numExpectedArgs-2; 
+
+	// so that we get a list of processed files to output to the comment
+    for(ii = 0; ii < numLayouts; ii++)
+		comment << args[arg++] << ", ";
+    comment << endl; 
+	comment << "// which was generated with timestamp " << mergedLayout->iTimestamp << endl;
+
+	SetHeaders(*iface, cdlName, comment.str(), uid, romOnly);
+
+	CCdlTkWriteCdlFile writer(*iface);
+	cout << "writing CDL file " << cdlName << endl;
+	writer.Process();
+
+	iInterfaceNamesUsed.clear();
+	return 0;
+	}
+
+void MLCompDataToCdl::ShowHelp(ostream& stream)
+	{
+	stream << "MLCompData2Cdl [-nodeletes] [-allparams] [-romonly] (<MLCompDataName>)+ <cdlName> <UID>" << endl;
+	stream << "  If the CDL file does not exist, writes out the API in the order of the MLCompData." << endl;
+	stream << "  If the CDL file does exist, and -nodeletes is not used, fills holes and appends new APIs to the end, to preseve API compatibility." << endl;
+	stream << "  If the CDL file does exist, and -nodeletes is used, processing will halt and report an error if any of the existing APIs are missing." << endl;
+	stream << "  If the CDL file does exist, existing APIs that do not have required params will be updated, appending missing params with default values." << endl;
+	stream << "  If -allparams is used, all processed APIs will have all available params added, otherwise only needed params are added." << endl;
+	stream << "  If -romonly is used, and if there is a previous CDL API it did not include the KCdlFlagRomOnly flag, then the flag will be added to the updated API." << endl;
+	stream << "  If more than one layout is supplied, they are merged together, and then the interface of the merged data is generated. " << endl;
+    stream << "  e.g. from \\S60\\AknLayout2\\group run " << endl;
+    stream << "  aknlayoutcompiler MLCompData2CDL -nodeletes ..\\xml\\pdp_av_dbl_prt\\display_eur_compData.xml ..\\xml\\pdl_av_dbl_lsc\\display_eur_compData.xml ..\\cdl\\AknLayoutScalable_Avkon.cdl 0x1020384E" << endl;
+    stream << "  aknlayoutcompiler MLCompData2CDL -nodeletes ..\\xml\\pdp_apps_dbl_prt\\display_eur_compData.xml ..\\xml\\pdl_apps_dbl_lsc\\display_eur_compData.xml ..\\cdl\\AknLayoutScalable_Apps.cdl 0x1020384F" << endl;
+	}
+
+void MLCompDataToCdl::LayoutToInterface(CCdlTkInterface& aInterface, const TMLCompData& aLayout, bool aDeletesAllowed, bool aAllParams)
+	{
+	const bool needsOptions = true;
+	const bool needsColsRows = true;
+	const bool doesntNeedOptions = false;
+	const bool doesntNeedColsRows = false;
+
+	AddGenericApiToInterface(aInterface, KTypeLayoutScalableComponentType, KFuncGetComponentTypeById, doesntNeedOptions, doesntNeedColsRows);
+	AddGenericApiToInterface(aInterface, KTypeLayoutScalableParameterLimits, KFuncGetParamLimitsById, needsOptions, doesntNeedColsRows);
+	AddGenericApiToInterface(aInterface, KTypeWindowComponentLayout, KFuncGetWindowComponentById, needsOptions, needsColsRows);
+	AddGenericApiToInterface(aInterface, KTypeTextComponentLayout, KFuncGetTextComponentById, needsOptions, needsColsRows);
+
+	for (TMLCompData::const_iterator pTab = aLayout.begin(); pTab != aLayout.end(); ++pTab)
+		{
+		AddTableToInterface(aInterface, **pTab, aAllParams);
+		}
+	ReplaceRemovedAPIs(aInterface, aLayout, aDeletesAllowed);
+	CleanUpAPIComments(aInterface);
+	}
+
+void MLCompDataToCdl::AddGenericApiToInterface(CCdlTkInterface& aInterface, const string& aReturnType, const string& aName, bool aNeedsOptions, bool aRequiresColsRows)
+	{
+	bool isNew = false;
+	const bool needsComponentId = true;
+	const bool doesntNeedAllParams = false;
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, aReturnType, aName, isNew);
+
+	CCdlTkApiParams& params = funcApi->Params();
+	CCdlTkApiParams oldParams = params;
+	UpdateParams(oldParams, params, aName, doesntNeedAllParams, aRequiresColsRows, isNew, needsComponentId, aNeedsOptions, aRequiresColsRows, aRequiresColsRows);
+
+	funcApi->SetComment(string("// Generic API\n"));
+	}
+
+void MLCompDataToCdl::AddTableToInterface(CCdlTkInterface& aInterface, TMLCompDataTable& aTable, bool aAllParams)
+	{
+	int line = 0;
+	for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
+		{
+		// only add parameter limits if the line is not simple
+		bool needsParamLimits = (*pLine)->NeedsOptions() || (*pLine)->NeedsCols() || (*pLine)->NeedsRows();
+		if(needsParamLimits)
+			{
+			AddParamLimitsToInterface(aInterface, **pLine, aAllParams);
+			}
+		AddLineToInterface(aInterface, **pLine, aAllParams);
+
+		for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
+			{
+			TMLCompDataTable::TMLCompDataSubTable& sub = **pSub;
+			int last = *(sub.rbegin());
+			if(line == last)
+				{
+				AddSubTableLimitsToInterface(aInterface, aTable, sub);
+				if(needsParamLimits)
+					AddSubTableParamLimitsToInterface(aInterface, aTable, sub, aAllParams);
+				AddSubTableToInterface(aInterface, aTable, sub, aAllParams);
+				}
+			}
+
+		line++;
+		}
+	}
+
+void MLCompDataToCdl::AddTableCommentToApi(TMLCompDataTable& aTable, CCdlTkApi& aApi)
+	{
+	aApi.SetComment(string("// LAF Table : ") + aTable.Name() + "\n");
+	}
+
+void MLCompDataToCdl::AddTableCommentToApi(TMLCompDataLine& aLine, CCdlTkApi& aApi)
+	{
+	if(aLine.iParentTable)
+		{
+		TMLCompDataTable& table = *(aLine.iParentTable);
+		AddTableCommentToApi(table, aApi);
+		}
+	}
+
+void MLCompDataToCdl::AddLineToInterface(CCdlTkInterface& aInterface, TMLCompDataLine& aLine, bool aAllParams)
+	{
+	bool isNew = false;
+	const bool requiresColsRows = true;
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, ReturnType(aLine), LineApiName(aLine), isNew);
+	AddParamsToFunc(aLine, *funcApi, aAllParams, isNew, requiresColsRows);
+	AddTableCommentToApi(aLine, *funcApi);
+	}
+
+void MLCompDataToCdl::AddParamLimitsToInterface(CCdlTkInterface& aInterface, TMLCompDataLine& aLine, bool aAllParams)
+	{
+	bool isNew = false;
+	const bool doesntRequireColsRows = false;
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, KTypeLayoutScalableParameterLimits, LineParamLimitsApiName(aLine), isNew);
+	AddParamsToFunc(aLine, *funcApi, aAllParams, isNew, doesntRequireColsRows);
+	AddTableCommentToApi(aLine, *funcApi);
+	}
+
+void MLCompDataToCdl::AddSubTableToInterface(CCdlTkInterface& aInterface, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, bool aAllParams)
+	{
+	bool isNew = false;
+	const bool requiresColsRows = true;
+	TMLCompDataLine& line = *aTable[aSubTable[0]];
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, ReturnType(line), SubTableApiName(aSubTable), isNew);
+	AddParamsToFunc(aTable, aSubTable, *funcApi, aAllParams, isNew, requiresColsRows);
+	AddTableCommentToApi(aTable, *funcApi);
+	}
+
+void MLCompDataToCdl::AddSubTableLimitsToInterface(CCdlTkInterface& aInterface, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable)
+	{
+	bool isNew = false;
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, KTypeLayoutScalableTableLimits, SubTableLimitsApiName(aSubTable), isNew);
+	AddTableCommentToApi(aTable, *funcApi);
+	}
+
+void MLCompDataToCdl::AddSubTableParamLimitsToInterface(CCdlTkInterface& aInterface, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, bool aAllParams)
+	{
+	bool isNew = false;
+	const bool doesntRequireColsRows = false;
+	CCdlTkFunctionApi* funcApi = ProcessFunctionApi(aInterface, KTypeLayoutScalableParameterLimits, SubTableParamLimtsApiName(aSubTable), isNew);
+	AddParamsToFunc(aTable, aSubTable, *funcApi, aAllParams, isNew, doesntRequireColsRows);
+	AddTableCommentToApi(aTable, *funcApi);
+	}
+
+void MLCompDataToCdl::AddParamsToFunc(TMLCompDataLine& aLine, CCdlTkFunctionApi& aFunc, bool aAllParams, bool aIsNew, bool aColsRowsRequired)
+	{
+	CCdlTkApiParams& params = aFunc.Params();
+	CCdlTkApiParams oldParams = params;
+
+	const bool doesntNeedComponentId = false;
+	bool options = aLine.NeedsOptions();
+	bool cols = aLine.NeedsCols();
+	bool rows = aLine.NeedsRows();
+	UpdateParams(oldParams, params, LineApiName(aLine), aAllParams, aColsRowsRequired, aIsNew, doesntNeedComponentId, options, cols, rows);
+	}
+
+void MLCompDataToCdl::AddParamsToFunc(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkFunctionApi& aFunc, bool aAllParams, bool aIsNew, bool aColsRowsRequired)
+	{
+	CCdlTkApiParams& params = aFunc.Params();
+	CCdlTkApiParams oldParams = params;
+
+	if(aIsNew || params.FindByName(KParamLineIndex) == params.end())
+		params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex));
+
+	const bool doesntNeedComponentId = false;
+	bool options = aSubTable.iNeedsOption;
+	bool cols = aSubTable.iNeedsCol;
+	bool rows = aSubTable.iNeedsRow;
+	UpdateParams(oldParams, params, SubTableApiName(aSubTable), aAllParams, aColsRowsRequired, aIsNew, doesntNeedComponentId, options, cols, rows);
+	}
+
+void MLCompDataToCdl::SetHeaders(CCdlTkInterface& aInterface, const string& aCdlName, const string& aComment, int aUid, bool aRomOnly)
+	{
+	aInterface.SetFileName(aCdlName);
+	aInterface.SetAdditionalComment(aComment);
+	aInterface.Header().SetUid(aUid);
+
+    // Note that if the rom only flag was already set in the existing API, then it will remain on
+    // even if -romonly was not supplied as a command line argument. To remove the flag, 
+    // the CDL file must be manually edited.
+    if(aRomOnly)
+    	aInterface.Header().Flags().SetFlag("KCdlFlagRomOnly");
+
+	string ifName(InterfaceName(CdlTkUtil::StripPath(aCdlName)));
+	aInterface.Header().SetName(ifName);
+	aInterface.Header().SetVersion(CCdlTkInterfaceHeader::CVersion(KGeneratedInterfaceMajorVer, KGeneratedInterfaceMinorVer));
+
+	CCdlTkCpp& cpp = aInterface.Cpp();
+	int size = cpp.size();
+	if(!find(cpp.begin(), cpp.end(), KIncludeLayoutInstanceHeaderScalableDef))
+		cpp.push_back(KIncludeLayoutInstanceHeaderScalableDef);
+	}
+
+string MLCompDataToCdl::SubTableApiName(TMLCompDataTable::TMLCompDataSubTable& aSubTable)
+	{
+	return CdlTkUtil::ToCpp(aSubTable.iName);
+	}
+
+string MLCompDataToCdl::SubTableLimitsApiName(TMLCompDataTable::TMLCompDataSubTable& aSubTable)
+	{
+	return CdlTkUtil::ToCpp(aSubTable.iName + KFuncLimitsSuffix);
+	}
+
+string MLCompDataToCdl::SubTableParamLimtsApiName(TMLCompDataTable::TMLCompDataSubTable& aSubTable)
+	{
+	return CdlTkUtil::ToCpp(aSubTable.iName + KFuncParamLimitsSuffix);
+	}
+
+string MLCompDataToCdl::LineApiName(TMLCompDataLine& aLine)
+	{
+	return CdlTkUtil::ToCpp(aLine.iName);
+	}
+
+string MLCompDataToCdl::LineParamLimitsApiName(TMLCompDataLine& aLine)
+	{
+	return CdlTkUtil::ToCpp(aLine.iName + KFuncParamLimitsSuffix);
+	}
+
+string MLCompDataToCdl::ReturnType(TMLCompDataLine& aLine)
+	{
+	string returnType = "BadType";
+	switch(aLine.iType)
+		{
+		case TMLCompDataLine::EScreenComponent:
+		case TMLCompDataLine::EContainerComponent:
+		case TMLCompDataLine::EPaneComponent:
+		case TMLCompDataLine::EGraphicComponent:
+			{
+			returnType = KTypeWindowComponentLayout;
+			break;
+			}
+		case TMLCompDataLine::ETextComponent:
+			{
+			returnType = KTypeTextComponentLayout;
+			break;
+			}
+		default:
+			{
+			throw GeneralErr(" MLCompDataToCdl::ReturnType - uncategorised component");
+			break;
+			}
+		}
+
+	return returnType;
+	}
+
+void MLCompDataToCdl::ReplaceRemovedAPIs(CCdlTkInterface& aInterface, const TMLCompData& aLayout, bool aDeletesAllowed)
+	{
+	bool error = false;
+	// look for apis for which there is no equivalent internal structure. 
+	CCdlTkApiList& apiList = aInterface.ApiList();
+	for(CCdlTkApiList::reverse_iterator pApi = apiList.rbegin(); pApi != apiList.rend(); ++pApi)
+		{
+		CCdlTkApi*& api = *pApi;
+		string apiName = api->Name();
+		if(iInterfaceNamesUsed.find(apiName) == iInterfaceNamesUsed.end())
+			{
+			if(aDeletesAllowed)
+				{
+				delete api; // remove the missing api
+				CCdlTkApi*& last = *(apiList.rbegin()); // get a reference to the pointer to the last element
+				api = last; // copy the last element pointer to fill the gap
+
+				// erasing the last element will not invalidate our reverse iterator
+				// but we need a forward iterator to the last element, 
+				// so take the address of our reference to the pointer
+				apiList.erase(&last); 
+				cout << "Replacing missing API: " << apiName << " <- " << api->Name() << endl;
+				}
+			else
+				{
+				error = true;
+				cout << "Detected missing API: " << apiName << endl;
+				}
+			}
+		}
+	if(error)
+		{
+		throw GeneralErr("Error: -nodeletes was specified on command line, but some APIs were missing.");
+		}
+	}
+
+void MLCompDataToCdl::CleanUpAPIComments(CCdlTkInterface& aInterface)
+	{
+	string currentComment;
+	CCdlTkApiList& apiList = aInterface.ApiList();
+	for(CCdlTkApiList::iterator pApi = apiList.begin(); pApi != apiList.end(); ++pApi)
+		{
+		CCdlTkApi& api = **pApi;
+		string nextComment = api.Comment();
+		if(nextComment == currentComment)
+			api.SetComment(string());
+		else
+			currentComment = nextComment;
+		}
+	}
+
+CCdlTkFunctionApi* MLCompDataToCdl::ProcessFunctionApi(CCdlTkInterface& aInterface, string aReturnType, string aName, bool& aIsNew)
+	{
+	iInterfaceNamesUsed.insert(aName);
+	CCdlTkFunctionApi* funcApi;
+	CCdlTkApi* api = aInterface.ApiList().Find(aName);
+	if(api)
+		{
+		funcApi = static_cast<CCdlTkFunctionApi*>(api);
+		UpdateFunctionApi(*funcApi, aInterface, aReturnType, aName);
+		}
+	else
+		{
+		funcApi = CreateFunctionApi(aInterface, aReturnType, aName);
+		aIsNew = true;
+		}
+	funcApi->SetReturnType(aReturnType);
+	funcApi->SetName(aName);
+	return funcApi;
+	}
+
+CCdlTkFunctionApi* MLCompDataToCdl::CreateFunctionApi(CCdlTkInterface& aInterface, string aReturnType, string aName)
+	{
+	cout << "Adding new API: " << aName << endl;
+	CCdlTkFunctionApi* api = new CCdlTkFunctionApi(aInterface);
+	api->SetReturnType(aReturnType);
+	api->SetName(aName);
+	aInterface.ApiList().push_back(api);
+	return api;	
+	}
+
+void MLCompDataToCdl::UpdateFunctionApi(CCdlTkFunctionApi& aApi, CCdlTkInterface& aInterface, string aReturnType, string aName)
+	{
+	aApi.SetReturnType(aReturnType);
+	aApi.SetName(aName);
+	}
+
+void MLCompDataToCdl::UpdateParams(
+	CCdlTkApiParams& aOldParams, 
+	CCdlTkApiParams& aParams, 
+	string aApiName, 
+	bool aAllParamsRequested,
+	bool aColsRowsRequired,
+	bool aIsNew, 
+	bool aNeedsComponentId,
+	bool aNeedsOptions, 
+	bool aNeedsCols, 
+	bool aNeedsRows)
+	{
+	const bool allParamsDoesntApply = false;
+	AddParamToParams(aOldParams, aParams, KParamComponentId, allParamsDoesntApply, aIsNew, aNeedsComponentId);
+	AddParamToParams(aOldParams, aParams, KParamOptionIndex, aAllParamsRequested, aIsNew, aNeedsOptions);
+	AddParamToParams(aOldParams, aParams, KParamColIndex, aAllParamsRequested && aColsRowsRequired, aIsNew, aNeedsCols && aColsRowsRequired);
+	AddParamToParams(aOldParams, aParams, KParamRowIndex, aAllParamsRequested && aColsRowsRequired, aIsNew, aNeedsRows && aColsRowsRequired);
+
+	if(aOldParams != aParams)
+		cout << "Updating parameters: " << aApiName << endl;
+	}
+
+void MLCompDataToCdl::AddParamToParams(
+	CCdlTkApiParams& aOldParams, 
+	CCdlTkApiParams& aParams, 
+	string aType, 
+	bool aAllParamsRequested, 
+	bool aIsNewLine, 
+	bool aNeedsParam)
+	{
+	// only add new params if needed
+	bool alreadyPresent = aOldParams.FindByName(aType) != aOldParams.end();
+	if((aNeedsParam || aAllParamsRequested) && !alreadyPresent)
+		{
+		// the only circumstance in which we don't use a default parameter, 
+		// is if we're adding a needed param to a new line
+		bool needsDefaultValue = !(aIsNewLine && aNeedsParam);
+		
+		string defaultValue;
+		if(aParams.size() != 0 && aParams.back().DefaultValue() == CdlTkUtil::IntToString(0))
+		{
+			defaultValue = CdlTkUtil::IntToString(0);
+		}
+		else
+		{
+			defaultValue = needsDefaultValue ? CdlTkUtil::IntToString(0) : string();
+		}
+		CCdlTkApiParam param(KTypeInt, aType, defaultValue);
+		aParams.push_back(param);
+	}
+	}
+