diff --git a/include/relapp.cpp b/include/relapp.cpp index 112ff1668..6a9d34303 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -1,866 +1,868 @@ -// $Id: relapp.cpp,v 1.1.1.1 1994-08-12 10:52:05 alex Exp $ -#include -#include -#include -#include -#include -#include - -#if XVT_OS == XVT_OS_WIN -extern "C" { -#include -} -#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"); - TCursor* cur = f->browse()->cursor(); - 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() -{ - user_destroy(); - return TApplication::destroy(); -} - - -void TRelation_application::set_fixed() -{ - TString s(16); - 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)); - _mask->disable(id); - const char* val = s.mid(u+1); - if (*val) - _mask->set(id, val); - } -} - - -void TRelation_application::enable_query() -{ - const bool query = _mask->mode() == MODE_QUERY; - const byte numkeys = _maskeys->items(); - - for (byte k = 1; k <= numkeys; 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); - const bool has_query = c.has_query(); - if (k == 1) - { -// THIS should have been fixed -// if (!query && has_query) c.check(STARTING_CHECK); - c.enable(query); - } - if (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); - } -/* - const bool full = !file().empty() && _first != -1; - pos = _mask->id2pos(DLG_FIRSTREC); - if (pos >= 0) _mask->fld(pos).enable(full); - pos = _mask->id2pos(DLG_LASTREC); - if (pos >= 0) _mask->fld(pos).enable(full); - pos = _mask->id2pos(DLG_STOPREC); - if (pos >= 0) _mask->fld(pos).enable(full); -*/ - } - - enable_query(); - -/* - const TRecnotype rpos = file().recno(); - pos = _mask->id2pos(DLG_PREVREC); - if (pos >= 0) _mask->fld(pos).enable(mod && rpos != _first); - pos = _mask->id2pos(DLG_NEXTREC); - if (pos >= 0) _mask->fld(pos).enable(mod && rpos != _last); -*/ -} - - -int TRelation_application::set_mode(int mode) -{ - static int _mode = NO_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); - - return _mode; -} - - -bool TRelation_application::autonum(TMask* m, bool rec) -{ - TToken_string k(get_next_key()); - - for (const char* n = k.get(0); n && *n; n = k.get()) - { - const short id = atoi(n); - if (id < 1) break; - 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()); - } - return k.not_empty(); -} - - -void TRelation_application::query_mode(bool pre_ins) -{ - TMask* old = _mask; - const bool changing = changing_mask(MODE_QUERY) || old == NULL; - - if (changing && old) - old->close_modal(); - - _mask = get_mask(MODE_QUERY); - if (changing) - { - if (old) _mask->open_modal(); - if (_maskeys) delete _maskeys; - _maskeys = new TKey_array(_mask); - set_limits(); - } - - _mask->reset(); - - if (pre_ins) - { - set_mode(NO_MODE); - autonum(_mask, FALSE); - init_query_insert_mode(*_mask); - } - else - { - set_mode(MODE_QUERY); - init_query_mode(*_mask); - } -} - - -void TRelation_application::insert_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("rim.$$"); - - 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); - } - - set_mode(MODE_INS); - 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 utente"); - 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); - set_mode(MODE_MOD); - - err = read(*_mask); - - if (changing) - _mask->open_modal(); - - if (err != NOERR) - { - error_box("Errore di caricamento dati nella maschera %d", err); - 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* f = get_search_field(); - if (f) - if (f->on_key(K_F9)) - if (find(1)) - return modify_mode(); - - 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"); - } - return FALSE; - } - } - else - if (k == 1 && !onereq && !onefill && c.get().not_empty()) - onefill = TRUE; - } - if (k == 1 && !onereq && !onefill) - { - if (err) - error_box("Manca un valore indispensabile"); - return FALSE; - } - return TRUE; -} - -// Guy: doesn't change fields -bool TRelation_application::find(byte k) -{ - 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)); - 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(); - if (mode == MODE_QUERY) - { - const bool cont = !dirty || yesno_box("Annullare i dati inseriti?"); - 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 k = yesnocancel_box("Registrare le modifiche?"); - if (k == K_ESC) - { - was_dirty = TRUE; - return FALSE; - } - if (k == K_NO) - { - get_relation()->restore_status(); - get_relation()->lfile()->reread(_unlock); // Unlock main file - was_dirty = FALSE; - return TRUE; - } - if (_mask->last_key() == K_ESC || _mask->last_key() == K_QUIT) - { - _mask->get_mask_fields(); - if (!_mask->check_fields()) // Exit with ESC didn't check values - { - _mask->first_focus(-_mask->fld(_mask->focus_field()).dlg()); - was_dirty = TRUE; - return FALSE; - } - } - } - was_dirty = FALSE; - - if (mode == MODE_INS) - { - bool changed = TRUE; - while (changed) - { - err = write(*_mask); - if (err == _isreinsert) - changed = autonum(_mask, TRUE); - else - changed = FALSE; - } - if (err == NOERR) - { - get_relation()->save_status(); - set_limits(); - get_relation()->restore_status(); - } - } - else - err = rewrite(*_mask); - - switch(err) - { - case NOERR: - 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(); - r->zero(); - m.autosave(r); - r->write(); - return r->status(); -} - - -int TRelation_application::rewrite(const TMask& m) -{ - TRelation *r = get_relation(); - r->zero(); - m.autosave(r); - r->rewrite(); - return r->status(); -} - - -bool TRelation_application::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 int err = r->remove(); - if (err == NOERR) - set_limits(); - else - return error_box("Errore di cancellazione"); - } - return TRUE; -} - - -bool TRelation_application::main_loop() -{ - long recins = -1; - - query_mode(); - _mask->open_modal(); - - KEY k; - - // Provoca l'autopremimento per il messaggio di LINK - if (_lnflag) _mask->send_key(K_SHIFT_ENTER, 0); - - do - { - // Seleziona il cursore a freccia - set_cursor(TASK_WIN, CURSOR_ARROW); - - // Dis/abilita cambio ditta - enable_menu_item(M_FILE_NEW, (_mask->mode() == MODE_QUERY)); - - - k = _mask->run(); - - // Seleziona il cursore a clessidra se necessario - if (k != K_QUIT && k != K_F9) set_cursor(TASK_WIN, CURSOR_WAIT); - - switch (k) - { - case K_ESC: - if (save(TRUE)) - { - if (_mask->query_mode()) - { - _mask->reset(); - set_fixed(); - } - else query_mode(); - } - if (_lnflag) k = K_QUIT; - break; - case K_QUIT: - if (save(TRUE)) - { - if (_mask->mode() == MODE_MOD && _autoins_caller.not_empty()) - recins = file().recno(); - } - else 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() || _lnflag) - { - recins = file().recno(); - k = K_QUIT; - } - else - modify_mode(); - } - break; - case K_INS: - if (_mask->mode() == MODE_QUERY) - insert_mode(); - else - if (save(TRUE)) - query_mode(TRUE); - break; - case K_DEL: - { - if (remove()) - query_mode(); - } - 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 (recins > 0 && _autoins_caller.not_empty()) - { - TMessage msg(_autoins_caller, 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->filter("", &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(); - const int max = _mask->fields(); - -// _autoins_caller = msg->from(); - _lnflag = TRUE; - - const char* v = body.get(); - - for (int i = 0; i < max && v != NULL; i++) - { - TMask_field& f = _mask->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(); - } - } - } - - return TRUE; -} +// $Id: relapp.cpp,v 1.2 1994-08-17 14:08:21 guy Exp $ +#include +#include +#include +#include +#include +#include + +#if XVT_OS == XVT_OS_WIN +extern "C" { +#include +} +#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"); + TCursor* cur = f->browse()->cursor(); + 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() +{ + user_destroy(); + return TApplication::destroy(); +} + + +void TRelation_application::set_fixed() +{ + TString s(16); + 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)); + _mask->disable(id); + const char* val = s.mid(u+1); + if (*val) + _mask->set(id, val); + } +} + + +void TRelation_application::enable_query() +{ + const bool query = _mask->mode() == MODE_QUERY; + const byte numkeys = _maskeys->items(); + + for (byte k = 1; k <= numkeys; 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); + const bool has_query = c.has_query(); + if (k == 1) + { + // THIS should have been fixed + // if (!query && has_query) c.check(STARTING_CHECK); + c.enable(query); + } + if (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); + } + /* + const bool full = !file().empty() && _first != -1; + pos = _mask->id2pos(DLG_FIRSTREC); + if (pos >= 0) _mask->fld(pos).enable(full); + pos = _mask->id2pos(DLG_LASTREC); + if (pos >= 0) _mask->fld(pos).enable(full); + pos = _mask->id2pos(DLG_STOPREC); + if (pos >= 0) _mask->fld(pos).enable(full); + */ + } + + enable_query(); + + /* + const TRecnotype rpos = file().recno(); + pos = _mask->id2pos(DLG_PREVREC); + if (pos >= 0) _mask->fld(pos).enable(mod && rpos != _first); + pos = _mask->id2pos(DLG_NEXTREC); + if (pos >= 0) _mask->fld(pos).enable(mod && rpos != _last); + */ +} + + +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); + + return _mode; +} + + +bool TRelation_application::autonum(TMask* m, bool rec) +{ + TToken_string k(get_next_key()); + + for (const char* n = k.get(0); n && *n; n = k.get()) + { + const short id = atoi(n); + if (id < 1) break; + 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()); + } + return k.not_empty(); +} + + +void TRelation_application::query_mode(bool pre_ins) +{ + TMask* old = _mask; + const bool changing = changing_mask(MODE_QUERY) || old == NULL; + + if (changing && old) + old->close_modal(); + + _mask = get_mask(MODE_QUERY); + if (changing) + { + if (old) _mask->open_modal(); + if (_maskeys) delete _maskeys; + _maskeys = new TKey_array(_mask); + set_limits(); + } + + _mask->reset(); + + if (pre_ins) + { + set_mode(NO_MODE); + autonum(_mask, FALSE); + init_query_insert_mode(*_mask); + } + else + { + set_mode(MODE_QUERY); + init_query_mode(*_mask); + } +} + + +void TRelation_application::insert_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("rim.$$"); + + 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); + } + + set_mode(MODE_INS); + 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 utente"); + 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); + set_mode(MODE_MOD); + + err = read(*_mask); + + if (changing) + _mask->open_modal(); + + if (err != NOERR) + { + error_box("Errore di caricamento dati nella maschera %d", err); + 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* f = get_search_field(); + if (f) + if (f->on_key(K_F9)) + if (find(1)) + return modify_mode(); + + 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"); + } + return FALSE; + } + } + else + if (k == 1 && !onereq && !onefill && c.get().not_empty()) + onefill = TRUE; + } + if (k == 1 && !onereq && !onefill) + { + if (err) + error_box("Manca un valore indispensabile"); + return FALSE; + } + return TRUE; +} + +// Guy: doesn't change fields +bool TRelation_application::find(byte k) +{ + 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)); + 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(); + if (mode == MODE_QUERY) + { + const bool cont = !dirty || yesno_box("Annullare i dati inseriti?"); + 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 k = yesnocancel_box(mode == MODE_MOD ? "Registrare le modifiche?" + : "Registrare i dati inseriti?"); + if (k == K_ESC) + { + was_dirty = TRUE; + return FALSE; + } + if (k == K_NO) + { + get_relation()->restore_status(); + get_relation()->lfile()->reread(_unlock); // Unlock main file + was_dirty = FALSE; + return TRUE; + } + if (_mask->last_key() == K_ESC || _mask->last_key() == K_QUIT) + { + _mask->get_mask_fields(); + if (!_mask->check_fields()) // Exit with ESC didn't check values + { + _mask->first_focus(-_mask->fld(_mask->focus_field()).dlg()); + was_dirty = TRUE; + return FALSE; + } + } + } + was_dirty = FALSE; + + if (mode == MODE_INS) + { + bool changed = TRUE; + while (changed) + { + err = write(*_mask); + if (err == _isreinsert) + changed = autonum(_mask, TRUE); + else + changed = FALSE; + } + if (err == NOERR) + { + get_relation()->save_status(); + set_limits(); + get_relation()->restore_status(); + } + } + else + err = rewrite(*_mask); + + switch(err) + { + case NOERR: + 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(); + r->zero(); + m.autosave(r); + r->write(); + return r->status(); +} + + +int TRelation_application::rewrite(const TMask& m) +{ + TRelation *r = get_relation(); + r->zero(); + m.autosave(r); + r->rewrite(); + return r->status(); +} + + +bool TRelation_application::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 int err = r->remove(); + if (err == NOERR) + set_limits(); + else + return error_box("Errore di cancellazione"); + } + return TRUE; +} + + +bool TRelation_application::main_loop() +{ + long recins = -1; + + query_mode(); + _mask->open_modal(); + + KEY k; + + // Provoca l'autopremimento per il messaggio di LINK + if (_lnflag) _mask->send_key(K_SHIFT_ENTER, 0); + + do + { + // Seleziona il cursore a freccia + set_cursor(TASK_WIN, CURSOR_ARROW); + + // Dis/abilita cambio ditta + enable_menu_item(M_FILE_NEW, (_mask->mode() == MODE_QUERY)); + + + k = _mask->run(); + + // Seleziona il cursore a clessidra se necessario + if (k != K_QUIT && k != K_F9) set_cursor(TASK_WIN, CURSOR_WAIT); + + switch (k) + { + case K_ESC: + if (save(TRUE)) + { + if (_mask->query_mode()) + { + _mask->reset(); + set_fixed(); + } + else query_mode(); + } + if (_lnflag) k = K_QUIT; + break; + case K_QUIT: + if (save(TRUE)) + { + if (_mask->mode() == MODE_MOD && _autoins_caller.not_empty()) + recins = file().recno(); + } + else 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() || _lnflag) + { + recins = file().recno(); + k = K_QUIT; + } + else + modify_mode(); + } + break; + case K_INS: + if (_mask->mode() == MODE_QUERY) + insert_mode(); + else + if (save(TRUE)) + query_mode(TRUE); + break; + case K_DEL: + { + if (remove()) + query_mode(); + } + 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 (recins > 0 && _autoins_caller.not_empty()) + { + TMessage msg(_autoins_caller, 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->filter("", &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(); + const int max = _mask->fields(); + + // _autoins_caller = msg->from(); + _lnflag = TRUE; + + const char* v = body.get(); + + for (int i = 0; i < max && v != NULL; i++) + { + TMask_field& f = _mask->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(); + } + } + } + + return TRUE; +}