#include <mask.h>
#include <printapp.h>
#include <recarray.h>
#include <tabutil.h>
#include <utility.h>
#include <sort.h>

#include <comuni.h>
#include <nditte.h>
#include <unloc.h>
#include <clifo.h>
#include <pconti.h>
#include <anagr.h>

#include "ba3.h"
#include "ba3800.h"

class BA3800_application : public TPrintapp
{                              
  TTable*           _tabivd;
  const char*       _buff;
  TSort*            _sort; 
  
  TDate   _datastampa;
  bool    _diffprod_fatto,_risimp_fatto;
  TString _numr_tot,_num_tot,_numr,_numr_da_stamp,_num_da_stamp,_numr_stamp,_num_stamp, _cont_num, _num;
  char    _sez_da_stamp,_let_da_stamp,_sez_stamp,_let_stamp,_sez_tot,_let_tot,_let,_sez;
  int     _cont_let,_cont_numr,_cont_gcs,_i;
  bool    _reset_righe_stampa,_statopatr_no_stamp,_sbilancio_ordine; 
  bool    _totale_attivita_gia_stampato,_totale_passivita_gia_stampato, _vaccata;    
  bool    _sbilancio_patr_gia_stampato,_attivo_o_passivo;
  TString _causale_ap, _causale_chi, _totale;
  char _liv;
  TString tmp;  

public:

  bool menu (MENU_TAG m) { return TPrintapp::menu(m) ; }
  virtual bool user_create() ;
  virtual bool user_destroy() { delete _tabivd; return true;}
  virtual bool set_print(int);
  
  virtual bool preprocess_page  (int,int);
  virtual print_action postprocess_page (int,int);
  virtual void postclose_print ();
  
  virtual void set_page(int,int);

  void intestazione_ditta();
  void intestazione_studio();
  void stampa_totali_studio();
  void stampa_totali_ditta();  
  bool preprocess_ditta(int);  
  bool preprocess_studio(int);
  
  void setta_righe_studio(const char*); 
  void setta_righe_ditta(const char*);  
  void totale_numero_arabo();
  void totale_numero_romano();
  void totale_lettera();   
  void init_sort();    
  void crea_sort_tabella();
  void crea_sort_piano_conti();
  void scrivi_record(const TString&,const TString&,const TString&, const TString &,int,int,long);
  void riempi_record(const TString&,const TString&,const TString&, const TString &,int,int,long);
  void set_bil_key(TString & key, char sezione, char lettera,
                   const char* numero_romano, const char * numero,
                   bool conti_ordine = true, int conto = 0,
                   int gruppo = 0, long sottoconto = 0L);
  const char* descrizione_lettera(char, char);
  const char* descrizione_numeroromano(char, char, int);
  const char* descrizione_numero(char, char, int, const TString &);
  const char* descrizione_sottoconto(int, int, long);  
  void setta_righe_descr(const char *, const char *);
  
  BA3800_application(char livello) : _liv(toupper(livello)) {}
};

const char * num2str(const TString & s)
{
	TString & str = get_tmp_string(20);

	str = s;
	str.trim();
	if (str.len() > 2)
	{
		str = s.left(2);
		const int sub = atoi(s.mid(2));
		switch (sub)
		{
			case 0:
			case 1:
				break;
			case 2:
				str << " bis";
				break;
			case 3:
				str << " ter";
				break;
			case 4:
				str << " quater";
				break;
			case 5:
				str << " quinquies";
				break;
			case 6:
				str << " sexies";
				break;
			default:
				break;
		}
	}
	return (const char *) str;
}

void BA3800_application::postclose_print()
{ 
  if (_liv == 'D')
    delete _sort;
}

void BA3800_application::set_bil_key(TString & key, char sezione, char lettera,
                                     const char* numero_romano, const char * numero,
                                     bool conti_ordine, int gruppo, int conto,
                                     long sottoconto)

{
  //Se esiste solamente la sezione,significa che e' un conto d'ordine
  //Forzo la lettera della classe a Z, per ottenere, grazie
  //all'ordinamento del sort, i record dei conti d'ordine per ultimi
	if (sezione == '\0')
		sezione = ' ';
	if (lettera == '\0')
		lettera = ' ';

	key.format("%1c%1c%-4s%-4s", sezione, ((conti_ordine && lettera == '\0' && sezione < '3') ? 'Z' : lettera), numero_romano, numero);

  if (gruppo < 0)
    key << "ZZZZZZZZZZZZ";
  else
    key << format("%03d%03d%06ld", gruppo, conto, sottoconto);
}

void BA3800_application::scrivi_record(const TString& sez,
                                       const TString& let,  const TString& numerorom, const TString & numero,
                                       int g,int c,long s)
{
  
  //Se esiste solamente la sezione,significa che e' un conto d'ordine
  //Forzo la lettera della classe a Z, per ottenere, grazie
  //all'ordinamento del sort, i record dei conti d'ordine per ultimi
	TString key;

  set_bil_key(key, sez[0], let[0], numerorom, numero, true, g, c, s);
  _sort->sort ((const char*) key);
}

void BA3800_application::riempi_record(const TString& sez,
                                       const TString& let,  const TString& numerorom, const TString & numero,
                                       int g,int c,long s)
{
	TString key;

  set_bil_key(key, sez[0], let[0], numerorom, numero, false, g, c, s);
  _sort->sort ((const char*) key);
}

void BA3800_application::crea_sort_tabella()
{
  TTable tabivd(TAB_IVD);
  
  // Compilo tanti record quante sono le classi IV direttiva trovate sulla
  // tabella %IVD, usando dei gruppi, conti e sottoconti fittizi. Successivamente
  // nel caso di stampa completa verranno stampati anche questi record; nel caso
  // di stampa non completa non verranno stampati.
  
  for (int err = tabivd.first(); err == NOERR; err = tabivd.next())
  {
		const TString & codtab = tabivd.get("CODTAB");
    const char sez = codtab[0];
    const char let = codtab[1];
    const TString16 nrom(codtab.mid(2, 4));
    const TString16 nu(codtab.mid(6));
		TString key;
    
    set_bil_key(key, sez, let,(const char*)nrom, nu, false,-1);
    _sort->sort ((const char*) key);
  }
}

// Passo al sort tutti i record presenti su piano dei conti, aventi la classe
// IV direttiva CEE.

