PDA

View Full Version : AutoComplete Numeric_Search



gs
2-Jul-2008, 10:56 AM
Hi,

Only recently I finally did implement David Martinko's AutoComplete
feature in a project. Very neat!

For *numeric* fields however the Search procedure appeared to
need a bit of extra work, as indeed the auctor intellectualis
himself noted.

The attached replacement for procedure NUMERIC_SEARCH seems to work,
for me at least.

Things could be further improved, I'm sure.
For instance, currently rows are always displayed in Ascending
order, irrespective of whether the index-segment involved has
an Up- or Down-direction. Amending that would require a different
seeding-loop, I guess.

Greetings,
Gerard.

Struct tNumeric_Search_Value
Number nValue
RowID riRow
End_Struct

// Class cLwDbAutoCompleteForm: replace by your own autocomplete-class
Use cLwDbAutoCompleteForm.pkg

Class cLwDbNumericAutoCompleteForm is a cLwDbAutoCompleteForm

Function FoundValueMatchesEnteredValue Integer iFile Integer iField Integer iCheckLen Number nCheckVal Returns Boolean
Boolean bMatch
Number nValue
Get_Field_Value iFile iField to nValue
Move (Left(nValue, iCheckLen) = nCheckVal) to bMatch
Function_Return bMatch
End_Function

Function NumberCompare tNumeric_Search_Value nsvNumber tNumeric_Search_Value nsvSearchNumber Returns Integer
Integer iRetVal
If (nsvNumber.nValue > nsvSearchNumber.nValue) ;
Function_Return (GT)
If (nsvNumber.nValue < nsvSearchNumber.nValue) ;
Function_Return (LT)
Function_Return (EQ)
End_Function

// Replacement for Procedure NUMERIC_SEARCH of AutoComplete_Mixin.Pkg
// Original procedure fails e.g. with indexes where the entry-field
// does not represent the first segment of the current index.
Procedure Numeric_Search Handle hoObj Handle hoList Number nEnteredValue
Boolean bOK bStop bMatch bNextSeed bIndexIsDescending bSearchFieldIsFirstInIndex
Handle hoServer
Integer i iLen iMaxLen iPrecision
Integer iSeedFactor iMaxSeedRounds
Integer iFindmode_FIRST iFindmode_NEXT iFindCount iMaxTotalFinds iValidCount iMaxListRows
Integer hFile hField iIdx iSegDirection iIdxFirstSeg
Number nValue nCurrentSeed
RowID riFirstOfCurrentRound riFirstOfLastRound

Get Integer_Value of oCol_Server item 0 to hoServer
Get Integer_Value of oCol_File item 0 to hFile
Get Integer_Value of oCol_Field item 0 to hField

Get Ordering of hoServer to iIdx
If (iIdx <=0) ; // No ordering given ==> use main index.
Get File_Field_Index of hoServer hFile hField to iIdx
If (iIdx <=0) ; // use autocomplete_index
Get piList_Index to iIdx

Integer iSegment iIdxSegmentCount iIdxField
Get_Attribute DF_INDEX_NUMBER_SEGMENTS of hFile iIdx to iIdxSegmentCount
For i from 1 to iIdxSegmentCount
Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx i to iIdxField
If (iIdxField = hField) Move i to iSegment
Until (iSegment > 0)

If (not(iSegment)) Begin
// Field is no part of current index. Should never happen.
Procedure_Return
End

Get_Attribute DF_INDEX_SEGMENT_DIRECTION of hFile iIdx iSegment to iSegDirection
If (iSegDirection = DF_DESCENDING) Begin
Move (LE) to iFindmode_FIRST
Move (LT) to iFindmode_NEXT
End
Else Begin
Move (GE) to iFindmode_FIRST
Move (GT) to iFindmode_NEXT
End

Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx 1 to iIdxFirstSeg
Move (iIdxFirstSeg = hField) to bSearchFieldIsFirstInIndex
If (not(bSearchFieldIsFirstInIndex)) Begin
// Define array for intermediate storage of search-results.
tNumeric_Search_Value[] narValues
End

// Maximize total number of finds, to avoid a hang-alike situations.
Move 250 to iMaxTotalFinds

// Maximize display-rows
Get piMax_Finds of hoObj to iMaxListRows
If (iMaxListRows <=0) Begin
Move 99 to iMaxListRows
End

// Get the length of the entry, this will be used to compare all finds
Move (Length(nEnteredValue)) to iLen

