Implement Issue #1118

Implement Issue #1118

//---------------------------------------------------------------------------------------
//  FILE:    UICharacterPool_ListPools.uc
//  AUTHOR:  Brit Steiner --  9/4/2014
//  PURPOSE: ListPools menu in the character pool system.
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------

class UICharacterPool_ListPools extends UIScreen
	dependson(CharacterPoolManager);

//----------------------------------------------------------------------------
// MEMBERS

// UI
var UIPanel	Container;
var UIBGBox    BG;
var UIList		List;
var UIButton	AcceptButton;
var UIX2PanelHeader TitleHeader;
var UINavigationHelp NavHelp;

//Default (active) pool
var CharacterPoolManager CharacterPoolMgr;

//Passed in by UICharacterPool if we're exporting
var public array<XComGameState_Unit> UnitsToExport;

var array<string> Data;
var bool bIsExporting;
var bool bHasSelectedImportLocation;

var localized public string m_strTitle;
var localized public string m_strTitleImportPoolLocation;
var localized public string m_strExportSubtitle;
var localized public string m_strImportSubtitle;
var localized public string m_strCreateNewPool;
var localized public string m_strTitleImportPoolCharacter;
var localized public string m_strImportAll;

var localized string m_strExportSuccessDialogueTitle;
var localized string m_strExportSuccessDialogueBody;

var localized string m_strExportConfirmDialogueTitle;
var localized string m_strExportConfirmDialogueBody;
var localized string m_strExportConfirmDialogueMultipleUnits;

var localized string m_strExportManySuccessDialogueTitle;
var localized string m_strExportManySuccessDialogueBody;

var localized string m_strDeletePoolDialogueTitle;
var localized string m_strDeletePoolDialogueBody;

var localized string m_strNewPoolFailedExtantTitle;
var localized string m_strNewPoolFailedExtantBody;
var localized string m_strNewPoolFailedBadFilenameTitle;
var localized string m_strNewPoolFailedBadFilenameBody;

var localized string m_strNewPoolSuccessTitle;
var localized string m_strNewPoolSuccessBody;

var array<string> EnumeratedFilenames; //Filenames found which contain importable character pools
var string SelectedFilename; //Filename selected by the user for import, if any
var string SelectedFriendlyName;

var int PoolToBeDeleted;

var array<CharacterPoolManager> ImportablePoolsLoaded; //Memory-resident pools that the user has browsed

delegate OnItemSelectedCallback(UIList _list, int itemIndex);

//----------------------------------------------------------------------------
// FUNCTIONS

simulated function InitScreen(XComPlayerController InitController, UIMovie InitMovie, optional name InitName)
{
	super.InitScreen(InitController, InitMovie, InitName);

	// ---------------------------------------------------------

	// Create Container
	Container = Spawn(class'UIPanel', self).InitPanel('').SetPosition(30, 110).SetSize(600, 800);

	// Create BG
	BG = Spawn(class'UIBGBox', Container).InitBG('', 0, 0, Container.width, Container.height);
	BG.SetAlpha(80);

	// Create Title text
	TitleHeader = Spawn(class'UIX2PanelHeader', Container);
	TitleHeader.InitPanelHeader('', m_strTitleImportPoolLocation, m_strImportSubtitle);
	TitleHeader.SetHeaderWidth(Container.width - 20);
	TitleHeader.SetPosition(10, 10);

	List = Spawn(class'UIList', Container);
	List.bAnimateOnInit = false;
	List.InitList('', 10, TitleHeader.height, TitleHeader.headerWidth - 20, Container.height - TitleHeader.height - 10);
	List.Navigator.LoopSelection = true;
	List.OnSelectionChanged = ItemChanged;

	BG.ProcessMouseEvents(List.OnChildMouseEvent);

	// ---------------------------------------------------------

	NavHelp = Spawn(class'UINavigationHelp', self).InitNavHelp();
	NavHelp.AddBackButton(OnCancel);

	// ---------------------------------------------------------

	CharacterPoolMgr = CharacterPoolManager(`XENGINE.GetCharacterPoolManager());
}
simulated function OnInit()
{
	super.OnInit();

	UpdateGamepadFocus();
}

simulated function UpdateGamepadFocus()
{
	if( `ISCONTROLLERACTIVE == false ) return;

	if(List.ItemCount > 0)
	{
		List.SetSelectedIndex(0);
		Navigator.SetSelected(List);
	}

	UpdateNavHelp();
}

simulated function ItemChanged(UIList ContainerList, int ItemIndex)
{
	UpdateNavHelp();
}

simulated function UpdateNavHelp()
{
	NavHelp.ClearButtonHelp();

	NavHelp.AddBackButton(OnCancel);

	//Toggle selection is constant
	if(List.ItemCount > 0)
		NavHelp.AddLeftHelp(class'UIUtilities_Text'.default.m_strGenericSelect, class'UIUtilities_Input'.static.GetAdvanceButtonIcon());

	if (`ISCONTROLLERACTIVE)
	{
		if(!bHasSelectedImportLocation || List.SelectedIndex > 0)
			NavHelp.AddLeftHelp(class'UISaveLoadGameListItem'.default.m_sDeleteLabel, class'UIUtilities_Input'.const.ICON_Y_TRIANGLE);
	}
}

simulated function OnReceiveFocus()
{
	super.OnReceiveFocus();
	UpdateGamepadFocus();
}

simulated function UpdateData( bool _bIsExporting )
{
	bIsExporting = _bIsExporting;

	if( bIsExporting )
	{
		TitleHeader.SetText(m_strTitle, m_strExportSubtitle);
		Data = GetExportList();
	}
	else
	{
		if( bHasSelectedImportLocation )
		{
			TitleHeader.SetText(m_strTitleImportPoolCharacter, SelectedFriendlyName);
			Data = GetImportList();
		}
		else
		{
			TitleHeader.SetText(m_strTitleImportPoolLocation, m_strImportSubtitle);
			Data = GetImportLocationList();
		}
	}

	List.OnItemClicked = OnClickLocal;

	UpdateDisplay();
}

simulated function UpdateDisplay()
{
	local UIMechaListItem SpawnedItem;
	local int i;

	if(List.itemCount > Data.length)
		List.ClearItems();

	while (List.itemCount < Data.length)
	{
		SpawnedItem = Spawn(class'UIMechaListItem', List.itemContainer);
		SpawnedItem.bAnimateOnInit = false;
		SpawnedItem.InitListItem();
	}

	for( i = 0; i < Data.Length; i++ )
	{
		if(bHasSelectedImportLocation || (bIsExporting && i == 0) || `ISCONTROLLERACTIVE)
			UIMechaListItem(List.GetItem(i)).UpdateDataValue(Data[i], "");
		else
			UIMechaListItem(List.GetItem(i)).UpdateDataButton(Data[i], class'UISaveLoadGameListItem'.default.m_sDeleteLabel, OnDeletePool);
	}
}

simulated function DeleteCurrentlySelectedPool()
{
	PoolToBeDeleted = List.SelectedIndex;

	if (bHasSelectedImportLocation)
	{
		if (PoolToBeDeleted > 0)
		{
			OnConfirmDeleteCharacter();
		}
	}
	else
	{
		if (PoolToBeDeleted != INDEX_NONE)
			OnConfirmDeletePool();
	}
}

simulated function OnDeletePool(UIButton Button)
{
	local int Index;

	Index = List.GetItemIndex(Button);
	PoolToBeDeleted = Index;

	if(Index != INDEX_NONE)
		OnConfirmDeletePool();
}

simulated function OnConfirmDeleteCharacter()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	kTag.StrValue0 = Data[PoolToBeDeleted];

	DialogData.strTitle	   = class'UICharacterPool'.default.m_strDeleteCharacterDialogueTitle;
	DialogData.strText     = `XEXPAND.ExpandString(m_strDeletePoolDialogueBody);
	DialogData.fnCallback  = OnConfirmDeletePoolCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated function OnConfirmDeletePool()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	kTag.StrValue0 = Data[PoolToBeDeleted];

	DialogData.strTitle = m_strDeletePoolDialogueTitle;
	DialogData.strText = `XEXPAND.ExpandString(m_strDeletePoolDialogueBody);
	DialogData.fnCallback = OnConfirmDeletePoolCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated public function OnConfirmDeletePoolCallback(Name eAction)
{
	local CharacterPoolManager PoolToDelete;

	if( eAction == 'eUIAction_Accept' )
	{
		PoolToDelete = new class'CharacterPoolManager';
		PoolToDelete.PoolFileName = EnumeratedFilenames[PoolToBeDeleted - (bIsExporting ? 1 : 0)]; // -1 to account for new pool button
		PoolToDelete.DeleteCharacterPool();
		UpdateData(bIsExporting);
	}
}

//------------------------------------------------------

simulated function bool OnUnrealCommand(int cmd, int arg)
{
	if( !CheckInputIsReleaseOrDirectionRepeat(cmd, arg) )
		return false;

	switch( cmd )
	{
		case class'UIUtilities_Input'.const.FXS_BUTTON_A:
		case class'UIUtilities_Input'.const.FXS_KEY_ENTER:
		case class'UIUtilities_Input'.const.FXS_KEY_SPACEBAR:
			OnAccept();
			return true;
		case class'UIUtilities_Input'.const.FXS_BUTTON_B:
		case class'UIUtilities_Input'.const.FXS_KEY_ESCAPE:
		case class'UIUtilities_Input'.const.FXS_R_MOUSE_DOWN:
			OnCancel();
			return true;

		case class'UIUtilities_Input'.const.FXS_BUTTON_Y :
			if(!bHasSelectedImportLocation || List.SelectedIndex > 0)
				DeleteCurrentlySelectedPool();
			return true;
	}

	return super.OnUnrealCommand(cmd, arg);
}

//------------------------------------------------------

simulated function OnAccept()
{

	if( `ISCONTROLLERACTIVE )
		OnClickLocal(List, List.SelectedIndex);
	//OnButtonCallback(AcceptButton);

	UpdateNavHelp();
}

simulated function OnCancel()
{
	if( !bIsExporting && bHasSelectedImportLocation )
	{
		//Return back to select location
		bHasSelectedImportLocation = false;
		// Then, refresh this screen:
		UpdateData( false );
		if( `ISCONTROLLERACTIVE )
			UpdateGamepadFocus();
	}
	else
	{
		ImportablePoolsLoaded.Length = 0; //Dump any characters not in the main pool by now
		Movie.Stack.Pop(self);
	}
}

