home *** CD-ROM | disk | FTP | other *** search
- /*
- * File......: TEXT.C
- * Author....: Brice de Ganahl
- * Date......: $Date: 17 Aug 1991 15:31:08 $
- * Revision..: $Revision: 1.4 $
- * Log file..: $Logfile: E:/nanfor/src/fttext.c_v $
- *
- * This is an original work by Brice de Ganahl and is placed in the
- * public domain. I hope it is useful but have no intention to
- * support it and do not claim that it is fit for any particular use.
- *
- * Doc headers by Glenn Scott & Don Caton
- *
- *
- * Modification history:
- * ---------------------
- *
- * $Log: E:/nanfor/src/fttext.c_v $
- *
- * Rev 1.4 17 Aug 1991 15:31:08 GLENN
- * Don Caton fixed some spelling errors in the doc
- *
- * Rev 1.3 15 Aug 1991 23:08:36 GLENN
- * Forest Belt proofread/edited/cleaned up doc
- *
- * Rev 1.2 29 Apr 1991 08:02:12 GLENN
- * Minor adjustments to documentation block
- *
- * Rev 1.1 29 Apr 1991 08:00:26 GLENN
- * ft_flastrec() -- name was longer than 10 characters so linkers couldn't
- * find the symbol. Just hacked off the last "c" so it is really
- * ft_flastre(). Sorry, folks. -- Glenn
- *
- * Rev 1.0 01 Apr 1991 01:02:48 GLENN
- * Nanforum Toolkit
- *
- */
-
- /* Notes:
-
- The Clipper internal functions used seem to be stable across
- versions but nothing is guaranteed. These functions begin
- with _t, are used for file I/O, and are compatible with their
- ANSI counterparts (just strip the _t and you have the ANSI name).
- See text.h for the prototypes.
-
- I compile these functions with the following MicroSoft C parameters:
-
- cl /c /AL /Od /Zl /Zi /FPa /Gs /W3 text.c
-
- Note that the /Od defeats optimization and is necessary only for
- compatibility with Blinker, Warplink, etc. If you are not overlaying
- this code you may want to change this to /Oalt. Likewise, the
- /Zi is for symbolic debugging info which you will want to omit in
- any final compiles.
-
- Some sample Clipper code which would use these functions is listed
- below. It will print out the contents of this file.
-
- ft_fuse( "text.c" )
- do while !ft_feof()
- ? ft_freadln()
- ft_fskip()
- enddo
- ft_fuse()
-
-
- */
-
-
- #include "extend.h"
- #include "fttext.h"
-
- #define TEXT_WORKAREAS 10
-
- static long recno[TEXT_WORKAREAS];
- static long offset[TEXT_WORKAREAS];
- static int handles[TEXT_WORKAREAS];
- static char *b;
- static char *c;
- static int area = 0;
- static long last_rec[TEXT_WORKAREAS];
- static long last_off[TEXT_WORKAREAS];
- static long lastbyte[TEXT_WORKAREAS];
- static int isEof[TEXT_WORKAREAS];
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FUSE()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Open or close a text file for use by the FT_F* functions
- * $SYNTAX$
- * FT_FUSE( [ <cFile> ] ) -> nHandle | NIL
- * $ARGUMENTS$
- * <cFile> is the text file you want to open. If not specified,
- * the file currently open, if any, will be closed.
- * $RETURNS$
- * If <cFile> is passed and the file is opened successfully, an
- * integer containing the file handle. If the file cannot be
- * opened, -1 will be returned.
- *
- * If FT_FUSE() is called without any arguments, it will close the
- * text file in the current "text area" and return NIL.
- * $DESCRIPTION$
- * The FT_F*() file functions are for reading text files, that is,
- * files where each line (record) is delimited by a CRLF pair.
- *
- * Each file is opened in its own "workarea", similar to the concept
- * use by dbf files. As provided, a maximum of 10 files (in 10
- * workareas) can be opened (assuming there are sufficient file
- * handles available). That number may be increased by modifying
- * the #define TEXT_WORKAREAS in the C source code and recompiling.
- * $EXAMPLES$
- * FT_FUSE( "text.c" ) // open text file
- * DO WHILE !FT_FEOF()
- * ? FT_FREADLN()
- * FT_FSKIP()
- * ENDDO
- * FT_FUSE() // close file
- * $SEEALSO$
- * FT_FUSE() FT_FSELECT()
- * $END$
- */
-
- void pascal ft_fuse()
- {
-
- if ( ISCHAR(1) ) {
- handles[area] = _topen( _parc(1), O_RDONLY|SH_DENYNO|O_BINARY );
- offset[area] = 0;
- recno[area] = 1;
- b = _exmgrab( b_size );
- c = _exmgrab( c_size );
- lastbyte[area] = _tlseek( handles[area], 0L, SEEK_END );
- _retni( handles[area] );
- }
- else {
- _tclose( handles[area] );
- _exmback( b, b_size );
- _exmback( c, c_size );
- _retni(1);
- recno[area] = 0L;
- offset[area] = 0L;
- handles[area] = 0;
- last_rec[area] = 0L;
- last_off[area] = 0L;
- lastbyte[area] = 0L;
- isEof[area] = 0;
- }
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FSELECT()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Select a text file workarea
- * $SYNTAX$
- * FT_FSELECT( <nArea> ) -> nArea
- * $ARGUMENTS$
- * <nArea> is the text file workarea to select.
- * $RETURNS$
- * The current selected text file area if no parameter is passed,
- * otherwise the previous area if a new area is selected.
- * $DESCRIPTION$
- * This function selects a text file "workarea" from 1 to 10. A
- * file may or may not be open in the selected area.
- *
- * Each file is opened in its own "workarea", similar to the concept
- * used by dbf files. As provided, a maximum of 10 files (in 10
- * workareas) can be opened (assuming there are sufficient file
- * handles available). That number may be increased by modifying
- * the #define TEXT_WORKAREAS in the C source code and recompiling.
- *
- * All the FT_F*() file functions operate on the file in the currently
- * selected text file workarea.
- *
- * Text file workareas are separate from and independent of Clipper's
- * database workareas.
- * $EXAMPLES$
- * FT_FSELECT(1)
- * nFile1 := FT_FUSE( "temp.c" )
- * ? FT_FLASTREC() // no. of lines in temp.c
- * FT_FSELECT(2)
- * nFile2 := FT_FUSE( "temp.h" )
- * ? FT_FLASTREC() // no. of lines in temp.h
- * $SEEALSO$
- * FT_FUSE()
- * $END$
- */
-
- void pascal ft_fselect()
- {
-
- _retni( area + 1 );
-
- if ( ISNUM(1) )
- area = _parni(1) - 1;
-
- }
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FGOTOP()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Go to the first record in a text file
- * $SYNTAX$
- * FT_FGOTOP() -> NIL
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * NIL
- * $DESCRIPTION$
- * This function moves the record pointer to the first record
- * in the currently selected text file workarea.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * FT_FUSE( "text.c" ) // open text file
- * DO WHILE !FT_FEOF()
- * ? FT_FREADLN() // read thru file
- * FT_FSKIP()
- * ENDDO
- * FT_FGOTOP() // go back to top
- * ? FT_FRECNO() // 1
- * $SEEALSO$
- * FT_FSELECT() FT_FUSE() FT_FRECNO() FT_FGOBOT()
- * $END$
- */
-
- void pascal ft_fgotop()
- {
-
- offset[area] = 0L;
- recno[area] = 1L;
-
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FRECNO()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Return the current record number of a text file
- * $SYNTAX$
- * FT_FRECNO() -> nRecNo
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * The current record number of a text file or 0 if no file is open.
- * $DESCRIPTION$
- * This function returns the current record number of the file open
- * in the currently selected text file workarea.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * FT_FUSE( "text.c" ) // open text file
- * DO WHILE !FT_FEOF()
- * ? FT_FREADLN() // read thru file
- * FT_FSKIP()
- * ENDDO
- * FT_FGOTOP() // go back to top
- * ? FT_FRECNO() // 1
- * $SEEALSO$
- * FT_FSELECT() FT_FUSE() FT_FGOTOP() FT_FGOBOT()
- * $END$
- */
-
-
- void pascal ft_frecno()
- {
-
- _retnl( recno[area] );
-
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FGOBOT()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Go to the last record in a text file
- * $SYNTAX$
- * FT_FGOBOT() -> NIL
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * NIL
- * $DESCRIPTION$
- * This function moves the record pointer to the last record of the
- * file in the currently selected text file workarea.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * // read last line
- * FT_FUSE( "text.c" )
- * FT_FGOBOT()
- * ? FT_FREADLN()
- * $SEEALSO$
- * FT_FSELECT() FT_FUSE() FT_FGOTOP() FT_FRECNO() FT_FREADLN()
- * $END$
- */
-
-
- void pascal ft_fgobot()
- {
-
- int x;
- int len;
- long loc;
-
- if ( last_rec[area] != 0 ) {
- recno[area] = last_rec[area];
- offset[area] = last_off[area];
- }
- else {
-
- loc = 0L;
-
- do {
-
- _tlseek( handles[area], offset[area], SEEK_SET );
- len = _tread( handles[area], c, c_size );
- for ( x = 0; x < len; x++ ) {
- if ( ((*(c + x) == 13) && (*(c + x + 1) == 10)) ||
- ((*(c + x) == 10) && (*(c + x + 1) == 13)) ||
- ( x - loc > b_size ) ) {
- recno[area]++;
- x++;
- loc = x + 1;
- }
- }
- offset[area] += loc;
-
- } while ( len == c_size );
-
- last_rec[area] = --recno[area];
- last_off[area] = offset[area];
-
- }
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FSKIP()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Move the record pointer to a new position in a text file
- * $SYNTAX$
- * FT_FSKIP( [ <nLines> ] ) -> NIL
- * $ARGUMENTS$
- * <nLines> is the number of lines to skip. Defaults to 1 if
- * not specified.
- * $RETURNS$
- * NIL
- * $DESCRIPTION$
- * This function moves the text file record pointer, similar to
- * the CLIPPER SKIP command.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * // display each record of a text file
- * FT_FUSE( "text.c" )
- * DO WHILE ! FT_FEOF()
- * ? FT_FREADLN()
- * FT_FSKIP()
- * ENDDO
- * $SEEALSO$
- * FT_FRECNO() FT_FGOTOP() FT_FGOBOT()
- * $END$
- */
-
- void pascal ft_fskip()
- {
-
- if ( ISNUM(1) )
- _ft_skip( _parni(1) );
- else
- _ft_skip(1);
-
- }
-
-
- static long _ft_skip( int recs )
- {
-
- int x;
- long read_pos;
- size_t read_len;
- long y;
-
-
- if ( recs > 0 ) {
- for (y = 0; y < recs; y++ ) {
- _tlseek( handles[area], offset[area], SEEK_SET );
- read_len = _tread( handles[area], b, b_size );
- for (x = 0; x < read_len; x++ ) {
- if ( ((*(b + x) == 13) && (*(b + x + 1) == 10)) ||
- ((*(b + x) == 10) && (*(b + x + 1) == 13)) ) {
- break;
- }
- }
- if ( (offset[area] + x + 2) < lastbyte[area] ) {
- isEof[area] = FALSE;
- offset[area] += (x + 2);
- recno[area] += 1;
- }
- else
- isEof[area] = TRUE;
- }
- }
- else {
- recs = -recs;
- isEof[area] = FALSE;
-
- if ( (recno[area] - recs) < 1 )
- return( 1 );
-
- for (y = recs; y > 0; y-- ) {
- if ( offset[area] - b_size < 0L ) {
- read_pos = 0;
- read_len = (size_t)offset[area];
- }
- else {
- read_pos = (size_t)(offset[area] - b_size);
- read_len = b_size;
- }
-
- _tlseek( handles[area], read_pos, SEEK_SET );
- read_len = _tread( handles[area], b, read_len );
-
- for (x = read_len - 4; x >= 0; x-- ) {
- if ( ((*(b + x) == 13) && (*(b + x + 1) == 10)) ||
- ((*(b + x) == 10) && (*(b + x + 1) == 13)) ) {
- break;
- }
- }
- if ( x < 0 ) {
- offset[area] = 0;
- recno[area] = 1;
- }
- else {
- offset[area] = read_pos + x + 2;
- recno[area]--;
- }
- }
- }
-
- return ( recno[area] );
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FREADLN()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Read a line from the currently selected text file
- * $SYNTAX$
- * FT_FREADLIN() -> cLine
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * A string containing the current record in a text file.
- * $DESCRIPTION$
- * This function returns a line of text read from the file in the
- * currently selected text file workarea. Text lines are delimited
- * with a CRLF pair. The record pointer is not moved.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * // display each record of a text file
- * FT_FUSE( "text.c" )
- * DO WHILE ! FT_FEOF()
- * ? FT_FREADLN()
- * FT_FSKIP()
- * ENDDO
- * $SEEALSO$
- * FT_FUSE() FT_FRECNO() FT_FGOTOP() FT_FGOBOT()
- * $END$
- */
-
-
- void pascal ft_freadln()
- {
-
- int x;
- long read;
-
- _tlseek( handles[area], offset[area], SEEK_SET );
- read = _tread( handles[area], b, b_size );
-
- for ( x = 0; x < b_size; x++ ) {
- if ( ((*(b + x) == 13) && (*(b + x + 1) == 10)) ||
- ((*(b + x) == 10) && (*(b + x + 1) == 13)) ||
- (*(b + x) == 26) || ( x >= (int)read) ) {
- break;
- }
- }
- _retclen( b, x );
-
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FLASTREC()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Determine the no. of records in the currently selected text file
- * $SYNTAX$
- * FT_FLASTREC() -> nLastRecordNum
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * An integer containing the number of records in the text file in
- * the currently selected text file workarea, or zero if no file
- * is currently open in the workarea.
- * $DESCRIPTION$
- * This function returns the number of the last record in a text file.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * FT_FUSE( "text.c" )
- * ? FT_FLASTREC()
- * $SEEALSO$
- * FT_FUSE() FT_FGOBOT() FT_FRECNO()
- * $END$
- */
-
-
- void pascal ft_flastre()
- {
-
- long old_rec;
- long old_offset;
-
- old_rec = recno[area];
- old_offset = offset[area];
-
- ft_fgobot();
- _retnl( last_rec[area] );
-
- recno[area] = old_rec;
- offset[area] = old_offset;
-
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FEOF()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Determine when end of text file is encountered
- * $SYNTAX$
- * FT_FEOF() -> lResult
- * $ARGUMENTS$
- * None
- * $RETURNS$
- * .T. if an attempt was made to skip past the last record of
- * the currently selected text file, otherwise .F.
- * $DESCRIPTION$
- * This function is similar to the CLIPPER Eof() function.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * FT_FUSE( "FTTEXT.C" )
- * FT_FGOBOT()
- * ? FT_FEOF() // .F.
- * FT_FSKIP()
- * ? FT_FEOF() // .T.
- * $SEEALSO$
- * FT_FUSE() FT_FGOBOT() FT_FSKIP()
- * $END$
- */
-
-
- void pascal ft_feof()
- {
- _retl( isEof[area] );
- }
-
-
- /* $DOC$
- * $FUNCNAME$
- * FT_FGOTO()
- * $CATEGORY$
- * File I/O
- * $ONELINER$
- * Move record pointer to specific record in a text file
- * $SYNTAX$
- * FT_FGOTO( nLine ) -> NIL
- * $ARGUMENTS$
- * <nLine> is the record number to go to.
- * $RETURNS$
- * NIL
- * $DESCRIPTION$
- * This function moves the record pointer to a specific record
- * in the file in the currently selected text file workarea. If
- * the record number requested is greater than the number of records
- * in the file, the record pointer will be positioned at the last
- * record.
- *
- * A text file "record" is a line of text terminated by a CRLF pair.
- * $EXAMPLES$
- * // read 5th line of text from file
- * FT_FUSE( "FTTEXT.C" )
- * FT_FGOTO(5)
- * cText := FT_FREADLN()
- * $SEEALSO$
- * FT_FRECNO() FT_FGOTOP() FT_FGOBOT() FT_FREADLN()
- * $END$
- */
-
- void pascal ft_fgoto()
- {
-
- long target;
- long last;
-
- target = _parnl(1);
- last = 0;
-
- if ( recno[area] > target ) {
- while ( recno[area] != target ) {
- last = recno[area];
- _ft_skip(-1);
- if ( recno[area] == last )
- break;
- }
- }
- else {
- while ( recno[area] != target ) {
- last = recno[area];
- _ft_skip(1);
- if ( recno[area] == last )
- break;
- }
- }
- }
-
-
-