/* ----------------------------------------------------------------------- This code is being 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. The functions included are: f_use() Opens a text file for use. f_select() Selects an area for a second text file. f_goto(n) Goes to the n'th line of the currently selected text file. f_skip(n) Skips n lines in the currently selected text file. f_gobot() Goes to the last line of the currently selected text file. f_gotop() Goes to the top of the currently selected text file. f_readln() Reads the current record of the currently selected text file. f_recno() Returns the record number of the currently selected text file. f_lastrec() Returns the last record number in the currently selected text file. f_eof() Returns true if an attempt was made to skip past the bottom. 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. f_use( "text.c" ) do while !f_eof() ? f_readln() f_skip() enddo f_use() This code was written in only a few hours and could use some optimization. If anyone takes the time to upgrade it, it would be nice to make it public. Brice de Ganahl 3/4/91 -----------------------------------------------------------------------*/ #include "nandef.h" #include "extend.h" #include "text.h" static long recno[10]; static long offset[10]; static int handles[10]; static char *b; static char *c; static int area = 0; static long last_rec[10]; static long last_off[10]; static long lastbyte[10]; static int isEof[10]; void pascal f_use() { 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; } } void pascal f_select() { _retni( area + 1 ); if ( ISNUM(1) ) area = _parni(1) - 1; } void pascal f_gotop() { offset[area] = 0L; recno[area] = 1L; } void pascal f_recno() { _retnl( recno[area] ); } void pascal f_gobot() { 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]; } } void pascal f_skip() { if ( ISNUM(1) ) f__skip( _parni(1) ); else f__skip(1); } long f__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] ); } void pascal f_readln() { 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 ); } void pascal f_lastrec() { long old_rec; long old_offset; old_rec = recno[area]; old_offset = offset[area]; f_gobot(); _retnl( last_rec[area] ); recno[area] = old_rec; offset[area] = old_offset; } void pascal f_eof() { _retl( isEof[area] ); } void pascal f_goto() { long target; long last; target = _parnl(1); last = 0; if ( recno[area] > target ) { while ( recno[area] != target ) { last = recno[area]; f__skip(-1); if ( recno[area] == last ) break; } } else { while ( recno[area] != target ) { last = recno[area]; f__skip(1); if ( recno[area] == last ) break; } } }