campo-sirio/include/text.cpp

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);
}