Files correlati : ve0.exe Ricompilazione Demo : [ ] Commento : 0001556: Documenti interattivi Se inserisco una descrizione del tipo : Programma Campo modulo Effetti canone di manut. prova1 prova2 prova3 prova4 prova5 prova6 la prima volte che faccio F8 dopo aver registrato vengono persi alcuni caratteri in mezzo git-svn-id: svn://10.65.10.50/trunk@20118 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			2048 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2048 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <colors.h>
 | ||
| #include <mailbox.h>
 | ||
| #include <msksheet.h>
 | ||
| #include <postman.h>
 | ||
| #include <progind.h>
 | ||
| #include <sheet.h>
 | ||
| #include <recarray.h>
 | ||
| #include <relapp.h>
 | ||
| #include <statbar.h>
 | ||
| #include <urldefid.h>
 | ||
| #include <utility.h>
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TRelation_application
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| TRelation_application::TRelation_application()
 | ||
|                      : _mask(NULL), _search_id(-1), _lnflag(0),
 | ||
|                        _autodelete(0), _navigating(false)
 | ||
| { }
 | ||
| 
 | ||
| TRelation_application::~TRelation_application()
 | ||
| { }
 | ||
| 
 | ||
| TCursor& TRelation_application::get_filtered_cursor() const
 | ||
