// ------------------------------------------------------------
// Calcolo liquidazioni
// Part 1: interfaccia
// fv 21-1-94
// ------------------------------------------------------------

#include <defmask.h>                  
#include <mailbox.h>
#include <prefix.h>
#include <progind.h>
#include <sheet.h>
#include <utility.h> 

#include "cg4300.h"
#include "cg4300a.h"

#include <mov.h>

real TLiquidazione_app::CENTO(100.0);

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

TLiquidazione_app::TLiquidazione_app(int m) :
_ditte(NULL), _selected(10000),
_year(4), _nomiditte(100), _menu(m), _firm_bookmark(-1)
{ 
  _isprint = _is_interactive = _canprint = TRUE; 
  _isplafond = _printonly = _is_visliq = FALSE; 
  _isvent = _isagricolo = _isbenzinaro = _isviaggio = FALSE; 
  _row = 1;  _what = all; _comp_acconto = FALSE; 
  _isriepilogo = FALSE; _calcall = FALSE;
  _isfinal = _isregis = FALSE;
  _recalc = needed;
}

bool TLiquidazione_app::user_create()
{                 
  // vediamo se c'e' il messaggio per calcolare in batch
  TMailbox mail;
  TProgind* pnd = NULL;
  TMessage* msg = mail.next_s("RCL");
  TToken_string subj(36);
  _is_interactive = msg == NULL;
  _recalc_only = FALSE; 
  bool is_header = TRUE;
  int  headerlen;
  TDate   printdate;            
  TString filename;         
  long    ditta;
  bool    nocalc = FALSE;                             
  
  _prind = NULL;

  if (msg != NULL) subj = msg->body();  
  
  if (_is_interactive) 
    pnd = new TProgind (3,"Preparazione archivi\nPrego attendere", 
                        FALSE, TRUE, 30); 
  else begin_wait();

  _nditte = new TRelation(LF_NDITTE);
  _nditte->add(LF_ATTIV,"CODDITTA=CODDITTA");
  _nditte_r   = &(_nditte->curr());
  _att_r      = &(_nditte->curr(LF_ATTIV));

  _ditte  = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "@1|Cod.@5R|Ragione Sociale@50|Vers.");
  _n_ditte = 0l;    
  
  // prevediamo la data che usera'; se calcola la liq. di un altro anno
  // si fottera' la frequenza versamenti                      
  
  if (_is_interactive)
  {
    TDate oggi(TODAY);                    
    _year.format("%d",oggi.year());
  }
  else // parse messaggio
  {
    _year       = subj.get(0);
    _month      = subj.get_int(1);
    ditta       = subj.get_long(2);  
    char rcl    = *(subj.get(3));
    _recalc_only = rcl == 'C';
    _is_visliq  = rcl == 'V';   
    // S/s =  stampa senza ricalcolo (minuscolo = definitivo)
    // L/l =  stampa con ricalcolo se necessario (minuscolo = definitivo)
    // C   =  solo ricalcolo
    // V   =  stampa ed ev. ricalcolo per visualizzazione
    // s o l minuscoli = registro bollato (setta B1)
    _isregis    = (rcl == 'l' || rcl == 'L' || 
                   rcl == 'S' || rcl == 's'); // stampa per registri    
    _isfinal    = rcl == 'l' || rcl == 's'; // se l minuscolo, definitivo 
    nocalc      = rcl == 'S' || rcl == 's';
    printdate   = subj.get(4);
    filename    = subj.get(5);
    headerlen   = subj.get_int(6);
    is_header   = subj.items() == 7;
    //modifica del 5/07/1995
    int f = printer().formlen(); 
    printer().formlen(f - headerlen);  
    //fine
  }
  
  if(pnd) pnd->addstatus(1);
  
  _rel = new TRelation(LF_MOV);
  _rel->add(LF_RMOVIVA,"NUMREG=NUMREG");
  _rel->add(LF_CAUSALI,"CODCAUS=CODCAUS");

  _cur = new TCursor(_rel, "", 2);

  _pim        = new TTable("PIM");
  _pum        = new TTable("PUM"); 
  _pam        = new TTable("PAM"); 
  _pom        = new TTable("POM"); 
  _ppa        = new TTable("PPA"); 
  _plm        = new TTable("PLM"); 
  _lim        = new TTable("LIM");
  _lam        = new TTable("LAM");
  _pla        = new TTable("%PLA");  
  _reg        = new TTable("REG"); 
  _iva        = new TTable("%IVA");
  _del        = new TTable("%DEL");
  _lia        = new TTable("%LIA");
  
  _mov        = &_cur->file(LF_MOV); 
  _rmoviva    = &_cur->file(LF_RMOVIVA); 

  _pim_r      = &(_pim->curr());
  _plm_r      = &(_plm->curr());
  _pum_r      = &(_pum->curr());
  _pam_r      = &(_pam->curr());
  _pom_r      = &(_pom->curr());
  _iva_r      = &(_iva->curr());
  _del_r      = &(_del->curr());
  _lim_r      = &(_lim->curr());
  _lam_r      = &(_lam->curr());
  _pla_r      = &(_pla->curr());
  _ppa_r      = &(_ppa->curr());
  _reg_r      = &(_reg->curr());
  _rmoviva_r  = &(_cur->curr(LF_RMOVIVA));
  _mov_r      = &(_mov->curr());

  // ACHTUNG: tutti i _codatt (codici attivita') sono
  // in realta' composti dal codice attivita' piu' il
  // tipo attivita' (1 o 2)
  // sarebbe piu' saggio fare 2 campi ma ci vuole 1 vita

  _pim_anno    = new TRecfield(*_pim_r,"CODTAB",0,3);
  _pim_codatt  = new TRecfield(*_pim_r,"CODTAB",4,9);
  _pim_codreg  = new TRecfield(*_pim_r,"CODTAB",10,12);  
  _pim_mese    = new TRecfield(*_pim_r,"CODTAB",13,14);
  _pim_tipocr  = new TRecfield(*_pim_r,"CODTAB",15,15);
  _pim_codiva  = new TRecfield(*_pim_r,"CODTAB",16,19);  
  _pim_tipodet = new TRecfield(*_pim_r,"CODTAB",20,20);  
  _pum_anno    = new TRecfield(*_pum_r,"CODTAB",0,3);
  _pum_codatt  = new TRecfield(*_pum_r,"CODTAB",4,9);
  _pum_mese    = new TRecfield(*_pum_r,"CODTAB",10,11);
  _pam_anno    = new TRecfield(*_pam_r,"CODTAB",0,3);
  _pam_codatt  = new TRecfield(*_pam_r,"CODTAB",4,9);
  _pam_mese    = new TRecfield(*_pam_r,"CODTAB",10,11);
  _pom_anno    = new TRecfield(*_pom_r,"CODTAB",0,3);
  _pom_codatt  = new TRecfield(*_pom_r,"CODTAB",4,9);
  _pom_mese    = new TRecfield(*_pom_r,"CODTAB",10,11);
  _ppa_year    = new TRecfield(*_ppa_r,"CODTAB",0,3);
  _ppa_codatt  = new TRecfield(*_ppa_r,"CODTAB",4,9);
  _ppa_month   = new TRecfield(*_ppa_r,"CODTAB",10,11);
  _ppa_kind    = new TRecfield(*_ppa_r,"CODTAB",12,12); 

  _plm_anno    = new TRecfield(*_plm_r,"CODTAB",0,3);
  _plm_codatt  = new TRecfield(*_plm_r,"CODTAB",4,9);
  _plm_mese    = new TRecfield(*_plm_r,"CODTAB",10,11);

  _pla_ditta   = new TRecfield(*_pla_r,"CODTAB",0,4);
  _pla_anno    = new TRecfield(*_pla_r,"CODTAB",5,8);
  _pla_codatt  = new TRecfield(*_pla_r,"CODTAB",9,14);

  _del_ditta   = new TRecfield(*_del_r,"CODTAB",0,4);
  _del_anno    = new TRecfield(*_del_r,"CODTAB",5,8);
  _del_mese    = new TRecfield(*_del_r,"CODTAB",9,10);
  _del_tipo    = new TRecfield(*_del_r,"CODTAB",11,11);

  _lim_anno    = new TRecfield(*_lim_r,"CODTAB",0,3);
  _lim_mese    = new TRecfield(*_lim_r,"CODTAB",4,6);
  
  _lam_anno    = new TRecfield(*_lam_r,"CODTAB",0,3);
  _lam_mese    = new TRecfield(*_lam_r,"CODTAB",4,6);
  
  __firm = TApplication::get_firm();

  if (pnd) pnd->addstatus(1);
  
  if (_is_interactive)
  { 
    build_nomiditte(pnd);            
    build_ditte_sheet(all);
  }

  if (pnd) pnd->addstatus(1);

  TApplication::set_firm(__firm);
  set_real_picture(REAL_PICTURE);  
  
  if (!_is_interactive)
  {            
    TTemp_window w(TASK_WIN);
    if (_recalc_only) 
      _isprint = FALSE;
    //else printer().set_export_file(filename, is_header, headerlen);
    else printer().set_export_file(filename, is_header);

    // calcola liquidazione 
    printer().setdate(printdate);
    _recalc  = nocalc ? never : needed;
    TApplication::set_firm(ditta);
    
    if (!look_lia()) 
    { end_wait();  return FALSE; }
 
    _nditte->zero(); 
    _nditte_r->put("CODDITTA", ditta); 
    _nditte->read();
    _freqviva = _lia->get("S7");

    TRectype& mov = _cur->curr();
    TRectype  from(_cur->curr()); from.zero();
    TRectype  to(from);
    TDate f(1, 1, atoi(_year));
    TDate t(1, _month == 13 ? 12 : _month, atoi(_year));
    t.set_end_month();
    from.put(MOV_DATAREG, f);
    to.put(MOV_DATAREG, t);
    _cur->setregion(from, to);
    _canprint = is_month_ok_strict(_month) || _month == 13;
    _isannual = _isriepilogo = _month == 13;
      
    //modifica del 03/05/1995 
    int need_refresh = FALSE;
    for (int m = 1; m < _month; m++)
      if (is_month_ok_strict(m) && (!look_lim(m) || !_lim->get_bool("B0")))
      {
        need_refresh = TRUE; 
        break;
      }

    if (need_refresh) _recalc = ever;

    // determina attivita' prevalente e istanzia cazzuole
    // per vedere che Kazzo di liquidazione calcolare
    TString attprev = _nditte->curr().get("CODATTPREV");
    TLocalisamfile& atts = _nditte->lfile(LF_ATTIV);
    atts.zero();
    atts.put("CODDITTA",ditta);
    atts.put("CODATT",  attprev);
    if (atts.read() != NOERR) atts.zero();
    // istanzia benzinaro
    _isbenzinaro = atts.get_bool("ART74_4");
      
    // riaggiusta relazione
    _nditte->read();               

    
    for (int mese = 1; mese < _month; mese++)   // fino a 13 compreso
      if (is_month_plain(mese) || _recalc == ever)
        update_firm(mese);
    
    if (is_month_plain(_month) || _month == 13) 
      update_firm(_month);
    
    if (_isprint && _descr_arr.items() > 0)
      print();            
                 
    // se ci sono altri mesi dopo l'ultimo calcolato, invalida il 
    // flag 'calcolato' del primo, per causare il ricalcolo dei
    // successivi (evitando problemi per credito precedente)
    for (m = _month+1; m <= 13; m++)
      if (look_lim(m))
      { 
        _lim->put("B0","");
        _lim->rewrite();
        break; 
      }
            
    TApplication::set_firm(__firm);      
    end_wait();
  }                    
  else delete pnd; 
  
  return _is_interactive;
}

