hsx

  Previous topic Next topic JavaScript is required for the print function Mail us feedback on this topic! Mail us feedback on this topic!  
c:\harbour\source\rdd\hsx
cftsfunc.c
TypeFunctionSourceLine
HB_FUNCCFTSADD(void)
HB_FUNC( CFTSADD )
{
   HB_FUNC_EXEC( HS_ADD );
}
cftsfunc.c76
HB_FUNCCFTSCLOSE(void)
HB_FUNC( CFTSCLOSE )
{
   HB_FUNC_EXEC( HS_CLOSE );
}
cftsfunc.c81
HB_FUNCCFTSCREA(void)
HB_FUNC( CFTSCREA )
{
   HB_FUNC_EXEC( HS_CREATE );
}
cftsfunc.c86
HB_FUNCCFTSDELETE(void)
HB_FUNC( CFTSDELETE )
{
   HB_FUNC_EXEC( HS_DELETE );
}
cftsfunc.c91
HB_FUNCCFTSIFDEL(void)
HB_FUNC( CFTSIFDEL )
{
   HB_FUNC_EXEC( HS_IFDEL );
}
cftsfunc.c96
HB_FUNCCFTSNEXT(void)
HB_FUNC( CFTSNEXT )
{
   HB_FUNC_EXEC( HS_NEXT );
}
cftsfunc.c101
HB_FUNCCFTSOPEN(void)
HB_FUNC( CFTSOPEN )
{
   HB_FUNC_EXEC( HS_OPEN );
}
cftsfunc.c106
HB_FUNCCFTSRECN(void)
HB_FUNC( CFTSRECN )
{
   HB_FUNC_EXEC( HS_KEYCOUNT );
}
cftsfunc.c111
HB_FUNCCFTSREPLAC(void)
HB_FUNC( CFTSREPLAC )
{
   HB_FUNC_EXEC( HS_REPLACE );
}
cftsfunc.c116
HB_FUNCCFTSSET(void)
HB_FUNC( CFTSSET )
{
   HB_FUNC_EXEC( HS_SET );
}
cftsfunc.c121
HB_FUNCCFTSUNDEL(void)
HB_FUNC( CFTSUNDEL )
{
   HB_FUNC_EXEC( HS_UNDELETE );
}
cftsfunc.c126
HB_FUNCCFTSVERI(void)
HB_FUNC( CFTSVERI )
{
   HB_FUNC_EXEC( HS_VERIFY );
}
cftsfunc.c131
HB_FUNCCFTSVERS(void)
HB_FUNC( CFTSVERS )
{
   HB_FUNC_EXEC( HS_VERSION );
}
cftsfunc.c136
hsx.c
TypeFunctionSourceLine
STATIC VOIDhb_hsxTableRelease( void * Cargo )
static void hb_hsxTableRelease( void * Cargo )
{
   LPHSXTABLE pTable = ( LPHSXTABLE ) Cargo;
   int iHandle;

   for( iHandle = 0; iHandle < pTable->iHandleSize; ++iHandle )
   {
      if( pTable->handleArray[ iHandle ] )
         hb_hsxDestroy( iHandle );
   }
}

static HB_TSD_NEW( s_hsxTable, sizeof( HSXTABLE ), NULL, hb_hsxTableRelease );
hsx.c354
STATIC LPHSXTABLEhb_hsxTable( void )
static LPHSXTABLE hb_hsxTable( void )
{
   return ( LPHSXTABLE ) hb_stackGetTSD( &s_hsxTable );
}

