Files correlati : Ricompilazione Demo : [ ] Commento : colors.* Aggiunta funzione per calcolo distanza tra colori per gestione trasparenze in menu principale dongle.cpp Corretta gestione chiave Eutron normale (non SV) image.cpp Migliorata gestion etrasparenze progind.cpp Corretta gestione messaggi su piu' righe relapp.cpp Corretta traduzione messaggi di richiesta salvataggio validate.cpp Sostituita TFixed_string errata con la corretta const TString& git-svn-id: svn://10.65.10.50/trunk@11123 c028cbd2-c16b-5b4b-a496-9718f37d4682
1881 lines
46 KiB
C++
Executable File
1881 lines
46 KiB
C++
Executable File
#include <defmask.h>
|
||
#include <mailbox.h>
|
||
#include <msksheet.h>
|
||
#include <postman.h>
|
||
#include <progind.h>
|
||
#include <sheet.h>
|
||
#include <recarray.h>
|
||
#include <relapp.h>
|
||
#include <urldefid.h>
|
||
#include <utility.h>
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TRelation_application
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TRelation_application::TRelation_application()
|
||
: _mask(NULL), _search_id(-1), _lnflag(FALSE),
|
||
_autodelete(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);
|
||
}
|
||
|
||
void TRelation_application::set_key_filter()
|
||
{
|
||
TString rf = get_user_read_filter(); rf.trim();
|
||
if (rf.not_empty())
|
||
{
|
||
TString expr;
|
||
for (int f = _mask->fields()-1; f >= 0; f--)
|
||
{
|
||
TMask_field& fld= _mask->fld(f);
|
||
if (fld.is_edit() && fld.in_key(0))
|
||
{
|
||
TBrowse* b = ((TEdit_field&)fld).browse();
|
||
if (b && b->cursor()->relation()->lfile().num() == get_relation()->lfile().num())
|
||
{
|
||
expr = b->get_filter();
|
||
if (expr.find(rf) < 0)
|
||
{
|
||
if (expr.not_empty())
|
||
{
|
||
expr.insert("(", 0);
|
||
expr << ")AND(" << rf << ')';
|
||
}
|
||
else
|
||
expr = rf;
|
||
b->set_filter(expr);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Setta i limiti
|
||
void TRelation_application::set_limits(
|
||
byte what) // @parm tipo di limite da assegnare al record
|
||
|
||
// @comm I limiti possibili sono:
|
||
// @flag 0 | Nessuna operazione
|
||
// @flag 1 | Primo record
|
||
// @flag 2 | Ultimo record
|
||
// @flag 3 | Entrambi
|
||
{
|
||
if (has_filtered_cursor())
|
||
{
|
||
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() && file().first() == NOERR)
|
||
_first = file().recno();
|
||
else
|
||
_first = -1;
|
||
}
|
||
if (what & 0x2)
|
||
{
|
||
if (!file().empty() && file().last() == NOERR)
|
||
_last = file().recno();
|
||
else
|
||
_last = -1;
|
||
}
|
||
}
|
||
|
||
void TRelation_application::set_find_button()
|
||
{
|
||
int pos = _mask->id2pos(DLG_FINDREC);
|
||
if (pos >= 0 && _mask->id2pos(DLG_FIRSTREC) >= 0) //se e' un bottone pentapartito...
|
||
{
|
||
TButton_field& f_find = (TButton_field &)_mask->fld(pos);
|
||
RCT rct_base; f_find.get_rect(rct_base);
|
||
const int bwidth = (rct_base.right - rct_base.left);
|
||
const int bheight = (rct_base.bottom - rct_base.top);
|
||
if (bwidth > 3*bheight/2) // Controllo se ho gia' ridimensionato i bottoni in precedenza
|
||
{
|
||
int bx = bwidth / 3;
|
||
int by = bheight / 2;
|
||
|
||
RCT r = rct_base; r.left += bx-2; r.right -= bx-2;
|
||
f_find.set_rect(r); // Ridimensiona il bottone centrale di ricerca
|
||
|
||
bx += 5; by += 3; // Aggiusta dimensioni bottoni sussidiari
|
||
|
||
pos = _mask->id2pos(DLG_FIRSTREC);
|
||
if (pos >= 0)
|
||
{
|
||
r = rct_base; r.top = r.bottom - by; r.right = r.left + bx;
|
||
_mask->fld(pos).set_rect(r);
|
||
}
|
||
pos = _mask->id2pos(DLG_PREVREC);
|
||
if (pos >= 0)
|
||
{
|
||
r = rct_base; r.bottom = r.top + by; r.right = r.left + bx;
|
||
_mask->fld(pos).set_rect(r);
|
||
}
|
||
pos = _mask->id2pos(DLG_NEXTREC);
|
||
if (pos >= 0)
|
||
{
|
||
r = rct_base; r.bottom = r.top + by; r.left = r.right - bx;
|
||
_mask->fld(pos).set_rect(r);
|
||
}
|
||
pos = _mask->id2pos(DLG_LASTREC);
|
||
if (pos >= 0)
|
||
{
|
||
r = rct_base; r.top = r.bottom - by; r.left = r.right - bx;
|
||
_mask->fld(pos).set_rect(r);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
bool TRelation_application::create()
|
||
{
|
||
bool ok = user_create();
|
||
if (ok)
|
||
{
|
||
write_enable();
|
||
_mask = get_mask(MODE_QUERY);
|
||
|
||
filter();
|
||
set_key_filter();
|
||
set_limits();
|
||
}
|
||
return TSkeleton_application::create();
|
||
}
|
||
|
||
|
||
bool TRelation_application::destroy()
|
||
{
|
||
user_destroy();
|
||
return TSkeleton_application::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)
|
||
{
|
||
if (all)
|
||
{
|
||
const int mode = _mask->mode();
|
||
const bool can_edit_some = user_can_write(NULL);
|
||
|
||
int pos = _mask->id2pos(DLG_SAVEREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabsave=mode != MODE_QUERY;
|
||
if (enabsave)
|
||
enabsave = user_can_write(get_relation());
|
||
_mask->fld(pos).enable(enabsave);
|
||
}
|
||
pos = _mask->id2pos(DLG_DELREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabdel = (mode == MODE_QUERY && can_edit_some) || (mode == MODE_MOD);
|
||
if (enabdel && mode == MODE_MOD)
|
||
{
|
||
TRelation& r = *get_relation();
|
||
const TRecnotype oldpos = r.lfile().recno();
|
||
enabdel = !protected_record(r);
|
||
if (r.lfile().recno() != oldpos)
|
||
r.lfile().readat(oldpos);
|
||
}
|
||
_mask->fld(pos).enable(enabdel);
|
||
}
|
||
|
||
pos = _mask->id2pos(DLG_FINDREC);
|
||
if (pos >= 0)
|
||
{
|
||
_mask->fld(pos).enable(_lnflag == 0);
|
||
|
||
pos = _mask->id2pos(DLG_FIRSTREC);
|
||
if (pos >= 0)
|
||
_mask->fld(pos).enable(_lnflag == 0 && _first > 0);
|
||
pos = _mask->id2pos(DLG_PREVREC);
|
||
const long recno = get_relation()->lfile().recno();
|
||
const bool enable_next_prev = _mask->edit_mode();
|
||
if (pos >= 0)
|
||
_mask->fld(pos).enable(_lnflag == 0 && enable_next_prev && _first > 0 && _first != recno);
|
||
pos = _mask->id2pos(DLG_NEXTREC);
|
||
if (pos >= 0)
|
||
_mask->fld(pos).enable(_lnflag == 0 && enable_next_prev && _last > 0 && _last != recno);
|
||
pos = _mask->id2pos(DLG_LASTREC);
|
||
if (pos >= 0)
|
||
_mask->fld(pos).enable(_lnflag == 0 && _last > 0);
|
||
}
|
||
|
||
pos = _mask->id2pos(DLG_NEWREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabins = (mode == MODE_QUERY || _lnflag == 0) && can_edit_some;
|
||
_mask->fld(pos).enable(enabins);
|
||
}
|
||
}
|
||
set_find_button();
|
||
enable_query();
|
||
}
|
||
|
||
|
||
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);
|
||
|
||
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;
|
||
if (!get_next_key(k))
|
||
{
|
||
k = get_next_key();
|
||
/*
|
||
if (k.not_empty())
|
||
NFCHECK("La 'const char* get_next_key()' verra' sostituita dalla 'bool get_next_key(TToken_string&)'");
|
||
*/
|
||
}
|
||
|
||
if (!rec && !m->query_mode())
|
||
m->reset();
|
||
_renum_message = "";
|
||
|
||
for (const char* n = k.get(0); n && *n; n = k.get())
|
||
{
|
||
const short id = atoi(n);
|
||
CHECKD (id > 0 && m->id2pos(id) >= 0, "Identificatore di autonumerazione errato: ", id);
|
||
const char* val = k.get();
|
||
TMask_field& f = m->field(id);
|
||
if (rec || f.empty())
|
||
f.set(val);
|
||
if (rec)
|
||
((TEditable_field&)f).autosave(*get_relation());
|
||
if (_renum_message.empty() || f.in_key(1))
|
||
_renum_message.format("L'elemento e' stato registrato con :\n %s = %s", (const char *) f.prompt(), (const char *) f.get());
|
||
}
|
||
return k.not_empty();
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Entra in modo di ricerca
|
||
void TRelation_application::query_mode(
|
||
bool pre_ins) // @parm Indica in quale modo andare:
|
||
//
|
||
// @flag TRUE | Entra in modo MODE_QUERY_INSERT
|
||
// @flag FALSE | Entra in modo MODE_QUERY (default)
|
||
{
|
||
TMask* old = _mask;
|
||
const bool was_open = old != NULL && old->is_open();
|
||
const bool changing = changing_mask(MODE_QUERY);
|
||
|
||
if (changing && was_open)
|
||
old->close_modal();
|
||
|
||
_mask = get_mask(MODE_QUERY);
|
||
if (changing)
|
||
{
|
||
if (was_open)
|
||
_mask->open_modal();
|
||
set_limits();
|
||
}
|
||
|
||
_mask->set_mode(pre_ins ? MODE_QUERYINS : MODE_QUERY);
|
||
_mask->reset();
|
||
_mask->disable_page(1); // Nasconde pagine inutili
|
||
|
||
if (pre_ins)
|
||
{
|
||
set_mode(NO_MODE);
|
||
init_query_insert_mode(*_mask);
|
||
}
|
||
else
|
||
{
|
||
set_mode(MODE_QUERY);
|
||
init_query_mode(*_mask);
|
||
}
|
||
}
|
||
|
||
|
||
void TRelation_application::insert_mode()
|
||
{
|
||
bool try_auto = TRUE;
|
||
|
||
if (_mask->query_mode())
|
||
try_auto = test_key(1, FALSE) == FALSE;
|
||
|
||
if (try_auto && !autonum(_mask, FALSE))
|
||
{
|
||
query_insert_mode();
|
||
return;
|
||
}
|
||
|
||
TRelation* r = get_relation();
|
||
for (int f = _mask->fields()-1; f >= 0; f--)
|
||
{
|
||
TMask_field& fld = _mask->fld(f);
|
||
if (fld.is_loadable() && fld.shown() && fld.in_key(0))
|
||
((TLoadable_field&)fld).autosave(*r);
|
||
}
|
||
if (!user_can_write(r))
|
||
{
|
||
warning_box("L'utente %s non puo' inserire in questo archivio",
|
||
(const char*)user());
|
||
return;
|
||
}
|
||
|
||
const bool changing = changing_mask(MODE_INS);
|
||
TFilename workname; workname.temp("msk");
|
||
if (changing)
|
||
{
|
||
_mask->set_workfile(workname);
|
||
_mask->save();
|
||
_mask->close_modal();
|
||
}
|
||
_mask = get_mask(MODE_INS);
|
||
if (changing)
|
||
{
|
||
_mask->reset();
|
||
_mask->set_workfile(workname);
|
||
_mask->load();
|
||
::remove(workname);
|
||
_mask->open_modal();
|
||
}
|
||
else
|
||
_mask->enable_page(1);
|
||
|
||
set_mode(MODE_INS);
|
||
r->zero(); // Azzera tutta la relazione!
|
||
|
||
init_insert_mode(*_mask);
|
||
|
||
// ....possibilmente spostare questa chiamata .....
|
||
if (_curr_transaction == TRANSACTION_INSERT)
|
||
ini2insert_mask();
|
||
}
|
||
|
||
bool TRelation_application::modify_mode()
|
||
{
|
||
TRelation* rel = get_relation();
|
||
if (!user_can_read(rel))
|
||
return warning_box("I dati non sono accessibili per l'utente %s",
|
||
(const char*)user());
|
||
|
||
const TReclock block = user_can_write(rel) ? _testandlock : _nolock;
|
||
int err = rel->read(_isequal, block);
|
||
if (err != NOERR)
|
||
{
|
||
if (err == _islocked)
|
||
message_box("I dati sono gia' usati da 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();
|
||
else
|
||
_mask->enable_page(1);
|
||
|
||
set_mode(MODE_MOD);
|
||
|
||
err = read(*_mask);
|
||
if (err != NOERR)
|
||
{
|
||
query_mode();
|
||
return FALSE;
|
||
}
|
||
|
||
rel->save_status();
|
||
init_modify_mode(*_mask);
|
||
|
||
// ....possibilmente spostare questa chiamata .....
|
||
if (_curr_transaction == TRANSACTION_MODIFY)
|
||
ini2insert_mask();
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
TEdit_field& TRelation_application::get_search_field() const
|
||
{
|
||
short id = _search_id;
|
||
|
||
if (id <= 0)
|
||
{
|
||
for (int i = _mask->fields()-1; i >= 0; i--)
|
||
{
|
||
const TMask_field& f = _mask->fld(i);
|
||
if (f.is_edit() && f.in_key(1) && f.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();
|
||
else
|
||
break;
|
||
}
|
||
|
||
TMask_field* dopo = &_mask->focus_field();
|
||
if (dopo != prima && dopo->is_edit() && dopo->in_key(0))
|
||
prima = (TEdit_field*)dopo;
|
||
else
|
||
break;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
HIDDEN bool delete_handler(TMask_field& f, KEY k)
|
||
{
|
||
if (k == K_TAB && f.focusdirty() && !f.empty())
|
||
{
|
||
TMask& m = f.mask();
|
||
const bool finale = *f.prompt() == 'A';
|
||
const int pos = m.id2pos(f.dlg());
|
||
if (pos >= 3)
|
||
{
|
||
const TMask_field& e = m.fld(pos - 3);
|
||
if (e.is_edit() && e.get().blank())
|
||
{
|
||
const short id = e.dlg() - (finale ? 200 : 100);
|
||
const TRelation_application& app = (TRelation_application&)main_app();
|
||
const TMask_field& orig = app.curr_mask().field(id);
|
||
bool req = orig.required();
|
||
if (!req && orig.is_edit())
|
||
{
|
||
const TEdit_field& e = (TEdit_field&)orig;
|
||
req = e.validate_func() == 12;
|
||
}
|
||
if (req)
|
||
{
|
||
TString str; str << (finale ? "A " : "Da ") << orig.prompt();
|
||
return f.error_box("Specificare anche il valore %s", (const char*)str);
|
||
}
|
||
}
|
||
}
|
||
if (finale && !f.get().blank())
|
||
{
|
||
const TMask_field& p = m.fld(pos - 1);
|
||
TString80 prec = p.get();
|
||
TString80 curr = f.get();
|
||
bool ok;
|
||
switch (p.class_id())
|
||
{
|
||
case CLASS_REAL_FIELD: ok = real(prec) <= real(curr); break;
|
||
case CLASS_DATE_FIELD: ok = TDate(prec) <= TDate(curr); break;
|
||
default : ok = prec <= curr; break;
|
||
}
|
||
if (!ok)
|
||
return f.error_box("Inserire un valore non inferiore a '%s'", (const char*)prec);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
int TRelation_application::delete_mode()
|
||
{
|
||
TEdit_field& fld = get_search_field();
|
||
TBrowse* brw = fld.browse();
|
||
if (brw)
|
||
{
|
||
brw->do_input(TRUE);
|
||
TCursor& cur = *brw->cursor();
|
||
|
||
TToken_string head(brw->head());
|
||
head.insert("@1|", 0);
|
||
TToken_string items(brw->items());
|
||
items.insert(" |", 0);
|
||
|
||
int tab1 = 0, tab2 = 0, y = 0;
|
||
// Nuovo modo basato sugli input
|
||
TToken_string inplist = brw->get_input_fields();
|
||
if (inplist.not_empty())
|
||
{
|
||
FOR_EACH_TOKEN(inplist, tok)
|
||
{
|
||
if (*tok != '"' && strchr(tok, '@') == NULL)
|
||
{
|
||
TMask_field& e = _mask->field(short(atoi(tok)));
|
||
if (e.active())
|
||
{
|
||
const int len = strlen(e.prompt());
|
||
if (len > tab1) tab1 = len;
|
||
const int size = e.size();
|
||
if (size > tab2) tab2 = size;
|
||
y++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
tab1 += 5;
|
||
tab2 += tab1+2;
|
||
|
||
cur = 0L;
|
||
TCursor_sheet sht(&cur, items, "Eliminazione", head, 0x4, y);
|
||
|
||
y = -1; // Posizione del campo precedente
|
||
TString prompt; // Prompt del campo corrente
|
||
const short delta = 100;
|
||
|
||
FOR_EACH_TOKEN(inplist, tok)
|
||
{
|
||
if (*tok != '"' && strchr(tok, '@') == NULL)
|
||
{
|
||
TMask_field& e = _mask->field(short(atoi(tok)));
|
||
if (!e.active())
|
||
continue;
|
||
|
||
const short id = e.dlg()+delta;
|
||
prompt = "Da "; prompt << e.prompt();
|
||
sht.add_static(DLG_NULL, 0, prompt, 1, ++y);
|
||
TString16 flags;
|
||
if (e.automagic()) flags << 'A';
|
||
if (e.roman()) flags << 'M';
|
||
if (e.right_justified()) flags << 'R';
|
||
if (e.uppercase()) flags << 'U';
|
||
if (e.zerofilled()) flags << 'Z';
|
||
switch (e.class_id())
|
||
{
|
||
case CLASS_DATE_FIELD:
|
||
{
|
||
TDate_field& d1 = sht.add_date(id, 0, "", tab1, y, flags);
|
||
TDate_field& d2 = sht.add_date(id+delta, 0, "A ", tab2, y, flags);
|
||
d1.set_handler(delete_handler);
|
||
d2.set_handler(delete_handler);
|
||
}
|
||
break;
|
||
case CLASS_REAL_FIELD:
|
||
{
|
||
TReal_field& r1 = sht.add_number(id, 0, "", tab1, y, e.size(), flags);
|
||
TReal_field& r2 = sht.add_number(id+delta, 0, "A ", tab2, y, e.size(), flags);
|
||
r1.set_handler(delete_handler);
|
||
r2.set_handler(delete_handler);
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
TEdit_field& e1 = sht.add_string(id, 0, "", tab1, y, e.size(), flags);
|
||
TEdit_field& e2 = sht.add_string(id+delta, 0, "A ", tab2, y, e.size(), flags);
|
||
e1.set_handler(delete_handler);
|
||
e2.set_handler(delete_handler);
|
||
}
|
||
break;
|
||
}
|
||
if (y == 0)
|
||
sht.first_focus(id);
|
||
}
|
||
}
|
||
|
||
sht.open_modal();
|
||
|
||
KEY tasto;
|
||
bool keep_running = TRUE;
|
||
while (keep_running)
|
||
{
|
||
tasto = sht.run();
|
||
if (tasto == K_ENTER)
|
||
{
|
||
TRectype rec_from(cur.curr()), rec_to(cur.curr());
|
||
rec_from.zero(); rec_to.zero();
|
||
TToken_string fldlist = brw->get_input_field_names();
|
||
TString80 str;
|
||
int fi = 0;
|
||
for (TString80 tok = inplist.get(fi); tok.not_empty(); tok = inplist.get(), fi++)
|
||
{
|
||
const TString16 fn = fldlist.get(fi);
|
||
const TFieldref fr(fn, 0);
|
||
if (*tok == '"')
|
||
{
|
||
str = tok;
|
||
str.ltrim(1); str.rtrim(1);
|
||
fr.write(str, rec_from);
|
||
fr.write(str, rec_to);
|
||
}
|
||
else
|
||
{
|
||
const short id = short(atoi(tok));
|
||
if (sht.id2pos(id+delta) >= 0)
|
||
{
|
||
str = sht.get(id+delta);
|
||
if (str.not_empty())
|
||
fr.write(str, rec_from);
|
||
str = sht.get(id+2*delta);
|
||
if (str.not_empty())
|
||
fr.write(str, rec_to);
|
||
}
|
||
else
|
||
{
|
||
str = _mask->get(id);
|
||
fr.write(str, rec_from);
|
||
fr.write(str, rec_to);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (rec_from.empty() && rec_to.empty())
|
||
{
|
||
sht.check(-1);
|
||
}
|
||
else
|
||
{
|
||
const long totit = cur.items();
|
||
cur.freeze(TRUE);
|
||
cur.curr() = rec_from;
|
||
cur.read();
|
||
while (cur.pos() < totit && cur.curr() <= rec_to)
|
||
{
|
||
sht.check(cur.pos());
|
||
++cur;
|
||
}
|
||
cur.freeze(FALSE);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
keep_running = FALSE;
|
||
if (tasto == K_DEL && sht.checked() == 0)
|
||
{
|
||
error_box("Non e' stato selezionato nessun elemento");
|
||
sht.select(0);
|
||
keep_running = TRUE;
|
||
}
|
||
}
|
||
}
|
||
sht.close_modal();
|
||
|
||
if (tasto == K_DEL)
|
||
{
|
||
long deleting = sht.checked();
|
||
TString msg;
|
||
msg = "Confermate l'eliminazione d";
|
||
if (deleting == 1)
|
||
msg << "ell'elemento selezionato?";
|
||
else
|
||
msg << "i " << deleting << " elementi selezionati?";
|
||
|
||
bool can_delete = yesno_box(msg);
|
||
if (can_delete && deleting > 100)
|
||
{
|
||
msg.insert("ATTENZIONE: ", 0);
|
||
can_delete = yesno_box(msg);
|
||
}
|
||
if (can_delete)
|
||
{
|
||
TWait_cursor hourglass;
|
||
long skipped = 0; // Record non cancellati perche' protetti
|
||
cur.freeze(TRUE); // Congelo il cursore altrimenti si riaggiorna troppo
|
||
for (long pos = sht.items()-1; deleting > 0; pos--)
|
||
{
|
||
if (sht.checked(pos))
|
||
{
|
||
cur = pos;
|
||
brw->do_output();
|
||
bool can_delete = FALSE;
|
||
if (find(1))
|
||
{
|
||
TRelation& r = *get_relation();
|
||
_autodelete = 0x3;
|
||
if (!protected_record(r))
|
||
{
|
||
if (modify_mode())
|
||
{
|
||
r.restore_status();
|
||
can_delete = remove();
|
||
}
|
||
query_mode();
|
||
}
|
||
_autodelete = FALSE;
|
||
}
|
||
if (!can_delete)
|
||
skipped++;
|
||
deleting--;
|
||
}
|
||
}
|
||
cur.freeze(FALSE);
|
||
if (skipped > 0)
|
||
{
|
||
if (skipped == 1)
|
||
warning_box("Un elemento non e' stato cancellato in quanto protetto.");
|
||
else
|
||
warning_box("%ld elementi non sono stati cancellati in quanto protetti.", skipped);
|
||
query_mode();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (search_mode())
|
||
_autodelete = TRUE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Controlla se una chiave e' completa ed esiste su file
|
||
//
|
||
// @rdesc Ritorna se la chave esiste sul file
|
||
bool TRelation_application::test_key(
|
||
word k, // @parm Chiave da ricercare
|
||
bool err) // @parm Indica se visualizzare eventuali errori occorsi
|
||
{
|
||
bool onereq = FALSE, onefill = FALSE;
|
||
|
||
for (TEditable_field* e = _mask->get_key_field(k, TRUE);
|
||
e != NULL;
|
||
e = _mask->get_key_field(k, FALSE))
|
||
{
|
||
if (e->required() && e->shown())
|
||
{
|
||
onereq = TRUE;
|
||
if (e->empty())
|
||
{
|
||
if (err)
|
||
{
|
||
TString msg(80);
|
||
msg = "Manca un valore indispensabile per la ricerca.";
|
||
#ifdef DBG
|
||
msg << "\nChiave " << int(k) << " - Campo " << e->dlg();
|
||
const TFieldref* fr = e->field();
|
||
if (fr != NULL)
|
||
{
|
||
msg << " - " << fr->name();
|
||
if (fr->to() > 0)
|
||
msg << '[' << fr->from() << ',' << fr->to() << ']';
|
||
}
|
||
#endif
|
||
error_box(msg);
|
||
_mask->first_focus(-e->dlg());
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
else
|
||
/* if (k == 1 && !onereq && !onefill && c.get().not_empty()) */
|
||
if (!onereq && !onefill && e->is_edit() && !e->empty())
|
||
onefill = TRUE;
|
||
}
|
||
if (k == 1 && !onereq && !onefill)
|
||
{
|
||
if (err)
|
||
error_box("Manca un valore indispensabile per la ricerca");
|
||
return FALSE;
|
||
}
|
||
return onefill || onereq;
|
||
}
|
||
|
||
bool TRelation_application::find(word k)
|
||
{
|
||
if (k == 0)
|
||
{
|
||
for (k = 1; k <= MAX_KEYS && !test_key(k, FALSE); k++);
|
||
if (k > MAX_KEYS)
|
||
return test_key(1, TRUE);
|
||
}
|
||
|
||
file().setkey(k);
|
||
file().zero();
|
||
for (TEditable_field* e = _mask->get_key_field(k, TRUE); e; e = _mask->get_key_field(k, FALSE))
|
||
{
|
||
if (e->shown()) // Ignora campi invisibili
|
||
e->autosave(*get_relation());
|
||
}
|
||
|
||
const int err = file().read(_isequal);
|
||
return err == NOERR;
|
||
}
|
||
|
||
|
||
bool TRelation_application::save(bool check_dirty)
|
||
{
|
||
static bool was_dirty = FALSE;
|
||
|
||
int pos = _mask->id2pos(DLG_SAVEREC);
|
||
if (pos < 0 || !_mask->fld(pos).active())
|
||
return TRUE;
|
||
|
||
int err = NOERR;
|
||
const int mode = _mask->mode();
|
||
if (check_dirty)
|
||
{
|
||
const int dirty = _mask->dirty();
|
||
|
||
if (mode == MODE_QUERY)
|
||
{
|
||
const char* ms = (mode == MODE_MOD) ? TR("Annullare le modifiche?") : TR("Annullare i dati inseriti?");
|
||
const bool cont = !dirty || yesno_box(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() > 1;
|
||
|
||
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: ";
|
||
switch (last)
|
||
{
|
||
case K_ESC:
|
||
w << TR("si desidera annullare?"); break;
|
||
case K_QUIT:
|
||
w << TR("si desidera uscire?"); break;
|
||
default:
|
||
w << TR("si desidera continuare?"); break;
|
||
}
|
||
k = yesno_box(w) ? K_NO : K_ESC;
|
||
if (k == K_ESC)
|
||
_mask->first_focus(-dirty);
|
||
}
|
||
else k = K_ESC;
|
||
}
|
||
else
|
||
k = yesnocancel_box("Si desidera registrare?");
|
||
|
||
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;
|
||
|
||
TWait_cursor hourglass;
|
||
if (mode == MODE_INS)
|
||
{
|
||
bool changed = TRUE;
|
||
bool changed_key = FALSE;
|
||
|
||
while (changed)
|
||
{
|
||
err = write(*_mask);
|
||
if (err == _isreinsert)
|
||
{
|
||
changed = autonum(_mask, TRUE);
|
||
if (!changed)
|
||
{
|
||
_mask->disable_starting_check();
|
||
enable_query(); // Abilita chiave 1 per rinumerazione manuale
|
||
}
|
||
else
|
||
changed_key = TRUE;
|
||
}
|
||
else
|
||
changed = FALSE;
|
||
}
|
||
if (err == NOERR)
|
||
{
|
||
if (changed_key)
|
||
message_box(_renum_message);
|
||
get_relation()->save_status();
|
||
set_limits();
|
||
get_relation()->restore_status();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
get_relation()->restore_status();
|
||
err = rewrite(*_mask);
|
||
}
|
||
|
||
switch(err)
|
||
{
|
||
case NOERR:
|
||
_recins = get_relation()->lfile().recno();
|
||
mask2mail(*_mask);
|
||
break;
|
||
case _isreinsert:
|
||
warning_box(TR("Esiste gia' un elemento con la stessa chiave"));
|
||
break;
|
||
default:
|
||
error_box(FR("Impossibile registrare i dati: errore %d"), err);
|
||
break;
|
||
}
|
||
return err == NOERR;
|
||
}
|
||
|
||
|
||
int TRelation_application::read(TMask& m)
|
||
{
|
||
const TRelation &r = *get_relation();
|
||
const int max = m.fields();
|
||
for (int i = 0; i < max; i++)
|
||
{
|
||
if (m.fld(i).is_sheet())
|
||
{
|
||
TSheet_field& f = (TSheet_field&)m.fld(i);
|
||
if (f.record() && !f.external_record())
|
||
f.record()->read(*f.putkey(r));
|
||
}
|
||
}
|
||
m.autoload(r);
|
||
return NOERR;
|
||
}
|
||
|
||
|
||
int TRelation_application::write(const TMask& m)
|
||
{
|
||
TRelation &r = *get_relation();
|
||
m.autosave(r);
|
||
|
||
// write relation and all independent sheets
|
||
int err=r.write();
|
||
const int max = m.fields();
|
||
for (int i = 0; i < max; i++)
|
||
{
|
||
if (m.fld(i).is_sheet())
|
||
{
|
||
TSheet_field& f = (TSheet_field& )m.fld(i);
|
||
if (f.record() && !f.external_record())
|
||
err|=f.record()->write(FALSE);
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
|
||
|
||
int TRelation_application::rewrite(const TMask& m)
|
||
{
|
||
int err;
|
||
|
||
TRelation& r = *get_relation();
|
||
m.autosave(r);
|
||
// rewrite relation and all independent sheets
|
||
r.rewrite();
|
||
err=r.status();
|
||
const int max = m.fields();
|
||
for (int i = 0; i < max; i++)
|
||
{
|
||
if (m.fld(i).is_sheet()) {
|
||
TSheet_field& f = (TSheet_field& )m.fld(i);
|
||
if (f.record()&& !f.external_record())
|
||
err|=f.record()->write(TRUE);
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Cancella il record corrente
|
||
//
|
||
// @rdesc Ritorna se il record e' stato eliminato
|
||
bool TRelation_application::relation_remove()
|
||
// @comm Se la maschera e' in MODE_MOD non e' possibile cancellare il record e viene
|
||
// emesso un <f CHECK> di errore.
|
||
{
|
||
CHECK(_mask->edit_mode(), "You can call remove in edit mode only");
|
||
|
||
TRelation& r = *get_relation();
|
||
r.restore_status();
|
||
if (protected_record(r))
|
||
return message_box("Elemento non eliminabile");
|
||
|
||
if (_curr_transaction == TRANSACTION_DELETE || yesno_box("Confermare l'eliminazione"))
|
||
{
|
||
r.restore_status();
|
||
const bool ok = remove();
|
||
if (ok || is_transaction())
|
||
set_limits();
|
||
else
|
||
return error_box("Errore di cancellazione %d", r.status());
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
bool TRelation_application::protected_record(TRelation &r)
|
||
{
|
||
if (user_can_write(&r))
|
||
return protected_record(r.curr());
|
||
return TRUE;
|
||
}
|
||
|
||
bool TRelation_application::remove()
|
||
{
|
||
int err = get_relation()->remove();
|
||
if (err == NOERR)
|
||
{
|
||
const int maxf = _mask->fields();
|
||
for (int i = 0; i < maxf; i++)
|
||
{
|
||
const TMask_field& mf = _mask->fld(i);
|
||
if (mf.is_sheet())
|
||
{
|
||
TSheet_field& f = (TSheet_field&)mf;
|
||
if (f.record()&& !f.external_record())
|
||
err |= f.record()->remove();
|
||
}
|
||
}
|
||
}
|
||
if (err == NOERR)
|
||
{
|
||
_mask->set_mode(NO_MODE);
|
||
mask2mail(*_mask);
|
||
}
|
||
return err == NOERR;
|
||
}
|
||
|
||
bool TRelation_application::firm_change_enabled() const
|
||
{
|
||
bool ok = TApplication::firm_change_enabled();
|
||
ok &= (_mask == NULL || _mask->query_mode()) && _lnflag == 0;
|
||
return ok;
|
||
}
|
||
|
||
void TRelation_application::main_loop()
|
||
{
|
||
KEY k;
|
||
do {
|
||
// ciclo delle transazioni
|
||
_recins = -1;
|
||
|
||
// imposta la maschera in query mode
|
||
query_mode();
|
||
_mask->open_modal();
|
||
|
||
// Provoca l'autopremimento per il messaggio di LINK
|
||
if (_lnflag)
|
||
{
|
||
if (_trans_counter < _ntransactions)
|
||
{
|
||
// la transazione <20> sul .ini : la imposta nelle variabili _curr_transaction...
|
||
if (load_transaction())
|
||
{
|
||
// la transazione necessita di autopremimento
|
||
_autodelete = _curr_transaction == TRANSACTION_DELETE;
|
||
if (_curr_transaction == TRANSACTION_INSERT )
|
||
_mask->send_key(K_CTRL+'N', 0);
|
||
else
|
||
_mask->send_key(K_AUTO_ENTER, 0);
|
||
}
|
||
}
|
||
else // la transazione non <20> sul .ini
|
||
{
|
||
_mask->send_key(K_AUTO_ENTER, 0);
|
||
}
|
||
}
|
||
|
||
if (is_transaction())
|
||
ini2query_mask();
|
||
|
||
do
|
||
{
|
||
const bool change = firm_change_enabled();
|
||
// Dis/abilita cambio ditta
|
||
enable_menu_item(M_FILE_NEW, change);
|
||
|
||
if (_mask->edit_mode())
|
||
{
|
||
if (_autodelete)
|
||
{
|
||
const int pos = _mask->id2pos(DLG_DELREC);
|
||
if (pos >= 0 && _mask->fld(pos).active())
|
||
_mask->send_key(K_CTRL+'E', 0);
|
||
else
|
||
error_box("Elemento non eliminabile.");
|
||
_autodelete = FALSE;
|
||
}
|
||
}
|
||
|
||
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 (_lnflag && _curr_transaction != TRANSACTION_RUN)
|
||
{
|
||
for (k = 1; k <= MAX_KEYS && !test_key(k, FALSE); k++);
|
||
if (k <= MAX_KEYS && find(k))
|
||
modify_mode();
|
||
else
|
||
k = K_QUIT; // Siamo sicuri? insert_mode()
|
||
}
|
||
else
|
||
{
|
||
if (find(0))
|
||
modify_mode();
|
||
else
|
||
insert_mode();
|
||
}
|
||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||
_mask->send_key(K_CTRL+'R', 0);
|
||
break;
|
||
case K_SAVE:
|
||
if (save(FALSE))
|
||
{
|
||
if (_autoins_caller.not_empty() || is_transaction())
|
||
{
|
||
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();
|
||
if (is_transaction())
|
||
{
|
||
_curr_transaction=TRANSACTION_MODIFY;
|
||
// _curr_trans_mode = TM_INTERACTIVE; // Siamo sicuri???
|
||
}
|
||
else
|
||
warning_box("Elemento gia' presente");
|
||
}
|
||
else
|
||
insert_mode();
|
||
}
|
||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||
_mask->send_key(K_CTRL+'R', 0);
|
||
break;
|
||
case K_DEL:
|
||
if (_mask->query_mode())
|
||
{
|
||
delete_mode();
|
||
}
|
||
else
|
||
{
|
||
if (relation_remove())
|
||
{
|
||
query_mode();
|
||
if (_autoins_caller.not_empty() || is_transaction())
|
||
{
|
||
if (_lnflag) _recins = 0;
|
||
k = K_QUIT;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case K_F9:
|
||
if (_mask->query_mode() || save(TRUE))
|
||
search_mode();
|
||
break;
|
||
default:
|
||
if (save(TRUE))
|
||
{
|
||
setkey();
|
||
int err = ~NOERR;
|
||
switch (k)
|
||
{
|
||
case K_HOME:
|
||
err = file().readat(_first, _testandlock);
|
||
break;
|
||
case K_NEXT:
|
||
err = file().reread();
|
||
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)
|
||
{
|
||
TString16 num;
|
||
num.format("%ld", _recins);
|
||
TMessage msg(autoins_caller(), _lnflag ? MSG_LN : MSG_AI, num);
|
||
msg.send();
|
||
}
|
||
|
||
if (is_transaction())
|
||
{
|
||
TConfig ini(_trans_ini.row(_trans_counter), "Transaction");
|
||
ini.set("Record", _recins);
|
||
if (_recins >= 0)
|
||
{
|
||
ini.set("Result", "OK");
|
||
ini.set("Error", "0");
|
||
edit_mask2ini();
|
||
}
|
||
else
|
||
{
|
||
const int err = get_relation()->status();
|
||
ini.set("Result", err == NOERR ? "CANCEL" : "ERROR");
|
||
ini.set("Error", err);
|
||
}
|
||
|
||
}
|
||
_trans_counter++;
|
||
} while ( _trans_counter < _ntransactions);
|
||
}
|
||
|
||
bool TRelation_application::filter()
|
||
{
|
||
if (parse_command_line())
|
||
return TRUE;
|
||
|
||
TMailbox mail;
|
||
TMessage* msg = mail.next_s(MSG_FS);
|
||
|
||
if (msg)
|
||
{
|
||
_mask = get_mask(MODE_MOD);
|
||
TToken_string body(msg->body());
|
||
|
||
short id = body.get_int();
|
||
while (id > 0)
|
||
{
|
||
_search_id = id;
|
||
TEdit_field& f = (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, 0x2);
|
||
if (s == NULL) id = 0;
|
||
}
|
||
}
|
||
|
||
mail.restart();
|
||
msg = mail.next_s(MSG_AI);
|
||
if (msg) _autoins_caller = msg->from();
|
||
|
||
mail.restart();
|
||
msg = mail.next_s(MSG_LN);
|
||
if (msg)
|
||
{
|
||
TToken_string body(msg->body());
|
||
const int key = body.get_int();
|
||
|
||
_autoins_caller = msg->from();
|
||
_lnflag = TRUE;
|
||
|
||
TString str, tmp;
|
||
const char* v = body.get();
|
||
for (int i = 0; v != NULL && i < _mask->fields(); i++)
|
||
{
|
||
TMask_field& f = _mask->fld(i);
|
||
if (f.active() && f.dlg() > 0 && f.in_key(key))
|
||
{
|
||
str = v;
|
||
tmp.format("%d=", f.dlg());
|
||
str.insert(tmp, 0);
|
||
_fixed.add(str);
|
||
v = body.get();
|
||
}
|
||
}
|
||
}
|
||
|
||
mail.restart();
|
||
msg = mail.next_s(MSG_ED);
|
||
if (msg)
|
||
{
|
||
TToken_string body(msg->body());
|
||
const int key = body.get_int();
|
||
|
||
_autoins_caller = msg->from();
|
||
_lnflag = 2;
|
||
|
||
TAssoc_array field_values;
|
||
const char * s;
|
||
TString t, v;
|
||
|
||
while((s = body.get()) != NULL)
|
||
{
|
||
t = s;
|
||
const int u = t.find('=');
|
||
|
||
CHECKS(u > 0, "Invalid edit message ", (const char *) body);
|
||
if (u > 0)
|
||
{
|
||
v = t.mid(u + 1);
|
||
|
||
t.cut(u);
|
||
field_values.add(t, v);
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < _mask->fields(); i++)
|
||
{
|
||
TMask_field& f = _mask->fld(i);
|
||
const TFieldref * field = f.field();
|
||
|
||
if (field && f.in_key(key))
|
||
{
|
||
TString16 field_name(field->name());
|
||
const int from = field->from();
|
||
const int to = field->to();
|
||
|
||
if (to >= 0)
|
||
field_name << "[" << (from + 1);
|
||
const TString * v = (const TString *) field_values.objptr(field_name);
|
||
|
||
TString val;
|
||
if (v == NULL && to >= 0)
|
||
{
|
||
v = (const TString *)field_values.objptr(field->name());
|
||
if (v)
|
||
val = v->sub(from, to);
|
||
}
|
||
else
|
||
if (v) val = *v;
|
||
|
||
if (v)
|
||
{
|
||
t.format("%d=", f.dlg());
|
||
val.insert(t, 0);
|
||
_fixed.add(val);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TRelation_application::set_link(TMask & m, const char * keyexpr)
|
||
{
|
||
CHECK(keyexpr != NULL, "Invalid expression");
|
||
TToken_string body(keyexpr);
|
||
const int key = body.get_int();
|
||
|
||
_lnflag = TRUE;
|
||
|
||
const char* v = body.get();
|
||
|
||
TString16 tmp;
|
||
const int max = m.fields();
|
||
for (int i = 0; i < max && v != NULL; i++)
|
||
{
|
||
TMask_field& f = m.fld(i);
|
||
|
||
if (f.active() && f.dlg() > 0 && f.in_key(key))
|
||
{
|
||
TString s(v);
|
||
tmp.format("%d=", f.dlg());
|
||
s.insert(tmp, 0);
|
||
_fixed.add(s);
|
||
v = body.get();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
bool TRelation_application::parse_command_line()
|
||
{
|
||
_trans_ini.destroy();
|
||
_trans_counter=0;
|
||
_curr_transaction = "";
|
||
_curr_trans_mode = 'I';
|
||
|
||
TFilename ini;
|
||
for (int i = argc()-1; i > 0; i--)
|
||
{
|
||
ini = argv(i);
|
||
ini.upper();
|
||
if ((ini[0] == '-' || ini[0] == '/') && ini[1] == 'I')
|
||
{
|
||
ini.ltrim(2);
|
||
CHECK(!ini.blank(),"Manca l'indicazione della transazione. Il nome va indicato di seguito al -i, senza interporre spaziatura.");
|
||
if (ini.find('*')>=0)
|
||
{
|
||
// metachars:
|
||
list_files(ini, _trans_ini);
|
||
}
|
||
else
|
||
_trans_ini.add(ini);
|
||
break;
|
||
}
|
||
}
|
||
|
||
_ntransactions= _trans_ini.items();
|
||
|
||
_lnflag = _ntransactions>0;
|
||
return _lnflag != 0;
|
||
}
|
||
|
||
// il valore di ritorno indica se attivare l'"automagia" (spedizione dei tasti e
|
||
// precaricamento della maschera)
|
||
bool TRelation_application::load_transaction()
|
||
{
|
||
bool retv = FALSE;
|
||
if (_trans_counter < _ntransactions)
|
||
{
|
||
TConfig cnf(_trans_ini.row(_trans_counter), "Transaction");
|
||
_curr_transaction = cnf.get("Action");
|
||
_curr_transaction.upper();
|
||
_curr_trans_mode = toupper(cnf.get("Mode")[0]);
|
||
_curr_trans_from = cnf.get("From");
|
||
const long firm = cnf.get_long("Firm");
|
||
if (firm > 0)
|
||
|
||
{
|
||
bool ok = set_firm(firm);
|
||
if (ok)
|
||
_mask->on_firm_change();
|
||
else
|
||
error_box("La ditta %ld non esiste", firm);
|
||
|
||
}
|
||
|
||
if (_curr_transaction == TRANSACTION_RUN)
|
||
retv= FALSE; // Ho gia' finito qui: basta il cambio ditta
|
||
else
|
||
retv = TRUE; // Attiva automagia
|
||
}
|
||
return retv;
|
||
}
|
||
|
||
void TRelation_application::ini2query_mask()
|
||
{
|
||
if (is_transaction())
|
||
{
|
||
TConfig ini(_trans_ini.row(_trans_counter), format("%d", get_relation()->lfile().num()));
|
||
ini2mask(ini, *_mask, TRUE);
|
||
}
|
||
}
|
||
|
||
void TRelation_application::ini2insert_mask()
|
||
{
|
||
if (is_transaction())
|
||
{
|
||
TConfig ini(_trans_ini.row(_trans_counter), format("%d", get_relation()->lfile().num()));
|
||
ini2mask(ini, *_mask, FALSE);
|
||
}
|
||
}
|
||
|
||
void TRelation_application::ini2mask(TConfig& ini, TMask& m, bool query)
|
||
{
|
||
const TString16 defpar = ini.get_paragraph();
|
||
for (int f = m.fields()-1; f >= 0; f--)
|
||
{
|
||
TMask_field& campo = m.fld(f);
|
||
const TFieldref* fref = campo.field();
|
||
if (fref)
|
||
{
|
||
if (!query || campo.in_key(0))
|
||
{
|
||
const TString& str = fref->read(ini, defpar);
|
||
if (str.not_empty())
|
||
campo.set(str);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!query && campo.is_sheet())
|
||
{
|
||
TSheet_field &sheet=(TSheet_field &)campo;
|
||
ini2sheet(ini, sheet);
|
||
}
|
||
}
|
||
}
|
||
ini.set_paragraph(defpar);
|
||
}
|
||
|
||
void TRelation_application::edit_mask2ini()
|
||
{
|
||
if (_trans_ini.row(_trans_counter).not_empty())
|
||
{
|
||
TString16 head;
|
||
head.format("%d", get_relation()->lfile().num());
|
||
TConfig ini(_trans_ini.row(_trans_counter), head);
|
||
mask2ini(*_mask, ini);
|
||
}
|
||
}
|
||
|
||
|
||
void TRelation_application::ini2sheet(TConfig& ini,TSheet_field &sheet)
|
||
{
|
||
if (sheet.record() != NULL)
|
||
{
|
||
const int lognum = sheet.record()->logic_num();
|
||
const TMask& sm = sheet.sheet_mask();
|
||
|
||
// scrive le righe nello sheet associato
|
||
TString16 defpar;
|
||
|
||
for (int r = 1; ;r++)
|
||
{
|
||
defpar.format("%d,%d", lognum, r);
|
||
if (ini.set_paragraph(defpar))
|
||
{
|
||
TToken_string& row = sheet.row(r-1);
|
||
for (int sf = sm.fields()-1; sf >= 0; sf--)
|
||
{
|
||
TMask_field& campo = sm.fld(sf);
|
||
const TFieldref* fref = campo.field();
|
||
if (fref)
|
||
{
|
||
const TString& str = fref->read(ini, defpar);
|
||
row.add(str, sheet.cid2index(campo.dlg()));
|
||
}
|
||
}
|
||
sheet.check_row(r-1);
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TRelation_application::sheet2ini(TSheet_field &sheet,TConfig& ini)
|
||
{
|
||
if (sheet.record() != NULL)
|
||
{
|
||
const int lognum = sheet.record()->logic_num();
|
||
const TMask& sm = sheet.sheet_mask();
|
||
|
||
// scrive le righe degli sheet associati
|
||
TString16 defpar;
|
||
TString str;
|
||
for (int r = 1 ; r <= sheet.items(); r++)
|
||
{
|
||
defpar.format("%d,%d", lognum, r);
|
||
|
||
TMask_field* fkey;
|
||
sheet.restart_key();
|
||
while (fkey = sheet.get_key(str))
|
||
{
|
||
ini.set(str, fkey->get(), defpar);
|
||
}
|
||
|
||
TToken_string& row = sheet.row(r-1);
|
||
const char* value;
|
||
int i;
|
||
for (i = 0, value = row.get(0); value; i++, value = row.get())
|
||
{
|
||
const TMask_field& campo = sm.field(FIRST_FIELD+i);
|
||
const TFieldref* fr = campo.field();
|
||
if (fr)
|
||
{
|
||
if (value == NULL || *value == '\0')
|
||
value = " ";
|
||
// ini.set(fr->name(), value, defpar);
|
||
fr->write(ini, defpar, value);
|
||
}
|
||
}
|
||
}
|
||
for (r = sheet.items()+1; ; r++)
|
||
{
|
||
defpar.format("%d,%d", lognum, r);
|
||
if (ini.set_paragraph(defpar))
|
||
ini.remove_all();
|
||
else
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TRelation_application::mask2ini(const TMask& m, TConfig& ini)
|
||
{
|
||
ini.set("Firm", get_firm(), "Transaction");
|
||
|
||
int year, release, tag, patch;
|
||
if (get_version_info(year, release, tag, patch))
|
||
{
|
||
TString80 ver;
|
||
ver.format("%d %d.%d-%d", year, release, tag, patch);
|
||
ini.set("Version", ver);
|
||
}
|
||
|
||
const TLocalisamfile& lfile = get_relation()->lfile();
|
||
|
||
TString16 defpar;
|
||
defpar.format("%d", lfile.num());
|
||
ini.set_paragraph(defpar);
|
||
switch (lfile.num())
|
||
{
|
||
case LF_TAB:
|
||
case LF_TABCOM:
|
||
case LF_TABGEN:
|
||
{
|
||
const TString& tabname = lfile.curr().get("COD");
|
||
ini.set("COD", tabname, defpar);
|
||
}
|
||
break;
|
||
}
|
||
for (int f = 0; f < m.fields(); f++)
|
||
{
|
||
TMask_field& campo = m.fld(f);
|
||
if (campo.shown())
|
||
{
|
||
const TFieldref* fr = campo.field();
|
||
if (fr)
|
||
{
|
||
if (campo.empty())
|
||
fr->write(ini, defpar, " ");
|
||
else
|
||
fr->write(ini, defpar, campo.get());
|
||
}
|
||
else
|
||
if (campo.is_sheet())
|
||
{
|
||
TSheet_field &sheet=(TSheet_field &)campo;
|
||
sheet2ini(sheet,ini); // It's virtual
|
||
}
|
||
}
|
||
}
|
||
ini.set_paragraph(defpar); // Reimposta paragrafo standard
|
||
}
|
||
|
||
bool TRelation_application::mask2mail(const TMask& m)
|
||
{
|
||
TWait_cursor hourglass;
|
||
bool ok = _curr_trans_from.empty() && ::can_dispatch_transaction(get_relation()->curr());
|
||
if (ok)
|
||
{
|
||
TFilename ininame; ininame.temp();
|
||
if (ok) // Test qualunque per usare {}
|
||
{
|
||
TConfig ini(ininame, "Transaction");
|
||
const char* action = "";
|
||
char mode[2] = { TM_AUTOMATIC, '\0' };
|
||
switch (m.mode())
|
||
{
|
||
case NO_MODE:
|
||
action = TRANSACTION_DELETE;
|
||
break;
|
||
case MODE_MOD:
|
||
action = TRANSACTION_MODIFY;
|
||
break;
|
||
default:
|
||
action = TRANSACTION_INSERT;
|
||
break;
|
||
}
|
||
ini.set("Action", action);
|
||
ini.set("Mode", mode);
|
||
mask2ini(m, ini);
|
||
}
|
||
ok = ::dispatch_transaction(get_relation()->curr(), ininame);
|
||
::remove(ininame);
|
||
}
|
||
return ok;
|
||
}
|