#include <msksheet.h>
#include <prefix.h>
#include <recarray.h>
#include <relapp.h>
#include <sheet.h>
#include <tabutil.h>
#include <utility.h>

#include "at0.h"
#include "atlib.h"

// nomi campi maschera
#include "at0100a.h"	// maschera principale
#include "at0100b.h"	// maschera genera donazioni
#include "at0100c.h"	// maschera famigliari
#include "at0100d.h"	// maschera ricerca parziale
#include "at0100e.h"	// maschera richiesta password
          
// nomi dei campi
#include "soggetti.h"
#include "donaz.h"
#include "contsan.h"
#include "benem.h"
#include "storico.h"
#include "famiglie.h"
#include "convoc.h"
#include "rconvoc.h"
#include "idoneita.h"

class TGestioneSoggetti : public TRelation_application
{
	TMask*					_msk;
	TRelation*   		_rel;
	TLocalisamfile* _donaz;
	TLocalisamfile* _contsan;
	TLocalisamfile* _benem;
	TLocalisamfile* _storico;
	TLocalisamfile* _famiglie;
	TLocalisamfile* _convoc;
	TLocalisamfile* _rconvoc;
	TLocalisamfile* _idoneita;
	TRecord_array*	_sdonazioni;		// sheet donazioni
	TRecord_array*  _scontrolli;		// sheet controlli
	TRecord_array*  _sbenemerenze;	// sheet benemerenze
	TRecord_array*  _sstorico;			// sheet storico
	TRecord_array*  _sfamiglia;			// sheet famiglia
	TRecord_array*  _sidoneita;			// sheet idoneita
	TArray*					_aconvocazioni;	// array delle convocazioni
	long 						_lastcod;				// ultimo codice soggetto assegnato
	long 						_lastfam;				// ultimo codice famiglia assegnato
	long						_famprec;				// codice famiglia precedente
	long						_famatt;				// codice famiglia attuale
	long						_codice;				// codice soggetto attuale (per famiglie)
	bool						_nuovaconv;			// nuova convocazione da registrare
	TDate						_oldconv;				// data ultima convocazione registrata su soggetto

	// parametri di sezione
	int							_numdon1, _numdon2;
	TString16				_catini1, _catfin1, _catini2, _catfin2, _oldgruppo, _oldrh, _oldkell, _oldfen, _olddu;
	bool						_sttess2, _dataisc, _ctrlpass, _permesso;
	
protected:
	virtual bool user_create();
	virtual bool user_destroy();
	virtual const char* get_next_key();
	virtual int scrivi(const TMask& m, bool ri);
	virtual int write(const TMask& m);
	virtual int rewrite(const TMask& m);
	virtual int read(TMask& m);
	virtual bool remove();
	virtual bool changing_mask(int mode) { return FALSE; }
	virtual TMask* get_mask( int mode = 0) { return _msk; }
	virtual TRelation* get_relation() const { return _rel; }
	virtual void on_firm_change();

	virtual void init_insert_mode(TMask& m);
	virtual void init_modify_mode(TMask& m);
	virtual void init_query_mode(TMask& m);

	// notify degli sheet	
	static bool donazioni_notify(TSheet_field& s, int r, KEY k);
	static bool controlli_notify(TSheet_field& s, int r, KEY k);
	static bool benemerenze_notify(TSheet_field& s, int r, KEY k);
	static bool storico_notify(TSheet_field& s, int r, KEY k);
	static bool famiglia_notify(TSheet_field& s, int r, KEY k);
	static bool idoneita_notify(TSheet_field& s, int r, KEY k);
	// handler dei campi o bottoni
	static bool ricparz_handler(TMask_field& f, KEY k);
	static bool convoc_handler(TMask_field& f, KEY k);
	static bool datanasc_handler(TMask_field& f, KEY k);
	static bool catdon_handler(TMask_field& f, KEY k);
	static bool dataconv_handler(TMask_field& f, KEY k);
	static bool genera_handler(TMask_field& f, KEY k);
	static bool famiglia_handler(TMask_field& f, KEY k);
	static bool collega_handler(TMask_field& f, KEY k);
	static bool nome_handler(TMask_field& f, KEY k);
	static bool nuova_handler(TMask_field& f, KEY k);
	static bool eseguigen_handler(TMask_field& f, KEY k);
	static bool tipocon_handler(TMask_field& f, KEY k);
	static bool idosos_handler(TMask_field& f, KEY k);
	static bool idoncon_handler(TMask_field& f, KEY k);
	static bool datadon_handler(TMask_field& f, KEY k);
	static bool datacon_handler(TMask_field& f, KEY k);
	static bool donprecsi_handler(TMask_field& f, KEY k);
	static bool donprecaf_handler(TMask_field& f, KEY k);	
	static bool donazioni_handler(TMask_field& f, KEY k);	
	static bool controlli_handler(TMask_field& f, KEY k);	
	static bool idoneita_handler(TMask_field& f, KEY k);	
	static bool storico_handler(TMask_field& f, KEY k);	
	static bool benem_handler(TMask_field& f, KEY k);	
	static bool gruppo_handler(TMask_field& f, KEY k);
	static bool rhantid_handler(TMask_field& f, KEY k);
	static bool kell_handler(TMask_field& f, KEY k);
	static bool fenotiporh_handler(TMask_field& f, KEY k);
	static bool du_handler(TMask_field& f, KEY k);
	static void c_reord(TSheet_field& controlli, TSheet_field& idoneita);
	
	// setta le abilitazioni ai campi di una riga dei controlli
	void tipocon_set_row(TMask& m);	
	// setta le abilitazioni ai campi di una riga delle idoneita
	void idosos_set_row(TMask& m);	
	// setta le abilitazioni ai campi di tutto lo sheet dei controlli	
	void tipocon_set_sheet(TSheet_field& s);	
	// setta le abilitazioni ai campi di tutto lo sheet dei controlli	
	void idosos_set_sheet(TSheet_field& s);	
	
public:
	void calcola_donazioni(TMask& mask, TSheet_field& s);		
	bool richiesta_password();
	TGestioneSoggetti() {}
};

HIDDEN inline TGestioneSoggetti& app() { return (TGestioneSoggetti&) main_app(); }

static int compare_date(const TObject** o1, const TObject** o2)
{
  TToken_string* s1 = (TToken_string*)*o1;
  TToken_string* s2 = (TToken_string*)*o2;
  
  const TDate d1(s1->get(0));
  const TDate d2(s2->get(0));
  
  int d=0;
  if (d1>d2) d=+1;
  else
  	if (d1<d2) d=-1;
	return d;
}	

void ordina_sheet_data(TSheet_field& s)
{
	TArray& as = s.rows_array();
	as.sort(compare_date);
}

void d_datepross(TSheet_field& s)
// calcola le date di prossima donazione in base a: donazioni, stato attuale, idoneit�
{
	TMask& m = s.mask();
	char modstato = ' ';     
	const TString16 stato = m.get(F_STATO);	// stato attuale
	const TString16 id1 = m.get(F_IDON1);		// idon. 1
	const TString16 id2 = m.get(F_IDON2);		// idon. 2
	const TString16 id3 = m.get(F_IDON3);		// idon. 3
	const TString16 id4 = m.get(F_IDON4);	  // idon. 4
	const int intsi = m.get_int(F_INTSI);		// intervallo per SI
	const int intaf = m.get_int(F_INTAF);		// intervallo per AF
	const TDate dataultdon(m.get_date(F_DATAULTDON));	// data ultima donazione
	const TString16 tipoultdon(m.get(F_TIPOULTDON));	// tipo ultima donazione
	TDate datasi(NULLDATE);		// data prossima si calcolata
	TDate dataaf(NULLDATE);		// data prossima af calcolata
	TDate dataultsi(NULLDATE);	// data ultima donazione si
	
	bool id_si = FALSE;		// il soggetto � idoneo per si?
	bool id_af = FALSE;		// il soggetto � idoneo per af?
	
  modstato = modstato_tcs(stato);
	if (modstato == 'I' || modstato == 'F')	// il soggetto � idoneo
	{ 
		id_si = ((is_idon(id1,id2,id3,id4,IDON_SI) || (m.get(F_STATOSI) == IDONEITA)) && (intsi != 0));		// il soggetto � idoneo SI
		id_af = ((is_idon(id1,id2,id3,id4,IDON_AF) || (m.get(F_STATOAF) == IDONEITA)) && (intaf != 0));		// il soggetto � idoneo AF
		
		if (dataultdon.ok())		// se ha fatto almeno una donazione
		{
			if (is_donaz(tipoultdon,IDON_SI))	// se l'ultima donazione � una SI
			{
				if (id_si) 
				{
					datasi=dataultdon;
					datasi+=intsi;
				}	
  			if (id_af) 
  			{
  				dataaf=dataultdon;
  				dataaf+=intaf;
  			}	
      }
      if (is_donaz(tipoultdon,IDON_AF))	// se l'ultima donazione � una AF
      {
      	dataultsi = m.get(F_DATAULTSI);
				if (id_si)
				{
					if (intaf != 0)
					{
						datasi=dataultdon; 
						datasi+=intaf;
					}	
					else
					{
						datasi=dataultdon;
					  datasi+=intsi;    
					}  
					if (dataultsi.ok())
						dataultsi+=intsi;
					if (dataultsi > datasi)
						datasi = dataultsi;
				}
				if (id_af)
				{
					dataaf=dataultdon;
					dataaf+=intaf;
				}					
      }	
 		}
 		else
 		{
 			if (id_si)
 				datasi= m.get_date(F_DATAULTID);
 			if (id_af)
 				dataaf= m.get_date(F_DATAULTID); 				
 		}
	}	
	TString16 statoparziale;
	TDate datastatoparziale;
	statoparziale = m.get(F_STATOSI);
	datastatoparziale = (TDate)m.get(F_DATASI);
	if (statoparziale == SOSPENSIONE)
		datasi = NULLDATE;
	if (statoparziale == IDONEITA)		
		if (datastatoparziale > datasi)
			datasi = datastatoparziale;
	statoparziale = m.get(F_STATOAF);
	datastatoparziale = (TDate)m.get(F_DATAAF);
	if (statoparziale == SOSPENSIONE)
		dataaf = NULLDATE;
	if (statoparziale == IDONEITA)		
		if (datastatoparziale > dataaf)
			dataaf = datastatoparziale;
	m.set(F_DATAPROSSI,datasi);
	m.set(F_DATAPROSAF,dataaf);
}