/* the conversion table for ASCII alpha pairs */
static const BYTE hb_hsxHashArray[] = {
/*        A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   W   V   X   Y   Z */
/* A */   7,102,222,185, 19, 48,167,  4,173,  4, 79,251,194,250,  7,187,  7,251,209,249, 41,101, 39, 29, 71, 40,
/* B */ 156,  3,  7,  7,149,  7,  7,  7,172,  7,  7,100,  7,  7,148,  7,  7,107, 38,  7,126,  7,  7,  7,  7,  7,
/* C */ 234,  7, 38,  7,229,  7,  7,208,145,  7,116,106,  7,  7,253,  7,  7,166, 40,237,129,  7,  7,  7, 63,  4,
/* D */ 125,  4,  4, 29,253,  7, 28,  7,226,  7,  7,  3,  3,  4,128,  7,  7,124, 44,  4,115,  7,  4,  7, 37,  7,
/* E */ 193, 37,236,198,114, 94,105,  3, 44,  7,  4,245,159,251, 93,151, 36,248,253,252, 36, 70, 28,147, 19,  4,
/* F */  92,  7,  7,  7,123, 78,  7,  7,180,  7,  7,150,  7,  7,122,  7,  7,104,  4, 35, 55,  7,  7,  7,  7,  7,
/* G */ 121,  7,  7,  7,195,  7,  2, 86, 77,  7,  7, 85,  2, 76, 55,  7,  7,179, 27,  4, 54,  7,  7,  7, 63,  7,
/* H */ 197,  7,  7,  7,228,  7,  7,  7,164,  7,  7, 18,  4,  1,220,  7,  7, 99,  7, 62, 35,  7,  7,  7,169,  7,
/* I */ 192, 98,250,207,155,143,158,  1,  7,  7,  1,212,163,248,250, 97,  7,178,225,252,142,120,  7,  4,  7, 84,
/* J */   4,  7,  7,  7, 34,  7,  7,  6,  6,  6,  6,  6,  6,  6, 15,  6,  6,  6,  6,  6, 34,  6,  6,  6,  6,  6,
/* K */  15,  6,  6,  6,135,  6,  6,  6, 69,  6,  6,  4,  6, 14, 14,  6,  6,  6, 14,  6,  6,  6,  6,  6, 27,  6,
/* L */ 253,  4, 13, 62,251, 18,  4,  6,255,  6, 26,213, 17,  6,238, 13,  6,  6, 83,162,154, 12,  6,  6,134,  6,
/* M */ 216, 54,  6,  6,254,  6,  6,  6,231,  6,  6,  6, 68, 12,223,140,  6,  6,  4,  6,146,  6,  6,  6,  4,  6,
/* N */ 230,  6,204,202,252, 53,246,  6,227,  4, 53,  4,  4, 43,205,  4,  6, 11,201,251, 75, 52, 11,  6, 33,  4,
/* O */  74, 96,161,171, 33, 73,168, 17,133,  4, 10,243,244,248, 82,219,  6,250,210,215,191, 52,119, 51, 32,  4,
/* P */ 186,  6,  6,  6,232,  6,  6,224,160,  6,  6,190,  6,  6,217, 26,  6,189, 32, 90, 67,  6,  6,  6, 51,  6,
/* Q */   6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,111,  6,  6,  6,  6,  6,  6,
/* R */ 249, 89,117,113,250, 47,110, 47,252,  6, 46, 25,199,112,249,109,  6,139,183,144,138, 50, 10,  6,153,  6,
/* S */  81,  6,175,  5,218,  9,  5,170,247,  5, 43, 66, 50, 16,206,177,  4,  5,176,252,182,  5,  9,  5, 61,  5,
/* T */ 242,  5, 16,  4,249,  5,  5,221,248,  5,  5, 25,  8,  5,241,  5,  5,250, 49,132,152,  5,  4,  5,181,  4,
/* U */  80, 95, 88, 61, 60,  8, 46,  5, 60,  5,  5,214,196,184, 45,131,  5,203,188,174,  5,  5,  5,  4,  5,  5,
/* V */ 137,  5,  5,  5,200,  5,  5,  5,130,  5,  5,  5,  5,  5, 49,  5,  5,  5,  5,  5,  4,  5,  5,  5,  5,  5,
/* W */ 136,  5,  5,  5, 65,  5,  5, 31, 59,  5,  4,  4,  5, 23, 58,  5,  5,  4,  4,  5,  5,  5,  5,  5,  5,  5,
/* X */   4,  5, 23,  5, 31,  5,  5,  5, 24,  5,  5,  5,  5,  5, 22, 22,  5,  5,  5, 45,  5,  5,  5,  5, 30,  5,
/* Y */  30, 21, 42, 72, 21,  5,  4,  5,  4,  4,  4,127, 20,103, 20, 87,  4, 64,108,  4,  4,  4,  4,  4,  4,  4,
/* Z */  42,  4,  4,  4, 56,  4,  4,  4, 24,  4,  4,  4,  4,  4, 41,  4,  4,  4,  4,  4,  4,  4,  4,  4,  3,  4 };
hsx.c368
STATIC INThb_hsxHashVal( int c1, int c2, int iKeyBits, BOOL fNoCase, int iFilter, BOOL fUseHash )
static int hb_hsxHashVal( int c1, int c2, int iKeyBits,
                          BOOL fNoCase, int iFilter, BOOL fUseHash )
{
   int iBitNum;

   if( fNoCase )
   {
#ifndef HB_CDP_SUPPORT_OFF
      PHB_CODEPAGE cdp;
      if( iFilter == 3 && ( cdp = hb_vmCDP() )->nChars )
      {
         c1 = ( BYTE ) cdp->s_upper[ c1 ];
         c2 = ( BYTE ) cdp->s_upper[ c2 ];
      }
      else
#endif
      {
         if( c1 >= 'a' && c1 <= 'z' )
            c1 -= 'a' - 'A';
         if( c2 >= 'a' && c2 <= 'z' )
            c2 -= 'a' - 'A';
      }
   }
   if( iFilter == 1 )
   {
      c1 &= 0x7F;
      if( c1 < 0x20 || c1 == 0x7f ) c1 = ' ';
      c2 &= 0x7F;
      if( c2 < 0x20 || c2 == 0x7f ) c2 = ' ';
   }

   if( c1 == ' ' || c2 == ' ' || c1 == 0 || c2 == 0 )
      iBitNum = 0;
   else if( fUseHash && c1 >= 'A' && c1 <= 'Z' && c2 >= 'A' && c2 <= 'Z' )
   {
      iBitNum = hb_hsxHashArray[ ( c1 - 'A' ) * 26 + ( c2 - 'A' ) ] + 1;
   }
   else
   {
      iBitNum = ( c1 + c2 * 78 ) % ( iKeyBits - 1 ) + 1;
      if( iBitNum == 1 )
         iBitNum++;
   }
   return iBitNum;
}
hsx.c403
STATIC VOIDhb_hsxHashStr( BYTE * pStr, ULONG ulLen, BYTE * pKey, int iKeySize, BOOL fNoCase, int iFilter, BOOL fUseHash )
static void hb_hsxHashStr( BYTE * pStr, ULONG ulLen, BYTE * pKey, int iKeySize,
                           BOOL fNoCase, int iFilter, BOOL fUseHash )
{
   int c1, c2, iBitNum, iKeyBits = iKeySize << 3;

   memset( pKey, '\0', iKeySize );
#if 0
/* This code keeps the strict CFTS behavior which stops string
   manipulating at first chr(0) character */
   if( pStr && ulLen-- && ( c1 = *pStr++ ) != 0 )
   {
      while( ulLen-- && ( c2 = *pStr++ ) != 0 )
      {
#else 
   /* This version can work well with embedded 0 characters */
   if( pStr && ulLen-- )
   {
      c1 = *pStr++;
      while( ulLen-- )
      {
         c2 = *pStr++;
#endif
         iBitNum = hb_hsxHashVal( c1, c2, iKeyBits, fNoCase, iFilter, fUseHash );
         if( iBitNum-- )
         {
            pKey[ iBitNum >> 3 ] |= 0x80 >> ( iBitNum & 7 );
         }
         c1 = c2;
      }
   }
}

static int hb_hsxStrCmp( BYTE * pSub, ULONG ulSub, BYTE * pStr, ULONG ulLen,
                         BOOL fNoCase, int iFilter )
{
   BOOL fResult = FALSE;
   BYTE c1, c2;
   ULONG ul;

   if( ulSub == 0 )
      return HSX_SUCCESSFALSE;

   while( !fResult && ulLen >= ulSub )
   {
      fResult = TRUE;
      for( ul = 0; fResult && ul < ulSub; ul++ )
      {
         c1 = pSub[ ul ];
         c2 = pStr[ ul ];
         if( fNoCase )
         {
#ifndef HB_CDP_SUPPORT_OFF
            PHB_CODEPAGE cdp;
            if( iFilter == 3 && ( cdp = hb_vmCDP() )->nChars )
            {
               c1 = ( BYTE ) cdp->s_upper[ c1 ];
               c2 = ( BYTE ) cdp->s_upper[ c2 ];
            }
            else
#endif
            {
               if( c1 >= 'a' && c1 <= 'z' )
                  c1 -= 'a' - 'A';
               if( c2 >= 'a' && c2 <= 'z' )
                  c2 -= 'a' - 'A';
            }
         }
#if 0
/* This code is for strict CftsVeri() behavior - uncomment if necessary
   but it's IMHO bug */
         if( iFilter == 1 )
         {
            c1 &= 0x7F;
            if( c1 < 0x20 || c1 == 0x7f ) c1 = ' ';
            c2 &= 0x7F;
            if( c2 < 0x20 || c2 == 0x7f ) c2 = ' ';
         }
#elif defined( HB_CDP_SUPPORT_OFF )
         HB_SYMBOL_UNUSED( iFilter );
#endif
         fResult = ( c1 == c2 );
      }
      --ulLen;
      ++pStr;
   }

   return fResult ? HSX_SUCCESS : HSX_SUCCESSFALSE;
}

static LPHSXINFO hb_hsxGetPointer( int iHandle )
{
   LPHSXTABLE pTable = hb_hsxTable();

   return ( iHandle >=0 && iHandle < pTable->iHandleSize ) ?
          pTable->handleArray[ iHandle ] : NULL;
}

static int hb_hsxCompile( char * szExpr, PHB_ITEM * pExpr )
{
   AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();

   *pExpr = NULL;
   if( pArea )
   {
      if( SELF_COMPILE( pArea, ( BYTE * ) szExpr ) == FAILURE )
         return HSX_BADPARMS;
      *pExpr = pArea->valResult;
      pArea->valResult = NULL;
   }
   else
   {
      HB_MACRO_PTR pMacro = hb_macroCompile( szExpr );
      if( !pMacro )
         return HSX_BADPARMS;
      *pExpr = hb_itemPutPtr( NULL, ( void * ) pMacro );
   }
   return HSX_SUCCESS;
}

static int hb_hsxEval( int iHandle, PHB_ITEM pExpr, BYTE *pKey, BOOL *fDeleted )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iResult = HSX_SUCCESS;
   BYTE * pStr;
   ULONG ulLen;

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( !pExpr )
      pExpr = pHSX->pKeyItem;

   if( !pExpr )
      return HSX_BADPARMS;

   if( hb_itemType( pExpr ) & HB_IT_STRING )
   {
      pStr = ( BYTE * ) hb_itemGetCPtr( pExpr );
      ulLen = hb_itemGetCLen( pExpr );
      if( fDeleted )
         *fDeleted = FALSE;
   }
   else
   {
      int iArea = 0;
      PHB_ITEM pItem;

      if( pHSX->iArea != 0 )
      {
         iArea = hb_rddGetCurrentWorkAreaNumber();
         if( iArea != pHSX->iArea )
            hb_rddSelectWorkAreaNumber( pHSX->iArea );
         else
            iArea = 0;
      }
      pItem = hb_vmEvalBlockOrMacro( pExpr );
      pStr = ( BYTE * ) hb_itemGetCPtr( pItem );
      ulLen = hb_itemGetCLen( pItem );
      if( fDeleted )
      {
         AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
         if( !pArea )
            *fDeleted = FALSE;
         else if( SELF_DELETED( pArea, fDeleted ) == FAILURE )
            iResult = HSX_RDDFAILURE;
      }
      if( iArea )
         hb_rddSelectWorkAreaNumber( iArea );
      if( hb_vmRequestQuery() )
         iResult = HSX_BADPARMS;
   }

   if( iResult == HSX_SUCCESS )
      hb_hsxHashStr( pStr, ulLen, pKey, pHSX->uiRecordSize, pHSX->fIgnoreCase,
                     pHSX->iFilterType, pHSX->fUseHash );

   return iResult;
}

static void hb_hsxGetRecCount( LPHSXINFO pHSX )
{
   pHSX->ulRecCount = ( ULONG ) ( ( hb_fileSize( pHSX->pFile ) - 
                                    HSXHEADER_LEN ) / pHSX->uiRecordSize );
}

static int hb_hsxHdrFlush( int iHandle )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( pHSX->fHdrChanged )
   {
      BYTE headrBuf[ HSXHEADER_LEN ];
      LPHSXHEADER pHeader = ( LPHSXHEADER ) headrBuf;
      USHORT uiBits = 0, uiSize = pHSX->uiRecordSize;

      while( uiSize >>= 1 )
         uiBits++;

      HB_PUT_LE_UINT32( pHeader->recCount,    pHSX->ulRecCount );
      HB_PUT_LE_UINT32( pHeader->recSize,     ( UINT32 ) pHSX->uiRecordSize );
      HB_PUT_LE_UINT32( pHeader->recSizeBits, ( UINT32 ) uiBits );
      HB_PUT_LE_UINT16( pHeader->ignoreCase,  pHSX->fIgnoreCase ? 1 : 0 );
      HB_PUT_LE_UINT16( pHeader->filterType,  pHSX->iFilterType );
      HB_PUT_LE_UINT32( pHeader->hashLetters, pHSX->fUseHash ? 1 : 0 );

      memset( pHeader->keyExpression, 0, HSXKEYEXP_LEN + 1 );
      if( pHSX->szKeyExpr )
         hb_strncpy( ( char * ) pHeader->keyExpression, pHSX->szKeyExpr, HSXKEYEXP_LEN );

      if( hb_fileWriteAt( pHSX->pFile, headrBuf, HSXHEADER_LEN, 0 ) != HSXHEADER_LEN )
         return HSX_BADHDRWRITE;

      pHSX->fHdrChanged = FALSE;
      pHSX->fFlush = TRUE;
   }
   return HSX_SUCCESS;
}