Get_Attribute DF_FIELD_LENGTH of hFile hField to iMaxLen
Get_Attribute DF_FIELD_PRECISION of hFile hField to iPrecision
Subtract iPrecision from iMaxLen

// Check whether current field represents the FIRST segment of the current index.
// If not, seeding makes no sense.
If (bSearchFieldIsFirstInIndex) Move (iMaxLen - iLen) to iMaxSeedRounds
Else Move 1 to iMaxSeedRounds

Clear hFile
For iSeedFactor from 0 to (iMaxSeedRounds -1)
Move ((10 ^ iSeedFactor) * nEnteredValue) to nCurrentSeed
If (bSearchFieldIsFirstInIndex) Begin
// If seeding-field is FIRST segment of the index: initialise buffer (indexjump).
// Send FillIndexForFindFirst of hoServer hFile iIdx iFindmode_FIRST // see VDF Help
Set_Field_Value hFile hField to nCurrentSeed
End
Send Request_Read of hoServer iFindmode_FIRST hFile iIdx

// Check RowID: must be different from first of last seeding-round.
Move (GetRowID(hFile)) to riFirstOfCurrentRound
If (not(IsSameRowID(riFirstOfCurrentRound, riFirstOfLastRound))) Begin
Move riFirstOfCurrentRound to riFirstOfLastRound
Repeat
Move (FoundValueMatchesEnteredValue(Self, hFile, hField, iLen, nEnteredValue)) to bMatch
If (bMatch) Begin
Get_Field_Value hFile hField to nValue
If (bSearchFieldIsFirstInIndex) Begin
Send Add_Item of hoList msg_None nValue
// Fill the other columns
Send FillOtherItems hoObj hoList
End
Else Begin
// in case current entry-field is NOT the first segment in the
// index: remember RowID; do sorting & listing AFTERWARDS.
Move nValue to narValues[iValidCount].nValue
Move (GetRowID(hFile)) to narValues[iValidCount].riRow
End
Increment iValidCount
Move (iValidCount >= iMaxListRows) to bStop
End

If (not(bStop)) Begin
Increment iFindCount
Move (iFindCount >= iMaxTotalFinds) to bStop
If (not(bStop)) Begin
If (bSearchFieldIsFirstInIndex) ;
Move (not(bMatch)) to bNextSeed
If (not(bNextSeed)) Begin
Send Request_Read of hoServer iFindmode_NEXT hFile iIdx
Move (not(Found)) to bStop
End
End
End
Until (bStop or bNextSeed)
End
Until (bStop)

If (not(bSearchFieldIsFirstInIndex)) Begin
// Sort array of found values ..
Move (SortArray(narValues, Self, get_NumberCompare)) to narValues
// .. and copy to autocomplete-list.
Integer iArrayCount
Move (SizeOfArray(narValues)) to iArrayCount
For i from 0 to (iArrayCount-1)
Send Add_Item of hoList msg_None narValues[i].nValue
// Refind record
Send Clear of hFile
Move (FindByRowId(hFile, narValues[i].riRow)) to bOK
If (bOK) Begin
// Fill the other columns
Send FillOtherItems hoObj hoList
End
Loop
End

// Check list if we found any matches.
If ((Item_Count(hoList)) > 0) Begin
Handle hoMain
Get phoListParent to hoMain
Send Resize_List of ghoAutocomplete
Send Add_Focus of ghoAutocomplete hoMain
End
Else Send Kill_AutoComplete
// Re-Synchronize the global buffer with the DD.
Send Refind_records of hoServer

End_Procedure // Numeric_Search

Procedure FillOtherItems Handle hoObj Handle hoList
Integer iItem hCol_File hCol_Field
String sValue
For iItem from 1 to (Item_Count(oCol_Server(hoObj)) - 1)
Get Integer_Value of oCol_File item iItem to hCol_File
Get Integer_Value of oCol_Field item iItem to hCol_Field
If (hCol_File) Get_Field_Value hCol_File hCol_Field to sValue
Else If (hCol_Field) Get hCol_Field to sValue
Send Add_Item of hoList msg_None sValue
Loop
End_Procedure

End_Class

gs
3-Jul-2008, 06:27 AM
OK, keeping to my motto 'finish what you start', I decided to swallow
this thing usque ad mala. Attached a version that will keep a descending
listorder where the current index is also descending.

Gerard.

