// *******************
// Stampa registri IVA
// *******************
#include "cg4.h"
#include "cg4400.h"
#include "cg4400a.h"
#include "cg4400b.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);
  bool    regst   = mov.get_bool(MOV_REGST);

  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;           
  
  if (app()._tipo_stampa != 1) //stampa di bollato
    if (regst)                 //il movimento e' gia' 
      return FALSE;            //stato stampato in forma definitiva

  if (datareg.month() < app()._stampa_mese)
    app()._stampa_mese = datareg.month(); 
  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::stampa_totali_finali()
{
  TConfig conf(CONFIG_DITTA);
  return conf.get_bool("StTfFr");
}

bool CG4400_application::stampa_datareg()
{
  TConfig conf(CONFIG_STUDIO);
  return conf.get_bool("NoDtRg");
}

bool CG4400_application::mask_select (TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    app()._ditte->enable_check();
    // seleziona e aggiungi alle gia' selezionate 
    if (app()._ditte->run() == K_ENTER)
    {
      for (long j = 0l; j < app()._ditte->items(); j++)
        app()._selected.set(j, app()._ditte->checked(j));
      app().set_choice_limits(f.mask());
    }
  }
  return TRUE;
}    

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

bool CG4400_application::mask_tipo_stampa(TMask_field& f, KEY k)
{
  TMask& m = f.mask();
  
  if (k == K_SPACE)
  {
    int tipo_stampa = m.get_int(TIPO_STAMPA);
    if (tipo_stampa == 3) //stampa su libro unico
    {
      m.enable_page(1);
      TMask_field& cc = f.mask().field(CODICE_LIB_UN);
      cc.set_dirty();
    }
    else
      m.disable_page(1);
  }
  return TRUE;
}  

bool CG4400_application::mask_mese (TMask_field& f, KEY k)
{      
  if (k == K_SPACE)
  {
    const short id = f.dlg();
    int mese;
    if (id == MESE) //Per stampa su libro unico
      mese = f.mask().get_int(MESE);
    if (id == FINO_A_MESE)
      mese = f.mask().get_int(FINO_A_MESE); //Per stampa su bollato
    if (id == MESE)
    {
      if (mese == 12)
      {
        f.mask().show (TIPO_RIEPILOGATIVO);
        f.mask().show (RIF_VID);
      }  
      else
      {
        f.mask().hide (TIPO_RIEPILOGATIVO);
        f.mask().hide (RIF_VID);
      }
    }   
    if (id == FINO_A_MESE) 
    {
      if (mese == 12)
        f.mask().show (TIPO_RIEPILOGATIVO);
      else f.mask().hide (TIPO_RIEPILOGATIVO);
    }
  }
  if (k==K_TAB && f.mask().is_running())
  {
    const short id = f.dlg();
    if (id == MESE)
      f.mask().send_key(K_TAB, CODICE_LIBRO_IVA);  
  }
  return TRUE;
}

bool CG4400_application::look_reg(int i, int anno, TString& codlib, int m, const char* cod, int* umese, long ditta)
{
  TString16 y; 
  
  y << anno << cod;
  _tabreg->zero();
  _tabreg->put("CODTAB", y);

  if (_tabreg->read() == NOERR)
  {
    int tipo = _tabreg->get_int("I0");
    if (tipo == 1 || tipo == 2)
    {
      TString16 cod_lib_un = _tabreg->get("S6");
      TDate u_data = _tabreg->get_date("D3");
      TDate sca_vid = _tabreg->get_date("D1");
      if (codlib != cod_lib_un)
      {
        if (_selected.ones() == 1L)
          if (_selected[i])
            message_box("Ditta %ld: il codice libro unico del registro non e' uguale al codice libro unico indicato", ditta);
        return FALSE;
      }
      if (m < *umese)
      { 
        if (_selected.ones() == 1L) 
          if (_selected[i])
            message_box("Ditta %ld: il mese indicato e' inferiore al mese dell'ultima data di stampa del registro", ditta);
        return FALSE;
      }   
      if (u_data.ok())
        *umese = u_data.month();
      else *umese = 0;
      
      if (sca_vid.ok())
        if (sca_vid.month() < m)
        {
          if (_selected.ones() == 1L) 
            if (_selected[i])
              message_box("Ditta %ld: la data scadenza di vidimazione del registro non deve essere inferiore al mese indicato", ditta);
          return FALSE;
        } 
    }
    return TRUE;   
  }
  return FALSE;
}

bool CG4400_application::look_regs(int anno, TString& codlib, int m, int* umese, long ditta, TProgind* prog)
{
  int a, tipo;
  TString16 codtab;
  bool ok = FALSE;
  *umese = 13;
  
  for (_tabreg->first(); !_tabreg->eof(); _tabreg->next())
  { 
    tipo   = _tabreg->get_int("I0");
    codtab = _tabreg->get("CODTAB");
    a = atoi(codtab.mid(0,4));
    if (a > anno)
      break;
    if (a == anno)   
      if ( tipo == 1 || tipo == 2 ) //registro iva
      {
        TString16 cod_lib_un = _tabreg->get("S6");
        TDate     sca_vid    = _tabreg->get_date("D1");
        TDate     u_data     = _tabreg->get_date("D3");
        if (codlib != cod_lib_un)
          continue;
        if (u_data.ok())
          if (m < u_data.month())
            continue;
        if (u_data.ok())
          *umese = (*umese < u_data.month()) ? *umese : u_data.month(); 
        if (sca_vid.ok())
          if (sca_vid.month() < m)
            continue;
        int month;  
        if (!u_data.ok())
          month = 0;
        else month = u_data.month();
        if (month < m - 1)
        {
          app().set_firm(__firm);
          delete prog;
          error_box("Ditta %ld: Stampare i registri dei mesi precedenti", ditta);
          app().stop_run();
        }
        ok = TRUE;  
      }    
  }
  return ok;
}

bool CG4400_application::mask_libun (TMask_field& f, KEY k)
{    
  if (k==K_TAB && f.mask().is_running())
  {
    TString16 codlib(f.mask().get(CODICE_LIB_UN));
    //modifica del 26/04/1995
    if (codlib.empty())
    {
      app()._test = TRUE;
      return FALSE;
    }
    //fine modifica
    
    if (app()._selected.ones() == 0l) return FALSE;
    
    TProgind* p = new TProgind(app()._ditte->items()/2,"Verifica parametri in corso...",FALSE,TRUE,30);
    
    TString16 cod(f.mask().get(CODICE_LIBRO_IVA));
    int fino_a_mese = f.mask().get_int(MESE);
    int  anno = f.mask().get_int(ANNO);
    bool ok   = FALSE;
    int last_mese = 13;
    int mese = 0;
    
    app().__firm = app().get_firm(); 
    
    for (int i = 0; i < app()._ditte->items(); i++)
    {
      //p->addstatus(1);
      long ditta = app()._ditte->row(i).get_long(1);
      if (prefix().exist(ditta))
      {
        p->addstatus(1);        
        app().set_firm(ditta);   
        if (cod.not_empty())
        {
          ok = app().look_reg(i,anno,codlib,fino_a_mese,cod,&mese,ditta);
          if (!ok)
          {
            //modifica del 21/04/1995 suggerita da Cinzia!!!
            /*****Rimodifica del 19/07/95 MI0817
            if (app()._selected.ones() == 1L)  //solo se ho selezionato 1 ditta devo dare il messaggio
              if (app()._selected[i])
                f.message_box("Ditta %ld: il registro %s non soddisfa i parametri indicati", ditta, (const char*)cod);  
            *****/ 
            continue;             
          }
          if (mese < fino_a_mese - 1) //indipendentemente se si tratta di una ditta selezionata oppure no
          {
            app().set_firm(app().__firm);
            delete p;
            f.error_box("Ditta %ld: Stampare i registri dei mesi precedenti", ditta);
            app().stop_run();
          }
        }     
        else
        {
          ok = app().look_regs(anno,codlib,fino_a_mese,&mese,ditta,p);
          if (!ok)
          {
            if (app()._selected.ones() == 1L)  //solo se ho selezionato 1 ditta devo dare il messaggio
              if (app()._selected[i])
                f.message_box("Ditta %ld: nessun registro soddisfa i parametri indicati", ditta);
            continue;
          } 
        }
        //if (app()._selected[i]) 
        last_mese = (last_mese < mese) ? last_mese : mese;
      }    
    }             
    app().set_firm(app().__firm); 

    if (last_mese == 13)
      last_mese = 0; //l'ultima data di stampa sul/sui registri specificati e' vuota (cioe' non sono ancora stati stampati sul libro unico specificato per l'anno specificato) 
    const char* me = "";
    me = format("%02d", last_mese);   
    f.mask().set(ULTIMO_MESE, me);
    delete p;
  }
  return TRUE;
}  

bool CG4400_application::mask_cod (TMask_field& f, KEY k)
{ 
  if (k == K_TAB)
  {
    TTable TabLbu ("%LBU");
    TString codtab; 
    int anno;
    
    TString16 codlib(f.get());
    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(ULTIMO_MESE,TabLbu.get_long("I0"));
      f.mask().set(ULTIMA_PAGINA,TabLbu.get_long("I1"));
      app()._codice_vidi = TabLbu.get("S4");
    }
    //modifica del 26/04/1995
    if (app()._test) 
    {
      f.mask().send_key(K_TAB, CODICE_LIBRO_IVA);
      app()._test = FALSE;
    }
    //fine modifica  
  }
  return TRUE;
}

bool CG4400_application::mask_data (TMask_field& f, KEY k)
{
  if (k == K_TAB && f.mask().is_running())
  {
    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;
      }
    if (f.dlg() == A_DATA)
      if (data.ok)
      {
        if ( data.day() == 31 && data.month() == 12 )
          f.mask().show (TIPO_RIEPILOGATIVO);
        else f.mask().hide (TIPO_RIEPILOGATIVO);
      }
  } 
  return TRUE;
} 

const char * CG4400_application::descr_doc()
{
  TTable  tab_tpd("%TPD");
  TString codtab(format("%-2s",(const char*) _tipodoc));
  
  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");
  TString 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::tipo_attivita()
{
  TLocalisamfile attiv (LF_ATTIV);
  
  attiv.zero();
  attiv.put("CODDITTA", get_firm());
  attiv.put("CODATT", _codatt);
  if (attiv.read() == NOERR)
    TMP = attiv.get("TIPOATT");
  else TMP = "";
  return TMP;   
}

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

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

TRectype& CG4400_application::ricerca_cf(char tipocf, long codcf)
{
  _clifo->zero();
  _clifo->put(CLI_TIPOCF, tipocf);
  _clifo->put(CLI_CODCF, codcf);
  _clifo->read();
  if (_clifo->bad())
    _clifo->zero();

  return _clifo->curr();
}

TRectype& CG4400_application::ricerca_occ(const char * occ)
{
  TLocalisamfile occas (LF_OCCAS);
  occas.zero();
  occas.put(OCC_CFPI, occ);
  occas.read();
  if (occas.bad())
    occas.zero();
  
  return occas.curr();
}

bool CG4400_application::year_handler(TMask_field& f, KEY key)
{                                                    
  if (key == K_TAB && f.focusdirty())
  {                         
    app().begin_wait();
    app().set_year(atoi(f.get()));
    app().build_nomiditte();
    app().build_ditte_sheet();    
    app().end_wait();
  }
  return TRUE;
} 

void CG4400_application::build_ditte_sheet()
{
  // build sheet
  _ditte->destroy();
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string* d = new TToken_string(64);
    *d = (TToken_string&)_nomiditte[i];
    const char vers = d->get_char(2);
    bool selectable = vers == '?';
    d->insert(" |", 0);        
    const long pos = _ditte->add(d);     
    if (selectable) 
      _ditte->disable(pos);
    else if (_selected[i]) 
      _ditte->check(pos);
  }     
}

// --------------------------- handlers per selezione ditte