simulated function OnClickLocal(UIList _list, int iItemIndex)
{
	if( bIsExporting )
	{
		if( iItemIndex == 0) //Request to create a new pool
		{
			// We want a new pool
			OpenNewExportPoolInputBox();
		}
		else
		{
			//TODO @nway: notify the game of the export pool: iItemIndex-1
			SelectedFilename = EnumeratedFilenames[iItemIndex-1];
			SelectedFriendlyName = Data[iItemIndex];
			// TODO: Confirm export
			`log("EXPORT location selected: " $string(iItemIndex-1) $ ":" $ SelectedFilename);
			OnExportCharacters();
		}
	}
	else
	{
		if( !bHasSelectedImportLocation )
		{
			// We just picked the import location
			bHasSelectedImportLocation = true;
			SelectedFilename = EnumeratedFilenames[iItemIndex];
			SelectedFriendlyName = Data[iItemIndex];
			`log("IMPORT location selected: " $string(iItemIndex) $ ":" $ SelectedFilename);
			// Then, refresh this screen:
			UpdateData( false );
		}
		else
		{
			`log("IMPORT character selected: " $string(iItemIndex));

			if (iItemIndex == 0) //"all" case
				DoImportAllCharacters(SelectedFilename);
			else
				DoImportCharacter(SelectedFilename, iItemIndex-1);

			bHasSelectedImportLocation = false;  // This will allow us to exit the screen
			OnCancel();
		}
	}
}

simulated function OnExportCharacters()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	if(UnitsToExport.Length == 1)
	{
		kTag.StrValue0 = UnitsToExport[0].GetName(eNameType_Full);
	}
	else
	{
		kTag.IntValue0 = UnitsToExport.Length;
		kTag.StrValue0 = `XEXPAND.ExpandString(m_strExportConfirmDialogueMultipleUnits);
	}

	DialogData.strTitle	   = m_strExportConfirmDialogueTitle;
	DialogData.strText     = `XEXPAND.ExpandString(m_strExportConfirmDialogueBody);
	DialogData.fnCallback  = OnExportCharactersCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated public function OnExportCharactersCallback(Name eAction)
{
	if( eAction == 'eUIAction_Accept' )
	{
		DoExportCharacters(SelectedFilename);
		OnCancel();
	}
}

simulated function array<string> GetExportList()
{
	local array<string> FriendlyNames;

	//The first item should be "create new pool", followed by all existing pools
	FriendlyNames.Length = 0;
	FriendlyNames.AddItem(m_strCreateNewPool);

	//Re-enumerate pool files
	EnumeratedFilenames.Length = 0;
	class'CharacterPoolManager'.static.EnumerateImportablePools(FriendlyNames, EnumeratedFilenames);

	return FriendlyNames;
}

simulated function array<string> GetImportLocationList()
{
	local array<string> FriendlyNames;

	//Re-enumerate pool files
	FriendlyNames.Length = 0;
	EnumeratedFilenames.Length = 0;
	class'CharacterPoolManager'.static.EnumerateImportablePools(FriendlyNames, EnumeratedFilenames);

	return FriendlyNames;
}

simulated function array<string> GetImportList()
{
	local array<string> Items;
	local CharacterPoolManager SelectedPool;
	local bool PoolAlreadyLoaded;
	local XComGameState_Unit PoolUnit;

	//Top item should let user grab all characters from the pool
	Items.AddItem(m_strImportAll);

	//Check if we've already deserialized the desired pool
	PoolAlreadyLoaded = false;
	foreach ImportablePoolsLoaded(SelectedPool)
	{
		if (SelectedPool.PoolFileName == SelectedFilename)
		{
			PoolAlreadyLoaded = true;
			break;
		}
	}

	//Instantiate a new pool with data from the file, if we haven't already
	if (!PoolAlreadyLoaded)
	{
		SelectedPool = new class'CharacterPoolManager';
		SelectedPool.PoolFileName = SelectedFilename;
		SelectedPool.LoadCharacterPool();
		ImportablePoolsLoaded.AddItem(SelectedPool);

		/// HL-Docs: ref:Bugfixes; issue:1118
		/// LoadCharacterPool() may alter PoolFileName in certain conditions.
		// Single line for Issue #1118
		SelectedFilename = SelectedPool.PoolFileName;
	}

	foreach SelectedPool.CharacterPool(PoolUnit)
	{
		if (PoolUnit.GetNickName() != "")
			Items.AddItem(PoolUnit.GetFirstName() @ PoolUnit.GetNickName() @ PoolUnit.GetLastName());
		else
			Items.AddItem(PoolUnit.GetFirstName() @ PoolUnit.GetLastName());
	}

	//If we didn't actually have valid characters to import, don't even show the "all" option
	if (Items.Length == 1)
		Items.Length = 0;

	return Items;
}

simulated function OpenNewExportPoolInputBox()
{
	local TInputDialogData kData;

//	if( !`GAMECORE.WorldInfo.IsConsoleBuild() || `ISCONTROLLERACTIVE )
//	{
		kData.strTitle = m_strCreateNewPool $":";
		kData.iMaxChars = 32; //TODO: @nway: what is the actual max on these names?
		kData.strInputBoxText = "";
		kData.fnCallback = OnNewExportPoolInputBoxClosed;

		Movie.Pres.UIInputDialog(kData);
/*	}
	else
	{
		XComPresentationLayerBase(Outer).UIKeyboard(m_strCreateNewPool $":",
													"",
													VirtualKeyboard_OnNewExportPoolInputBoxAccepted,
													VirtualKeyboard_OnNewExportPoolInputBoxCancelled,
													false,
													32
		);
	}*/
}

// TEXT INPUT BOX (PC)
function OnNewExportPoolInputBoxClosed(string text)
{
	local TDialogueBoxData kDialogData;
	if (text != "")
	{
		`log("Player wants a new pool named '" $text $"'.");

		//Sanitize the filename that the user entered
		text = class'UIUtilities'.static.SanitizeFilenameFromUserInput(text);

		//The filename might have been totally sanitized away
		if (text == "")
		{
			kDialogData.eType = eDialog_Normal;
			kDialogData.strTitle = m_strNewPoolFailedBadFilenameTitle;
			kDialogData.strText = m_strNewPoolFailedBadFilenameBody;
			kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
			Movie.Pres.UIRaiseDialog(kDialogData);
			return;
		}

		//The pool might already exist
		if (!DoMakeEmptyPool(text))
		{
			kDialogData.eType = eDialog_Normal;
			kDialogData.strTitle = m_strNewPoolFailedExtantTitle;
			kDialogData.strText = m_strNewPoolFailedExtantBody;
			kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
			Movie.Pres.UIRaiseDialog(kDialogData);
			return;
		}

		//Show a success dialog, letting them know that they still need to export their character to the new, empty pool
		kDialogData.eType = eDialog_Normal;
		kDialogData.strTitle = m_strNewPoolSuccessTitle;
		kDialogData.strText = m_strNewPoolSuccessBody;
		kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
		Movie.Pres.UIRaiseDialog(kDialogData);

		//Now that import pool list should be updated, we can call refresh to grab that new lit and repopulate the list.
		UpdateData(true);
	}
}

function VirtualKeyboard_OnNewExportPoolInputBoxAccepted(string text, bool bWasSuccessful)
{
	OnNewExportPoolInputBoxClosed(bWasSuccessful ? text : "");
}

function VirtualKeyboard_OnNewExportPoolInputBoxCancelled()
{
	OnNewExportPoolInputBoxClosed("");
}

simulated function DoImportCharacter(string FilenameForImport, int IndexOfCharacter)
{
	local CharacterPoolManager ImportPool;
	local XComGameState_Unit ImportUnit;

	//Find the character pool we want to import from
	foreach ImportablePoolsLoaded(ImportPool)
	{
		if (ImportPool.PoolFileName == FilenameForImport)
			break;
	}
	`assert(ImportPool.PoolFileName == FilenameForImport);

	//Grab the unit (we already know the index)
	ImportUnit = ImportPool.CharacterPool[IndexOfCharacter];

	//Put the unit in the default character pool
	if (ImportUnit != None)
		CharacterPoolMgr.CharacterPool.AddItem(ImportUnit);

	//Save the default character pool
	CharacterPoolMgr.SaveCharacterPool();

	`log("Imported character" @ FilenameForImport @ IndexOfCharacter @ ":" @ ImportUnit.GetFullName());
}

simulated function DoImportAllCharacters(string FilenameForImport)
{
	local CharacterPoolManager ImportPool;
	local XComGameState_Unit ImportUnit;

	if(ImportablePoolsLoaded.Length > 0)
	{
		//Find the character pool we want to import from
		foreach ImportablePoolsLoaded(ImportPool)
		{
			if(ImportPool.PoolFileName == FilenameForImport)
				break;
		}

		if(ImportPool == none)
		{
			ImportPool = ImportablePoolsLoaded[0];
		}
		`assert(ImportPool.PoolFileName == FilenameForImport);

		//Grab each unit and put it in the default pool
		foreach ImportPool.CharacterPool(ImportUnit)
		{
			if(ImportUnit != None)
				CharacterPoolMgr.CharacterPool.AddItem(ImportUnit);
		}

		//Save the default character pool
		CharacterPoolMgr.SaveCharacterPool();

		`log("Imported characters" @ FilenameForImport);
	}
}

