From 2d64dfd5dad0b98b63ef7d506be15ed74ac679e0 Mon Sep 17 00:00:00 2001 From: Irwin Rodriguez Date: Tue, 26 May 2026 16:12:19 +0200 Subject: [PATCH 1/2] Implements (partial) functions CURSORSETPROP() AND CURSORGETPROP() --- src/Runtime/XSharp.VFP.Tests/CommandTests.prg | 60 +++++ .../XSharp.VFP/Cursors/DbFunctions.prg | 230 ++++++++++++++++-- src/Runtime/XSharp.VFP/ToDo-C.prg | 15 -- 3 files changed, 275 insertions(+), 30 deletions(-) diff --git a/src/Runtime/XSharp.VFP.Tests/CommandTests.prg b/src/Runtime/XSharp.VFP.Tests/CommandTests.prg index edf90877f9..81266e206f 100644 --- a/src/Runtime/XSharp.VFP.Tests/CommandTests.prg +++ b/src/Runtime/XSharp.VFP.Tests/CommandTests.prg @@ -288,6 +288,66 @@ BEGIN NAMESPACE XSharp.VFP.Tests TRY ; System.IO.Directory.Delete(cTempPath, TRUE) ; CATCH ; END TRY END TRY END METHOD + + [Fact]; + METHOD TestCursorSetPropAndCursorGetProp() AS VOID + VAR cOldDir := System.IO.Directory.GetCurrentDirectory() + VAR oDir := System.IO.Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), ; + "CursorPropTest_" + Guid.NewGuid():ToString("N"))) + VAR cTempPath := oDir:FullName + + TRY + SET DEFAULT TO (cTempPath) + CREATE TABLE TmpX (Id INT, Name C(20), Active L) + INSERT INTO TmpX VALUES (1, "Alice", .T.) + GO TOP + + // Default buffering is 1 (off) + Assert.Equal(1, (INT) CursorGetProp("Buffering")) + Assert.Equal(3, (INT) CursorGetProp("SourceType")) + + // Set buffering to optimistic table (5) + Assert.True(CursorSetProp("Buffering", 5)) + Assert.Equal(5, (INT) CursorGetProp("Buffering")) + + // Set buffering to pessimistic row (2) -- by alias + Assert.True(CursorSetProp("Buffering", 2, "TmpX")) + Assert.Equal(2, (INT) CursorGetProp("Buffering")) + + // Set buffering -- by workarea number + Assert.True(CursorSetProp("Buffering", 3, Select())) + Assert.Equal(3, (INT) CursorGetProp("Buffering")) + + // Invalid buffering value -> FALSE + Assert.False(CursorSetProp("Buffering", 0)) + Assert.False(CursorSetProp("Buffering", 6)) + Assert.False(CursorSetProp("Buffering", "abc")) + + // Invalid alias -> FALSE for SET, NIL for GET + Assert.False(CursorSetProp("Buffering", 2, "NoSuchAlias")) + Assert.False(CursorGetProp("Buffering", "NoSuchAlias")) + + // Read-only properties + VAR cSrc := CursorGetProp("SourceName") + Assert.True(IsString(cSrc)) + Assert.True(((STRING) cSrc):Contains(".DBF")) + Assert.Equal("", (STRING) CursorGetProp("Database")) + Assert.Equal("", (STRING) CursorGetProp("SQL")) + Assert.Equal(0, (INT) CursorGetProp("ConnectHandle")) + + // Cargo cleared on close + Assert.True(CursorSetProp("Buffering", 5)) + XSharp.CoreDb.CloseAll() + DbUseArea(TRUE, "DBFVFP", Path.Combine(cTempPath, "TmpX.dbf"), "TmpX", FALSE, FALSE) + Assert.Equal(1, (INT) CursorGetProp("Buffering")) + + FINALLY + XSharp.CoreDb.CloseAll() + SET DEFAULT TO (cOldDir) + System.IO.Directory.SetCurrentDirectory(cOldDir) + TRY ; System.IO.Directory.Delete(cTempPath, TRUE) ; CATCH ; END TRY + END TRY + END METHOD END CLASS END NAMESPACE diff --git a/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg b/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg index ccda527e92..1abc514159 100644 --- a/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg +++ b/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg @@ -7,6 +7,7 @@ USING System USING System.Collections.Generic USING System.Text +USING XSharp.RDD INTERNAL FUNCTION _DoInArea(uArea as Usual, action as @@Func, defaultValue as T, cFunction as STRING, nArg as DWORD) as T IF IsNil(uArea) @@ -354,24 +355,223 @@ INTERNAL FUNCTION _AreaFromParam(uArea AS USUAL) AS DWORD RETURN 0 +INTERNAL CLASS _WorkareaCargo + export fldState AS Dictionary + EXPORT cursorProps AS Dictionary + + CONSTRUCTOR() + fldState := Dictionary{} + cursorProps := Dictionary{System.StringComparer.OrdinalIgnoreCase} + END CONSTRUCTOR +END CLASS + +INTERNAL FUNCTION _GetWorkareaCargo(nArea AS DWORD) AS _WorkareaCargo + VAR oCargo := RuntimeState.Workareas:GetCargo(nArea) + IF oCargo IS _WorkareaCargo VAR cargo + RETURN cargo + ENDIF + VAR newCargo := _WorkareaCargo{} + RuntimeState.Workareas:SetCargo(nArea, newCargo) + RETURN newCargo + INTERNAL FUNCTION _GetFldStateFromCargo(nArea AS DWORD, nField AS INT) AS BYTE - LOCAL cargo AS Dictionary - LOCAL oCargo := RuntimeState.Workareas:GetCargo(nArea) AS OBJECT - IF oCargo IS Dictionary VAR dict - LOCAL b AS BYTE - IF dict:TryGetValue(nField, REF b) - RETURN b - ENDIF + VAR cargo := _GetWorkareaCargo(nArea) + LOCAL b as BYTE + if cargo:fldState:TryGetValue(nField, REF b) + return b ENDIF RETURN 1 INTERNAL FUNCTION _SetFldStateInCargo(nArea AS DWORD, nField AS INT, nState AS BYTE) AS VOID - LOCAL oCargo := RuntimeState.Workareas:GetCargo(nArea) AS OBJECT - LOCAL dict AS Dictionary - IF oCargo IS Dictionary VAR existing - dict := existing - ELSE - dict := Dictionary{} - RuntimeState.Workareas:SetCargo(nArea, dict) + VAR cargo := _GetWorkareaCargo(nArea) + cargo:fldState[nField] := nState + +INTERNAL STATIC CLASS _CursorPropDefaults + INTERNAL STATIC _defaults AS Dictionary + + STATIC CONSTRUCTOR + _defaults := Dictionary{} + _defaults:Add("Buffering", 1) + _defaults:Add("AutoIncError", FALSE) + _defaults:Add("FetchMemo", FALSE) + _defaults:Add("FetchSize", 100) + _defaults:Add("MapBinary", FALSE) + _defaults:Add("MapVarchar", FALSE) + _defaults:Add("MaxRecords", -1) + _defaults:Add("Refresh", -2) + _defaults:Add("CompareMemo", TRUE) + _defaults:Add("FetchAsNeeded", FALSE) + _defaults:Add("Prepared", FALSE) + _defaults:Add("SendUpdates", FALSE) + _defaults:Add("UpdateType", 1) + _defaults:Add("WhereType", 3) + _defaults:Add("UseMemoSize", 255) + _defaults:Add("BatchUpdateCount", 1) + END CONSTRUCTOR + + INTERNAL STATIC METHOD GetDefault(cProperty AS STRING) AS OBJECT + LOCAL result AS OBJECT + IF _defaults:TryGetValue(cProperty, REF result) + return result + ENDIF + RETURN NIL + END METHOD + + INTERNAL STATIC METHOD SetDefault(cProperty AS STRING, oValue AS OBJECT) AS VOID + _defaults[cProperty] := oValue + END METHOD +END CLASS + +INTERNAL FUNCTION _GetCursorProp(nArea AS DWORD, cProperty AS STRING) AS OBJECT + VAR cargo := _GetWorkareaCargo(nArea) + LOCAL result AS OBJECT + if cargo:cursorProps:TryGetValue(cProperty, REF result) + RETURN result + ENDIF + + RETURN _CursorPropDefaults.GetDefault(cProperty) + +INTERNAL FUNCTION _SetCursorProp(nArea AS DWORD, cProperty AS STRING, oValue AS OBJECT) AS VOID + LOCAL cargo AS _WorkareaCargo + cargo := _GetWorkareaCargo(nArea) + cargo:cursorProps[cProperty] := oValue + + +/// +[FoxProFunction("CURSORSETPROP", FoxFunctionCategory.CursorAndTable, FoxEngine.WorkArea, FoxFunctionStatus.Partial, FoxCriticality.High)]; +FUNCTION CursorSetProp(cProperty, eExpression, uArea) AS LOGIC CLIPPER + IF !IsString(cProperty) + RETURN FALSE + ENDIF + LOCAL cProp := (STRING) cProperty AS STRING + LOCAL nProp := GetCursorProperty(cProp) AS LONG + LOCAL lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 AS LOGIC + IF lSessionDefault + IF nProp == (LONG) CursorProperty.Buffering + IF IsNumeric(eExpression) + LOCAL nVal := (INT) eExpression AS INT + IF nVal < 1 .OR. nVal > 5 + RETURN FALSE + ENDIF + ELSE + RETURN FALSE + ENDIF + ENDIF + _CursorPropDefaults.SetDefault(cProp, eExpression) + RETURN TRUE + ENDIF + LOCAL nArea := _AreaFromParam(uArea) AS DWORD + IF nArea == 0 + RETURN FALSE ENDIF - dict[nField] := nState + VAR nOldArea := RuntimeState.CurrentWorkarea + RuntimeState.CurrentWorkarea := nArea + TRY + IF !Used() + RETURN FALSE + ENDIF + IF nProp == (LONG) CursorProperty.Buffering + IF !IsNumeric(eExpression) + RETURN FALSE + ENDIF + LOCAL nBuff := (INT) eExpression AS INT + IF nBuff < 1 .OR. nBuff > 5 + RETURN FALSE + ENDIF + _SetCursorProp(nArea, "Buffering", nBuff) + RETURN TRUE + ENDIF + IF nProp == (LONG) CursorProperty.AutoIncError + IF !IsLogic(eExpression) + RETURN FALSE + ENDIF + _SetCursorProp(nArea, "AutoIncError", eExpression) + RETURN TRUE + ENDIF + IF nProp == (LONG) CursorProperty.Refresh + IF !IsNumeric(eExpression) + RETURN FALSE + ENDIF + _SetCursorProp(nArea, "Refresh", eExpression) + RETURN TRUE + ENDIF + _SetCursorProp(nArea, cProp, eExpression) + RETURN TRUE + FINALLY + RuntimeState.CurrentWorkarea := nOldArea + END TRY + +/// +[FoxProFunction("CURSORGETPROP", FoxFunctionCategory.CursorAndTable, FoxEngine.WorkArea, FoxFunctionStatus.Partial, FoxCriticality.High)]; +FUNCTION CursorGetProp(cProperty, uArea) AS USUAL CLIPPER + IF !IsString(cProperty) + RETURN NIL + ENDIF + LOCAL cProp := (STRING) cProperty AS STRING + LOCAL nProp := GetCursorProperty(cProp) AS LONG + LOCAL lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 AS LOGIC + IF lSessionDefault + RETURN _CursorPropDefaults.GetDefault(cProp) + ENDIF + LOCAL nArea := _AreaFromParam(uArea) AS DWORD + IF nArea == 0 + RETURN FALSE + ENDIF + VAR nOldArea := RuntimeState.CurrentWorkarea + RuntimeState.CurrentWorkarea := nArea + TRY + IF !Used() + RETURN FALSE + ENDIF + IF nProp == (LONG) CursorProperty.SourceType + RETURN 3 + ENDIF + IF nProp == (LONG) CursorProperty.SourceName + RETURN DbInfo(DBI_FULLPATH) + ENDIF + IF nProp == (LONG) CursorProperty.Database + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.SQL + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.ConnectHandle + RETURN 0 + ENDIF + IF nProp == (LONG) CursorProperty.ConnectName + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.Tables + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.KeyFieldList + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.UpdatableFieldList + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.UpdateNameList + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.ParameterList + RETURN "" + ENDIF + IF nProp == (LONG) CursorProperty.RecordsFetched + RETURN -1 + ENDIF + IF nProp == (LONG) CursorProperty.FetchIsComplete + RETURN TRUE + ENDIF + IF nProp == (LONG) CursorProperty.ADOBookmark + RETURN NIL + ENDIF + IF nProp == (LONG) CursorProperty.ADOCodePage + RETURN 0 + ENDIF + IF nProp == (LONG) CursorProperty.ADORecordset + RETURN NIL + ENDIF + RETURN _GetCursorProp(nArea, cProp) + FINALLY + RuntimeState.CurrentWorkarea := nOldArea + END TRY diff --git a/src/Runtime/XSharp.VFP/ToDo-C.prg b/src/Runtime/XSharp.VFP/ToDo-C.prg index c9a6b66a42..836fe5c500 100644 --- a/src/Runtime/XSharp.VFP/ToDo-C.prg +++ b/src/Runtime/XSharp.VFP/ToDo-C.prg @@ -44,21 +44,6 @@ FUNCTION CreateOffline (ViewName , cPath) THROW NotImplementedException{} // RETURN FALSE -/// -- todo -- -/// -[FoxProFunction("CURSORGETPROP", FoxFunctionCategory.CursorAndTable, FoxEngine.WorkArea, FoxFunctionStatus.Stub, FoxCriticality.High)]; -FUNCTION CursorGetProp (cProperty , uArea) - THROW NotImplementedException{} - // RETURN NIL - - -/// -- todo -- -/// -[FoxProFunction("CURSORSETPROP", FoxFunctionCategory.CursorAndTable, FoxEngine.WorkArea, FoxFunctionStatus.Stub, FoxCriticality.High)]; -FUNCTION CursorSetProp (cProperty , eExpression, uArea) - THROW NotImplementedException{} - // RETURN FALSE - /// -- todo -- /// [FoxProFunction("CURSORTOXML", FoxFunctionCategory.General, FoxEngine.RuntimeCore, FoxFunctionStatus.Stub, FoxCriticality.Medium)]; From fedd1f1f9a2fd70056f44f57e50ce46c8be772de Mon Sep 17 00:00:00 2001 From: Irwin Rodriguez Date: Tue, 26 May 2026 19:25:25 +0200 Subject: [PATCH 2/2] Use CursorProperty enum instead of strings in CursorSetPro/CursorGetProp --- .../XSharp.VFP/Cursors/DbFunctions.prg | 157 ++++++++---------- 1 file changed, 73 insertions(+), 84 deletions(-) diff --git a/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg b/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg index 1abc514159..ff17808999 100644 --- a/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg +++ b/src/Runtime/XSharp.VFP/Cursors/DbFunctions.prg @@ -357,11 +357,11 @@ INTERNAL FUNCTION _AreaFromParam(uArea AS USUAL) AS DWORD INTERNAL CLASS _WorkareaCargo export fldState AS Dictionary - EXPORT cursorProps AS Dictionary + EXPORT cursorProps AS Dictionary CONSTRUCTOR() fldState := Dictionary{} - cursorProps := Dictionary{System.StringComparer.OrdinalIgnoreCase} + cursorProps := Dictionary{} END CONSTRUCTOR END CLASS @@ -387,54 +387,54 @@ INTERNAL FUNCTION _SetFldStateInCargo(nArea AS DWORD, nField AS INT, nState AS B cargo:fldState[nField] := nState INTERNAL STATIC CLASS _CursorPropDefaults - INTERNAL STATIC _defaults AS Dictionary + INTERNAL STATIC _defaults AS Dictionary STATIC CONSTRUCTOR - _defaults := Dictionary{} - _defaults:Add("Buffering", 1) - _defaults:Add("AutoIncError", FALSE) - _defaults:Add("FetchMemo", FALSE) - _defaults:Add("FetchSize", 100) - _defaults:Add("MapBinary", FALSE) - _defaults:Add("MapVarchar", FALSE) - _defaults:Add("MaxRecords", -1) - _defaults:Add("Refresh", -2) - _defaults:Add("CompareMemo", TRUE) - _defaults:Add("FetchAsNeeded", FALSE) - _defaults:Add("Prepared", FALSE) - _defaults:Add("SendUpdates", FALSE) - _defaults:Add("UpdateType", 1) - _defaults:Add("WhereType", 3) - _defaults:Add("UseMemoSize", 255) - _defaults:Add("BatchUpdateCount", 1) + _defaults := Dictionary{} + _defaults:Add(CursorProperty.Buffering, 1) + _defaults:Add(CursorProperty.AutoIncError, FALSE) + _defaults:Add(CursorProperty.FetchMemo, FALSE) + _defaults:Add(CursorProperty.FetchSize, 100) + _defaults:Add(CursorProperty.MapBinary, FALSE) + _defaults:Add(CursorProperty.MapVarchar, FALSE) + _defaults:Add(CursorProperty.MaxRecords, -1) + _defaults:Add(CursorProperty.Refresh, -2) + _defaults:Add(CursorProperty.CompareMemo, TRUE) + _defaults:Add(CursorProperty.FetchAsNeeded, FALSE) + _defaults:Add(CursorProperty.Prepared, FALSE) + _defaults:Add(CursorProperty.SendUpdates, FALSE) + _defaults:Add(CursorProperty.UpdateType, 1) + _defaults:Add(CursorProperty.WhereType, 3) + _defaults:Add(CursorProperty.UseMemoSize, 255) + _defaults:Add(CursorProperty.BatchUpdateCount, 1) END CONSTRUCTOR - INTERNAL STATIC METHOD GetDefault(cProperty AS STRING) AS OBJECT + INTERNAL STATIC METHOD GetDefault(prop AS CursorProperty) AS OBJECT LOCAL result AS OBJECT - IF _defaults:TryGetValue(cProperty, REF result) + IF _defaults:TryGetValue(prop, REF result) return result ENDIF RETURN NIL END METHOD - INTERNAL STATIC METHOD SetDefault(cProperty AS STRING, oValue AS OBJECT) AS VOID - _defaults[cProperty] := oValue + INTERNAL STATIC METHOD SetDefault(prop AS CursorProperty, oValue AS OBJECT) AS VOID + _defaults[prop] := oValue END METHOD END CLASS -INTERNAL FUNCTION _GetCursorProp(nArea AS DWORD, cProperty AS STRING) AS OBJECT +INTERNAL FUNCTION _GetCursorProp(nArea AS DWORD, prop AS CursorProperty) AS OBJECT VAR cargo := _GetWorkareaCargo(nArea) LOCAL result AS OBJECT - if cargo:cursorProps:TryGetValue(cProperty, REF result) + if cargo:cursorProps:TryGetValue(prop, REF result) RETURN result ENDIF - RETURN _CursorPropDefaults.GetDefault(cProperty) + RETURN _CursorPropDefaults.GetDefault(prop) -INTERNAL FUNCTION _SetCursorProp(nArea AS DWORD, cProperty AS STRING, oValue AS OBJECT) AS VOID +INTERNAL FUNCTION _SetCursorProp(nArea AS DWORD, prop AS CursorProperty, oValue AS OBJECT) AS VOID LOCAL cargo AS _WorkareaCargo cargo := _GetWorkareaCargo(nArea) - cargo:cursorProps[cProperty] := oValue + cargo:cursorProps[prop] := oValue /// @@ -443,13 +443,14 @@ FUNCTION CursorSetProp(cProperty, eExpression, uArea) AS LOGIC CLIPPER IF !IsString(cProperty) RETURN FALSE ENDIF - LOCAL cProp := (STRING) cProperty AS STRING - LOCAL nProp := GetCursorProperty(cProp) AS LONG - LOCAL lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 AS LOGIC + VAR cProp := (STRING) cProperty + VAR nProp := GetCursorProperty(cProp) + VAR prop := (CursorProperty) nProp + VAR lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 IF lSessionDefault IF nProp == (LONG) CursorProperty.Buffering IF IsNumeric(eExpression) - LOCAL nVal := (INT) eExpression AS INT + VAR nVal := (INT) eExpression IF nVal < 1 .OR. nVal > 5 RETURN FALSE ENDIF @@ -457,10 +458,10 @@ FUNCTION CursorSetProp(cProperty, eExpression, uArea) AS LOGIC CLIPPER RETURN FALSE ENDIF ENDIF - _CursorPropDefaults.SetDefault(cProp, eExpression) + _CursorPropDefaults.SetDefault(prop, eExpression) RETURN TRUE ENDIF - LOCAL nArea := _AreaFromParam(uArea) AS DWORD + VAR nArea := _AreaFromParam(uArea) IF nArea == 0 RETURN FALSE ENDIF @@ -470,7 +471,8 @@ FUNCTION CursorSetProp(cProperty, eExpression, uArea) AS LOGIC CLIPPER IF !Used() RETURN FALSE ENDIF - IF nProp == (LONG) CursorProperty.Buffering + SWITCH prop + CASE CursorProperty.Buffering IF !IsNumeric(eExpression) RETURN FALSE ENDIF @@ -478,25 +480,24 @@ FUNCTION CursorSetProp(cProperty, eExpression, uArea) AS LOGIC CLIPPER IF nBuff < 1 .OR. nBuff > 5 RETURN FALSE ENDIF - _SetCursorProp(nArea, "Buffering", nBuff) + _SetCursorProp(nArea, CursorProperty.Buffering, nBuff) RETURN TRUE - ENDIF - IF nProp == (LONG) CursorProperty.AutoIncError + CASE CursorProperty.AutoIncError IF !IsLogic(eExpression) RETURN FALSE ENDIF - _SetCursorProp(nArea, "AutoIncError", eExpression) + _SetCursorProp(nArea, CursorProperty.AutoIncError, eExpression) RETURN TRUE - ENDIF - IF nProp == (LONG) CursorProperty.Refresh + CASE CursorProperty.Refresh IF !IsNumeric(eExpression) RETURN FALSE ENDIF - _SetCursorProp(nArea, "Refresh", eExpression) + _SetCursorProp(nArea, CursorProperty.Refresh, eExpression) RETURN TRUE - ENDIF - _SetCursorProp(nArea, cProp, eExpression) - RETURN TRUE + OTHERWISE + _SetCursorProp(nArea, prop, eExpression) + RETURN TRUE + END SWITCH FINALLY RuntimeState.CurrentWorkarea := nOldArea END TRY @@ -507,13 +508,14 @@ FUNCTION CursorGetProp(cProperty, uArea) AS USUAL CLIPPER IF !IsString(cProperty) RETURN NIL ENDIF - LOCAL cProp := (STRING) cProperty AS STRING - LOCAL nProp := GetCursorProperty(cProp) AS LONG - LOCAL lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 AS LOGIC + VAR cProp := (STRING) cProperty + VAR nProp := GetCursorProperty(cProp) + VAR prop := (CursorProperty) nProp + VAR lSessionDefault := IsNumeric(uArea) .AND. (INT) uArea == 0 IF lSessionDefault - RETURN _CursorPropDefaults.GetDefault(cProp) + RETURN _CursorPropDefaults.GetDefault(prop) ENDIF - LOCAL nArea := _AreaFromParam(uArea) AS DWORD + VAR nArea := _AreaFromParam(uArea) IF nArea == 0 RETURN FALSE ENDIF @@ -523,55 +525,42 @@ FUNCTION CursorGetProp(cProperty, uArea) AS USUAL CLIPPER IF !Used() RETURN FALSE ENDIF - IF nProp == (LONG) CursorProperty.SourceType + SWITCH prop + CASE CursorProperty.SourceType RETURN 3 - ENDIF - IF nProp == (LONG) CursorProperty.SourceName + CASE CursorProperty.SourceName RETURN DbInfo(DBI_FULLPATH) - ENDIF - IF nProp == (LONG) CursorProperty.Database + CASE CursorProperty.Database RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.SQL + CASE CursorProperty.SQL RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.ConnectHandle + CASE CursorProperty.ConnectHandle RETURN 0 - ENDIF - IF nProp == (LONG) CursorProperty.ConnectName + CASE CursorProperty.ConnectName RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.Tables + CASE CursorProperty.Tables RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.KeyFieldList + CASE CursorProperty.KeyFieldList RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.UpdatableFieldList + CASE CursorProperty.UpdatableFieldList RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.UpdateNameList + CASE CursorProperty.UpdateNameList RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.ParameterList + CASE CursorProperty.ParameterList RETURN "" - ENDIF - IF nProp == (LONG) CursorProperty.RecordsFetched + CASE CursorProperty.RecordsFetched RETURN -1 - ENDIF - IF nProp == (LONG) CursorProperty.FetchIsComplete + CASE CursorProperty.FetchIsComplete RETURN TRUE - ENDIF - IF nProp == (LONG) CursorProperty.ADOBookmark + CASE CursorProperty.ADOBookmark RETURN NIL - ENDIF - IF nProp == (LONG) CursorProperty.ADOCodePage + CASE CursorProperty.ADOCodePage RETURN 0 - ENDIF - IF nProp == (LONG) CursorProperty.ADORecordset + CASE CursorProperty.ADORecordset RETURN NIL - ENDIF - RETURN _GetCursorProp(nArea, cProp) + OTHERWISE + RETURN _GetCursorProp(nArea, prop) + END SWITCH FINALLY RuntimeState.CurrentWorkarea := nOldArea END TRY