Automatically add ammo tab for custom ammo replacements

class TestCWRUIConfig extends UTUIFrontEnd;

struct DynamicPageInfo
{
	var name Tag;
	var EReplacementType ReplacementType;
	var name DatastoreReference;

	var bool Hidden;
	var name After;

	// Runtime
	var transient TestCWRUITabList CreatedPage;
};

struct LocalizedPageCaptionMap
{
	var localized name Tag;
	var localized string Text;
};

var() transient localized string Title;
var() transient localized string BuildingUIMessage;

var() transient localized string ConfirmNoOptionsMessage;
var() transient localized string ConfirmNoOptionsTitle;
var() transient localized string ConfirmNoOptionsButtonAccept;

var() transient localized string ConfirmHideAmmoMessage;
var() transient localized string ConfirmHideAmmoTitle;
var() transient localized string ConfirmHideAmmoButtonAccept;

var() transient localized string CustomAmmoReplacementMessage;
var() transient localized string CustomAmmoReplacementTitle;

var() transient localized string ShowAmmoCaption;
var() transient localized string HideAmmoCaption;
var() transient localized string TransferAmmoCaption;

var() transient localized array<LocalizedPageCaptionMap> TitlesMapping;
var() transient array<DynamicPageInfo> DynamicPages;

/** Reference to the messagebox scene. */
var transient UTUIScene_MessageBox MessageBoxReference;

var transient TestCWRUI UIData;

var bool bAmmoVisible;
var bool bAmmoInfoShown;

/** Initialize callback */
event Initialized()
{
	local int i;
	local UTUITabControl TempTabControl;

	Super.Initialized();

	TempTabControl = UTUITabControl(FindChild('pnlTabControl', true));

	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].Hidden) continue;

		DynamicPages[i].CreatedPage = CreateReplacementTab(TempTabControl, DynamicPages[i]);
	}

	i = DynamicPages.Find('Tag', 'Weapons');
	if (i != INDEX_NONE && DynamicPages[i].CreatedPage != none)
	{
		DynamicPages[i].CreatedPage.OnExtraSave = OnReplacementsExtraSave_Weapons;
	}
}

/** Scene activated event, sets up the title for the scene. */
event SceneActivated(bool bInitialActivation)
{
	local array<string> MessageBoxOptions;

	Super.SceneActivated(bInitialActivation);

	if (bInitialActivation)
	{
		UIData = class'TestCWRUI'.static.GetData();

		MessageBoxReference = GetMessageBoxScene();
		if (MessageBoxReference != none)
		{
			MessageBoxOptions.Length = 0;
			MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
			MessageBoxReference.Display(BuildingUIMessage, Title);
			LoadTimed();
		}
		else
		{
			InitLoad();
		}
	}
}

function InitLoad()
{
	UIData.LoadAll();
	InitReplacements();

	if (MessageBoxReference != none)
	{
		CloseScene(MessageBoxReference);
	}
}

function InitReplacements()
{
	local int i, AmmoIdx, InsertIdx;
	local array<ReplacementInfoEx> ConfigWeaponReplacements, ConfigAmmoReplacements;
	local array<ReplacementInfoEx> SimpleAmmoReplacements;
	local ReplacementOptionsInfo EmptyOptions;
	local bool bCustomAmmo;

	// update all dynamic pages
	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none)
		{
			DynamicPages[i].CreatedPage.LoadReplacements(UIData);
		}
	}

	// check if config ammo replacements differ from current simple ammo replacements
	if (class'TestCentralWeaponReplacement'.static.GetConfigReplacements(RT_Weapon, ConfigWeaponReplacements) &&
		class'TestCentralWeaponReplacement'.static.GetConfigReplacements(RT_Ammo, ConfigAmmoReplacements))
	{
		for (i=0; i<ConfigAmmoReplacements.Length; i++)
		{
			if (ConfigAmmoReplacements[i].Options != EmptyOptions)
			{
				bCustomAmmo = true;
				break;
			}
		}

		if (!bCustomAmmo)
		{
			SimpleAmmoReplacements = GetAmmoBasicReplacementsFor(ConfigWeaponReplacements);

			if (ConfigAmmoReplacements.Length != SimpleAmmoReplacements.Length)
			{
				bCustomAmmo = true;
			}
			else
			{
				for (i=0; i<SimpleAmmoReplacements.Length; i++)
				{
					ConfigAmmoReplacements.RemoveItem(SimpleAmmoReplacements[i]);
				}

				if (ConfigAmmoReplacements.Length > 0)
				{
					bCustomAmmo = true;
				}
			}
		}
	}

	// add ammo tab if custom ammo replacements are found
	AmmoIdx = DynamicPages.Find('Tag', 'Ammo');
	if (bCustomAmmo && AmmoIdx != INDEX_NONE)
	{
		bAmmoVisible = true;
		InsertIdx = DynamicPages.Find('Tag', DynamicPages[AmmoIdx].After);
		if (InsertIdx != INDEX_NONE) InsertIdx += 1;
		DynamicPages[AmmoIdx].CreatedPage = CreateReplacementTab(TabControl, DynamicPages[AmmoIdx], InsertIdx, true);
		if (DynamicPages[AmmoIdx].CreatedPage != none)
		{
			DynamicPages[AmmoIdx].CreatedPage.LoadReplacements(UIData);
		}
	}
}

/** Sets the title for this scene. */
function SetTitle()
{
	local UILabel TitleLabel;

	TitleLabel = GetTitleLabel();
	if ( TitleLabel != None )
	{
		TitleLabel.SetDataStoreBinding(Title);
	}
}

/** Setup the scene's button bar. */
function SetupButtonBar()
{
	local int index;

	if(ButtonBar != None)
	{
		ButtonBar.Clear();
		ButtonBar.AppendButton("<Strings:UTGameUI.ButtonCallouts.Back>", OnButtonBar_Back);
		ButtonBar.AppendButton("<Strings:UTGameUI.ButtonCallouts.Accept>", OnButtonBar_Accept);

		if(TabControl != None && UTTabPage(TabControl.ActivePage) != none)
		{
			if (bAmmoVisible)
			{
				index = DynamicPages.Find('Tag', 'Ammo');
				if (index != INDEX_NONE && TabControl.ActivePage == DynamicPages[index].CreatedPage)
				{
					ButtonBar.AppendButton(HideAmmoCaption, OnButtonBar_HideAmmo);
				}
			}

			index = DynamicPages.Find('Tag', 'Weapons');
			if (index != INDEX_NONE && TabControl.ActivePage == DynamicPages[index].CreatedPage)
			{
				ButtonBar.AppendButton(bAmmoVisible ? HideAmmoCaption : ShowAmmoCaption, OnButtonBar_ShowAmmo);
				if (bAmmoVisible)
				{
					ButtonBar.AppendButton(TransferAmmoCaption, OnButtonBar_TransferAmmo);
				}
			}

			// Let the current tab page append buttons.
			UTTabPage(TabControl.ActivePage).SetupButtonBar(ButtonBar);
		}
	}
}

function bool HandleInputKey( const out InputEventParameters EventParms )
{
	local bool bResult;
	local UTTabPage CurrentTabPage;

	// Let the tab page's get first chance at the input
	CurrentTabPage = UTTabPage(TabControl.ActivePage);
	bResult = CurrentTabPage.HandleInputKey(EventParms);

	// If the tab page didn't handle it, let's handle it ourselves.
	if(bResult==false)
	{
		if(EventParms.EventType==IE_Released)
		{
			if(EventParms.InputKeyName=='XboxTypeS_B' || EventParms.InputKeyName=='Escape')
			{
				OnBack();
				bResult=true;
			}
		}
	}

	return bResult;
}

/** Buttonbar Accept Callback. */
function bool OnButtonBar_Accept(UIScreenObject InButton, int PlayerIndex)
{
	local array<string> MessageBoxOptions;
	local array<string> pages;
	local string pagesstr, str;

	if (HasIgnoredOptions(pages))
	{
		MessageBoxReference = GetMessageBoxScene();
		if(MessageBoxReference != none)
		{
			JoinArray(pages, pagesstr, "\n");
			str = Repl(ConfirmNoOptionsMessage, "  ", "\n");
			str = Repl(str, "`pages", pagesstr);

			MessageBoxOptions.AddItem(ConfirmNoOptionsButtonAccept);
			MessageBoxOptions.AddItem("<Strings:UTGameUI.ButtonCallouts.Cancel>");

			MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
			MessageBoxReference.Display(str, ConfirmNoOptionsTitle, OnAccept_Confirm, 1);
			return true;
		}
	}

	OnAccept();
	CloseScene(Self);

	return true;
}

/** Buttonbar Back Callback. */
function bool OnButtonBar_Back(UIScreenObject InButton, int InPlayerIndex)
{
	OnBack();

	return true;
}

/** Buttonbar ShowAmmo Callback. */
function bool OnButtonBar_HideAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	local array<string> MessageBoxOptions;

	MessageBoxReference = GetMessageBoxScene();
	if(MessageBoxReference != none)
	{
		MessageBoxOptions.AddItem(ConfirmHideAmmoButtonAccept);
		MessageBoxOptions.AddItem("<Strings:UTGameUI.ButtonCallouts.Cancel>");

		MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
		MessageBoxReference.Display(Repl(ConfirmHideAmmoMessage, "  ", "\n"), ConfirmHideAmmoTitle, OnHideAmmo_Confirm, 1);
		return true;
	}

	ToggleAmmoTab(true);
	return true;
}

/** Buttonbar ShowAmmo Callback. */
function bool OnButtonBar_ShowAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	ToggleAmmoTab();

	return true;
}

/** Buttonbar TransferAmmo Callback. */
function bool OnButtonBar_TransferAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	TransferAmmo();

	return true;
}

/**
 * Callback for the accept confirmation dialog box.
 *
 * @param SelectedOption	Selected item
 * @param PlayerIndex	Index of player that performed the action.
 */
function OnAccept_Confirm(UTUIScene_MessageBox MessageBox, int SelectedOption, int PlayerIndex)
{
	if(SelectedOption == 0)
	{
		OnAccept();
		CloseScene(self);
	}
}

/**
 * Callback for the ignore ammo replacement dialog box.
 *
 * @param SelectedOption	Selected item
 * @param PlayerIndex	Index of player that performed the action.
 */
function OnHideAmmo_Confirm(UTUIScene_MessageBox MessageBox, int SelectedOption, int PlayerIndex)
{
	if(SelectedOption == 0)
	{
		ToggleAmmoTab(true);
	}
}

/** Callback for when the user wants to back out of this screen. */
function OnBack()
{
	CloseScene(self);
}

function OnAccept()
{
	local int i;

	// save all dynamic pages
	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none)
		{
			DynamicPages[i].CreatedPage.SaveReplacements();
		}
	}
}