simulated function DoExportCharacters(string FilenameForExport)
{
	local int i;
	local XComGameState_Unit ExportUnit;
	local CharacterPoolManager ExportPool;

	//Just to be sure we don't have stale data, kill all cached pools and re-open the one we want
	ImportablePoolsLoaded.Length = 0;
	ExportPool = new class'CharacterPoolManager';
	ExportPool.PoolFileName = FilenameForExport;
	ExportPool.LoadCharacterPool();

	//Copy out each character
	for (i = 0; i < UnitsToExport.Length; i++)
	{
		ExportUnit = UnitsToExport[i];

		if (ExportUnit != None)
			ExportPool.CharacterPool.AddItem(ExportUnit);

		`log("Exported character" @ ExportUnit.GetFullName() @ "to pool" @ FilenameForExport);
	}

	//Save it
	ExportPool.SaveCharacterPool();

	ExportSuccessDialogue();
}

simulated function ExportSuccessDialogue()
{
	local XGParamTag LocTag;
	local int i;
	local TDialogueBoxData kDialogData;

	if (UnitsToExport.Length <= 0)
		return;

	kDialogData.eType = eDialog_Normal;

	if( UnitsToExport.Length > 25 )
	{
		LocTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
		LocTag.IntValue0 = UnitsToExport.Length;

		kDialogData.strTitle = m_strExportManySuccessDialogueTitle;
		kDialogData.strText = `XEXPAND.ExpandString(m_strExportManySuccessDialogueBody);
	}
	else
	{
		kDialogData.strTitle = m_strExportSuccessDialogueTitle;
		kDialogData.strText = m_strExportSuccessDialogueBody;

		for (i = 0; i < UnitsToExport.Length; i++)
		{
			kDialogData.strText = kDialogData.strText $ "\n" $ UnitsToExport[i].GetFullName();
		}
	}

	kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;

	Movie.Pres.UIRaiseDialog(kDialogData);
}

//Returns false if pool already exists
simulated function bool DoMakeEmptyPool(string NewFriendlyName)
{
	local CharacterPoolManager ExportPool;
	local string FullFileName;
	FullFileName = CharacterPoolMgr.ImportDirectoryName $ "\\" $ NewFriendlyName $ ".bin";

	if(EnumeratedFilenames.Find(FullFileName) != INDEX_NONE)
		return false;

	ExportPool = new class'CharacterPoolManager';
	ExportPool.PoolFileName = FullFileName;
	ExportPool.SaveCharacterPool();
	return true;
}

//==============================================================================

defaultproperties
{
	InputState      = eInputState_Evaluate;
	PoolToBeDeleted = INDEX_NONE;
	bIsNavigable	= true;
	bIsExporting	= false;
	bHasSelectedImportLocation = false;
}

//---------------------------------------------------------------------------------------
//  FILE:    UICharacterPool_ListPools.uc
//  AUTHOR:  Brit Steiner --  9/4/2014
//  PURPOSE: ListPools menu in the character pool system.
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------

class UICharacterPool_ListPools extends UIScreen
	dependson(CharacterPoolManager);

//----------------------------------------------------------------------------
// MEMBERS

// UI
var UIPanel	Container;
var UIBGBox    BG;
var UIList		List;
var UIButton	AcceptButton;
var UIX2PanelHeader TitleHeader;
var UINavigationHelp NavHelp;

//Default (active) pool
var CharacterPoolManager CharacterPoolMgr;

//Passed in by UICharacterPool if we're exporting
var public array<XComGameState_Unit> UnitsToExport;

var array<string> Data;
var bool bIsExporting;
var bool bHasSelectedImportLocation;

var localized public string m_strTitle;
var localized public string m_strTitleImportPoolLocation;
var localized public string m_strExportSubtitle;
var localized public string m_strImportSubtitle;
var localized public string m_strCreateNewPool;
var localized public string m_strTitleImportPoolCharacter;
var localized public string m_strImportAll;

var localized string m_strExportSuccessDialogueTitle;
var localized string m_strExportSuccessDialogueBody;

var localized string m_strExportConfirmDialogueTitle;
var localized string m_strExportConfirmDialogueBody;
var localized string m_strExportConfirmDialogueMultipleUnits;

var localized string m_strExportManySuccessDialogueTitle;
var localized string m_strExportManySuccessDialogueBody;

var localized string m_strDeletePoolDialogueTitle;
var localized string m_strDeletePoolDialogueBody;

var localized string m_strNewPoolFailedExtantTitle;
var localized string m_strNewPoolFailedExtantBody;
var localized string m_strNewPoolFailedBadFilenameTitle;
var localized string m_strNewPoolFailedBadFilenameBody;

var localized string m_strNewPoolSuccessTitle;
var localized string m_strNewPoolSuccessBody;

var array<string> EnumeratedFilenames; //Filenames found which contain importable character pools
var string SelectedFilename; //Filename selected by the user for import, if any
var string SelectedFriendlyName;

var int PoolToBeDeleted;

var array<CharacterPoolManager> ImportablePoolsLoaded; //Memory-resident pools that the user has browsed

delegate OnItemSelectedCallback(UIList _list, int itemIndex);

//----------------------------------------------------------------------------
// FUNCTIONS

simulated function InitScreen(XComPlayerController InitController, UIMovie InitMovie, optional name InitName)
{
	super.InitScreen(InitController, InitMovie, InitName);

	// ---------------------------------------------------------

	// Create Container
	Container = Spawn(class'UIPanel', self).InitPanel('').SetPosition(30, 110).SetSize(600, 800);

	// Create BG
	BG = Spawn(class'UIBGBox', Container).InitBG('', 0, 0, Container.width, Container.height);
	BG.SetAlpha(80);

	// Create Title text
	TitleHeader = Spawn(class'UIX2PanelHeader', Container);
	TitleHeader.InitPanelHeader('', m_strTitleImportPoolLocation, m_strImportSubtitle);
	TitleHeader.SetHeaderWidth(Container.width - 20);
	TitleHeader.SetPosition(10, 10);

	List = Spawn(class'UIList', Container);
	List.bAnimateOnInit = false;
	List.InitList('', 10, TitleHeader.height, TitleHeader.headerWidth - 20, Container.height - TitleHeader.height - 10);
	List.Navigator.LoopSelection = true;
	List.OnSelectionChanged = ItemChanged;

	BG.ProcessMouseEvents(List.OnChildMouseEvent);

	// ---------------------------------------------------------

	NavHelp = Spawn(class'UINavigationHelp', self).InitNavHelp();
	NavHelp.AddBackButton(OnCancel);

	// ---------------------------------------------------------

	CharacterPoolMgr = CharacterPoolManager(`XENGINE.GetCharacterPoolManager());
}
simulated function OnInit()
{
	super.OnInit();

	UpdateGamepadFocus();
}

simulated function UpdateGamepadFocus()
{
	if( `ISCONTROLLERACTIVE == false ) return;

	if(List.ItemCount > 0)
	{
		List.SetSelectedIndex(0);
		Navigator.SetSelected(List);
	}

	UpdateNavHelp();
}

simulated function ItemChanged(UIList ContainerList, int ItemIndex)
{
	UpdateNavHelp();
}

simulated function UpdateNavHelp()
{
	NavHelp.ClearButtonHelp();

	NavHelp.AddBackButton(OnCancel);

	//Toggle selection is constant
	if(List.ItemCount > 0)
		NavHelp.AddLeftHelp(class'UIUtilities_Text'.default.m_strGenericSelect, class'UIUtilities_Input'.static.GetAdvanceButtonIcon());

	if (`ISCONTROLLERACTIVE)
	{
		if(!bHasSelectedImportLocation || List.SelectedIndex > 0)
			NavHelp.AddLeftHelp(class'UISaveLoadGameListItem'.default.m_sDeleteLabel, class'UIUtilities_Input'.const.ICON_Y_TRIANGLE);
	}
}

simulated function OnReceiveFocus()
{
	super.OnReceiveFocus();
	UpdateGamepadFocus();
}

simulated function UpdateData( bool _bIsExporting )
{
	bIsExporting = _bIsExporting;

	if( bIsExporting )
	{
		TitleHeader.SetText(m_strTitle, m_strExportSubtitle);
		Data = GetExportList();
	}
	else
	{
		if( bHasSelectedImportLocation )
		{
			TitleHeader.SetText(m_strTitleImportPoolCharacter, SelectedFriendlyName);
			Data = GetImportList();
		}
		else
		{
			TitleHeader.SetText(m_strTitleImportPoolLocation, m_strImportSubtitle);
			Data = GetImportLocationList();
		}
	}

	List.OnItemClicked = OnClickLocal;

	UpdateDisplay();
}

simulated function UpdateDisplay()
{
	local UIMechaListItem SpawnedItem;
	local int i;

	if(List.itemCount > Data.length)
		List.ClearItems();

	while (List.itemCount < Data.length)
	{
		SpawnedItem = Spawn(class'UIMechaListItem', List.itemContainer);
		SpawnedItem.bAnimateOnInit = false;
		SpawnedItem.InitListItem();
	}

	for( i = 0; i < Data.Length; i++ )
	{
		if(bHasSelectedImportLocation || (bIsExporting && i == 0) || `ISCONTROLLERACTIVE)
			UIMechaListItem(List.GetItem(i)).UpdateDataValue(Data[i], "");
		else
			UIMechaListItem(List.GetItem(i)).UpdateDataButton(Data[i], class'UISaveLoadGameListItem'.default.m_sDeleteLabel, OnDeletePool);
	}
}

simulated function DeleteCurrentlySelectedPool()
{
	PoolToBeDeleted = List.SelectedIndex;

	if (bHasSelectedImportLocation)
	{
		if (PoolToBeDeleted > 0)
		{
			OnConfirmDeleteCharacter();
		}
	}
	else
	{
		if (PoolToBeDeleted != INDEX_NONE)
			OnConfirmDeletePool();
	}
}

simulated function OnDeletePool(UIButton Button)
{
	local int Index;

	Index = List.GetItemIndex(Button);
	PoolToBeDeleted = Index;

	if(Index != INDEX_NONE)
		OnConfirmDeletePool();
}

