[VsIntegration] Add default namespace XSharp at the start of the Usings list

//
// 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.
//
USING System.Collections.Concurrent
USING System.Collections.Generic
USING System
USING System.Linq
USING System.Diagnostics
USING XSharpModel
USING System.Collections.Immutable
USING STATIC XSharpModel.XFileTypeHelpers
BEGIN NAMESPACE XSharpModel
    DELEGATE FindMemberComparer (oElement AS XELement, nValue AS LONG ) AS LONG

	[DebuggerDisplay("{FullPath,nq}")];
	CLASS XFile
		// Fields
		PRIVATE _globalType		AS XType
		PRIVATE _lastWritten	AS System.DateTime
		PRIVATE _lock			AS OBJECT
		PRIVATE _parsed			AS LOGIC
		PRIVATE _type			AS XFileType
		PRIVATE _typeList		AS ConcurrentDictionary<STRING, XType>
		PRIVATE _entityList		AS List<XElement>
		PRIVATE _usings			AS List<STRING>
		PRIVATE _usingStatics	AS List<STRING>
		PRIVATE filePath AS STRING
		PRIVATE _project AS XProject

		// Methods
		CONSTRUCTOR(fullPath AS STRING)
			SUPER()
			//
			SELF:filePath := fullPath
			SELF:_type := GetFileType(fullPath)
			SELF:InitTypeList()
			SELF:_parsed := ! SELF:HasCode
			SELF:_lock := OBJECT{}
			SELF:_lastWritten := System.DateTime.MinValue

		PROPERTY EntityList AS 	List<XElement> GET _entityList
		METHOD FirstMember() AS XTypeMember
			IF (! SELF:HasCode)
				RETURN NULL
			ENDIF
			IF (SELF:TypeList == NULL || SELF:TypeList:Count == 0)
				RETURN NULL
			ENDIF
			BEGIN LOCK SELF:_lock
				VAR element := SELF:TypeList:FirstOrDefault()
				RETURN element:Value:Members:FirstOrDefault()
			END
			///
			/// Find member in file based on 0 based line number
			///
			///

		METHOD FindMember(oDel AS FindMemberComparer, nValue AS LONG) AS XElement
			LOCAL oResult := NULL_OBJECT AS XElement
			LOCAL oLast AS XElement
			// perform binary search to speed up things
			VAR current := 0
			VAR bottom := 0
            IF (_entityList == NULL_OBJECT)
                RETURN NULL_OBJECT
            ENDIF
			VAR top := _entityList:Count
			oLast := _entityList:FirstOrDefault()
			DO WHILE top - bottom > 1
				// determine middle
				current := (bottom + top) / 2
				VAR oElement := _entityList[current]
				VAR result := oDel(oElement, nValue)
				IF result == 0
					// found
					RETURN oElement
				ELSEIF result = 1 // element is after the search point
					top := current
				ELSE		// element is before the search point
					oLast := oElement
					bottom := current
				ENDIF
			ENDDO
			IF oResult == NULL
				oResult := oLast	// the last entity we saw before the selected line
			ENDIF
			RETURN oResult

		PRIVATE METHOD CompareByLine(oElement AS XELement, nLine AS LONG) AS LONG
			LOCAL nResult AS LONG
			LOCAL nStart, nEnd AS LONG
			nStart := oElement:Range:StartLine
			nEnd   := oElement:Range:EndLine
			IF oElement IS XType
				VAR oType := oElement ASTYPE XType
				IF oType:Members:Count > 0
					nEnd := oType:Members[0]:Range:StartLine-1
				ENDIF
			ENDIF
			IF nStart <= nLine .AND. nEnd>= nLine
				nResult := 0
			ELSEIF nStart > nLine
				nResult := 1
			ELSE
				nResult := -1
			ENDIF
			RETURN nResult

		METHOD FindMemberAtRow(nLine AS LONG) AS XElement
			nLine += 1
			RETURN SELF:FindMember(CompareByLine, nLine)

			///
			/// Find member in file based on 0 based position
			///
			///
		PRIVATE METHOD CompareByPosition(oElement AS XELement, nPos AS LONG) AS LONG
			LOCAL nResult AS LONG
			LOCAL nStart, nEnd AS LONG
			nStart := oElement:Interval:Start
			nEnd   := oElement:Interval:Stop
			IF oElement IS XType
				VAR oType := oElement ASTYPE XType
				IF oType:Members:Count > 0
					nEnd := oType:Members[0]:Interval:Start-2
				ENDIF
			ENDIF
			IF nStart <= nPos .AND. nEnd >= nPos
				nResult := 0
			ELSEIF nStart > nPos
				nResult := 1
			ELSE
				nResult := -1
			ENDIF
			RETURN nResult

		METHOD FindMemberAtPosition(nPos AS LONG) AS XElement
			RETURN SELF:FindMember(CompareByPosition, nPos)

		METHOD InitTypeList() AS VOID
			SELF:_usings		:= List<STRING>{}
			SELF:_usingStatics	:= List<STRING>{}
			SELF:_entityList    := List<XElement>{}
		    SELF:_typeList		:= ConcurrentDictionary<STRING, XType>{System.StringComparer.InvariantCultureIgnoreCase}
		    _usings.Add("XSharp")
			IF SELF:HasCode
				SELF:_globalType	:= XType.CreateGlobalType(SELF)
				SELF:_typeList:TryAdd(SELF:_globalType:Name, SELF:_globalType)
			ENDIF

		METHOD SetTypes(types AS IDictionary<STRING, XType>, usings AS IList<STRING>, ;
			staticUsings AS IList<STRING>, aEntities AS IList<XElement>) AS VOID
			IF SELF:HasCode
				WriteOutputMessage("-->> SetTypes() "+ SELF:SourcePath)
				BEGIN LOCK SELF
					FOREACH VAR type IN _typeList
						SELF:Project:RemoveType(type:Value)
					NEXT
					SELF:_typeList:Clear()
					SELF:_usings:Clear()
					SELF:_usingStatics:Clear()
					FOREACH type AS KeyValuePair<STRING, XType> IN types
						SELF:_typeList:TryAdd(type:Key, type:Value)
						IF (XType.IsGlobalType(type:Value))
							SELF:_globalType := type:Value
						ENDIF
						SELF:Project:AddType(type:Value)
					NEXT
					SELF:_usings:AddRange(usings)
					if SELF:_usings:IndexOf("XSharp") == -1
						SELF:_usings:Insert(0, "XSharp")
					ENDIF
					SELF:_usingStatics:AddRange(staticUsings)
					SELF:_entityList:Clear()
					SELF:_entityList:AddRange(aEntities)
				END LOCK
				WriteOutputMessage(String.Format("<<-- SetTypes() {0} (Types: {1}, Entities: {2})", SELF:SourcePath, _typeList:Count, SELF:_entityList:Count))
			ENDIF

		METHOD BuildTypes(oInfo AS ParseResult) AS VOID
			LOCAL aTypes	      AS Dictionary<STRING, XType>
			LOCAL aUsings		  AS List<STRING>
			LOCAL aUsingStatics   AS List<STRING>
			LOCAL oType		      AS XType
			LOCAL aEntities		  AS List<XElement>
			aTypes			:= Dictionary<STRING, XType>{}
			aUsings			:= List<STRING>{}
			aUsingStatics	:= List<STRING>{}
			FOREACH oElement AS EntityObject IN oInfo:Types
				oType   := XType.create(SELF, oElement,oInfo)
				IF !aTypes:ContainsKey(oType:FullName)
					aTypes:Add( oType:FullName, oType)
				ELSE
					// this should only happen if there are two PARTIAL CLASS parts in the same file
					// now merge the second in the first
					LOCAL oType2 := aTypes[oType:FullName] AS XType
					IF oType2:File == oType:File
						oType2 := oType2:Merge(oType)
						aTypes[oType:FullName] := oType2
					ENDIF
				ENDIF
				SELF:Project:RemoveMergedType(oType:FullName)
			NEXT
			// Now add NameSpaces
			FOREACH oNS AS NameSpaceObject IN oInfo:NameSpaces
				oType := XType{ oNS:Name, Kind.Namespace, Modifiers.Public, Modifiers.Public, oNS:Span, oNS:Interval ,SELF}
				IF !aTypes:ContainsKey(oType:FullName)
					aTypes:Add( oType:FullName, oType)
				ENDIF
			NEXT
			//
			FOREACH oLine AS LineObject IN oInfo:SpecialLines
				IF oLine:eType == LineType.Using
					LOCAL cName AS STRING
					cName := oLine:cArgument
					IF cName:ToLower():StartsWith("static")
						aUsingStatics:Add(cName:Substring(6))
					ELSE
						aUsings:Add(cName)
					ENDIF
				ENDIF
			NEXT
			// get our objects in file order from the oInfo:Entities list
			aEntities := List<XELement>{}
			FOREACH oElement AS EntityObject IN oInfo:Entities
				IF oElement:oCargo != NULL_OBJECT
					aEntities:add ( (XElement) oElement:oCargo)
				ENDIF
			NEXT
			SELF:SetTypes(aTypes, aUsings, aUsingStatics, aEntities:ToImmutableArray())
			RETURN

		METHOD WaitParsing() AS VOID
			//
			IF SELF:HasCode

				WriteOutputMessage("-->> WaitParsing()")
				BEGIN LOCK SELF:_lock

					IF ! SELF:Parsed
						BEGIN USING VAR walker := SourceWalker{SELF}
							TRY
								VAR lines := System.IO.File.ReadAllLines(SELF:SourcePath)
								VAR info := walker:Parse(lines, FALSE)
								BuildTypes(info)
							CATCH exception AS System.Exception
								XSolution.WriteException(exception)
							END TRY
						END USING
					ENDIF
				END LOCK
				WriteOutputMessage("<<-- WaitParsing()")
			ENDIF

			// Properties
		PROPERTY AllUsingStatics AS IList<STRING>
			GET

				IF (! SELF:HasCode)

					RETURN NULL
				ENDIF
				WriteOutputMessage("-->> AllUsingStatics")
				VAR statics := List<STRING>{}
				BEGIN LOCK SELF:_lock

					statics:AddRange(SELF:_usingStatics)
					IF (((SELF:Project != NULL) .AND. (SELF:Project:ProjectNode != NULL)) .AND. SELF:Project:ProjectNode:ParseOptions:HasRuntime)

						FOREACH asm AS AssemblyInfo IN SELF:Project:AssemblyReferences

							VAR globalclass := asm:GlobalClassName
							IF (! String.IsNullOrEmpty(globalclass))

								statics:AddUnique(globalclass)
							ENDIF
						NEXT
					ENDIF
				END LOCK
				WriteOutputMessage("<<-- AllUsingStatics")
				RETURN statics
			END GET
		END PROPERTY

		PROPERTY ContentHashCode AS DWORD
			GET
				IF ! SELF:HasCode .OR. SELF:TypeList == NULL
					RETURN 0
				ENDIF
				BEGIN LOCK SELF:_lock
					VAR hash := 0U
					FOREACH type AS XType IN SELF:TypeList:Values
						FOREACH xmem AS XTypeMember IN type:Members
							BEGIN UNCHECKED
								hash += (DWORD)xmem:Prototype:GetHashCode()
								hash += (DWORD) xmem:Range:StartLine
							END UNCHECKED
						NEXT
					NEXT
					RETURN hash
				END LOCK
			END GET
		END PROPERTY

		PROPERTY FullPath AS STRING GET SELF:filePath SET SELF:filePath := VALUE
		PROPERTY GlobalType AS XType GET SELF:_globalType
		PROPERTY HasCode AS LOGIC GET SELF:IsSource .OR. SELF:IsXaml .OR. SELF:IsHeader
		PROPERTY HasParseErrors AS LOGIC AUTO
		PROPERTY IsHeader AS LOGIC GET SELF:_type == XFileType.Header
		PROPERTY IsSource AS LOGIC GET SELF:_type == XFileType.SourceCode
		PROPERTY IsXaml AS LOGIC GET SELF:_type == XFileType.XAML
		PROPERTY LastWritten AS System.DateTime GET SELF:_lastWritten SET SELF:_lastWritten := VALUE
		PROPERTY Name AS STRING GET System.IO.Path.GetFileNameWithoutExtension(SELF:filePath)

		PROPERTY Parsed AS LOGIC
			GET
				WriteOutputMessage("-->> Parsed")
				LOCAL flag AS LOGIC
				BEGIN LOCK SELF:_lock

					flag := SELF:_parsed
				END LOCK
				WriteOutputMessage("<<-- Parsed")
				RETURN flag
			END GET
		END PROPERTY

		PROPERTY Project AS XProject
			GET
				IF SELF:_project == NULL
					SELF:_project := XSolution.OrphanedFilesProject
					SELF:_project:AddFile(SELF:filePath)
				ENDIF
				RETURN SELF:_project
			END GET
			SET
				SELF:_project := VALUE
			END SET
		END PROPERTY

		PROPERTY SourcePath AS STRING
			GET
				IF (SELF:IsXaml)
					RETURN SELF:XamlCodeBehindFile
				ENDIF
				RETURN SELF:FullPath
			END GET
		END PROPERTY

		PROPERTY TypeList AS IDictionary<STRING, XType>
			GET
				IF ! SELF:HasCode
					RETURN NULL
				ENDIF
				BEGIN LOCK SELF:_lock
					RETURN SELF:_typeList
				END LOCK
			END GET
		END PROPERTY

		PROPERTY Usings AS IList<STRING>
			GET
				IF ! SELF:HasCode
					RETURN NULL
				ENDIF
				RETURN _usings:ToArray()
			END GET
		END PROPERTY

		PROPERTY XamlCodeBehindFile AS STRING
			GET
				VAR projectNode := SELF:Project:ProjectNode
				RETURN System.IO.Path.ChangeExtension(System.IO.Path.Combine(projectNode:IntermediateOutputPath, System.IO.Path.GetFileName(SELF:FullPath)), ".g.prg")
			END GET
		END PROPERTY

		PROPERTY XFileType AS XFileType GET SELF:_type

		METHOD WriteOutputMessage(message AS STRING) AS VOID
			XSolution.WriteOutputMessage("XModel.File "+message)

	END CLASS

