campo-sirio/include/brwbut.cpp
guy e9a34d143f Migliorata gestione sheet ricerca
git-svn-id: svn://10.65.10.50/branches/R_10_00@23179 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016-02-25 11:34:01 +00:00

1984 lines
46 KiB
C++
Raw Blame History

#include <dongle.h>
#include <execp.h>
#include <msksheet.h>
#include <recarray.h>
#include <recset.h>
#include <relapp.h>
#include <sheet.h>
#include <urldefid.h>
#include <utility.h>
#include "../mg/anamag.h"
///////////////////////////////////////////////////////////
// TBrowse_button
///////////////////////////////////////////////////////////
TBrowse_button::TBrowse_button(TEdit_field* f)
: _fld(f)
{ }
TBrowse_button::~TBrowse_button()
{
}
// Certified 100%
TEditable_field& TBrowse_button::field(short id) const
{
if (id > 0)
{
TMask_field& f = _fld->mask().field(id);
CHECKD(f.is_editable(), "Can't use in a browse the field ", id);
return (TEditable_field&)f;
}
return *_fld;
}
///////////////////////////////////////////////////////////
// TList_sheet
///////////////////////////////////////////////////////////
// Certified 100%
TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
: TBrowse_button(f), _row(-1), _caption(caption), _head(head)
{ }
// Certified 100%
TList_sheet::~TList_sheet()
{ }
// Certified 100%
void TList_sheet::parse_input(TScanner& scanner)
{
_inp_id.add(scanner.pop());
}
// Certified 100%
void TList_sheet::parse_item(TScanner& scanner)
{
_data.add(new TToken_string(scanner.string()));
}
// Certified 100%
void TList_sheet::parse_output(TScanner& scanner)
{
_out_id.add(scanner.pop());
}
// il numero di riga selezionata
int TList_sheet::do_input()
{
if (_inp_id.empty_items())
return -2; // List empty!
_inp_id.restart();
TToken_string rowsel(80);
for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
{
if (*fld == '"')
{
rowsel.add(fld+1);
if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1);
}
else
{
const short id = field().atodlg(fld);
if (id > 0)
{
const TMask_field& f = field(id);
if (f.class_id() == CLASS_ZOOM_FIELD)
{
const TZoom_field& z = (TZoom_field&)f;
rowsel.add(z.get_first_line());
}
else
rowsel.add(f.get());
}
else rowsel.add("");
}
}
TString fd, it;
for (int i = 0 ; i < _data.items(); i++)
{
TToken_string& ts =_data.row(i);
ts.restart();
const char * item;
for (item = rowsel.get(0); item ; item = rowsel.get())
{
it = item; it.trim();
fd = ts.get(); fd.trim();
if (fd != it) break;
}
if (!item) return i;
}
return -1; // Value not found!
}
// Certified 50%
void TList_sheet::do_output(CheckTime t)
{
if (_row < 0 || t == FINAL_CHECK)
return;
_out_id.restart();
TToken_string& rowsel = _data.row(_row);
rowsel.restart();
for (const char* fld = _out_id.get(); fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(id);
const char* val = rowsel.get();
if (t != STARTING_CHECK || f.field() == NULL)
{
const bool hit = f.get() != val;
f.set(val);
if (hit && field().dlg() != id)
{
f.on_hit();
if (t == RUNNING_CHECK)
f.check();
}
}
}
}
// Certified 100%
KEY TList_sheet::run()
{
TArray_sheet sci(3, 3, -3, -3, _caption, _head);
sci.rows_array() = _data;
_row = do_input();
sci.select(_row);
const KEY k = sci.run();
switch (k)
{
case K_ENTER:
_row = (int)sci.selected();
do_output();
break;
default:
break;
}
return k;
}
// Certified 100%
bool TList_sheet::check(CheckTime t)
{
_row = do_input();
bool passed = _row != -1;
if (passed)
do_output(t);
else
{
switch(field().check_type())
{
case CHECK_SEARCH: passed = true; break;
default: break;
}
}
return passed;
}
///////////////////////////////////////////////////////////
// TBrowse
///////////////////////////////////////////////////////////
// Certified 100%
TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter, const char* orderby)
: TBrowse_button(f),
_relation(r), _filter(filter), _secondary(false), _alt_browse(NULL),
_custom_filter_handler(NULL)
{
if (*orderby && *orderby)
_cursor = new TSorted_cursor(r, orderby, "", key);
else
_cursor = new TCursor (r, "", key);
custom_cursor();
}
// Certified 100%
TBrowse::TBrowse(TEdit_field* f, TCursor* c)
: TBrowse_button(f),
_relation(NULL), _cursor(c), _secondary(false), _alt_browse(NULL),
_custom_filter_handler(NULL)
{
custom_cursor();
}
// Certified 100%
TBrowse::~TBrowse()
{
// Se e' stato usato il primo costruttore devo distruggere la relazione ed il cursore
if (_relation)
{
delete _cursor;
delete _relation;
}
if (_alt_browse)
delete _alt_browse;
}
static bool descr_filter_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TString expr;
if (!f.get().empty()) // Filtro attivato!
{
const short id = f.dlg()-500;
TString e = f.mask().get(id); // Espressione regolare
e.strip("\"'"); // Tolgo caratteri che potrebbero dare problemi
if (!e.blank())
expr << "(DESCR+DESCRAGG)" << "?=\"" << e << '"';
if (expr.empty())
f.reset();
}
((TBrowse_sheet&) f.mask()).add_custom_filter(expr);
}
return true;
}
void TBrowse::custom_cursor()
{
TRelation* relation = _relation ? _relation : _cursor->relation();
const int logicnum = relation->lfile().num();
switch(logicnum)
{
case LF_ANAMAG :
if (_cursor->key() == 2 && ini_get_bool(CONFIG_DITTA, "Main", "CUSTOM_SEARCH_" TOSTRING(LF_ANAMAG), false, 2))
{
delete _cursor;
_cursor = new TSorted_cursor(relation, ANAMAG_DESCR "|" ANAMAG_DESCRAGG "[1,50]", "", 2);
set_custom_filter_handler(descr_filter_handler);
}
break;
default:
break;
}
}
void TBrowse::custom_display()
{
switch(_cursor->file().num())
{
case LF_ANAMAG:
if (_cursor->key() == 2 && ini_get_bool(CONFIG_DITTA, "Main", "CUSTOM_SEARCH_" TOSTRING(LF_ANAMAG), false, 2))
{
TToken_string & it = (TToken_string &) items();
if (it.find(ANAMAG_DESCRAGG) < 0)
{
const char * s = it.get(0);
for (int i = 0; s && *s; s = it.get(++i))
if (strcmp(s, ANAMAG_DESCR) == 0)
{
add_display_field(HR("Descrizione aggiuntiva@50"), ANAMAG_DESCRAGG, i + 1);
break;
}
}
}
break;
case LF_TABMOD:
{
_cursor->file().zero(); // Azzera il record corrente in modo da impostare "MOD"
const TString& mod =_cursor->curr().get("MOD");
const word cod = dongle().module_name2code(mod);
field().set_module(cod);
}
break;
default:
break;
}
}
// Certified 100%
void TBrowse::parse_display(TScanner& scanner)
{
const char* s = scanner.string();
_head.add(dictionary_translate_header(s));
s = scanner.line();
_items.add(s);
}
void TBrowse::parse_input(TScanner& scanner)
{
const char* s = scanner.pop();
_inp_fn.add(s);
s = scanner.pop();
if (*s == '"') // Constant string
{
scanner.push();
TString& str = scanner.line();
_inp_id.add(str);
}
else // Field on the mask
{
CHECKS(_inp_id.get_pos(s) < 0, "Duplicate input field ", s);
_inp_id.add(s);
if (scanner.popkey() == "SE")
_inp_id << '@'; // Special FILTERing field
else
scanner.push();
}
}
void TBrowse::parse_output(TScanner& scanner)
{
const char* s = scanner.pop();
#ifdef DBG
field().atodlg(s);
#endif
_out_id.add(s);
s = scanner.pop();
_out_fn.add(s);
_secondary = false;
}
bool TBrowse::parse_copy(const TString& what, const TBrowse& b)
{
const bool all = what.starts_with("AL");
if (all || what == "US")
{
set_insert(b.get_insert());
_filter = b.get_filter();
if (!field().has_warning() && b.field().has_warning())
field().set_warning(b.field().get_warning());
if (!all) return true;
}
if (all || what == "IN")
{
_inp_id = b._inp_id;
_inp_fn = b._inp_fn;
if (!all) return true;
}
if (all || what == "DI")
{
_head = b._head;
_items = b._items;
if (!all) return true;
}
if (all || what == "OU")
{
_out_id = b._out_id;
_out_fn = b._out_fn;
_secondary = b.field().has_check();
}
return true;
}
void TBrowse::replace_cursor(TCursor* c)
{
if (_relation != NULL)
{
CHECK(c->file().num() == _cursor->file().num(), "Replacing incompatible cursor");
delete _relation;
_relation = NULL; // Not owned cursor!
delete _cursor;
}
_cursor = c;
}
void TBrowse::parse_join(TScanner& scanner)
{
TString80 j(scanner.pop()); // File or table
CHECKS(_relation, "Can't join to NULL relation ", (const char*)j);
int to;
if (scanner.popkey() == "TO") // TO keyword
{
const char* t = scanner.pop();
to = name2log(t);
}
else
{
to = 0; // _relation->lfile()->num();
scanner.push();
}
int key = 1;
if (scanner.popkey() == "KE")
key = scanner.integer();
else
scanner.push();
int alias = 0;
if (scanner.popkey() == "AL")
alias = scanner.integer();
else
scanner.push();
TToken_string exp(80);
if (scanner.pop() == "INTO")
{
const char* r = scanner.pop();
while (strchr(r, '=') != NULL)
{
exp.add(r);
r = scanner.pop();
}
}
scanner.push();
#ifdef DBG
if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
#endif
if (isdigit(j[0]))
_relation->add(atoi(j), exp, key, to, alias); // join file
else
{
#ifdef DBG
if (j[0] != '&' && j.len() > 4)
yesnofatal_box("'%s' non <20> una tabella valida: %d", (const char*)j);
#endif
_relation->add(j, exp, key, to, alias); // join table
}
}
void TBrowse::parse_insert(TScanner& scanner)
{
const TString& key = scanner.popkey();
_insert.cut(0);
if (key != "NO")
{
_insert << key[0] << scanner.line();
_insert.trim();
}
}
// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro
int TBrowse::input_fields()
{
int inp = 0;
FOR_EACH_TOKEN(_inp_id, fld)
{
if (*fld && *fld != '"' && strchr(fld, '@') == NULL)
{
TMask_field& f = field(field().atodlg(fld));
if (f.active() && f.is_editable())
inp++;
}
}
return inp;
}
const char* TBrowse::get_input_fields() const
{
return _inp_id;
}
const char* TBrowse::get_input_field_names() const
{
return _inp_fn;
}
void TBrowse::add_input_field(const char * id, const char * name, const int pos, bool select)
{
TString strid(id) ;
if (select)
strid << '@';
if (pos < 0 || pos >= _items.items())
{
_inp_id.add(strid);
_inp_fn.add(name);
}
else
{
_inp_id.insert_at(strid, pos);
_inp_fn.insert_at(name, pos);
}
}
void TBrowse::remove_display_field(const int pos)
{
if (pos < 0)
{
_head.cut(0);
_items.cut(0);
}
else
{
_head.destroy(pos);
_items.destroy(pos);
}
}
void TBrowse::copy_input(const TBrowse * b)
{
if (b)
{
_inp_id = b->_inp_id;
_inp_fn = b->_inp_fn;
}
}
void TBrowse::copy_display(const TBrowse* b)
{
if (b)
b->get_display_fields(_head, _items);
}
void TBrowse::copy_output(const TBrowse * b)
{
if (b)
{
_out_id = b->_out_id;
_out_fn = b->_out_fn;
}
}
void TBrowse::add_display_field(const char * hd, const char * name, const int pos)
{
if (pos < 0 || pos >= _items.items())
{
_head.add(dictionary_translate_header(hd));
_items.add(name);
}
else
{
_head.insert_at(dictionary_translate_header(hd), pos);
_items.insert_at(name, pos);
}
}
void TBrowse::remove_input_field(const int pos)
{
if (pos < 0)
{
_inp_id.cut(0);
_inp_fn.cut(0);
}
else
{
_inp_id.destroy(pos);
_inp_fn.destroy(pos);
}
}
void TBrowse::add_output_field(const char * id, const char * name, const int pos)
{
if (pos < 0 || pos >= _items.items())
{
_out_id.add(id);
_out_fn.add(name);
}
else
{
_out_id.insert_at(id, pos);
_out_fn.insert_at(name, pos);
}
}
void TBrowse::remove_output_field(const int pos)
{
if (pos < 0)
{
_out_id.cut(0);
_out_fn.cut(0);
}
else
{
_out_id.destroy(pos);
_out_fn.destroy(pos);
}
}
const char* TBrowse::get_output_fields() const
{
return _out_id;
}
const char* TBrowse::get_output_field_names() const
{
return _out_fn;
}
// @doc INTERNAL
// @mfunc Ritorna il numero di campi non vuoti e non filtrati
//
// @rdesc Numero di campi non vuoti e non filtrati
int TBrowse::do_input(
bool filter) // @parm Indica se effettuare il filtro sulla selezione
// @comm Questa funzione serve ai <c TCursor_sheet>
{
int ne = 0;
if (_inp_id.empty())
return ne;
_cursor->file(0).zero(); // was cur.zero() che non va bene per le tabelle di modulo
TRectype& cur = _cursor->curr();
TRectype filtrec(cur);
_inp_id.restart();
_inp_fn.restart();
TString val; // Value to output
bool tofilter = false;
for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
{
const TFieldref fldref(_inp_fn.get(), 0); // Output field
if (*fld == '"')
{
val = (fld+1);
if (val.not_empty()) val.rtrim(1);
tofilter = filter;
}
else
{
const TMask_field* campf = NULL;
if (*fld == '-')
{
TSheet_field* sheet = field().mask().get_sheet();
if (sheet != NULL)
{
const short id = atoi(fld+1);
campf = &sheet->mask().field(id);
}
}
else
{
const short id = field().atodlg(fld);
campf = &field(id);
}
if (campf != NULL)
{
const TMask_field& f = *campf;
val = f.get();
switch (f.class_id())
{
case CLASS_REAL_FIELD:
// Cerco di allineare correttamente i campi interi salvati parzialmente su codtab
if (fldref.to() > 1 && f.size() > 1 && val.full() &&
((TReal_field&)f).decimals() == 0 && fldref.name() == "CODTAB")
{
const int len = fldref.len(cur);
if (f.size() == len && val.len() < len)
val.right_just(len);
}
break;
case CLASS_DATE_FIELD:
if (f.right_justified())
{
const TDate d(val);
val = d.string(ANSI);
}
break;
default:
break;
}
const bool filter_flag = strchr(fld, '@') != NULL;
tofilter = filter && filter_flag;
if (f.is_edit() && val.not_empty() && !filter_flag)
ne++; // Increment not empty fields count
}
}
fldref.write(val, *_cursor->relation());
if (tofilter)
{
const int len = fldref.len(cur);
if (val.len() < len && cur.type(fldref.name()) == _alfafld)
val.rpad(len, '~');
fldref.write(val, filtrec);
}
}
if (!filter)
return ne;
TString work(_filter.size());
bool filter_update = false;
for (int i = 0; _filter[i]; i++)
{
if (_filter[i] == '"')
{
do
{
work << _filter[i++];
} while (_filter[i] && _filter[i] != '"');
work << '"';
if (!_filter[i]) break;
}
else
if (_filter[i] == '#')
{
if (_filter[++i] == '-')
{
TString val;
TSheet_field* sheet = field().mask().get_sheet();
if (sheet != NULL)
{
const short id = atoi(&_filter[++i]);
val = sheet->mask().field(id).get();
}
work << '"' << val << '"';
}
else
work << '"' << field(atoi(&_filter[i])).get() << '"';
while (isspace(_filter[i])) i++;
while (isdigit(_filter[i])) i++;
i--;
}
else
{
work << _filter[i];
if (_filter[i] == '-' && _filter[i + 1] == '>')
filter_update = true;
}
}
_cursor->relation()->mask2rel(field().mask());
if (!_cursor->frozen())
{
_cursor->setfilter(work, filter_update);
_cursor->setregion(filtrec, filtrec);
}
return ne;
}
static TBit_array s_checked;
static short s_checking = 0;
void TBrowse::do_output(CheckTime t)
{
if (t == FINAL_CHECK)
return;
const bool master = s_checking == 0;
if (master)
{
s_checking = field().dlg();
s_checked.reset();
// Rendo intoccabili i campi del MIO output
for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
s_checked.set(id);
}
}
TString sum;
TToken_string flds(24, '+');
const TRelation& relation = *_cursor->relation();
TBit_array spotted;
_out_fn.restart();
const char* fld;
for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(id);
flds = _out_fn.get();
bool do_that = t != STARTING_CHECK || f.field() == NULL || (f.mask().mode() == MODE_INS && !f.in_key(0));
if (do_that && main_app().class_id() == CLASS_RELATION_APPLICATION)
{
// Considera a parte l'inizializzazione delle transazioni!
// Non sovrascrivere con degli output campi che potrebbero essere riempiti dal .ini
if (!f.empty() && f.field() != NULL)
{
const TMask& m = f.mask();
if (!m.is_running() && m.get_sheet() == NULL) // Maschera principale chiusa
{
const TRelation_application& ra = (const TRelation_application&)main_app();
if (ra.is_transaction())
do_that = false;
}
}
}
if (do_that)
{
sum.cut(0);
for(const char* fr = flds.get(0); fr; fr = flds.get())
{
if (*fr == '"')
{
sum << (fr+1);
sum.rtrim(1);
}
else
{
const TFieldref fld(fr, 0);
sum << fld.read(relation);
}
}
bool hit = false;
if (master)
{
f.set(sum);
hit = id != s_checking; // Il mio handler viene fatto nella on_key
}
else
{
if (!s_checked[id])
{
f.set(sum);
s_checked.set(id);
hit = true;
}
}
spotted.set(id, hit);
}
}
for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
if (spotted[id])
{
TMask_field& f = field(id);
f.check();
f.on_hit();
}
}
if (master)
s_checking = 0;
}
void TBrowse::do_clear(CheckTime t)
{
const bool master = s_checking == 0;
if (master)
{
s_checking = field().dlg();
s_checked.reset();
// Rendo intoccabili i campi del MIO input
for (const char* fld = _inp_id.get(0); fld && *fld; fld = _inp_id.get())
{
if (isdigit(*fld))
{
const short id = field().atodlg(fld);
s_checked.set(id);
}
}
}
for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(atoi(fld));
if (f.field() == NULL && field().dlg() != id &&
!s_checked[id] && _inp_id.get_pos(fld) < 0)
{
f.reset();
s_checked.set(id);
f.on_hit();
f.check(t);
}
}
if (master)
s_checking = 0;
}
bool TBrowse::do_link(bool insert)
{
bool ok = false;
TString app;
if (_insert.starts_with("MTB", true))
_cursor->file().get_relapp(app);
else
app = _insert.mid(1);
if (app.find('#') >= 0)
{
const TString w(app);
app = "";
for (const char* f = w; *f; f++)
{
if (*f == '#')
{
app << field().evaluate_field(f);
while (isspace(*f)) ++f;
while (isdigit(*f)) ++f;
if (*f)
app << ' ' << *f;
else
break;
}
else
app << *f;
}
}
TFilename msg; msg.temp("msg", "ini");
app << " /i" << msg;
{
bool set_link = true;
TConfig ini(msg, "Transaction");
if (insert)
{
ini.set("Action", TRANSACTION_RUN);
set_link = field().empty() && do_input(false) > 0;
}
else
ini.set("Action", TRANSACTION_LINK);
if (set_link)
{
TString8 paragraph; paragraph << _cursor->file().num();
ini.set_paragraph(paragraph);
// Uso sempre la chiave 1 per collegarmi agli altri programmi
const TRelation& rel = *_cursor->relation();
const RecDes& recd = rel.curr().rec_des(); // Descrizione del record della testata
const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1
TString inp_val;
for (int i = 0; i < kd.NkFields; i++)
{
const int nf = kd.FieldSeq[i] % MaxFields;
const RecFieldDes& rf = recd.Fd[nf];
const TFieldref fldref(rf.Name, 0);
inp_val = fldref.read(rel);
fldref.write(ini, paragraph, inp_val);
}
}
}
TExternal_app a(app);
a.run();
field().mask().set_focus();
if (msg.not_empty())
{
TConfig ini(msg, "Transaction");
_rec = ini.get_long("Record");
if (_rec > 0 || !insert) // Modifica o cancellazione
_cursor->update(); // Forza ricalcolo cursore
if (_rec >= 0)
{
_cursor->file().readat(_rec);
ok = _cursor->ok();
if (ok)
{
rec_cache(_cursor->file().num()).notify_change(); // Svuota eventule cache
do_output();
}
}
msg.fremove();
}
return ok;
}
TToken_string& TBrowse::create_siblings(TToken_string& siblings) const
{
siblings = ""; // Azzera la lista dei campi associati
TBit_array key(4); // Elenco delle chiavi gia' utilizzate
key.set(_cursor->key());
TString fn; // Nome campo
// Scorre la lista dei campi di output
int n = 0;
TToken_string& outid = (TToken_string&)_out_id;
for (const char* i = outid.get(0); i; i = outid.get(), n++)
{
const short id = field().atodlg(i);
const TEditable_field& f = field(id);
if (!f.active() || !f.is_edit()) // Scarta i campi non editabili
continue;
const TEdit_field& e = (const TEdit_field&)f;
const TBrowse* b = e.browse();
if (b == NULL)
continue; // Scarta i campi senza ricerca
const TCursor* c = b->cursor();
// Considera ricerche sullo stesso file ma con chiave diversa
if (c->file().num() == _cursor->file().num() &&
(key[c->key()] == false || id == field().dlg()))
{
_out_fn.get(n, fn); // Legge nome del campo su file
int pos = ((TToken_string&)_items).get_pos(fn); // Determina header corrispondente
if (pos < 0) // Se non lo trova identico ...
{
const int q = fn.find('[');
if (q > 0)
{
fn.cut(q);
pos = ((TToken_string&)_items).get_pos(fn); // ... ritenta senza parentesi
}
}
if (pos >= 0)
{
siblings.add(id);
TString80 h; _head.get(pos, h);
siblings.add(h);
const int et = siblings.find('@');
if (et > 0) siblings.cut(et);
key.set(c->key()); // Marca la chiave come usata
}
}
}
return siblings;
}
KEY TBrowse::run()
{
TEdit_field& e = field();
const TString& val = e.get();
if (val.starts_with("*"))
{
TFuzzy_browse fb(&e, cursor()->key());
const KEY k = fb.run();
if (k == K_ENTER)
{
do_input(true);
_cursor->read(_isgteq);
do_output();
}
return k;
} else
if (val.starts_with("%") && _alt_browse)
{
const KEY k = _alt_browse->run();
if (k == K_ENTER)
{
do_input(true);
_cursor->read(_isgteq);
do_output();
}
return k;
}
xvt_scr_set_busy_cursor();
do_input(true);
_cursor->read(_isgteq);
TString caption = _cursor->file().description();
if (caption.blank())
caption = TR("Selezione");
KEY k = K_ESC;
long selected = 0;
TToken_string siblings, vals;
create_siblings(siblings);
{
byte buttons = 0;
if (_insert.not_empty())
{
// Mette il bottone di gestione, a meno che ...
if (_cursor->items() == 0)
buttons = 2; // Non mette il bottone collega se non ci sono elementi
else
buttons = 3;
if (_insert[0] == 'M' || _insert[0] == 'R')
{
const TString& maskname = e.mask().source_file();
if (maskname.mid(2,2).compare("tb", 2, true) == 0 && e.in_key(0))
{
const char* tabname = _cursor->file().name();
if (maskname.mid(4, 3).compare(tabname, 3, true) == 0)
buttons = 0;
}
}
}
for (const char* i = _inp_id.get(0); i; i = _inp_id.get())
{
if (*i != '\0' && *i != '"' && strchr(i, '@') == NULL)
{
const short id = e.atodlg(i);
const TEditable_field& f = field(id);
if (f.active() && f.is_editable())
{
vals.add(i);
vals.add(f.get());
vals.add((int)f.dirty());
}
}
}
xvt_scr_reset_busy_cursor();
TBrowse_sheet s(_cursor, _items, caption, _head, buttons, e, siblings, _custom_filter_handler);
k = s.run();
selected = s.selected();
}
switch (k)
{
case K_ESC:
case K_QUIT:
break;
case K_CTRL+'G':
*_cursor = selected;
k = do_link(false) ? K_ENTER : K_ESC;
break;
case K_INS:
k = do_link(true) ? K_ENTER : K_ESC;
break;
case K_ENTER:
*_cursor = selected;
do_output();
break;
default:
{
for (const char* i = vals.get(0); i && *i; i = vals.get())
{
const short id = field().atodlg(i);
TEditable_field& f = field(id);
f.set(vals.get());
f.set_dirty(vals.get_int());
}
}
if (k >= K_CTRL) // Scatta la ricerca su di una chiave alternativa
{
TMask& m = field().mask();
const int tag = k - K_CTRL - K_F1;
const short id = siblings.get_int(tag * 2);
TEdit_field& ef = m.efield(id);
ef.set_focus();
k = K_F9;
if (m.is_running())
m.send_key(k, id, &ef); //m.send_key(k, id);
}
break;
}
return k;
}
void TBrowse::set_cursor(TCursor* c)
{
if (_cursor != NULL)
delete _cursor;
_cursor = c ;
}
bool TBrowse::check(CheckTime t)
{
bool passed = true;
if (_secondary == true && t != RUNNING_CHECK)
return true;
CheckType chk = field().check_type();
// Se ho la ricerca alternativa ed il campo comincia per % ...
if (t == RUNNING_CHECK)
{
const TString& magic = field().get();
if (magic[0] == '*' && cursor()->key() > 1)
{
TFuzzy_browse fb(&field(), cursor()->key());
if (fb.check(t))
{
if (chk == CHECK_NONE) // Se trovo la chiave forzo gli output (RAGSOC in righe prima nota)
chk = CHECK_NORMAL;
}
else
return false;
} else
if (magic[0] =='%' && _alt_browse != NULL)
{
if (_alt_browse->check(t))
{
if (chk == CHECK_NONE) // Se trovo la chiave forzo gli output (RAGSOC in righe prima nota)
chk = CHECK_NORMAL;
}
else
return false;
}
}
if (chk != CHECK_NONE)
{
const TMaskmode mode = (TMaskmode)field().mask().mode();
if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY))
chk = CHECK_NORMAL;
const int ne = do_input(true);
if (ne || chk == CHECK_REQUIRED)
{
passed = _cursor->test() == NOERR;
if (t != FINAL_CHECK)
{
if (passed)
{
_cursor->repos();
do_output(t);
if (t == STARTING_CHECK && field().dirty() > 1)
field().set_dirty(true);
}
else
{
if (chk == CHECK_SEARCH)
{
passed = true;
}
else
{
do_clear(t);
if (!field().mask().query_mode() && field().check_enabled())
field().set_dirty(3);
}
}
}
else
{
if (chk == CHECK_SEARCH)
passed = true;
}
}
else
{
if (chk == CHECK_SEARCH)
passed = true;
else
{
if (t != FINAL_CHECK)
do_clear(t);
}
}
}
return passed;
}
bool TBrowse::empty_check()
{
if (field().mask().query_mode() || field().check_type() != CHECK_REQUIRED)
return true;
else
return do_input() > 0;
}
bool TBrowse::set_alt_browse(int altkey)
{
if (_alt_browse)
delete _alt_browse;
if (altkey > 2)
_alt_browse = new TAlternative_browse(&field(), altkey);
return altkey > 2;
}
///////////////////////////////////////////////////////////
// TFile_select
///////////////////////////////////////////////////////////
TFile_select::TFile_select(TEdit_field* ef, const char* filter)
: TBrowse_button(ef), _filter(filter)
{ }
void TFile_select::parse_input(TScanner& scanner)
{
scanner.pop();
}
void TFile_select::parse_output(TScanner& scanner)
{
scanner.pop();
}
KEY TFile_select::run()
{
TFilename path;
path = field().get();
if (path.full() && _filter.find('.') > 0 && !_filter.ends_with(".*"))
path.ext(_filter.ext());
FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(path, &fs);
bool good = xvt_dm_post_file_open(&fs, field().prompt()) == FL_OK;
if (good)
{
xvt_fsys_convert_fspec_to_str(&fs, path.get_buffer(), path.size());
good = _filter.blank() || xvt_str_match(path.name(), _filter, false);
if (good)
field().set(path);
else
field().error_box(FR("Il nome del file non corrisponde a %s"), _filter.get_buffer());
}
return good ? K_ENTER : K_ESC;
}
bool TFile_select::check(CheckTime ct)
{
const TFilename name = field().get();
if (ct != STARTING_CHECK && name.empty() &&
field().check_type() == CHECK_REQUIRED)
return false;
bool ok = _filter.empty() || xvt_str_match(name, _filter, false);
if (ok && field().roman()) // Must exist
ok = name.exist();
return ok;
}
///////////////////////////////////////////////////////////
// TDir_select
///////////////////////////////////////////////////////////
TDir_select::TDir_select(TEdit_field* ef) : TBrowse_button(ef)
{ }
void TDir_select::parse_input(TScanner& scanner)
{
scanner.pop();
}
void TDir_select::parse_output(TScanner& scanner)
{
scanner.pop();
}
KEY TDir_select::run()
{
DIRECTORY savedir;
xvt_fsys_get_dir(&savedir);
DIRECTORY dir;
xvt_fsys_convert_str_to_dir(field().get(), &dir);
bool good = xvt_dm_post_dir_sel(&dir) == FL_OK;
xvt_fsys_set_dir(&savedir);
if (good)
{
TFilename path;
xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size());
field().set(path);
}
return good ? K_ENTER : K_ESC;
}
bool TDir_select::check(CheckTime ct)
{
const TFilename name = field().get();
if (ct != STARTING_CHECK && name.empty() &&
field().check_type() == CHECK_REQUIRED)
return false;
bool ok = true;
if (field().roman()) // Must exist
ok = name.exist();
return ok;
}
///////////////////////////////////////////////////////////
// TProfile_select
///////////////////////////////////////////////////////////
TProfile_select::TProfile_select(TEdit_field* ef)
: TBrowse_button(ef)
{ }
void TProfile_select::parse_input(TScanner& scanner)
{
scanner.pop();
}
void TProfile_select::parse_output(TScanner& scanner)
{
scanner.pop();
}
HIDDEN int get_profile_desc(TConfig& cfg, void* jolly)
{
const int num = atoi(cfg.get_paragraph());
if (num > 0)
{
TString_array& p = *(TString_array*)jolly;
TToken_string* str = new TToken_string;
str->format("%4d", num);
str->add(cfg.get("Description"));
p.add(str);
}
return false;
}
int TProfile_select::get_descriptions(TString_array& a) const
{
TFilename profname;
field().mask().make_profile_name(profname);
TConfig prof(profname);
a.destroy();
prof.for_each_paragraph(get_profile_desc, &a);
a.sort();
return a.items();
}
KEY TProfile_select::run()
{
TArray_sheet p(3, 3, -3, -3, TR("Profili"), HR("Codice@6R|Descrizione@60"), 0x6, 2);
const short id = DLG_USER+1;
TEdit_field& prompt = p.add_string(id, 0, PR("Salva con nome "), 1, 0, 60);
p.add_button(DLG_SAVEREC, PR("~Registra"), K_CTRL+'r', TOOL_SAVEREC);
prompt.set(field().get());
TMask& m = field().mask();
TFilename profname; m.make_profile_name(profname);
bool running = true;
KEY key;
while (running)
{
p.destroy();
TString_array& a = p.rows_array();
get_descriptions(a);
p.field(DLG_SAVEREC).enable(a.items()>0);
FOR_EACH_ARRAY_ROW_BACK(a, r, row)
if (field().get() == row->get(1)) break;
if (r)
p.select(r);
key = p.run();
switch(key)
{
case K_ENTER:
{
const int num = p.row().get_int(0);
TString16 para; para << m.load_profile(num);
prompt.set(p.row().get(1));
running = false;
}
break;
case K_CTRL+'r':
{
const TString& name = p.get(id);
FOR_EACH_ARRAY_ROW_BACK(a, r, row)
if (r != p.selected() && name == row->get(1)) break;
if (r < 0)
{
const int num = p.row().get_int(0);
m.save_profile(num, name);
running = false;
}
else
error_box("Esiste gi<67> un profilo di nome\n%s",
(const char*)name);
}
break;
case K_INS:
{
const TString& name = p.get(id);
if (!name.blank())
{
FOR_EACH_ARRAY_ROW_BACK(a, r, row)
if (name == row->get(1)) break;
if (r < 0)
{
TString16 para; para << m.save_profile(-1, name);
field().set(name);
running = false;
}
else
error_box("Esiste gi<67> un profilo di nome\n%s",
(const char*)name);
}
else
error_box("E' necessario dare un nome al profilo");
}
break;
case K_DEL:
{
TString16 para; para << p.row().get_int(0);
const TString desc = p.row().get(1);
TConfig prof(profname, para);
if (yesno_box("Confermare la cancellazione del profilo %s\n%s",
(const char*)para, (const char*)desc))
prof.remove_all();
}
break;
default:
running = false;
break;
}
}
field().set(prompt.get());
return key;
}
bool TProfile_select::check(CheckTime ct)
{
switch (ct)
{
case STARTING_CHECK:
{
TMask& m = field().mask();
TFilename name; m.make_profile_name(name);
TString16 para; para << m.load_profile();
TConfig ini(name, para);
field().set(ini.get("Description"));
}
break;
case RUNNING_CHECK:
if (!field().empty())
{
const TString& name = field().get();
TString_array a;
get_descriptions(a);
FOR_EACH_ARRAY_ROW_BACK(a, r, row)
{
if (name == row->get(1))
{
field().mask().load_profile(row->get_int(0));
break;
}
}
if (r < 0)
return field().error_box("Profilo inesistente");
}
break;
case FINAL_CHECK:
if (!field().active())
{
TMask& m = field().mask();
m.save_profile();
}
break;
default:
break;
}
return true;
}
///////////////////////////////////////////////////////////
// TReport_select
///////////////////////////////////////////////////////////
TReport_select::TReport_select(TEdit_field* ef, const char* classe)
: TBrowse_button(ef), _classe(classe)
{ }
void TReport_select::parse_input(TScanner& scanner)
{
scanner.pop();
}
void TReport_select::parse_output(TScanner& scanner)
{
scanner.pop();
}
KEY TReport_select::run()
{
TFilename path = field().get();
if (select_custom_file(path, "rep", _classe))
{
path = path.name();
path.ext("");
field().set(path);
}
return path.not_empty() ? K_ENTER : K_ESC;
}
bool TReport_select::check(CheckTime ct)
{
TFilename name = field().get();
if (ct != STARTING_CHECK && name.empty() &&
field().check_type() == CHECK_REQUIRED)
return false;
bool ok = true;
if (field().roman()) // Must exist
ok = name.custom_path();
return ok;
}
///////////////////////////////////////////////////////////
// TFuzzy_browse
///////////////////////////////////////////////////////////
static TFuzzy_browse* _curr_fbrowse = NULL;
TCursor& TFuzzy_browse::cursor()
{
TBrowse& b = *field().browse();
TCursor& c = *b.cursor();
if (_altfld.empty())
{
const RecDes& rd = c.curr().rec_des();
CHECKD(_altkey > 0 && _altkey <= rd.NKeys, "Invalid browse key ", _altkey);
const KeyDes& kd = rd.Ky[_altkey-1];
const int mf = kd.FieldSeq[kd.NkFields-1] % MaxFields;
_altfld = rd.Fd[mf].Name;
_outfld = "RAGSOC";
TToken_string outfields = b.get_output_fields();
const int outpos = outfields.get_pos(field().dlg());
if (outpos >= 0)
{
outfields = b.get_output_field_names();
outfields.get(outpos, _outfld);
}
}
return c;
}
static void clean_string(TString& str)
{
char* d = str.get_buffer();
for (const char* s = d; *s; s++)
if (*s < '\0' || isalnum(*s)) *d++ = *s;
*d = '\0';
str.upper();
}
TRecnotype TFuzzy_browse::find_magic(const TString& magic_val, double& best)
{
const TBrowse& b = *field().browse();
TCursor& c = cursor();
c = 0L;
TRecnotype recno = -1;
TRectype& curr = c.curr();
curr.put(_altfld, magic_val);
recno = c.read();
if (recno >= 0 && curr.get(_altfld).starts_with(magic_val))
return recno;
recno = -1;
best = 0.66;
const int testlen = magic_val.len()+1;
if (testlen > 3)
{
for (c = 0L; c.ok(); ++c)
{
TString80 val = curr.get(_altfld);
clean_string(val);
for (int i = val.find(magic_val[0], 0); i >= 0; i = val.find(magic_val[0], i+1))
{
double n = xvt_str_fuzzy_compare(val.mid(i, testlen), magic_val);
n -= i*0.01;
if (n > best)
{
best = n;
recno = c.pos();
if (n >= 1.0)
break;
}
}
}
} else
if (testlen > 0)
{
for (c = 0L; c.ok(); ++c)
{
TString80 val = curr.get(_altfld);
clean_string(val);
const int i = val.find(magic_val);
if (i >= 0)
{
const double n = 1.0 - 0.01*i;
if (n > best)
{
best = n;
recno = c.pos();
if (n >= 1.0)
break;
}
}
}
}
if (recno >= 0)
c = recno;
else
best = 0;
return recno;
}
TRecnotype TFuzzy_browse::find(const TString& raw_val)
{
TString80 magic_val = raw_val;
clean_string(magic_val);
double best = 0;
TRecnotype recno = find_magic(magic_val, best);
if (best < 0.8 && raw_val.find(' ') > 0)
{
magic_val = raw_val;
magic_val.strip_double_spaces();
const int spc = magic_val.find(' ');
if (spc > 0)
{
const TString& left = magic_val.left(spc);
const TString& right = magic_val.mid(spc+1);
magic_val.cut(0) << right << ' ' << left;
clean_string(magic_val);
double altbest = 0;
const TRecnotype altrecno = find_magic(magic_val, altbest);
if (altbest > best)
{
best = altbest;
recno = altrecno;
}
}
}
return recno;
}
bool TFuzzy_browse::check(CheckTime /*t*/)
{
const TRecnotype recno = find(field().get());
if (recno >= 0)
{
field().set(cursor().curr().get(_outfld));
return true;
}
return run() == K_ENTER;
}
static bool fuzzy_code_handler(TMask_field& f, KEY k)
{
if (k == K_F2)
{
f.reset();
k = K_SPACE;
}
if (k == K_SPACE || k == K_TAB)
{
const TString& str = ((TEdit_field&)f).get_window_data();
const TRecnotype pos = _curr_fbrowse->find(str);
if (pos >= 0)
{
TSheet& s = (TSheet&)f.mask();
if (k == K_TAB)
{
f.set(s.row(pos).get(0));
s.post_select(pos);
}
else
s.select(pos);
}
}
return true;
}
KEY TFuzzy_browse::run()
{
const TBrowse& b = *field().browse();
TCursor& c = cursor();
TString caption = c.file().description();
if (caption.blank())
caption = TR("Selezione");
TToken_string fields, head;
b.get_display_fields(head, fields);
TCursor_sheet sheet(&c, fields, caption, head, 0, 2);
TEdit_field& e = sheet.add_string(field().dlg(), 0, field().prompt(), 1, 1, field().size(), "U");
e.set_handler(fuzzy_code_handler);
_curr_fbrowse = this;
TString80 val = field().get();
val.strip("*");
e.set(val);
e.on_key(K_SPACE);
sheet.first_focus(e.dlg());
const KEY k = sheet.run();
_curr_fbrowse = NULL;
if (k == K_ENTER)
{
c = sheet.selected();
const TFieldref fr(_outfld, 0);
field().set(fr.read(*c.relation()));
}
return k;
}
TFuzzy_browse::TFuzzy_browse(TEdit_field* ef, int altkey) : TBrowse_button(ef), _altkey(altkey)
{
}
///////////////////////////////////////////////////////////
// TAlternative_browse
///////////////////////////////////////////////////////////
static TBit_array _alternative_bits;
static bool alternative_filter(const TRelation* rel)
{
const TRecnotype recno = rel->file().recno();
return _alternative_bits[recno];
}
TCursor& TAlternative_browse::cursor()
{
if (_cursor == NULL)
{
TBrowse& b = *field().browse();
TCursor& c = *b.cursor();
const RecDes& rd = c.curr().rec_des();
const KeyDes& kd = rd.Ky[_altkey-1];
const int mf = kd.FieldSeq[kd.NkFields-1] % MaxFields;
_altfld = rd.Fd[mf].Name;
_outfld = "RAGSOC";
TToken_string outfields = b.get_output_fields();
const int outpos = outfields.get_pos(field().dlg());
if (outpos >= 0)
{
outfields = b.get_output_field_names();
outfields.get(outpos, _outfld);
}
_cursor = new TCursor(c.relation(), "", _altkey);
_alternative_bits.reset();
const TRecnotype old = c.pos();
for (c = 0L; c.ok(); ++c)
{
if (c.curr().get(_altfld).full())
_alternative_bits.set(c.file().recno());
}
_cursor->set_filterfunction(alternative_filter);
_cursor->items();
_cursor->freeze();
c = old;
}
return *_cursor;
}
static bool alternative_code_handler(TMask_field& f, KEY k)
{
if (k == K_F2)
{
f.reset();
k = K_SPACE;
}
if (k == K_SPACE || k == K_TAB)
{
const TString& str = ((TEdit_field&)f).get_window_data();
const TRecnotype pos = _curr_fbrowse->find(str);
if (pos >= 0)
{
TSheet& s = (TSheet&)f.mask();
if (k == K_TAB)
{
f.set(s.row(pos).get(0));
s.post_select(pos);
}
else
s.select(pos);
}
}
return true;
}
KEY TAlternative_browse::run()
{
const TBrowse& b = *field().browse();
TCursor& c = cursor();
TString caption = c.file().description();
if (caption.blank())
caption = TR("Selezione");
TToken_string fields, head;
b.get_display_fields(head, fields);
const int pos = fields.get_pos(_altfld);
const int sz = c.curr().length(_altfld);
if (pos > 0)
{
fields.destroy(pos);
fields.insert_at(_altfld, 0);
TString80 h; head.get(pos, h);
head.destroy(pos);
head.insert_at(h, 0);
}
else
{
fields.insert_at(_altfld, 0);
TString80 h; h << "Cod.Alt.@" << sz;
head.insert_at(h, 0);
}
TCursor_sheet sheet(&c, fields, caption, head, 0, 2);
TEdit_field& e = sheet.add_string(field().dlg(), 0, head.before('@'), 1, 1, sz, "U");
e.set_handler(alternative_code_handler);
_curr_fbrowse = this;
TString80 val = field().get();
val.strip("%");
e.set(val);
e.on_key(K_SPACE);
sheet.first_focus(e.dlg());
const KEY k = sheet.run();
_curr_fbrowse = NULL;
if (k == K_ENTER)
{
c = sheet.selected();
field().set(c.curr().get(_outfld));
}
return k;
}
TAlternative_browse::TAlternative_browse(TEdit_field* ef, int altkey) : TFuzzy_browse(ef, altkey), _cursor(NULL)
{ }
TAlternative_browse::~TAlternative_browse()
{
if (_cursor)
delete _cursor;
}