void BA3800_application::crea_sort_piano_conti()
{
  TLocalisamfile pconti(LF_PCON);
  TString sez,let,numerorom, num_conto;
  TString sez_conto,let_conto,numr_conto, numero;
  int     indbil;
  char    sezione,lettera,tmcf;
  int     g,c;
  long    s;
  bool    classe_conto          = false;
  bool    conto_dettagliato     = false;
  bool    stsottbil;

  for (int err = pconti.first(); err == NOERR; err = pconti.next())
  {
    //    _prog->addstatus(1);
    g         = pconti.get_int (PCN_GRUPPO);
    c         = pconti.get_int (PCN_CONTO);
    s         = pconti.get_long(PCN_SOTTOCONTO);
    sez       = pconti.get(PCN_SEZIVD);
    let       = pconti.get(PCN_LETTIVD);
    sezione   = sez[0];
    lettera   = let[0];
    numerorom = pconti.get(PCN_NUMRIVD);
    numero    = pconti.get(PCN_NUMIVD);
		if (atoi(numero) != 0 && numero.len() == 1)
			numero.insert("0");  // pacco per fare andare anche i record vecchi cosa si deve fare!!!!
    
    // Se si tratta di un conto e contiene la classe, allora lo passo al sort.
    // Gli eventuali sottoconti avranno la stessa classe.
    
    if ((g != 0) && (c != 0) && (s == 0))
    {
      stsottbil   = pconti.get_bool(PCN_STSOTTBIL);
      tmcf        = pconti.get     (PCN_TMCF)[0];
      indbil      = pconti.get_int (PCN_INDBIL);

      //Se sono nello stesso gruppo, ma ho un conto diverso da quello precedentemente
      //analizzato, e se questi contiene la classe IV dir. CEE,
      //allore devo controllare se va dettagliato (se STSOTTBIL e' true il conto non
      //va dettagliato, se false va dettagliato)

      if (sez != "0")
      {
        if (stsottbil || tmcf == 'C' || tmcf == 'F')
          conto_dettagliato = false;
        else
          conto_dettagliato = true;

        sez_conto  = sez;
        
        if (let != "")
          let_conto  = let;
        else
          if ((sez == "1")||(sez == "2"))
            let_conto  = "Z";
          else
            let_conto = let;
        
        numr_conto   = numerorom;
        num_conto    = numero;  
        
        riempi_record(sez_conto,let_conto,numr_conto,num_conto,g,c,0);
        
        classe_conto = true;
      }
      else
      {
        classe_conto      = false; // Metto conto dettagliato = true perche' potrebbero esserci dei sottoconti
        conto_dettagliato = true;  // di questo conto che hanno la classe e quindi vanno stampati.
      }
    }
    
    // Se si tratta di un sottoconto e contiene la classe, allora lo passo al sort.

    if ((g != 0) && (c != 0) && (s != 0))
    {       
      // classe_conto indica se il conto precedentemente letto conteneva
      // la classe. In caso affermativo anche questo sottoconto appena
      // letto avra' la stessa classe del conto.
      
      if (classe_conto)
      {
        if (conto_dettagliato) 
          riempi_record(sez_conto,let_conto,numr_conto,num_conto,g,c,s);
      }
      else
        if (sez != "0")
          riempi_record(sez,let,numerorom,numero,g,c,s);
    }
  }
}

bool BA3800_application::set_print(int)
{       
  TMask msk("ba3800a");

  const KEY tasto= msk.run(); 

  if (tasto == K_ENTER) 
  {  
    _datastampa = msk.get(F_DATASTAMPA);    

    _cont_let  = 0;
    _cont_numr = 0;
    _cont_num  = "";
    _cont_gcs  = 0;
    
    _totale = "XXXXXXXXXXX";
    
    _sez_stamp  = ' ';
    _let_stamp  = ' ';
    _numr_stamp = "";
    _num_stamp  = "";
    _sez_tot    = ' ';
    _let_tot    = ' ';
    _numr_tot   = "";
    _num_tot    = ""; 
    
    _statopatr_no_stamp            = true;   
    _diffprod_fatto                = false;            
    _risimp_fatto                  = false;
    _totale_attivita_gia_stampato  = false;
    _totale_passivita_gia_stampato = false;
    _sbilancio_ordine              = false; 
    _sbilancio_patr_gia_stampato   = false;
    _attivo_o_passivo              = false;
		_vaccata									  	 = false;
    
    printer().footerlen(5);
    
    if (_liv == 'S')
      intestazione_studio();
    else
      if (_liv == 'D')
      { 
        init_sort();
        crea_sort_tabella();
        crea_sort_piano_conti();
        _sort->endsort();
        intestazione_ditta();
      }
    
    return true;
  }
  return false;
}    