END NAMESPACE

//
// 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.
//
USING System.Collections.Concurrent
USING System.Collections.Generic
USING System
USING System.Linq
USING System.Diagnostics
USING XSharpModel
USING System.Collections.Immutable
USING STATIC XSharpModel.XFileTypeHelpers
BEGIN NAMESPACE XSharpModel
    DELEGATE FindMemberComparer (oElement AS XELement, nValue AS LONG ) AS LONG

	[DebuggerDisplay("{FullPath,nq}")];
	CLASS XFile
		// Fields
		PRIVATE _globalType		AS XType
		PRIVATE _lastWritten	AS System.DateTime
		PRIVATE _lock			AS OBJECT
		PRIVATE _parsed			AS LOGIC
		PRIVATE _type			AS XFileType
		PRIVATE _typeList		AS ConcurrentDictionary<STRING, XType>
		PRIVATE _entityList		AS List<XElement>
		PRIVATE _usings			AS List<STRING>
		PRIVATE _usingStatics	AS List<STRING>
		PRIVATE filePath AS STRING
		PRIVATE _project AS XProject

		// Methods
		CONSTRUCTOR(fullPath AS STRING)
			SUPER()
			//
			SELF:filePath := fullPath
			SELF:_type := GetFileType(fullPath)
			SELF:InitTypeList()
			SELF:_parsed := ! SELF:HasCode
			SELF:_lock := OBJECT{}
			SELF:_lastWritten := System.DateTime.MinValue

		PROPERTY EntityList AS 	List<XElement> GET _entityList
		METHOD FirstMember() AS XTypeMember
			IF (! SELF:HasCode)
				RETURN NULL
			ENDIF
			IF (SELF:TypeList == NULL || SELF:TypeList:Count == 0)
				RETURN NULL
			ENDIF
			BEGIN LOCK SELF:_lock
				VAR element := SELF:TypeList:FirstOrDefault()
				RETURN element:Value:Members:FirstOrDefault()
			END
			///
			/// Find member in file based on 0 based line number
			///
			///

		METHOD FindMember(oDel AS FindMemberComparer, nValue AS LONG) AS XElement
			LOCAL oResult := NULL_OBJECT AS XElement
			LOCAL oLast AS XElement
			// perform binary search to speed up things
			VAR current := 0
			VAR bottom := 0
            IF (_entityList == NULL_OBJECT)
                RETURN NULL_OBJECT
            ENDIF
			VAR top := _entityList:Count
			oLast := _entityList:FirstOrDefault()
			DO WHILE top - bottom > 1
				// determine middle
				current := (bottom + top) / 2
				VAR oElement := _entityList[current]
				VAR result := oDel(oElement, nValue)
				IF result == 0
					// found
					RETURN oElement
				ELSEIF result = 1 // element is after the search point
					top := current
				ELSE		// element is before the search point
					oLast := oElement
					bottom := current
				ENDIF
			ENDDO
			IF oResult == NULL
				oResult := oLast	// the last entity we saw before the selected line
			ENDIF
			RETURN oResult

		PRIVATE METHOD CompareByLine(oElement AS XELement, nLine AS LONG) AS LONG
			LOCAL nResult AS LONG
			LOCAL nStart, nEnd AS LONG
			nStart := oElement:Range:StartLine
			nEnd   := oElement:Range:EndLine
			IF oElement IS XType
				VAR oType := oElement ASTYPE XType
				IF oType:Members:Count > 0
					nEnd := oType:Members[0]:Range:StartLine-1
				ENDIF
			ENDIF
			IF nStart <= nLine .AND. nEnd>= nLine
				nResult := 0
			ELSEIF nStart > nLine
				nResult := 1
			ELSE
				nResult := -1
			ENDIF
			RETURN nResult

		METHOD FindMemberAtRow(nLine AS LONG) AS XElement
			nLine += 1
			RETURN SELF:FindMember(CompareByLine, nLine)

			///
			/// Find member in file based on 0 based position
			///
			///
		PRIVATE METHOD CompareByPosition(oElement AS XELement, nPos AS LONG) AS LONG
			LOCAL nResult AS LONG
			LOCAL nStart, nEnd AS LONG
			nStart := oElement:Interval:Start
			nEnd   := oElement:Interval:Stop
			IF oElement IS XType
				VAR oType := oElement ASTYPE XType
				IF oType:Members:Count > 0
					nEnd := oType:Members[0]:Interval:Start-2
				ENDIF
			ENDIF
			IF nStart <= nPos .AND. nEnd >= nPos
				nResult := 0
			ELSEIF nStart > nPos
				nResult := 1
			ELSE
				nResult := -1
			ENDIF
			RETURN nResult

		METHOD FindMemberAtPosition(nPos AS LONG) AS XElement
			RETURN SELF:FindMember(CompareByPosition, nPos)

		METHOD InitTypeList() AS VOID
			SELF:_usings		:= List<STRING>{}
			SELF:_usingStatics	:= List<STRING>{}
			SELF:_entityList    := List<XElement>{}
		    SELF:_typeList		:= ConcurrentDictionary<STRING, XType>{System.StringComparer.InvariantCultureIgnoreCase}
			IF SELF:HasCode
				SELF:_globalType	:= XType.CreateGlobalType(SELF)
				SELF:_typeList:TryAdd(SELF:_globalType:Name, SELF:_globalType)
			ENDIF

		METHOD SetTypes(types AS IDictionary<STRING, XType>, usings AS IList<STRING>, ;
			staticUsings AS IList<STRING>, aEntities AS IList<XElement>) AS VOID
			IF SELF:HasCode
				WriteOutputMessage("-->> SetTypes() "+ SELF:SourcePath)
				BEGIN LOCK SELF
					FOREACH VAR type IN _typeList
						SELF:Project:RemoveType(type:Value)
					NEXT
					SELF:_typeList:Clear()
					SELF:_usings:Clear()
					SELF:_usingStatics:Clear()
					FOREACH type AS KeyValuePair<STRING, XType> IN types
						SELF:_typeList:TryAdd(type:Key, type:Value)
						IF (XType.IsGlobalType(type:Value))
							SELF:_globalType := type:Value
						ENDIF
						SELF:Project:AddType(type:Value)
					NEXT
					SELF:_usings:AddRange(usings)
					SELF:_usingStatics:AddRange(staticUsings)
					SELF:_entityList:Clear()
					SELF:_entityList:AddRange(aEntities)
				END LOCK
				WriteOutputMessage(String.Format("<<-- SetTypes() {0} (Types: {1}, Entities: {2})", SELF:SourcePath, _typeList:Count, SELF:_entityList:Count))
			ENDIF

		METHOD BuildTypes(oInfo AS ParseResult) AS VOID
			LOCAL aTypes	      AS Dictionary<STRING, XType>
			LOCAL aUsings		  AS List<STRING>
			LOCAL aUsingStatics   AS List<STRING>
			LOCAL oType		      AS XType
			LOCAL aEntities		  AS List<XElement>
			aTypes			:= Dictionary<STRING, XType>{}
			aUsings			:= List<STRING>{}
			aUsingStatics	:= List<STRING>{}
			FOREACH oElement AS EntityObject IN oInfo:Types
				oType   := XType.create(SELF, oElement,oInfo)
				IF !aTypes:ContainsKey(oType:FullName)
					aTypes:Add( oType:FullName, oType)
				ELSE
					// this should only happen if there are two PARTIAL CLASS parts in the same file
					// now merge the second in the first
					LOCAL oType2 := aTypes[oType:FullName] AS XType
					IF oType2:File == oType:File
						oType2 := oType2:Merge(oType)
						aTypes[oType:FullName] := oType2
					ENDIF
				ENDIF
				SELF:Project:RemoveMergedType(oType:FullName)
			NEXT
			// Now add NameSpaces
			FOREACH oNS AS NameSpaceObject IN oInfo:NameSpaces
				oType := XType{ oNS:Name, Kind.Namespace, Modifiers.Public, Modifiers.Public, oNS:Span, oNS:Interval ,SELF}
				IF !aTypes:ContainsKey(oType:FullName)
					aTypes:Add( oType:FullName, oType)
				ENDIF
			NEXT
			//
			FOREACH oLine AS LineObject IN oInfo:SpecialLines
				IF oLine:eType == LineType.Using
					LOCAL cName AS STRING
					cName := oLine:cArgument
					IF cName:ToLower():StartsWith("static")
						aUsingStatics:Add(cName:Substring(6))
					ELSE
						aUsings:Add(cName)
					ENDIF
				ENDIF
			NEXT
			// get our objects in file order from the oInfo:Entities list
			aEntities := List<XELement>{}
			FOREACH oElement AS EntityObject IN oInfo:Entities
				IF oElement:oCargo != NULL_OBJECT
					aEntities:add ( (XElement) oElement:oCargo)
				ENDIF
			NEXT
			SELF:SetTypes(aTypes, aUsings, aUsingStatics, aEntities:ToImmutableArray())
			RETURN

		METHOD WaitParsing() AS VOID
			//
			IF SELF:HasCode

				WriteOutputMessage("-->> WaitParsing()")
				BEGIN LOCK SELF:_lock

					IF ! SELF:Parsed
						BEGIN USING VAR walker := SourceWalker{SELF}
							TRY
								VAR lines := System.IO.File.ReadAllLines(SELF:SourcePath)
								VAR info := walker:Parse(lines, FALSE)
								BuildTypes(info)
							CATCH exception AS System.Exception
								XSolution.WriteException(exception)
							END TRY
						END USING
					ENDIF
				END LOCK
				WriteOutputMessage("<<-- WaitParsing()")
			ENDIF

			// Properties
		PROPERTY AllUsingStatics AS IList<STRING>
			GET

				IF (! SELF:HasCode)

					RETURN NULL
				ENDIF
				WriteOutputMessage("-->> AllUsingStatics")
				VAR statics := List<STRING>{}
				BEGIN LOCK SELF:_lock

					statics:AddRange(SELF:_usingStatics)
					IF (((SELF:Project != NULL) .AND. (SELF:Project:ProjectNode != NULL)) .AND. SELF:Project:ProjectNode:ParseOptions:HasRuntime)

						FOREACH asm AS AssemblyInfo IN SELF:Project:AssemblyReferences

							VAR globalclass := asm:GlobalClassName
							IF (! String.IsNullOrEmpty(globalclass))

								statics:AddUnique(globalclass)
							ENDIF
						NEXT
					ENDIF
				END LOCK
				WriteOutputMessage("<<-- AllUsingStatics")
				RETURN statics
			END GET
		END PROPERTY

		PROPERTY ContentHashCode AS DWORD
			GET
				IF ! SELF:HasCode .OR. SELF:TypeList == NULL
					RETURN 0
				ENDIF
				BEGIN LOCK SELF:_lock
					VAR hash := 0U
					FOREACH type AS XType IN SELF:TypeList:Values
						FOREACH xmem AS XTypeMember IN type:Members
							BEGIN UNCHECKED
								hash += (DWORD)xmem:Prototype:GetHashCode()
								hash += (DWORD) xmem:Range:StartLine
							END UNCHECKED
						NEXT
					NEXT
					RETURN hash
				END LOCK
			END GET
		END PROPERTY

		PROPERTY FullPath AS STRING GET SELF:filePath SET SELF:filePath := VALUE
		PROPERTY GlobalType AS XType GET SELF:_globalType
		PROPERTY HasCode AS LOGIC GET SELF:IsSource .OR. SELF:IsXaml .OR. SELF:IsHeader
		PROPERTY HasParseErrors AS LOGIC AUTO
		PROPERTY IsHeader AS LOGIC GET SELF:_type == XFileType.Header
		PROPERTY IsSource AS LOGIC GET SELF:_type == XFileType.SourceCode
		PROPERTY IsXaml AS LOGIC GET SELF:_type == XFileType.XAML
		PROPERTY LastWritten AS System.DateTime GET SELF:_lastWritten SET SELF:_lastWritten := VALUE
		PROPERTY Name AS STRING GET System.IO.Path.GetFileNameWithoutExtension(SELF:filePath)

		PROPERTY Parsed AS LOGIC
			GET
				WriteOutputMessage("-->> Parsed")
				LOCAL flag AS LOGIC
				BEGIN LOCK SELF:_lock

					flag := SELF:_parsed
				END LOCK
				WriteOutputMessage("<<-- Parsed")
				RETURN flag
			END GET
		END PROPERTY

		PROPERTY Project AS XProject
			GET
				IF SELF:_project == NULL
					SELF:_project := XSolution.OrphanedFilesProject
					SELF:_project:AddFile(SELF:filePath)
				ENDIF
				RETURN SELF:_project
			END GET
			SET
				SELF:_project := VALUE
			END SET
		END PROPERTY

		PROPERTY SourcePath AS STRING
			GET
				IF (SELF:IsXaml)
					RETURN SELF:XamlCodeBehindFile
				ENDIF
				RETURN SELF:FullPath
			END GET
		END PROPERTY

		PROPERTY TypeList AS IDictionary<STRING, XType>
			GET
				IF ! SELF:HasCode
					RETURN NULL
				ENDIF
				BEGIN LOCK SELF:_lock
					RETURN SELF:_typeList
				END LOCK
			END GET
		END PROPERTY

		PROPERTY Usings AS IList<STRING>
			GET
				IF ! SELF:HasCode
					RETURN NULL
				ENDIF
				RETURN _usings:ToArray()
			END GET
		END PROPERTY

		PROPERTY XamlCodeBehindFile AS STRING
			GET
				VAR projectNode := SELF:Project:ProjectNode
				RETURN System.IO.Path.ChangeExtension(System.IO.Path.Combine(projectNode:IntermediateOutputPath, System.IO.Path.GetFileName(SELF:FullPath)), ".g.prg")
			END GET
		END PROPERTY

		PROPERTY XFileType AS XFileType GET SELF:_type

		METHOD WriteOutputMessage(message AS STRING) AS VOID
			XSolution.WriteOutputMessage("XModel.File "+message)

	END CLASS