bool CG4400_application::to_ditt_handler(TMask_field& f, KEY key)
{
  TMask& m = f.mask();
  if (key == K_F9)
    app().to_butt_handler(m.field(BUT_DTO), K_SPACE);
  if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(DA_CODICE), m.get_long(A_CODICE)); 
    app().set_choice_limits(m);
    m.field(F_SELECT).set(format("%ld", l));
  }
  return TRUE;
}

bool CG4400_application::fr_ditt_handler(TMask_field& f, KEY key)
{                          
  TMask& m = f.mask();
  if (key == K_F9)
    app().fr_butt_handler(m.field(BUT_DFR), K_SPACE);
  else if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(DA_CODICE), m.get_long(A_CODICE)); 
    app().set_choice_limits(m);
    m.field(F_SELECT).set(format("%ld", l)); 
  }
  return TRUE;
}

bool CG4400_application::to_butt_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)
  {
    TArray_sheet* sh = app().get_ditte_sheet();
    TMask& m = f.mask();
    
    sh->disable_check();    
    if (sh->run() == K_ENTER)
    {
      app().select_firm_range(m.get_long(DA_CODICE),sh->row(sh->selected()).get_long(1)); 
      app().set_choice_limits(m);           
    }
  }
  return TRUE;
}

bool CG4400_application::fr_butt_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)
  {
    TMask& m = f.mask();
    TArray_sheet* sh = app().get_ditte_sheet();

    sh->disable_check();    
    if (sh->run() == K_ENTER)
    {
      app().select_firm_range(sh->row(sh->selected()).get_long(1), m.get_long(A_CODICE)); 
      app().set_choice_limits(m);
    }
  }
  return TRUE;
}

void CG4400_application::set_choice_limits(TMask& m)
{     
  long first = -1l, last = -1l;
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_selected[i])
    {
      long dit = _ditte->row(i).get_long(1);
      if (first == -1l) first = dit;
      if (last < dit)   last  = dit;
    }
  }
  if (first != -1) m.field(DA_CODICE).set(format("%ld",first));                        
  if (last  != -1) m.field(A_CODICE).set(format("%ld",last));                        
  m.set(F_SELECT, _selected.ones());
  //modifica del 02/06/1995
  if (m.is_running()) 
    if (first != -1l) app().set_firm(first);   
  //fine  
}

long CG4400_application::select_firm_range(long from, long to)
{
  if (to == 0l) to = 99999L;                              
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_ditte->disabled(i))
      continue;

    TToken_string& d = _ditte->row(i);
    const char vers = d.get_char(3);
    if (vers == '?')
      continue;

    const long cod = d.get_long(1);
    if (cod >= from && cod <= to)
    {
      _selected.set(i); 
      _ditte->check(i);
    }
    else 
    {
      _selected.set(i,FALSE);
      _ditte->uncheck(i);
    }
  } 
  return _selected.ones();
}

void CG4400_application::build_nomiditte(TProgind* pnd)
{                 
  _nomiditte.destroy();
  // ricostruire _nomiditte e rifare build_ditte_sheet
  TLocalisamfile& dt = _nditte->lfile();

  for (dt.first(); !dt.eof(); dt.next())
  {     
    // check no archivi
    bool good = prefix().exist(dt.get_long("CODDITTA"));                        
    if (good) 
    {   
      // check no parametri liquidazione                                               
      //TApplication::set_firm(dt.get_long("CODDITTA"));   
      if (!look_lia(dt.get_long("CODDITTA"))) good = FALSE; 
    }
    _n_ditte++;
    TToken_string* d = new TToken_string(64);
    d->add(dt.get("CODDITTA"));
    d->add(dt.get("RAGSOC"));
    if (good) d->add(_tablia->get("S7"));
    else d->add("??");
    
    _nomiditte.add(d);  
  }
  //if (pnd) pnd->addstatus(1);
  //TApplication::set_firm(__firm);
}

bool CG4400_application::user_create()
{
  //TProgind* pnd = NULL;
  
  //pnd = new TProgind (2,"Preparazione archivi\nPrego attendere", 
  //                    FALSE, TRUE, 30);
  
  _com    = new TLocalisamfile(LF_COMUNI);
  _anag   = new TLocalisamfile(LF_ANAG);
  _unloc  = new TLocalisamfile(LF_UNLOC);
  _attiv  = new TLocalisamfile(LF_ATTIV);
  _tab    = new TLocalisamfile(LF_TAB);
  _tabcom = new TLocalisamfile(LF_TABCOM);
  _indlib = new TLocalisamfile(LF_INDLIB);
  _tabreg = new TTable("REG");
  _tabiva = new TTable("%IVA");  
  _tablbu = new TTable("%LBU");
  _tablim = new TTable("LIM");
  _tabpim = new TTable("PIM");
  _tablia = new TTable("%LIA");
  _tabpla = new TTable("%PLA");
  _tabppa = new TTable("PPA");
  _tabvid = new TTable("%VID"); 
  _clifo  = new TLocalisamfile(LF_CLIFO);
  _occas  = new TLocalisamfile(LF_OCCAS);
  
  _desc27 = new TParagraph_string("", 27);
  
  _nditte = new TRelation(LF_NDITTE);
  
  _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, "", 2);
  
  _ditte = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                            "@1|Cod.@5R|Ragione Sociale@50|Vers.");
  
  //if (pnd) pnd->addstatus(1);
  
  _n_ditte = 0l;
  __firm = TApplication::get_firm();
  
  TDate oggi(TODAY);                    
  _annoes = oggi.year();
  
  build_nomiditte();            
  build_ditte_sheet();
  
  add_cursor(_cur);
  add_file(LF_MOV);
  add_file(LF_RMOVIVA);
  
  //delete pnd;
  
  return TRUE;
}

bool CG4400_application::user_destroy()
{
  delete _ditte;
  delete _nditte;
  delete _com;
  delete _unloc;
  delete _anag;
  delete _attiv;
  delete _indlib;
  delete _tab;
  delete _tabcom;
  delete _tabreg; 
  delete _tabiva;  
  delete _tablbu;
  delete _tablim;
  delete _tabpim;
  delete _tablia;
  delete _tabpla;
  delete _tabppa;
  delete _tabvid;
  delete _clifo;
  delete _occas;
  delete _cur;
  delete _rel;
  delete _desc27;
  
  return TRUE;
}

void CG4400_application::calcola_progressivi() 
{
  TTable pim ("PIM");  
  TString80 chiave;
  int i, num=0;
  
  if (_tipo_stampa == 3)
    num = _fino_a_mese;
  if ( _tipo_stampa == 2 || _tipo_stampa == 4 )  
    num = _datareg.month();
  
  //il discorso e' indipendente dalla frequenza!
  //if (_frequiva == 'T')
  //  if (num%3 != 0)
  //     num = num - (num%3);
  
  //calcolo i totali del periodo
  
  chiave = "";
  //_codatt e' gia' Z perche' lo leggo dal registro
  chiave << _annoes << _codatt;  
  pim.zero();
  pim.put ("CODTAB", chiave);
  TRectype r (pim.curr());
  pim.read(_isgteq);
  for (; !pim.eof(); pim.next())
  {
    if (pim.curr() != r) break;
    
    TString80 codtab = pim.get("CODTAB");
    TString16 codreg = codtab.mid(10,3); 
    int mese = atoi(codtab.mid(13,2)); 
    if (_codreg == codreg.trim() && mese == num)
    {
      TString16 codiva = codtab.mid(16,4);
      int tipodet = atoi(codtab.mid(20,1));
      real impo   = pim.get_real("R0");
      real impos  = pim.get_real("R1");
      real implo  = pim.get_real("R2");  
      //se il registro e' corrispettivi l'imponibile e l'iva li trovo in S2
      if (_corrispettivi) 
      {
        TToken_string cs (pim.get("S2")); 
        impo = cs.get(0);                 
        impos = cs.get(1);
      }
      //se in sospensione d'imposta l'imponibile e l'iva li trovo in R11 e R12
      if (_sosp_imposta)   //in genere non sara' mai un corrispettivo 
      {
        impo = pim.get_real("R11");
        impos = pim.get_real("R12");
      }
      TToken_string fatt_rit (pim.get("S1")); //e' sempre un acquisto
      real im (fatt_rit.get(0));
      real is (fatt_rit.get(1));
      impo  += im;
      impos += is;
      implo += im+is;  // potrei percio' ignorare l'importo lordo
      if (impo != ZERO || impos != ZERO || implo != ZERO)
        _tot_iva_array.add_riga(impo,impos,implo,ZERO,ZERO,ZERO,codiva); 
      if (_tipo_reg == 2) //registro acquisti
        if (impo != ZERO || impos != ZERO) 
          _iva_array.add_riga(impo,impos,ZERO,ZERO,codiva,tipodet,0,TRUE); 
    }   
  }
  
  //calcolo i totali progressivi
  if (_tipo_stampa == 3)
    num = _fino_a_mese;
  if ( _tipo_stampa == 2 || _tipo_stampa == 4 )  
    num = _datareg.month();
  
  for (i=1; i<=num; i++)
  {
    chiave = "";
    chiave << _annoes << _codatt;
    pim.zero();
    pim.put("CODTAB", chiave);
    TRectype r (pim.curr());
    pim.read(_isgteq);
    for (; !pim.eof(); pim.next())
    {
      if (pim.curr() != r) break;
      TString80 codtab = pim.get("CODTAB");
      TString16 codreg = codtab.mid(10,3);
      int       mese   = atoi(codtab.mid(13,2)); 
      if (_codreg == codreg.trim() && mese == i)
      {
        TString16 codiva = codtab.mid(16,4);
        int tipodet = atoi(codtab.mid(20,1));
        real impo   = pim.get_real("R0");
        real impos  = pim.get_real("R1");
        real implo  = pim.get_real("R2"); 
        //se il registro e' corrispettivi l'imponibile e l'iva li trovo in S2
        if (_corrispettivi) 
        {
          TToken_string cs (pim.get("S2")); 
          impo = cs.get(0);                 
          impos = cs.get(1);
        }
        //se in sospensione d'imposta l'imponibile e l'iva li trovo in R11 e R12
        if (_sosp_imposta) 
        {
         impo = pim.get_real("R11");
         impos = pim.get_real("R12");
        }
        TToken_string fatt_rit (pim.get("S1"));
        real im (fatt_rit.get(0));
        real is (fatt_rit.get(1));
        impo  += im; 
        impos += is;
        implo += im+is;
        if (impo != ZERO || impos != ZERO || implo != ZERO)
          _tot_iva_array.add_riga(ZERO,ZERO,ZERO,impo,impos,implo,codiva); 
        if (_tipo_reg == 2) //registro acquisti
          if (impo != ZERO || impos != ZERO)
            _iva_array.add_riga(ZERO,ZERO,impo,impos,codiva,tipodet,0,TRUE); 
      }   
    }
  }       
}

int CG4400_application::riga_rmoviva()
{ 
  TString  codiva;
  real     impo, impos;
  int      tipodet, tipocr, tipoatt; 
  bool     intra;
  
  TLocalisamfile& rmoviva = _cur->file(LF_RMOVIVA);
  bool ok = _cur->is_first_match(LF_RMOVIVA);
  int nrec = 0;
  
  TRecnotype nr = rmoviva.recno();
  
  while (ok)
  {
    nrec++;
    TRectype iva (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);
    intra   = iva.get_bool(RMI_INTRA); 
    tipoatt = iva.get_int("TIPOATT");
    
    _riga_rmi.add_riga(impo,impos,ZERO,ZERO,codiva,tipodet,tipocr,intra,tipoatt);
    
    if (_tipo_stampa == 1) //stampa di prova
    {
      if (_tipodoc == "FS")
      {
        real somma = -(impo + impos);
        _tot_iva_array.add_riga(ZERO,ZERO,somma,ZERO,ZERO,ZERO,codiva); 
      }      
      else if (_tipodoc == "CR" || _tipodoc == "RF" || _tipodoc == "SC")
        _tot_iva_array.add_riga(ZERO,ZERO,impo+impos,ZERO,ZERO,ZERO,codiva);
      if (_tipodoc != "CR" && _tipodoc != "SC" && _tipodoc != "RF")
        _tot_iva_array.add_riga(impo,impos,ZERO,ZERO,ZERO,ZERO,codiva); 
      
      if (_tipo_reg == 2) //registro acquisti (non ha senso parlare di importi lordi)
        _iva_array.add_riga(impo,impos,ZERO,ZERO,codiva,tipodet,0,TRUE);
    }
    
    ok = _cur->next_match(LF_RMOVIVA);
  }
  rmoviva.readat(nr);
  
  return nrec;   
}

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