simulated function OnConfirmDeleteCharacter()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	kTag.StrValue0 = Data[PoolToBeDeleted];

	DialogData.strTitle	   = class'UICharacterPool'.default.m_strDeleteCharacterDialogueTitle;
	DialogData.strText     = `XEXPAND.ExpandString(m_strDeletePoolDialogueBody);
	DialogData.fnCallback  = OnConfirmDeletePoolCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated function OnConfirmDeletePool()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	kTag.StrValue0 = Data[PoolToBeDeleted];

	DialogData.strTitle = m_strDeletePoolDialogueTitle;
	DialogData.strText = `XEXPAND.ExpandString(m_strDeletePoolDialogueBody);
	DialogData.fnCallback = OnConfirmDeletePoolCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated public function OnConfirmDeletePoolCallback(Name eAction)
{
	local CharacterPoolManager PoolToDelete;

	if( eAction == 'eUIAction_Accept' )
	{
		PoolToDelete = new class'CharacterPoolManager';
		PoolToDelete.PoolFileName = EnumeratedFilenames[PoolToBeDeleted - (bIsExporting ? 1 : 0)]; // -1 to account for new pool button
		PoolToDelete.DeleteCharacterPool();
		UpdateData(bIsExporting);
	}
}

//------------------------------------------------------

simulated function bool OnUnrealCommand(int cmd, int arg)
{
	if( !CheckInputIsReleaseOrDirectionRepeat(cmd, arg) )
		return false;

	switch( cmd )
	{
		case class'UIUtilities_Input'.const.FXS_BUTTON_A:
		case class'UIUtilities_Input'.const.FXS_KEY_ENTER:
		case class'UIUtilities_Input'.const.FXS_KEY_SPACEBAR:
			OnAccept();
			return true;
		case class'UIUtilities_Input'.const.FXS_BUTTON_B:
		case class'UIUtilities_Input'.const.FXS_KEY_ESCAPE:
		case class'UIUtilities_Input'.const.FXS_R_MOUSE_DOWN:
			OnCancel();
			return true;

		case class'UIUtilities_Input'.const.FXS_BUTTON_Y :
			if(!bHasSelectedImportLocation || List.SelectedIndex > 0)
				DeleteCurrentlySelectedPool();
			return true;
	}

	return super.OnUnrealCommand(cmd, arg);
}

//------------------------------------------------------

simulated function OnAccept()
{

	if( `ISCONTROLLERACTIVE )
		OnClickLocal(List, List.SelectedIndex);
	//OnButtonCallback(AcceptButton);

	UpdateNavHelp();
}

simulated function OnCancel()
{
	if( !bIsExporting && bHasSelectedImportLocation )
	{
		//Return back to select location
		bHasSelectedImportLocation = false;
		// Then, refresh this screen:
		UpdateData( false );
		if( `ISCONTROLLERACTIVE )
			UpdateGamepadFocus();
	}
	else
	{
		ImportablePoolsLoaded.Length = 0; //Dump any characters not in the main pool by now
		Movie.Stack.Pop(self);
	}
}

simulated function OnClickLocal(UIList _list, int iItemIndex)
{
	if( bIsExporting )
	{
		if( iItemIndex == 0) //Request to create a new pool
		{
			// We want a new pool
			OpenNewExportPoolInputBox();
		}
		else
		{
			//TODO @nway: notify the game of the export pool: iItemIndex-1
			SelectedFilename = EnumeratedFilenames[iItemIndex-1];
			SelectedFriendlyName = Data[iItemIndex];
			// TODO: Confirm export
			`log("EXPORT location selected: " $string(iItemIndex-1) $ ":" $ SelectedFilename);
			OnExportCharacters();
		}
	}
	else
	{
		if( !bHasSelectedImportLocation )
		{
			// We just picked the import location
			bHasSelectedImportLocation = true;
			SelectedFilename = EnumeratedFilenames[iItemIndex];
			SelectedFriendlyName = Data[iItemIndex];
			`log("IMPORT location selected: " $string(iItemIndex) $ ":" $ SelectedFilename);
			// Then, refresh this screen:
			UpdateData( false );
		}
		else
		{
			`log("IMPORT character selected: " $string(iItemIndex));

			if (iItemIndex == 0) //"all" case
				DoImportAllCharacters(SelectedFilename);
			else
				DoImportCharacter(SelectedFilename, iItemIndex-1);

			bHasSelectedImportLocation = false;  // This will allow us to exit the screen
			OnCancel();
		}
	}
}

simulated function OnExportCharacters()
{
	local XGParamTag        kTag;
	local TDialogueBoxData  DialogData;

	kTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
	if(UnitsToExport.Length == 1)
	{
		kTag.StrValue0 = UnitsToExport[0].GetName(eNameType_Full);
	}
	else
	{
		kTag.IntValue0 = UnitsToExport.Length;
		kTag.StrValue0 = `XEXPAND.ExpandString(m_strExportConfirmDialogueMultipleUnits);
	}

	DialogData.strTitle	   = m_strExportConfirmDialogueTitle;
	DialogData.strText     = `XEXPAND.ExpandString(m_strExportConfirmDialogueBody);
	DialogData.fnCallback  = OnExportCharactersCallback;

	DialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericYes;
	DialogData.strCancel = class'UIUtilities_Text'.default.m_strGenericNo;

	Movie.Pres.UIRaiseDialog(DialogData);
}

simulated public function OnExportCharactersCallback(Name eAction)
{
	if( eAction == 'eUIAction_Accept' )
	{
		DoExportCharacters(SelectedFilename);
		OnCancel();
	}
}

simulated function array<string> GetExportList()
{
	local array<string> FriendlyNames;

	//The first item should be "create new pool", followed by all existing pools
	FriendlyNames.Length = 0;
	FriendlyNames.AddItem(m_strCreateNewPool);

	//Re-enumerate pool files
	EnumeratedFilenames.Length = 0;
	class'CharacterPoolManager'.static.EnumerateImportablePools(FriendlyNames, EnumeratedFilenames);

	return FriendlyNames;
}

simulated function array<string> GetImportLocationList()
{
	local array<string> FriendlyNames;

	//Re-enumerate pool files
	FriendlyNames.Length = 0;
	EnumeratedFilenames.Length = 0;
	class'CharacterPoolManager'.static.EnumerateImportablePools(FriendlyNames, EnumeratedFilenames);

	return FriendlyNames;
}

simulated function array<string> GetImportList()
{
	local array<string> Items;
	local CharacterPoolManager SelectedPool;
	local bool PoolAlreadyLoaded;
	local XComGameState_Unit PoolUnit;

	//Top item should let user grab all characters from the pool
	Items.AddItem(m_strImportAll);

	//Check if we've already deserialized the desired pool
	PoolAlreadyLoaded = false;
	foreach ImportablePoolsLoaded(SelectedPool)
	{
		if (SelectedPool.PoolFileName == SelectedFilename)
		{
			PoolAlreadyLoaded = true;
			break;
		}
	}

	//Instantiate a new pool with data from the file, if we haven't already
	if (!PoolAlreadyLoaded)
	{
		SelectedPool = new class'CharacterPoolManager';
		SelectedPool.PoolFileName = SelectedFilename;
		SelectedPool.LoadCharacterPool();
		ImportablePoolsLoaded.AddItem(SelectedPool);
	}

	foreach SelectedPool.CharacterPool(PoolUnit)
	{
		if (PoolUnit.GetNickName() != "")
			Items.AddItem(PoolUnit.GetFirstName() @ PoolUnit.GetNickName() @ PoolUnit.GetLastName());
		else
			Items.AddItem(PoolUnit.GetFirstName() @ PoolUnit.GetLastName());
	}

	//If we didn't actually have valid characters to import, don't even show the "all" option
	if (Items.Length == 1)
		Items.Length = 0;

	return Items;
}

simulated function OpenNewExportPoolInputBox()
{
	local TInputDialogData kData;

//	if( !`GAMECORE.WorldInfo.IsConsoleBuild() || `ISCONTROLLERACTIVE )
//	{
		kData.strTitle = m_strCreateNewPool $":";
		kData.iMaxChars = 32; //TODO: @nway: what is the actual max on these names?
		kData.strInputBoxText = "";
		kData.fnCallback = OnNewExportPoolInputBoxClosed;

		Movie.Pres.UIInputDialog(kData);
/*	}
	else
	{
		XComPresentationLayerBase(Outer).UIKeyboard(m_strCreateNewPool $":",
													"",
													VirtualKeyboard_OnNewExportPoolInputBoxAccepted,
													VirtualKeyboard_OnNewExportPoolInputBoxCancelled,
													false,
													32
		);
	}*/
}

// TEXT INPUT BOX (PC)
function OnNewExportPoolInputBoxClosed(string text)
{
	local TDialogueBoxData kDialogData;
	if (text != "")
	{
		`log("Player wants a new pool named '" $text $"'.");

		//Sanitize the filename that the user entered
		text = class'UIUtilities'.static.SanitizeFilenameFromUserInput(text);

		//The filename might have been totally sanitized away
		if (text == "")
		{
			kDialogData.eType = eDialog_Normal;
			kDialogData.strTitle = m_strNewPoolFailedBadFilenameTitle;
			kDialogData.strText = m_strNewPoolFailedBadFilenameBody;
			kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
			Movie.Pres.UIRaiseDialog(kDialogData);
			return;
		}

		//The pool might already exist
		if (!DoMakeEmptyPool(text))
		{
			kDialogData.eType = eDialog_Normal;
			kDialogData.strTitle = m_strNewPoolFailedExtantTitle;
			kDialogData.strText = m_strNewPoolFailedExtantBody;
			kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
			Movie.Pres.UIRaiseDialog(kDialogData);
			return;
		}

		//Show a success dialog, letting them know that they still need to export their character to the new, empty pool
		kDialogData.eType = eDialog_Normal;
		kDialogData.strTitle = m_strNewPoolSuccessTitle;
		kDialogData.strText = m_strNewPoolSuccessBody;
		kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;
		Movie.Pres.UIRaiseDialog(kDialogData);

		//Now that import pool list should be updated, we can call refresh to grab that new lit and repopulate the list.
		UpdateData(true);
	}
}

function VirtualKeyboard_OnNewExportPoolInputBoxAccepted(string text, bool bWasSuccessful)
{
	OnNewExportPoolInputBoxClosed(bWasSuccessful ? text : "");
}

function VirtualKeyboard_OnNewExportPoolInputBoxCancelled()
{
	OnNewExportPoolInputBoxClosed("");
}

