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