void TGestioneSoggetti::calcola_donazioni(TMask& mask, TSheet_field& s)
{
	TDate ultdata(NULLDATE);
	TString16 ulttipo = '  ';
	TMask_field& f = mask.field(F_TIPOULTDON);
	const int i = s.items()-1;
	const int donprecsi = mask.get_int(F_DONPRECSI);
	const int donprecaf = mask.get_int(F_DONPRECAF);	
	if (i < 0)	// non ha donazioni
	{
		int zerodon = 0;
		mask.set(F_DATAULTDON,ultdata);
		mask.set(F_DATAULTSI,ultdata);
		mask.set(F_DATAULTAF,ultdata);
		mask.set(F_TOTDONSI,donprecsi);
		mask.set(F_TOTDONAF,donprecaf);
		f.set(ulttipo);
		f.on_key(K_TAB);
	}	
	else	
	{ 
		TToken_string& row = s.row(i);
		ultdata = TDate(row.get(0));
		ulttipo = row.get();
		mask.set(F_DATAULTDON,ultdata);  			  	
		f.set(ulttipo);
		f.on_key(K_TAB);
		TDate dataultsi(NULLDATE);
		TDate dataultaf(NULLDATE);
		int totdonsi = 0;
		int totdonaf = 0;        
		for (int r=0; r<s.items(); r++)
		{
			TToken_string& row = s.row(r);
			ultdata = TDate(row.get(0));
			ulttipo = row.get();
			if (is_donaz(ulttipo,IDON_SI))
			{
				dataultsi = ultdata;
				totdonsi++;
			}
			else
				if (is_donaz(ulttipo,IDON_AF))
				{
					dataultaf = ultdata;
					totdonaf++;
				}
		}					
		mask.set(F_DATAULTSI, dataultsi);
		mask.set(F_TOTDONSI, totdonsi+donprecsi);
		mask.set(F_DATAULTAF, dataultaf);
		mask.set(F_TOTDONAF, totdonaf+donprecaf);
		mask.set(F_TOTDON, totdonaf+donprecaf+totdonsi+donprecsi); //Aggiunto da Marco il 09/07/99 in modo che il cambio di categoria avvenga in modo corretto
		TString16 catdon = mask.get(F_CATDON);		
		int totdon = mask.get_int(F_TOTDON);
		if ((catdon == _catini1 || _catini1.empty()) && (totdon>=_numdon1) && _catfin1.not_empty())
		{
			mask.set(F_CATDON, _catfin1);
			catdon = _catfin1;
		}	
		if ((catdon == _catini2 || _catini2.empty()) && (totdon>=_numdon2) && _catfin2.not_empty() && !_sttess2)
		{
			mask.set(F_CATDON, _catfin2);
			catdon = _catfin2;
		}	
		mask.field(F_CATDON).on_key(K_TAB);			
		TDate dataisc = mask.get_date(F_DATAISC);
		if (!dataisc.ok() && _dataisc)
		{ 
			if (!mask.get_date(F_DATAPRISI) == NULLDATE)
				mask.set(F_DATAISC,mask.get(F_DATAPRISI));
			else
		  {
				TToken_string& row = s.row(0);
				TDate primadata = TDate(row.get(0));			
				mask.set(F_DATAISC,primadata);
			}				  	
		}			
	}		
	d_datepross(s);
}

void TGestioneSoggetti::init_insert_mode(TMask& m)
{
	m.set(F_NOTIZIARIO,TRUE);
	m.set(F_BENEM,TRUE);
	m.hide(F_RICPARZ);
}

void TGestioneSoggetti::init_modify_mode(TMask& m)
{
	m.hide(F_RICPARZ);           
	_oldgruppo = m.get(F_GRUPPOAB0);	
	_oldrh = m.get(F_RHANTID);	
	_oldfen = m.get(F_FENOTIPORH);	
	_oldkell = m.get(F_KELL);	
	_olddu = m.get(F_DU);	
}

void TGestioneSoggetti::init_query_mode(TMask& m)
{
	m.show(F_RICPARZ);
}

bool TGestioneSoggetti::donazioni_handler(TMask_field& f, KEY k)
{
  if (!f.mask().is_running())
  {
		TSheet_field& s = (TSheet_field&)f;
		const int n = s.items()-1;
		if (n >= 0)
			s.select(n, TRUE);	
	}
	return TRUE;
}

bool TGestioneSoggetti::controlli_handler(TMask_field& f, KEY k)
{
  if (!f.mask().is_running())
  {
		TSheet_field& s = (TSheet_field&)f;
		const int n = s.items()-1;
		if (n >= 0)
			s.select(n, TRUE);	
	}
	return TRUE;
}

bool TGestioneSoggetti::idoneita_handler(TMask_field& f, KEY k)
{
  if (!f.mask().is_running())
  {
		TSheet_field& s = (TSheet_field&)f;
		const int n = s.items()-1;
		if (n >= 0)
			s.select(n, TRUE);	
	}
	return TRUE;
}

bool TGestioneSoggetti::storico_handler(TMask_field& f, KEY k)
{
  if (!f.mask().is_running())
  {
		TSheet_field& s = (TSheet_field&)f;
		const int n = s.items()-1;
		if (n >= 0)
			s.select(n, TRUE);	
	}
	return TRUE;
}

bool TGestioneSoggetti::benem_handler(TMask_field& f, KEY k)
{
  if (!f.mask().is_running())
  {
		TSheet_field& s = (TSheet_field&)f;
		const int n = s.items()-1;
		if (n >= 0)
			s.select(n, TRUE);	
	}
	return TRUE;
}

bool TGestioneSoggetti::datadon_handler(TMask_field& f, KEY k)
{
	if (f.to_check(k))
	{
		TMask& m = f.mask();
		
		TSheet_field& s = *m.get_sheet();
		const TString16 datadon = f.get();
		for (int r=s.items()-1; r>=0; r--)
		{
			if (r != s.selected())
			{
				TToken_string& row = s.row(r); 
				if (datadon == row.get(0))
					return f.error_box("Data donazione %s gia' inserita",(const char*)datadon);
			}					
		}				
	}
	return TRUE;
}

bool TGestioneSoggetti::datacon_handler(TMask_field& f, KEY k)
{
	if (f.to_check(k))
	{
		TMask& m = f.mask();
		
		TSheet_field& s = *m.get_sheet();
		const TDate datacon = f.get();
		for (int r=s.items()-1; r>=0; r--)
		{
			if (r != s.selected())
			{
				TToken_string& row = s.row(r); 
				TDate datarow = TDate(row.get(0));
				if (datacon == datarow)
					return f.error_box("Data controllo %s gia' inserita",(const char*)datacon.string());
				else
					if (datacon < datarow)
						return f.yesno_box("ATTENZIONE! Esiste un controllo sanitario %s con data successiva. Vuoi continuare?", row.get(1));
			}					
		}				
		TMask& mask = s.mask();
		TDate datastato = mask.get_date(F_DATASTATO);
		if (datacon < datastato)
			return f.yesno_box("ATTENZIONE! Data controllo inferiore alla data stato.;Vuoi continuare?");
		datastato = mask.get_date(F_DATASI);			
		if (datacon < datastato)
			return f.yesno_box("ATTENZIONE! Data controllo inferiore alla data stato SI.;Vuoi continuare?");
		datastato = mask.get_date(F_DATAAF);			
		if (datacon < datastato)
			return f.yesno_box("ATTENZIONE! Data controllo inferiore alla data stato AF.;Vuoi continuare?");
	}
	return TRUE;
}

bool TGestioneSoggetti::donprecsi_handler(TMask_field& f, KEY k)
{
	static int oldprecsi;
	if (k==K_TAB)
	{
		TMask& m = f.mask();
		const int donprecsi = m.get_int(F_DONPRECSI);
		if (f.focusdirty())
		{
			const int totdonsi = m.get_int(F_TOTDONSI);
			m.set(F_TOTDONSI,totdonsi-oldprecsi+donprecsi);
			int totdon = m.get_int(F_TOTDON)-oldprecsi+donprecsi;
			//Le righe seguenti sono state aggiunte da Marco in data 05/08/99 per gestire il cambio di categoria in caso di donazioni non dettagliate
			//m.set(F_TOTDON,totdon-oldprecsi+donprecsi); unica riga usata da Cristina
			m.set(F_TOTDON,totdon);
			TString16 catdon = m.get(F_CATDON);		
		  if ((catdon == app()._catini1 || app()._catini1.empty()) && (totdon>=app()._numdon1) && app()._catfin1.not_empty())
		  {
				m.set(F_CATDON, app()._catfin1);
				catdon = app()._catfin1;
			}	
			if ((catdon == app()._catini2 || app()._catini2.empty()) && (totdon>=app()._numdon2) && app()._catfin2.not_empty() && !app()._sttess2)
			{
				m.set(F_CATDON, app()._catfin2);
				catdon = app()._catfin2;
			}	
			m.field(F_CATDON).on_key(K_TAB);	
			// fino a qui	
		}
		oldprecsi = donprecsi;
	}
	return TRUE;
}			

bool TGestioneSoggetti::donprecaf_handler(TMask_field& f, KEY k)
{
	static int oldprecaf;
	if (k==K_TAB)
	{
		TMask& m = f.mask();
		const int donprecaf = m.get_int(F_DONPRECAF);
		if (f.focusdirty())
		{
			const int totdonaf = m.get_int(F_TOTDONAF);
			m.set(F_TOTDONAF,totdonaf-oldprecaf+donprecaf);
			const int totdon = m.get_int(F_TOTDON);
			m.set(F_TOTDON,totdon-oldprecaf+donprecaf);
		}
		oldprecaf = donprecaf;
	}
	return TRUE;
}			

bool TGestioneSoggetti::datanasc_handler(TMask_field& f, KEY k)
{
	if (f.to_check(k) || k == K_ENTER)
	{
		TMask& m = f.mask();
		if (f.empty())                                    
		{
			if  (m.insert_mode())
				return f.error_box("La data di nascita e' obbligatoria");	
	    if (m.edit_mode())
	    	 	f.warning_box("La data di nascita e' vuota."); 
	  }
	  else
	  {
		  if (m.insert_mode())
			{  
			  TLocalisamfile sog(LF_SOGGETTI);                                                        
			  sog.setkey(2);
				sog.zero();
				sog.put(SOG_COGNOME,m.get(F_COGNOME));
				sog.put(SOG_NOME,m.get(F_NOME));
				sog.put(SOG_DATANASC,m.get_date(F_DATANASC));
				if (sog.read() == NOERR && (m.get_long(F_CODICE) != sog.get_long(SOG_CODICE)))
					return f.error_box("Soggetto con cognome, nome e data di nascita uguali gi� esistente");
      }
		}	  	
	}   
	return TRUE;	
}

bool TGestioneSoggetti::catdon_handler(TMask_field& f, KEY k)
{
	if (f.to_check(k))
	{
		TMask& m = f.mask();
		if (m.get(F_CATNOND1).not_empty() || m.get(F_CATNOND2).not_empty())
			if (cache().get("CTD",m.get(F_CATDON)).get_bool("B0"))
		   	f.warning_box("ATTENZIONE: il soggetto ha almeno una categoria non donatori. Verificare!"); 
	}   
	return TRUE;	
}