gs schreef:
> Hi,
>
> Only recently I finally did implement David Martinko's AutoComplete
> feature in a project. Very neat!
>
> For *numeric* fields however the Search procedure appeared to
> need a bit of extra work, as indeed the auctor intellectualis
> himself noted.
>
> The attached replacement for procedure NUMERIC_SEARCH seems to work,
> for me at least.
>
> Things could be further improved, I'm sure.
> For instance, currently rows are always displayed in Ascending
> order, irrespective of whether the index-segment involved has
> an Up- or Down-direction. Amending that would require a different
> seeding-loop, I guess.
>
> Greetings,
> Gerard.
>
>
> ------------------------------------------------------------------------
>
> Struct tNumeric_Search_Value
> Number nValue
> RowID riRow
> End_Struct
>
> // Class cLwDbAutoCompleteForm: replace by your own autocomplete-class
> Use cLwDbAutoCompleteForm.pkg
>
> Class cLwDbNumericAutoCompleteForm is a cLwDbAutoCompleteForm
>
> Function FoundValueMatchesEnteredValue Integer iFile Integer iField Integer iCheckLen Number nCheckVal Returns Boolean
> Boolean bMatch
> Number nValue
> Get_Field_Value iFile iField to nValue
> Move (Left(nValue, iCheckLen) = nCheckVal) to bMatch
> Function_Return bMatch
> End_Function
>
> Function NumberCompare tNumeric_Search_Value nsvNumber tNumeric_Search_Value nsvSearchNumber Returns Integer
> Integer iRetVal
> If (nsvNumber.nValue > nsvSearchNumber.nValue) ;
> Function_Return (GT)
> If (nsvNumber.nValue < nsvSearchNumber.nValue) ;
> Function_Return (LT)
> Function_Return (EQ)
> End_Function
>
> // Replacement for Procedure NUMERIC_SEARCH of AutoComplete_Mixin.Pkg
> // Original procedure fails e.g. with indexes where the entry-field
> // does not represent the first segment of the current index.
> Procedure Numeric_Search Handle hoObj Handle hoList Number nEnteredValue
> Boolean bOK bStop bMatch bNextSeed bIndexIsDescending bSearchFieldIsFirstInIndex
> Handle hoServer
> Integer i iLen iMaxLen iPrecision
> Integer iSeedFactor iMaxSeedRounds
> Integer iFindmode_FIRST iFindmode_NEXT iFindCount iMaxTotalFinds iValidCount iMaxListRows
> Integer hFile hField iIdx iSegDirection iIdxFirstSeg
> Number nValue nCurrentSeed
> RowID riFirstOfCurrentRound riFirstOfLastRound
>
> Get Integer_Value of oCol_Server item 0 to hoServer
> Get Integer_Value of oCol_File item 0 to hFile
> Get Integer_Value of oCol_Field item 0 to hField
>
> Get Ordering of hoServer to iIdx
> If (iIdx <=0) ; // No ordering given ==> use main index.
> Get File_Field_Index of hoServer hFile hField to iIdx
> If (iIdx <=0) ; // use autocomplete_index
> Get piList_Index to iIdx
>
> Integer iSegment iIdxSegmentCount iIdxField
> Get_Attribute DF_INDEX_NUMBER_SEGMENTS of hFile iIdx to iIdxSegmentCount
> For i from 1 to iIdxSegmentCount
> Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx i to iIdxField
> If (iIdxField = hField) Move i to iSegment
> Until (iSegment > 0)
>
> If (not(iSegment)) Begin
> // Field is no part of current index. Should never happen.
> Procedure_Return
> End
>
> Get_Attribute DF_INDEX_SEGMENT_DIRECTION of hFile iIdx iSegment to iSegDirection
> If (iSegDirection = DF_DESCENDING) Begin
> Move (LE) to iFindmode_FIRST
> Move (LT) to iFindmode_NEXT
> End
> Else Begin
> Move (GE) to iFindmode_FIRST
> Move (GT) to iFindmode_NEXT
> End
>
> Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx 1 to iIdxFirstSeg
> Move (iIdxFirstSeg = hField) to bSearchFieldIsFirstInIndex
> If (not(bSearchFieldIsFirstInIndex)) Begin
> // Define array for intermediate storage of search-results.
> tNumeric_Search_Value[] narValues
> End
>
> // Maximize total number of finds, to avoid a hang-alike situations.
> Move 250 to iMaxTotalFinds
>
> // Maximize display-rows
> Get piMax_Finds of hoObj to iMaxListRows
> If (iMaxListRows <=0) Begin
> Move 99 to iMaxListRows
> End
>
> // Get the length of the entry, this will be used to compare all finds
> Move (Length(nEnteredValue)) to iLen
>
> Get_Attribute DF_FIELD_LENGTH of hFile hField to iMaxLen
> Get_Attribute DF_FIELD_PRECISION of hFile hField to iPrecision
> Subtract iPrecision from iMaxLen
>
> // Check whether current field represents the FIRST segment of the current index.
> // If not, seeding makes no sense.
> If (bSearchFieldIsFirstInIndex) Move (iMaxLen - iLen) to iMaxSeedRounds
> Else Move 1 to iMaxSeedRounds
>
> Clear hFile
> For iSeedFactor from 0 to (iMaxSeedRounds -1)
> Move ((10 ^ iSeedFactor) * nEnteredValue) to nCurrentSeed
> If (bSearchFieldIsFirstInIndex) Begin
> // If seeding-field is FIRST segment of the index: initialise buffer (indexjump).
> // Send FillIndexForFindFirst of hoServer hFile iIdx iFindmode_FIRST // see VDF Help
> Set_Field_Value hFile hField to nCurrentSeed
> End
> Send Request_Read of hoServer iFindmode_FIRST hFile iIdx
>
> // Check RowID: must be different from first of last seeding-round.
> Move (GetRowID(hFile)) to riFirstOfCurrentRound
> If (not(IsSameRowID(riFirstOfCurrentRound, riFirstOfLastRound))) Begin
> Move riFirstOfCurrentRound to riFirstOfLastRound
> Repeat
> Move (FoundValueMatchesEnteredValue(Self, hFile, hField, iLen, nEnteredValue)) to bMatch
> If (bMatch) Begin
> Get_Field_Value hFile hField to nValue
> If (bSearchFieldIsFirstInIndex) Begin
> Send Add_Item of hoList msg_None nValue
> // Fill the other columns
> Send FillOtherItems hoObj hoList
> End
> Else Begin
> // in case current entry-field is NOT the first segment in the
> // index: remember RowID; do sorting & listing AFTERWARDS.
> Move nValue to narValues[iValidCount].nValue
> Move (GetRowID(hFile)) to narValues[iValidCount].riRow
> End
> Increment iValidCount
> Move (iValidCount >= iMaxListRows) to bStop
> End
>
> If (not(bStop)) Begin
> Increment iFindCount
> Move (iFindCount >= iMaxTotalFinds) to bStop
> If (not(bStop)) Begin
> If (bSearchFieldIsFirstInIndex) ;
> Move (not(bMatch)) to bNextSeed
> If (not(bNextSeed)) Begin
> Send Request_Read of hoServer iFindmode_NEXT hFile iIdx
> Move (not(Found)) to bStop
> End
> End
> End
> Until (bStop or bNextSeed)
> End
> Until (bStop)
>
> If (not(bSearchFieldIsFirstInIndex)) Begin
> // Sort array of found values ..
> Move (SortArray(narValues, Self, get_NumberCompare)) to narValues
> // .. and copy to autocomplete-list.
> Integer iArrayCount
> Move (SizeOfArray(narValues)) to iArrayCount
> For i from 0 to (iArrayCount-1)
> Send Add_Item of hoList msg_None narValues[i].nValue
> // Refind record
> Send Clear of hFile
> Move (FindByRowId(hFile, narValues[i].riRow)) to bOK
> If (bOK) Begin
> // Fill the other columns
> Send FillOtherItems hoObj hoList
> End
> Loop
> End
>
> // Check list if we found any matches.
> If ((Item_Count(hoList)) > 0) Begin
> Handle hoMain
> Get phoListParent to hoMain
> Send Resize_List of ghoAutocomplete
> Send Add_Focus of ghoAutocomplete hoMain
> End
> Else Send Kill_AutoComplete
> // Re-Synchronize the global buffer with the DD.
> Send Refind_records of hoServer
>
> End_Procedure // Numeric_Search
>
> Procedure FillOtherItems Handle hoObj Handle hoList
> Integer iItem hCol_File hCol_Field
> String sValue
> For iItem from 1 to (Item_Count(oCol_Server(hoObj)) - 1)
> Get Integer_Value of oCol_File item iItem to hCol_File
> Get Integer_Value of oCol_Field item iItem to hCol_Field
> If (hCol_File) Get_Field_Value hCol_File hCol_Field to sValue
> Else If (hCol_Field) Get hCol_Field to sValue
> Send Add_Item of hoList msg_None sValue
> Loop
> End_Procedure
>
> End_Class


