6bac6177c4
Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunte utili per gestione dizionario assoc.cpp Aggiunta possibilita' di selezionare un elemento causale di un assoc controls.cpp Corretta gestione scrollbar dei listbox diction.cpp Migliorata selezione caratteri da trimmare dalle traduzioni isam.cpp Corretto azzeramento dei memo (non azzerava il TString_array corrispondente) msksheet.cpp Resa personalizzabile la larghezza della colonna col numero di riga netsock.cpp Migliorata gestione "a capo" in protocollo soap progind.cpp Corretto posizionamento progind sovrapposte relapp.cpp Cambiato un messaggio di richiesta annullamento git-svn-id: svn://10.65.10.50/trunk@11651 c028cbd2-c16b-5b4b-a496-9718f37d4682
1949 lines
47 KiB
C++
Executable File
1949 lines
47 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(0),
|
||
_autodelete(0), _navigating(false)
|
||
{ }
|
||
|
||
TRelation_application::~TRelation_application()
|
||
{ }
|
||
|
||
TCursor& TRelation_application::get_filtered_cursor() const
|
||
{
|
||
TEdit_field& f = get_search_field();
|
||
TCursor* cur = f.browse()->cursor();
|
||
return *cur;
|
||
}
|
||
|
||
void TRelation_application::setkey()
|
||
{
|
||
if (has_filtered_cursor())
|
||
{
|
||
get_filtered_cursor().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();
|
||
b->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 ok ? TSkeleton_application::create() : ok;
|
||
}
|
||
|
||
|
||
bool TRelation_application::destroy()
|
||
{
|
||
user_destroy();
|
||
return TSkeleton_application::destroy();
|
||
}
|
||
|
||
|
||
void TRelation_application::set_fixed()
|
||
{
|
||
TToken_string s(256, '=');
|
||
for (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()
|
||
{
|
||
const int mode = _mask->mode();
|
||
const bool can_edit_some = user_can_write(NULL);
|
||
|
||
int pos = _mask->id2pos(DLG_SAVEREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabsave=mode != MODE_QUERY;
|
||
if (enabsave)
|
||
enabsave = user_can_write(get_relation());
|
||
_mask->fld(pos).enable(enabsave);
|
||
}
|
||
pos = _mask->id2pos(DLG_DELREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabdel = (mode == MODE_QUERY && can_edit_some) || (mode == MODE_MOD);
|
||
if (enabdel && mode == MODE_MOD)
|
||
{
|
||
TRelation& r = *get_relation();
|
||
const TRecnotype oldpos = r.lfile().recno();
|
||
enabdel = !protected_record(r);
|
||
if (r.lfile().recno() != oldpos)
|
||
r.lfile().readat(oldpos);
|
||
}
|
||
_mask->fld(pos).enable(enabdel);
|
||
}
|
||
|
||
pos = _mask->id2pos(DLG_FINDREC);
|
||
if (pos >= 0)
|
||
{
|
||
_mask->fld(pos).enable(_lnflag == 0);
|
||
|
||
const long recno = get_relation()->lfile().recno();
|
||
const bool enable_next_prev = _mask->edit_mode();
|
||
|
||
pos = _mask->id2pos(DLG_FIRSTREC);
|
||
if (pos >= 0)
|
||
_mask->fld(pos).enable(_lnflag == 0 && (enable_next_prev ? _first != recno : _first > 0));
|
||
pos = _mask->id2pos(DLG_PREVREC);
|
||
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 && (enable_next_prev ? _last != recno : _last > 0));
|
||
}
|
||
|
||
pos = _mask->id2pos(DLG_NEWREC);
|
||
if (pos >= 0)
|
||
{
|
||
bool enabins = (mode == MODE_QUERY || _lnflag == 0) && can_edit_some;
|
||
_mask->fld(pos).enable(enabins);
|
||
}
|
||
|
||
set_find_button();
|
||
enable_query();
|
||
}
|
||
|
||
void TRelation_application::update_navigation_bar()
|
||
{
|
||
if (_mask->query_mode())
|
||
{
|
||
set_limits();
|
||
set_toolbar();
|
||
}
|
||
}
|
||
|
||
bool TRelation_application::save_and_new() const
|
||
{ return FALSE; }
|
||
|
||
int TRelation_application::set_mode(int mode)
|
||
{
|
||
static int _mode = NO_MODE;
|
||
if (mode < NO_MODE) mode = _mode;
|
||
|
||
const int m = ((TMaskmode)mode == NO_MODE) ? (int) MODE_QUERY : mode;
|
||
_mask->set_mode(m);
|
||
|
||
set_toolbar();
|
||
_mode = mode;
|
||
|
||
const char* t = "";
|
||
switch(mode)
|
||
{
|
||
case MODE_QUERY:
|
||
t = "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);
|
||
|
||
// Aggiorna bottoni di ricerca: utile soprattutto per ve0 che imposta CODNUM
|
||
if (has_filtered_cursor())
|
||
{
|
||
set_limits();
|
||
set_toolbar();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void TRelation_application::insert_mode()
|
||
{
|
||
bool try_auto = TRUE;
|
||
|
||
if (_mask->query_mode())
|
||
try_auto = test_key(1, FALSE) == 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))
|
||
{
|
||
warning_box(TR("I dati non sono accessibili per l'utente %s"), (const char*)user());
|
||
query_mode();
|
||
return FALSE;
|
||
}
|
||
|
||
const TReclock block = user_can_write(rel) ? _testandlock : _nolock;
|
||
int err = rel->read(_isequal, block);
|
||
if (err != NOERR)
|
||
{
|
||
if (err == _islocked)
|
||
message_box("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 .....
|
||
// Forse deve essere fatta prima della init_modify_mode()!
|
||
if (_curr_transaction == TRANSACTION_MODIFY)
|
||
ini2insert_mask();
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
TEdit_field& TRelation_application::get_search_field() const
|
||
{
|
||
short id = _search_id;
|
||
|
||
if (id <= 0 || !_mask->field(id).shown())
|
||
{
|
||
for (int i = _mask->fields()-1; i >= 0; i--)
|
||
{
|
||
const TMask_field& f = _mask->fld(i);
|
||
if (f.is_edit() && f.in_key(1) && f.shown())
|
||
{
|
||
id = f.dlg();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return _mask->efield(id);
|
||
}
|
||
|
||
bool TRelation_application::search_mode()
|
||
{
|
||
if (_mask->mode() != MODE_QUERY)
|
||
query_mode();
|
||
|
||
TEdit_field* prima = &get_search_field();
|
||
while (prima)
|
||
{
|
||
if (prima->on_key(K_F9))
|
||
{
|
||
if (find(1))
|
||
return modify_mode();
|
||
else
|
||
break;
|
||
}
|
||
|
||
TMask_field* dopo = &_mask->focus_field();
|
||
if (dopo != prima && dopo->is_edit() && dopo->in_key(0))
|
||
prima = (TEdit_field*)dopo;
|
||
else
|
||
break;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
HIDDEN bool delete_handler(TMask_field& f, KEY k)
|
||
{
|
||
if (k == K_TAB && f.focusdirty() && !f.empty())
|
||
{
|
||
TMask& m = f.mask();
|
||
const bool finale = *f.prompt() == 'A';
|
||
const int pos = m.id2pos(f.dlg());
|
||
if (pos >= 3)
|
||
{
|
||
const TMask_field& e = m.fld(pos - 3);
|
||
if (e.is_edit() && e.get().blank())
|
||
{
|
||
const short id = e.dlg() - (finale ? 200 : 100);
|
||
const TRelation_application& app = (TRelation_application&)main_app();
|
||
const TMask_field& orig = app.curr_mask().field(id);
|
||
bool req = orig.required();
|
||
if (!req && orig.is_edit())
|
||
{
|
||
const TEdit_field& e = (TEdit_field&)orig;
|
||
req = e.validate_func() == 12;
|
||
}
|
||
if (req)
|
||
{
|
||
TString str; str << (finale ? "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.format(FR("Confermare l'eliminazione di %d elementi"), deleting);
|
||
bool can_delete = yesno_box(msg);
|
||
if (can_delete && deleting > 100)
|
||
{
|
||
msg.insert(TR("ATTENZIONE: "), 0);
|
||
can_delete = yesno_box(msg);
|
||
}
|
||
if (can_delete)
|
||
{
|
||
TWait_cursor hourglass;
|
||
long skipped = 0; // Record non cancellati perche' protetti
|
||
cur.freeze(TRUE); // Congelo il cursore altrimenti si riaggiorna troppo
|
||
for (long pos = sht.items()-1; deleting > 0; pos--)
|
||
{
|
||
if (sht.checked(pos))
|
||
{
|
||
cur = pos;
|
||
brw->do_output();
|
||
bool can_delete = FALSE;
|
||
if (find(1))
|
||
{
|
||
TRelation& r = *get_relation();
|
||
_autodelete = 0x3;
|
||
if (!protected_record(r))
|
||
{
|
||
if (modify_mode())
|
||
{
|
||
r.restore_status();
|
||
can_delete = remove();
|
||
}
|
||
query_mode();
|
||
}
|
||
_autodelete = FALSE;
|
||
}
|
||
if (!can_delete)
|
||
skipped++;
|
||
deleting--;
|
||
}
|
||
}
|
||
cur.freeze(FALSE);
|
||
set_limits(); // Riaggiorno il numero del primo/ultimo record
|
||
|
||
if (skipped > 0)
|
||
{
|
||
warning_box(FR("%ld elementi non sono stati cancellati in quanto protetti."), skipped);
|
||
query_mode();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (search_mode())
|
||
_autodelete = TRUE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Controlla se una chiave e' completa ed esiste su file
|
||
//
|
||
// @rdesc Ritorna se la chave esiste sul file
|
||
bool TRelation_application::test_key(
|
||
word k, // @parm Chiave da ricercare
|
||
bool err) // @parm Indica se visualizzare eventuali errori occorsi
|
||
{
|
||
bool onereq = FALSE, onefill = FALSE;
|
||
|
||
for (TEditable_field* e = _mask->get_key_field(k, TRUE);
|
||
e != NULL;
|
||
e = _mask->get_key_field(k, FALSE))
|
||
{
|
||
if (e->required() && e->shown())
|
||
{
|
||
onereq = TRUE;
|
||
if (e->empty())
|
||
{
|
||
if (err)
|
||
{
|
||
TString msg(80);
|
||
msg = TR("Manca un valore indispensabile per la ricerca.");
|
||
#ifdef DBG
|
||
msg << "\nChiave " << int(k) << " - Campo " << e->dlg();
|
||
const TFieldref* fr = e->field();
|
||
if (fr != NULL)
|
||
{
|
||
msg << " - " << fr->name();
|
||
if (fr->to() > 0)
|
||
msg << '[' << fr->from() << ',' << fr->to() << ']';
|
||
}
|
||
#endif
|
||
error_box(msg);
|
||
_mask->first_focus(-e->dlg());
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
else
|
||
/* if (k == 1 && !onereq && !onefill && c.get().not_empty()) */
|
||
if (!onereq && !onefill && e->is_edit() && !e->empty())
|
||
onefill = TRUE;
|
||
}
|
||
if (k == 1 && !onereq && !onefill)
|
||
{
|
||
if (err)
|
||
error_box(TR("Manca un valore indispensabile per la ricerca"));
|
||
return FALSE;
|
||
}
|
||
return onefill || onereq;
|
||
}
|
||
|
||
bool TRelation_application::find(word k)
|
||
{
|
||
if (k == 0)
|
||
{
|
||
for (k = 1; k <= MAX_KEYS && !test_key(k, FALSE); k++);
|
||
if (k > MAX_KEYS)
|
||
return test_key(1, TRUE);
|
||
}
|
||
|
||
file().setkey(k);
|
||
file().zero();
|
||
for (TEditable_field* e = _mask->get_key_field(k, TRUE); e; e = _mask->get_key_field(k, FALSE))
|
||
{
|
||
if (e->shown()) // Ignora campi invisibili
|
||
e->autosave(*get_relation());
|
||
}
|
||
|
||
const int err = file().read(_isequal);
|
||
return err == NOERR;
|
||
}
|
||
|
||
|
||
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 bool cont = !dirty || yesno_box(TR("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 last = _mask->last_key();
|
||
const bool annulla = last == K_ESC || last == K_QUIT || last == K_F9;
|
||
const bool errore = dirty && _mask->field(dirty).dirty() > 1;
|
||
|
||
KEY k;
|
||
if (errore)
|
||
{
|
||
if (annulla)
|
||
{
|
||
TString w;
|
||
TMask_field& df = _mask->field(dirty);
|
||
if (df.is_edit())
|
||
w = ((TEdit_field&)df).get_warning();
|
||
if (w.blank())
|
||
{
|
||
w = df.prompt();
|
||
if (!w.blank())
|
||
{
|
||
w.trim();
|
||
w << ' ' << TR("inconsistente.");
|
||
}
|
||
}
|
||
if (w.blank())
|
||
w = TR("Campo inconsistente.");
|
||
w << '\n';
|
||
switch (last)
|
||
{
|
||
case K_ESC:
|
||
w << TR("Si desidera annullare?"); break;
|
||
case K_QUIT:
|
||
w << TR("Si desidera uscire?"); break;
|
||
default:
|
||
w << TR("Si desidera continuare?"); break;
|
||
}
|
||
k = yesno_box(w) ? K_NO : K_ESC;
|
||
if (k == K_ESC)
|
||
_mask->first_focus(-dirty);
|
||
}
|
||
else k = K_ESC;
|
||
}
|
||
else
|
||
k = yesnocancel_box("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(TR("Elemento non eliminabile"));
|
||
|
||
if (_curr_transaction == TRANSACTION_DELETE || yesno_box(TR("Confermare l'eliminazione")))
|
||
{
|
||
r.restore_status();
|
||
const bool ok = remove();
|
||
if (ok || is_transaction())
|
||
set_limits();
|
||
else
|
||
{
|
||
const int err = r.status();
|
||
if (err != NOERR) // Succede nei remove con richiesta di conferma all'utente
|
||
return error_box(FR("Errore di cancellazione %d"), err);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
bool TRelation_application::protected_record(TRelation &r)
|
||
{
|
||
if (user_can_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(TR("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)
|
||
{
|
||
if (find(1))
|
||
{
|
||
if (_curr_transaction == TRANSACTION_INSERT)
|
||
_curr_transaction = TRANSACTION_MODIFY;
|
||
modify_mode();
|
||
}
|
||
else
|
||
{
|
||
if (_curr_transaction == TRANSACTION_MODIFY)
|
||
_curr_transaction = TRANSACTION_INSERT;
|
||
insert_mode();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (find(0))
|
||
modify_mode();
|
||
else
|
||
insert_mode();
|
||
}
|
||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||
_mask->send_key(K_CTRL+'R', 0);
|
||
break;
|
||
case K_SAVE:
|
||
if (save(FALSE))
|
||
{
|
||
if (_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)
|
||
{
|
||
|
||
if (is_transaction())
|
||
_curr_transaction=TRANSACTION_MODIFY;
|
||
else
|
||
warning_box(TR("Elemento gia' presente"));
|
||
modify_mode();
|
||
|
||
}
|
||
else
|
||
insert_mode();
|
||
}
|
||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||
_mask->send_key(K_CTRL+'R', 0);
|
||
break;
|
||
case K_DEL:
|
||
if (_mask->query_mode())
|
||
{
|
||
delete_mode();
|
||
}
|
||
else
|
||
{
|
||
if (relation_remove())
|
||
{
|
||
query_mode();
|
||
if (_autoins_caller.not_empty() || is_transaction())
|
||
{
|
||
if (_lnflag) _recins = 0;
|
||
k = K_QUIT;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case K_F9:
|
||
if (_mask->query_mode() || save(TRUE))
|
||
search_mode();
|
||
break;
|
||
default:
|
||
if (save(TRUE))
|
||
{
|
||
setkey();
|
||
int err = ~NOERR;
|
||
switch (k)
|
||
{
|
||
case K_HOME:
|
||
err = file().readat(_first, _testandlock);
|
||
break;
|
||
case K_NEXT:
|
||
err = file().reread();
|
||
if (has_filtered_cursor())
|
||
{
|
||
TCursor& cur = get_filtered_cursor();
|
||
cur.curr() = file().curr();
|
||
cur.read();
|
||
++cur;
|
||
file().curr() = cur.curr();
|
||
err = get_relation()->read(_isequal, _testandlock);
|
||
}
|
||
else
|
||
err = file().next(_testandlock);
|
||
break;
|
||
case K_PREV:
|
||
file().reread();
|
||
if (has_filtered_cursor())
|
||
{
|
||
TCursor& cur = get_filtered_cursor();
|
||
cur.curr() = file().curr();
|
||
cur.read();
|
||
--cur;
|
||
file().curr() = cur.curr();
|
||
err = get_relation()->read(_isequal, _testandlock);
|
||
}
|
||
else
|
||
err = file().prev(_testandlock);
|
||
break;
|
||
case K_END:
|
||
err = file().readat(_last, _testandlock);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (err == NOERR || err == _islocked)
|
||
{
|
||
_navigating = true;
|
||
modify_mode();
|
||
_navigating = false;
|
||
}
|
||
else
|
||
query_mode();
|
||
}
|
||
break;
|
||
}
|
||
} while (k != K_QUIT);
|
||
|
||
if (_mask->is_open())
|
||
_mask->close_modal();
|
||
|
||
_mask->set_mode(NO_MODE);
|
||
|
||
if (autoins_caller().not_empty() && _recins >= 0)
|
||
{
|
||
NFCHECK("Obsolete LINK message calling convention");
|
||
TString16 num;
|
||
num.format("%ld", _recins);
|
||
TMessage msg(autoins_caller(), _lnflag ? MSG_LN : MSG_AI, num);
|
||
msg.send();
|
||
}
|
||
|
||
if (is_transaction())
|
||
{
|
||
TConfig ini(_trans_ini.row(_trans_counter), "Transaction");
|
||
ini.set("Record", _recins);
|
||
if (_recins >= 0)
|
||
{
|
||
ini.set("Result", "OK");
|
||
ini.set("Error", "0");
|
||
edit_mask2ini();
|
||
}
|
||
else
|
||
{
|
||
const int err = get_relation()->status();
|
||
ini.set("Result", err == NOERR ? "CANCEL" : "ERROR");
|
||
ini.set("Error", err);
|
||
}
|
||
|
||
}
|
||
_trans_counter++;
|
||
} while ( _trans_counter < _ntransactions);
|
||
}
|
||
|
||
bool TRelation_application::filter()
|
||
{
|
||
if (parse_command_line())
|
||
return TRUE;
|
||
|
||
TMailbox mail;
|
||
TMessage* msg = mail.next_s(MSG_FS);
|
||
|
||
if (msg)
|
||
{
|
||
_mask = get_mask(MODE_MOD);
|
||
TToken_string body(msg->body());
|
||
|
||
short id = body.get_int();
|
||
while (id > 0)
|
||
{
|
||
_search_id = id;
|
||
TEdit_field& f = (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())
|
||
{
|
||
TString8 n; n.format("%d", get_relation()->lfile().num());
|
||
TConfig ini(_trans_ini.row(_trans_counter), n);
|
||
ini2mask(ini, *_mask, TRUE);
|
||
}
|
||
}
|
||
|
||
void TRelation_application::ini2insert_mask()
|
||
{
|
||
if (is_transaction())
|
||
{
|
||
TString8 n; n.format("%d", get_relation()->lfile().num());
|
||
TConfig ini(_trans_ini.row(_trans_counter), n);
|
||
ini2mask(ini, *_mask, FALSE);
|
||
}
|
||
}
|
||
|
||
void TRelation_application::ini2mask(TConfig& ini, TMask& m, bool query)
|
||
{
|
||
const TString16 defpar = ini.get_paragraph();
|
||
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())
|
||
{
|
||
TString8 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
|
||
{
|
||
if (campo.class_id() == CLASS_DATE_FIELD && campo.right_justified())
|
||
{
|
||
const TDate d = campo.get();
|
||
fr->write(ini, defpar, d.string(ANSI));
|
||
}
|
||
else
|
||
fr->write(ini, defpar, campo.get());
|
||
}
|
||
}
|
||
else
|
||
if (campo.is_sheet())
|
||
{
|
||
TSheet_field &sheet=(TSheet_field &)campo;
|
||
sheet2ini(sheet,ini); // It's virtual
|
||
}
|
||
}
|
||
}
|
||
ini.set_paragraph(defpar); // Reimposta paragrafo standard
|
||
}
|
||
|
||
bool TRelation_application::mask2mail(const TMask& m)
|
||
{
|
||
TWait_cursor hourglass;
|
||
bool ok = _curr_trans_from.empty() && ::can_dispatch_transaction(get_relation()->curr());
|
||
if (ok)
|
||
{
|
||
TFilename ininame; ininame.temp();
|
||
if (ok) // Test qualunque per usare {}
|
||
{
|
||
TConfig ini(ininame, "Transaction");
|
||
const char* action = "";
|
||
char mode[2] = { TM_AUTOMATIC, '\0' };
|
||
switch (m.mode())
|
||
{
|
||
case NO_MODE:
|
||
action = TRANSACTION_DELETE;
|
||
break;
|
||
case MODE_MOD:
|
||
action = TRANSACTION_MODIFY;
|
||
break;
|
||
default:
|
||
action = TRANSACTION_INSERT;
|
||
break;
|
||
}
|
||
ini.set("Action", action);
|
||
ini.set("Mode", mode);
|
||
mask2ini(m, ini);
|
||
}
|
||
ok = ::dispatch_transaction(get_relation()->curr(), ininame);
|
||
::remove(ininame);
|
||
}
|
||
return ok;
|
||
}
|