bool TGestioneSoggetti::dataconv_handler(TMask_field& f, KEY k)
{
	if ((k == K_TAB) && (f.focusdirty()) && (!f.empty()))
	{ 
		const char modstato = modstato_tcs(f.mask().get(F_STATO));
		const char modstatosi = modstato_tcs(f.mask().get(F_STATOSI));		
		if (modstato == 'S' || modstatosi == 'S')
		{
			f.error_box("ATTENZIONE!\nSoggetto sospeso.\nNon e' possibile inserire una convocazione.");
			f.mask().set(F_DATACONV, app()._oldconv);
		}	
		else
		 	if (yesno_box("ATTENZIONE!\nNuova convocazione per il soggetto.\nConfermare la convocazione?"))
		 	{
				TLocalisamfile rconvoc(LF_RCONVOC);
				rconvoc.setkey(3);
				rconvoc.zero();
				rconvoc.put(RCV_CODICE, f.mask().get(F_CODICE));
				rconvoc.put(RCV_DATACONV, f.mask().get(F_DATACONV));
				if (rconvoc.read() == NOERR)
				{
					if (!(rconvoc.get_bool(RCV_ANNULLATO)))                      
					{
						f.error_box("Convocazione gia' esistente per il soggetto");
						f.mask().set(F_DATACONV, app()._oldconv);
					}						
					else
					{
			 			app()._nuovaconv = TRUE;
			 			f.mask().field(F_STAMPATACONV).enable();
					}			 			
				}		 			
		 	  else
		 	  {
		 			app()._nuovaconv = TRUE;
		 			f.mask().field(F_STAMPATACONV).enable();
				}		 			
			}	 		
		else
			f.mask().set(F_DATACONV, app()._oldconv);
	}		
	return TRUE;	
}

bool TGestioneSoggetti::eseguigen_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TMask& m = f.mask();
		const int quante = m.get_int(F_QUANTEGEN);
		if (quante > 0)
		{
			const bool automatica = (m.get(F_COMEGEN) == "A");
			TDate finoal = m.get_date(F_FINOALGEN);
			TSheet_field& g = (TSheet_field&)m.field(F_DONGEN);
			g.destroy();
			const TString16 tipo = m.get(F_TIPOGEN);
			const TString16 luogo = m.get(F_LUOGOGEN);
			for (int r=0;r<quante;r++)
			{
				TToken_string& row = g.row(r);
				if (automatica)
				{
					row.add(finoal,0);
					finoal -=90;
				}				
				row.add(tipo,1);
				row.add(luogo,2);
			}
			g.force_update();
		}
		else
			f.error_box("Non e' possibile generare meno di 1 donazione");
	}	
	return TRUE;
}

bool TGestioneSoggetti::nome_handler(TMask_field& f, KEY k)
{ 
	/*
  if (k == K_TAB && f.focusdirty())
  {
  	TMask& m = f.mask();
  	long codsog = m.get_long(F_ES_CODICE);
  	if (codsog == 0)
  	{
      f.on_key(K_F9);
      m.field(F_ES_CODICE).on_key(K_TAB);
		}      
  }	
  */
  if (f.to_check(k))
  {
  	TMask& m = f.mask();
  	long codsog = m.get_long(F_ES_CODICE);
  	if (codsog == 0)
  	{
      f.on_key(K_F9);
      m.field(F_ES_CODICE).on_key(K_TAB);
    }  
  }	
  return TRUE;
}

bool TGestioneSoggetti::collega_handler(TMask_field& f, KEY k)
{               
	TMask& m = f.mask();
	long codfam = m.get_long(F_ES_CODICE);
	if (codfam != 0)
	{
		TLocalisamfile fam(LF_FAMIGLIE);
		fam.setkey(2);
		TRectype& recfam = fam.curr();
		recfam.zero();
		recfam.put(FAM_CODFAM, codfam);
		if (fam.read() == NOERR)
		{
			TRectype* key = new TRectype(LF_FAMIGLIE);
			key->put(FAM_FAMIGLIA, fam.get_long(FAM_FAMIGLIA));
			TRecord_array a_famiglia(LF_FAMIGLIE, FAM_PROGFAM);
			a_famiglia.read(key);
			TSheet_field& s = (TSheet_field&)m.field(F_FAMIGLIARI);
			s.destroy();                                         	
			for (int r=1; r<=a_famiglia.rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = a_famiglia.row(r);
				row.add(riga.get(FAM_GRADOPAR));
				row.add(riga.get(FAM_CODFAM));
				s.check_row(r-1);
			}
			const int ar = s.items();
			TToken_string& row = s.row(ar);
			row.add("  ");
			row.add(app()._codice);
			s.check_row(ar);
			s.force_update();
			m.show(F_FAMIGLIARI);
			m.hide(-1);
		}			
	}
	return TRUE;
}

bool TGestioneSoggetti::nuova_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		app()._famatt = -1;	// significa che devo attribuire alla famiglia un nuovo codice
		TMask& m = f.mask();
		TSheet_field& s = (TSheet_field&)m.field(F_FAMIGLIARI);
		TToken_string& row = s.row(0);
		row.add("CA");
		row.add(app()._codice);
		s.check_row(0);
		s.force_update(0);
		m.show(F_FAMIGLIARI);
		m.hide(-1);
	}
	return TRUE;
}

bool TGestioneSoggetti::famiglia_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TMask& m = f.mask();
		app()._codice = m.get_long(F_CODICE);
		TMask msk("at0100c");
		msk.set_handler(F_ES_CODICE, collega_handler);
		msk.set_handler(F_ES_COGNOME, collega_handler);
		msk.set_handler(F_ES_NOME, nome_handler);
		msk.set_handler(F_NUOVA,nuova_handler);
		TSheet_field& s = (TSheet_field&)msk.field(F_FAMIGLIARI);
		s.set_notify(famiglia_notify);
		s.destroy();                                         	
		for (int r=1; r<=app()._sfamiglia->rows(); r++)
		{
			TToken_string& row = s.row(r-1);
			const TRectype& riga = app()._sfamiglia->row(r);
			row.add(riga.get(FAM_GRADOPAR));
			row.add(riga.get(FAM_CODFAM));
			s.check_row(r-1);
		}
		if (app()._sfamiglia->rows() == 0)
		{                        
			msk.show(-1);
			msk.hide(F_FAMIGLIARI);
		}
		else
		{   
			s.force_update();
			msk.hide(-1);
			msk.show(F_FAMIGLIARI);
		}
		
		if (msk.run() == K_ENTER)
		{                      
			app()._sfamiglia->destroy_rows();
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = app()._sfamiglia->row(r,TRUE);
				rec.put(FAM_GRADOPAR, row.get(0));
				rec.put(FAM_CODFAM, row.get());
			}	
		}
	}
	return TRUE;
}

bool TGestioneSoggetti::genera_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TMask msk("at0100b");
		msk.set_handler(F_ESEGUIGEN,eseguigen_handler);
		
  	if (msk.run() == K_ENTER) 
  	{
			TSheet_field& g = (TSheet_field&)msk.field(F_DONGEN);
			if (g.items() > 0)
			{
  			TMask& m = f.mask();
				TSheet_field& s = (TSheet_field&)m.field(F_DONAZIONI);
				for (int r=0;r<g.items();r++)
				{
					TToken_string& row = s.row(-1);
					TToken_string& rowgen = g.row(r);
					row.add(rowgen.get(0));
					row.add(rowgen.get());
					row.add(rowgen.get());
				}
				ordina_sheet_data(s);
 				s.force_update();
 				app().calcola_donazioni(m, s);
 				const int totdonsi = m.get_int(F_TOTDONSI);
 				const int totdonaf = m.get_int(F_TOTDONAF);
 				m.set(F_TOTDON,totdonsi+totdonaf);
 				
			}			
  	}
	}
	return TRUE;	
}

bool TGestioneSoggetti::ricparz_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TMask msk("at0100d");
  	if (msk.run() == K_ENTER) 
  	{ 
  		TString filtro;
  		if (!msk.field(F_RP_DATANASC).empty())
  			filtro << "(ANSI(" << SOG_DATANASC << ")=\"" 
  						 << msk.get_date(F_RP_DATANASC).string(ANSI) << "\")";
  		if (!msk.field(F_RP_COGNOME).empty())
  		{       
  			if (filtro.not_empty())
  				filtro << "&&"; 
  			filtro << '(' << SOG_COGNOME << "?=\"" 
  						 << msk.get(F_RP_COGNOME) << "\")"; 
  		}				 
  		if (!msk.field(F_RP_NOME).empty())
  		{       
  			if (filtro.not_empty())
  				filtro << "&&"; 
  			filtro << '(' << SOG_NOME << "?=\"" 
  						 << msk.get(F_RP_NOME) << "\")"; 
  		}				 
  		TCursor cur(app().get_relation(), filtro, 2);
  		TToken_string fields,head;
  		fields.add(SOG_CODICE); head.add("Codice@9");
  		fields.add(SOG_COGNOME); head.add("Cognome@25");
  		fields.add(SOG_NOME); head.add("Nome@25");
  		fields.add(SOG_DATANASC); head.add("Nato il@10");
  		fields.add(SOG_CODSEZ); head.add("Sez.");
  		fields.add(SOG_CODSOT); head.add("Sot.");
  		fields.add(SOG_TESSAVIS); head.add("Tessera");
  		TCursor_sheet srp(&cur,fields,"RICERCA SOGGETTI",head);
  		if (srp.run() == K_ENTER)
  		{
  			TToken_string row = srp.row();
  			f.mask().set(F_CODICE, row.get(0));
  			f.mask().send_key(K_TAB,F_CODICE);
  		}
  	}
	}
	return TRUE;	
}

bool TGestioneSoggetti::convoc_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TString filtro;
		long codice = f.mask().get_long(F_CODICE);
		if (codice != 0)
		{
 			TRelation relconv = TRelation(LF_RCONVOC);
 			relconv.add(LF_CONVOC, "NUMERO==NUMERO");
 			TRectype recrconv(LF_RCONVOC);
 			recrconv.put(RCV_CODICE, codice);
			TCursor cur(&relconv, "", 3, &recrconv, &recrconv);
			TToken_string fields,head;
			fields.add(RCV_DATACONV); head.add("Data cart.");
			fields.add("115->PUNTO"); head.add("Punto");
			fields.add(RCV_CHIAMATA); head.add("Tipo");
			fields.add(RCV_STAMPATO); head.add("St.");
			fields.add(RCV_ANNULLATO); head.add("Ann.");
			fields.add("115->DATA"); head.add("Data conv.");
			fields.add(RCV_NUMERO); head.add("Conv.num.");
			TCursor_sheet sconv(&cur,fields,"Convocazioni del soggetto",head);
			sconv.run();
		}			
	}
	return TRUE;	
}