Struct tNumeric_Search_Value
Number nValue
RowID riRow
End_Struct

// Class cLwDbAutoCompleteForm: replace by your own autocomplete-class
Use cLwDbAutoCompleteForm.pkg

Class cLwDbNumericAutoCompleteForm is a cLwDbAutoCompleteForm

Procedure Construct_Object
Forward Send Construct_Object

{DesignTime=false}
Property Boolean pbIdxSegIsDesc False

// With pbKeepDirection=TRUE a DESC index-segment will result in a DESC
// sorting order in the AutoComplete list (i.e. same ordering as in
// the standard promptlist).
Property Boolean pbKeepDirection True
End_Procedure

// Replacement for Procedure NUMERIC_SEARCH of AutoComplete_Mixin.Pkg
// Original procedure fails e.g. with indexes where the entry-field
// does not represent the first segment of the current index.
Register_Function NumberCompare tNumeric_Search_Value nsvNumber tNumeric_Search_Value nsvSearchNumber Returns Integer
Procedure Numeric_Search Handle hoObj Handle hoList Number nEnteredValue
Boolean bOK bStop bMatch bNextSeed bIndexIsDescending bSearchFieldIsFirstInIndex
Handle hoServer
Integer i iLen iMaxLen iPrecision
Integer iSeedFactor iMaxSeedRounds
Integer iFindmode_FIRST iFindmode_NEXT iFindCount iMaxTotalFinds iValidCount iMaxListRows
Integer hFile hField iIdx iSegDirection iIdxFirstSeg
Number nValue nCurrentSeed
RowID riFirstOfCurrentRound riFirstOfLastRound