static int hb_hsxFlush( int iHandle )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( pHSX->fChanged )
   {
      HB_FOFFSET fOffset;
      ULONG ulSize;

      fOffset = ( HB_FOFFSET ) HSXHEADER_LEN +
                ( HB_FOFFSET ) ( pHSX->ulFirstRec - 1 ) *
                ( HB_FOFFSET ) pHSX->uiRecordSize;
      ulSize = pHSX->ulBufRec * pHSX->uiRecordSize;

      if( hb_fileWriteAt( pHSX->pFile, pHSX->pBuffer, ulSize, fOffset ) != ulSize )
         return HSX_BADWRITE;

      pHSX->fChanged = FALSE;
      pHSX->fFlush = TRUE;
   }
   return HSX_SUCCESS;
}

static int hb_hsxFlushAll( int iHandle )
{
   int iRetVal;

   iRetVal = hb_hsxFlush( iHandle );
   if( iRetVal == HSX_SUCCESS )
      iRetVal = hb_hsxHdrFlush( iHandle );

   return iRetVal;
}

static int hb_hsxHdrRead( int iHandle )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   BYTE headrBuf[ HSXHEADER_LEN ];
   LPHSXHEADER pHeader = ( LPHSXHEADER ) headrBuf;
   int iResult = HSX_SUCCESS;

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( hb_fileReadAt( pHSX->pFile, headrBuf, HSXHEADER_LEN, 0 ) != HSXHEADER_LEN )
      return HSX_BADREAD;

   pHSX->ulRecCount = HB_GET_LE_UINT32( pHeader->recCount );
   pHSX->uiRecordSize = HB_GET_LE_UINT32( pHeader->recSize );
   pHSX->fIgnoreCase = HB_GET_LE_UINT16( pHeader->ignoreCase ) != 0;
   pHSX->iFilterType = HB_GET_LE_UINT16( pHeader->filterType );
   pHSX->fUseHash = HB_GET_LE_UINT32( pHeader->hashLetters ) != 0;

   if( pHeader->keyExpression[0] >= ' ' )
   {
      headrBuf[ HSXHEADER_LEN - 1 ] = '\0';
      pHSX->szKeyExpr = hb_strdup( ( char * ) pHeader->keyExpression );
      iResult = hb_hsxCompile( pHSX->szKeyExpr, &pHSX->pKeyItem );
   }

   /* update the record counter */
   hb_hsxGetRecCount( pHSX );

   return iResult;
}

static int hb_hsxRead( int iHandle, ULONG ulRecord, BYTE ** pRecPtr )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   BOOL fCount = pHSX->fShared;

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( ulRecord > pHSX->ulRecCount && fCount )
   {
      hb_hsxGetRecCount( pHSX );
      fCount = FALSE;
   }

   if( ulRecord == 0 || ulRecord > pHSX->ulRecCount )
      return HSX_RECBOUND;

   if( pHSX->ulFirstRec == 0 || ulRecord < pHSX->ulFirstRec ||
        ulRecord >= pHSX->ulFirstRec + pHSX->ulBufRec )
   {
      HB_FOFFSET fOffset;
      ULONG ulSize, ulFirst;
      int iRetVal;

      if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
         return iRetVal;

      ulFirst = ulRecord;
      if( pHSX->fWrLocked && pHSX->fShared )
         pHSX->ulBufRec = 1;
      else if( ulFirst + pHSX->ulBufSize - 1 <= pHSX->ulRecCount )
         pHSX->ulBufRec = pHSX->ulBufSize;
      else
      {
         if( fCount )
            hb_hsxGetRecCount( pHSX );
         pHSX->ulBufRec = HB_MIN( pHSX->ulBufSize, pHSX->ulRecCount - ulFirst + 1 );
      }

      fOffset = ( HB_FOFFSET ) HSXHEADER_LEN +
                ( HB_FOFFSET ) ( ulFirst - 1 ) *
                ( HB_FOFFSET ) pHSX->uiRecordSize;
      ulSize = pHSX->ulBufRec * pHSX->uiRecordSize;

      if( hb_fileReadAt( pHSX->pFile, pHSX->pBuffer, ulSize, fOffset ) != ulSize )
      {
         pHSX->ulFirstRec = pHSX->ulBufRec = 0;
         return HSX_BADREAD;
      }
      pHSX->ulFirstRec = ulFirst;
   }

   *pRecPtr = pHSX->pBuffer + ( ulRecord - pHSX->ulFirstRec ) * pHSX->uiRecordSize;

   return HSX_SUCCESS;
}

static int hb_hsxAppend( int iHandle, ULONG * pulRecNo, BYTE **pRecPtr )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( pHSX->ulFirstRec == 0 || pHSX->ulBufRec == pHSX->ulBufSize ||
        pHSX->ulFirstRec + pHSX->ulBufRec != pHSX->ulRecCount + 1 )
   {
      int iRetVal;

      if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
         return iRetVal;

      *pulRecNo = pHSX->ulFirstRec = ++pHSX->ulRecCount;
      pHSX->ulBufRec = 1;
   }
   else
   {
      pHSX->ulBufRec++;
      *pulRecNo = ++pHSX->ulRecCount;
   }
   *pRecPtr = pHSX->pBuffer + ( pHSX->ulBufRec - 1 ) * pHSX->uiRecordSize;
   pHSX->fHdrChanged = TRUE;

   return HSX_SUCCESS;
}