messaggio CG4400_application::controlla_b0()
{
  TTable lim ("LIM");
  TString16 chiave = "";
  TString16 ditta  = "";
  int i, mese;
  ditta << get_firm();
  
  if (_tipo_stampa == 1) //stampa di prova
    mese = _data_a.month();
  else 
    mese = _fino_a_mese;   
  
  if (_tipo_riepilogativo == ' ' || _tipo_riepilogativo == 'P')
  {
    if (_frequiva == 'T') //nella tabella LIM ho solo i mesi 3, 6, 9, 12
    {
      for (i=3; i<=mese; i+=3)
      {
        chiave = "";
        TString16 m (format("%02d", i));
        chiave << _annoes << m;
        lim.put("CODTAB", chiave);
        if (lim.read() == NOERR)
        { 
          if (! lim.get_bool("B0"))
            return no_liquidazione;
        }
        else return no_liquidazione;
      }
    }                
    if (_frequiva == 'M')
    {
      for (i=1 ; i<=mese; i++)
      {
        chiave = "";
        TString16 m (format("%02d", i));
        chiave << _annoes << m;
        lim.put("CODTAB", chiave);
        if (lim.read() == NOERR)
        {
          if (! lim.get_bool("B0"))
            return no_liquidazione;
        }
        else return no_liquidazione; 
      } 
    }      
  }
  else if (_tipo_riepilogativo == 'A')
    //if (_riep_liq)
    {
      chiave = "";
      chiave << _annoes << 13;
      lim.put("CODTAB", chiave);
      if (lim.read() == NOERR)
      {
        if (! lim.get_bool("B0"))
          return no_liquidazione;
      }
      else return no_liquidazione;
    }  
  return B0_settato;   
}

messaggio CG4400_application::controlla_liquidazione()
{
  TTable lim ("LIM");
  TString mesi_cal = "";
  TString16 chiave = "";
  TString16 ditta  = "";
  int i, mese;
  bool continua;
  ditta << get_firm();
  
  if (_tipo_stampa == 1) //stampa di prova
    mese = _data_a.month();
  else 
    mese = _fino_a_mese;   
  
  if (_tipo_riepilogativo == ' ' || _tipo_riepilogativo == 'P')
  {
    if (_frequiva == 'T') //nella tabella LIM ho solo i mesi 3, 6, 9, 12
    {
      for (i=3; i<=mese; i+=3)
      {
        chiave = "";
        TString16 m (format("%02d", i));
        chiave << _annoes << m;
        lim.put("CODTAB", chiave);
        if (lim.read() == NOERR)
        { 
          if (! lim.get_bool("B0"))
            mesi_cal << itom(i) << "\n";
        }
        else mesi_cal << itom(i) << "\n";
      }
    }                
    if (_frequiva == 'M')
    {
      for (i=1 ; i<=mese; i++)
      {
        chiave = "";
        TString16 m (format("%02d", i));
        chiave << _annoes << m;
        lim.put("CODTAB", chiave);
        if (lim.read() == NOERR)
        {
          if (! lim.get_bool("B0"))
            mesi_cal << itom(i) << "\n"; 
        }
        else mesi_cal << itom(i) << "\n"; 
      } 
    }      
    if (mesi_cal.not_empty())
    {
      warning_box ("Ditta %s: la liquidazione da stampare sul registro %s relativa ai mesi di \n %s non e' stata ancora calcolata", (const char*)ditta, (const char*) _codreg, (const char *)mesi_cal);
      continua = yesno_box("Si desidera ugualmente proseguire?");
      if (!continua) return non_proseguire;
      continua = yesno_box("Si desidera proseguire con il calcolo e la stampa di liquidazione? \n (altrimenti si prosegue con la sola stampa di liquidazione)");
      if (!continua) return prosegui_stampa;
      return prosegui_cal_stampa;
    }       
  }
  else if (_tipo_riepilogativo == 'A')
    //if (_riep_liq)
    {
      chiave = "";
      chiave << _annoes << 13;
      lim.put("CODTAB", chiave);
      if (lim.read() == NOERR)
      {
        if (! lim.get_bool("B0"))
        {
          continua = yesno_box("Ditta %s: non eseguito calcolo liquidazione annuale da stampare sul registro %s. Si desidera ugualmente proseguire?", (const char*)ditta, (const char*) _codreg);
          if (!continua) return non_proseguire;
          continua = yesno_box("Si desidera proseguire con il calcolo e la stampa di liquidazione? \n (altrimenti si prosegue con la sola stampa di liquidazione)");
          if (!continua) return prosegui_stampa;
          return prosegui_cal_stampa;
        }
      }
      else
      {
        continua = yesno_box("Ditta %s: non eseguito calcolo liquidazione annuale da stampare sul registro %s. Si desidera ugualmente proseguire?", (const char*)ditta, (const char*) _codreg);
        if (!continua) return non_proseguire;
        continua = yesno_box("Si desidera proseguire con il calcolo e la stampa di liquidazione? \n (altrimenti si prosegue con la sola stampa di liquidazione)");
        if (!continua) return prosegui_stampa;
        return prosegui_cal_stampa;
      }    
    }  
  return B0_settato;   
}

//controlla che i movimenti con anno data di registrazione < dell'anno indicato a video siano stati gia' stampati in forma definitiva*/ 
//questo controllo viene fatto solo per stampa di bollato (non su libro unico)
bool CG4400_application::controlla_mov()
{
  TLocalisamfile mov (LF_MOV);
  bool ok = TRUE;
  byte tipo;
  TString16 ditta = "";
  TRecnotype rec = _tabreg->recno();
  for (mov.first(); !mov.eof(); mov.next())
  {
    TString16 reg = mov.get(MOV_REG);
    if (reg.empty()) continue; //non e' un movimento iva
    TDate datareg = mov.get_date(MOV_DATAREG);
    if (_stampa_tutti_i_registri)
      cerca_reg (reg, &tipo);
    if ( (_stampa_tutti_i_registri && (tipo == 1 || tipo == 2))
        || (!_stampa_tutti_i_registri && reg == _codreg) )
    {    
      bool stampato = mov.get_bool(MOV_REGST);
      if ( datareg.year() < _annoes )
      {  
        long numreg   = mov.get_long(MOV_NUMREG);
        if (!stampato)
          ok = FALSE;
      }
    }
  }
  _tabreg->readat(rec);
  return ok;
}

bool CG4400_application::cerca_libro_gio(TString& datas, bool* good)
{
  TString app(4);
  app = format("%04d", _annoes);
  
  *good = TRUE;
  TRecnotype rec = _tabreg->recno();
  _tabreg->zero();
  _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
    {    
      const TDate& data = _tabreg->get_date("D3");
      if (data > _data_a)
      {
//        datas = format("%02/%02d/%4d", data.day(), data.month(), data.year());
        datas = data;          // Meglio cosi'
        *good = FALSE;
        return FALSE;
      }
      return TRUE;
    }
  }
  _tabreg->readat(rec);
  //return TRUE;
  return FALSE;
}

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

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++;
  
  _stampa = stampa_totali_finali();
  if (_stampa)
  {
    set_row(++r, "Tipo documento@54gTotale 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%s",  (const char*) doc._descrdoc);
      set_row(rr, "@54g%r", &doc._totdoc); 
    }
    _doc_array.destroy(); 
  } 
  
  if (rr > 0)
    rr++;
  else
    rr = r;
  
  if (_stampa && _tipo_reg == 2)
  {
    if (_stampa_cred_pre && _mese_credito==0 && _credito > ZERO)
    {
      set_row (++rr, "** CREDITO INIZIO ANNO @39g%r", &_credito);
      rr++;
    }
  }
  
  if (_esiste_riga_iva && _stampa)
  {
    if (_tipo_reg == 1 && _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 != 1)
    {
      if (_tipo_reg == 1 && _corrispettivi)
        set_row(rr,"@84g----------- P R O G R E S S I V I --------------");
      else
        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 != 1)
        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 != 1)
      {  
        if (_corrispettivi)
          set_row(rr, "@94gV E N D I T E@118gCORRISPETTIVI"); 
        else
          set_row(rr, "@93gV E N D I T E");
      }  
    }      
    rr++;
    set_row(rr, "iva  Descrizione@30gImponibile@49gImposta");
    if (_tipo_reg == 1 && _corrispettivi)
      set_row(rr, "@63gImporti lordi");
    if (_tipo_stampa != 1)
    {
      if (_tipo_reg == 1 && _corrispettivi)
        set_row(rr++, "@87gImponibile@107gImposta@118gImporti Lordi");
      else
        set_row(rr++, "@86gImponibile@106gImposta");
    }
    else rr++;
    rr++;
  }
  return rr;  
}  

//la stampa "tipi di indetraibilita'" viene fatta solo per gli acquisti 
int CG4400_application::stampa_acquisti(int row)
{
  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 = ZERO;
  
  _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 != 1)
        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);
            set_row(++rw, "TOTALE");
            if (tot_imponib != ZERO)
              set_row(rw, "@25g%r", &tot_imponib);
            if (tot_imposta != ZERO)
              set_row(rw, "@41g%r", &tot_imposta);

            if (_tipo_stampa != 1)
            {
              //set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
              if (tot_imponibp != ZERO)
                set_row(rw, "@81g%r", &tot_imponibp);
              if (tot_impostap != ZERO)
                set_row(rw, "@98g%r", &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 != 1)
                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);
            set_row(++rw, "TOTALE");
            if (tot_imponib != ZERO)
              set_row(rw, "@25g%r", &tot_imponib);
            if (tot_imposta != ZERO)
              set_row(rw, "@41g%r", &tot_imposta);
            if (_tipo_stampa != 1) 
            {
              //set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
              if (tot_imponibp != ZERO)
                set_row(rw, "@81g%r", &tot_imponibp);
              if (tot_impostap != ZERO)
                set_row(rw, "@98g%r", &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 != 1)
                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 (_iva_array.items() > 0)
    if (tdetprec == 9)
    {
      //set_row(++rw, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
      set_row(++rw, "TOTALE");
      if (tot_imponib != ZERO)
        set_row(rw, "@25g%r", &tot_imponib);
      if (tot_imposta != ZERO)
        set_row(rw, "@41g%r", &tot_imposta);
      if (_tipo_stampa != 1)
      {
        //set_row(rw, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
        if (tot_imponibp != ZERO)
          set_row(rw, "@81g%r", &tot_imponibp);
        if (tot_impostap != ZERO)
          set_row(rw, "@98g%r", &tot_impostap);
      }  
    }
  _iva_array.destroy(); 
  rw++;
  return rw;
}

