home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 16 / CD_ASCQ_16_0994.iso / news / 4611 / fw16d.ins / SOURCE / FUNCTION / TFILE.C < prev    next >
C/C++ Source or Header  |  1994-06-11  |  22KB  |  864 lines

  1. /*
  2. ╔═══════════════════════════════════════════════════════════════╗
  3. ║ Módulo: TFile.c                                               ║
  4. ║ Lenguaje: C Para Clipper 5.xx                                 ║
  5. ║ Fecha: Nov.   1993                                            ║
  6. ╚═══════════════════════════════════════════════════════════════╝
  7. */
  8. #pragma inline
  9.  
  10. #include <ClipApi.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13.  
  14. extern int  _terror;
  15. extern int  _tcommit( int );
  16.  
  17. typedef struct
  18. {
  19.    WORD wDummy[ 3 ];
  20. } OVM;
  21.  
  22. typedef OVM* OVMP;
  23.  
  24. extern OVMP  _vmAlloc( WORD );
  25. extern char* _vmLock( OVMP );
  26. extern void  _vmUnLock( OVMP );
  27. extern void  _vmFree( OVMP );
  28.  
  29. static LONG near lSkip( int );
  30. static int  near iScanEol( char *, int );
  31. static int  near iScanBol( char *, int );
  32. static void near RetSelf( void );
  33. static void near SetStruct( void );
  34. static void near GetStruct( void );
  35. static long lFileMove( long read1, long read2, long end1, long end2,
  36.                         char *pBuff1, char *pBuff2 );
  37.  
  38. CLIPPER TFNew( void );     // ( cFileName )   -> Initiated TFile Object.
  39. CLIPPER TFOpen( void );    // ( nOpenMode )   -> Handle. Si > 0 OK.
  40. CLIPPER TFCreate( void );  // ( nCreateMode ) -> Handle. Si > 0 OK.
  41. CLIPPER TFClose( void );   // ( )             -> lClosed
  42. CLIPPER TFGoTop( void );   // ()              -> nil
  43. CLIPPER TFRecno( void );   // ()              -> nRecno    ( nLine )
  44. CLIPPER TFGoBottom( void );// ()              -> nil
  45. CLIPPER TFSkip( void );    // ( +- nLines )   -> nil
  46. CLIPPER TFReadLn( void );  // ()              -> cLine
  47. CLIPPER TFLastRec( void ); // ()              -> nLastRec
  48. CLIPPER TFlEof( void );    // ()              -> BOOL
  49. CLIPPER TFlBof( void );    // ()              -> BOOL
  50. CLIPPER TFGoTo( void );   // ( nLine )       -> nil
  51. CLIPPER TFWriteLn( void ); // ( cCadena, lInsert ) -> nil
  52. CLIPPER TFAppend( void );  // ( nLines )      -> nil
  53. CLIPPER TFDelete( void );  // ( nLines )      -> nil
  54. CLIPPER TFInsert( void );  // ( nLines )      -> nil
  55.         
  56.  
  57. // TFile instances.
  58. #define OT_cFILENAME      1
  59. #define OT_cFILESTRT      2
  60.  
  61.  
  62. // Allocation sizes
  63. #define BIGBLOCK   4096
  64. #define LITBLOCK   1024
  65. #define KBIGBLOCK     4
  66. #define KLITBLOCK     1
  67.  
  68. typedef struct
  69. {
  70.     long lRecno;
  71.     long lOffSet;
  72.     int  iHandle;
  73.     long lLastRec;
  74.     long lLastOff;
  75.     long lLastByte;
  76.     int  isEof;
  77.  
  78. } OFILE;
  79.  
  80. static OFILE * oFile;
  81.  
  82. static BOOL bCharged = FALSE;
  83.  
  84. // Nuestro Handle.
  85. static WORD wHandle = 0;
  86.  
  87. static char crlf[] = { (char) 0x0D, (char) 0x0A };
  88.  
  89. static OVMP oMBuff = 0;     // Buffer normal de 1Kb.
  90. static OVMP oMBig1;         // 1er. Buffer Gordo  de 4Kb.
  91. static OVMP oMBig2;         // 2º Buffer Gordo  de 4Kb.
  92.  
  93.  
  94. //---------------------------------------------------------------------------//
  95.  
  96. static void near RetSelf()
  97. {
  98.     _bcopy( (LPBYTE) _eval, (LPBYTE) ( _lbase + 1), 14 );
  99. }
  100.  
  101. //---------------------------------------------------------------------------//
  102.  
  103. static void near SetStruct()
  104. {
  105.     if( bCharged )
  106.     {
  107.        _VSTRUNLOCK( _tos );
  108.        _cAtPut( _lbase + 1, OT_cFILESTRT, _tos-- );
  109.        bCharged = FALSE;
  110.     }
  111. }
  112.  
  113. //---------------------------------------------------------------------------//
  114.  
  115. static void near GetStruct()
  116. {
  117.     if( !bCharged )
  118.     {
  119.        _cAt( _lbase + 1, OT_cFILESTRT, -1, ++_tos );
  120.        _VSTRLOCK( _tos );
  121.        oFile = ( OFILE * ) _VSTR( _tos );
  122.        bCharged = TRUE;
  123.     }
  124. }
  125.  
  126. //---------------------------------------------------------------------------//
  127.  
  128. CLIPPER TFNew() // ( cFileName )
  129. {
  130.     PCLIPVAR pcFile = _param( 1, CHARACTER );
  131.  
  132.     if( pcFile )
  133.     {
  134.        _cAtPut( _lbase + 1, OT_cFILENAME, pcFile );
  135.     }
  136.  
  137.     _BYTESNEW( sizeof( OFILE ) );
  138.     _VSTRLOCK( _eval );
  139.  
  140.     _bset( (LPBYTE) _VSTR( _eval ), 0, sizeof( OFILE ) );
  141.     _VSTRUNLOCK( _eval );
  142.  
  143.     _cAtPut( _lbase + 1, OT_cFILESTRT, _eval );
  144.  
  145.     // Un método constuctor debe devolver SELF.
  146.     RetSelf();
  147.  
  148.     
  149. }
  150.  
  151. //---------------------------------------------------------------------------//
  152.  
  153. CLIPPER TFOpen() // ( nOpenMode )
  154. {
  155.     // int iOpenAttr = _param( 1, ANYNUMBER ) ? _parni( 1 ) : O_RDONLY | SH_DENYNO| O_BINARY ;
  156.     int iOpenAttr = ( _param( 1, ANYNUMBER ) ? _parni( 1 ) : O_RDWR );
  157.  
  158.     GetStruct();
  159.  
  160.     if( !oFile->iHandle )
  161.     {
  162.        oFile->iHandle   = _topen( _parc( 0, OT_cFILENAME ), iOpenAttr ) ;
  163.        oFile->lOffSet   = 0;
  164.        oFile->lRecno    = 1;
  165.        oFile->lLastByte = _tlseek( oFile->iHandle, 0, SEEK_END );
  166.  
  167.     }
  168.  
  169.     _retni( oFile->iHandle );
  170.  
  171.     SetStruct();
  172. }
  173.  
  174. //---------------------------------------------------------------------------//
  175.  
  176. CLIPPER TFCreate() // ( nCreateMode )
  177. {
  178.     int iCreaAttr = ( _param( 1, ANYNUMBER ) ? _parni( 1 ) : 0 );
  179.  
  180.     GetStruct();
  181.  
  182.     if( !oFile->iHandle )
  183.     {
  184.        oFile->iHandle   = _tcreat( _parc( 0, OT_cFILENAME ), iCreaAttr ) ;
  185.        oFile->lOffSet   = 0;
  186.        oFile->lRecno    = 1;
  187.        oFile->lLastByte = _tlseek( oFile->iHandle, 0, SEEK_END );
  188.     }
  189.  
  190.     _retni( oFile->iHandle );
  191.  
  192.     SetStruct();
  193. }
  194.  
  195. //---------------------------------------------------------------------------//
  196.  
  197. CLIPPER TFClose() // ()
  198. {
  199.     GetStruct();
  200.  
  201.     if( oFile->iHandle )
  202.     {
  203.        _tclose( oFile->iHandle );
  204.          
  205.        _bset( (LPBYTE) ( oFile ), 0, sizeof( OFILE ) );
  206.  
  207.        _retl( TRUE );
  208.     }
  209.     else
  210.        _retl( FALSE );
  211.  
  212.     SetStruct();
  213. }
  214.  
  215. //---------------------------------------------------------------------------//
  216.  
  217. CLIPPER TFGoTop() // ()
  218. {
  219.     GetStruct();
  220.  
  221.     oFile->lOffSet = 0;
  222.     oFile->lRecno  = 1;
  223.  
  224.     SetStruct();
  225. }
  226.  
  227. //---------------------------------------------------------------------------//
  228.  
  229. CLIPPER TFRecno() // ()
  230. {
  231.     GetStruct();
  232.  
  233.     _retnl( oFile->lRecno );
  234.  
  235.     SetStruct();
  236. }
  237.  
  238. //---------------------------------------------------------------------------//
  239.  
  240. CLIPPER TFGoBottom() // ()
  241. {
  242.     int  iEolOffSet;
  243.     int  iLen, iBlockLen;
  244.     char * cBuff, * cTemp;
  245.  
  246.     GetStruct();
  247.  
  248.     if( oFile->iHandle )
  249.     {
  250.  
  251.         if( oFile->lLastRec != 0 )
  252.         {
  253.             oFile->lRecno  = oFile->lLastRec;
  254.             oFile->lOffSet = oFile->lLastOff;
  255.         }
  256.         else
  257.         {
  258.             cBuff       = _vmLock( oMBig1 );
  259.  
  260.             do
  261.             {
  262.                 cTemp = cBuff;
  263.  
  264.                 _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  265.                 iLen  = _tread(  oFile->iHandle, cTemp, BIGBLOCK );
  266.                 iBlockLen = iLen;
  267.                 do
  268.                 {
  269.                      iEolOffSet = iScanEol( cTemp, iLen );
  270.                      if( ( iEolOffSet == iLen ) ||
  271.                          ( ( iEolOffSet + 1 ) == iLen ) )
  272.                      {
  273.                         break;
  274.                      }
  275.                      cTemp   += iEolOffSet + 2;
  276.                      iLen    -= ( iEolOffSet + 2 );
  277.                      oFile->lRecno++;
  278.                      oFile->lOffSet += iEolOffSet + 2;
  279.  
  280.                 } while ( ( iLen > 0 ) );
  281.  
  282.             } while ( iBlockLen == BIGBLOCK );
  283.  
  284.             oFile->lLastRec = oFile->lRecno;
  285.             oFile->lLastOff = oFile->lOffSet;
  286.             _vmUnLock( oMBig1 );
  287.         }
  288.     }
  289.  
  290.     SetStruct();
  291.  
  292.     lSkip( -1 );
  293. }
  294.  
  295. //---------------------------------------------------------------------------//
  296.  
  297. CLIPPER TFSkip()
  298. {
  299.     GetStruct();
  300.  
  301.     if( oFile->iHandle )
  302.     {
  303.         if( _param( 1, ANYNUMBER ) )
  304.             lSkip( _parni( 1 ) );
  305.         else
  306.             lSkip( 1 );
  307.     }
  308.     SetStruct();
  309. }
  310.  
  311. //---------------------------------------------------------------------------//
  312.  
  313. static long near lSkip( int iRecs )
  314. {
  315.  
  316.    int  iEolOffSet;
  317.    LONG lReadPos;
  318.    int  iLen;
  319.    int  icRecs;
  320.    char * cBuff = _vmLock( oMBuff );
  321.  
  322.    if ( iRecs > 0 )
  323.    {
  324.       for( icRecs = 0; icRecs < iRecs; icRecs++ )
  325.       {
  326.          _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  327.          iLen = _tread( oFile->iHandle, cBuff, LITBLOCK );
  328.  
  329.          iEolOffSet = iScanEol( cBuff, iLen );
  330.  
  331.          if ( ( iEolOffSet != iLen ) &&
  332.               ( ( oFile->lOffSet + iEolOffSet + 2 ) < oFile->lLastByte ) )
  333.          {
  334.             oFile->isEof    = FALSE;
  335.             oFile->lOffSet += ( iEolOffSet + 2 );
  336.             oFile->lRecno++;
  337.          }
  338.          else
  339.          {
  340.             oFile->isEof = TRUE;
  341.             icRecs      = iRecs; // termina bucle
  342.          }
  343.       }
  344.    }
  345.    else
  346.    {
  347.       iRecs       = -iRecs;
  348.       oFile->isEof = FALSE;
  349.  
  350.       if ( ( oFile->lRecno - iRecs ) > 1 )      // <--- reversed if condition
  351.       {
  352.          for ( icRecs = iRecs; icRecs > 0; icRecs-- )
  353.          {
  354.             if ( LITBLOCK > oFile->lOffSet )
  355.             {
  356.                lReadPos = 0;
  357.                iLen     = (int) oFile->lOffSet;
  358.             }
  359.             else
  360.             {
  361.                lReadPos = oFile->lOffSet - LITBLOCK;
  362.                iLen     = LITBLOCK;
  363.             }
  364.  
  365.             _tlseek( oFile->iHandle, lReadPos, SEEK_SET );
  366.  
  367.             iLen = _tread( oFile->iHandle, cBuff, iLen );
  368.  
  369.             iEolOffSet = iScanBol( cBuff, iLen ) ;
  370.  
  371.             if( iLen - iEolOffSet )
  372.             {
  373.                 iEolOffSet = iScanBol( cBuff, iEolOffSet ) ;
  374.                 oFile->lOffSet = lReadPos + iEolOffSet + 2;
  375.                 oFile->lRecno--;
  376.             }
  377.             else
  378.             {
  379.                oFile->lOffSet = 0;
  380.                oFile->lRecno  = 1;
  381.             }
  382.          }
  383.       }
  384.       else
  385.       {
  386.          oFile->lOffSet = 0;
  387.          oFile->lRecno  = 1;
  388.       }
  389.    }
  390.  
  391.    _vmUnLock( oMBuff );
  392.  
  393.    return ( oFile->lRecno );
  394.  
  395. }
  396.  
  397. //---------------------------------------------------------------------------//
  398.  
  399. CLIPPER TFReadLn()
  400. {
  401.  
  402.    int iEolOffSet;
  403.    int iRead;
  404.    char * cBuff = _vmLock( oMBuff );
  405.  
  406.    GetStruct();
  407.  
  408.    if( oFile->iHandle )
  409.    {
  410.  
  411.        _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  412.  
  413.        iRead      = (int) _tread( oFile->iHandle, cBuff, LITBLOCK );
  414.  
  415.        iEolOffSet = iScanEol( cBuff, iRead );
  416.  
  417.        _retclen( cBuff, iEolOffSet );
  418.  
  419.    }
  420.    else
  421.       _retc( "" );
  422.  
  423.    _vmUnLock( oMBuff );
  424.  
  425.    SetStruct();
  426.  
  427. }
  428.  
  429. //---------------------------------------------------------------------------//
  430.  
  431. CLIPPER TFLastRec()
  432. {
  433.    LONG  lOldRec;
  434.    LONG  lOldOffSet;
  435.  
  436.    GetStruct();
  437.  
  438.    lOldRec    = oFile->lRecno;
  439.    lOldOffSet = oFile->lOffSet;
  440.  
  441.    TFGoBottom();
  442.  
  443.    GetStruct();
  444.  
  445.    _retnl( oFile->lLastRec );
  446.  
  447.    oFile->lRecno  = lOldRec;
  448.    oFile->lOffSet = lOldOffSet;
  449.  
  450.    SetStruct();
  451.  
  452. }
  453.  
  454. //---------------------------------------------------------------------------//
  455.  
  456. CLIPPER TFlBof()
  457. {
  458.    GetStruct();
  459.    _retl( ( oFile->lRecno == 1 ) );
  460.    SetStruct();
  461. }
  462.  
  463.  
  464. //---------------------------------------------------------------------------//
  465.  
  466. CLIPPER TFlEof()
  467. {
  468.    GetStruct();
  469.    _retl( oFile->isEof );
  470.    SetStruct();
  471. }
  472.  
  473. //---------------------------------------------------------------------------//
  474.  
  475. CLIPPER TFGoTo() // ( nRec )
  476. {
  477.    LONG lTarget  = _parnl( 1 );
  478.    LONG lLastRec = 0;
  479.  
  480.    GetStruct();
  481.  
  482.    if( oFile->iHandle )
  483.    {
  484.        if ( oFile->lRecno > lTarget )
  485.        {
  486.           while ( oFile->lRecno != lTarget )
  487.           {
  488.              lLastRec = oFile->lRecno;
  489.              lSkip( -1 );
  490.              if ( oFile->lRecno == lLastRec )
  491.                 break;
  492.           }
  493.        }
  494.        else
  495.        {
  496.           while ( oFile->lRecno != lTarget )
  497.           {
  498.              lLastRec = oFile->lRecno;
  499.              lSkip( 1 );
  500.              if ( oFile->lRecno == lLastRec )
  501.                 break;
  502.           }
  503.        }
  504.    }
  505.  
  506.    SetStruct();
  507. }
  508.  
  509. //---------------------------------------------------------------------------//
  510.  
  511. CLIPPER TFWriteLn() // ( cCadenaToWrite, lInsertMode )
  512. {
  513.    int iEolOffSet;
  514.    char * cBuff = _parc( 1 );
  515.    int iLen     = _parclen( 1 );
  516.    long read1;
  517.    long read2;
  518.    long end1;
  519.    long end2;
  520.  
  521.    if( oFile->iHandle )
  522.    {
  523.        char * pTmp  = _vmLock( oMBuff );
  524.        char * pBig1 = _vmLock( oMBig1 );
  525.        char * pBig2 = _vmLock( oMBig2 );
  526.  
  527.        GetStruct();
  528.  
  529.        /* find end of first record to be replaced */
  530.  
  531.        end1  = _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  532.        read1 = _tread ( oFile->iHandle, pTmp, LITBLOCK );
  533.  
  534.        /* if insert mode, leave pointer alone and skip below */
  535.  
  536.        if( _param( 2, LOGICAL ) && _parl( 2 ) )
  537.        {
  538.           iEolOffSet = 0;
  539.        }
  540.        else
  541.        {
  542.           iEolOffSet = iScanEol( pTmp, (int) read1 );
  543.        }
  544.  
  545.        /* save two buffers' worth of data from end of record on */
  546.                                 //
  547.        _tlseek( oFile->iHandle, end1 + iEolOffSet, SEEK_SET );
  548.        read1 = _tread( oFile->iHandle, pBig1, BIGBLOCK );  /* now read in a big glob */
  549.        read2 = _tread( oFile->iHandle, pBig2, BIGBLOCK );  /* now read in a big glob */
  550.        end2  = end1 + read1 + read1 + iEolOffSet;
  551.  
  552.        /* write the new record */
  553.                                 //
  554.        _tlseek( oFile->iHandle, end1, SEEK_SET );
  555.        _twrite( oFile->iHandle, cBuff, iLen );
  556.        end1 +=  (long)iLen;
  557.  
  558.        end1 = lFileMove( read1, read2, end1, end2, pBig1, pBig2 ); /* loop to write */
  559.                                 //
  560.        _tlseek( oFile->iHandle, end1, SEEK_SET );
  561.        _twrite( oFile->iHandle, pBig1, 0 );
  562.        oFile->lLastRec  = 0;
  563.        oFile->lLastByte = _tlseek( oFile->iHandle, 0L, SEEK_END );
  564.        _vmUnLock( oMBuff );
  565.        _vmUnLock( oMBig1 );
  566.        _vmUnLock( oMBig2 );
  567.  
  568.        SetStruct();
  569.  
  570.    }
  571. }
  572.  
  573. //---------------------------------------------------------------------------//
  574.  
  575. CLIPPER TFAppend() // nLines
  576. {
  577.    int iLines = ( ISNUM( 1 ) ? _parni( 1 ) : 1 );
  578.    long read1;
  579.    int iIdx;
  580.  
  581.    if( oFile->iHandle )
  582.    {
  583.        char * pBuff = _vmLock( oMBuff );
  584.  
  585.        /* go to end of file */
  586.  
  587.        TFGoBottom();
  588.  
  589.        GetStruct();
  590.  
  591.        /* find end of record */
  592.  
  593.        _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  594.        read1 = _tread( oFile->iHandle, pBuff, LITBLOCK );
  595.  
  596.        /* determine if CRLF pair exists, if not, add one */
  597.  
  598.        if ( iScanEol( pBuff, (int)read1 ) == (int)read1 )
  599.        {
  600.           _tlseek( oFile->iHandle, oFile->lLastByte, SEEK_SET );
  601.           _twrite( oFile->iHandle, crlf, 2 );
  602.           iLines--;
  603.        }
  604.  
  605.        /* loop to write new lines */
  606.  
  607.        for( iIdx = 0; iIdx < iLines; iIdx++ )
  608.            _twrite( oFile->iHandle, crlf, 2 );
  609.  
  610.        _vmUnLock( oMBuff );
  611.  
  612.        oFile->lLastRec = 0L;
  613.  
  614.        TFGoBottom();  // El SetStruct() de gobottom guarda los datos del objeto.
  615.    }
  616. }
  617.  
  618. //---------------------------------------------------------------------------//
  619.  
  620. CLIPPER TFDelete() // ( nLines )
  621. {
  622.    int  iLines = ( ISNUM( 1 ) ? _parni( 1 ) : 1 );
  623.    long read1;
  624.    long read2;
  625.    long end1;
  626.    long end2;
  627.    long lCurRec;
  628.    long lCurOff;
  629.  
  630.    if( oFile->iHandle )
  631.    {
  632.        char * pBig1 = _vmLock( oMBig1 );
  633.        char * pBig2 = _vmLock( oMBig2 );
  634.  
  635.        GetStruct();
  636.  
  637.        lCurRec = oFile->lRecno;
  638.        lCurOff = oFile->lOffSet;
  639.  
  640.        /* save address to current record ( first record to be deleted ) */
  641.        end1 = lCurOff;
  642.  
  643.        /* skip over deleted records, point to first 'to be retained' record */
  644.  
  645.        lSkip( iLines ) ;
  646.        _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  647.  
  648.        /* save two buffers' worth of data */
  649.        read1 = _tread( oFile->iHandle, pBig1, BIGBLOCK );  /* now read in a big glob */
  650.        read2 = _tread( oFile->iHandle, pBig2, BIGBLOCK );  /* now read in a big glob */
  651.        end2  = oFile->lOffSet+ read1 + read1;
  652.  
  653.        end1 = lFileMove( read1, read2, end1, end2, pBig1, pBig2 ); /* loop to write */
  654.                                 //
  655.        _tlseek( oFile->iHandle, end1, SEEK_SET );
  656.        _twrite( oFile->iHandle, pBig1, 0 );
  657.        oFile->lLastRec  = 0;
  658.        oFile->lLastByte = _tlseek( oFile->iHandle, 0L, SEEK_END );
  659.        oFile->lRecno    = lCurRec;
  660.        oFile->lOffSet   = lCurOff;
  661.  
  662.        _vmUnLock( oMBig1 );
  663.        _vmUnLock( oMBig2 );
  664.  
  665.        SetStruct();
  666.    }
  667. }
  668.  
  669. //---------------------------------------------------------------------------//
  670.  
  671. CLIPPER TFInsert() // ( [ nLines ] )
  672. {
  673.    int iLines = ( ISNUM( 1 ) ? _parni( 1 ) : 1 );
  674.    long read1;
  675.    long read2;
  676.    long end1;
  677.    long end2;
  678.  
  679.    if( oFile->iHandle )
  680.    {
  681.        char * pBig1 = _vmLock( oMBig1 );
  682.        char * pBig2 = _vmLock( oMBig2 );
  683.  
  684.        GetStruct();
  685.  
  686.        /* find end of first record to be replaced */
  687.        end1 = _tlseek( oFile->iHandle, oFile->lOffSet, SEEK_SET );
  688.  
  689.        /* save two buffers' worth of data from current record */
  690.        read1 = _tread( oFile->iHandle, pBig1, BIGBLOCK );  /* now read in a big glob */
  691.        read2 = _tread( oFile->iHandle, pBig2, BIGBLOCK );  /* now read in a big glob */
  692.        end2  = end1 + read1 + read2;
  693.  
  694.        /* write the new records */
  695.                                 //
  696.        _tlseek( oFile->iHandle, end1, SEEK_SET );
  697.  
  698.  
  699.        /* need this loop to consider that No. lines inserted may be more than
  700.           the amount saved by the two buffers above
  701.        */
  702.  
  703.        do
  704.        {
  705.           _twrite( oFile->iHandle, crlf, 2 );
  706.           end1 += 2;
  707.        } while( --iLines );
  708.  
  709.        end1 = lFileMove( read1, read2, end1, end2, pBig1, pBig2 ); /* loop to write */
  710.                                                    //
  711.        oFile->lLastByte = _tlseek( oFile->iHandle, end1, SEEK_SET );
  712.        oFile->lLastRec  = 0L;
  713.        _twrite( oFile->iHandle, pBig1, 0 );
  714.  
  715.        _vmUnLock( oMBig1 );
  716.        _vmUnLock( oMBig2 );
  717.  
  718.        SetStruct();
  719.    }
  720. }
  721.  
  722. //---------------------------------------------------------------------------//
  723.  
  724. //  Busca el Par CRLF en un buffer.
  725.  
  726. static int near iScanEol( char *buf, int buf_len )
  727. {
  728.    asm {
  729.             push  di             // save flags and registers
  730.             push  es
  731.             pushf
  732.             cld                  // move forward
  733.             les   di, buf        // point to buffer
  734.             mov   bx, di         // save buffer start for offset calc later
  735.             mov   cx, buf_len    // scan entire buffer
  736.             mov   al, 00Dh
  737.        }
  738.    _feol1:
  739.    asm {
  740.             repne scasb        // look for a CR
  741.             jcxz  _feolerr       // no find, return entire buffer
  742.             cmp   byte ptr es:[di], 00Ah    // got a CRLF pair?
  743.             jne   _feol1
  744.             dec   di
  745.             jmp   _feoldone
  746.        }
  747.  
  748.    _feolerr:
  749.    asm {
  750.             mov   di, bx         // on no find return entire length of buffer
  751.             add   di, buf_len    //  but truncate any LF or EOF markers
  752.             cmp   byte ptr es:[di-1], 01Ah // test for end of file marker
  753.             je    _feolerr1
  754.             cmp   byte ptr es:[di-1], 00Ah // test for an errant LF
  755.             jne   _feoldone
  756.        }
  757.  
  758.    _feolerr1:
  759.    asm      dec   di;
  760.  
  761.    _feoldone:
  762.    asm {
  763.             mov   ax, di         // subtract current pointer pos from start to
  764.             sub   ax, bx         // learn offset within buffer
  765.             popf
  766.             pop   es
  767.             pop   di
  768.        }
  769.  
  770.    return _AX;
  771. }
  772.  
  773. //---------------------------------------------------------------------------//
  774.  
  775. //  Busca el Par CRLF en un buffer. PA' atras.
  776.  
  777. static int near iScanBol( char *buf, int buf_len )
  778. {
  779.    asm {
  780.             push  di             // save flags and registers
  781.             push  es
  782.             pushf
  783.             std                  // move back'rdz
  784.             les   di, buf        // point to buffer tail
  785.             mov   bx, di         // save buffer start for offset calc later
  786.             add   di, buf_len
  787.             dec   di
  788.             mov   cx, buf_len    // scan entire buffer
  789.             mov   al, 00Dh
  790.        }
  791.    _fbol1:
  792.    asm {
  793.             repne scasb          // look for a CR
  794.             jcxz  _fbolerr       // no find, return entire buffer
  795.             cmp   byte ptr es:[di+2], 00Ah  // check for CRLF pair
  796.             jne   _fbol1
  797.             inc   di             // yes, point to CR
  798.             jmp   _fboldone      // otherwise keep looking
  799.        }
  800.    _fbolerr:
  801.    asm      mov   di, bx;        // on no find return length of buffer
  802.    _fboldone:
  803.    asm {
  804.             mov   ax, di         // subtract current pointer pos from start to
  805.             sub   ax, bx         //  learn offset within buffer
  806.             popf
  807.             pop   es
  808.             pop   di
  809.        }
  810.  
  811.    return _AX;
  812. }
  813.  
  814. //---------------------------------------------------------------------------//
  815.  
  816. // Mueve texto en el fichero arriba ó abajo despues de "Insert" ó "delete".
  817.  
  818. static long lFileMove( long read1, long read2, long end1, long end2,
  819.                        char * pBuff1, char * pBuff2 )
  820. {
  821.    do
  822.    {                           //
  823.       _tlseek( oFile->iHandle, end1, SEEK_SET );
  824.       _twrite( oFile->iHandle, pBuff1, (int)read1 );
  825.       end1 += read1 ;     // end1 should now point to eof
  826.  
  827.       if( read2 == 0 )
  828.       {
  829.          break;
  830.       }
  831.                                //
  832.       _tlseek( oFile->iHandle, end2, SEEK_SET );
  833.       read1 = _tread( oFile->iHandle, pBuff1, BIGBLOCK );
  834.       end2 += read1;
  835.                                //
  836.       _tlseek( oFile->iHandle, end1, SEEK_SET );
  837.       _twrite( oFile->iHandle, pBuff2, (int)read2 );
  838.       end1 += read2 ;
  839.                                //
  840.       _tlseek( oFile->iHandle, end2, SEEK_SET );
  841.       read2 = _tread( oFile->iHandle, pBuff2, BIGBLOCK );   // now read in a big glob
  842.       end2 += read2 ;
  843.  
  844.    } while ( read1 > 0 );
  845.  
  846.    return ( end1 );
  847.  
  848. }
  849.  
  850.  
  851. //---------------------------------------------------------------------------//
  852.  
  853. CLIPPER __TFInit() // ( nClassHandle )
  854. {
  855.     if( !oMBuff )
  856.     {
  857.         oMBuff  = _vmAlloc( KLITBLOCK );
  858.         oMBig1  = _vmAlloc( KBIGBLOCK );
  859.         oMBig2  = _vmAlloc( KBIGBLOCK );
  860.     }
  861. }
  862.  
  863. //---------------------------------------------------------------------------//
  864.