function OnReplacementsExtraSave_Weapons(TestCWRUITabList RefTab)
{
	local array<ReplacementInfoEx> WeaponReplacements, AmmoReplacements;

	if (!bAmmoVisible)
	{
		WeaponReplacements = RefTab.GetReplacements();
		AmmoReplacements = GetAmmoBasicReplacementsFor(WeaponReplacements);

		class'TestCentralWeaponReplacement'.static.SetConfigReplacements(RT_Ammo, AmmoReplacements);
	}
}

function ToggleAmmoTab(optional bool bForceHide)
{
	local int AmmoIdx, InsertIdx;
	local TestCWRUITabList TabPage;
	AmmoIdx = DynamicPages.Find('Tag', 'Ammo');
	if (AmmoIdx == INDEX_NONE)
		return;

	if (bAmmoVisible || bForceHide)
	{
		bAmmoVisible = false;
		if (DynamicPages[AmmoIdx].CreatedPage != none)
		{
			TabControl.RemovePage(DynamicPages[AmmoIdx].CreatedPage, GetBestPlayerIndex());
		}
	}
	else
	{
		bAmmoVisible = true;
		InsertIdx = DynamicPages.Find('Tag', DynamicPages[AmmoIdx].After);
		if (InsertIdx != INDEX_NONE) InsertIdx += 1;
		TabPage = CreateReplacementTab(TabControl, DynamicPages[AmmoIdx], InsertIdx, true);
		if (TabPage != none)
		{
			DynamicPages[AmmoIdx].CreatedPage = TabPage;
			TabPage.LoadReplacements(UIData);
		}

		if (!bAmmoInfoShown)
		{
			bAmmoInfoShown = true;
			DisplayMessageBox(Repl(CustomAmmoReplacementMessage, "  ", "\n"), CustomAmmoReplacementTitle);
		}
	}

	SetupButtonBar();
}

function TransferAmmo()
{
	local int WeaponIdx, AmmoIdx;
	local array<ReplacementInfoEx> WeaponReplacements, AmmoReplacements;

	WeaponIdx = DynamicPages.Find('Tag', 'Weapons');
	AmmoIdx = DynamicPages.Find('Tag', 'Ammo');
	if (WeaponIdx == INDEX_NONE || AmmoIdx == INDEX_NONE ||
		DynamicPages[WeaponIdx].CreatedPage == none || DynamicPages[AmmoIdx].CreatedPage == none)
		return;

	WeaponReplacements = DynamicPages[WeaponIdx].CreatedPage.GetReplacements();
	AmmoReplacements = GetAmmoBasicReplacementsFor(WeaponReplacements);

	if (AmmoReplacements.Length > 0)
	{
		DynamicPages[AmmoIdx].CreatedPage.AddReplacements(AmmoReplacements, true);
	}
}

function array<ReplacementInfoEx> GetAmmoBasicReplacementsFor(array<ReplacementInfoEx> WeaponReplacements)
{
	local ReplacementInfoEx Replacement;
	local int i;
	local name AmmoClassFrom;
	local string AmmoClassTo;
	local array<ReplacementInfoEx> Replacements;

	for (i=0; i<WeaponReplacements.Length; i++)
	{
		if (!UIData.GetAmmoInfoForWeapon(WeaponReplacements[i].OldClassName,, AmmoClassFrom))
			continue;

		Replacement.OldClassName = AmmoClassFrom;

		if (UIData.GetAmmoInfoForWeapon(WeaponReplacements[i].NewClassPath, AmmoClassTo))
		{
			Replacement.NewClassPath = AmmoClassTo;
		}
		else
		{
			Replacement.NewClassPath = "";
		}

		Replacements.AddItem(Replacement);
	}

	return Replacements;
}

function bool HasIgnoredOptions(out array<string> OutPages)
{
	local int i;
	local string str;

	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none && DynamicPages[i].CreatedPage.IsIgnoringOptions())
		{
			str = GetTabString(DynamicPages[i].Tag);
			OutPages.AddItem(str);
		}
	}

	return OutPages.Length > 0;
}

function LoadTimed(optional float time = 2.0)
{
	local PlayerController PC;

	PC = GetPlayerOwner().Actor;
	if (PC != none)
	{
		PC.SetTimer(2.0, false, 'InitLoad', self);
	}
	else
	{
		InitLoad();
	}
}

function string GetTabString(name Tag)
{
	local int index;
	index = TitlesMapping.Find('Tag', Tag);
	if (index != INDEX_NONE)
	{
		return TitlesMapping[index].Text;
	}

	 Return Localize("Titles", string(Tag), string(class.GetPackageName()));
}

function TestCWRUITabList CreateReplacementTab(UTUITabControl InTabControl, DynamicPageInfo PageInfo, optional int InsertIndex = INDEX_NONE, optional bool bSkipActivate, optional int PlayerIndex=GetBestPlayerIndex())
{
	local TestCWRUITabList TabPage;
	Local name TabName;
	TabName = name("pnlTabRep_"$PageInfo.Tag);
	TabPage = TestCWRUITabList(CreateNamedTabPage(InTabControl, class'TestCWRUITabList', TabName));
	if (TabPage != none)
	{
		TabPage.SetTitle(Caps(GetTabString(PageInfo.Tag)));
		TabPage.SetReplacementInfo(PageInfo.ReplacementType, PageInfo.DatastoreReference);

		InTabControl.InsertPage(TabPage, PlayerIndex, InsertIndex, !bSkipActivate);
	}

	return TabPage;
}

static function UITabPage CreateNamedTabPage(UITabControl OwnerControl, class<UITabPage> TabPageClass, optional name WidgetName, optional UITabPage PagePrefab )
{
	local UITabPage TabPage;
	TabPage = UITabPage(OwnerControl.CreateWidget(OwnerControl, TabPageClass, PagePrefab, WidgetName));
	if (TabPage != none) TabPage.GetTabButton(OwnerControl);
	return TabPage;
}

DefaultProperties
{
	Title="[Central Weapon Replacement]"
	BuildingUIMessage="Building UI. May take some seconds..."

	ConfirmNoOptionsMessage="You have switched to simple mode but there are replacement options set for the following pages:  `pages    By continuing saving the replacements, the options will be cleared to default. Do you want to continue?"
	ConfirmNoOptionsTitle="Clear out options"
	ConfirmNoOptionsButtonAccept="CONTINUE"

	CustomAmmoReplacementMessage="By enabling custom ammo replacement, you have to either transfer all the ammo replacements from the current weapon replacement or setup your own replacements.    No ammo pickups will be replaced automatically by whatever weapon you choose to be replaced."
	CustomAmmoReplacementTitle="Custom ammo replacment"

	ConfirmHideAmmoMessage="You made changes to the ammo replacements. By switching back to simple ammo replacement (based on the selected weapons), you will loose any made changes to the ammo replacements.    Do you want to ignore these changes and switch to simple ammo replacement?"
	ConfirmHideAmmoTitle="Ignore custom replacements?"
	ConfirmHideAmmoButtonAccept="IGNORE"

	ShowAmmoCaption="CUSTOM AMMO"
	HideAmmoCaption="SIMPLE AMMO"
	TransferAmmoCaption="TRANSFER AMMO"

	TitlesMapping[0]=(Tag="Weapons",Text="Weapons")
	TitlesMapping[1]=(Tag="Healths",Text="Health")
	TitlesMapping[2]=(Tag="Armors",Text="Armor")
	TitlesMapping[3]=(Tag="Powerups",Text="Powerups")
	TitlesMapping[4]=(Tag="Deployables",Text="Deployables")
	TitlesMapping[5]=(Tag="Vehicles",Text="Vehicles")
	TitlesMapping[6]=(Tag="Customs",Text="Customs")
	TitlesMapping[7]=(Tag="Ammos",Text="Ammo")

	DynamicPages.Add((Tag="Weapons",ReplacementType=RT_Weapon,DatastoreReference="WeaponSelection"))
	DynamicPages.Add((Tag="Ammo",ReplacementType=RT_Ammo,DatastoreReference="AmmoSelection",Hidden=true,After="Weapons"))
	DynamicPages.Add((Tag="Healths",ReplacementType=RT_Health,DatastoreReference="HealthSelection"))
	DynamicPages.Add((Tag="Armors",ReplacementType=RT_Armor,DatastoreReference="ArmorSelection"))
	DynamicPages.Add((Tag="Powerups",ReplacementType=RT_Powerup,DatastoreReference="PowerupSelection"))
	DynamicPages.Add((Tag="Deployables",ReplacementType=RT_Deployable,DatastoreReference="DeployableSelection"))
	DynamicPages.Add((Tag="Vehicles",ReplacementType=RT_Vehicle,DatastoreReference="VehicleSelection"))
	DynamicPages.Add((Tag="Customs",ReplacementType=RT_Custom,DatastoreReference="CustomSelection",Hidden=true))
}

class TestCWRUIConfig extends UTUIFrontEnd;

struct DynamicPageInfo
{
	var name Tag;
	var EReplacementType ReplacementType;
	var name DatastoreReference;

	var bool Hidden;
	var name After;

	// Runtime
	var transient TestCWRUITabList CreatedPage;
};

struct LocalizedPageCaptionMap
{
	var localized name Tag;
	var localized string Text;
};

var() transient localized string Title;
var() transient localized string BuildingUIMessage;

var() transient localized string ConfirmNoOptionsMessage;
var() transient localized string ConfirmNoOptionsTitle;
var() transient localized string ConfirmNoOptionsButtonAccept;

var() transient localized string ConfirmHideAmmoMessage;
var() transient localized string ConfirmHideAmmoTitle;
var() transient localized string ConfirmHideAmmoButtonAccept;

var() transient localized string CustomAmmoReplacementMessage;
var() transient localized string CustomAmmoReplacementTitle;

var() transient localized string ShowAmmoCaption;
var() transient localized string HideAmmoCaption;
var() transient localized string TransferAmmoCaption;

var() transient localized array<LocalizedPageCaptionMap> TitlesMapping;
var() transient array<DynamicPageInfo> DynamicPages;

/** Reference to the messagebox scene. */
var transient UTUIScene_MessageBox MessageBoxReference;

var transient TestCWRUI UIData;

var bool bAmmoVisible;
var bool bAmmoInfoShown;

/** Initialize callback */
event Initialized()
{
	local int i;
	local UTUITabControl TempTabControl;

	Super.Initialized();

	TempTabControl = UTUITabControl(FindChild('pnlTabControl', true));

	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].Hidden) continue;

		DynamicPages[i].CreatedPage = CreateReplacementTab(TempTabControl, DynamicPages[i]);
	}

	i = DynamicPages.Find('Tag', 'Weapons');
	if (i != INDEX_NONE && DynamicPages[i].CreatedPage != none)
	{
		DynamicPages[i].CreatedPage.OnExtraSave = OnReplacementsExtraSave_Weapons;
	}
}

/** Scene activated event, sets up the title for the scene. */
event SceneActivated(bool bInitialActivation)
{
	local array<string> MessageBoxOptions;

	Super.SceneActivated(bInitialActivation);

	if (bInitialActivation)
	{
		UIData = class'TestCWRUI'.static.GetData();

		MessageBoxReference = GetMessageBoxScene();
		if (MessageBoxReference != none)
		{
			MessageBoxOptions.Length = 0;
			MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
			MessageBoxReference.Display(BuildingUIMessage, Title);
			LoadTimed();
		}
		else
		{
			InitLoad();
		}
	}
}