Get Integer_Value of oCol_Server item 0 to hoServer
Get Integer_Value of oCol_File item 0 to hFile
Get Integer_Value of oCol_Field item 0 to hField

Get Ordering of hoServer to iIdx
If (iIdx <=0) ; // No ordering given ==> use main index.
Get File_Field_Index of hoServer hFile hField to iIdx
If (iIdx <=0) ; // use autocomplete_index
Get piList_Index to iIdx

Integer iSegment iIdxSegmentCount iIdxField
Get_Attribute DF_INDEX_NUMBER_SEGMENTS of hFile iIdx to iIdxSegmentCount
For i from 1 to iIdxSegmentCount
Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx i to iIdxField
If (iIdxField = hField) Move i to iSegment
Until (iSegment > 0)

If (not(iSegment)) Begin
// Field is no part of current index. Should never happen.
Procedure_Return
End

Get_Attribute DF_INDEX_SEGMENT_DIRECTION of hFile iIdx iSegment to iSegDirection
Set pbIdxSegIsDesc to (iSegDirection = DF_DESCENDING)

If ( (pbIdxSegIsDesc(Self)) and (not(pbKeepDirection(Self))) ) Begin
Move (LE) to iFindmode_FIRST
Move (LT) to iFindmode_NEXT
End
Else Begin
Move (GE) to iFindmode_FIRST
Move (GT) to iFindmode_NEXT
End

Get_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIdx 1 to iIdxFirstSeg
Move (iIdxFirstSeg = hField) to bSearchFieldIsFirstInIndex
If (not(bSearchFieldIsFirstInIndex)) Begin
// Define array for intermediate storage of search-results.
tNumeric_Search_Value[] narValues
End

// Maximize total number of finds, to avoid a hang-alike situations.
Move 250 to iMaxTotalFinds

// Maximize display-rows
Get piMax_Finds of hoObj to iMaxListRows
If (iMaxListRows <=0) Begin
Move 99 to iMaxListRows
End

// Get the length of the entry, this will be used to compare all finds
Move (Length(nEnteredValue)) to iLen

Get_Attribute DF_FIELD_LENGTH of hFile hField to iMaxLen
Get_Attribute DF_FIELD_PRECISION of hFile hField to iPrecision
Subtract iPrecision from iMaxLen

// Check whether current field represents the FIRST segment of the current index.
// If not, seeding makes no sense.
If (bSearchFieldIsFirstInIndex) Move (iMaxLen - iLen) to iMaxSeedRounds
Else Move 1 to iMaxSeedRounds

