home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
nan_news
/
toolkit
/
fttext.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-17
|
17KB
|
660 lines
/*
* 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;
}
}
}