#ifndef __TEXTFILE_H
#define __TEXTFILE_H

#ifndef __STDIO_H
#include <stdio.h>
#endif                                     

#ifndef __STRINGS_H
#include <strings.h>
#endif

#ifndef __RELATION_H
#include <relation.h>
#endif

#ifndef __WINDOW_H
#include <window.h>
#endif

// @doc INTERNAL

// @enum direction | Direzioni da seguire nella lettura del file di testo
enum direction {
  up,   // @emem Direzione verso l'alto
  down, // @emem Direzione verso il basso
  updown};      // @emem Entrambe le direzioni


// @doc INTERNAL

// @enum style | Stile del carattere da utilizzare per il disegno del testo
enum style {
  normal = XVT_FS_NONE,                 // @emem Stile carattere normale
  bold = XVT_FS_BOLD,           // @emem Stile carattere in grassetto
  italic = XVT_FS_ITALIC,               // @emem Stile carattere in corsivo
  underlined = XVT_FS_UNDERLINE,        // @emem Stile carattere sottolineato
  tabbed = XVT_FS_SCALE };              // @emem Stile carattere scalato

// @doc EXTERNAL

// @class TTextfile | Classe per la definizione delle procedure di stampa di un testo
//
// @base public | TObject
class TTextfile: public TObject
// @author:(INTERNAL) Villa

