#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // @doc INTERNAL // @func HIDDEN void | smart_trim | Elimina gli spazi iniziali e/o finali da un stringa HIDDEN void smart_trim( TString & s, // @parm Stringa byte mode // @parm operazione da effettuare ( 0 = nessuna operazione // 1 = trimma a sinistra // 2 = trimma a destra // 3 = trimma da entrambi i lati ) { switch (mode) { case 1: s.ltrim(); break; case 2: s.rtrim(); break; case 3: s.trim(); break; default: break; } } /////////////////////////////////////////////////////////// // 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 = button = false; dirty = focusdirty = false; roman = read_only = false; firm = ghost = false; password = false; trim = 3; pipeallowed = false; user = false; } // Certified 100% char TMask_field::TField_Flags::update(const char* f, bool reset) { const char * s; for (s = f; *s; s++) switch(*s) { case '#': trim = 2; break; case '@': trim = 1; break; case ' ': case '_': trim = 0; break; case '*': password = !reset; break; case 'A': automagic = persistent = !reset; break; case 'B': button = !reset; break; case 'D': enable_default = enabled = reset; break; case 'F': firm = persistent = !reset; break; case 'G': ghost = !reset; break; case 'H': show_default = shown = reset; break; case 'I': break; // reserved for sheetfield insert case 'L': read_only = !reset; break; case 'M': roman = !reset; break; case 'P': persistent = !reset; break; case 'R': rightjust = !reset; break; case 'T': user = !reset; break; case 'U': uppercase = !reset; break; case 'Z': zerofilled = !reset; break; default : break; } return *s; } /////////////////////////////////////////////////////////// // TField_property_sheet /////////////////////////////////////////////////////////// class TField_property_sheet : public TProperty_sheet { public: TField_property_sheet(const TOperable_field& f); }; TField_property_sheet::TField_property_sheet(const TOperable_field& f) : TProperty_sheet(f.prompt(), 60, 10) { add_cat(TR("Sorgente")); TFilename fn = f.mask().source_file(); fn.lower(); add_prop(TR("Maschera"), fn); add_prop(TR("Personalizzata"), fn.find("custom") > 0 ? "Si" : "No"); if (f.mask().get_sheet() != NULL) add_prop(TR("Spreadsheet"), f.mask().get_sheet()->dlg()); add_cat(TR("Informazioni")); TString16 id; id << f.dlg(); // p.add_prop(TR("Tipo"), class_name()); // Per ora ritorna sempre "Field"! add_prop(TR("Identificatore"), id); add_prop(TR("Lunghezza"), long(f.size())); if (f.help().full()) add_prop(TR("Help"), f.help()); add_prop(TR("Obbligatorio"), f.required() ? TR("Si") : TR("No")); add_cat(TR("Database")); id.cut(0); if (f.field() != NULL) { const TIsam_handle f0 = atoi(f.field()->id()); if (f0 <= 0) { if (main_app().class_id() == CLASS_RELATION_APPLICATION) { TRelation_application& ra = (TRelation_application&)main_app(); id = ra.get_relation()->file(0).name(); } } else id << f0; TString80 str; str << *f.field(); add_prop(TR("Campo"), str); } else { // add_prop(TR("Campo"), TR("Nessuno")); ??? if (class_id() == CLASS_EDIT_FIELD || is_kind_of(CLASS_EDIT_FIELD)) { const TEdit_field& ef = (TEdit_field&)f; const TBrowse* b = ef.browse(); if (b != NULL && b->cursor() != NULL) id = b->cursor()->file(0).name(); } } if (id.full()) { add_prop(TR("Tabella"), id); add_prop(TR("Descrizione"), prefix().description(id)); } } /////////////////////////////////////////////////////////// // TMask_field /////////////////////////////////////////////////////////// TMask_field::TControl_data TMask_field::_ctl_data; void TMask_field::TControl_data::reset() { _dlg = -1; _x = _y = -1; _width = 0; _height = 1; _size = 0; _decimals = 0; _bmp_up = _bmp_dn = 0; _prompt.cut(0); _flags.cut(0); _park.spaces(256); _park.cut(0); } void TMask_field::update_flags(const char* f, bool reset) { _flags.update(f, reset); show(shown()); enable(enabled()); set_read_only(read_only()); } TMask_field::TMask_field(TMask* m) : _mask(m), _groups(NULL), _ctl(NULL) { } // Certified 100% TMask_field::~TMask_field() { if (_ctl) delete _ctl; if (_groups) delete _groups; } // 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::is_kind_of(word cid) const { return cid == CLASS_FIELD || TObject::is_kind_of(cid); } // Certified 100% bool TMask_field::ok() const { return _ctl != NULL; } // Certified 100% void TMask_field::parse_head(TScanner&) {} short TMask_field::dlg() const { return _ctl ? _ctl->id() : _ctl_data._dlg; } void TMask_field::highlight() const { #ifdef DBG yesnofatal_box("Can't set the focus to non-operable field %d", dlg()); #endif } void TMask_field::set_focus() const { #ifdef DBG yesnofatal_box("Can't set the focus to non-operable field %d", dlg()); #endif } void TMask_field::set_justify(bool r) { _flags.rightjust = r; if (_ctl) _ctl->set_rjust(r); } void TMask_field::set_read_only(bool r) { _flags.read_only = r && !in_key(1); if (_ctl) _ctl->set_read_only(_flags.read_only); } // @doc INTERNAL // Certified 100% // @mfunc Converte una stringa in un identificatore di campo. short TMask_field::atodlg( const char* s) const // @parm stringa da convertire in numero // @comm In modo DBG controlla anche che sia un numero valido { short d = (s && *s) ? atoi(s) : 0; #ifdef DBG if (d == 0 || d < -1 || d > 1000) { yesnofatal_box("Identificatore non valido nel campo %d: '%s'", _ctl_data._dlg, s); d = DLG_NULL; } #endif return d; } // @doc EXTERNAL // @mfunc Imposta la posizione void TMask_field::set_caret_pos( int pos) // @parm Posizione { _ctl->set_caret_pos(pos); } // @doc EXTERNAL // @mfunc Costruisce il campo void TMask_field::construct( short id, // @parm Identificatore del campo const char* prompt, // @parm Prompt del campo int x, // @parm Posizione in x (in caratteri) del campo nella maschera int y, // @parm Posizione in y (in caratteri) del campo nella maschera int len, // @parm Lunghezza del buffer campo WINDOW parent, // @parm Finestra padre alla quale assegnare il campo const char* flags, // @parm Flags del campo (default "") int width, // @parm Lunghezza a video del campo short bmp_up, // @parm Immagine standard del bottone short bmp_dn) // @parm Immagine spremuta del bottone // @parm TScanner& | scanner | File dal quale leggere leggere le informazioni // @syntax void construct(TScanner& scanner, WINDOW parent); // @syntax void construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags, int width); // // @comm E' possibile costruire il campo leggendo direttamente dal file, oppure passare alla funzione // tutti i parametri necessari alla definizione del campo stesso { _ctl_data.reset(); _ctl_data._x = x; _ctl_data._y = y; _ctl_data._prompt = prompt; _ctl_data._size = len; switch(class_id()) { case CLASS_REAL_FIELD: ((TReal_field*)this)->set_decimals(width); _ctl_data._width = len; break; case CLASS_BUTTON_FIELD: case CLASS_BUTTON_TOOL: _ctl_data._height = len; _ctl_data._width = width <= 0 ? 12 : width; _ctl_data._bmp_up = bmp_up; _ctl_data._bmp_dn = bmp_dn; break; case CLASS_MEMO_FIELD: _ctl_data._height = len; _ctl_data._width = width; _ctl_data._size = len * width; break; case CLASS_TREE_FIELD: case CLASS_OUTLOOK_FIELD: _ctl_data._height = len; _ctl_data._width = width; _ctl_data._size = 0; break; default: _ctl_data._width = width == 0 ? len : width; break; } _ctl_data._dlg = id; _ctl_data._flags = flags; _flags.update(flags); create(parent); } void TMask_field::construct(TScanner& scanner, WINDOW parent) { _ctl_data.reset(); _ctl_data._dlg = atodlg(scanner.pop()); parse_head(scanner); scanner.popkey(); // BEGIN #ifdef DBG const TMask& m = mask(); if (scanner.key() != "BE") { NFCHECK("Testata errata o BEGIN mancante nel campo %d della maschera", _ctl_data._dlg, (const char*)m.source_file()); scanner.push(); } if (_ctl_data._dlg > 0) { FOR_EACH_MASK_FIELD(m, i, mf) { if (mf->dlg() == _ctl_data._dlg && mf->parent() == parent) NFCHECK("Esistono due campi con identificatore %d", _ctl_data._dlg); } } #endif while(scanner.popkey() != "EN") // END of control parse_item(scanner); create(parent); } void TMask_field::destroy() { if (_ctl != NULL) _ctl->destroy(); } void TMask_field::set_group(byte group) { if (_groups == NULL) _groups = new TBit_array; _groups->set(long(group)); _groups->set(0L); } bool TMask_field::parse_item(TScanner& scanner) { if (scanner.key() == "PR") // PROMPT { _ctl_data._x = scanner.integer(); _ctl_data._y = scanner.integer(); _ctl_data._prompt = dictionary_translate_prompt(scanner.string(), is_editable() ? 0 : -1); return true; } if (scanner.key() == "FL") // FLAGS { const char* f = scanner.string(); if (_flags.update(f) == '\0') _ctl_data._flags << f; return true; } if (scanner.key() == "GR") { if (_groups == NULL) _groups = new TBit_array; _groups->set(scanner.line()); return true; } NFCHECK("'%s' Token non riconosciuto nel campo %d: %s", (const char*)scanner.token(), (int)dlg(), (const char*)_ctl_data._prompt); return false; } // Certified 100% WINDOW TMask_field::parent() const { CHECK(_ctl, "Can't get the parent of a NULL control"); return _ctl->parent(); } RCT& TMask_field::get_rect(RCT& r) const { if (_ctl) _ctl->get_rect(r); else memset(&r, 0, sizeof(r)); return r; } void TMask_field::set_rect(const RCT& r) { if (_ctl) _ctl->set_rect(r); } void TMask_field::set_rect(short cx, short cy, short cwidth, short cheight, short clen) { if (_ctl) _ctl->set_rect(cx, cy, cwidth, cheight, clen); } // Certified 100% // @doc EXTERNAL // @mfunc Abilita/disabilita il campo (lo rende scrivibile) void TMask_field::enable( bool on) // @parm Operazione da svolgere: // // @flag true | Abilita il campo (default) // @flag false | Disabilita il campo { _flags.enabled = on; } // Certified 100% void TMask_field::enable_default() { const bool ed = _flags.enable_default; enable(ed); } // Certified 100% // @doc EXTERNAL // @mfunc Permette di rendere visibile/invisibile un campo void TMask_field::show( bool on) // @parm Operazione da svolgere: // // @flag true | Rendere visibile il campo (default) // @flag false | Rendere invisibile il campo { if (_ctl) { _ctl->show(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 is_operable() && enabled() && shown() && !read_only(); } void TMask_field::set_dirty(byte d) { if (_flags.dirty == 3) { if (d == false) // Non permette di annullare il dirty dei campi errati return; } _flags.dirty = d; set_focusdirty(d != 0); } // Certified 100% const char* TMask_field::prompt() const { return _ctl ? _ctl->caption() : ""; } // Certified 100% void TMask_field::reset() { if (!_flags.persistent) set(""); } // Certified 100% void TMask_field::set_prompt(const char* p) { if (_ctl) _ctl->set_caption(p); } int TMask_field::page() const { return _mask->win2page(parent()); } void TMask_field::set(const char*) { // Place holder } void TMask_field::set(long n) { TString16 s; s << n; set(s); } const TString& TMask_field::get() const { return EMPTY_STRING; } long TMask_field::get_long() const { return atol(get()); } void TMask_field::set_default(const char*) { NFCHECK("Only loadables can have a default"); } const TString& TMask_field::get_default() const { NFCHECK("Only loadables can have a default"); return EMPTY_STRING; } const TString & TMask_field::evaluate_field(short id) const { if (id == 0) return get(); const TMask* m = &mask(); if (id < 0) { TSheet_field* sh = m->get_sheet(); if (sh != NULL) { m = &sh->mask(); id = -id; } } const int pos = m->id2pos(id); if (pos >= 0) return m->fld(pos).get(); return EMPTY_STRING; } const TString & TMask_field::evaluate_field(const char * s) const { if (s && *s) { if (s[0] == '#') s++; const short id = atoi(s); return evaluate_field(id); } return EMPTY_STRING; } // @doc EXTERNAL // @mfunc Verifica se il campo deve essere sottoposto a check // // @rdesc Ritorna il risultato: // // @flag true | Se il campo e' da sottoporre a check // @flag false | Se il campo non e' da sottoporre check bool TMask_field::to_check( KEY k, // @parm Tasto da passare al campo come simulazione di inizio controllo bool checkrun) const // @parm Permette di ritornare true se la maschera e' in start_run() mode { bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); if (!yes && checkrun) yes = k == K_TAB && !mask().is_running(); return yes; } void TMask_field::send_key(KEY k, short to) { _mask->send_key(k, to, this); } void TMask_field::check_type(CheckType) { CHECK(0, "Can't set check type to non-edit field"); } void TMask_field::set_handler(CONTROL_HANDLER) { CHECK(0, "Can't set the handler to a TMask_field"); } bool TMask_field::on_hit() { CHECK(0, "Can't hit non-operable field"); return false; } // Certified 100% bool TMask_field::on_key(KEY key) { #ifdef DBG if (key > (K_CTRL+K_SPACE)) return error_box("Tasto ignorato %d", key); #endif return true; } #define build_msg() \ char* _msg = _ctl_data._park.get_buffer(256); \ va_list argptr; va_start(argptr,fmt); \ vsprintf(_msg,fmt,argptr);va_end(argptr) // @doc EXTERNAL // @mfunc Crea una error-box relativo al campo (chiama ) // // @rdesc Ritorna sempre false bool TMask_field::error_box( const char* fmt, // @parm Formato della stringa da scrivere ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti // viene creata una finestra di errore normale. { build_msg(); TMask& m = mask(); if (m.is_sheetmask() && !m.is_running()) m.get_sheet()->error_box(_msg); else m.post_error_message(_msg, 3); return false; } bool TMask_field::message_box(const char* fmt, ...) const { build_msg(); mask().post_error_message(_msg, 1); return false; } // @doc EXTERNAL // @mfunc Crea una warning-box relativo al campo (chiama ) // // @rdesc Ritorna sempre false bool TMask_field::warning_box( const char* fmt, // @parm Formato della stringa da scrivere ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti // viene creata una finestra di warning normale. { build_msg(); if (mask().is_sheetmask() && !mask().is_running()) { xvt_dm_post_speech(_msg, 1, true); xvtil_statbar_set(_msg); beep(1); } else { mask().post_error_message(_msg, 2); } 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; } /////////////////////////////////////////////////////////// // TText_field /////////////////////////////////////////////////////////// // Certified 100% word TText_field::class_id() const { return CLASS_TEXT_FIELD; } // Certified 100% bool TText_field::is_kind_of(word cid) const { return cid == CLASS_TEXT_FIELD || TMask_field::is_kind_of(cid); } // Certified 100% void TText_field::create(WINDOW parent) { _ctl = new TText_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, 0, 1, _ctl_data._flags, _ctl_data._prompt); } /////////////////////////////////////////////////////////// // TGroup_field /////////////////////////////////////////////////////////// // Certified 100% word TGroup_field::class_id() const { return CLASS_GROUPBOX_FIELD; } TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) { _flags.persistent = true; } // _size means _heigth void TGroup_field::parse_head(TScanner& scanner) { _ctl_data._width = scanner.integer(); _ctl_data._size = scanner.integer(); } void TGroup_field::create(WINDOW parent) { _ctl = new TGroupbox_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._size, _ctl_data._flags, _ctl_data._prompt); } /////////////////////////////////////////////////////////// // TOperable_field /////////////////////////////////////////////////////////// TOperable_field::TOperable_field(TMask* m) : TMask_field(m), _message(NULL), _handler(NULL), _help(NULL) { } TOperable_field::~TOperable_field() { if (_help) delete _help; if (_message) delete _message; } TToken_string* TOperable_field::message(int m, bool crea) { TToken_string* msg = _message ? _message->rowptr(m) : NULL; if (msg == NULL && crea) { if (_message == NULL) _message = new TString_array(2); msg = new TToken_string(16); _message->add(msg, m); } return msg; } bool TOperable_field::parse_item(TScanner& scanner) { if (scanner.key() == "HE") // HELP { _help = new TString(scanner.string()); return true; } if (scanner.key() == "ME") { const TString& m = scanner.line().trim(); // Togli spazi message(0, true)->add(m); return true; } return TMask_field::parse_item(scanner); } void TOperable_field::set_focus() const { mask().set_focus_field(dlg()); if (_ctl != NULL) _ctl->set_focus(); } // Certified 100% bool TOperable_field::is_kind_of(word cid) const { return cid == CLASS_OPERABLE_FIELD || TMask_field::is_kind_of(cid); } void TOperable_field::enable(bool on) { TMask_field::enable(on); if (_ctl) _ctl->enable(on); } bool TOperable_field::on_key( KEY key) // @parm Tasto notificato { switch(key) { case K_F11: if (handler(key)) { TProperty_sheet p(prompt(), 60, 10); p.add_cat(TR("Sorgente")); TFilename fn = mask().source_file(); fn.lower(); p.add_prop(TR("Maschera"), fn); p.add_prop(TR("Personalizzata"), fn.find("custom") > 0 ? "Si" : "No"); if (mask().get_sheet() != NULL) p.add_prop(TR("Spreadsheet"), mask().get_sheet()->dlg()); p.add_cat(TR("Informazioni")); TString16 id; id << dlg(); // p.add_prop(TR("Tipo"), class_name()); // Per ora ritorna sempre "Field"! p.add_prop(TR("Identificatore"), id); p.add_prop(TR("Lunghezza"), long(size())); if (_help != NULL) p.add_prop(TR("Help"), *_help); p.add_prop(TR("Obbligatorio"), required() ? TR("Si") : TR("No")); p.add_cat(TR("Database")); id.cut(0); if (field() != NULL) { const TIsam_handle f0 = atoi(field()->id()); if (f0 <= 0) { if (main_app().class_id() == CLASS_RELATION_APPLICATION) { TRelation_application& ra = (TRelation_application&)main_app(); id = ra.get_relation()->file(0).name(); } } else id << f0; TString80 str; str << *field(); p.add_prop(TR("Campo"), str); } else { // p.add_prop(TR("Campo"), TR("Nessuno")); ??? if (class_id() == CLASS_EDIT_FIELD || is_kind_of(CLASS_EDIT_FIELD)) { const TEdit_field& ef = (TEdit_field&)*this; const TBrowse* b = ef.browse(); if (b != NULL && b->cursor() != NULL) id = b->cursor()->file(0).name(); } } if (id.full()) { p.add_prop(TR("Tabella"), id); p.add_prop(TR("Descrizione"), prefix().description(id)); } p.run(); } break; case K_CTRL + K_TAB: mask().notify_focus_field(dlg()); return handler(key); default: return handler(key); } return TMask_field::on_key(key); } // 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(TMask& mask, TToken_string& msg) { TFilename a; for (const char* m = msg.get(1); m; m = msg.get()) { if (a.not_empty()) a << ' '; for (const char* f = m; *f; f++) { if (*f == '#') { mask.focus_field().evaluate_field(f); break; } else a << *f; } } TExternal_app app(a); app.run(); mask.set_focus(); } // Certified 90% bool TOperable_field::do_message(int num) { const int MAX_CMD = 18; static const char* commands[MAX_CMD] = { "ADD", // 0 "CHECK", // 1 "CLEAR", // 2 "CO", // 3 "DEL", // 4 "DIRTY", // 5 "DISABLE", // 6 "ENABLE", // 7 "ENABLEDEF", // 8 "EXIT", // 9 "HIDE", // 10 "NORMAL", // 11 "PUSH", // 12 "REQUIRED", // 13 "RESET", // 14 "RU", // 15 "SHOW", // 16 "TAB", // 17 }; TToken_string* mess = message(num); if (mess == NULL || mess->empty()) return false; TToken_string msg(16, ','); TString256 value; for (const char* m = mess->get(0); m && *m; m = mess->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 == 9) // EXIT { mask().stop_run(atoi(dlg)); continue; } else if (cmd == 15) // RUN { run_app(mask(), msg); continue; } short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; const bool broadcast = dlg && strchr(dlg, '@'); if (broadcast) fld = -fld; if (value[0] == '"') value = value.strip("\"'"); else switch (cmd) { case 0: modify_list(true, mask().field(fld), msg); continue; case 1: mask().field(fld).set_dirty(); mask().field(fld).on_key(K_TAB); continue; case 2: mask().disable(fld); mask().reset(fld); continue; case 3: value = copy_value(msg, get()); break; case 4: modify_list(false, mask().field(fld), msg); continue; case 5: mask().field(fld).set_dirty(); continue; case 6: mask().disable(fld); continue; case 7: mask().enable(fld); continue; case 8: mask().enable_default(fld); continue; case 10: mask().hide(fld); continue; case 11: mask().field(fld).check_type(CHECK_NORMAL); continue; case 12: mask().field(fld).on_hit(); continue; case 13: mask().field(fld).check_type(CHECK_REQUIRED); continue; case 14: key = K_F2; break; case 16: mask().show(fld); continue; case 17: mask().field(fld).on_key(K_TAB); continue; default: key = atoi(value); break; } if (key) { if (key > 0) send_key(key, fld); } else { // Setta a value il campo fld solo se ha un valore diverso da value if (broadcast) { const int max = mask().fields(); for (int i = 0; i < max; i++) { TMask_field& f = mask().fld(i); if (f.in_group((int)-fld)) { const TString& 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; } void TOperable_field::highlight() const { if (_ctl) _ctl->set_focus(); } bool TOperable_field::handler(KEY k) { bool ok = true; if (_handler) ok = _handler(*this, k); return ok; } // Certified 90% bool TOperable_field::on_hit() { const bool ok = handler(K_SPACE); if (ok && has_message()) do_message(0); return ok; } /////////////////////////////////////////////////////////// // TLoadable_field /////////////////////////////////////////////////////////// bool TLoadable_field::parse_item(TScanner& scanner) { if (scanner.key() == "DE") // DEFAULT { set_default(scanner.line()); return true; } return TOperable_field::parse_item(scanner); } // @cmember Ritorna il valore di default del campo const TString& TLoadable_field::get_default() const { return _default; } // @cmember Imposta il valore di default del campo void TLoadable_field::set_default(const char* def) { _default = def; } /////////////////////////////////////////////////////////// // Button_field /////////////////////////////////////////////////////////// TButton_field::TButton_field(TMask* m) : TOperable_field(m) { } word TButton_field::class_id() const { return CLASS_BUTTON_FIELD; } bool TButton_field::is_kind_of(word cid) const { return cid == CLASS_BUTTON_FIELD || TOperable_field::is_kind_of(cid); } void TButton_field::parse_head(TScanner& scanner) { _ctl_data._width = scanner.integer(); if (_ctl_data._width <= 0) _ctl_data._width = 10; _ctl_data._height = scanner.integer(); // Height if (_ctl_data._height <= 0) _ctl_data._height = 1; } bool TButton_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") { const short bmp = (short)scanner.integer(); if (_ctl_data._bmp_up == 0) _ctl_data._bmp_up = bmp; else _ctl_data._bmp_dn = bmp; return bmp > 0; } return TOperable_field::parse_item(scanner); } void TButton_field::create(WINDOW parent) { _virtual_key = _exit_key = 0; switch (dlg()) { case DLG_OK: if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Conferma") _ctl_data._prompt = BR("~Conferma", _ctl_data._width); _exit_key = K_ENTER; if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("~Conferma", _ctl_data._width)) _ctl_data._bmp_up = BMP_OK; break; case DLG_CANCEL: if (_ctl_data._prompt.empty()) _ctl_data._prompt = BR("Annulla", _ctl_data._width); _virtual_key = _exit_key = K_ESC; if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("Annulla", _ctl_data._width)) _ctl_data._bmp_up = BMP_CANCEL; break; case DLG_DELREC: if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Elimina") _ctl_data._prompt = BR("~Elimina", _ctl_data._width); _exit_key = K_DEL; if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("~Elimina", _ctl_data._width)) { _ctl_data._bmp_up = BMP_DELREC; _ctl_data._bmp_dn = BMP_DELRECDN; } break; case DLG_PRINT: if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Stampa") _ctl_data._prompt = BR("~Stampa", _ctl_data._width); _exit_key = K_ENTER; if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == BR("~Stampa", _ctl_data._width)) _ctl_data._bmp_up = BMP_PRINT; break; case DLG_QUIT: if (_ctl_data._prompt.empty()) _ctl_data._prompt = BR("Fine", _ctl_data._width); _virtual_key = K_F4; _exit_key = K_QUIT; if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == BR("Fine", _ctl_data._width)) { _ctl_data._bmp_up = BMP_QUIT; _ctl_data._bmp_dn = BMP_QUITDN; } break; case DLG_SELECT: if (_ctl_data._bmp_up <= 0) _ctl_data._bmp_up = BMP_SELECT; _exit_key = K_ENTER; break; default: break; } _ctl = new TPushbutton_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width+2, _ctl_data._height, _ctl_data._flags, _ctl_data._prompt, _ctl_data._bmp_up, _ctl_data._bmp_dn); TToken_string* mess = message(0); if (mess) { TToken_string msg(mess->get(0), ','); const TFixed_string m = msg.get(0); if (m == "EXIT") { _exit_key = msg.get_int(); if (_exit_key == 0) _exit_key = ((TPushbutton_control*)_ctl)->mnemonic(); } else { if (msg.get_int() == 0) _exit_key = atoi(m); } } if (_virtual_key == 0) { const char acc = ((TPushbutton_control*)_ctl)->mnemonic(); _virtual_key = (acc > ' ') ? toupper(acc) : _exit_key; } } bool TButton_field::on_key(KEY key) { bool ok = true; if (key == K_SPACE) { if (dlg() != DLG_CANCEL && dlg() != DLG_QUIT) { const TMask& m = mask(); if (parent() == m.toolwin()) ok = m.focus_field().on_key(K_TAB); } if (ok) { if (xvt_vobj_get_attr(NULL_WIN, ATTR_SPEECH_MODE) & (1<<7)) { TString str = prompt(); str.strip("~"); xvt_dm_post_speech(str, 7, true); } ok = on_hit(); if (ok && _exit_key > 0 && !has_message()) mask().stop_run(_exit_key); } } else ok = TOperable_field::on_key(key); return ok; } void TButton_field::set_bmp(short up, short dn) { ((TPushbutton_control*)_ctl)->set_bmp(up, dn); } void TButton_field::set_bmp(const char * up, const char * dn) { ((TPushbutton_control*)_ctl)->set_bmp(up, dn); } void TButton_field::set_central_icon(unsigned icon) { ((TPushbutton_control*)_ctl)->set_icon(icon); } /////////////////////////////////////////////////////////// // TEditable_field /////////////////////////////////////////////////////////// TEditable_field::TEditable_field(TMask* m) : TLoadable_field(m), _field(NULL), _prompt(NULL), _keys(NULL), _warning(NULL), _drivers(NULL), _userdata(NULL), _validate(NULL) { } TEditable_field::~TEditable_field() { if (_prompt) delete _prompt; if (_field) delete _field; if (_keys) delete _keys; if (_validate) delete _validate; if (_warning) delete _warning; if (_drivers) delete _drivers; if (_userdata) delete _userdata; } void TEditable_field::set_warning(const char* w) { if (_warning) *_warning = w; else _warning = new TString(w); if (_warning->empty()) { delete _warning; _warning = NULL; } } // Certified 100% const char* TEditable_field::prompt() const { return _prompt ? _prompt->caption() : ""; } void TEditable_field::reset_driver(short id) { if (_drivers != NULL) { if (id == 0) _drivers->destroy(); else { for (int f = _drivers->last(); f >= 0; f--) { const short fid = (short)_drivers->get_long(f); if (fid == id) _drivers->destroy(f, true); } } } } bool TEditable_field::add_driver(short id) { if (id != 0) { if (_drivers == NULL) _drivers = new TPointer_array; _drivers->add_long(id); } return id != 0; } TOperable_field* TEditable_field::get_driver(int n, bool test) const { TOperable_field* driver = NULL; if (_drivers != NULL) { const short id = (short)_drivers->get_long(n); if (id != 0) { if (id < 0) { TSheet_field* sheet = mask().get_sheet(); if (sheet) { const int pos = sheet->mask().id2pos(-id); if (pos >= 0) driver = (TOperable_field*)&sheet->mask().fld(pos); } } else { const int pos = mask().id2pos(id); if (pos >= 0) { driver = (TOperable_field*)&mask().fld(pos); if (test) { TString16 msg; msg.format("CHECK,%d", dlg()); TToken_string* tok = driver->message(0, false); if (tok == NULL || tok->get_pos(msg) < 0) driver->message(0, true)->add(msg); } } } } } return driver; } TOperable_field* TEditable_field::driver(int n) const { return get_driver(n, false); } void TEditable_field::test_drivers() const { if (_drivers != NULL) { for (int i = 0; i < _drivers->items(); i++) get_driver(i, true); } } // Ritorna il messaggio d'errore associato al campo const char* TEditable_field::get_warning() const { return _warning ? (const char*)*_warning : ""; } bool TEditable_field::parse_item(TScanner& scanner) { const TString& k = scanner.key(); if (k == "FI") // FIELD { set_field(scanner.line()); return true; } if (k == "KE") // KEY { if (_keys == NULL) _keys = new TBit_array; _keys->set(scanner.line()); _keys->set(0L); return true; } if (k == "DR") // DRIVENBY { TToken_string lista(scanner.line(), ' '); FOR_EACH_TOKEN(lista, tok) { const short id = atoi(tok); add_driver(id); } return true; } if (k == "CU") // CUSTOM DATA { if (_userdata == NULL) _userdata = new TToken_string(scanner.string()); else _userdata->add(scanner.string()); return true; } if (scanner.key() == "VA") { #ifdef DBG if (_validate) return yesnofatal_box("VALIDATE duplicata nel campo %d", _ctl_data._dlg); #endif _validate = new TValidation_data; 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, _ctl_data._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", _ctl_data._dlg, nparms); #endif for (int i = 0; i < nparms; i++) { // per risolvere problemi nelle formule // l'ultimo parametro viene letto fino in fondo alla riga if (i == nparms-1) { TString& str = scanner.line().trim(); if (str[0] == '{' && str.ends_with("}")) // caso speciale di formule tra graffe { str.rtrim(1); str.ltrim(1); } _validate->_parms.add(str); } else _validate->_parms.add(scanner.operand()); } return true; } if (scanner.key() == "WA") { const char* msg = dictionary_translate(scanner.string()); set_warning(msg); return true; } return TLoadable_field::parse_item(scanner); } void TEditable_field::set_key(byte key) { if (_keys == NULL) _keys = new TBit_array; _keys->set(long(key)); _keys->set(0L); } // Certified 90% word TEditable_field::last_key() const { long u = _keys ? _keys->last_one() : 0; if (u < 0) u = 0; return (word)u; } // Certified 90% word TEditable_field::first_key() const { if (_keys == NULL) return 0; const int last = last_key(); int i; for (i = 1; i <= last; i++) if (in_key(i) == true) break; return (word)i; } // Certified 90% bool TEditable_field::has_a_common_key(const TMask_field & f) const { const int last = last_key(); for (int i = 1; i <= last; i++) if (in_key(i) && f.in_key(i)) return true; return false; } bool TEditable_field::test_key_complete(bool normal) const { TMask& m = mask(); for (int k = 1; k <= MAX_KEYS; k++) { if (in_key(k) && m.key_valid(k)) { bool complete = true; for (TEditable_field* e = m.get_key_field(k, true); e; e = m.get_key_field(k, false)) { e->set_focusdirty(false); if (e->is_edit()) complete &= e->required(); } if (normal && !complete) m.set_test_field(dlg()); else m.stop_run(K_AUTO_ENTER); return true; } } return false; } // Certified 90% void TEditable_field::reset_key(byte key) { if (_keys) { _keys->reset(long(key)); if (key == 0 || last_key() == 0) { delete _keys; // Se non ci sono piu' chiavi azzera tutto _keys = NULL; } } } // @doc EXTERNAL // @mfunc Chiama l' eventuale funzione di validazione // // @rdesc Ritorna il risultato dell funzione di validazione: // // @flag true | Se la validata ha avuto successo // @flag false | Se la validata no ha avuto successo bool TEditable_field::validate( KEY k) // @parm Tasto da passare alla funzione di validazione { bool ok = true; if (_validate != NULL) ok = ::validate(_validate->_func, *this, k, _validate->_parms); return ok; } // Certified 90% // @doc EXTERNAL // @mfunc Crea il prompt del controllo // // @rdesc Ritorna la lunghezza del prompt creato word TEditable_field::create_prompt( WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo word width, // @parm Larghezza del controllo word height) // @parm Altezza del controllo { if (_ctl_data._prompt.not_empty()) { TString flags; if (hidden()) flags << 'H'; if (height < 3) { width = _ctl_data._prompt.len(); word i; for (i = 0; i < width && _ctl_data._prompt[(int)i] == '@'; i += 2); width -= i; _prompt = new TText_control(parent, -1, _ctl_data._x, _ctl_data._y, 0, 1, flags, _ctl_data._prompt); } else { if (right_justified()) flags << 'R'; _prompt = new TGroupbox_control(parent, -1, _ctl_data._x, _ctl_data._y, width, height, flags, _ctl_data._prompt); } } return width; } void TEditable_field::show(bool on) { TOperable_field::show(on); if (_prompt) _prompt->show(on); } void TEditable_field::set_prompt(const char* p) { if (_prompt) _prompt->set_caption(p); else NFCHECK("Can't set prompt to control %d", dlg()); } // Certified 90% void TEditable_field::set_field(const TString& fr) { if (_field != NULL) { if (fr.blank()) { delete _field; _field = NULL; } else *_field = fr; } else { if (fr.full()) _field = new TFieldref(fr, 0); } } // Certified 100% // Legge il valore attuale del campo in formato RAW const TString& TEditable_field::get() const { return _str; } // Certified 100% // Aggiusta un valore letto da file in formato RAW const char* TEditable_field::reformat(const char* data) const { return data; } // Certified 100% // Setta il valore RAW e WIN del campo con un valore RAW void TEditable_field::set(const char* data) { _str = reformat(data); const char* val = raw2win(_str); set_window_data(val); const TMask& m = mask(); if (m.is_running() || m.is_sheetmask()) set_dirty(); } // Certified 100% // Converte da formato RAW a formato WIN const char* TEditable_field::raw2win(const char* data) const { return reformat(data); } // Certified 100% // Converte da formato WIN a formato RAW const char* TEditable_field::win2raw(const char* data) const { return reformat(data); } bool TEditable_field::autosave(TRelation& r) { if (_field) _field->write(get(), r); return _field != NULL; } bool TEditable_field::autoload(const TRelation& r) { if (_field) set(_field->read(r)); return _field != NULL; } /////////////////////////////////////////////////////////// // Boolean_field /////////////////////////////////////////////////////////// TBoolean_field::TBoolean_field(TMask* m) : TEditable_field(m) {} word TBoolean_field::class_id() const { return CLASS_BOOLEAN_FIELD; } bool TBoolean_field::is_kind_of(word cid) const { return cid == CLASS_BOOLEAN_FIELD || TEditable_field::is_kind_of(cid); } void TBoolean_field::create(WINDOW parent) { _ctl = new TCheckbox_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, 0, _ctl_data._flags, _ctl_data._prompt); } void TBoolean_field::set_prompt(const char* p) { _ctl->set_caption(p); } const char* TBoolean_field::reformat(const char* data) const { return (data && *data > ' ' && *data != '0' && *data != 'N') ? "X" : ""; } void TBoolean_field::set_window_data(const char* data) { if (_ctl) ((TCheckbox_control*)_ctl)->check(*data > ' '); } TString& TBoolean_field::get_window_data() { const bool on = _ctl != NULL && ((TCheckbox_control*)_ctl)->checked(); _str = on ? "X" : ""; return _str; } bool TBoolean_field::parse_item(TScanner& scanner) { if (scanner.key() == "ME") { const bool tf = scanner.integer() != 0; // Message true or false TToken_string* ts = message(tf, true); ts->add(scanner.line().strip_spaces()); return true; } return TEditable_field::parse_item(scanner); } bool TBoolean_field::on_hit() { const bool ok = handler(K_SPACE); if (ok) { const bool on = get() == "X"; do_message(on); } return ok; } bool TBoolean_field::on_key(KEY key) { switch (key) { case K_SPACE: get_window_data(); set_dirty(); on_hit(); return true; case K_F2: if (!read_only()) { set(""); set_dirty(); } return true; default: return TEditable_field::on_key(key); } return false; } /////////////////////////////////////////////////////////// // TCheckbutton_field /////////////////////////////////////////////////////////// // Copiato da TButton::parse_item void TCheckbutton_field::parse_head(TScanner& scanner) { _ctl_data._width = scanner.integer(); if (_ctl_data._width <= 0) _ctl_data._width = 10; _ctl_data._height = scanner.integer(); // Height if (_ctl_data._height <= 0) _ctl_data._height = 1; } // Copiato da TButton::parse_item bool TCheckbutton_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") { const short bmp = (short)scanner.integer(); if (_ctl_data._bmp_up == 0) _ctl_data._bmp_up = bmp; else _ctl_data._bmp_dn = bmp; return bmp > 0; } return TOperable_field::parse_item(scanner); } void TCheckbutton_field::create(WINDOW parent) { _ctl = new TCheckbutton_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width+2, _ctl_data._height, _ctl_data._flags, _ctl_data._prompt, _ctl_data._bmp_up, _ctl_data._bmp_dn); } TCheckbutton_field::TCheckbutton_field(TMask* mask) : TBoolean_field(mask) { } /////////////////////////////////////////////////////////// // TBrowse_button /////////////////////////////////////////////////////////// TBrowse_button::TBrowse_button(TEdit_field* f) : _fld(f) { } TBrowse_button::~TBrowse_button() { } // Certified 100% TEditable_field& TBrowse_button::field(short id) const { if (id > 0) { TMask_field& f = _fld->mask().field(id); CHECKD(f.is_editable(), "Can't use in a browse the field ", id); return (TEditable_field&)f; } return *_fld; } /////////////////////////////////////////////////////////// // TList_sheet /////////////////////////////////////////////////////////// // Certified 100% TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) : TBrowse_button(f), _row(-1), _caption(caption), _head(head) { } // Certified 100% TList_sheet::~TList_sheet() { } // Certified 100% void TList_sheet::parse_input(TScanner& scanner) { _inp_id.add(scanner.pop()); } // Certified 100% void TList_sheet::parse_item(TScanner& scanner) { _data.add(new TToken_string(scanner.string())); } // Certified 100% void TList_sheet::parse_output(TScanner& scanner) { _out_id.add(scanner.pop()); } // il numero di riga selezionata int TList_sheet::do_input() { if (_inp_id.empty_items()) return -2; // List empty! _inp_id.restart(); TToken_string rowsel(80); for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { rowsel.add(fld+1); if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1); } else { const short id = field().atodlg(fld); if (id > 0) { const TMask_field& f = field(id); if (f.class_id() == CLASS_ZOOM_FIELD) { const TZoom_field& z = (TZoom_field&)f; rowsel.add(z.get_first_line()); } else rowsel.add(f.get()); } else rowsel.add(""); } } TString fd, it; for (int i = 0 ; i < _data.items(); i++) { TToken_string& ts =_data.row(i); ts.restart(); const char * item; for (item = rowsel.get(0); item ; item = rowsel.get()) { it = item; it.trim(); fd = ts.get(); fd.trim(); if (fd != it) break; } if (!item) return i; } return -1; // Value not found! } // Certified 50% void TList_sheet::do_output(CheckTime t) { if (_row < 0 || t == FINAL_CHECK) return; _out_id.restart(); TToken_string& rowsel = _data.row(_row); rowsel.restart(); for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) { const short id = field().atodlg(fld); TMask_field& f = field(id); const char* val = rowsel.get(); if (t != STARTING_CHECK || f.field() == NULL) { const bool hit = f.get() != val; f.set(val); if (hit && field().dlg() != id) { f.on_hit(); if (t == RUNNING_CHECK) f.check(); } } } } // Certified 100% KEY TList_sheet::run() { TArray_sheet sci(3, 3, -3, -3, _caption, _head); sci.rows_array() = _data; _row = do_input(); sci.select(_row); const KEY k = sci.run(); switch (k) { case K_ENTER: _row = (int)sci.selected(); do_output(); break; default: break; } return k; } // Certified 100% bool TList_sheet::check(CheckTime t) { _row = do_input(); bool passed = _row != -1; if (passed) do_output(t); else { switch(field().check_type()) { case CHECK_SEARCH: passed = true; break; default: break; } } return passed; } /////////////////////////////////////////////////////////// // TBrowse /////////////////////////////////////////////////////////// // Certified 100% TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) : TBrowse_button(f), _relation(r), _cursor(new TCursor (r, "", key)), _filter(filter), _secondary(false), _custom_filter_handler(NULL) {} // Certified 100% TBrowse::TBrowse(TEdit_field* f, TCursor* c) : TBrowse_button(f), _relation(NULL), _cursor(c), _secondary(false), _custom_filter_handler(NULL) {} // Certified 100% TBrowse::~TBrowse() { // Se e' stato usato il primo costruttore devo distruggere la relazione ed il cursore if (_relation) { delete _cursor; delete _relation; } } // Certified 100% void TBrowse::parse_display(TScanner& scanner) { const char* s = scanner.string(); _head.add(dictionary_translate_header(s)); s = scanner.line(); _items.add(s); } void TBrowse::parse_input(TScanner& scanner) { const char* s = scanner.pop(); _inp_fn.add(s); s = scanner.pop(); if (*s == '"') // Constant string { scanner.push(); TString& str = scanner.line(); _inp_id.add(str); } else // Field on the mask { CHECKS(_inp_id.get_pos(s) < 0, "Duplicate input field ", s); _inp_id.add(s); if (scanner.popkey() == "SE") _inp_id << '@'; // Special FILTERing field else scanner.push(); } } void TBrowse::parse_output(TScanner& scanner) { const char* s = scanner.pop(); #ifdef DBG field().atodlg(s); #endif _out_id.add(s); s = scanner.pop(); _out_fn.add(s); _secondary = false; } bool TBrowse::parse_copy(const TString& what, const TBrowse& b) { const bool all = what == "AL"; if (all || what == "US") { set_insert(b.get_insert()); _filter = b.get_filter(); if (!field().has_warning() && b.field().has_warning()) field().set_warning(b.field().get_warning()); if (!all) return true; } if (all || what == "IN") { _inp_id = b._inp_id; _inp_fn = b._inp_fn; if (!all) return true; } if (all || what == "DI") { _head = b._head; _items = b._items; if (!all) return true; } if (all || what == "OU") { _out_id = b._out_id; _out_fn = b._out_fn; _secondary = b.field().has_check(); } return true; } void TBrowse::parse_join(TScanner& scanner) { TString80 j(scanner.pop()); // File or table CHECKS(_relation, "Can't join to NULL relation ", (const char*)j); int to; if (scanner.popkey() == "TO") // TO keyword { const char* t = scanner.pop(); to = name2log(t); } else { to = 0; // _relation->lfile()->num(); scanner.push(); } int key = 1; if (scanner.popkey() == "KE") key = scanner.integer(); else scanner.push(); int alias = 0; if (scanner.popkey() == "AL") alias = scanner.integer(); else scanner.push(); TToken_string exp(80); if (scanner.pop() == "INTO") { const char* r = scanner.pop(); while (strchr(r, '=') != NULL) { exp.add(r); r = scanner.pop(); } } scanner.push(); #ifdef DBG if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); #endif if (isdigit(j[0])) _relation->add(atoi(j), exp, key, to, alias); // join file else { #ifdef DBG if (j.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 TString& key = scanner.popkey(); _insert.cut(0); if (key != "NO") { _insert << key[0] << scanner.line(); _insert.trim(); } } // Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro int TBrowse::input_fields() { int inp = 0; for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) { if (*fld != '"' && strchr(fld, '@') == NULL) { TMask_field& f = field(field().atodlg(fld)); if (f.active() && f.is_editable()) inp++; } } return inp; } const char* TBrowse::get_input_fields() const { return _inp_id; } const char* TBrowse::get_input_field_names() const { return _inp_fn; } void TBrowse::add_input_field(const char * id, const char * name, const int pos, bool select) { TString strid(id) ; if (select) strid << '@'; if (pos < 0) { _inp_id.add(strid); _inp_fn.add(name); } else { _inp_id.insert_at(strid, pos); _inp_fn.insert_at(name, pos); } } void TBrowse::remove_display_field(const int pos) { if (pos < 0) { _head.cut(0); _items.cut(0); } else { _head.destroy(pos); _items.destroy(pos); } } void TBrowse::copy_input(const TBrowse * b) { if (b) { _inp_id = b->_inp_id; _inp_fn = b->_inp_fn; } } void TBrowse::copy_display(const TBrowse * b) { if (b) { _head = b->_head; _items = b->_items; } } void TBrowse::copy_output(const TBrowse * b) { if (b) { _out_id = b->_out_id; _out_fn = b->_out_fn; } } void TBrowse::add_display_field(const char * hd, const char * name, const int pos) { if (pos < 0) { _head.add(dictionary_translate_header(hd)); _items.add(name); } else { _head.insert_at(dictionary_translate_header(hd), pos); _items.insert_at(name, pos); } } void TBrowse::remove_input_field(const int pos) { if (pos < 0) { _inp_id.cut(0); _inp_fn.cut(0); } else { _inp_id.destroy(pos); _inp_fn.destroy(pos); } } void TBrowse::add_output_field(const char * id, const char * name, const int pos) { if (pos < 0) { _out_id.add(id); _out_fn.add(name); } else { _out_id.insert_at(id, pos); _out_fn.insert_at(name, pos); } } void TBrowse::remove_output_field(const int pos) { if (pos < 0) { _out_id.cut(0); _out_fn.cut(0); } else { _out_id.destroy(pos); _out_fn.destroy(pos); } } const char* TBrowse::get_output_fields() const { return _out_id; } const char* TBrowse::get_output_field_names() const { return _out_fn; } // @doc INTERNAL // @mfunc Ritorna il numero di campi non vuoti e non filtrati // // @rdesc Numero di campi non vuoti e non filtrati int TBrowse::do_input( bool filter) // @parm Indica se effettuare il filtro sulla selezione // @comm Questa funzione serve ai { int ne = 0; if (_inp_id.empty()) return ne; TRectype& cur = _cursor->curr(); _cursor->file(0).zero(); // was cur.zero() che non va bene per le tabelle di modulo TRectype filtrec(cur); _inp_id.restart(); _inp_fn.restart(); TString val; // Value to output bool tofilter = false; for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { val = (fld+1); if (val.not_empty()) val.rtrim(1); tofilter = filter; } else { const TMask_field* campf = NULL; if (*fld == '-') { TSheet_field* sheet = field().mask().get_sheet(); if (sheet != NULL) { const short id = atoi(fld+1); campf = &sheet->mask().field(id); } } else { const short id = field().atodlg(fld); campf = &field(id); } if (campf != NULL) { const TMask_field& f = *campf; val = f.get(); if (f.class_id() == CLASS_DATE_FIELD && f.right_justified()) { const TDate d(val); val = d.string(ANSI); } const bool filter_flag = strchr(fld, '@') != NULL; tofilter = filter && filter_flag; if (f.is_edit() && val.not_empty() && !filter_flag) ne++; // Increment not empty fields count } } const TFieldref fldref(_inp_fn.get(), 0); // Output field fldref.write(val, *_cursor->relation()); if (tofilter) { const int len = fldref.len(cur); if (val.len() < len && cur.type(fldref.name()) == _alfafld) val.rpad(len, '~'); fldref.write(val, filtrec); } } if (!filter) return ne; TString work(_filter.size()); bool filter_update = false; for (int i = 0; _filter[i]; i++) { if (_filter[i] == '"') { do { work << _filter[i++]; } while (_filter[i] && _filter[i] != '"'); work << '"'; if (!_filter[i]) break; } else if (_filter[i] == '#') { if (_filter[++i] == '-') { TString val; TSheet_field* sheet = field().mask().get_sheet(); if (sheet != NULL) { const short id = atoi(&_filter[++i]); val = sheet->mask().field(id).get(); } work << '"' << val << '"'; } else work << '"' << field(atoi(&_filter[i])).get() << '"'; while (isspace(_filter[i])) i++; while (isdigit(_filter[i])) i++; i--; } else { work << _filter[i]; if (_filter[i] == '-' && _filter[i + 1] == '>') filter_update = true; } } _cursor->relation()->mask2rel(field().mask()); _cursor->setfilter(work, filter_update); _cursor->setregion(filtrec, filtrec); return ne; } static TBit_array s_checked; static short s_checking = 0; void TBrowse::do_output(CheckTime t) { if (t == FINAL_CHECK) return; const bool master = s_checking == 0; if (master) { s_checking = field().dlg(); s_checked.reset(); // Rendo intoccabili i campi del MIO output for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) { const short id = field().atodlg(fld); s_checked.set(id); } } TString sum; TToken_string flds(24, '+'); const TRelation& relation = *_cursor->relation(); TBit_array spotted; _out_fn.restart(); const char* fld; for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) { const short id = field().atodlg(fld); TMask_field& f = field(id); flds = _out_fn.get(); bool do_that = t != STARTING_CHECK || f.field() == NULL || (f.mask().mode() == MODE_INS && !f.in_key(0)); if (do_that && main_app().class_id() == CLASS_RELATION_APPLICATION) { // Considera a parte l'inizializzazione delle transazioni! // Non sovrascrivere con degli output campi che potrebbero essere riempiti dal .ini if (!f.empty() && f.field() != NULL) { const TMask& m = f.mask(); if (!m.is_running() && m.get_sheet() == NULL) // Maschera principale chiusa { const TRelation_application& ra = (const TRelation_application&)main_app(); if (ra.is_transaction()) do_that = false; } } } if (do_that) { sum.cut(0); for(const char* fr = flds.get(0); fr; fr = flds.get()) { if (*fr == '"') { sum << (fr+1); sum.rtrim(1); } else { const TFieldref fld(fr, 0); sum << fld.read(relation); } } bool hit = false; if (master) { f.set(sum); hit = id != s_checking; // Il mio handler viene fatto nella on_key } else { if (!s_checked[id]) { f.set(sum); s_checked.set(id); hit = true; } } spotted.set(id, hit); } } for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) { const short id = field().atodlg(fld); if (spotted[id]) { TMask_field& f = field(id); f.check(); f.on_hit(); } } if (master) s_checking = 0; } void TBrowse::do_clear(CheckTime t) { const bool master = s_checking == 0; if (master) { s_checking = field().dlg(); s_checked.reset(); // Rendo intoccabili i campi del MIO input for (const char* fld = _inp_id.get(0); fld && *fld; fld = _inp_id.get()) { if (isdigit(*fld)) { const short id = field().atodlg(fld); s_checked.set(id); } } } for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) { const short id = field().atodlg(fld); TMask_field& f = field(atoi(fld)); if (f.field() == NULL && field().dlg() != id && !s_checked[id] && _inp_id.get_pos(fld) < 0) { f.reset(); s_checked.set(id); f.on_hit(); f.check(t); } } if (master) s_checking = 0; } bool TBrowse::do_link(bool insert) { bool ok = false; TString app; if (_insert.starts_with("MTB", true)) _cursor->file().get_relapp(app); else app = _insert.mid(1); if (app.find('#') >= 0) { const TString w(app); app = ""; for (const char* f = w; *f; f++) { if (*f == '#') { const int id = atoi(++f); app << field(id).get(); while (isspace(*f)) ++f; while (isdigit(*f)) ++f; if (*f) app << ' ' << *f; else break; } else app << *f; } } TFilename msg; msg.temp("msg"); app << " /i" << msg; if (insert) { TConfig ini(msg, "Transaction"); ini.set("Action", TRANSACTION_RUN); } else { TConfig ini(msg, "Transaction"); ini.set("Action", TRANSACTION_LINK); TString8 paragraph; paragraph << _cursor->file().num(); ini.set_paragraph(paragraph); // Uso sempre la chiave 1 per collegarmi agli altri programmi const TRelation& rel = *_cursor->relation(); const RecDes& recd = rel.curr().rec_des(); // Descrizione del record della testata const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1 TString inp_val; for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = recd.Fd[nf]; const TFieldref fldref(rf.Name, 0); inp_val = fldref.read(rel); fldref.write(ini, paragraph, inp_val); } } TExternal_app a(app); a.run(); field().mask().set_focus(); if (msg.not_empty()) { TConfig ini(msg, "Transaction"); _rec = ini.get_long("Record"); if (_rec > 0 || !insert) // Modifica o cancellazione _cursor->update(); // Forza ricalcolo cursore if (_rec >= 0) { _cursor->file().readat(_rec); ok = _cursor->ok(); if (ok) { rec_cache(_cursor->file().num()).notify_change(); // Svuota eventule cache do_output(); } } ::remove(msg); } return ok; } TToken_string& TBrowse::create_siblings(TToken_string& siblings) { siblings = ""; // Azzera la lista dei campi associati TBit_array key(4); // Elenco delle chiavi gia' utilizzate key.set(_cursor->key()); TString fn; // Nome campo // Scorre la lista dei campi di output int n = 0; for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) { const short id = field().atodlg(i); const TEditable_field& f = field(id); if (!f.active() || !f.is_edit()) // Scarta i campi non editabili continue; const TEdit_field& e = (const TEdit_field&)f; const TBrowse* b = e.browse(); if (b == NULL) continue; // Scarta i campi senza ricerca const TCursor* c = b->cursor(); // Considera ricerche sullo stesso file ma con chiave diversa if (c->file().num() == _cursor->file().num() && (key[c->key()] == false || id == field().dlg())) { 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() { begin_wait(); do_input(true); _cursor->read(_isgteq); TString caption = _cursor->file().description(); if (caption.blank()) caption = TR("Selezione"); KEY k = K_ESC; long selected = 0; TToken_string siblings, vals; create_siblings(siblings); { byte buttons = 0; if (_insert.not_empty()) { // Mette il bottone di gestione, a meno che ... if (_cursor->items() == 0) buttons = 2; // Non mette il bottone collega se non ci sono elementi else buttons = 3; if (_insert[0] == 'M' || _insert[0] == 'R') { const TString& maskname = field().mask().source_file(); if (maskname.mid(2,2).compare("tb", 2, true) == 0 && field().in_key(0)) { const char* tabname = _cursor->file().name(); if (maskname.mid(4, 3).compare(tabname, 3, true) == 0) buttons = 0; } } } for (const char* i = _inp_id.get(0); i; i = _inp_id.get()) { if (*i != '\0' && *i != '"' && strchr(i, '@') == NULL) { const short id = field().atodlg(i); const TEditable_field& f = field(id); if (f.active() && f.is_editable()) { vals.add(i); vals.add(f.get()); vals.add((int)f.dirty()); } } } end_wait(); TBrowse_sheet s(_cursor, _items, caption, _head, buttons, field(), siblings, _custom_filter_handler); k = s.run(); selected = s.selected(); } switch (k) { case K_ESC: case K_QUIT: break; case K_CTRL+'G': *_cursor = selected; k = do_link(false) ? K_ENTER : K_ESC; break; case K_INS: k = do_link(true) ? K_ENTER : K_ESC; break; case K_ENTER: *_cursor = selected; do_output(); break; default: { for (const char* i = vals.get(0); i && *i; i = vals.get()) { const short id = field().atodlg(i); TEditable_field& f = field(id); f.set(vals.get()); f.set_dirty(vals.get_int()); } } if (k >= K_CTRL) // Scatta la ricerca su di una chiave alternativa { TMask& m = field().mask(); const int tag = k - K_CTRL - K_F1; const short id = siblings.get_int(tag * 2); TEdit_field& ef = m.efield(id); ef.set_focus(); k = K_F9; if (m.is_running()) m.send_key(k, id, &ef); //m.send_key(k, id); } break; } return k; } void TBrowse::set_cursor(TCursor * c) { if (_cursor != NULL) delete _cursor; _cursor = c ; } bool TBrowse::check(CheckTime t) { bool passed = true; if (_secondary == true && t != RUNNING_CHECK) return true; CheckType chk = field().check_type(); if (chk != CHECK_NONE) { const TMaskmode mode = (TMaskmode)field().mask().mode(); if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY)) chk = CHECK_NORMAL; const int ne = do_input(true); if (ne || chk == CHECK_REQUIRED) { passed = _cursor->test() == NOERR; if (t != FINAL_CHECK) { if (passed) { _cursor->repos(); do_output(t); if (t == STARTING_CHECK && field().dirty() > 1) field().set_dirty(true); } else { if (chk == CHECK_SEARCH) { passed = true; } else { do_clear(t); if (!field().mask().query_mode() && field().check_enabled()) field().set_dirty(3); } } } else { if (chk == CHECK_SEARCH) passed = true; } } else { if (chk == CHECK_SEARCH) passed = true; else { if (t != FINAL_CHECK) do_clear(t); } } } return passed; } bool TBrowse::empty_check() { if (field().mask().query_mode() || field().check_type() != CHECK_REQUIRED) return true; else return do_input() > 0; } /////////////////////////////////////////////////////////// // TFile_select /////////////////////////////////////////////////////////// TFile_select::TFile_select(TEdit_field* ef, const char* filter) : TBrowse_button(ef), _filter(filter) { } void TFile_select::parse_input(TScanner& scanner) { scanner.pop(); } void TFile_select::parse_output(TScanner& scanner) { scanner.pop(); } KEY TFile_select::run() { TFilename path; path = field().get(); if (path.full() && _filter.find('.') > 0 && !_filter.ends_with(".*")) path.ext(_filter.ext()); FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(path, &fs); bool good = xvt_dm_post_file_open(&fs, field().prompt()) == FL_OK; if (good) { xvt_fsys_convert_fspec_to_str(&fs, path.get_buffer(), path.size()); good = _filter.blank() || xvt_str_match(path.name(), _filter, false); if (good) field().set(path); else field().error_box(FR("Il nome del file non corrisponde a %s"), _filter.get_buffer()); } return good ? K_ENTER : K_ESC; } bool TFile_select::check(CheckTime ct) { const TFilename name = field().get(); if (ct != STARTING_CHECK && name.empty() && field().check_type() == CHECK_REQUIRED) return false; bool ok = _filter.empty() || xvt_str_match(name, _filter, false); if (ok && field().roman()) // Must exist ok = name.exist(); return ok; } /////////////////////////////////////////////////////////// // TDir_select /////////////////////////////////////////////////////////// TDir_select::TDir_select(TEdit_field* ef) : TBrowse_button(ef) { } void TDir_select::parse_input(TScanner& scanner) { scanner.pop(); } void TDir_select::parse_output(TScanner& scanner) { scanner.pop(); } KEY TDir_select::run() { DIRECTORY savedir; xvt_fsys_get_dir(&savedir); DIRECTORY dir; xvt_fsys_convert_str_to_dir(field().get(), &dir); bool good = xvt_dm_post_dir_sel(&dir) == FL_OK; xvt_fsys_set_dir(&savedir); if (good) { TFilename path; xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size()); field().set(path); } return good ? K_ENTER : K_ESC; } bool TDir_select::check(CheckTime ct) { const TFilename name = field().get(); if (ct != STARTING_CHECK && name.empty() && field().check_type() == CHECK_REQUIRED) return false; bool ok = true; if (field().roman()) // Must exist ok = name.exist(); return ok; } /////////////////////////////////////////////////////////// // TProfile_select /////////////////////////////////////////////////////////// TProfile_select::TProfile_select(TEdit_field* ef) : TBrowse_button(ef) { } void TProfile_select::parse_input(TScanner& scanner) { scanner.pop(); } void TProfile_select::parse_output(TScanner& scanner) { scanner.pop(); } HIDDEN int get_profile_desc(TConfig& cfg, void* jolly) { const int num = atoi(cfg.get_paragraph()); if (num > 0) { TString_array& p = *(TString_array*)jolly; TToken_string* str = new TToken_string; str->format("%4d", num); str->add(cfg.get("Description")); p.add(str); } return false; } int TProfile_select::get_descriptions(TString_array& a) const { TFilename profname; field().mask().make_profile_name(profname); TConfig prof(profname); a.destroy(); prof.for_each_paragraph(get_profile_desc, &a); a.sort(); return a.items(); } KEY TProfile_select::run() { TArray_sheet p(3, 3, -3, -3, TR("Profili"), HR("Codice@6R|Descrizione@60"), 0x6, 2); const short id = DLG_USER+1; TEdit_field& prompt = p.add_string(id, 0, PR("Salva con nome "), 1, 0, 60); p.add_button(DLG_SAVEREC, PR("~Registra"), K_CTRL+'r', TOOL_SAVEREC); prompt.set(field().get()); TMask& m = field().mask(); TFilename profname; m.make_profile_name(profname); bool running = true; KEY key; while (running) { p.destroy(); TString_array& a = p.rows_array(); get_descriptions(a); p.field(DLG_SAVEREC).enable(a.items()>0); FOR_EACH_ARRAY_ROW_BACK(a, r, row) if (field().get() == row->get(1)) break; if (r) p.select(r); key = p.run(); switch(key) { case K_ENTER: { const int num = p.row().get_int(0); TString16 para; para << m.load_profile(num); prompt.set(p.row().get(1)); running = false; } break; case K_CTRL+'r': { const TString& name = p.get(id); FOR_EACH_ARRAY_ROW_BACK(a, r, row) if (r != p.selected() && name == row->get(1)) break; if (r < 0) { const int num = p.row().get_int(0); m.save_profile(num, name); running = false; } else error_box("Esiste gia' un profilo di nome\n%s", (const char*)name); } break; case K_INS: { const TString& name = p.get(id); if (!name.blank()) { FOR_EACH_ARRAY_ROW_BACK(a, r, row) if (name == row->get(1)) break; if (r < 0) { TString16 para; para << m.save_profile(-1, name); field().set(name); running = false; } else error_box("Esiste gia' un profilo di nome\n%s", (const char*)name); } else error_box("E' necessario dare un nome al profilo"); } break; case K_DEL: { TString16 para; para << p.row().get_int(0); const TString desc = p.row().get(1); TConfig prof(profname, para); if (yesno_box("Confermare la cancellazione del profilo %s\n%s", (const char*)para, (const char*)desc)) prof.remove_all(); } break; default: running = false; break; } } field().set(prompt.get()); return key; } bool TProfile_select::check(CheckTime ct) { switch (ct) { case STARTING_CHECK: { TMask& m = field().mask(); TFilename name; m.make_profile_name(name); TString16 para; para << m.load_profile(); TConfig ini(name, para); field().set(ini.get("Description")); } break; case RUNNING_CHECK: if (!field().empty()) { const TString& name = field().get(); TString_array a; get_descriptions(a); FOR_EACH_ARRAY_ROW_BACK(a, r, row) { if (name == row->get(1)) { field().mask().load_profile(row->get_int(0)); break; } } if (r < 0) return field().error_box("Profilo inesistente"); } break; case FINAL_CHECK: if (!field().active()) { TMask& m = field().mask(); m.save_profile(); } break; default: break; } return true; } /////////////////////////////////////////////////////////// // TReport_select /////////////////////////////////////////////////////////// TReport_select::TReport_select(TEdit_field* ef, const char* classe) : TBrowse_button(ef), _classe(classe) { } void TReport_select::parse_input(TScanner& scanner) { scanner.pop(); } void TReport_select::parse_output(TScanner& scanner) { scanner.pop(); } KEY TReport_select::run() { TFilename path = field().get(); if (select_custom_file(path, "rep", _classe)) { path = path.name(); path.ext(""); field().set(path); } return path.not_empty() ? K_ENTER : K_ESC; } bool TReport_select::check(CheckTime ct) { TFilename name = field().get(); if (ct != STARTING_CHECK && name.empty() && field().check_type() == CHECK_REQUIRED) return false; bool ok = true; if (field().roman()) // Must exist ok = name.custom_path(); return ok; } /////////////////////////////////////////////////////////// // TEdit_field /////////////////////////////////////////////////////////// TEdit_field::TEdit_field(TMask* mask) : TEditable_field(mask), _check(CHECK_NONE), _forced(false), _check_enabled(false), _browse(NULL) { } TEdit_field::~TEdit_field() { if (_browse) delete _browse; } word TEdit_field::class_id() const { return CLASS_EDIT_FIELD; } void TEdit_field::set_len(short w) { } void TEdit_field::set_width(short width, short dwidth) { RCT rect; get_rect(rect); rect.right= rect.left+width; set_rect(rect); } void TEdit_field::parse_head(TScanner& scanner) { _ctl_data._size = scanner.integer(); #ifdef DBG if (_ctl_data._size <= 0) { _ctl_data._size = 8; NFCHECK("Il campo %d ha dimensione nulla: uso %d", _ctl_data._dlg, _ctl_data._size); } #endif _ctl_data._width = scanner.integer(); if (_ctl_data._width == 0) _ctl_data._width = _ctl_data._size; } const TBrowse* TEdit_field::parse_browse(TScanner& scanner) const { const TBrowse* b = NULL; const int pos = mask().id2pos(scanner.integer()); if (pos >= 0) { const TMask_field& f = mask().fld(pos); if (f.is_edit()) b = ((TEdit_field&)f).browse(); } return b; } bool TEdit_field::set_selector(char s, const TString& str) { #ifdef DBG if (_browse) NFCHECK("%cSELECT duplicato nel campo %d", s, _ctl_data._dlg); #endif if (_browse == NULL) { switch (s) { case 'D': _browse = new TDir_select(this); break; case 'F': _browse = new TFile_select(this, str); break; case 'P': _browse = new TProfile_select(this); set_default("NONE"); break; case 'R': _browse = new TReport_select(this, str); break; default: break; } _check_enabled = _browse != NULL; } return _browse != NULL; } bool TEdit_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") // PICTURE { _picture = scanner.string(); return true; } if (scanner.key() == "CH") { const TString& ct = scanner.popkey(); if (ct == "NO") _check = CHECK_NORMAL; else if (ct == "RE") _check = CHECK_REQUIRED; else if (ct == "FO") { _check = CHECK_REQUIRED; _forced = true; } else if (ct == "SE") _check = CHECK_SEARCH; 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 = NULL; TString16 tablename = scanner.pop(); const int logicnum = table2logic(tablename); if (logicnum > 0) { TFilename f = prefix().get_filename(logicnum); f.ext("dbf"); if (f.exist()) // Controlla l'esistenza del file { switch (logicnum) { case LF_TABGEN: case LF_TABCOM: case LF_TAB: case LF_TABMOD: r = new TRelation(tablename); break; default: r = new TRelation(logicnum); tablename.cut(0); } } } else error_box("Il campo %d usa il file o tabella non valida %s", dlg(), (const char*)tablename); if (scanner.popkey() == "KE") { key = scanner.integer(); #ifdef DBG if (key < 1 || key > MAX_KEYS) { yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); key = 1; } #endif } else scanner.push(); TString filter; if (scanner.popkey() == "SE") filter = (const char*)scanner.line(); else scanner.push(); if (r != NULL) { _browse = new TBrowse(this, r, key, filter); // create browse with no filter ... // ... complete relation by parsing all Join items ... while (scanner.popkey() == "JO") { if (browse()) browse()->parse_join(scanner); else scanner.line(); } scanner.push(); if (tablename.full()) { tablename.insert("MTB", 0); browse()->set_insert(tablename); } _check_enabled = true; } else { while (scanner.popkey() == "JO") scanner.line(); scanner.push(); } return true; } if (scanner.key() == "CO") // Copyuse { const TString8 what(scanner.popkey()); const TBrowse* b = parse_browse(scanner); if (b) { if (what == "US" || what == "AL") { if (_browse == NULL) _browse = new TBrowse(this, b->cursor()); else NFCHECK("COPY USE e USE nel campo %d", _ctl_data._dlg); } if (_browse) { _check_enabled = true; return browse()->parse_copy(what, *b); } } else NFCHECK("Il campo %d non puo' copiare la browse da chi non ce l'ha", _ctl_data._dlg); } if (scanner.key() == "SH") // SHEET { #ifdef DBG if (_browse) NFCHECK("SHEET duplicato nel campo %d", _ctl_data._dlg); #endif _browse = new TList_sheet(this, _ctl_data._prompt, scanner.string()); _check_enabled = true; return true; } if (scanner.key() == "FS") // FSELECT { return set_selector('F', scanner.string()); } if (scanner.key() == "DS") // DSELECT { return set_selector('D', EMPTY_STRING); } if (scanner.key() == "PS") // PSELECT { return set_selector('P', EMPTY_STRING); } if (scanner.key() == "RS") // RSELECT { return set_selector('R', scanner.string()); } if (scanner.key() == "IT") // ITEM { #ifdef DBG if (sheet() == NULL) return yesnofatal_box("ITEM senza SHEET nel campo %d", _ctl_data._dlg); else #endif sheet()->parse_item(scanner); return true; } if (scanner.key() == "IN") { if (_browse) _browse->parse_input(scanner); else scanner.line(); return true; } if (scanner.key() == "DI") { if (browse()) browse()->parse_display(scanner); else scanner.line(); return true; } if (scanner.key() == "OU") { if (_browse) _browse->parse_output(scanner); else scanner.line(); return true; } if (scanner.key() == "AD") { if (browse()) browse()->parse_insert(scanner); else scanner.line(); return true; } if (scanner.key() == "ME") { TString& l = scanner.line().strip_spaces(); int m = 0; if (l[0] == '0') { l.ltrim(1); l.ltrim(); m = 1; } message(m, true)->add(l); return true; } return TEditable_field::parse_item(scanner); } void TEdit_field::set_background() { COLOR c = NORMAL_BACK_COLOR; if (enabled()) { int status = required() ? 1 : 0; if (read_only()) status |= 2; switch (status) { case 1: if (!same_color(NORMAL_BACK_COLOR, REQUIRED_BACK_COLOR)) c = REQUIRED_BACK_COLOR; break; case 2: c = blend_colors(DISABLED_BACK_COLOR, NORMAL_BACK_COLOR, 0.5); break; case 3: c = blend_colors(DISABLED_BACK_COLOR, REQUIRED_BACK_COLOR, 0.5); break; default: break; } } ((TField_control*)_ctl)->set_back_color(c); if (_browse) ((TField_control*)_ctl)->show_button(active()); } void TEdit_field::check_type(CheckType c) { _check = c; set_background(); } void TEdit_field::set_read_only(bool r) { if (r != read_only()) { TMask_field::set_read_only(r); const bool ok = r == read_only(); if (ok) { set_background(); if (_browse != NULL && _browse->is_browse()) { TToken_string out_ids(((TBrowse*)_browse)->get_output_fields()); TMask& m = mask(); FOR_EACH_TOKEN(out_ids, fld) m.field(atoi(fld)).set_read_only(r); } } } } // Filtro magico sulle ditte esistenti HIDDEN bool firm_filter(const TRelation* rel) { const long firm = rel->curr().get_long(NDT_CODDITTA); return prefix().exist(firm); } void TEdit_field::create(WINDOW parent) { const int len = create_prompt(parent, 0, 0); _size = _ctl_data._size; _ctl_data._x += len; if (_browse) // Decide se attivare o meno il bottone di ricerca _ctl_data._flags << 'B'; if (_ctl_data._prompt.find("@g") >= 0 || _ctl_data._prompt.find("@G") >= 0) { _ctl_data._flags << '{'; _ctl_data._x += len; } if (_ctl_data._prompt.find("@b") >= 0 || _ctl_data._prompt.find("@B") >= 0) _ctl_data._flags << '}'; _ctl = new TField_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._size, _ctl_data._flags, ""); if (_browse && !enabled_default()) ((TField_control*)_ctl)->show_button(false); if (_browse && validate_func() == 24) { TCursor* cursor = browse()->cursor(); if (cursor) { const int logicnum = cursor->file().num(); if (logicnum == LF_NDITTE) cursor->set_filterfunction(firm_filter); } } if (required()) check_type(CHECK_REQUIRED); // Force color change } const char* TEdit_field::reformat(const char* str) const { TString& s = _ctl_data._park; s = str; const byte trim_mode = _flags.trim; smart_trim(s, trim_mode); if (s.not_empty()) { word len = s.len(); if (len > size()) { #ifdef DBG yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), str, _size); #endif s.cut(len = size()); } if (_flags.zerofilled) { if (len > 0 && len < size()) { if (isdigit(s[0]) && real::is_natural(s)) s.right_just(size(), '0'); } const char* w; for (w = (const char*)s; *w == '0'; w++) ; if (*w == '\0') s.cut(0); } if (_flags.rightjust && !(trim_mode & 1) && !s.blank()) s.right_just(size()); if (_flags.uppercase) s.upper(); } return s; } const char* TEdit_field::raw2win(const char* raw) const { return reformat(raw); } const char* TEdit_field::win2raw(const char* win) const { return reformat(win); } void TEdit_field::set_window_data(const char* data) { _ctl->set_caption(data); } void TEdit_field::autoselect(bool on) { _ctl->autoselect(on); } TString& TEdit_field::get_window_data() { _str = win2raw(_ctl->caption()); return _str; } // Certified 90% bool TEdit_field::on_hit() { const int vf = validate_func(); if (vf >= 0) { if (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC || vf == 21) { const bool ok = validate(K_TAB); // Check validation expression if (!ok) return false; } } const bool ok = handler(K_TAB); if (ok && has_message()) { if (empty() && message(1)) do_message(1); else do_message(0); } return ok; } // @doc EXTERNAL // @mfunc Mostra un messaggio di errore di default per il campo // // @rdesc Ritorna sempre false bool TEdit_field::default_error_box() const // @comm Se il campo non possiede un warning particolare chiama la // indicando genericamente che il valore immesso non e' valido, altrimenti // riporta il warning associato al campo { if (!has_warning()) { const TString p(prompt()); if (isalnum(p[0])) { const TString val(get()); error_box(TR("Valore non valido per %s: %s"), (const char*)p, (const char*)val); } else error_box(TR("Valore non valido: %s"), (const char*)get()); } else error_box(get_warning()); return false; } bool TEdit_field::autosave(TRelation& r) { if (_flags.user) _str = user(); return TEditable_field::autosave(r); } bool TEdit_field::on_key(KEY key) { const int vf = validate_func(); switch(key) { case K_CTRL+K_TAB: set_focusdirty(false); break; case K_TAB: /* if (vf >= 0 && (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC)) set_focusdirty(); // Forza validate */ if (to_check(K_TAB, true)) { if (class_id() == CLASS_EDIT_FIELD) // Altrimenti l'ha gia' fatto { const TString& raw = get_window_data(); set_window_data(raw2win(raw)); } bool ok = validate(key); // Check validation expression if (!ok) { if (has_warning()) default_error_box(); return false; } TMask& m = mask(); const bool query = m.query_mode(); const bool vuoto = empty(); if (_browse) { if (browse()) { // if (check_enabled() && (!query || forced()) && vf != 21) if (check_enabled() && vf != 21) { if (!query || forced()) ok = _browse->check(); else _browse->check(); } } else { ok = query || _browse->check(); // Check consistency } } if (ok) ok = on_hit(); else { if (vuoto) ok = true; else default_error_box(); } if (ok) { set_focusdirty(false); if (query && m.is_running() && in_key(0)) test_key_complete(); } else set_focusdirty(!vuoto); return ok; } else { TMask& m = mask(); bool ok = handler(K_TAB); if (ok && m.query_mode() && m.is_running() && in_key(0)) test_key_complete(); return ok; } break; case K_ENTER: // if (field() != NULL || mask().mode() == NO_MODE) { bool ok = validate(K_ENTER); // Check validation expression if (!ok) { if (has_warning()) default_error_box(); return false; } if (!mask().query_mode() /* || forced() */) { ok = !(check_type() == CHECK_REQUIRED && empty()); // check consistency if (ok && _browse) { if (browse()) { if (ok && check_enabled() && vf != 21) // 21 = NOT_EMPTY_CHECK_FIELD { if (dirty()) ok = browse()->check(FINAL_CHECK); // Check consistency else ok = browse()->empty_check(); } } else ok = _browse->check(FINAL_CHECK); } if (!ok) return default_error_box(); } } break; case K_F2: if (!read_only()) set(""); break; case K_F9: if (!read_only()) { if (check_enabled()) { if (focusdirty()) get_window_data(); KEY k = K_ESC; if (_browse) k = _browse->run(); else beep(); if (k != K_F9 && active()) set_focus(); if (k == K_ENTER) { bool ok = true; set_dirty(); // Controlla i validate che non vengono fatti da on_hit const int vf = validate_func(); if (vf >= 0 && vf != AUTOEXIT_FUNC && vf != NUMCALC_FUNC && vf != STRCALC_FUNC && vf != 21) { ok = validate(K_TAB); if (!ok && has_warning()) default_error_box(); } // Esegue handler if (ok) ok = on_hit(); if (ok) { TMask & m = mask(); if (m.is_running()) { set_focusdirty(false); // Evita doppia esecuzione handlers! if (m.query_mode() && in_key(0)) test_key_complete(); if (m.is_running()) { set_focusdirty(false); send_key(K_TAB, 0); // Passa al campo successivo } } } return ok; } else return false; } else if (_browse == NULL && has_button()) { if (focusdirty()) get_window_data(); return handler(K_F9); } } break; case K_F12: if (has_virtual_keyboard()) { TVirtual_keyboard keyboard(*this); get_window_data(); keyboard.run(); } return true; break; case K_CTRL+K_SPACE: set_dirty(true); return handler(K_SPACE); default: break; } return TEditable_field::on_key(key); } // @mfunc Controlla se il campo ha la necessita' di eseguire una ricerca sul cursore o // sulla tabella associata al momento della sua inizializzazione // // @rdesc Ritorna true se il campo ha un TArray_sheet associato oppure un TCursor_sheet // con check_type non nullo. bool TEdit_field::has_check() const { bool ok = false; if (_browse) ok = browse() == NULL || check_type() != CHECK_NONE; return ok; } bool TEdit_field::check(CheckTime t) { bool ok = true; if (check_enabled() || (t == STARTING_CHECK && shown())) { if (_browse && validate_func() != 21) ok = _browse->check(t); } return ok; } void TEdit_field::set_query_button(TBrowse_button * brw) { if (_browse) delete _browse; _browse=brw; } // @doc EXTERNAL void TEdit_field::enable(bool on) { TEditable_field::enable(on); set_background(); } // @mfunc Permette di abilitare/disabilitare un check di un campo void TEdit_field::enable_check( bool on) // @parm Operazione da svolgere // // @flag true | Abilita il check del campo (default) // @flag false | Disabilita il check del campo { _check_enabled = on; ((TField_control*)_ctl)->show_button(on && active()); } /////////////////////////////////////////////////////////// // Date_field /////////////////////////////////////////////////////////// TDate_field::TDate_field(TMask* m) : TEdit_field(m) { } word TDate_field::class_id() const { return CLASS_DATE_FIELD; } // Certified 100% bool TDate_field::is_kind_of(word cid) const { return cid == CLASS_DATE_FIELD || TEdit_field::is_kind_of(cid); } void TDate_field::create(WINDOW w) { // Elimina il flag R che si interpreta come salva in formato ANSI _ctl_data._flags.strip("AR"); TEdit_field::create(w); if (automagic()) { TDate d(TODAY); set(d.string()); } } void TDate_field::parse_head(TScanner&) { _ctl_data._size = _ctl_data._width = 10; } // @doc EXTERNAL // @mfunc Permette di formattare la data secondo i flag correnti // // @rdesc Ritorna la data formattata const char* TDate_field::win2raw( const char* datum) const // @parm Stringa contenenete la data da formattare // @comm Permette di gestire anche alcuni date particolari come: // // @flag IERI | Inserisce la data del giorno precedente a quella del sistema // @flag OGGI | Inserisce la data del sistema // @flag DOMANI | Inserisce la data del giorno successivo a quella del sistema // @flag PRIMO | Primo giorno dell'anno (01-01-aa) // @flag PASQUA | Giorno di pasqua // @flag ANGELO | Lunedi' dell'angelo // @flag NATALE | Giorno di natale (25-12-aa) // @flag ULTIMO | Ultimo giorno dell'anno (31-12-aa) { TString& s = _ctl_data._park; s = datum; s.trim(); if (s.not_empty()) { if (isdigit(s[0]) && s.len() < 10) { long d; int m, y; const int items = sscanf(s, "%ld-%d-%d", &d, &m, &y); switch(items) { case 1: d = atoi(s.left(2)); m = atoi(s.mid(2, 2)); y = atoi(s.mid(4)); break; case 2: y = 0; break; case 3: break; default: d = 0; break; } if (d > 0) { if (m <= 0 || y <= 0) { const TDate oggi(TODAY); if (m <= 0) m = oggi.month(); if (y <= 0) y = oggi.year(); } if (y < 100) y += (y <= 20) ? 2000 : 1900; s.format("%02d-%02d-%4d", int(d), m, y); } } else { bool ok = true; TDate g(TODAY); s.upper(); if (s[0] == 'I') // "IERI" { --g; } else if (s[0] == 'D') // "DOMANI" { ++g; } else if (s.starts_with("PO")) // "POSDOMANI" { g += 2; } else if (s.starts_with("PA")) // s == "PASQUA" { g.set_easter(); } else if (s.starts_with("AN")) // s == "ANGELO" { g.set_easter(); ++g; } else if (s[0] == 'A') // s == "ALTROIERI" { g -= 2; } else if (s[0] == 'P') // s == "PRIMO" { g.set_month(1); g.set_day(1); } else if (s[0] == 'N') // s == "NATALE" { g.set_month(12); g.set_day(25); } else if (s[0] == 'U') //s == "ULTIMO" { g.set_month(12); g.set_day(31); } else if (s[0] != 'O') // s != "OGGI" ok = false; if (ok) s = g.string(); } } return s; } const char* TDate_field::reformat(const char* str) const { TString& s = _ctl_data._park; s = str; if (s.len() == 8) s = TDate(str).string(); else if (s.blank()) s.cut(0); return s; } const char* TDate_field::raw2win( const char* datum) const // @parm Stringa contenenete la data da formattare { return reformat(datum); } bool TDate_field::on_key(KEY key) { if (to_check(key)) { const TString& data = get_window_data(); if (data.not_empty()) // data not empty { if (!TDate::isdate(data)) { error_box("Data errata o formato non valido"); return false; } else set_window_data(data); } } else { if (key == K_F9 && browse() == NULL) { RCT rct; get_rect(rct); TDate olddate; const TString& data = get_window_data(); if (TDate::isdate(data)) olddate = TDate(data); long ansidate = olddate.date2ansi(); ansidate = xvt_dm_post_choose_date(parent(), &rct, ansidate); const TDate newdate(ansidate); if (newdate != olddate) set(newdate.string()); return true; } if (_ctl->is_edit_key(key)) { const bool ok = isalnum(key) || key == '-'; if (!ok) beep(); return ok; } } return TEdit_field::on_key(key); } bool TDate_field::autosave(TRelation& r) { if (field()) { const char* td = get(); if (right_justified()) { TDate d(td); td = d.string(ANSI); } field()->write(td, r); return true; } return false; } /////////////////////////////////////////////////////////// // Real_field /////////////////////////////////////////////////////////// TReal_field::TReal_field(TMask* m) : TEdit_field(m) { } word TReal_field::class_id() const { return CLASS_REAL_FIELD; } // Certified 100% bool TReal_field::is_kind_of(word cid) const { return cid == CLASS_REAL_FIELD || TEdit_field::is_kind_of(cid); } void TReal_field::create(WINDOW w) { _ctl_data._flags.strip("AFM"); if (!roman()) _ctl_data._flags << 'R'; // Forza l'allineamento a destra per i numeri TEdit_field::create(w); if (_flags.firm) { TMask_field::set(prefix().get_codditta()); } else if (automagic()) TMask_field::set(TDate(TODAY).year()); } bool TReal_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") // PICTURE { _picture = scanner.string(); if (_decimals == 0) { if (_picture[0] == '.') _decimals = atoi(&_picture[1]); else { const int comma = _picture.find(','); if (comma >= 0) _decimals = _picture.len() - comma - 1; } } return true; } return TEdit_field::parse_item(scanner); } const char* TReal_field::reformat(const char* data) const { TString& str = _ctl_data._park; if (!real::is_null(data)) { const int d = decimals(); word s = size(); if ((d == 0 || roman()) && s <= 6) { str.format("%ld", atol(data)); // Gestione "veloce" degli interi } else { const real r(data); // Gestione standard dei reali str = r.string(0, decimals()); } if (_flags.zerofilled) { if (roman()) { s = d; if (s <= 0) s = 4; const real r(data); str = r.string(s, 0, '0'); } else str.right_just(s, '0'); } } else str.cut(0); return str; } bool TReal_field::on_key(KEY key) { if (to_check(key)) { const TString& n = get_window_data(); if (roman()) { const int r = atoi(n); if (r < 0) return error_box("Numero romano errato"); } else { if (!real::is_real(n)) return error_box("Valore numerico non valido"); if (_flags.uppercase && real(n).sign() < 0) return error_box("Il numero deve essere positivo"); if (key == K_TAB && _flags.firm) { const long f = atol(n); if (f > 0 && prefix().exist(f)) prefix().set_codditta(f); } } set_window_data(raw2win(n)); } else { if (_ctl->is_edit_key(key)) { bool ok = true; switch (key) { case '.': ok = !(_flags.zerofilled || _flags.roman || size() < 4); break; case ',': ok = _decimals > 0; break; case '-': ok = !_flags.uppercase; break; default : if (_flags.roman) ok = strchr("0123456789IVXLCDMivxlcdm", key) != NULL; else ok = strchr("0123456789", key) != NULL; break; } if (!ok) beep(); return ok; } else if (key == K_F12) { if (has_virtual_keyboard()) { TVirtual_numpad numpad(*this); get_window_data(); numpad.run(); } return true; } } return TEdit_field::on_key(key); } void TReal_field::parse_head(TScanner& scanner) { _ctl_data._size = scanner.integer(); #ifdef DBG if (_ctl_data._size <= 0) { _ctl_data._size = 9; yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", _ctl_data._dlg, _ctl_data._size); } #endif _ctl_data._width = _ctl_data._size; _decimals = scanner.integer(); } const char* TReal_field::raw2win(const char* data) const { TString& s = _ctl_data._park; if (data == NULL) data = ""; if (roman()) { s = itor(atoi(data)); } else { if (!real::is_null(data)) { real n(data); if (_picture.empty()) { if (_flags.zerofilled) s = n.stringa(_size, _decimals, '0'); else s = n.stringa(0, _decimals); } else { s = n.string(_picture); } const int extra = s.len() - _size; if (extra > 0) s.ltrim(extra); } else s.cut(0); } return s; } const char* TReal_field::win2raw(const char* data) const { TString& str = _ctl_data._park; if (roman()) { int r = atoi(data); if (r == 0) // Se non e' scritto in arabo converti da romano r = rtoi(data); if (r > 0) { int d = decimals(); if (d < 1) d = 4; if (_flags.zerofilled) str.format("%0*d", d, r); else str.format("%*d", d, r); } else str.cut(0); } else { real n(real::ita2eng(data)); if (n.is_zero()) str.cut(0); else { if (_flags.zerofilled) str = n.string(_size, _decimals, '0'); else str = n.string(); } } return str; } void TReal_field::set_decimals(int d) { _decimals = d; if (_picture[0] == '.') { if (d > 0) _picture.format(".%d", d); else _picture = "."; } else { if (_picture.not_empty()) { const int pdot = _picture.find(','); if (pdot >= 0) _picture.cut(pdot); if (d > 0) { _picture << ','; while (d-- > 0) _picture << '@'; } } } } /////////////////////////////////////////////////////////// // Currency_field /////////////////////////////////////////////////////////// #include // Certified 100% word TCurrency_field::class_id() const { return CLASS_CURRENCY_FIELD; } // Certified 100% bool TCurrency_field::is_kind_of(word cid) const { return cid == CLASS_CURRENCY_FIELD || TEdit_field::is_kind_of(cid); } TCurrency& TCurrency_field::get_currency(TCurrency& cur) const { const real num(get()); const char* value = NULL; real exchange; exchange_type et = _exchange_undefined; const TMask_field* d0 = driver(0); if (d0) { value = d0->get(); const TMask_field* d1 = driver(1); if (d1) { exchange = real(d1->get()); const TMask_field* d2 = driver(2); if (d2) et = d2->get().blank() ? _exchange_base : _exchange_contro; } } cur.set_num(num); cur.force_value(value, exchange, et); cur.set_price(_flags.uppercase != 0); return cur; } void TCurrency_field::set(const TCurrency& cur, bool hit) { TMask_field* d0 = (TMask_field*)driver(0); if (d0) d0->set(cur.get_value()); const real& num = cur.get_num(); if (num.is_zero()) TEdit_field::set(""); else TEdit_field::set(num.string()); if (hit) on_hit(); } const char* TCurrency_field::reformat(const char* data) const { return real::is_null(data) ? "" : data; } const char* TCurrency_field::raw2win(const char* data) const { const real num = data; if (num == ZERO) return ""; const TMask_field* d0 = driver(0); const char* value = d0 ? (const char*)d0->get() : NULL; const bool price = _flags.uppercase != 0; TCurrency cur(num, value, ZERO, _exchange_undefined, price); TString& s = _ctl_data._park; s = cur.string(true); const int extra = s.len() - size(); if (extra > 0) s.ltrim(extra); return s; } const char* TCurrency_field::win2raw(const char* data) const { TString& str = _ctl_data._park; str = data; str.strip("."); str.replace(',', '.'); bool is_formula = false; for (int i = 0; str[i]; i++) { if (strchr("0123456789.", str[i]) == NULL) { is_formula = true; break; } } real num; if (is_formula) { TExpression e(str, _numexpr, true); for (int i = e.numvar()-1; i >= 0; i--) { TMask_field* f = mask().find_by_fieldname(e.varname(i)); if (f) e.setvar(i, f->get()); } num = e.as_real(); } else num = real(str); if (num.is_zero()) str.cut(0); else { const TMask_field* d0 = driver(0); const char* value = d0 ? (const char*)d0->get() : NULL; const bool price = _flags.uppercase != 0; TCurrency cur(num, value, ZERO, _exchange_undefined, price); str = cur.get_num().string(); } return str; } bool TCurrency_field::on_key(KEY key) { if (key == K_TAB && focusdirty()) { const TString& raw = get_window_data(); set_window_data(raw2win(raw)); } else { if (_ctl->is_edit_key(key)) { bool ok = true; switch (key) { case '-': ok = !_flags.uppercase; break; case K_F12 : if (has_virtual_keyboard()) { TVirtual_numpad numpad(*this, true); get_window_data(); numpad.run(); } return true; break; default : ok = strchr("0123456789.,+*-/()", key) != NULL; break; } if (!ok) beep(); return ok; } } return TEdit_field::on_key(key); } bool TCurrency_field::autosave(TRelation& r) { return TEditable_field::autosave(r); } bool TCurrency_field::autoload(const TRelation& r) { return TEditable_field::autoload(r); } void TCurrency_field::parse_head(TScanner& scanner) { int size = scanner.integer(); if (size <= 0) size = 18; _ctl_data._size = _ctl_data._width = size; } void TCurrency_field::create(WINDOW w) { _ctl_data._flags.strip("AMZ"); _ctl_data._flags << 'R'; TEdit_field::create(w); } TCurrency_field::TCurrency_field(TMask* m) : TEdit_field(m) { } /////////////////////////////////////////////////////////// // List_field /////////////////////////////////////////////////////////// TList_field::TList_field(TMask* m) : TEditable_field(m), _size(0) { } 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()); const char* v = dictionary_translate_prompt(ts.get(), _ctl_data._width); _values.add(v); CHECKS(v == NULL || strlen(v) <= (word)_ctl_data._width, "List item is too long:", v); ts.cut(0); while (scanner.popkey() == "ME") ts.add(scanner.line().strip_spaces()); scanner.push(); *message(-1, true) = ts; } void TList_field::parse_head(TScanner& scanner) { _ctl_data._size = scanner.integer(); _ctl_data._width = scanner.integer(); if (_ctl_data._width == 0) _ctl_data._width = _ctl_data._size; } bool TList_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") // ITEM { read_item(scanner); return true; } return TEditable_field::parse_item(scanner); } int TList_field::items() const { return _codes.items(); } // @doc EXTERNAL // @mfunc Aggiunge delle voci al list sheet void TList_field::add_item( const char* s) // @parm Voci da aggiungere // @comm Se il parametro