END NAMESPACE


show off Item syntax

show off Item syntax

-- Copyright (c) 2006 Portland State University.
-- This is an example program for the Omega programming language;
-- for more information, see:
--   http://www.cs.pdx.edu/~sheard/Omega/index.html
-- Research and development on Omega is supported by a grant
-- from the National Science Foundation.

-- Existential hiding and operators on anonymous sums

data Covert :: (a ~> *0) ~> *0 where
  Hide :: t x -> Covert t
 deriving Item(cv)

-- conventional (ADT) syntax would be
-- data Covert f = exists x . Hide (f x) deriving Item(cv)

toNat :: Int -> Covert Nat'
toNat 0 = Hide Z
toNat n = case toNat (n-1) of Hide b -> Hide(S b)

-- Copyright (c) 2006 Portland State University.
-- This is an example program for the Omega programming language;
-- for more information, see:
--   http://www.cs.pdx.edu/~sheard/Omega/index.html
-- Research and development on Omega is supported by a grant
-- from the National Science Foundation.

-- Existential hiding and operators on anonymous sums

data Covert :: (a ~> *0) ~> *0 where
  Hide :: t x -> Covert t

toNat :: Int -> Covert Nat'
toNat 0 = Hide Z
toNat n = case toNat (n-1) of Hide b -> Hide(S b)


QtScriptTools: data for code generation updated

Modified:
codegen/QtScriptTools/QScriptEngineDebugger.prg

$header

#include "hbclass.ch"

#ifndef QT4XHB_NO_REQUESTS
REQUEST QACTION
REQUEST QMENU
REQUEST QTOOLBAR
REQUEST QMAINWINDOW
REQUEST QWIDGET
#endif

CLASS QScriptEngineDebugger INHERIT QObject

   METHOD new
   METHOD delete
   METHOD action
   METHOD attachTo
   METHOD autoShowStandardWindow
   METHOD createStandardMenu
   METHOD createStandardToolBar
   METHOD detach
   METHOD setAutoShowStandardWindow
   METHOD standardWindow
   METHOD state
   METHOD widget

   METHOD onEvaluationResumed
   METHOD onEvaluationSuspended

   DESTRUCTOR destroyObject

END CLASS

$destructor

#pragma BEGINDUMP

#include <QScriptEngineDebugger>

#include "qt4xhb_common.h"
#include "qt4xhb_macros.h"
#include "qt4xhb_utils.h"

$prototype=QScriptEngineDebugger ( QObject * parent = 0 )
HB_FUNC_STATIC( QSCRIPTENGINEDEBUGGER_NEW )
{
  QScriptEngineDebugger * o = new QScriptEngineDebugger ( OPQOBJECT(1,0) );
  _qt4xhb_storePointerAndFlag ( o, false );
}

$deleteMethod

$prototype=QAction * action ( DebuggerAction action ) const
$method=|QAction *|action|QScriptEngineDebugger::DebuggerAction

$prototype=void attachTo ( QScriptEngine * engine )
$method=|void|attachTo|QScriptEngine *

$prototype=bool autoShowStandardWindow () const
$method=|bool|autoShowStandardWindow|

$prototype=QMenu * createStandardMenu ( QWidget * parent = 0 )
$method=|QMenu *|createStandardMenu|QWidget *=0

$prototype=QToolBar * createStandardToolBar ( QWidget * parent = 0 )
$method=|QToolBar *|createStandardToolBar|QWidget *=0

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

$prototype=void setAutoShowStandardWindow ( bool autoShow )
$method=|void|setAutoShowStandardWindow|bool

$prototype=QMainWindow * standardWindow () const
$method=|QMainWindow *|standardWindow|

$prototype=DebuggerState state () const
$method=|QScriptEngineDebugger::DebuggerState|state|

$prototype=QWidget * widget ( DebuggerWidget widget ) const
$method=|QWidget *|widget|QScriptEngineDebugger::DebuggerWidget

#pragma ENDDUMP

$header

#include "hbclass.ch"

#ifndef QT4XHB_NO_REQUESTS
REQUEST QACTION
REQUEST QMENU
REQUEST QTOOLBAR
REQUEST QMAINWINDOW
REQUEST QWIDGET
#endif

CLASS QScriptEngineDebugger INHERIT QObject

   METHOD new
   METHOD delete
   METHOD action
   METHOD attachTo
   METHOD autoShowStandardWindow
   METHOD createStandardMenu
   METHOD createStandardToolBar
   METHOD detach
   METHOD setAutoShowStandardWindow
   METHOD standardWindow
   METHOD state
   METHOD widget

   METHOD onEvaluationResumed
   METHOD onEvaluationSuspended

   DESTRUCTOR destroyObject

END CLASS

$destructor

#pragma BEGINDUMP

#include <QScriptEngineDebugger>

#include "qt4xhb_common.h"
#include "qt4xhb_macros.h"
#include "qt4xhb_utils.h"

/*
QScriptEngineDebugger ( QObject * parent = 0 )
*/
HB_FUNC_STATIC( QSCRIPTENGINEDEBUGGER_NEW )
{
  QScriptEngineDebugger * o = new QScriptEngineDebugger ( OPQOBJECT(1,0) );
  _qt4xhb_storePointerAndFlag ( o, false );
}

$deleteMethod

/*
QAction * action ( DebuggerAction action ) const
*/
$method=|QAction *|action|QScriptEngineDebugger::DebuggerAction

/*
void attachTo ( QScriptEngine * engine )
*/
$method=|void|attachTo|QScriptEngine *

/*
bool autoShowStandardWindow () const
*/
$method=|bool|autoShowStandardWindow|

/*
QMenu * createStandardMenu ( QWidget * parent = 0 )
*/
$method=|QMenu *|createStandardMenu|QWidget *=0

/*
QToolBar * createStandardToolBar ( QWidget * parent = 0 )
*/
$method=|QToolBar *|createStandardToolBar|QWidget *=0

/*
void detach ()
*/
$method=|void|detach|

/*
void setAutoShowStandardWindow ( bool autoShow )
*/
$method=|void|setAutoShowStandardWindow|bool

/*
QMainWindow * standardWindow () const
*/
$method=|QMainWindow *|standardWindow|

/*
DebuggerState state () const
*/
$method=|QScriptEngineDebugger::DebuggerState|state|

/*
QWidget * widget ( DebuggerWidget widget ) const
*/
$method=|QWidget *|widget|QScriptEngineDebugger::DebuggerWidget

#pragma ENDDUMP


Changed test. Robert has a network share M:

//
// 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.
//
USING System
USING System.Collections.Generic
USING System.Linq
USING System.Text
USING XUnit
USING System.Globalization

BEGIN NAMESPACE XSharp.VO.Tests

	CLASS TransFormTests

		[Fact, Trait("Category", "TransForm")];
		METHOD LogicalTest() AS VOID
			// with @R other chars are appended, but only a single YN or TF flag is written. Other positions become a space
			Assert.Equal("Y", Transform(TRUE, "Y"))
			Assert.Equal("N", Transform(FALSE, "Y"))
			Assert.Equal("T", Transform(TRUE, "L"))
			Assert.Equal("F", Transform(FALSE, "L"))
			Assert.Equal("T x", Transform(TRUE, "@R L x"))
			Assert.Equal("F x", Transform(FALSE, "@R L x"))
			Assert.Equal("Y x", Transform(TRUE, "@R YYx"))
			Assert.Equal("N x", Transform(FALSE, "@R YYx"))
			SetNatDll("French.DLL")
			Assert.Equal("O", Transform(TRUE, "Y"))
			Assert.Equal("N", Transform(FALSE, "Y"))
			Assert.Equal("V", Transform(TRUE, "L"))
			Assert.Equal("F", Transform(FALSE, "L"))
			Assert.Equal("V x", Transform(TRUE, "@R L x"))
			Assert.Equal("F x", Transform(FALSE, "@R L x"))
			Assert.Equal("O x", Transform(TRUE, "@R YYx"))
			Assert.Equal("N x", Transform(FALSE, "@R YYx"))

		[Fact, Trait("Category", "TransForm")];
		METHOD DateTest() AS VOID
			// with @R other chars are appended, but only a single YN or TF flag is written. Other positions become a space
			Assert.Equal("10/12/2010", Transform(2010.12.10,"@E"))
			Assert.Equal("20/11/2010", Transform(2010.11.20,"@E"))
			SetDateFormat("dd-mm-yyyy")
			Assert.Equal("20-11-2010", Transform(2010.11.20,"@D"))
			SetDateFormat("dd-mm-yy")
			Assert.Equal("20-11-10", Transform(2010.11.20,"@D"))

		[Fact, Trait("Category", "TransForm")];
		METHOD StringTest() AS VOID
			Assert.Equal("ABC", Transform("abc", "@!"))
			Assert.Equal("AbC", Transform("abc", "!a!"))
			Assert.Equal("1234 AB", Transform("1234ab", "@R! 9999 AA"))
			Assert.Equal("1234 AB", Transform("1234ab", "@R 9999 !!"))

		[Fact, Trait("Category", "TransForm")];
		METHOD LongTest() AS VOID
			SetDecimalSep('.')
			SetThousandSep(',')
			Assert.Equal("  1", Transform(1, "999"))
			Assert.Equal("123", Transform(123, "###"))
			Assert.Equal("**", Transform(123, "##"))
			Assert.Equal("**", Transform(123, "99"))
			Assert.Equal("(1)", Transform(-1, "@( 99"))
			Assert.Equal("(-1)", Transform(-1, "@( 999"))
			Assert.Equal("( -1)", Transform(-1, "@( 9999"))
			Assert.Equal("(-1)", Transform(-1, "@) 9999"))
			Assert.Equal(" (-1)", Transform(-1, "@) 99999"))
			Assert.Equal("   ", Transform(0, "@Z 999"))
			Assert.Equal(" -1 DB", Transform(-1, "@X 999"))
			Assert.Equal(" -1 DB", Transform(-1, "@XC 999"))
			Assert.Equal("  1 CR", Transform(1, "@XC 999"))
			Assert.Equal("  1 CR", Transform(1, "@C 999"))
			Assert.Equal("  0", Transform(0, "@C 999"))
			Assert.Equal("1,234", Transform(1234, "9,999"))
			SetDecimalSep(',')
			SetThousandSep('.')
			Assert.Equal("1.234", Transform(1234, "9,999"))

		[Fact, Trait("Category", "TransForm")];
		METHOD FLoatTest() AS VOID
			SetDecimalSep('.')
			SetThousandSep(',')
			Assert.Equal("1.23", Transform(1.23, "9.99"))
			Assert.Equal("1,23", Transform(1.23, "@E 9.99"))
			Assert.Equal("*.**", Transform(12.34, "9.99"))

// some new failing tests:
	[Fact, Trait("Category", "TransForm")];
	METHOD IntLiteralTest() AS VOID
		LOCAL dec AS DWORD
		LOCAL thou AS DWORD

		dec := SetDecimalSep(Asc(","))
		thou := SetThousandSep(Asc("."))
		Assert.Equal(" 12.345,00" , Transform(12345.0, "999,999.99"))
		// this fails:
		Assert.Equal(" 12.345,00" , Transform(12345, "999,999.99"))

		SetDecimalSep(Asc("."))
		SetThousandSep(Asc(","))
		Assert.Equal(" 12,345.00" , Transform(12345.0, "999,999.99"))
		Assert.Equal(" 12,345.00" , Transform(12345, "999,999.99"))

		SetDecimalSep(dec)
		SetThousandSep(thou)
	RETURN