void CG4400_application::set_page_tot_reg()
{
  int rr=0;
  
  rr = stampa_prospetto();
  
  if (_esiste_riga_iva && _stampa)
  {  
    real tot_imponib, tot_imposta, tot_lordo, tot_imponibp, tot_impostap, tot_lordop;
    tot_imponib = tot_imposta = tot_lordo = tot_imponibp = tot_impostap = tot_lordop = ZERO;
    
    _tot_iva_array.sort(compare_rows); //viene ordinato per codice iva
    
    for (int k = 0; k < _tot_iva_array.items(); k++)
    {
      TRiga& riga = (TRiga&)_tot_iva_array[k];
      //row = rr+k;
      set_row(rr, "%4s", (const char*)riga._codiva);
      TString80 descr = descr_iva(riga._codiva);
      set_row(rr, "@5g%-.21s",(const char*)descr);
      if (riga._imponibile != ZERO)
        set_row(rr, "@25g%r", &riga._imponibile);
      if (riga._imposta != ZERO)
        set_row(rr, "@41g%r", &riga._imposta);
      if (_tipo_reg == 1 && _corrispettivi)
        if (riga._implordo != ZERO)
          set_row(rr, "@61g%r", &riga._implordo);
      if (_tipo_stampa != 1)
      {   
        if (riga._imponibilep != ZERO)
          set_row(rr, "@81g%r", &riga._imponibilep);
        if (riga._impostap != ZERO)
          set_row(rr, "@98g%r", &riga._impostap);
        if (_tipo_reg == 1 && _corrispettivi)
          if (riga._implordop != ZERO)
            set_row(rr, "@115g%r", &riga._implordop);    
      }
      rr++;  
      tot_imponib += riga._imponibile;
      tot_imposta += riga._imposta;
      tot_lordo   += riga._implordo;
      tot_imponibp+= riga._imponibilep;
      tot_impostap+= riga._impostap;
      tot_lordop  += riga._implordop;
    }  
    _tot_iva_array.destroy();
    rr++;
    //set_row(rr, "TOTALE@25g%r@41g%r", &tot_imponib, &tot_imposta);
    set_row(rr, "TOTALE");
    if (tot_imponib != ZERO)
      set_row(rr, "@25g%r", &tot_imponib);
    if (tot_imposta != ZERO)
      set_row(rr, "@41g%r", &tot_imposta);
    if (_tipo_reg == 1 && _corrispettivi)
      if (tot_lordo != ZERO) 
        set_row(rr, "@61g%r", &tot_lordo);
    if (_tipo_stampa != 1)
    {
      //set_row(rr, "@81g%r@98g%r", &tot_imponibp, &tot_impostap);
      if (tot_imponibp != ZERO)
        set_row(rr, "@81g%r", &tot_imponibp);
      if (tot_impostap != ZERO)
        set_row(rr, "@98g%r", &tot_impostap);   
      if (_tipo_reg == 1 && _corrispettivi) 
        if (tot_lordop != ZERO)
          set_row(rr, "@115g%r", &tot_lordop);
    } 
    
    if (_tipo_reg == 2) rr = stampa_acquisti(rr); 
  }
  if (_tipo_reg == 2 && _tipo_stampa != 1)
    stampa_plafonds(rr);
}

void CG4400_application::stampa_plafonds(int r)
{
  TTable pla ("%PLA");  
  TTable ppa ("PPA"); 
  TString80 chiave;
  int num;
  real r1, r2, r3;
  
  r1 = r2 = r3 = ZERO;
  
  if (_tipo_stampa == 3)
    num = _fino_a_mese;
  if ( _tipo_stampa == 2 || _tipo_stampa == 4 )  
    num = _datareg.month();
  
  TString16 nm (format("%02d", num));
  
  // forza il tipoatt a 1
  //char buf[10]; strcpy(buf,_codatt);
  //buf[strlen(buf) - 1] = '1';
  
  chiave = "";
  //chiave << _annoes << buf;
  
  chiave.format("%05ld", get_firm());
  chiave << _annoes;
  chiave << _codatt << "1";
  pla.put("CODTAB", chiave);
  
  if (pla.read() == NOERR)
  {
    r1 = pla.get_real("R5"); //totali esp. art.8
    r2 = pla.get_real("R6"); //totali esp. art.8 bis
    r3 = pla.get_real("R7"); //totali esp. art 9
  }
  
  if (r1 > ZERO || r2 > ZERO || r3 > ZERO)
  {
    set_row(++r, "QUADRO RELATIVO ALLA DISPONIBILITA' E UTILIZZAZIONE MENSILE DEI PLAFONDS");
    r++;
    TString mese(9);
    mese = itom(num);
    mese.right_just();
    set_row(++r, "%s", (const char*) mese);
    set_row(++r, ""); 
    r++;
  }
  else return;
  
  if (r1 > ZERO) 
  {
    real r8 = ZERO;
    r8 = stampa_valori_plafonds(r1, num, ppa, "1");
    //if (r8 > ZERO)
    if (!r8.is_zero())
    {
      real pri = ZERO;
      real pre = ZERO;
      chiave = "";
      chiave << _annoes << _codatt << "1" << nm << "1";
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        pri = ppa.get_real("R0"); 
        pre = ppa.get_real("R1");
      }
      chiave = "";
      chiave << _annoes << _codatt << "2" << nm << "1";
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        pri += ppa.get_real("R0"); 
        pre += ppa.get_real("R1");
      }
      real x = r8 - pri - pre;
      set_row(r++, "ART. 8 1° comma lettere a-b    Disponibile  %r", &r8);
      set_row(r++, "Utilizzato all'interno@44g%r", &pri);
      set_row(r++, "Utilizzato per l'importazione@44g%r  riporto %r", &pre, &x);
    }
  }
  
  if (r2 > ZERO) 
  {
    real r8b = ZERO;
    r8b = stampa_valori_plafonds(r2, num, ppa, "2");
    //if (r8b > ZERO)
    if (!r8b.is_zero())
    {
      real pri = ZERO;
      real pre = ZERO;
      chiave = ""; 
      chiave << _annoes << _codatt << "1" << nm << "2";
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        pri = ppa.get_real("R0"); 
        pre = ppa.get_real("R1");
      } 
      chiave = "";
      chiave << _annoes << _codatt << "2" << nm << "2";
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        pri += ppa.get_real("R0"); 
        pre += ppa.get_real("R1");
      }
      real x = r8b - pri - pre;
      r++;
      set_row(r++, "ART. 8 bis 1° comma            Disponibile  %r", &r8b);
      set_row(r++, "Utilizzato all'interno@44g%r", &pri);
      set_row(r++, "Utilizzato per l'importazione@44g%r  riporto %r", &pre, &x);
    }
  }
  
  if (r3 > ZERO) 
  {
    real r9 = ZERO;
    r9 = stampa_valori_plafonds(r3, num, ppa, "3");
    //if (r9 > ZERO)
    if (!r9.is_zero())
    {
      real pri = ZERO;
      real pre = ZERO;
      chiave = "";
      chiave << _annoes << _codatt << "1" << nm << "3";
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        pri = ppa.get_real("R0"); 
        pre = ppa.get_real("R1");
      }
      chiave = "";
      chiave << _annoes << _codatt << "2" << nm << "3";
      ppa.put("CODTAB", chiave);                    
      if (ppa.read() == NOERR)
      {
        pri += ppa.get_real("R0"); 
        pre += ppa.get_real("R1");
      }
      real x = r9 - pri - pre;
      r++;
      set_row(r++, "ART. 9 1° comma                Disponibile  %r", &r9);
      set_row(r++, "Utilizzato all'interno@44g%r", &pri);
      set_row(r++, "Utilizzato per l'importazione@44g%r  riporto %r", &pre, &x);
    }
  }  
}

real CG4400_application::stampa_valori_plafonds(const real& r1, const int mese, TTable& ppa, const char* tipo)
{ 
  real r, si8, se8;
  TString80 chiave;
  int i;
  
  r = r1;
  si8 = se8 = ZERO;
  if (mese > 1)
  {
    for (i=1; i<mese; i++)
    {
      chiave = "";
      TString16 m (format("%02d", i));
      chiave << _annoes << _codatt << "1" << m << tipo;
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        si8 += ppa.get_real("R0");
        se8 += ppa.get_real("R1");
      }
      chiave = "";
      chiave << _annoes << _codatt << "2" << m << tipo;
      ppa.put("CODTAB", chiave);
      if (ppa.read() == NOERR)
      {
        si8 += ppa.get_real("R0");
        se8 += ppa.get_real("R1");
      }  
    }
    r = r1 - si8 - se8;
  }
  return r;
}     