bool TLiquidazione_app::user_destroy()
{
  delete _ditte;

  delete _pim_anno;
  delete _pim_codreg;
  delete _pim_mese;
  delete _pim_tipocr;
  delete _pim_codiva;
  delete _ppa_year;
  delete _ppa_codatt;
  delete _ppa_month;
  delete _ppa_kind;
  delete _plm_anno;
  delete _plm_codatt;
  delete _plm_mese;
  delete _pum_anno;
  delete _pum_codatt;
  delete _pum_mese;
  delete _pam_codatt;
  delete _pam_anno;
  delete _pam_mese;
  delete _pom_codatt;
  delete _pom_anno;
  delete _pom_mese;
  delete _lim_anno;
  delete _lim_mese;
  delete _lam_anno;
  delete _lam_mese;
  delete _pla_anno;
  delete _pla_codatt;
  delete _pim_codatt;
  delete _del_ditta;
  delete _del_anno;
  delete _del_mese;
  delete _del_tipo;

  delete _pim;
  delete _pum;
  delete _pam;
  delete _pom;
  delete _ppa;
  delete _plm;
  delete _lim;
  delete _lam;
  delete _pla;
  delete _del;

  delete _nditte;
  delete _rel;
  delete _cur;   
  
  return TRUE;
}

bool TLiquidazione_app::set_print(int)
{
  _descr_arr.destroy();
  _errors.destroy();
  
  switch(_menu)
  {
  case 1: // liquidazione
    _isprint = TRUE;
    while (set_liquidazione()) 
    {
      if (_selected.ones() > 0l)
      {
        TRectype& mov = _cur->curr();
        TRectype  from(_cur->curr()); from.zero();
        TRectype  to(from);
        TDate f(1, 1, atoi(_year));
        TDate t(1, _month == 13 ? 12 : _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to);

        return recalc_all() && _isprint;
      }
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  case 2: // estrazione deleghe
    _isprint = FALSE;     
    //build_ditte_sheet(all);
    while (set_deleghe()) 
    { 
      if (_calcall || _selected.ones() > 0l)
      {
        TRectype & mov = _cur->curr();
        TRectype from(_cur->curr()); from.zero();
        TRectype to(from);
        TDate f(1, _recalc == one ? _month : 1, atoi(_year));
        TDate t(1, _month == 13 ? 12 : _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to);  
        extract_deleghe(); 
        return _isprint;
      } 
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  case 3: // calcolo acconto
    _isprint = TRUE;
    _month = 12; 
    //build_ditte_sheet(all);    
    real inf; real ina;  // cotale obbrobrio non fu da me cercato, ne' mai condiviso
    while (set_acconto(inf, ina)) 
    { 
      if (_calcall || _selected.ones() > 0l)
      {
        TRectype & mov = _cur->curr();
        TRectype from(_cur->curr()); from.zero();
        TRectype to(from); 
        TDate f(1, _recalc == one ? _month : 1, atoi(_year));
        TDate t(1, _month == 13 ? 12 : _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to); 
        recalc_acconti(inf, ina); 
        return _isprint; 
      } 
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  }
  return FALSE;
}

long TLiquidazione_app::select_firm_range(long from, long to, wht freq)
{
  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 == '?' || (freq == mnt && vers == 'T') || (freq == trimestre && vers == 'M'))
      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();
}

// ----------------------------------------------- handlers

bool TLiquidazione_app::ch_year_handler(TMask_field& f, KEY key)
{                                                    
  if (key == K_TAB && f.focusdirty())
  {                         
    app().begin_wait();
    app().reset_choices(f.mask());
    app().set_year(f.get());
    app().build_nomiditte();
    app().build_ditte_sheet(f.mask().source_file() == "cg4300a.msk" ?
                            (wht)atoi(f.mask().get(CG43_RDB_VERS))  :
                            all);    
    app().end_wait();
  }
  return TRUE;
} 

void TLiquidazione_app::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                                               
      if (!look_lia(dt.get_long("CODDITTA"))) good = FALSE; 
    }
    else continue;
    
    TToken_string* d = new TToken_string(64);
    
    // add record 
    d->add(dt.get("CODDITTA"));
    d->add(dt.get("RAGSOC"));
    if (good) d->add(_lia->get("S7"));
    else      d->add("??"); 
    
    _nomiditte.add(d);  
  }
  if (pnd) pnd->addstatus(1);
}