// Tests that need to be moved in separate files in VO.Tests:
	[Fact, Trait("Category", "StringEq")];
	METHOD StringEquality() AS VOID
		LOCAL c1,c2 AS STRING
		LOCAL u1,u2 AS USUAL
		LOCAL exact AS LOGIC
		u1 := c1 := "TESTLONG"
		u2 := c2 := "TEST"
		exact := SetExact( FALSE )

		Assert.Equal(TRUE, c1 = c2)
		Assert.Equal(TRUE, c1 != c2)

		Assert.Equal(TRUE, u1 = u2)
		Assert.Equal(FALSE, u1 != u2)

		SetExact( exact )
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD StrTests() AS VOID
		LOCAL exact,thou,digit,decimal,fixed_,digitfixed AS USUAL
		exact := SetDecimalSep(Asc("."))
		thou := SetThousandSep(Asc(","))
		digit := SetDigit(6)
		decimal := SetDecimal(3)
		fixed_ := SetFixed(FALSE)
		digitfixed := SetDigitFixed(FALSE)

		Assert.Equal( "     1.2"			, Str(1.2) )
		Assert.Equal( "    12.3"			, Str(12.3) )
		Assert.Equal( "    12.34"			, Str(12.34) )
		Assert.Equal( "   123.456"			, Str(123.456) )
		Assert.Equal( "  1234.567"			, Str(1234.567) )
		Assert.Equal( "  1234.5678"			, Str(1234.5678) )
		Assert.Equal( "  1234.5679012345"	, Str(1234.5679012345) )
		Assert.Equal( "123456.78901234567"	, Str(123456.78901234567) )
		Assert.Equal( "999999" , Str(999999) )
		Assert.Equal( "******" , Str(1000000) )

		SetDecimalSep(exact)
		SetThousandSep(thou)
		SetDigit(digit)
		SetDecimal(decimal)
		SetFixed(fixed_)
		SetDigitFixed(digitfixed)
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD Str_With_SetFixed_TRUE() AS VOID

	   SetDecimalSep(Asc("."))
	   SetThousandSep(Asc(","))
	   SetDecimal(3)
	   SetDigit(12)

	   SetFixed(TRUE)
	   SetDigitFixed(TRUE)

	   Assert.Equal( Str(12.34)            		, "          12.340")
	   Assert.Equal( Str1(12.34)          		, "          12.340")
	   Assert.Equal( Str(123.456)         		, "         123.456")
	   Assert.Equal( Str1(123.456)       		, "         123.456")
	   Assert.Equal( Str(1230.4567)         	, "        1230.457")
	   Assert.Equal( Str1(1230.4567)        	, "        1230.457")
	   Assert.Equal( Str(100000001234.4567)		, "100000001234.457")
	   Assert.Equal( Str1(100000001234.4567)	, "100000001234.457")
	   Assert.Equal( Str(1000000001234.4567)	, "****************")
	   Assert.Equal( Str1(1000000001234.4567)	, "****************")
	   Assert.Equal( Str(12.3)              	, "          12.300")
	   Assert.Equal( Str1(12.3)            		, "          12.300")
	   Assert.Equal( Str(12.34567)        	 	, "          12.346")
	   Assert.Equal( Str1(12.34567)        		, "          12.346")
	   Assert.Equal( Str(12.34 , 10, 2)    		, "     12.34")
	   Assert.Equal( Str(12.34 , 5, 2)     		, "12.34")
	   Assert.Equal( Str(12.34 , 4, 2)     		, "12.3")
	   Assert.Equal( Str(12.34 , 4, 1)     		, "12.3")
	   Assert.Equal( Str(12.34 , 2, 1)     		, "**")
	   Assert.Equal( Str3(12.34 , 10, 2)   		, "     12.34")
	   Assert.Equal( Str3(12.34 , 5, 2)    		, "12.34")
	   Assert.Equal( Str3(12.34 , 4, 2)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 4, 1)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 2, 1)    		, "**")
	   Assert.Equal( Str(-12.34)            	, "         -12.340")
	   Assert.Equal( Str1(-12.34)           	, "         -12.340")
	   Assert.Equal( Str(-12.3456)         		, "         -12.346")
	   Assert.Equal( Str1(-12.3456)         	, "         -12.346")
	   Assert.Equal( Str(-12.34 , 10, 2)    	, "    -12.34")
	   Assert.Equal( Str(-12.34 , 5, 2)     	, "-12.3")	 //VO wrong: -2.34
	   Assert.Equal( Str(-12.34 , 4, 2)     	, "-12.")
	   Assert.Equal( Str(-12.34 , 4, 1)     	, " -12")    //VO wrong: -2.3
	   Assert.Equal( Str(-12.34 , 2, 1)     	, "**")
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD Str_With_SetFixed_FALSE() AS VOID

	   SetDecimalSep(Asc("."))
	   SetThousandSep(Asc(","))
	   SetDecimal(3)
	   SetDigit(12)

	   SetFixed(FALSE)
	   SetDigitFixed(FALSE)

	   Assert.Equal( Str(12.34)            		, "          12.34")
	   Assert.Equal( Str1(12.34)          		, "          12.34")
	   Assert.Equal( Str(123.456)         		, "         123.456")
	   Assert.Equal( Str1(123.456)				, "         123.456")
	   Assert.Equal( Str(1230.4567)         	, "        1230.4567")
	   Assert.Equal( Str1(1230.4567)        	, "        1230.4567")
	   Assert.Equal( Str(100000001234.4567)		, "100000001234.4567")
	   Assert.Equal( Str1(100000001234.4567)	, "100000001234.4567")
	   Assert.Equal( Str(1000000001234.4567)	, "*****************")
	   Assert.Equal( Str1(1000000001234.4567)	, "*****************")
	   Assert.Equal( Str(12.3)              	, "          12.3")
	   Assert.Equal( Str1(12.3)            		, "          12.3")
	   Assert.Equal( Str(12.34567)         		, "          12.34567")
	   Assert.Equal( Str1(12.34567)        		, "          12.34567")
	   Assert.Equal( Str(12.34 , 10, 2)    		, "     12.34")
	   Assert.Equal( Str(12.34 , 5, 2)     		, "12.34")
	   Assert.Equal( Str(12.34 , 4, 2)     		, "12.3")
	   Assert.Equal( Str(12.34 , 4, 1)     		, "12.3")
	   Assert.Equal( Str(12.34 , 2, 1)     		, "**")
	   Assert.Equal( Str3(12.34 , 10, 2)   		, "     12.34")
	   Assert.Equal( Str3(12.34 , 5, 2)    		, "12.34")
	   Assert.Equal( Str3(12.34 , 4, 2)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 4, 1)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 2, 1)    		, "**")
	   Assert.Equal( Str(-12.34)            	, "         -12.34")
	   Assert.Equal( Str1(-12.34)           	, "         -12.34")
	   Assert.Equal( Str(-12.3456)         		, "         -12.3456")
	   Assert.Equal( Str1(-12.3456)         	, "         -12.3456")
	   Assert.Equal( Str(-12.34 , 10, 2)    	, "    -12.34")
	   Assert.Equal( Str(-12.34 , 5, 2)     	, "-12.3")	 //VO: -2.34
	   Assert.Equal( Str(-12.34 , 4, 2)     	, "-12.")
	   Assert.Equal( Str(-12.34 , 4, 1)     	, " -12")    //VO: -2.3
	   Assert.Equal( Str(-12.34 , 2, 1)     	, "**")

	[Fact, Trait("Category", "Val")];
	METHOD ValTests() AS VOID
		Assert.Equal(123, (INT) Val("123") )
		Assert.Equal(123.456, (FLOAT) Val("123.456") )

		Assert.Equal(0, (INT) Val("") )

		Assert.Equal(0, (INT) Val("abc") )
		Assert.Equal(123, (INT) Val("123abc") )
		Assert.Equal(123, (INT) Val("123abc456") )
		Assert.Equal(123, (INT) Val("123abc456.789") )
		Assert.Equal(0, (INT) Val("abc123456.789") )
		Assert.Equal(255, (INT) Val("0xFF") )
		Assert.Equal(0xFFFF, (INT) Val("0xFFFF") )
		Assert.Equal(4294967295, (INT64) Val("0xFFFFFFFF") )
		Assert.Equal(11, (INT) Val("11L11") )
		Assert.Equal(1.000, (FLOAT) Val("1,000.1") )
		Assert.Equal(1.001, (FLOAT) Val("1,001.1") )
	RETURN

	[Fact, Trait("Category", "SplitPath")];
	METHOD SplitPathTests() AS VOID
		LOCAL cDrive := "",cDir := "",cFile := "",cExt := "" AS STRING
		SplitPath("C:\folder\file.ext" ,  cDrive , cDir , cFile , cExt)

		Assert.Equal("C:" , cDrive)
		Assert.Equal("\folder\" , cDir)

		Assert.Equal("file" , cFile)
		Assert.Equal(".ext" , cExt)
	RETURN

	[Fact, Trait("Category", "SplitPathVO")];
	METHOD SplitPathVO() AS VOID
		LOCAL cPath ,cDrive ,cDir ,cFile ,cExt AS STRING
		LOCAL pszDrive, pszDir AS PSZ
		LOCAL pszFile, pszExt AS PSZ

		cPath := "C:\testfolder\testfile.prg"

		pszDrive := MemAlloc(2+1)
		pszDir   := MemAlloc(255+1)
		pszFile  := MemAlloc(255+1)
		pszExt   := MemAlloc(7+1)

		SplitPath(String2Psz(cPath), pszDrive, pszDir,        ;
			 pszFile, pszExt)

		cDrive := Psz2String(pszDrive)
		cDir   := Psz2String(pszDir)
		cFile  := Psz2String(pszFile)
		cExt   := Psz2String(pszExt)

		MemFree(pszDrive)
		MemFree(pszDir)
		MemFree(pszFile)
		MemFree(pszExt)

		Assert.Equal("\testfolder\" , cDir)
		Assert.Equal("\testfolder\" , cDir)
		Assert.Equal("testfile" , cFile)
		Assert.Equal(".prg" , cExt)
	RETURN

	[Fact, Trait("Category", "Directory")];
	METHOD DirectoryTests() AS VOID
		Assert.Equal(0u , ALen(Directory("K:\drive does not exist")))
		Assert.Equal(0u , ALen(Directory("K:\drive does not exist","V")))
		Assert.Equal(0u , ALen(Directory("C:\invalid:path")))
		Assert.Equal(1u , ALen(Directory("C:\invalid:path","V")))
		Assert.Equal(0u , ALen(Directory("C:invalid:path")))
		Assert.Equal(1u , ALen(Directory("C:invalid:path","V")))
		Assert.Equal(0u , ALen(Directory("N:")))
		Assert.Equal(0u , ALen(Directory("N:","V")))

	[Fact, Trait("Category", "Empty")];
	METHOD EmptyFuncTests() AS VOID
		Assert.True(Empty(0))
		Assert.True(Empty(false))
		Assert.True(Empty(""))
		Assert.True(Empty(Chr(10) + Chr(9) + Chr(13)))
		Assert.True(Empty(NULL_SYMBOL))
		Assert.True(Empty(0000.00.00))
		Assert.True(Empty({}))

		Assert.True(Empty(NULL_PTR))
		LOCAL p AS PTR
		p := NULL_PTR
		Assert.True(Empty(p))

		Assert.True(Empty(NULL_PSZ))
		LOCAL z AS PSZ
		z := NULL_PSZ
		Assert.True(Empty(z))

		Assert.False(Empty(1))
		Assert.False(Empty(true))
		Assert.False(Empty("a"))
		Assert.False(Empty(Chr(1)))
		Assert.False(Empty(#abc))
		Assert.False(Empty(2000.01.01))
		Assert.False(Empty({{}}))

		p := @p
		Assert.False(Empty(p))
		z := String2Psz("test")
		Assert.False(Empty(z))

	[Fact, Trait("Category", "IsClassOf")];
	METHOD IsClassOf_Tests() AS VOID
		Assert.True(IsClassOf(#TestClassChild, #TestClassParent))
		Assert.False(IsClassOf(#TestClassParent, #TestClassChild))
		Assert.True(IsClassOf(#TestClassChild, #TestClassChild))
		Assert.True(IsClassOf(#TestClassParent, #TestClassParent))
		Assert.False(IsClassOf(#None, #None))
		Assert.False(IsClassOf(#None, #TestClassChild))
		Assert.False(IsClassOf(#TestClassChild, #None))

	[Fact, Trait("Category", "AClone")];
	METHOD AClone_Tests() AS VOID
		Assert.True(ALen(AClone({1}))==1)
		Assert.True(ALen(AClone({1,2}))==2)
		Assert.True(  AClone({1,2})[2] ==2  )
		Assert.True(  AClone({1,{2,3},4})[2,2] == 3  )
		Assert.True(  AClone({1,{},4})[3] == 4  )

		Assert.True(AClone(NULL_ARRAY)==NULL_ARRAY)
		LOCAL aNull := NULL_ARRAY AS ARRAY
		Assert.True(AClone(aNull)==NULL_ARRAY)
		Assert.True(ALen(AClone({}))==0)
		Assert.True(ALen(AClone({{}}))==1)

	[Fact, Trait("Category", "ACloneShallow")];
	METHOD ACloneShallow_Tests() AS VOID
		Assert.True(ALen(ACloneShallow({1}))==1)
		Assert.True(ALen(ACloneShallow({1,2}))==2)
		Assert.True(  ACloneShallow({1,2})[2] ==2  )
		Assert.True(  ACloneShallow({1,{2,3},4})[2,2] == 3  )
		Assert.True(  ACloneShallow({1,{},4})[3] == 4  )

		LOCAL aSub AS ARRAY
		aSub := {1,2}
		Assert.True(  ACloneShallow({1,aSub,3})[2] == aSub  )

		Assert.True(ACloneShallow(NULL_ARRAY)==NULL_ARRAY)
		LOCAL aNull AS ARRAY
		aNull := NULL_ARRAY
		Assert.True(ACloneShallow(aNull)==NULL_ARRAY)
		Assert.True(ALen(ACloneShallow({}))==0)
		Assert.True(ALen(ACloneShallow({{}}))==1)

	[Fact, Trait("Category", "AClone")];
	METHOD ACloneWith_NULL_ARRAY_as_Elements() AS VOID
		Assert.True(  ALen(  AClone({NULL_ARRAY,NULL_ARRAY}) ) == 2  )
		Assert.True(  AClone({NULL_ARRAY})[1] == NULL_ARRAY  )

		Assert.True(  ALen(  ACloneShallow({NULL_ARRAY,NULL_ARRAY}) ) == 2  )
		Assert.True(  ACloneShallow({NULL_ARRAY})[1] == NULL_ARRAY  )

	END CLASS
END NAMESPACE

CLASS TestClassParent
END CLASS
CLASS TestClassChild INHERIT TestClassParent
END CLASS

//
// 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.
//
USING System
USING System.Collections.Generic
USING System.Linq
USING System.Text
USING XUnit
USING System.Globalization

BEGIN NAMESPACE XSharp.VO.Tests

	CLASS TransFormTests

		[Fact, Trait("Category", "TransForm")];
		METHOD LogicalTest() AS VOID
			// with @R other chars are appended, but only a single YN or TF flag is written. Other positions become a space
			Assert.Equal("Y", Transform(TRUE, "Y"))
			Assert.Equal("N", Transform(FALSE, "Y"))
			Assert.Equal("T", Transform(TRUE, "L"))
			Assert.Equal("F", Transform(FALSE, "L"))
			Assert.Equal("T x", Transform(TRUE, "@R L x"))
			Assert.Equal("F x", Transform(FALSE, "@R L x"))
			Assert.Equal("Y x", Transform(TRUE, "@R YYx"))
			Assert.Equal("N x", Transform(FALSE, "@R YYx"))
			SetNatDll("French.DLL")
			Assert.Equal("O", Transform(TRUE, "Y"))
			Assert.Equal("N", Transform(FALSE, "Y"))
			Assert.Equal("V", Transform(TRUE, "L"))
			Assert.Equal("F", Transform(FALSE, "L"))
			Assert.Equal("V x", Transform(TRUE, "@R L x"))
			Assert.Equal("F x", Transform(FALSE, "@R L x"))
			Assert.Equal("O x", Transform(TRUE, "@R YYx"))
			Assert.Equal("N x", Transform(FALSE, "@R YYx"))

		[Fact, Trait("Category", "TransForm")];
		METHOD DateTest() AS VOID
			// with @R other chars are appended, but only a single YN or TF flag is written. Other positions become a space
			Assert.Equal("10/12/2010", Transform(2010.12.10,"@E"))
			Assert.Equal("20/11/2010", Transform(2010.11.20,"@E"))
			SetDateFormat("dd-mm-yyyy")
			Assert.Equal("20-11-2010", Transform(2010.11.20,"@D"))
			SetDateFormat("dd-mm-yy")
			Assert.Equal("20-11-10", Transform(2010.11.20,"@D"))

		[Fact, Trait("Category", "TransForm")];
		METHOD StringTest() AS VOID
			Assert.Equal("ABC", Transform("abc", "@!"))
			Assert.Equal("AbC", Transform("abc", "!a!"))
			Assert.Equal("1234 AB", Transform("1234ab", "@R! 9999 AA"))
			Assert.Equal("1234 AB", Transform("1234ab", "@R 9999 !!"))

		[Fact, Trait("Category", "TransForm")];
		METHOD LongTest() AS VOID
			SetDecimalSep('.')
			SetThousandSep(',')
			Assert.Equal("  1", Transform(1, "999"))
			Assert.Equal("123", Transform(123, "###"))
			Assert.Equal("**", Transform(123, "##"))
			Assert.Equal("**", Transform(123, "99"))
			Assert.Equal("(1)", Transform(-1, "@( 99"))
			Assert.Equal("(-1)", Transform(-1, "@( 999"))
			Assert.Equal("( -1)", Transform(-1, "@( 9999"))
			Assert.Equal("(-1)", Transform(-1, "@) 9999"))
			Assert.Equal(" (-1)", Transform(-1, "@) 99999"))
			Assert.Equal("   ", Transform(0, "@Z 999"))
			Assert.Equal(" -1 DB", Transform(-1, "@X 999"))
			Assert.Equal(" -1 DB", Transform(-1, "@XC 999"))
			Assert.Equal("  1 CR", Transform(1, "@XC 999"))
			Assert.Equal("  1 CR", Transform(1, "@C 999"))
			Assert.Equal("  0", Transform(0, "@C 999"))
			Assert.Equal("1,234", Transform(1234, "9,999"))
			SetDecimalSep(',')
			SetThousandSep('.')
			Assert.Equal("1.234", Transform(1234, "9,999"))

		[Fact, Trait("Category", "TransForm")];
		METHOD FLoatTest() AS VOID
			SetDecimalSep('.')
			SetThousandSep(',')
			Assert.Equal("1.23", Transform(1.23, "9.99"))
			Assert.Equal("1,23", Transform(1.23, "@E 9.99"))
			Assert.Equal("*.**", Transform(12.34, "9.99"))

// some new failing tests:
	[Fact, Trait("Category", "TransForm")];
	METHOD IntLiteralTest() AS VOID
		LOCAL dec AS DWORD
		LOCAL thou AS DWORD

		dec := SetDecimalSep(Asc(","))
		thou := SetThousandSep(Asc("."))
		Assert.Equal(" 12.345,00" , Transform(12345.0, "999,999.99"))
		// this fails:
		Assert.Equal(" 12.345,00" , Transform(12345, "999,999.99"))

		SetDecimalSep(Asc("."))
		SetThousandSep(Asc(","))
		Assert.Equal(" 12,345.00" , Transform(12345.0, "999,999.99"))
		Assert.Equal(" 12,345.00" , Transform(12345, "999,999.99"))

		SetDecimalSep(dec)
		SetThousandSep(thou)
	RETURN

// Tests that need to be moved in separate files in VO.Tests:
	[Fact, Trait("Category", "StringEq")];
	METHOD StringEquality() AS VOID
		LOCAL c1,c2 AS STRING
		LOCAL u1,u2 AS USUAL
		LOCAL exact AS LOGIC
		u1 := c1 := "TESTLONG"
		u2 := c2 := "TEST"
		exact := SetExact( FALSE )

		Assert.Equal(TRUE, c1 = c2)
		Assert.Equal(TRUE, c1 != c2)

		Assert.Equal(TRUE, u1 = u2)
		Assert.Equal(FALSE, u1 != u2)

		SetExact( exact )
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD StrTests() AS VOID
		LOCAL exact,thou,digit,decimal,fixed_,digitfixed AS USUAL
		exact := SetDecimalSep(Asc("."))
		thou := SetThousandSep(Asc(","))
		digit := SetDigit(6)
		decimal := SetDecimal(3)
		fixed_ := SetFixed(FALSE)
		digitfixed := SetDigitFixed(FALSE)

		Assert.Equal( "     1.2"			, Str(1.2) )
		Assert.Equal( "    12.3"			, Str(12.3) )
		Assert.Equal( "    12.34"			, Str(12.34) )
		Assert.Equal( "   123.456"			, Str(123.456) )
		Assert.Equal( "  1234.567"			, Str(1234.567) )
		Assert.Equal( "  1234.5678"			, Str(1234.5678) )
		Assert.Equal( "  1234.5679012345"	, Str(1234.5679012345) )
		Assert.Equal( "123456.78901234567"	, Str(123456.78901234567) )
		Assert.Equal( "999999" , Str(999999) )
		Assert.Equal( "******" , Str(1000000) )

		SetDecimalSep(exact)
		SetThousandSep(thou)
		SetDigit(digit)
		SetDecimal(decimal)
		SetFixed(fixed_)
		SetDigitFixed(digitfixed)
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD Str_With_SetFixed_TRUE() AS VOID

	   SetDecimalSep(Asc("."))
	   SetThousandSep(Asc(","))
	   SetDecimal(3)
	   SetDigit(12)

	   SetFixed(TRUE)
	   SetDigitFixed(TRUE)

	   Assert.Equal( Str(12.34)            		, "          12.340")
	   Assert.Equal( Str1(12.34)          		, "          12.340")
	   Assert.Equal( Str(123.456)         		, "         123.456")
	   Assert.Equal( Str1(123.456)       		, "         123.456")
	   Assert.Equal( Str(1230.4567)         	, "        1230.457")
	   Assert.Equal( Str1(1230.4567)        	, "        1230.457")
	   Assert.Equal( Str(100000001234.4567)		, "100000001234.457")
	   Assert.Equal( Str1(100000001234.4567)	, "100000001234.457")
	   Assert.Equal( Str(1000000001234.4567)	, "****************")
	   Assert.Equal( Str1(1000000001234.4567)	, "****************")
	   Assert.Equal( Str(12.3)              	, "          12.300")
	   Assert.Equal( Str1(12.3)            		, "          12.300")
	   Assert.Equal( Str(12.34567)        	 	, "          12.346")
	   Assert.Equal( Str1(12.34567)        		, "          12.346")
	   Assert.Equal( Str(12.34 , 10, 2)    		, "     12.34")
	   Assert.Equal( Str(12.34 , 5, 2)     		, "12.34")
	   Assert.Equal( Str(12.34 , 4, 2)     		, "12.3")
	   Assert.Equal( Str(12.34 , 4, 1)     		, "12.3")
	   Assert.Equal( Str(12.34 , 2, 1)     		, "**")
	   Assert.Equal( Str3(12.34 , 10, 2)   		, "     12.34")
	   Assert.Equal( Str3(12.34 , 5, 2)    		, "12.34")
	   Assert.Equal( Str3(12.34 , 4, 2)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 4, 1)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 2, 1)    		, "**")
	   Assert.Equal( Str(-12.34)            	, "         -12.340")
	   Assert.Equal( Str1(-12.34)           	, "         -12.340")
	   Assert.Equal( Str(-12.3456)         		, "         -12.346")
	   Assert.Equal( Str1(-12.3456)         	, "         -12.346")
	   Assert.Equal( Str(-12.34 , 10, 2)    	, "    -12.34")
	   Assert.Equal( Str(-12.34 , 5, 2)     	, "-12.3")	 //VO wrong: -2.34
	   Assert.Equal( Str(-12.34 , 4, 2)     	, "-12.")
	   Assert.Equal( Str(-12.34 , 4, 1)     	, " -12")    //VO wrong: -2.3
	   Assert.Equal( Str(-12.34 , 2, 1)     	, "**")
	RETURN

	[Fact, Trait("Category", "Str")];
	METHOD Str_With_SetFixed_FALSE() AS VOID

	   SetDecimalSep(Asc("."))
	   SetThousandSep(Asc(","))
	   SetDecimal(3)
	   SetDigit(12)

	   SetFixed(FALSE)
	   SetDigitFixed(FALSE)

	   Assert.Equal( Str(12.34)            		, "          12.34")
	   Assert.Equal( Str1(12.34)          		, "          12.34")
	   Assert.Equal( Str(123.456)         		, "         123.456")
	   Assert.Equal( Str1(123.456)				, "         123.456")
	   Assert.Equal( Str(1230.4567)         	, "        1230.4567")
	   Assert.Equal( Str1(1230.4567)        	, "        1230.4567")
	   Assert.Equal( Str(100000001234.4567)		, "100000001234.4567")
	   Assert.Equal( Str1(100000001234.4567)	, "100000001234.4567")
	   Assert.Equal( Str(1000000001234.4567)	, "*****************")
	   Assert.Equal( Str1(1000000001234.4567)	, "*****************")
	   Assert.Equal( Str(12.3)              	, "          12.3")
	   Assert.Equal( Str1(12.3)            		, "          12.3")
	   Assert.Equal( Str(12.34567)         		, "          12.34567")
	   Assert.Equal( Str1(12.34567)        		, "          12.34567")
	   Assert.Equal( Str(12.34 , 10, 2)    		, "     12.34")
	   Assert.Equal( Str(12.34 , 5, 2)     		, "12.34")
	   Assert.Equal( Str(12.34 , 4, 2)     		, "12.3")
	   Assert.Equal( Str(12.34 , 4, 1)     		, "12.3")
	   Assert.Equal( Str(12.34 , 2, 1)     		, "**")
	   Assert.Equal( Str3(12.34 , 10, 2)   		, "     12.34")
	   Assert.Equal( Str3(12.34 , 5, 2)    		, "12.34")
	   Assert.Equal( Str3(12.34 , 4, 2)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 4, 1)     	, "12.3")
	   Assert.Equal( Str3(12.34 , 2, 1)    		, "**")
	   Assert.Equal( Str(-12.34)            	, "         -12.34")
	   Assert.Equal( Str1(-12.34)           	, "         -12.34")
	   Assert.Equal( Str(-12.3456)         		, "         -12.3456")
	   Assert.Equal( Str1(-12.3456)         	, "         -12.3456")
	   Assert.Equal( Str(-12.34 , 10, 2)    	, "    -12.34")
	   Assert.Equal( Str(-12.34 , 5, 2)     	, "-12.3")	 //VO: -2.34
	   Assert.Equal( Str(-12.34 , 4, 2)     	, "-12.")
	   Assert.Equal( Str(-12.34 , 4, 1)     	, " -12")    //VO: -2.3
	   Assert.Equal( Str(-12.34 , 2, 1)     	, "**")

	[Fact, Trait("Category", "Val")];
	METHOD ValTests() AS VOID
		Assert.Equal(123, (INT) Val("123") )
		Assert.Equal(123.456, (FLOAT) Val("123.456") )

		Assert.Equal(0, (INT) Val("") )

		Assert.Equal(0, (INT) Val("abc") )
		Assert.Equal(123, (INT) Val("123abc") )
		Assert.Equal(123, (INT) Val("123abc456") )
		Assert.Equal(123, (INT) Val("123abc456.789") )
		Assert.Equal(0, (INT) Val("abc123456.789") )
		Assert.Equal(255, (INT) Val("0xFF") )
		Assert.Equal(0xFFFF, (INT) Val("0xFFFF") )
		Assert.Equal(4294967295, (INT64) Val("0xFFFFFFFF") )
		Assert.Equal(11, (INT) Val("11L11") )
		Assert.Equal(1.000, (FLOAT) Val("1,000.1") )
		Assert.Equal(1.001, (FLOAT) Val("1,001.1") )
	RETURN

	[Fact, Trait("Category", "SplitPath")];
	METHOD SplitPathTests() AS VOID
		LOCAL cDrive := "",cDir := "",cFile := "",cExt := "" AS STRING
		SplitPath("C:\folder\file.ext" ,  cDrive , cDir , cFile , cExt)

		Assert.Equal("C:" , cDrive)
		Assert.Equal("\folder\" , cDir)

		Assert.Equal("file" , cFile)
		Assert.Equal(".ext" , cExt)
	RETURN

	[Fact, Trait("Category", "SplitPathVO")];
	METHOD SplitPathVO() AS VOID
		LOCAL cPath ,cDrive ,cDir ,cFile ,cExt AS STRING
		LOCAL pszDrive, pszDir AS PSZ
		LOCAL pszFile, pszExt AS PSZ

		cPath := "C:\testfolder\testfile.prg"

		pszDrive := MemAlloc(2+1)
		pszDir   := MemAlloc(255+1)
		pszFile  := MemAlloc(255+1)
		pszExt   := MemAlloc(7+1)

		SplitPath(String2Psz(cPath), pszDrive, pszDir,        ;
			 pszFile, pszExt)

		cDrive := Psz2String(pszDrive)
		cDir   := Psz2String(pszDir)
		cFile  := Psz2String(pszFile)
		cExt   := Psz2String(pszExt)

		MemFree(pszDrive)
		MemFree(pszDir)
		MemFree(pszFile)
		MemFree(pszExt)

		Assert.Equal("\testfolder\" , cDir)
		Assert.Equal("\testfolder\" , cDir)
		Assert.Equal("testfile" , cFile)
		Assert.Equal(".prg" , cExt)
	RETURN

	[Fact, Trait("Category", "Directory")];
	METHOD DirectoryTests() AS VOID
		Assert.Equal(0u , ALen(Directory("K:\drive does not exist")))
		Assert.Equal(0u , ALen(Directory("K:\drive does not exist","V")))
		Assert.Equal(0u , ALen(Directory("C:\invalid:path")))
		Assert.Equal(1u , ALen(Directory("C:\invalid:path","V")))
		Assert.Equal(0u , ALen(Directory("C:invalid:path")))
		Assert.Equal(1u , ALen(Directory("C:invalid:path","V")))
		Assert.Equal(0u , ALen(Directory("M:")))
		Assert.Equal(0u , ALen(Directory("M:","V")))

	[Fact, Trait("Category", "Empty")];
	METHOD EmptyFuncTests() AS VOID
		Assert.True(Empty(0))
		Assert.True(Empty(false))
		Assert.True(Empty(""))
		Assert.True(Empty(Chr(10) + Chr(9) + Chr(13)))
		Assert.True(Empty(NULL_SYMBOL))
		Assert.True(Empty(0000.00.00))
		Assert.True(Empty({}))

		Assert.True(Empty(NULL_PTR))
		LOCAL p AS PTR
		p := NULL_PTR
		Assert.True(Empty(p))

		Assert.True(Empty(NULL_PSZ))
		LOCAL z AS PSZ
		z := NULL_PSZ
		Assert.True(Empty(z))

		Assert.False(Empty(1))
		Assert.False(Empty(true))
		Assert.False(Empty("a"))
		Assert.False(Empty(Chr(1)))
		Assert.False(Empty(#abc))
		Assert.False(Empty(2000.01.01))
		Assert.False(Empty({{}}))

		p := @p
		Assert.False(Empty(p))
		z := String2Psz("test")
		Assert.False(Empty(z))

	[Fact, Trait("Category", "IsClassOf")];
	METHOD IsClassOf_Tests() AS VOID
		Assert.True(IsClassOf(#TestClassChild, #TestClassParent))
		Assert.False(IsClassOf(#TestClassParent, #TestClassChild))
		Assert.True(IsClassOf(#TestClassChild, #TestClassChild))
		Assert.True(IsClassOf(#TestClassParent, #TestClassParent))
		Assert.False(IsClassOf(#None, #None))
		Assert.False(IsClassOf(#None, #TestClassChild))
		Assert.False(IsClassOf(#TestClassChild, #None))

	[Fact, Trait("Category", "AClone")];
	METHOD AClone_Tests() AS VOID
		Assert.True(ALen(AClone({1}))==1)
		Assert.True(ALen(AClone({1,2}))==2)
		Assert.True(  AClone({1,2})[2] ==2  )
		Assert.True(  AClone({1,{2,3},4})[2,2] == 3  )
		Assert.True(  AClone({1,{},4})[3] == 4  )

		Assert.True(AClone(NULL_ARRAY)==NULL_ARRAY)
		LOCAL aNull := NULL_ARRAY AS ARRAY
		Assert.True(AClone(aNull)==NULL_ARRAY)
		Assert.True(ALen(AClone({}))==0)
		Assert.True(ALen(AClone({{}}))==1)

	[Fact, Trait("Category", "ACloneShallow")];
	METHOD ACloneShallow_Tests() AS VOID
		Assert.True(ALen(ACloneShallow({1}))==1)
		Assert.True(ALen(ACloneShallow({1,2}))==2)
		Assert.True(  ACloneShallow({1,2})[2] ==2  )
		Assert.True(  ACloneShallow({1,{2,3},4})[2,2] == 3  )
		Assert.True(  ACloneShallow({1,{},4})[3] == 4  )

		LOCAL aSub AS ARRAY
		aSub := {1,2}
		Assert.True(  ACloneShallow({1,aSub,3})[2] == aSub  )

		Assert.True(ACloneShallow(NULL_ARRAY)==NULL_ARRAY)
		LOCAL aNull AS ARRAY
		aNull := NULL_ARRAY
		Assert.True(ACloneShallow(aNull)==NULL_ARRAY)
		Assert.True(ALen(ACloneShallow({}))==0)
		Assert.True(ALen(ACloneShallow({{}}))==1)

	[Fact, Trait("Category", "AClone")];
	METHOD ACloneWith_NULL_ARRAY_as_Elements() AS VOID
		Assert.True(  ALen(  AClone({NULL_ARRAY,NULL_ARRAY}) ) == 2  )
		Assert.True(  AClone({NULL_ARRAY})[1] == NULL_ARRAY  )

		Assert.True(  ALen(  ACloneShallow({NULL_ARRAY,NULL_ARRAY}) ) == 2  )
		Assert.True(  ACloneShallow({NULL_ARRAY})[1] == NULL_ARRAY  )

	END CLASS
END NAMESPACE

CLASS TestClassParent
END CLASS
CLASS TestClassChild INHERIT TestClassParent
END CLASS


codegen/Qt3DAnimation: updated

codegen/Qt3DAnimation: updated

Modified:
codegen/Qt3DAnimation/QAdditiveClipBlend.prg

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

$project=Qt5xHb
$module=Qt3DAnimation

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=QAbstractClipBlendNode

$addMethods

$addSignals

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=explicit QAdditiveClipBlend(Qt3DCore::QNode *parent = nullptr)

$prototype=explicit QAdditiveClipBlend(QAdditiveClipBlendPrivate &dd, Qt3DCore::QNode *parent = nullptr) [protected]

$prototype=~QAdditiveClipBlend()
$deleteMethod

%%
%% Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *baseClip READ baseClip WRITE setBaseClip NOTIFY baseClipChanged)
%%

$prototype=Qt3DAnimation::QAbstractClipBlendNode *baseClip() const

$prototype=void setBaseClip(Qt3DAnimation::QAbstractClipBlendNode *baseClip) (slot)

%%
%% Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *additiveClip READ additiveClip WRITE setAdditiveClip NOTIFY additiveClipChanged)
%%

$prototype=Qt3DAnimation::QAbstractClipBlendNode *additiveClip() const

$prototype=void setAdditiveClip(Qt3DAnimation::QAbstractClipBlendNode *additiveClip) (slot)

%%
%% Q_PROPERTY(float additiveFactor READ additiveFactor WRITE setAdditiveFactor NOTIFY additiveFactorChanged)
%%

$prototype=float additiveFactor() const

$prototype=void setAdditiveFactor(float additiveFactor) (slot)

%%
%%
%%

$prototype=Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE [private]

$beginSignals
$signal=|additiveFactorChanged(float)
$signal=|baseClipChanged(Qt3DAnimation::QAbstractClipBlendNode*)
$signal=|additiveClipChanged(Qt3DAnimation::QAbstractClipBlendNode*)
$endSignals

#pragma ENDDUMP

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

$project=Qt5xHb
$module=Qt3DAnimation

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=QAbstractClipBlendNode

$addMethods

$addSignals

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=explicit QAdditiveClipBlend(Qt3DCore::QNode *parent = nullptr)

$prototype=explicit QAdditiveClipBlend(QAdditiveClipBlendPrivate &dd, Qt3DCore::QNode *parent = nullptr) [protected]

$prototype=~QAdditiveClipBlend()
$deleteMethod

%%
%% Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *baseClip READ baseClip WRITE setBaseClip NOTIFY baseClipChanged)
%%

$prototype=Qt3DAnimation::QAbstractClipBlendNode *baseClip() const

$prototype=void setBaseClip(Qt3DAnimation::QAbstractClipBlendNode *baseClip) (slot)

%%
%% Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *additiveClip READ additiveClip WRITE setAdditiveClip NOTIFY additiveClipChanged)
%%

$prototype=Qt3DAnimation::QAbstractClipBlendNode *additiveClip() const

$prototype=void setAdditiveClip(Qt3DAnimation::QAbstractClipBlendNode *additiveClip) (slot)

%%
%% Q_PROPERTY(float additiveFactor READ additiveFactor WRITE setAdditiveFactor NOTIFY additiveFactorChanged)
%%

$prototype=float additiveFactor() const

$prototype=void setAdditiveFactor(float additiveFactor) (slot)

%%
%%
%%

$prototype=Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE [private]

$beginSignals
$signal=additiveFactorChanged(float)
$signal=baseClipChanged(Qt3DAnimation::QAbstractClipBlendNode*)
$signal=additiveClipChanged(Qt3DAnimation::QAbstractClipBlendNode*)
$endSignals

#pragma ENDDUMP


QtUiLoader: module updated

QtUiLoader: module updated

Modified:
source/QtUiTools/QUiLoader.prg

/*

  Qt5xHb - bibliotecas de ligao entre Harbour/xHarbour e Qt Framework 5

  Copyright (C) 2012-2017 Marcos Antonio Gambeta <marcosgambeta@uol.com.br>

*/

#include "hbclass.ch"

#ifndef QT5XHB_NO_REQUESTS
REQUEST QACTION
REQUEST QACTIONGROUP
REQUEST QLAYOUT
REQUEST QWIDGET
REQUEST QDIR
#endif

CLASS QUiLoader INHERIT QObject

   DATA self_destruction INIT .F.

   METHOD new
   METHOD delete
   METHOD addPluginPath
   METHOD availableLayouts
   METHOD availableWidgets
   METHOD clearPluginPaths
   METHOD createAction
   METHOD createActionGroup
   METHOD createLayout
   METHOD createWidget
   METHOD isLanguageChangeEnabled
   METHOD load
   METHOD pluginPaths
   METHOD setLanguageChangeEnabled
   METHOD setWorkingDirectory
   METHOD workingDirectory

   DESTRUCTOR destroyObject

END CLASS

PROCEDURE destroyObject () CLASS QUiLoader
   IF ::self_destruction
      ::delete()
   ENDIF
RETURN

#pragma BEGINDUMP

#include <Qt>

#ifndef __XHARBOUR__
#include <QUiLoader>
#endif

#include "qt5xhb_common.h"
#include "qt5xhb_macros.h"
#include "qt5xhb_utils.h"

#ifdef __XHARBOUR__
#include <QUiLoader>
#endif

#include <QStringList>
#include <QDir>

/*
QUiLoader ( QObject * parent = 0 )
*/
HB_FUNC_STATIC( QUILOADER_NEW )
{
  if( ISBETWEEN(0,1) && ISOPTQOBJECT(1) )
  {
    QUiLoader * o = new QUiLoader ( OPQOBJECT(1,0) );
    _qt5xhb_storePointerAndFlag( o, false );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

HB_FUNC_STATIC( QUILOADER_DELETE )
{
  QUiLoader * obj = (QUiLoader *) hb_itemGetPtr( hb_objSendMsg( hb_stackSelfItem(), "POINTER", 0 ) );

  if( obj )
  {
    delete obj;
    obj = NULL;
    PHB_ITEM self = hb_stackSelfItem();
    PHB_ITEM ptr = hb_itemPutPtr( NULL, NULL );
    hb_objSendMsg( self, "_pointer", 1, ptr );
    hb_itemRelease( ptr );
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
void addPluginPath ( const QString & path )
*/
HB_FUNC_STATIC( QUILOADER_ADDPLUGINPATH )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) )
    {
      obj->addPluginPath ( PQSTRING(1) );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
QStringList availableLayouts () const
*/
HB_FUNC_STATIC( QUILOADER_AVAILABLELAYOUTS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->availableLayouts ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
QStringList availableWidgets () const
*/
HB_FUNC_STATIC( QUILOADER_AVAILABLEWIDGETS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->availableWidgets ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
void clearPluginPaths ()
*/
HB_FUNC_STATIC( QUILOADER_CLEARPLUGINPATHS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    obj->clearPluginPaths ();
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
virtual QAction * createAction ( QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEACTION )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISOPTQOBJECT(1) && ISOPTCHAR(2) )
    {
      QAction * ptr = obj->createAction ( OPQOBJECT(1,0), OPQSTRING(2,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QACTION" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QActionGroup * createActionGroup ( QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEACTIONGROUP )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISOPTQOBJECT(1) && ISOPTCHAR(2) )
    {
      QActionGroup * ptr = obj->createActionGroup ( OPQOBJECT(1,0), OPQSTRING(2,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QACTIONGROUP" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QLayout * createLayout ( const QString & className, QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATELAYOUT )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) && ISOPTQOBJECT(2) && ISOPTCHAR(3) )
    {
      QLayout * ptr = obj->createLayout ( PQSTRING(1), OPQOBJECT(2,0), OPQSTRING(3,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QLAYOUT" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QWidget * createWidget ( const QString & className, QWidget * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEWIDGET )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) && ISOPTQWIDGET(2) && ISOPTCHAR(3) )
    {
      QWidget * ptr = obj->createWidget ( PQSTRING(1), OPQWIDGET(2,0), OPQSTRING(3,QString()) );
      _qt5xhb_createReturnQWidgetClass ( ptr, "QWIDGET" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
bool isLanguageChangeEnabled () const
*/
HB_FUNC_STATIC( QUILOADER_ISLANGUAGECHANGEENABLED )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    hb_retl( obj->isLanguageChangeEnabled () );
  }
}

/*
QWidget * load ( QIODevice * device, QWidget * parentWidget = 0 )
*/
HB_FUNC_STATIC( QUILOADER_LOAD )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISQIODEVICE(1) && ISOPTQWIDGET(2) )
    {
      QWidget * ptr = obj->load ( PQIODEVICE(1), OPQWIDGET(2,0) );
      _qt5xhb_createReturnQWidgetClass ( ptr, "QWIDGET" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
QStringList pluginPaths () const
*/
HB_FUNC_STATIC( QUILOADER_PLUGINPATHS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->pluginPaths ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
void setLanguageChangeEnabled ( bool enabled )
*/
HB_FUNC_STATIC( QUILOADER_SETLANGUAGECHANGEENABLED )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISLOG(1) )
    {
      obj->setLanguageChangeEnabled ( PBOOL(1) );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
void setWorkingDirectory ( const QDir & dir )
*/
HB_FUNC_STATIC( QUILOADER_SETWORKINGDIRECTORY )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISQDIR(1) )
    {
      QDir * par1 = (QDir *) _qt5xhb_itemGetPtr(1);
      obj->setWorkingDirectory ( *par1 );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
QDir workingDirectory () const
*/
HB_FUNC_STATIC( QUILOADER_WORKINGDIRECTORY )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QDir * ptr = new QDir( obj->workingDirectory () );
    _qt5xhb_createReturnClass ( ptr, "QDIR", true );
  }
}

#pragma ENDDUMP

/*

  Qt5xHb - bibliotecas de ligao entre Harbour/xHarbour e Qt Framework 5

  Copyright (C) 2012-2017 Marcos Antonio Gambeta <marcosgambeta@uol.com.br>

*/

#include "hbclass.ch"

#ifndef QT5XHB_NO_REQUESTS
REQUEST QACTION
REQUEST QACTIONGROUP
REQUEST QLAYOUT
REQUEST QWIDGET
REQUEST QDIR
#endif

CLASS QUiLoader INHERIT QObject

   DATA self_destruction INIT .F.

   METHOD new
   METHOD delete
   METHOD addPluginPath
   METHOD availableLayouts
   METHOD availableWidgets
   METHOD clearPluginPaths
   METHOD createAction
   METHOD createActionGroup
   METHOD createLayout
   METHOD createWidget
   METHOD isLanguageChangeEnabled
   METHOD load
   METHOD pluginPaths
   METHOD setLanguageChangeEnabled
   METHOD setWorkingDirectory
   METHOD workingDirectory

   DESTRUCTOR destroyObject

END CLASS

PROCEDURE destroyObject () CLASS QUiLoader
   IF ::self_destruction
      ::delete()
   ENDIF
RETURN

#pragma BEGINDUMP

#include <Qt>

#ifndef __XHARBOUR__
#include <QUiLoader>
#endif

#include "qt5xhb_common.h"
#include "qt5xhb_macros.h"
#include "qt5xhb_utils.h"

#ifdef __XHARBOUR__
#include <QUiLoader>
#endif

#include <QStringList>
#include <QDir>

/*
QUiLoader ( QObject * parent = 0 )
*/
HB_FUNC_STATIC( QUILOADER_NEW )
{
  if( ISBETWEEN(0,1) && ISOPTQOBJECT(1) )
  {
    QUiLoader * o = new QUiLoader ( OPQOBJECT(1,0) );
    _qt5xhb_storePointerAndFlag( o, false );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

HB_FUNC_STATIC( QUILOADER_DELETE )
{
  QUiLoader * obj = (QUiLoader *) hb_itemGetPtr( hb_objSendMsg( hb_stackSelfItem(), "POINTER", 0 ) );

  if( obj )
  {
    delete obj;
    obj = NULL;
    PHB_ITEM self = hb_stackSelfItem();
    PHB_ITEM ptr = hb_itemPutPtr( NULL, NULL );
    hb_objSendMsg( self, "_pointer", 1, ptr );
    hb_itemRelease( ptr );
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
void addPluginPath ( const QString & path )
*/
HB_FUNC_STATIC( QUILOADER_ADDPLUGINPATH )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) )
    {
      obj->addPluginPath ( PQSTRING(1) );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
QStringList availableLayouts () const
*/
HB_FUNC_STATIC( QUILOADER_AVAILABLELAYOUTS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->availableLayouts ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
QStringList availableWidgets () const
*/
HB_FUNC_STATIC( QUILOADER_AVAILABLEWIDGETS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->availableWidgets ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
void clearPluginPaths ()
*/
HB_FUNC_STATIC( QUILOADER_CLEARPLUGINPATHS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    obj->clearPluginPaths ();
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
virtual QAction * createAction ( QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEACTION )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISOPTQOBJECT(1) && ISOPTCHAR(2) )
    {
      QAction * ptr = obj->createAction ( OPQOBJECT(1,0), OPQSTRING(2,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QACTION" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QActionGroup * createActionGroup ( QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEACTIONGROUP )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISOPTQOBJECT(1) && ISOPTCHAR(2) )
    {
      QActionGroup * ptr = obj->createActionGroup ( OPQOBJECT(1,0), OPQSTRING(2,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QACTIONGROUP" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QLayout * createLayout ( const QString & className, QObject * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATELAYOUT )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) && ISOPTQOBJECT(2) && ISOPTCHAR(3) )
    {
      QLayout * ptr = obj->createLayout ( PQSTRING(1), OPQOBJECT(2,0), OPQSTRING(3,QString()) );
      _qt5xhb_createReturnClass ( ptr, "QLAYOUT" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
virtual QWidget * createWidget ( const QString & className, QWidget * parent = 0, const QString & name = QString() )
*/
HB_FUNC_STATIC( QUILOADER_CREATEWIDGET )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISCHAR(1) && ISOPTQWIDGET(2) && ISOPTCHAR(3) )
    {
      QWidget * par2 = ISNIL(2)? 0 : (QWidget *) _qt5xhb_itemGetPtr(2);
      QWidget * ptr = obj->createWidget ( PQSTRING(1), par2, OPQSTRING(3,QString()) );
      _qt5xhb_createReturnQWidgetClass ( ptr, "QWIDGET" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
bool isLanguageChangeEnabled () const
*/
HB_FUNC_STATIC( QUILOADER_ISLANGUAGECHANGEENABLED )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    hb_retl( obj->isLanguageChangeEnabled () );
  }
}

/*
QWidget * load ( QIODevice * device, QWidget * parentWidget = 0 )
*/
HB_FUNC_STATIC( QUILOADER_LOAD )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISQIODEVICE(1) && ISOPTQWIDGET(2) )
    {
      QIODevice * par1 = (QIODevice *) _qt5xhb_itemGetPtr(1);
      QWidget * par2 = ISNIL(2)? 0 : (QWidget *) _qt5xhb_itemGetPtr(2);
      QWidget * ptr = obj->load ( par1, par2 );
      _qt5xhb_createReturnQWidgetClass ( ptr, "QWIDGET" );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }
}

/*
QStringList pluginPaths () const
*/
HB_FUNC_STATIC( QUILOADER_PLUGINPATHS )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QStringList strl = obj->pluginPaths ();
    _qt5xhb_convert_qstringlist_to_array ( strl );
  }
}

/*
void setLanguageChangeEnabled ( bool enabled )
*/
HB_FUNC_STATIC( QUILOADER_SETLANGUAGECHANGEENABLED )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISLOG(1) )
    {
      obj->setLanguageChangeEnabled ( PBOOL(1) );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
void setWorkingDirectory ( const QDir & dir )
*/
HB_FUNC_STATIC( QUILOADER_SETWORKINGDIRECTORY )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    if( ISQDIR(1) )
    {
      QDir * par1 = (QDir *) _qt5xhb_itemGetPtr(1);
      obj->setWorkingDirectory ( *par1 );
    }
    else
    {
      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
    }
  }

  hb_itemReturn( hb_stackSelfItem() );
}

/*
QDir workingDirectory () const
*/
HB_FUNC_STATIC( QUILOADER_WORKINGDIRECTORY )
{
  QUiLoader * obj = (QUiLoader *) _qt5xhb_itemGetPtrStackSelfItem();

  if( obj )
  {
    QDir * ptr = new QDir( obj->workingDirectory () );
    _qt5xhb_createReturnClass ( ptr, "QDIR", true );
  }
}

#pragma ENDDUMP


clean up a bit

clean up a bit

-- Modeling Opetopes
-- here is Eric's editor: http://sma.epfl.ch/~finster/opetope/opetope.html
--
-- Note: Kock et al. use a similar scheme, where
--          - dots    <-->   lines
--          - spheres <-->   dots
--          - lines disappear
--          -                spheres appear

-- Note: In Eric's new work (at IAS) there are no
--       dots any more, instead he uses 'output cards', so
--          - (output) cards   <-->  lines
--          - space between stacked cards <--> output cards
--          - lines disappear
--          -                (regular) cards appear

import "../tests/Nat.prg"

kind Trees = NoTree | Pre (Tree d) Trees deriving syntax (ts) List(NoTree, Pre)

data ZoomCompley :: Tree e ~> Tree f ~> * where
  Nily :: ZoomCompley a a
  Consy :: Stack a b -> ZoomCompley b c -> ZoomCompley a c
 deriving List(cply)

data ZoomComplex :: Trees ~> * where
  Nilx :: ZoomComplex [()tr]ts
  Endx :: Stack a b -> ZoomComplex [a, b]ts
  Consx :: Stack a b -> ZoomComplex [b; c]ts -> ZoomComplex [a, b; c]ts
 deriving syntax (cplx) List(Nilx, Consx) Item(Endx)

data Dir :: *2 where
  Hor :: Dir
  Ver :: Dir

-- define the Tree kind, a rose tree
-- note: we may need a two-level kind, since we need to track disjointness
--       of subtrees
-- todo: later we may want to have a label kind parameter too

data Tree :: Dir ~> *1 where
  Unit :: Tree Ver
  Ni :: Tree Hor
  Fork :: Tree d ~> Tree Hor ~> Tree Hor
 deriving syntax (tr) List(Ni, Fork) Unit(Unit)

-- make it singleton

data Tree' :: Tree d ~> * where
  In :: Tree' ()tr
  Fork :: Tree' head -> Tree' tail -> Tree' [head; tail]tr
  Done :: Tree' []tr
 deriving syntax (ar) List(Done, Fork) Unit(In) -- "arbre"
-- http://www.papoulipoesique.com/wp-content/uploads/2013/06/arbre.jpg

-- define a proposition for subtrees
-- to be checked: TakeHead must ensure that all the node is consumed

prop Subtree :: Tree d ~> Tree e ~> * where
  UnitSub :: Subtree ()tr tr
  BothNil :: Subtree []tr []tr
  TakeHead :: Subtree head head' -> Subtree tail tail' -> Subtree [head; tail]tr [head'; tail']tr

-- now we can stack cards (these are zooms in Kock et al. parlance)

data Stack :: Tree d ~> Tree e ~> * where
  Corolla :: Corolla tr => Tree' tr -> Stack tr ()tr

  -- are these needed?
  SubDone :: Stack ()tr []tr -- ({}z)z
  SubCont :: Stack ()tr tr -> Stack ()tr [tr]tr -- ({inner}z)z

  -- needed?
  Encompass :: Subtree consumed tr => Stack consumed prod -> Stack tr prod

  -- put a frame around a niche
  Frame :: (Equal {nodes tr} {nodeValence out}) => Stack tr out -> Stack tr out

  -- the following three grab a node (and possibly its offsprings) and incorporate it into a single card
  NodeDone :: Stack []tr [()tr]tr
  Pick :: {- EntireNode => -} Stack head prodhead -> Stack tail prodtail -> Stack [head; tail]tr [prodhead; prodtail]tr
  Exclude :: {- EntireNode => -} Stack tail prod -> Stack [()tr; tail]tr prod

  On :: (Subtree tr' tr, Pointers 1t at out) => Stack tr' out' -> Stack tr out -> Tree' at -> Stack tr {graft out' at out}

  -- building niches
  NicheDone :: Stack ()tr []tr
  Niche :: Stack tr out -> Stack tr [out]tr
  Also :: () -- (Pointers 1t at tr)
         => Tree' at -> Stack tr' out' -> Stack tr out -> Stack {extgraft tr' at tr} [out'; out]tr

 deriving syntax(z) Record(NicheDone, Also) Item(Frame)

-- it remains to define corollas

prop Corolla :: Tree d ~> * where
  None' :: Corolla []tr
  One' :: Corolla tail -> Corolla [()tr; tail]tr

--  o   --->  |
--  |         |

lolliCell :: Stack []tr ()tr
lolliCell = Corolla Done

--  |         |
--  o   --->  |
--  |         |

dolliCell :: Stack [()tr]tr ()tr
dolliCell = Corolla $ Fork In Done

--              |
--  [o]   --->  o
--   |          |

lolliFrame :: Stack []tr [()tr]tr
lolliFrame = Encompass NodeDone

--   |          |
--  [o]   --->  o
--   |          |

dolliFrame :: Stack [()tr]tr [()tr]tr
dolliFrame = Encompass (Exclude NodeDone)

--   |          |
--   |          o
-- [[o]]  --->  |
--   |          o
--   |          |

stacked :: Stack [()tr]tr [[()tr]tr]tr
stacked = (dolliFrame `On` dolliFrame) (In `Fork` Done)

--   |
--  [|]   --->  o
--   |          |

crossed :: Stack ()tr []tr
crossed = SubDone

-- we can now join things
--
dolliForever = [dolliFrame; dolliForever]cply
nopetope = [crossed, lolliFrame; dolliForever]cply

-- back to unit as fast as possible...
--
stopetope = [crossed, lolliFrame, dolliCell]cply
neverstopetope = [crossed, lolliFrame, dolliCell; neverstopetope]cply
stopetope' = [crossed, lolliFrame; (dolliCell)cplx]cplx
stopetope'' = [crossed, lolliFrame, dolliCell]cplx

--   |          o
-- [[|]]  --->  |
--   |          o
--   |          |

drossed :: Stack ()tr [[]tr]tr
drossed = SubCont SubDone
-- drossed = (SubDone `On` NodeDone) In
-- Note: can we find a way to graft here? Then On would be feasible

-- ################################
-- ############  Niches ###########
-- ################################

--  |          +
--  |          |

-- this is a niche, but assume to be a frame
niche0 :: Stack ()tr []tr
niche0 = {}z

--  |           |
-- [|]          +
--  |           |

-- this is a niche, but assume to be a frame
niche1 :: Stack ()tr [[]tr]tr
niche1 = {()ar=SubDone; {}z}z

--  |         o   o
-- [|]  --->   \ /
-- [|]          +
--  |           |

-- this is a niche, but assume to be a frame
niche2 :: Stack ()tr [[]tr, []tr]tr
niche2 = {()ar=SubDone; niche1}z

--                |
--  |         o   o
-- [o]  --->   \ /
-- [|]          +
--  |           |

niche10 :: Stack [()tr]tr [[()tr]tr, []tr]tr
niche10 = {()ar=Exclude NodeDone; Niche SubDone}z

-- ################################
-- ############  Frames ###########
-- ################################

--   |              |
--  /|\         o   o
-- |[o]|  --->   \ /
-- |[|]|          o
--  \|/           |
--   |

cyclops :: Stack [()tr]tr [[()tr]tr, []tr]tr
cyclops = (niche10)z

-- Stacking, Valence, Affine subtree, Substitute at an affine position

-- counting Units in a tree

valence :: Tree d ~> Nat
{valence []tr} = 0t
{valence [head; tail]tr} = {plus {valence head} {valence tail}}
{valence ()tr} = 1t

-- counting siblings of a tree

nodeValence :: Tree d ~> Nat
{nodeValence []tr} = 0t
{nodeValence [head; tail]tr} = (1+{nodeValence tail})t

-- counting nodes in a tree

nodes :: Tree d ~> Nat
{nodes ()tr} = t
{nodes []tr} = 1t
{nodes [head; tail]tr} = {plus {nodes head} {nodes tail}}

-- nodeValenceAt: given a (multi)pointer, determine the node valences at those positions
--               WHERE     IN
nodeValenceAt :: Tree d ~> Tree e ~> Nat
{nodeValenceAt ()tr tree} = {nodeValence tree}
{nodeValenceAt []tr []tr} = 0t
{nodeValenceAt [head'; tail']tr [head; tail]tr} = {plus {nodeValenceAt head' head} {nodeValenceAt tail' tail}}

-- a pointer is a valence-1 subtree of a tree
-- it is used to mark a unit in a tree where substitution will occur
--
prop Pointers :: Nat ~> Tree d ~> Tree e ~> * where
  Finger :: Pointers 1t ()tr ()tr
  Finished :: Pointers 0t []tr []tr
  ThisWay :: Pointers 1t head' head -> Pointers n tail' tail -> Pointers (1+n)t [head'; tail']tr [head; tail]tr
  ElseWhere :: Pointers n tail' tail -> Pointers n [[]tr; tail']tr [head; tail]tr

-- http://en.wikipedia.org/wiki/Grafting
--
-- graft WHAT      WHERE     IN
graft :: Tree d ~> Tree e ~> Tree f ~> Tree f
{graft what ()tr ()tr} = what
{graft what []tr tr} = tr
{graft what [head'; tail']tr [head; tail]tr} = [{graft what head' head}; {graft what tail' tail}]tr

extgraft :: Tree what ~> Tree wher ~> Tree tree ~> Tree tree'
{extgraft what ()tr ()tr} = what
{extgraft what []tr ()tr} = ()tr
{extgraft what [head; tail]tr ()tr} = [{extgraft what head ()tr}; {extgraft what tail ()tr}]tr
{extgraft what []tr []tr} = []tr
{extgraft what []tr [head; tail]tr} = [head; tail]tr
{extgraft what [head'; tail']tr [head; tail]tr} = [{extgraft what head' head}; {extgraft what tail' tail}]tr

{- TODO? multiGraft :: Treelist -> where -> in -}

{- NOTE: we have an Omega bug here:

prompt> :norm {graft []tr ()tr ()tr}
Normalizes to:
  []tr

prompt> :kind []tr
[]tr :: Tree Hor  = []tr

prompt> :kind {graft []tr ()tr ()tr}
{graft []tr ()tr ()tr} :: Tree Ver  = {graft []tr ()tr ()tr}

... BUT: Hor /= Ver :-(
-}

-- substitution: replace a pointed node (of valence n) in a tree with an
-- other tree of (valence n) -- TODO

-- HERE IS A NICE RESEARCH QUESTION:
-- is it possible to "proof search" a Zoom?
-- i.e.
{-

class ZoomLike (int :: Tree) (out :: Tree) where
  zoom :: (Nodes int ~ Valence out) => Zoom int out

-}

-- Modeling Opetopes
-- here is Eric's editor: http://sma.epfl.ch/~finster/opetope/opetope.html
--
-- Note: Kock et al. use a similar scheme, where
--          - dots    <-->   lines
--          - spheres <-->   dots
--          - lines disappear
--          -                spheres appear

-- Note: In Eric's new work (at IAS) there are no
--       dots any more, instead he uses 'output cards', so
--          - (output) cards   <-->  lines
--          - space between stacked cards <--> output cards
--          - lines disappear
--          -                (regular) cards appear

import "../tests/Nat.prg"

kind Trees = NoTree | Pre (Tree d) Trees deriving syntax (ts) List(NoTree, Pre)

data ZoomCompley :: Tree e ~> Tree f ~> * where
  Nily :: ZoomCompley a a
  Consy :: Stack a b -> ZoomCompley b c -> ZoomCompley a c
 deriving List(cply)

data ZoomComplex :: Trees ~> * where
  Nilx :: ZoomComplex [()tr]ts
  Endx :: Stack a b -> ZoomComplex [a, b]ts
  Consx :: Stack a b -> ZoomComplex [b; c]ts -> ZoomComplex [a, b; c]ts
 deriving syntax (cplx) List(Nilx, Consx) Item(Endx)

data Dir :: *2 where
  Hor :: Dir
  Ver :: Dir

-- define the Tree kind, a rose tree
-- note: we may need a two-level kind, since we need to track disjointness
--       of subtrees
-- todo: later we may want to have a label kind parameter too

data Tree :: Dir ~> *1 where
  Unit :: Tree Ver
  Ni :: Tree Hor
  Fork :: Tree d ~> Tree Hor ~> Tree Hor
 deriving syntax (tr) List(Ni, Fork) Unit(Unit)

-- make it singleton

data Tree' :: Tree d ~> * where
  In :: Tree' ()tr
  Fork :: Tree' head -> Tree' tail -> Tree' [head; tail]tr
  Done :: Tree' []tr
 deriving syntax (ar) List(Done, Fork) Unit(In) -- "arbre"
-- http://www.papoulipoesique.com/wp-content/uploads/2013/06/arbre.jpg

-- define a proposition for subtrees
-- to be checked: TakeHead must ensure that all the node is consumed

prop Subtree :: Tree d ~> Tree e ~> * where
  UnitSub :: Subtree ()tr tr
  BothNil :: Subtree []tr []tr
  TakeHead :: Subtree head head' -> Subtree tail tail' -> Subtree [head; tail]tr [head'; tail']tr

-- now we can stack cards (these are zooms in Kock et al. parlance)

data Stack :: Tree d ~> Tree e ~> * where
  Corolla :: Corolla tr => Tree' tr -> Stack tr ()tr
  SubDone :: Stack ()tr []tr
  SubCont :: Stack ()tr tr -> Stack ()tr [tr]tr
  --Subdivision :: Stack ()tr sub -> Stack tr rest -> Stack tr [sub; rest]tr
  Encompass :: Subtree consumed tr => Stack consumed prod -> Stack tr prod

  -- put a frame around a niche
  Frame :: (Equal {nodes tr} {nodeValence out}) => Stack tr out -> Stack tr out

  -- the following three grab a node (and possibly its offsprings) and incorporate it into a single card
  NodeDone :: Stack []tr [()tr]tr
  Pick :: {- EntireNode => -} Stack head prodhead -> Stack tail prodtail -> Stack [head; tail]tr [prodhead; prodtail]tr
  Exclude :: {- EntireNode => -} Stack tail prod -> Stack [()tr; tail]tr prod
  -- we need a way to sequence cards
  -- MultiCard :: ??? Disjoint a b 0 => Subtree a -> Subtree b -> Stack tr a [proda, prodb]tr

  On :: (Subtree tr' tr, Pointers 1t at out) => Stack tr' out' -> Stack tr out -> Tree' at -> Stack tr {graft out' at out}

  -- building niches
  NicheDone :: Stack ()tr []tr
  Niche :: Stack tr out -> Stack tr [out]tr
  Also :: () -- (Pointers 1t at tr)
         => Tree' at -> Stack tr' out' -> Stack tr out -> Stack {extgraft tr' at tr} [out'; out]tr

 deriving syntax(z) Record(NicheDone, Also)

-- it remains to define corollas

prop Corolla :: Tree d ~> * where
  None' :: Corolla []tr
  One' :: Corolla tail -> Corolla [()tr; tail]tr

--  o   --->  |
--  |         |

lolliCell :: Stack []tr ()tr
lolliCell = Corolla Done

--  |         |
--  o   --->  |
--  |         |

dolliCell :: Stack [()tr]tr ()tr
dolliCell = Corolla $ Fork In Done

--              |
--  [o]   --->  o
--   |          |

lolliFrame :: Stack []tr [()tr]tr
lolliFrame = Encompass NodeDone

--   |          |
--  [o]   --->  o
--   |          |

dolliFrame :: Stack [()tr]tr [()tr]tr
dolliFrame = Encompass (Exclude NodeDone)

--   |          |
--   |          o
-- [[o]]  --->  |
--   |          o
--   |          |

stacked :: Stack [()tr]tr [[()tr]tr]tr
stacked = (dolliFrame `On` dolliFrame) (In `Fork` Done)

--   |
--  [|]   --->  o
--   |          |

crossed :: Stack ()tr []tr
crossed = SubDone

-- we can now join things
--
dolliForever = [dolliFrame; dolliForever]cply
nopetope = [crossed, lolliFrame; dolliForever]cply

-- back to unit as fast as possible...
--
stopetope = [crossed, lolliFrame, dolliCell]cply
neverstopetope = [crossed, lolliFrame, dolliCell; neverstopetope]cply
stopetope' = [crossed, lolliFrame; (dolliCell)cplx]cplx
stopetope'' = [crossed, lolliFrame, dolliCell]cplx

--   |          o
-- [[|]]  --->  |
--   |          o
--   |          |

drossed :: Stack ()tr [[]tr]tr
drossed = SubCont SubDone
-- drossed = (SubDone `On` NodeDone) In
-- Note: can we find a way to graft here? Then On would be feasible

-- ################################
-- ############  Niches ###########
-- ################################

--  |          +
--  |          |

-- this is a niche, but assume to be a frame
niche0 :: Stack ()tr []tr
niche0 = {}z

--  |           |
-- [|]          +
--  |           |

-- this is a niche, but assume to be a frame
niche1 :: Stack ()tr [[]tr]tr
niche1 = {()ar=SubDone; {}z}z

--  |         o   o
-- [|]  --->   \ /
-- [|]          +
--  |           |

-- this is a niche, but assume to be a frame
niche2 :: Stack ()tr [[]tr, []tr]tr
niche2 = {()ar=SubDone; niche1}z

--                |
--  |         o   o
-- [o]  --->   \ /
-- [|]          +
--  |           |

niche10 :: Stack [()tr]tr [[()tr]tr, []tr]tr
niche10 = {()ar=Exclude NodeDone; Niche SubDone}z

-- ################################
-- ############  Frames ###########
-- ################################

--   |              |
--  /|\         o   o
-- |[o]|  --->   \ /
-- |[|]|          o
--  \|/           |
--   |

cyclops :: Stack [()tr]tr [[()tr]tr, []tr]tr
cyclops = Frame niche10

-- Stacking, Valence, Affine subtree, Substitute at an affine position

-- counting Units in a tree

valence :: Tree d ~> Nat
{valence []tr} = 0t
{valence [head; tail]tr} = {plus {valence head} {valence tail}}
{valence ()tr} = 1t

-- counting siblings of a tree

nodeValence :: Tree d ~> Nat
{nodeValence []tr} = 0t
{nodeValence [head; tail]tr} = (1+{nodeValence tail})t

-- counting nodes in a tree

nodes :: Tree d ~> Nat
{nodes ()tr} = t
{nodes []tr} = 1t
{nodes [head; tail]tr} = {plus {nodes head} {nodes tail}}

-- nodeValenceAt: given a (multi)pointer, determine the node valences at those positions
--               WHERE     IN
nodeValenceAt :: Tree d ~> Tree e ~> Nat
{nodeValenceAt ()tr tree} = {nodeValence tree}
{nodeValenceAt []tr []tr} = 0t
{nodeValenceAt [head'; tail']tr [head; tail]tr} = {plus {nodeValenceAt head' head} {nodeValenceAt tail' tail}}

-- a pointer is a valence-1 subtree of a tree
-- it is used to mark a unit in a tree where substitution will occur
--
prop Pointers :: Nat ~> Tree d ~> Tree e ~> * where
  Finger :: Pointers 1t ()tr ()tr
  Finished :: Pointers 0t []tr []tr
  ThisWay :: Pointers 1t head' head -> Pointers n tail' tail -> Pointers (1+n)t [head'; tail']tr [head; tail]tr
  ElseWhere :: Pointers n tail' tail -> Pointers n [[]tr; tail']tr [head; tail]tr

-- http://en.wikipedia.org/wiki/Grafting
--
-- graft WHAT      WHERE     IN
graft :: Tree d ~> Tree e ~> Tree f ~> Tree f
{graft what ()tr ()tr} = what
{graft what []tr tr} = tr
{graft what [head'; tail']tr [head; tail]tr} = [{graft what head' head}; {graft what tail' tail}]tr

extgraft :: Tree what ~> Tree wher ~> Tree tree ~> Tree tree'
{extgraft what ()tr ()tr} = what
{extgraft what []tr ()tr} = ()tr
{extgraft what [head; tail]tr ()tr} = [{extgraft what head ()tr}; {extgraft what tail ()tr}]tr
{extgraft what []tr []tr} = []tr
{extgraft what []tr [head; tail]tr} = [head; tail]tr
{extgraft what [head'; tail']tr [head; tail]tr} = [{extgraft what head' head}; {extgraft what tail' tail}]tr

{- TODO? multiGraft :: Treelist -> where -> in -}

{- NOTE: we have an Omega bug here:

prompt> :norm {graft []tr ()tr ()tr}
Normalizes to:
  []tr

prompt> :kind []tr
[]tr :: Tree Hor  = []tr

prompt> :kind {graft []tr ()tr ()tr}
{graft []tr ()tr ()tr} :: Tree Ver  = {graft []tr ()tr ()tr}

... BUT: Hor /= Ver :-(
-}

-- substitution: replace a pointed node (of valence n) in a tree with an
-- other tree of (valence n) -- TODO

-- HERE IS A NICE RESEARCH QUESTION:
-- is it possible to "proof search" a Zoom?
-- i.e.
{-

class ZoomLike (int :: Tree) (out :: Tree) where
  zoom :: (Nodes int ~ Valence out) => Zoom int out

-}