// cg4400.cpp
// Stampa tabella registri
#include "cg4.h"
#include "cg4400.h"
#include "cg4400a.h"

static TString256 TMP;

inline CG4400_application& app() { return (CG4400_application&)main_app(); }

bool CG4400_application::filter_func (const TRelation * r)
{
  TLocalisamfile & mov = r->lfile(LF_MOV);
  TString16 codreg  = mov.get(MOV_REG);
  TDate   datareg = mov.get_date(MOV_DATAREG);  
  int     annoiva = mov.get_int(MOV_ANNOIVA);
  
  if (codreg != (app()._codreg) || annoiva != (app()._annoes)) 
    return FALSE;           
  
  if (app()._data_da.string() != "" && app()._data_a.string() != "")
    if ( (datareg < app()._data_da || datareg > app()._data_a ) || (!datareg.ok()) )
      return FALSE;           
  
  return TRUE;
}

HIDDEN int compare_rows(const TObject** o1, const TObject** o2)
{
  TRiga* r1 = (TRiga*)*o1;
  TRiga* r2 = (TRiga*)*o2;
  
  return (strcmp((const char*)r1->_codiva, (const char*)r2->_codiva));
}

HIDDEN int compare_fields(const TObject** o1, const TObject** o2)
{
  TRigaiva* r1 = (TRigaiva*)*o1;
  TRigaiva* r2 = (TRigaiva*)*o2;
  TString16 campo1;
  TString16 campo2;
  
  campo1.format("%d%4s", r1->_tipodet, (const char*)r1->_codiva); 
  campo2.format("%d%4s", r2->_tipodet, (const char*)r2->_codiva); 
  return strcmp(campo1, campo2);
}

/*
   bool CG4400_application::libro_giornale_iva_unico()
   {
   TConfig conf(CONFIG_DITTA);

   return conf.get("StLgiU") == "X";
   }
   */

bool CG4400_application::mask_select (TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  { 
    TBit_array& sel = app()._selected; 
    TArray_sheet& dit = *app()._ditte;
    
    for (int j = 0; j < dit.items(); j++)
      dit.check(j, sel[j]);

    // seleziona e aggiungi alle gia' selezionate 
    if (dit.run() == K_ENTER)
    {
      for (int j = 0; j < dit.items(); j++)
        sel.set(j, dit.checked(j));
    }
    const long numd = sel.ones();
    f.mask().set(F_SELECT, numd);
  }
  return TRUE;
}       

bool CG4400_application::mask_azzera (TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    app()._selected.reset();
    app()._ditte->uncheck(-1);
    f.mask().reset(F_SELECT);
  }
  return TRUE;
}

bool CG4400_application::mask_firm_to (TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {   
    TMask& m = f.mask();
    const long from = m.get_long(DA_CODICE);
    long to = m.get_long(A_CODICE);
    if (from != 0 || to != 0)
    { 
      TBit_array& sel = app()._selected;
      if (to == 0) to = 99999;
      for (int i = 0; i < app()._ditte->items(); i++)
      {
        TToken_string& d = app()._ditte->row(i);
        const long cod = d.get_long(1);
        if (cod >= from && cod <= to)
          sel.set(i);
      }  
      //      m.reset(DA_CODICE);
      //      m.reset(A_CODICE);
      const long numd = sel.ones();
      f.mask().set(F_SELECT, numd);
    }
  }
  return TRUE; 
}

bool CG4400_application::mask_mese (TMask_field& f, KEY k)
{
  if (k == K_ENTER) 
  {
    int mese  = f.mask().get_int(MESE);
    int umese = f.mask().get_int(ULTIMO_MESE);

    if (mese != umese+1)
      return f.warning_box ("Le stampe devono essere richieste mese per mese!\n"
                            "I mesi successivi a %s non sono ancora stati stampati.", itom(umese));    
  }
  return TRUE;
}

bool CG4400_application::mask_cod (TMask_field& f, KEY k)
{ 
  TTable TabLbu ("%LBU");
  TString codtab; 
  int anno;
  
  if (k == K_TAB || f.focusdirty())
  {
    TString codlib = f.mask().get(CODICE_LIB_UN);
    anno = f.mask().get_int(ANNO);
    
    TabLbu.zero();
    codtab.format ("%04d%-3s", anno, (const char*)codlib);
    TabLbu.put ("CODTAB", codtab);
    TabLbu.read();
    if ( TabLbu.good() )
    {
      // f.mask().set(MESE,TabLbu.get_long("I0")+1);
      f.mask().set(ULTIMO_MESE,TabLbu.get_long("I0"));
      f.mask().set(ULTIMA_PAGINA,TabLbu.get_long("I1"));
    }
  }
  return TRUE;
}

bool CG4400_application::mask_data (TMask_field& f, KEY k)
{
  if (k == K_ENTER)
  {
    const int anno = f.mask().get_int(ANNO);
    TDate data(f.get());
    if (data.ok()) 
      if (data.year() != anno)
      {
        f.warning_box("L'anno delle date limite deve essere uguale all'anno iva specificato");
        return FALSE;
      }  
  } 
  return TRUE;
} 

bool CG4400_application::mask_tipo (TMask_field& f, KEY k)
{
  if (k == K_TAB)
  {
    TDate data(f.get());
    if (data.ok()) 
      if ( data.day() == 31 && data.month() == 12 )
        f.mask().show (TIPO_RIEPILOGATIVO);
  } 
  return TRUE;
} 

/*
   bool mask_fino_a_mese (TMask_field& f, KEY k)
   { 
   if (k == K_ENTER)
   {
   TTable TabReg ("REG");
   TString16 codtab;
   int giorni_del_mese;
   TString codreg = f.mask().get(CODICE_LIBRO);
   int tipo       = f.mask().get_int(TIPO_STAMPA);
   int anno       = f.mask().get_int(ANNO);
   
   if ( (tipo == 1) || (tipo == 4) ) 
   { 
   int fino_a_mese = f.mask().get_int(FINO_A_MESE);
   if (fino_a_mese == 12)
   giorni_del_mese = 31;
   else
   {
   TDate primo = format("01/%02d/%4d", fino_a_mese+1, anno);
   --primo;
   giorni_del_mese = primo.day();
   }
   TDate datasup = format("%02d/%02d/%4d",giorni_del_mese,fino_a_mese,anno);       
   if (codreg != "")
   {
   TabReg.zero();
   codtab << anno << codreg;
   TabReg.put ("CODTAB", codtab);
   TabReg.read();
   if ( TabReg.good() )
   {
   TDate data = TabReg.get_date("D3");
   if (datasup < data)
   {
   TString16 datas = format("%02d/%4d", data.month(), data.year());
   f.warning_box ("La data specificata non deve essere inferiore al %s (ultima data di stampa specificata sul registro)", (const char*)datas);    
   return FALSE;
   }
   }
   }
   if (tipo == 4)
   {
   TabReg.zero();
   TabReg.put ("CODTAB", anno);
   TRectype r (TabReg.curr());
   TabReg.read(_isgteq);
   for (; !TabReg.eof(); TabReg.next())
   {
   if (TabReg.curr() != r) break;
   
   int tiporeg = TabReg.get_int("I0");
   if (tiporeg == 5) //libro giornale
   {    
   TDate data = TabReg.get_date("D3");
   if (datasup > data)
   {
   TString16 datas = format("%02d/%4d", data.month(), data.year());
   f.warning_box ("La data specificata non deve essere superiore al %s (ultima data di stampa del libro giornale)", (const char*)datas);    
   return FALSE;
   }
   }
   }
   } 
   }
   }
   return TRUE;
   }
   */

