973 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			973 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//      $Id: relapp.cpp,v 1.70 1995-11-07 11:38:23 villa Exp $        
 | 
						|
#include <mailbox.h>
 | 
						|
#include <sheet.h>
 | 
						|
#include <urldefid.h>
 | 
						|
#include <relapp.h>
 | 
						|
#include <utility.h>
 | 
						|
#include <xvtility.h>
 | 
						|
 | 
						|
#if XVT_OS == XVT_OS_WIN
 | 
						|
#include <windows.h>
 | 
						|
#endif
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Array delle chiavi della maschera di ricerca
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TChiave : public TObject
 | 
						|
{
 | 
						|
  enum { MAX = 16 };
 | 
						|
  int _pos[MAX];
 | 
						|
  byte _num;
 | 
						|
 | 
						|
public:
 | 
						|
  void add(int p);
 | 
						|
  int pos(byte n) const { return (n >= _num) ? -1 : _pos[n]; }
 | 
						|
  byte items() const { return _num; }
 | 
						|
  TChiave() : _num(0) {}
 | 
						|
  virtual ~TChiave() {}
 | 
						|
};
 | 
						|
 | 
						|
void TChiave::add(int p)
 | 
						|
{
 | 
						|
  CHECKD(_num < MAX, "Too many fields in key : field n.", p);
 | 
						|
  _pos[_num++] = p;
 | 
						|
}
 | 
						|
 | 
						|
class TKey_array : public TArray
 | 
						|
{
 | 
						|
  const TMask* _mask;
 | 
						|
 | 
						|
public:
 | 
						|
  TKey_array(const TMask* m);
 | 
						|
  virtual ~TKey_array() {}
 | 
						|
 | 
						|
  TChiave& key(byte k);
 | 
						|
};
 | 
						|
 | 
						|
TChiave& TKey_array::key(byte k)
 | 
						|
{
 | 
						|
  k--;
 | 
						|
  TChiave* chiave = (TChiave*)objptr(k);
 | 
						|
  if (chiave == NULL)
 | 
						|
  {
 | 
						|
    chiave = new TChiave;
 | 
						|
    add(chiave, k);
 | 
						|
  }
 | 
						|
  return *chiave;
 | 
						|
}
 | 
						|
 | 
						|