static int hb_hsxUpdate( int iHandle, ULONG ulRecord, BYTE **pRecPtr )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( ulRecord > pHSX->ulRecCount )
   {
      /* this is intentional - when HSX index is bound with workarea
       * then all updates should be synced by WA locks and it should
       * be save to use REPLACE called from GOCOLD() method instead of
       * ADD for newly appended records */
      if( pHSX->iArea != 0 )
         pHSX->ulRecCount = ulRecord;
      else if( pHSX->fShared )
         hb_hsxGetRecCount( pHSX );
   }

   if( ulRecord == 0 || ulRecord > pHSX->ulRecCount )
      return HSX_RECBOUND;

   if( pHSX->ulFirstRec == 0 || ulRecord < pHSX->ulFirstRec ||
        ulRecord >= pHSX->ulFirstRec + pHSX->ulBufRec )
   {
      int iRetVal;

      if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
         return iRetVal;

      pHSX->ulFirstRec = ulRecord;
      pHSX->ulBufRec = 1;
   }
   *pRecPtr = pHSX->pBuffer + ( ulRecord - pHSX->ulFirstRec ) * pHSX->uiRecordSize;

   return HSX_SUCCESS;
}

static int hb_hsxLock( int iHandle, int iAction, ULONG ulRecord )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal = HSX_SUCCESS, iRet;
   BOOL fResult;

   HB_SYMBOL_UNUSED( ulRecord );

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( pHSX->fReadonly )
   {
      switch( iAction )
      {
         case HSX_WRITELOCK:
         case HSX_UPDATELOCK:
         case HSX_APPENDLOCK:
         case HSX_HDRWRITELOCK:
            return HSX_LOCKFAILED;
      }
   }

   /*
    * When HSX is bound with with workarea it should be synced
    * by WA locks to not cause additional overhead with repeated
    * operations. hb_hsxAdd() should be called when WA APPEND_LOCK
    * is set and hb_hsxReplace() inside GOCOLD() method
    */
   if( pHSX->fShared && pHSX->iArea == 0 )
   {
      switch( iAction )
      {
         case HSX_READLOCK:
            break;

         case HSX_WRITELOCK:
         case HSX_UPDATELOCK:
         case HSX_APPENDLOCK:
            for( ;; )
            {
               fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
                                      FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT );
               if( fResult )
                  break;
               hb_releaseCPU();
            }
            if( iRetVal == HSX_SUCCESS )
            {
               /* discrad buffers in shared mode */
               pHSX->ulFirstRec = pHSX->ulBufRec = 0;
               if( iAction == HSX_APPENDLOCK )
                  hb_hsxGetRecCount( pHSX );
               else if( iAction == HSX_WRITELOCK )
                  pHSX->fWrLocked = TRUE;
            }
            break;

         case HSX_HDRREADLOCK:
            for( ;; )
            {
               fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
                                      FL_LOCK | FLX_SHARED | FLX_WAIT );
               if( fResult )
                  break;
               hb_releaseCPU();
            }
            break;

         case HSX_HDRWRITELOCK:
            for( ;; )
            {
               fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
                                      FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT );
               if( fResult )
                  break;
               hb_releaseCPU();
            }
            break;

         case HSX_READUNLOCK:
            break;

         case HSX_WRITEUNLOCK:
         case HSX_UPDATEUNLOCK:
         case HSX_APPENDUNLOCK:
            iRetVal = hb_hsxFlush( iHandle );
            if( iAction == HSX_APPENDLOCK )
               pHSX->fWrLocked = FALSE;
         case HSX_HDRWRITEUNLOCK:
            iRet = hb_hsxHdrFlush( iHandle );
            if( iRetVal == HSX_SUCCESS )
               iRetVal = iRet;
         case HSX_HDRREADUNLOCK:
            if( ! hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
                               FL_UNLOCK ) )
            {
               if( iRetVal == HSX_SUCCESS )
                  iRetVal = HSX_CANNOTUNLOCK;
            }
            break;
      }
   }

   return iRetVal;
}

static int hb_hsxIfDel( int iHandle, ULONG ulRecord )
{
   BYTE *pRecPtr;
   int iRetVal, iRet;

   iRetVal = hb_hsxLock( iHandle, HSX_READLOCK, ulRecord );

   if( iRetVal == HSX_SUCCESS )
   {
      iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = *pRecPtr & 0x80 ? HSX_SUCCESS : HSX_SUCCESSFALSE;
   }
   iRet = hb_hsxLock( iHandle, HSX_READUNLOCK, ulRecord );
   if( iRet != HSX_SUCCESS )
      iRetVal = iRet;
   return iRetVal;
}

static int hb_hsxDelete( int iHandle, ULONG ulRecord )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal, iRet;

   if( ! pHSX )
      return HSX_BADHANDLE;

   iRetVal = hb_hsxLock( iHandle, HSX_UPDATELOCK, ulRecord );
   if( iRetVal == HSX_SUCCESS )
   {
      BYTE *pRecPtr;

      iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
      if( iRetVal == HSX_SUCCESS )
      {
         if( *pRecPtr & 0x80 )
            iRetVal = HSX_ISDELETED;
         else
         {
            *pRecPtr |= 0x80;
            pHSX->fChanged = TRUE;
            iRetVal = HSX_SUCCESS;
         }
      }
      iRet = hb_hsxLock( iHandle, HSX_UPDATEUNLOCK, ulRecord );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }
   return iRetVal;
}

static int hb_hsxUnDelete( int iHandle, ULONG ulRecord )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal, iRet;

   if( ! pHSX )
      return HSX_BADHANDLE;

   iRetVal = hb_hsxLock( iHandle, HSX_UPDATELOCK, ulRecord );
   if( iRetVal == HSX_SUCCESS )
   {
      BYTE *pRecPtr;

      iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
      if( iRetVal == HSX_SUCCESS )
      {
         if( ( *pRecPtr & 0x80 ) == 0 )
            iRetVal = HSX_NOTDELETED;
         else
         {
            *pRecPtr &= ~0x80;
            pHSX->fChanged = TRUE;
            iRetVal = HSX_SUCCESS;
         }
      }
      iRet = hb_hsxLock( iHandle, HSX_UPDATEUNLOCK, ulRecord );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }
   return iRetVal;
}

static int hb_hsxReplace( int iHandle, ULONG ulRecord, PHB_ITEM pExpr, BOOL fDeleted )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal, iRet;

   if( ! pHSX )
      return HSX_BADHANDLE;

   iRetVal = hb_hsxLock( iHandle, HSX_WRITELOCK, ulRecord );
   if( iRetVal == HSX_SUCCESS )
   {
      BYTE * pRecPtr;

      iRetVal = hb_hsxUpdate( iHandle, ulRecord, &pRecPtr );
      if( iRetVal == HSX_SUCCESS )
      {
         iRetVal = hb_hsxEval( iHandle, pExpr, pRecPtr, pExpr ? NULL : &fDeleted );
         if( iRetVal == HSX_SUCCESS )
         {
            if( fDeleted )
               *pRecPtr |= 0x80;
            pHSX->fChanged = TRUE;
         }
      }
      iRet = hb_hsxLock( iHandle, HSX_WRITEUNLOCK, ulRecord );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }
   return iRetVal;
}

static int hb_hsxAdd( int iHandle, ULONG *pulRecNo, PHB_ITEM pExpr, BOOL fDeleted )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal, iRet;

   if( ! pHSX )
      return HSX_BADHANDLE;

   if( !pExpr && !pHSX->pKeyItem )
      return HSX_BADPARMS;

   iRetVal = hb_hsxLock( iHandle, HSX_APPENDLOCK, 0 );
   if( iRetVal == HSX_SUCCESS )
   {
      BYTE * pRecPtr;
      ULONG ulRecNo;

      iRetVal = hb_hsxAppend( iHandle, &ulRecNo, &pRecPtr );
      if( iRetVal == HSX_SUCCESS )
      {
         iRetVal = hb_hsxEval( iHandle, pExpr, pRecPtr, pExpr ? NULL : &fDeleted );
         if( iRetVal == HSX_SUCCESS )
         {
            if( fDeleted )
               *pRecPtr |= 0x80;
            pHSX->fChanged = TRUE;
            if( pulRecNo )
               *pulRecNo = ulRecNo;
         }
      }
      iRet = hb_hsxLock( iHandle, HSX_APPENDUNLOCK, 0 );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }

   return iRetVal;
}