//da una SHEET non e' possibile mandare messaggi nella maschera!!!
bool CG4400_application::tipostampa_handler (TMask_field& f, KEY k)
{
  if (k == K_TAB) 
  {
    TMask& m = f.mask();
    int stampa_su   = m.get_int(TIPO_STAMPA);
    if ( (stampa_su == 1) || (stampa_su == 4) ) 
    {  
      m.hide (CODICE_LIB_UN);
      m.hide (CODICE_LIBRO_PROVA);
      m.hide (MESE);
      m.hide (ULTIMO_MESE);
      m.hide (ULTIMA_PAGINA);
      m.hide (CODICE_LIBRO_IVA);
      m.hide (DATA_STAMPA);
      m.hide (DA_DATA);
      m.hide (A_DATA);
      m.show (CODICE_LIBRO);
      m.show (TIPO_RIEPILOGATIVO);
      m.show (FINO_A_MESE);
    }
    if (stampa_su == 2)
    {
      m.show (CODICE_LIB_UN);
      m.hide (CODICE_LIBRO_PROVA);
      m.show (MESE);
      m.show (ULTIMO_MESE);
      m.show (ULTIMA_PAGINA);
      m.show (CODICE_LIBRO_IVA);
      m.hide (DATA_STAMPA);
      m.hide (DA_DATA);
      m.hide (A_DATA);
      m.hide (CODICE_LIBRO);
      m.hide (TIPO_RIEPILOGATIVO);
      m.hide (FINO_A_MESE);       
    } 
    if (stampa_su == 3)
    {
      m.hide (CODICE_LIB_UN);
      m.hide (MESE);
      m.hide (ULTIMO_MESE);
      m.hide (ULTIMA_PAGINA);
      m.hide (CODICE_LIBRO_IVA);
      m.hide (CODICE_LIBRO);
      m.show (CODICE_LIBRO_PROVA);
      m.show (DATA_STAMPA);
      m.show (DA_DATA);
      m.show (A_DATA);
      m.hide (TIPO_RIEPILOGATIVO);
      m.hide (FINO_A_MESE);       
    } 
  }
  return TRUE;
} 

const char * CG4400_application::descr_doc(const char * tipo)
{
  TTable  tab_tpd("%TPD");
  const TString16 codtab(format("%-2s", tipo));
  
  tab_tpd.zero();
  tab_tpd.put("CODTAB", codtab);
  if (tab_tpd.read()==NOERR)
    TMP = tab_tpd.get("S0");
  else
    TMP = "";

  return TMP;
} 

const char * CG4400_application::descr_iva(const char * cod)
{
  TTable  tab_iva("%IVA");
  const TString16 codtab(format ("%-4s", cod));
  
  tab_iva.zero();
  tab_iva.put("CODTAB", codtab);
  if (tab_iva.read()==NOERR)
    TMP = tab_iva.get("S0");
  else
    TMP = "";

  return TMP;
} 

const char * CG4400_application::desc_attivita(const char * codatt)
{
  TTable attiv ("%AIS");

  attiv.zero();
  attiv.put("CODTAB", codatt);
  if (attiv.read()==NOERR)
    TMP = attiv.get("S0");
  else
    TMP = "";
  return TMP;
}

const char * CG4400_application::ricerca_cf(char tipocf, long codcf)
{
  _clifo->zero();
  _clifo->put(CLI_TIPOCF, tipocf);
  _clifo->put(CLI_CODCF, codcf);
  if (_clifo->read() == NOERR)
    TMP = _clifo->get(CLI_RAGSOC);
  else
    TMP = "";
  return TMP;
}

const char * CG4400_application::ricerca_occ(const char * occ)
{
  TLocalisamfile occas (LF_OCCAS);

  occas.zero();
  occas.put(OCC_CFPI, occ);
  
  if (occas.read() == NOERR)
    TMP = occas.get(OCC_RAGSOC);
  else
    TMP = "";
  return TMP;
}

bool CG4400_application::user_create()
{
  _nditte = new TLocalisamfile(LF_NDITTE);
  _ditte  = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "@1|Cod.@5|Ragione Sociale@50");
  for (_nditte->first(); !_nditte->eof(); _nditte->next())
  {
    TToken_string* d = new TToken_string(64);
    d->add(" ");
    d->add(_nditte->get("CODDITTA"));
    d->add(_nditte->get("RAGSOC"));
    _ditte->add(*d);
  }
  _n_ditte = _ditte->items();

  _com    = new TLocalisamfile(LF_COMUNI);
  _anag   = new TLocalisamfile(LF_ANAG);
  _tab    = new TLocalisamfile(LF_TAB);
  _tabcom = new TLocalisamfile(LF_TABCOM);
  _tabreg = new TTable("REG");
  _tabiva = new TTable("%IVA");  
  _tablbu = new TTable("%LBU");
  _tabinl = new TTable("%INL");
  _tablim = new TTable("LIM");
  _tabpim = new TTable("PIM");
  _tablia = new TTable("LIA");   
  _clifo  = new TLocalisamfile(LF_CLIFO);
  _occas  = new TLocalisamfile(LF_OCCAS);
  _rel    = new TRelation (LF_MOV);
  _rel->add(LF_CAUSALI,"CODCAUS=CODCAUS",1,LF_MOV);
  _rel->add(LF_RMOVIVA,"NUMREG=NUMREG",1,LF_MOV);
  _cur = new TCursor(_rel, "", 1);

  add_cursor(_cur);
  add_file(LF_MOV);
  add_file(LF_RMOVIVA); 
  return TRUE;
}

bool CG4400_application::user_destroy()
{
  delete _ditte;
  delete _nditte;
  delete _tab;
  delete _tabcom;
  delete _cur;
  delete _rel;
  delete _clifo; 
  return TRUE;
}


void CG4400_application::calcola_progressivi(real& r0, real& r1, const char* codiva, const int tipocr) 
{
  TTable  pim ("PIM");  
  TString chiave;
  int i, num=0;
  
  if (_tipo_stampa == 1)
    num = _datareg.month();
  if ( (_tipo_stampa == 2) || (_tipo_stampa == 4) )  
    num = _fino_a_mese;
  
  if (_frequiva == 'T')
    for (i=3; i<num+3; i+=3)
    {
      chiave = "";
      chiave << _annoes << _codatt << _codreg << i << tipocr << codiva;
      pim.put("CODTAB", chiave);
      if (pim.read()==NOERR)
      {
        r0 += pim.get_real("R0");
        r1 += pim.get_real("R1");
      }
    }
  else //frequenza mensile
    for (i=1; i<=num; i++)
    {
      chiave = "";
      chiave << _annoes << _codatt << _codreg << i << tipocr <<codiva;
      pim.put("CODTAB", chiave);
      if (pim.read()==NOERR)
      {
        r0 += pim.get_real("R0");
        r1 += pim.get_real("R1");
      }
    }       
}

