[Runtime] Fixes #830

[Runtime] Fixes #830

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

DELEGATE ShowErrorDialog_Delegate(oError AS Error) AS INT
GLOBAL ShowErrorDialog_Handler AS ShowErrorDialog_Delegate

PROCEDURE ErrorSys _INIT1
   ErrorBlock( {|oError| DefError(oError)} )
   SetErrorLog( TRUE )
   SetErrorLogFile( "VOERROR.LOG" )
   RETURN

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/break/*" />
FUNCTION _Break(uValue AS USUAL) AS USUAL
	BREAK uValue

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/errorblock/*" />
FUNCTION ErrorBlock() AS USUAL STRICT
	LOCAL cbOld AS CODEBLOCK
	cbOld := XSharp.RuntimeState.GetValue<CODEBLOCK>(Set.ErrorBlock)
	IF cbOld == NULL_CODEBLOCK
		cbOld := {|e| DefError(  e ) }
		XSharp.RuntimeState.SetValue<CODEBLOCK>(Set.ErrorBlock, cbOld)
	ENDIF
	RETURN cbOld

FUNCTION ErrorExec(pErrInfo AS Exception) AS USUAL
    local cbError as CODEBLOCK
    local oError  as XSharp.Error
    cbError := ErrorBlock()
	oError := ErrorBuild(XSharp.Error{pErrInfo})
    RETURN cbError:Eval(oError)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/errorblock/*" />
FUNCTION ErrorBlock(cbNewSetting AS CODEBLOCK) AS USUAL
	LOCAL cbOld AS CODEBLOCK
	cbOld := XSharp.RuntimeState.GetValue<CODEBLOCK>(Set.ErrorBlock)
	XSharp.RuntimeState.SetValue<CODEBLOCK>(Set.ErrorBlock, cbNewSetting)
	RETURN cbOld

/// <exclude />
FUNCTION VO_Sprintf( format AS USUAL,  args PARAMS OBJECT[] ) AS STRING
    IF format:IsString
	    RETURN _VO_Sprintf( (STRING) format, args)
    ENDIF
    RETURN _VO_Sprintf( (DWORD) format, args)

INTERNAL FUNCTION DefError(oErr AS OBJECT) AS OBJECT PASCAL

	LOCAL dwChoice			AS INT
	LOCAL cMessage			AS STRING
	LOCAL cTitle			AS STRING
	LOCAL hf				AS IntPtr
	STATIC LOCAL dwDefError 		AS DWORD

	IF !(oErr IS Error)
		VAR err := Error{}
		err:Gencode   := EG_WRONGCLASS
		err:Severity  := ES_ERROR
		err:FuncSym    := "DefError"
		err:Arg        := oErr:ToString()
		err:ArgNum    :=  1
		err:CanDefault := .T.
		THROW err

	ENDIF
	LOCAL oError := (Error) oErr AS Error
	IF oError:CanDefault
		// network open error?
		IF (oError:Gencode = EG_OPEN)
			IF (oError:OSCode  = 32) .OR.;					// Sharing Violation
				(oError:OSCode  = 33)    .OR.;				// Lock Violation
				(oError:Gencode = EG_APPENDLOCK)
				NetErr(.T.)
				RETURN E_DEFAULT                // continue with default behavior
			ENDIF
		ENDIF
	ENDIF

	IF oError:Severity = ES_WARNING
		cTitle := "WARNING"
	ELSE
		cTitle := "ERROR"
	ENDIF

	IF oError:SubstituteType = PTR
		oError:Severity := ES_CATASTROPHIC
	ENDIF

	cMessage := oError:ToString()

	dwChoice := 3

	IF SetErrorLog()
		hf := __OpenErrorLog()

		IF hf != F_ERROR
			FSeek3(hf, 0, FS_END)
			__WriteErrorLog(hf, cMessage, oError)
			FClose(hf)
		ENDIF
	ENDIF
	IF ShowErrorDialog_Handler != NULL
		dwChoice := ShowErrorDialog_Handler(oError)
	ELSE
		dwChoice := MessageBoxW(IntPtr.Zero, cMessage, cTitle, MB_ABORTRETRYIGNORE)
	ENDIF

	DO CASE
	CASE dwChoice = IDIGNORE
		IF oError:CanSubstitute
			RETURN NULL
		ELSE
			RETURN E_DEFAULT
		ENDIF

	CASE dwChoice = IDRETRY
		RETURN E_RETRY
	ENDCASE

	IF CanBreak()
		THROW XSharp.Internal.WrappedException{oError}
	ENDIF

	ErrorLevel(oError:Gencode)

	dwDefError := 0

	CoreDb.CloseAll()

	_Quit()

	RETURN NIL

INTERNAL FUNCTION __OpenErrorLog() AS IntPtr PASCAL

	LOCAL cFile                     AS STRING
	LOCAL cBuffer                   AS STRING
	LOCAL hfRet                     AS IntPtr
    LOCAL cFolder                   AS STRING
    cFolder := System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly():Location)
	cFile := System.IO.Path.Combine(cFolder, SetErrorLogFile())

	hfRet := FOpen2(cFile, FO_WRITE)

	IF hfRet != F_ERROR
		FSeek3( hfRet, 0, FS_END)
		FPutS( hfRet, "", 0)
	ELSE
		hfRet := FCreate2(cFile, FC_ARCHIVED)

		IF FError() = 3                          // path not found

			cFile :=""

			IF !GetDefaultDir() ==""
				cBuffer :="SetDefaultDir: " +GetDefaultDir()
				SetDefaultDir(NULL_PSZ)
			ELSE
				cBuffer :="SetDefault: " +GetDefault()
				SetDefault("")
			ENDIF

			//_IError(EG_ARG, .F., String2Psz(cBuffer))
			? cBuffer
		ENDIF
	ENDIF

	RETURN hfRet

INTERNAL FUNCTION __WriteErrorLog (hf AS IntPtr, cMsg AS STRING, oError AS Error) AS VOID PASCAL
   LOCAL cExe		AS STRING

	FPutS(hf, "***********************ERROR********************************")
	FPutS(hf, __VERSION__ )
	FPutS(hf, DateTime.Now:ToString())
	cExe	:= _ExecName()
	FPutS(hf, "Application: " + cExe )
	FPutS(hf, " " )
	FPutS(hf, "Error message:" )
	FPutS(hf, "--------------" )
	FPutS(hf, cMsg)

	FPutS(hf, "Error Object created:" )
	FPutS(hf, "--------------------" )
	FPutS(hf, "SubSystem       :" + AsString(oError:SubSystem) )
	FPutS(hf, "SubCode         :" + AsString(oError:SubCode)   )
	FPutS(hf, "GenCode         :" + ErrString(oError:Gencode ) )

	IF oError:SubCode = E_EXCEPTION
		FPutS(hf, "ExceptionCode   :" + oError:OSCode:ToString("X") )
		FPutS(hf, "ExceptionFlags  :" + oError:ArgType:ToString("X") )
		FPutS(hf, "ExceptionAddress:" + oError:FuncPtr:ToString("X") )
		FPutS(hf, "ParamNumber     :" + AsString(oError:ArgNum)    )
		FPutS(hf, "ExceptionInfo   :" + AsString(oError:FuncSym) )

	ELSE

		FPutS(hf, "OsCode          :" + oError:OSCode:ToString() )
		FPutS(hf, "ArgType         :" + TypeString(oError:ArgType    ) )
		FPutS(hf, "FuncPtr         :" + oError:FuncPtr:ToString()   )
		FPutS(hf, "ArgNum          :" + oError:ArgNum:ToString()    )
		FPutS(hf, "FuncSym         :" + oError:FuncSym:ToString()   )

	ENDIF

	FPutS(hf, "Severity        :" + AsString(oError:Severity ) )
	FPutS(hf, "CanDefault      :" + AsString(oError:CanDefault))
	FPutS(hf, "CanRetry        :" + AsString(oError:CanRetry ) )
	FPutS(hf, "CanSubstitute   :" + AsString(oError:CanSubstitute))
	FPutS(hf, "Operation       :" + AsString(oError:Operation) )
	FPutS(hf, "Description     :" + AsString(oError:Description))
	FPutS(hf, "FileName        :" + AsString(oError:FileName ) )
	FPutS(hf, "Tries           :" + AsString(oError:Tries    ) )
	FPutS(hf, "FileHandle      :" + AsString(oError:FileHandle))
	FPutS(hf, "SubCodeText     :" + AsString(oError:SubCodeText))
	FPutS(hf, "Arg             :" + AsString(oError:Arg) )
	FPutS(hf, "ArgTypeReq      :" + TypeString(oError:ArgTypeReq) )
	FPutS(hf, "MaxSize         :" + AsString(oError:MaxSize      ) )
	FPutS(hf, "SubstituteType  :" + TypeString(oError:SubstituteType))
	FPutS(hf, "CallFuncSym     :" + AsString(oError:CallFuncSym ) )
	FPutS(hf, "--------------------" )

	RETURN
INTERNAL _DLL FUNCTION MessageBoxW(hwnd AS IntPtr, lpText AS STRING, lpCaption AS STRING, uType AS DWORD)	AS INT PASCAL:USER32.MessageBoxW UNICODE

INTERNAL  DEFINE MB_ABORTRETRYIGNORE    := 0x00000002U

INTERNAL DEFINE IDOK            := 1
INTERNAL DEFINE IDCANCEL        := 2
INTERNAL DEFINE IDABORT         := 3
INTERNAL DEFINE IDRETRY         := 4
INTERNAL DEFINE IDIGNORE        := 5
INTERNAL DEFINE IDYES           := 6
INTERNAL DEFINE IDNO            := 7
INTERNAL DEFINE IDCLOSE         := 8
INTERNAL DEFINE IDHELP          :=9
INTERNAL DEFINE IDTRYAGAIN      := 10
INTERNAL DEFINE IDCONTINUE      := 11

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

DELEGATE ShowErrorDialog_Delegate(oError AS Error) AS INT
GLOBAL ShowErrorDialog_Handler AS ShowErrorDialog_Delegate

PROCEDURE ErrorSys _INIT1
   ErrorBlock( {|oError| DefError(oError)} )
   SetErrorLog( TRUE )
   SetErrorLogFile( "VOERROR.LOG" )
   RETURN

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/break/*" />
FUNCTION _Break(uValue AS USUAL) AS USUAL
	BREAK uValue

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/errorblock/*" />
FUNCTION ErrorBlock() AS USUAL STRICT
	LOCAL cbOld AS CODEBLOCK
	cbOld := XSharp.RuntimeState.GetValue<CODEBLOCK>(Set.ErrorBlock)
	IF cbOld == NULL_CODEBLOCK
		cbOld := {|e| DefError(  e ) }
		XSharp.RuntimeState.SetValue<CODEBLOCK>(Set.ErrorBlock, cbOld)
	ENDIF
	RETURN cbOld

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/errorblock/*" />
FUNCTION ErrorBlock(cbNewSetting AS CODEBLOCK) AS USUAL
	LOCAL cbOld AS CODEBLOCK
	cbOld := XSharp.RuntimeState.GetValue<CODEBLOCK>(Set.ErrorBlock)
	XSharp.RuntimeState.SetValue<CODEBLOCK>(Set.ErrorBlock, cbNewSetting)
	RETURN cbOld

/// <exclude />
FUNCTION VO_Sprintf( format AS USUAL,  args PARAMS OBJECT[] ) AS STRING
    IF format:IsString
	    RETURN _VO_Sprintf( (STRING) format, args)
    ENDIF
    RETURN _VO_Sprintf( (DWORD) format, args)

INTERNAL FUNCTION DefError(oErr AS OBJECT) AS OBJECT PASCAL

	LOCAL dwChoice			AS INT
	LOCAL cMessage			AS STRING
	LOCAL cTitle			AS STRING
	LOCAL hf				AS IntPtr
	STATIC LOCAL dwDefError 		AS DWORD

	IF !(oErr IS Error)
		VAR err := Error{}
		err:Gencode   := EG_WRONGCLASS
		err:Severity  := ES_ERROR
		err:FuncSym    := "DefError"
		err:Arg        := oErr:ToString()
		err:ArgNum    :=  1
		err:CanDefault := .T.
		THROW err

	ENDIF
	LOCAL oError := (Error) oErr AS Error
	IF oError:CanDefault
		// network open error?
		IF (oError:Gencode = EG_OPEN)
			IF (oError:OSCode  = 32) .OR.;					// Sharing Violation
				(oError:OSCode  = 33)    .OR.;				// Lock Violation
				(oError:Gencode = EG_APPENDLOCK)
				NetErr(.T.)
				RETURN E_DEFAULT                // continue with default behavior
			ENDIF
		ENDIF
	ENDIF

	IF oError:Severity = ES_WARNING
		cTitle := "WARNING"
	ELSE
		cTitle := "ERROR"
	ENDIF

	IF oError:SubstituteType = PTR
		oError:Severity := ES_CATASTROPHIC
	ENDIF

	cMessage := oError:ToString()

	dwChoice := 3

	IF SetErrorLog()
		hf := __OpenErrorLog()

		IF hf != F_ERROR
			FSeek3(hf, 0, FS_END)
			__WriteErrorLog(hf, cMessage, oError)
			FClose(hf)
		ENDIF
	ENDIF
	IF ShowErrorDialog_Handler != NULL
		dwChoice := ShowErrorDialog_Handler(oError)
	ELSE
		dwChoice := MessageBoxW(IntPtr.Zero, cMessage, cTitle, MB_ABORTRETRYIGNORE)
	ENDIF

	DO CASE
	CASE dwChoice = IDIGNORE
		IF oError:CanSubstitute
			RETURN NULL
		ELSE
			RETURN E_DEFAULT
		ENDIF

	CASE dwChoice = IDRETRY
		RETURN E_RETRY
	ENDCASE

	IF CanBreak()
		THROW XSharp.Internal.WrappedException{oError}
	ENDIF

	ErrorLevel(oError:Gencode)

	dwDefError := 0

	CoreDb.CloseAll()

	_Quit()

	RETURN NIL

INTERNAL FUNCTION __OpenErrorLog() AS IntPtr PASCAL

	LOCAL cFile                     AS STRING
	LOCAL cBuffer                   AS STRING
	LOCAL hfRet                     AS IntPtr
    LOCAL cFolder                   AS STRING
    cFolder := System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly():Location)
	cFile := System.IO.Path.Combine(cFolder, SetErrorLogFile())

	hfRet := FOpen2(cFile, FO_WRITE)

	IF hfRet != F_ERROR
		FSeek3( hfRet, 0, FS_END)
		FPutS( hfRet, "", 0)
	ELSE
		hfRet := FCreate2(cFile, FC_ARCHIVED)

		IF FError() = 3                          // path not found

			cFile :=""

			IF !GetDefaultDir() ==""
				cBuffer :="SetDefaultDir: " +GetDefaultDir()
				SetDefaultDir(NULL_PSZ)
			ELSE
				cBuffer :="SetDefault: " +GetDefault()
				SetDefault("")
			ENDIF

			//_IError(EG_ARG, .F., String2Psz(cBuffer))
			? cBuffer
		ENDIF
	ENDIF

	RETURN hfRet

INTERNAL FUNCTION __WriteErrorLog (hf AS IntPtr, cMsg AS STRING, oError AS Error) AS VOID PASCAL
   LOCAL cExe		AS STRING

	FPutS(hf, "***********************ERROR********************************")
	FPutS(hf, __VERSION__ )
	FPutS(hf, DateTime.Now:ToString())
	cExe	:= _ExecName()
	FPutS(hf, "Application: " + cExe )
	FPutS(hf, " " )
	FPutS(hf, "Error message:" )
	FPutS(hf, "--------------" )
	FPutS(hf, cMsg)

	FPutS(hf, "Error Object created:" )
	FPutS(hf, "--------------------" )
	FPutS(hf, "SubSystem       :" + AsString(oError:SubSystem) )
	FPutS(hf, "SubCode         :" + AsString(oError:SubCode)   )
	FPutS(hf, "GenCode         :" + ErrString(oError:Gencode ) )

	IF oError:SubCode = E_EXCEPTION
		FPutS(hf, "ExceptionCode   :" + oError:OSCode:ToString("X") )
		FPutS(hf, "ExceptionFlags  :" + oError:ArgType:ToString("X") )
		FPutS(hf, "ExceptionAddress:" + oError:FuncPtr:ToString("X") )
		FPutS(hf, "ParamNumber     :" + AsString(oError:ArgNum)    )
		FPutS(hf, "ExceptionInfo   :" + AsString(oError:FuncSym) )

	ELSE

		FPutS(hf, "OsCode          :" + oError:OSCode:ToString() )
		FPutS(hf, "ArgType         :" + TypeString(oError:ArgType    ) )
		FPutS(hf, "FuncPtr         :" + oError:FuncPtr:ToString()   )
		FPutS(hf, "ArgNum          :" + oError:ArgNum:ToString()    )
		FPutS(hf, "FuncSym         :" + oError:FuncSym:ToString()   )

	ENDIF

	FPutS(hf, "Severity        :" + AsString(oError:Severity ) )
	FPutS(hf, "CanDefault      :" + AsString(oError:CanDefault))
	FPutS(hf, "CanRetry        :" + AsString(oError:CanRetry ) )
	FPutS(hf, "CanSubstitute   :" + AsString(oError:CanSubstitute))
	FPutS(hf, "Operation       :" + AsString(oError:Operation) )
	FPutS(hf, "Description     :" + AsString(oError:Description))
	FPutS(hf, "FileName        :" + AsString(oError:FileName ) )
	FPutS(hf, "Tries           :" + AsString(oError:Tries    ) )
	FPutS(hf, "FileHandle      :" + AsString(oError:FileHandle))
	FPutS(hf, "SubCodeText     :" + AsString(oError:SubCodeText))
	FPutS(hf, "Arg             :" + AsString(oError:Arg) )
	FPutS(hf, "ArgTypeReq      :" + TypeString(oError:ArgTypeReq) )
	FPutS(hf, "MaxSize         :" + AsString(oError:MaxSize      ) )
	FPutS(hf, "SubstituteType  :" + TypeString(oError:SubstituteType))
	FPutS(hf, "CallFuncSym     :" + AsString(oError:CallFuncSym ) )
	FPutS(hf, "--------------------" )

	RETURN
INTERNAL _DLL FUNCTION MessageBoxW(hwnd AS IntPtr, lpText AS STRING, lpCaption AS STRING, uType AS DWORD)	AS INT PASCAL:USER32.MessageBoxW UNICODE

INTERNAL  DEFINE MB_ABORTRETRYIGNORE    := 0x00000002U

INTERNAL DEFINE IDOK            := 1
INTERNAL DEFINE IDCANCEL        := 2
INTERNAL DEFINE IDABORT         := 3
INTERNAL DEFINE IDRETRY         := 4
INTERNAL DEFINE IDIGNORE        := 5
INTERNAL DEFINE IDYES           := 6
INTERNAL DEFINE IDNO            := 7
INTERNAL DEFINE IDCLOSE         := 8
INTERNAL DEFINE IDHELP          :=9
INTERNAL DEFINE IDTRYAGAIN      := 10
INTERNAL DEFINE IDCONTINUE      := 11


codegen/QtTest: updated

codegen/QtTest: updated

Modified:
codegen/QtTest/QTestEventList.prg

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=

$addMethods

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

//[1]QTestEventList ()
//[2]QTestEventList ( const QTestEventList & other )

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=

   METHOD new
   METHOD delete
   METHOD addDelay
   METHOD addKeyClick1
   METHOD addKeyClick2
   METHOD addKeyClick
   METHOD addKeyClicks
   METHOD addKeyPress1
   METHOD addKeyPress2
   METHOD addKeyPress
   METHOD addKeyRelease1
   METHOD addKeyRelease2
   METHOD addKeyRelease
   METHOD addMouseClick
   METHOD addMouseDClick
   METHOD addMouseMove
   METHOD addMousePress
   METHOD addMouseRelease
   METHOD clear
   METHOD simulate

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

//[1]QTestEventList ()
//[2]QTestEventList ( const QTestEventList & other )

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP


Fixes DependentUpon node with paths

Fixes DependentUpon node with paths

// Application : XPorter
// XPorter.prg , Created : 28-9-2016   15:02
// User : robert

USING System.Collections.Generic
USING System.Xml
DEFINE EXTENSION := "xsproj"  AS STRING

CLASS ProjectConverter
	PROTECT oDoc 	AS XmlDocument
	PROTECT nGroup  AS LONG
	PROTECT cSchema AS STRING
	PROTECT cGuid   AS STRING
	PROTECT cPath	AS STRING
	PROTECT oProgress AS IProgress
	PROTECT lVulcanRtWritten AS LOGIC
	PROPERTY Guid AS STRING GET cGuid
	CONSTRUCTOR(oProg AS IProgress)
		cSchema := "http://schemas.microsoft.com/developer/msbuild/2003"
		nGroup  := 0
        cGuid   := System.Guid.NewGuid().ToString("B"):ToUpper()
        lVulcanRtWritten := FALSE
        SELF:oProgress := oProg

METHOD ConvertProjectFile(cSource AS STRING, cTarget AS STRING) AS LOGIC
	oProgress:WriteLine("Creating ... "+System.IO.Path.GetFileName(cTarget))
	cPath := System.IO.Path.GetDirectoryName(cSource)+"\"
	IF ! SELF:LoadFile(cSource)
		RETURN FALSE
	ENDIF
	SELF:WalkNode(oDoc)
	SELF:SaveFile(cTarget)
	RETURN TRUE

  METHOD Save2String() AS STRING STRICT
      LOCAL cString         AS STRING
      LOCAL oWriter             AS System.Xml.XmlTextWriter
      LOCAL oStringWriter       AS System.IO.StringWriter
      cString := oDoc:OuterXml
      oStringWriter := System.IO.StringWriter{}
      oWriter     := System.Xml.XmlTextWriter{oStringWriter}
      oWriter:Formatting := System.Xml.Formatting.Indented
      oDoc:WriteTo(oWriter)
      cString := oStringWriter:ToString()
      RETURN cString

   METHOD SaveFile(strFileName AS STRING) AS LOGIC STRICT
      LOCAL lRet        AS LOGIC
      LOCAL oTargetFile  AS System.IO.StreamWriter
      lRet := FALSE
      IF oDoc:HasChildNodes
         oTargetFile := System.IO.StreamWriter{strFileName, FALSE}
         oTargetFile:Write( SELF:Save2String() )
         oTargetFile:Close()
         lRet := TRUE
      ENDIF
      RETURN lRet

METHOD CloneNode(oNode AS XmlNode) AS XmlNode
	LOCAL oResult AS XmlNode
	oResult := oNode:CloneNode(FALSE)
	oResult:InnerText := oNode:InnerText
	RETURN oResult

METHOD UpdateNode(oParent AS XmlNode, oElement AS XmlElement) AS VOID
	LOCAL oChild AS XmlElement
	LOCAL oAttribute AS XmlAttribute
	IF aDelete:Contains(oElement:Name:ToLower())
		// remove the node
		oParent:RemoveChild(oElement)
	ELSEIF aRename:ContainsKey(oElement:Name)
		// Renaming Nodes is not supported. Create a new node and
		// Copy its attributes and children
		// and then replace the existing node
		oChild := oDoc:CreateElement(aRename[oElement:Name],cSchema)
		DO WHILE oElement:HasAttributes
			oChild:SetAttributeNode(oElement:RemoveAttributeNode(oElement:Attributes[0]))
		ENDDO
		DO WHILE oElement:HasChildNodes
			oChild:AppendChild(oElement:FirstChild)
		ENDDO
		oParent:ReplaceChild(oChild, oElement)
	ELSE
		// Some nodes that require special processing
		SWITCH oElement:Name:ToLower()
		CASE "compile"
		CASE "none"
		CASE "vobinary"
		CASE "nativeresource"
			VAR oChild1 := oElement:FirstChild
			IF oChild1 != NULL .and. oChild1:Name:ToLowerInvariant() == "dependentupon"
				VAR  cInnerText := oChild1:InnerText
				IF cInnerText:Contains("\")
					cInnerText := cInnerText:Substring(cInnerText:IndexOf("\")+1)
					oChild1:InnerText := cInnerText
				ENDIF
			ENDIF

		CASE "import"
			// change import
			oAttribute := (XmlAttribute) oElement:Attributes:GetNamedItem("Project")
			IF oAttribute:Value:ToLower():Contains("vulcan.net")
				oAttribute:Value := "$(XSharpProjectExtensionsPath)XSharp.props"
			ENDIF
		CASE "projectguid"
			// new guid
			oElement:InnerText := cGuid
		CASE "projectreference"
			// update extension in project references
			oAttribute := (XmlAttribute) oElement:Attributes:GetNamedItem("Include")
			IF oAttribute != NULL
				oAttribute:Value := oAttribute:Value:Replace(".vnproj", "."+EXTENSION)
			ENDIF
		CASE "propertygroup"
			// Only insert code inside the first propertygroup
			IF ++nGroup == 1
				LOCAL oImport AS XmlNode
				// Add Import
				oImport := oDoc:CreateElement("Import",cSchema)
				oAttribute := oDoc:CreateAttribute("Project")
				oAttribute:Value := "$(MSBuildExtensionsPath)\XSharp\XSharp.Default.props"
				oImport:Attributes:Append(oAttribute)
				oParent:InsertBefore(oImport, oElement)
				// Add propertygroup before Import with Label="Globals" and child <XSharpProjectExtensionsPath>
				oChild := oDoc:CreateElement( "PlatformTarget", cSchema)
				oChild:InnerText := "x86"
				oElement:InsertBefore(oChild,oElement:FirstChild)
				oChild := oDoc:CreateElement( "Dialect", cSchema)
				oChild:InnerText := "Vulcan"
				oElement:InsertBefore(oChild,oElement:FirstChild)
				oChild := oDoc:CreateElement( "XSharpProjectExtensionsPath", cSchema)
				oChild:InnerText := "$(MSBuildExtensionsPath)\XSharp\"
				oElement:InsertBefore(oChild, oElement:FirstChild )

				LOCAL lHasCondition := FALSE AS LOGIC
				IF oElement:HasAttributes
					lHasCondition := (oElement:Attributes:GetNamedItem("Condition") != NULL)
				ENDIF
				IF ! lHasCondition
					oChild := oDoc:CreateElement("Platform", cSchema)
					oAttribute := oDoc:CreateAttribute("Condition")
					oAttribute:Value := " '$(Platform)' == '' "
					oChild:Attributes:Append(oAttribute)
					oChild:InnerText := "AnyCPU"
					oElement:PrependChild(oChild)
				ENDIF
			ELSE
				// ALl other project groups.
				// Adjust the condition when needed
				VAR oCondition := (XMLAttribute) oElement:Attributes:GetNamedItem("Condition")
				// <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'" Label="Configuration">
				IF oCondition != NULL
					VAR  cInnerText := oCondition:InnerText
					if ! cInnerText:ToLower():Contains("platform")
						if cInnerText:ToLower():Contains("release")
							oCondition:InnerText := "'$(Configuration)|$(Platform)'=='Release|AnyCPU'"
						else
							oCondition:InnerText := "'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"
						endif
					ENDIF
				ENDIF
			ENDIF
		CASE "projectextensions"
			// Import the schema
			oChild := oDoc:CreateElement("Import", cSchema)
			oAttribute := oDoc:CreateAttribute("Project")
			oAttribute:Value := "$(XSharpProjectExtensionsPath)XSharp.targets"
			oChild:Attributes:Append(oAttribute)
			oParent:InsertBefore(oChild, oElement)
			// add <ProjectCapabilities><ProjectConfigurationsDeclaredAsItems /></ProjectCapabilities>
			oChild := oDoc:CreateElement("ProjectCapabilities",cSchema)
			oChild:AppendChild(oDoc:CreateElement("ProjectConfigurationsDeclaredAsItems",cSchema))
			oElement:AppendChild(oChild)
		CASE "reference"
			// Add VulcanRT assemblies after 1st reference
			IF !SELF:lVulcanRtWritten
				oChild := oDoc:CreateElement("Reference",cSchema)
				oAttribute := oDoc:CreateAttribute("Include")
				oAttribute:Value := "VulcanRT"
				oChild:Attributes:Append(oAttribute)
				VAR oSub := oDoc:CreateElement("Name",cSchema)
				oSub:InnerText := "VulcanRT"
				oChild:AppendChild(oSub)
				oSub := oDoc:CreateElement("AssemblyName",cSchema)
				oSub:InnerText := "VulcanRT.DLL"
				oChild:AppendChild(oSub)
				oElement:ParentNode:AppendChild(oChild)
				oChild := oDoc:CreateElement("Reference",cSchema)
				oAttribute := oDoc:CreateAttribute("Include")
				oAttribute:Value := "VulcanRTFuncs"
				oChild:Attributes:Append(oAttribute)
				oSub := oDoc:CreateElement("Name",cSchema)
				oSub:InnerText := "VulcanRTFuncs"
				oChild:AppendChild(oSub)
				oSub := oDoc:CreateElement("AssemblyName",cSchema)
				oSub:InnerText := "VulcanRTFuncs.DLL"
				oChild:AppendChild(oSub)
				oElement:ParentNode:AppendChild(oChild)
				SELF:lVulcanRtWritten := TRUE
			ENDIF
		OTHERWISE
			// All other elements should not be changed
			NOP
		END SWITCH
	ENDIF
	RETURN

METHOD WalkNode(oNode AS XmlNode) AS VOID
	LOCAL aChildren AS List<XmlNode>
	aChildren := List<XmlNode>{}
	FOREACH oChild AS XmlNode IN oNode:ChildNodes
		aChildren:Add(oChild)
	NEXT
	FOREACH oChild AS XmlNode IN aChildren
		IF oChild IS XmlElement
			SELF:UpdateNode(oNode, (XmlElement) oChild)
		ENDIF
		SELF:WalkNode((XMlNode) oChild)
	NEXT
	RETURN

    PROTECT METHOD _LoadFileFromReader(oReader AS System.IO.TextReader) AS LOGIC STRICT
        LOCAL lOk AS LOGIC
        TRY
            oDoc := System.Xml.XmlDocument{}
            oDoc:Load(oReader)
            lOk := TRUE
        CATCH
            lOk := FALSE
        END TRY
        RETURN lOk

   METHOD LoadFile(strFileName AS STRING) AS LOGIC STRICT
        LOCAL lResult := FALSE AS LOGIC
        IF System.IO.File.Exists(strFileName)
            LOCAL oReader AS System.IO.TextReader
            oReader := System.IO.StreamReader{strFileName,TRUE}
            lResult := SELF:_LoadFileFromReader(oReader)
            oReader:Close()
        ENDIF
        RETURN lResult

   METHOD LoadFileFromString(strXMLString AS STRING) AS LOGIC STRICT
        LOCAL lResult AS LOGIC
        LOCAL oReader AS System.IO.StringReader
        oReader := System.IO.StringReader{strXMLString}
        lResult := SELF:_LoadFileFromReader(oReader)
        oReader:Close()
        RETURN lResult

	STATIC PROTECT aRename AS Dictionary<STRING, STRING>
	STATIC PROTECT aDelete AS List<STRING>
	STATIC CONSTRUCTOR()
		aRename := Dictionary<STRING, STRING> {StringComparer.CurrentCultureIgnoreCase}
		aRename:Add("ZeroBasedArrays","AZ")
		aRename:Add("CaseSensitiveIdentifiers","CS")
		aRename:Add("CheckFloatOverflows","FOVF")
		aRename:Add("ImplicitNamespaceLookup","INS")
		aRename:Add("AllowLateBinding","LB")
		aRename:Add("UseDefaultNamespace","NS")
		aRename:Add("CheckForOverflowUnderflow","OVF")
		aRename:Add("GeneratePreprocessorOutput","PPO")
		aRename:Add("AllowUnsafeCode","UnSafe")
		aRename:Add("VOCompatibleStringInit","VO2")
		aRename:Add("AllMethodsVirtual","VO3")
		aRename:Add("ImplicitSignConversions","VO4")
		aRename:Add("VOCompatibleCallingConventions","VO5")
		aRename:Add("VOResolveFunctionPointers","VO6")
		aRename:Add("VOCompatibleImplicitConversions","VO7")
		aRename:Add("VOCompatiblePreprocessor","VO8")
		aRename:Add("VOCompatibleImplicitRetvals","VO9")
		aRename:Add("VOCompatibleIIF","VO10")
		aRename:Add("VOCompatibleArithmeticConversions","VO11")
		aRename:Add("IntegerDivisionsReturnFloat","VO12")
		aRename:Add("VOCompatibleStringComparisons","VO13")
		aRename:Add("VOFloatLiterals","VO14")
		aRename:Add("AdditionalOptions","CommandLineOption")
		// Items to delete

		VAR aTemp := List<STRING>{}
		aTemp:Add("DisabledWarnings")
		aTemp:Add("ProjectName")
		aTemp:Add("ProjectExt")
		aTemp:Add("ProjectDir")
		aTemp:Add("ProjectFileName")
		aTemp:Add("ProjectPath")
		aTemp:Add("ProjectView")
		aTemp:Add("SchemaVersion")
		aDelete := List<STRING>{}
		FOREACH s AS STRING IN aTemp
			aDelete:Add(s:ToLower())
		NEXT

	RETURN

STATIC METHOD Convert(cFile AS STRING, oProgress AS IProgress) AS VOID
	LOCAL oConverter AS ProjectConverter
	LOCAL cSource AS STRING
	LOCAL cTarget AS STRING
	oConverter := ProjectConverter{oProgress}
	cSource := cFile
	cTarget := System.IO.Path.ChangeExtension(cSource, EXTENSION)
	IF oConverter:ConvertProjectFile(cSource, cTarget)
		oProgress:WriteLine( "Converted "+System.IO.Path.GetFileName(cSource)+" to " +System.IO.Path.GetFileName(cTarget))
	ELSE
		oProgress:WriteLine( "An error occurred")
	ENDIF
	RETURN

END CLASS

// Application : XPorter
// XPorter.prg , Created : 28-9-2016   15:02
// User : robert

USING System.Collections.Generic
USING System.Xml
DEFINE EXTENSION := "xsproj"  AS STRING

CLASS ProjectConverter
	PROTECT oDoc 	AS XmlDocument
	PROTECT nGroup  AS LONG
	PROTECT cSchema AS STRING
	PROTECT cGuid   AS STRING
	PROTECT cPath	AS STRING
	PROTECT oProgress AS IProgress
	PROTECT lVulcanRtWritten AS LOGIC
	PROPERTY Guid AS STRING GET cGuid
	CONSTRUCTOR(oProg AS IProgress)
		cSchema := "http://schemas.microsoft.com/developer/msbuild/2003"
		nGroup  := 0
        cGuid   := System.Guid.NewGuid().ToString("B"):ToUpper()
        lVulcanRtWritten := FALSE
        SELF:oProgress := oProg

METHOD ConvertProjectFile(cSource AS STRING, cTarget AS STRING) AS LOGIC
	oProgress:WriteLine("Creating ... "+System.IO.Path.GetFileName(cTarget))
	cPath := System.IO.Path.GetDirectoryName(cSource)+"\"
	IF ! SELF:LoadFile(cSource)
		RETURN FALSE
	ENDIF
	SELF:WalkNode(oDoc)
	SELF:SaveFile(cTarget)
	RETURN TRUE

  METHOD Save2String() AS STRING STRICT
      LOCAL cString         AS STRING
      LOCAL oWriter             AS System.Xml.XmlTextWriter
      LOCAL oStringWriter       AS System.IO.StringWriter
      cString := oDoc:OuterXml
      oStringWriter := System.IO.StringWriter{}
      oWriter     := System.Xml.XmlTextWriter{oStringWriter}
      oWriter:Formatting := System.Xml.Formatting.Indented
      oDoc:WriteTo(oWriter)
      cString := oStringWriter:ToString()
      RETURN cString

   METHOD SaveFile(strFileName AS STRING) AS LOGIC STRICT
      LOCAL lRet        AS LOGIC
      LOCAL oTargetFile  AS System.IO.StreamWriter
      lRet := FALSE
      IF oDoc:HasChildNodes
         oTargetFile := System.IO.StreamWriter{strFileName, FALSE}
         oTargetFile:Write( SELF:Save2String() )
         oTargetFile:Close()
         lRet := TRUE
      ENDIF
      RETURN lRet

METHOD CloneNode(oNode AS XmlNode) AS XmlNode
	LOCAL oResult AS XmlNode
	oResult := oNode:CloneNode(FALSE)
	oResult:InnerText := oNode:InnerText
	RETURN oResult

METHOD UpdateNode(oParent AS XmlNode, oElement AS XmlElement) AS VOID
	LOCAL oChild AS XmlElement
	LOCAL oAttribute AS XmlAttribute
	IF aDelete:Contains(oElement:Name:ToLower())
		// remove the node
		oParent:RemoveChild(oElement)
	ELSEIF aRename:ContainsKey(oElement:Name)
		// Renaming Nodes is not supported. Create a new node and
		// Copy its attributes and children
		// and then replace the existing node
		oChild := oDoc:CreateElement(aRename[oElement:Name],cSchema)
		DO WHILE oElement:HasAttributes
			oChild:SetAttributeNode(oElement:RemoveAttributeNode(oElement:Attributes[0]))
		ENDDO
		DO WHILE oElement:HasChildNodes
			oChild:AppendChild(oElement:FirstChild)
		ENDDO
		oParent:ReplaceChild(oChild, oElement)
	ELSE
		// Some nodes that require special processing
		SWITCH oElement:Name:ToLower()
		CASE "compile"
		CASE "none"
			VAR oLink := oElement:FirstChild
			IF oLink != NULL .and. oLink:Name:ToLowerInvariant() == "link"
				LOCAL cChild AS STRING
				LOCAL cNew   AS STRING
				cChild := oElement:GetAttribute("Include")
				cNew   := System.IO.Path.GetFileName(cChild)
				cChild := System.IO.Path.Combine(cPath, cChild)
				cNew   := System.IO.Path.Combine(cPath, cNew)
				IF System.IO.File.Exists(cChild)
					// create a normal file that includes the original file
					System.IO.File.WriteAllText(cNew, e"#include \"" + oElement:GetAttribute("Include") + e"\"\r\n")
					oElement:SetAttribute("Include", System.IO.Path.GetFileName(cChild))
					oElement:RemoveChild(oLink)
				ENDIF
			ENDIF

		CASE "import"
			// change import
			oAttribute := (XmlAttribute) oElement:Attributes:GetNamedItem("Project")
			IF oAttribute:Value:ToLower():Contains("vulcan.net")
				oAttribute:Value := "$(XSharpProjectExtensionsPath)XSharp.props"
			ENDIF
		CASE "projectguid"
			// new guid
			oElement:InnerText := cGuid
		CASE "projectreference"
			// update extension in project references
			oAttribute := (XmlAttribute) oElement:Attributes:GetNamedItem("Include")
			IF oAttribute != NULL
				oAttribute:Value := oAttribute:Value:Replace(".vnproj", "."+EXTENSION)
			ENDIF
		CASE "propertygroup"
			// Only insert code inside the first propertygroup
			IF ++nGroup == 1
				LOCAL oImport AS XmlNode
				// Add Import
				oImport := oDoc:CreateElement("Import",cSchema)
				oAttribute := oDoc:CreateAttribute("Project")
				oAttribute:Value := "$(MSBuildExtensionsPath)\XSharp\XSharp.Default.props"
				oImport:Attributes:Append(oAttribute)
				oParent:InsertBefore(oImport, oElement)
				// Add propertygroup before Import with Label="Globals" and child <XSharpProjectExtensionsPath>
				oChild := oDoc:CreateElement( "PlatformTarget", cSchema)
				oChild:InnerText := "x86"
				oElement:InsertBefore(oChild,oElement:FirstChild)
				oChild := oDoc:CreateElement( "Dialect", cSchema)
				oChild:InnerText := "Vulcan"
				oElement:InsertBefore(oChild,oElement:FirstChild)
				oChild := oDoc:CreateElement( "XSharpProjectExtensionsPath", cSchema)
				oChild:InnerText := "$(MSBuildExtensionsPath)\XSharp\"
				oElement:InsertBefore(oChild, oElement:FirstChild )

				LOCAL lHasCondition := FALSE AS LOGIC
				IF oElement:HasAttributes
					lHasCondition := (oElement:Attributes:GetNamedItem("Condition") != NULL)
				ENDIF
				IF ! lHasCondition
					oChild := oDoc:CreateElement("Platform", cSchema)
					oAttribute := oDoc:CreateAttribute("Condition")
					oAttribute:Value := " '$(Platform)' == '' "
					oChild:Attributes:Append(oAttribute)
					oChild:InnerText := "AnyCPU"
					oElement:PrependChild(oChild)
				ENDIF
			ELSE
				// ALl other project groups.
				// Adjust the condition when needed
				VAR oCondition := (XMLAttribute) oElement:Attributes:GetNamedItem("Condition")
				// <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'" Label="Configuration">
				IF oCondition != NULL
					VAR  cInnerText := oCondition:InnerText
					if ! cInnerText:ToLower():Contains("platform")
						if cInnerText:ToLower():Contains("release")
							oCondition:InnerText := "'$(Configuration)|$(Platform)'=='Release|AnyCPU'"
						else
							oCondition:InnerText := "'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"
						endif
					ENDIF
				ENDIF
			ENDIF
		CASE "projectextensions"
			// Import the schema
			oChild := oDoc:CreateElement("Import", cSchema)
			oAttribute := oDoc:CreateAttribute("Project")
			oAttribute:Value := "$(XSharpProjectExtensionsPath)XSharp.targets"
			oChild:Attributes:Append(oAttribute)
			oParent:InsertBefore(oChild, oElement)
			// add <ProjectCapabilities><ProjectConfigurationsDeclaredAsItems /></ProjectCapabilities>
			oChild := oDoc:CreateElement("ProjectCapabilities",cSchema)
			oChild:AppendChild(oDoc:CreateElement("ProjectConfigurationsDeclaredAsItems",cSchema))
			oElement:AppendChild(oChild)
		CASE "reference"
			// Add VulcanRT assemblies after 1st reference
			IF !SELF:lVulcanRtWritten
				oChild := oDoc:CreateElement("Reference",cSchema)
				oAttribute := oDoc:CreateAttribute("Include")
				oAttribute:Value := "VulcanRT"
				oChild:Attributes:Append(oAttribute)
				VAR oSub := oDoc:CreateElement("Name",cSchema)
				oSub:InnerText := "VulcanRT"
				oChild:AppendChild(oSub)
				oSub := oDoc:CreateElement("AssemblyName",cSchema)
				oSub:InnerText := "VulcanRT.DLL"
				oChild:AppendChild(oSub)
				oElement:ParentNode:AppendChild(oChild)
				oChild := oDoc:CreateElement("Reference",cSchema)
				oAttribute := oDoc:CreateAttribute("Include")
				oAttribute:Value := "VulcanRTFuncs"
				oChild:Attributes:Append(oAttribute)
				oSub := oDoc:CreateElement("Name",cSchema)
				oSub:InnerText := "VulcanRTFuncs"
				oChild:AppendChild(oSub)
				oSub := oDoc:CreateElement("AssemblyName",cSchema)
				oSub:InnerText := "VulcanRTFuncs.DLL"
				oChild:AppendChild(oSub)
				oElement:ParentNode:AppendChild(oChild)
				SELF:lVulcanRtWritten := TRUE
			ENDIF
		OTHERWISE
			// All other elements should not be changed
			NOP
		END SWITCH
	ENDIF
	RETURN

METHOD WalkNode(oNode AS XmlNode) AS VOID
	LOCAL aChildren AS List<XmlNode>
	aChildren := List<XmlNode>{}
	FOREACH oChild AS XmlNode IN oNode:ChildNodes
		aChildren:Add(oChild)
	NEXT
	FOREACH oChild AS XmlNode IN aChildren
		IF oChild IS XmlElement
			SELF:UpdateNode(oNode, (XmlElement) oChild)
		ENDIF
		SELF:WalkNode((XMlNode) oChild)
	NEXT
	RETURN

    PROTECT METHOD _LoadFileFromReader(oReader AS System.IO.TextReader) AS LOGIC STRICT
        LOCAL lOk AS LOGIC
        TRY
            oDoc := System.Xml.XmlDocument{}
            oDoc:Load(oReader)
            lOk := TRUE
        CATCH
            lOk := FALSE
        END TRY
        RETURN lOk

   METHOD LoadFile(strFileName AS STRING) AS LOGIC STRICT
        LOCAL lResult := FALSE AS LOGIC
        IF System.IO.File.Exists(strFileName)
            LOCAL oReader AS System.IO.TextReader
            oReader := System.IO.StreamReader{strFileName,TRUE}
            lResult := SELF:_LoadFileFromReader(oReader)
            oReader:Close()
        ENDIF
        RETURN lResult

   METHOD LoadFileFromString(strXMLString AS STRING) AS LOGIC STRICT
        LOCAL lResult AS LOGIC
        LOCAL oReader AS System.IO.StringReader
        oReader := System.IO.StringReader{strXMLString}
        lResult := SELF:_LoadFileFromReader(oReader)
        oReader:Close()
        RETURN lResult

	STATIC PROTECT aRename AS Dictionary<STRING, STRING>
	STATIC PROTECT aDelete AS List<STRING>
	STATIC CONSTRUCTOR()
		aRename := Dictionary<STRING, STRING> {StringComparer.CurrentCultureIgnoreCase}
		aRename:Add("ZeroBasedArrays","AZ")
		aRename:Add("CaseSensitiveIdentifiers","CS")
		aRename:Add("CheckFloatOverflows","FOVF")
		aRename:Add("ImplicitNamespaceLookup","INS")
		aRename:Add("AllowLateBinding","LB")
		aRename:Add("UseDefaultNamespace","NS")
		aRename:Add("CheckForOverflowUnderflow","OVF")
		aRename:Add("GeneratePreprocessorOutput","PPO")
		aRename:Add("AllowUnsafeCode","UnSafe")
		aRename:Add("VOCompatibleStringInit","VO2")
		aRename:Add("AllMethodsVirtual","VO3")
		aRename:Add("ImplicitSignConversions","VO4")
		aRename:Add("VOCompatibleCallingConventions","VO5")
		aRename:Add("VOResolveFunctionPointers","VO6")
		aRename:Add("VOCompatibleImplicitConversions","VO7")
		aRename:Add("VOCompatiblePreprocessor","VO8")
		aRename:Add("VOCompatibleImplicitRetvals","VO9")
		aRename:Add("VOCompatibleIIF","VO10")
		aRename:Add("VOCompatibleArithmeticConversions","VO11")
		aRename:Add("IntegerDivisionsReturnFloat","VO12")
		aRename:Add("VOCompatibleStringComparisons","VO13")
		aRename:Add("VOFloatLiterals","VO14")
		aRename:Add("AdditionalOptions","CommandLineOption")
		// Items to delete

		VAR aTemp := List<STRING>{}
		aTemp:Add("DisabledWarnings")
		aTemp:Add("ProjectName")
		aTemp:Add("ProjectExt")
		aTemp:Add("ProjectDir")
		aTemp:Add("ProjectFileName")
		aTemp:Add("ProjectPath")
		aTemp:Add("ProjectView")
		aTemp:Add("SchemaVersion")
		aDelete := List<STRING>{}
		FOREACH s AS STRING IN aTemp
			aDelete:Add(s:ToLower())
		NEXT

	RETURN

STATIC METHOD Convert(cFile AS STRING, oProgress AS IProgress) AS VOID
	LOCAL oConverter AS ProjectConverter
	LOCAL cSource AS STRING
	LOCAL cTarget AS STRING
	oConverter := ProjectConverter{oProgress}
	cSource := cFile
	cTarget := System.IO.Path.ChangeExtension(cSource, EXTENSION)
	IF oConverter:ConvertProjectFile(cSource, cTarget)
		oProgress:WriteLine( "Converted "+System.IO.Path.GetFileName(cSource)+" to " +System.IO.Path.GetFileName(cTarget))
	ELSE
		oProgress:WriteLine( "An error occurred")
	ENDIF
	RETURN

END CLASS