bool CG4400_application::compila_reg(const TMask& m)
{       
  int anno;
  TString16 codtab = ""; 
  TString16 cod_lib_un;
  TDate sca_vid;
  
  _tipo_stampa = m.get_int(TIPO_STAMPA);
  if (_tipo_stampa == 3)  //stampa su libro unico di studio
    _codreg = m.get(CODICE_LIBRO_IVA);
  else if (_tipo_stampa == 1) //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) 
      {
        if (_tipo_stampa != 3)  //per il libro unico e' gia' stato controllato nell'handler
          warning_box("Non esistono registri IVA della Ditta %ld per l'anno %d", 
                      _ditta, _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)
    {
      if (_tipo_stampa != 3)
        warning_box("Il registro IVA specificato non esiste nella \n Ditta %ld", _ditta);
      return FALSE;
    }
    else
    {
      _tipo_reg = _tabreg->get_int("I0");
      if (_tipo_reg == 1 || _tipo_reg == 2) //registro iva
      {
        cod_lib_un = _tabreg->get("S6"); 
        sca_vid    = _tabreg->get_date("D1");
        if (_tipo_stampa != 1) 
          _u_data = _tabreg->get_date ("D3");
        if ( _tipo_stampa == 2 || _tipo_stampa == 4 )
        {
          if (cod_lib_un.not_empty())
          {
            warning_box ("Ditta %ld: sul registro non deve essere indicato il codice del libro unico", _ditta);
            return FALSE;
          }  
          if (sca_vid.ok())
            if (sca_vid.month() < _fino_a_mese)
            {
              warning_box ("Ditta %ld: il mese della data scadenza vidimazione riportata sul registro non deve essere inferiore al mese indicato", _ditta);
              return FALSE;
            }
          if (_u_data.ok())
            if (_data_a < _u_data)
            {
//              TString16 datas = format("%02d/%02d/%4d", _u_data.day(), _u_data.month(), _u_data.year());
//              warning_box ("Ditta %ld: la data specificata non deve essere inferiore al %s (ultima data di stampa specificata sul registro)", _ditta, (const char*)datas);     
//              return FALSE;
              return warning_box ("Ditta %ld: la data specificata non deve essere inferiore al %s (ultima data di stampa specificata sul registro)", _ditta, (const char*)_u_data.string());    
            }
          if (_tipo_stampa == 4) //stampa con riferimenti al libro giornale
          {
            TString16 datas; 
            bool good;
            bool ok = cerca_libro_gio(datas,&good);
            if (!ok)
            {
              if (!good)
                warning_box ("Ditta %ld: la data indicata non deve essere superiore al %s (ultima data di stampa del libro giornale)", _ditta, (const char*)datas);
              return FALSE;
            }  
          } 
        }
        _pagine_stampate = _tabreg->get_long("I1");
        _numini          = _pagine_stampate;
        _corrispettivi   = _tabreg->get_bool("B0");
        _sosp_imposta    = _tabreg->get_bool("B1");
        _liquidazione    = _tabreg->get_bool("B7");
        _riep_liq        = _tabreg->get_bool("B6");
        _stampa_cred_pre = _tabreg->get_bool("B4");
        _stampa_ind_ditta = _tabreg->get_bool("B9");
        _stampa_ind_comp  = _tabreg->get_bool("B5");
        _cod_un_loc       = _tabreg->get_int ("I7");
        _mese_credito     = _tabreg->get_int ("I8"); //campo nascosto sulla tabella dei registri: mese di stampa credito anno precedente
        _mese_ultima_liq  = _tabreg->get_int ("I4");
        _codatt           = _tabreg->get("S8");
        _tipoatt          = tipo_attivita(); 
        _attivita         = desc_attivita();
        _desc_lib         = _tabreg->get ("S0");
      }
      else 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  = "";
    _esiste_riga_iva = FALSE;
    _auto_intraf = FALSE;
    _intesta_liq = 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, riga = 0;
    bool intra;
    TString80 comune, prov, comcf, capcf, civcf;
    TString80 viacf;
    TString ragsoc;
    TString tipo_op = "";

    TLocalisamfile& mov  = _cur->file(LF_MOV);
    TLocalisamfile& caus = _cur->file(LF_CAUSALI);
    
    _datareg = mov.get_date(MOV_DATAREG);
    
    if (_tipo_stampa != 3 && _liquidazione)
    {
      int da;
      if (_tipo_stampa == 1)
        da = _data_da.month();
      else da = 1;  
      int a = _datareg.month();
      for (int m = da; m < a; m++)
      {
        if (!_st_liq[m])
          if (stampo_liquidazione(m))
          {
//          _datareg = format("01/%02d/%4d", m, _annoes); //serve per la preprocess_header (intestazione per la stampa liquidazione)
            _datareg = TDate(1, m, _annoes); // Meglio cosi'
            TFilename t;
            t.temp("reg");    
            if (_scelta == B0_settato || _scelta == prosegui_stampa)
            {
              if (_tipo_stampa == 1)
                send_message('S',t, m); 
              else send_message('s',t, m);
            }
            else //_scelta == prosegui_cal_stampa
            {
              if (_tipo_stampa == 1)
                send_message('L', t, m);  
              else send_message('l', t, m);
            }
            //TString80 nomef; nomef = t.path(); nomef << "\\" << t.name();
            //if (fexist(nomef))
            if (fexist(t))
            {  
              _intesta_liq = TRUE; 
              //printer().footerlen(0);
              if (!_mov_empty) printer().formfeed();
              merge_export_file(t,FALSE,TRUE); 
              _intesta_liq = FALSE; 
              reset_print();
              remove(t);
            }  
          }
        _st_liq[m] = TRUE;
      }
    }
    
    _datareg = mov.get_date(MOV_DATAREG);
    _mov_empty = FALSE;

    if ( _datareg.month() != _dataregp.month() && _dataregp.ok() )
    {
      _auto_intraf = FALSE;  
      printer().formfeed();
      //printer().footerlen(5); //devo rimetterlo cosi'
    }
    
    _dataregp = _datareg;

    TDate     datadoc  = mov.get_date(MOV_DATADOC);
    long      numreg   = mov.get_long(MOV_NUMREG);
    long      protiva  = mov.get_long(MOV_PROTIVA);
    long      uprotiva = mov.get_long(MOV_UPROTIVA);
    real      totdoc   = mov.get_real(MOV_TOTDOC);
    TString16 numdoc   = mov.get(MOV_NUMDOC);
    char      tipocf   = mov.get(MOV_TIPO)[0];
    TString16 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);
    TString16 codval   = mov.get(MOV_CODVALI);  
    real      corrval  = mov.get_real(MOV_CORRVALUTA);
    //bool      intra    = caus.get_bool(CAU_INTRACOM); //da prendere sul movimento 
    bool      autof    = caus.get_bool(CAU_AUTOFATT);
    TString80 descrcau = caus.get(CAU_DESCR);
    
    if (_cur->pos() == 0)
      _uprotivap = uprotiva ? uprotiva : protiva;
    
    //aggiornamento di mov
    if (_tipo_stampa != 1)
      if (!stampato)
      {
        mov.put(MOV_REGST,TRUE);
        mov.rewrite();
      }      
    
    if (codcf == 0l)
      ragsoc = descrcau;
    else
    {
      if (ocfpi.trim().empty())
      {
        TRectype dep = ricerca_cf(tipocf, codcf);
        ragsoc = dep.get (CLI_RAGSOC);
        viacf  = dep.get (CLI_INDCF);
        civcf  = dep.get (CLI_CIVCF);
        capcf  = dep.get (CLI_CAPCF);
        comcf  = dep.get (CLI_COMCF);
        char tipoa = dep.get_char(CLI_TIPOAPER);
        if (tipoa == 'F')
        {
          TString80 cognome, nome;
          cognome = ragsoc.mid(0,30);
          nome    = ragsoc.mid(30,20);
          cognome.trim(); nome.trim();
          ragsoc = cognome;
          ragsoc << " " << nome;
        }
      }
      else
      {
        TRectype dep = ricerca_occ(ocfpi);
        ragsoc = dep.get (OCC_RAGSOC);
        viacf  = dep.get (OCC_INDIR);
        civcf  = dep.get (OCC_CIV);
        capcf  = dep.get (OCC_CAP);
        comcf  = dep.get (OCC_COM);
      }
      TRectype com = look_comuni(comcf);
      comune       = com.get(COM_DENCOM);
      prov         = com.get(COM_PROVCOM);  
    }
    
    _tipodoc   = mov.get(MOV_TIPODOC);
    _descr_doc = descr_doc();
    TString app(datadoc.string(brief, '/'));
    
    if (stampa_totali_finali())
      _doc_array.add_riga(_tipodoc,_descr_doc,totdoc); 

    //setto le righe di stampa
    _r = 1;
    if (!_stampa_data_reg) 
      set_row(_r, "%s", (const char* ) _datareg.string(brief, '/'));
    set_row(_r, "@9g%5ld", protiva);
    if (datadoc.ok())
      set_row(_r, "@15g%s", (const char*) app);
    set_row(_r, "@24g%s",   (const char*) numdoc);
    if (codcf != 0l)
      set_row(_r, "@31g%6ld", codcf);
    *_desc27 = (const char*) ragsoc;  
    //set_row(_r, "@38g#a", _desc25);
    set_row(_r, "@68g%2s",  (const char*) _tipodoc);
    if (_stampa_width == 132)
      set_row(_r, "@70g%r", &totdoc);
    else set_row(_r, "@78g%r", &totdoc);

    if (_tipo_stampa == 1)    //in caso di stampa di prova
      if (! (_tipo_reg == 1 && _corrispettivi)) //e se non si tratta di registro vendite corrispettivi
        if (! (_cur->pos()==0)) //il primo movimento non va controllato
        {
          if (protiva != _uprotivap + 1)
          {
            set_row(_r+1, "@2g*** NUM.PROT.FUORI SEQUENZA");
            riga = _r+2;
          }
          _uprotivap = uprotiva ? uprotiva : protiva;
        }
    
    const char* r;
    int i = 1;
    while ((r = _desc27->get()) != NULL)
    {
      set_row (i, "@38g%s", r);
      i++; 
    }
    if (i > riga) riga = i; 
    
    if (codcf != 0l && _stampa_ind_comp)
    {
      //set_row(_r, "@38g%-.27s", (const char*)ragsoc);
      if (viacf.not_empty())  //se la via non e' vuota non puo' essere vuoto il comune
      {  
        set_row (/*_r+1*/ i++, "@38g%-.23s %-3s",(const char *)viacf, (const char *)civcf);
        set_row (/*_r+2*/ i++, "@38g%s %-.21s", (const char *)capcf, (const char *)comune);
        riga = /*_r+3*/ i;
      }  
      else if (comune.not_empty())
      {
        set_row (/*_r+1*/ i++, "@38g%s %-.21s", (const char *)capcf, (const char *)comune);
        riga = /*_r+2*/ i;  
      }  
    }
    
    _nrec = riga_rmoviva();   
    if (_nrec > 0)
    {
      _esiste_riga_iva = TRUE;
      for (int j = 0; j < _riga_rmi.items(); j++)
      {
        TRigaiva& riga = (TRigaiva&)_riga_rmi[j];
        rr = _r+j;
        intra = riga._intra;
        if (_stampa_width == 132)
        {
          set_row(rr, "@85g%r",   &riga._imponibile);
          set_row(rr, "@101g%4s",(const char*)riga._codiva);
          if (_tipo_reg == 2)
            set_row(rr, "@106g%d", riga._tipodet);
          set_row(rr, "@107g%r",  &riga._imposta);
          set_row(rr, "@123g%d",  riga._tipocr);
          if (_tipoatt == "E" && _tipo_reg != 2)
            set_row(rr, "@125g%d", riga._tipoatt);
          if (_tipo_stampa == 4) //stampa con riferimento al libro giornale
            set_row(rr, "@126g%5ld", numgio); 
        }
        else  //stampa a 198
        {
          set_row(rr, "@93g%r",   &riga._imponibile);
          set_row(rr, "@109g%4s",(const char*)riga._codiva);
          if (_tipo_reg == 2)
            set_row(rr, "@114g%d", riga._tipodet);
          set_row(rr, "@116g%r",  &riga._imposta);
          if (_tipoatt == "E" && _tipo_reg != 2)
            set_row(rr, "@132g%d", riga._tipoatt);
          set_row(rr, "@134g%d",  riga._tipocr);
          if (_tipo_stampa == 4) //stampa con riferimento al libro giornale
            set_row(rr, "@136g%7ld", numgio);
        }    
      } 
      _riga_rmi.destroy();
    }
    
    if ( intra && autof)
    {
      _auto_intraf = TRUE;
      tipo_op = "3";
    }  
    else if (intra) 
      tipo_op = "1";
    else if (autof)
      tipo_op = "2";

    set_row(_r, "@66g%s",   (const char*) tipo_op);
    
    if (_tipo_stampa == 1) //stampa di prova
    {
      if (_stampa_width == 132)
      {  
        set_row(_r, "@126g%5ld", numreg);
        if (stampato)
          set_row(_r, "@131g*"); //solo in stampa di prova!
      }
      else //198 
      {
        set_row(_r, "@136g%7ld", numreg); 
        if (stampato)
          set_row(_r, "@144g*");
      }  
    }
    if (_tipo_stampa == 4 && _stampa_width == 198)
    {
      TLocalisamfile rmoviva (LF_RMOVIVA);
      rmoviva.zero();
      rmoviva.put(RMI_NUMREG,numreg);
      TRectype rec(rmoviva.curr());
      rmoviva.read(_isgteq);     
      for ( ; !rmoviva.eof(); rmoviva.next())
      {
        if (rmoviva.curr() != rec) break;

        int  gruppo = rmoviva.get_int("GRUPPO");
        int  conto  = rmoviva.get_int("CONTO");
        long sottoc = rmoviva.get_long("SOTTOCONTO");
        TConto tc (gruppo,conto,sottoc);
        TString80 descr = tc.descrizione();
        set_row(_r, "@144g%3d %3d %6d", gruppo, conto, sottoc);
        set_row(_r, "@159g%-.39s", (const char*) descr); 
        break;
      }
    }   
    
    if (riga <= rr) riga = ++rr;
    
    if (corrval != ZERO)
    {
      TString vall (corrval.string("###.###.###.###,@@"));
      set_row(riga, "@24gCodice valuta %-3s  Corrispettivo in valuta %s", (const char*) codval, (const char*) vall);
    }
  }
  return TRUE;
}

void CG4400_application::scrivi_reg(const TDate& data)
{
  TString16 codtab; 
  TTable Tabreg ("REG");
  
  codtab << _annoes << _codreg;
  Tabreg.zero();
  Tabreg.put("CODTAB", codtab);  
  if (Tabreg.read() == NOERR)
  {
    const TDate d = Tabreg.get_date("D3");
    if (!_mov_empty) //cioe' se e' stata stampata almeno una pagina
    {
      TDate ultima_data(data); 
      ultima_data.set_end_month();       // Meglio cosi'
      
      if (ultima_data > d) 
        Tabreg.put("D3", ultima_data);
    }  
    else if (_data_a > d) 
      Tabreg.put("D3", _data_a);

    if (_tipo_reg == 2 && _stampa_cred_pre)
      if (_mese_credito == 0 && _credito > ZERO)
        if (_mov_empty) 
          Tabreg.put("I8", (long)_fino_a_mese);
        else Tabreg.put("I8", (long)_datareg.month());

    Tabreg.rewrite();
  }  
  
  if (_tipo_stampa == 3)
  {
    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.rewrite();
    } 
  }
}