int CG4400_application::riga_rmoviva()
{ 
  TString  codiva;
  real     impo, impos, impop, imposp;
  int      tipodet, tipocr;    

  _cur->save_status();
  bool ok = _cur->is_first_match(LF_RMOVIVA);
  int nrec = 0;
  
  while (ok)
  {
    nrec++;
    TRectype iva (_cur->file(LF_RMOVIVA).curr());
    tipodet = iva.get_int (RMI_TIPODET);
    tipocr  = iva.get_int (RMI_TIPOCR); 
    impo    = iva.get_real(RMI_IMPONIBILE);
    impos   = iva.get_real(RMI_IMPOSTA);
    codiva  = iva.get(RMI_CODIVA);
    
    impop = imposp = 0.00;
    _riga_rmi.add_riga(impo,impos,codiva,tipodet,tipocr,impop,imposp);
    
    if (_tipo_reg == 2) //registro acquisti
    {
      if (_tipo_stampa != 3)  //stampa definitiva
        calcola_progressivi(impop,imposp,codiva,tipocr);
      _iva_array.add_riga(impo,impos,codiva,tipodet,tipocr,impop,imposp);
    }
    
    impop = imposp = 0.00;
    if (_tipo_stampa != 3)
      calcola_progressivi(impop,imposp,codiva,tipocr); 
    
    _tot_iva_array.add_riga(impo,impos,codiva,_tipodoc,impop,imposp);
    
    ok = _cur->next_match(LF_RMOVIVA);
  }
  _cur->restore_status();
  
  return nrec;   
}

int CG4400_application::setta_riga(int r, const TRigaiva& riga, real& tot1, 
                                   real& tot2, real& tot3, real& tot4)
{
  set_row(r, "%3s", (const char*)riga._codiva);
  TString descr = descr_iva(riga._codiva); 
  set_row(r, "@5g%s",(const char*)descr);
  set_row(r, "@25g%r", &riga._imponibile);
  set_row(r, "@41g%r", &riga._imposta);
  if (_tipo_stampa != 3)
  {
    set_row(r, "@81g%r", &riga._imponibilep);
    set_row(r++, "@98g%r", &riga._impostap); 
  }
  else r++;
  tot1 += riga._imponibile;
  tot2 += riga._imposta;
  tot3 += riga._imponibilep;
  tot4 += riga._impostap;
  
  return r;
}

bool CG4400_application::controlla_liquidazione()
{
  TTable lim ("LIM");
  TTable pim ("PIM");
  TTable lia ("LIA");
  TString mesi_ric = "";
  TString mesi_cal = "";
  TString16 chiave = "";
  TString16 ditta  = "";
  int i;
  
  ditta << get_firm();
  
  if (lim.empty()) 
    return yesno_box("Ditta %s : non esiste la tabella liquidazione iva mensile! Vuoi ugualmente continuare la stampa?", (const char*) ditta);
  if (pim.empty())
    return yesno_box("Ditta %s : non esiste la tabella progressivi iva mensile! Vuoi ugualmente continuare la stampa?", (const char*) ditta);
  
  chiave << _annoes;
  lia.put("CODTAB", chiave);
  if (lia.read() == NOERR)
    _frequiva = lia.get("S7")[0];
  
  if (_frequiva == 'T') //nella tabella LIM ho solo i mesi 3, 6, 9, 12
  {
    for (i=3; i<=_fino_a_mese; i+=3)
    {
      chiave = "";
      chiave << _annoes << i;
      lim.put("CODTAB", chiave);
      if (lim.read() == NOERR)
      {
        bool calcolato = lim.get_bool("B0"); 
        if (!calcolato)
          
          // return yesno_box("La liquidazione relativa al mese di %s deve essere ricalcolata. Vuoi ugualmente continuare la stampa?", itom(i) );         
          mesi_ric << itom(i) << "\n";
      }
      else 
        //  return yesno_box("La liquidazione relativa al mese di %s non e' stata calcolata. Vuoi ugualmente continuare la stampa?", itom(i) );
        mesi_cal << itom(i) << "\n";  
    }
  }                
  if (_frequiva == 'M')
  {
    for (i=1 ; i<=_fino_a_mese; i++)
    {
      chiave = "";
      chiave << _annoes << i;
      lim.put("CODTAB", chiave);
      if (lim.read() == NOERR)
      {
        bool calcolato = lim.get_bool("B0"); 
        if (!calcolato)
          // return yesno_box("La liquidazione relativa al mese di %s deve essere ricalcolata. Vuoi ugualmente continuare la stampa?", itom(i) );
          mesi_ric << itom(i) << "\n";         
      }
      else 
        // return yesno_box("La liquidazione relativa al mese di %s non e' stata calcolata. Vuoi ugualmente continuare la stampa?", itom(i) );  
        mesi_cal << itom(i) << "\n";       
    } 
  }
  
  if (mesi_ric.not_empty())
  {
    warning_box ("Ditta %s : deve essere ricalcolata la liquidazione relativa ai mesi di:\n %s ", (const char*)ditta, (const char *)mesi_ric);
    return yesno_box("Vuoi ugualmente continuare la stampa?");
  }
  if (mesi_cal.not_empty())
  {
    warning_box ("Ditta %s : la liquidazione relativa ai mesi di \n %s non e' stata ancora calcolata", (const char*)ditta, (const char *)mesi_cal);
    return yesno_box("Vuoi ugualmente continuare la stampa?");
  }       
  return TRUE;   
}

//controlla che i movimenti con data di registrazione compresa tra l'anno precedente e l'ultima data stampata siano tutti gia' stati stampati in forma definitiva*/ 
bool CG4400_application::controlla_mov()
{
  TLocalisamfile mov (LF_MOV);
  bool ok = TRUE;
  byte tipo;
  TString16 ditta = "";
  TDate udata; 
  TDate data = format("01/01/%4d", _annoes - 1);
  TRecnotype rec = _tabreg->recno();
  for (mov.first(); !mov.eof(); mov.next())
  {
    TString16 reg = mov.get(MOV_REG);
    if (reg.empty()) continue;
    TDate datareg = mov.get_date(MOV_DATAREG);
    if (_stampa_tutti_i_registri)
      cerca_reg (reg, tipo, udata);
    else udata = _data_da;   
    if ( (_stampa_tutti_i_registri && ((tipo == 1)||(tipo == 2)))
        || ((!_stampa_tutti_i_registri)&&(reg == _codreg)) )
      if ( (datareg >= data) && (datareg <= udata) )
      {  
        bool stampato = mov.get_bool(MOV_REGST);
        long numreg   = mov.get_long(MOV_NUMREG);
        if (!stampato)
        {
          ditta = "";
          ditta << get_firm();
          warning_box("Ditta %s : il movimento con numero di registrazione %ld non e' ancora stato stampato in forma definitiva!", (const char*)ditta, numreg);
          ok = FALSE;
        }
      }  
  }
  _tabreg->readat(rec);
  return ok;
}

void CG4400_application::cerca_reg(const TString& c, byte& t, TDate& d)
{
  TString16 cod = "";
  
  cod << _annoes << c;
  _tabreg->zero();
  _tabreg->put("CODTAB", cod); 
  if (_tabreg->read() == NOERR)
  {
    t = _tabreg->get_int ("I0");
    d = _tabreg->get_date("D3");
  }
}

/*
   bool CG4400_application::controlla_mov()
   {
   bool ok = TRUE;
   
   if (_stampa_tutti_i_registri)
   {
   TRecnotype rec = _tabreg->recno();//la first l'ho gia' fatta 
   for (; !_tabreg->eof(); _tabreg->next())
   {  
   TString codtab = _tabreg->get("CODTAB");
   int anno = atoi(codtab.mid(0,4));
   if (anno != _annoes) break;
   
   TDate data_da    = _tabreg->get_date("D3");
   TString16 codreg = codtab.mid(4,3);
   leggi_movimenti(data_da, codreg, ok);
   }
   _tabreg->readat(rec);
   }
   else
   leggi_movimenti(_data_da, _codreg, ok);
   
   return ok;
   }

   void CG4400_application::leggi_movimenti(const TDate& d, const TString& cod, bool& ok)          
   {
   TLocalisamfile mov (LF_MOV);
   bool stampato;
   long numreg; 
   TString codreg;
   
   TDate data = format("01/01/%4d", _annoes - 1);
   mov.zero();
   TRectype a (mov.curr());
   mov.put(MOV_DATAREG, data); 
   a.put  (MOV_DATAREG, d);
   mov.read(_isgteq);
   while (mov.curr() < a && !mov.eof())
   {
   stampato = mov.get_bool(MOV_STAMPATO);
   numreg   = mov.get_long(MOV_NUMREG);
   codreg   = mov.get(MOV_REG);
   if (codreg == cod)
   if (!stampato)
   {
   warning_box("Il movimento con numero di registrazione %ld non e' ancora stato stampato in forma definitiva!", numreg);
   ok = FALSE;
   }
   mov.next();
   }  
   }
   */