static int hb_hsxSeekSet( int iHandle, BYTE * pStr, ULONG ulLen )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal;

   if( !pHSX )
      return HSX_BADHANDLE;

   iRetVal = hb_hsxFlushAll( iHandle );
   if( iRetVal == HSX_SUCCESS )
   {
      if( pHSX->ulRecCount == 0 )
         iRetVal = HSX_NORECS;
      else
      {
         if( pHSX->pSearchVal )
            hb_xfree( pHSX->pSearchVal );
         pHSX->pSearchVal = ( BYTE * ) hb_xgrab( ulLen + 1 );
         memcpy( pHSX->pSearchVal, pStr, ulLen );
         pHSX->pSearchVal[ ulLen ] = '\0';
         pHSX->ulSearch = ulLen;
         if( ! pHSX->pSearchKey )
            pHSX->pSearchKey = ( BYTE * ) hb_xgrab( pHSX->uiRecordSize );
         hb_hsxHashStr( pStr, ulLen, pHSX->pSearchKey,
                        pHSX->uiRecordSize, pHSX->fIgnoreCase,
                        pHSX->iFilterType, pHSX->fUseHash );
         pHSX->ulCurrRec = 0;
      }
   }
   return iRetVal;
}

static int hb_hsxNext( int iHandle, ULONG * pulRecNo )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iRetVal, iRet;

   *pulRecNo = 0;

   if( ! pHSX )
      return HSX_BADHANDLE;

   iRetVal = hb_hsxLock( iHandle, HSX_READLOCK, 0 );
   if( iRetVal == HSX_SUCCESS )
   {
      BYTE * pRecPtr;
      int i;

      while( pHSX->ulCurrRec < pHSX->ulRecCount )
      {
         iRetVal = hb_hsxRead( iHandle, ++pHSX->ulCurrRec, &pRecPtr );
         if( iRetVal != HSX_SUCCESS )
            break;
         if( ! hb_setGetDeleted() || ( *pRecPtr & 0x80 ) == 0 ) /* Not deleted */
         {
            for( i = 0; i < pHSX->uiRecordSize; i++ )
            {
               if( ( pRecPtr[ i ] & pHSX->pSearchKey[ i ] ) != pHSX->pSearchKey[ i ] )
                  break;
            }
            if( i == pHSX->uiRecordSize )
            {
               *pulRecNo = pHSX->ulCurrRec;
               break;
            }
         }
      }

      iRet = hb_hsxLock( iHandle, HSX_READUNLOCK, 0 );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }
   return iRetVal;
}

static LPHSXINFO hb_hsxNew( void )
{
   LPHSXINFO pHSX;
   int iHandle = 0;
   LPHSXTABLE pTable = hb_hsxTable();

   if( pTable->iHandleSize == 0 )
   {
      pTable->iHandleSize = HSX_HALLOC;
      pTable->handleArray = ( LPHSXINFO * ) hb_xgrab( sizeof( LPHSXINFO ) * HSX_HALLOC );
      memset( pTable->handleArray, 0, sizeof( LPHSXINFO ) * pTable->iHandleSize );
   }
   else
   {
      while( iHandle < pTable->iHandleSize )
      {
         if( pTable->handleArray[ iHandle ] == NULL )
            break;
         iHandle++;
      }
      if( iHandle == pTable->iHandleSize )
      {
         pTable->iHandleSize += HSX_HALLOC;
         pTable->handleArray = ( LPHSXINFO * ) hb_xrealloc( pTable->handleArray, 
                                          sizeof( LPHSXINFO ) * pTable->iHandleSize );
         memset( &pTable->handleArray[ iHandle ], 0, sizeof( LPHSXINFO ) * HSX_HALLOC );
      }
   }
   pTable->handleArray[ iHandle ] = pHSX = ( LPHSXINFO ) hb_xgrab( sizeof( HSXINFO ) );
   pTable->iHandleCount++;
   memset( pHSX, 0, sizeof( HSXINFO ) );
   pHSX->iHandle = iHandle;
   pHSX->pFile = NULL;

   return pHSX;
}

static void hb_hsxExpDestroy( PHB_ITEM pItem )
{
   if( hb_itemType( pItem ) == HB_IT_POINTER )
      hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pItem ) );
   hb_itemRelease( pItem );
}

static int hb_hsxVerify( int iHandle, BYTE * szText, ULONG ulLen,
                         BYTE * szSub, ULONG ulSub, int iType )
{
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   int iResult;

   if( !szSub && pHSX )
   {
      szSub = pHSX->pSearchVal;
      ulSub = pHSX->ulSearch;
   }
   if( !pHSX )
      iResult = HSX_BADHANDLE;
   else if( !szText || !szSub )
      iResult = HSX_BADPARMS;
   else if( ulSub > ulLen || ulSub == 0 )
      /* !ulSub -> do not accept empty substrings as $ operator at runtime */
      iResult = HSX_SUCCESSFALSE;
   else
   {
      ULONG ul, ull;

      switch( iType )
      {
         case HSX_VERIFY_BEGIN:
            iResult = hb_hsxStrCmp( szSub, ulSub, szText, ulSub,
                                    pHSX->fIgnoreCase, pHSX->iFilterType );
            break;
         case HSX_VERIFY_END:
            iResult = hb_hsxStrCmp( szSub, ulSub, szText + ulLen - ulSub, ulSub,
                                    pHSX->fIgnoreCase, pHSX->iFilterType );
            break;
         case HSX_VERIFY_AND:
            iResult = HSX_SUCCESS;
            for( ul = 0; ul < ulSub && iResult == HSX_SUCCESS; ul++ )
            {
               while( szSub[ ul ] == ' ' && ul < ulSub )
                  ++ul;
               ull = ul;
               while( szSub[ ull ] != ' ' && ull < ulSub )
                  ++ull;
               iResult = hb_hsxStrCmp( &szSub[ ul ], ull - ul, szText, ulLen,
                                       pHSX->fIgnoreCase, pHSX->iFilterType );
               ul = ull;
            }
            break;
/*
         case HSX_VERIFY_OR:
            iResult = HSX_SUCCESSFALSE;
            for( ul = 0; ul < ulSub && iResult == HSX_SUCCESSFALSE; ul++ )
            {
               while( szSub[ ul ] == ' ' && ul < ulSub )
                  ++ul;
               ull = ul;
               while( szSub[ ull ] != ' ' && ull < ulSub )
                  ++ull;
               iResult = hb_hsxStrCmp( &szSub[ ul ], ull - ul, szText, ulLen,
                                       pHSX->fIgnoreCase, pHSX->iFilterType );
               ul = ull;
            }
            break;
*/
         case HSX_VERIFY_PHRASE:
         default:
            iResult = hb_hsxStrCmp( szSub, ulSub, szText, ulLen,
                                    pHSX->fIgnoreCase, pHSX->iFilterType );
      }
   }
   return iResult;
}

static int hb_hsxDestroy( int iHandle )
{
   LPHSXTABLE pTable = hb_hsxTable();

   if( iHandle >=0 && iHandle < pTable->iHandleSize && pTable->handleArray[ iHandle ] != NULL )
   {
      LPHSXINFO pHSX = pTable->handleArray[ iHandle ];
      int iRetVal = HSX_SUCCESS;

      if( pHSX->pFile )
      {
         iRetVal = hb_hsxFlushAll( iHandle );
         hb_fileClose( pHSX->pFile );
      }

      if( pHSX->szFileName )
         hb_xfree( pHSX->szFileName );
      if( pHSX->pSearchVal )
         hb_xfree( pHSX->pSearchVal );
      if( pHSX->pSearchKey )
         hb_xfree( pHSX->pSearchKey );
      if( pHSX->pBuffer )
         hb_xfree( pHSX->pBuffer );
      if( pHSX->szKeyExpr )
         hb_xfree( pHSX->szKeyExpr );
      if( pHSX->pKeyItem )
         hb_hsxExpDestroy( pHSX->pKeyItem );
      hb_xfree( pHSX );

      pTable->handleArray[ iHandle ] = NULL;
      if( --pTable->iHandleCount == 0 )
      {
         hb_xfree( pTable->handleArray );
         pTable->iHandleSize = 0;
         pTable->handleArray = NULL;
      }
      return iRetVal;
   }
   return HSX_BADHANDLE;
}