function InitLoad()
{
	UIData.LoadAll();
	InitReplacements();

	if (MessageBoxReference != none)
	{
		CloseScene(MessageBoxReference);
	}
}

function InitReplacements()
{
	local int i;

	// update all dynamic pages
	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none)
		{
			DynamicPages[i].CreatedPage.LoadReplacements(UIData);
		}
	}
}

/** Sets the title for this scene. */
function SetTitle()
{
	local UILabel TitleLabel;

	TitleLabel = GetTitleLabel();
	if ( TitleLabel != None )
	{
		TitleLabel.SetDataStoreBinding(Title);
	}
}

/** Setup the scene's button bar. */
function SetupButtonBar()
{
	local int index;

	if(ButtonBar != None)
	{
		ButtonBar.Clear();
		ButtonBar.AppendButton("<Strings:UTGameUI.ButtonCallouts.Back>", OnButtonBar_Back);
		ButtonBar.AppendButton("<Strings:UTGameUI.ButtonCallouts.Accept>", OnButtonBar_Accept);

		if(TabControl != None && UTTabPage(TabControl.ActivePage) != none)
		{
			if (bAmmoVisible)
			{
				index = DynamicPages.Find('Tag', 'Ammo');
				if (index != INDEX_NONE && TabControl.ActivePage == DynamicPages[index].CreatedPage)
				{
					ButtonBar.AppendButton(HideAmmoCaption, OnButtonBar_HideAmmo);
				}
			}

			index = DynamicPages.Find('Tag', 'Weapons');
			if (index != INDEX_NONE && TabControl.ActivePage == DynamicPages[index].CreatedPage)
			{
				ButtonBar.AppendButton(bAmmoVisible ? HideAmmoCaption : ShowAmmoCaption, OnButtonBar_ShowAmmo);
				if (bAmmoVisible)
				{
					ButtonBar.AppendButton(TransferAmmoCaption, OnButtonBar_TransferAmmo);
				}
			}

			// Let the current tab page append buttons.
			UTTabPage(TabControl.ActivePage).SetupButtonBar(ButtonBar);
		}
	}
}

function bool HandleInputKey( const out InputEventParameters EventParms )
{
	local bool bResult;
	local UTTabPage CurrentTabPage;

	// Let the tab page's get first chance at the input
	CurrentTabPage = UTTabPage(TabControl.ActivePage);
	bResult = CurrentTabPage.HandleInputKey(EventParms);

	// If the tab page didn't handle it, let's handle it ourselves.
	if(bResult==false)
	{
		if(EventParms.EventType==IE_Released)
		{
			if(EventParms.InputKeyName=='XboxTypeS_B' || EventParms.InputKeyName=='Escape')
			{
				OnBack();
				bResult=true;
			}
		}
	}

	return bResult;
}

/** Buttonbar Accept Callback. */
function bool OnButtonBar_Accept(UIScreenObject InButton, int PlayerIndex)
{
	local array<string> MessageBoxOptions;
	local array<string> pages;
	local string pagesstr, str;

	if (HasIgnoredOptions(pages))
	{
		MessageBoxReference = GetMessageBoxScene();
		if(MessageBoxReference != none)
		{
			JoinArray(pages, pagesstr, "\n");
			str = Repl(ConfirmNoOptionsMessage, "  ", "\n");
			str = Repl(str, "`pages", pagesstr);

			MessageBoxOptions.AddItem(ConfirmNoOptionsButtonAccept);
			MessageBoxOptions.AddItem("<Strings:UTGameUI.ButtonCallouts.Cancel>");

			MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
			MessageBoxReference.Display(str, ConfirmNoOptionsTitle, OnAccept_Confirm, 1);
			return true;
		}
	}

	OnAccept();
	CloseScene(Self);

	return true;
}

/** Buttonbar Back Callback. */
function bool OnButtonBar_Back(UIScreenObject InButton, int InPlayerIndex)
{
	OnBack();

	return true;
}

/** Buttonbar ShowAmmo Callback. */
function bool OnButtonBar_HideAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	local array<string> MessageBoxOptions;

	MessageBoxReference = GetMessageBoxScene();
	if(MessageBoxReference != none)
	{
		MessageBoxOptions.AddItem(ConfirmHideAmmoButtonAccept);
		MessageBoxOptions.AddItem("<Strings:UTGameUI.ButtonCallouts.Cancel>");

		MessageBoxReference.SetPotentialOptions(MessageBoxOptions);
		MessageBoxReference.Display(Repl(ConfirmHideAmmoMessage, "  ", "\n"), ConfirmHideAmmoTitle, OnHideAmmo_Confirm, 1);
		return true;
	}

	ToggleAmmoTab(true);
	return true;
}

/** Buttonbar ShowAmmo Callback. */
function bool OnButtonBar_ShowAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	ToggleAmmoTab();

	return true;
}

/** Buttonbar TransferAmmo Callback. */
function bool OnButtonBar_TransferAmmo(UIScreenObject InButton, int InPlayerIndex)
{
	TransferAmmo();

	return true;
}

/**
 * Callback for the accept confirmation dialog box.
 *
 * @param SelectedOption	Selected item
 * @param PlayerIndex	Index of player that performed the action.
 */
function OnAccept_Confirm(UTUIScene_MessageBox MessageBox, int SelectedOption, int PlayerIndex)
{
	if(SelectedOption == 0)
	{
		OnAccept();
		CloseScene(self);
	}
}

/**
 * Callback for the ignore ammo replacement dialog box.
 *
 * @param SelectedOption	Selected item
 * @param PlayerIndex	Index of player that performed the action.
 */
function OnHideAmmo_Confirm(UTUIScene_MessageBox MessageBox, int SelectedOption, int PlayerIndex)
{
	if(SelectedOption == 0)
	{
		ToggleAmmoTab(true);
	}
}

/** Callback for when the user wants to back out of this screen. */
function OnBack()
{
	CloseScene(self);
}

function OnAccept()
{
	local int i;

	// save all dynamic pages
	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none)
		{
			DynamicPages[i].CreatedPage.SaveReplacements();
		}
	}
}

function OnReplacementsExtraSave_Weapons(TestCWRUITabList RefTab)
{
	local array<ReplacementInfoEx> WeaponReplacements, AmmoReplacements;

	if (!bAmmoVisible)
	{
		WeaponReplacements = RefTab.GetReplacements();
		AmmoReplacements = GetAmmoBasicReplacementsFor(WeaponReplacements);

		class'TestCentralWeaponReplacement'.static.SetConfigReplacements(RT_Ammo, AmmoReplacements);
	}
}

function ToggleAmmoTab(optional bool bForceHide)
{
	local int AmmoIdx, InsertIdx;
	local TestCWRUITabList TabPage;
	AmmoIdx = DynamicPages.Find('Tag', 'Ammo');
	if (AmmoIdx == INDEX_NONE)
		return;

	if (bAmmoVisible || bForceHide)
	{
		bAmmoVisible = false;
		if (DynamicPages[AmmoIdx].CreatedPage != none)
		{
			TabControl.RemovePage(DynamicPages[AmmoIdx].CreatedPage, GetBestPlayerIndex());
		}
	}
	else
	{
		bAmmoVisible = true;
		InsertIdx = DynamicPages.Find('Tag', DynamicPages[AmmoIdx].After);
		if (InsertIdx != INDEX_NONE) InsertIdx += 1;
		TabPage = CreateReplacementTab(TabControl, DynamicPages[AmmoIdx], InsertIdx, true);
		if (TabPage != none)
		{
			DynamicPages[AmmoIdx].CreatedPage = TabPage;
			TabPage.LoadReplacements(UIData);
		}

		if (!bAmmoInfoShown)
		{
			bAmmoInfoShown = true;
			DisplayMessageBox(Repl(CustomAmmoReplacementMessage, "  ", "\n"), CustomAmmoReplacementTitle);
		}
	}

	SetupButtonBar();
}

function TransferAmmo()
{
	local int WeaponIdx, AmmoIdx;
	local array<ReplacementInfoEx> WeaponReplacements, AmmoReplacements;

	WeaponIdx = DynamicPages.Find('Tag', 'Weapons');
	AmmoIdx = DynamicPages.Find('Tag', 'Ammo');
	if (WeaponIdx == INDEX_NONE || AmmoIdx == INDEX_NONE ||
		DynamicPages[WeaponIdx].CreatedPage == none || DynamicPages[AmmoIdx].CreatedPage == none)
		return;

	WeaponReplacements = DynamicPages[WeaponIdx].CreatedPage.GetReplacements();
	AmmoReplacements = GetAmmoBasicReplacementsFor(WeaponReplacements);

	if (AmmoReplacements.Length > 0)
	{
		DynamicPages[AmmoIdx].CreatedPage.AddReplacements(AmmoReplacements, true);
	}
}

function array<ReplacementInfoEx> GetAmmoBasicReplacementsFor(array<ReplacementInfoEx> WeaponReplacements)
{
	local ReplacementInfoEx Replacement;
	local int i;
	local name AmmoClassFrom;
	local string AmmoClassTo;
	local array<ReplacementInfoEx> Replacements;

	for (i=0; i<WeaponReplacements.Length; i++)
	{
		if (!UIData.GetAmmoInfoForWeapon(WeaponReplacements[i].OldClassName,, AmmoClassFrom))
			continue;

		Replacement.OldClassName = AmmoClassFrom;

		if (UIData.GetAmmoInfoForWeapon(WeaponReplacements[i].NewClassPath, AmmoClassTo))
		{
			Replacement.NewClassPath = AmmoClassTo;
		}
		else
		{
			Replacement.NewClassPath = "";
		}

		Replacements.AddItem(Replacement);
	}

	return Replacements;
}

function bool HasIgnoredOptions(out array<string> OutPages)
{
	local int i;
	local string str;

	for (i=0; i<DynamicPages.Length; i++)
	{
		if (DynamicPages[i].CreatedPage != none && DynamicPages[i].CreatedPage.IsIgnoringOptions())
		{
			str = GetTabString(DynamicPages[i].Tag);
			OutPages.AddItem(str);
		}
	}

	return OutPages.Length > 0;
}

function LoadTimed(optional float time = 2.0)
{
	local PlayerController PC;

	PC = GetPlayerOwner().Actor;
	if (PC != none)
	{
		PC.SetTimer(2.0, false, 'InitLoad', self);
	}
	else
	{
		InitLoad();
	}
}

function string GetTabString(name Tag)
{
	local int index;
	index = TitlesMapping.Find('Tag', Tag);
	if (index != INDEX_NONE)
	{
		return TitlesMapping[index].Text;
	}

	 Return Localize("Titles", string(Tag), string(class.GetPackageName()));
}