void TGestioneSoggetti::tipocon_set_row(TMask& m)
{
	const TString16 tipo = m.get(F_C_TIPOCON);
	const char modstato = modstato_tcs(tipo);
  if ( modstato == 'I' || modstato == 'M')
  {
		m.field(F_C_IDON1).enable();
		m.field(F_C_IDON2).enable();
		m.field(F_C_IDON3).enable();
		m.field(F_C_IDON4).enable();
		m.field(F_C_INTSI).disable();
		m.field(F_C_INTAF).disable();
		TString16 idon1 = m.get(F_C_IDON1);
		TString16 idon2 = m.get(F_C_IDON2);
		TString16 idon3 = m.get(F_C_IDON3);
		TString16 idon4 = m.get(F_C_IDON4);
		// propongo i dati precedenti per idoneita'
		if (idon1.empty() && idon2.empty() && idon3.empty() && idon4.empty())
		{
			const TMask& mask = *(app().get_mask());
			m.set(F_C_IDON1,mask.get(F_IDON1));
			m.set(F_C_IDON2,mask.get(F_IDON2));
			m.set(F_C_IDON3,mask.get(F_IDON3));
			m.set(F_C_IDON4,mask.get(F_IDON4));
			m.set(F_C_INTSI,mask.get(F_INTSI));
			m.set(F_C_INTAF,mask.get(F_INTAF));
			idon1 = m.get(F_C_IDON1);
			idon2 = m.get(F_C_IDON2);
			idon3 = m.get(F_C_IDON3);
			idon4 = m.get(F_C_IDON4);
		}
		if (is_idon(idon1,idon2,idon3,idon4,IDON_SI))
			m.field(F_C_INTSI).enable();
		else
			m.field(F_C_INTSI).reset();					
		if (is_idon(idon1,idon2,idon3,idon4,IDON_AF))
			m.field(F_C_INTAF).enable();
		else			
			m.field(F_C_INTAF).reset();					
  }
  else
	{
		m.field(F_C_IDON1).reset();
		m.field(F_C_IDON1).disable();
		m.field(F_C_IDON2).reset();
		m.field(F_C_IDON2).disable();
		m.field(F_C_IDON3).reset();
		m.field(F_C_IDON3).disable();
		m.field(F_C_IDON4).reset();
		m.field(F_C_IDON4).disable();
		m.field(F_C_INTSI).reset();
		m.field(F_C_INTSI).disable();
		m.field(F_C_INTAF).reset();
		m.field(F_C_INTAF).disable();
	}
}	

void TGestioneSoggetti::idosos_set_row(TMask& m)
{
	const TString16 idosos = m.get(F_I_IDO_SOS);
  if (idosos == IDONEITA)
  {
		m.field(F_I_INTERVALLO).enable();
		const int intervallo = m.get_int(F_I_INTERVALLO);
		if (intervallo==0)
		{
			const TMask& mask = *(app().get_mask());
			const TString idon = m.get(F_I_TIPOIDO);
			if (idon == IDON_SI)
				m.set(F_I_INTERVALLO,mask.get(F_INTSI));
			else
				m.set(F_I_INTERVALLO,mask.get(F_INTAF));
		}			
		m.field(F_I_FINESOS).reset();
		m.field(F_I_FINESOS).disable();
  }
  else
	{
		m.field(F_I_INTERVALLO).reset();
		m.field(F_I_INTERVALLO).disable();
		m.field(F_I_FINESOS).enable();
	}
}	

void TGestioneSoggetti::tipocon_set_sheet(TSheet_field& s)
{
	for (int r=0;r<s.items();r++)
	{
		TToken_string& row = s.row(r);
		const TString16 tipo = row.get(1);
		const char modstato = modstato_tcs(tipo);
		if (modstato == 'I' || modstato == 'M')
		{
			s.enable_cell(r,2);		
			s.enable_cell(r,3);		
			s.enable_cell(r,4);		
			s.enable_cell(r,5);		
			const TString16 idon1 = row.get(2);
			const TString16 idon2 = row.get(3);
			const TString16 idon3 = row.get(4);
			const TString16 idon4 = row.get(5);
			if (is_idon(idon1,idon2,idon3,idon4,IDON_SI))
				s.enable_cell(r,6);
			else
				s.disable_cell(r,6);
			if (is_idon(idon1,idon2,idon3,idon4,IDON_AF))
				s.enable_cell(r,7);		
			else				
				s.disable_cell(r,7);		
		}
		else
		{
			s.disable_cell(r,2);		
			s.disable_cell(r,3);		
			s.disable_cell(r,4);		
			s.disable_cell(r,5);		
			s.disable_cell(r,6);		
			s.disable_cell(r,7);		
		}
	}
}

void TGestioneSoggetti::idosos_set_sheet(TSheet_field& s)
{
	for (int r=0;r<s.items();r++)
	{
		TToken_string& row = s.row(r);
		const TString16 idosos = row.get(2);
		if (idosos == IDONEITA)
		{
			s.enable_cell(r,3);		
			s.disable_cell(r,4);
		}
		else
		{
			s.disable_cell(r,3);		
			s.enable_cell(r,4);		
		}
	}
}

bool TGestioneSoggetti::idoncon_handler(TMask_field& f, KEY k)
{
	if (f.to_check(k))
	{
		TMask& m = f.mask();
		const TString16 idon = f.get();
		if (is_idon_one(idon,IDON_SI))
			m.field(F_C_INTSI).enable();
		if (is_idon_one(idon,IDON_AF))
			m.field(F_C_INTAF).enable();
	}
	return TRUE;
}	    

bool TGestioneSoggetti::tipocon_handler(TMask_field& f, KEY k)
{
  if (f.to_check(k))
  { 
    TMask& m = f.mask();
    app().tipocon_set_row(m);
 		if (app()._ctrlpass)
 		{
	  	TString80 responsab = m.get(F_C_RESPONSAB);
	  	if (responsab.empty())
	  		m.set(F_C_RESPONSAB, user());
 		}    
	}    
	return TRUE;
}	    

bool TGestioneSoggetti::idosos_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  { 
    TMask& m = f.mask();
    app().idosos_set_row(m);
 		if (app()._ctrlpass)
 		{
	  	TString80 responsab = m.get(F_I_RESPONSAB);
	  	if (responsab.empty())
	  		m.set(F_I_RESPONSAB, user());
 		}    
	}    
	return TRUE;
}	    

bool TGestioneSoggetti::gruppo_handler(TMask_field& f, KEY k)
{          
	bool ok = TRUE;                  
	if (f.to_check(k))
	{
		const TString gr = f.get();
		if ((gr != app()._oldgruppo) && (app()._oldgruppo.not_empty()))
			ok = f.yesno_box("Attenzione. E' stato modificato il gruppo sanguigno. Confermi?");
		if (ok)	
			app()._oldgruppo =  gr;
		else
			f.set(app()._oldgruppo);	
	}
	return ok;
}	    

bool TGestioneSoggetti::rhantid_handler(TMask_field& f, KEY k)
{          
	bool ok = TRUE;                  
	if (f.to_check(k))
	{
		const TString gr = f.get();
		if ((gr != app()._oldrh) && (app()._oldrh.not_empty()))
			ok = f.yesno_box("Attenzione. E' stato modificato il valore rh/antid. Confermi?");
		if (ok)	
			app()._oldrh =  gr;
		else
			f.set(app()._oldrh);	
	}
	return ok;
}	    

bool TGestioneSoggetti::kell_handler(TMask_field& f, KEY k)
{          
	bool ok = TRUE;                  
	if (f.to_check(k))
	{
		const TString gr = f.get();
		if ((gr != app()._oldkell) && (app()._oldkell.not_empty()))
			ok = f.yesno_box("Attenzione. E' stato modificato il kell. Confermi?");
		if (ok)	
			app()._oldkell =  gr;
		else
			f.set(app()._oldkell);	
	}
	return ok;
}	    

bool TGestioneSoggetti::fenotiporh_handler(TMask_field& f, KEY k)
{          
	bool ok = TRUE;                  
	if (f.to_check(k))
	{
		const TString gr = f.get();
		if ((gr != app()._oldfen) && (app()._oldfen.not_empty()))
			ok = f.yesno_box("Attenzione. E' stato modificato il fenotipo rh. Confermi?");
		if (ok)	
			app()._oldfen =  gr;
		else
			f.set(app()._oldfen);	
	}
	return ok;
}	    

bool TGestioneSoggetti::du_handler(TMask_field& f, KEY k)
{          
	bool ok = TRUE;                  
	if (f.to_check(k))
	{
		const TString gr = f.get();
		if ((gr != app()._olddu) && (app()._olddu.not_empty()))
			ok = f.yesno_box("Attenzione. E' stato modificato il du. Confermi?");
		if (ok)	
			app()._olddu =  gr;
		else
			f.set(app()._olddu);	
	}
	return ok;
}	    

void TGestioneSoggetti::on_firm_change()
{
	_rel->lfile().last();
	_lastcod = _rel->lfile().get_long(SOG_CODICE);
}

bool TGestioneSoggetti::user_create()
{
	_msk = new TMask("at0100a");
	_rel = new TRelation(LF_SOGGETTI);
	
	_donaz 		= new TLocalisamfile(LF_DONAZ);
	_contsan 	= new TLocalisamfile(LF_CONTSAN);
	_benem 		=	new TLocalisamfile(LF_BENEM);
	_storico 	=	new TLocalisamfile(LF_STORICO);
	_famiglie = new TLocalisamfile(LF_FAMIGLIE);
	_convoc 	= new TLocalisamfile(LF_CONVOC);
	_rconvoc 	= new TLocalisamfile(LF_RCONVOC);
	_idoneita = new TLocalisamfile(LF_IDONEITA);
	
	_sdonazioni 	= new TRecord_array(LF_DONAZ,DON_PROGDON);
	_scontrolli 	= new TRecord_array(LF_CONTSAN,CON_PROGCON);
	_sbenemerenze = new TRecord_array(LF_BENEM,BEN_PROGBEN);	
	_sstorico 		= new TRecord_array(LF_STORICO,STO_PROGSTO);	
	_sfamiglia 		= new TRecord_array(LF_FAMIGLIE, FAM_PROGFAM);
	_sidoneita 		= new TRecord_array(LF_IDONEITA, IDO_PROGIDO);

	_msk->set_handler(F_RICPARZ,ricparz_handler);
	_msk->set_handler(F_CONVOCAZIONI,convoc_handler);
	_msk->set_handler(F_DATANASC,datanasc_handler);
	_msk->set_handler(F_CATDON,catdon_handler);
	_msk->set_handler(F_DATACONV,dataconv_handler);
	_msk->set_handler(F_GENERA,genera_handler);
	_msk->set_handler(F_FAMIGLIA,famiglia_handler);
	_msk->set_handler(F_DONPRECSI,donprecsi_handler);
	_msk->set_handler(F_DONPRECAF,donprecaf_handler);
	_msk->set_handler(F_GRUPPOAB0,gruppo_handler);
	_msk->set_handler(F_RHANTID,rhantid_handler);
	_msk->set_handler(F_KELL,kell_handler);
	_msk->set_handler(F_FENOTIPORH,fenotiporh_handler);
	_msk->set_handler(F_DU,du_handler);
	TSheet_field& sd = (TSheet_field&)_msk->field(F_DONAZIONI);
	sd.set_handler(donazioni_handler);
	sd.set_notify(donazioni_notify);
	TMask& sdmask = sd.sheet_mask();
	sdmask.set_handler(F_D_DATADON, datadon_handler);
	
	TSheet_field& sc = (TSheet_field&)_msk->field(F_CONTROLLI);
	sc.set_handler(controlli_handler);
	sc.set_notify(controlli_notify);
  TMask& scmask = sc.sheet_mask();
	scmask.set_handler(F_C_DATACON, datacon_handler);
	scmask.set_handler(F_C_TIPOCON, tipocon_handler);
	scmask.set_handler(F_C_IDON1, idoncon_handler);
	scmask.set_handler(F_C_IDON2, idoncon_handler);
	scmask.set_handler(F_C_IDON3, idoncon_handler);
	scmask.set_handler(F_C_IDON4, idoncon_handler);

	TSheet_field& si = (TSheet_field&)_msk->field(F_IDONEITA);
	si.set_handler(idoneita_handler);
	si.set_notify(idoneita_notify);
  TMask& simask = si.sheet_mask();
	simask.set_handler(F_I_IDO_SOS, idosos_handler);

	TSheet_field& sb = (TSheet_field&)_msk->field(F_BENEMERENZE);
	sb.set_handler(benem_handler);
	sb.set_notify(benemerenze_notify);
	TSheet_field& ss = (TSheet_field&)_msk->field(F_STORICO);
	ss.set_handler(storico_handler);
	ss.set_notify(storico_notify);

	_rel->lfile().last();
	_lastcod = _rel->lfile().get_long(SOG_CODICE);
	
	_famiglie->last();
	_lastfam = _famiglie->get_long(FAM_FAMIGLIA);
	_famatt = _famprec = 0;
	
	set_search_field(F_COGNOME);
	
  TConfig config(CONFIG_STUDIO);
  _numdon1 = config.get_int("NumDon1");
  _numdon2 = config.get_int("NumDon2");
  _catini1 = config.get("CatIni1");
  _catfin1 = config.get("CatFin1");
  _catini2 = config.get("CatIni2");
  _catfin2 = config.get("CatFin2");
  _sttess2 = config.get_bool("StTess2");
  _dataisc = config.get_bool("DataIsc");
  _ctrlpass = config.get_bool("CtrlPass");
	if (_ctrlpass)
		_permesso = richiesta_password();
	return TRUE;
}	
	