static int hb_hsxCreate( char * szFile, int iBufSize, int iKeySize,
                         BOOL fIgnoreCase, int iFilter, PHB_ITEM pExpr )
{
   char szFileName[ _POSIX_PATH_MAX + 1 ], * szExpr = NULL;
   PHB_ITEM pKeyExpr = NULL;
   ULONG ulBufSize;
   USHORT uiRecordSize;
   LPHSXINFO pHSX;
   PHB_FILE pFile;
   int iRetVal;

   if( !szFile || ! *szFile )
      return HSX_BADPARMS;

   hb_strncpy( szFileName, szFile, _POSIX_PATH_MAX );

   if( iKeySize < 1 || iKeySize > HSXMAXKEY_SIZE )
      iKeySize = HSXDEFKEY_SIZE;
   if( iFilter < 1 || iFilter > 3 )
      iFilter = HSXDEFFILTER;

   ulBufSize = iBufSize * 1024;
   if( ulBufSize == 0 )
      ulBufSize = HSXDEFBUF_LEN;
   else if( ulBufSize < HSXMINBUF_LEN )
      ulBufSize = HSXMINBUF_LEN;
   else if( ulBufSize > HSXMAXBUF_LEN )
      ulBufSize = HSXMAXBUF_LEN;
   uiRecordSize = ( USHORT ) 0x08 << iKeySize;
   ulBufSize /= uiRecordSize;
   if( ulBufSize == 0 )
      ulBufSize = 1;

   if( pExpr )
   {
      if( hb_itemGetCLen( pExpr ) > 0 )
      {
         szExpr = hb_itemGetCPtr( pExpr );
         iRetVal = hb_hsxCompile( szExpr, &pKeyExpr );
         if( iRetVal != HSX_SUCCESS )
            return iRetVal;
      }
      else if( hb_itemType( pExpr ) == HB_IT_BLOCK )
         pKeyExpr = hb_itemNew( pExpr );
   }

   pFile = hb_fileExtOpen( ( BYTE * ) szFileName, ( BYTE * ) HSX_FILEEXT,
                           FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE |
                           FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
                           NULL, NULL );

   if( !pFile )
   {
      if( pKeyExpr )
         hb_hsxExpDestroy( pKeyExpr );
      return HSX_CREATEFAIL;
   }

   pHSX = hb_hsxNew();
   pHSX->uiRecordSize = uiRecordSize;
   pHSX->fIgnoreCase = fIgnoreCase;
   pHSX->iFilterType = iFilter;
   pHSX->fUseHash = fIgnoreCase && iKeySize == 2 && iFilter != 3;
   pHSX->pFile = pFile;
   pHSX->szFileName = hb_strdup( szFileName );
   pHSX->fShared = FALSE;
   pHSX->fReadonly = FALSE;
   if( szExpr )
      pHSX->szKeyExpr = hb_strdup( szExpr );
   pHSX->pKeyItem = pKeyExpr;
   pHSX->pBuffer = ( BYTE * ) hb_xalloc( ulBufSize * uiRecordSize );
   if( pHSX->pBuffer == NULL )
   {
      hb_hsxDestroy( pHSX->iHandle );
      return HSX_MEMERR;
   }
   pHSX->ulBufSize = ulBufSize;

   pHSX->fHdrChanged = TRUE;
   iRetVal = hb_hsxHdrFlush( pHSX->iHandle );
   if( iRetVal != HSX_SUCCESS )
   {
      hb_hsxDestroy( pHSX->iHandle );
      return iRetVal;
   }

   return pHSX->iHandle;
}

static int hb_hsxOpen( char * szFile, int iBufSize, int iMode )
{
   char szFileName[ _POSIX_PATH_MAX + 1 ];
   BOOL fShared, fReadonly;
   PHB_FILE pFile;
   ULONG ulBufSize;
   USHORT uiFlags;
   LPHSXINFO pHSX;
   int iRetVal, iRet;

   if( !szFile || ! *szFile )
      return HSX_BADPARMS;

   hb_strncpy( szFileName, szFile, _POSIX_PATH_MAX );

   ulBufSize = iBufSize * 1024;
   if( ulBufSize == 0 )
      ulBufSize = HSXDEFBUF_LEN;
   else if( ulBufSize < HSXMINBUF_LEN )
      ulBufSize = HSXMINBUF_LEN;
   else if( ulBufSize > HSXMAXBUF_LEN )
      ulBufSize = HSXMAXBUF_LEN;

   if( iMode < 0 || iMode > 3 )
      iMode = HSXDEFOPENMODE;

   fReadonly = ( iMode & 0x02 ) != 0;
   fShared = ( iMode & 0x01 ) == 0;
   if( hb_setGetAutoShare() == 2 )
      fShared = FALSE;
   uiFlags = ( fReadonly ? FO_READ : FO_READWRITE ) |
             ( fShared ? FO_DENYNONE : FO_EXCLUSIVE );

   pFile = hb_fileExtOpen( ( BYTE * ) szFileName, ( BYTE * ) HSX_FILEEXT,
                           uiFlags | FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
                           NULL, NULL );

   if( !pFile )
      return HSX_OPENERR;

   pHSX = hb_hsxNew();
   pHSX->pFile = pFile;
   pHSX->szFileName = hb_strdup( szFileName );
   pHSX->fShared = fShared;
   pHSX->fReadonly = fReadonly;
   iRetVal = hb_hsxLock( pHSX->iHandle, HSX_HDRREADLOCK, 0 );
   if( iRetVal == HSX_SUCCESS )
   {
      iRetVal = hb_hsxHdrRead( pHSX->iHandle );
      iRet = hb_hsxLock( pHSX->iHandle, HSX_HDRREADUNLOCK, 0 );
      if( iRetVal == HSX_SUCCESS )
         iRetVal = iRet;
   }
   if( iRetVal != HSX_SUCCESS )
   {
      hb_hsxDestroy( pHSX->iHandle );
      return iRetVal;
   }

   ulBufSize /= pHSX->uiRecordSize;
   if( ulBufSize == 0 )
      ulBufSize = 1;

   pHSX->pBuffer = ( BYTE * ) hb_xalloc( ulBufSize * pHSX->uiRecordSize );
   if( pHSX->pBuffer == NULL )
   {
      hb_hsxDestroy( pHSX->iHandle );
      return HSX_MEMERR;
   }
   pHSX->ulBufSize = ulBufSize;

   return pHSX->iHandle;
}

