campo-sirio/include/text.cpp
guy dc133a5ec1 Migliorata esportazione Excel da TPrintapp
git-svn-id: svn://10.65.10.50/branches/R_10_00@23005 c028cbd2-c16b-5b4b-a496-9718f37d4682
2014-10-27 08:22:37 +00:00

1055 lines
26 KiB
C++
Executable File
Raw Blame History

#include <printer.h>
#include <relation.h>
#include <text.h>
#include <window.h>
#include <xvtility.h>
#define TEXT_TMP_SIZE 1024
static TString _TEXT_TMP(TEXT_TMP_SIZE);
static char* TEXT_TMP = (char*)(const char*)_TEXT_TMP;
class _HotSpot : public TObject
{
public:
// TArray _spots; // tokenstrings
char _bg, _fg;
_HotSpot (char fg, char bg)
{
_fg = fg;
_bg = bg;
}
};
// @doc EXTERNAL
// @mfunc Permette di settare gli hot_spot
void TTextfile::set_hotspots (
char fg, // @parm Colore di foreground da utilizzare per l'hotspot
char bg) // @parm Colore di background da utilizzare per l'hotspot
// @comm Aggiunge all'array gli hotspots relativi alla pagina in memoria
// (come <c TToken_string> con x<pipe>y<pipe>text)
{
_HotSpot *hp = new _HotSpot (fg, bg);
_hotspots.add (hp);
}
style TTextfile::_trans_style (char ch)
{
switch (ch)
{
case 'r':
return normal;
case 'i':
return italic;
case 'b':
return bold;
case 'u':
return underlined;
case 't':
return tabbed;
default:
return normal;
}
}
void TTextfile::_save_changes()
{
TWait_cursor hourglass;
// fa i dovuti replace anche sul disco (solo replace di linee esistenti)
long line = 0l;
fclose(_index);
remove(_indname);
const TString oldfile(_filename);
_filename.temp("txtf");
FILE* newf = fopen(_filename, "a+");
if ((_index = fopen(_indname, "w+b")) == NULL || newf == NULL)
{
NFCHECK("Impossibile aprire files temporanei");
freeze();
return;
}
// fseek(_instr, 0l, SEEK_SET);
rewind(_instr);
while (!feof(_instr))
{
const long l = ftell(newf);
fwrite (&l, sizeof(long), 1, _index);
if (ferror(_index) || ferror(newf))
{
error_box ("Errore di scrittura file temporaneo: scrittura interrotta");
freeze ();
}
if (fgets(TEXT_TMP, TEXT_TMP_SIZE, _instr) == NULL)
break;
if (line >= _page_start && line <= _page_end)
{
TString& lin = (TString&)(_page[(int)(line - _page_start)]);
if (_dirty_lines[line - _page_start])
{
strcpy(TEXT_TMP, lin);
strcat(TEXT_TMP, "\n");
}
}
fprintf(newf, "%s", TEXT_TMP);
line++;
}
fflush(_index);
fclose(_instr);
fclose(newf);
remove(oldfile);
rename(_filename, oldfile);
_filename = oldfile;
_instr = fopen(_filename, "a+");
}
void TTextfile::_read_page (long n)
{
if (_dirty_lines.ones() > 0l)
{
_save_changes();
_dirty_lines.reset();
}
switch (_direction)
{
case down:
_page_start = n;
break;
case up:
_page_start = n + _page_size;
break;
case updown:
_page_start = n - (_page_size / 2l);
break;
}
if (_page_start < 0l)
_page_start = 0l;
if ((_page_start + _page_size) > _lines)
_page_end = _lines - 1;
else
_page_end = _page_start + _page_size - 1;
// zap hotspots
_spots.destroy ();
long l = 0l;
if (_page_start != 0l)
{
fseek (_index, _page_start * (long) sizeof (long), SEEK_SET);
fread (&l, sizeof (long), 1, _index);
}
fseek (_instr, l, SEEK_SET);
for (long i = _page_start; i <= _page_end; i++)
{
if (feof (_instr))
break;
fgets (TEXT_TMP, TEXT_TMP_SIZE, _instr);
TEXT_TMP[strlen (TEXT_TMP) - 1] = '\0';
TString & ts = (TString &) _page[(int) (i - _page_start)];
CHECK(ts.size() > 0, "Corrupted string");
ts = TEXT_TMP;
if (_interactive)
{
TString hcol (6);
// find hotspots and compile list
int len = 0;
const char *cp;
read_line (i, 0, FALSE);
while ((cp = piece ()))
{
for (int z = 0; z < _hotspots.items (); z++)
{
_HotSpot & hs = (_HotSpot &) _hotspots[z];
if (hs._fg == get_foreground () && hs._bg == get_background ())
{
TToken_string *tts = new TToken_string (50);
tts->add (i); // line number
tts->add (len);
tts->add (len + (int) strlen (cp));
tts->add (cp);
tts->add (z);
_spots.add (tts);
break;
}
}
len += strlen (cp);
}
}
}
}
// @doc EXTERNAL
// @mfunc Legge il testo formattato
void TTextfile::read_line (
long n, // @parm Numero della linea da leggere
long pos, // @parm Numero della colonna da leggere (mai utilizzata)
bool pg) // @parm Fa si' che se la linea non e' nella pagina corrente non si faccia nulla,
// diversamente rilegge una nuova pagina dal file.
{
CHECK (_isopen, "Attempt operation on closed file");
// CHECKD (n >= 0 && n < _lines, "Line not present", n);
if (pg && !_in_page (n))
_read_page (n);
TString *tp = (TString *) _page.objptr (int (n - _page_start));
if (tp == NULL)
return;
const char *sp = (const char *) (*tp);
_item = 0;
_line = "";
int ndx = 0, p = 0;
bool first = TRUE;
_cur_line = n;
char ch;
int col = ((int) 'w' << 8) | (int) 'n';
long stl = (long) col << 16;
while ((ch = *sp++))
{
if (ch == '<' && *(sp) == '@')
{
// merge field if rel != NULL;
// else fill with whitespace
const char * save_sp = sp;
TToken_string id(80, '@');
sp++;
bool terminated = FALSE;
while ((ch = *sp++) != '>' && !terminated)
if (ch != '\0')
id << ch;
else terminated = TRUE;
if (!terminated) // Prosegue normalmente se non trova la matching >
{
// id contains tokenstring separated by @
// but with casinations for possible lack of spacing
// add spaces if needed
for (int i = 0; i < id.len(); i++)
{
if (id[i] == '@' && id [i+1] == '@')
{
id.insert(" ", i+1);
i+= 2;
}
}
// parse string
int len;
TString80 file;
TString16 field;
TString80 format;
char just;
file = id.get();
format = id.get();
len = (int)id.get_long();
just = id.get_char();
int pos = 0;
if ((pos = file.find("->")) == -1)
error_box("field specification error");
else
{
file.cut(pos);
field = file.mid(pos+2);
}
if (len == 0) len = id.len();
TString txt(512);
TFieldtypes type;
if (_rel != NULL)
{
// retrieve file and field
if (atoi(file) == 0)
{
// tabella
TLocalisamfile& t = _rel->lfile(file);
txt = t.get(field);
type = t.curr().type(field);
}
else
{
TLocalisamfile& f = _rel->lfile(atoi(file));
txt = f.get(field);
type = f.curr().type(field);
}
// apply format to date and number
switch (type)
{
case _longfld:
case _realfld:
{
real r(txt);
txt = r.string(format);
}
break;
case _datefld:
{
TDate dd(txt);
TFormatted_date d(dd, format);
txt = d.string();
}
break;
default:
break;
}
// justify as requested
if (txt.len() < len)
{
switch(type)
{
case _longfld:
case _realfld:
txt.right_just(len);
break;
default:
txt.left_just(len);
break;
}
}
}
else
{
txt.left_just(len);
}
// ficca il testo cola' dove si puote
const int txtlen = txt.len();
for (int k = 0; k < txtlen; k++)
TEXT_TMP[ndx++] = txt[k];
} // see (!terminated) above
else // Restore sp pointer
{
sp = save_sp;
ch = '<';
}
}
if (ch == '@' || (ch == '$' && *(sp) == '['))
{
if (!first && p >= pos)
{
CHECKD(ndx < TEXT_TMP_SIZE, "Bad TEXT_TMP index ", ndx);
_styles[_item++] = stl;
TEXT_TMP[ndx] = '\0';
_line.add (TEXT_TMP);
ndx = 0;
}
while (ch && (ch == '@' || (ch == '$' && *sp == '[')))
{
if (ch == '@') // font style change ?
{
const char c = *sp++;
if (c == '@')
{
_styles[_item++] = stl;
_line.add("@");
}
else
{
style sss = _trans_style (c);
if (sss == normal)
stl = (long) col << 16;
else
stl |= (long) sss;
}
}
else if (ch == '$' && *sp == '[') // color change
{
++sp; // eat '['
col = *sp++;
++sp; // eat ','
col |= ((int) (*sp++) << 8);
++sp; // eat ']'
stl = (stl & 0x0000ffff) | ((long) col << 16);
}
ch = *sp++;
} // while
}
if (ch && p >= pos)
{
CHECKD(ndx < TEXT_TMP_SIZE, "Bad TEXT_TMP index ", ndx);
first = FALSE;
TEXT_TMP[ndx++] = ch;
}
p++;
}
_styles[_item++] = stl;
TEXT_TMP[ndx] = '\0';
_line.add(TEXT_TMP);
_item = 0;
}
// @doc EXTERNAL
// @mfunc Ritorna la stringa di caratteri senza formattazione
//
// @rdesc Ritorna la stringa di caratteri ed eventualmente con i campi sostituiti
// se la relazione non e' NULL
const char* TTextfile::line(
long j, // @parm Riga di cui ritornare la stringa
long pos, // @parm Colonna di cui ritornare la stringa
int howmuch) // @parm Numero di caratteri utili della stringa da ritornare (default -1)
// @comm Se <p howmuch> assume valore -1 ritorna tutta la pagina
{
if (_cur_line != j)
read_line (j);
*TEXT_TMP = '\0';
FOR_EACH_TOKEN(_line, l)
strcat (TEXT_TMP, l);
if (howmuch >= 0)
{
if (((unsigned int)pos+howmuch) < strlen(TEXT_TMP))
TEXT_TMP[pos+howmuch] = '\0';
}
return strlen(TEXT_TMP) > (word)pos ? &(TEXT_TMP[pos]) : "";
}
// @doc EXTERNAL
// @mfunc Cerca una stringa di testo all'interno di una riga
//
// @rdesc Ritorna la posizione in cui e' stato rintracciato il testo. Ritorna -1 se non e' stato
// trovato il testo passato.
long TTextfile::search(
const char* txt, // @parm Testo da cercare
int& ret, // @parm Intero in cui posizionare la posizne del carattere
long from, // @parm Posizione all'interno della riga da cui iniziare la ricerca (default 0)
bool down, // @parm Indica se la ricerca va effettuata all'indietro:
//
// @flag TRUE | Ricerca dalla posizione indicata all'inizio della riga (default)
// @flag FALSE | Ricerca dalla posizione indicata alla fine della riga
bool casesens, // @parm Indica se ricerca il testo con criterio case sensitive (default FALSE)
bool regexp) // @parm indica se considerare la stringa un'espressione regolare (def. FALSE)
// @comm Cerca in una riga per volta rispettando i formati
{
TString text(txt);
if (!casesens)
text.lower();
if (regexp && !text.ends_with("*"))
text << '*';
TString lin(512);
for (long i = from; down ? (i < lines()) : (i >= 0); down ? i++ : i--)
{
lin = line(i);
if (!casesens)
lin.lower();
if (regexp)
{
for (ret = 0; lin[ret]; ret++)
{
if (lin.mid(ret).match(text))
return i;
}
}
else
{
ret = lin.find(text);
if (ret >= 0)
return i;
}
}
return -1l;
}
// @doc EXTERNAL
// @mfunc Sostituisce un testo all'interno di una riga
//
// @rdesc Ritorna la posizione in cui e' stato sostituito il testo. Ritorna -1 se non e' stata
// fatto nessuna operazione di sostituzione.
int TTextfile::replace(
long l, // @parm Numero della riga nella quale sostituire il testo
const char* txt, // @parm Test da inserire nella riga
int pos, // @parm Posizione nella quale inserire il testo (default 0)
int len) // @parm Lunghezza del testo da sostituire (default 0)
{
if (_cur_line != l)
read_line(l);
TString& line = (TString&)_page[int(l-_page_start)];
char ch; int i = 0, cnt = 0, skip = 0;
bool sforating = FALSE;
// here's a nice casin
while(i < 256)
{
if (!sforating)
{
ch = line[i++];
if (ch == '\0')
sforating = TRUE;
else if (ch == '@' && strchr("ribuokt",line[i]) != NULL)
{
skip +=2; i++; cnt--;
}
else if (ch == '$' && line[i] == '[')
{
skip +=3; i++; cnt--;
while(line[i++] != ']')
if (line[i] == '\0')
return -1;
else skip++;
}
}
if (cnt == pos)
{
line.overwrite(txt, cnt+skip);
_dirty_lines.set(l-_page_start);
return cnt;
}
else cnt++;
}
return -1;
}
// @doc EXTERNAL
// @mfunc Ritorna la stringa di caratteri con la formattazione
//
// @rdesc La stringa ritornata ha la formattazione (ovvere tutti i @codes, in modo che anche
// la printer la possa utilizzare)
const char *TTextfile::line_formatted(
long j) //parm Numero della riga da ritornare
{
if (_cur_line != j)
read_line (j);
TString* tp = (TString*)_page.objptr(int(j-_page_start));
strcpy(TEXT_TMP, (const char*)(*tp));
return TEXT_TMP;
}
long TTextfile::get_attribute (int pos)
{
long stl = 0;
if (pos == -1)
{
CHECK (_item > 0, "must execute piece() before style()!");
stl = _styles[_item - 1];
}
else
{
int x = 0, nd = 0;
const char *c;
_line.restart ();
while ((c = _line.get ()) != NULL)
{
x += strlen (c);
stl = _styles[nd++];
if ((x - 1) >= pos)
break;
}
}
return stl;
}
// @doc EXTERNAL
// @mfunc Ritorna lo stile del piece
//
// @rdesc Ritorna un numero (vedi <t style>) indicante lo stile
int TTextfile::get_style (
int pos) // @parm Posizione del carattere di cui ritornare lo stile (default -1)
// @comm Se viene passato a <p pos> valore -1 ritorna lo stile di tutta la piece, altrimente
// solamente quello del carattere selezionato.
{
const long x = get_attribute(pos) & ~tabbed;
return (int) (x & 0x0000ffff);
}
// @doc EXTERNAL
// @mfunc Ritorna il colore di background del piece
//
// @rdesc Ritorna il codice del colore, NULL se il carattere non esiste
char TTextfile::get_background (
int pos) // @parm Posizione del carattere di cui conoscere il colore di background (default -1)
// @comm Se <p pos> e' minore di 0 ritorna il colore dell'intero piece, altrimenti solamente
// quello del carattere selezionato.
//
// @xref <mf TTextfile::get_foreground>
{
long x = get_attribute (pos);
return (char) (x >> 24);
}
// @doc EXTERNAL
// @mfunc Ritorna il colore di foreground del piece
//
// @rdesc Ritorna il codice del colore, NULL se il carattere non esiste
char TTextfile::get_foreground (
int pos) // @parm Posizione del carattere di cui conoscere il colore di background (default -1)
// @comm Se <p pos> e' minore di 0 ritorna il colore dell'intero piece, altrimenti solamente
// quello del carattere selezionato.
//
// @xref <mf TTextfile::get_bakcground>
{
long x = get_attribute (pos);
return (char) ((x >> 16) & 0x000000ff);
}
const char* TTextfile::piece()
{
const char* l = _line.get(_item);
if (l == NULL)
return NULL;
_item++;
return strcpy(TEXT_TMP, l);
}
// @doc EXTERNAL
// @mfunc Ritorna la parola alla posizione indicata
//
// @rdesc Stringa indicante la parola cercate
const char *TTextfile::word_at (
long x, // @parm Numero della parola da ritornare
long y) // @parm Numero della linea su cui cercare la parole
{
CHECK (_isopen, "Attempt operation on closed file");
TString s (line (y));
int x2 = 0;
if (x < s.len ())
{
while (isspace (s[(int) x]))
{
if (x == (s.len () - 1) && y < (_lines - 1l))
{
s = line (++y);
x = 0l;
}
else if (x < (s.len () - 1))
x++;
else
break;
}
while (isalnum (s[(int) x]))
TEXT_TMP[x2++] = s[(int) x++];
}
TEXT_TMP[x2] = '\0';
return TEXT_TMP;
}
// @doc EXTERNAL
// @mfunc Aggiunge una riga al text (con i formati del caso)
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag TRUE | Se la riga e' stat aggiuntac correttamente
// @flag FALSE | Se non e' riuscot ad aggiungere la riga
bool TTextfile::append (
const char *l) // @parm Riga da aggiungere
{
CHECK (_isopen, "Attempt operation on closed file");
if (!_accept)
return FALSE;
fseek (_instr, 0l, SEEK_END);
fseek (_index, 0l, SEEK_END);
long cpos = ftell (_instr);
fprintf (_instr, "%s\n", l);
fwrite (&cpos, sizeof (long), 1, _index);
if (ferror (_index) || ferror (_instr))
{
error_box ("Errore di scrittura file temporaneo: scrittura interrotta");
freeze ();
}
fflush (_index);
fflush (_instr);
_lines++;
_dirty = TRUE;
if ((_lines) < (_page_start + _page_size))
{
if (_interactive)
{
_page.add (new TString(l), int(_lines - _page_start - 1));
_page_end++;
int len = 0;
const char *cp;
read_line (_lines - 1);
while ((cp = piece ()))
{
for (int z = 0; z < _hotspots.items (); z++)
{
_HotSpot & hs = (_HotSpot &) _hotspots[z];
if (hs._fg == get_foreground () && hs._bg == get_background ())
{
TToken_string *tts = new TToken_string (50);
tts->add (_lines - 1l); // line number
//
tts->add (len);
tts->add (len + (int) strlen (cp));
tts->add (cp);
tts->add (z);
_spots.add (tts);
break;
}
}
len += strlen (cp);
}
}
return TRUE;
}
return FALSE;
}
void TTextfile::close ()
{
if (_isopen)
{
fclose (_instr);
fclose (_index);
_instr = _index = NULL;
_isopen = FALSE;
}
}
void TTextfile::print ()
{
printer().print_txt(*this);
}
// @doc EXTERNAL
// @mfunc Scrive il testo (non formattato) su file
//
// @rdesc Ritorna il risultato dell'operazione di scrittura
//
// @flag TRUE | Se e' riuscito a scrivere il testo
// @flag FALSE | Se ha avuto qualche problema nella gestione del file in cui scrivere
bool TTextfile::write (
const char *path, // @parm Nome del file in cui scrivere il testo
TPoint * from, // @parm Punto da cui iniziare a scrivere il testo
TPoint * to) // @parm Punto a cui terminare di scrivere il testo
{
FILE* fp = fopen(path, "w");
if (fp != NULL)
{
TString s(512);
long starty = from == NULL ? 0l : from->y;
int startx = from == NULL ? 0 : (int) from->x;
long endy = to == NULL ? _lines - 1l : to->y;
int endx = to == NULL ? -1 : (int) to->x;
for (long j = starty; j <= endy; j++)
{
s = line(j);
if (j == endy && endx == -1)
endx = s.len();
if (j == starty && j == endy)
s = s.sub(startx, endx);
else if (j == starty)
s = s.mid(startx);
else if (j == endy)
s = s.left(endx);
fprintf(fp, "%s\n", (const char *) s);
}
fclose (fp);
}
else
warning_box ("Impossibile scrivere il file %s; scrittura fallita", path);
return fp != NULL;
}
// @doc EXTERNAL
// @mfunc Scrive il testo da punto a punto (non formattato) su string_array
void TTextfile::write(
TString_array& arr, // @parm Array in cui scrivere il testo
TPoint * from, // @parm Punto da cui iniziare a scrivere il testo
TPoint * to) // @parm Punto a cui terminare di scrivere il testo
{
arr.destroy();
TString s(512);
long starty = from == NULL ? 0l : from->y;
int startx = from == NULL ? 0 : (int) from->x;
long endy = to == NULL ? _lines - 1l : to->y;
int endx = to == NULL ? -1 : (int) to->x;
for (long j = starty; j <= endy; j++)
{
s = line(j);
if (j == endy && endx == -1)
endx = s.len();
if (j == starty && j == endy)
s = s.sub(startx, endx);
else if (j == starty)
s = s.mid(startx);
else if (j == endy)
s = s.left(endx);
arr.add(s);
}
}
// Determina il tipo di una stringa: 0=ignoto; 1=stringa; 2=numero
static int str_type(TString& str)
{
str.rtrim();
if (str.blank())
return 0;
bool is_string = false;
bool is_number = true;
for (int i=0; str[i]; i++)
{
const char c = str[i];
if (c < '\0' || isalnum(c))
is_string = true;
if (strchr("0123456789,.", c) == NULL)
is_number = false;
}
if (is_number)
{
str.strip(".");
str.replace(',', '.');
const real r(str);
str = r.stringe();
}
return is_number ? 2 : (is_string ? 1 : 0);
}
static bool is_text_line(TString& str)
{
const int l = str.trim().len();
if (l >= 64)
{
const char c = str[0];
if (strchr("_-=", c) != NULL && str[l/2] == c && str[l-1] == c)
return true;
}
return false;
}
bool TTextfile::write_xls(const TFilename& xls)
{
const TPrinter& pr = printer();
int headerlen = pr.headersize();
const int footerlen = pr.footersize();
const int pagelen = pr.formlen();
TString str;
int tabstart = 1;
int tabstop = pagelen - footerlen;
if (_lines < tabstop) tabstop = _lines;
int header_end = 12;
if (headerlen > 3)
header_end = headerlen;
if (header_end > tabstop)
header_end = tabstop;
for (long j = 1; j < header_end; j++)
{
read_line(j);
str = piece();
if (is_text_line(str))
{
if (tabstart <= 1)
tabstart = j+1;
else
{
tabstop = j;
headerlen = j;
}
}
}
if (tabstart <= 1 && headerlen > 0)
tabstart = headerlen;
if (tabstart < 2)
tabstart = 2;
TTabulator tab;
for (long j = tabstart; j < tabstop; j++)
{
read_line(j);
int x = 0;
for (const char* cp = piece(); cp; cp = piece())
{
str = cp;
const int len = str.len();
if (str_type(str) > 0)
tab.add_field(x, str.len());
x += len;
}
}
tab.sort();
TToken_string riga(256, '\t');
TString8 ext = pr.get_form_name().ext(); ext.lower();
const bool is_rep = ext == "frm" || ext == "rep";
ofstream out(xls);
for (long j = 0; j < _lines; j++)
{
const int row = j % pagelen;
if (is_rep)
{
// Esporto la testata solo nella prima pagina e lascio il footer perch<63> nei form <20> variabile in lunghezza
if (row < headerlen && j >= pagelen)
continue;
}
else
{
// Esporto la testata solo nella prima pagina ed il footer solo nell'ultima
if ((row < headerlen && j >= pagelen) || (row >= pagelen-footerlen && row < _lines-pagelen))
continue;
}
read_line(j);
riga.cut(0);
int x = 0;
for (const char* cp = piece(); cp; cp = piece())
{
str = cp;
const int len = str.len();
const int st = str_type(str);
if (st > 0)
{
int idx, pos;
if (tab.find_column(x, str.len(), idx, pos))
{
const char* old = riga.get(pos);
if (old && *old)
str.insert(old);
riga.add(str, pos);
}
}
x += len;
}
if (riga.full())
out << riga << endl;
}
return xls.exist();
}
void TTextfile::destroy ()
{
CHECK(_istemp, "destroy() chiamata su testo permanente!");
if (_page.items () > 0)
{
if (_index)
fclose (_index);
if (_instr)
fclose (_instr);
_filename.fremove();
_indname.fremove();
_page_start = _lines = 0l;
_page_end = _cur_line = -1l;
_accept = TRUE;
_instr = fopen (_filename, "a+");
_indname.temp ();
_index = fopen (_indname, "w+b");
if (_index == NULL || _instr == NULL)
{
cantwrite_box (_filename);
freeze ();
}
_isopen = TRUE;
// _page.destroy ();
_spots.destroy ();
}
}
TTextfile ::TTextfile (const char *file, int pagesize, direction preferred,
bool interactive):
_page (pagesize), _dirty_lines(pagesize), _page_start (0l), _page_end (-1l), _page_size (pagesize),
_lines (0l), _cur_line (-1), _filename (file), _index (NULL),
_direction (preferred), _item (0), _line (256), _hotspots (4), _dirty (FALSE),
_istemp (FALSE), _accept (TRUE), _interactive(interactive), _rel(NULL)
{
// open file & build index
if (file == NULL || *file <= ' ')
{
_filename.temp("txtf");
_istemp = TRUE;
}
for (int i = 0; i < pagesize; i++)
_page.add(new TString(132));
_isopen = TRUE;
_instr = fopen (_filename, "a+");
_indname.temp("txti");
_index = fopen (_indname, "w+b");
if (_index == NULL || _instr == NULL)
{
cantwrite_box(_filename);
freeze ();
}
if (!_istemp)
while (!feof(_instr))
{
const long l = ftell (_instr);
fwrite (&l, sizeof (long), 1, _index);
if (ferror(_index) || ferror(_instr))
{
cantwrite_box(_indname);
freeze();
}
if (fgets (TEXT_TMP, TEXT_TMP_SIZE, _instr) == NULL)
break;
_lines++;
}
}
TTextfile::~TTextfile ()
{
if (_index)
fclose (_index);
if (_instr)
fclose (_instr);
if (_istemp) remove ((const char *) _filename);
remove ((const char *) _indname);
}