function TestCWRUITabList CreateReplacementTab(UTUITabControl InTabControl, DynamicPageInfo PageInfo, optional int InsertIndex = INDEX_NONE, optional bool bSkipActivate, optional int PlayerIndex=GetBestPlayerIndex())
{
	local TestCWRUITabList TabPage;
	Local name TabName;
	TabName = name("pnlTabRep_"$PageInfo.Tag);
	TabPage = TestCWRUITabList(CreateNamedTabPage(InTabControl, class'TestCWRUITabList', TabName));
	if (TabPage != none)
	{
		TabPage.SetTitle(Caps(GetTabString(PageInfo.Tag)));
		TabPage.SetReplacementInfo(PageInfo.ReplacementType, PageInfo.DatastoreReference);

		InTabControl.InsertPage(TabPage, PlayerIndex, InsertIndex, !bSkipActivate);
	}

	return TabPage;
}

static function UITabPage CreateNamedTabPage(UITabControl OwnerControl, class<UITabPage> TabPageClass, optional name WidgetName, optional UITabPage PagePrefab )
{
	local UITabPage TabPage;
	TabPage = UITabPage(OwnerControl.CreateWidget(OwnerControl, TabPageClass, PagePrefab, WidgetName));
	if (TabPage != none) TabPage.GetTabButton(OwnerControl);
	return TabPage;
}

DefaultProperties
{
	Title="[Central Weapon Replacement]"
	BuildingUIMessage="Building UI. May take some seconds..."

	ConfirmNoOptionsMessage="You have switched to simple mode but there are replacement options set for the following pages:  `pages    By continuing saving the replacements, the options will be cleared to default. Do you want to continue?"
	ConfirmNoOptionsTitle="Clear out options"
	ConfirmNoOptionsButtonAccept="CONTINUE"

	CustomAmmoReplacementMessage="By enabling custom ammo replacement, you have to either transfer all the ammo replacements from the current weapon replacement or setup your own replacements.    No ammo pickups will be replaced automatically by whatever weapon you choose to be replaced."
	CustomAmmoReplacementTitle="Custom ammo replacment"

	ConfirmHideAmmoMessage="You made changes to the ammo replacements. By switching back to simple ammo replacement (based on the selected weapons), you will loose any made changes to the ammo replacements.    Do you want to ignore these changes and switch to simple ammo replacement?"
	ConfirmHideAmmoTitle="Ignore custom replacements?"
	ConfirmHideAmmoButtonAccept="IGNORE"

	ShowAmmoCaption="CUSTOM AMMO"
	HideAmmoCaption="SIMPLE AMMO"
	TransferAmmoCaption="TRANSFER AMMO"

	TitlesMapping[0]=(Tag="Weapons",Text="Weapons")
	TitlesMapping[1]=(Tag="Healths",Text="Health")
	TitlesMapping[2]=(Tag="Armors",Text="Armor")
	TitlesMapping[3]=(Tag="Powerups",Text="Powerups")
	TitlesMapping[4]=(Tag="Deployables",Text="Deployables")
	TitlesMapping[5]=(Tag="Vehicles",Text="Vehicles")
	TitlesMapping[6]=(Tag="Customs",Text="Customs")
	TitlesMapping[7]=(Tag="Ammos",Text="Ammo")

	DynamicPages.Add((Tag="Weapons",ReplacementType=RT_Weapon,DatastoreReference="WeaponSelection"))
	DynamicPages.Add((Tag="Ammo",ReplacementType=RT_Ammo,DatastoreReference="AmmoSelection",Hidden=true,After="Weapons"))
	DynamicPages.Add((Tag="Healths",ReplacementType=RT_Health,DatastoreReference="HealthSelection"))
	DynamicPages.Add((Tag="Armors",ReplacementType=RT_Armor,DatastoreReference="ArmorSelection"))
	DynamicPages.Add((Tag="Powerups",ReplacementType=RT_Powerup,DatastoreReference="PowerupSelection"))
	DynamicPages.Add((Tag="Deployables",ReplacementType=RT_Deployable,DatastoreReference="DeployableSelection"))
	DynamicPages.Add((Tag="Vehicles",ReplacementType=RT_Vehicle,DatastoreReference="VehicleSelection"))
	DynamicPages.Add((Tag="Customs",ReplacementType=RT_Custom,DatastoreReference="CustomSelection",Hidden=true))
}


Update pb-to-cpp.uc

Update pb-to-cpp.uc

Removes array names from table in reverse order, otherwise ReadKey reaches out of bounds before the end of the loop.

# pb-to-cpp.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.5 on 1/15/2014 3:27:43 PM
# Comment: Converts PB source code to C++; modified by Daniel Corbier

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Converts PB source code to C++; modified by Daniel Corbier
Selected: False
Highlight: False
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Highlight: True
PassOnce: False
Find: {@Start}
Replace: // This file ({@Eval: Extract(ShortName(InputFile), ".")}.cpp) was converted from {@Eval: Extract(ShortName(InputFile), ".")}.Bas
         // with {@Eval: AppName} on {@Eval: TimeStamp()} using the Open Source
         // PowerBASIC to C++ converter found at https://github.com/uCalc/powerbasic-to-cpp

         {@Define:
            Var: Array As String
            Var: ArrayNames As Table
            Var: CleanUp As String
            Var: BitType As String
         }

Criteria: 2
Comment: Handles long line break (underscore _)
Pass: 1

Criteria: 3
Highlight: True
PassOnce: False
Find: {nl}{line} _ [{comment:".*"}] {nl}

Replace: {comment: ' {comment}{nl}}{nl}{line}{sp}

Criteria: 4
Highlight: True
SkipOver: True
Find: {"[\(\)]"} {@Note: These are ( and ); must be skipped}
Replace: [Skip over]

Criteria: 5
Highlight: True
SkipOver: True
Find: ' [{comment:".*"}]
Replace: [Skip over]

Criteria: 6
Comment: Processes some operators
Pass: 2

Criteria: 7
Comment: Bitwise AND and OR
Highlight: True
Find: ({expr%})
Replace: ({@Eval: Replace(Replace('{expr}', "&&", "&"), "||", "|")})

Criteria: 8
Comment: Logical (short-circuit) AND
Highlight: True
Find: And
Replace: &&

Criteria: 9
Comment: Logical (short-circuit) OR
Highlight: True
Find: Or
Replace: ||

Criteria: 10
Highlight: True
Find: Xor
Replace: ^

Criteria: 11
Highlight: True
Find: Not
Replace: ~

Criteria: 12
Highlight: True
Find: IsFalse
Replace: !

Criteria: 13
Highlight: True
Find: <>
Replace: !=

Criteria: 14
Highlight: True
Find: =
Replace: ==

Criteria: 15
Highlight: True
SkipOver: True
Find: { {nl}[%]|Then|Else|For|: } {var:" *[a-z\@\.]+"}[({index})] =
Replace: [Skip over]

Criteria: 16
Highlight: True
SkipOver: True
Find: { { #If | #ElseIf } Not | ' [{comment:".*"}] }
Replace: [Skip over]

Criteria: 17
Highlight: True
SkipOver: True
Find: Macro {name}[({params})] =
Replace: [Skip over]

Criteria: 18
Highlight: True
PassOnce: False
Find: Sub {name:1} [Alias {alias}]([{args}])[{exp: Export}] [{comment:" *'.*"}] {nl}
         {code+}
      End Sub
Replace: {exp:extern "C" __declspec(dllexport)} void {exp:__stdcall} {name}({args}) { {comment}
            {code}
         !!ReleaseDynamicArrays!!}

Criteria: 19
Highlight: True
BackColor: DarkKhaki
PassOnce: False
Find: Function {name:1} [Alias {alias}]([{args}])[{exp: Export}] As {type}[{comment:" *'.*"}]{nl}
         {code+}
      End Function
Replace: {exp:extern "C" __declspec(dllexport)} {type} {exp:__stdcall} {name}({args}) { {comment}
            {code}
         !!ReleaseDynamicArrays!!}

Criteria: 20
Highlight: True
PassOnce: False
Find: Function PBMain [()] [As Long]
Replace: Function main() As Long

Criteria: 21
Highlight: True
PassOnce: False
Find: Declare Function {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])] As {type}
Replace: {lib: extern __declspec(dllimport)} {type} {name}({args})

Criteria: 22
Highlight: True
Find: Declare Sub {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])]
Replace: {lib: extern __declspec(dllimport)} void {name}({args})

Criteria: 23
Highlight: True
Find: Static
Replace: static dim

Criteria: 24
Comment:
Pass: 3

Criteria: 25
Highlight: True
SkipOver: True
Find: // [{comment:".*"}]
Replace: [Skip over]

Criteria: 26
Highlight: True
Find: ' [{comment:".*"}]
Replace: // {comment}

Criteria: 27
Highlight: True
BackColor: Green
PassOnce: False
Find: {nl}%{equate} = {value}
Replace: {nl}const int {equate} = {value};

Criteria: 28
Highlight: True
BackColor: Green
Find: %{equate}
Replace: {equate}

Criteria: 29
Highlight: True
BackColor: SandyBrown
Find: {"&h"}
Replace: 0x

Criteria: 30
Highlight: True
BackColor: Green
PassOnce: False
Find: If {cond} Then {statement} [Else {else}]{nl}
Replace: if ({cond}) {{statement}{nl}}{else: else {{else}{nl}}}{nl}