bool TLiquidazione_app::to_ditt_handler(TMask_field& f, KEY key)
{
  TMask& m = f.mask();
  if (key == K_F9)
  {
    app().to_butt_handler(m.field(CG43_BUT_DTO), K_SPACE);
  }
  if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(CG43_FLD_DFR),
                                           m.get_long(CG43_FLD_DTO), 
                                           (wht)m.get_int(CG43_RDB_VERS));
    app().set_choice_limits(m);
    m.field(CG43_FLD_SELECTED).set(format("%ld", l));
  }
  return TRUE;
}

bool TLiquidazione_app::fr_ditt_handler(TMask_field& f, KEY key)
{                          
  TMask& m = f.mask();
  if (key == K_F9)
  {
    app().fr_butt_handler(m.field(CG43_BUT_DFR), K_SPACE);
  }
  else if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(CG43_FLD_DFR),
                                           m.get_long(CG43_FLD_DTO), 
                                           (wht)m.get_int(CG43_RDB_VERS));

    app().set_choice_limits(m);
    m.set(CG43_FLD_SELECTED, l);
  }
  return TRUE;
}

bool TLiquidazione_app::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(CG43_FLD_DFR),sh->row(sh->selected()).get_long(1), 
                              (wht)m.get_int(CG43_RDB_VERS));
      app().set_choice_limits(m);
    }
  }
  return TRUE;
}