bool CG4400_application::ventilazione(const char* iva)
{
  TTable tabiva ("%IVA");
  TString16 chiave = "";
  chiave << iva;
  tabiva.put("CODTAB", chiave);
  if (tabiva.read()==NOERR)
  {
    TString16 vent = tabiva.get("S1");
    if (vent == "VE")
      return TRUE; 
  }
  return FALSE;
}

int CG4400_application::stampa_prospetto()
{
  TString riga(_stampa_width);
  int r=1, rr=0;

  reset_print();
  riga.fill('-');
  set_row(r, "%s", (const char *) riga);
  r++;
  set_row(r, "Legenda Tipo Operazione:  1=operazione intracomunitaria  2=AF art.34 comma 3");  
  if (_auto_intraf)
    set_row(r, "@78g3=operazione intracomunitaria e AF art.34 comma 3");
  r++;
  set_row(++r, "Tipo documento@30gTotale documento");
  r+=2; 
  for (int j = 0; j < _doc_array.items(); j++)
  {
    TTipodoc& doc = (TTipodoc&)_doc_array[j];
    rr = r+j;
    set_row(rr, "%2s",      (const char*) doc._tipodoc);
    set_row(rr, "@3g%.25s", (const char*) doc._descrdoc);
    set_row(rr, "@29g%r",   &doc._totdoc); 
  }
  _doc_array.destroy();
  
  if (rr > 0)
    rr++;
  else
    rr = r;
  
  if (_nrec > 0)  //numero records di rmoviva
  {
    if (_corrispettivi)
      set_row(++rr, "@26g------------------ P E R I O D O -------------------");
    else
      set_row(++rr, "@26g---------- P E R I O D O -----------");
    if (_tipo_stampa != 3)
      set_row(rr,"@82g------ P R O G R E S S I V I ------");
    rr++;
    set_row(rr, "Cod.");
    if (_tipo_reg == 2)
    {
      set_row(rr, "@36gA C Q U I S T I");
      if (_tipo_stampa != 3)
        set_row(rr, "@92gA C Q U I S T I");
    }
    if (_tipo_reg == 1) //un registro corrispettivi puo' solo essere un registro vendite 
    {
      set_row(rr, "@37gV E N D I T E");
      if (_corrispettivi)
        set_row(rr, "@63gCORRISPETTIVI");
      if (_tipo_stampa != 3)
        set_row(rr, "@93gV E N D I T E");
    }      
    rr++;
    set_row(rr, "iva Descrizione@30gImponibile@49gImposta");
    if (_corrispettivi)
      set_row(rr, "@63gImporti lordi");
    if (_tipo_stampa != 3)
      set_row(rr++, "@86gImponibile@106gImposta");
    else rr++;
    rr++;
  }    
  return rr;  
}  