e' passato con il formato di una // composta da codice|descrizione { TToken_string t(s); TString item(t.get()); const int pos = _codes.get_pos(item); if (pos < 0) { _codes.add(item); item = t.get(); _values.add(item); ((TListbox_control*)_ctl)->set_values(_codes, _values); } } void TList_field::delete_item(const char* s) { const TString t(s); const int pos = _codes.get_pos(t); if (pos >= 0 ) { _codes.destroy(pos); _values.destroy(pos); ((TListbox_control*)_ctl)->set_values(_codes, _values); if (pos == current()) { current(0); if (active() || ghost()) 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 = ""; } for (int i = 1; i <= 12; i++) { char num[4]; sprintf(num, "%02d", i); _codes.add(num); _values.add(itom(i)); } if (atoi(csafe) > 0) { _codes.add(csafe); _values.add(vsafe); if (message(0)) { *message(_codes.items()-1, true) = *message(0); message(0)->cut(0); } } } ((TListbox_control*)_ctl)->set_values(_codes, _values); if (roman() && automagic()) { const char* init = format("%02d", TDate(TODAY).month()); set(init); } else current(0); } const char* TList_field::win2raw(const char* data) const { // fool the compiler to keep const TToken_string& codes = ((TList_field*)this)->_codes; TToken_string& value = ((TList_field*)this)->_values; TString80 str = data; // data puo' venire da una TToken_string::get int pos = value.get_pos(str); if (pos < 0) // Ci riprovo coi codici pos = codes.get_pos(str); if (pos < 0 && (str.blank() || str == "0")) { str = codes.get(0); // Uso codes come riferimento per blank pos = 0; } CHECKS(pos >= 0, "Unknown listbox value:", data); return codes.get(pos); } const char* TList_field::raw2win(const char* data) const { // fool the compiler to keep const TToken_string& codes = ((TList_field*)this)->_codes; TToken_string& value = ((TList_field*)this)->_values; TString256 str = data; // data puo' venire da una TToken_string::get int pos = codes.get_pos(str); if (pos < 0 && (str.blank() || str == "0")) { codes.get(0, str); if (str.blank() || str == "0") pos = 0; } CHECKS(pos >= 0, "Unknown listbox code:", data); return value.get(pos); } bool TList_field::select_by_ofs(int n) { const bool changed = ((TListbox_control*)_ctl)->select_by_ofs(n); if (changed) _str = _codes.get(current()); return changed; } bool TList_field::select_by_initial(char c) { const bool changed = ((TListbox_control*)_ctl)->select_by_initial(c); if (changed) _str = _codes.get(current()); return changed; } // @doc EXTERNAL // @mfunc Sostituisce alle voci correnti quelle passate come parametri void TList_field::replace_items( const char* codes, // @parm Codici da sostituire ai correnti const char* values) // @parm Voci da sostituire a quelle correnti // @comm I parametri