void CG4400_application::aggiorna_reg(const bool aggiorna_vidi)
{
  TString16 codtab; 
  TTable Tabreg ("REG");
  TLocalisamfile IndBil (LF_INDLIB);
  
  codtab << _annoes << _codreg;
  Tabreg.zero();
  Tabreg.put("CODTAB", codtab);  
  if (Tabreg.read() == NOERR)
  {
    TDate d = Tabreg.get_date("D3");
    if (!_mov_empty) //cioe' se e' stata stampata almeno una pagina
    {                //controllo inutile visto che e' chiamata nella
                     //preprocess_header
      TDate ultima_data(_datareg); 
      ultima_data.set_end_month();       

      if (ultima_data > d) 
        Tabreg.put("D3", ultima_data);
    }  
    else if (_data_a > d) 
      Tabreg.put("D3", _data_a);

    Tabreg.put("I1", _pagine_stampate);
    
    if (_intesta_liq)
      if (_tipo_riepilogativo == 'A')
        Tabreg.put("I4", 13L);
      else Tabreg.put("I4", (long)_datareg.month());

    if (_tipo_reg == 2 && _stampa_cred_pre)
      if (_mese_credito == 0 && _credito > ZERO)
        if (_mov_empty) 
          Tabreg.put("I8", (long)_fino_a_mese);
        else Tabreg.put("I8", (long)_datareg.month());
    
    Tabreg.rewrite();
  }

  if (_tipo_stampa == 3) //stampa su libro unico

    // sul file indlib (indice libro unico) devo generare una riga per ogni 
    // registro stampato (ricordarsi che la stampa su libro unico deve 
    // avvenire mese per mese!) 
    // inoltre non posso stampare due volte lo stesso mese perche' la stampa 
    // avviene a fine mese

  {       
    long numero_riga = 1L;
    if (!aggiorna_vidi)
    {                        
      bool trovato = FALSE;
      //long ditta = get_firm();
      
      IndBil.zero(); 

      TRectype nuovo   (IndBil.curr());

      IndBil.put("ANNO", _annoes);
      IndBil.put("CODLIB", _codlib);
      TRectype rec (IndBil.curr());
      
      for (IndBil.read(_isgteq); !IndBil.eof(); IndBil.next())
      { 
        if (IndBil.curr() != rec) break;
        
        int annoreg = IndBil.get_int("ANNOREG");
        int mesereg = IndBil.get_int("MESEREG");
        long cditta = IndBil.get_long("CODDITTA");
        TString16 codreg = IndBil.get("CODREG");
        TString16 codvid = IndBil.get("CODVID");
        if (_annoes == annoreg && _fino_a_mese == mesereg
            && _ditta == cditta && codreg == _codreg && _codice_vidi == codvid)
        {    
          trovato = TRUE;
          numero_riga = IndBil.get_long("NUMREG");
          break;                              
        }
        else numero_riga = IndBil.get_long("NUMREG") + 1;        
        // cosi' mi posiziono su quel mese (altrimenti rischio di generare 
        // due righe per lo stesso mese e registro => la stampa di vidimazione 
        // mi sballa tutta!!!
      }        
      nuovo.put("ANNO", _annoes);
      nuovo.put("CODLIB", _codlib);
      nuovo.put("NUMREG", numero_riga);
      
      nuovo.put("ANNOREG", _annoes);
      nuovo.put("MESEREG", _fino_a_mese);  // su libro unico ho un solo mese in gioco!
      nuovo.put("PAGINI", _primast + 1);   // numero iniziale pagina libro unico
      nuovo.put("PAGFIN", _u_stampata);    // numero finale pagina libro unico
      nuovo.put("CODDITTA", _ditta);
      nuovo.put("CODREG", _codreg);
      nuovo.put("CODVID", _codice_vidi);
      nuovo.put("PAGINIUT", _numini + 1);
      nuovo.put("PAGFINUT", _pagine_stampate);
      
      if (!trovato)
        IndBil.write(nuovo);                                              
      else IndBil.rewrite(nuovo);                                              
    } 
    //_primast = _u_stampata; //per la numerazione dei registri successivi
    aggiorna_lib();
  } 
}

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();
  }
}

bool CG4400_application::stampo_liquidazione(int mese)
{
  //test tradotti alla lettera da AS/400
  //assolutamente incongruenti !!!
  if (_tipo_stampa == 1)
  {
    if ( (_frequiva == 'T' && (mese == 3 || mese == 6 || mese == 9 || mese == 12)) 
        || _frequiva != 'T' || (mese == 12 && _tipo_riepilogativo == 'A') )    
      return TRUE;
  }
  else
  {
    if ( (_frequiva == 'T' && (mese == 3 || mese == 6 || mese == 9 || mese == 12)) 
        || _frequiva != 'T' || (mese == 12 && _tipo_riepilogativo == 'A') )    
      if ( (mese == 12 && _tipo_riepilogativo == 'A' && _mese_ultima_liq != 13) 
          || (mese != 12 && mese > _mese_ultima_liq)
          || (mese == 12 && _tipo_riepilogativo != 'A' && mese > _mese_ultima_liq) )
        return TRUE;
  }                 
  return FALSE;            
}

void CG4400_application::stampa_vidi()
{
  TLocalisamfile IndBil (LF_INDLIB);
  TTable    TabVid ("%VID");
  TString16 codreg;
  TString16 vid;
  long      ditta, pagfin, pagfinut;
  int       mese;
  TPrintrow row;
  
  _ok_vidi = FALSE;
  
  if (!printer().isopen())
    printer().open();
  
  IndBil.zero();
  IndBil.put("ANNO", _annoes);
  IndBil.put("CODLIB", _codlib);
  TRectype rec (IndBil.curr());
  IndBil.read (_isgteq);
  for (; !IndBil.eof(); IndBil.next())
  { 
    if (IndBil.curr() != rec) break;
    ditta  = IndBil.get_long("CODDITTA");
    codreg = IndBil.get("CODREG");
    if (ditta == _ditta && codreg == _codreg)
    {
      if (!_ok_vidi)
      {
        ++_u_stampata;
        ++_pagine_stampate;
        _ok_vidi = TRUE;
      }
      mese = IndBil.get_int("MESEREG");
      pagfin = IndBil.get_long("PAGFIN");
      pagfinut = IndBil.get_long("PAGFINUT");
      if (mese == 12)
      {
        ++pagfin;
        ++pagfinut; 
        TRectype nuovo (IndBil.curr());
        nuovo.put("PAGFIN", pagfin);
        nuovo.put("PAGFINUT", pagfinut);
        IndBil.rewrite(nuovo);
      }
      row.reset();
      row.put(format("%s", itom(mese)), 0);
      row.put(format("%5ld", IndBil.get_long("PAGINI")), 10);
      row.put(format("%5ld", pagfin), 17);
      row.put(format("%5ld", IndBil.get_long("PAGINIUT")), 25);
      row.put(format("%5ld", pagfinut), 32);
      vid  = IndBil.get("CODVID");
      TabVid.zero();
      TabVid.put("CODTAB", vid);
      if (TabVid.read() == NOERR)
      {
        row.put(format("%-.32s", (const char*)TabVid.get("S0")), 39);
        row.put(format("%7d",TabVid.get_long("I0")), 71);
        row.put(format("%7d",TabVid.get_long("I1")), 79);
        row.put(format("%7d",TabVid.get_long("I2")), 87);
        TDate d(TabVid.get_long("D0"));
        row.put(format("%s", (const char*)d.string()), 95);
        row.put(format("%-.26s", (const char*)TabVid.get("S1")), 106);
      }   
      printer().print(row);
    } 
  }
  printer().close();
}

void CG4400_application::liq_b0_settato()
{
  TFilename f;
  f.temp("rg");
  if (_tipo_stampa == 1)
    send_message('S',f, _datareg.month()); 
  else send_message('s',f, _datareg.month()); 
  //TString80 nomef; 
  //nomef = f.path(); nomef << "\\" << f.name();
  //if (fexist(nomef))
  if (fexist(f))
  {
    printer().formfeed();
    _intesta_liq = TRUE;
    //printer().footerlen(0); 
    merge_export_file(f,FALSE,TRUE);
    _intesta_liq = FALSE;
    remove(f);
  } 
}

void CG4400_application::liq_other_case()
{
  if (_scelta == prosegui_cal_stampa)
  {
    if (stampo_liquidazione(_datareg.month()))
    {
      _t.temp("reg");    
      if (_tipo_stampa == 1)
        send_message('L', _t, _datareg.month());  
      else send_message('l', _t, _datareg.month());
    }
    else //se chiamo la liquidazione con L o l mi calcola anche i progressivi
      if (_tipo_stampa != 1)
      {
        TFilename app;
        app.temp();
        send_message('C', app, _datareg.month()); 
      }  
  }
  if (_scelta == prosegui_stampa) 
  {
    if (stampo_liquidazione(_datareg.month()))
    {
      _t.temp("reg");    
      if (_tipo_stampa == 1)
        send_message('S', _t, _datareg.month());  
      else send_message('s', _t, _datareg.month()); 
    }  
    if (_tipo_stampa != 1) //in stampa di prova i progressivi me li calcolo io!!! 
    {                      //Why???
      TFilename app;
      app.temp();
      send_message('C', app, _datareg.month());
    } 
  }
  if (_scelta == no_liquidazione && _tipo_stampa != 1)
  {
    TFilename app;
    app.temp();
    send_message('C', app, _datareg.month()); 
  }
}

print_action CG4400_application::postprocess_page (int file, int counter)
{
  if (file == LF_MOV)
  {   
    if (counter)  //dopo aver fatto un REPEAT_PAGE (cioe' dopo aver stampato le righe settate in set_page_tot_reg()), in pratica a rottura di mese o alla fine
    {
      reset_print(); 
      if (_liquidazione) 
        if (!_st_liq[_datareg.month()] && stampo_liquidazione(_datareg.month()))
        {
          _st_liq[_datareg.month()] = TRUE;
          if (_scelta == B0_settato)
            liq_b0_settato();
          if (_scelta == prosegui_stampa || _scelta == prosegui_cal_stampa)
          {  
            if (fexist(_t))
            {
              printer().formfeed();
              _intesta_liq = TRUE;
              //printer().footerlen(0);
              merge_export_file(_t,FALSE,TRUE);
              _intesta_liq = FALSE;
              remove(_t);
            }
          }   
        }
      //modifica del 26/07/1995
      TRecnotype pos   = _cur->pos();
      long       items = _cur->items();
      if (pos == items-1) 
      { 
        if (_tipo_stampa != 3 && _liquidazione)  
          stampa_liq_mesi_succ(); 
        //09/11/1995
        if (_tipo_stampa != 1) 
        {
          int da = _datareg.month() + 1;
          int a  = _data_a.month();   
          for (int m=da; m<=a; m++)
          {
            TDate data(1, m, _annoes); 
            data.set_end_month(); 
            scrivi_reg(data);    
          }   
        }
        //fine  
      }    
      //fine modifica        
    } 
    if (!counter)
    {
      bool FINITO = FALSE;
      TRecnotype pos   = _cur->pos();
      long       items = _cur->items();
      
      FINITO = (pos == items-1);
      
      if ( FINITO )  
      {
        liq_other_case();
        if (_tipo_stampa != 1)
          calcola_progressivi();
        set_page_tot_reg();
        return REPEAT_PAGE;
      }
      else 
      {
        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())
        {
          liq_other_case();
          if (_tipo_stampa != 1)
            calcola_progressivi();
          set_page_tot_reg();
          return REPEAT_PAGE; 
        }
      }
    }
  }   
  return NEXT_PAGE;
}

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

  m.set_handler (TIPO_STAMPA, mask_tipo_stampa); 
  m.set_handler (DA_DATA,  mask_data);
  m.set_handler (A_DATA,   mask_data);
  m.set_handler (MESE,     mask_mese);
  m.set_handler (FINO_A_MESE, mask_mese);
  m.set_handler (CODICE_LIB_UN, mask_cod);
  m.set_handler (CODICE_LIBRO_IVA, mask_libun);
  m.set_handler (DLG_SELECT, mask_select);
  m.set_handler (F_ANNULLA,  mask_azzera);
  m.set_handler (A_CODICE,  to_ditt_handler);
  m.set_handler (DA_CODICE, fr_ditt_handler);
  m.set_handler (BUT_DTO,  to_butt_handler);
  m.set_handler (BUT_DFR,  fr_butt_handler);
  m.set_handler (ANNO, year_handler);
  
  m.field(F_SELECT).set(format("%ld",_selected.ones()));
  set_choice_limits(m);
  
  //printer().footerlen(5);
  set_real_picture("###.###.###.###");
  
  while (ok = set_ditte(m)) 
  {
    if (_selected.ones() > 0l)
    {
      _annoes      = m.get_int(ANNO);//in realta' e' l'anno IVA !!!
      _tipo_stampa = m.get_int(TIPO_STAMPA);
      _stampa_width = m.get_int(STAMPA_WIDTH);
      _stampa_len   = m.get_int(STAMPA_LEN);
      if (_stampa_width == 1)
        _stampa_width = 132;
      else _stampa_width = 198;
      if (_stampa_len != 0)
        printer().formlen(_stampa_len);
      //Se stampa di prova l'utente indica data_da e data_a
      if (_tipo_stampa == 1)                            
      {
        _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);
          _data_da = TDate(1, 1, _annoes);    // Meglio cosi'
        
        if (!_data_a.ok())
//          _data_a = format("31/12/%4d", _annoes);
          _data_a = TDate(31, 12, _annoes);    // Meglio cosi'
        
        const TDate d(31,12,_annoes);
        if (_data_a == d)
          _tipo_riepilogativo = m.get(TIPO_RIEPILOGATIVO)[0];
        else _tipo_riepilogativo = ' ';  
        printer().setdate(_data_stampa);
      }
      else   //stampe definitive
      {
        if ( (_tipo_stampa == 2) || (_tipo_stampa == 4) )
        {
          _fino_a_mese = m.get_int(FINO_A_MESE);
//          _data_da = format("01/01/%4d", _annoes);  //e non ultima data di stampa del registro (come invece verrebbe spontaneo di pensare)
          _data_da = TDate(1, 1, _annoes);        // Meglio cosi'
        }
        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);
          _rif_vid     = m.get_bool(RIF_VID);
          _primast     = _u_stampata;
//        _data_da     = format("01/%02d/%04d", _fino_a_mese, _annoes); 
          _data_da     = TDate(1, _fino_a_mese, _annoes);   // Meglio cosi'
        }     
        if (_fino_a_mese == 12)
        {
          giorni_del_mese = 31;
          _tipo_riepilogativo = m.get(TIPO_RIEPILOGATIVO)[0];
        }
        else
        {
          _tipo_riepilogativo = ' ';
//          TDate primo = format("01/%02d/%4d", _fino_a_mese+1, _annoes);
//          --primo;
          TDate primo(1, _fino_a_mese, _annoes); 
          primo.set_end_month();                    // Meglio cosi'
          
          giorni_del_mese = primo.day();
        }