static int hb_hsxIndex( char * szFile, PHB_ITEM pExpr, int iKeySize, int iMode,
                        int iBufSize, BOOL fIgnoreCase, int iFilter )
{
   int iRetVal = HSX_SUCCESS, iHandle;
   ULONG ulRecNo = 0, ulRecCount = 0, ulNewRec, ulRec;
   ERRCODE errCode;
   AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();

   if( !pArea )
   {
      hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_INDEX" );
      return HSX_NOTABLE;
   }

   iHandle = hb_hsxCreate( szFile, iBufSize, iKeySize, fIgnoreCase, iFilter, pExpr );
   if( iHandle < 0 )
      return iHandle;

   errCode = SELF_RECCOUNT( pArea, &ulRecCount );
   if( errCode != FAILURE && ulRecCount )
   {
      errCode = SELF_RECNO( pArea, &ulRecNo );
      if( errCode != FAILURE )
      {
         for( ulRec = 1; ulRec <= ulRecCount; ulRec++ )
         {
            errCode = SELF_GOTO( pArea, ulRec );
            if( errCode == FAILURE )
               break;
            iRetVal = hb_hsxAdd( iHandle, &ulNewRec, NULL, FALSE );
            if( iRetVal != HSX_SUCCESS )
               break;
            if( ulNewRec != ulRec )
            {
               iRetVal = HSX_RECBOUND;
               break;
            }
         }
         if( pArea->valResult )
         {
            hb_itemRelease( pArea->valResult );
            pArea->valResult = NULL;
         }
         if( ulRecNo )
            SELF_GOTO( pArea, ulRecNo );
      }
   }
   hb_hsxDestroy( iHandle );
   if( iRetVal != HSX_SUCCESS )
      return iRetVal;
   if( errCode == FAILURE )
      return HSX_RDDFAILURE;

   return hb_hsxOpen( szFile, iBufSize, iMode );
}

static int hb_hsxFilter( int iHandle, BYTE * pSeek, ULONG ulSeek,
                         PHB_ITEM pVerify, int iVerifyType )
{
   AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
   LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
   BOOL fDestroyExpr = FALSE, fValid;
   int iResult = HSX_SUCCESS;
   ERRCODE errCode;
   ULONG ulRecNo = 0, ulRec;
   PHB_ITEM pItem;

   if( !pHSX )
      return HSX_BADHANDLE;

   if( !pArea )
   {
      hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_FILTER" );
      return HSX_NOTABLE;
   }

   if( ! pVerify || hb_itemType( pVerify ) == HB_IT_NIL )
      pVerify = pHSX->pKeyItem;
   else
   {
      if( hb_itemGetCLen( pVerify ) > 0 )
      {
         iResult = hb_hsxCompile( hb_itemGetCPtr( pVerify ), &pVerify );
         if( iResult != HSX_SUCCESS )
            return HSX_BADPARMS;
         fDestroyExpr = TRUE;
      }
      else if( hb_itemType( pVerify ) != HB_IT_BLOCK )
      {
         pVerify = NULL;
      }
   }

   errCode = SELF_RECNO( pArea, &ulRecNo );
   if( errCode != FAILURE )
      iResult = hb_hsxSeekSet( iHandle, pSeek, ulSeek );

   fValid = TRUE;
   pItem = hb_itemNew( NULL );
   while( iResult == HSX_SUCCESS && errCode != FAILURE )
   {
      iResult = hb_hsxNext( iHandle, &ulRec );
      if( iResult != HSX_SUCCESS || ulRec == 0 )
         break;
      if( pVerify )
      {
         errCode = SELF_GOTO( pArea, ulRec );
         if( errCode == FAILURE )
            break;
         errCode = SELF_EVALBLOCK( pArea, pVerify );
         if( errCode == FAILURE )
            break;
         fValid = hb_hsxVerify( iHandle,
                                ( BYTE * ) hb_itemGetCPtr( pArea->valResult ),
                                hb_itemGetCLen( pArea->valResult ),
                                pSeek, ulSeek, iVerifyType ) == HSX_SUCCESS;
      }
      if( fValid )
      {
         /* set record in WA RM filter */
         hb_itemPutNInt( pItem, ulRec );
         errCode = SELF_INFO( pArea, DBI_RM_ADD, pItem );
      }
   }
   if( pArea->valResult )
   {
      hb_itemRelease( pArea->valResult );
      pArea->valResult = NULL;
   }
   hb_itemRelease( pItem );

   if( ulRecNo )
      SELF_GOTO( pArea, ulRecNo );

   if( fDestroyExpr )
      hb_hsxExpDestroy( pVerify );

   return errCode == FAILURE ? HSX_RDDFAILURE : iResult;
}


/* ************************************************************************ */
/* .prg level functions: HS_*() */
/* ************************************************************************ */

/* hs_Create( , , , , ,  )
                     -> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
   Creates a new, empty HiPer-SEEK index file */
HB_FUNC( HS_CREATE )
{
   hb_retni( hb_hsxCreate( hb_parc( 1 ), hb_parni( 2 ), hb_parni( 3 ),
                           hb_param( 4, HB_IT_LOGICAL ) == NULL || hb_parl( 4 ),
                           hb_parni( 5 ), hb_param( 6, HB_IT_ANY ) ) );
}

/* hs_Open( , ,  )
                     -> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
   Opens an existing HiPer-SEEK index file */
HB_FUNC( HS_OPEN )
{
   hb_retni( hb_hsxOpen( hb_parc( 1 ), hb_parni( 2 ),
             hb_param( 3, HB_IT_NUMERIC ) ? hb_parni( 3 ) : HSXDEFOPENMODE ) );
}

/* hs_Close(  ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
   Closes a previously opened HiPer-SEEK index file */