bool TLiquidazione_app::fr_butt_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)
  {
    TMask& m = f.mask();
    TArray_sheet* sh = ((TLiquidazione_app&)main_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(CG43_FLD_DTO), 
                              (wht)m.get_int(CG43_RDB_VERS));
      app().set_choice_limits(m);
    }
  }
  return TRUE;
}

bool TLiquidazione_app::what_freq_handler(TMask_field& f, KEY key)
{    
  if (key == K_SPACE && f.dirty())
  {  
    if (f.get()[0] == '3')       // trimestre intelligente
    {
      int month = f.mask().get_int(CG43_LST_MESE);
      if  (month > 3) 
        while (!is_trim(month)) month--;  
      else month = 3; 
      
      f.mask().field(CG43_LST_TRIM).set(format("%d",month)); 
    }
    app().reset_choices(f.mask());                            
    app().build_ditte_sheet((wht)atoi(f.get()));
  } 
  return TRUE;
}

void TLiquidazione_app::reset_choices(TMask& m)
{
  _selected.reset();  
  if (m.source_file() == "cg4300a.msk")
  {
   m.reset(CG43_FLD_SELECTED);
   m.reset(CG43_FLD_DFR);
   m.reset(CG43_FLD_DTO);
  } 
  _ditte->check(-1, FALSE);
}