simulated function DoImportCharacter(string FilenameForImport, int IndexOfCharacter)
{
	local CharacterPoolManager ImportPool;
	local XComGameState_Unit ImportUnit;

	//Find the character pool we want to import from
	foreach ImportablePoolsLoaded(ImportPool)
	{
		if (ImportPool.PoolFileName == FilenameForImport)
			break;
	}
	`assert(ImportPool.PoolFileName == FilenameForImport);

	//Grab the unit (we already know the index)
	ImportUnit = ImportPool.CharacterPool[IndexOfCharacter];

	//Put the unit in the default character pool
	if (ImportUnit != None)
		CharacterPoolMgr.CharacterPool.AddItem(ImportUnit);

	//Save the default character pool
	CharacterPoolMgr.SaveCharacterPool();

	`log("Imported character" @ FilenameForImport @ IndexOfCharacter @ ":" @ ImportUnit.GetFullName());
}

simulated function DoImportAllCharacters(string FilenameForImport)
{
	local CharacterPoolManager ImportPool;
	local XComGameState_Unit ImportUnit;

	if(ImportablePoolsLoaded.Length > 0)
	{
		//Find the character pool we want to import from
		foreach ImportablePoolsLoaded(ImportPool)
		{
			if(ImportPool.PoolFileName == FilenameForImport)
				break;
		}

		if(ImportPool == none)
		{
			ImportPool = ImportablePoolsLoaded[0];
		}
		`assert(ImportPool.PoolFileName == FilenameForImport);

		//Grab each unit and put it in the default pool
		foreach ImportPool.CharacterPool(ImportUnit)
		{
			if(ImportUnit != None)
				CharacterPoolMgr.CharacterPool.AddItem(ImportUnit);
		}

		//Save the default character pool
		CharacterPoolMgr.SaveCharacterPool();

		`log("Imported characters" @ FilenameForImport);
	}
}

simulated function DoExportCharacters(string FilenameForExport)
{
	local int i;
	local XComGameState_Unit ExportUnit;
	local CharacterPoolManager ExportPool;

	//Just to be sure we don't have stale data, kill all cached pools and re-open the one we want
	ImportablePoolsLoaded.Length = 0;
	ExportPool = new class'CharacterPoolManager';
	ExportPool.PoolFileName = FilenameForExport;
	ExportPool.LoadCharacterPool();

	//Copy out each character
	for (i = 0; i < UnitsToExport.Length; i++)
	{
		ExportUnit = UnitsToExport[i];

		if (ExportUnit != None)
			ExportPool.CharacterPool.AddItem(ExportUnit);

		`log("Exported character" @ ExportUnit.GetFullName() @ "to pool" @ FilenameForExport);
	}

	//Save it
	ExportPool.SaveCharacterPool();

	ExportSuccessDialogue();
}

simulated function ExportSuccessDialogue()
{
	local XGParamTag LocTag;
	local int i;
	local TDialogueBoxData kDialogData;

	if (UnitsToExport.Length <= 0)
		return;

	kDialogData.eType = eDialog_Normal;

	if( UnitsToExport.Length > 25 )
	{
		LocTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
		LocTag.IntValue0 = UnitsToExport.Length;

		kDialogData.strTitle = m_strExportManySuccessDialogueTitle;
		kDialogData.strText = `XEXPAND.ExpandString(m_strExportManySuccessDialogueBody);
	}
	else
	{
		kDialogData.strTitle = m_strExportSuccessDialogueTitle;
		kDialogData.strText = m_strExportSuccessDialogueBody;

		for (i = 0; i < UnitsToExport.Length; i++)
		{
			kDialogData.strText = kDialogData.strText $ "\n" $ UnitsToExport[i].GetFullName();
		}
	}

	kDialogData.strAccept = class'UIUtilities_Text'.default.m_strGenericAccept;

	Movie.Pres.UIRaiseDialog(kDialogData);
}

//Returns false if pool already exists
simulated function bool DoMakeEmptyPool(string NewFriendlyName)
{
	local CharacterPoolManager ExportPool;
	local string FullFileName;
	FullFileName = CharacterPoolMgr.ImportDirectoryName $ "\\" $ NewFriendlyName $ ".bin";

	if(EnumeratedFilenames.Find(FullFileName) != INDEX_NONE)
		return false;

	ExportPool = new class'CharacterPoolManager';
	ExportPool.PoolFileName = FullFileName;
	ExportPool.SaveCharacterPool();
	return true;
}

//==============================================================================

defaultproperties
{
	InputState      = eInputState_Evaluate;
	PoolToBeDeleted = INDEX_NONE;
	bIsNavigable	= true;
	bIsExporting	= false;
	bHasSelectedImportLocation = false;
}


Issue #838 - unprivated XCGSC_Kismet::FindSequenceOp

//---------------------------------------------------------------------------------------
//  FILE:    XComGameStateContext_Kismet.uc
//  AUTHOR:  David Burchanowski  --  1/15/2014
//  PURPOSE: XComGameStateContexts for kismet events
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------
class XComGameStateContext_Kismet extends XComGameStateContext
	native(Core);

var private name SeqOpMap;		// the kismet map this seqop resides in
var private name SeqOpName;		// the name of this specific seqop
var private name SeqOpClassName;// the class name of this sequenceOp
var private array<int> ActivatedInputs; // the inputs that were active when this op fired
var private int ActivatedOutput; // the output that was activated when this op fired

cpptext
{
	// saves all variables in the list to the specified game state
	static void SaveKismetVars(TArray<USequenceVariable*>& KismetVariables, UXComGameState* NewGameState);
}

native function SetSequenceOp(SequenceOp SeqOp);
native /*private*/ function SequenceOp FindSequenceOp(); // Issue #838 - unprivated
native private function ExecuteSequenceOp(SequenceOp SeqOp);
native private function RestoreActivatedInputs(SequenceOp SeqOp);

native function SaveAttachedKismetVars(SequenceOp SeqOp, XComGameState NewGameState);
native function RestoreAttachedKismetVars(SequenceOp SeqOp);

function XComGameState ContextBuildGameState()
{
	local XComGameStateHistory History;
	local XComGameState GameState;
	local SequenceOp SeqOp;
	local X2KismetSeqOpVisualizer SeqOpVisualizer;

	History = `XComHistory;

	SeqOp = FindSequenceOp();
	if(SeqOp != none)
	{
		if(SequenceEvent(SeqOp) == none)
		{
			// make sure that any seq vars attached to this op are set to the correct values before processing the node.
			// we need to skip this for events, though, as their values are set externally in code and we will just overwrite them
			RestoreAttachedKismetVars(SeqOp);
		}

		// activate and process the sequence node
		ExecuteSequenceOp(SeqOp);

		// save the resulting kismet state to the history
		GameState = History.CreateNewGameState(true, self);

		SaveAttachedKismetVars(SeqOp, GameState);

		// give the op the chance to modify the gamestate if it needs to
		SeqOpVisualizer = X2KismetSeqOpVisualizer(SeqOp);
		if(SeqOpVisualizer != none)
		{
			SeqOpVisualizer.ModifyKismetGameState(GameState);
		}

		GameState.GetContext().SetAssociatedPlayTiming(SPT_AfterSequential);
	}

	return GameState;
}

protected function ContextBuildVisualization()
{
	local SequenceOp SeqOp;
	local X2KismetSeqOpVisualizer VisInterface;
	local XComGameState_TimerData Timer;

	//If we are watching a replay, and this replay is of a challenge mode run, skip kismet driven visualization (ie. narratives)
	if (`REPLAY.bInReplay && !`REPLAY.bInTutorial)
	{
		Timer = XComGameState_TimerData(`XCOMHISTORY.GetSingleGameStateObjectForClass(class'XComGameState_TimerData', true));
		if ((Timer != none) && Timer.bIsChallengeModeTimer)
		{
			return;
		}
	}

	SeqOp = FindSequenceOp();
	if(SeqOp != none)
	{
		VisInterface = X2KismetSeqOpVisualizer(SeqOp);
		if(VisInterface != none)
		{
			// restore any attached vars to the values they contained when this op
			// was originally activated. This allows us to mask the fact that visualization and activation
			// happen at different times from the seqop developers
			RestoreAttachedKismetVars(SeqOp);

			SeqOp.PublishLinkedVariableValues();

			RestoreActivatedInputs(SeqOp);

			VisInterface.BuildVisualization(AssociatedState);
		}
	}
}

function string SummaryString()
{
	local SequenceOp SeqOp;

	SeqOp = FindSequenceOp();
	return "Kismet: " $ ((SeqOp != none) ? string(SeqOp.Name) : ("SeqOp not found: '" $ string(SeqOpMap) $ "." $ string(SeqOpName) $ "'"));
}

function string ToString()
{
	return "Kismet Context";
}