TKey_array::TKey_array(const TMask* m) : _mask(m)
 | 
						|
{
 | 
						|
  const byte keys = m->num_keys();
 | 
						|
  for (int f = 0; f < m->fields(); f++)
 | 
						|
  {
 | 
						|
    TMask_field& c = m->fld(f);
 | 
						|
    if (c.in_key(0))
 | 
						|
      for (byte k = 1; k <= keys; k++)
 | 
						|
        if (c.in_key(k))
 | 
						|
          key(k).add(f);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TRelation_application
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TRelation_application::TRelation_application()
 | 
						|
: _mask(NULL), _maskeys(NULL), _search_id(-1), _lnflag(FALSE)
 | 
						|
{}
 | 
						|
 | 
						|
TRelation_application::~TRelation_application()
 | 
						|
{
 | 
						|
  if (_maskeys) delete _maskeys;
 | 
						|
}
 | 
						|
 | 
						|
void TRelation_application::setkey()
 | 
						|
{
 | 
						|
  if (has_filtered_cursor())
 | 
						|
  {
 | 
						|
    TEdit_field* f = (TEdit_field*) get_search_field();
 | 
						|
    TCursor* cur = f->browse()->cursor();
 | 
						|
    cur->setkey();
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  file().setkey(1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// what - meaning
 | 
						|
//  0   - nop
 | 
						|
//  1   - first
 | 
						|
//  2   - last
 | 
						|
//  3   - both
 | 
						|
void TRelation_application::set_limits(byte what)
 | 
						|
{
 | 
						|
  if (has_filtered_cursor())
 | 
						|
  {
 | 
						|
    TEdit_field* f = (TEdit_field*)get_search_field();
 | 
						|
    CHECK(f, "Manca il campo di ricerca");
 | 
						|
    
 | 
						|
    TBrowse* b = f->browse();
 | 
						|
    TCursor* cur = b ? 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();
 | 
						|
    _maskeys = new TKey_array(_mask);
 | 
						|
    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()
 | 
						|
{   
 | 
						|
  if (_maskeys) delete _maskeys;
 | 
						|
  user_destroy();
 | 
						|
  return TApplication::destroy();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TRelation_application::set_fixed()
 | 
						|
{
 | 
						|
  TString256 s;
 | 
						|
  for (const char* f = _fixed.get(0); f && *f; f = _fixed.get())
 | 
						|
  {
 | 
						|
    s = f;
 | 
						|
    const int u = s.find('=');
 | 
						|
    const int id = atoi(s.left(u));
 | 
						|
    const char* val = s.mid(u+1);
 | 
						|
    if (*val)
 | 
						|
      _mask->set(id, val);
 | 
						|
    _mask->disable(id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TRelation_application::enable_query()
 | 
						|
{
 | 
						|
  const bool query = _mask->query_mode(); 
 | 
						|
  const bool keyon = query || get_relation()->status() == _isreinsert;
 | 
						|
 | 
						|
  for (byte k = 1; k <= _maskeys->items(); k++)
 | 
						|
  {
 | 
						|
    const TChiave& chiave = _maskeys->key(k);
 | 
						|
    for (int i = 0; i < chiave.items(); i++)
 | 
						|
    {
 | 
						|
      const int num = chiave.pos(i);
 | 
						|
      TMask_field& c = _mask->fld(num);
 | 
						|
      if (c.enabled_default())
 | 
						|
      {
 | 
						|
        if (k == 1)
 | 
						|
          c.enable(keyon);
 | 
						|
        if (c.has_query())
 | 
						|
          ((TEdit_field&)c).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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TRelation_application::autonum(TMask* m, bool rec)
 | 
						|
{
 | 
						|
  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.get().empty()) f.set(val);
 | 
						|
    if (rec) 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();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TRelation_application::query_mode(bool pre_ins)
 | 
						|
{
 | 
						|
  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();
 | 
						|
    if (_maskeys) delete _maskeys;
 | 
						|
    _maskeys = new TKey_array(_mask);
 | 
						|
    set_limits();
 | 
						|
  }
 | 
						|
 | 
						|
  _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();
 | 
						|
      delete _maskeys;
 | 
						|
      _maskeys = new TKey_array(_mask);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  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();                
 | 
						|
    delete _maskeys;                
 | 
						|
    _maskeys = new TKey_array(_mask);
 | 
						|
  }
 | 
						|
  
 | 
						|
  set_mode(MODE_MOD);
 | 
						|
 | 
						|
  err = read(*_mask);
 | 
						|
  if (err != NOERR)
 | 
						|
  {
 | 
						|
    query_mode();
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  get_relation()->save_status();
 | 
						|
  init_modify_mode(*_mask);
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TMask_field* TRelation_application::get_search_field() const
 | 
						|
{
 | 
						|
  if (_search_id > 0) 
 | 
						|
    return &_mask->field(_search_id);
 | 
						|
  
 | 
						|
  const TChiave& k = _maskeys->key(1);
 | 
						|
  for (int i = 0; i < k.items(); i++)
 | 
						|
  {
 | 
						|
    TMask_field* f = &_mask->fld(k.pos(i));
 | 
						|
    if (f->required()) return f;
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TRelation_application::search_mode()
 | 
						|
{
 | 
						|
  if (_mask->mode() != MODE_QUERY)
 | 
						|
    query_mode();
 | 
						|
 | 
						|
  TMask_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) ? NULL : dopo;
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TRelation_application::test_key(byte k, bool err)
 | 
						|
{
 | 
						|
  const TChiave& chiave = _maskeys->key(k);
 | 
						|
  bool onereq = FALSE, onefill = FALSE;
 | 
						|
 | 
						|
  for (int i = 0; i < chiave.items(); i++)
 | 
						|
  {
 | 
						|
    const int num = chiave.pos(i);
 | 
						|
    TMask_field& c = _mask->fld(num);
 | 
						|
    
 | 
						|
    if (c.required())
 | 
						|
    {
 | 
						|
      onereq = TRUE;
 | 
						|
      if (c.get().empty())
 | 
						|
      {
 | 
						|
        if (err)
 | 
						|
        {
 | 
						|
          _mask->first_focus(-c.dlg());
 | 
						|
          error_box("Manca un valore indispensabile per la ricerca");
 | 
						|
        }
 | 
						|
        return FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      /*      if (k == 1 && !onereq && !onefill && c.get().not_empty()) */
 | 
						|
      if (!onereq && !onefill && c.is_edit() && c.get().not_empty()) 
 | 
						|
        onefill = TRUE;
 | 
						|
  }
 | 
						|
  if (k == 1 && !onereq && !onefill)
 | 
						|
  {
 | 
						|
    if (err)
 | 
						|
      error_box("Manca un valore indispensabile per la ricerca");
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  return onefill || onereq;
 | 
						|
}
 | 
						|
 | 
						|
// Guy: doesn't change fields
 | 
						|
bool TRelation_application::find(byte k)
 | 
						|
{                         
 | 
						|
  if (changing_keys()) 
 | 
						|
  {
 | 
						|
    delete _maskeys;
 | 
						|
    _maskeys= new TKey_array(_mask);
 | 
						|
  }
 | 
						|
  
 | 
						|
  const byte numkeys = _maskeys->items();
 | 
						|
 | 
						|
  if (k == 0)
 | 
						|
  {
 | 
						|
    for (k = 1; k <= numkeys && !test_key(k, FALSE); k++);
 | 
						|
    if (k > numkeys)
 | 
						|
      return test_key(1, TRUE);
 | 
						|
  }
 | 
						|
 | 
						|
  file().setkey(k);
 | 
						|
  file().zero();
 | 
						|
  const TChiave& chiave = _maskeys->key(k);
 | 
						|
  for (int i = 0; i < chiave.items(); i++)
 | 
						|
  {
 | 
						|
    const TMask_field& c = _mask->fld(chiave.pos(i));
 | 
						|
    if (c.shown())                        // Ignora campi invisibili
 | 
						|
      c.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) 
 | 
						|
      { 
 | 
						|
        TString80 w(_mask->field(dirty).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();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TRelation_application::relation_remove()
 | 
						|
{
 | 
						|
  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();
 | 
						|
  if (ok) ok = _mask == NULL || _mask->query_mode();
 | 
						|
  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))
 | 
						|
        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 (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();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  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();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 |