//      _data_a=format("%02d/%02d/%4d",giorni_del_mese,_fino_a_mese,_annoes);
        _data_a = TDate(giorni_del_mese, _fino_a_mese, _annoes);  // Meglio cosi'
      }
      _stampa_data_reg = stampa_datareg();
      if (_tipo_stampa == 3)
        compila_lib();
      stampa_registri_IVA(m);
    }
    else 
    {
      warning_box("Nessuna ditta selezionata!");
      continue;
    } 
  }
  return FALSE;
}

bool CG4400_application::look_lia(long ditta)
{
  if (ditta == 0l) ditta = get_firm();
  
  TString16 y; y.format("%05ld%04d", ditta, _annoes);
  
  _tablia->zero();
  _tablia->put("CODTAB", y);
  _tablia->read();
  const bool ok = _tablia->good(); 
  if (ok) 
    _credito = _tablia->get_real("R0");
  else _credito = ZERO;  
  return ok;
}

void CG4400_application::look_reg()
{
  _liquidazione  = _tabreg->get_bool("B7");
  _riep_liq      = _tabreg->get_bool("B6");
  _corrispettivi = _tabreg->get_bool("B0");   
  _sosp_imposta  = _tabreg->get_bool("B1"); 
  _pagine_stampate  = _tabreg->get_long("I1");
  _numini           = _pagine_stampate;
  _cod_un_loc       = _tabreg->get_int("I7");
  _mese_ultima_liq  = _tabreg->get_int("I4");
  _mese_credito     = _tabreg->get_int("I8");
  _codatt           = _tabreg->get("S8");
  _tipoatt          = tipo_attivita();
  _attivita         = desc_attivita();
  _desc_lib         = _tabreg->get ("S0");
  _stampa_ind_ditta = _tabreg->get_bool ("B9");
  _stampa_ind_comp  = _tabreg->get_bool ("B5"); 
  _stampa_cred_pre  = _tabreg->get_bool ("B4");
}

void CG4400_application::clear_stliq() 
{
  for (int i=0; i <= 12; i++)
    _st_liq[i] = FALSE;
}

bool CG4400_application::setta_mask(long i)
{
  if (_stampa_mese == 13) _stampa_mese = 0;          
  if (_tipo_stampa == 2 || _tipo_stampa == 4)
  {
    TMask mb("cg4400b"); 
    mb.set(F_CODDITTA, _ditta);
    mb.set(F_RAGSOC, _ditte->row(i).get(2));
    mb.set(COD_LIB, _codreg);
    const char* m = "";
    m = format("%02d", _stampa_mese);
    mb.set(U_MESE, m);
    mb.set(U_PAGINA, _pagine_stampate);
    if (_u_data.ok())
      mb.set(U_DATA, _u_data.string());
    KEY tasto = mb.run();
    if (tasto != K_ENTER) return FALSE;  
    //correzione errore MI3213
    _pagine_stampate = mb.get_long(U_PAGINA);
    //
  }
  return TRUE;
}

void CG4400_application::no_movimenti()
{
  _mov_empty = TRUE;
  if (_liquidazione)
  {
    int da, a;
    //stampo la liquidazione per tutti i mesi fino a _fino_a_mese  
    if (_tipo_stampa == 2 || _tipo_stampa == 4)
      da = 1;
    if (_tipo_stampa == 3)
      da = _fino_a_mese;
    if (_tipo_stampa == 1) 
      da = _data_da.month();
    if (_tipo_stampa == 1)
      a = _data_a.month();
    else a = _fino_a_mese;      
    for (int m = da; m <= a; m++)
    {
      if (stampo_liquidazione(m))
      {
        if (! printer().isopen())
          printer().open();
        TFilename f;
        f.temp("rgp");
//        _datareg = format("01/%02d/%4d", m, _annoes); //serve per la preprocess_header
        _datareg = TDate(1, m, _annoes);  // Meglio cosi'
        
        if (_scelta == B0_settato || _scelta == prosegui_stampa)
        {
          if (_tipo_stampa == 1)
            send_message('S',f, m); 
          else send_message('s',f, m);
        }
        else //_scelta == prosegui_cal_stampa
        {
          if (_tipo_stampa == 1)
            send_message('L', f, m);  
          else send_message('l', f, m);
        }
        if (fexist(f))
        {  
          _intesta_liq = TRUE;
          //printer().footerlen(0);
          merge_export_file(f,FALSE,TRUE);
          printer().formfeed();
          _intesta_liq = FALSE;
          remove(f); 
        }  
      }
    }
    if (printer().isopen()) printer().close();
  }
  if (_tipo_stampa != 1) scrivi_reg(_datareg); //aggiorno il registro anche se non ho stampato proprio nulla per quel mese!        
}

bool CG4400_application::stampa_registri_IVA(const TMask& m) 
{
  bool ok = FALSE;
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_selected[(long)i])
    {
      bool msg = TRUE;
      _ditta       = _ditte->row(i).get_long(1);
      _frequiva    = _ditte->row(i).get_char(3);
      _intesta_liq = FALSE;
      _intesta_vidi = FALSE;
      _primast = _u_stampata; 
      _ok_vidi = FALSE;
      _stampa_mese = 13;
      
      TApplication::set_firm(_ditta);
      look_lia();
      ok = compila_reg(m);   
      if (!ok) continue;
      if (_tipo_stampa == 2 || _tipo_stampa == 4)
        if (!controlla_mov())
        {
          TApplication::set_firm(__firm);
          return fatal_box("Finire di stampare registri anno precedente");
        }
      if (!_stampa_tutti_i_registri)
      {
        _scelta = controlla_b0();
        _cur->set_filterfunction(filter_func);
        //modifica del 09/11/1995
        //la filter function viene chiamata quando posiziono il cursore
        //e' lei che determina _stampa_mese da settare in setta_mask
        (*_cur) = 0L; 
        //fine
        ok = setta_mask(i); 
        if (!ok) continue;
        if (_liquidazione)
        {
          if (_tipo_stampa == 2 || _tipo_stampa == 4)
            _size_header = _stampa_ind_ditta ? 3 : 2;
          else _size_header = 3;
          clear_stliq();
          _scelta = controlla_liquidazione();
          if (_scelta == non_proseguire) 
            return FALSE;
        } 
        //(*_cur) = 0L; 
        const long item = _cur->items();

        // 17.5.95 Leggo parametri di stampa del registro  
        TString16   config;
        const long  codditta = get_firm();   
        const char* reg      = (const char*)_codreg;
        config.format("REG%05ld%03s", codditta, reg);
        printer().read_configuration(config);
        
        //09/11/1995
        _mov_empty = TRUE;
        //fine
        
        if (item > 0l)
        {
          //modifica del 26/07/1995
          //_mov_empty = TRUE;
          //fine
          
          print(); 
          
          if (is_cancelled()) return FALSE;
          
          /***           
          if (_tipo_stampa != 3 && _liquidazione)  
            stampa_liq_mesi_succ();
          ***/  
        }
        //non ci sono movimenti da stampare nel periodo richiesto!
        else no_movimenti(); 

        if (_tipo_stampa == 3 && _rif_vid)
        { 
          _intesta_vidi = TRUE;
          stampa_vidi(); //stampa riferimenti vidimazione
        }
      }  
      else //stampa tutti i registri 
      {
        TString16 codtab, cod_lib_un;
        int anno; 
        TDate sca_vid;
        for (_tabreg->first(); !_tabreg->eof(); _tabreg->next())
        { 
          _tipo_reg = _tabreg->get_int("I0");
          codtab = _tabreg->get("CODTAB");
          anno = atoi(codtab.mid(0,4));
          if (anno > _annoes)
            break;
          if (anno == _annoes)   
            if ( _tipo_reg == 1 || _tipo_reg == 2 ) //registro iva
            {
              _codreg    = codtab.mid(4,3);
              cod_lib_un = _tabreg->get("S6");
              sca_vid    = _tabreg->get_date("D1");
              _stampa_ind_ditta = _tabreg->get_bool("B9");
              _liquidazione     = _tabreg->get_bool("B7");
              if (_tipo_stampa != 1)
                _u_data = _tabreg->get_date("D3");
              if (_tipo_stampa == 2 || _tipo_stampa == 4)
              {
                if (cod_lib_un.not_empty())
                  continue; 
                if (sca_vid.ok())
                  if (sca_vid.month() < _fino_a_mese)
                    continue;
                if (_u_data.ok())
                  if (_data_a < _u_data)  //e' molto imp. che rimanga < e non <= !!! 
                  {                       //(per via del discorso liq. annuale)
                    message_box("Ditta %ld: Il registro %s e' gia' stato stampato come bollato di %s", _ditta, (const char*) _codreg, itom(_fino_a_mese)); 
                    continue;
                  }   
              }
              if (_tipo_stampa == 4) //stampa con riferimenti al libro giornale
              {
                TString16 d;
                bool good;
                TRecnotype rec = _tabreg->recno();
                bool trovato = cerca_libro_gio(d, &good);
                _tabreg->readat(rec);
                if (!trovato)  
                  continue; 
              }
              if (_tipo_stampa == 3) //stampa su libro unico
              {
                if (cod_lib_un != _codlib)
                  continue;
                if (sca_vid.ok())
                  if (sca_vid.month() < _fino_a_mese)   
                    continue;
                if (_u_data.ok())
                  if (_fino_a_mese < _u_data.month()) //significa che e' gia' 
                    continue;                         //stato stampato        
              }
              msg = FALSE;
              
              look_reg();
              
              _intesta_liq  = FALSE;
              _intesta_vidi = FALSE; 
              _primast = _u_stampata; //per la numerazione dei registri successivi
              _ok_vidi = FALSE;
              _stampa_mese = 13;
              _scelta = controlla_b0(); //sul registro non va stampata la liq. ma comunque 
              //va richiamata per il calcolo progressivi (a seconda di b0) 
              //se non e' stampa di prova
              
              //modifica del 09/11/1995
              _cur->set_filterfunction(NULL);
              _cur->set_filterfunction(filter_func); 
              (*_cur) = 0L;
              //fine
              ok = setta_mask(i);    
              if (!ok) continue;
              
              if (_liquidazione)
              {
                if (_tipo_stampa == 2 || _tipo_stampa == 4)
                  _size_header = _stampa_ind_ditta ? 3 : 2;
                else _size_header = 3;
                clear_stliq();
                _scelta = controlla_liquidazione();
                if (_scelta == non_proseguire) 
                  return FALSE;
              } 
              /***
              _cur->set_filterfunction(NULL);
              _cur->set_filterfunction(filter_func); 
              (*_cur) = 0L;                        
              ***/
              // Guardo se ci sono movimenti
              const long items = _cur->items();

              // 17.5.95 Leggo parametri di stampa del registro  
              TString16   config;
              const long  codditta = get_firm();   
              const char* reg = (const char*)_codreg;
              config.format("REG%05ld%03s", codditta, reg);
              printer().read_configuration(config);
              
              //09/11/1995
              _mov_empty = TRUE;
              //fine
              
              if (items > 0l)
              {  
                //modifica del 26/07/1995;
                //_mov_empty = TRUE;
                //fine
                
                print(); 
                
                if (is_cancelled()) return FALSE;
                
                /***
                if (_tipo_stampa != 3 && _liquidazione)  
                  stampa_liq_mesi_succ();
                ***/  
              }
              else 
                no_movimenti();

              if (_tipo_stampa == 3 && _rif_vid)
              { 
                _intesta_vidi = TRUE;
                stampa_vidi(); //stampa riferimenti vidimazione
              } 
            }  
        } //for
        if (msg)
          //if ( (_tipo_stampa != 3) || (_tipo_stampa == 3 && _fino_a_mese == 1 && _selected.ones() == 1L) ) //il messaggio seguente, nel caso di stampa su libro unico,    
          if(_tipo_stampa == 3 && _fino_a_mese == 1 && _selected.ones() == 1L)
            message_box("Ditta %ld: nessun registro soddisfa i parametri indicati", _ditta);                 //viene gia' dato nell'handler 
      }                                                                                                      //da Gennaio)  
    }
  }
  TApplication::set_firm(__firm);
  return TRUE;
}