// @access:(INTERNAL) Private Member
{
  // @ccost:(INTERNAL) DEFAULT_PAGESIZE | 128 | Dimensione di default della pagina
  enum {DEFAULT_PAGESIZE = 128};

  // @cmember:(INTERNAL) Pagina di testo correntemente in memoria
  TArray _page;
  // @cmember:(INTERNAL) Un bit per ogni riga, TRUE se ci si e' fatto replace
  TBit_array _dirty_lines;
  // @cmember:(INTERNAL) Inizio della pagina in coordinate testo
  long _page_start;
  // @cmember:(INTERNAL) Fine della pagina in coordinate testo
  long _page_end;
  // @cmember:(INTERNAL) Numero di righe di <p _page>
  long _page_size;
  // @cmember:(INTERNAL) Numero totale delle linee di testo
  long _lines;
  // @cmember:(INTERNAL) Numero della linea corrente
  long _cur_line;                             
  // @cmember:(INTERNAL) Nome del file di testo (puo' essere temporaneo)
  TFilename _filename;
  // @cmember:(INTERNAL) Nome del file indice (sempre temporaneo)
  TFilename _indname;
  // @cmember:(INTERNAL) Puntatore al file indice
  FILE* _index;
  // @cmember:(INTERNAL) Puntatore al file di testo
  FILE* _instr;
  // @cmember:(INTERNAL) Direzione ottimale di lettura del file (vedi <t direction>)
  direction _direction;
  
  // @cmember:(INTERNAL) Piece corrente
  int _item;
  // @cmember:(INTERNAL) Testo della riga corrente
  TToken_string _line;
  // @cmember:(INTERNAL) Codifica delllo stile e del colore del carattere
  long _styles[256];
  // @cmember:(INTERNAL) Indica se la piece e' <e style.tabbed>
  bool _tabbed_piece; 

  // @cmember:(INTERNAL) Punti ipertestuali come passati da utente (<c TViswin>)
  TArray _hotspots;
  // @cmember:(INTERNAL) Rappresentazione interna punti ipertestuali
  TArray _spots;
  // @cmember:(INTERNAL) Indice se e' stato modificato
  bool _dirty;
  // @cmember:(INTERNAL) Indica se i file sono aperti
  bool _isopen;
  // @cmember:(INTERNAL) Indica se si tratta di un file temporaneo
  bool _istemp;
  // @cmember:(INTERNAL) Indica se e' permesso dare una <mf TTextfile::append>
  bool _accept;
  // @cmember:(INTERNAL) Indica se si sta modificando con <mf TTextfile::add> e si puo' fare <mf TTextfile::replace>
  bool _interactive;

  // @cmember:(INTERNAL) Gestisce la sostituzione di campi al posto di tag nel testo
  TRelation* _rel;

  // @cmember:(INTERNAL) Riempe la pagina contenente <p line>, ottimizzando start ed end
  void _read_page(long line);
  // @cmember:(INTERNAL) Ritorna TRUE se la roga <p l> e' nella pagina corrente
  bool _in_page(long l)        
  { return  l >= _page_start && l < _page_end; }
  // @cmember:(INTERNAL) Salva i replace fatti sul file (anche temporaneo)
  void _save_changes();
  
  //  void   _parse_style(long j);

  // @cmember:(INTERNAL) Traduce il tag dello stile passato in <p c> (tag) con uno di <t style> (stile XVT)
  style _trans_style(char c);          
  
  // @access Public Member
public:
  // @cmember Ritorna il numero totale delle linee di testo
  long lines()
  { return _lines; }
  // @cmember Ritorna se sono state effettuate delle modifiche
  bool changed() 
  { return _dirty; } 
  

  // @cmember Ritorna la stringa di caratteri senza formattazione
  const char* line(long row, long column = 0, int howmuch = -1);

  // @cmember Ritorna la stringa di caratteri con la formattazione
  const char* line_formatted(long row);

  // @cmember Aggiunge una riga al text (con i formati del caso)
  bool append(const char* l);  

  // @cmember Chiude tutti i files per poter copiare o eseguire operazioni. Dopo aver chiamato
  //          questa funzione non si puo' piu' fare nulla.
  void close();
  // @cmember Stampa su carta
  void print();
  // @cmember Chiude l'aggiunta di nuove linee
  void freeze() 
  { _accept = FALSE; }
  // @cmember Ritorna se e' possibile aggiungere delle nuove righe (TRUE se non vengono accettate)
  bool frozen() 
  { return  !_accept; }
  
  // @cmember Legge il testo formattato
  void read_line(long j, long b = 0, bool pg = TRUE);
  // @cmember Ritorna il pezzo di linea successivo con stile e colore
  const char* piece();            
  // @cmember Ritorna lo stile del piece (vedi <t style>)
  int get_style(int pos = -1);
  // @cmember Ritorna il colore di background del piece
  char get_background(int pos = -1);
  // @cmember Ritorna il colore di foreground del piece
  char get_foreground(int pos = -1); 
  // @cmember Ritorna gli attributi alla posizione <p pos>
  long get_attribute(int pos = -1);

  // @cmember Ritorna la parola alla posizione indicata
  const char* word_at(long x, long y);                  

  // @cmember Ritorna il pezzo di testo indicato (da <p form> a <p to>), allochera' un altro
  //           TText che deve essere disfatto dall'utente.
  TTextfile*  section(TPoint& from, TPoint& to) 
  { return this; }    
  // @cmember Ritorna il nome del file su cui si sta lavorando
  const char* name() 
  { return (const char*)_filename; }  
  // @cmember Permette di settare il valore di <p _iteractive> (vedi sopra)
  void interactive(bool on = TRUE) 
  { _interactive = on; }
  
  // @cmember Scrive il testo (non formattato) su file
  bool write(const char* path, TPoint* from = NULL, TPoint* to = NULL);
  // @cmember Scrive il testo (non formattato) su TString_array
  void write(TString_array& a, TPoint* from = NULL, TPoint* to = NULL);
  // @cmember Disfa tutto e svuota il file
  void destroy(); 

  // @cmember Cerca una stringa di testo all'interno di una riga
  long search (const char* txt, int& pos, long from = 0, bool down = TRUE, bool casesens = FALSE, bool regexp = FALSE);
  // @cmember Sostituisce un testo all'interno di una riga
  int replace(long line, const char* txt, int pos = 0, int len = -1);

  // @cmember Permette di settare gli hot_spot
  void set_hotspots(char fg, char bg = 'w');
  // @cmember Ritorna l'array di hotspots
  TArray& hotspots() 
  { return _spots; }
  
  // @cmember Associa una relazione che viene usata (nello stato corrente) per
  //          risolvere eventuali campi per merge (marcati nel testo come
  //          <lt>@file-<gt>fieldname@[format]@[len]@[just]<gt>
  void set_relation(TRelation* r) 
  { _rel = r; }
  
  // @cmember Costruttore
  TTextfile(const char* file = NULL, int pagesize = DEFAULT_PAGESIZE, direction preferred = updown, bool interactive = TRUE);
  // @cmember Distruttore
  virtual ~TTextfile();
};

#endif