void BA3800_application::totale_numero_arabo()
{
  if (_cont_gcs != 0)//(_cont_gcs >= 2)
  {
    //Fai il totale del numero arabo e stampalo 
    if (_num.not_empty())
    {
      set_row (_i,FR("@18gTotale@25g%s)"), num2str(_num));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
  }
}

void BA3800_application::totale_numero_romano()
{
  if (_cont_num.not_empty())//(_cont_num >= 2)
  {
    //Fai il totale del numero romano e stampalo
    int numeror = atoi(_numr);
    TString numrom  = itor(numeror); 
    if (numrom != "")
    {
      set_row (_i, FR("@14gTotale@21g%s"), (const char*) numrom);
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
  }
}  

void BA3800_application::totale_lettera()
{
  if (_cont_numr != 0)//(_cont_numr >= 2)
  {
    //Fai il totale della lettera e stampalo 
    if (_let != ' ')
    {
      set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
  }
}

void BA3800_application::stampa_totali_studio()
{
  const TString16 diff_prod("9B");
  const TString16 ris_imp  ("9E        21");
  
  _num  = _num_tot;
  _numr = _numr_tot;
  _let  = _let_tot;

  if (_tabivd->eof()) 
  {
    _num_tot  = "";
    _numr_tot = "";
    _let_tot  = ' ';
    _sez_tot  = ' ';
  }    

  if (_num_da_stamp != _num_tot)
  {       
    totale_numero_arabo();
    
    if (_sez_stamp == '9')
    {
      TString16 classe;
      
      classe.format("%c%c%8s%-4s", _sez_da_stamp,_let_da_stamp,(const char*)_numr_da_stamp,(const char*)_num_da_stamp);
			classe.rtrim();
      
      if (classe > ris_imp && !_risimp_fatto)
      { 
        if (_num_tot == "20" || _num_tot == "21")
        {
          set_row (_i, FR("@4gTotale delle partite straordinarie"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          set_row (_i,FR("@4gRisultato prima delle imposte"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          _risimp_fatto = true;
        }
      }
    }
    
    _cont_gcs = 0;
  }
  if (_numr_da_stamp != _numr_tot)
  {
    totale_numero_arabo();
    totale_numero_romano();
    _cont_gcs = 0;
    _cont_num = "";
  }   
  if (_let_da_stamp!=_let_tot)
  { 
    if (_sez_stamp == '9')
    {
      TString16 classe;
      
      classe.format("%c%c%8s%-4s",_sez_stamp,_let_stamp,(const char*)_numr_stamp,(const char*)_num_stamp);
			classe.rtrim();
      
      totale_numero_arabo();
      totale_numero_romano();
      
      if (_cont_numr != 0)//(_cont_numr >= 2)
      {
        //Fai il totale della lettera e stampalo  
        if (_let_stamp == 'D')
          set_row (_i,FR("@4gTotale delle rettifiche"));
        else          
          if (_let != ' ')
            if (_sez_stamp == '9' && _let_stamp != 'E')
              set_row (_i, FR("@3gTotale@10g%c@12g)"), _let);
            else  
              if (_sez_stamp != '9')
                set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
        if (_let != ' ')
        {
          if (_sez_stamp == '9' && _let_stamp != 'E')  
            set_row (_i++,"@86g%s", (const char*) _totale);
          else
            if (_sez_stamp != '9')                    
              set_row (_i++,"@86g%s", (const char*) _totale);    
        }
      }
      
      if (classe > diff_prod && !_diffprod_fatto)
      { 
        if (_let_tot == 'A' || _let_tot == 'B') //Solo se esiste una delle due lettere
        {               
          set_row (_i++,FR("@4gDifferenza tra valore e costi della produzione@86g%s"), (const char*) _totale);
          _diffprod_fatto = true;
        }
      }
    }
    else
    {
      totale_numero_arabo();
      totale_numero_romano();
      totale_lettera();
    }   
    
    _cont_gcs = 0;
    _cont_num = 0;
    _cont_numr = 0;
  }     
  if (_sez_da_stamp != _sez_tot)
  {
    totale_numero_arabo();
    totale_numero_romano();
    
    if (_cont_numr != 0)//(_cont_numr >= 2)
    {
      //Fai il totale della lettera e stampalo
      if (_let != ' ')
      {   
        if (_sez_stamp == '9' && _let_stamp != 'E')
        {
          set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
          set_row (_i++,"@86g%s", (const char*) _totale);
        }
        else
          if (_sez_stamp != '9')
          {
            set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
      }
    }
    if (_sez_stamp == '1')
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);
      set_row (_i, FR("@0gTOTALE ATTIVO"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
    
    if (_sez_stamp == '2') //&& (_let_stamp != 'Z'))
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);
      set_row (_i, FR("@0gTOTALE PASSIVO"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }  
    
    if (_sez_stamp == '2')
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);
      set_row (_i++, FR("@0gSALDO STATO PATRIMONIALE"));
      set_row (_i, FR("@0gSBILANCIO (ATTIVO - PASSIVO)"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }

    if (_sez_stamp == '9')
    { 
      if (_tabivd->eof()) 
      {  
        if ((_let_stamp == 'A' || _let_stamp == 'B') && !_diffprod_fatto)//Solo se esiste una delle due lettere
        {               
          set_row (_i++, FR("@4gDifferenza tra valore e costi della produzione@86g%s"), (const char*) _totale);
          _diffprod_fatto = true;
        }
        if (!_risimp_fatto)  
        {  
          set_row (_i, FR("@4gRisultato prima delle imposte"));
          set_row (_i++,"@86g%s", (const char*) _totale);
        }
      }  
      
      char app = ' ';
      set_row (_i++,"@0g%c", app);
      set_row (_i,FR("@0gRISULTATO CONTO ECONOMICO"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
    _cont_gcs = 0;
    _cont_num = 0;
    _cont_numr = 0;
    _cont_let = 0;
  }
}

void BA3800_application::stampa_totali_ditta()
{
  bool gia_stampato_conto_ord = false;
  const TString16 diff_prod("9B");
  const TString16 ris_imp  ("9E        21");
  
  _num  = _num_tot;
  _numr = _numr_tot;
  _let  = _let_tot;

  if (_buff == NULL) 
  {
    _num_tot  = "";
    _numr_tot = "";
    _let_tot  = ' ';
    _sez_tot  = ' ';
  }  
  
  if ((_sez_stamp == '1' || _sez_stamp == '2') && _let_stamp != 'Z')  
    _attivo_o_passivo = true;

  if (_num_da_stamp != _num_tot)
  {       
    if (_let_stamp != 'Z')
    {
      if (_sez_stamp != '5')
        if (_cont_gcs != 0)//(_cont_gcs >= 2)
        {
          //Fai il totale del numero arabo e stampalo 
          if (_num.not_empty())
          {
            set_row (_i, FR("@18gTotale@25g%s)"), num2str(_num));
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
        }
    }
    if (_sez_stamp == '9')
    {
      TString16 classe;
      
      classe.format("%c%c%8s%-4s", _sez_da_stamp,_let_da_stamp,(const char*)_numr_da_stamp,(const char*)_num_da_stamp);
			classe.rtrim();
      
      if (classe > ris_imp && !_risimp_fatto)
      { 
        if (_num_tot == "20" || _num_tot == "21")
        {
          set_row (_i, FR("@4gTotale delle partite straordinarie"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          set_row (_i, FR("@4gRisultato prima delle imposte"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          _risimp_fatto = true;
        }
      }
    }
    
    _cont_gcs = 0;
  }
  if (_numr_da_stamp != _numr_tot)
  {
    if (_let_stamp != 'Z')
    {
      if (_sez_stamp != '5')
      {
        if (_cont_gcs != 0)//(_cont_gcs >= 2)
        {
          //Fai il totale del numero arabo e stampalo 
          if (_num.not_empty())
          {
            set_row (_i, FR("@18gTotale@25g%s)"), num2str(_num));
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
        }
        if (_cont_num.not_empty())//(_cont_num >= 2)
        {
          //Fai il totale del numero romano e stampalo
          int numeror = atoi(_numr);
          TString numrom  = itor(numeror); 
          if (numrom != "")
          {
            set_row (_i,FR("@14gTotale@21g%s"), (const char*) numrom);
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
        }
      }
    }
    _cont_gcs = 0;
    _cont_num = 0;
  }   
  if (_let_da_stamp!=_let_tot)
  { 
    if (_sez_stamp == '9')
    {
      TString16 classe;
      
      classe.format("%c%c%8s%-4s",_sez_stamp,_let_stamp,(const char*)_numr_stamp,(const char*)_num_stamp);
			classe.ltrim();
      
      if (_cont_gcs != 0)//(_cont_gcs >= 2)
      {
        //Fai il totale del numero arabo e stampalo
        if (_num.not_empty())
        {
          set_row (_i,FR("@18gTotale@25g%s)"), num2str(_num));
          set_row (_i++,"@86g%s", (const char*) _totale);
        }
      }
      if (_cont_num.not_empty())//(_cont_num >= 2)
      {
        //Fai il totale del numero romano e stampalo  
        int numeror = atoi(_numr);
        TString numrom  = itor(numeror);
        if (numrom != "")
        {
          set_row (_i, FR("@14gTotale@21g%s"), (const char*) numrom);
          set_row (_i++,"@86g%s", (const char*) _totale);
        }
      }
      if (_cont_numr != 0)//(_cont_numr >= 2)
      {
        //Fai il totale della lettera e stampalo  
        if (_let_stamp == 'D')
          set_row (_i, FR("@4gTotale delle rettifiche"));
        else          
          if (_let != ' ')
            if (_sez_stamp == '9' && _let_stamp != 'E')
              set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
            else  
              if (_sez_stamp != '9')
                set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
        if (_let != ' ')
        {
          if (_sez_stamp == '9' && _let_stamp != 'E')  
            set_row (_i++,"@86g%s", (const char*) _totale);
          else
            if (_sez_stamp != '9')                    
              set_row (_i++,"@86g%s", (const char*) _totale);    
        }
      }
      
      if (classe > diff_prod && _diffprod_fatto)
      { 
        if (_let_tot == 'A' || _let_tot == 'B') //Solo se esiste una delle due lettere
        {               
          set_row (_i++, FR("@4gDifferenza tra valore e costi della produzione@86g%s"), (const char*)_totale);
          _diffprod_fatto = false;
        }
      }
    }
    else
    {
      if (_let_stamp != 'Z')
      {
        if (_sez_stamp != '5')
        {
          if (_cont_gcs != 0)//(_cont_gcs >= 2)
          {
            //Fai il totale del numero arabo e stampalo 
            if (_num.not_empty())
            {
              set_row (_i,FR("@18gTotale@25g%s)"), num2str(_num));
              set_row (_i++,"@86g%s", (const char*) _totale);
            }
          }
          if (_cont_num.not_empty())//(_cont_num >= 2)
          {
            //Fai il totale del numero romano e stampalo
            int numeror = atoi(_numr);
            TString numrom  = itor(numeror); 
            if (numrom != "")
            {
              set_row (_i,FR("@14gTotale@21g%s"), (const char*) numrom);
              set_row (_i++,"@86g%s", (const char*) _totale);
            }
          }
          if (_cont_numr != 0)//(_cont_numr >= 2)
          {
            //Fai il totale della lettera e stampalo 
            if (_let != ' ')
            {
              set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
              set_row (_i++,"@86g%s", (const char*) _totale);
            }
          }
        }   
      }
      
      if ((_sez_stamp == '1')&&(_let_da_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i,FR("@0gTOTALE ATTIVO"));
        set_row (_i++,"@86g%s", (const char*) _totale);
        _totale_attivita_gia_stampato = true;
      }
      
      if ((_sez_stamp == '2')&&(_let_da_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i,FR("@0gTOTALE PASSIVO"));
        set_row (_i++,"@86g%s", (const char*) _totale);
        _totale_passivita_gia_stampato = true;
      }
      
      if ((_sez_stamp == '1')&&(_let_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i, FR("@0gTOTALE CONTI D' ORDINE ATTIVI"));
        set_row (_i++,"@86g%s", (const char*) _totale);
        gia_stampato_conto_ord = true;
      }
      
      if ((_sez_stamp == '2')&&(_let_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i, FR("@0gTOTALE CONTI D' ORDINE PASSIVI"));
        set_row (_i++,"@86g%s", (const char*) _totale);
        _i++;                                            
        gia_stampato_conto_ord = true;
        if (!_attivo_o_passivo) 
        {
          set_row (_i++,FR("@0gSALDO CONTI D' ORDINE"));
          set_row (_i,FR("@0gSBILANCIO"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          _sbilancio_ordine = true;  
          _sbilancio_patr_gia_stampato = true;
        }
      }
    }
    _cont_gcs  = 0;
    _cont_num  = 0;
    _cont_numr = 0;
  }     
  if (_sez_da_stamp != _sez_tot)
  {
    if (_let_stamp != 'Z')
    {
      if (_sez_stamp != '5')
      {
        if (_cont_gcs != 0)//(_cont_gcs >= 2)
        {
          //Fai il totale del numero arabo e stampalo
          if (_num .not_empty())
          {
            set_row (_i,FR("@18gTotale@25g%s)"), num2str(_num));
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
        }
        if (_cont_num .not_empty())//(_cont_num >= 2)
        {
          //Fai il totale del numero romano e stampalo
          int numeror = atoi(_numr);
          TString numrom  = itor(numeror);
          if (numrom != "")
          {
            set_row (_i, FR("@14gTotale@21g%s"), (const char*) numrom);
            set_row (_i++,"@86g%s", (const char*) _totale);
          }
        }
        if (_cont_numr != 0)//(_cont_numr >= 2)
        {
          //Fai il totale della lettera e stampalo
          if (_let != ' ')
          {   
            if (_sez_stamp == '9' && _let_stamp != 'E')
            {
              set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
              set_row (_i++,"@86g%s", (const char*) _totale);
            }
            else
              if (_sez_stamp != '9')
              {
                set_row (_i,FR("@3gTotale@10g%c@12g)"), _let);
                set_row (_i++,"@86g%s", (const char*) _totale);
              }
          }
        }
      }
    }

    if (!_totale_attivita_gia_stampato)
      if ((_sez_stamp == '1') && (_let_stamp != 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i,FR("@0gTOTALE ATTIVO"));
        set_row (_i++,"@86g%s", (const char*) _totale);
      }
    
    if (!_totale_passivita_gia_stampato)
      if ((_sez_stamp == '2') && (_let_stamp != 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i,FR("@0gTOTALE PASSIVO"));
        set_row (_i++,"@86g%s", (const char*) _totale);
      }  
    
    if (!gia_stampato_conto_ord)
    {                                                
      if (_sez_stamp == '2')
      {           
        if (!_sbilancio_patr_gia_stampato)
        {  
          char app = ' ';
          set_row (_i++,"@0g%c", app);
          set_row (_i++, FR("@0gSALDO STATO PATRIMONIALE"));
          set_row (_i, FR("@0gSBILANCIO (ATTIVO - PASSIVO)"));
          set_row (_i++,"@86g%s", (const char*) _totale);
          _sbilancio_patr_gia_stampato = true;
        }
      }
      if ((_sez_stamp == '1')&&(_let_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i, FR("@0gTOTALE CONTI D' ORDINE ATTIVI"));
        set_row (_i++,"@86g%s", (const char*) _totale);
      }
      
      if ((_sez_stamp == '2')&&(_let_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);
        set_row (_i,FR("@0gTOTALE CONTI D' ORDINE PASSIVI"));
        set_row (_i++,"@86g%s", (const char*) _totale);  
        _i++;                
        if (!_sbilancio_ordine)
        {
          set_row (_i++,"@0g%c", app);
          set_row (_i++, FR("@0gSALDO CONTI D' ORDINE"));
          set_row (_i, FR("@0gSBILANCIO"));
          set_row (_i++,"@86g%s", (const char*) _totale);   
          _sbilancio_ordine = true;  
        }
      }
    }

    if (_sez_stamp == '2')
    {
      char app = ' ';
      if (!_sbilancio_patr_gia_stampato)
      {
        set_row (_i++,"@0g%c", app);
        set_row (_i++, FR("@0gSALDO STATO PATRIMONIALE"));
        set_row (_i, FR("@0gSBILANCIO (ATTIVO - PASSIVO)"));
        set_row (_i++,"@86g%s", (const char*) _totale);
      }
      if (!_sbilancio_ordine)
      {   
        set_row (_i++,"@0g%c", app);
        set_row (_i++, FR("@0gSALDO CONTI D' ORDINE"));
        set_row (_i, FR("@0gSBILANCIO"));
        set_row (_i++,"@86g%s", (const char*) _totale);
      }          
    }
    if (_sez_stamp == '5')
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);
      set_row (_i, FR("@0gTOTALE CONTI D' ORDINE"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
    if (_sez_stamp == '9')
    { 
      if (_tabivd->eof()) 
      {  
        if ((_let_stamp == 'A' || _let_stamp == 'B') && _diffprod_fatto)//Solo se esiste una delle due lettere
        {               
          set_row (_i++,FR("@4gDifferenza tra valore e costi della produzione@86g%s"), (const char*) _totale);
          _diffprod_fatto = false;
        }
        if (!_risimp_fatto)  
        {  
          set_row (_i, FR("@4gRisultato prima delle imposte"));
          set_row (_i++,"@86g%s", (const char*) _totale);
        }
      }  
      
      char app = ' ';
      set_row (_i++,"@0g%c", app);  
      set_row (_i,FR("@0gRISULTATO CONTO ECONOMICO"));
      set_row (_i++,"@86g%s", (const char*) _totale);
    }
    _cont_gcs = 0;
    _cont_num = "";
    _cont_numr = 0;
    _cont_let = 0;
  }
}

print_action BA3800_application::postprocess_page(int file, int counter)
{                       
  if (_liv == 'S')
  {
    if (_sez_da_stamp != _sez_stamp)
    {
      if (_sez_da_stamp == '9')
      {                      
        reset_print();
        _i = 1;
        setta_righe_studio(TR("CONTO ECONOMICO"));
        _reset_righe_stampa = false; 
      }
    }

    set_auto_ff(false);   
    
    if (_tabivd->eof()) 
      return NEXT_PAGE;
  } 
  else
    if (_liv == 'D')
    {  
      struct bil_ivd* bil = (struct bil_ivd*) _buff;                              

      bil = (struct bil_ivd*) _buff;     
      
      if (_sez_da_stamp != _sez_stamp)
      {
        if (_sez_da_stamp == '5')
        { 
          reset_print();
          _i = 1;
          setta_righe_ditta(TR("CONTI D' ORDINE"));
          _reset_righe_stampa = false;
        }
        if (_sez_da_stamp == '9')
        {                      
          reset_print();
          _i = 1;
          setta_righe_ditta(TR("CONTO ECONOMICO"));
          _reset_righe_stampa = false; 
        }
      }

      set_auto_ff(false); 
      
      if (_buff == NULL)
        return NEXT_PAGE;
    }

  return REPEAT_PAGE;
}

bool BA3800_application::preprocess_page(int file, int counter)
{      
  if (_liv == 'S')
  {
    if (preprocess_studio(counter))
      return true;
    else 
      return false;
  }
  else if (_liv == 'D')
  {
    if (preprocess_ditta(counter))
      return true;
    else 
      return false;
  }

  return true;
}


bool BA3800_application::preprocess_studio(int counter)
{ 
  TString saldostr,saldo_rafstr;    
  
  if (counter == 0)
  {          
    _tabivd->setkey(1);
    _tabivd->zero();
    _tabivd->first();  
    reset_print();
    _i = 1;
  }                    
  else
    _tabivd->next();
  
  if (_reset_righe_stampa)
  {
    reset_print();
    _i = 1;
  }
  else
    _reset_righe_stampa = true;                 
  
  if (counter)
  {
    _sez_stamp  = _sez_da_stamp;
    _let_stamp  = _let_da_stamp;
    _numr_stamp = _numr_da_stamp;
    _num_stamp  = _num_da_stamp;
    _sez_tot    = _sez_da_stamp;
    _let_tot    = _let_da_stamp;
    _numr_tot   = _numr_da_stamp;
    _num_tot    = _num_da_stamp;
  }


  if (!_tabivd->eof())
  { 
    TString16 codtab;

    codtab = _tabivd->get("CODTAB");
    _sez_da_stamp  = codtab[0];
    _let_da_stamp  = codtab[1];
    _numr_da_stamp = codtab.mid(2, 4);
    _numr_da_stamp.ltrim();
    _num_da_stamp  = codtab.mid(6, 4);
    _num_da_stamp.ltrim();

    if (counter)
      stampa_totali_studio(); 
  }
  else
	{
		stampa_totali_studio(); 
		_sez_da_stamp = ' ';
		_sez_stamp    = ' ';
	}      
  return true;
}

bool BA3800_application::preprocess_ditta(int counter)
{
  TString  key((const char*)_buff);
  int     g,c;
  long    s;
  
  if (!counter)
  {
    reset_print();
    _i = 1;
  }

  if (_reset_righe_stampa)
  {
    reset_print();
    _i = 1;
  }
  else
    _reset_righe_stampa = true;
  
  if (counter)
  {
    _sez_stamp = key[0];
    _let_stamp = key[1];
    _numr_stamp = key.mid(2, 4);
    _numr_stamp.ltrim();
    _num_stamp = key.mid(6, 4);
    _num_stamp.ltrim();
    _sez_tot = _sez_stamp;
    _let_tot = _let_stamp;
    _numr_tot = _numr_stamp;
    _num_tot = _num_stamp;
  }

  _buff = _sort->retrieve();

  if (_buff != NULL)
  {
		key = (const char *) _buff;
    _sez_da_stamp  = key[0];
    _let_da_stamp  = key[1];
    _numr_da_stamp = key.mid(2, 4);
    _numr_da_stamp.ltrim();
    _num_da_stamp  = key.mid(6, 4);
    _num_da_stamp.ltrim();
    g = atoi(key.mid(10, 3));
    c = atoi(key.mid(13, 3));
    s = atol(key.mid(16));      

    if (counter)
      stampa_totali_ditta(); 
  }
  else
  {
    stampa_totali_ditta(); 
    _sez_da_stamp = ' ';
    _sez_stamp    = ' ';
	}

  return true;
}

void BA3800_application::set_page(int file, int counter)
{ 
  if (_liv == 'S')
  {
    if (_sez_da_stamp != _sez_stamp)
    {
      if ((_sez_da_stamp=='1')||((_sez_da_stamp=='2')&&(_statopatr_no_stamp)))
      {
        setta_righe_studio(TR("STATO PATRIMONIALE"));
        _statopatr_no_stamp = false;
      }
      if (_sez_da_stamp == '2')
        setta_righe_studio("");
      if (_sez_da_stamp == '9')
        set_auto_ff(true);
    }
    else 
    {
      if (!_tabivd->eof())
        setta_righe_studio("");
    }
  } 
  else if (_liv == 'D')
  {
    if (_sez_da_stamp != _sez_stamp)
    {
      if ((_sez_da_stamp=='1')||((_sez_da_stamp=='2')&&(_statopatr_no_stamp)))
      {
        setta_righe_ditta (TR("STATO PATRIMONIALE"));
        _statopatr_no_stamp = false;
      }
      if (_sez_da_stamp == '2')
        setta_righe_ditta("");
      if ((_sez_da_stamp == '5') || (_sez_da_stamp == '9'))
        set_auto_ff(true);
    }
    else
    {
      if (_buff != NULL)
        setta_righe_ditta("");
    }
  }
}

void BA3800_application::setta_righe_studio(const char * titolo)
{
  int numeror;
  TString numrom, numero;
  bool stampa_classe = true; 
  numeror = atoi(_numr_da_stamp);
  numrom  = itor(numeror);
  numero  = _num_da_stamp;  
	numero.ltrim();

  //Se la classe prelevata dal record corrente del sort e' diversa dalla classe
  //prelevata dal record precedente, allora stampo la nuova classe con i relativi
  //sottoconti. In caso contrario continuo a stampare solo i sottoconti.

  if (_sez_da_stamp != _sez_stamp)
  {
    set_row (_i++,"@0g%s", titolo);
    char app = ' ';
    set_row(_i++,"@0g%c", app);
    
    if (_sez_da_stamp == '1')
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);   
      set_row (_i++, FR("@0gATTIVO"));
      set_row (_i++,"@0g%c", app);
    }
    else
      if (_sez_da_stamp == '2')
      {
        char app = ' ';
        set_row(_i++,"@0g%c", app); 
        set_row (_i++, FR("@0gPASSIVO"));
        set_row(_i++,"@0g%c", app); 
      }
    
    if (stampa_classe)
    {
      if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp== '9'))
      { 
        _cont_let  = 1;
        _cont_numr = 1;
        _cont_num  = "1";
        _cont_gcs  = 1;

        if (_let_da_stamp != ' ')
        {                                                 
          set_row(_i,"@0g%c)", _let_da_stamp);  
					const TString & descr = descrizione_lettera(_sez_da_stamp,_let_da_stamp);
          setta_righe_descr(descr, "@3g%s");
        }
        if (numrom != "")
        {                    
          set_row(_i,"@3g%8s -", (const char*) numrom);
					const TString & descr = descrizione_numeroromano(_sez_da_stamp,_let_da_stamp,numeror);
          setta_righe_descr(descr, "@14g%s");
        }
        if (numero.not_empty())
        {  
          set_row(_i,"@13g%s)", num2str(_num_da_stamp));
				  const TString & descr = descrizione_numero(_sez_da_stamp,_let_da_stamp,numeror,numero);
          setta_righe_descr(descr,"@27g%s");
        }
      }
    }
  }
  else
    if ((_let_da_stamp != _let_stamp) && (_sez_da_stamp == _sez_stamp))
    {
      if (stampa_classe)
      {
        if ((_sez_da_stamp=='1') ||
					  (_sez_da_stamp=='2') || 
						(_sez_da_stamp=='9'))
        {                                                        
          _cont_numr = 1;
          _cont_num  = "1";
          _cont_gcs  = 1;
          if (_let_da_stamp != ' ')
          {                                                 
            set_row(_i,"@0g%c)", _let_da_stamp);
						const TString & descr = descrizione_lettera(_sez_da_stamp,_let_da_stamp);
            setta_righe_descr(descr, "@3g%s");
          }
          if (numrom != "")
          {                               
            set_row(_i,"@3g%8s -", (const char*) numrom);
						const TString & descr = descrizione_numeroromano(_sez_da_stamp,_let_da_stamp,numeror);
            setta_righe_descr(descr, "@14g%s");
          }
          if (numero.not_empty())
          {  
            set_row(_i,"@13g%s)", num2str(_num_da_stamp));
					  const TString & descr = descrizione_numero(_sez_da_stamp,_let_da_stamp,numeror,numero);
            setta_righe_descr(descr, "@27g%s");
          }
        }
      }
    }
    else
      if ((_numr_da_stamp != _numr_stamp) &&
				  (_sez_da_stamp == _sez_stamp) &&
					(_let_da_stamp == _let_stamp))
      {
        if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp=='9'))
        { 
          _cont_num  = "1";
          _cont_gcs  = 1;
          if (numrom != "")
          {                               
            set_row(_i,"@3g%8s -", (const char*) numrom);
						const TString & descr = descrizione_numeroromano(_sez_da_stamp,_let_da_stamp,numeror);
            setta_righe_descr(descr, "@14g%s");
          }
          if (numero.not_empty())
          {   
            set_row(_i,"@13g%s)", num2str(_num_da_stamp));
					  const TString & descr = descrizione_numero(_sez_da_stamp,_let_da_stamp,numeror,numero);
            setta_righe_descr(descr, "@27g%s");
          }
        }
      }
      else
        if ((_num_da_stamp != _num_stamp) && 
					  (_sez_da_stamp == _sez_stamp) &&
						(_let_da_stamp == _let_stamp) &&
						(_numr_da_stamp==_numr_stamp))
        {
          if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp=='9'))
          {   
            set_row(_i,"@13g%s)", num2str(_num_da_stamp));
					  const TString & descr = descrizione_numero(_sez_da_stamp,_let_da_stamp,numeror,numero);
            setta_righe_descr(descr, "@27g%s");
            _cont_gcs = 1;
          }
        }
}

void BA3800_application::setta_righe_ditta(const char* titolo)
{
  TString key((const char *) _buff);
  int gruppo, conto;
  char sezione,lettera;
  long sottoc;
  TString numrom, numero, numr;
  bool stampa_classe = true;    
  
  sezione = key[0];
  lettera = key[1];
  numr = key.mid(2, 4);
  numr.ltrim();
	numrom = itor(atoi(numr));
  numero =  key.mid(6, 4);
  numero.ltrim();
  gruppo = atoi(key.mid(10, 3));
  conto = atoi(key.mid(13, 3));
  sottoc  = atol(key.mid(16));      

  //Se la classe prelevata dal record corrente del sort e' diversa dalla classe
  //prelevata dal record precedente, allora stampo la nuova classe con i relativi
  //sottoconti. In caso contrario continuo a stampare solo i sottoconti.

  if (sezione == '1' && lettera == 'A' && !_vaccata)
	{
    set_row (_i, FR("@3gTotale  )"));
    set_row (_i++,"@86g%s", (const char*) _totale);
		_vaccata = true;
	}

  if (_sez_da_stamp != _sez_stamp)
  {
    set_row (_i++,"@0g%s", titolo);
    char app = ' ';
    set_row(_i++,"@0g%c", app);
    
    if ((_sez_da_stamp == '1')&&(_let_da_stamp == 'Z'))
    {
      char app = ' ';
      set_row (_i++,"@0g%c", app);   
      set_row (_i++,FR("@0gCONTI D' ORDINE ATTIVI"));
      set_row (_i++,"@0g%c", app);
      stampa_classe = false;
    } 
    else
      if ((_sez_da_stamp == '1')&&(_let_da_stamp != 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);   
        set_row (_i++,FR("@0gATTIVO"));
        set_row (_i++,"@0g%c", app);
      }
    
    if ((_sez_da_stamp == '2')&&(_let_da_stamp == 'Z'))
    {
      char app = ' ';
      set_row(_i++,"@0g%c", app); 
      set_row (_i++, FR("@0gCONTI D' ORDINE PASSIVI"));
      set_row(_i++,"@0g%c", app); 
      stampa_classe = false;
    } 
    else
      if ((_sez_da_stamp == '2')&&(_let_da_stamp != 'Z'))
      {
        char app = ' ';
        set_row(_i++,"@0g%c", app); 
        set_row (_i++, FR("@0gPASSIVO"));
        set_row(_i++,"@0g%c", app); 
      }
    
    if (stampa_classe)
    {
      if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp== '9'))
      { 
        _cont_let  = 1;
        _cont_numr = 1;
        _cont_num  = "1";
        _cont_gcs  = 1;

        if (lettera != ' ')
        {
					const TString descr(descrizione_lettera(sezione, lettera));

          set_row(_i,"@0g%c)", lettera); 
          setta_righe_descr(descr, "@3g%s");
        }
        if (numrom != "")
        {
          set_row(_i,"@3g%8s -", (const char*) numrom);
				  const TString & descr = descrizione_numeroromano(sezione, lettera, atoi(numr));
          setta_righe_descr(descr, "@14g%s");
 
        }
        if (numero.not_empty())
        {
          set_row(_i,"@13g%s)", num2str(numero));
				  const TString & descr = descrizione_numero(sezione, lettera, atoi(numr), numero);
          setta_righe_descr(descr, "@27g%s");
        }
      }
    }
  }
  else
    if ((_let_da_stamp != _let_stamp) &&
			  (_sez_da_stamp == _sez_stamp))
    {
      if ((_sez_da_stamp == '1') &&
				  (_let_da_stamp == 'Z'))
      {
        char app = ' ';
        set_row (_i++,"@0g%c", app);   
        set_row (_i++,FR("@0gCONTI D' ORDINE ATTIVI"));
        set_row (_i++,"@0g%c", app);
        stampa_classe = false;
      }
      if ((_sez_da_stamp == '2')&&(_let_da_stamp == 'Z'))
      {
        char app = ' ';
        set_row(_i++,"@0g%c", app); 
        set_row (_i++,FR("@0gCONTI D' ORDINE PASSIVI"));
        set_row(_i++,"@0g%c", app); 
        stampa_classe = false;
      }
      if (stampa_classe)
      {
        if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp=='9'))
        {
          set_row(_i,"@0g%c)", lettera);  
					const TString descr(descrizione_lettera(sezione, lettera));
          setta_righe_descr(descr, "@3g%s");
          _cont_numr = 1;
          _cont_num  = "1";
          _cont_gcs  = 1;
          
          if (numrom != "")
          {
            set_row(_i,"@3g%8s -", (const char*) numrom);
					  const TString & descr = descrizione_numeroromano(sezione, lettera, atoi(numr));
            setta_righe_descr(descr, "@14g%s");
          }
          if (numero.not_empty())
          {
            set_row(_i,"@13g%s)", num2str(numero));
						const TString & descr = descrizione_numero(sezione, lettera, atoi(numr), numero);
            setta_righe_descr(descr, "@27g%s");
          }
        }
      }
    }
    else
      if ((_numr_da_stamp != _numr_stamp) &&
				  (_sez_da_stamp == _sez_stamp) &&
					(_let_da_stamp==_let_stamp))
      {
        if ((_sez_da_stamp=='1')||(_sez_da_stamp=='2')||(_sez_da_stamp=='9'))
        {
          set_row(_i,"@3g%8s -", (const char*) numrom);
				  const TString & descr = descrizione_numeroromano(sezione, lettera, atoi(numr));
          setta_righe_descr(descr, "@14g%s");
          _cont_num  = "1";
          _cont_gcs  = 1;
          
          if (numero.not_empty())
          {
            set_row(_i,"@13g%s)", num2str(numero));
						const TString & descr = descrizione_numero(sezione, lettera, atoi(numr), numero);
            setta_righe_descr(descr, "@27g%s");
          }
        }
      }
      else
        if ((_num_da_stamp != _num_stamp) &&
					  (_sez_da_stamp == _sez_stamp) &&
						(_let_da_stamp == _let_stamp) &&
						(_numr_da_stamp == _numr_stamp))
        {
          if ((_sez_da_stamp == '1') ||
						  (_sez_da_stamp == '2') ||
							(_sez_da_stamp == '9'))
          {
            set_row(_i,"@13g%s)", num2str(numero));
						const TString & descr = descrizione_numero(sezione, lettera, atoi(numr), numero);
            setta_righe_descr(descr, "@27g%s");
            _cont_gcs = 1;
          }
        }
  if (gruppo != 0)
  {
    _cont_gcs += 1;
    set_row (_i,"@20g%d", gruppo);
    set_row (_i,"@24g%d", conto);
    if (sottoc != 0L) // Omette la stampa dello 0
      set_row (_i,"@28g%ld", sottoc);
	  const TString & descr = descrizione_sottoconto(gruppo, conto, sottoc);
    set_row (_i,"@35g%s", (const char*) descr);
    set_row (_i,"@88g%s", (const char*) _totale);
    _i++;
  }  
}

void BA3800_application::setta_righe_descr(const char * str, const char * formato)
{
	TParagraph_string s(str, 40);
  const char * r;

  while ((r = s.get()) != NULL)
		set_row (_i++, formato, r);
}

void BA3800_application::intestazione_ditta()
{
  TString datastampastr;
  TString sep(132),sep1(147);

  TString app(8);
  TLocalisamfile nditte (LF_NDITTE);
  TLocalisamfile comuni (LF_COMUNI);
  TLocalisamfile unloc (LF_UNLOC);
  TLocalisamfile anag (LF_ANAG);
  TString codice_ditta,ragsoc,indulc,civulc,capulc,com,prov,comulc;
  TString cofi,paiv,tipoa,codanagr;  

  reset_header();
  
  nditte.setkey(1);
  codice_ditta << get_firm();
  nditte.zero();
  nditte.put(NDT_CODDITTA,codice_ditta);
  nditte.read();
  app      = nditte.get(NDT_CODDITTA);
  ragsoc   = nditte.get(NDT_RAGSOC);
  tipoa    = nditte.get(NDT_TIPOA);
  codanagr = nditte.get(NDT_CODANAGR);
  
  unloc.setkey(1);
  unloc.zero();
  unloc.put(ULC_CODDITTA,app);
  unloc.put(ULC_CODULC,"1");
  unloc.read();
  indulc = unloc.get(ULC_INDULC);
  civulc = unloc.get(ULC_CIVULC);
  capulc = unloc.get(ULC_CAPULC);
  comulc = unloc.get(ULC_COMULC);
  
  comuni.setkey(1);
  comuni.zero();
  comuni.put(COM_COM,comulc);
  comuni.read();
  com  = comuni.get(COM_DENCOM);
  prov = comuni.get(COM_PROVCOM);

  anag.setkey(1); 
  anag.zero();
  anag.put(ANA_TIPOA,tipoa);
  anag.put(ANA_CODANAGR,codanagr);
  anag.read();
  cofi = anag.curr().get(ANA_COFI);
  paiv = anag.curr().get(ANA_PAIV);

  set_header (1, FR("@0gDITTA@6g%-5s"), (const char*) codice_ditta);
  set_header (1, "@12g%-45s", (const char*) ragsoc);
  set_header (1, "@59g%-25s", (const char*) indulc);
  set_header (1, "@86g%-9s", (const char*) civulc);
  set_header (1, "@97g%-5s", (const char*) capulc);
  set_header (1, "@103g%-25s", (const char*) com);
  set_header (1, "@129g%-3s", (const char*) prov);

  sep << FR("Pag. @#");
  sep.right_just(132); 
  set_header(2,(const char*) sep);
  
  datastampastr = _datastampa.string();

  set_header (2,FR("@0gPartita iva@12g%-11s"), (const char*) paiv);
  set_header (2,FR("@30gCodice fiscale@45g%-16s"), (const char*) cofi);
  set_header (2,FR("@105gData@110g%s"),(const char*) datastampastr);
  set_header (3,FR("@0gSTAMPA TABELLA IV DIRETTIVA"));
  
  sep.fill('-');                            //Stampa 132 - (sep(132))       
  set_header (4, (const char *) sep);
}                                                 

void BA3800_application::intestazione_studio()
{ 
  TString sep(132);
  TString datastampastr;
  
  reset_header();
  
  sep << FR("Pag. @#");
  sep.right_just(132); 
  set_header(1,(const char*) sep);
  
  set_header (1,FR("@0gStudio"));
  
  datastampastr = _datastampa.string();

  set_header (1,FR("@105gData@110g%s"),(const char*) datastampastr);
  set_header (2,FR("@0gSTAMPA TABELLA IV DIRETTIVA"));              
  
  sep.fill('-');                            //Stampa 132 - (sep(132))       
  set_header (3, (const char *) sep);
}

const char* BA3800_application::descrizione_lettera(char sezione, char lettera)
{
  TString16 key;

  key.format("%1c%1c", sezione, lettera);
	
  return cache().get(TAB_IVD, key, "S0");
}

const char* BA3800_application::descrizione_numeroromano(char sezione, char lettera, int numr)
{
  TString16 key;

  if (numr > 0)
    key.format("%1c%1c%04d", sezione, lettera, numr);
  else
    key.format("%c%c    ", sezione, lettera);
	
  return cache().get(TAB_IVD, key, "S0");
}

const char* BA3800_application::descrizione_numero(char sezione, char lettera, int numr, const TString &  numero)
{
  TString16 key;

  if (numr > 0)
    key.format("%1c%1c%04d%-4s",sezione, lettera, numr, (const char *) numero);
  else
    key.format("%1c%1c    %-4s",sezione,lettera, (const char *) numero);

  return cache().get(TAB_IVD, key, "S0");
}     

const char* BA3800_application::descrizione_sottoconto(int gruppo, int conto, long sottoc)
{
  TString16 key;

  key << gruppo;
  if (conto != 0)
    key << '|' << conto;
  if (sottoc != 0)
		key << '|' <<  sottoc;
  return cache().get(LF_PCON, key, PCN_DESCR);
}

void BA3800_application::init_sort()
{
  _sort = new TSort(23);
  
  _sort -> addsortkey(0,22);
  _sort->init();
}

bool BA3800_application::user_create()
{
	open_files(LF_TAB, LF_TABCOM, LF_NDITTE, LF_COMUNI, LF_UNLOC, LF_ANAG, LF_PCON, LF_CLIFO, 0);
	_tabivd = new TTable(TAB_IVD);
  return true;
}

int ba3800 (int argc, char* argv[])
{
  if (argc > 3)
  {
    BA3800_application a(*argv[2]);
    a.run(argc, argv, TR("Stampa Tabella IV Direttiva CEE"));
  }
    else
      error_box("Usage: BA3 -7 {D|S}");
  return 0;
}