void CG4400_application::stampa_liq_mesi_succ()
{
  int da = _datareg.month() + 1;
  int a  = _data_a.month();   
  for (int m = da; m <= a; m++)
  {
    if (stampo_liquidazione(m))
    {
      /*
      if (!printer().isopen())
        printer().open();
      */  
//    _datareg = format("01/%02d/%4d", m, _annoes); //serve per la preprocess_header (intestazione per la stampa liquidazione)
      _datareg = TDate(1, m, _annoes);     // Meglio cosi'
      TFilename t;
      t.temp("iva");    
      if (_tipo_stampa == 1)
        send_message('L',t, m);    //prima era S ma non andava bene!
      else send_message('l',t,m);  //prima era s
      //TString80 nomef; nomef = t.path(); nomef << "\\" << t.name();
      //if (fexist(nomef))
      if (fexist(t))
      {  
        _intesta_liq = TRUE;
        printer().formfeed(); 
        //printer().footerlen(0);
        merge_export_file(t,FALSE,TRUE);  
        _intesta_liq = FALSE;
        remove(t);  
      } 
    }
  }
  //if (printer().isopen()) printer().close();
}  

void CG4400_application::send_message(char tipo, const TFilename& nome, int mese)
{
  const char* app; 

  if (tipo == 'S' || tipo == 's')
    app = "cg4 -2 -S";
  else if (tipo == 'C')
    app = "cg4 -2 -C";
  else app = "cg4 -2";

  TToken_string ss(10);
  
  ss.add(_annoes);
  if (_tipo_riepilogativo == 'A' && mese == 12)
    ss.add(13);
  else ss.add(mese);                                     
  ss.add(_ditta);
  ss.add(tipo);
  ss.add(_data_stampa.string()); 
  ss.add(nome); 
  ss.add(_size_header); 
  //ss.add("x");

  TMessage liq (app, "RCL", ss);
  liq.send();
  
  TExternal_app pn(app);
  pn.run();              
}

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.field(DA_DATA).set("");
  m.field(A_DATA).set("");
  m.field(CODICE_LIBRO_PROVA).set("");
  
  KEY tasto;     
  tasto = m.run();
  //  m.first_focus(tasto); 
  return tasto == K_ENTER;
}

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

  return _com->curr();
}

void CG4400_application::get_dati_ditta()
{
  TLocalisamfile nditte(LF_NDITTE); 
  TLocalisamfile anag(LF_ANAG);
  TLocalisamfile unloc(LF_UNLOC);
  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);

  _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); 
  } 
  
  if (_cod_un_loc)
  {
    unloc.zero();
    unloc.put(ULC_CODDITTA, get_firm());
    unloc.put(ULC_CODULC, _cod_un_loc);
    unloc.read();
    if (unloc.read() == NOERR) 
    {  
      TRectype dep = look_comuni (unloc.get(ULC_COMULC));
      _comunefis   = dep.get(COM_DENCOM);
      _provfis     = dep.get(COM_PROVCOM);
      _cap         = dep.get(COM_CAPCOM);
      _viafis      = unloc.get(ULC_INDULC);
      _viafis.rtrim();
      _viafis << " " << unloc.get(ULC_CIVULC);
    }
  }   
}

int CG4400_application::stampa_intestazione()
{
  int r = 1;
  TString codice_ditta;
  TString riga(_stampa_width);
  
  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 == 1)
  {
    riga = "REGISTRO DI PROVA   Data @<";
    riga.right_just(_stampa_width-6);
  }
  riga.overwrite (format("Partita iva %s Codice fiscale %s", (const char*)_paiva, (const char*)_cofi));
  set_header (r, riga);
  
  return r; 
}

void CG4400_application::preprocess_header()
{
  int r=1;
  char cor, nd1, nd2;
  char tipo = ' ';
  char type = ' '; 
  int  mese, anno;
  TString riga(_stampa_width);
  TString data(30);   
  
  riga.fill('-');   
  
  if (_tipo_stampa != 3)
  {
    mese = _datareg.month();
    anno = _datareg.year();
  }
  else //se _tipo_stampa == 3 (su libro unico) sto stampando un solo mese
  {
    mese = _fino_a_mese;
    anno = _annoes;
  }
  
  data.format("%s %s %d", "mese di", itom(mese), anno);

  reset_header();

  if (_tipo_stampa == 2 || _tipo_stampa == 4)
  {
    if (_stampa_ind_ditta)
      r = stampa_intestazione();
  }
  else // se stampa di prova o su libro unico l'intestazione della ditta 
    // va sempre stampata  
    r = stampa_intestazione();

  if (_tipo_stampa == 3 && !_intesta_vidi)
  {
    ++_u_stampata;
    ++_pagine_stampate; 
  }
  
  if (_tipo_stampa == 2 || _tipo_stampa == 4)
    ++_pagine_stampate;
  
  if (_tipo_stampa == 3)
    set_header(r, "@94gProgr.Studio %ld@114gProgr.Utente %ld", _u_stampata, _pagine_stampate);

  // cosi' sono sicura che l'aggiornamento viene fatto ad ogni salto pagina 
  // (cioe' a rottura di mese)  
  if (_tipo_stampa != 1) aggiorna_reg(_ok_vidi); 
  
  r++;
  
  /*
  if (!_intesta_vidi)
    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);
  */
  if (!_intesta_vidi)
  {
    if (_intesta_liq)
      set_header(r, "Registro IVA: %s %s   %s", (const char*)_codreg, 
                 (const char*)_desc_lib, (const char*) data);
    else 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); 
  }
  else 
  {
    set_header(r++, "Registro IVA: %s %s", (const char *) _codreg, (const char *) _desc_lib); 
    set_header(r, "RIFERIMENTI VIDIMAZIONE"); 
  }
  
  if (_intesta_liq) //se sto stampando sul registro la liquidazione
  {                 //l'intestazione (piuttosto dettagliata) e' gestita
    /*              //dal prg di liquidazione perche' molte info che devono 
    r++;            //comparire in questa intestazione la stampa reg. non le conosce.
    set_header(r++, "CALCOLO LIQUIDAZIONE IVA");
    set_header(r++,riga);
    TString title (80);
    title << "Liquidazione IVA ";
    if (_tipo_riepilogativo == 'A' && mese == 12)
      title << "Annuale " << format("%d", anno);    
    else
    {
      title << "del periodo";
      title << format(" %s %d", itom(mese), anno);
    }
    set_header(r++, "%s@102g Frequenza %s", (const char*) title, _frequiva == 'T' ? "T" : "M");  
    set_header(r++,riga);
    set_header(r,""); 
    */
  }   
  else  //non sto stampando la liquidazione
  {
    r++;
    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 (_tipoatt == "E") //attivita' mista
    {
      tipo = 'A';
      type = 'T';
    }
    /*
       if ((!_stampa_data_reg) && _stampa_width == 132)
       set_header(r,"Data I/P");
    */
    if (_tipo_stampa == 1) //stampa di prova (_intesta_vidi e' di sicuro FALSE)
    {
      if (_stampa_width == 132) 
      {
        set_header(r,"@10gNum.@19gDocumento@66gT Tipo@102gCod %c@123gT %c@128gNum", nd1, tipo);
        r++;
        set_header(r, "Data reg. prot.@17gData@24gNumero Codice Ragione sociale/descrizione@66gO Doc.@74gTotale doc.@90gImponibile  Iva %c@115gImposta@123g%c %c@128gReg", nd2, cor, type);
        r++;
      }
      else  //stampa a 198
      {
        set_header(r,"Registrazione Documento@66gT Tipo@110gCod %c@132g%c T@139gNum.", nd1, tipo, cor);
        r++;
        set_header(r, "Data Protocollo  Data@24gNumero Codice Ragione sociale/descrizione@66gO Documento@80gTot.Documento@98gImponibile  Iva %c@124gImposta@132g%c %c@139gReg.", nd2, type, cor);
        r++;
      }  
    }
  else if (!_intesta_vidi)
  {
    if (_stampa_width == 132)
    {
      set_header(r,"@10gNum.@19gDocumento@66gT Tipo@102gCod %c@123gT %c", nd1, tipo);
      if (_tipo_stampa == 4) //stampa definitiva con rif. al libro giornale
        set_header(r, "@128gNum."); 
      r++;
      set_header(r, "Data reg. prot.@17gData@24gNumero Codice Ragione sociale/descrizione@66gO Doc.@74gTotale doc.@90gImponibile  Iva %c@115gImposta@123g%c %c", 
                 nd2, cor, type);
      if (_tipo_stampa == 4)
        set_header(r, "@128gop."); 
      r++;
    }
    else //stampa a 198
    {
      set_header(r,"Registrazione Documento@66gT Tipo@110gCod %c@132g%c T", nd1, tipo);
      if (_tipo_stampa == 4)
        set_header(r, "@139gNum.");
      r++;
      set_header(r, "Data Protocollo  Data@24gNumero Codice Ragione sociale/descrizione@66gO Documento@80gTot.Documento@98gImponibile  Iva %c@124gImposta@132g%c %c", nd2, type, cor);
      if (_tipo_stampa == 4)
        set_header(r, "@139gop. @144gCodice conto @159gDescrizione sottoconto");
      r++;
    }  
  }
  else if (_tipo_stampa == 3 && _intesta_vidi)
  {
    TString tr(52);
    tr.fill('-');
    set_header(r++,"@10gPagine studio  Pagine utente ----------------  V I D I M A Z I O N E  %s", (const char*)tr);
    set_header(r++,"Mese@12gda@20ga@27gda@35ga   Intestatario@71gN.fogli Pag.in. Pag.fin.  Data     Ufficio");
  }
    if (_stampa_ind_comp && !_intesta_vidi)
      set_header(r++, "@38gGeneralita'");
    
    set_header(r, riga);
  } 
}

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














