home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 April B / Pcwk4b98.iso / Borland / Dbase50w / EXTERN.PAK / DBFILE.CPP < prev    next >
C/C++ Source or Header  |  1994-08-02  |  23KB  |  851 lines

  1. //============================================================================
  2. //
  3. // Dbfile.cpp
  4. //
  5. // Main source file for dbfile, a dBASE for Windows example.
  6. //
  7. // This example implements a series of textfile manipulation routines. These
  8. // routines are accessible from dBASEWin through the EXTERN system.
  9. // A Textfile object on the dBASE side initiates the contact by creating
  10. // a corresponding C++ Textfile object through a call to TFinit which 
  11. // returns a pointer to that C++ object to the dBASE object.  After that
  12. // the dBASE object can call into this DLL for specific routines.  The
  13. // C++ routine calls back to the dBASE object through DBase->GetThis()
  14. // to get the this pointer of the corresponding C++ object and calls
  15. // the wanted memberfunction of that object.
  16. //
  17. // Right now the available routines are: 
  18. //     close               - closes the current file if any.
  19. //     eof                 - helps detect EOF.
  20. //     error               - tells if an error was encountered.
  21. //     fieldseparator      - sets the field separator.
  22. //     filter              - sets the filter string.
  23. //     geterror            - returns the last error encountered if any.
  24. //     getfield            - gets the next field of the current record.
  25. //     getline             - gets the next line.
  26. //     getrec              - gets the next record.
  27. //     lineseparator       - sets the line separator.
  28. //     open                - opens a file.
  29. //     release             - releases the C++ object.
  30. //
  31. // A line is ended by a lineseparator or EOF. If you add a '+' char
  32. // to the char you send to "SetLineSeparator" it is assumed that
  33. // the lineseparator is one or more char's of that lineseparator.
  34. // A rec is a line that contains fields. Getrec sets up the fields 
  35. // and returns the number of fields in the current rec. A field is 
  36. // surrounded by one or more field separators including as special 
  37. // cases the start and the end of a line.  
  38. // If the filter is set a getline or getrec will search till
  39. // a line is found that contains the filter string as a substring.
  40. //
  41. // The file dbfile.h will give a quick idea of how the C++ class is
  42. // set up. The file dbfile.prg will tell you how things work on the
  43. // dBASEWin side.  The file dbasevar.h deals with the basic classes
  44. // that ease the communication between C++ and dBASEWin.
  45. //
  46. //============================================================================
  47.  
  48.    // Get the header.
  49. #include "dbfile.h"
  50.  
  51.    // If you want to test the TextFile C++ class under DOS, define DOSTEST.
  52.    // This will isolate the class from any Windows and dBASE details and
  53.    // allows this file to be compiled and linked with DOS programs.
  54. #ifndef DOSTEST
  55.  
  56. //============================================================================
  57. //
  58. //  You can create an instance of class CSession in DBaseInitInstance() 
  59. //  and set it up. In subsequent call backs, a pointer to this instance 
  60. //  can be retrieved with a call to GetSession().  Data that is kept on 
  61. //  a per-instance basis (DBaseVars for example) should be kept in the 
  62. //  session object.
  63. //
  64. //============================================================================
  65.  
  66. class CSession {
  67. public:
  68.  
  69.    // Local objects.
  70.  
  71.    CSession(){
  72.        // Initialize objects local to this session.
  73.    }
  74.    ~CSession(){
  75.        // Destroy objects local to this session.
  76.    }
  77.  
  78.    // Memberfunctions to use local objects.
  79. };
  80.  
  81.  
  82. extern "C" {
  83.  
  84. //============================================================================
  85. //
  86. //  Usual DLL functions.
  87. //
  88. //============================================================================
  89.  
  90. int FAR PASCAL LibMain(HINSTANCE, WORD, WORD, LPSTR){
  91.  
  92.    return 1;
  93. }
  94. int CALLBACK WEP(int /*nParam*/){return(1);}
  95.  
  96. //
  97. //  This function is called every time an Instance of dBASE loads the DLL.  
  98. //  If for some reason the DLL determines that it cannot load, it can return 
  99. //  an error.  If the DLL loads properly it should return DBASE_INIT_OK.
  100. //
  101.  
  102. int CALLBACK DBaseInitInstance(void){
  103.  
  104.    asm int 3;     // break point for the debugger.
  105.  
  106.    DBase()->SetSession(new CSession());
  107.  
  108.        //
  109.        // Possible Error return Values
  110.        //
  111.        //return DBASE_INIT_NO_MULTI_INSTANCE;
  112.        //return DBASE_INIT_ERROR;
  113.  
  114.    return DBASE_INIT_OK;
  115. }
  116.  
  117. //
  118. //  DBaseExitInstance() is called when an instance of dBASE terminates or 
  119. //  manually unloads a DLL through the RELEASE DLL command.  This give the 
  120. //  DLL a chance to free any resources associated with a running instance.
  121. //
  122.  
  123. void CALLBACK DBaseExitInstance(void){
  124. }
  125.  
  126.    // End of DOSTEST define
  127. #endif
  128.  
  129. //============================================================================
  130. //
  131. // Implementation of memberfunctions of the TextFile class.
  132. //
  133. //============================================================================
  134.  
  135.    // Some common defines.
  136. #define LINE  0
  137. #define REC   1
  138.  
  139. //
  140. // AddToText( char*, char * ).
  141. //
  142. // Helper function to append a char string to the Text string. The 
  143. // Text buffer grows as needed to fit the largest rec or line 
  144. // encountered in the file.
  145. //
  146. // Returns 1 on success, 0 on error.
  147. //
  148.  
  149. BOOL TextFile::AddToText( char * Begin, char * End ) {
  150.  
  151.    unsigned int Len;
  152.    char SaveIt = *End;
  153.  
  154.        // Zero terminate the incoming string.
  155.    *End = 0x0;
  156.    Len = strlen( Begin );
  157.        
  158.        // See if we need more room.
  159.    if( (TextLen + Len) > MaxTextLen ) {
  160.        char * NewText;
  161.  
  162. #ifdef NO_EXCEPTIONS
  163.  
  164.        MaxTextLen = TextLen + Len;
  165.        NewText = new char[ MaxTextLen + 1 ];
  166.        if( NewText != NULL ) {
  167.            strcpy( NewText, Text );
  168.            delete [] Text;
  169.            Text = NewText;
  170.        }
  171.        else {
  172.                // Must be something wrong.
  173.            Text[0] = 0x0;
  174.            TextLen = 0;
  175.            *End = SaveIt;
  176.            return 0;
  177.        }
  178.  
  179. #else  // NO_EXCEPTIONS
  180.  
  181.        try {
  182.            MaxTextLen = TextLen + Len;
  183.            NewText = new char[ MaxTextLen + 1 ];
  184.            strcpy( NewText, Text );
  185.            delete [] Text;
  186.            Text = NewText;
  187.        }
  188.        catch(...) {
  189.            
  190.                // Must be something wrong.
  191.            Text[0] = 0x0;
  192.            TextLen = 0;
  193.            *End = SaveIt;
  194.            return 0;
  195.        }
  196.  
  197. #endif  // NO_EXCEPTIONS
  198.  
  199.    }
  200.        // Now simply copy it in.
  201.    strcpy( Text + TextLen, Begin );
  202.    TextLen += Len;
  203.  
  204.        // Restore.
  205.    *End = SaveIt;
  206.  
  207.        // Return success.
  208.    return 1;
  209. }
  210.            
  211. //
  212. // Close(). 
  213. //
  214. // Closes the file and sets Handle to 0.
  215. //
  216. // Returns 1 on success, 0 on error.
  217. //
  218.  
  219. BOOL TextFile::Close() {
  220.  
  221.    if( Handle != 0 )
  222.        if( close( Handle ) != 0 )
  223.            return 0;
  224.  
  225.    Handle = 0;
  226.  
  227.        // return success.
  228.    return 1;
  229. }
  230.  
  231. //
  232. // GetField( int ). 
  233. //
  234. // This returns a pointer to the field specified by the WhichField 
  235. // parameter.  The fields are contained inside a rec separated by
  236. // single fieldseparators.  When you send a field away, you simply insert
  237. // a zero at the end of that field.  Next time you come back here you
  238. // put that separator back which you can always find as the first char
  239. // of the Text buffer.
  240. //
  241. // Returns pointer to field, or pointer to empty string in case of error.
  242. //
  243.  
  244. char * TextFile::GetField( int WhichField ) {
  245.  
  246.    char *FieldStart = Text + 1, *FieldEnd = Text + 1, Separator = Text[0];
  247.  
  248.        // First see if we have to reinsert the end of a previous
  249.        // field we sent away.
  250.    if( SaveFieldEndPtr != NULL ) {
  251.        *SaveFieldEndPtr = Text[0];
  252.        SaveFieldEndPtr = NULL;
  253.    }
  254.  
  255.        // Check if we have the field at all.
  256.    if( WhichField <= 0 || WhichField > NumberOfFields ) 
  257.        return "";
  258.  
  259.        // Find the field in the Text buffer.
  260.    while( --WhichField > 0 ) {
  261.        FieldStart = strchr( FieldStart, Separator );
  262.        if( FieldStart == NULL ) {
  263.            strcpy( ErrorString, "Record corrupted" );
  264.            return "";
  265.        }
  266.        FieldStart++;
  267.    }
  268.  
  269.        // Find the end and mark it.
  270.    FieldEnd = strchr( FieldStart, Separator );
  271.    if( FieldEnd != NULL ) {
  272.        SaveFieldEndPtr = FieldEnd;
  273.        *FieldEnd = 0x0;
  274.    }
  275.  
  276.        // Send it away.
  277.    return FieldStart;
  278. }
  279.  
  280.  
  281. //
  282. // Open( char* ). 
  283. //
  284. // If a file was already open, that file is closed before the 
  285. // requested file is opened.  Handle is set to the file.
  286. //
  287. // Returns 1 on success, 0 on error.
  288. //
  289.  
  290. BOOL TextFile::Open( char *FileToOpen ) {
  291.    
  292.       // Is there already a file open.
  293.       // If so, close it. Check for proper return.
  294.    if( Handle != 0 )
  295.       if( close( Handle ) != 0 )
  296.          return 0;
  297.  
  298.       // Now open the file requested. Check for valid pointer return.
  299.    if( ( Handle = open( FileToOpen, O_RDONLY | O_TEXT ) ) == -1 )
  300.       return 0;
  301.  
  302.        // Start a new errorstring. Set up the Buffer.
  303.    ErrorString[ 0 ] = 0x0;
  304.    BufPtr = Buffer;
  305.    Buffer[ 0 ] = 0x0;
  306.  
  307.       // Return success.
  308.    return 1;
  309. }
  310.  
  311. //
  312. // ReadNextItem( char ).
  313. //
  314. // Reads the next item, either a line or a rec as indicated by the
  315. // LineOrRec parameter, into the Text character buffer.  The file 
  316. // is buffer by buffer read into Buffer.  Buffer is scanned for
  317. // separators and EOF.  After a field separator is found we handle 
  318. // field details if we're reading a rec.  After we find a line separator 
  319. // the BufPtr is set to after the separator for the next readitem.
  320. // The Buffer is flushed into the Text buffer after each field and
  321. // line or when the Buffer runs out.  At the end a complete next
  322. // line or rec will be in the Text buffer.
  323. //
  324. // Returns Text on success, "" on error.
  325. //
  326.  
  327. char * TextFile::ReadNextItem( char LineOrRec ) {
  328.  
  329.    char Done, Found = 0, StartOfRec;
  330.    unsigned int NumberOfBytes;
  331.    char BothSeparators[3] = { LineSeparator, 0x0, 0x0 };
  332.    char * SepPtr = NULL, SepFound = 0x0;
  333.  
  334.        // In error state?
  335.    if( Error() )
  336.        return "";
  337.  
  338.        // Are we in business already?
  339.    if( Handle == 0 ) {
  340.        strcpy( ErrorString, "No file open\n" );
  341.        return "";
  342.    }
  343.  
  344.        // If we're scanning for a rec, we need the fieldseparator.
  345.    if( LineOrRec == REC ) 
  346.        BothSeparators[1] = FieldSeparator;
  347.  
  348.        // Keep reading till we found the next item.
  349.    while( !Found ) {
  350.  
  351.            // Set up for the search and initialize Text.
  352.        Done = 0;
  353.        Text[0] = 0x0;
  354.        TextLen = 0;
  355.        NumberOfFields = 0;
  356.        SaveFieldEndPtr = NULL;
  357.        StartOfRec = (LineOrRec == REC );
  358.  
  359.            // Read and scan till we find a separator or EOF.
  360.        while( !Done ) {
  361.  
  362.                // Did we run out of chars in the Buffer.
  363.            if( *BufPtr == 0x0 ) {
  364.  
  365.                    // Read in a buffer full. 
  366.                NumberOfBytes = (unsigned int) read( Handle, 
  367.                                                     Buffer, BUFFERLENGTH );
  368.  
  369.                    // Check for EOF or error.
  370.                if( NumberOfBytes == (unsigned int) -1 || 
  371.                    NumberOfBytes == 0 ) {
  372.                    if( NumberOfBytes != 0 ) {
  373.                        strcpy( ErrorString, "Error Reading\n" );
  374.                        return "";   // Error.
  375.                    }
  376.                    Done = 1;        // EOF.
  377.  
  378.                        // If there's nothing in the textbuffer we
  379.                        // can't find a next item.
  380.                    if( Text[0] == 0x0 ) {
  381.                        Found = 1;
  382.                    }
  383.                        // But if there is something check if we have
  384.                        // the last field of the file that we haven't
  385.                        // counted yet.
  386.                    else if( LineOrRec == REC && SepFound == 0x0 )
  387.                        NumberOfFields++;
  388.                        
  389.                    continue;
  390.                }
  391.  
  392.                    // Set up for the search.
  393.                BufPtr = Buffer;
  394.                *( BufPtr + NumberOfBytes ) = 0x0;
  395.                CopyPtr = Buffer;
  396.            }
  397.  
  398.                // If we scan for a REC, first eat any fieldseparators
  399.                // at the beginning. If we run out of Buffer, fall
  400.                // through and read more. We also put the current
  401.                // fieldseparator as the first char of the Text.
  402.            if( StartOfRec == 1 ) {
  403.  
  404.                while( *BufPtr == FieldSeparator )
  405.                    BufPtr++;
  406.                if( *BufPtr == 0x0 ) 
  407.                    continue;
  408.  
  409.                StartOfRec = 0;
  410.                Text[ 0 ] = FieldSeparator;
  411.                TextLen++;
  412.                CopyPtr = BufPtr;
  413.            }
  414.  
  415.                // Look for the next separator IF we're not already
  416.                // inside a separator. 
  417.            if( SepFound == 0x0 ) {
  418.  
  419.                    // Cruise till we find a separator.
  420.                SepPtr = strpbrk( BufPtr, BothSeparators );
  421.  
  422.                    // If we found a separator.
  423.                if( SepPtr != NULL ) {
  424.  
  425.                        // Mark the end. 
  426.                    BufPtr = SepPtr;
  427.                    SepFound = *SepPtr;
  428.  
  429.                        // If we are looking for fields.
  430.                    if( LineOrRec == REC ) {
  431.  
  432.                            // Increase number of fields. Send one 
  433.                            // fieldseparator to text as well IF
  434.                            // we found a fieldseparator.
  435.                        NumberOfFields++;
  436.                        if( SepFound == FieldSeparator )
  437.                            BufPtr++;
  438.                    }
  439.                }
  440.                else {  // We did not find a separator. Adjust BufPtr.
  441.  
  442.                    BufPtr += strlen( BufPtr );
  443.                }
  444.  
  445.                    // Add what we have to Text.
  446.                if( AddToText( CopyPtr, BufPtr ) == 0 ) {
  447.            
  448.                        // Error occured.
  449.                    strcpy( ErrorString, "Line/Field too long" );
  450.                    return "";
  451.                }
  452.            }
  453.  
  454.                // If we found a separator ( or are inside a separator ).
  455.            if( SepFound != 0x0 ) {
  456.  
  457.                    // If we found a lineseparator and only singles of
  458.                    // those are allowed, simply skip one and continue.
  459.                if( SepFound == LineSeparator && PlusLineSeparator == 0 ) {
  460.                    BufPtr++;
  461.                    SepFound = 0x0;
  462.                    Done = 1;
  463.                    CopyPtr = BufPtr;
  464.                    continue;
  465.                }
  466.  
  467.                    // Now we scan till we run out of separators.
  468.                while( *BufPtr == SepFound ) 
  469.                    BufPtr++;
  470.  
  471.                    // If we found the end of the buffer, fall
  472.                    // through and continue reading.
  473.                if( *BufPtr == 0x0 ) 
  474.                    continue;
  475.  
  476.                    // Special case for when we found a lineseparator
  477.                    // after a bunch of fieldseparators. Means we have
  478.                    // to fall through and scan for the end of the rec.
  479.                if( *BufPtr == LineSeparator ) {
  480.                    SepFound = LineSeparator;
  481.                    continue;
  482.                }
  483.                    
  484.                    // We're done IF we were looking for lineseparator(s).
  485.                if( SepFound == LineSeparator )
  486.                    Done = 1;
  487.  
  488.                    // Either way, we're done with the separator found.
  489.                    // And we can adjust copyptr.
  490.                SepFound = 0x0;
  491.                CopyPtr = BufPtr;
  492.            }
  493.        }
  494.  
  495.            // Now see if a filter is in place.
  496.        if( Filter[0] != 0x0 ) {
  497.            if( strstr( Text, Filter ) != NULL )
  498.                Found = 1;
  499.        }
  500.        else {
  501.                // Otherwise we have found what we wanted.
  502.            Found = 1;
  503.        }
  504.    }
  505.  
  506.        // Return success.
  507.    return Text;
  508. }
  509.  
  510. //
  511. // SetFilter( char* ). 
  512. //
  513. // Sets the Filter char string. ReadNextItem only returns the next 
  514. // item IF it contains the Filter string as a substring.
  515. // Can be called with SetFilter( "" ) to set the filter to nothing.
  516. //
  517. // Returns 1 on success. 0 on error.
  518. //
  519.  
  520. BOOL TextFile::SetFilter( char *InFilter ) {
  521.    
  522.    unsigned int Len = strlen( InFilter );
  523.  
  524.        // If there's enough room, copy it in and leave.
  525.    if( Len <= FilterLen ) {
  526.        strcpy( Filter, InFilter );
  527.        return 1;
  528.    }
  529.        // Not enough room, start with a clean slate.
  530.    delete [] Filter;
  531.  
  532.        // Create some room.
  533.  
  534. #ifdef NO_EXCEPTIONS
  535.  
  536.    Filter = new char [ Len + 1 ];
  537.    if( Filter != NULL ){
  538.        FilterLen = Len;
  539.    }
  540.    else {
  541.            // Guess not.
  542.        strcpy( ErrorString, "Filter too long" );
  543.        FilterLen = 0;
  544.        return 0;
  545.    }
  546.  
  547. #else // NO_EXCEPTIONS
  548.  
  549.    try {
  550.        Filter = new char [ Len + 1 ];
  551.        FilterLen = Len;
  552.    }
  553.    catch(...) {
  554.            // Guess not.
  555.        strcpy( ErrorString, "Filter too long" );
  556.        FilterLen = 0;
  557.        return 0;
  558.    }
  559.  
  560. #endif // NO_EXCEPTIONS
  561.  
  562.    strcpy( Filter, InFilter );
  563.  
  564.        // Success.
  565.    return 1;
  566. }
  567.  
  568. //
  569. // SetFieldSeparator( char * ). 
  570. //
  571. // Sets the fieldseparator char. 
  572. //
  573. // Returns 1 on success, 0 on error.
  574. //
  575.  
  576. BOOL TextFile::SetFieldSeparator( char *Separator ) {
  577.  
  578.        // If nothing there, ignore, but return error.
  579.    if( Separator == NULL )  
  580.        return 0;
  581.  
  582.        // Set the FieldSeparator. 
  583.    FieldSeparator = *Separator;
  584.  
  585.        // We did it.
  586.    return 1;
  587. }
  588.  
  589. //
  590. // SetLineSeparator( char * ). 
  591. //
  592. // Sets the lineseparator char. If the second char of the incoming 
  593. // string is a '+' it is assumed that the separator is multiples of 
  594. // the lineseparator char.
  595. //
  596. // ASSUMES a string is sent over, not a single character!!
  597. //
  598. // Returns 1 on success, 0 on error.
  599. //
  600.  
  601. BOOL TextFile::SetLineSeparator( char *Separator ) {
  602.  
  603.        // If nothing there, ignore, but return error.
  604.    if( Separator == NULL )  
  605.        return 0;
  606.  
  607.        // Set the LineSeparator and PlusLineSeparator if needed.
  608.    LineSeparator = *Separator;
  609.    if( *(Separator+1) == '+' )
  610.        PlusLineSeparator = 1;
  611.    else
  612.        PlusLineSeparator = 0;
  613.  
  614.        // We did it.
  615.    return 1;
  616. }
  617.  
  618.    // If you want to test the C++ class under DOS, define DOSTEST.
  619. #ifndef DOSTEST
  620.  
  621. //============================================================================
  622.  
  623. //
  624. // TextFile routines called from the dBASEWin side.
  625. //
  626.  
  627. //============================================================================
  628.  
  629. //
  630. // GetCPlusPlusThis().
  631. //
  632. // Helper function to get the C++ this pointer out of the dBASEWin object.
  633. //
  634. // Returns a TextFile pointer.
  635. //
  636.  
  637. TextFile* GetCPlusPlusThis() {
  638.  
  639.        // Local vars. Get the this of the dBASEWin object.
  640.    DVar CThis, DBaseThis( DBase()->GetThis() );
  641.  
  642.        // Get the this of the corresponding C++ object.
  643.    DBaseThis->Property( "MYSTRUCT", CThis );
  644.  
  645.    return (TextFile*)(CThis->Long());
  646. }
  647.  
  648. //
  649. // TFclose().
  650. //
  651. // Closes the file.
  652. //
  653. // Returns 1 on success, 0 on error.
  654. //
  655.  
  656. BOOL _export _pascal TFclose() {
  657.  
  658.    return GetCPlusPlusThis()->Close();
  659. }
  660.  
  661. //
  662. // TFeof().
  663. //
  664. // Returns 1 on EOF, 0 otherwise.
  665. //
  666.  
  667. BOOL _export _pascal TFeof() {
  668.  
  669.    return GetCPlusPlusThis()->Eof();
  670. }
  671.  
  672. //
  673. // TFerror().
  674. //
  675. // Returns 1 on error set, 0 otherwise.
  676. //
  677.  
  678. BOOL _export _pascal TFerror() {
  679.  
  680.    return GetCPlusPlusThis()->Error();
  681. }
  682.  
  683. //
  684. // TFfilter( char* ).
  685. //
  686. // Sets the filter.
  687. //
  688. // Returns 1 on success, 0 on error.
  689. //
  690.  
  691. BOOL _export _pascal TFfilter( char * Filter ) {
  692.  
  693.    return GetCPlusPlusThis()->SetFilter( Filter );
  694. }
  695.  
  696. //
  697. // TFfieldseparator( char* ).
  698. //
  699. // Sets the fieldseparator char.
  700. //
  701. // Returns 1 on success, 0 on error.
  702. //
  703.  
  704. BOOL _export _pascal TFfieldseparator( char *InString ) {
  705.    
  706.    return GetCPlusPlusThis()->SetFieldSeparator( InString );
  707. }
  708.  
  709. //
  710. // TFgeterror().
  711. //
  712. // Returns pointer to the errorstring of the object.
  713. //
  714.  
  715. char * _export _pascal TFgeterror() {
  716.  
  717.    return GetCPlusPlusThis()->GetErrorString();
  718. }
  719.  
  720. //
  721. // TFgetfield( int ).
  722. //
  723. // Returna a pointer to the field as indicated by the parameter.
  724. //
  725. // Returns pointer to a field on success, "" on error.
  726. //
  727.  
  728. char * _export _pascal TFgetfield( int WhichField ) {
  729.  
  730.    return GetCPlusPlusThis()->GetField( WhichField );
  731. }
  732.  
  733. //
  734. // TFgetrec()
  735. //
  736. // Returns # of fields in the next rec on success, 0 on error or EOF.
  737. //
  738.  
  739. int _export _pascal TFgetrec() {
  740.  
  741.    TextFile * TFptr = GetCPlusPlusThis();
  742.    if( TFptr->ReadNextItem( REC ) != NULL )
  743.        return TFptr->GetNumberOfFields();
  744.    else
  745.        return 0;
  746. }
  747.  
  748. //
  749. // TFgetline().
  750. //
  751. // Returns pointer to the next line on success, "" on error or on EOF.
  752. //
  753.  
  754. char * _export _pascal TFgetline() {
  755.  
  756.    return GetCPlusPlusThis()->ReadNextItem( LINE );
  757. }
  758.  
  759. //
  760. // TFinit().
  761. //
  762. // Initialization routine called from dBASEWin when the dBASEWin 
  763. // textfile object gets created.
  764. //
  765. // Return pointer (cast to a long) to a C++ TextFile object on success, 
  766. // 0 on error.
  767. //
  768.  
  769. long _export _pascal TFinit() {
  770.  
  771.    TextFile * ThisTextFile;
  772.  
  773. #ifdef NO_EXCEPTIONS
  774.  
  775.        // Get the this of the CTextFile to be used.
  776.    ThisTextFile = new TextFile;
  777.    if( ThisTextFile != NULL ) {
  778.  
  779.            // Return pointer cast to a long.
  780.        return (long) ThisTextFile;
  781.    }
  782.    else {
  783.  
  784.            // Failure.
  785.        return 0L;
  786.    }
  787.  
  788. #else  // NO_EXCEPTIONS
  789.  
  790.    try {
  791.  
  792.            // Get the this of the CTextFile to be used.
  793.        ThisTextFile = new TextFile;
  794.  
  795.            // Return pointer cast to a long.
  796.        return (long) ThisTextFile;
  797.    }
  798.    catch( ... ) {
  799.  
  800.            // Failure.
  801.        return 0L;
  802.    }
  803.  
  804. #endif  // NO_EXCEPTIONS
  805.  
  806. }
  807.  
  808. //
  809. // TFlineseparator( char* ).
  810. //
  811. // Sets the line separator char.
  812. //
  813. // Returns 1 on success, 0 on error.
  814. //
  815.  
  816. BOOL _export _pascal TFlineseparator( char *InString ) {
  817.    
  818.    return GetCPlusPlusThis()->SetLineSeparator( InString );
  819. }
  820.  
  821. //
  822. // TFopen( char* ).
  823. //
  824. // Opens a new file.
  825. //
  826. // Returns 1 on sucess, 0 on error.
  827. //
  828.  
  829. BOOL _export _pascal TFopen( char * FileToOpen ) {
  830.  
  831.    return GetCPlusPlusThis()->Open( FileToOpen );
  832. }
  833.  
  834. //
  835. // TFrelease().
  836. //
  837. // Releases the C++ TextFile object.
  838. //
  839. // Returns 1 on sucess, 0 on error.
  840. //
  841.  
  842. void _export _pascal TFrelease() {
  843.  
  844.    delete GetCPlusPlusThis();
  845. }
  846.  
  847. }  // extern "C"   
  848.    
  849.    // End of DOSTEST define
  850. #endif   
  851.