e9a34d143f
git-svn-id: svn://10.65.10.50/branches/R_10_00@23179 c028cbd2-c16b-5b4b-a496-9718f37d4682
1984 lines
46 KiB
C++
1984 lines
46 KiB
C++
#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;
|
||
}
|