e

devono essere TToken_string se lo voci da sostiutire // sono piu' di una { _codes = codes; _values = values; if (_ctl) add_list(); } void TList_field::create(WINDOW parent) { const int len = create_prompt(parent, 0, 0); _ctl_data._x += len; _size = _ctl_data._width; _ctl = new TListbox_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._flags, _ctl_data._prompt, _codes, _values); add_list(); } int TList_field::str2curr(const char* data) { TString str(data); if (roman() && str.len() < 2) str.insert("0",0); if (_flags.uppercase) str.upper(); int i = str.blank() ? 0 : _codes.get_pos(str); 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 (shown() || ghost()) { if (items() && str.not_empty()) NFCHECK("'%s' non e' un valore valido per il campo %s: %d", data, prompt(), dlg()); } i = 0; } return i; } void TList_field::reset() { if (!_flags.persistent) current(0); } void TList_field::set(const char* data) { const int i = str2curr(data); current(i); set_dirty(); } void TList_field::set_window_data(const char* data) { NFCHECK(0,"So' passato da 'sta stronza!!!"); const int i = str2curr(win2raw(data)); current(i); } void TList_field::current(int n) { if (_ctl) ((TListbox_control*)_ctl)->select(n); _str = _codes.get(n); _str.trim(); } int TList_field::current() const { int c; if (_ctl) c = ((TListbox_control*)_ctl)->selected(); else c = ((TList_field*)this)->_codes.get_pos(_str); // Fool the compiler for const sake return c; } TString& TList_field::get_window_data() { const int c = current(); _str = ((TList_field*)this)->_codes.get(c); _str.trim(); return _str; } bool TList_field::on_hit() { const bool ok = handler(K_SPACE); if (ok) { const int n = current(); do_message(n); } return ok; } bool TList_field::on_key(KEY key) { switch(key) { case K_CTRL+K_TAB: set_focusdirty(false); break; case K_SPACE: get_window_data(); set_dirty(); return on_hit(); case K_F2: if (!read_only()) current(0); break; default: if (to_check(key, true) || key == K_ENTER) { bool ok = true; if (validate_func() >= 0) { ok = validate(key); if (!ok) { if (has_warning()) return error_box(get_warning()); } } } break; } return TEditable_field::on_key(key); } // Certified 100% bool TList_field::is_kind_of(word cid) const { return cid == CLASS_LIST_FIELD || TEditable_field::is_kind_of(cid); } /////////////////////////////////////////////////////////// // TRadio_field /////////////////////////////////////////////////////////// TRadio_field::TRadio_field(TMask* mask) : TList_field(mask) { } // Annulla _ctl altrimenti verrebbe cancellato due volte essendo anche nell'array TRadio_field::~TRadio_field() { } word TRadio_field::class_id() const { return CLASS_RADIO_FIELD; } void TRadio_field::create(WINDOW parent) { const int items = _codes.items(); if (_ctl_data._prompt.full()) { const word dy = _flags.zerofilled ? 3 : items+2; create_prompt(parent, _ctl_data._width, dy); } _ctl = new TRadiobutton_control(parent, _ctl_data._dlg, _ctl_data._x + 1, _ctl_data._y + 1, _ctl_data._width - 2, _flags.zerofilled ? 1 : items, _ctl_data._flags, _values); current(0); } int TRadio_field::current() const { int c; if (_ctl) c = ((TRadiobutton_control*)_ctl)->get_checked(); else c = TList_field::current(); return c; } void TRadio_field::current(int n) { if (_ctl) ((TRadiobutton_control*)_ctl)->check_button(n); _str = _codes.get(n); _str.trim(); } bool TRadio_field::select_by_initial(char c) { for (int i = _values.items()-1; i >= 0; i--) { const char* tok = _values.get(i); if (toupper(*tok) == toupper(c) && _str != _codes.get(i)) { current(i); return true; } } return false; } /////////////////////////////////////////////////////////// // TMemo_field /////////////////////////////////////////////////////////// TMemo_field::TMemo_field(TMask* mask) : TEdit_field(mask) { } TMemo_field::~TMemo_field() { } void TMemo_field::parse_head(TScanner& scanner) { _ctl_data._width = scanner.integer(); _ctl_data._height = scanner.integer(); } void TMemo_field::create(WINDOW parent) { create_prompt(parent, 0, 1); if (_ctl_data._height > 1) _ctl_data._height--; _size = 8192; _ctl = new TMultiline_control(parent, _ctl_data._dlg, _ctl_data._x, _ctl_data._y+1, _ctl_data._width, _ctl_data._height, _size, _ctl_data._flags, ""); } // Certified 100% // Aggiusta un valore letto da file in formato RAW const char* TMemo_field::reformat(const char* data) const { return data; } const char* TMemo_field::raw2win(const char* data) const { //#ifdef XI_R4 if (strchr(data, '\r') == NULL) return data; TString& s = _ctl_data._park; s = data; s.replace('\r', '\n'); /* #else if (strchr(data, '\n') == NULL) return data; TString& s = _ctl_data._park; s = data; for (int i = 0; s[i]; i++) if (s[i] == '\n') s[i] = '\r'; #endif */ return s; } const char* TMemo_field::win2raw(const char* data) const { //#ifdef XI_R4 return data; /* #else if (strchr(data, '\r') == NULL) return data; _ctl_data._park = data; for (char* s = (char*)(const char*)_ctl_data._park; *s; s++) if (*s == '\r') *s = '\n'; return _ctl_data._park; #endif */ } bool TMemo_field::on_key(KEY k) { if (k == K_ENTER || k == K_TAB && focusdirty()) get_window_data(); return TEdit_field::on_key(k); } /////////////////////////////////////////////////////////// // Zoom_field /////////////////////////////////////////////////////////// TZoom_field::TZoom_field(TMask* mask) : TEdit_field(mask) { } TZoom_field::~TZoom_field( ) { } void TZoom_field::create(WINDOW parent) { _ctl_data._flags << 'B'; TEdit_field::create(parent); } class TZoom_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TZoom_mask(const char* prompt, int width = 70); }; bool TZoom_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_DELREC: if (e == fe_button) { reset(DLG_USER); return false; } break; default: break; } return true; } TZoom_mask::TZoom_mask(const char* prompt, int width) : TAutomask(prompt, 1, width+2, 18) { const bool select = AUTOSELECT; const bool autoend = AUTOEND; AUTOSELECT = false; AUTOEND = true; add_button_tool(DLG_OK, "", TOOL_OK); add_button_tool(DLG_DELREC, "Azzera", TOOL_DELREC); add_button_tool(DLG_CANCEL, "", TOOL_CANCEL); add_memo(DLG_USER, 0, "", 1, 0, width, -2); set_handlers(); AUTOSELECT = select; AUTOEND = autoend; } bool TZoom_field::on_key( KEY key ) { static KEY __k = 0; switch (key) { case K_TAB: if (focusdirty()) get_window_data(); break; case K_F9: if (browse() != NULL) break; case K_F8: { get_window_data(); TZoom_mask m(prompt(), size()); if (xvt_chr_is_alnum(__k)) { _str << char(__k); __k = char(0); } m.set(DLG_USER, _str.rtrim()); if (m.run() == K_ENTER && !read_only()) { _str = m.get(DLG_USER); set_window_data(raw2win(_str.rtrim())); } return true; } break; default: if (AUTOZOOM && xvt_chr_is_alnum(key)) { get_window_data(); if (_str.len() >= size()) { __k = key; if (mask().is_running()) on_key(K_F8); else { TSheet_field* s = mask().get_sheet(); if (s != NULL) dispatch_e_char(s->mask().win(), K_F8); } } } break; } return TEdit_field::on_key(key); } // Certified 100% // Aggiusta un valore letto da file in formato RAW const char* TZoom_field::reformat(const char* data) const { return data; } const char* TZoom_field::raw2win(const char* data) const { TFixed_string str(data); int a_capo = str.find('\n'); if (a_capo < 0 || a_capo > (int)size()) a_capo = min((int)size(), str.len()); const char c = str[a_capo]; str[a_capo] = '\0'; _ctl_data._park = str; str[a_capo] = c; return _ctl_data._park; } const char* TZoom_field::win2raw(const char* data) const { TString& str = _ctl_data._park; str = data; // Elimino improbabili righe successive da data int a_capo = str.find('\r'); if (a_capo >= 0) str.cut(a_capo); // Aggiungo le righe del memo a partire dalla seconda a_capo = _str.find('\n'); if (a_capo < 0 || a_capo > (int)size()) a_capo = min((int) size(), _str.len()); const char* d = _str; str << (d+a_capo); return str; } const char* TZoom_field::get_first_line() const { return raw2win(_str); }