473 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			473 lines
		
	
	
		
			9.9 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);
 | 
						|
}
 |