HB_FUNC( HS_CLOSE )
{
   if( hb_param( 1, HB_IT_NUMERIC ) )
      hb_retni( hb_hsxDestroy( hb_parni( 1 ) ) );
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_Index( , , , , , ,
              ) -> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
   Creates and populates a new HiPer-SEEK index */
HB_FUNC( HS_INDEX )
{
   hb_retni( hb_hsxIndex( hb_parc( 1 ), hb_param( 2, HB_IT_ANY ), hb_parni( 3 ),
                          hb_param( 4, HB_IT_NUMERIC ) ? hb_parni( 4 ) : HSXDEFOPENMODE,
                          hb_parni( 5 ),
                          hb_param( 6, HB_IT_LOGICAL ) == NULL || hb_parl( 6 ),
                          hb_parni( 7 ) ) );
}

/* hs_Add( , [], [lDel] ) -> nVal >= 1 (RECNO), nVal < 0 (ERROR CODE)
   Adds a text string entry to a HiPer-SEEK index file */
HB_FUNC( HS_ADD )
{
   if( hb_param( 1, HB_IT_NUMERIC ) )
   {
      ULONG ulRecNo;
      int iRetVal;

      iRetVal = hb_hsxAdd( hb_parni( 1 ), &ulRecNo,
                           hb_param( 2, HB_IT_BLOCK | HB_IT_STRING ),
                           hb_parl( 3 ) );

      if( iRetVal == HSX_SUCCESS )
         hb_retnint( ulRecNo );
      else
         hb_retni( iRetVal );
   }
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_Replace( , [], , [lDel] ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
   Replaces current HiPer-SEEK index entry with a new value */
HB_FUNC( HS_REPLACE )
{
   if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 3, HB_IT_NUMERIC ) )
      hb_retni( hb_hsxReplace( hb_parni( 1 ), hb_parnl( 3 ), 
                               hb_param( 2, HB_IT_BLOCK | HB_IT_STRING ),
                               hb_parl( 4 ) ) );
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_IfDel( ,  ) -> nVal = {0|1} (DELETED), nVal < 0 (ERROR CODE)
   Determines if a HiPer-SEEK record is marked as deleted */
HB_FUNC( HS_IFDEL )
{
   if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
      hb_retni( hb_hsxIfDel( hb_parni( 1 ), hb_parnl( 2 ) ) );
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_Delete( ,  ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
   Deletes specifed index record from HiPer-SEEK index file */
HB_FUNC( HS_DELETE )
{
   if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
      hb_retni( hb_hsxDelete( hb_parni( 1 ), hb_parnl( 2 ) ) );
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_Undelete( ,  ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
   Unmarks the specified HiPer-SEEK record as being deleted */
HB_FUNC( HS_UNDELETE )
{
   if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
      hb_retni( hb_hsxUnDelete( hb_parni( 1 ), hb_parnl( 2 ) ) );
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_KeyCount(  ) -> nVal >= 0 (RECCOUNT), nVal < 0 (ERROR CODE)
   Returns the number of entries in a HiPer-SEEK index */
HB_FUNC( HS_KEYCOUNT )
{
   if( hb_param( 1, HB_IT_NUMERIC ) )
   {
      LPHSXINFO pHSX = hb_hsxGetPointer( hb_parni( 1 ) );

      if( pHSX )
      {
         if( pHSX->fShared )
            hb_hsxGetRecCount( pHSX );

         hb_retnint( pHSX->ulRecCount );
      }
      else
         hb_retni( HSX_BADHANDLE );
   }
   else
      hb_retni( HSX_BADPARMS );
}

/* hs_Set( ,  ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
   Sets up parameters for a subsequent hs_Next() call */
HB_FUNC( HS_SET )
{
   BYTE * pStr = ( BYTE * ) hb_parc( 2 );
   int iRetVal = HSX_BADPARMS;

   if( pStr && hb_param( 1, HB_IT_NUMERIC ) )
      iRetVal = hb_hsxSeekSet( hb_parni( 1 ), pStr, hb_parclen( 2 ) );
   hb_retni( iRetVal );
}

/* hs_Filter( , , [xRealExp], [nBufSize], [nOpenMode] ) -> nRecMatch
   Sets a WA RM filter using a HiPer-SEEK index */
HB_FUNC( HS_FILTER )
{
   BYTE * szText = ( BYTE * ) hb_parc( 2 ), * pBuff = NULL;
   ULONG ulLen = hb_parclen( 2 ), ulRecords = 0, ull, ul;
   int iHandle = -1, iResult = HSX_BADPARMS;
   BOOL fNew = FALSE, fToken = TRUE;

   if( hb_parclen( 1 ) > 0 )
   {
      if( ulLen > 0 )
      {
         iHandle = hb_hsxOpen( hb_parc( 1 ), hb_parni( 4 ),
               hb_param( 5, HB_IT_NUMERIC ) ? hb_parni( 5 ) : HSXDEFOPENMODE );
         if( iHandle >= 0 )
            fNew = TRUE;
         else
            iResult = iHandle;
      }
   }
   else if( hb_param( 1, HB_IT_NUMERIC ) )
   {
      LPHSXINFO pHSX = hb_hsxGetPointer( hb_parni( 1 ) );

      if( ! pHSX )
         iResult = HSX_BADHANDLE;
      else
      {
         iHandle = pHSX->iHandle;
         if( !szText )
         {
            ulLen = pHSX->ulSearch;
            if( ulLen && pHSX->pSearchVal )
            {
               pBuff = ( BYTE * ) hb_xgrab( ulLen + 1 );
               memcpy( pBuff, pHSX->pSearchVal, ulLen );
               pBuff[ ulLen ] = '\0';
               szText = pBuff;
               fToken = FALSE;
            }
         }
      }
   }
   if( iHandle >= 0 && ulLen > 0 )
   {
      PHB_ITEM pItem = hb_itemNew( NULL );
      AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();

      if( !pArea )
      {
         hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_FILTER" );
         iResult = HSX_NOTABLE;
      }
      /* create empty workarea RM filter */
      else if( SELF_INFO( pArea, DBI_RM_CREATE, pItem ) == FAILURE )
         iResult = HSX_RDDFAILURE;
      else
      {
         /* to be SIX compatible divide given text on space delimited tokens */
         if( fToken )
         {
            iResult = HSX_SUCCESS;
            for( ul = 0; ul < ulLen && iResult == HSX_SUCCESS; ul++ )
            {
               while( szText[ ul ] == ' ' && ul < ulLen )
                  ++ul;
               ull = ul;
               while( szText[ ull ] != ' ' && ull < ulLen )
                  ++ull;
               iResult = hb_hsxFilter( iHandle, &szText[ ul ], ull - ul,
                                 hb_param( 3, HB_IT_ANY ), HSX_VERIFY_PHRASE );
               ul = ull;
            }
         }
         else
         {
            iResult = hb_hsxFilter( iHandle, szText, ulLen,
                                    hb_param( 3, HB_IT_ANY ),
                                    HSX_VERIFY_PHRASE );
         }
      }
      if( iResult == HSX_SUCCESS )
      {
         hb_itemPutNI( pItem, 0 );
         if( SELF_INFO( pArea, DBI_RM_COUNT, pItem ) == FAILURE )
            iResult = HSX_RDDFAILURE;
         else
            ulRecords = hb_itemGetNL( pItem );
      }
      hb_itemRelease( pItem );

      if( fNew )
         hb_hsxDestroy( iHandle );
   }
   if( pBuff )
      hb_xfree( pBuff );

   if( iResult != HSX_SUCCESS )
      hb_retni( iResult );
   else
      hb_retnint( ulRecords );
}

/* hs_Next(  ) -> nVal >= 0 (RECNO), nVal < 0 (ERROR CODE)
   Searches a HiPer-SEEK index file for first/next match */
HB_FUNC( HS_NEXT )
{
   ULONG ulRecNo = 0;
   int iRetVal = HSX_BADPARMS;

   if( hb_param( 1, HB_IT_NUMERIC ) )
      iRetVal = hb_hsxNext( hb_parni( 1 ), &ulRecNo );

   if( iRetVal == HSX_SUCCESS )
      hb_retnint( ulRecNo );
   else
      hb_retni( iRetVal );
}

/* hs_Verify( , , ,  )
          -> nVal = {0|1} (VERIFIED), nVal < 0 (ERROR CODE)
   hs_Verify( ,  ) -> lOK
   Verifies hs_Next() hit against code block expression */
HB_FUNC( HS_VERIFY )
{
   if( hb_param( 1, HB_IT_NUMERIC ) )
   {
      int iHandle = hb_parni( 1 );
      PHB_ITEM pExpr = hb_param( 2, HB_IT_BLOCK );
      BYTE * szText = NULL;
      ULONG ulLen = 0;
      LPHSXINFO pHSX;

      pHSX = hb_hsxGetPointer( iHandle );
      if( !pHSX )
      {
         hb_retni( HSX_BADHANDLE );
         return;
      }
      if( pExpr )
         pExpr = hb_vmEvalBlockOrMacro( pExpr );
      else
      {
         pExpr = hb_param( 2, HB_IT_STRING );
         if( !pExpr && pHSX->pKeyItem )
            pExpr = hb_vmEvalBlockOrMacro( pHSX->pKeyItem );
      }
      if( pExpr )
      {
         szText = ( BYTE * ) hb_itemGetCPtr( pExpr );
         ulLen = hb_itemGetCLen( pExpr );
      }

      hb_retni( hb_hsxVerify( hb_parni( 1 ), szText, ulLen,
                              ( BYTE * ) hb_parc( 3 ), hb_parclen( 3 ),
                              hb_parni( 4 ) ) );
   }
   else
   {
      PHB_ITEM pExpr = hb_param( 1, HB_IT_BLOCK );
      BYTE * szSub = ( BYTE * ) hb_parc( 2 ), * szText = NULL;
      ULONG ulSub = hb_parclen( 2 ), ulLen = 0;
      BOOL fIgnoreCase = hb_parl( 3 );

      if( ulSub )
      {
         pExpr = pExpr ? hb_vmEvalBlockOrMacro( pExpr ) : hb_param( 2, HB_IT_STRING );

         if( pExpr )
         {
            szText = ( BYTE * ) hb_itemGetCPtr( pExpr );
            ulLen = hb_itemGetCLen( pExpr );
         }
      }
      hb_retl( ulLen && ulSub && hb_hsxStrCmp( szSub, ulSub, szText, ulLen,
                                               fIgnoreCase, 3 ) );
   }
}

/* hs_Version() ->  */
HB_FUNC( HS_VERSION )
{
   static const char szVer[] = "HiPer-SEEK / FTS library emulation";
   char * pszHBVersion, * pszVersion;

   pszHBVersion = hb_verHarbour();
   pszVersion = hb_xstrcat( NULL, szVer, ": ", pszHBVersion );
   hb_retclen_buffer( pszVersion, strlen( pszVersion ) );
   hb_xfree( pszHBVersion );
}
hsx.c449

Page url: http://www.yourdomain.com/help/index.html?hsx.htm