1003 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1003 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <mailbox.h>
 | |
| #include <sheet.h>
 | |
| #include <urldefid.h>
 | |
| #include <relapp.h>
 | |
| #include <utility.h>
 | |
| #define STRICT
 | |
| #define XVT_INCL_NATIVE
 | |
| #include <xvtility.h>
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
| #include <windows.h>
 | |
| #endif
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRelation_application
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TRelation_application::TRelation_application()
 | |
|                      : _mask(NULL), _search_id(-1), _lnflag(FALSE)
 | |
| { }
 | |
| 
 | |
| TRelation_application::~TRelation_application()
 | |
| { }
 | |
| 
 | |
| void TRelation_application::setkey()
 | |
| {
 | |
|   if (has_filtered_cursor())
 | |
|   {
 | |
|     TEdit_field& f = get_search_field();
 | |
|     TCursor* cur = f.browse()->cursor();
 | |
|     cur->setkey();
 | |
|     return;
 | |
|   }
 | |
|   file().setkey(1);
 | |
| }
 | |
| 
 | |
| 
 | |
| // @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())
 | |
|   {
 | |
|     TEdit_field& f = get_search_field();
 | |
|     
 | |
|     TBrowse* b = f.browse();
 | |
|     TCursor* cur = b != NULL ? b->cursor() : NULL;
 | |
|     if (cur)
 | |
|     {
 | |
|       cur->setkey();
 | |
|       f.browse()->do_input(TRUE);
 | |
|       if (cur->items() == 0) _first = _last = -1;
 | |
|       else
 | |
|       {
 | |
|         if (what & 0x1)
 | |
|         {
 | |
|           *cur = 0;
 | |
|           _first = cur->file().recno();
 | |
|         }
 | |
|         if (what & 0x2)
 | |
|         {
 | |
|           *cur = cur->items() - 1;
 | |
|           _last = cur->file().recno();
 | |
|         }
 | |
|       }
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   file().setkey(1);
 | |
|   if (what & 0x1)
 | |
|   {
 | |
|     if (file().empty()) _first = 1;
 | |
|     else
 | |
|     {
 | |
|       file().first();
 | |
|       _first = file().recno();
 | |
|     }
 | |
|   }
 | |
|   if (what & 0x2)
 | |
|   {
 | |
|     if (file().empty()) _last = 1;
 | |
|     else
 | |
|     {
 | |
|       file().last();
 | |
|       _last = file().recno();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TRelation_application::create()
 | |
| {
 | |
|   TApplication::create();
 | |
|   const bool ok = user_create();
 | |
|   if (ok)
 | |
|   {
 | |
|     write_enable();
 | |
|     _mask = get_mask(MODE_QUERY);
 | |
|     filter();
 | |
|     set_limits();
 | |
|     dispatch_e_menu(BAR_ITEM(1));
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRelation_application::menu(MENU_TAG m)
 | |
| {
 | |
|   if (m == BAR_ITEM(1))
 | |
|     return main_loop();
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRelation_application::destroy()
 | |
| {   
 | |
|   user_destroy();
 | |
|   return TApplication::destroy();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRelation_application::set_fixed()
 | |
| {
 | |
|   TToken_string s(256, '=');
 | |
|   for (const char* f = _fixed.get(0); f && *f; f = _fixed.get())
 | |
|   {
 | |
|     s = f;
 | |
|     const int id = s.get_int(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(bool all)
 | |
| {
 | |
|   const int mode = _mask->mode();
 | |
|   int pos;
 | |
| 
 | |
|   if (all)
 | |
|   {
 | |
|     pos = _mask->id2pos(DLG_SAVEREC);
 | |
|     if (pos >= 0) _mask->fld(pos).enable(mode != MODE_QUERY);
 | |
|     pos = _mask->id2pos(DLG_DELREC);
 | |
|     if (pos >= 0) 
 | |
|     {               
 | |
|       bool enabdel = mode == MODE_MOD;
 | |
|       if (enabdel)
 | |
|       {
 | |
|         TRelation& r = *get_relation();
 | |
|         const TRecnotype oldpos = r.lfile().recno();
 | |
|         enabdel = !protected_record(r.curr());
 | |
|         if (r.lfile().recno() != oldpos) 
 | |
|           r.lfile().readat(oldpos);
 | |
|       }  
 | |
|       _mask->fld(pos).enable(enabdel);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   enable_query();
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRelation_application::save_and_new() const
 | |
| { return FALSE; }
 | |
| 
 | |
| 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);
 | |
| 
 | |
|   if (mode == _mode)
 | |
|   {
 | |
|     set_toolbar(FALSE); // Fast buttons update
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     set_toolbar(TRUE);  // Full buttons update
 | |
|     _mode = mode;
 | |
|   }
 | |
| 
 | |
|   const char* t = "";
 | |
|   switch(mode)
 | |
|   {
 | |
|   case MODE_QUERY: 
 | |
|     t = "Ricerca"; break;
 | |
|   case MODE_MOD: 
 | |
|     t = "Modifica"; break;
 | |
|   case NO_MODE: 
 | |
|     t = "Ricerca/Inserimento"; break;
 | |
|   case MODE_INS: 
 | |
|     t = "Inserimento"; break;
 | |
|   default: 
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   xvt_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(get_next_key());
 | |
|   
 | |
|   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, "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("Il documento 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();
 | |
| 
 | |
|   if (pre_ins)
 | |
|   {
 | |
|     set_mode(NO_MODE);
 | |
|     init_query_insert_mode(*_mask);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     set_mode(MODE_QUERY);
 | |
|     init_query_mode(*_mask);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRelation_application::insert_mode()
 | |
| {               
 | |
|   if (_mask->query_mode())
 | |
|   {                        
 | |
|     if (test_key(1, FALSE) == FALSE)
 | |
|     {
 | |
|       if (!autonum(_mask, FALSE))
 | |
|       {
 | |
|         query_insert_mode();
 | |
|         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();
 | |
|       ::remove(workname);
 | |
|       _mask->open_modal();
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (!autonum(_mask, FALSE))
 | |
|     {
 | |
|       query_insert_mode(); 
 | |
|       return;
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   set_mode(MODE_INS);
 | |
| 
 | |
|   get_relation()->zero();          // Azzera tutta la relazione!
 | |
|   init_insert_mode(*_mask);
 | |
| }
 | |
| 
 | |
| bool TRelation_application::modify_mode()
 | |
| {
 | |
|   int err = get_relation()->read(_isequal, _testandlock);
 | |
|   if (err != NOERR)
 | |
|   {
 | |
|     if (err == _islocked)
 | |
|       message_box("I dati sono gia' in uso ad un altro programma");
 | |
|     else
 | |
|       error_box("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();                
 | |
|   
 | |
|   set_mode(MODE_MOD);
 | |
|                                   
 | |
|   err = read(*_mask);
 | |
|   if (err != NOERR)
 | |
|   {
 | |
|     query_mode();
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   get_relation()->save_status();
 | |
|   init_modify_mode(*_mask);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| TEdit_field& TRelation_application::get_search_field() const
 | |
| {                      
 | |
|   short id = _search_id;
 | |
|                         
 | |
|   if (id <= 0)
 | |
|   {                      
 | |
|     const int max = _mask->fields();
 | |
|     for (int i = 0; i < max; i++)
 | |
|     {
 | |
|       const TMask_field& f = _mask->fld(i);
 | |
|       if (f.in_key(1) && f.required()) 
 | |
|       {
 | |
|         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();
 | |
|     }        
 | |
|     
 | |
|     TMask_field* dopo = &_mask->focus_field();
 | |
|     prima = (dopo == prima || !dopo->is_edit()) ? NULL : (TEdit_field*)dopo;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| // @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(
 | |
|      byte 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())
 | |
|     {
 | |
|       onereq = TRUE;
 | |
|       if (e->empty())         
 | |
|       {
 | |
|         if (err)
 | |
|         {
 | |
|           error_box("Manca un valore indispensabile per la ricerca");
 | |
|           _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("Manca un valore indispensabile per la ricerca");
 | |
|     return FALSE;
 | |
|   }
 | |
|   return onefill || onereq;
 | |
| }
 | |
| 
 | |
| bool TRelation_application::find(byte 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRelation_application::save(bool check_dirty)
 | |
| {
 | |
|   static bool was_dirty = FALSE;
 | |
|   
 | |
|   int err = NOERR;
 | |
|   const int mode = _mask->mode();
 | |
| 
 | |
|   if (check_dirty)
 | |
|   {
 | |
|     const int dirty = _mask->dirty();
 | |
| 
 | |
|     const char* ms = (mode == MODE_MOD) ? "le modifiche" : "i dati inseriti";
 | |
|     
 | |
|     if (mode == MODE_QUERY)
 | |
|     {
 | |
|       const bool cont = !dirty || yesno_box("Annullare %s?", ms);
 | |
|       return cont;
 | |
|     }
 | |
| 
 | |
|     if (!dirty && !was_dirty) 
 | |
|     {  
 | |
|       if (mode == MODE_MOD)
 | |
|       {
 | |
|         get_relation()->restore_status();
 | |
|         get_relation()->lfile().reread(_unlock);           // Unlock main file
 | |
|       }
 | |
|       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() > TRUE;
 | |
|     
 | |
|     KEY k; 
 | |
|     if (errore)
 | |
|     {
 | |
|       if (annulla) 
 | |
|       { 
 | |
|         TString w(80);
 | |
|         if (_mask->field(dirty).is_edit())
 | |
|           w = _mask->efield(dirty).get_warning();
 | |
|         if (w.empty()) 
 | |
|           w = "Campo inconsistente";
 | |
|         w << ": si desidera ";
 | |
|         switch (last)
 | |
|         {
 | |
|         case K_ESC:                   
 | |
|           w << "annullare?"; break;
 | |
|         case K_QUIT:
 | |
|           w << "uscire?"; break;  
 | |
|         default:
 | |
|           w << "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("Registrare %s?", ms); 
 | |
|     
 | |
|     if (k == K_ESC || k == K_NO)
 | |
|     {                   
 | |
|       if (mode == MODE_MOD)
 | |
|       {
 | |
|         get_relation()->restore_status();
 | |
|         get_relation()->lfile().reread(_unlock);     // Unlock main file
 | |
|       }  
 | |
|       was_dirty = FALSE;
 | |
|       return k == K_NO;
 | |
|     }        
 | |
| 
 | |
|     if (annulla)
 | |
|     {
 | |
|       if (!_mask->check_fields())                   // Exit with ESC didn't check values
 | |
|       {                       
 | |
|         _mask->first_focus(-_mask->focus_field().dlg());
 | |
|         was_dirty = TRUE; 
 | |
|         return FALSE;
 | |
|       } 
 | |
|     }   
 | |
|   }
 | |
|   was_dirty = FALSE;
 | |
|   
 | |
|   begin_wait();
 | |
|   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);
 | |
|   }
 | |
|   end_wait();
 | |
|   
 | |
|   switch(err)
 | |
|   {
 | |
|   case NOERR:
 | |
|     _recins = get_relation()->lfile().recno();
 | |
|     break;
 | |
|   case _isreinsert:
 | |
|     warning_box("Esiste gia' un documento con la stessa chiave");
 | |
|     break;
 | |
|   default:
 | |
|     error_box("Impossibile registrare i dati: errore %d", err);
 | |
|     break;
 | |
|   }
 | |
|   return err == NOERR;
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRelation_application::read(TMask& m)
 | |
| {
 | |
|   const TRelation &r = *get_relation();
 | |
|   m.autoload(r);
 | |
|   return NOERR;
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRelation_application::write(const TMask& m)
 | |
| {
 | |
|   TRelation &r = *get_relation();
 | |
|   m.autosave(r);
 | |
|   r.write();    
 | |
|   return r.status();
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRelation_application::rewrite(const TMask& m)
 | |
| {
 | |
|   TRelation& r = *get_relation();
 | |
|   m.autosave(r);
 | |
|   r.rewrite();
 | |
|   return r.status();
 | |
| }
 | |
| 
 | |
| // @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->mode() == MODE_MOD, "You can call remove in MODE_MOD only");
 | |
|   TRelation *r = get_relation();
 | |
| 
 | |
|   r->restore_status();
 | |
| 
 | |
|   if (protected_record(r->curr()))
 | |
|     return message_box("Registrazione non eliminabile");
 | |
| 
 | |
|   if (yesno_box("Confermare l'eliminazione"))
 | |
|   {
 | |
|     r->restore_status();
 | |
|     const bool ok = remove();
 | |
|     if (ok)
 | |
|       set_limits();
 | |
|     else
 | |
|       return error_box("Errore di cancellazione %d", r->status());
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRelation_application::remove()
 | |
| {
 | |
|   const int err = get_relation()->remove();
 | |
|   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;
 | |
| }
 | |
| 
 | |
| bool TRelation_application::main_loop()
 | |
| { 
 | |
|   _recins = -1;
 | |
|   
 | |
|   query_mode();
 | |
|   _mask->open_modal();
 | |
| 
 | |
|   KEY k;
 | |
|   
 | |
|   // Provoca l'autopremimento per il messaggio di LINK
 | |
|   if (_lnflag) _mask->send_key(K_AUTO_ENTER, 0);
 | |
|   
 | |
|   do
 | |
|   {
 | |
|     const bool change = firm_change_enabled();
 | |
|     // Dis/abilita cambio ditta
 | |
|     enable_menu_item(M_FILE_NEW, change);
 | |
|     // Dis/abilita cambio parametri
 | |
|     enable_menu_item(M_FILE_REVERT, change);
 | |
| 
 | |
|     k = _mask->run();
 | |
| 
 | |
|     switch (k)
 | |
|     {
 | |
|     case K_ESC:
 | |
|       if (save(TRUE))
 | |
|         query_mode();
 | |
|       if (_lnflag) 
 | |
|         k = K_QUIT;
 | |
|       break;                             
 | |
|     case K_QUIT:      
 | |
|       if (!save(TRUE))
 | |
|         k = K_ENTER;
 | |
|       break;
 | |
|     case K_ENTER:
 | |
|       if (find(0)) modify_mode();
 | |
|       else insert_mode();
 | |
|       break;
 | |
|     case K_SAVE:
 | |
|       if (save(FALSE))
 | |
|       {
 | |
|         if (_autoins_caller.not_empty())
 | |
|         {
 | |
|           k = K_QUIT;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           if (save_and_new())
 | |
|           {
 | |
|             if (_mask->insert_mode())
 | |
|               insert_mode();
 | |
|             else
 | |
|               query_mode();
 | |
|           }  
 | |
|           else  
 | |
|             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)
 | |
|         { 
 | |
|           modify_mode();
 | |
|           warning_box("Documento gia' presente");
 | |
|         }
 | |
|         else
 | |
|           insert_mode();
 | |
|       }  
 | |
|       break;
 | |
|     case K_DEL:
 | |
|       if (relation_remove())
 | |
|         query_mode();
 | |
|       if (_autoins_caller.not_empty())
 | |
|       {    
 | |
|         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();
 | |
|           err = file().next(_testandlock);
 | |
|           break;
 | |
|         case K_PREV:
 | |
|           err = file().reread();
 | |
|           err = file().prev(_testandlock);
 | |
|           break;
 | |
|         case K_END:
 | |
|           err = file().readat(_last, _testandlock);
 | |
|           break;
 | |
|         default:
 | |
|           break;
 | |
|         }
 | |
|         if (err == NOERR || err == _islocked) modify_mode();
 | |
|         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)
 | |
|   {                                
 | |
|     TMessage msg(autoins_caller(), _lnflag ? MSG_LN : MSG_AI, format("%ld", _recins));
 | |
|     msg.send();
 | |
|   }
 | |
| 
 | |
|   return k != K_QUIT;
 | |
| }
 | |
| 
 | |
| bool TRelation_application::filter()
 | |
| {
 | |
|   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 = (TEdit_field&)_mask->field(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);
 | |
|       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;
 | |
|     
 | |
|     const char* v = body.get();
 | |
|     TString80 s;
 | |
|     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))
 | |
|       {        
 | |
|         s = v;                
 | |
|         _fixed.add(format("%d=%s", f.dlg(), (const char*)s));
 | |
|         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;
 | |
|     TString80 t;
 | |
|     
 | |
|     while((s = body.get()) != NULL)
 | |
|     {  
 | |
|       t = s;
 | |
|       const int u = t.find('=');
 | |
|       
 | |
|       CHECKS(u > 0, "Invalid edit message ", (const char *) body);
 | |
|       if (u > 0)
 | |
|       {                       
 | |
|         const TString 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)
 | |
|           _fixed.add(format("%d=%s", f.dlg(), (const char*)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();
 | |
|   
 | |
|   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))
 | |
|     {                          
 | |
|       const TString s(v);                        
 | |
|       _fixed.add(format("%d=%s", f.dlg(), (const char*) s));
 | |
|       v = body.get();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 |