408 lines
11 KiB
C++
Executable File
408 lines
11 KiB
C++
Executable File
#include <text.h>
|
|
#include <fstream.h>
|
|
#include <ctype.h>
|
|
|
|
static char mytmpstr[257];
|
|
|
|
class _HotSpot : public TObject
|
|
{
|
|
public:
|
|
// TArray _spots; // tokenstrings
|
|
char _bg, _fg;
|
|
|
|
_HotSpot(char fg, char bg) { _fg = fg; _bg = bg; }
|
|
virtual ~_HotSpot() {}
|
|
};
|
|
|
|
|
|
void TTextfile::set_hotspots(char fg, char bg)
|
|
{
|
|
_HotSpot* hp = new _HotSpot(fg,bg);
|
|
_hotspots.add(hp);
|
|
}
|
|
|
|
|
|
style TTextfile::_trans_style(char ch)
|
|
{
|
|
switch(ch)
|
|
{
|
|
case 'r': return normal; break;
|
|
case 'i': return italic; break;
|
|
case 'b': return bold; break;
|
|
case 'u': return underlined; break;
|
|
case 'o': return overstrike; break;
|
|
case 'k': return smallcaps; break;
|
|
default: return normal; break;
|
|
}
|
|
}
|
|
|
|
void TTextfile::_read_page(long n)
|
|
{
|
|
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;
|
|
fseek(_index, _page_start*(long)sizeof(long), SEEK_SET);
|
|
if (_page_start != 0l)
|
|
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(mytmpstr, sizeof(mytmpstr),_instr);
|
|
mytmpstr[strlen(mytmpstr) -1] = '\0';
|
|
TString& ts = (TString&)_page[(int)(i-_page_start)];
|
|
ts = mytmpstr;
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTextfile::read_line(long n, long pos, bool pg)
|
|
{
|
|
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 == '@' || (ch == '$' && *(sp) == '['))
|
|
{
|
|
if (!first && p >= pos)
|
|
{
|
|
_styles[_item++] = stl;
|
|
mytmpstr[ndx] = '\0';
|
|
_line.add(mytmpstr);
|
|
ndx = 0;
|
|
}
|
|
while(ch && (ch == '@' || (ch == '$' && *sp == '[')))
|
|
{
|
|
if (ch == '@') // font style change ?
|
|
{
|
|
style sss = _trans_style(*sp++);
|
|
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)
|
|
{
|
|
first = FALSE;
|
|
mytmpstr[ndx++] = ch;
|
|
}
|
|
p++;
|
|
}
|
|
_styles[_item++] = stl;
|
|
mytmpstr[ndx] = '\0';
|
|
_line.add(mytmpstr);
|
|
_item = 0;
|
|
}
|
|
|
|
const char* TTextfile::line(long j, long pos)
|
|
{
|
|
if (_cur_line != j) read_line(j);
|
|
*mytmpstr = '\0';
|
|
_line.restart();
|
|
for (int i = 0; i < _line.items(); i++)
|
|
strcat(mytmpstr, (const char*)_line.get());
|
|
return strlen(mytmpstr) > (word)pos ? &(mytmpstr[pos]) : "";
|
|
}
|
|
|
|
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())
|
|
{
|
|
x += strlen(c);
|
|
stl = _styles[nd++];
|
|
if ((x-1) >= pos) break; }
|
|
}
|
|
return stl;
|
|
}
|
|
|
|
int TTextfile::get_style(int pos)
|
|
{
|
|
long x = get_attribute(pos);
|
|
return (int)(x & 0x0000ffff);
|
|
}
|
|
|
|
char TTextfile::get_background(int pos)
|
|
{
|
|
long x = get_attribute(pos);
|
|
return (char)(x >> 24);
|
|
}
|
|
|
|
char TTextfile::get_foreground(int pos)
|
|
{
|
|
long x = get_attribute(pos);
|
|
return (char)((x >> 16) & 0x000000ff);
|
|
}
|
|
|
|
const char* TTextfile::piece()
|
|
{
|
|
if (_item >= _line.items()) return NULL;
|
|
return strcpy (mytmpstr, (const char*)_line.get(_item++));
|
|
}
|
|
|
|
const char* TTextfile::word_at(long x, long y)
|
|
{
|
|
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])) mytmpstr[x2++] = s[(int)x++];
|
|
}
|
|
mytmpstr[x2] = '\0';
|
|
return mytmpstr;
|
|
}
|
|
|
|
|
|
bool TTextfile::append(const char* l)
|
|
{
|
|
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))
|
|
{
|
|
TString* ll = new TString(l);
|
|
_page.add(ll);
|
|
_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()
|
|
{
|
|
CHECK(_isopen, "Attempt operation on closed file");
|
|
fclose(_instr);
|
|
fclose(_index);
|
|
_instr = _index = NULL;
|
|
_isopen = FALSE;
|
|
}
|
|
|
|
void TTextfile::print()
|
|
{
|
|
CHECK(_isopen, "Attempt operation on closed file");
|
|
warning_box("Funzione non ancora implementata");
|
|
// TBI istanzia una printer inibendo la scelta di video
|
|
// add all lines (maybe new method: print_txt)
|
|
// print
|
|
}
|
|
|
|
|
|
bool TTextfile::write(const char* path, TPoint* from, TPoint* to)
|
|
{
|
|
bool ok = FALSE;
|
|
FILE* fp;
|
|
if ((fp = fopen(path, "w")) != NULL)
|
|
{
|
|
ok = TRUE;
|
|
TString256 s;
|
|
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 ok;
|
|
}
|
|
|
|
|
|
void TTextfile::destroy()
|
|
{
|
|
CHECK(_istemp,"destroy() chiamata su testo permanente!");
|
|
if (_page.items() > 0)
|
|
{
|
|
if (_index) fclose(_index);
|
|
if (_instr) fclose(_instr);
|
|
remove((const char*)_filename);
|
|
remove((const char*)_indname);
|
|
_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)
|
|
{
|
|
error_box("Impossibile aprire files temporanei");
|
|
freeze();
|
|
}
|
|
_isopen = TRUE;
|
|
_page.destroy();
|
|
_spots.destroy();
|
|
}
|
|
}
|
|
|
|
|
|
TTextfile::TTextfile(const char* file, int pagesize, direction preferred) :
|
|
_page_size(pagesize), _page(pagesize), _filename(file), _lines(0l),
|
|
_index(NULL), _page_start(0l), _page_end(-1l), _direction(preferred),
|
|
_dirty(FALSE), _istemp(FALSE), _item(0), _line(256), _cur_line(-1),
|
|
_hotspots(4), _accept(TRUE)
|
|
{
|
|
// open file & build index
|
|
if (file == NULL) { _filename.temp(); _istemp = TRUE; }
|
|
|
|
_instr = fopen(_filename,"a+");
|
|
_indname.temp();
|
|
_index = fopen(_indname, "w+b");
|
|
|
|
if (_index == NULL || _instr == NULL)
|
|
{
|
|
error_box("Impossibile aprire files temporanei");
|
|
freeze();
|
|
}
|
|
if (file != NULL)
|
|
while (!feof(_instr))
|
|
{
|
|
const long l = ftell(_instr);
|
|
fwrite(&l, sizeof(long), 1, _index);
|
|
if (ferror(_index) || ferror(_instr))
|
|
{
|
|
error_box("Errore di scrittura file temporaneo: scrittura interrotta");
|
|
freeze();
|
|
}
|
|
fgets(mytmpstr, sizeof(mytmpstr), _instr);
|
|
_lines++;
|
|
}
|
|
_isopen = TRUE;
|
|
}
|
|
|
|
|
|
|
|
TTextfile::~TTextfile()
|
|
{
|
|
if (_index) fclose(_index);
|
|
if (_instr) fclose(_instr);
|
|
if (_istemp) remove((const char*)_filename);
|
|
remove((const char*)_indname);
|
|
}
|
|
|
|
|