void TLiquidazione_app::set_choice_limits(TMask& m)
{     
  long first = -1l, last = -1l;
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_selected[i])
    {
      const long dit = _ditte->row(i).get_long(1);
      if (first == -1l) first = dit;
      if (last < dit)   last  = dit;
    }
  }
  if (first != -1) m.set(CG43_FLD_DFR, first);                        
  if (last  != -1) m.set(CG43_FLD_DTO, last);                        
  m.set(CG43_FLD_SELECTED, _selected.ones());
}

void TLiquidazione_app::build_ditte_sheet(wht what)
{
  // build sheet
  _ditte->destroy();
  _what = what;
  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 unselectable = vers == '?';
    if ((what == mnt && vers == 'T') || (what == trimestre && vers == 'M'))
      continue;
    
    d->insert(" |", 0);        
    
    const long pos = _ditte->add(d);     
    if (unselectable)      _ditte->disable(pos);
    else if (_selected[i]) _ditte->check(pos);
  }     
}


// ----------------------------------------------------

bool TLiquidazione_app::set_liquidazione()
{
  TMask m("cg4300a.msk");       
  
  m.set_handler(CG43_FLD_DTO,  to_ditt_handler);
  m.set_handler(CG43_FLD_DFR,  fr_ditt_handler);
  m.set_handler(CG43_BUT_DTO,  to_butt_handler);
  m.set_handler(CG43_BUT_DFR,  fr_butt_handler);
  m.set_handler(CG43_RDB_VERS, what_freq_handler);
  m.set_handler(CG43_FLD_ANNO, ch_year_handler);
  
  m.field(CG43_FLD_SELECTED).set(format("%ld",_selected.ones()));
  m.field(CG43_FLD_ANNO).set(_year);
  set_choice_limits(m);
  
  KEY k;
  // stampa abilitata per default
  m.set(CG43_CHK_STAMPA,"X");  
  
  _month = m.get_int(CG43_LST_MESE);
  
  do  
  {
    m.field(CG43_RDB_VERS).set(format("%d",(int)_what));
    
    if ((k = m.run()) == K_ESC) break;                   
    
    // handlers have set everything

    _month   = _what == trimestre ? m.get_int(CG43_LST_TRIM) : 
    m.get_int(CG43_LST_MESE);
    
    _year      = m.get(CG43_FLD_ANNO);
    _date      = m.get(CG43_FLD_DATA);
    _isprint   = m.get_bool(CG43_CHK_STAMPA);
    _recalc    = (recalc)m.get_long(CG43_LST_CALC);
    _printonly = m.get_bool(CG43_CHK_FINAL);

    if (_isprint) printer().setdate(_date);
    if (_printonly) _recalc = never;

    // ------------------------------------------------
    m.first_focus(k);
    
    switch(k)
    { 
    case DLG_SELECT:
      _ditte->enable_check();
      // seleziona e aggiungi alle gia' selezionate 
      if (_ditte->run() == K_ENTER)
      {
        for (long j = 0l; j < _ditte->items(); j++)
          _selected.set(j, _ditte->checked(j));
        set_choice_limits(m);
      }
      break;

    case CG43_BUT_ANN:
      reset_choices(m);
      break;
    }
  }  
  while (k != K_ENTER && k != K_ESC);      

  return k == K_ENTER;
}

int cg4300(int argc, char* argv[])
{
  TApplication::check_parameters(argc, argv);
  
  const char* title = "Liquidazione IVA";
  int menu = 1;
  
  if (argc > 2)
  {
    const char mode = argv[2][1];
    switch (mode)
    {
    case 'A':
      title = "Calcolo acconti";
      menu = 3;
      break;
    case 'C':
      title = "Ricalcolo progressivi IVA";
      break;
    case 'D': 
      title = "Estrazione versamenti";
      menu = 2;
      break;
    case 'S':
      title = "Stampa liquidazione"; 
      break;  
    default:
      break;  
    }  
  }

  TLiquidazione_app main_app(menu);
  main_app.run(argc, argv, title);
  return TRUE;
}