| {
 | ||
|   const TEdit_field& f = get_search_field();
 | ||
|   return *f.browse()->cursor();
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::setkey()
 | ||
| {
 | ||
|   if (has_filtered_cursor())
 | ||
|     get_filtered_cursor().setkey();
 | ||
|   else
 | ||
|     file().setkey(1);
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::set_key_filter()
 | ||
| {
 | ||
|   TString rf = get_user_read_filter(); rf.trim();
 | ||
|   if (rf.not_empty())
 | ||
|   {
 | ||
|     TString expr;
 | ||
|     for (int f = _mask->fields()-1; f >= 0; f--)
 | ||
|     {
 | ||
|       TMask_field& fld= _mask->fld(f);
 | ||
|       if (fld.is_edit() && fld.in_key(0))
 | ||
|       {
 | ||
|         TBrowse* b = ((TEdit_field&)fld).browse();
 | ||
|         if (b && b->cursor()->relation()->lfile().num() == get_relation()->lfile().num())
 | ||
|         {
 | ||
|           expr = b->get_filter();
 | ||
|           if (expr.find(rf) < 0)
 | ||
|           {
 | ||
|             if (expr.not_empty())
 | ||
|             {
 | ||
|               expr.insert("(", 0);
 | ||
|               expr << ")&&(" << rf << ')';
 | ||
|             }
 | ||
|             else
 | ||
|               expr = rf;
 | ||
|             b->set_filter(expr);
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // @doc INTERNAL
 | ||
| 
 | ||
| // @mfunc Setta i limiti
 | ||
| void TRelation_application::set_limits(
 | ||
|      byte what) // @parm tipo di limite da assegnare al record
 | ||
| 
 | ||
| // @comm I limiti possibili sono:
 | ||
| // @flag 0 | Nessuna operazione
 | ||
| // @flag 1 | Primo record
 | ||
| // @flag 2 | Ultimo record
 | ||
| // @flag 3 | Entrambi
 | ||
| {
 | ||
|   if (has_filtered_cursor())
 | ||
|   {
 | ||
|     const TEdit_field& f = get_search_field();
 | ||
|     if (f.browse() != NULL)
 | ||
|       f.browse()->do_input(true);
 | ||
|    
 | ||
|     TCursor& cur = get_filtered_cursor();
 | ||
|     cur.setkey();
 | ||
|     if (cur.items() > 0) 
 | ||
|     {
 | ||
|       if (what & 0x1)
 | ||
|       {
 | ||
|         cur = 0;
 | ||
|         _first = cur.file().recno();
 | ||
|       }
 | ||
|       if (what & 0x2)
 | ||
|       {
 | ||
|         cur = cur.items() - 1;
 | ||
|         _last = cur.file().recno();
 | ||
|       }
 | ||
|     }
 | ||
|     else
 | ||
|       _first = _last = -1;
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     setkey();
 | ||
|     if (!file().empty())
 | ||
|     {
 | ||
|       if (what & 0x1)
 | ||
|       {
 | ||
|         if (file().first() == NOERR)
 | ||
| 			    _first = file().recno();
 | ||
|       }
 | ||
|       if (what & 0x2)
 | ||
|       {
 | ||
|         if (file().last() == NOERR) 
 | ||
| 	        _last = file().recno();
 | ||
|       }
 | ||
|     }
 | ||
|     else
 | ||
|       _first = _last = -1;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::set_find_button()
 | ||
| {
 | ||
|   // Ricalcola posizioni bootoni di navigazione con la vecchia toolbar
 | ||
|   WINDOW bar = _mask->toolbar();
 | ||
|   if (bar != NULL_WIN)
 | ||
|     xvt_toolbar_realize(_mask->toolbar());
 | ||
|   else // Non c'e' la nuova relapbar
 | ||
|   {
 | ||
|     int pos = _mask->id2pos(DLG_FINDREC);
 | ||
|     if (pos >= 0 && _mask->id2pos(DLG_FIRSTREC) >= 0) //se e' un bottone pentapartito...
 | ||
| 	  {
 | ||
| 		  TButton_field& f_find = (TButton_field &)_mask->fld(pos);
 | ||
| 		  RCT rct_base;	f_find.get_rect(rct_base);
 | ||
|       const int bwidth = (rct_base.right - rct_base.left);
 | ||
|       const int bheight = (rct_base.bottom - rct_base.top);
 | ||
|       if (bwidth > 3*bheight/2) // Controllo se ho gia' ridimensionato i bottoni in precedenza
 | ||
|       {
 | ||
| 		    int bx = bwidth / 3;
 | ||
| 		    int by = bheight / 2;
 | ||
| 
 | ||
|         RCT r = rct_base; 
 | ||
|         r.left += bx;  r.right -= bx;
 | ||
|         if (!NATIVE_CONTROLS)
 | ||
|         {
 | ||
|           r.left -= 2; r.right += 2;
 | ||
|         }
 | ||
| 			  f_find.set_rect(r); // Ridimensiona il bottone centrale di ricerca
 | ||
|   			
 | ||
|         if (!NATIVE_CONTROLS)
 | ||
|         {
 | ||
|           bx += 5; by += 3;   // Aggiusta dimensioni bottoni sussidiari
 | ||
|         }
 | ||
| 
 | ||
| 		    pos = _mask->id2pos(DLG_FIRSTREC);
 | ||
| 		    if (pos >= 0)
 | ||
| 		    {	
 | ||
| 			    r = rct_base; r.top = r.bottom - by;  r.right = r.left + bx;
 | ||
| 			    _mask->fld(pos).set_rect(r);
 | ||
| 		    }
 | ||
| 		    pos = _mask->id2pos(DLG_PREVREC);
 | ||
| 		    if (pos >= 0) 
 | ||
| 		    {
 | ||
| 			    r = rct_base; r.bottom = r.top + by;  r.right = r.left + bx;
 | ||
| 			    _mask->fld(pos).set_rect(r);
 | ||
| 		    }
 | ||
| 		    pos = _mask->id2pos(DLG_NEXTREC);
 | ||
| 		    if (pos >= 0) 
 | ||
| 		    {
 | ||
| 			    r = rct_base; r.bottom = r.top + by;  r.left = r.right - bx;
 | ||
| 			    _mask->fld(pos).set_rect(r);
 | ||
| 		    }
 | ||
| 		    pos = _mask->id2pos(DLG_LASTREC);
 | ||
| 		    if (pos >= 0) 
 | ||
| 		    {
 | ||
| 			    r = rct_base; r.top = r.bottom - by;  r.left = r.right - bx;
 | ||
| 			    _mask->fld(pos).set_rect(r);
 | ||
| 		    }
 | ||
|       }
 | ||
| 	  }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::create()
 | ||
| {
 | ||
|   bool ok = user_create();
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     write_enable();
 | ||
|     _mask = get_mask(MODE_QUERY);
 | ||
| 
 | ||
|     filter();
 | ||
|     set_key_filter();
 | ||
|     set_limits();
 | ||
|   }
 | ||
|   return ok ? TSkeleton_application::create() : ok;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TRelation_application::destroy()
 | ||
| {   
 | ||
|   user_destroy();
 | ||
|   return TSkeleton_application::destroy();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TRelation_application::set_fixed()
 | ||
| {
 | ||
|   TToken_string s(256, '=');
 | ||
|   FOR_EACH_TOKEN(_fixed, f)
 | ||
|   {
 | ||
|     s = f;
 | ||
|     const short id = s.get_int(0);
 | ||
|     if (id > 0 && _mask->id2pos(id) >= 0)
 | ||
|     {
 | ||
|       s = s.get();
 | ||
|       if (s.not_empty())
 | ||
|         _mask->set(id, s);
 | ||
|       
 | ||
|       if (_lnflag < 2)  
 | ||
|         _mask->disable(id);
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::enable_query()
 | ||
| {
 | ||
|   const bool query = _mask->query_mode(); 
 | ||
|   const bool keyon = query || get_relation()->status() == _isreinsert;
 | ||
| 
 | ||
|   for (int i = _mask->fields() - 1; i >= 0; i--)
 | ||
|   {
 | ||
|     TMask_field& c = _mask->fld(i);
 | ||
| 
 | ||
| 		if (c.in_key(0) && c.enabled_default())
 | ||
|     {
 | ||
|       if (c.in_key(1))
 | ||
|         c.enable(keyon);
 | ||
|       if (c.is_edit())
 | ||
|       {
 | ||
|         TEdit_field& e = (TEdit_field&)c;
 | ||
|         if (e.browse() != NULL)
 | ||
|           e.enable_check(query);
 | ||
|       }  
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   set_fixed();
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::set_toolbar()
 | ||
| {
 | ||
|   const int mode = _mask->mode();
 | ||
|   const bool can_edit_some = user_can_write(NULL);
 | ||
|   
 | ||
|   int pos = _mask->id2pos(DLG_SAVEREC);
 | ||
|   if (pos >= 0)
 | ||
|   {
 | ||
|     bool enabsave=mode != MODE_QUERY;
 | ||
|     if (enabsave)
 | ||
|       enabsave = user_can_write(get_relation());
 | ||
|     _mask->fld(pos).enable(enabsave);
 | ||
|   }
 | ||
|   pos = _mask->id2pos(DLG_DELREC);
 | ||
|   if (pos >= 0) 
 | ||
|   {               
 | ||
|     bool enabdel = (mode == MODE_QUERY && can_edit_some) || (mode == MODE_MOD);
 | ||
|     if (enabdel && mode == MODE_MOD)
 | ||
|     {
 | ||
|       TRelation& r = *get_relation();
 | ||
|       const TRecnotype oldpos = r.lfile().recno();
 | ||
|       enabdel = !protected_record(r);
 | ||
|       if (r.lfile().recno() != oldpos) 
 | ||
|         r.lfile().readat(oldpos);
 | ||
|     }  
 | ||
|     _mask->fld(pos).enable(enabdel);
 | ||
|   }
 | ||
| 
 | ||
|   pos = _mask->id2pos(DLG_FINDREC);
 | ||
|   if (pos >= 0) 
 | ||
| 	{
 | ||
|     _mask->fld(pos).enable(_lnflag == 0);
 | ||
| 		
 | ||
| 		const long recno = get_relation()->lfile().recno();
 | ||
| 		const bool enable_next_prev = _mask->edit_mode();
 | ||
|     const bool can_nav = _lnflag == 0 && _curr_transaction != TRANSACTION_LINK;
 | ||
| 
 | ||
|     pos = _mask->id2pos(DLG_FIRSTREC);
 | ||
| 		if (pos >= 0)
 | ||
| 			_mask->fld(pos).enable(can_nav && (enable_next_prev ? _first != recno : _first > 0));
 | ||
| 		pos = _mask->id2pos(DLG_PREVREC);
 | ||
| 		if (pos >= 0) 
 | ||
| 			_mask->fld(pos).enable(can_nav && enable_next_prev && _first > 0 && _first != recno);
 | ||
| 		pos = _mask->id2pos(DLG_NEXTREC);
 | ||
| 		if (pos >= 0) 
 | ||
| 			_mask->fld(pos).enable(can_nav && enable_next_prev && _last > 0 && _last != recno);
 | ||
| 		pos = _mask->id2pos(DLG_LASTREC);
 | ||
| 		if (pos >= 0) 
 | ||
|       _mask->fld(pos).enable(can_nav && (enable_next_prev ? _last != recno : _last > 0));
 | ||
| 	}
 | ||
| 
 | ||
|   pos = _mask->id2pos(DLG_NEWREC);
 | ||
|   if (pos >= 0) 
 | ||
|   {
 | ||
|     bool enabins = (mode == MODE_QUERY || _lnflag == 0) && can_edit_some;
 | ||
|     _mask->fld(pos).enable(enabins);
 | ||
|   }
 | ||
| 
 | ||
|   set_find_button();
 | ||
|   enable_query();
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::update_navigation_bar()
 | ||
| {
 | ||
|   if (_mask->query_mode())
 | ||
|   {
 | ||
|     set_limits();
 | ||
|     set_toolbar();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::save_and_new() const
 | ||
| { return false; }
 | ||
| 
 | ||
| bool TRelation_application::save_and_quit() const
 | ||
| {
 | ||
|   return (_autoins_caller.full() || _curr_transaction.not_empty()) && _curr_trans_mode != TM_REMAIN;
 | ||
| }
 | ||
| 
 | ||
| int TRelation_application::set_mode(int mode)
 | ||
| {
 | ||
|   static int _mode = NO_MODE;
 | ||
|   if (mode < NO_MODE) mode = _mode;
 | ||
|   
 | ||
|   const int m = ((TMaskmode)mode == NO_MODE) ? (int) MODE_QUERY : mode;
 | ||
|   _mask->set_mode(m);
 | ||
| 
 | ||
|   set_toolbar();
 | ||
|   _mode = mode;
 | ||
| 
 | ||
|   const char* t = "";
 | ||
|   switch(mode)
 | ||
|   {
 | ||
|   case MODE_QUERY: 
 | ||
|     t = TR("Ricerca"); break;
 | ||
|   case MODE_MOD: 
 | ||
|     t = TR("Modifica"); break;
 | ||
|   case NO_MODE: 
 | ||
|     t = TR("Ricerca/Inserimento"); break;
 | ||
|   case MODE_INS: 
 | ||
|     t = TR("Inserimento"); break;
 | ||
|   default: 
 | ||
|     break;
 | ||
|   }
 | ||
| 
 | ||
|   xvtil_statbar_set(t, TRUE);
 | ||
| 
 | ||
|   return _mode;
 | ||
| }
 | ||
| 
 | ||
| // @doc INTERNAL
 | ||
| 
 | ||
| // @mfunc Permette di autonumerare un record
 | ||
| //
 | ||
| // @rdesc Ritorna se e' riuscito a creare una nuova autonumerazione:
 | ||
| //
 | ||
| // @flag TRUE | La chiave non e' vuota
 | ||
| // @flag FALSE | Non e' riuscito ad autonumerare il documento
 | ||
| bool TRelation_application::autonum(
 | ||
|      TMask* m,  // @parm Maschera a cui applicare l'autonumerazione 
 | ||
|      bool rec)  // @parm Indica se registrare la chiave anche sul record corrente
 | ||
| {
 | ||
|   TToken_string k;
 | ||
|   if (!get_next_key(k))
 | ||
|   {
 | ||
|     k = get_next_key();
 | ||
| /*
 | ||
|     if (k.not_empty())
 | ||
|       NFCHECK("La 'const char* get_next_key()' verra' sostituita dalla 'bool get_next_key(TToken_string&)'");
 | ||
| */
 | ||
|   }
 | ||
|   
 | ||
|   if (!rec && !m->query_mode()) 
 | ||
|     m->reset();
 | ||
|   _renum_message = "";
 | ||
|   
 | ||
|   for (const char* n = k.get(0); n && *n; n = k.get())
 | ||
|   {
 | ||
|     const short id = atoi(n);                                                       
 | ||
|     CHECKD (id > 0 && m->id2pos(id) >= 0, "Identificatore di autonumerazione errato: ", id);
 | ||
|     const char* val = k.get();
 | ||
|     TMask_field& f = m->field(id);
 | ||
|     if (rec || f.empty()) 
 | ||
|       f.set(val);
 | ||
|     if (rec) 
 | ||
|       ((TEditable_field&)f).autosave(*get_relation());
 | ||
|     if (_renum_message.empty() || f.in_key(1))
 | ||
|       _renum_message.format("L'elemento e' stato registrato con :\n  %s = %s", (const char *) f.prompt(), (const char *) f.get());
 | ||
|   }
 | ||
|   return k.not_empty();
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Entra in modo di ricerca
 | ||
| void TRelation_application::query_mode(
 | ||
|      bool pre_ins)  // @parm Indica in quale modo andare:
 | ||
|       //
 | ||
|       // @flag TRUE | Entra in modo MODE_QUERY_INSERT
 | ||
|       // @flag FALSE | Entra in modo MODE_QUERY (default)
 | ||
| {
 | ||
|   TMask* old = _mask;            
 | ||
|   const bool was_open = old != NULL && old->is_open();
 | ||
|   const bool changing = changing_mask(MODE_QUERY);
 | ||
| 
 | ||
|   if (changing && was_open)
 | ||
|     old->close_modal();
 | ||
| 
 | ||
|   _mask = get_mask(MODE_QUERY);
 | ||
|   if (changing)
 | ||
|   {
 | ||
|     if (was_open) 
 | ||
|       _mask->open_modal();
 | ||
|     set_limits();
 | ||
|   }
 | ||
|   
 | ||
|   _mask->set_mode(pre_ins ? MODE_QUERYINS : MODE_QUERY);
 | ||
|   _mask->reset();
 | ||
|   _mask->disable_page(1); // Nasconde pagine inutili
 | ||
| 
 | ||
|   if (pre_ins)
 | ||
|   {
 | ||
|     set_mode(NO_MODE);
 | ||
|     init_query_insert_mode(*_mask);
 | ||
| 		enable_query();
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     set_mode(MODE_QUERY);
 | ||
|     init_query_mode(*_mask);
 | ||
| 		enable_query();
 | ||
|     
 | ||
|     // Aggiorna bottoni di ricerca: utile soprattutto per ve0 che imposta CODNUM
 | ||
|     if (has_filtered_cursor()) 
 | ||
|     {
 | ||
|       set_limits();
 | ||
|       set_toolbar(); 
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TRelation_application::insert_mode()
 | ||
| { 
 | ||
|   bool try_auto = true;
 | ||
| 
 | ||
|   if (_mask->query_mode())
 | ||
|     try_auto = !test_key(1, FALSE);
 | ||
| 
 | ||
|   if (try_auto && !autonum(_mask, FALSE))
 | ||
|   {
 | ||
|     query_insert_mode();
 | ||
|     return;
 | ||
|   }
 | ||
| 
 | ||
|   TRelation* r = get_relation();
 | ||
|   r->zero();
 | ||
|   _mask->autosave(*r);
 | ||
| 
 | ||
|   if (!user_can_write(r))
 | ||
|   {
 | ||
|     warning_box(FR("L'utente %s non puo' inserire in questo archivio"), (const char*)user());
 | ||
|     return;
 | ||
|   }
 | ||
| 
 | ||
|   const bool changing = changing_mask(MODE_INS);
 | ||
|   TFilename workname; workname.temp("msk");
 | ||
|   if (changing)
 | ||
|   {
 | ||
|     _mask->set_workfile(workname);
 | ||
|     _mask->save();
 | ||
|     _mask->close_modal();
 | ||
|   }
 | ||
|   _mask = get_mask(MODE_INS);
 | ||
|   if (changing)
 | ||
|   {
 | ||
|     _mask->reset();
 | ||
|     _mask->set_workfile(workname);
 | ||
|     _mask->load();
 | ||
|     xvt_fsys_remove_file(workname);
 | ||
|     _mask->open_modal();
 | ||
|   }
 | ||
|   else
 | ||
|     _mask->enable_page(1);
 | ||
| 
 | ||
|   set_mode(MODE_INS);
 | ||
|   r->zero();          // Azzera tutta la relazione!
 | ||
|   
 | ||
| 	_mask->load_defaults();
 | ||
|   init_insert_mode(*_mask);
 | ||
|   
 | ||
|   // ....possibilmente spostare questa chiamata .....
 | ||
|   if (is_transaction() && _curr_transaction == TRANSACTION_INSERT)
 | ||
|     ini2insert_mask(); 
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::modify_mode()
 | ||
| {
 | ||
|   TRelation* rel = get_relation();
 | ||
|   if (!user_can_read(rel))
 | ||
|   {
 | ||
|     warning_box(TR("I dati non sono accessibili per l'utente %s"), (const char*)user());
 | ||
|     query_mode();
 | ||
|     return FALSE;
 | ||
|   }
 | ||
| 
 | ||
|   const TReclock block = user_can_write(rel) ? _testandlock : _nolock;
 | ||
|   int err = rel->read(_isequal, block);
 | ||
|   if (err != NOERR)
 | ||
|   {
 | ||
|     if (err == _islocked)
 | ||
|       message_box(TR("I dati sono gia' usati da un altro programma"));
 | ||
|     else
 | ||
|       error_box(FR("Impossibile leggere i dati: errore %d"), err);
 | ||
|     query_mode();
 | ||
|     return FALSE;
 | ||
|   }
 | ||
| 
 | ||
|   const bool changing = changing_mask(MODE_MOD);
 | ||
|   if (changing)
 | ||
|     _mask->close_modal();
 | ||
| 
 | ||
|   _mask = get_mask(MODE_MOD);
 | ||
|   
 | ||
|   if (changing)
 | ||
|     _mask->open_modal();                
 | ||
|   else
 | ||
|     _mask->enable_page(1);
 | ||
|   
 | ||
|   set_mode(MODE_MOD);
 | ||
|                              
 | ||
|   err = read(*_mask);
 | ||
|   if (err != NOERR)
 | ||
|   {
 | ||
|     query_mode();
 | ||
|     return FALSE;
 | ||
|   }
 | ||
| 
 | ||
|   rel->save_status();
 | ||
|   init_modify_mode(*_mask);
 | ||
| 
 | ||
|   // ....possibilmente spostare questa chiamata .....
 | ||
|   // Forse deve essere fatta prima della init_modify_mode()!
 | ||
|   if (_curr_transaction == TRANSACTION_MODIFY)
 | ||
|     ini2insert_mask(); 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TEdit_field& TRelation_application::get_search_field() const
 | ||
| {                      
 | ||
|   short id = _search_id;
 | ||
|                         
 | ||
|   if (id <= 0 || !_mask->field(id).shown())
 | ||
|   {                      
 | ||
|     for (int i = _mask->fields()-1; i >= 0; i--)
 | ||
|     {
 | ||
|       const TMask_field& f = _mask->fld(i);
 | ||
|       if (f.is_edit() && f.in_key(1) && f.shown()) 
 | ||
|       {
 | ||
|         id = f.dlg();
 | ||
|         break;
 | ||
|       }  
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   return _mask->efield(id);
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::search_mode()
 | ||
| {
 | ||
|   if (_mask->mode() != MODE_QUERY)
 | ||
|     query_mode();
 | ||
| 
 | ||
|   TEdit_field* prima = &get_search_field();
 | ||
|   while (prima)
 | ||
|   {
 | ||
|     if (prima->on_key(K_F9))
 | ||
|     {
 | ||
|       if (find(1))
 | ||
|         return modify_mode();
 | ||
|       else
 | ||
|         break;  
 | ||
|     }        
 | ||
|     
 | ||
|     TMask_field* dopo = &_mask->focus_field();
 | ||
|     if (dopo != prima && dopo->is_edit() && dopo->in_key(0))
 | ||
|       prima = (TEdit_field*)dopo; 
 | ||
|     else
 | ||
|       break;
 | ||
|   }
 | ||
|   return false;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN bool delete_handler(TMask_field& f, KEY k)
 | ||
| {
 | ||
|   if (k == K_TAB && f.focusdirty() && !f.empty())
 | ||
|   {
 | ||
|     TMask& m = f.mask();
 | ||
|     const bool finale = *f.prompt() == 'A';
 | ||
|     const int pos = m.id2pos(f.dlg());
 | ||
|     if (pos >= 3)
 | ||
|     {           
 | ||
|       const TMask_field& e = m.fld(pos - 3);
 | ||
|       if (e.is_edit() && e.get().blank())
 | ||
|       {
 | ||
|         const short id = e.dlg() - (finale ? 200 : 100);
 | ||
|         const TRelation_application& app = (TRelation_application&)main_app();
 | ||
|         const TMask_field& orig = app.curr_mask().field(id);
 | ||
|         bool req = orig.required();
 | ||
|         if (!req && orig.is_edit())
 | ||
|         {
 | ||
|           const TEdit_field& e = (TEdit_field&)orig;
 | ||
|           req = e.validate_func() == 12;
 | ||
|         }
 | ||
|         if (req)
 | ||
|         {
 | ||
|           TString str; str << (finale ? TR("A ") : TR("Da ")) << orig.prompt();
 | ||
|           return f.error_box(FR("Specificare anche il valore %s"), (const char*)str);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     if (finale && !f.get().blank())
 | ||
|     {                                       
 | ||
|       const TMask_field& p = m.fld(pos - 1);
 | ||
|       TString80 prec = p.get();
 | ||
|       TString80 curr = f.get();
 | ||
|       bool ok;
 | ||
|       switch (p.class_id())
 | ||
|       {
 | ||
|       case CLASS_REAL_FIELD: ok = real(prec) <= real(curr); break;
 | ||
|       case CLASS_DATE_FIELD: ok = TDate(prec) <= TDate(curr); break;
 | ||
|       default              : ok = prec <= curr; break;
 | ||
|       }
 | ||
|       if (!ok)
 | ||
|         return f.error_box(FR("Inserire un valore non inferiore a '%s'"), (const char*)prec);
 | ||
|     }
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| int TRelation_application::delete_mode()
 | ||
| {
 | ||
|   TEdit_field& fld = get_search_field();
 | ||
|   TBrowse* brw = fld.browse(); 
 | ||
|   if (brw)
 | ||
|   {                
 | ||
|     brw->do_input(TRUE);
 | ||
|     TCursor& cur = *brw->cursor();
 | ||
|   
 | ||
|     TToken_string head(brw->head());
 | ||
|     head.insert("@1|", 0); 
 | ||
|     TToken_string items(brw->items());
 | ||
|     items.insert(" |", 0); 
 | ||
|     
 | ||
|     int tab1 = 0, tab2 = 0, y = 0;
 | ||
|     // Nuovo modo basato sugli input
 | ||
|     TToken_string inplist = brw->get_input_fields();
 | ||
|     if (inplist.not_empty())
 | ||
|     {
 | ||
|       FOR_EACH_TOKEN(inplist, tok)
 | ||
|       {
 | ||
|         if (*tok != '"' && strchr(tok, '@') == NULL)
 | ||
|         {
 | ||
|           TMask_field& e = _mask->field(short(atoi(tok)));
 | ||
|           if (e.active())
 | ||
|           {
 | ||
|             const int len = strlen(e.prompt());
 | ||
|             if (len > tab1) tab1 = len;
 | ||
|             const int size = e.size();
 | ||
|             if (size > tab2) tab2 = size;
 | ||
|             y++;
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     tab1 += 5;
 | ||
|     tab2 += tab1+2;
 | ||
|     
 | ||
|     cur = 0L;
 | ||
|     TCursor_sheet sht(&cur, items, TR("Eliminazione"), head, 0x4, y);
 | ||
|     
 | ||
|     y = -1;         // Posizione del campo precedente
 | ||
|     TString prompt; // Prompt del campo corrente
 | ||
|     const short delta = 100;
 | ||
| 
 | ||
|     FOR_EACH_TOKEN(inplist, tok)
 | ||
|     {
 | ||
|       if (*tok != '"' && strchr(tok, '@') == NULL)
 | ||
|       {
 | ||
|         TMask_field& e = _mask->field(short(atoi(tok)));
 | ||
|         if (!e.active())
 | ||
|           continue;
 | ||
|         
 | ||
|         const short id = e.dlg()+delta; 
 | ||
|         prompt = "Da "; prompt << e.prompt();
 | ||
|         sht.add_static(DLG_NULL, 0, prompt, 1, ++y);
 | ||
|         TString16 flags;            
 | ||
|         if (e.automagic())       flags << 'A';
 | ||
|         if (e.roman())           flags << 'M';
 | ||
|         if (e.right_justified()) flags << 'R';
 | ||
|         if (e.uppercase())       flags << 'U';
 | ||
|         if (e.zerofilled())      flags << 'Z';
 | ||
|         switch (e.class_id())
 | ||
|         {
 | ||
|         case CLASS_DATE_FIELD:
 | ||
|           {
 | ||
|             TDate_field& d1 = sht.add_date(id, 0, "", tab1, y, flags);
 | ||
|             TDate_field& d2 = sht.add_date(id+delta, 0, "A ", tab2, y, flags);
 | ||
|             d1.set_handler(delete_handler);
 | ||
|             d2.set_handler(delete_handler);
 | ||
|           }
 | ||
|           break;
 | ||
|         case CLASS_REAL_FIELD:
 | ||
|           {
 | ||
|             TReal_field& r1 = sht.add_number(id, 0, "", tab1, y, e.size(), flags);
 | ||
|             TReal_field& r2 = sht.add_number(id+delta, 0, "A ", tab2, y, e.size(), flags);
 | ||
|             r1.set_handler(delete_handler);
 | ||
|             r2.set_handler(delete_handler);
 | ||
|           }
 | ||
|           break;
 | ||
|         default:
 | ||
|           {
 | ||
|             TEdit_field& e1 = sht.add_string(id, 0, "", tab1, y, e.size(), flags);
 | ||
|             TEdit_field& e2 = sht.add_string(id+delta, 0, "A ", tab2, y, e.size(), flags);
 | ||
|             e1.set_handler(delete_handler);
 | ||
|             e2.set_handler(delete_handler);
 | ||
|           }
 | ||
|           break;
 | ||
|         } 
 | ||
|         if (y == 0)
 | ||
|           sht.first_focus(id);
 | ||
|       }
 | ||
|     }    
 | ||
|     
 | ||
|     sht.open_modal();
 | ||
| 
 | ||
|     KEY tasto;
 | ||
|     bool keep_running = TRUE;
 | ||
|     while (keep_running)
 | ||
|     {
 | ||
|       tasto = sht.run();
 | ||
|       if (tasto == K_ENTER)
 | ||
|       {
 | ||
|         TRectype rec_from(cur.curr()), rec_to(cur.curr());
 | ||
|         rec_from.zero(); rec_to.zero();
 | ||
|         TToken_string fldlist = brw->get_input_field_names();
 | ||
|         TString80 str;
 | ||
|         int fi = 0;        
 | ||
|         for (TString80 tok = inplist.get(fi); tok.not_empty(); tok = inplist.get(), fi++)
 | ||
|         { 
 | ||
|           const TString16 fn = fldlist.get(fi);
 | ||
|           const TFieldref fr(fn, 0);
 | ||
|           if (*tok == '"')
 | ||
|           {   
 | ||
|             str = tok;
 | ||
|             str.ltrim(1); str.rtrim(1);
 | ||
|             fr.write(str, rec_from);
 | ||
|             fr.write(str, rec_to);
 | ||
|           }
 | ||
|           else
 | ||
|           {
 | ||
|             const short id = short(atoi(tok));
 | ||
|             if (sht.id2pos(id+delta) >= 0)
 | ||
|             {       
 | ||
|               str = sht.get(id+delta);                
 | ||
|               if (str.not_empty())
 | ||
|                 fr.write(str, rec_from);
 | ||
|               str = sht.get(id+2*delta);                
 | ||
|               if (str.not_empty())
 | ||
|                 fr.write(str, rec_to);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|               str = _mask->get(id);
 | ||
|               fr.write(str, rec_from);
 | ||
|               fr.write(str, rec_to);
 | ||
|             }
 | ||
|           }                   
 | ||
|         } 
 | ||
|         
 | ||
|         if (rec_from.empty() && rec_to.empty())
 | ||
|         {   
 | ||
|           sht.check(-1);
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           const long totit = cur.items();
 | ||
|           cur.freeze(TRUE);
 | ||
|           cur.curr() = rec_from;
 | ||
|           cur.read();
 | ||
|           while (cur.pos() < totit && cur.curr() <= rec_to)
 | ||
|           {
 | ||
|             sht.check(cur.pos());
 | ||
|             ++cur;
 | ||
|           }
 | ||
|           cur.freeze(FALSE);
 | ||
|         }  
 | ||
|       } 
 | ||
|       else
 | ||
|       {
 | ||
|         keep_running = FALSE;
 | ||
|         if (tasto == K_DEL && sht.checked() == 0)
 | ||
|         {
 | ||
|           error_box(TR("Non e' stato selezionato nessun elemento"));
 | ||
|           sht.select(0);
 | ||
|           keep_running = TRUE;
 | ||
|         }
 | ||
|       }
 | ||
|     }  
 | ||
|     sht.close_modal();
 | ||
|  
 | ||
|     if (tasto == K_DEL)
 | ||
|     { 
 | ||
|       long deleting = sht.checked();
 | ||
|       TString msg;
 | ||
|       msg.format(FR("Confermare l'eliminazione di %d elementi"), deleting);
 | ||
|       bool can_delete = yesno_box(msg);
 | ||
|       if (can_delete && deleting > 100)
 | ||
|       {
 | ||
|         msg.insert(TR("ATTENZIONE: "), 0);
 | ||
|         can_delete = yesno_box(msg);
 | ||
|       }
 | ||
|       if (can_delete)
 | ||
|       {                
 | ||
|         TWait_cursor hourglass;
 | ||
|         long skipped = 0; // Record non cancellati perche' protetti
 | ||
|         cur.freeze(TRUE); // Congelo il cursore altrimenti si riaggiorna troppo       
 | ||
|         for (long pos = sht.items()-1; deleting > 0; pos--)  
 | ||
|         {       
 | ||
|           if (sht.checked(pos))
 | ||
|           {
 | ||
|             cur = pos;
 | ||
|             brw->do_output();
 | ||
|             bool can_delete = FALSE;
 | ||
|             if (find(1))
 | ||
|             {
 | ||
|               TRelation& r = *get_relation();
 | ||
|               _autodelete = 0x3;
 | ||
|               if (!protected_record(r))
 | ||
|               {
 | ||
|                 if (modify_mode())
 | ||
|                 {
 | ||
|                   r.restore_status();
 | ||
|                   can_delete = remove();  
 | ||
|                 }
 | ||
|                 query_mode();  
 | ||
|               }                  
 | ||
|               _autodelete = FALSE;
 | ||
|             }
 | ||
|             if (!can_delete)
 | ||
|               skipped++;
 | ||
|             deleting--;
 | ||
|           }
 | ||
|         }  
 | ||
|         cur.freeze(FALSE);
 | ||
|         set_limits(); // Riaggiorno il numero del primo/ultimo record
 | ||
| 
 | ||
|         if (skipped > 0)
 | ||
|         {
 | ||
|           warning_box(FR("%ld elementi non sono stati cancellati in quanto protetti."), skipped);
 | ||
|           query_mode();  
 | ||
|         }  
 | ||
|       }
 | ||
|     }
 | ||
|   }        
 | ||
|   else
 | ||
|   {
 | ||
|     if (search_mode())
 | ||
|       _autodelete = TRUE;
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // @doc INTERNAL
 | ||
| 
 | ||
| // @mfunc Controlla se una chiave e' completa ed esiste su file
 | ||
| //
 | ||
| // @rdesc Ritorna se la chave esiste sul file
 | ||
| bool TRelation_application::test_key(
 | ||
|      word k,  // @parm Chiave da ricercare
 | ||
|      bool err)  // @parm Indica se visualizzare eventuali errori occorsi
 | ||
| {
 | ||
|   bool onereq = FALSE, onefill = FALSE;
 | ||
| 
 | ||
|   for (TEditable_field* e = _mask->get_key_field(k, TRUE);
 | ||
|        e != NULL; 
 | ||
|        e = _mask->get_key_field(k, FALSE))
 | ||
|   {
 | ||
|     if (e->required() && e->shown())
 | ||
|     {
 | ||
|       onereq = TRUE;
 | ||
|       if (e->empty())         
 | ||
|       {
 | ||
|         if (err)
 | ||
|         {                                               
 | ||
|           TString msg(80);
 | ||
|           msg = TR("Manca un valore indispensabile per la ricerca.");
 | ||
| #ifdef DBG
 | ||
|           msg << "\nChiave " << int(k) << " - Campo " << e->dlg(); 
 | ||
|           const TFieldref* fr = e->field();
 | ||
|           if (fr != NULL)
 | ||
|           {
 | ||
|             msg << " - " << fr->name(); 
 | ||
|             if (fr->to() > 0)
 | ||
|               msg << '[' << fr->from() << ',' << fr->to() << ']';
 | ||
|           }    
 | ||
| #endif          
 | ||
|           error_box(msg);
 | ||
|           _mask->first_focus(-e->dlg());
 | ||
|         }
 | ||
|         return FALSE;
 | ||
|       }
 | ||
|     }
 | ||
|     else
 | ||
|       /*      if (k == 1 && !onereq && !onefill && c.get().not_empty()) */
 | ||
|       if (!onereq && !onefill && e->is_edit() && !e->empty()) 
 | ||
|         onefill = TRUE;
 | ||
|   }
 | ||
|   if (k == 1 && !onereq && !onefill)
 | ||
|   {
 | ||
|     if (err)
 | ||
|       error_box(TR("Manca un valore indispensabile per la ricerca"));
 | ||
|     return FALSE;
 | ||
|   }
 | ||
|   return onefill || onereq;
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::find(word k)
 | ||
| {                         
 | ||
|   if (k == 0)
 | ||
|   {
 | ||
|     for (k = 1; k <= MAX_KEYS && !test_key(k, FALSE); k++);
 | ||
|     if (k > MAX_KEYS)
 | ||
|       return test_key(1, TRUE);
 | ||
|   }
 | ||
| 
 | ||
|   file().setkey(k);
 | ||
|   file().zero();
 | ||
|   for (TEditable_field* e = _mask->get_key_field(k, TRUE); e; e = _mask->get_key_field(k, FALSE))
 | ||
|   {
 | ||
|     if (e->shown())                        // Ignora campi invisibili
 | ||
|       e->autosave(*get_relation());
 | ||
|   }
 | ||
| 
 | ||
|   const int err = file().read(_isequal);
 | ||
|   return err == NOERR;
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::edit_cancel()
 | ||
| {
 | ||
|   if (_mask->mode() == MODE_MOD)
 | ||
|   {
 | ||
|     TRelation* rel = get_relation();
 | ||
|     rel->restore_status();
 | ||
|     rel->lfile().reread(_unlock);           // Unlock main file
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::save(bool check_dirty)
 | ||
| {
 | ||
|   static bool was_dirty = FALSE;
 | ||
|   
 | ||
|   int pos = _mask->id2pos(DLG_SAVEREC);
 | ||
|   if (pos < 0 || !_mask->fld(pos).active()) 
 | ||
|   {
 | ||
|     edit_cancel();
 | ||
|     return true;
 | ||
|   }
 | ||
| 
 | ||
|   int err = NOERR;
 | ||
|   const int mode = _mask->mode();
 | ||
|   if (check_dirty)
 | ||
|   {
 | ||
|     const short dirty = _mask->dirty();
 | ||
| 
 | ||
|     if (mode == MODE_QUERY)
 | ||
|     {
 | ||
|       const bool cont = !dirty || yesno_box(TR("Annullare i dati inseriti?"));
 | ||
|       return cont;
 | ||
|     }
 | ||
| 
 | ||
|     if (!dirty && !was_dirty) 
 | ||
|     {  
 | ||
|       edit_cancel();
 | ||
|       return true;
 | ||
|     }
 | ||
|     
 | ||
|     const KEY last = _mask->last_key();
 | ||
|     const bool annulla = last == K_ESC || last == K_QUIT || last == K_F9;
 | ||
|     const bool errore = dirty && _mask->field(dirty).dirty() > 1;
 | ||
|     
 | ||
|     KEY k; 
 | ||
|     if (errore)
 | ||
|     {
 | ||
|       if (annulla) 
 | ||
|       { 
 | ||
|         TString w;
 | ||
|         TMask_field& df = _mask->field(dirty);
 | ||
|         if (df.is_edit())
 | ||
|           w = ((TEdit_field&)df).get_warning();
 | ||
|         if (w.blank()) 
 | ||
|         {
 | ||
|           w = df.prompt();
 | ||
|           if (!w.blank()) 
 | ||
|           {
 | ||
|             w.trim();
 | ||
|             w << ' ' << TR("inconsistente.");
 | ||
|           }
 | ||
|         }
 | ||
|         if (w.blank()) 
 | ||
|           w = TR("Campo inconsistente.");
 | ||
|         w << '\n';
 | ||
|         switch (last)
 | ||
|         {
 | ||
|         case K_ESC:                   
 | ||
|           w << TR("Si desidera annullare?"); break;
 | ||
|         case K_QUIT:
 | ||
|           w << TR("Si desidera uscire?"); break;  
 | ||
|         default:
 | ||
|           w << TR("Si desidera continuare?"); break;
 | ||
|         } 
 | ||
|         k = yesno_box(w) ? K_NO : K_ESC;
 | ||
|         if (k == K_ESC) 
 | ||
|           _mask->first_focus(-dirty);
 | ||
|       }  
 | ||
|       else k = K_ESC;
 | ||
|     }
 | ||
|     else
 | ||
|       k = yesnocancel_box(TR("Si desidera registrare?")); 
 | ||
|     
 | ||
|     if (k == K_ESC || k == K_NO)
 | ||
|     {
 | ||
|       edit_cancel();
 | ||
|       was_dirty = false;
 | ||
|       return k == K_NO;
 | ||
|     }        
 | ||
| 
 | ||
|     if (annulla)
 | ||
|     {
 | ||
|       TMask_field& ff = _mask->focus_field();
 | ||
|       if (ff.focusdirty() && ff.is_edit()) // I need simulate tab on the current field!
 | ||
|       {
 | ||
|         if (!ff.on_key(K_TAB))
 | ||
|         {
 | ||
|           _mask->first_focus(-ff.dlg());
 | ||
|           was_dirty = TRUE; 
 | ||
|           return FALSE;
 | ||
|         }
 | ||
|       }
 | ||
|       if (!_mask->check_fields())                   // Exit with ESC didn't check values
 | ||
|       {                       
 | ||
|         // check_fields sets the focus on the blocking field
 | ||
|         _mask->first_focus(-_mask->focus_field().dlg());
 | ||
|         was_dirty = TRUE; 
 | ||
|         return FALSE;
 | ||
|       } 
 | ||
|     }   
 | ||
|   }
 | ||
|   was_dirty = FALSE;
 | ||
|   
 | ||
|   TWait_cursor hourglass;
 | ||
|   if (mode == MODE_INS)
 | ||
|   {
 | ||
|     bool changed = TRUE;        
 | ||
|     bool changed_key = FALSE;
 | ||
| 
 | ||
|     while (changed)
 | ||
|     {
 | ||
|       err = write(*_mask);
 | ||
|       if (err == _isreinsert)
 | ||
|       {
 | ||
|         changed = autonum(_mask, TRUE);
 | ||
|         if (!changed) 
 | ||
|         {
 | ||
|           _mask->disable_starting_check();
 | ||
|           enable_query();             // Abilita chiave 1 per rinumerazione manuale
 | ||
|         }
 | ||
|         else
 | ||
|           changed_key = TRUE;
 | ||
|       }  
 | ||
|       else
 | ||
|         changed = FALSE;
 | ||
|     }
 | ||
|     if (err == NOERR)
 | ||
|     {
 | ||
|       if (changed_key)
 | ||
|         message_box(_renum_message);
 | ||
|       get_relation()->save_status();
 | ||
|       set_limits();
 | ||
|       get_relation()->restore_status();
 | ||
|     }
 | ||
|   }
 | ||
|   else 
 | ||
|   {  
 | ||
|     get_relation()->restore_status();
 | ||
|     err = rewrite(*_mask);
 | ||
|   }
 | ||
|   
 | ||
|   switch(err)
 | ||
|   {
 | ||
|   case NOERR:
 | ||
|     _recins = get_relation()->lfile().recno();
 | ||
|     mask2mail(*_mask);
 | ||
|     break;
 | ||
|   case _isreinsert:
 | ||
|     warning_box(TR("Esiste gia' un elemento con la stessa chiave"));
 | ||
|     break;
 | ||
|   default:
 | ||
|     error_box(FR("Impossibile registrare i dati: errore %d"), err);
 | ||
|     break;
 | ||
|   }
 | ||
|   return err == NOERR;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| int TRelation_application::read(TMask& m)
 | ||
| {
 | ||
|   const TRelation &r = *get_relation();
 | ||
| 
 | ||
| /* Metodo VECCHIO!
 | ||
|   const int max = m.fields();
 | ||
|   for (int i = 0; i < max; i++)
 | ||
|   {
 | ||
|     if (m.fld(i).is_sheet()) 
 | ||
|     {
 | ||
|       TSheet_field& f = (TSheet_field&)m.fld(i);
 | ||
|       if (f.record() && !f.external_record()) 
 | ||
|         f.record()->read(*f.putkey(r));
 | ||
|     }
 | ||
|   }
 | ||
| */
 | ||
|   if (m.sheets() > 0)  // Metodo Salvatempo
 | ||
|   {
 | ||
|     FOR_EACH_MASK_SHEET(m, i, s)
 | ||
|     {
 | ||
|       if (s->record() && !s->external_record()) 
 | ||
|         s->record()->read(*s->putkey(r));
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   m.autoload(r);
 | ||
|   return NOERR;
 | ||
| }
 | ||
| 
 | ||
| int TRelation_application::write(const TMask& m)
 | ||
| {
 | ||
|   TRelation &r = *get_relation();
 | ||
|   m.autosave(r);
 | ||
|   r.curr().set_creation_info();
 | ||
| 
 | ||
|   // write relation and all independent sheets 
 | ||
|   int err=r.write();
 | ||
| 
 | ||
| /*
 | ||
|   const int max = m.fields();
 | ||
|   for (int i = 0; i < max; i++)
 | ||
|   {
 | ||
|     if (m.fld(i).is_sheet()) 
 | ||
|     {
 | ||
|       TSheet_field& f = (TSheet_field& )m.fld(i);
 | ||
|       if (f.record() && !f.external_record())
 | ||
|         err|=f.record()->write(FALSE);
 | ||
|     }
 | ||
|   }
 | ||
| */
 | ||
|   FOR_EACH_MASK_SHEET(m, i, s)
 | ||
|   {
 | ||
|     if (s->record() && !s->external_record())
 | ||
|       err |= s->record()->write(false);
 | ||
|   }
 | ||
| 
 | ||
|   return err;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| int TRelation_application::rewrite(const TMask& m)
 | ||
| {
 | ||
|   TRelation& r = *get_relation();
 | ||
|   m.autosave(r);
 | ||
|   r.curr().set_modify_info();
 | ||
|   // rewrite relation and all independent sheets 
 | ||
|   r.rewrite();
 | ||
|   int err=r.status();
 | ||
| 
 | ||
|   /*
 | ||
|   const int max = m.fields();
 | ||
|   for (int i = 0; i < max; i++)
 | ||
|   {
 | ||
|     if (m.fld(i).is_sheet()) 
 | ||
|     {
 | ||
|       TSheet_field& f = (TSheet_field&)m.fld(i);
 | ||
|       if (f.record()&& !f.external_record())
 | ||
|         err|=f.record()->write(TRUE);
 | ||
|     }
 | ||
|   }
 | ||
|   */
 | ||
|   FOR_EACH_MASK_SHEET(m, i, s)
 | ||
|   {
 | ||
|     if (s->record() && !s->external_record())
 | ||
|       err |= s->record()->write(true);
 | ||
|   }
 | ||
| 
 | ||
|   return err;
 | ||
| }
 | ||
| 
 | ||
| // @doc INTERNAL
 | ||
| 
 | ||
| // @mfunc Cancella il record corrente
 | ||
| //
 | ||
| // @rdesc Ritorna se il record e' stato eliminato
 | ||
| bool TRelation_application::relation_remove()
 | ||
| // @comm Se la maschera e' in MODE_MOD non e' possibile cancellare il record e viene
 | ||
| //   emesso un <f CHECK> di errore.
 | ||
| {
 | ||
|   CHECK(_mask->edit_mode(), "You can call remove in edit mode only");
 | ||
| 
 | ||
|   TRelation& r = *get_relation();
 | ||
|   r.restore_status();
 | ||
|   if (protected_record(r))
 | ||
|     return message_box(TR("Elemento non eliminabile"));
 | ||
| 
 | ||
|   if (_curr_transaction == TRANSACTION_DELETE || yesno_box(TR("Confermare l'eliminazione")))
 | ||
|   {
 | ||
|     r.restore_status();
 | ||
|     const bool ok = remove();
 | ||
|     if (ok || is_transaction())
 | ||
|       set_limits();
 | ||
|     else
 | ||
|     {
 | ||
|       const int err = r.status();
 | ||
|       if (err != NOERR) // Succede nei remove con richiesta di conferma all'utente
 | ||
|         return error_box(FR("Errore di cancellazione %d"), err);
 | ||
|     }
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TRelation_application::protected_record(TRelation &r) 
 | ||
| {
 | ||
|   if (user_can_delete(&r))
 | ||
|     return protected_record(r.curr());
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::remove()
 | ||
| {
 | ||
|   int err = get_relation()->remove();
 | ||
|   if (err == NOERR)
 | ||
|   {
 | ||
|     const int maxf = _mask->fields();
 | ||
|     for (int i = 0; i < maxf; i++)
 | ||
|     {
 | ||
|       const TMask_field& mf = _mask->fld(i);
 | ||
|       if (mf.is_sheet()) 
 | ||
|       {
 | ||
|         TSheet_field& f = (TSheet_field&)mf;
 | ||
|         if (f.record()&& !f.external_record())
 | ||
|           err |= f.record()->remove();
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   if (err == NOERR)
 | ||
|   {
 | ||
|     _mask->set_mode(NO_MODE);
 | ||
|     mask2mail(*_mask);
 | ||
|   }
 | ||
|   return err == NOERR;
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::firm_change_enabled() const
 | ||
| {
 | ||
|   bool ok = TApplication::firm_change_enabled();
 | ||
|   ok &= (_mask == NULL || _mask->query_mode()) && _lnflag == 0;
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::main_loop()
 | ||
| { 
 | ||
|   KEY k;
 | ||
|   do { 
 | ||
|     // ciclo delle transazioni
 | ||
|     _recins = -1;
 | ||
|     
 | ||
|     // imposta la maschera in query mode
 | ||
|     query_mode();
 | ||
|     _mask->open_modal();
 | ||
|     
 | ||
|     // Provoca l'autopremimento per il messaggio di LINK
 | ||
|     if (_lnflag)
 | ||
|     {
 | ||
|       if (_trans_counter < _ntransactions)
 | ||
|       {
 | ||
|         // la transazione <20> sul .ini : la imposta nelle variabili _curr_transaction...
 | ||
|         if (load_transaction())
 | ||
|         {
 | ||
|           // la transazione necessita di autopremimento
 | ||
|           _autodelete = _curr_transaction == TRANSACTION_DELETE;
 | ||
|           if (_curr_transaction == TRANSACTION_INSERT )
 | ||
|             _mask->send_key(K_CTRL+'N', 0);
 | ||
|           else 
 | ||
|             _mask->send_key(K_AUTO_ENTER, 0);
 | ||
|         } 
 | ||
|       } 
 | ||
|       else // la transazione non <20> sul .ini 
 | ||
|       {
 | ||
|         _mask->send_key(K_AUTO_ENTER, 0);
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     if (is_transaction())  
 | ||
|       ini2query_mask();
 | ||
|     
 | ||
|     do
 | ||
|     {
 | ||
|       const bool change = firm_change_enabled();
 | ||
|       // Dis/abilita cambio ditta
 | ||
|       enable_menu_item(M_FILE_NEW, change);
 | ||
|       
 | ||
|       if (_mask->edit_mode())
 | ||
|       {
 | ||
|         if (_autodelete)
 | ||
|         {                                
 | ||
|           const int pos = _mask->id2pos(DLG_DELREC);
 | ||
|           if (pos >= 0 && _mask->fld(pos).active())
 | ||
|             _mask->send_key(K_CTRL+'E', 0);    
 | ||
|           else
 | ||
|             error_box(TR("Elemento non eliminabile."));
 | ||
|           _autodelete = FALSE;
 | ||
|         } 
 | ||
|       }
 | ||
|   
 | ||
|       k = _mask->run();
 | ||
|   
 | ||
|       switch (k)
 | ||
|       {
 | ||
|       case K_ESC:
 | ||
|         if (save(TRUE))
 | ||
|         {
 | ||
|           if (save_and_quit())
 | ||
|             k = K_QUIT;
 | ||
|           else
 | ||
|             query_mode();
 | ||
|         }
 | ||
|         break;                             
 | ||
|       case K_QUIT:      
 | ||
|         if (!save(TRUE))
 | ||
|           k = K_ENTER;
 | ||
|         break;
 | ||
|       case K_F1:
 | ||
|         dispatch_e_menu(M_HELP_CONTENTS);
 | ||
|         break;
 | ||
|       case K_F2:
 | ||
|         dispatch_e_menu(M_FILE_ABOUT);
 | ||
|         break;
 | ||
|       case K_ENTER:
 | ||
|         if (_lnflag && _curr_transaction != TRANSACTION_RUN)
 | ||
|         {     
 | ||
|           if (find(1))
 | ||
|           {
 | ||
|             if (_curr_transaction == TRANSACTION_INSERT)
 | ||
|               _curr_transaction = TRANSACTION_MODIFY;
 | ||
|             modify_mode();
 | ||
|           }
 | ||
|           else       
 | ||
|           { 
 | ||
|             if (_curr_transaction == TRANSACTION_MODIFY)
 | ||
|               _curr_transaction = TRANSACTION_INSERT;
 | ||
|             insert_mode();
 | ||
|           }
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           if (find(0)) 
 | ||
|             modify_mode();
 | ||
|           else 
 | ||
|             insert_mode();
 | ||
|         }
 | ||
|         if (_curr_trans_mode == TM_AUTOMATIC)
 | ||
|           _mask->send_key(K_CTRL+'R', 0);    
 | ||
|         break;
 | ||
|       case K_SAVE:
 | ||
|         if (save(FALSE))
 | ||
|         {
 | ||
|           if (save_and_quit())
 | ||
|           {
 | ||
|             k = K_QUIT;
 | ||
|           }
 | ||
|           else
 | ||
|           {
 | ||
|             if (save_and_new())
 | ||
|             {
 | ||
|               if (_mask->insert_mode())
 | ||
|                 insert_mode();
 | ||
|               else
 | ||
|                 query_mode();
 | ||
|             }  
 | ||
|             else  
 | ||
| 						{
 | ||
| 							const TMask_field & f = _mask->focus_field();
 | ||
| 
 | ||
| 							_mask->first_focus(-f.dlg(), false);
 | ||
|               modify_mode();
 | ||
| 						}
 | ||
|           }  
 | ||
|         }
 | ||
|         break;
 | ||
|       case K_INS:
 | ||
|         if (_mask->query_mode() || save(TRUE))
 | ||
|         {
 | ||
|           const bool trovato = _mask->query_mode() && test_key(1, FALSE) && find(1);
 | ||
|           if (trovato)
 | ||
|           { 
 | ||
|             if (is_transaction())
 | ||
|               _curr_transaction=TRANSACTION_MODIFY;
 | ||
|             else
 | ||
|               warning_box(TR("Elemento gia' presente"));
 | ||
|             modify_mode();
 | ||
|           }
 | ||
|           else
 | ||
|             insert_mode();
 | ||
|         }  
 | ||
|         if (_curr_trans_mode == TM_AUTOMATIC)
 | ||
|           _mask->send_key(K_CTRL+'R', 0);    
 | ||
|         break;
 | ||
|       case K_DEL:
 | ||
|         if (_mask->query_mode())
 | ||
|         {  
 | ||
|           delete_mode();           
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           if (relation_remove())
 | ||
|           {
 | ||
|             query_mode();
 | ||
|             if (_autoins_caller.not_empty() || is_transaction())
 | ||
|             {    
 | ||
|               if (_lnflag) _recins = 0;
 | ||
|               k = K_QUIT;
 | ||
|             }  
 | ||
|           }
 | ||
|         }
 | ||
|         break;
 | ||
|       case K_F9:   
 | ||
|         if (_mask->query_mode() || save(TRUE))
 | ||
|           search_mode();
 | ||
|         break;
 | ||
|       default:
 | ||
|         if (save(TRUE))
 | ||
|         {
 | ||
|           setkey();
 | ||
|           int err = ~NOERR;
 | ||
|           switch (k)
 | ||
|           {
 | ||
|           case K_HOME:
 | ||
|             err = file().readat(_first, _testandlock);
 | ||
|             break;
 | ||
|           case K_NEXT:
 | ||
|             err = file().reread();
 | ||
|             if (has_filtered_cursor())
 | ||
|             {
 | ||
|               TCursor& cur = get_filtered_cursor();
 | ||
|               cur.curr() = file().curr();
 | ||
|               cur.read();
 | ||
|               ++cur;
 | ||
|               file().curr() = cur.curr();
 | ||
|               err = get_relation()->read(_isequal, _testandlock);
 | ||
|             }
 | ||
|             else
 | ||
|               err = file().next(_testandlock);
 | ||
|             break;
 | ||
|           case K_PREV:
 | ||
|             file().reread();
 | ||
|             if (has_filtered_cursor())
 | ||
|             {
 | ||
|               TCursor& cur = get_filtered_cursor();
 | ||
|               cur.curr() = file().curr();
 | ||
|               cur.read();
 | ||
|               --cur;
 | ||
|               file().curr() = cur.curr();
 | ||
|               err = get_relation()->read(_isequal, _testandlock);
 | ||
|             }
 | ||
|             else
 | ||
|               err = file().prev(_testandlock);
 | ||
|             break;
 | ||
|           case K_END:
 | ||
|             err = file().readat(_last, _testandlock);
 | ||
|             break;
 | ||
|           default:
 | ||
|             break;
 | ||
|           }
 | ||
|           if (err == NOERR || err == _islocked) 
 | ||
|           {
 | ||
|             _navigating = true;
 | ||
|             modify_mode();
 | ||
|             _navigating = false;
 | ||
|           }
 | ||
|           else 
 | ||
|             query_mode();
 | ||
|         }
 | ||
|         break;
 | ||
|       }
 | ||
|     } while (k != K_QUIT);
 | ||
| 
 | ||
|     if (_mask->is_open())
 | ||
|       _mask->close_modal();
 | ||
| 
 | ||
|     _mask->set_mode(NO_MODE);
 | ||
| 
 | ||
|     if (autoins_caller().not_empty() && _recins >= 0)
 | ||
|     { 
 | ||
|       NFCHECK("Obsolete LINK message calling convention");
 | ||
|       TString16 num; 
 | ||
|       num.format("%ld", _recins);
 | ||
|       TMessage msg(autoins_caller(), _lnflag ? MSG_LN : MSG_AI, num);
 | ||
|       msg.send();
 | ||
|     }
 | ||
|     
 | ||
|     if (is_transaction())
 | ||
|     { 
 | ||
|       TConfig ini(_trans_ini.row(_trans_counter), "Transaction");
 | ||
|       ini.set("Record", _recins);
 | ||
|       if (_recins >= 0)
 | ||
|       {
 | ||
|         ini.set("Result", "OK");
 | ||
|         ini.set("Error", "0");
 | ||
|         edit_mask2ini();
 | ||
|       }
 | ||
|       else
 | ||
|       {                    
 | ||
|         const int err = get_relation()->status();
 | ||
|         ini.set("Result", err == NOERR ? "CANCEL" : "ERROR");
 | ||
|         ini.set("Error", err);
 | ||
|       }   
 | ||
|     
 | ||
|     }
 | ||
|     _trans_counter++;
 | ||
|   } while ( _trans_counter < _ntransactions);
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::filter()
 | ||
| {                          
 | ||
|   if (parse_command_line())
 | ||
|     return true;
 | ||
| 
 | ||
|   TMailbox mail;
 | ||
|   TMessage* msg = mail.next_s(MSG_FS);
 | ||
| 
 | ||
|   if (msg)
 | ||
|   {
 | ||
|     _mask = get_mask(MODE_MOD);
 | ||
|     TToken_string body(msg->body());
 | ||
| 
 | ||
|     short id = body.get_int();
 | ||
|     while (id > 0)
 | ||
|     {
 | ||
|       _search_id = id;
 | ||
|       TEdit_field& f = _mask->efield(id);
 | ||
|       TCursor* cur = f.browse()->cursor();
 | ||
|       TRectype& rec = cur->curr();
 | ||
|       rec.zero();
 | ||
|       
 | ||
|       TString80 t;
 | ||
|       const char* s;
 | ||
|       while((s = body.get()) != NULL)
 | ||
|       {
 | ||
|         t = s;
 | ||
|         const int u = t.find('=');
 | ||
|         if (u < 0)
 | ||
|         {
 | ||
|           id = atoi(t);
 | ||
|           break;
 | ||
|         }
 | ||
|         _fixed.add(t);
 | ||
|         const short fid = atoi(t.left(u));
 | ||
|         const TFieldref* campo = _mask->field(fid).field();
 | ||
|         if (campo != NULL)
 | ||
|           campo->write(t.mid(u+1), rec);
 | ||
|       }
 | ||
|       cur->setfilter("");
 | ||
|       cur->setregion(rec, rec, 0x2);
 | ||
|       if (s == NULL) id = 0;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   mail.restart();
 | ||
|   msg = mail.next_s(MSG_AI);
 | ||
|   if (msg) _autoins_caller = msg->from();
 | ||
| 
 | ||
|   mail.restart();
 | ||
|   msg = mail.next_s(MSG_LN);
 | ||
|   if (msg) 
 | ||
|   {
 | ||
|     TToken_string body(msg->body());
 | ||
|     const int key = body.get_int();
 | ||
|     
 | ||
|     _autoins_caller = msg->from();
 | ||
|     _lnflag = TRUE;
 | ||
|     
 | ||
|     TString str, tmp;
 | ||
|     const char* v = body.get();
 | ||
|     for (int i = 0; v != NULL && i < _mask->fields(); i++)
 | ||
|     {
 | ||
|       TMask_field& f = _mask->fld(i);
 | ||
|       if (f.active() && f.dlg() > 0 && f.in_key(key))
 | ||
|       {        
 | ||
|         str = v;
 | ||
|         tmp.format("%d=", f.dlg());
 | ||
|         str.insert(tmp, 0);
 | ||
|         _fixed.add(str);
 | ||
|         v = body.get();
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   mail.restart();
 | ||
|   msg = mail.next_s(MSG_ED);
 | ||
|   if (msg) 
 | ||
|   {
 | ||
|     TToken_string body(msg->body());
 | ||
|     const int key = body.get_int();
 | ||
|     
 | ||
|     _autoins_caller = msg->from();
 | ||
|     _lnflag = 2;       
 | ||
| 
 | ||
|     TAssoc_array field_values;
 | ||
|     const char * s;
 | ||
|     TString t, v;
 | ||
|     
 | ||
|     while((s = body.get()) != NULL)
 | ||
|     {  
 | ||
|       t = s;
 | ||
|       const int u = t.find('=');
 | ||
|       
 | ||
|       CHECKS(u > 0, "Invalid edit message ", (const char *) body);
 | ||
|       if (u > 0)
 | ||
|       {                       
 | ||
|         v = t.mid(u + 1);
 | ||
|         
 | ||
|         t.cut(u);
 | ||
|         field_values.add(t, v);
 | ||
|       } 
 | ||
|     }
 | ||
|       
 | ||
|     for (int i = 0; i < _mask->fields(); i++)
 | ||
|     {
 | ||
|       TMask_field& f = _mask->fld(i);
 | ||
|       const TFieldref * field = f.field();
 | ||
|       
 | ||
|       if (field && f.in_key(key))
 | ||
|       {                                       
 | ||
|         TString16 field_name(field->name()); 
 | ||
|         const int from = field->from();
 | ||
|         const int to = field->to();
 | ||
|         
 | ||
|         if (to >= 0)
 | ||
|           field_name << "[" << (from + 1);
 | ||
|         const TString * v = (const TString *) field_values.objptr(field_name);
 | ||
|         
 | ||
|         TString val;
 | ||
|         if (v == NULL && to >= 0)
 | ||
|         {
 | ||
|           v = (const TString *)field_values.objptr(field->name());
 | ||
|           if (v) 
 | ||
|             val = v->sub(from, to);
 | ||
|         }
 | ||
|         else
 | ||
|           if (v) val = *v;   
 | ||
|         
 | ||
|         if (v && f.dlg() > 0)
 | ||
|         {
 | ||
|           t.format("%d=", f.dlg());
 | ||
|           val.insert(t, 0);
 | ||
|           _fixed.add(val);
 | ||
|         }  
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::set_link(TMask & m, const char * keyexpr)
 | ||
| {
 | ||
|   CHECK(keyexpr != NULL, "Invalid expression");
 | ||
|   TToken_string body(keyexpr);
 | ||
|   const int key = body.get_int();
 | ||
|   
 | ||
|   _lnflag = TRUE;
 | ||
|   
 | ||
|   const char* v = body.get();
 | ||
|   
 | ||
|   TString16 tmp;                      
 | ||
|   const int max = m.fields();
 | ||
|   for (int i = 0; i < max && v != NULL; i++)
 | ||
|   {
 | ||
|     TMask_field& f = m.fld(i);
 | ||
|     
 | ||
|     if (f.active() && f.dlg() > 0 && f.in_key(key))
 | ||
|     {                          
 | ||
|       TString s(v);  
 | ||
|       tmp.format("%d=", f.dlg());
 | ||
|       s.insert(tmp, 0);
 | ||
|       _fixed.add(s);
 | ||
|       v = body.get();
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TRelation_application::parse_command_line() 
 | ||
| {         
 | ||
|   _trans_ini.destroy(); 
 | ||
|   _trans_counter=0;
 | ||
|   _curr_transaction = "";
 | ||
|   _curr_trans_mode = 'I';
 | ||
|   
 | ||
|   TFilename ini;
 | ||
|   for (int i = argc()-1; i > 0; i--)
 | ||
|   {
 | ||
|     ini = argv(i);
 | ||
|     if ((ini[0] == '-' || ini[0] == '/') && (ini[1] == 'I' || ini[1] == 'i'))
 | ||
|     {
 | ||
|       ini.ltrim(2);
 | ||
|       CHECK(!ini.blank(),"Manca l'indicazione della transazione. Il nome va indicato di seguito al -i, senza interporre spaziatura.");
 | ||
|       if (ini.find('*')>=0)
 | ||
|       {
 | ||
|         // metachars:
 | ||
|         list_files(ini, _trans_ini);
 | ||
|       }
 | ||
|       else
 | ||
|         _trans_ini.add(ini);
 | ||
|       break;
 | ||
|     }
 | ||
|   } 
 | ||
|   
 | ||
|   _ntransactions= _trans_ini.items();
 | ||
|   
 | ||
|   _lnflag = _ntransactions>0;
 | ||
|   return _lnflag != 0;
 | ||
| }                         
 | ||
| 
 | ||
| // il valore di ritorno  indica se attivare l'"automagia":
 | ||
| // spedizione dei tasti e precaricamento della maschera
 | ||
| bool TRelation_application::load_transaction() 
 | ||
| {
 | ||
|   bool retv = FALSE;
 | ||
|   if (_trans_counter < _ntransactions)
 | ||
|   {
 | ||
|     TConfig cnf(_trans_ini.row(_trans_counter), "Transaction");
 | ||
|     _curr_transaction = cnf.get("Action");
 | ||
|     _curr_transaction.upper();
 | ||
|     _curr_trans_mode = toupper(cnf.get("Mode")[0]);
 | ||
|     _curr_trans_from = cnf.get("From");  
 | ||
|     const long firm = cnf.get_long("Firm");
 | ||
|     if (firm > 0)    
 | ||
|     {
 | ||
|       bool ok = set_firm(firm);
 | ||
|       if (ok) 
 | ||
|         _mask->on_firm_change();
 | ||
|       else
 | ||
|         error_box(FR("La ditta %ld non esiste"), firm);
 | ||
|     }
 | ||
|     if (_curr_transaction == TRANSACTION_RUN)
 | ||
|       retv = false;    // Ho gia' finito qui: basta il cambio ditta
 | ||
|     else
 | ||
|       retv = true;    // Attiva automagia
 | ||
|   }
 | ||
|   return retv;
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::on_firm_change()
 | ||
| {
 | ||
|   TApplication::on_firm_change();
 | ||
|   if (_mask != NULL)
 | ||
|   {
 | ||
|     set_limits(0x3);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::ini2query_mask() 
 | ||
| {            
 | ||
|   if (is_transaction())
 | ||
|   {         
 | ||
|     TString8 n; n.format("%d", get_relation()->lfile().num());
 | ||
|     TConfig ini(_trans_ini.row(_trans_counter), n);
 | ||
|     ini2mask(ini, *_mask, TRUE);
 | ||
|   }     
 | ||
| }      
 | ||
| 
 | ||
| void TRelation_application::ini2insert_mask() 
 | ||
| {
 | ||
|   if (is_transaction())
 | ||
|   {        
 | ||
|     TString8 n; n.format("%d", get_relation()->lfile().num());
 | ||
|     TConfig ini(_trans_ini.row(_trans_counter), n);
 | ||
|     ini2mask(ini, *_mask, FALSE);
 | ||
|   }     
 | ||
| }
 | ||
|  
 | ||
| void TRelation_application::ini2mask(TConfig& ini, TMask& m, bool query)
 | ||
| {
 | ||
|   const TString16 defpar = ini.get_paragraph();
 | ||
| 	TString tmp;
 | ||
| 
 | ||
| 	_fixed.cut(0);
 | ||
|   for (int f = m.fields()-1; f >= 0; f--)
 | ||
|   {
 | ||
|     TMask_field& campo = m.fld(f);
 | ||
|     const TFieldref* fref = campo.field();
 | ||
|     if (fref)
 | ||
|     {
 | ||
|       if (!query || campo.in_key(0))
 | ||
|       {
 | ||
|         const TString& str = fref->read(ini, defpar);
 | ||
|         if (str.not_empty())
 | ||
| 				{
 | ||
|           campo.set(str);
 | ||
| 					if (query)
 | ||
| 					{
 | ||
| 						tmp.format("%d=%s", campo.dlg(), (const char *) str);
 | ||
| 						_fixed.add(tmp);
 | ||
| 					}
 | ||
| 				}
 | ||
|       }
 | ||
|     }
 | ||
|     else 
 | ||
|     {
 | ||
|       if (!query && campo.is_sheet())
 | ||
|       {
 | ||
|         TSheet_field &sheet=(TSheet_field &)campo;
 | ||
|         ini2sheet(ini, sheet);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   ini.set_paragraph(defpar);
 | ||
| 	if (query)
 | ||
| 		set_fixed();
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::edit_mask2ini() 
 | ||
| {            
 | ||
|   const TString& str = _trans_ini.row(_trans_counter);
 | ||
|   if (str.full())
 | ||
|   {         
 | ||
|     TString8 head; head.format("%d", get_relation()->lfile().num());
 | ||
|     TConfig ini(str, head);
 | ||
|     mask2ini(*_mask, ini);
 | ||
|   }     
 | ||
| }      
 | ||
| 
 | ||
| 
 | ||
| void TRelation_application::ini2sheet(TConfig& ini,TSheet_field &sheet)
 | ||
| {
 | ||
|   if (sheet.record() != NULL)
 | ||
|   {
 | ||
|     const int lognum = sheet.record()->logic_num();
 | ||
|     const TMask& sm = sheet.sheet_mask();
 | ||
| 
 | ||
|     // scrive le righe nello sheet associato
 | ||
|     TString16 defpar;
 | ||
|     
 | ||
|     for (int r = 1; ;r++)
 | ||
|     {
 | ||
|       defpar.format("%d,%d", lognum, r);
 | ||
|       if (ini.set_paragraph(defpar))
 | ||
|       {
 | ||
|         TToken_string& row = sheet.row(r-1);
 | ||
|         for (int sf = sm.fields()-1; sf >= 0; sf--)
 | ||
|         {
 | ||
|           TMask_field& campo = sm.fld(sf);
 | ||
|           const TFieldref* fref = campo.field();
 | ||
|           if (fref)
 | ||
|           {     
 | ||
|             const TString& str = fref->read(ini, defpar);
 | ||
|             row.add(str, sheet.cid2index(campo.dlg()));
 | ||
|           } 
 | ||
|         }
 | ||
|         sheet.check_row(r-1);
 | ||
|       }
 | ||
|       else
 | ||
|         break;
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TRelation_application::sheet2ini(TSheet_field &sheet,TConfig& ini)
 | ||
| {
 | ||
|   if (sheet.record() != NULL)
 | ||
|   {
 | ||
|     const int lognum = sheet.record()->logic_num();
 | ||
|     const TMask& sm = sheet.sheet_mask();
 | ||
| 
 | ||
|     // scrive le righe degli sheet associati
 | ||
|     TString16 defpar;
 | ||
|     TString str;
 | ||
|     int r;
 | ||
|     
 | ||
|     for (r = 1 ; r <= sheet.items(); r++)
 | ||
|     {
 | ||
|       defpar.format("%d,%d", lognum, r);
 | ||
|   
 | ||
|       TMask_field* fkey;
 | ||
|       sheet.restart_key();
 | ||
|       while ((fkey = sheet.get_key(str)))
 | ||
|       {
 | ||
|         ini.set(str, fkey->get(), defpar);
 | ||
|       }        
 | ||
|       
 | ||
|       TToken_string& row = sheet.row(r-1);
 | ||
|       const char* value;
 | ||
|       int i;
 | ||
|       for (i = 0, value = row.get(0); value; i++, value = row.get())
 | ||
|       {
 | ||
|         const TMask_field& campo = sm.field(FIRST_FIELD+i);
 | ||
|         const TFieldref* fr = campo.field();
 | ||
|         if (fr)
 | ||
|         {
 | ||
|           if (value == NULL || *value == '\0') 
 | ||
|             value = " ";
 | ||
|           // ini.set(fr->name(), value, defpar);
 | ||
|           fr->write(ini, defpar, value);
 | ||
|         } 
 | ||
|       } 
 | ||
|     } 
 | ||
|     for (r = sheet.items()+1; ; r++)
 | ||
|     {
 | ||
|       defpar.format("%d,%d", lognum, r);
 | ||
|       if (ini.set_paragraph(defpar))
 | ||
|         ini.remove_all();
 | ||
|       else
 | ||
|         break;  
 | ||
|     }
 | ||
|   }
 | ||
| } 
 | ||
| 
 | ||
| void TRelation_application::mask2ini(const TMask& m, TConfig& ini)
 | ||
| {
 | ||
|   ini.set("Firm", get_firm(), "Transaction");
 | ||
| 
 | ||
|   int year, release, tag, patch;
 | ||
|   if (get_version_info(year, release, tag, patch))
 | ||
|   {
 | ||
|     TString80 ver;
 | ||
|     ver.format("%d %d.%d-%d", year, release, tag, patch);
 | ||
|     ini.set("Version", ver);
 | ||
|   }
 | ||
| 
 | ||
|   const TLocalisamfile& lfile = get_relation()->lfile();
 | ||
|   
 | ||
|   TString16 defpar; 
 | ||
|   defpar.format("%d", lfile.num());
 | ||
|   ini.set_paragraph(defpar);
 | ||
|   switch (lfile.num())
 | ||
|   {
 | ||
|     case LF_TAB:
 | ||
|     case LF_TABCOM:
 | ||
|     case LF_TABGEN:
 | ||
|     {          
 | ||
|       const TString& tabname = lfile.curr().get("COD");
 | ||
|       ini.set("COD", tabname, defpar);
 | ||
|     }
 | ||
|     break;
 | ||
|   }
 | ||
|   for (int f = 0; f < m.fields(); f++)
 | ||
|   {
 | ||
|     TMask_field& campo = m.fld(f);
 | ||
|     if (campo.shown())
 | ||
|     { 
 | ||
|       const TFieldref* fr = campo.field();
 | ||
|       if (fr)
 | ||
|       {                
 | ||
|         if (campo.empty())
 | ||
|           fr->write(ini, defpar, " ");
 | ||
|         else
 | ||
|         {
 | ||
|           if (campo.class_id() == CLASS_DATE_FIELD && campo.right_justified())
 | ||
|           {
 | ||
|             const TDate d(campo.get());
 | ||
|             fr->write(ini, defpar, d.string(ANSI));
 | ||
|           }
 | ||
|           else
 | ||
|             fr->write(ini, defpar, campo.get());
 | ||
|         }
 | ||
|       } 
 | ||
|       else 
 | ||
|         if (campo.is_sheet())
 | ||
|         {
 | ||
|           TSheet_field &sheet=(TSheet_field &)campo;
 | ||
|           sheet2ini(sheet,ini);  // It's virtual
 | ||
|         }
 | ||
|     }
 | ||
|   } 
 | ||
|   ini.set_paragraph(defpar); // Reimposta paragrafo standard
 | ||
| }
 | ||
| 
 | ||
| bool TRelation_application::mask2mail(const TMask& m)
 | ||
| {
 | ||
|   TWait_cursor hourglass;
 | ||
|   bool ok = _curr_trans_from.empty() && ::can_dispatch_transaction(get_relation()->curr());   
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     TFilename ininame; ininame.temp();
 | ||
|     if (ok) // Test qualunque per usare {}
 | ||
|     {
 | ||
|       TConfig ini(ininame, "Transaction");
 | ||
|       const char* action = "";
 | ||
|       char mode[2] = { TM_AUTOMATIC, '\0' };
 | ||
|       switch (m.mode())
 | ||
|       {
 | ||
|       case NO_MODE:
 | ||
|         action = TRANSACTION_DELETE;
 | ||
|         break;
 | ||
|       case MODE_MOD:
 | ||
|         action = TRANSACTION_MODIFY;
 | ||
|         break;
 | ||
|       default:
 | ||
|         action = TRANSACTION_INSERT;
 | ||
|         break;
 | ||
|       }
 | ||
|       ini.set("Action", action);
 | ||
|       ini.set("Mode", mode);
 | ||
|       mask2ini(m, ini);
 | ||
|     }
 | ||
|     ok = ::dispatch_transaction(get_relation()->curr(), ininame);
 | ||
|     xvt_fsys_remove_file(ininame);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 |