bool TGestioneSoggetti::user_destroy()	
{
	delete _sidoneita;
	delete _sfamiglia;
	delete _sstorico;
	delete _sbenemerenze;
	delete _scontrolli;
	delete _sdonazioni;
	delete _idoneita;
	delete _rconvoc;
	delete _convoc;
	delete _famiglie;
	delete _storico;
	delete _benem;
	delete _contsan;
	delete _donaz;	
	delete _rel;
	delete _msk;
	return TRUE;
}

const char* TGestioneSoggetti::get_next_key()
{
	// per gestione famiglie
	_famatt = _famprec = 0;
	// autonumerazione progressiva dei soggetti
	return format("%d|%ld", F_CODICE, _lastcod+1 );
}	

bool TGestioneSoggetti::remove()
{
 	// cancella donazioni
 	// cancella controlli sanitari
 	// cancella storico
 	// sistema nucleo familiare	** da fare
 	// annulla convocazioni del soggetto
 	// alla fine: cancella il soggetto!
 	
 	bool ok = TRUE;
	int err; 	
 	ok = yesno_box("ATTENZIONE!\nCon questa operazione si elimina definitivamente tutta la scheda del soggetto.\nConfermare l'eliminazione?");
  
  if (ok)
  {
	 	// cancella donazioni
		err = _sdonazioni->remove();	
	  if (err == _iseof || err == _isemptyfile)
			err = NOERR;
		
		// cancella controlli sanitari	
		if (err = NOERR) err = _scontrolli->remove();
		if (err == _iseof || err == _isemptyfile)
			err = NOERR;
	
		// cancella benemerenze
		if (err = NOERR) err = _sbenemerenze->remove();
		if (err == _iseof || err == _isemptyfile)
			err = NOERR;
	
	 	// cancella storico
		if (err == NOERR) err = _sstorico->remove();	
	  if (err == _iseof || err == _isemptyfile)
			err = NOERR;
		
		// cancellare le convocazioni del soggetto
			
		// cancella il soggetto	
		if (err == NOERR) ok = TRelation_application::remove();
		return (ok && err==NOERR);
	}		
	else
		return TRUE;
}