Clear hFile
For iSeedFactor from 0 to (iMaxSeedRounds -1)
Send FillIndexForFindFirst of hoServer hFile iIdx iFindmode_FIRST // see VDF Help
If (bSearchFieldIsFirstInIndex) Begin
// If seeding-field is FIRST segment of the index (&only then): initialise buffer (indexjump).
If (pbIdxSegIsDesc(Self) and pbKeepDirection(Self)) ;
Move (( (10^(iMaxLen - iLen - 1 - iSeedFactor)) * (nEnteredValue + 1)) -1) to nCurrentSeed
Else ;
Move ( (10^ iSeedFactor) * nEnteredValue ) to nCurrentSeed
Set_Field_Value hFile hField to nCurrentSeed
End
Send Request_Read of hoServer iFindmode_FIRST hFile iIdx

// Check RowID: must be different from first of last seeding-round.
Move (GetRowID(hFile)) to riFirstOfCurrentRound
If (not(IsSameRowID(riFirstOfCurrentRound, riFirstOfLastRound))) Begin
Move riFirstOfCurrentRound to riFirstOfLastRound
Repeat
Get_Field_Value hFile hField to nValue
Move (Left(nValue, iLen) = nEnteredValue) to bMatch

If (bMatch) Begin
// Get_Field_Value hFile hField to nValue
If (bSearchFieldIsFirstInIndex) Begin
Send Add_Item of hoList msg_None nValue
Send FillOtherListCols hoObj hoList
End
Else Begin
// in case current entry-field is NOT the first segment in the
// index: remember RowID; do sorting & listing AFTERWARDS.
Move nValue to narValues[iValidCount].nValue
Move (GetRowID(hFile)) to narValues[iValidCount].riRow
End
Increment iValidCount
Move (iValidCount >= iMaxListRows) to bStop
End

If (not(bStop)) Begin
Increment iFindCount
Move (iFindCount >= iMaxTotalFinds) to bStop
If (not(bStop)) Begin
If (bSearchFieldIsFirstInIndex) ;
Move (not(bMatch)) to bNextSeed
If (not(bNextSeed)) Begin
Send Request_Read of hoServer iFindmode_NEXT hFile iIdx
Move (not(Found)) to bNextSeed
End
End
End
Until (bStop or bNextSeed)
End
Until (bStop)

If (not(bSearchFieldIsFirstInIndex)) Begin
// Sort array of found values ..
Move (SortArray(narValues, Self, get_NumberCompare)) to narValues
// .. and copy to autocomplete-list.
Integer iArrayCount
Move (SizeOfArray(narValues)) to iArrayCount
For i from 0 to (iArrayCount-1)
Send Add_Item of hoList msg_None narValues[i].nValue
// Refind record
Send Clear of hFile
Move (FindByRowId(hFile, narValues[i].riRow)) to bOK
If (bOK) ;
Send FillOtherListCols hoObj hoList
Loop
End

// Check list if we found any matches.
If ((Item_Count(hoList)) > 0) Begin
Handle hoMain
Get phoListParent to hoMain
Send Resize_List of ghoAutocomplete
Send Add_Focus of ghoAutocomplete hoMain
End
Else Send Kill_AutoComplete
// Re-Synchronize the global buffer with the DD.
Send Refind_records of hoServer

End_Procedure // Numeric_Search

Procedure FillOtherListCols Handle hoObj Handle hoList
Integer iItem hCol_File hCol_Field
String sValue
For iItem from 1 to (Item_Count(oCol_Server(hoObj)) - 1)
Get Integer_Value of oCol_File item iItem to hCol_File
Get Integer_Value of oCol_Field item iItem to hCol_Field
If (hCol_File) Get_Field_Value hCol_File hCol_Field to sValue
Else If (hCol_Field) Get hCol_Field to sValue
Send Add_Item of hoList msg_None sValue
Loop
End_Procedure

Function NumberCompare tNumeric_Search_Value nsvNumber tNumeric_Search_Value nsvSearchNumber Returns Integer
Integer iRetVal

Boolean bIdxSegIsDesc bKeepDirection bInvert
Get pbIdxSegIsDesc to bIdxSegIsDesc
Get pbKeepDirection to bKeepDirection
Move (bIdxSegIsDesc and bKeepDirection) to bInvert

If (nsvNumber.nValue > nsvSearchNumber.nValue) ;
Function_Return (If(bInvert, (LT),(GT)))
If (nsvNumber.nValue < nsvSearchNumber.nValue) ;
Function_Return (If(bInvert, (GT),(LT)))
Function_Return (EQ)
End_Function

End_Class