From 8be91486970ee329f53a7f216d95fe334298ba10 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 29 Mar 1995 15:44:53 +0000 Subject: [PATCH] Corretto errore MI0159 git-svn-id: svn://10.65.10.50/trunk@1192 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/maskfld.cpp | 6380 +++++++++++++++++++++--------------------- include/validate.cpp | 16 +- 2 files changed, 3210 insertions(+), 3186 deletions(-) diff --git a/include/maskfld.cpp b/include/maskfld.cpp index 01cf04eef..23dee6d09 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -1,3185 +1,3195 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if XVT_OS == XVT_OS_WIN -#include -#endif - -HIDDEN TString256 fpark; - -/////////////////////////////////////////////////////////// -// Field Flags -/////////////////////////////////////////////////////////// - -// Certified 100% -TMask_field::TField_Flags::TField_Flags() -{ - automagic = persistent = FALSE; - enabled = enable_default = TRUE; - shown = show_default = TRUE; - uppercase = rightjust = FALSE; - zerofilled = FALSE; - dirty = focusdirty = FALSE; - roman = exchange = FALSE; - firm = ghost = FALSE; - password = FALSE; - trim = TRUE; -} - -// Certified 100% -char TMask_field::TField_Flags::update(const char* f) -{ - for (const char* s = f; *s; s++) - switch(toupper(*s)) - { - case ' ': - case '_': - trim = FALSE; break; - case '*': - password = TRUE; break; - case 'A': - automagic = persistent = TRUE; break; - case 'D': - enable_default = enabled = FALSE; break; - case 'F': - firm = persistent = TRUE; break; - case 'G': - ghost = TRUE; break; - case 'H': - show_default = shown = FALSE; break; - case 'M': - roman = TRUE; break; - case 'P': - persistent = TRUE; break; - case 'R': - rightjust = TRUE; break; - case 'U': - uppercase = TRUE; break; - case 'V': - exchange = TRUE; break; - case 'Z': - zerofilled = TRUE; break; - default : - CHECKS(0, "FLAG sconosciuto in ", f); - break; - } - return *s; -} - - -/////////////////////////////////////////////////////////// -// TMask_field -/////////////////////////////////////////////////////////// - -int TMask_field::_x; // Position of the field -int TMask_field::_y; -int TMask_field::_width; -TString80 TMask_field::_prompt; - -TMask_field::TMask_field(TMask* m) -: _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), - _keys(0), _groups(0), _help(0), _handler(NULL), - _validate_func(-1), _validate_parms(1), _field(NULL) -{} - -// Certified 100% -TMask_field::~TMask_field() -{ - if (_field) delete _field; -} - - -// Certified 100% -bool TMask_field::is_edit() const -{ - const word c = class_id(); - return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD; -} - - -// Certified 100% -const char* TMask_field::class_name() const -{ return "Field"; } - - -// Certified 100% -word TMask_field::class_id() const -{ return CLASS_FIELD; } - - -// Certified 100% -bool TMask_field::ok() const -{ return win() != NULL_WIN && dlg() >= -1; } - - -// Certified 100% -void TMask_field::parse_head(TScanner&) -{} - - -// Certified 100% -short TMask_field::atodlg(const char* s) const -{ - short d = s ? atoi(s) : 0; - -#ifdef DBG - if (d == 0 || d < -1 || d > 1000) - { - yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); - d = -1; - } -#endif - - return d; -} - -void TMask_field::construct(short id, const char* prompt, int x, int y, - int len, WINDOW parent, const char* flags, int width) -{ - _x = x; _y = y; - _prompt = prompt; - _size = len; - if (class_id() == CLASS_REAL_FIELD) - { - ((TReal_field*)this)->set_decimals(width); - _width = _size; - } - else _width = width < 1 ? _size : width; - _dlg = id; - _flags.update(flags); - - create(parent); -} - - -void TMask_field::construct(TScanner& scanner, WINDOW parent) -{ - _dlg = atodlg(scanner.pop()); - parse_head(scanner); - _prompt.cut(0); - - scanner.popkey(); // BEGIN -#ifdef DBG - if (scanner.key() != "BE") - { - yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); - scanner.push(); - } -#endif - - while(scanner.popkey() != "EN") // END of control - parse_item(scanner); - create(parent); -} - -bool TMask_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PR") // PROMPT - { - _x = scanner.integer(); - _y = scanner.integer(); - _prompt = scanner.string(); - return TRUE; - } - - if (scanner.key() == "FL") // FLAG - { - const char* f = scanner.string(); - return _flags.update(f) == '\0'; - } - - if (scanner.key() == "FI") // FIELD - { - CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); - _field = new TFieldref(scanner.line(), 0); - return TRUE; - } - - if (scanner.key() == "HE") // HELP - { - _help = scanner.string(); - return TRUE; - } - - if (scanner.key() == "KE") // KEY - { - _keys.set(scanner.line()); - _keys.set(0L); - return TRUE; - } - - if ( scanner.key() == "CU") // CUSTOM DATA - { - _userdata.add(scanner.string()); - return TRUE; - } - - if (scanner.key() == "ME") - { - if (_message.objptr(0) == 0) - _message.add(new TToken_string(64), 0); - TToken_string& ts = (TToken_string&)_message[0]; - ts.add(scanner.line().strip_spaces()); - return TRUE; - } - - if (scanner.key() == "GR") - { - _groups.set(scanner.line()); - return TRUE; - } - - return FALSE; -} - - -long TMask_field::default_flags() const -{ - long f = CTL_FLAG_NATIVE_JUST; - - if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; - if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; - - return f; -} - -// Certified 100% -WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy, - const char* title, WINDOW parent, - long flags) -{ - _win = xvt_create_control(ct, - _x, _y, dx, dy, - (char*)title, - parent, - flags | default_flags(), - PTR_LONG(this), - _dlg); - - return _win; -} - - -// Certified 100% -WINDOW TMask_field::parent() const -{ return xvt_vobj_get_parent(win()); } - - -// Certified 90% -int TMask_field::create_prompt(WINDOW parent, int width, int heigth) -{ - const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; - if (width < 1) width = _prompt.len() - (_prompt[0] == '@' ? 2 : 0); - _prompt.rtrim(); // Could save some bytes - - if (width) - { - const long flags = default_flags() & (~CTL_FLAG_DISABLED); // Static controls shouldn't be grayed - -#if XVT_OS == XVT_OS_WIN - const int k = _prompt.find('~'); - if (k >= 0) _prompt[k] = '&'; - if (required() && _prompt[0] != '@') - _prompt.insert("@b", 0); -#endif - _promptwin = xvt_create_control - ( - wt, - _x, _y, width, heigth, - _prompt, - parent, - flags, - 0L, - -1 - ); - } - return width; -} - - -// Certified 100% -void TMask_field::destroy() -{ - if (_win) - { xvt_vobj_destroy(_win); _win = NULL_WIN; } - if (_promptwin) - { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } -} - - -// Certified 100% -void TMask_field::create(WINDOW parent) -{ - _width = _prompt.len(); - if (_width) - wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); -} - - -// Certified 100% -void TMask_field::enable(bool on) -{ - const word c = class_id(); - if (c != CLASS_FIELD) - { - xvt_vobj_set_enabled(_win, on); - _flags.enabled = on; - } -} - - -// Certified 100% -void TMask_field::enable_default() -{ - const bool ed = _flags.enable_default; - enable(ed); -} - - -// Certified 100% -void TMask_field::show(bool on) -{ - xvt_vobj_set_visible(_win, on); - if (_promptwin != NULL_WIN) - xvt_vobj_set_visible(_promptwin, on); - _flags.shown = on; -} - - -// Certified 100% -void TMask_field::show_default() -{ - const bool sd = _flags.show_default; - show(sd); -} - - -// Certified 100% -bool TMask_field::active() const -{ - return enabled() && shown() && class_id() != CLASS_FIELD; -}; - - -// Certified 90% -word TMask_field::last_key() const -{ - long u = _keys.last_one(); - if (u < 0) u = 0; - return (word)u; -} - -void TMask_field::set_dirty(bool d) -{ - if (_flags.dirty == 3 && d == FALSE) - return; - _flags.dirty = d; - set_focusdirty(d); -} - - - -// Certified 99% -const char* TMask_field::get_window_data() const -{ - return xvt_vobj_get_title(win(), (char*)(const char*)fpark, fpark.size()); -} - - -// Certified 99% -void TMask_field::set_window_data(const char* data) -{ - if (data != NULL) - xvt_vobj_set_title(win(), (char*)data); -} - - -// Certified 100% -void TMask_field::set_field_data(const char*) -{} - - -// Certified 100% -const char* TMask_field::get_field_data() const -{ return NULL; } - - -const char* TMask_field::picture_data(const char* data, bool video) -{ - fpark = data; - if (video) - { - fpark.trim(); - if (_flags.uppercase) fpark.upper(); - } - return fpark; -} - - -// Certified 90% -const char* TMask_field::prompt() const -{ - if (_promptwin != NULL_WIN) - _prompt = xvt_get_title(_promptwin); - else - _prompt = ""; - - return _prompt; -} - - -// Certified 100% -void TMask_field::reset() -{ - if (!_flags.persistent && class_id() != CLASS_FIELD) - set(""); -} - - -// Certified 100% -void TMask_field::set_prompt(const char* p) -{ - if (_promptwin != NULL_WIN) - xvt_vobj_set_title(_promptwin, (char*) p); -} - - -void TMask_field::set(const char* s) -{ - if (_dlg == 108) - _dlg = 108; - - if (mask().is_running()) - { - set_window_data(s); - set_dirty(); - } - else - set_field_data(s); -} - -TString& TMask_field::get() const -{ - static TString256 gpark; - - if (mask().is_running()) - gpark = get_window_data(); - else - gpark = get_field_data(); - - if (_flags.trim) gpark.trim(); - return gpark; -} - - -void TMask_field::undo() -{ - set_window_data(get_field_data()); -} - - -bool TMask_field::autoload(const TRelation* r) -{ - if (_field) - { - set(_field->read(r)); - return TRUE; - } - return FALSE; -} - - -bool TMask_field::autosave(TRelation* r) const -{ - if (_field) - { - _field->write(get(), r); - return TRUE; - } - return FALSE; -} - - -// Certified 50% -HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) -{ -#ifdef DBG - if (f.class_id() != CLASS_LIST_FIELD) - { - yesnofatal_box("Can't add/delete items of non list-box field %d", f.dlg()); - return; - } -#endif - TList_field& l = (TList_field&)f; - - TToken_string item(16); - item = msg.get(); - if (add) item.add(msg.get()); - item.strip("\"'"); - if (add) - l.add_item(item); - else - l.delete_item(item); -} - - -// Certified 99% -HIDDEN const char* copy_value(TToken_string& msg, const TString& val) -{ - int from = msg.get_int()-1; - int to = -1; - if (from < 0) from = 0; - else to = msg.get_int(); - return val.sub(from, to); -} - -HIDDEN void run_app(const TMask& mask, TToken_string& msg) -{ - TFilename a(msg.get(1)); - - for (const char* m = msg.get(); m; m = msg.get()) - { - a << ' '; - for (const char* f = m; *f; f++) - { - if (*f == '#') - { - const int id = atoi(++f); - a << mask.get(id); - break; - } - else - a << *f; - } - } - TExternal_app app(a); - app.run(); -} - - -void TMask_field::send_key(KEY k, short to) -{ - mask().send_key(k, to, this); -} - - -// Certified 90% -bool TMask_field::do_message(int num) -{ - const int MAX_CMD = 17; - static const char* commands[MAX_CMD] = - { - "ADD", // 0 - "CLEAR", // 1 - "CO", // 2 - "DEL", // 3 - "DIRTY", // 4 - "DISABLE", // 5 - "ENABLE", // 6 - "ENABLEDEF", // 7 - "EXIT", // 8 - "HIDE", // 9 - "NORMAL", // 10 - "PUSH", // 11 - "REQUIRED", // 12 - "RESET", // 13 - "RU", // 14 - "SHOW", // 15 - "UNDO" // 16 - }; - - TToken_string* message = (TToken_string*)_message.objptr(num); - if (message == NULL || message->empty()) return FALSE; - - TToken_string msg(16, ','); - TString256 value; - - for (const char* m = message->get(0); m && *m; m = message->get()) - { - KEY key = 0; - msg = m; - value = msg.get(); - const char* dlg = msg.get(); - - int cmd = -1; - if (isalpha(value[0])) // binary search - { - int f = 0, l = MAX_CMD-1; - while (TRUE) - { - cmd = (f+l)>>1; - const int cmp = strcmp(value, commands[cmd]); - if (cmp == 0) break; - if (cmp > 0) f = cmd+1; - else l = cmd-1; - if (f > l) - { - cmd = -1; - break; - } - } - } - - if (cmd == 8) - { - mask().stop_run(atoi(dlg)); - continue; - } else - if (cmd == 14) - { - run_app(mask(), msg); - continue; - } - - - short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; - bool broadcast = dlg && strchr(dlg, '@'); - if (value[0] == '"') value = value.strip("\"'"); - else switch (cmd) - { - case 0: - modify_list(TRUE, mask().field(fld), msg); continue; - case 1: - key = 11000+'c'; break; - case 2: - value = copy_value(msg, get()); break; - case 3: - modify_list(FALSE, mask().field(fld), msg); continue; - case 4: - mask().field(fld).set_dirty(); continue; - case 5: - key = 11000+'d'; break; - case 6: - key = 11000+'e'; break; - case 7: - key = 11000+'E'; break; - case 9: - key = 11000+'h'; break; - case 10: - mask().efield(fld).check_type(CHECK_NORMAL); continue; - case 11: - key = K_SPACE; break; - case 12: - mask().efield(fld).check_type(CHECK_REQUIRED); continue; - case 13: - key = K_F2; break; - case 15: - key = 11000+'s'; break; - case 16: - key = K_F3; break; - default: - key = atoi(value); - break; - } - - if (key) - { - if (key > 0) - { - if (broadcast) fld = -fld; - send_key(key, fld); - } - } - else - { - // Setta a value il campo fld solo se ha un valore diverso da value - if (broadcast) - { - for (int i = 0; i < mask().fields(); i++) - { - TMask_field& f = mask().fld(i); - if (f.in_group((int)fld)) - { - const char* prev = f.get(); - if (value != prev) - { - f.set(value); - if (f.shown() || f.ghost()) - f.on_hit(); - } - } - } - } - else - { - TMask_field& f = mask().field(fld); - const char* prev = f.get(); - if (value != prev) - { - f.set(value); - if (f.shown() || f.ghost()) - f.on_hit(); - } - } - } - } - - return TRUE; -} - - -bool TMask_field::test_focus_change() -{ - bool ok = TRUE; - if (focusdirty()) on_key(K_TAB); // Comportamento normale - else if (is_edit() && in_key(1)) on_hit(); // Serve per eseguire gli handler autoprementi - return ok; -} - - -// Certified 90% -bool TMask_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - do_message(0); - return TRUE; -} - - -bool TMask_field::to_check(KEY k, bool checkrun) const -{ - bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); - - if (!yes && checkrun) - yes = k == K_TAB && !mask().is_running(); - - return yes; -} - -// Certified 90% -bool TMask_field::on_key(KEY key) -{ - if (key > 11000) - { - switch(key-11000) - { - case 'E': - enable_default(); break; - case 'c': - reset(); on_hit(); - case 'd': - disable(); break; - case 'e': - enable(); break; - case 'h': - hide(); break; - case 's': - show(); break; -#ifdef DBG - default : - return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); -#endif - } - return TRUE; - } - - switch(key) - { - case K_SPACE: - set_dirty(); - break; - case K_PREV: - case K_NEXT: - send_key(key, 0); - break; - case K_F1: -#if XVT_OS == XVT_OS_WIN - if (fexist("prassi.hlp")) - { - struct MULTIGUY - { - UINT mkSize; - BYTE mkKeylist; - char mkKeyphrase[16]; - } mk; - - TFilename topic(mask().source_file()); topic.ext(""); - mk.mkSize = sizeof(MULTIGUY); - mk.mkKeylist = 'M'; - strcpy(mk.mkKeyphrase, topic); - - TFilename hlp("prassi.hlp"); - const TString16 mod(topic.left(2)); - if (mod != "ba") hlp.insert(mod, 0); - - HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); - WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); - break; - } -#endif - case K_SHIFT+K_F1: - if (_help.not_empty()) - message_box(_help); - else - beep(); - set_focus(); - break; - case K_F11: - { - const char* c = ""; - if (field()) - c = field()->name(); - message_box("State utilizzando il campo %d della maschera '%s'\n" - "corrispondente al campo su file '%s'", - dlg(), (const char*)mask().source_file(), c); - set_focus(); - } - break; - - case K_F2: - if (is_edit()) set(""); - else reset(); - set_dirty(); - break; - case K_F3: - undo(); - set_dirty(); - break; - default: - break; - } - - if (_handler) - return _handler(*this, key); - - return TRUE; -} - -void TMask_field::highlight() const -{ - xvt_scr_set_focus_vobj(win()); -} - -void TMask_field::set_focus() const -{ - const bool force = mask().is_running(); - mask().set_focus_win(win(), force); -} - -HIDDEN char* const _msg = &__tmp_string[512]; -#define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) - -bool TMask_field::error_box(const char* fmt, ...) const -{ - build_msg(); - if (mask().is_sheetmask() && !mask().is_running()) - { - xvt_statbar_set(_msg); - beep(); - } - else - { - set_focus(); - ::error_box("%s", _msg); - set_focus(); - } - return FALSE; -} - -bool TMask_field::message_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - ::message_box("%s", _msg); - set_focus(); - return FALSE; -} - -bool TMask_field::warning_box(const char* fmt, ...) const -{ - build_msg(); - - if (mask().is_sheetmask() && !mask().is_running()) - { - xvt_statbar_set(_msg); - beep(); - } - else - { - set_focus(); - ::warning_box("%s", _msg); - set_focus(); - } - return FALSE; -} - -bool TMask_field::yesno_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const bool yes = ::yesno_box("%s", _msg); - set_focus(); - return yes; -} - -KEY TMask_field::yesnocancel_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const KEY k = ::yesnocancel_box("%s", _msg); - set_focus(); - return k; -} - -/////////////////////////////////////////////////////////// -// TList_sheet -/////////////////////////////////////////////////////////// - -// Certified 100% -TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) -: _fld(f), _row(-1) -{ - _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); -} - -// Certified 100% -TList_sheet::~TList_sheet() -{ - delete _sheet; -} - -// Certified 100% -TMask_field& TList_sheet::field(short id) const -{ return field().mask().field(id); } - - -// Certified 100% -void TList_sheet::read_item(TScanner& scanner) -{ - TToken_string ts(scanner.string()); - _sheet->add(ts); -} - - -// Certified 100% -void TList_sheet::parse_input(TScanner& scanner) -{ - _inp_id.add(scanner.pop()); -} - - -// 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()) 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 = _fld->atodlg(fld); - if (id > 0) rowsel.add(field().mask().get(id)); - else rowsel.add(""); - } - } - - TString80 fd, it; - for (int i = 0 ; i < _sheet->items(); i++) - { - TToken_string& ts =_sheet->row(i); - - ts.restart(); - for ( const char* 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 = _sheet->row(_row); - rowsel.restart(); - for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) - { - const short id = _fld->atodlg(fld); - if (t != STARTING_CHECK || field().field() == NULL) - { - TMask_field& f = field(id); - f.set(rowsel.get()); - if (field().dlg() != id) - f.on_hit(); - } - } -} - - -// Certified 100% -KEY TList_sheet::run() -{ - _row = do_input(); - - _sheet->select(_row); - - const KEY k = _sheet->run(); - - switch (k) - { - case K_ENTER: - _row = (int)_sheet->selected(); - do_output(); - break; - default: - break; - } - - return k; -} - - -// Certified 100% -bool TList_sheet::check(CheckTime t) -{ - const bool passed = (_row = do_input()) != -1; - if (passed) do_output(t); - return passed; -} - - -/////////////////////////////////////////////////////////// -// TBrowse -/////////////////////////////////////////////////////////// - -// Certified 100% -TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) -: _relation(r), _cursor(new TCursor (r, filter, key)), - _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) -{} - - -// Certified 100% -TBrowse::TBrowse(TEdit_field* f, TCursor* c) -: _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) -{} - - -// Certified 100% -TBrowse::~TBrowse() -{ - if (_relation) - { - delete _relation; - delete _cursor; - } -} - - -// Certified 100% -void TBrowse::parse_display(TScanner& scanner) -{ - const char* s; - s = scanner.string(); - _head.add(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(); - _inp_id.add(scanner.line()); - } - else // Field on the mask - { - TString80 str(s); - if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field - else scanner.push(); - _inp_id.add(str); - } -} - - -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); -} - - -bool TBrowse::parse_copy(const TString& what, const TBrowse& b) -{ - const bool all = what == "AL"; - if (all || what == "US") - { - set_insert(b.get_insert()); - _filter = b.get_filter(); - if (field()._warning.empty()) - field()._warning = b.field()._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 = TRUE; - } - return TRUE; -} - - -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(); - - byte 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.len() > 4) - yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); - else -#endif - _relation->add(j, exp, key, to, alias); // join table - } -} - - -void TBrowse::parse_insert(TScanner& scanner) -{ - const TString16 key(scanner.popkey()); - - if (key == "NO") _insert = ""; - else - { - if (key == "RU") - { - _insert = "R"; - _insert << scanner.line(); - } - else - { - _insert = "M"; - _insert << scanner.line(); - } - _insert.trim(); - } -} - - -// Certified 100% -TMask_field& TBrowse::field(short n) const -{ return _fld->mask().field(n); } - - -// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro -int TBrowse::inputs() -{ - int inp = 0; - for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) - { - - if (*fld != '"' && strchr(fld, '@') == NULL && field(atoi(fld)).is_edit()) - inp++; - } - return inp; -} - -// Ritorna il numero di campi non vuoti e non filtrati -int TBrowse::do_input(bool filter) -{ - int ne = 0; - if (_inp_id.empty()) return ne; - - TRectype& cur = _cursor->curr(); - - cur.zero(); - TRectype filtrec(cur); - - _inp_id.restart(); - _inp_fn.restart(); - - TString256 val; // Value to output - bool tofilter; - - for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) - { - if (*fld == '"') - { - val = (fld+1); - if (val.not_empty()) val.rtrim(1); - tofilter = filter; - } - else - { - const short id = _fld->atodlg(fld); - const bool filter_flag = strchr(fld, '@') != NULL; - tofilter = filter && filter_flag; - val = field(id).get(); - if (field(id).is_edit() && val.not_empty() && !filter_flag) - ne++; // Increment not empty fields count - } - - TFieldref fldref(_inp_fn.get(), 0); // Output field - fldref.write(val, _cursor->relation()); - if (tofilter) - { - if (val.empty()) val.fill('~', fldref.len(cur)); - fldref.write(val, filtrec); - } - } - - if (!filter) return ne; - - TString work(_filter.size()); - 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] == '#') - { - work << '"' << field(atoi(&_filter[++i])).get() << '"'; - while (isspace(_filter[i])) i++; - while (isdigit(_filter[i])) i++; - i--; - } - else work << _filter[i]; - } - - _cursor->setfilter(work); - _cursor->setregion(filtrec, filtrec); - - return ne; -} - - -void TBrowse::do_output(CheckTime t) -{ - if (t == FINAL_CHECK) - return; - - TString256 sum; - TToken_string flds(24, '+'); - - _out_fn.restart(); - for (const char* 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(); - if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) - { - sum.cut(0); - for(const char* fr = flds.get(0); fr; fr = flds.get()) - { - const char* val; - if (*fr == '"') - { - const TString80 v(fr); - val = v.mid(1, v.len()-2); - } - else - { - const TFieldref fld(fr, 0); - val = fld.read(_cursor->relation()); - } - sum << val; - } - - f.set(sum); - if (field().dlg() != id) - f.on_hit(); - } - } -} - - -void TBrowse::do_clear() -{ - for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) - { - TMask_field& f = field(atoi(fld)); - if (f.field() == NULL && _inp_id.get_pos(fld) < 0) - f.reset(); - } -} - - - -bool TBrowse::do_insert() -{ - bool ok = FALSE; - TString80 app; - - if (_insert[0] == 'M') - { - TString80 nm(_insert.mid(1)); - if (nm.compare("batb", 4, TRUE) == 0) // Programma gestione tabelle - app = format("ba3 -0 %s", (const char*)nm.mid(4)); - // Obbligatorio usare la format globale - else // Programma generico di browse/edit - app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); - // Obbligatorio usare la format globale - } - else - { - app = _insert.mid(1); - } - /* - #if XVT_OS == XVT_OS_WIN - if (strnicmp(app, main_app().name(), 3) == 0) - app.insert("a", 3); - #endif - */ - TMailbox mail; - TMessage msg(app, MSG_AI, ""); - mail.send(msg); - - TExternal_app a(app); - a.run(); - - if (mail.check()) - { - TMessage* rcv = mail.next_s(MSG_AI); - if (rcv != NULL) _rec = atoi(rcv->body()); - if (_rec > 0) - { - _cursor->file().readat(_rec); - ok = _cursor->ok(); - if (ok) do_output(); -#ifdef DBG - else yesnofatal_box("Selezione da programma esterno errata"); -#endif - } - } - return ok; -} - - -TToken_string& TBrowse::create_siblings(TToken_string& siblings) -{ - const TMask& mask = field().mask(); - siblings = ""; // Azzera la lista dei campi associati - - // if (!mask.is_running()) return siblings; - - TBit_array key(4); // Elenco delle chiavi gia' utilizzate - key.set(_cursor->key()); - - // Scorre la lista dei campi di output - int n = 0; - for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) - { - const short id = _fld->atodlg(i); - const TMask_field& f = mask.field(id); - if (!f.shown() || !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 == _fld->dlg())) - { - TString16 fn(_out_fn.get(n)); // Legge nome del campo su file - int pos = _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 = _items.get_pos(fn); // ... ritenta senza parentesi - } - } - if (pos >= 0) - { - siblings.add(id); - const char* h = _head.get(pos); - 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() -{ - do_input(TRUE); - _cursor->read(_isgteq); - - const TLocalisamfile& f = _cursor->file(); - TString80 caption(prefix().description(f.name())); - if (!isalnum(caption[0])) - caption = "Selezione"; - - KEY k = K_ESC; - long selected = 0; - - TToken_string siblings; - create_siblings(siblings); - -{ - TToken_string* sib = siblings.empty() ? NULL : &siblings; - byte buttons = 0; - if (_insert.not_empty()) - { - buttons = 1; // Mette il bottone di gestione, a meno che ... - - const TString& maskname = _fld->mask().source_file(); - if (maskname.compare("batb", 4, TRUE) == 0 && _fld->in_key(0)) - { - const char* tabname = _cursor->file().name(); - if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0) - buttons = 0; - } - } - - TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); - k = s.run(); - selected = s.selected(); -} - -switch (k) -{ - case K_INS: - k = do_insert() ? K_ENTER : K_ESC; - break; - case K_ENTER: - *_cursor = selected; - do_output(); - break; -default: - if (k >= K_CTRL) - { - const TMask& m = _fld->mask(); - const short id = siblings.get_int((k - K_CTRL) << 1); - TEdit_field& ef = m.efield(id); - ef.set_focus(); - k = K_F9; - if (m.is_running()) - ef.send_key(k, 0); - } - break; -} - -return k; -} - -bool TBrowse::check(CheckTime t) -{ - bool passed = TRUE; - - if (_secondary == TRUE && t != RUNNING_CHECK) - return TRUE; - - if (_fld->check_type() != CHECK_NONE) - { - const TMaskmode mode = (TMaskmode)field().mask().mode(); - - CheckType chk = _fld->check_type(); - const int ne = do_input(TRUE); - if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL; - if (ne || chk == CHECK_REQUIRED) - { - _cursor->setkey(); - _cursor->file().read(_isequal); - passed = _cursor->ok(); - - if (t != FINAL_CHECK) - { - if (passed) - { - _cursor->repos(); - do_output(t); - } - else - { - do_clear(); - if (!_fld->mask().query_mode() && _fld->check_enabled()) - _fld->set_dirty(3); - } - } - } - else - if (t != FINAL_CHECK) do_clear(); - } - return passed; -} - -bool TBrowse::empty_check() -{ - if ( field().mask().query_mode() || _fld->check_type() == CHECK_NONE || - _fld->check_type() == CHECK_NORMAL) - return TRUE; - else - return do_input() > 0; -} - - -/////////////////////////////////////////////////////////// -// TEdit_field -/////////////////////////////////////////////////////////// - -TEdit_field::TEdit_field(TMask* mask) -: TMask_field(mask), _browse(NULL), _sheet(NULL), - _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(FALSE), - _forced(FALSE) -{} - -TEdit_field::~TEdit_field() -{ - if (_browse) delete _browse; else - if (_sheet) delete _sheet; -} - -word TEdit_field::class_id() const -{ return CLASS_EDIT_FIELD; } - - -void TEdit_field::enable(bool on) -{ - TMask_field::enable(on); - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on && check_enabled() && shown()); -} - -void TEdit_field::show(bool on) -{ - TMask_field::show(on); - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on && check_enabled() && enabled()); -} - - -void TEdit_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); -#ifdef DBG - if (_size < 1) - { - _size = 8; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); - } -#endif - _width = scanner.integer(); - if (_width == 0) _width = _size; -} - - -const TBrowse* TEdit_field::get_browse(TScanner& scanner) const -{ - const int id = scanner.integer(); - const TEdit_field& f = mask().efield(id); - const TBrowse* b = (const TBrowse*)f.browse(); -#ifdef DBG - if (b == NULL) - yesnofatal_box("La USE del campo %d e' nulla e non puo' essere copiata nel campo %d", id, dlg()); -#endif - return b; -} - - -bool TEdit_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PI") // PICTURE - { - _picture = scanner.string(); -#ifdef DBG - if (_picture == "." && _size > 9 && _size != 15) - ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", - dlg(), (const char*)_prompt); -#endif - return TRUE; - } - - if (scanner.key() == "CH") - { - scanner.pop(); - if (scanner.key() == "NO") _check = CHECK_NORMAL; - else if (scanner.key() == "RE") _check = CHECK_REQUIRED; - else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;} - else _check = CHECK_NONE; - return TRUE; - } - - if (scanner.key() == "US") // USE - { -#ifdef DBG - if (_browse != NULL) - return yesnofatal_box("USE duplicata nel campo %d", dlg()); -#endif - - int key = 1; - TRelation* r; - - const int logicnum = scanner.integer(); - TString16 tabmaskname; - - if (logicnum > 0) - r = new TRelation(logicnum); - else - { - tabmaskname = scanner.pop(); -#ifdef DBG - if (tabmaskname.len() > 4) - return yesnofatal_box("'%s' non e' una tabella valida: %d", - (const char*)tabmaskname, dlg()); -#endif - r = new TRelation(tabmaskname); - } - - if (scanner.popkey() == "KE") - { - key = scanner.integer(); -#ifdef DBG - if (key < 1 || key > 15) - { - yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); - key = 1; - } -#endif - } - else scanner.push(); - - const char* filter = ""; - if (scanner.popkey() == "SE") - filter = (const char*)scanner.line(); - else - scanner.push(); - - _browse = new TBrowse(this, r, key, filter); - - if (tabmaskname.not_empty()) - { - tabmaskname.insert("MBATB", 0); - _browse->set_insert(tabmaskname); - } - - _check_enabled = TRUE; - return TRUE; - } - - if (scanner.key() == "CO") // Copyuse - { - const TString16 what(scanner.popkey()); - - const TBrowse* b = get_browse(scanner); - if (b == NULL) return FALSE; - - if (what == "US" || what == "AL") - _browse = new TBrowse(this, b->cursor()); - - if (_browse) - { - _check_enabled = TRUE; - return _browse->parse_copy(what, *b); - } - -#ifdef DBG - return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); -#endif - } - - if (scanner.key() == "JO") - { -#ifdef DBG - if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); -#endif - _browse->parse_join(scanner); - return TRUE; - } - - if (scanner.key() == "SH") // SHEET - { -#ifdef DBG - if (_sheet) return yesnofatal_box("SHEET duplicato nel campo %d", dlg()); -#endif - _sheet = new TList_sheet(this, _prompt, scanner.string()); - _check_enabled = TRUE; - return TRUE; - } - - if (scanner.key() == "IT") // ITEM - { -#ifdef DBG - if (_sheet == NULL) return yesnofatal_box("ITEM senza SHEET nel campo %d", dlg()); -#endif - _sheet->read_item(scanner); - return TRUE; - } - - if (scanner.key() == "IN") - { - if (_browse) _browse->parse_input(scanner); else - if (_sheet) _sheet->parse_input(scanner); -#ifdef DBG - else yesnofatal_box("INPUT senza USE o SHEET nel campo %d", dlg()); -#endif - return TRUE; - } - - if (scanner.key() == "DI") - { -#ifdef DBG - if(!_browse) return yesnofatal_box("DISPLAY senza USE nel campo %d", dlg()); -#endif - _browse->parse_display(scanner); - return TRUE; - } - - if (scanner.key() == "OU") - { - if (_browse) _browse->parse_output(scanner); - else if (_sheet) _sheet->parse_output(scanner); -#ifdef DBG - else return yesnofatal_box("OUTPUT senza USE nel campo %d", dlg()); -#endif - return TRUE; - } - - if (scanner.key() == "AD") - { -#ifdef DBG - if(!_browse) return yesnofatal_box("ADD senza USE nel campo %d", dlg()); -#endif - _browse->parse_insert(scanner); - return TRUE; - } - - if (scanner.key() == "VA") - { - const char* n = scanner.pop(); - _validate_func = isdigit(*n) ? atoi(n) : -1; -#ifdef DBG - if (_validate_func < 0) - return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); -#endif - - const int _nparms = scanner.integer(); -#ifdef DBG - if (_nparms < 0 || _nparms > 100) - return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", dlg(), _nparms); -#endif - - for(int i = 0; i < _nparms; i++) - _validate_parms.add(scanner.operand()); - - return TRUE; - } - - if (scanner.key() == "WA") - { - _warning = scanner.string(); - return TRUE; - } - if (scanner.key() == "ME") - { - TFixed_string l(scanner.line().strip_spaces()); - int m = 0; - if (l[0] == '0') - { - l.ltrim(1); - l.ltrim(); - m = 1; - } - if (_message.objptr(m) == 0) - _message.add(new TToken_string(64), m); - TToken_string& ts = (TToken_string&)_message[m]; - ts.add(l); - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - - -void TEdit_field::create(WINDOW parent) -{ - const int len = create_prompt(parent); - - long bandiere = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; - if (_flags.uppercase) bandiere |= CTL_FLAG_MAC_GENEVA9; - if (_flags.password) bandiere |= CTL_FLAG_MAC_MONACO9; - - _x += len; - -#if XVTWS == WMWS - const int delta = 2; -#else - const int delta = 1; -#endif - - wincreate(WC_EDIT, _width+delta, 1, _str, parent, bandiere); - -#if XVT_OS == XVT_OS_WIN - HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW); - SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo -#endif - - if (_browse || _sheet) - { - long flags = default_flags(); - if (flags & CTL_FLAG_DISABLED) - { - flags &= ~CTL_FLAG_DISABLED; - flags |= CTL_FLAG_INVISIBLE; - } - _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, - 2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9); - } -} - -void TEdit_field::destroy() -{ - if (_buttonwin) - { xvt_vobj_destroy(_buttonwin); _buttonwin = NULL_WIN; } - TMask_field::destroy(); -} - - -void TEdit_field::set_window_data(const char* data) -{ - TMask_field::set_window_data(format(data)); -} - - -void TEdit_field::set_field_data(const char* data) -{ _str = data; } - -const char* TEdit_field::get_field_data() const -{ return _str; } - - -const char* TEdit_field::format(const char* d) -{ - fpark = d; - if (_flags.trim) fpark.trim(); - - if (fpark.not_empty()) - { - int len = fpark.len(); - if (len > _size) - { -#ifdef DBG - yesnofatal_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size); -#endif - fpark.cut(len = _size); - } - - if (len < _size) - { - if (_flags.zerofilled) - { - if (isdigit(fpark[0]) && real::is_real(fpark)) - fpark.right_just(_size, '0'); - } - else - if (_flags.rightjust) - fpark.right_just(_size); - } - - if (_flags.uppercase) - fpark.upper(); - } - - return fpark; -} - - -const char* TEdit_field::picture_data(const char* data, bool video) -{ - if (video) - { - data = format(data); - xvt_vobj_set_title(win(), (char*)data); - return get_window_data(); - } - - set_window_data(data); - TMask_field::get_window_data(); - - if (_flags.trim) fpark.trim(); - return fpark; -} - - -bool TEdit_field::validate(KEY k) -{ - return ::validate(_validate_func, *this, k, _validate_parms); -} - -// Certified 90% -bool TEdit_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - if (_message.objptr(1) && get() == "") do_message(1); - else do_message(0); - return TRUE; -} - -bool TEdit_field::default_error_box() const -{ - if (_warning.empty()) - { - const TString& p = prompt(); - if (isalnum(p[0])) - error_box("Valore non valido per %s: '%s'", (const char*)p, (const char*)get()); - else - error_box("Valore non valido: '%s'", (const char*)get()); - } - else - error_box(_warning); - return FALSE; -} - -bool TEdit_field::on_key(KEY key) -{ - switch(key) - { - case K_TAB: - if (_validate_func == AUTOEXIT_FUNC || - _validate_func == NUMCALC_FUNC || - _validate_func == STRCALC_FUNC) - set_focusdirty(); // Forza validate - if (to_check(K_TAB, TRUE)) - { - set(get()); - bool ok = validate(key); // Check validation expression - - if (!ok) - { - if (_warning.not_empty()) - error_box(_warning); - return FALSE; - } - - TMask& m = mask(); - const bool query = m.query_mode(); - - if (_sheet) ok = query || _sheet->check(); // Check consistency - else - if (_browse && check_enabled() && (!query || forced()) && _validate_func != 21) - ok = _browse->check(); - - if (!ok) return default_error_box(); - - ok = on_hit(); - if (!ok) return FALSE; - - if (query && required() && in_key(0)) - { - const byte keys = m.num_keys(); - - for (int i = 1; i <= keys; i++) - if (in_key(i) && m.key_valid(i)) - { - for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) - m.field(fld).set_dirty(FALSE); - mask().stop_run(K_AUTO_ENTER); - break; - } - } - return TRUE; - } - break; - case K_ENTER: - if (field() != NULL || mask().mode() == NO_MODE) - { - if (focusdirty()) set(get()); - - bool ok = validate(K_ENTER); // Check validation expression - if (!ok) - { - if (_warning.not_empty()) - error_box(_warning); - return FALSE; - } - - const bool query = mask().query_mode(); - - // check consistency - if (_sheet) ok = query || _sheet->check(FINAL_CHECK); - else - if (_browse && - check_enabled() && - _validate_func != 21 && // 21 = NOT_EMPTY_CHECK_FIELD - (!query || forced())) - { - if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency - else ok = _browse->empty_check(); - } - else - ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); - - if (!ok) - return default_error_box(); - } - break; - case K_F9: - if (check_enabled()) - { - enable_check(FALSE); - if (dirty()) set(get()); - KEY k = K_ESC; - if (_browse) k = _browse->run(); - else - if (_sheet) k = _sheet->run(); - else beep(); - if (k != K_F9) set_focus(); - enable_check(TRUE); - if (k == K_ENTER) - { - set_dirty(); - if (mask().is_running()) - send_key(K_TAB, 0); - else - on_hit(); - return TRUE; - } - else - return FALSE; - } - break; - default: - break; - } - - return TMask_field::on_key(key); -} - - -bool TEdit_field::has_check() const -{ - if (_browse) return check_type() != CHECK_NONE; - return _sheet != NULL; -} - -bool TEdit_field::check(CheckTime t) -{ - bool ok = TRUE; - if (check_enabled() || (t == STARTING_CHECK && shown())) - { - if (_browse) ok = (_validate_func == 21) || _browse->check(t); - else if (_sheet) ok = _sheet->check(t); - } - return ok; -} - -void TEdit_field::enable_check(bool on) -{ - _check_enabled = on; - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on); -} - - -/////////////////////////////////////////////////////////// -// Boolean_field -/////////////////////////////////////////////////////////// - - -TBoolean_field::TBoolean_field(TMask* m) -: TMask_field(m), _on(FALSE) -{} - - -word TBoolean_field::class_id() const -{ return CLASS_BOOLEAN_FIELD; } - - -void TBoolean_field::create(WINDOW parent) -{ - wincreate(WC_CHECKBOX, _prompt.len()+4, 1, _prompt, parent, 0); -} - - -const char* TBoolean_field::get_window_data() const -{ - CHECK(win(), "Control window not initialized"); - fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; - fpark[1] = '\0'; - return fpark; -} - - -void TBoolean_field::set_window_data(const char* data) -{ - CHECK(win(), "Control window not initialized"); - - if (data == NULL) data = ""; - const bool b = toupper(*data) == 'X'; - xvt_check_box(win(), b); -} - - -void TBoolean_field::set_field_data(const char* data) -{ - if (data == NULL) data = ""; - _on = toupper(*data) == 'X'; -} - -const char* TBoolean_field::get_field_data() const -{ - return _on ? "X" : " "; -} - - -bool TBoolean_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "ME") - { - const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE - - if (_message.items() == 0) - { - _message.add(new TToken_string(16)); - _message.add(new TToken_string(16)); - } - TToken_string& ts = (TToken_string&)_message[tf]; - ts.add(scanner.line().strip_spaces()); - - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - -void TBoolean_field::enable(bool on) -{ - _flags.enabled = on; - xvt_enable_control(_win, on); -} - - -bool TBoolean_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, K_SPACE); - if (!ok) return FALSE; - } - const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; - do_message(n); - return TRUE; -} - -bool TBoolean_field::on_key(KEY key) -{ - if (key == K_SPACE) - { - on_hit(); - set_dirty(); - return TRUE; - } - return TMask_field::on_key(key); -} - -/////////////////////////////////////////////////////////// -// Button_field -/////////////////////////////////////////////////////////// - -TButton_field::TButton_field(TMask* m) -: TMask_field(m) -{ - _flags.persistent = TRUE; -} - - -word TButton_field::class_id() const -{ return CLASS_BUTTON_FIELD; } - -void TButton_field::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - if (_width < 1) _width = 9; - _size = scanner.integer(); // Height - if (_size < 1) _size = 1; -} - - -bool TButton_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PI") - { - const int bmp = scanner.integer(); - _prompt << '#' << bmp; - return bmp > 0; - } - return TMask_field::parse_item(scanner); -} - - -void TButton_field::create(WINDOW parent) -{ - long flags = CTL_FLAG_CENTER_JUST; - - switch (dlg()) - { - case DLG_OK: - if (_prompt.empty()) - _prompt = "Conferma"; - _virtual_key = _exit_key = K_ENTER; - flags |= CTL_FLAG_DEFAULT; - break; - case DLG_CANCEL: - if (_prompt.empty()) - _prompt = "Annulla"; - _virtual_key = _exit_key = K_ESC; - break; - case DLG_DELREC: - if (_prompt.empty()) - _prompt = "Elimina"; - _virtual_key = 'E'; - _exit_key = K_DEL; - break; - case DLG_PRINT: - if (_prompt.empty()) - _prompt = "Stampa"; - _virtual_key = 'S'; - _exit_key = K_ENTER; - break; - case DLG_QUIT: - if (_prompt.empty()) - _prompt = "Fine"; - _virtual_key = K_F4; - _exit_key = K_QUIT; - break; - default: - { - _exit_key = 0; - TToken_string* message = (TToken_string*)_message.objptr(0); - if (message != NULL) - { - TToken_string msg(message->get(0), ','); - const TFixed_string m(msg.get(0)); - if (m == "EXIT") - _exit_key = msg.get_int(); - else - if (msg.get_int() == 0) _exit_key = atoi(m); - } - const int n = _prompt.find('~'); - _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; - } - break; - } - -#if XWTWS == WMWS - const int diesis = _prompt.find('#'); - if (diesis > 0) _prompt.cut(diesis); - _prompt.center_just(_width); -#endif - - wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); -} - -void TButton_field::enable(bool on) -{ - _flags.enabled = on; - xvt_enable_control(_win, on); -} - -void TButton_field::show(bool on) -{ - TMask_field::show(on); -} - - -bool TButton_field::on_key(KEY key) - -{ - if (key == K_SPACE) - { - on_hit(); - return TRUE; - } - return TMask_field::on_key(key); -} - -/////////////////////////////////////////////////////////// -// Date_field -/////////////////////////////////////////////////////////// - -word TDate_field::class_id() const -{ return CLASS_DATE_FIELD; } - -void TDate_field::create(WINDOW w) -{ - TEdit_field::create(w); - if (automagic()) - { - TDate d(TODAY); - set(d.string()); - } -} - -void TDate_field::parse_head(TScanner&) {} - -TDate_field::TDate_field(TMask* m) : TEdit_field(m) -{ - _size = _width = 10; -} - - -bool TDate_field::on_key(KEY key) -{ - if (to_check(key)) - { - TFixed_string data(get_window_data(), 15); - data.trim(); - if (data.not_empty()) - { - bool changed = FALSE; - if (isdigit(data[0])) - { - if (data.len() == 6) // Fix century (for this millenium only) - { - data.insert("19", 4); - changed = TRUE; - } - for (int meno = 2; meno <= 5; meno += 3) - if (data[meno] != '-') - { - data.insert("-", meno); - changed = TRUE; - } - if (data.len() == 8) // Fix century (for this millenium only) - { - data.insert("19", 6); - changed = TRUE; - } - } - else - { - TDate g(TODAY); - data.upper(); - if (data == "IERI") - { - --g; - changed = TRUE; - } - else - if (data == "DOMANI") - { - ++g; - changed = TRUE; - } - TString16 gstring(g.string()); - if (data == "PRIMO") - { - gstring.overwrite("01-01", 0); - changed = TRUE; - } - else - if (data == "NATALE") - { - gstring.overwrite("25-12", 0); - changed = TRUE; - } - else - if (data == "ULTIMO") - { - gstring.overwrite("31-12", 0); - changed = TRUE; - } - else - if (data == "OGGI") changed = TRUE; - if (changed) data = gstring; - } - - TDate d(data); - if (!d.ok()) - { - error_box("Data errata o formato non valido"); - return FALSE; - } - else - if (changed) - TMask_field::set_window_data(d.string()); - } - } - - return TEdit_field::on_key(key); -} - -const char * TDate_field::get_window_data() const -{ - const char * data = TEdit_field::get_window_data(); - if (roman()) - { - const TDate d(data); - data = d.string(ANSI); - } - return data; -} - - -void TDate_field::set_window_data(const char * data) -{ - if (roman()) - { - const TDate d(data); - data = d.string(); - } - TEdit_field::set_window_data(data); -} - -/////////////////////////////////////////////////////////// -// Real_field -/////////////////////////////////////////////////////////// - -TReal_field::TReal_field(TMask* m) : TEdit_field(m) -{} - -word TReal_field::class_id() const -{ return CLASS_REAL_FIELD; } - -void TReal_field::create(WINDOW w) -{ - TEdit_field::create(w); - _flags.rightjust = TRUE; - - if (_flags.firm) - set(::format("%ld", main_app().get_firm())); - else - if (automagic()) - { - TDate d(TODAY); - set(::format("%d", d.year())); - } -} - -bool TReal_field::autoload(const TRelation* r) -{ - const bool ok = TMask_field::autoload(r); - if (ok && _flags.zerofilled && _str.not_empty()) - { - int s = size(); - if (roman()) - { - s = decimals(); - if (s < 1) s = 4; - } - _str.right_just(s, '0'); - } - - return ok; -} - -bool TReal_field::on_key(KEY key) -{ - if (to_check(key)) - { - if (roman()) - { - const int r = atoi(get_window_data()); - if (r < 0) return error_box("Numero romano errato"); - } - else - { - const char* n = get(); - if (*n && !real::is_real(n)) - return error_box("Valore numerico non valido"); - if (_flags.uppercase && *n == '-') - return error_box("Il numero deve essere positivo"); - if (_flags.firm) - { - const long f = atol(n); - if (f > 0 && prefix().exist(f)) - main_app().set_firm(f); - else - return error_box("Ditta non utilizzabile in contabilita'"); - } - } - } - - return TEdit_field::on_key(key); -} - -void TReal_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); - -#ifdef DBG - if (_size < 1) - { - _size = 9; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); - } -#endif - - _width = _size; - _decimals = scanner.integer(); -} - -void TReal_field::set_window_data(const char* data) -{ - if (data == NULL) data = ""; - - if (roman()) - { - data = itor(atoi(data)); - TMask_field::set_window_data(data); - } - else - { - real n(data); - if (!n.is_zero()) - { - if (exchangeable() && decimals()) - { - const real& e = mask().exchange(); - n /= e; - } - if (_picture.empty()) - data = n.stringa(_size, _decimals); - else - data = n.string(_picture); - } - else data = ""; - TEdit_field::set_window_data(data); - } -} - -const char* TReal_field::get_window_data() const -{ - TEdit_field::get_window_data(); - if (roman()) - { - int r = atoi(fpark); - if (r == 0) r = rtoi(fpark); - if (r > 0) - { - int s = decimals(); - if (s < 1) s = 4; - if (_flags.zerofilled) - fpark.format("%0*d", s, r); - else - fpark.format("%*d", s, r); - } - else fpark.cut(0); - } - else - { - fpark = real::ita2eng(fpark); - if (exchangeable() && decimals()) - { - real n(fpark); - const real& e = mask().exchange(); - n *= e; - if (n.is_zero()) fpark.cut(0); - else fpark = n.string(); - } - } - - return fpark; -} - -void TReal_field::set_decimals(int d) -{ - _decimals = d; - if (_picture[0] == '.') - { - if (d > 0) _picture.format(".%d", d); - else _picture = "."; - } -} - - -void TReal_field::exchange(bool show_value, const real& nuo) -{ - const int dec = show_value ? 2 : 0; // Quanti decimali voglio - const bool value = decimals() != 0; // Sono attualmente in valuta ? - - if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito! - - if (mask().is_running()) - { - const char* n = get_window_data(); - if (*n) - { - const real& vec = mask().exchange(); - real r(n); - if (!show_value) - r *= nuo; - r /= vec; - r.round(dec); - set_decimals(dec); - TEdit_field::set_window_data(r.string(_picture)); - } - } - - if (decimals() != dec) - set_decimals(dec); -} - -/////////////////////////////////////////////////////////// -// List_field -/////////////////////////////////////////////////////////// - -TList_field::TList_field(TMask* m) : TMask_field(m) -{} - -word TList_field::class_id() const -{ - return CLASS_LIST_FIELD; -} - - -void TList_field::read_item(TScanner& scanner) -{ - TToken_string ts(scanner.string()); - _codes.add(ts.get()); - _values.add(ts.get()); - - ts = ""; - while (scanner.popkey() == "ME") - ts.add(scanner.line().strip_spaces()); - scanner.push(); - - _message.add(ts); -} - - -void TList_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); - _width = scanner.integer(); - if (_width < 1) _width = _size+3; -} - - -bool TList_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "IT") // ITEM - { - read_item(scanner); - return TRUE; - } - - if (scanner.key() == "LI") // LISTITEM - { - TScanner sc(scanner.pop()); - while (sc.popkey() == "IT") // ITEM - read_item(sc); - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - - -int TList_field::items() const -{ - return _codes.items(); -} - -void TList_field::add_item(const char* s) -{ - TToken_string t(s); - const TString16 item(t.get()); - const int pos = _codes.get_pos(item); - - if (pos < 0 ) - { - _codes.add(item); - xvt_list_add(win(), -1, (char*)t.get()); - } -} - - -void TList_field::delete_item(const char* s) -{ - TString16 t(s); - const int pos = _codes.get_pos(t); - - if (pos >= 0 ) - { - _codes.destroy(pos); - xvt_list_rem(win(), pos); - if (mask().is_running()) - { - xvt_list_set_sel(win(), 0, TRUE); - if (shown()) on_hit(); - } - } -} - - -void TList_field::add_list() -{ - if (roman() && _codes.items() < 12) - { - TString csafe, vsafe; - if (atoi(_codes) > 0) - { - csafe = _codes; _codes = ""; - vsafe = _values; _values = ""; - } - _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); - _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); - _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); - if (atoi(csafe) > 0) - { - _codes.add(csafe); - _values.add(vsafe); - if (_message.objptr(0)) - { - _message.add(_message[0], _codes.items()-1); - _message.add(NULL, 0); - } - } - } - - SLIST lst = xvt_slist_create(); - for (const char* item = _values.get(0); item; item = _values.get()) - xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); - xvt_list_add(win(), -1, (char*)lst); - xvt_slist_destroy(lst); - - const char* init = ""; - if (roman() && automagic()) - init = format("%02d", TDate(TODAY).month()); - set_field_data(init); -} - - -void TList_field::replace_items(const char* codes, const char* values) -{ - _codes = codes; - _values = values; - - if (win() != NULL_WIN) - { - xvt_list_clear(win()); - add_list(); - current(0); - } -} - - -void TList_field::create(WINDOW parent) -{ - const int len = create_prompt(parent); - _x += len; - - wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); - add_list(); -} - - -int TList_field::str2curr(const char* data) -{ - TString16 str(data); - - if (roman() && str.len() < 2) - str.insert("0",0); - if (_flags.uppercase) - str.upper(); - - int i = str.not_empty() ? _codes.get_pos(str) : 0; - - if (i < 0) // Se non trova il codice ritenta dopo trim - { - for (i = 0; str[i] == '0' || str[i] == ' '; i++); - if (i > 0) - { - str.ltrim(i); - i = _codes.get_pos(str); - } - } - - if (i < 0) - { - if (items() && str.not_empty()) - yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", - data, prompt(), dlg()); - i = 0; - } - return i; -} - - -void TList_field::set_window_data(const char* data) -{ - CHECKD(win(), "Control window not initialized ", dlg()); - const int i = str2curr(data); - current(i); -} - - -void TList_field::current(int n) -{ - xvt_list_set_sel(win(), n, TRUE); -} - -int TList_field::current() const -{ - const int sel = xvt_list_get_sel_index(win()); -#ifdef DBG - if (sel < 0 && items() > 0) - error_box("Lista senza selezione nel campo %d", dlg()); -#endif - return sel; -} - -const char* TList_field::get_window_data() const -{ - const int c = current(); - const char* v = ((TList_field*)this)->_codes.get(c); - return v; -} - -void TList_field::set_field_data(const char* data) -{ - const int i = str2curr(data); - _str = _codes.get(i); -} - -bool TList_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, K_SPACE); - if (!ok) return FALSE; - } - const int n = mask().is_running() ? current() : str2curr(_str); - do_message(n); - return TRUE; -} - -const char* TList_field::get_field_data() const -{ - return _str; -} - -bool TList_field::on_key(KEY key) -{ - if (key >= '0' && key <= 'z') - { - const int index = xvt_list_get_sel_index(win()); - CHECK(index >= 0, "List with no selection!"); - int newindex = -1; - -#if XVTWS == WMWS - if (key >= 'A' && key <= 'z') - { - for (int i = index+1; i != index; i++) - { - char item[16]; - bool flag; - - do - { - flag = xvt_list_get_elt(win(), i, item, 16); - if (!flag) - { - CHECK(i, "La lista e' vuota!"); - i = -1; - break; - } - } while (!flag); - if (flag && toupper(*item) == toupper(key)) - { - newindex = i; - break; - } - } // for - } // alphabetic -#endif - - if (key >= '0' && key <= '9') - { - newindex = (key == '0') ? 10 : key - '1'; - if (newindex > items()) - { - newindex = -1; - beep(); - } - } - - if (newindex >= 0) - { - xvt_list_suspend(win()); - xvt_list_set_sel(win(), index, FALSE); - xvt_list_set_sel(win(), newindex, TRUE); - xvt_list_resume(win()); - } - } // alphanumeric - -#if XVTWS == VMWS - if (key == K_TAB && class_id() == CLASS_LIST_FIELD) - dispacth_e_char(win(), K_F9); -#endif - - if (key == K_SPACE) on_hit(); - - return TMask_field::on_key(key); -} - - -/////////////////////////////////////////////////////////// -// TRadio_field -/////////////////////////////////////////////////////////// - -TRadio_field::TRadio_field(TMask* mask) -: TList_field(mask), _nitems(0), _active_item(0) -{} - - -word TRadio_field::class_id() const -{ - return CLASS_RADIO_FIELD; -} - - -void TRadio_field::create(WINDOW parent) -{ - const short id = dlg(); // Salva il control id - const int items = _codes.items(); - - if (_prompt.not_empty()) - { - const int dy = _flags.zerofilled ? 3 : items+2; - create_prompt(parent, _width, dy); - } - _x++; _y++; - _values.restart(); - - const char* s; - - const int width = _flags.zerofilled ? (_width-2)/items-1 : _width-2; - for(_nitems = 0; (s = _values.get()) != NULL; _nitems++) - { - CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); - - wincreate(WC_RADIOBUTTON, width, 1, s, parent,0); - _radio_ctl_win[_nitems] = _win; - _dlg += 1000; - - if (_flags.zerofilled) - _x += width+1; - else - _y++; - } - _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug - - _dlg = id; // Ripristina control id - - set_field_data(""); -} - -void TRadio_field::destroy() -{ - if (_promptwin) - { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } - - for(int i = 0; i < _nitems; i++) - { - xvt_vobj_destroy(_radio_ctl_win[i]); - _radio_ctl_win[i] = NULL_WIN; - } -} - - -int TRadio_field::current() const -{ - const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); - return c; -} - - -void TRadio_field::current(int n) -{ - _active_item = n; - xvt_check_radio_button(win(), _radio_ctl_win, _nitems); -} - - -void TRadio_field::check_radiobutton(WINDOW checked) -{ - for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); - CHECK(i < _nitems, "Trying to check an invalid radio button"); - current(i); -} - - -void TRadio_field::enable(bool on) -{ - _flags.enabled = on; - for(int i = 0; i < _nitems; i++) - xvt_enable_control(_radio_ctl_win[i], on); -} - - -void TRadio_field::show(bool on) -{ - if (_promptwin) - xvt_vobj_set_visible(_promptwin, on); - - for(int i = 0; i < _nitems; i++) - xvt_vobj_set_visible(_radio_ctl_win[i], on); - _flags.shown = on; -} - -// Return TRUE if focus has left the radio -bool TRadio_field::move_focus(int d) -{ - const int act = _active_item + d; - if (act >= _nitems || act < 0) - { - _active_item = current(); - return TRUE; - } - xvt_set_front_control(_radio_ctl_win[_active_item = act]); - return FALSE; -} - - -/////////////////////////////////////////////////////////// -// TGroup_field -/////////////////////////////////////////////////////////// - -TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) -{ - _flags.persistent = TRUE; -} - -// _size means _heigth -void TGroup_field::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - _size = scanner.integer(); -} - -void TGroup_field::create(WINDOW parent) -{ - const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; - wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); -} - - -void TGroup_field::set_window_data(const char* data) -{ xvt_set_title(win(), data); } - -void TGroup_field::set_field_data(const char* data) -{ xvt_set_title(win(), data); } - +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if XVT_OS == XVT_OS_WIN +#include +#endif + +HIDDEN TString256 fpark; + +/////////////////////////////////////////////////////////// +// Field Flags +/////////////////////////////////////////////////////////// + +// Certified 100% +TMask_field::TField_Flags::TField_Flags() +{ + automagic = persistent = FALSE; + enabled = enable_default = TRUE; + shown = show_default = TRUE; + uppercase = rightjust = FALSE; + zerofilled = FALSE; + dirty = focusdirty = FALSE; + roman = exchange = FALSE; + firm = ghost = FALSE; + password = FALSE; + trim = TRUE; +} + +// Certified 100% +char TMask_field::TField_Flags::update(const char* f) +{ + for (const char* s = f; *s; s++) + switch(toupper(*s)) + { + case ' ': + case '_': + trim = FALSE; break; + case '*': + password = TRUE; break; + case 'A': + automagic = persistent = TRUE; break; + case 'D': + enable_default = enabled = FALSE; break; + case 'F': + firm = persistent = TRUE; break; + case 'G': + ghost = TRUE; break; + case 'H': + show_default = shown = FALSE; break; + case 'M': + roman = TRUE; break; + case 'P': + persistent = TRUE; break; + case 'R': + rightjust = TRUE; break; + case 'U': + uppercase = TRUE; break; + case 'V': + exchange = TRUE; break; + case 'Z': + zerofilled = TRUE; break; + default : + CHECKS(0, "FLAG sconosciuto in ", f); + break; + } + return *s; +} + + +/////////////////////////////////////////////////////////// +// TMask_field +/////////////////////////////////////////////////////////// + +int TMask_field::_x; // Position of the field +int TMask_field::_y; +int TMask_field::_width; +TString80 TMask_field::_prompt; + +TMask_field::TMask_field(TMask* m) +: _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), + _keys(0), _groups(0), _help(0), _handler(NULL), + _validate_func(-1), _validate_parms(1), _field(NULL) +{} + +// Certified 100% +TMask_field::~TMask_field() +{ + if (_field) delete _field; +} + + +// Certified 100% +bool TMask_field::is_edit() const +{ + const word c = class_id(); + return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD; +} + + +// Certified 100% +const char* TMask_field::class_name() const +{ return "Field"; } + + +// Certified 100% +word TMask_field::class_id() const +{ return CLASS_FIELD; } + + +// Certified 100% +bool TMask_field::ok() const +{ return win() != NULL_WIN && dlg() >= -1; } + + +// Certified 100% +void TMask_field::parse_head(TScanner&) +{} + + +// Certified 100% +short TMask_field::atodlg(const char* s) const +{ + short d = s ? atoi(s) : 0; + +#ifdef DBG + if (d == 0 || d < -1 || d > 1000) + { + yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); + d = -1; + } +#endif + + return d; +} + +void TMask_field::construct(short id, const char* prompt, int x, int y, + int len, WINDOW parent, const char* flags, int width) +{ + _x = x; _y = y; + _prompt = prompt; + _size = len; + if (class_id() == CLASS_REAL_FIELD) + { + ((TReal_field*)this)->set_decimals(width); + _width = _size; + } + else _width = width < 1 ? _size : width; + _dlg = id; + _flags.update(flags); + + create(parent); +} + + +void TMask_field::construct(TScanner& scanner, WINDOW parent) +{ + _dlg = atodlg(scanner.pop()); + parse_head(scanner); + _prompt.cut(0); + + scanner.popkey(); // BEGIN +#ifdef DBG + if (scanner.key() != "BE") + { + yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); + scanner.push(); + } +#endif + + while(scanner.popkey() != "EN") // END of control + parse_item(scanner); + create(parent); +} + +bool TMask_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PR") // PROMPT + { + _x = scanner.integer(); + _y = scanner.integer(); + _prompt = scanner.string(); + return TRUE; + } + + if (scanner.key() == "FL") // FLAG + { + const char* f = scanner.string(); + return _flags.update(f) == '\0'; + } + + if (scanner.key() == "FI") // FIELD + { + CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); + _field = new TFieldref(scanner.line(), 0); + return TRUE; + } + + if (scanner.key() == "HE") // HELP + { + _help = scanner.string(); + return TRUE; + } + + if (scanner.key() == "KE") // KEY + { + _keys.set(scanner.line()); + _keys.set(0L); + return TRUE; + } + + if ( scanner.key() == "CU") // CUSTOM DATA + { + _userdata.add(scanner.string()); + return TRUE; + } + + if (scanner.key() == "ME") + { + if (_message.objptr(0) == 0) + _message.add(new TToken_string(64), 0); + TToken_string& ts = (TToken_string&)_message[0]; + ts.add(scanner.line().strip_spaces()); + return TRUE; + } + + if (scanner.key() == "GR") + { + _groups.set(scanner.line()); + return TRUE; + } + + return FALSE; +} + + +long TMask_field::default_flags() const +{ + long f = CTL_FLAG_NATIVE_JUST; + + if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; + if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; + + return f; +} + +// Certified 100% +WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy, + const char* title, WINDOW parent, + long flags) +{ + _win = xvt_create_control(ct, + _x, _y, dx, dy, + (char*)title, + parent, + flags | default_flags(), + PTR_LONG(this), + _dlg); + + return _win; +} + + +// Certified 100% +WINDOW TMask_field::parent() const +{ return xvt_vobj_get_parent(win()); } + + +// Certified 90% +int TMask_field::create_prompt(WINDOW parent, int width, int heigth) +{ + const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; + if (width < 1) width = _prompt.len() - (_prompt[0] == '@' ? 2 : 0); + _prompt.rtrim(); // Could save some bytes + + if (width) + { + const long flags = default_flags() & (~CTL_FLAG_DISABLED); // Static controls shouldn't be grayed + +#if XVT_OS == XVT_OS_WIN + const int k = _prompt.find('~'); + if (k >= 0) _prompt[k] = '&'; + if (required() && _prompt[0] != '@') + _prompt.insert("@b", 0); +#endif + _promptwin = xvt_create_control + ( + wt, + _x, _y, width, heigth, + _prompt, + parent, + flags, + 0L, + -1 + ); + } + return width; +} + + +// Certified 100% +void TMask_field::destroy() +{ + if (_win) + { xvt_vobj_destroy(_win); _win = NULL_WIN; } + if (_promptwin) + { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } +} + + +// Certified 100% +void TMask_field::create(WINDOW parent) +{ + _width = _prompt.len(); + if (_width) + wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); +} + + +// Certified 100% +void TMask_field::enable(bool on) +{ + const word c = class_id(); + if (c != CLASS_FIELD) + { + xvt_vobj_set_enabled(_win, on); + _flags.enabled = on; + } +} + + +// Certified 100% +void TMask_field::enable_default() +{ + const bool ed = _flags.enable_default; + enable(ed); +} + + +// Certified 100% +void TMask_field::show(bool on) +{ + xvt_vobj_set_visible(_win, on); + if (_promptwin != NULL_WIN) + xvt_vobj_set_visible(_promptwin, on); + _flags.shown = on; +} + + +// Certified 100% +void TMask_field::show_default() +{ + const bool sd = _flags.show_default; + show(sd); +} + + +// Certified 100% +bool TMask_field::active() const +{ + return enabled() && shown() && class_id() != CLASS_FIELD; +}; + + +// Certified 90% +word TMask_field::last_key() const +{ + long u = _keys.last_one(); + if (u < 0) u = 0; + return (word)u; +} + +void TMask_field::set_dirty(bool d) +{ + if (_flags.dirty == 3 && d == FALSE) + return; + _flags.dirty = d; + set_focusdirty(d); +} + + + +// Certified 99% +const char* TMask_field::get_window_data() const +{ + return xvt_vobj_get_title(win(), (char*)(const char*)fpark, fpark.size()); +} + + +// Certified 99% +void TMask_field::set_window_data(const char* data) +{ + if (data != NULL) + xvt_vobj_set_title(win(), (char*)data); +} + + +// Certified 100% +void TMask_field::set_field_data(const char*) +{} + + +// Certified 100% +const char* TMask_field::get_field_data() const +{ return NULL; } + + +const char* TMask_field::picture_data(const char* data, bool video) +{ + fpark = data; + if (video) + { + fpark.trim(); + if (_flags.uppercase) fpark.upper(); + } + return fpark; +} + + +// Certified 90% +const char* TMask_field::prompt() const +{ + if (_promptwin != NULL_WIN) + _prompt = xvt_get_title(_promptwin); + else + _prompt = ""; + + return _prompt; +} + + +// Certified 100% +void TMask_field::reset() +{ + if (!_flags.persistent && class_id() != CLASS_FIELD) + set(""); +} + + +// Certified 100% +void TMask_field::set_prompt(const char* p) +{ + if (_promptwin != NULL_WIN) + xvt_vobj_set_title(_promptwin, (char*) p); +} + + +void TMask_field::set(const char* s) +{ + if (_dlg == 108) + _dlg = 108; + + if (mask().is_running()) + { + set_window_data(s); + set_dirty(); + } + else + set_field_data(s); +} + +TString& TMask_field::get() const +{ + static TString256 gpark; + + if (mask().is_running()) + gpark = get_window_data(); + else + gpark = get_field_data(); + + if (_flags.trim) gpark.trim(); + return gpark; +} + + +void TMask_field::undo() +{ + set_window_data(get_field_data()); +} + + +bool TMask_field::autoload(const TRelation* r) +{ + if (_field) + { + set(_field->read(r)); + return TRUE; + } + return FALSE; +} + + +bool TMask_field::autosave(TRelation* r) const +{ + if (_field) + { + _field->write(get(), r); + return TRUE; + } + return FALSE; +} + + +// Certified 50% +HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) +{ +#ifdef DBG + if (f.class_id() != CLASS_LIST_FIELD) + { + yesnofatal_box("Can't add/delete items of non list-box field %d", f.dlg()); + return; + } +#endif + TList_field& l = (TList_field&)f; + + TToken_string item(16); + item = msg.get(); + if (add) item.add(msg.get()); + item.strip("\"'"); + if (add) + l.add_item(item); + else + l.delete_item(item); +} + + +// Certified 99% +HIDDEN const char* copy_value(TToken_string& msg, const TString& val) +{ + int from = msg.get_int()-1; + int to = -1; + if (from < 0) from = 0; + else to = msg.get_int(); + return val.sub(from, to); +} + +HIDDEN void run_app(const TMask& mask, TToken_string& msg) +{ + TFilename a(msg.get(1)); + + for (const char* m = msg.get(); m; m = msg.get()) + { + a << ' '; + for (const char* f = m; *f; f++) + { + if (*f == '#') + { + const int id = atoi(++f); + a << mask.get(id); + break; + } + else + a << *f; + } + } + TExternal_app app(a); + app.run(); +} + + +void TMask_field::send_key(KEY k, short to) +{ + mask().send_key(k, to, this); +} + + +// Certified 90% +bool TMask_field::do_message(int num) +{ + const int MAX_CMD = 17; + static const char* commands[MAX_CMD] = + { + "ADD", // 0 + "CLEAR", // 1 + "CO", // 2 + "DEL", // 3 + "DIRTY", // 4 + "DISABLE", // 5 + "ENABLE", // 6 + "ENABLEDEF", // 7 + "EXIT", // 8 + "HIDE", // 9 + "NORMAL", // 10 + "PUSH", // 11 + "REQUIRED", // 12 + "RESET", // 13 + "RU", // 14 + "SHOW", // 15 + "UNDO" // 16 + }; + + TToken_string* message = (TToken_string*)_message.objptr(num); + if (message == NULL || message->empty()) return FALSE; + + TToken_string msg(16, ','); + TString256 value; + + for (const char* m = message->get(0); m && *m; m = message->get()) + { + KEY key = 0; + msg = m; + value = msg.get(); + const char* dlg = msg.get(); + + int cmd = -1; + if (isalpha(value[0])) // binary search + { + int f = 0, l = MAX_CMD-1; + while (TRUE) + { + cmd = (f+l)>>1; + const int cmp = strcmp(value, commands[cmd]); + if (cmp == 0) break; + if (cmp > 0) f = cmd+1; + else l = cmd-1; + if (f > l) + { + cmd = -1; + break; + } + } + } + + if (cmd == 8) + { + mask().stop_run(atoi(dlg)); + continue; + } else + if (cmd == 14) + { + run_app(mask(), msg); + continue; + } + + + short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; + bool broadcast = dlg && strchr(dlg, '@'); + if (value[0] == '"') value = value.strip("\"'"); + else switch (cmd) + { + case 0: + modify_list(TRUE, mask().field(fld), msg); continue; + case 1: + key = 11000+'c'; break; + case 2: + value = copy_value(msg, get()); break; + case 3: + modify_list(FALSE, mask().field(fld), msg); continue; + case 4: + mask().field(fld).set_dirty(); continue; + case 5: + key = 11000+'d'; break; + case 6: + key = 11000+'e'; break; + case 7: + key = 11000+'E'; break; + case 9: + key = 11000+'h'; break; + case 10: + mask().efield(fld).check_type(CHECK_NORMAL); continue; + case 11: + key = K_SPACE; break; + case 12: + mask().efield(fld).check_type(CHECK_REQUIRED); continue; + case 13: + key = K_F2; break; + case 15: + key = 11000+'s'; break; + case 16: + key = K_F3; break; + default: + key = atoi(value); + break; + } + + if (key) + { + if (key > 0) + { + if (broadcast) fld = -fld; + send_key(key, fld); + } + } + else + { + // Setta a value il campo fld solo se ha un valore diverso da value + if (broadcast) + { + for (int i = 0; i < mask().fields(); i++) + { + TMask_field& f = mask().fld(i); + if (f.in_group((int)fld)) + { + const char* prev = f.get(); + if (value != prev) + { + f.set(value); + if (f.shown() || f.ghost()) + f.on_hit(); + } + } + } + } + else + { + TMask_field& f = mask().field(fld); + const char* prev = f.get(); + if (value != prev) + { + f.set(value); + if (f.shown() || f.ghost()) + f.on_hit(); + } + } + } + } + + return TRUE; +} + + +bool TMask_field::test_focus_change() +{ + bool ok = TRUE; + if (focusdirty()) on_key(K_TAB); // Comportamento normale + else if (is_edit() && in_key(1)) on_hit(); // Serve per eseguire gli handler autoprementi + return ok; +} + + +// Certified 90% +bool TMask_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); + if (!ok) return FALSE; + } + do_message(0); + return TRUE; +} + + +bool TMask_field::to_check(KEY k, bool checkrun) const +{ + bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); + + if (!yes && checkrun) + yes = k == K_TAB && !mask().is_running(); + + return yes; +} + +// Certified 90% +bool TMask_field::on_key(KEY key) +{ + if (key > 11000) + { + switch(key-11000) + { + case 'E': + enable_default(); break; + case 'c': + reset(); on_hit(); + case 'd': + disable(); break; + case 'e': + enable(); break; + case 'h': + hide(); break; + case 's': + show(); break; +#ifdef DBG + default : + return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); +#endif + } + return TRUE; + } + + switch(key) + { + case K_SPACE: + set_dirty(); + break; + case K_PREV: + case K_NEXT: + send_key(key, 0); + break; + case K_F1: +#if XVT_OS == XVT_OS_WIN + if (fexist("prassi.hlp")) + { + struct MULTIGUY + { + UINT mkSize; + BYTE mkKeylist; + char mkKeyphrase[16]; + } mk; + + TFilename topic(mask().source_file()); topic.ext(""); + mk.mkSize = sizeof(MULTIGUY); + mk.mkKeylist = 'M'; + strcpy(mk.mkKeyphrase, topic); + + TFilename hlp("prassi.hlp"); + const TString16 mod(topic.left(2)); + if (mod != "ba") hlp.insert(mod, 0); + + HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); + WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); + break; + } +#endif + case K_SHIFT+K_F1: + if (_help.not_empty()) + message_box(_help); + else + beep(); + set_focus(); + break; + case K_F11: + { + const char* c = ""; + if (field()) + c = field()->name(); + message_box("State utilizzando il campo %d della maschera '%s'\n" + "corrispondente al campo su file '%s'", + dlg(), (const char*)mask().source_file(), c); + set_focus(); + } + break; + + case K_F2: + if (is_edit()) set(""); + else reset(); + set_dirty(); + break; + case K_F3: + undo(); + set_dirty(); + break; + default: + break; + } + + if (_handler) + return _handler(*this, key); + + return TRUE; +} + +void TMask_field::highlight() const +{ + xvt_scr_set_focus_vobj(win()); +} + +void TMask_field::set_focus() const +{ + const bool force = mask().is_running(); + mask().set_focus_win(win(), force); +} + +HIDDEN char* const _msg = &__tmp_string[512]; +#define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) + +bool TMask_field::error_box(const char* fmt, ...) const +{ + build_msg(); + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + set_focus(); + ::error_box("%s", _msg); + set_focus(); + } + return FALSE; +} + +bool TMask_field::message_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + ::message_box("%s", _msg); + set_focus(); + return FALSE; +} + +bool TMask_field::warning_box(const char* fmt, ...) const +{ + build_msg(); + + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + set_focus(); + ::warning_box("%s", _msg); + set_focus(); + } + return FALSE; +} + +bool TMask_field::yesno_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + const bool yes = ::yesno_box("%s", _msg); + set_focus(); + return yes; +} + +KEY TMask_field::yesnocancel_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + const KEY k = ::yesnocancel_box("%s", _msg); + set_focus(); + return k; +} + +/////////////////////////////////////////////////////////// +// TList_sheet +/////////////////////////////////////////////////////////// + +// Certified 100% +TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) +: _fld(f), _row(-1) +{ + _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); +} + +// Certified 100% +TList_sheet::~TList_sheet() +{ + delete _sheet; +} + +// Certified 100% +TMask_field& TList_sheet::field(short id) const +{ return field().mask().field(id); } + + +// Certified 100% +void TList_sheet::read_item(TScanner& scanner) +{ + TToken_string ts(scanner.string()); + _sheet->add(ts); +} + + +// Certified 100% +void TList_sheet::parse_input(TScanner& scanner) +{ + _inp_id.add(scanner.pop()); +} + + +// 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()) 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 = _fld->atodlg(fld); + if (id > 0) rowsel.add(field().mask().get(id)); + else rowsel.add(""); + } + } + + TString80 fd, it; + for (int i = 0 ; i < _sheet->items(); i++) + { + TToken_string& ts =_sheet->row(i); + + ts.restart(); + for ( const char* 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 = _sheet->row(_row); + rowsel.restart(); + for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) + { + const short id = _fld->atodlg(fld); + if (t != STARTING_CHECK || field().field() == NULL) + { + TMask_field& f = field(id); + f.set(rowsel.get()); + if (field().dlg() != id) + f.on_hit(); + } + } +} + + +// Certified 100% +KEY TList_sheet::run() +{ + _row = do_input(); + + _sheet->select(_row); + + const KEY k = _sheet->run(); + + switch (k) + { + case K_ENTER: + _row = (int)_sheet->selected(); + do_output(); + break; + default: + break; + } + + return k; +} + + +// Certified 100% +bool TList_sheet::check(CheckTime t) +{ + const bool passed = (_row = do_input()) != -1; + if (passed) do_output(t); + return passed; +} + + +/////////////////////////////////////////////////////////// +// TBrowse +/////////////////////////////////////////////////////////// + +// Certified 100% +TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) +: _relation(r), _cursor(new TCursor (r, filter, key)), + _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) +{} + + +// Certified 100% +TBrowse::TBrowse(TEdit_field* f, TCursor* c) +: _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) +{} + + +// Certified 100% +TBrowse::~TBrowse() +{ + if (_relation) + { + delete _relation; + delete _cursor; + } +} + + +// Certified 100% +void TBrowse::parse_display(TScanner& scanner) +{ + const char* s; + s = scanner.string(); + _head.add(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(); + _inp_id.add(scanner.line()); + } + else // Field on the mask + { + TString80 str(s); + if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field + else scanner.push(); + _inp_id.add(str); + } +} + + +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); +} + + +bool TBrowse::parse_copy(const TString& what, const TBrowse& b) +{ + const bool all = what == "AL"; + if (all || what == "US") + { + set_insert(b.get_insert()); + _filter = b.get_filter(); + if (field()._warning.empty()) + field()._warning = b.field()._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 = TRUE; + } + return TRUE; +} + + +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(); + + byte 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.len() > 4) + yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); + else +#endif + _relation->add(j, exp, key, to, alias); // join table + } +} + + +void TBrowse::parse_insert(TScanner& scanner) +{ + const TString16 key(scanner.popkey()); + + if (key == "NO") _insert = ""; + else + { + if (key == "RU") + { + _insert = "R"; + _insert << scanner.line(); + } + else + { + _insert = "M"; + _insert << scanner.line(); + } + _insert.trim(); + } +} + + +// Certified 100% +TMask_field& TBrowse::field(short n) const +{ return _fld->mask().field(n); } + + +// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro +int TBrowse::inputs() +{ + int inp = 0; + for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) + { + + if (*fld != '"' && strchr(fld, '@') == NULL && field(atoi(fld)).is_edit()) + inp++; + } + return inp; +} + +// Ritorna il numero di campi non vuoti e non filtrati +int TBrowse::do_input(bool filter) +{ + int ne = 0; + if (_inp_id.empty()) return ne; + + TRectype& cur = _cursor->curr(); + + cur.zero(); + TRectype filtrec(cur); + + _inp_id.restart(); + _inp_fn.restart(); + + TString256 val; // Value to output + bool tofilter; + + for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) + { + if (*fld == '"') + { + val = (fld+1); + if (val.not_empty()) val.rtrim(1); + tofilter = filter; + } + else + { + const short id = _fld->atodlg(fld); + const bool filter_flag = strchr(fld, '@') != NULL; + tofilter = filter && filter_flag; + val = field(id).get(); + if (field(id).is_edit() && val.not_empty() && !filter_flag) + ne++; // Increment not empty fields count + } + + TFieldref fldref(_inp_fn.get(), 0); // Output field + fldref.write(val, _cursor->relation()); + if (tofilter) + { + if (val.empty()) val.fill('~', fldref.len(cur)); + fldref.write(val, filtrec); + } + } + + if (!filter) return ne; + + TString work(_filter.size()); + 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] == '#') + { + work << '"' << field(atoi(&_filter[++i])).get() << '"'; + while (isspace(_filter[i])) i++; + while (isdigit(_filter[i])) i++; + i--; + } + else work << _filter[i]; + } + + _cursor->setfilter(work); + _cursor->setregion(filtrec, filtrec); + + return ne; +} + + +void TBrowse::do_output(CheckTime t) +{ + if (t == FINAL_CHECK) + return; + + TString256 sum; + TToken_string flds(24, '+'); + + _out_fn.restart(); + for (const char* 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(); + if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) + { + sum.cut(0); + for(const char* fr = flds.get(0); fr; fr = flds.get()) + { + const char* val; + if (*fr == '"') + { + const TString80 v(fr); + val = v.mid(1, v.len()-2); + } + else + { + const TFieldref fld(fr, 0); + val = fld.read(_cursor->relation()); + } + sum << val; + } + + f.set(sum); + if (field().dlg() != id) + f.on_hit(); + } + } +} + + +void TBrowse::do_clear() +{ + for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) + { + TMask_field& f = field(atoi(fld)); + if (f.field() == NULL && _inp_id.get_pos(fld) < 0) + f.reset(); + } +} + + + +bool TBrowse::do_insert() +{ + bool ok = FALSE; + TString80 app; + + if (_insert[0] == 'M') + { + TString80 nm(_insert.mid(1)); + if (nm.compare("batb", 4, TRUE) == 0) // Programma gestione tabelle + app = format("ba3 -0 %s", (const char*)nm.mid(4)); + // Obbligatorio usare la format globale + else // Programma generico di browse/edit + app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); + // Obbligatorio usare la format globale + } + else + { + app = _insert.mid(1); + } + /* + #if XVT_OS == XVT_OS_WIN + if (strnicmp(app, main_app().name(), 3) == 0) + app.insert("a", 3); + #endif + */ + TMailbox mail; + TMessage msg(app, MSG_AI, ""); + mail.send(msg); + + TExternal_app a(app); + a.run(); + + if (mail.check()) + { + TMessage* rcv = mail.next_s(MSG_AI); + if (rcv != NULL) _rec = atoi(rcv->body()); + if (_rec > 0) + { + _cursor->file().readat(_rec); + ok = _cursor->ok(); + if (ok) do_output(); +#ifdef DBG + else yesnofatal_box("Selezione da programma esterno errata"); +#endif + } + } + return ok; +} + + +TToken_string& TBrowse::create_siblings(TToken_string& siblings) +{ + const TMask& mask = field().mask(); + siblings = ""; // Azzera la lista dei campi associati + + // if (!mask.is_running()) return siblings; + + TBit_array key(4); // Elenco delle chiavi gia' utilizzate + key.set(_cursor->key()); + + // Scorre la lista dei campi di output + int n = 0; + for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) + { + const short id = _fld->atodlg(i); + const TMask_field& f = mask.field(id); + if (!f.shown() || !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 == _fld->dlg())) + { + TString16 fn(_out_fn.get(n)); // Legge nome del campo su file + int pos = _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 = _items.get_pos(fn); // ... ritenta senza parentesi + } + } + if (pos >= 0) + { + siblings.add(id); + const char* h = _head.get(pos); + 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() +{ + do_input(TRUE); + _cursor->read(_isgteq); + + const TLocalisamfile& f = _cursor->file(); + TString80 caption(prefix().description(f.name())); + if (!isalnum(caption[0])) + caption = "Selezione"; + + KEY k = K_ESC; + long selected = 0; + + TToken_string siblings; + create_siblings(siblings); + +{ + TToken_string* sib = siblings.empty() ? NULL : &siblings; + byte buttons = 0; + if (_insert.not_empty()) + { + buttons = 1; // Mette il bottone di gestione, a meno che ... + + const TString& maskname = _fld->mask().source_file(); + if (maskname.compare("batb", 4, TRUE) == 0 && _fld->in_key(0)) + { + const char* tabname = _cursor->file().name(); + if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0) + buttons = 0; + } + } + + TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); + k = s.run(); + selected = s.selected(); +} + +switch (k) +{ + case K_INS: + k = do_insert() ? K_ENTER : K_ESC; + break; + case K_ENTER: + *_cursor = selected; + do_output(); + break; +default: + if (k >= K_CTRL) + { + const TMask& m = _fld->mask(); + const short id = siblings.get_int((k - K_CTRL) << 1); + TEdit_field& ef = m.efield(id); + ef.set_focus(); + k = K_F9; + if (m.is_running()) + ef.send_key(k, 0); + } + break; +} + +return k; +} + +bool TBrowse::check(CheckTime t) +{ + bool passed = TRUE; + + if (_secondary == TRUE && t != RUNNING_CHECK) + return TRUE; + + if (_fld->check_type() != CHECK_NONE) + { + const TMaskmode mode = (TMaskmode)field().mask().mode(); + + CheckType chk = _fld->check_type(); + const int ne = do_input(TRUE); + if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL; + if (ne || chk == CHECK_REQUIRED) + { + _cursor->setkey(); + _cursor->file().read(_isequal); + passed = _cursor->ok(); + + if (t != FINAL_CHECK) + { + if (passed) + { + _cursor->repos(); + do_output(t); + } + else + { + do_clear(); + if (!_fld->mask().query_mode() && _fld->check_enabled()) + _fld->set_dirty(3); + } + } + } + else + if (t != FINAL_CHECK) do_clear(); + } + return passed; +} + +bool TBrowse::empty_check() +{ + if ( field().mask().query_mode() || _fld->check_type() == CHECK_NONE || + _fld->check_type() == CHECK_NORMAL) + return TRUE; + else + return do_input() > 0; +} + + +/////////////////////////////////////////////////////////// +// TEdit_field +/////////////////////////////////////////////////////////// + +TEdit_field::TEdit_field(TMask* mask) +: TMask_field(mask), _browse(NULL), _sheet(NULL), + _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(FALSE), + _forced(FALSE) +{} + +TEdit_field::~TEdit_field() +{ + if (_browse) delete _browse; else + if (_sheet) delete _sheet; +} + +word TEdit_field::class_id() const +{ return CLASS_EDIT_FIELD; } + + +void TEdit_field::enable(bool on) +{ + TMask_field::enable(on); + if (_buttonwin != NULL_WIN) + xvt_vobj_set_visible(_buttonwin, on && check_enabled() && shown()); +} + +void TEdit_field::show(bool on) +{ + TMask_field::show(on); + if (_buttonwin != NULL_WIN) + xvt_vobj_set_visible(_buttonwin, on && check_enabled() && enabled()); +} + + +void TEdit_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); +#ifdef DBG + if (_size < 1) + { + _size = 8; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + } +#endif + _width = scanner.integer(); + if (_width == 0) _width = _size; +} + + +const TBrowse* TEdit_field::get_browse(TScanner& scanner) const +{ + const int id = scanner.integer(); + const TEdit_field& f = mask().efield(id); + const TBrowse* b = (const TBrowse*)f.browse(); +#ifdef DBG + if (b == NULL) + yesnofatal_box("La USE del campo %d e' nulla e non puo' essere copiata nel campo %d", id, dlg()); +#endif + return b; +} + + +bool TEdit_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PI") // PICTURE + { + _picture = scanner.string(); +#ifdef DBG + if (_picture == "." && _size > 9 && _size != 15) + ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", + dlg(), (const char*)_prompt); +#endif + return TRUE; + } + + if (scanner.key() == "CH") + { + scanner.pop(); + if (scanner.key() == "NO") _check = CHECK_NORMAL; + else if (scanner.key() == "RE") _check = CHECK_REQUIRED; + else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;} + else _check = CHECK_NONE; + return TRUE; + } + + if (scanner.key() == "US") // USE + { +#ifdef DBG + if (_browse != NULL) + return yesnofatal_box("USE duplicata nel campo %d", dlg()); +#endif + + int key = 1; + TRelation* r; + + const int logicnum = scanner.integer(); + TString16 tabmaskname; + + if (logicnum > 0) + r = new TRelation(logicnum); + else + { + tabmaskname = scanner.pop(); +#ifdef DBG + if (tabmaskname.len() > 4) + return yesnofatal_box("'%s' non e' una tabella valida: %d", + (const char*)tabmaskname, dlg()); +#endif + r = new TRelation(tabmaskname); + } + + if (scanner.popkey() == "KE") + { + key = scanner.integer(); +#ifdef DBG + if (key < 1 || key > 15) + { + yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); + key = 1; + } +#endif + } + else scanner.push(); + + const char* filter = ""; + if (scanner.popkey() == "SE") + filter = (const char*)scanner.line(); + else + scanner.push(); + + _browse = new TBrowse(this, r, key, filter); + + if (tabmaskname.not_empty()) + { + tabmaskname.insert("MBATB", 0); + _browse->set_insert(tabmaskname); + } + + _check_enabled = TRUE; + return TRUE; + } + + if (scanner.key() == "CO") // Copyuse + { + const TString16 what(scanner.popkey()); + + const TBrowse* b = get_browse(scanner); + if (b == NULL) return FALSE; + + if (what == "US" || what == "AL") + _browse = new TBrowse(this, b->cursor()); + + if (_browse) + { + _check_enabled = TRUE; + return _browse->parse_copy(what, *b); + } + +#ifdef DBG + return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); +#endif + } + + if (scanner.key() == "JO") + { +#ifdef DBG + if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); +#endif + _browse->parse_join(scanner); + return TRUE; + } + + if (scanner.key() == "SH") // SHEET + { +#ifdef DBG + if (_sheet) return yesnofatal_box("SHEET duplicato nel campo %d", dlg()); +#endif + _sheet = new TList_sheet(this, _prompt, scanner.string()); + _check_enabled = TRUE; + return TRUE; + } + + if (scanner.key() == "IT") // ITEM + { +#ifdef DBG + if (_sheet == NULL) return yesnofatal_box("ITEM senza SHEET nel campo %d", dlg()); +#endif + _sheet->read_item(scanner); + return TRUE; + } + + if (scanner.key() == "IN") + { + if (_browse) _browse->parse_input(scanner); else + if (_sheet) _sheet->parse_input(scanner); +#ifdef DBG + else yesnofatal_box("INPUT senza USE o SHEET nel campo %d", dlg()); +#endif + return TRUE; + } + + if (scanner.key() == "DI") + { +#ifdef DBG + if(!_browse) return yesnofatal_box("DISPLAY senza USE nel campo %d", dlg()); +#endif + _browse->parse_display(scanner); + return TRUE; + } + + if (scanner.key() == "OU") + { + if (_browse) _browse->parse_output(scanner); + else if (_sheet) _sheet->parse_output(scanner); +#ifdef DBG + else return yesnofatal_box("OUTPUT senza USE nel campo %d", dlg()); +#endif + return TRUE; + } + + if (scanner.key() == "AD") + { +#ifdef DBG + if(!_browse) return yesnofatal_box("ADD senza USE nel campo %d", dlg()); +#endif + _browse->parse_insert(scanner); + return TRUE; + } + + if (scanner.key() == "VA") + { + const char* n = scanner.pop(); + _validate_func = isdigit(*n) ? atoi(n) : -1; +#ifdef DBG + if (_validate_func < 0) + return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); +#endif + + const int _nparms = scanner.integer(); +#ifdef DBG + if (_nparms < 0 || _nparms > 100) + return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", dlg(), _nparms); +#endif + + for(int i = 0; i < _nparms; i++) + _validate_parms.add(scanner.operand()); + + return TRUE; + } + + if (scanner.key() == "WA") + { + _warning = scanner.string(); + return TRUE; + } + if (scanner.key() == "ME") + { + TFixed_string l(scanner.line().strip_spaces()); + int m = 0; + if (l[0] == '0') + { + l.ltrim(1); + l.ltrim(); + m = 1; + } + if (_message.objptr(m) == 0) + _message.add(new TToken_string(64), m); + TToken_string& ts = (TToken_string&)_message[m]; + ts.add(l); + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + + +void TEdit_field::create(WINDOW parent) +{ + const int len = create_prompt(parent); + + long bandiere = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; + if (_flags.uppercase) bandiere |= CTL_FLAG_MAC_GENEVA9; + if (_flags.password) bandiere |= CTL_FLAG_MAC_MONACO9; + + _x += len; + +#if XVTWS == WMWS + const int delta = 2; +#else + const int delta = 1; +#endif + + wincreate(WC_EDIT, _width+delta, 1, _str, parent, bandiere); + +#if XVT_OS == XVT_OS_WIN + HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW); + SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo +#endif + + if (_browse || _sheet) + { + long flags = default_flags(); + if (flags & CTL_FLAG_DISABLED) + { + flags &= ~CTL_FLAG_DISABLED; + flags |= CTL_FLAG_INVISIBLE; + } + _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, + 2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9); + } +} + +void TEdit_field::destroy() +{ + if (_buttonwin) + { xvt_vobj_destroy(_buttonwin); _buttonwin = NULL_WIN; } + TMask_field::destroy(); +} + + +void TEdit_field::set_window_data(const char* data) +{ + TMask_field::set_window_data(format(data)); +} + + +void TEdit_field::set_field_data(const char* data) +{ _str = data; } + +const char* TEdit_field::get_field_data() const +{ return _str; } + + +const char* TEdit_field::format(const char* d) +{ + fpark = d; + if (_flags.trim) fpark.trim(); + + if (fpark.not_empty()) + { + int len = fpark.len(); + if (len > _size) + { +#ifdef DBG + yesnofatal_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size); +#endif + fpark.cut(len = _size); + } + + if (len < _size) + { + if (_flags.zerofilled) + { + if (isdigit(fpark[0]) && real::is_real(fpark)) + fpark.right_just(_size, '0'); + } + else + if (_flags.rightjust) + fpark.right_just(_size); + } + + if (_flags.uppercase) + fpark.upper(); + } + + return fpark; +} + + +const char* TEdit_field::picture_data(const char* data, bool video) +{ + if (video) + { + data = format(data); + xvt_vobj_set_title(win(), (char*)data); + return get_window_data(); + } + + set_window_data(data); + TMask_field::get_window_data(); + + if (_flags.trim) fpark.trim(); + return fpark; +} + + +bool TEdit_field::validate(KEY k) +{ + return ::validate(_validate_func, *this, k, _validate_parms); +} + +// Certified 90% +bool TEdit_field::on_hit() +{ + if (_validate_func >= 0 && + (_validate_func == AUTOEXIT_FUNC || + _validate_func == NUMCALC_FUNC || + _validate_func == STRCALC_FUNC)) + { + set(get()); + bool ok = validate(is_edit() ? K_TAB : K_SPACE); // Check validation expression + if (!ok) return FALSE; + } + if (_handler) + { + bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); + if (!ok) return FALSE; + } + if (_message.objptr(1) && get() == "") do_message(1); + else do_message(0); + return TRUE; +} + +bool TEdit_field::default_error_box() const +{ + if (_warning.empty()) + { + const TString& p = prompt(); + if (isalnum(p[0])) + error_box("Valore non valido per %s: '%s'", (const char*)p, (const char*)get()); + else + error_box("Valore non valido: '%s'", (const char*)get()); + } + else + error_box(_warning); + return FALSE; +} + +bool TEdit_field::on_key(KEY key) +{ + switch(key) + { + case K_TAB: + if (_validate_func >= 0 && + (_validate_func == AUTOEXIT_FUNC || + _validate_func == NUMCALC_FUNC || + _validate_func == STRCALC_FUNC)) + set_focusdirty(); // Forza validate + if (to_check(K_TAB, TRUE)) + { + set(get()); + bool ok = validate(key); // Check validation expression + + if (!ok) + { + if (_warning.not_empty()) + error_box(_warning); + return FALSE; + } + + TMask& m = mask(); + const bool query = m.query_mode(); + + if (_sheet) ok = query || _sheet->check(); // Check consistency + else + if (_browse && check_enabled() && (!query || forced()) && _validate_func != 21) + ok = _browse->check(); + + if (!ok) return default_error_box(); + + ok = on_hit(); + if (!ok) return FALSE; + + if (query && required() && in_key(0)) + { + const byte keys = m.num_keys(); + + for (int i = 1; i <= keys; i++) + if (in_key(i) && m.key_valid(i)) + { + for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) + m.field(fld).set_dirty(FALSE); + mask().stop_run(K_AUTO_ENTER); + break; + } + } + return TRUE; + } + break; + case K_ENTER: + if (field() != NULL || mask().mode() == NO_MODE) + { + if (focusdirty()) set(get()); + + bool ok = validate(K_ENTER); // Check validation expression + if (!ok) + { + if (_warning.not_empty()) + error_box(_warning); + return FALSE; + } + + const bool query = mask().query_mode(); + + // check consistency + if (_sheet) ok = query || _sheet->check(FINAL_CHECK); + else + if (_browse && + check_enabled() && + _validate_func != 21 && // 21 = NOT_EMPTY_CHECK_FIELD + (!query || forced())) + { + if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency + else ok = _browse->empty_check(); + } + else + ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); + + if (!ok) + return default_error_box(); + } + break; + case K_F9: + if (check_enabled()) + { + enable_check(FALSE); + if (dirty()) set(get()); + KEY k = K_ESC; + if (_browse) k = _browse->run(); + else + if (_sheet) k = _sheet->run(); + else beep(); + if (k != K_F9) set_focus(); + enable_check(TRUE); + if (k == K_ENTER) + { + set_dirty(); + if (mask().is_running()) + send_key(K_TAB, 0); + else + on_hit(); + return TRUE; + } + else + return FALSE; + } + break; + default: + break; + } + + return TMask_field::on_key(key); +} + + +bool TEdit_field::has_check() const +{ + if (_browse) return check_type() != CHECK_NONE; + return _sheet != NULL; +} + +bool TEdit_field::check(CheckTime t) +{ + bool ok = TRUE; + if (check_enabled() || (t == STARTING_CHECK && shown())) + { + if (_browse) ok = (_validate_func == 21) || _browse->check(t); + else if (_sheet) ok = _sheet->check(t); + } + return ok; +} + +void TEdit_field::enable_check(bool on) +{ + _check_enabled = on; + if (_buttonwin != NULL_WIN) + xvt_vobj_set_visible(_buttonwin, on); +} + + +/////////////////////////////////////////////////////////// +// Boolean_field +/////////////////////////////////////////////////////////// + + +TBoolean_field::TBoolean_field(TMask* m) +: TMask_field(m), _on(FALSE) +{} + + +word TBoolean_field::class_id() const +{ return CLASS_BOOLEAN_FIELD; } + + +void TBoolean_field::create(WINDOW parent) +{ + wincreate(WC_CHECKBOX, _prompt.len()+4, 1, _prompt, parent, 0); +} + + +const char* TBoolean_field::get_window_data() const +{ + CHECK(win(), "Control window not initialized"); + fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; + fpark[1] = '\0'; + return fpark; +} + + +void TBoolean_field::set_window_data(const char* data) +{ + CHECK(win(), "Control window not initialized"); + + if (data == NULL) data = ""; + const bool b = toupper(*data) == 'X'; + xvt_check_box(win(), b); +} + + +void TBoolean_field::set_field_data(const char* data) +{ + if (data == NULL) data = ""; + _on = toupper(*data) == 'X'; +} + +const char* TBoolean_field::get_field_data() const +{ + return _on ? "X" : " "; +} + + +bool TBoolean_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "ME") + { + const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE + + if (_message.items() == 0) + { + _message.add(new TToken_string(16)); + _message.add(new TToken_string(16)); + } + TToken_string& ts = (TToken_string&)_message[tf]; + ts.add(scanner.line().strip_spaces()); + + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + +void TBoolean_field::enable(bool on) +{ + _flags.enabled = on; + xvt_enable_control(_win, on); +} + + +bool TBoolean_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, K_SPACE); + if (!ok) return FALSE; + } + const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; + do_message(n); + return TRUE; +} + +bool TBoolean_field::on_key(KEY key) +{ + if (key == K_SPACE) + { + on_hit(); + set_dirty(); + return TRUE; + } + return TMask_field::on_key(key); +} + +/////////////////////////////////////////////////////////// +// Button_field +/////////////////////////////////////////////////////////// + +TButton_field::TButton_field(TMask* m) +: TMask_field(m) +{ + _flags.persistent = TRUE; +} + + +word TButton_field::class_id() const +{ return CLASS_BUTTON_FIELD; } + +void TButton_field::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + if (_width < 1) _width = 9; + _size = scanner.integer(); // Height + if (_size < 1) _size = 1; +} + + +bool TButton_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PI") + { + const int bmp = scanner.integer(); + _prompt << '#' << bmp; + return bmp > 0; + } + return TMask_field::parse_item(scanner); +} + + +void TButton_field::create(WINDOW parent) +{ + long flags = CTL_FLAG_CENTER_JUST; + + switch (dlg()) + { + case DLG_OK: + if (_prompt.empty()) + _prompt = "Conferma"; + _virtual_key = _exit_key = K_ENTER; + flags |= CTL_FLAG_DEFAULT; + break; + case DLG_CANCEL: + if (_prompt.empty()) + _prompt = "Annulla"; + _virtual_key = _exit_key = K_ESC; + break; + case DLG_DELREC: + if (_prompt.empty()) + _prompt = "Elimina"; + _virtual_key = 'E'; + _exit_key = K_DEL; + break; + case DLG_PRINT: + if (_prompt.empty()) + _prompt = "Stampa"; + _virtual_key = 'S'; + _exit_key = K_ENTER; + break; + case DLG_QUIT: + if (_prompt.empty()) + _prompt = "Fine"; + _virtual_key = K_F4; + _exit_key = K_QUIT; + break; + default: + { + _exit_key = 0; + TToken_string* message = (TToken_string*)_message.objptr(0); + if (message != NULL) + { + TToken_string msg(message->get(0), ','); + const TFixed_string m(msg.get(0)); + if (m == "EXIT") + _exit_key = msg.get_int(); + else + if (msg.get_int() == 0) _exit_key = atoi(m); + } + const int n = _prompt.find('~'); + _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; + } + break; + } + +#if XWTWS == WMWS + const int diesis = _prompt.find('#'); + if (diesis > 0) _prompt.cut(diesis); + _prompt.center_just(_width); +#endif + + wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); +} + +void TButton_field::enable(bool on) +{ + _flags.enabled = on; + xvt_enable_control(_win, on); +} + +void TButton_field::show(bool on) +{ + TMask_field::show(on); +} + + +bool TButton_field::on_key(KEY key) + +{ + if (key == K_SPACE) + { + on_hit(); + return TRUE; + } + return TMask_field::on_key(key); +} + +/////////////////////////////////////////////////////////// +// Date_field +/////////////////////////////////////////////////////////// + +word TDate_field::class_id() const +{ return CLASS_DATE_FIELD; } + +void TDate_field::create(WINDOW w) +{ + TEdit_field::create(w); + if (automagic()) + { + TDate d(TODAY); + set(d.string()); + } +} + +void TDate_field::parse_head(TScanner&) {} + +TDate_field::TDate_field(TMask* m) : TEdit_field(m) +{ + _size = _width = 10; +} + + +bool TDate_field::on_key(KEY key) +{ + if (to_check(key)) + { + TFixed_string data(get_window_data(), 15); + data.trim(); + if (data.not_empty()) + { + bool changed = FALSE; + if (isdigit(data[0])) + { + if (data.len() == 6) // Fix century (for this millenium only) + { + data.insert("19", 4); + changed = TRUE; + } + for (int meno = 2; meno <= 5; meno += 3) + if (data[meno] != '-') + { + data.insert("-", meno); + changed = TRUE; + } + if (data.len() == 8) // Fix century (for this millenium only) + { + data.insert("19", 6); + changed = TRUE; + } + } + else + { + TDate g(TODAY); + data.upper(); + if (data == "IERI") + { + --g; + changed = TRUE; + } + else + if (data == "DOMANI") + { + ++g; + changed = TRUE; + } + TString16 gstring(g.string()); + if (data == "PRIMO") + { + gstring.overwrite("01-01", 0); + changed = TRUE; + } + else + if (data == "NATALE") + { + gstring.overwrite("25-12", 0); + changed = TRUE; + } + else + if (data == "ULTIMO") + { + gstring.overwrite("31-12", 0); + changed = TRUE; + } + else + if (data == "OGGI") changed = TRUE; + if (changed) data = gstring; + } + + TDate d(data); + if (!d.ok()) + { + error_box("Data errata o formato non valido"); + return FALSE; + } + else + if (changed) + TMask_field::set_window_data(d.string()); + } + } + + return TEdit_field::on_key(key); +} + +const char * TDate_field::get_window_data() const +{ + const char * data = TEdit_field::get_window_data(); + if (roman()) + { + const TDate d(data); + data = d.string(ANSI); + } + return data; +} + + +void TDate_field::set_window_data(const char * data) +{ + if (roman()) + { + const TDate d(data); + data = d.string(); + } + TEdit_field::set_window_data(data); +} + +/////////////////////////////////////////////////////////// +// Real_field +/////////////////////////////////////////////////////////// + +TReal_field::TReal_field(TMask* m) : TEdit_field(m) +{} + +word TReal_field::class_id() const +{ return CLASS_REAL_FIELD; } + +void TReal_field::create(WINDOW w) +{ + TEdit_field::create(w); + _flags.rightjust = TRUE; + + if (_flags.firm) + set(::format("%ld", main_app().get_firm())); + else + if (automagic()) + { + TDate d(TODAY); + set(::format("%d", d.year())); + } +} + +bool TReal_field::autoload(const TRelation* r) +{ + const bool ok = TMask_field::autoload(r); + if (ok && _flags.zerofilled && _str.not_empty()) + { + int s = size(); + if (roman()) + { + s = decimals(); + if (s < 1) s = 4; + } + _str.right_just(s, '0'); + } + + return ok; +} + +bool TReal_field::on_key(KEY key) +{ + if (to_check(key)) + { + if (roman()) + { + const int r = atoi(get_window_data()); + if (r < 0) return error_box("Numero romano errato"); + } + else + { + const char* n = get(); + if (*n && !real::is_real(n)) + return error_box("Valore numerico non valido"); + if (_flags.uppercase && *n == '-') + return error_box("Il numero deve essere positivo"); + if (_flags.firm) + { + const long f = atol(n); + if (f > 0 && prefix().exist(f)) + main_app().set_firm(f); + else + return error_box("Ditta non utilizzabile in contabilita'"); + } + } + } + + return TEdit_field::on_key(key); +} + +void TReal_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); + +#ifdef DBG + if (_size < 1) + { + _size = 9; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + } +#endif + + _width = _size; + _decimals = scanner.integer(); +} + +void TReal_field::set_window_data(const char* data) +{ + if (data == NULL) data = ""; + + if (roman()) + { + data = itor(atoi(data)); + TMask_field::set_window_data(data); + } + else + { + real n(data); + if (!n.is_zero()) + { + if (exchangeable() && decimals()) + { + const real& e = mask().exchange(); + n /= e; + } + if (_picture.empty()) + data = n.stringa(_size, _decimals); + else + data = n.string(_picture); + } + else data = ""; + TEdit_field::set_window_data(data); + } +} + +const char* TReal_field::get_window_data() const +{ + TEdit_field::get_window_data(); + if (roman()) + { + int r = atoi(fpark); + if (r == 0) r = rtoi(fpark); + if (r > 0) + { + int s = decimals(); + if (s < 1) s = 4; + if (_flags.zerofilled) + fpark.format("%0*d", s, r); + else + fpark.format("%*d", s, r); + } + else fpark.cut(0); + } + else + { + fpark = real::ita2eng(fpark); + if (exchangeable() && decimals()) + { + real n(fpark); + const real& e = mask().exchange(); + n *= e; + if (n.is_zero()) fpark.cut(0); + else fpark = n.string(); + } + } + + return fpark; +} + +void TReal_field::set_decimals(int d) +{ + _decimals = d; + if (_picture[0] == '.') + { + if (d > 0) _picture.format(".%d", d); + else _picture = "."; + } +} + + +void TReal_field::exchange(bool show_value, const real& nuo) +{ + const int dec = show_value ? 2 : 0; // Quanti decimali voglio + const bool value = decimals() != 0; // Sono attualmente in valuta ? + + if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito! + + if (mask().is_running()) + { + const char* n = get_window_data(); + if (*n) + { + const real& vec = mask().exchange(); + real r(n); + if (!show_value) + r *= nuo; + r /= vec; + r.round(dec); + set_decimals(dec); + TEdit_field::set_window_data(r.string(_picture)); + } + } + + if (decimals() != dec) + set_decimals(dec); +} + +/////////////////////////////////////////////////////////// +// List_field +/////////////////////////////////////////////////////////// + +TList_field::TList_field(TMask* m) : TMask_field(m) +{} + +word TList_field::class_id() const +{ + return CLASS_LIST_FIELD; +} + + +void TList_field::read_item(TScanner& scanner) +{ + TToken_string ts(scanner.string()); + _codes.add(ts.get()); + _values.add(ts.get()); + + ts = ""; + while (scanner.popkey() == "ME") + ts.add(scanner.line().strip_spaces()); + scanner.push(); + + _message.add(ts); +} + + +void TList_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); + _width = scanner.integer(); + if (_width < 1) _width = _size+3; +} + + +bool TList_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "IT") // ITEM + { + read_item(scanner); + return TRUE; + } + + if (scanner.key() == "LI") // LISTITEM + { + TScanner sc(scanner.pop()); + while (sc.popkey() == "IT") // ITEM + read_item(sc); + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + + +int TList_field::items() const +{ + return _codes.items(); +} + +void TList_field::add_item(const char* s) +{ + TToken_string t(s); + const TString16 item(t.get()); + const int pos = _codes.get_pos(item); + + if (pos < 0 ) + { + _codes.add(item); + xvt_list_add(win(), -1, (char*)t.get()); + } +} + + +void TList_field::delete_item(const char* s) +{ + TString16 t(s); + const int pos = _codes.get_pos(t); + + if (pos >= 0 ) + { + _codes.destroy(pos); + xvt_list_rem(win(), pos); + if (mask().is_running()) + { + xvt_list_set_sel(win(), 0, TRUE); + if (shown()) on_hit(); + } + } +} + + +void TList_field::add_list() +{ + if (roman() && _codes.items() < 12) + { + TString csafe, vsafe; + if (atoi(_codes) > 0) + { + csafe = _codes; _codes = ""; + vsafe = _values; _values = ""; + } + _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); + _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); + _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); + if (atoi(csafe) > 0) + { + _codes.add(csafe); + _values.add(vsafe); + if (_message.objptr(0)) + { + _message.add(_message[0], _codes.items()-1); + _message.add(NULL, 0); + } + } + } + + SLIST lst = xvt_slist_create(); + for (const char* item = _values.get(0); item; item = _values.get()) + xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); + xvt_list_add(win(), -1, (char*)lst); + xvt_slist_destroy(lst); + + const char* init = ""; + if (roman() && automagic()) + init = format("%02d", TDate(TODAY).month()); + set_field_data(init); +} + + +void TList_field::replace_items(const char* codes, const char* values) +{ + _codes = codes; + _values = values; + + if (win() != NULL_WIN) + { + xvt_list_clear(win()); + add_list(); + current(0); + } +} + + +void TList_field::create(WINDOW parent) +{ + const int len = create_prompt(parent); + _x += len; + + wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); + add_list(); +} + + +int TList_field::str2curr(const char* data) +{ + TString16 str(data); + + if (roman() && str.len() < 2) + str.insert("0",0); + if (_flags.uppercase) + str.upper(); + + int i = str.not_empty() ? _codes.get_pos(str) : 0; + + if (i < 0) // Se non trova il codice ritenta dopo trim + { + for (i = 0; str[i] == '0' || str[i] == ' '; i++); + if (i > 0) + { + str.ltrim(i); + i = _codes.get_pos(str); + } + } + + if (i < 0) + { + if (items() && str.not_empty()) + yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", + data, prompt(), dlg()); + i = 0; + } + return i; +} + + +void TList_field::set_window_data(const char* data) +{ + CHECKD(win(), "Control window not initialized ", dlg()); + const int i = str2curr(data); + current(i); +} + + +void TList_field::current(int n) +{ + xvt_list_set_sel(win(), n, TRUE); +} + +int TList_field::current() const +{ + const int sel = xvt_list_get_sel_index(win()); +#ifdef DBG + if (sel < 0 && items() > 0) + error_box("Lista senza selezione nel campo %d", dlg()); +#endif + return sel; +} + +const char* TList_field::get_window_data() const +{ + const int c = current(); + const char* v = ((TList_field*)this)->_codes.get(c); + return v; +} + +void TList_field::set_field_data(const char* data) +{ + const int i = str2curr(data); + _str = _codes.get(i); +} + +bool TList_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, K_SPACE); + if (!ok) return FALSE; + } + const int n = mask().is_running() ? current() : str2curr(_str); + do_message(n); + return TRUE; +} + +const char* TList_field::get_field_data() const +{ + return _str; +} + +bool TList_field::on_key(KEY key) +{ + if (key >= '0' && key <= 'z') + { + const int index = xvt_list_get_sel_index(win()); + CHECK(index >= 0, "List with no selection!"); + int newindex = -1; + +#if XVTWS == WMWS + if (key >= 'A' && key <= 'z') + { + for (int i = index+1; i != index; i++) + { + char item[16]; + bool flag; + + do + { + flag = xvt_list_get_elt(win(), i, item, 16); + if (!flag) + { + CHECK(i, "La lista e' vuota!"); + i = -1; + break; + } + } while (!flag); + if (flag && toupper(*item) == toupper(key)) + { + newindex = i; + break; + } + } // for + } // alphabetic +#endif + + if (key >= '0' && key <= '9') + { + newindex = (key == '0') ? 10 : key - '1'; + if (newindex > items()) + { + newindex = -1; + beep(); + } + } + + if (newindex >= 0) + { + xvt_list_suspend(win()); + xvt_list_set_sel(win(), index, FALSE); + xvt_list_set_sel(win(), newindex, TRUE); + xvt_list_resume(win()); + } + } // alphanumeric + +#if XVTWS == VMWS + if (key == K_TAB && class_id() == CLASS_LIST_FIELD) + dispacth_e_char(win(), K_F9); +#endif + + if (key == K_SPACE) on_hit(); + + return TMask_field::on_key(key); +} + + +/////////////////////////////////////////////////////////// +// TRadio_field +/////////////////////////////////////////////////////////// + +TRadio_field::TRadio_field(TMask* mask) +: TList_field(mask), _nitems(0), _active_item(0) +{} + + +word TRadio_field::class_id() const +{ + return CLASS_RADIO_FIELD; +} + + +void TRadio_field::create(WINDOW parent) +{ + const short id = dlg(); // Salva il control id + const int items = _codes.items(); + + if (_prompt.not_empty()) + { + const int dy = _flags.zerofilled ? 3 : items+2; + create_prompt(parent, _width, dy); + } + _x++; _y++; + _values.restart(); + + const char* s; + + const int width = _flags.zerofilled ? (_width-2)/items-1 : _width-2; + for(_nitems = 0; (s = _values.get()) != NULL; _nitems++) + { + CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); + + wincreate(WC_RADIOBUTTON, width, 1, s, parent,0); + _radio_ctl_win[_nitems] = _win; + _dlg += 1000; + + if (_flags.zerofilled) + _x += width+1; + else + _y++; + } + _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug + + _dlg = id; // Ripristina control id + + set_field_data(""); +} + +void TRadio_field::destroy() +{ + if (_promptwin) + { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } + + for(int i = 0; i < _nitems; i++) + { + xvt_vobj_destroy(_radio_ctl_win[i]); + _radio_ctl_win[i] = NULL_WIN; + } +} + + +int TRadio_field::current() const +{ + const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); + return c; +} + + +void TRadio_field::current(int n) +{ + _active_item = n; + xvt_check_radio_button(win(), _radio_ctl_win, _nitems); +} + + +void TRadio_field::check_radiobutton(WINDOW checked) +{ + for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); + CHECK(i < _nitems, "Trying to check an invalid radio button"); + current(i); +} + + +void TRadio_field::enable(bool on) +{ + _flags.enabled = on; + for(int i = 0; i < _nitems; i++) + xvt_enable_control(_radio_ctl_win[i], on); +} + + +void TRadio_field::show(bool on) +{ + if (_promptwin) + xvt_vobj_set_visible(_promptwin, on); + + for(int i = 0; i < _nitems; i++) + xvt_vobj_set_visible(_radio_ctl_win[i], on); + _flags.shown = on; +} + +// Return TRUE if focus has left the radio +bool TRadio_field::move_focus(int d) +{ + const int act = _active_item + d; + if (act >= _nitems || act < 0) + { + _active_item = current(); + return TRUE; + } + xvt_set_front_control(_radio_ctl_win[_active_item = act]); + return FALSE; +} + + +/////////////////////////////////////////////////////////// +// TGroup_field +/////////////////////////////////////////////////////////// + +TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) +{ + _flags.persistent = TRUE; +} + +// _size means _heigth +void TGroup_field::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + _size = scanner.integer(); +} + +void TGroup_field::create(WINDOW parent) +{ + const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; + wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); +} + + +void TGroup_field::set_window_data(const char* data) +{ xvt_set_title(win(), data); } + +void TGroup_field::set_field_data(const char* data) +{ xvt_set_title(win(), data); } + diff --git a/include/validate.cpp b/include/validate.cpp index 04a1a4f5e..c13621f70 100755 --- a/include/validate.cpp +++ b/include/validate.cpp @@ -472,7 +472,21 @@ HIDDEN bool _reqif_val(TEdit_field& f, KEY k) HIDDEN bool _autoexit_val(TEdit_field& f, KEY key) { - if (f.mask().mode() != MODE_QUERY) return TRUE; + TMask& m = f.mask(); + + if (m.mode() != MODE_QUERY) return TRUE; + + const int next = m.next_fld(); + + if (next != DLG_NULL && next != f.dlg() && m.field(next).in_key(0)) + { + const byte last = m.num_keys(); + + for (byte k = 1; k <= last; k++) + if (f.in_key(k) && m.field(next).in_key(k)) + return TRUE; + } + const int nparms = get_val_param_num(); bool one_not_empty = FALSE; for (int i = nparms; i-- > 0;)