function string VerboseDebugString()
{
	local XComGameStateHistory History;
	local XComGameState_KismetVariable KismetObject;
	local SequenceOp SeqOp;
	local string Result;
	local int LinkIndex;
	local int VariableIndex;

	SeqOp = FindSequenceOp();
	if(SeqOp == none) return "";

	History = `XCOMHISTORY;

	// dump the var name and comment
	Result = SeqOp.Name $ "\n\"" $ SeqOp.ObjComment $ "\"\n\n";

	// dump input links
	Result $= "Input Links (-> indicates activated link):\n";
	for(LinkIndex = 0; LinkIndex < SeqOp.InputLinks.Length; LinkIndex++)
	{
		if(ActivatedInputs.Find(LinkIndex) != INDEX_NONE)
		{
			Result $= "-> ";
		}

		Result $= SeqOp.InputLinks[LinkIndex].LinkDesc $ "\n";
	}

	// dump output links
	Result $= "\nOutput Links (-> indicates activated link):\n";
	for(LinkIndex = 0; LinkIndex < SeqOp.OutputLinks.Length; LinkIndex++)
	{
		if(LinkIndex == ActivatedOutput)
		{
			Result $= "-> ";
		}

		Result $= SeqOp.OutputLinks[LinkIndex].LinkDesc $ "\n";
	}

	// dump linked variables
	Result $= "\nLinked Variables:\n";

	for(LinkIndex = 0; LinkIndex < SeqOp.VariableLinks.Length; LinkIndex++)
	{
		Result $= SeqOp.VariableLinks[LinkIndex].LinkDesc $ ":\n";

		for(VariableIndex = 0; VariableIndex < SeqOp.VariableLinks[LinkIndex].LinkedVariables.Length; VariableIndex++)
		{
			Result $= "  "; // indent to make things readable

			// find the linked variable in the history
			foreach History.IterateByClassType(class'XComGameState_KismetVariable', KismetObject)
			{
				if(KismetObject.VarName == string(SeqOp.VariableLinks[LinkIndex].LinkedVariables[VariableIndex].VarName))
				{
					// get the correct version of this object for the associated state
					KismetObject = XComGameState_KismetVariable(History.GetGameStateForObjectID(KismetObject.ObjectID,, AssociatedState.HistoryIndex));

					// append to the result
					Result $= KismetObject.ToString();
					break;
				}
			}

			Result $= "\n";
		}
	}

	return Result;
}

//---------------------------------------------------------------------------------------
//  FILE:    XComGameStateContext_Kismet.uc
//  AUTHOR:  David Burchanowski  --  1/15/2014
//  PURPOSE: XComGameStateContexts for kismet events
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------
class XComGameStateContext_Kismet extends XComGameStateContext
	native(Core);

var private name SeqOpMap;		// the kismet map this seqop resides in
var private name SeqOpName;		// the name of this specific seqop
var private name SeqOpClassName;// the class name of this sequenceOp
var private array<int> ActivatedInputs; // the inputs that were active when this op fired
var private int ActivatedOutput; // the output that was activated when this op fired

cpptext
{
	// saves all variables in the list to the specified game state
	static void SaveKismetVars(TArray<USequenceVariable*>& KismetVariables, UXComGameState* NewGameState);
}

native function SetSequenceOp(SequenceOp SeqOp);
native private function SequenceOp FindSequenceOp();
native private function ExecuteSequenceOp(SequenceOp SeqOp);
native private function RestoreActivatedInputs(SequenceOp SeqOp);

native function SaveAttachedKismetVars(SequenceOp SeqOp, XComGameState NewGameState);
native function RestoreAttachedKismetVars(SequenceOp SeqOp);

function XComGameState ContextBuildGameState()
{
	local XComGameStateHistory History;
	local XComGameState GameState;
	local SequenceOp SeqOp;
	local X2KismetSeqOpVisualizer SeqOpVisualizer;

	History = `XComHistory;

	SeqOp = FindSequenceOp();
	if(SeqOp != none)
	{
		if(SequenceEvent(SeqOp) == none)
		{
			// make sure that any seq vars attached to this op are set to the correct values before processing the node.
			// we need to skip this for events, though, as their values are set externally in code and we will just overwrite them
			RestoreAttachedKismetVars(SeqOp);
		}

		// activate and process the sequence node
		ExecuteSequenceOp(SeqOp);

		// save the resulting kismet state to the history
		GameState = History.CreateNewGameState(true, self);

		SaveAttachedKismetVars(SeqOp, GameState);

		// give the op the chance to modify the gamestate if it needs to
		SeqOpVisualizer = X2KismetSeqOpVisualizer(SeqOp);
		if(SeqOpVisualizer != none)
		{
			SeqOpVisualizer.ModifyKismetGameState(GameState);
		}

		GameState.GetContext().SetAssociatedPlayTiming(SPT_AfterSequential);
	}

	return GameState;
}