int TGestioneSoggetti::read(TMask& m)
{
	_famatt = _famprec = 0;
	_nuovaconv = FALSE;
	_oldconv = NULLDATE;
	int err = TRelation_application::read(m);
	if (err == NOERR)
	{
		_oldconv = m.get_date(F_DATACONV);
		m.field(F_STAMPATACONV).reset();
		m.field(F_STAMPATACONV).disable();
		TRectype* key = new TRectype(LF_DONAZ);
		key->put(DON_CODICE, m.get(F_CODICE));
		err = _sdonazioni->read(key);
		if (err == NOERR)
		{
			TSheet_field& s = (TSheet_field&)m.field(F_DONAZIONI);
			s.destroy();
			for (int r=1; r<=_sdonazioni->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _sdonazioni->row(r);
				row.add(riga.get(DON_DATADON));			// 0
				row.add(riga.get(DON_TIPODON));			// 1
				row.add(riga.get(DON_LUOGODON));		// 2
				row.add("");	// descrizione luogo	// 3
				row.add(riga.get(DON_ETICHETTA));		// 4
				row.add(riga.get(DON_PRIMADON));		// 5
				row.add(riga.get(DON_CODSEZ));			// 6
				row.add(riga.get(DON_CODSOT));			// 7
				row.add("");	// denominazione sezione		// 8
				row.add("");	// denominazione sottogruppo// 9
				row.add(riga.get(DON_CC));					// 10
				row.add(riga.get(DON_PA));          // 11
				row.add(riga.get(DON_HB));					// 12
				row.add(riga.get(DON_SGPT));				// 13
				row.add(riga.get(DON_PROTIDEMIA));	// 14
				s.check_row(r-1);
			}
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}
	if (err == NOERR)
	{
		TRectype* key = new TRectype(LF_CONTSAN);
		key->put(CON_CODICE, m.get(F_CODICE));
		err = _scontrolli->read(key);
		if (err == NOERR)
		{
			TSheet_field& s = (TSheet_field&)m.field(F_CONTROLLI);
			s.destroy();
			for (int r=1; r<=_scontrolli->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _scontrolli->row(r);
				row.add(riga.get(CON_DATACON));
				row.add(riga.get(CON_TIPOCON));
				row.add(riga.get(CON_IDON1));
				row.add(riga.get(CON_IDON2));
				row.add(riga.get(CON_IDON3));
				row.add(riga.get(CON_IDON4));
				row.add(riga.get(CON_INTSI));
				row.add(riga.get(CON_INTAF));
				row.add(riga.get(CON_PROSSTIPO));
				row.add(riga.get(CON_PROSSDATA));
				row.add(riga.get(CON_MOTIVO));
				row.add(riga.get(CON_RESPONSAB));
			}
			TGestioneSoggetti::tipocon_set_sheet(s);
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}
	if (err == NOERR)
	{
		TRectype* key = new TRectype(LF_IDONEITA);
		key->put(IDO_CODICE, m.get(F_CODICE));
		err = _sidoneita->read(key);
		if (err == NOERR)
		{
			TSheet_field& s = (TSheet_field&)m.field(F_IDONEITA);
			s.destroy();
			for (int r=1; r<=_sidoneita->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _sidoneita->row(r);
				row.add(riga.get(IDO_DATAIDO));
				row.add(riga.get(IDO_TIPOIDO));
				row.add(riga.get(IDO_IDO_SOS));
				row.add(riga.get(IDO_INTERVALLO));
				row.add(riga.get(IDO_FINESOS));
				row.add(riga.get(IDO_MOTIVO));
				row.add(riga.get(IDO_RESPONSAB));
			}
			TGestioneSoggetti::idosos_set_sheet(s);
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}

	if (err == NOERR)
	{
		TRectype* key = new TRectype(LF_BENEM);
		key->put(BEN_CODICE, m.get(F_CODICE));
		err = _sbenemerenze->read(key);
		if (err == NOERR)
		{
			TSheet_field& s = (TSheet_field&)m.field(F_BENEMERENZE);
			s.destroy();
			for (int r=1; r<=_sbenemerenze->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _sbenemerenze->row(r);
				row.add(riga.get(BEN_TIPOBEN));
				row.add("");	// descrizione benemerenze
				row.add(riga.get(BEN_DATAMAT));
				row.add(riga.get(BEN_BONUS));
				row.add(riga.get(BEN_DATABEN));
				row.add(riga.get(BEN_DATACON));
				row.add(riga.get(BEN_RITIRATA));
				row.add(riga.get(BEN_CODSEZ));
				row.add(riga.get(BEN_CODSOT));
				row.add(riga.get(BEN_GRUPPOAZIE));
				row.add("");	// denominazione sezione
				row.add("");	// denominazione sottogruppo
				row.add("");	// denominazione gruppo aziendale
				s.check_row(r-1);
			}
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}	
	if (err == NOERR)
	{
		TRectype* key = new TRectype(LF_STORICO);
		key->put(STO_CODICE, m.get(F_CODICE));
		err = _sstorico->read(key);
		if (err == NOERR)
		{
			TSheet_field& s = (TSheet_field&)m.field(F_STORICO);
			s.destroy();
			for (int r=1; r<=_sstorico->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _sstorico->row(r);
				row.add(riga.get(STO_DATAISC));
				row.add(riga.get(STO_DATADIM));
				row.add(riga.get(STO_CODSEZ));
				row.add(riga.get(STO_CODSOT));
				row.add(riga.get(STO_CATISC));
				row.add(riga.get(STO_MOTDIM));
			}
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}	
	if (err == NOERR)
	{
		TLocalisamfile fam(LF_FAMIGLIE);
		fam.setkey(2);
		TRectype& recfam = fam.curr();
		recfam.zero();
		recfam.put(FAM_CODFAM, m.get(F_CODICE));
		if (fam.read() == NOERR)
		{
			TRectype* key = new TRectype(LF_FAMIGLIE);
			_famprec = _famatt = fam.get_long(FAM_FAMIGLIA);
			key->put(FAM_FAMIGLIA, _famprec);
			_sfamiglia->read(key);
		}			
		else
		{
			_famprec = _famatt = 0;
			_sfamiglia->destroy_rows();			
		}			
	}
	return err;
}

int TGestioneSoggetti::write(const TMask& m)
{  
	long curcod = m.get_long(F_CODICE);
	if (curcod > _lastcod) _lastcod = curcod;
	return TGestioneSoggetti::scrivi(m, FALSE);	
}

int TGestioneSoggetti::rewrite(const TMask& m)
{
	return TGestioneSoggetti::scrivi(m, TRUE);	
}

int TGestioneSoggetti::scrivi(const TMask& m, bool ri)
{                             
	// questo trucco � autorizzato dal capo!
	bool ok = TRUE;
	int err = NOERR;
	TMask& hmask = (TMask&) m;
	if (ok)
	{	
		TDate oggi(TODAY);
		hmask.set(F_DATAULTAGG,oggi);
		hmask.set(F_UTENULTAGG,user());
		const TDate dataprossi = hmask.get_date(F_DATAPROSSI);
		const TDate dataconv = hmask.get_date(F_DATACONV);
		const char stato = modstato_tcs(hmask.get(F_STATO));
		const TString16 statosi = hmask.get(F_STATOSI);
		// cancellazione la data convocazione se sospeso
		// o se � venuto a donare (la dataprossi diventa > della dataconvoc.
		if ((stato == 'S') || (statosi == SOSPENSIONE) || (dataprossi > dataconv) || !dataprossi.ok())
		{
			TLocalisamfile rconvoc(LF_RCONVOC);
			rconvoc.setkey(3);
			rconvoc.zero();
			rconvoc.put(RCV_CODICE, hmask.get(F_CODICE));
			rconvoc.put(RCV_DATACONV, dataconv);
			if (rconvoc.read() == NOERR)
			{
				rconvoc.put(RCV_ANNULLATO, TRUE);
				int err = rconvoc.rewrite();
			}
			const TDate datanulla(NULLDATE);
			hmask.set(F_DATACONV, datanulla);
			hmask.set(F_DATAULTSOL, datanulla);
			const int numzero = 0;
			hmask.set(F_NUMCONV,numzero);
		}	
		
		TDate dataisc = hmask.get_date(F_DATAISC);
		if (!dataisc.ok() && _dataisc)
		{ 
			// attenzione: questa operazione viene eseguita due volte
			// togliere!
			if (hmask.get_date(F_DATAPRISI).ok())
				hmask.set(F_DATAISC,hmask.get(F_DATAPRISI));
			else
			{
				TSheet_field& s = (TSheet_field&)m.field(F_DONAZIONI);
				if (s.items()>0)
				{
					ordina_sheet_data(s);
					TToken_string& row = s.row(0);
					hmask.set(F_DATAISC,row.get(0));
				}			
			}			
		}
		err = ri ? TRelation_application::rewrite(m) : TRelation_application::write(m);
		if (err == NOERR)
		{
			_sdonazioni->destroy_rows();
			TSheet_field& s = (TSheet_field&)m.field(F_DONAZIONI);
			TRectype* key = new TRectype(LF_DONAZ);
			key->put(DON_CODICE, m.get(F_CODICE));
			_sdonazioni->set_key(key);
			
			ordina_sheet_data(s);
			
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = _sdonazioni->row(r,TRUE);
				rec.put(DON_DATADON, row.get(0));	
				rec.put(DON_TIPODON, row.get());	//	1
				rec.put(DON_LUOGODON, row.get());	//	2
				// descrizione luogo							//	3
				rec.put(DON_ETICHETTA, row.get(4));	
				rec.put(DON_PRIMADON, row.get());	//	5
				TString16 codsez = row.get(6);
				TString16 codsot = row.get(7);
				if (codsez.blank())
				{
					codsez = hmask.get(F_CODSEZ);
					codsot = hmask.get(F_CODSOT);
				}	
				rec.put(DON_CODSEZ, codsez);		//	6
				rec.put(DON_CODSOT, codsot);		//	7
				// denominazione sezione					//	8
				// denominazione sottogruppo			//	9
				rec.put(DON_CC, row.get(10));
				rec.put(DON_PA, row.get());				//	11
				rec.put(DON_HB, row.get());				//	12
				rec.put(DON_SGPT, row.get());			//	13
				rec.put(DON_PROTIDEMIA, row.get());	//	14
			}
			err = ri ? _sdonazioni->rewrite() : _sdonazioni->write();
		}
		if (err == NOERR)
		{
			_scontrolli->destroy_rows();
			TSheet_field& s = (TSheet_field&)m.field(F_CONTROLLI);
			TRectype* key = new TRectype(LF_CONTSAN);
			key->put(CON_CODICE, m.get(F_CODICE));
			_scontrolli->set_key(key);
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				if (row.empty_items())
					s.destroy(r-1);
			}                     
			ordina_sheet_data(s);		
			for (r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = _scontrolli->row(r,TRUE);
				rec.put(CON_DATACON,   row.get(0));
				rec.put(CON_TIPOCON,   row.get());
				rec.put(CON_IDON1,     row.get());
				rec.put(CON_IDON2,     row.get());
				rec.put(CON_IDON3,     row.get());
				rec.put(CON_IDON4,     row.get());
				rec.put(CON_INTSI,     row.get());
				rec.put(CON_INTAF, 		 row.get());
				rec.put(CON_PROSSTIPO, row.get());
				rec.put(CON_PROSSDATA, row.get());
				rec.put(CON_MOTIVO, 	 row.get());
				rec.put(CON_RESPONSAB, row.get());
			}
			err = ri ? _scontrolli->rewrite() : _scontrolli->write();
		}
		if (err == NOERR)
		{
			_sidoneita->destroy_rows();
			TSheet_field& s = (TSheet_field&)m.field(F_IDONEITA);
			TRectype* key = new TRectype(LF_IDONEITA);
			key->put(IDO_CODICE, m.get(F_CODICE));
			_sidoneita->set_key(key);
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				if (row.empty_items())
					s.destroy(r-1);
			}		                     
			ordina_sheet_data(s);
			for (r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = _sidoneita->row(r,TRUE);
				rec.put(IDO_DATAIDO,   row.get(0));
				rec.put(IDO_TIPOIDO,   row.get());
				rec.put(IDO_IDO_SOS, 	 row.get());
				rec.put(IDO_INTERVALLO,row.get());
				rec.put(IDO_FINESOS, 	 row.get());
				rec.put(IDO_MOTIVO, 	 row.get());
				rec.put(IDO_RESPONSAB, row.get());
			}
			err = ri ? _sidoneita->rewrite() : _sidoneita->write();
		}
		if (err == NOERR)
		{
			_sbenemerenze->destroy_rows();
			TSheet_field& s = (TSheet_field&)m.field(F_BENEMERENZE);
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				if (row.empty())
					s.destroy(r-1);
			}			
			s.force_update();
			TRectype* key = new TRectype(LF_BENEM);
			key->put(BEN_CODICE, m.get(F_CODICE));
			_sbenemerenze->set_key(key);
			                     
			ordina_sheet_data(s);
			
			for (r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = _sbenemerenze->row(r,TRUE);
				rec.put(BEN_TIPOBEN, 		row.get(0));
				rec.put(BEN_DATAMAT, 		row.get(2));
				rec.put(BEN_BONUS, 			row.get());
				rec.put(BEN_DATABEN, 		row.get());
				rec.put(BEN_DATACON, 		row.get());
				rec.put(BEN_RITIRATA, 	row.get());
				rec.put(BEN_CODSEZ, 		row.get());
				rec.put(BEN_CODSOT, 		row.get());
				rec.put(BEN_GRUPPOAZIE,	row.get());
			}
			err = ri ? _sbenemerenze->rewrite() : _sbenemerenze->write();
		}
		if (err == NOERR)
		{
			_sstorico->destroy_rows();
			TSheet_field& s = (TSheet_field&)m.field(F_STORICO);
			TRectype* key = new TRectype(LF_STORICO);
			key->put(STO_CODICE, m.get(F_CODICE));
			_sstorico->set_key(key);
			
			// ordinamento dello sheet storico
			ordina_sheet_data(s);
			
			for (int r=s.items(); r>0; r--)
			{
				TToken_string& row = s.row(r-1);
				TRectype& rec = _sstorico->row(r,TRUE);
				rec.put(STO_DATAISC, row.get(0));
				rec.put(STO_DATADIM, row.get());
				rec.put(STO_CODSEZ, row.get());
				rec.put(STO_CODSOT, row.get());
				rec.put(STO_CATISC, row.get());
				rec.put(STO_MOTDIM, row.get());
			}
			err = ri ? _sstorico->rewrite() : _sstorico->write();
		}
		if (err == NOERR)
		{ 
			if (_famatt == -1)
			{
				TRectype* key = new TRectype(LF_FAMIGLIE);
				key->put(FAM_FAMIGLIA, _lastfam+1);
				_sfamiglia->set_key(key);
				_lastfam = _lastfam+1;
			}
			if (_famatt != _famprec)
				err = ri ? _sfamiglia->rewrite() : _sfamiglia->write();
		}		
		if ((err == NOERR) && (_nuovaconv))
		{                  
			TDate datac = m.get_date(F_DATACONV);
			if (datac.ok())
			{
				TLocalisamfile rconvoc(LF_RCONVOC);
			
				int progconv = 0;
				TLocalisamfile convoc(LF_CONVOC);
				convoc.setkey(2);
				convoc.zero();
				convoc.put(COV_DATA, m.get(F_DATACONV));
				convoc.put(COV_PUNTO, m.get(F_PUNTOCONV));
				convoc.put(COV_TIPO, "SI");
				convoc.put(COV_CODSEZ, m.get(F_CODSEZ));
				convoc.put(COV_CODSOT, m.get(F_CODSOT));
				if (convoc.read() == NOERR)
				{
					rconvoc.setkey(1);
					rconvoc.zero();
					rconvoc.put(COV_NUMERO, convoc.get(RCV_NUMERO));
					TRectype r(rconvoc.curr());
					int items = 0;
				  for(rconvoc.read(); !rconvoc.eof(); rconvoc.next())
				  {   
				    if (rconvoc.curr() != r) break;
				    progconv = rconvoc.get_int(RCV_PROGCONV);
					}
					progconv++;
				}
				else
				{           
					progconv++;
					convoc.setkey(1);
					convoc.last();
					const long numero = convoc.get_long(COV_NUMERO)+1;
					convoc.zero();
					convoc.put(COV_DATA, m.get(F_DATACONV));
					convoc.put(COV_PUNTO, m.get(F_PUNTOCONV));
					convoc.put(COV_TIPO, "SI");
					convoc.put(COV_CODSEZ, m.get(F_CODSEZ));
					convoc.put(COV_CODSOT, m.get(F_CODSOT));
					convoc.put(COV_NUMERO, numero);
					convoc.put(COV_NOTE, "Convocazione automatica");
					convoc.write();
				}				
				rconvoc.setkey(3);
				rconvoc.zero();
				rconvoc.put(RCV_CODICE, m.get(F_CODICE));
				rconvoc.put(RCV_DATACONV, m.get(F_DATACONV));
				if ((rconvoc.read() != NOERR) || (rconvoc.get_bool(RCV_ANNULLATO)))
				{
					rconvoc.zero();
					rconvoc.put(RCV_CODICE, m.get(F_CODICE));
					rconvoc.put(RCV_DATACONV, m.get(F_DATACONV));
					rconvoc.put(RCV_NUMERO, convoc.get_long(COV_NUMERO));
					rconvoc.put(RCV_PROGCONV, progconv);
					rconvoc.put(RCV_CHIAMATA, 'C');
					rconvoc.put(RCV_STAMPATO, m.get(F_STAMPATACONV));
					err = rconvoc.write();
				}
			}			
		}
	}	
	return err;
}

void TGestioneSoggetti::c_reord(TSheet_field& s, TSheet_field& si)
{           
	const TDate datanulla(NULLDATE);
	TDate data(NULLDATE);
	TDate prossdata(NULLDATE);
	TString16 tipo = "  ";
	TString16 prosstipo = "  ";
	char modstato = ' ';			  
	int r_ultid = -1;					// riga ultima idoneit�
	int r_ultstato = -1;			// riga ultimo stato valido
	char penultstato = ' ';		// penultimo stato valido
	char ultstato = ' ';			// ultimo stato valido
	TDate dataultstato(NULLDATE);	// data ultimo stato valido
	
	for (int r=s.items()-1; r>=0; r--)
	{ 			
		TToken_string& row = s.row(r);
		tipo = row.get(1);
   	modstato = modstato_tcs(tipo);
 		if ((modstato != 'N') && (r_ultstato == -1))
 			r_ultstato = r;
 		else if ((modstato != 'N') && (penultstato == ' '))
					 penultstato = modstato;
		if ((modstato == 'I') && (r_ultid == -1))
			r_ultid = r;
 	}		
	TString16 id1 = '  ';		
	TString16 id2 = '  ';		
	TString16 id3 = '  ';		
	TString16 id4 = '  ';			
	int intsi = 0;
	int intaf = 0;
	tipo = '  ';
	prosstipo = '  ';
	data = TDate(NULLDATE);
	prossdata = TDate(NULLDATE);

 	if (r_ultid != -1)
 	{
 		TToken_string& row = s.row(r_ultid);
		data = TDate(row.get(0));
		tipo = row.get();
		id1 = row.get();		
		id2 = row.get();
		id3 = row.get();
		id4 = row.get();
		intsi = row.get_int();
		intaf = row.get_int();
 	}
	TMask& mask = s.mask();
	mask.field(F_DATAULTID).set(data);			
	mask.field(F_DATAULTID).on_key(K_TAB);
	mask.field(F_TIPOULTID).set(tipo);
	mask.field(F_TIPOULTID).on_key(K_TAB);
	mask.field(F_IDON1).set(id1);
	mask.field(F_IDON1).on_key(K_TAB);
	mask.field(F_IDON2).set(id2);
	mask.field(F_IDON2).on_key(K_TAB);
	mask.field(F_IDON3).set(id3);
	mask.field(F_IDON3).on_key(K_TAB);
	mask.field(F_IDON4).set(id4);
	mask.field(F_IDON4).on_key(K_TAB);
	mask.set(F_INTSI,intsi);
	mask.field(F_INTSI).on_key(K_TAB);
	mask.set(F_INTAF,intaf);
	mask.field(F_INTAF).on_key(K_TAB);

 	tipo = '  ';
 	if (r_ultstato != -1)
 	{
 	 	TToken_string& row = s.row(r_ultstato);
		dataultstato = TDate(row.get(0)); 	 	
		tipo = row.get();
		prosstipo = row.get(8);
		prossdata = TDate(row.get());
		ultstato = modstato_tcs(tipo);
	}
	mask.set(F_STATO,tipo);
	mask.field(F_STATO).on_key(K_TAB);
	mask.set(F_DATASTATO,dataultstato);
	mask.set(F_PROS_STATO,prosstipo);
	mask.field(F_PROS_STATO).on_key(K_TAB);
	mask.set(F_DATA_PROS,prossdata);
	  
	if (intsi>0)
	{
	  mask.set(F_STATOSI,tipo);
	  mask.set(F_DATASI,dataultstato);
	  //if (prosstipo == "FS")
	  if (modstato_tcs(prosstipo)=='F')
	  	mask.set(F_FINESOSSI,prossdata);
		else	  	
	  	mask.set(F_FINESOSSI,datanulla);
	}
	else
	{
	  mask.set(F_STATOSI,"  ");
	  mask.set(F_DATASI,datanulla);
	  mask.set(F_FINESOSSI,datanulla);
	}
	if (intaf>0)
	{
	  mask.set(F_STATOAF,tipo);
	  mask.set(F_DATAAF,dataultstato);
	  //if (prosstipo == "FS")
	  if (modstato_tcs(prosstipo)=='F')
		  mask.set(F_FINESOSAF,prossdata);
		else
		  mask.set(F_FINESOSAF,datanulla);
	}
	else
	{
	  mask.set(F_STATOAF,"  ");
	  mask.set(F_DATAAF,datanulla);
	  mask.set(F_FINESOSAF,datanulla);
	}
		                             
	/*	                             
  mask.set(F_STATOSI,"  ");
  mask.set(F_STATOAF,"  ");
  mask.set(F_DATASI,datanulla);
  mask.set(F_DATAAF,datanulla);
  mask.set(F_FINESOSSI,datanulla);
  mask.set(F_FINESOSAF,datanulla);
	*/  
	// riordino le idoneita
	for (int ri=0; ri<si.items(); ri++)
	{ 			  
		TToken_string& row = si.row(ri);
		TDate dataido = TDate(row.get(0));
		TString16 tipoido = row.get();
		TString16 ido_sos = row.get();
		int intervallo = row.get_int();
		TDate finesos = TDate(row.get());
		if (tipoido == IDON_SI)
			if ((intervallo != 0) && (intsi == 0))
			{
				mask.set(F_INTSI, intervallo);
				mask.field(F_INTSI).on_key(K_TAB);
			}					
		if (tipoido == IDON_AF)
			if ((intervallo != 0) && (intaf == 0))
			{
				mask.set(F_INTAF, intervallo);
				mask.field(F_INTAF).on_key(K_TAB);
			}					
		if (dataido >= dataultstato)
		{ 
			if (tipoido == IDON_SI)
			{
				mask.field(F_DATASI).set(dataido);			
				mask.field(F_STATOSI).set(ido_sos);			
				mask.field(F_FINESOSSI).set(finesos);
				if (intervallo != 0 && ido_sos == IDONEITA)
				{
					mask.set(F_INTSI,intervallo);
					if (id1 != IDON_SI && id2 != IDON_SI && id3 != IDON_SI && id4 != IDON_SI)
						if (id1.empty())
							mask.field(F_IDON1).set(IDON_SI);
						else						
							if (id2.empty())
								mask.field(F_IDON2).set(IDON_SI);
							else						
								if (id3.empty())
									mask.field(F_IDON3).set(IDON_SI);
								else						
									if (id4.empty())
										mask.field(F_IDON4).set(IDON_SI);
				}				
			}				
			if (tipoido == IDON_AF)
			{
				mask.field(F_DATAAF).set(dataido);			
				mask.field(F_STATOAF).set(ido_sos);			
				mask.field(F_FINESOSAF).set(finesos);
				if (intervallo != 0 && ido_sos == IDONEITA)
				{
					mask.set(F_INTAF,intervallo);
					if (id1 != IDON_PL && id2 != IDON_PL && id3 != IDON_PL && id4 != IDON_PL)
						if (id1.empty())
							mask.field(F_IDON1).set(IDON_PL);
						else						
							if (id2.empty())
								mask.field(F_IDON2).set(IDON_PL);
							else						
								if (id3.empty())
									mask.field(F_IDON3).set(IDON_PL);
								else						
									if (id4.empty())
										mask.field(F_IDON4).set(IDON_PL);
				}				
			}				
		}			
	}			
	const TString16 catcoll = cache().get("TCS",tipo).get("S7"); 
	if (catcoll.not_empty())
	{
		mask.set(F_CATDON,catcoll);
		mask.field(F_CATDON).on_key(K_TAB);
	}		
	// verifico la concordanza di stato soggetto e stato idoneita
	TString16 statosi = mask.get(F_STATOSI);
	TString16 statoaf = mask.get(F_STATOAF);
	TDate datastatosi = mask.get_date(F_DATASI);
	TDate datastatoaf = mask.get_date(F_DATAAF);
	if (statosi.not_empty() || statoaf.not_empty())
	{ 
		TString16 stato = mask.get(F_STATO);
		char modstato = modstato_tcs(stato);           
		// prima c'era un &&
		if ((statosi == IDONEITA) || (statoaf == IDONEITA))
	  	if ((modstato != 'I') && (modstato != 'F')) //corretto || con && da Marco in data 07/09/99
	  		stato = IDONEITA;
		//if ((statosi == SOSPENSIONE || statosi.empty()) && (statoaf == SOSPENSIONE || statoaf.empty()))
		if ((statosi == SOSPENSIONE) && (statoaf == SOSPENSIONE))
	  	if (modstato != 'S')
	  		stato = SOSPENSIONE;      
		char statocalcolato =	modstato_tcs(stato);
		if (modstato != statocalcolato)
		{
			mask.set(F_STATO, stato);
			mask.field(F_STATO).on_key(K_TAB);
			mask.set(F_PROS_STATO,"  ");
			mask.field(F_PROS_STATO).on_key(K_TAB);
			mask.set(F_DATA_PROS,datanulla);
			mask.field(F_DATA_PROS).on_key(K_TAB);
			if (statocalcolato == 'I')
			{   
				TDate datacalcolata = NULLDATE;
				if (statosi == IDONEITA)
					datacalcolata = datastatosi;
				if ((statoaf == IDONEITA) && (datastatoaf > datacalcolata))
					datacalcolata = datastatoaf;					
				mask.set(F_DATASTATO,datacalcolata);
			}
			else
				if (datastatoaf > datastatosi)
					mask.set(F_DATASTATO,datastatoaf);
				else
					mask.set(F_DATASTATO,datastatosi);							
	  }
	}	  
 	d_datepross(s);
	
 	if (((penultstato == 'S') || (penultstato == 'I')) && ((ultstato == 'I') || (ultstato == 'F')))
 	{
 		data = mask.get_date(F_DATAPROSSI);
		if (data < dataultstato && data.ok()) mask.set(F_DATAPROSSI,dataultstato);
 		data = mask.get_date(F_DATAPROSAF);		
 		if (data < dataultstato && data.ok()) mask.set(F_DATAPROSAF,dataultstato);
 	}
 	// verifico la categoria e lo stato
	TString16 catdon = mask.get(F_CATDON);		
 	const bool dimissione = cache().get("CTD", catdon).get_bool("B0");
	const char statocalcolato = modstato_tcs(mask.get(F_STATO));
	// tolto l'if da Cristina il 18/06/99 - da qui
	// rimesso da Marco il 06/07/99 modificando dimissione in !dimissione e suddividendolo in due if
	if ((statocalcolato == 'I') || (statocalcolato == 'F'))
	{
		int totdon = mask.get_int(F_TOTDON);
		if (!dimissione)
		{
			//Operazione sostituita da Marco il 26/07/99 al posto di quella commentata sotto
			if ((catdon == app()._catini1 || app()._catini1.empty()) && (totdon>=app()._numdon1) && app()._catfin1.not_empty())
			{
				mask.set(F_CATDON, app()._catfin1);    
				catdon = app()._catfin1;
			}	
			const bool tstampata = mask.get_bool(F_T_STAMPATA);				
			if ((catdon == app()._catini2 || app()._catini2.empty()) && (totdon>=app()._numdon2) && app()._catfin2.not_empty() && ((!app()._sttess2)|| (tstampata)))
			{
				mask.set(F_CATDON, app()._catfin2);
				catdon = app()._catfin2;
			}	
		// Corretto da Marco il 26/07/99 sostituendolo con quello sopra
		// Reinserito come else da Marco il 07/09/99 per gestire il cambio in caso di inserimento idoneit� parziali invece di controllo
		}
		else
		{
			if ((totdon>=app()._numdon1) && (app()._catfin1.not_empty()))
			{
				mask.set(F_CATDON, app()._catfin1);
				catdon = app()._catfin1;
			}	
			const bool tstampata = mask.get_bool(F_T_STAMPATA);
			if ((totdon>=app()._numdon2) && (app()._catfin2.not_empty()) && ((!app()._sttess2) || (tstampata)))
			{
				mask.set(F_CATDON, app()._catfin2);
				catdon = app()._catfin2;
			}	
		}
		mask.field(F_CATDON).on_key(K_TAB);			
		TDate datanulla(NULLDATE);
		mask.set(F_DATADIM,datanulla);
		//fino a qui 
	}				
}

bool TGestioneSoggetti::famiglia_notify(TSheet_field& s, int r, KEY k)
{
	static long oldcodice;
	switch (k)
	{ 
		case K_ENTER:				// uscita da riga modificata
		{     
			TToken_string& row = s.row(r);
			const long codice = row.get_long(1);
			if (codice != 0)
			{
				TLocalisamfile fam(LF_FAMIGLIE);
				fam.setkey(2);
				TRectype& recfam = fam.curr();
				recfam.zero();
				recfam.put(FAM_CODFAM, codice);
				if (fam.read() == NOERR)
					if (fam.get_long(FAM_FAMIGLIA) != app()._famatt)
						return s.error_box("Soggetto gia' inserito in altra famiglia");
				app()._famprec = 0;
			}
		}
		break;		
		case K_CTRL+K_DEL:  // avvenuta cancellazione riga
		{
			if (s.items() == 1 || oldcodice == app()._codice)
			{
				s.destroy();
				app()._famatt = 0;
				TMask& m = s.mask();
				m.show(-1);
				m.hide(F_FAMIGLIARI);
			}
			else
				app()._famprec = 0;
		}     
		break;
		case K_DEL:					// richiesta di cancellazione riga
		{
			if (s.items() == 2)
				return s.yesno_box("Attenzione: dopo la cancellazione la famiglia verra' eliminata");
			TToken_string& row = s.row(r);
			const long codice = row.get_long(1);
			oldcodice = codice;
			if (app()._codice == codice)
				return s.yesno_box("Attenzione: si sta eliminando il soggetto dalla famiglia");
		}	
		break;
	} 	
	return TRUE;
}

bool TGestioneSoggetti::donazioni_notify(TSheet_field& s, int r, KEY k)
{              
	static TToken_string oldrow;
	bool modified = FALSE;
	TMask& mask = s.mask();
	if (k == K_CTRL+K_DEL)		// avvenuta cancellazione riga
	{
		int totdon = mask.get_int(F_TOTDON);
 		mask.set(F_TOTDON,totdon-1);
 		const TDate data = oldrow.get(0);
 		const TString16 tipo = oldrow.get();
		if (data == mask.get_date(F_DATAULTDON) 
			  || data == mask.get_date(F_DATAULTSI)
	  		|| data == mask.get_date(F_DATAULTAF))
			modified = TRUE;	  		
 		if (is_donaz(tipo,IDON_SI))
 		{
 			totdon = mask.get_int(F_TOTDONSI);
 			mask.set(F_TOTDONSI,totdon-1);
 		}	
 		else
 			if (is_donaz(tipo,IDON_AF))
 			{
 				totdon = mask.get_int(F_TOTDONAF);
 				mask.set(F_TOTDONAF,totdon-1);
 			}	
	}
	else
	{
		switch (k)                                           
		{ 
			case K_DEL:						// richiesta di cancellazione riga
				oldrow = s.row(r);
			break;				
	  	case K_SPACE:				// inizio modifica riga
	  		oldrow = s.row(r);
	  	break;
			case K_ENTER:				// uscita da riga modificata
			{
				TToken_string& row = s.row(r);
	 			const TDate actdata(row.get(0));
	 			const TString16 acttipo(row.get());
	 			const TDate olddata = oldrow.get(0);
	 			const TString16 oldtipo = oldrow.get();
//Righe aggiunte da Marco in data 05/08/99 per visualizzare un messaggio di avvertimento in caso di donazione in stato di sospensione
	 			const char statocalcolato = modstato_tcs(mask.get(F_STATO)); 
	 			const char statosi = modstato_tcs(mask.get(F_STATOSI));
	 			const char statoaf = modstato_tcs(mask.get(F_STATOAF));
	 			if (actdata > mask.get_date(F_DATASTATO))
	 				if (((statocalcolato != 'I') && (statocalcolato != 'F')) || ((statosi != 'I') && (is_donaz(acttipo,IDON_SI)))
	 						|| ((statoaf != 'I') && (is_donaz(acttipo,IDON_AF))))     
	  			{
	  				TString messaggio = "";
	  				messaggio << "Stato soggetto non compatibile per una donazione.\n";
	  				messaggio << "In caso si prosegua, adeguare manualmente lo stato del soggetto!!!";
	  				s.warning_box(messaggio);	
	  			};   
//fino a qui
	  		if (olddata != actdata)
	  		{
  				ordina_sheet_data(s);
  				s.force_update();
					if (olddata == mask.get_date(F_DATAULTSI) 
							|| olddata == mask.get_date(F_DATAULTAF)
							|| actdata > mask.get_date(F_DATAULTSI) 
							|| actdata > mask.get_date(F_DATAULTAF))
	    			modified = TRUE;
				}		    			
	  		if (oldtipo != acttipo)
	  			modified = TRUE;
	  	}		
	  	break;  	
	  	case K_CTRL+K_INS:	// avvenuto inserimento riga (ancora vuota)
// Aggiunte le righe seguenti da Marco il 05/08/99 per visualizzare un messaggio in caso di inserimento donazione su soggetto non idoneo
	  		if ((modstato_tcs(mask.get(F_STATO)) != 'I') && (modstato_tcs(mask.get(F_STATO)) != 'F'))
	  		{	
	  			TString messaggio = "";
	  			messaggio << "Stato soggetto non compatibile per una donazione.\n";
	  			messaggio << "In caso si prosegua, adeguare manualmente lo stato del soggetto!!!";
	  			s.warning_box(messaggio);	
	  		} 
//Fino a qui
	  		const int totdon = mask.get_int(F_TOTDON);
	  		mask.set(F_TOTDON,totdon+1);  			
	  	break;
	  }
	}	  
  if (modified)
  	app().calcola_donazioni(mask, s);
  return TRUE;  
}

bool TGestioneSoggetti::controlli_notify(TSheet_field& s, int r, KEY k)
{
	static bool delete_l = FALSE;	// flag per cancellazione ultima riga
	static TToken_string oldrow;
	bool modified = FALSE;
	TMask& mask = s.mask();
	if (k == K_CTRL+K_DEL)	// avvenuta cancellazione riga
  {
		if (delete_l)
  		modified = TRUE;
  	delete_l = FALSE;	
 	}		
	else	
	{
		switch (k)
		{
			case K_INS:  			// richiesta inserimento riga
				return app()._permesso;
			break;		
	  	case K_SPACE:	  	// inizio modifica riga	  		
	  		oldrow = s.row(r);
	  	break;
			case K_ENTER:			// uscita da riga modificata
			{             
				TToken_string& row = s.row(r);
	 			const TDate actdata(row.get(0));
	 			const TString16 acttipo(row.get());
	 			const TDate olddata(oldrow.get(0));
	 			const TString16 oldtipo(oldrow.get());
	 			if (olddata != actdata)
	  		{
	  			ordina_sheet_data(s);
	  			app().tipocon_set_sheet(s);
	  			s.force_update();
	  		}	
				if (modstato_tcs(oldtipo) != 'N' || modstato_tcs(acttipo) != 'N')
	    		modified = TRUE;						    		
	  	}		
	  	break;  	
	  	case K_DEL:  	  	// richiesta di cancellazione riga
	  	{	             
	  		oldrow = s.row(r);
	  		const TString16 oldtipo(oldrow.get(1));
	  		if (r == (s.items()-1) && modstato_tcs(oldtipo) != 'N') 
	  			delete_l = TRUE;
				return app()._permesso;	  			
	 		}		
	  	break;	
	  }
  }
  if (modified)
  {
		TSheet_field& i = (TSheet_field&)mask.field(F_IDONEITA);
  	c_reord(s, i);		
	}  	
	return TRUE;  
}

bool TGestioneSoggetti::idoneita_notify(TSheet_field& s, int r, KEY k)
{               
	static TToken_string oldrow;
	bool modified = FALSE;
	TMask& mask = s.mask();

	if (k == K_CTRL+K_DEL)	// avvenuta cancellazione riga
  		modified = TRUE;
	else	
	{
		switch (k)
		{                                          
			case K_INS:  			// richiesta inserimento riga
				return app()._permesso;
			break;		
	  	case K_SPACE:	  	// inizio modifica riga
	  		oldrow = s.row(r);
	  	break;
			case K_ENTER:			// uscita da riga modificata
			{
				TToken_string& row = s.row(r);
	 			const TDate actdata(row.get(0));
	 			const TString16 acttipo(row.get());
				const TString16 actidosos(row.get());	 			
	 			const TDate olddata(oldrow.get(0));
	 			const TString16 oldtipo(oldrow.get());
	 			const TString16 oldidosos(oldrow.get());
	 			if (olddata != actdata)
	  		{
	  			ordina_sheet_data(s);
	  			app().idosos_set_sheet(s);
	  			s.force_update();
	  		}	
	  		if (olddata!=actdata || oldtipo!=acttipo || oldidosos!=actidosos)
	    		modified = TRUE;
	  	}		
	  	break;  	
	  	case K_DEL:
	  		return app()._permesso;
	  }
  }
  if (modified)
  {
		TSheet_field& c = (TSheet_field&)mask.field(F_CONTROLLI);
		c_reord(c,s);
	}		
	return TRUE;  
}


bool TGestioneSoggetti::benemerenze_notify(TSheet_field& s, int r, KEY k)
{
  if (k == K_ENTER)
  {
  }
	return TRUE;  
}

bool TGestioneSoggetti::storico_notify(TSheet_field& s, int r, KEY k)
{
  if (k == K_ENTER)
  {
  }
	return TRUE;  
}

bool TGestioneSoggetti::richiesta_password()
{                      
	TMask& mask = *(app().get_mask());
	TMask msk("at0100e");
  if (msk.run() == K_ENTER) 
  {
  	if (msk.get(F_PASSWORD) == "BAMP")
  	{   
  		mask.enable(F_CONTROLLI);
  		mask.enable(F_IDONEITA);
  		return TRUE;
		}  		
		else  		
		{
			error_box("Password errata! Non e' possibile modificare la situazione sanitaria");			
  		mask.disable(F_CONTROLLI);
  		mask.disable(F_IDONEITA);
		}			
  }
	return FALSE;  
}

int at0100(int argc, char* argv[])
{
	TGestioneSoggetti a;
	a.run(argc, argv, "Soggetti");
	return 0;
}