Criteria: 31
Highlight: True
PassOnce: False
Find: If {cond} Then {nl}
         {code+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 32
Highlight: True
PassOnce: False
Find: For {x} = {start} To {stop} [Step {inc=1}]{nl}
         {code+}
      Next
Replace: for ({x}={start}; {x}{@Eval: IIF(sgn({inc})>0, '<', '>')}={stop}; {x} += {inc}) {
            {code}
         }

Criteria: 33
Highlight: True
PassOnce: False
Find: While {cond} {nl}
         {code+}
      Wend
Replace: while ({cond}) {
            {code}
         }

Criteria: 34
Highlight: True
PassOnce: False
Find: Do { {while: While} | {until: Until} } {cond} {nl}
         {code+}
      Loop
Replace: while ({while: {cond}}{until:!({cond})}) {
            {code}
         }

Criteria: 35
Highlight: True
PassOnce: False
Find: Do{nl}
         {code+}
      Loop { {while: While} | {until: Until} } {cond}
Replace: do {
            {code}
         } while ({while: {cond}}{until:!({cond})})

Criteria: 36
Selected: True
Highlight: True
Find: !!ReleaseDynamicArrays!!
Replace: {@Eval:
            CleanUp = ""
            uc_For(x, Count(ArrayNames), 1, -1,
               Array = ReadKey(ArrayNames, x)
               CleanUp=CleanUp+"delete[] "+Array+";{nl}"
               Delete(ArrayNames, Array)
            )
            CleanUp
         }

Criteria: 37
Highlight: True
BackColor: Orange
PassOnce: False
Find: { Dim | {member: {nl}}} {var:1} As {type} [{ptr: Ptr}]
Replace: {member: {nl}}{type} {ptr:*}{var};

Criteria: 38
Highlight: True
PassOnce: False
Find: {nl} {bitfield:1} As Bit * {size} [{in: In {type}}]
Replace: {nl}{@Eval:
            IIf("{type}" <> "", SetVar(BitType, "{type}"))
            BitType
         } {bitfield} : {size};

Criteria: 39
Highlight: True
PassOnce: False
Find: Dim {array}({subscript}) As {type}
Replace: {type} *{array} = new {type} [{subscript}+1];{@Eval:
            Insert(ArrayNames, "{array}")
         }{@Define:: Syntax: {array}({index}) ::= {array}[{index}]}

Criteria: 40
Highlight: True
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

Criteria: 41
Highlight: True
BackColor: Gold
PassOnce: False
Find: { Local | Global | Register }
Replace: Dim

Criteria: 42
Highlight: True
Find: @
Replace: *

Criteria: 43
Highlight: True
BackColor: Silver
Find: VarPtr({var})
Replace: &{var}

Criteria: 44
Highlight: True
BackColor: DeepSkyBlue
PassOnce: False
Find: Function = {value}
Replace: return {value};

Criteria: 45
Highlight: True
Find: Exit Sub
Replace: return;

Criteria: 46
Highlight: True
BackColor: Lime
Find: Long
Replace: int

Criteria: 47
Highlight: True
BackColor: Red
Find: Single
Replace: float

Criteria: 48
Highlight: True
Find: { Double | Extended | Ext }
Replace: double{@Note: May instead use "long double" for Extended}

Criteria: 49
Highlight: True
Find: Byte
Replace: unsigned char

Criteria: 50
Highlight: True
Find: Integer
Replace: short

Criteria: 51
Highlight: True
Find: Word
Replace: unsigned short

Criteria: 52
Highlight: True
Find: Dword
Replace: unsigned int

Criteria: 53
Find: AsciiZ
Replace: LPCSTR

Criteria: 54
Highlight: True
BackColor: SlateBlue
PassOnce: False
Find: ByRef {arg} As {type:1}
Replace: {type}& {arg}

Criteria: 55
Highlight: True
BackColor: Pink
PassOnce: False
Find: ByVal {arg} As {type:1} [{ptr: Ptr}]
Replace: {type} {ptr:*}{arg}

Criteria: 56
Highlight: True
PassOnce: False
Find: Type {name:1}
         {members+}
      End Type
Replace: struct {name} {
            {members}
         }

Criteria: 57
Highlight: True
Find: Macro {name} [{params: ({paramlist})}] = {replacement}
Replace: #define {name}{params} {replacement}

Criteria: 58
Highlight: True
Find: #If
Replace: #if

Criteria: 59
Highlight: True
Find: #Else
Replace: #else

Criteria: 60
Highlight: True
Find: #ElseIf
Replace: #elif

Criteria: 61
Highlight: True
Find: #EndIf
Replace: #endif

Criteria: 62
Highlight: True
PassOnce: False
Find: [{NOT: Not }] %Def({const})
Replace: {NOT:!}defined {const}

Criteria: 63
Comment: Adds semi-colons to statements
Pass: 4

Criteria: 64
Highlight: True
SkipOver: True
Find: { "{" | "}" | ; | //[{".*"}] | #{".*"} } {nl} [{"[ \n]+"}]
Replace: [Skip over]

Criteria: 65
Comment: Skips over so that colons in bit fields are not affected
Highlight: True
SkipOver: True
Find: struct {name:1} "{" {members+} "}"
Replace: [Skip over]

Criteria: 66
Highlight: True
Find: :
Replace: ;

Criteria: 67
Highlight: True
PassOnce: False
Find: {nl}
Replace: ;{nl}

Criteria: 68
Highlight: True
Find: Quad
Replace: __int64

# End Search

# pb-to-cpp.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.5 on 1/14/2014 7:19:30 PM
# Comment: Converts PB source code to C++; modified by Daniel Corbier

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Converts PB source code to C++; modified by Daniel Corbier
Selected: False
Highlight: False
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Highlight: True
PassOnce: False
Find: {@Start}
Replace: // This file ({@Eval: Extract(ShortName(InputFile), ".")}.cpp) was converted from {@Eval: Extract(ShortName(InputFile), ".")}.Bas
         // with {@Eval: AppName} on {@Eval: TimeStamp()} using the Open Source
         // PowerBASIC to C++ converter found at https://github.com/uCalc/powerbasic-to-cpp

         {@Define:
            Var: Array As String
            Var: ArrayNames As Table
            Var: CleanUp As String
            Var: BitType As String
         }

Criteria: 2
Comment: Handles long line break (underscore _)
Pass: 1

Criteria: 3
Highlight: True
PassOnce: False
Find: {nl}{line} _ [{comment:".*"}] {nl}

Replace: {comment: ' {comment}{nl}}{nl}{line}{sp}

Criteria: 4
Highlight: True
SkipOver: True
Find: {"[\(\)]"} {@Note: These are ( and ); must be skipped}
Replace: [Skip over]

Criteria: 5
Highlight: True
SkipOver: True
Find: ' [{comment:".*"}]
Replace: [Skip over]

Criteria: 6
Comment: Processes some operators
Pass: 2

Criteria: 7
Comment: Bitwise AND and OR
Highlight: True
Find: ({expr%})
Replace: ({@Eval: Replace(Replace('{expr}', "&&", "&"), "||", "|")})

Criteria: 8
Comment: Logical (short-circuit) AND
Highlight: True
Find: And
Replace: &&

Criteria: 9
Comment: Logical (short-circuit) OR
Highlight: True
Find: Or
Replace: ||

Criteria: 10
Highlight: True
Find: Xor
Replace: ^

Criteria: 11
Highlight: True
Find: Not
Replace: ~

Criteria: 12
Highlight: True
Find: IsFalse
Replace: !

Criteria: 13
Highlight: True
Find: <>
Replace: !=

Criteria: 14
Highlight: True
Find: =
Replace: ==

Criteria: 15
Highlight: True
SkipOver: True
Find: { {nl}[%]|Then|Else|For|: } {var:" *[a-z\@\.]+"}[({index})] =
Replace: [Skip over]

Criteria: 16
Highlight: True
SkipOver: True
Find: { { #If | #ElseIf } Not | ' [{comment:".*"}] }
Replace: [Skip over]

Criteria: 17
Highlight: True
SkipOver: True
Find: Macro {name}[({params})] =
Replace: [Skip over]

Criteria: 18
Highlight: True
PassOnce: False
Find: Sub {name:1} [Alias {alias}]([{args}])[{exp: Export}] [{comment:" *'.*"}] {nl}
         {code+}
      End Sub
Replace: {exp:extern "C" __declspec(dllexport)} void {exp:__stdcall} {name}({args}) { {comment}
            {code}
         !!ReleaseDynamicArrays!!}

Criteria: 19
Highlight: True
BackColor: DarkKhaki
PassOnce: False
Find: Function {name:1} [Alias {alias}]([{args}])[{exp: Export}] As {type}[{comment:" *'.*"}]{nl}
         {code+}
      End Function
Replace: {exp:extern "C" __declspec(dllexport)} {type} {exp:__stdcall} {name}({args}) { {comment}
            {code}
         !!ReleaseDynamicArrays!!}

Criteria: 20
Highlight: True
PassOnce: False
Find: Function PBMain [()] [As Long]
Replace: Function main() As Long

Criteria: 21
Highlight: True
PassOnce: False
Find: Declare Function {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])] As {type}
Replace: {lib: extern __declspec(dllimport)} {type} {name}({args})

Criteria: 22
Highlight: True
Find: Declare Sub {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])]
Replace: {lib: extern __declspec(dllimport)} void {name}({args})

Criteria: 23
Highlight: True
Find: Static
Replace: static dim

Criteria: 24
Comment:
Pass: 3

Criteria: 25
Highlight: True
SkipOver: True
Find: // [{comment:".*"}]
Replace: [Skip over]

Criteria: 26
Highlight: True
Find: ' [{comment:".*"}]
Replace: // {comment}

Criteria: 27
Highlight: True
BackColor: Green
PassOnce: False
Find: {nl}%{equate} = {value}
Replace: {nl}const int {equate} = {value};

Criteria: 28
Highlight: True
BackColor: Green
Find: %{equate}
Replace: {equate}

Criteria: 29
Highlight: True
BackColor: SandyBrown
Find: {"&h"}
Replace: 0x

Criteria: 30
Highlight: True
BackColor: Green
PassOnce: False
Find: If {cond} Then {statement} [Else {else}]{nl}
Replace: if ({cond}) {{statement}{nl}}{else: else {{else}{nl}}}{nl}

Criteria: 31
Highlight: True
PassOnce: False
Find: If {cond} Then {nl}
         {code+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 32
Highlight: True
PassOnce: False
Find: For {x} = {start} To {stop} [Step {inc=1}]{nl}
         {code+}
      Next
Replace: for ({x}={start}; {x}{@Eval: IIF(sgn({inc})>0, '<', '>')}={stop}; {x} += {inc}) {
            {code}
         }

Criteria: 33
Highlight: True
PassOnce: False
Find: While {cond} {nl}
         {code+}
      Wend
Replace: while ({cond}) {
            {code}
         }

Criteria: 34
Highlight: True
PassOnce: False
Find: Do { {while: While} | {until: Until} } {cond} {nl}
         {code+}
      Loop
Replace: while ({while: {cond}}{until:!({cond})}) {
            {code}
         }

Criteria: 35
Highlight: True
PassOnce: False
Find: Do{nl}
         {code+}
      Loop { {while: While} | {until: Until} } {cond}
Replace: do {
            {code}
         } while ({while: {cond}}{until:!({cond})})

Criteria: 36
Highlight: True
Find: !!ReleaseDynamicArrays!!
Replace: {@Eval:
            CleanUp = ""
            uc_For(x, 1, Count(ArrayNames), 1,
               Array = ReadKey(ArrayNames, x)
               CleanUp=CleanUp+"delete[] "+Array+";{nl}"
               Delete(ArrayNames, Array)
            )
            CleanUp
         }

Criteria: 37
Highlight: True
BackColor: Orange
PassOnce: False
Find: { Dim | {member: {nl}}} {var:1} As {type} [{ptr: Ptr}]
Replace: {member: {nl}}{type} {ptr:*}{var};

Criteria: 38
Highlight: True
PassOnce: False
Find: {nl} {bitfield:1} As Bit * {size} [{in: In {type}}]
Replace: {nl}{@Eval:
            IIf("{type}" <> "", SetVar(BitType, "{type}"))
            BitType
         } {bitfield} : {size};

Criteria: 39
Highlight: True
PassOnce: False
Find: Dim {array}({subscript}) As {type}
Replace: {type} *{array} = new {type} [{subscript}+1];{@Eval:
            Insert(ArrayNames, "{array}")
         }{@Define:: Syntax: {array}({index}) ::= {array}[{index}]}

Criteria: 40
Highlight: True
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

Criteria: 41
Highlight: True
BackColor: Gold
PassOnce: False
Find: { Local | Global | Register }
Replace: Dim

Criteria: 42
Highlight: True
Find: @
Replace: *

Criteria: 43
Highlight: True
BackColor: Silver
Find: VarPtr({var})
Replace: &{var}

Criteria: 44
Highlight: True
BackColor: DeepSkyBlue
PassOnce: False
Find: Function = {value}
Replace: return {value};

Criteria: 45
Highlight: True
Find: Exit Sub
Replace: return;

Criteria: 46
Highlight: True
BackColor: Lime
Find: Long
Replace: int

Criteria: 47
Highlight: True
BackColor: Red
Find: Single
Replace: float

Criteria: 48
Highlight: True
Find: { Double | Extended | Ext }
Replace: double{@Note: May instead use "long double" for Extended}

Criteria: 49
Highlight: True
Find: Byte
Replace: unsigned char

Criteria: 50
Highlight: True
Find: Integer
Replace: short

Criteria: 51
Highlight: True
Find: Word
Replace: unsigned short

Criteria: 52
Highlight: True
Find: Dword
Replace: unsigned int

Criteria: 53
Find: AsciiZ
Replace: LPCSTR

Criteria: 54
Highlight: True
BackColor: SlateBlue
PassOnce: False
Find: ByRef {arg} As {type:1}
Replace: {type}& {arg}

Criteria: 55
Highlight: True
BackColor: Pink
PassOnce: False
Find: ByVal {arg} As {type:1} [{ptr: Ptr}]
Replace: {type} {ptr:*}{arg}

Criteria: 56
Highlight: True
PassOnce: False
Find: Type {name:1}
         {members+}
      End Type
Replace: struct {name} {
            {members}
         }

Criteria: 57
Highlight: True
Find: Macro {name} [{params: ({paramlist})}] = {replacement}
Replace: #define {name}{params} {replacement}

Criteria: 58
Highlight: True
Find: #If
Replace: #if

Criteria: 59
Highlight: True
Find: #Else
Replace: #else

Criteria: 60
Highlight: True
Find: #ElseIf
Replace: #elif

Criteria: 61
Highlight: True
Find: #EndIf
Replace: #endif

Criteria: 62
Highlight: True
PassOnce: False
Find: [{NOT: Not }] %Def({const})
Replace: {NOT:!}defined {const}

Criteria: 63
Comment: Adds semi-colons to statements
Pass: 4

Criteria: 64
Highlight: True
SkipOver: True
Find: { "{" | "}" | ; | //[{".*"}] | #{".*"} } {nl} [{"[ \n]+"}]
Replace: [Skip over]

Criteria: 65
Comment: Skips over so that colons in bit fields are not affected
Highlight: True
SkipOver: True
Find: struct {name:1} "{" {members+} "}"
Replace: [Skip over]

Criteria: 66
Highlight: True
Find: :
Replace: ;

Criteria: 67
Highlight: True
PassOnce: False
Find: {nl}
Replace: ;{nl}

Criteria: 68
Selected: True
Highlight: True
Find: Quad
Replace: __int64

# End Search


Update filehandler.uc

Update filehandler.uc

Added PRINT #

# filehandler.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/11/2014 7:02:25 PM
# Comment: File handler

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: File handler
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Comment:
Pass: 1

Criteria: 2
BackColor: Yellow
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 3
BackColor: DeepSkyBlue
Find: {@Start}
Replace: #include <iostream>
         #include <fstream>
         {@Var: FreeFileNum}

Criteria: 4
BackColor: DeepSkyBlue
Find: Open {filespec}
      { For {{Input: Input}|{Output: Output}|{Append: Append}|{Binary: Binary}|{Random: Random}}|{Default: } }
      { Access Read | Access Write | Access Read Write | }
      { Lock {{LockRead: Read}|{LockWrite: Write}|{LockBoth: Read Write}|{LockShared: Shared}}|{LockDefault: } }
      As [#]{filenum} [Len = {size=128}]
Replace: fstream file_{filenum} (string({filespec}).c_str(),
            {Input:   ios::in}
            {Output:  ios::out | ios::trunc}
            {Append:  ios::out | ios::app}
            {Binary:  ios::binary | ios::in | ios::out}
            {Random:  ios::binary | ios::in | ios::out}
            {Default: ios::binary | ios::in | ios::out}
         );

Criteria: 5
BackColor: Lime
Find: Close [#]{filenum}
Replace: file_{filenum}.close() ' PB: Close #{filenum}

Criteria: 6
BackColor: RoyalBlue
PassOnce: False
Find: Close [#]{file1}, {more}
Replace: Close {file1}
         Close {more}

Criteria: 7
BackColor: Pink
Find: Seek [#] {filenum}, {position}
Replace: file_{filenum}.seekg({position}-1)
         file_{filenum}.seekp({position}-1)

Criteria: 8
Find: Seek([#] {filenum})
Replace: file_{filenum}.tellg()+1

Criteria: 9
BackColor: SlateBlue
Find: LOF({filenum})
Replace: (missing)

Criteria: 10
Find: EOF({filenum})
Replace: file_{filenum}.eof()

Criteria: 11
Find: FreeFile
Replace: {@Eval: FreeFileNum += 1; FreeFileNum}

Criteria: 12
BackColor: Green
Find: Get$ [#] {filenum}, {count}, {StringVar}
Replace: {StringVar}.resize({count})
         file_{filenum}.read(&{StringVar}[0], {count})

Criteria: 13
BackColor: SandyBrown
Find: Put$ [#] {filenum}, {text}
Replace: file_{filenum}.write(&{text}[0], {text}.size())

Criteria: 14
Find: IsFile({file})
Replace: PB_ISFILE({file})

Criteria: 15
BackColor: Gold
Find: EXE.Extn$
Replace: PB_EXE_EXTN

Criteria: 16
BackColor: Silver
Find: EXE.Full$
Replace: PB_EXE_FULL()

Criteria: 17
Find: EXE.Name$
Replace: PB_EXE_NAME

Criteria: 18
BackColor: CornflowerBlue
Find: EXE.Namex$
Replace: PB_EXE_NAMEX

Criteria: 19
Find: EXE.Path$
Replace: PB_EXE_PATH

Criteria: 20
Find: Dir$({mask})
Replace: PB_DIR({mask})

Criteria: 21
Find: Dir$([Next])
Replace: PB_DIR_NEXT()

Criteria: 22
Selected: True
Find: Print #{filenum}, {text}
Replace: file_{filenum} << {text} << endl;

Criteria: 23
Comment:
Pass: 2

Criteria: 24
BackColor: Yellow
Find: fstream {file} ({args+})
Replace: {@Eval: Replace('{Self}', '{"[ \n]+"}', ' ')}

# End Search

# filehandler.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.5 on 3/6/2014 11:27:00 AM
# Comment: File handler

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: File handler
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Comment:
Pass: 1

Criteria: 2
BackColor: Yellow
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 3
BackColor: DeepSkyBlue
Find: {@Start}
Replace: #include <iostream>
         #include <fstream>
         {@Var: FreeFileNum}

Criteria: 4
BackColor: DeepSkyBlue
Find: Open {filespec}
      { For {{Input: Input}|{Output: Output}|{Append: Append}|{Binary: Binary}|{Random: Random}}|{Default: } }
      { Access Read | Access Write | Access Read Write | }
      { Lock {{LockRead: Read}|{LockWrite: Write}|{LockBoth: Read Write}|{LockShared: Shared}}|{LockDefault: } }
      As [#]{filenum} [Len = {size=128}]
Replace: fstream file_{filenum} (string({filespec}).c_str(),
            {Input:   ios::in}
            {Output:  ios::out | ios::trunc}
            {Append:  ios::out | ios::app}
            {Binary:  ios::binary | ios::in | ios::out}
            {Random:  ios::binary | ios::in | ios::out}
            {Default: ios::binary | ios::in | ios::out}
         );

Criteria: 5
BackColor: Lime
Find: Close [#]{filenum}
Replace: file_{filenum}.close() ' PB: Close #{filenum}

Criteria: 6
BackColor: RoyalBlue
PassOnce: False
Find: Close [#]{file1}, {more}
Replace: Close {file1}
         Close {more}

Criteria: 7
BackColor: Pink
Find: Seek [#] {filenum}, {position}
Replace: file_{filenum}.seekg({position}-1)
         file_{filenum}.seekp({position}-1)

Criteria: 8
Find: Seek([#] {filenum})
Replace: file_{filenum}.tellg()+1

Criteria: 9
BackColor: SlateBlue
Find: LOF({filenum})
Replace: (missing)

Criteria: 10
Find: EOF({filenum})
Replace: file_{filenum}.eof()

Criteria: 11
Find: FreeFile
Replace: {@Eval: FreeFileNum += 1; FreeFileNum}

Criteria: 12
BackColor: Green
Find: Get$ [#] {filenum}, {count}, {StringVar}
Replace: {StringVar}.resize({count})
         file_{filenum}.read(&{StringVar}[0], {count})

Criteria: 13
BackColor: SandyBrown
Find: Put$ [#] {filenum}, {text}
Replace: file_{filenum}.write(&{text}[0], {text}.size())

Criteria: 14
Find: IsFile({file})
Replace: PB_ISFILE({file})

Criteria: 15
BackColor: Gold
Find: EXE.Extn$
Replace: PB_EXE_EXTN

Criteria: 16
BackColor: Silver
Find: EXE.Full$
Replace: PB_EXE_FULL()

Criteria: 17
Find: EXE.Name$
Replace: PB_EXE_NAME

Criteria: 18
BackColor: CornflowerBlue
Find: EXE.Namex$
Replace: PB_EXE_NAMEX

Criteria: 19
Find: EXE.Path$
Replace: PB_EXE_PATH

Criteria: 20
Find: Dir$({mask})
Replace: PB_DIR({mask})

Criteria: 21
Selected: True
Find: Dir$([Next])
Replace: PB_DIR_NEXT()

Criteria: 22
Comment:
Pass: 2

Criteria: 23
BackColor: Yellow
Find: fstream {file} ({args+})
Replace: {@Eval: Replace('{Self}', '{"[ \n]+"}', ' ')}

# End Search


Update strings.uc

Update strings.uc

Added Hex$(), Oct$()
Updated Str$() so it supports precision arg (in pbstrings.h)
Combined UCase$() and LCase$() into the same pattern as other similar string patterns

# strings.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/21/2014 12:43:54 PM
# Comment: Converts string-related code from PowerBASIC to C++

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Converts string-related code from PowerBASIC to C++
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Find: {@Start}
Replace: #include <algorithm>
         #include <string>
         #include <sstream>
         #include "pbstrings.h"
         using namespace std;{nl}{nl}

Criteria: 2
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 3
Find: String
Replace: string

Criteria: 4
Find: WString
Replace: wstring

Criteria: 5
BackColor: DodgerBlue
PassOnce: False
Find: InStr([{n=1},] {MainStr}, {MatchStr})
Replace: PB_INSTR({n}, {MainStr}, {MatchStr})

Criteria: 6
BackColor: Tomato
PassOnce: False
Find: InStr([{n=1},] {MainStr}, Any {MatchStr})
Replace: PB_INSTR_ANY({n}, {MainStr}, {MatchStr})

Criteria: 7
BackColor: Red
PassOnce: False
Find: Left$({Str}, {n})
Replace: PB_LEFT({Str}, {n})

Criteria: 8
BackColor: Brown
PassOnce: False
Find: Right$({Str}, {n})
Replace: PB_RIGHT({Str}, {n})

Criteria: 9
BackColor: Orange
PassOnce: False
Find: Mid$({Str}, {Start} [, {Length=FULL_STRING}])
Replace: PB_MID({Str}, {Start}, {Length})

Criteria: 10
BackColor: DeepSkyBlue
PassOnce: False
Find: {Sep: {nl} | : | Then | Else }
      Mid$({Str}, {Start} [, {Length=FULL_STRING}]) = {Txt%}
Replace: {Sep} PB_MID_REPLACE({Str}, {Txt}, {Start}, {Length})

Criteria: 11
BackColor: RoyalBlue
PassOnce: False
Find: Val({Str})
Replace: stold({Str})

Criteria: 12
Selected: True
Find: Space$({count})
Replace: string({count}, _char( ))

Criteria: 13
Find: String$({count}, {char})
Replace: string({count}, {char})

Criteria: 14
BackColor: Violet
Find: String$({count}, {q}{char}{q})
Replace: string({count}, _char({char}))

Criteria: 15
Find: {function: UCase | LCase | Hex | Oct | Str}$({arg})
Replace: PB_{@Eval: UCase("{function}", "{'.*'}")}({arg})

Criteria: 16
Find: Trim$({Str} [, ANY {chars=" "}])
Replace: PB_TRIM_ANY({Str}, {chars})

Criteria: 17
BackColor: Gold
Find: LTrim$({Str} [, ANY {chars=" "}])
Replace: PB_LTRIM_ANY({Str}, {chars})

Criteria: 18
BackColor: Silver
Find: RTrim$({Str} [, ANY {chars=" "}])
Replace: PB_RTRIM_ANY({Str}, {chars})

Criteria: 19
Find: Extract$([{start=1},] {MainStr}, {MatchStr})
Replace: PB_EXTRACT({start}, {MainStr}, {MatchStr})

Criteria: 20
Find: Extract$([{start=1},] {MainStr}, Any {MatchStr})
Replace: PB_EXTRACT_ANY({start}, {MainStr}, {MatchStr})

Criteria: 21
Find: Remain$([{start=1},] {MainStr}, {MatchStr})
Replace: PB_REMAIN({start}, {MainStr}, {MatchStr})

Criteria: 22
Find: Remain$([{start=1},] {MainStr}, Any {MatchStr})
Replace: PB_REMAIN_ANY({start}, {MainStr}, {MatchStr})

Criteria: 23
Find: Remove$({Str}, {MatchStr})
Replace: PB_REMOVE({Str}, {MatchStr})

Criteria: 24
Find: Remove$({Str}, Any {MatchStr})
Replace: PB_REMOVE_ANY({Str}, {MatchStr})

Criteria: 25
Find: Replace {MatchStr} With {NewStr} In {MainStr}
Replace: PB_REPLACE({MainStr}, {MatchStr}, {NewStr})

Criteria: 26
Find: Replace Any {MatchStr} With {NewStr} In {MainStr}
Replace: PB_REPLACE_ANY({MainStr}, {MatchStr}, {NewStr})

Criteria: 27
Find: Repeat$({count}, {Str})
Replace: PB_REPEAT({Str}, {count})

Criteria: 28
Find: Asc({Str}[, {pos=1}])
Replace: PB_ASC({Str}, {pos})

Criteria: 29
Find: ${equate: NUL|BEL|BS|TAB|LF|VT|FF|CR|CRLF|EOF|ESC|SPC|DQ|SQ|QCQ }
Replace: PB_{@Eval: UCase("{equate}", "{'.*'}")}

# End Search

# strings.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/19/2014 12:58:24 PM
# Comment: Converts string-related code from PowerBASIC to C++

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Converts string-related code from PowerBASIC to C++
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Find: {@Start}
Replace: #include <algorithm>
         #include <string>
         #include "pbstrings.h"
         using namespace std;{nl}{nl}

Criteria: 2
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 3
Find: String
Replace: string

Criteria: 4
Selected: True
Find: WString
Replace: wstring

Criteria: 5
BackColor: DodgerBlue
PassOnce: False
Find: InStr([{n=1},] {MainStr}, {MatchStr})
Replace: PB_INSTR({n}, {MainStr}, {MatchStr})

Criteria: 6
BackColor: Tomato
PassOnce: False
Find: InStr([{n=1},] {MainStr}, Any {MatchStr})
Replace: PB_INSTR_ANY({n}, {MainStr}, {MatchStr})

Criteria: 7
BackColor: Red
PassOnce: False
Find: Left$({Str}, {n})
Replace: PB_LEFT({Str}, {n})

Criteria: 8
BackColor: Brown
PassOnce: False
Find: Right$({Str}, {n})
Replace: PB_RIGHT({Str}, {n})

Criteria: 9
BackColor: Orange
PassOnce: False
Find: Mid$({Str}, {Start} [, {Length=FULL_STRING}])
Replace: PB_MID({Str}, {Start}, {Length})

Criteria: 10
BackColor: DeepSkyBlue
PassOnce: False
Find: {Sep: {nl} | : | Then | Else }
      Mid$({Str}, {Start} [, {Length=FULL_STRING}]) = {Txt%}
Replace: {Sep} PB_MID_REPLACE({Str}, {Txt}, {Start}, {Length})

Criteria: 11
BackColor: RoyalBlue
PassOnce: False
Find: Val({Str})
Replace: stold({Str})

Criteria: 12
BackColor: Pink
PassOnce: False
Find: Str$({Number})
Replace: to_string((long double){Number})

Criteria: 13
Find: Space$({count})
Replace: string({count}, _char( ))

Criteria: 14
Find: String$({count}, {char})
Replace: string({count}, {char})

Criteria: 15
BackColor: Violet
Find: String$({count}, {q}{char}{q})
Replace: string({count}, _char({char}))

Criteria: 16
Find: UCase$({text})
Replace: PB_UCASE({text})

Criteria: 17
BackColor: YellowGreen
Find: LCase$({text})
Replace: PB_LCASE({text})

Criteria: 18
Find: Trim$({Str} [, ANY {chars=" "}])
Replace: PB_TRIM_ANY({Str}, {chars})

Criteria: 19
BackColor: Gold
Find: LTrim$({Str} [, ANY {chars=" "}])
Replace: PB_LTRIM_ANY({Str}, {chars})

Criteria: 20
BackColor: Silver
Find: RTrim$({Str} [, ANY {chars=" "}])
Replace: PB_RTRIM_ANY({Str}, {chars})

Criteria: 21
Find: Extract$([{start=1},] {MainStr}, {MatchStr})
Replace: PB_EXTRACT({start}, {MainStr}, {MatchStr})

Criteria: 22
Find: Extract$([{start=1},] {MainStr}, Any {MatchStr})
Replace: PB_EXTRACT_ANY({start}, {MainStr}, {MatchStr})

Criteria: 23
Find: Remain$([{start=1},] {MainStr}, {MatchStr})
Replace: PB_REMAIN({start}, {MainStr}, {MatchStr})

Criteria: 24
Find: Remain$([{start=1},] {MainStr}, Any {MatchStr})
Replace: PB_REMAIN_ANY({start}, {MainStr}, {MatchStr})

Criteria: 25
Find: Remove$({Str}, {MatchStr})
Replace: PB_REMOVE({Str}, {MatchStr})

Criteria: 26
Find: Remove$({Str}, Any {MatchStr})
Replace: PB_REMOVE_ANY({Str}, {MatchStr})

Criteria: 27
Find: Replace {MatchStr} With {NewStr} In {MainStr}
Replace: PB_REPLACE({MainStr}, {MatchStr}, {NewStr})

Criteria: 28
Find: Replace Any {MatchStr} With {NewStr} In {MainStr}
Replace: PB_REPLACE_ANY({MainStr}, {MatchStr}, {NewStr})

Criteria: 29
Find: Repeat$({count}, {Str})
Replace: PB_REPEAT({Str}, {count})

Criteria: 30
Find: Asc({Str}[, {pos=1}])
Replace: PB_ASC({Str}, {pos})

Criteria: 31
Find: ${equate: NUL|BEL|BS|TAB|LF|VT|FF|CR|CRLF|EOF|ESC|SPC|DQ|SQ|QCQ }
Replace: PB_{@Eval: UCase("{equate}", "{'.*'}")}

# End Search


Update implicit-dim.uc

Update implicit-dim.uc

Function name is no longer included in list of implicit local variables

# implicit-dim.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.96 on 5/15/2014 3:33:12 PM
# Comment: Declares variables (with Dim) that were not explicitely declared before

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Declares variables (with Dim) that were not explicitely declared before
Selected: False
Highlight: False
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile: ImplicitDim.Bas
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Find: {@Note:

         This transform does the following:

         * Declares variables that were not previously declared explicitely
         * Comments out user declarations that are from the Windows API
         * Ensures that the casing of variables/functions is consistent
           with their declarations since C++ is case-sensitive

      }

Replace: {@Define::
            Token: \x27.* ~~ Properties: ucWhitespace
            Token: _[^\n]*\n ~~ Properties: ucWhitespace
         }
         {@Define:
            Var: Globals As Table
            Var: ImplicitDim As Table
            Var: ExplicitDim As Table
            Var: CurrentRoutine As String
            Var: Prototype As String
            Var: Prototypes As String
            Var: ExpIndex As Long
            Var: ImpIndex As Long
            Var: FuncIndex As Long
            Var: GlobalIndex As Long
            SyntaxArg: NameAndSpecifier = "[a-z][a-z0-9_]*[$#!?%&]*"
         }
         {@Exec:
            Split(File("WinAPIKeywords.txt"))
            uc_For(x, 1, StringItemCount, 2, Insert(Globals, StringItem(x)))
         }

Criteria: 2
Comment: Teporarily adds Dim keyword in front of args for further parsing
Pass: 1

Criteria: 3
Find: {nl}{routine: Sub | Function } {etc}([{args}]) [[{exp: Export}] As {type:1}]
Replace: {@Eval:
            Prototype = {Q}{routine} {etc}({args:Dim {args}}){exp}{type: As {type}}{Q}
            Prototypes += "{nl}Declare " + Prototype
            "{nl}" + Prototype
         }

Criteria: 4
SkipOver: True
Find: {nl}Function =
Replace: [Skip over]

Criteria: 5
Comment: Inserts explicitly Dimmed variable names in global or local tables
Pass: 2

Criteria: 6
PassOnce: False
Find: {@Start}
Replace: ' Prototypes
         {@Eval: Prototypes}
         ' End of prototypes{nl}

Criteria: 7
Find: Global{" +"}{variable:NameAndSpecifier}
Replace: {Self}{@Evaluate: Insert(Globals, {variable})}

Criteria: 8
BackColor: Silver
Find: {nl}{ Macro | Type | Union | % | $[$] | Declare {func:1} }  {name:1}
Replace: {Self}{@Evaluate: Insert(Globals, {name})}

Criteria: 9
BackColor: Lime
Find: {nl}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"}
Replace: {Self}{@Define:
            Var: {RoutineName}ExplicitDim As Table
            Var: {RoutineName}ImplicitDim As Table
         }{@Eval: SetVar(CurrentRoutine, "{RoutineName}"); Insert(Globals,"{RoutineName}")}

Criteria: 10
Find: {nl}End { Sub | Function }
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, "")}

Criteria: 11
BackColor: Pink
Find: {declare: Dim [[Optional] { ByVal | ByRef }] | Local | Static | Register | fstream }
      {" +"}{variable:NameAndSpecifier}
Replace: {Self}{@Eval: Insert(~Eval(CurrentRoutine)ExplicitDim, "{variable}")}

Criteria: 12
Comment: Temporarily inserts declaration for each individual variable a lines with a list of multiple vars, for easier parsing
BackColor: SlateBlue
PassOnce: False
Find: {declare: Global|Dim|Local|Static|Register} {variable},
Replace: {declare} {variable} ::: {declare}

Criteria: 13
Find: {nl}%{equate:1} = {@If: Index(Globals, {equate})}
Replace: {nl} ' <WinAPI> {equate} =

Criteria: 14
Find: {nl}Declare {method: Sub | Function } {name:1}  {@If: Index(Globals, {name})}
Replace: {nl} ' <WinAPI> Declare {method} {name}

Criteria: 15
Comment: Places non-Dimmed variable names in separate local tables
Pass: 3

Criteria: 16
Find: [{eq: %}]{name:NameAndSpecifier} [{IsFunc:" *\("}]
Replace: {eq}{@Eval:
            ExpIndex    = Index(~Eval(CurrentRoutine)ExplicitDim, "{name}")
            ImpIndex    = Index(~Eval(CurrentRoutine)ImplicitDim, "{name}")
            FuncIndex   = Index(Globals, Remove("{name}", "{'[$#!?%&]+'}"))
            GlobalIndex = Index(Globals, "{name}")
            IIf(ExpIndex+ImpIndex+FuncIndex+GlobalIndex == 0 And "{IsFunc}" == "",
                Insert(~Eval(CurrentRoutine)ImplicitDim, "{name}"))

            text = "{name}"
            IIf(GlobalIndex, text = ReadKey(Globals, GlobalIndex))
            IIf(ExpIndex, text = ReadKey(~Eval(CurrentRoutine)ExplicitDim, ExpIndex))
            IIf(ImpIndex, text = ReadKey(~Eval(CurrentRoutine)ImplicitDim, ImpIndex))
            text + "{IsFunc}"
         }

Criteria: 17
SkipOver: True
Find: {"[a-z0-9_]+"}  {UDT:"\.[a-z0-9_\@\.]+"}
Replace: [Skip over]

Criteria: 18
SkipOver: True
Find: {"&h[0-9a-f]+"}
Replace: [Skip over]

Criteria: 19
SkipOver: True
Find: {@Eval: "{'"+Retain(FileText("PBKeywords.txt"), "{keyword:'.*'}", Delim("\b|"))+"\b'}"}
Replace: [Skip over]

Criteria: 20
BackColor: Brown
Find: {"\n"}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"}
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, {RoutineName})}

Criteria: 21
Find: {"\n"}End { Sub | Function }
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, "")}

Criteria: 22
Comment: Inserts local Dim statements for variables that were not dimmed
Pass: 4

Criteria: 23
BackColor: Purple
Find: {nl}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"} {etc}
Replace: {Self}
         {@Eval:
            Range(1, Count({RoutineName}ImplicitDim),
            {Q}"   Dim "+ReadKey({RoutineName}ImplicitDim, x)+" ' Implicit"+Chr(10){Q})
         }

Criteria: 24
Comment: Clean up (temp declaration statements removed)
Pass: 5

Criteria: 25
BackColor: Violet
Find: ::: {declare:1}
Replace: ,

Criteria: 26
BackColor: CornflowerBlue
Find: (Dim {args})
Replace: ({@Eval: Replace("{args}", "::: Dim", ",")})

Criteria: 27
Find: Dim {nl}
Replace: {Nothing}

# End Search

# implicit-dim.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.96 on 5/14/2014 9:09:03 AM
# Comment: Declares variables (with Dim) that were not explicitely declared before

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: Declares variables (with Dim) that were not explicitely declared before
Selected: False
Highlight: False
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile: ImplicitDim.Bas
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Find: {@Note:

         This transform does the following:

         * Declares variables that were not previously declared explicitely
         * Comments out user declarations that are from the Windows API
         * Ensures that the casing of variables/functions is consistent
           with their declarations since C++ is case-sensitive

      }

Replace: {@Define::
            Token: \x27.* ~~ Properties: ucWhitespace
            Token: _[^\n]*\n ~~ Properties: ucWhitespace
         }
         {@Define:
            Var: Globals As Table
            Var: ImplicitDim As Table
            Var: ExplicitDim As Table
            Var: CurrentRoutine As String
            Var: Prototype As String
            Var: Prototypes As String
            Var: ExpIndex As Long
            Var: ImpIndex As Long
            Var: GlobalIndex As Long
         }
         {@Exec:
            Split(File("WinAPIKeywords.txt"))
            uc_For(x, 1, StringItemCount, 2, Insert(Globals, StringItem(x)))
         }

Criteria: 2
Comment: Teporarily adds Dim keyword in front of args for further parsing
Pass: 1

Criteria: 3
Selected: True
Find: {nl}{routine: Sub | Function } {etc}([{args}]) [[{exp: Export}] As {type:1}]
Replace: {@Eval:
            Prototype = {Q}{routine} {etc}({args:Dim {args}}){type: {exp} As {type}}{Q}
            Prototypes += "{nl}Declare " + Prototype
            "{nl}" + Prototype
         }

Criteria: 4
SkipOver: True
Find: {nl}Function =
Replace: [Skip over]

Criteria: 5
Comment: Inserts explicitly Dimmed variable names in global or local tables
Pass: 2

Criteria: 6
PassOnce: False
Find: {@Start}
Replace: ' Prototypes
         {@Eval: Prototypes}
         ' End of prototypes{nl}

Criteria: 7
Find: Global{" +"}{variable:"[a-z][a-z0-9_]*[#!?%&]*"}
Replace: {Self}{@Evaluate: Insert(Globals, {variable})}

Criteria: 8
BackColor: Silver
Find: {nl}{ Macro | Type | Union | % | $[$] | Declare {func:1} }  {name:1}
Replace: {Self}{@Evaluate: Insert(Globals, {name})}

Criteria: 9
BackColor: Lime
Find: {nl}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"}
Replace: {Self}{@Define:
            Var: {RoutineName}ExplicitDim As Table
            Var: {RoutineName}ImplicitDim As Table
         }{@Eval: SetVar(CurrentRoutine, "{RoutineName}"); Insert(Globals,"{RoutineName}")}

Criteria: 10
Find: {nl}End { Sub | Function }
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, "")}

Criteria: 11
BackColor: Pink
Find: {declare: Dim [[Optional] { ByVal | ByRef }] | Local | Static | Register | fstream }
      {" +"}{variable:"[a-z][a-z0-9_]*[#!?%&]*"}
Replace: {Self}{@Eval: Insert(~Eval(CurrentRoutine)ExplicitDim, "{variable}")}

Criteria: 12
Comment: Temporarily inserts declaration for each individual variable a lines with a list of multiple vars, for easier parsing
BackColor: SlateBlue
PassOnce: False
Find: {declare: Global|Dim|Local|Static|Register} {variable},
Replace: {declare} {variable} ::: {declare}

Criteria: 13
Find: {nl}%{equate:1} = {@If: Index(Globals, {equate})}
Replace: {nl} ' <WinAPI> {equate} =

Criteria: 14
Find: {nl}Declare {method: Sub | Function } {name:1}  {@If: Index(Globals, {name})}
Replace: {nl} ' <WinAPI> Declare {method} {name}

Criteria: 15
Comment: Places non-Dimmed variable names in separate local tables
Pass: 3

Criteria: 16
Find: [{eq: %}]{name:"[a-z][a-z0-9_]*[#!?%&]*"} [{IsFunc:" *\("}]
Replace: {eq}{@Eval:
            ExpIndex    = Index(~Eval(CurrentRoutine)ExplicitDim, "{name}")
            ImpIndex    = Index(~Eval(CurrentRoutine)ImplicitDim, "{name}")
            GlobalIndex = Index(Globals, "{name}")
            IIf(ExpIndex+ImpIndex+GlobalIndex == 0 And "{IsFunc}" == "",
                Insert(~Eval(CurrentRoutine)ImplicitDim, "{name}"))

            text = "{name}"
            IIf(GlobalIndex, text = ReadKey(Globals, GlobalIndex))
            IIf(ExpIndex, text = ReadKey(~Eval(CurrentRoutine)ExplicitDim, ExpIndex))
            IIf(ImpIndex, text = ReadKey(~Eval(CurrentRoutine)ImplicitDim, ImpIndex))
            text + "{IsFunc}"
         }

Criteria: 17
SkipOver: True
Find: {"[a-z0-9_]+"}  {UDT:"\.[a-z0-9_\@\.]+"}
Replace: [Skip over]

Criteria: 18
SkipOver: True
Find: {"&h[0-9a-f]+"}
Replace: [Skip over]

Criteria: 19
SkipOver: True
Find: {@Eval: "{'"+Retain(FileText("PBKeywords.txt"), "{keyword:'.*'}", Delim("\b|"))+"\b'}"}
Replace: [Skip over]

Criteria: 20
BackColor: Brown
Find: {"\n"}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"}
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, {RoutineName})}

Criteria: 21
Find: {"\n"}End { Sub | Function }
Replace: {Self}{@Evaluate: SetVar(CurrentRoutine, "")}

Criteria: 22
Comment: Inserts local Dim statements for variables that were not dimmed
Pass: 4

Criteria: 23
BackColor: Purple
Find: {nl}{ Sub | Function }{" +"}{RoutineName:"[a-z0-9_]+"} {etc}
Replace: {Self}
         {@Eval:
            Range(1, Count({RoutineName}ImplicitDim),
            {Q}"   Dim "+ReadKey({RoutineName}ImplicitDim, x)+" ' Implicit"+Chr(10){Q})
         }

Criteria: 24
Comment: Clean up (temp declaration statements removed)
Pass: 5

Criteria: 25
BackColor: Violet
Find: ::: {declare:1}
Replace: ,

Criteria: 26
BackColor: CornflowerBlue
Find: (Dim {args})
Replace: ({@Eval: Replace("{args}", "::: Dim", ",")})

Criteria: 27
Find: Dim {nl}
Replace: {Nothing}

# End Search