protected function ContextBuildVisualization()
{
	local SequenceOp SeqOp;
	local X2KismetSeqOpVisualizer VisInterface;
	local XComGameState_TimerData Timer;

	//If we are watching a replay, and this replay is of a challenge mode run, skip kismet driven visualization (ie. narratives)
	if (`REPLAY.bInReplay && !`REPLAY.bInTutorial)
	{
		Timer = XComGameState_TimerData(`XCOMHISTORY.GetSingleGameStateObjectForClass(class'XComGameState_TimerData', true));
		if ((Timer != none) && Timer.bIsChallengeModeTimer)
		{
			return;
		}
	}

	SeqOp = FindSequenceOp();
	if(SeqOp != none)
	{
		VisInterface = X2KismetSeqOpVisualizer(SeqOp);
		if(VisInterface != none)
		{
			// restore any attached vars to the values they contained when this op
			// was originally activated. This allows us to mask the fact that visualization and activation
			// happen at different times from the seqop developers
			RestoreAttachedKismetVars(SeqOp);

			SeqOp.PublishLinkedVariableValues();

			RestoreActivatedInputs(SeqOp);

			VisInterface.BuildVisualization(AssociatedState);
		}
	}
}

function string SummaryString()
{
	local SequenceOp SeqOp;

	SeqOp = FindSequenceOp();
	return "Kismet: " $ ((SeqOp != none) ? string(SeqOp.Name) : ("SeqOp not found: '" $ string(SeqOpMap) $ "." $ string(SeqOpName) $ "'"));
}

function string ToString()
{
	return "Kismet Context";
}

function string VerboseDebugString()
{
	local XComGameStateHistory History;
	local XComGameState_KismetVariable KismetObject;
	local SequenceOp SeqOp;
	local string Result;
	local int LinkIndex;
	local int VariableIndex;

	SeqOp = FindSequenceOp();
	if(SeqOp == none) return "";

	History = `XCOMHISTORY;

	// dump the var name and comment
	Result = SeqOp.Name $ "\n\"" $ SeqOp.ObjComment $ "\"\n\n";

	// dump input links
	Result $= "Input Links (-> indicates activated link):\n";
	for(LinkIndex = 0; LinkIndex < SeqOp.InputLinks.Length; LinkIndex++)
	{
		if(ActivatedInputs.Find(LinkIndex) != INDEX_NONE)
		{
			Result $= "-> ";
		}

		Result $= SeqOp.InputLinks[LinkIndex].LinkDesc $ "\n";
	}

	// dump output links
	Result $= "\nOutput Links (-> indicates activated link):\n";
	for(LinkIndex = 0; LinkIndex < SeqOp.OutputLinks.Length; LinkIndex++)
	{
		if(LinkIndex == ActivatedOutput)
		{
			Result $= "-> ";
		}

		Result $= SeqOp.OutputLinks[LinkIndex].LinkDesc $ "\n";
	}

	// dump linked variables
	Result $= "\nLinked Variables:\n";

	for(LinkIndex = 0; LinkIndex < SeqOp.VariableLinks.Length; LinkIndex++)
	{
		Result $= SeqOp.VariableLinks[LinkIndex].LinkDesc $ ":\n";

		for(VariableIndex = 0; VariableIndex < SeqOp.VariableLinks[LinkIndex].LinkedVariables.Length; VariableIndex++)
		{
			Result $= "  "; // indent to make things readable

			// find the linked variable in the history
			foreach History.IterateByClassType(class'XComGameState_KismetVariable', KismetObject)
			{
				if(KismetObject.VarName == string(SeqOp.VariableLinks[LinkIndex].LinkedVariables[VariableIndex].VarName))
				{
					// get the correct version of this object for the associated state
					KismetObject = XComGameState_KismetVariable(History.GetGameStateForObjectID(KismetObject.ObjectID,, AssociatedState.HistoryIndex));

					// append to the result
					Result $= KismetObject.ToString();
					break;
				}
			}

			Result $= "\n";
		}
	}

	return Result;
}


Update pb-to-cpp.uc

Update pb-to-cpp.uc

Added CvDwd

# pb-to-cpp.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/17/2014 7:01:20 PM
# Comment: Converts PB source code to C++; modified by Daniel Corbier

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 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
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
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

         #include "pbOS.h"
         #include "pbMisc.h"
         {@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: Functions, Subs, =
Pass: 2

Criteria: 7
Highlight: True
Find: =
Replace: ==

Criteria: 8
SkipOver: True
Find: { + | - | * | / | % | & | ^ | ! }=
Replace: [Skip over]

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

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

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

Criteria: 12
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: 13
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: 14
Highlight: True
PassOnce: False
Find: Function PBMain [()] [As Long]
Replace: Function main() As Long

Criteria: 15
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: 16
Highlight: True
Find: Declare Sub {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])]
Replace: {lib: extern __declspec(dllimport)} void {name}({args})

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

Criteria: 18
Comment: Misc
Pass: 3

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

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

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

Criteria: 22
Highlight: True
BackColor: Green
Find: %{equate:"[a-z]+"}
Replace: {equate}

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

Criteria: 24
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: 25
Highlight: True
PassOnce: False
Find: If {cond} Then {nl}
         {code+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 26
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: 27
Highlight: True
PassOnce: False
Find: While {cond} {nl}
         {code+}
      Wend
Replace: while ({cond}) {
            {code}
         }

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

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

Criteria: 30
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: 31
Highlight: True
BackColor: Orange
PassOnce: False
Find: { Dim | {member: {nl}}} {var:1} As {type} [{ptr: Ptr}]
Replace: {member: {nl}}{type} {ptr:*}{var};

Criteria: 32
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: 33
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: 34
Highlight: True
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

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

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

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

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

Criteria: 39
Find: Iterate
Replace: continue

Criteria: 40
Find: Exit
Replace: break

Criteria: 41
Highlight: True
Find: Exit Sub
Replace: return

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

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

Criteria: 44
Find: Double
Replace: double

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

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

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

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

Criteria: 49
Find: AsciiZ
Replace: LPCSTR

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

Criteria: 51
SkipOver: True
Find: long double
Replace: [Skip over]

Criteria: 52
Highlight: True
Find: { Extended | Ext }
Replace: long double

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

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

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

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

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

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

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

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

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

Criteria: 62
Find: Choose[&]({index}, {choice})
Replace: IIf({index}, {choice}, 0)

Criteria: 63
Find: Choose$({index}, {choice})
Replace: IIf({index}, {choice}, "")

Criteria: 64
PassOnce: False
Find: Choose[{type: $ | & }]({index}, {choice1}, {more})
Replace: IIf({index}, {choice1}, Choose{type}({index}, {more}))

Criteria: 65
Find: StdOut {text} { {sameline: ;} | {NewLine: } }
Replace: cout << {text} {NewLine: << endl;}

Criteria: 66
Find: Sleep {milliseconds}
Replace: PB_SLEEP({milliseconds})

Criteria: 67
Selected: True
Find: CvDwd({string} [, {offset=1}])
Replace: PB_CVDWD({string}, {offset})

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

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

Criteria: 70
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: 71
SkipOver: True
Find: ({cond} ? {this} :
Replace: [Skip over]

Criteria: 72
Highlight: True
Find: :
Replace: ;

Criteria: 73
SkipOver: True
Find: ::
Replace: [Skip over]

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

Criteria: 75
PassOnce: False
Find: IIf[$]({cond}, {this}, {that})
Replace: ({cond} ? {this} : {that})

Criteria: 76
Find: _char([{char= }])
Replace: '{char}'

# End Search

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

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 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
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
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

         #include "pbOS.h"
         #include "pbMisc.h"
         {@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: Functions, Subs, =
Pass: 2

Criteria: 7
Highlight: True
Find: =
Replace: ==

Criteria: 8
SkipOver: True
Find: { + | - | * | / | % | & | ^ | ! }=
Replace: [Skip over]

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

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

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

Criteria: 12
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: 13
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: 14
Highlight: True
PassOnce: False
Find: Function PBMain [()] [As Long]
Replace: Function main() As Long

Criteria: 15
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: 16
Highlight: True
Find: Declare Sub {name:1} [Lib {lib}] [Alias {alias}]
      [([{args}])]
Replace: {lib: extern __declspec(dllimport)} void {name}({args})

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

Criteria: 18
Comment: Misc
Pass: 3

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

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

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

Criteria: 22
Highlight: True
BackColor: Green
Find: %{equate:"[a-z]+"}
Replace: {equate}

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

Criteria: 24
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: 25
Highlight: True
PassOnce: False
Find: If {cond} Then {nl}
         {code+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 26
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: 27
Highlight: True
PassOnce: False
Find: While {cond} {nl}
         {code+}
      Wend
Replace: while ({cond}) {
            {code}
         }

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

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

Criteria: 30
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: 31
Highlight: True
BackColor: Orange
PassOnce: False
Find: { Dim | {member: {nl}}} {var:1} As {type} [{ptr: Ptr}]
Replace: {member: {nl}}{type} {ptr:*}{var};

Criteria: 32
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: 33
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: 34
Highlight: True
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

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

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

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

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

Criteria: 39
Find: Iterate
Replace: continue

Criteria: 40
Find: Exit
Replace: break

Criteria: 41
Highlight: True
Find: Exit Sub
Replace: return

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

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

Criteria: 44
Find: Double
Replace: double

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

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

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

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

Criteria: 49
Find: AsciiZ
Replace: LPCSTR

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

Criteria: 51
SkipOver: True
Find: long double
Replace: [Skip over]

Criteria: 52
Highlight: True
Find: { Extended | Ext }
Replace: long double

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

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

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

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

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

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

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

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

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

Criteria: 62
Find: Choose[&]({index}, {choice})
Replace: IIf({index}, {choice}, 0)

Criteria: 63
Find: Choose$({index}, {choice})
Replace: IIf({index}, {choice}, "")

Criteria: 64
PassOnce: False
Find: Choose[{type: $ | & }]({index}, {choice1}, {more})
Replace: IIf({index}, {choice1}, Choose{type}({index}, {more}))

Criteria: 65
Find: StdOut {text} { {sameline: ;} | {NewLine: } }
Replace: cout << {text} {NewLine: << endl;}

Criteria: 66
Selected: True
Find: Sleep {milliseconds}
Replace: PB_SLEEP({milliseconds})

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

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

Criteria: 69
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: 70
SkipOver: True
Find: ({cond} ? {this} :
Replace: [Skip over]

Criteria: 71
Highlight: True
Find: :
Replace: ;

Criteria: 72
SkipOver: True
Find: ::
Replace: [Skip over]

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

Criteria: 74
PassOnce: False
Find: IIf[$]({cond}, {this}, {that})
Replace: ({cond} ? {this} : {that})

Criteria: 75
Find: _char([{char= }])
Replace: '{char}'

# End Search


Update pb-to-cpp.uc

Update pb-to-cpp.uc

Added transforms for pointers

# convert.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.0 on 12/12/2013 10:07:36 AM
# 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: 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
Find: ' {comment~}
Replace: // {comment}

Criteria: 2
BackColor: Green
Find: {nl}%{equate} = {value%}
Replace: {nl}const int {equate} = {value};

Criteria: 3
BackColor: Green
Find: %{equate}
Replace: {equate}

Criteria: 4
BackColor: SandyBrown
Find: {"&h"}
Replace: 0x

Criteria: 5
BackColor: Green
Find: If {cond%} Then {statement%}{nl}
Replace: if ({cond}) { {statement} }{nl}

Criteria: 6
Find: If {cond%} Then {nl}
         {code%+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 7
BackColor: DarkKhaki
Find: Function {name} ([{args%}]) As {type%}{nl}
         {code%+}
      End Function
Replace: {type} {name}({args}) {
            {code}
         }

Criteria: 8
Find: Sub {name} ([{args%}]){nl}
         {code%+}
      End Sub
Replace: void {name}({args}) {
            {code}
         }

Criteria: 9
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: 10
Find: While {cond%} {nl}
         {code%+}
      Wend
Replace: while ({cond}) {
            {code}
         }

Criteria: 11
BackColor: Orange
Find: Dim {var} As {type%} [{ptr: Ptr}]
Replace: {type} {ptr:*}{var};

Criteria: 12
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

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

Criteria: 14
Find: @
Replace: *

Criteria: 15
BackColor: Silver
Find: VarPtr({var})
Replace: &{var}

Criteria: 16
BackColor: DeepSkyBlue
Find: Function = {value}
Replace: return {value};

Criteria: 17
BackColor: Lime
Find: Long
Replace: long

Criteria: 18
BackColor: Red
Find: Single
Replace: float

Criteria: 19
BackColor: SlateBlue
Find: ByRef {arg} As {type%:1}
Replace: {type}& {arg}

Criteria: 20
BackColor: Pink
Find: ByVal {arg} As {type%:1}
Replace: {type} {arg}

# End Search

# convert.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.0 on 12/11/2013 12:34:34 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: 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
Find: ' {comment~}
Replace: // {comment}

Criteria: 2
BackColor: Green
Find: {nl}%{equate} = {value%}
Replace: {nl}const int {equate} = {value};

Criteria: 3
BackColor: Green
Find: %{equate}
Replace: {equate}

Criteria: 4
BackColor: SandyBrown
Find: {"&h"}
Replace: 0x

Criteria: 5
BackColor: Green
Find: If {cond%} Then {statement%}{nl}
Replace: if ({cond}) { {statement} }{nl}

Criteria: 6
Find: If {cond%} Then {nl}
         {code%+}
      End If
Replace: if ({cond}) {
            {code}
         }

Criteria: 7
BackColor: DarkKhaki
Find: Function {name} ([{args%}]) As {type%}{nl}
         {code%+}
      End Function
Replace: {type} {name}({args}) {
            {code}
         }

Criteria: 8
Find: Sub {name} ([{args%}]){nl}
         {code%+}
      End Sub
Replace: void {name}({args}) {
            {code}
         }

Criteria: 9
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: 10
Find: While {cond%} {nl}
         {code%+}
      Wend
Replace: while ({cond}) {
            {code}
         }

Criteria: 11
BackColor: Orange
Find: Dim {var} As {type%}
Replace: {type} {var};

Criteria: 12
BackColor: SandyBrown
PassOnce: False
Find: Dim {var1}, {more}
Replace: Dim {var1}
         Dim {more}

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

Criteria: 14
BackColor: DeepSkyBlue
Find: Function = {value}
Replace: return {value};

Criteria: 15
BackColor: Lime
Find: Long
Replace: long

Criteria: 16
BackColor: Red
Find: Single
Replace: float

Criteria: 17
BackColor: SlateBlue
Find: ByRef {arg} As {type%:1}
Replace: {type}& {arg}

Criteria: 18
BackColor: Pink
Find: ByVal {arg} As {type%:1}
Replace: {type} {arg}

# End Search


Update math.uc

Update math.uc

Added Randomize and Rnd

# math.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.5 on 1/31/2014 12:32:06 PM
# Comment: Converts math-related code from PowerBASIC to C++

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: False
Exclude: False
Comment: Converts math-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
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: ^ (power)
Pass: 1

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

Criteria: 3
Enabled: True
BackColor: Gold
Precedence: 100
Find: {x} ^ {y}  {@Note: precedence property set to 100}
Replace: pow({x}, {y})

Criteria: 4
Comment: Bitwise AND and OR
Pass: 2

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

Criteria: 6
Enabled: True
Comment: Bitwise AND and OR
BackColor: YellowGreen
Find: ({expr})
Replace: ({@Eval: Replace(Replace('{expr}', "And", "&"), "Or", "|")})

Criteria: 7
Comment: Everything else
Pass: 3

Criteria: 8
Enabled: True
Find: {@Start}
      {@Note:
         ToDo:  \ exp10 frac sgn shift
               eqv imp bin hex oct Not
               and fix LCase for next version
      }
Replace: #include <math.h>
         #include <stdlib.h>
         {@Note: rand & srand are in stdlib.h}

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

Criteria: 10
Enabled: False
Find: {func: Abs|Sin|Cos|Tan|Exp|Exp2|Log|Log2|Log10|Ceil}
Replace: {@Evaluate: LCase({func})}

Criteria: 11
Enabled: True
Find: Mod
Replace: %

Criteria: 12
Enabled: True
BackColor: Yellow
Find: Atn
Replace: atan

Criteria: 13
Enabled: True
BackColor: Lime
Find: Sqr
Replace: sqrt

Criteria: 14
Enabled: True
BackColor: Brown
Find: Fix
Replace: trunc

Criteria: 15
Enabled: True
BackColor: Pink
Find: Cint
Replace: lround

Criteria: 16
Enabled: True
BackColor: Red
Find: Incr {var:1}
Replace: {var}++

Criteria: 17
Enabled: True
BackColor: RoyalBlue
Find: Decr {var:1}
Replace: {var}--

Criteria: 18
Enabled: True
Comment: Logical (short-circuit) AND
Find: And
Replace: &&

Criteria: 19
Enabled: True
Comment: Logical (short-circuit) OR
BackColor: Purple
Find: Or
Replace: ||

Criteria: 20
Enabled: True
BackColor: Khaki
Find: Xor
Replace: ^

Criteria: 21
Enabled: True
BackColor: Green
Find: Not
Replace: ~

Criteria: 22
Enabled: True
SkipOver: True
Find: #{metastatement:1} Not
Replace: [Skip over]

Criteria: 23
Enabled: True
BackColor: Silver
Find: IsTrue {x}
Replace: ({x} <> 0)

Criteria: 24
Enabled: True
BackColor: SandyBrown
Find: IsFalse {x}
Replace: !{x}

Criteria: 25
Enabled: True
BackColor: Violet
Find: <>
Replace: !=

Criteria: 26
Enabled: True
Find: Randomize {number}
Replace: srand({number})

Criteria: 27
Enabled: True
Selected: True
Find: Rnd[()]
Replace: (rand() / RAND_MAX)

Criteria: 28
Enabled: True
Find: Rnd({a}, {b})
Replace: (rand() % ({b}) + ({a}))

# End Search

# math.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.5 on 1/20/2014 4:50:16 PM
# Comment: Converts math-related code from PowerBASIC to C++

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: False
Exclude: False
Comment: Converts math-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
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: ^ (power)
Pass: 1

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

Criteria: 3
Enabled: True
BackColor: Gold
Precedence: 100
Find: {x} ^ {y}  {@Note: precedence property set to 100}
Replace: pow({x}, {y})

Criteria: 4
Comment: Bitwise AND and OR
Pass: 2

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

Criteria: 6
Enabled: True
Comment: Bitwise AND and OR
BackColor: YellowGreen
Find: ({expr})
Replace: ({@Eval: Replace(Replace('{expr}', "And", "&"), "Or", "|")})

Criteria: 7
Comment: Everything else
Pass: 3

Criteria: 8
Enabled: True
Selected: True
Find: {@Start}
      {@Note:
         ToDo:  \ exp10 frac sgn shift
               eqv imp bin hex oct Not
               and fix LCase for next version
      }
Replace: #include <math.h>{nl}

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

Criteria: 10
Enabled: False
Find: {func: Abs|Sin|Cos|Tan|Exp|Exp2|Log|Log2|Log10|Ceil}
Replace: {@Evaluate: LCase({func})}

Criteria: 11
Enabled: True
Find: Mod
Replace: %

Criteria: 12
Enabled: True
BackColor: Yellow
Find: Atn
Replace: atan

Criteria: 13
Enabled: True
BackColor: Lime
Find: Sqr
Replace: sqrt

Criteria: 14
Enabled: True
BackColor: Brown
Find: Fix
Replace: trunc

Criteria: 15
Enabled: True
BackColor: Pink
Find: Cint
Replace: lround

Criteria: 16
Enabled: True
BackColor: Red
Find: Incr {var:1}
Replace: {var}++

Criteria: 17
Enabled: True
BackColor: RoyalBlue
Find: Decr {var:1}
Replace: {var}--

Criteria: 18
Enabled: True
Comment: Logical (short-circuit) AND
Find: And
Replace: &&

Criteria: 19
Enabled: True
Comment: Logical (short-circuit) OR
BackColor: Purple
Find: Or
Replace: ||

Criteria: 20
Enabled: True
BackColor: Khaki
Find: Xor
Replace: ^

Criteria: 21
Enabled: True
BackColor: Green
Find: Not
Replace: ~

Criteria: 22
Enabled: True
SkipOver: True
Find: #{metastatement:1} Not
Replace: [Skip over]

Criteria: 23
Enabled: True
BackColor: Silver
Find: IsTrue {x}
Replace: ({x} <> 0)

Criteria: 24
Enabled: True
BackColor: SandyBrown
Find: IsFalse {x}
Replace: !{x}

Criteria: 25
Enabled: True
BackColor: Violet
Find: <>
Replace: !=

# End Search


Create typespecifiers.uc

Create typespecifiers.uc

This refactors PB code in preparation for conversion to C++ as follows:

* Adds explicit ByRef to routine parameters that are not explicitly preceded by ByVal or ByRef
* Changes type specifiers to type names in parameter or variable definitions (ex: Dim txt$ becomes Dim txt As String) and removes them elsewhere
* Adds data type name to params that have neither an explicit type name or specifier, based on DefType definitions

See the typespecifiers.bas sample file.

Note: This includes additional code missing in the uCalc Transform 2.0 version of the same transform.

# TypeSpecifiers.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.0 on 10/28/2013 5:34:10 PM
# Comment: Replaces data type specifiers with explicit type names

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: Replaces data type specifiers with explicit type names
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
Highlight: False
Find: {@Note:
         This transform does the following:

         * Adds explicit ByRef to args w/o ByVal or ByRef
         * Changes type specifiers to type names in param
           definitions and removes them elsewhere
         * Adds data type name to params that have neither
           an explicit type name or specifier, based on
           DefType definitions

         The section to the immediate right defines the
         required tables and an array to accomplish this.
      }
Replace: {@Define:
            LineContinue: " _"
            Var: DefTypeInitial(255) As String
            Var: Specifier As Table = _
                 {"%", "Integer", "&", "Long", "&&", "Quad", _
                  "?", "Byte", "??", "Word", "???", "Dword", _
                  "!", "Single", "#", "Double", "##", "Extended", _
                  "@", "Currency", "@@", "CurrencyX", "$", "String"}
            Var: DefType As Table = _
                 {"INT", "Integer", "LNG", "Long", "QUD", "Quad", _
                 "BYT", "Byte", "WRD", "Word", "DWD", "Dword", _
                 "SNG", "Single", "DBL", "Double", "EXT", "Extended", _
                 "CUR", "Currency", "CUX", "CurrencyX", "STR", "String"}
            Var: dType="(INT|LNG|QUD|BYT|WRD|DWD|SNG|DBL|EXT|CUR|CUX|STR)\b"
         }{@Define:: Token: \x27.* ~~ Properties: ucWhitespace}

Criteria: 2
Comment: Handles DefType declarations; also inserts <Arg> marker for easier parsing
Pass: 1

Criteria: 3
Comment: Stores the DefType statement associated with character initials
Highlight: False
BackColor: Purple
Find: {"Def"}{type:"{@Eval: dType}"} {char} {nl}
Replace: {@Eval:
            SetVar(DefTypeInitial(Asc(LCase("{char}"))), ReadStr(DefType, "{type}"))
            SetVar(DefTypeInitial(Asc(UCase("{char}"))), ReadStr(DefType, "{type}"))
         }

Criteria: 4
Comment: Changes a DefType range into multiple DefType statements
Highlight: False
BackColor: SlateBlue
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {from}-{to} {nl}
Replace: {@Eval: Range(Asc("{from}"), Asc("{to}"), "'Def{type} '+Chr(x)+Chr(10)")}

Criteria: 5
Comment: Break DefType statements containing commas into multiple DefStype statements (one per line)
Highlight: False
BackColor: Pink
PassOnce: False
Find: {"Def"}{type:"{@Eval: dType}"} {etc}, {more} {nl}
Replace: Def{type} {etc}
         Def{type} {more}

Criteria: 6
Comment: Inserts <arg> marker for easier parsing
Highlight: False
BackColor: Red
Find: {nl}{decl: Sub | Function } {etc} ({args})
Replace: {nl}{decl} {etc}(<Arg>{@Eval: Replace("{args}", ",", ", <Arg>")})

Criteria: 7
Highlight: False
SkipOver: True
Find: {nl}Function =
Replace: [Skip over]

Criteria: 8
Comment: Inserts ByRef to params that have neither ByRef nor ByVal
Pass: 2

Criteria: 9
Comment: Inserts ByRef in front of params that do not explicitlly have ByVal or ByRef
Highlight: False
BackColor: SandyBrown
Find: <Arg> [{optional: Optional}] {name:1}
Replace: <Arg>{optional} ByRef {name}

Criteria: 10
Comment: Skips params that already have ByVal or ByRef
Highlight: False
BackColor: Green
SkipOver: True
Find: <Arg> [Optional] { ByVal | ByRef }
Replace: [Skip over]

Criteria: 11
Comment: Adds explicit data types to arg or variable declarations (functions also)
Pass: 3

Criteria: 12
Highlight: False
BackColor: RoyalBlue
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}
Replace: <Arg>{by} {name} As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 13
Highlight: False
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1}{spec:"[!?@#$%&]+"}
Replace: <Arg>{by} {name} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 14
Selected: True
Highlight: False
SkipOver: True
Find: <Arg> [Optional] {by: ByVal | ByRef } {name:1} As
Replace: [Skip over]

Criteria: 15
Highlight: False
BackColor: Tomato
PassOnce: False
Find: {decl: Dim | Global | Local | Static } {etc} {spec:"[!?@#$%&]+"}
Replace: {decl} {etc} As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 16
Comment: Adds the appropriate type for functions with no explicit type or specifier
Highlight: False
BackColor: CornflowerBlue
Find: {nl}Function {name:1}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: DefTypeInitial(Asc("{name}"))}

Criteria: 17
Comment: Changes function type specifier to data type name
Highlight: False
Find: {nl}Function {name:1}{spec:"[!?@#$%&]+"}([{args%}])
Replace: {nl}Function {name}({args}) As {@Eval: ReadStr(Specifier, "{spec}")}

Criteria: 18
Comment: Skips functions that already have an explicit type
Highlight: False
BackColor: Gold
Find: {nl}Function {name}([{args%}]) As {type}
Replace: {nl}Function {name}({args}) As {type}

Criteria: 19
Comment: Cleans up; removes <Arg> marker; as well as type specifiers
Pass: 4

Criteria: 20
Comment: Removes <Arg> that was inserted in earlier pass
Highlight: False
BackColor: SandyBrown
Find: <Arg>
Replace: {Nothing}

Criteria: 21
Comment: Removes statement specifiers
Highlight: False
BackColor: Violet
Find: {variable:"[a-z0-9_]+"}{spec:"[!?@#$%&]+"}
Replace: {variable}

# End Search

error: pathspec 'convert/typespecifiers.uc' did not match any file(s) known to git