//la stampa "tipi di indetraibilita'" viene fatta solo per gli acquisti 
void CG4400_application::stampa_acquisti(int row)
{
  if (_tipo_reg == 2)
  {
    real tot_imponib, tot_imposta, tot_imponibp, tot_impostap;
    row+=2;
    int tdetprec = -1;
    int rw = row;
    tot_imponib = tot_imposta = tot_imponibp = tot_impostap = 0.00;
    
    _iva_array.sort(compare_fields);
    for (int s = 0; s < _iva_array.items(); s++)
    {
      TRigaiva& riga = (TRigaiva&)_iva_array[s];
      switch (riga._tipodet)
      {
      case 1: if (riga._tipodet != tdetprec)
      {    
        set_row(rw++, "----- Indetraibile su op.es. -----");
        set_row(rw, "Cod.");
        rw++;
        set_row(rw, "iva Descrizione@30gImponibile@49gImposta");
        if (_tipo_stampa != 3)
          set_row(rw++, "@86gImponibile@106gImposta"); 
        else rw++;
        rw++;
      }
              rw = setta_riga(rw, riga, tot_imponib, tot_imposta, tot_imponibp, tot_impostap);
              tdetprec = riga._tipodet;
              break;
            case 3: if (tdetprec == 1)
            {
              set_row(++rw, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
              if (_tipo_stampa != 3)
                set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
              tot_imponib = tot_imposta = tot_imponibp = tot_impostap = 0.00;
              rw+=2;
            }
              if (riga._tipodet != tdetprec)
              { 
                set_row(rw++, "----- Passaggi interni -----");
                set_row(rw, "Cod.");
                rw++;
                set_row(rw, "iva Descrizione@30gImponibile@49gImposta");
                if (_tipo_stampa != 3)
                  set_row(rw++, "@86gImponibile@106gImposta");
                else rw++;    
                rw++;
              }
              rw = setta_riga(rw, riga, tot_imponib, tot_imposta, tot_imponibp, tot_impostap);
              tdetprec = riga._tipodet;
              break;
            case 9: if ( (tdetprec == 1) || (tdetprec == 3) )
            {
              set_row(++rw, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
              if (_tipo_stampa != 3)
                set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap); 
              tot_imponib = tot_imposta = tot_imponibp = tot_impostap = 0.00;
              rw+=2;
            }
              if (riga._tipodet != tdetprec)
              {  
                set_row(rw++, "----- N.D. 9 - acquisti indeducibili per ART.19 -----");
                set_row(rw, "Cod.");
                rw++;
                set_row(rw, "iva Descrizione@30gImponibile@49gImposta");
                if (_tipo_stampa != 3)
                  set_row(rw++, "@86gImponibile@106gImposta");
                else rw++; 
                rw++;
              }
              rw = setta_riga(rw, riga, tot_imponib, tot_imposta, tot_imponibp, tot_impostap);
              tdetprec = riga._tipodet; 
              break;
            default: break;                         
            }
    }  
    if (tdetprec == 9)
    {
      set_row(++rw, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
      if (_tipo_stampa != 3)
        set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
    }
    _iva_array.destroy();
  }
}

void CG4400_application::set_page_tot_reg()
{
  TString16 codivaprec = "";
  int row=0, rr=0;
  
  rr = stampa_prospetto();
  
  if (_nrec > 0) //numero di records di rmoviva
  {  
    real tot_imponib, tot_imposta, tot_imponibp, tot_impostap, tot_lordo;
    real dep_imponib, dep_imposta, dep_lordo;
    tot_imponib = tot_imposta = tot_imponibp = tot_impostap = tot_lordo = ZERO;
    dep_imponib = dep_imposta = dep_lordo = ZERO;
    
    _tot_iva_array.sort(compare_rows);
    
    for (int k = 0; k < _tot_iva_array.items(); k++)
    {
      TRiga& riga = (TRiga&)_tot_iva_array[k];
      //row = rr+k;
      if (codivaprec == "") 
        codivaprec = riga._codiva;
      if (codivaprec != riga._codiva)
      {
        set_row(rr, "%3s",    (const char*)codivaprec);
        TString descr = descr_iva(codivaprec);
        set_row(rr, "@5g%s",  (const char*)descr);
        if (dep_imponib != ZERO)
          set_row(rr, "@25g%r", &dep_imponib);
        if (dep_imposta != ZERO)
          set_row(rr, "@41g%r", &dep_imposta);
        if (dep_lordo != ZERO)
          set_row(rr, "@61g%r", &dep_lordo);
        if (_tipo_stampa != 3)
        {
          set_row(rr, "@81g%r", &riga._imponibilep);
          set_row(rr, "@98g%r", &riga._impostap); 
        }   
        rr++;  
        codivaprec = riga._codiva;
        dep_imponib = dep_imposta = dep_lordo = ZERO;
      }      
      if (_corrispettivi)
      {
        if (riga._tipodoc == "CR" || riga._tipodoc == "RF" || riga._tipodoc == "SC")
        {
          dep_lordo   += riga._imponibile;
          dep_imposta += riga._imposta;
          tot_lordo   += riga._imponibile;
          tot_imposta += riga._imposta;
        }  
        else if (riga._tipodoc == "CN" || riga._tipodoc == "RN" || riga._tipodoc == "SN" || riga._tipodoc != "FS")
        {
          dep_imponib += riga._imponibile;
          dep_imposta += riga._imposta;
          tot_imponib += riga._imponibile;
          tot_imposta += riga._imposta;
        }
        if (riga._tipodoc == "FS")
        {
          real somma = riga._imponibile + riga._imposta;
          if (ventilazione(riga._codiva)) //con ventilazione
          {
            dep_imponib += somma;
            tot_imponib += somma;
            somma = -somma;
            dep_lordo   += somma;
          }
          else //senza ventilazione 
          { 
            dep_imponib += riga._imponibile;
            tot_imponib += riga._imponibile;
            dep_imposta += riga._imposta;
            tot_imposta += riga._imposta;
            somma = -somma;
            dep_lordo += somma; 
          }
          tot_lordo += somma;
        } 
      }
      else //non e' un registro corrispettivo
      {
        //set_row(row, "@25g%r", &riga._imponibile);
        //set_row(row, "@41g%r", &riga._imposta);
        dep_imponib += riga._imponibile;
        dep_imposta  += riga._imposta; 
        tot_imponib  += riga._imponibile;
        tot_imposta  += riga._imposta;
        tot_imponibp += riga._imponibilep;
        tot_impostap += riga._impostap;
      }
      if (k == (_tot_iva_array.items()-1)) 
      {
        set_row(rr, "%3s",    (const char*)riga._codiva);
        TString descr = descr_iva(riga._codiva);
        set_row(rr, "@5g%s",  (const char*)descr);
        if (dep_imponib != ZERO)
          set_row(rr, "@25g%r", &dep_imponib);
        if (dep_imposta != ZERO)
          set_row(rr, "@41g%r", &dep_imposta);
        if (dep_lordo != ZERO)
          set_row(rr, "@61g%r", &dep_lordo);
        if (_tipo_stampa != 3)
        {
          set_row(rr, "@81g%r", &riga._imponibilep);
          set_row(rr, "@98g%r", &riga._impostap); 
        }   
      }
      /*
         if (_tipo_stampa != 3)
         {
         set_row(rr, "@81g%r", &riga._imponibilep);
         set_row(rr, "@98g%r", &riga._impostap); 
         } 
         */ 
    }  
    _tot_iva_array.destroy();
    rr++;
    set_row(++rr, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
    if (_corrispettivi) 
      if (tot_lordo != ZERO)
        set_row(rr, "@61g%r", &tot_lordo);
    if (_tipo_stampa != 3)
      set_row(rr, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
    
    stampa_acquisti(rr);
  } 
}

bool CG4400_application::compila_reg(const TMask& m)
{       
  int anno;
  long codditta = _nditte->get_long("CODDITTA"); 
  TString16 codtab = ""; 
  
  _tipo_stampa = m.get_int(TIPO_STAMPA);
  if (_tipo_stampa == 2)  //stampa su libro unico di studio
    _codreg = m.get(CODICE_LIBRO_IVA);
  else if (_tipo_stampa == 3) //stampa di prova
    _codreg = m.get(CODICE_LIBRO_PROVA);        
  else _codreg = m.get(CODICE_LIBRO);
  
  if (_codreg.trim().empty())
  {
    _stampa_tutti_i_registri = TRUE;
    _tabreg->first(); 
    if (!_tabreg->eof()) 
    { 
      codtab  = _tabreg->get("CODTAB");
      anno    = atoi(codtab.mid(0,4));
      if (anno > _annoes) 
      {
        warning_box("Non esistono registri IVA della Ditta %ld per l'anno %d", 
                    codditta, _annoes);
        return FALSE;
      }
    }
  }  
  else   // stampa un solo registro
  {
    _stampa_tutti_i_registri = FALSE;
    codtab << _annoes << _codreg;         
    _tabreg->zero();
    _tabreg->put("CODTAB", codtab);
    if (_tabreg->read() == NOERR)
    {
      _tipo_reg        = _tabreg->get_int("I0");
      _pagine_stampate = _tabreg->get_int("I1");
      _corrispettivi   = _tabreg->get_bool("B0");
      //_pagine_numerate = tab_reg.get_int("I2");
      //_stampa_ok       = tab_reg.get_int("I7");
      //_nprog_da        = tab_reg.get_long ("I6");
      //_tot_dare        = tab_reg.get_real ("R1")
      //_tot_avere       = tab_reg.get_real ("R2");
      if (_tipo_stampa != 3) 
      {
        _data_da = _tabreg->get_date ("D3");
        if (!_data_da.ok())
          _data_da = format("01/01/%4d", _annoes);
      }  
      if ( _tipo_stampa == 1 || _tipo_stampa == 4 )
        if ( _data_a <= _data_da)
        {
          TString16 datas = format("%02d/%4d", _data_da.month(), _data_da.year());
          warning_box ("La data specificata deve essere superiore al %s (ultima data di stampa specificata sul registro)", (const char*)datas);    
          return FALSE;
        }       
      _stampa_ind_ditta = _tabreg->get_bool ("B9");
      _codatt           = _tabreg->get("S8");
      _attivita         = desc_attivita(_codatt);
      _desc_lib         = _tabreg->get ("S0");
    }
    else
    {
      warning_box("Il registro IVA specificato non esiste nella \n Ditta %ld", codditta);
      return FALSE;
    }
  }
  
  if (_tipo_stampa == 4)
  {
    TString app(4);
    _tabreg->zero();
    app = format("%04d", _annoes);
    _tabreg->put ("CODTAB", app);
    TRectype r (_tabreg->curr());
    _tabreg->read(_isgteq);
    for (; !_tabreg->eof(); _tabreg->next())
    {
      if (_tabreg->curr() != r) break;
      
      int tiporeg = _tabreg->get_int("I0");
      if (tiporeg == 5) //libro giornale
      {    
        TDate data = _tabreg->get_date("D3");
        if (_data_a > data)
        {
          TString16 datas = format("%02d/%4d", data.month(), data.year());
          warning_box ("La data specificata non deve essere superiore al %s (ultima data di stampa del libro giornale)", (const char*)datas);    
          return FALSE;
        }
      }
    }
  }
  return TRUE;
}

bool CG4400_application::compila_lib()
{       
  TTable tab_lib ("%LBU");
  TString16 cod;
  
  cod << _annoes << _codlib;
  tab_lib.zero();
  tab_lib.put("CODTAB", cod);
  
  if (tab_lib.read() == NOERR)
  {
    _stampa_ind_ditta = tab_lib.get_bool("B1");
    return TRUE;
  }
  return FALSE;
}

bool CG4400_application::preprocess_print(int file, int counter)
{ 
  if (file == LF_MOV)
  {       
    long items = _cur->items();
    if (!items)
      return FALSE;
    _iva_array.destroy();
    _riga_rmi.destroy();
    _tot_iva_array.destroy();
    _doc_array.destroy();
    _dataregp  = "";
    _mov_empty = TRUE;
    _primast   = _u_stampata;
    _auto_intraf = FALSE;
    set_print_zero();
  }
  return TRUE;
} 

bool CG4400_application::preprocess_page(int file, int counter)
{ 
  if (file == LF_MOV)
  {
    if (counter) return TRUE; 
    reset_print();
    int rr = 0;
    TString ragsoc;
    TString tipo_op = "";

    TLocalisamfile& mov  = _cur->file(LF_MOV);
    TLocalisamfile& caus = _cur->file(LF_CAUSALI);

    _datareg = mov.get_date(MOV_DATAREG);
    
    _mov_empty = FALSE;

    if ( (_datareg.month() != _dataregp.month()) && (_dataregp.ok()) )
    {
      if (_tipo_stampa == 2)
        ++ _u_stampata;
      _auto_intraf = FALSE;  
      printer().formfeed();
    }
    
    _dataregp = _datareg;

    TDate   datadoc  = mov.get_date(MOV_DATADOC);
    long    numreg   = mov.get_long(MOV_NUMREG);
    long    protiva  = mov.get_long(MOV_PROTIVA);
    real    totdoc   = mov.get_real(MOV_TOTDOC);
    TString numdoc   = mov.get(MOV_NUMDOC);
    char    tipocf   = mov.get(MOV_TIPO)[0];
    TString ocfpi    = mov.get(MOV_OCFPI);
    long    codcf    = mov.get_long(MOV_CODCF);
    long    numgio   = mov.get_long(MOV_NUMGIO);
    bool    stampato = mov.get_bool(MOV_REGST);
    bool    intra    = caus.get_bool(CAU_INTRACOM);
    bool    autof    = caus.get_bool(CAU_AUTOFATT);
    TString descrcau = caus.get(CAU_DESCR);
    
    //aggiornamento di mov
    if (_tipo_stampa != 3)
      if (!stampato)
      {
        mov.put(MOV_REGST,TRUE);
        mov.rewrite();
      }      
    
    if ( intra && autof)
    {
      _auto_intraf = TRUE;
      tipo_op = "3";
    }  
    else if (intra) 
      tipo_op = "1";
    else if (autof)
      tipo_op = "2";
    
    if ( (tipocf == 'C') || (tipocf == 'F') )
    {
      if (ocfpi.trim().empty())
        ragsoc = ricerca_cf(tipocf, codcf);
      else
        ragsoc = ricerca_occ(ocfpi);
    }
    else ragsoc = descrcau;
    
    _tipodoc   = mov.get(MOV_TIPODOC);
    _descr_doc = descr_doc(_tipodoc);
    TString app = datadoc.string(2, '/');
    
    _doc_array.add_riga(_tipodoc,_descr_doc,totdoc); 

    //setto le righe di stampa
    _r = 1;
    set_row(_r, "%s",       (const char*) _datareg.string(2, '/'));
    set_row(_r, "@9g%5d",   protiva);
    set_row(_r, "@15g%s",   (const char*) app);
    set_row(_r, "@24g%s",   (const char*) numdoc);
    set_row(_r, "@32g%ld",  codcf);
    set_row(_r, "@39g%.28s",(const char*) ragsoc);
    set_row(_r, "@68g%s",   (const char*) tipo_op);
    set_row(_r, "@70g%2s",  (const char*) _tipodoc);
    set_row(_r, "@72g%r",   &totdoc);
    
    _nrec = riga_rmoviva();
    if (_nrec > 0)
    {
      for (int j = 0; j < _riga_rmi.items(); j++)
      {
        TRigaiva& riga = (TRigaiva&)_riga_rmi[j];
        rr = _r+j;
        set_row(rr, "@87g%r",   &riga._imponibile);
        set_row(rr, "@102g%4s",(const char*)riga._codiva);
        if (_tipo_reg == 2)
          set_row(rr, "@107g%d",  riga._tipodet);
        set_row(rr, "@108g%r",  &riga._imposta);
        set_row(rr, "@124g%d",  riga._tipocr);
      } 
      _riga_rmi.destroy();
    }
    //int tipocr = _cur->file(LF_RMOVIVA)->get_int(RMI_TIPOCR);
    //set_row(_r, "@124g%d",  tipocr);
    if (_tipo_stampa == 3) //stampa di prova
    {
      set_row(_r, "@125g%6d", numreg);
      if (stampato)
        set_row(_r, "@131g*");
    }
    if (_tipo_stampa == 4) //stampa con riferimento al libro giornale
      set_row(_r, "@125g%ld", numgio);
  }
  return TRUE;
}

void CG4400_application::aggiorna_reg()
{
  TString16 codtab; 
  TTable Tabreg ("REG");
  TTable TabInl ("%INL");
  long pag;
  //long stampate;
  
  word ultimast = get_page_number();
  if (_stampa_tutti_i_registri)  //ho fatto un salto pagina dopo avere stampato un registro
    --ultimast;
  
  codtab << _annoes << _codreg;
  Tabreg.zero();
  Tabreg.put("CODTAB", codtab);  
  if (Tabreg.read() == NOERR)
  {
    //stampate = ultimast + 1;
    if (!_mov_empty) //cioe' se e' stata stampata almeno una pagina
    {
      pag = _pagine_stampate + ultimast;
      Tabreg.put("I1", pag);
    }  
    Tabreg.put("D3", _data_a);
    Tabreg.rewrite();
  }
  if (_tipo_stampa == 2) //stampa su libro unico
    //sulla tabella %inl (indice libro unico) devo generare una riga per ogni registro stampato
    if (!_mov_empty)
    {
      bool trovato  = FALSE;
      codtab = "";
      codtab << _annoes << _codlib;
      TabInl.zero();
      TRectype nuovo   (TabInl.curr());
      TRectype recprec (TabInl.curr());
      TabInl.put("CODTAB", codtab);
      
      TRectype rec (TabInl.curr());
      TabInl.read (_isgteq);
      for (; !TabInl.eof(); TabInl.next())
      { 
        if (TabInl.curr() != rec) break;
        
        trovato = TRUE;
        recprec = TabInl.curr();
      }
      
      TString cod = "";
      if (trovato)
      {  
        TString16 cod_inl = recprec.get("CODTAB");
        long numero_riga  = atol(cod_inl.mid(7,6)) + 1;
        TString16 num_riga (format("%6d", numero_riga));
        cod_inl = cod_inl.mid(0,7); 
        nuovo   = recprec;
        cod << cod_inl << num_riga;
      }
      else
      {
        TString16 num_riga ( format("%6d", 1L) );
        cod << codtab << num_riga;
      }
      
      long numini = _pagine_stampate + 1;
      nuovo.put("CODTAB", cod);
      nuovo.put("I0", (long)_annoes);
      nuovo.put("I1", (long)_fino_a_mese);
      nuovo.put("I2", (long)(_primast + 1));
      nuovo.put("I3", (long)(_primast + ultimast));
      nuovo.put("I4", get_firm());
      nuovo.put("S0", _codreg);
      nuovo.put("I5", (long)numini);
      nuovo.put("I6", (long)(numini + ultimast - 1));
      
      if (trovato)
        TabInl.rewrite(nuovo);
      else      
        TabInl.write(nuovo);
      
      _u_stampata  += ultimast;
    } 
}

void CG4400_application::aggiorna_lib()
{
  TString16 cod = ""; 
  TTable lbu ("%LBU");
  
  cod << _annoes << _codlib;
  lbu.zero();
  lbu.put("CODTAB", cod);  
  if (lbu.read() == NOERR)
  {
    lbu.put("I0", (long) _fino_a_mese);
    lbu.put("I1", (long) _u_stampata);
    lbu.rewrite();
  }
}

print_action CG4400_application::postprocess_page (int file, int counter)
{
  if (file == LF_MOV)
    if (!counter)
    {
      bool FINITO = FALSE;
      TRecnotype pos   = _cur->pos();
      long       items = _cur->items();
      
      FINITO = (pos == items-1);
      
      if ( FINITO )  
      {
        set_page_tot_reg();
        return REPEAT_PAGE;
      }
      else //if ( (_tipo_stampa == 1) || (_tipo_stampa == 4) )
      {
        TLocalisamfile& mov = _cur->file(LF_MOV);
        _cur->save_status();
        ++(*_cur);
        _dataregs = mov.get_date(MOV_DATAREG);
        --(*_cur);
        _cur->restore_status();

        if (_dataregs.month() != _dataregp.month())
        {
          set_page_tot_reg();
          return REPEAT_PAGE; 
        } 
      } 
    }
  return NEXT_PAGE;
}

print_action CG4400_application::postprocess_print(int file, int counter)
{
  if (file == LF_MOV)
  {
    //aggiorna registri solo se non e' stampa di prova
    if ( (_tipo_stampa != 3) && (!_stampa_tutti_i_registri) )
      aggiorna_reg();
    if (_stampa_tutti_i_registri)
      //if (!_mov_empty )
    {
      if (_tipo_stampa == 2)
        ++ _u_stampata;
      /*
         TRecnotype pos   = _cur->pos();
         long       items = _cur->items();
         if (pos < items-1)
         printer().formfeed();
         */   
    }     
    /*
       if (_stampa_tutti_i_registri)
       {
       TString16 codtab;
       int anno, tipo;
       //vado avanti dal punto in cui sono
       _tabreg->next();
       for (; !_tabreg->eof(); _tabreg->next())
       { 
       tipo = _tabreg->get_int("I0");
       if ( (tipo == 1) || (tipo == 2) ) //registro iva
       {
       codtab = _tabreg->get("CODTAB");
       anno = atoi(codtab.mid(0,4));
       break;
       }  
       }
       if ( (_tabreg->eof()) || (anno != _annoes) )
       { 
       if (_tipo_stampa == 2) //stampa su libro unico
       aggiorna_lib();
       return NEXT_PAGE;
       }  
       else
       {
       _tipo_reg        = _tabreg->get_int("I0");
       _desc_lib        = _tabreg->get("S0");
       _data_da         = _tabreg->get_date("D3");
       _pagine_stampate = _tabreg->get_int("I1");
       _codreg          = codtab.mid(4,3);
       _primast         = get_page_number();
       if (!_mov_empty )
       printer().formfeed();
       _cur->set_filterfunction(NULL);
       _cur->set_filterfunction(filter_func);
       _mov_empty = TRUE;
       return REPEAT_PAGE;
       }
       }
       */
  }  
  
  return NEXT_PAGE;   
}

bool CG4400_application::set_print(int n)
{
  TMask m("cg4400a");

  const bool ok = set_ditte(m);
  
  if (ok)
    if (_selected.ones() > 0l)
    {
      _annoes      = m.get_int(ANNO);//in realta' e' l'anno IVA !!!
      _tipo_stampa = m.get_int(TIPO_STAMPA);
      //Se stampa di prova l'utente indica data_da e data_a
      if (_tipo_stampa == 3)                            
      {
        _data_stampa = m.get(DATA_STAMPA);
        _data_da     = m.get(DA_DATA);
        _data_a      = m.get(A_DATA);
        if (!_data_da.ok())
          _data_da = format("01/01/%4d", _annoes);
        if (!_data_a.ok())
          _data_a = format("31/12/%4d", _annoes);
        printer().setdate(_data_stampa);
      }
      // senno' data_da e' letta dal registro
      else   //stampe definitive
      {
        int giorni_del_mese; 
        if ( (_tipo_stampa == 1) || (_tipo_stampa == 4) )
          _fino_a_mese = m.get_int(FINO_A_MESE);
        else  //stampa su libro unico
        { 
          _codlib      = m.get(CODICE_LIB_UN);      
          _fino_a_mese = m.get_int(MESE);
          _u_stampata  = m.get_int(ULTIMA_PAGINA);
          //set_page_number(_u_stampata + 1);
        }     
        if (_fino_a_mese == 12)
          giorni_del_mese = 31;
        else
        {
          TDate primo = format("01/%02d/%4d", _fino_a_mese+1, _annoes);
          --primo;
          giorni_del_mese = primo.day();
        }
        _data_a=format("%02d/%02d/%4d",giorni_del_mese,_fino_a_mese,_annoes);
        // NB data_da viene letta nella compila_reg
      }
      if (_tipo_stampa == 2)
        compila_lib();
      stampa_registri_IVA(m);
    }
    else warning_box("Nessuna ditta selezionata!"); 

  return FALSE;
}

void CG4400_application::stampa_registri_IVA(const TMask& m) 
{
  long l;
  long firm = TApplication::get_firm();
  bool ok = FALSE;

  for (l = 0l, _nditte->first(); !_nditte->eof(); l++, _nditte->next())
  {
    if (_selected[l])
    {
      TApplication::set_firm(_nditte->get_long("CODDITTA"));
      ok = compila_reg(m);   // cerca il primo registro valido (nel caso di stampa tutti i registri), senno' legge i dati del registro specificato
      if (!ok) continue;
      if (!_stampa_tutti_i_registri)
        _cur->set_filterfunction(filter_func);
      _frequiva = _nditte->get("FREQVIVA")[0];
      if (_tipo_stampa != 3) //stampa definitiva
        ok = controlla_liquidazione() && controlla_mov();

      if (!ok) continue;

      if (!_stampa_tutti_i_registri)
      {
        (*_cur) = 0L;          
        const long item = _cur->items();
        if (item > 0)
          print();
        if (_tipo_stampa != 3) aggiorna_reg();   
      }  
      else
      {
        TString16 codtab;
        int anno, tipo;
        for (_tabreg->first(); !_tabreg->eof(); _tabreg->next())
        { 
          tipo = _tabreg->get_int("I0");
          codtab = _tabreg->get("CODTAB");
          anno = atoi(codtab.mid(0,4));
          if (anno > _annoes)
            break;
          if (anno == _annoes)   
            if ( tipo == 1 || tipo == 2 ) //registro iva
            {
              _tipo_reg        = _tabreg->get_int("I0");
              _codreg          = codtab.mid(4,3);
              _corrispettivi   = _tabreg->get_bool("B0");
              if (_tipo_stampa != 3)
              {
                _data_da = _tabreg->get_date("D3");
                if (!_data_da.ok())  //e' la prima volta che stampo
                  _data_da = format("01/01/%4d", _annoes);
              }
              if (_tipo_stampa == 1 || _tipo_stampa == 4)
                if (_data_a <= _data_da)
                  warning_box("Il registro %s e' gia' stato stampato come bollato di %s", (const char*) _codreg, itom(_fino_a_mese)); 
              _pagine_stampate  = _tabreg->get_int("I1");
              _codatt           = _tabreg->get("S8");
              _attivita         = desc_attivita(_codatt);
              _desc_lib         = _tabreg->get ("S0");
              _stampa_ind_ditta = _tabreg->get_bool ("B9");
              //_primast       = get_page_number();
              _cur->set_filterfunction(NULL);
              _cur->set_filterfunction(filter_func);
              // Vado a vedere se ci sono movimenti              
              (*_cur) = 0L;          
              const long items = _cur->items();
              if (items > 0)
                //set_page_number(_u_stampata + 1);
                print();
              if (_tipo_stampa != 3) aggiorna_reg();
            }  
        }
      }
      if (_tipo_stampa == 2)
        aggiorna_lib();
    }           
  }
  
  TApplication::set_firm(firm);
}

bool CG4400_application::set_ditte(TMask& m)
{
  _selected.reset();
  
  m.field(F_SELECT).set("0");
  m.field(DA_CODICE).set("");
  m.field(A_CODICE).set("");
  m.field(TIPO_STAMPA).set("1");
  
  m.set_handler (TIPO_STAMPA, tipostampa_handler);
  m.set_handler (A_CODICE, mask_firm_to); 
  m.set_handler (DA_DATA,  mask_data);
  m.set_handler (A_DATA,   mask_data);
  m.set_handler (A_DATA,   mask_tipo);
  m.set_handler (MESE,     mask_mese);
  m.set_handler (CODICE_LIB_UN, mask_cod);
  m.set_handler (DLG_SELECT, mask_select);
  m.set_handler (F_ANNULLA,  mask_azzera);
  
  KEY tasto;     

  _stampa_width = 132;
  set_real_picture("###.###.###.###");

  tasto = m.run();

  //  m.first_focus(tasto);
  
  return tasto == K_ENTER;
}

TRectype& look_comuni (const char * cod, TLocalisamfile *comuni)
{
  comuni->zero();
  comuni->put(COM_COM, cod);
  comuni->read();
  if (comuni->bad())
    comuni->zero();

  return comuni->curr();
}

void CG4400_application::get_dati_ditta()
{
  TLocalisamfile nditte(LF_NDITTE); 
  TLocalisamfile anag(LF_ANAG); 
  TString        codanagr;
  TString        tipoa;

  nditte.zero();
  nditte.put(NDT_CODDITTA, get_firm());   
  nditte.read();

  if (nditte.bad()) nditte.zero();

  codanagr = nditte.get(NDT_CODANAGR);
  tipoa    = nditte.get(NDT_TIPOA);
  _ragsoc  = nditte.get(NDT_RAGSOC);

  anag.setkey(1);
  anag.zero();
  anag.put (ANA_TIPOA, tipoa);
  anag.put (ANA_CODANAGR, codanagr);
  anag.read();
  if (anag.bad()) anag.zero();
  
  _cofi      = anag.get(ANA_COFI);
  _paiva     = anag.get(ANA_PAIV);
  _comunefis = anag.get(ANA_COMRF);

  if (_comunefis.empty()) 
    _comunefis   = anag.get(ANA_COMRES);

  TRectype dep = look_comuni (_comunefis, _com);

  _comunefis   = dep.get(COM_DENCOM);
  _provfis     = dep.get(COM_PROVCOM);
  _cap         = dep.get(COM_CAPCOM);
  if (_comunefis.empty()) 
  {
    _viafis      = anag.get(ANA_INDRF);
    _viafis.rtrim();
    _viafis << " " << anag.get (ANA_CIVRF); 
  }
  else
  {
    _viafis      = anag.get(ANA_INDRES);
    _viafis.rtrim();
    _viafis << " " << anag.get (ANA_CIVRES); 
  }
}

int CG4400_application::stampa_intestazione()
{
  int r = 1;
  TString codice_ditta;
  TString riga(_stampa_width);
  //TString riga(132);

  get_dati_ditta();
  codice_ditta << get_firm(); 

  set_header (r, "Ditta %s %s %s %s %s %s", (const char*)codice_ditta,
              (const char*)_ragsoc, (const char*)_viafis,
              (const char*)_cap, (const char*)_comunefis,
              (const char*)_provfis);
  r++;
  //printer().setdate(_data);
  if (_tipo_stampa == 3)
    riga = "STAMPA DI PROVA   Data @<";
  //else
  //  riga = "Data @<";
  riga.right_just(_stampa_width-6);
  //riga.right_just(127);
  riga.overwrite (format ("Partita iva %s Codice fiscale %s", (const char*)_paiva, (const char*)_cofi));
  set_header (r, "%s", (const char*) riga);
  r++;

  return r; 
}

void CG4400_application::preprocess_header()
{
  int r=1;
  TString cor, nd1, nd2; 
  TString riga(_stampa_width);
  TString data;   
  
  if ( (_tipo_stampa == 1) || (_tipo_stampa == 4) )
    data.format("%s %s %d", (const char*)"mese di", itom(_datareg.month()), 
                _datareg.year());
  else if (_tipo_stampa == 2)
    data.format("%s %s %d", (const char*)"mese di", itom(_fino_a_mese), _annoes);                
  else //stampa di prova
    data.format("%s %s %d", (const char*)"mese di", itom(_data_da.month()), _annoes);                

  reset_header();

  if (_tipo_stampa != 3)
    if (_stampa_ind_ditta)
      r = stampa_intestazione();

  if (_tipo_stampa == 2)
  {
    long num = _u_stampata + 1;
    set_header(r++, "@94gProgr.Studio %ld@114gProgr.Utente @#", num);
  }

  set_header(r, "Registro IVA: %s %s   %s    Attivita\' %s %s",
             (const char *) _codreg, (const char *) _desc_lib, 
             (const char *) data, (const char *) _codatt,
             (const char *) _attivita);
  r++;
  riga.fill('-'); 
  set_header(r, riga);
  r++;
  if (_tipo_reg == 1)  //registro vendite
  {
    cor = "R";
    nd1 = "";
    nd2 = "";
  }  
  if (_tipo_reg == 2)
  { 
    cor = "C";
    nd1 = "N";
    nd2 = "D";
  }
  if (_tipo_stampa == 3) //stampa di prova
  {
    set_header(r,"@10gNum.@19gDocumento@68gT Tipo@103gCod %s@121g@124gT@128gNum",  (const char*) nd1);
    r++;
    set_header(r, "Data reg. prot.@17gData@25gNumero Codice Ragione sociale/descrizione@68gO Doc.@76gTotale doc.@91gImponibile  Iva %s@112gImposta@124g%s@128gReg", (const char*) nd2, (const char*) cor);
    r++;
  }
  else
  {
    set_header(r,"@10gNum.@19gDocumento@68gT Tipo@103gCod %s@121g@124gT", (const char*) nd1);
    if (_tipo_stampa == 4) //stampa definitiva con rif. al libro giornale
      set_header(r, "@128gNum."); 
    r++;
    set_header(r, "Data reg. prot.@17gData@25gNumero Codice Ragione sociale/descrizione@68gO Doc.@76gTotale doc.@91gImponibile  Iva %s@112gImposta@124g%s", 
               (const char*) nd2, (const char*) cor);
    if (_tipo_stampa == 4)
      set_header(r, "@128gop."); 
    r++;
  } 
  riga.fill('-'); 
  set_header(r, riga);
}

int cg4400 (int argc, char * argv[])
{
  CG4400_application a;
  a.run(argc, argv, "Stampa registri IVA");
  return 0;
}














