#include #include #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT #define WIN32_LEAN_AND_MEAN #define STRICT #include #endif #include #include #include #include #include #include #include #include #define DLG_PAGETAGS 31000 HIDDEN const char* const MASK_EXT = "msk"; /////////////////////////////////////////////////////////// // PAGE BUTTONS /////////////////////////////////////////////////////////// class TPage_field : public TRadio_field { byte _def; protected: virtual void current(int) { } // Evita il reset virtual int current() const { return _def; } public: virtual void set_prompt(const char* p); void create(WINDOW parent); void set_default(byte d) { _def = d; } void show_button(int i, bool on); TPage_field(TMask* m) : TRadio_field(m) { } virtual ~TPage_field() { } }; void TPage_field::create(WINDOW parent) { _ctl = new TTagbutton_control(parent, _ctl_data._dlg, 0, 0, 80, 1, "", _values, _def); } void TPage_field::set_prompt(const char* p) { _ctl->set_caption(p); } void TPage_field::show_button(int i, bool on) { TTagbutton_control* tag = (TTagbutton_control*)_ctl; tag->show_button(i, on); } /////////////////////////////////////////////////////////// // TMask methods /////////////////////////////////////////////////////////// void TMask::init_mask() { _msg_field = 0; _msg_key = 0; _sheets = _pages = 0; // Azzera numero pagine e sheets _sheet = NULL; // Non appartiene a nessuno sheet _enabled.set(MAX_PAGES); _enabled.set(); // Abilita tutte le pagine _should_check = TRUE; _focus = _first_focus = 0; // Il primo ha il focus _page = -1; // Nessuna pagina corrente _handler = NULL; // Nessun handler utente _mode = NO_MODE; // Inizializza modo _exchange = 1.0; // Il cambio per la valuta e' la lira _error_severity = 0; _msg_field = 0; _msg_key = 0; _test_fld = -1; _last_test = -1; memset(_pagewin, 0, sizeof(_pagewin)); } TMask::TMask(const char* title, int pages, int cols, int rows, int xpos, int ypos) { init_mask(); for (_pages = 0; _pages < pages; _pages++) _pagewin[_pages] = create_interface(NULL_WIN, xpos, ypos, cols, rows, title, this, pages > 1); } // @doc EXTERNAL // @mfunc Legge la maschera da file void TMask::read_mask( const char* name, // @parm Nome della maschera da leggere (senza estensione) int num, // @parm Numero della maschera da leggere all'interno del file int max) // @parm Numero massimo di pagine che deve avere la maschera { if (max <= 0) max = MAX_PAGES; _source_file = name; _source_file.ext(MASK_EXT); _source_file.lower(); TScanner scanner(_source_file); long start_t = clock(); while (clock() == start_t) continue; // Attende scatto timer start_t = clock(); if (num == 0) _total_time = _build_time = _init_time = 0; for (int i = 0; i < num; i++) { while (scanner.ok()) if (scanner.line() == "ENDMASK") break; } init_mask(); TToken_string captions(80); main_app().begin_wait(); while (scanner.ok() && scanner.popkey() != "EN") { if (scanner.key() == "PA") { CHECKD(_pages < MAX_PAGES, "Maschera con troppe pagine: ", _pages); WINDOW w = read_page(scanner, FALSE); TString title(80); xvt_vobj_get_title(w, (char*)(const char*)title, title.size()); captions.add(title); _pagewin[_pages++] = w; if (_pages >= max) break; } else if (scanner.key() == "TO") { CHECK(toolwin() == NULL_WIN, "La maschera puo' avere una sola TOOLBAR"); _pagewin[MAX_PAGES] = read_page(scanner, TRUE); } } if (_pages <= 0) fatal_box("Impossibile leggere la maschera %s", name); if (_pages > 1 || toolwin()) add_tag_buttons(captions); if (num == 0) _total_time = clock()-start_t; main_app().end_wait(); } void TMask::add_tag_button(byte pag, TToken_string& tags, byte sel) { TPage_field* pf = new TPage_field(this); pf->_ctl_data._dlg = DLG_PAGETAGS + 100 * pag; pf->replace_items("1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16", tags); pf->set_default(sel); pf->create(_pagewin[pag]); _field.add(pf); } void TMask::add_tag_buttons(TToken_string& tags) { for (byte p = 0; p < _pages; p++) add_tag_button(p, tags, p); } void TMask::add_default_tag_buttons() { TToken_string tags(_pages * 6); for (int p = 1; p <= _pages; p++) { tags.add("Pag."); tags << p; } add_tag_buttons(tags); } TMask::TMask(const char* maskname, int num, int max) { if (maskname && *maskname) read_mask(maskname, num, max); } TMask::~TMask() { for (int p = MAX_PAGES; p >= 0; p--) if (_pagewin[p]) { if (xvt_vobj_get_attr(_pagewin[p], ATTR_NATIVE_WINDOW) != 0) xvt_vobj_destroy(_pagewin[p]); _pagewin[p] = NULL_WIN; } } word TMask::class_id() const { return CLASS_MASK; } bool TMask::is_kind_of(word c) const { if (c == CLASS_MASK) return TRUE; return TWindow::is_kind_of(c); } void TMask::open() { if (!_open || _page != 0) { _open = TRUE; if (toolwin()) xvt_vobj_set_visible(toolwin(), TRUE); } _focus = first_focus(0); set_focus_field(fld(_focus).dlg()); } int TMask::find_first_active(WINDOW p) const { const int max = fields(); for (int f = 0; f < max; f++) { TMask_field& c = fld(f); if (c.active() && c.parent() == p) return f; } return -1; } int TMask::first_focus(short id) { static int tempfirstfocus = -1; int f = _first_focus; if (id == 0) { if (tempfirstfocus >= 0) { f = tempfirstfocus; if (fld(f).dirty() == FALSE) fld(f).set_dirty(); tempfirstfocus = -1; } else { if (f < 0 || !fld(f).active()) { f = find_first_active(_pagewin[0]); if (f < 0 && toolwin()) f = find_first_active(toolwin()); } } } else { if (id > 0) { f = _first_focus = id2pos(id); tempfirstfocus = -1; } else f = tempfirstfocus = id2pos(-id); } CHECKD(f >= 0 && f < fields(), "Invalid focus field ", f); return f; } TOperable_field& TMask::focus_field() const { if (is_open()) { const short focus = get_focus_id(win()); if (focus > 0 ) ((TMask *)this)->_focus = id2pos(focus); } TMask_field & f = fld(_focus); CHECK(f.is_kind_of(CLASS_OPERABLE_FIELD), "A non operable_field has the focus"); return (TOperable_field&)f; } void TMask::set_focus_field(short id) { const int pos = id2pos(id); CHECKD(pos >= 0, "Can't set focus to field ", id); _focus = pos; if (is_open()) { const TMask_field& f = fld(pos); int p = find_parent_page(f); if (p < 0 || p >= _pages || !page_enabled(p)) p = 0; show_page(p); } } void TMask::notify_focus_field(short id) { const int pos = id2pos(id); _focus = pos; } bool TMask::can_be_closed() const { bool ok = TRUE; if (is_running() && (edit_mode() || insert_mode()) && dirty()) ok = yesno_box("Annullare i dati inseriti?"); return ok; } void TMask::close() { _open = FALSE; _page = -1; for (int p = 0; p <= MAX_PAGES; p++) if (_pagewin[p]) xvt_vobj_set_visible(_pagewin[p], FALSE); } short TMask::dirty() const { const int max = fields(); for (int i = 0; i < max; i++) { const TMask_field& f = fld(i); if (f.dirty() && f.active()) return f.dlg(); } return 0; } void TMask::load_checks() const { const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (f.has_check()) f.check(STARTING_CHECK); } } // @doc EXTERNAL // @mfunc Abilita/disabilita una pagina e tutte le successive void TMask::enable_page( byte page, // @parm Pagina da abilitare/disabilitare bool on) // @parm Operazione da svolgere: // // @flag TRUE | Abilita la pagina

(default) // @flag FALSE | Disabilita la pagina

{ CHECK(page > 0, "Can't enable/disable first page"); if (_enabled[page] != on) { for (byte i = page; i < _pages; i++) { _enabled.set(i, on); for (byte b = 0; b < _pages; b++) { TPage_field& pf = (TPage_field&)field(DLG_PAGETAGS + 100 * b); pf.show_button(i, on); } } } } // Controlla lo stato di abilitazione di una pagina // Certified 100% bool TMask::page_enabled(byte p) const { CHECKD(p <= MAX_PAGES, "Page too high ", (int)p); const bool on = _pagewin[p] != NULL_WIN && _enabled[p]; return on; } void TMask::start_run() { const long start = clock(); const int max = fields(); if (_should_check) { load_checks(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (f.dirty() <= TRUE) { f.set_dirty(FALSE); const bool op = f.is_operable() && !f.is_kind_of(CLASS_BUTTON_FIELD); if (op && (f.active() || f.ghost())) f.on_hit(); // Lancia messaggio di inizializzazione } } } _should_check = TRUE; // Make sure that "nearly" all fields are clean! for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (query_mode() && f.is_edit() && f.in_key(1) && !f.automagic() && !f.empty()) { f.set_dirty(TRUE); } else { if (f.dirty() == TRUE) f.set_dirty(FALSE); } } _init_time = clock()-start; _last_test = -1; } bool TMask::check_fields() { WINDOW curpage = NULL_WIN; // Page under test const bool sheet = is_sheetmask() && !is_open(); const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); const bool on = f.active() || (f.shown() && f.is_kind_of(CLASS_SHEET_FIELD)); if (on) // Don't test inactive fields { if (f.parent() != curpage) { const int pa = find_parent_page(f); if (!page_enabled(pa)) break; // Page disabled: end of test curpage = f.parent(); // Update current page } if (sheet) f.set_dirty(); // Force check in sheet masks if (f.on_key(K_ENTER) == FALSE) { if (is_open()) set_focus_field(f.dlg()); return FALSE; } } } return TRUE; } void TMask::check_field( short fld_id ) { field( fld_id ).on_hit(); field( fld_id ).check(); } // @doc EXTERNAL // @mfunc Converte un identificatore di campo nella sua posizione // // @rdesc Ritorna la posizione del campo nella maschera (-1 se non lo trova) int TMask::id2pos( short id) const // @parm Identificatore del campo del quale trovare la posizione // @comm Cerca nella maschera il campo con identificatore

e ne ritorna il numero ordinale // (es. il campo 120 e' il quarto della maschera) { const int MAX_FIELDS = 256; static byte positions[MAX_FIELDS]; // 100 <= id < MAX_FIELDS const int max = fields(); const int j = id-100; int pos = -1; if (j >= 0 && j < MAX_FIELDS) // Try using cache { pos = positions[j]; if (pos >= 0 && pos < max) { const TMask_field& f = fld(pos); if (f.dlg() == id) // Mask could have been changed! return pos; } } for (pos = 0; pos < max; pos++) // Standard linear search { const TMask_field& f = fld(pos); if (f.dlg() == id) { if (j >= 0 && j < MAX_FIELDS) // Store position for the next time positions[j] = pos; return pos; } } return -1; // Not found! } TMask_field& TMask::field(short id) const { int pos = id2pos(id); #ifdef DBG if (pos < 0) { yesnofatal_box("Il campo %d non esiste", id); pos = 0; } #endif return fld(pos); } TEdit_field& TMask::efield(short id) const { TMask_field& f = field(id); CHECKD(f.is_edit(), "Impossibile trattare come editabile il campo ", id); return (TEdit_field&)f; } // @doc EXTERNAL int TMask::find_parent_page(const TMask_field& f) const { const WINDOW pw = f.parent(); for (int p = 0; p < _pages; p++) if (pw == _pagewin[p]) return p; return MAX_PAGES; // Toolbar button } // @mfunc Forza la chiusura della maschera // // @rdesc Ritorna il risultato dell'operazione: // // @flag TRUE | E' riuscita a chiudere la maschera // @flag FALSE | Non e' riuscita a chiudere la maschera bool TMask::stop_run( KEY key) // @parm Tasto che deve provocare la chiusura // @comm Permette di chiudere la maschera come se l'utente avesse premuto il tasto

. // Nel caso la maschera non si chiuda (es. un check fallito), ritorna FALSE. { if (key != K_AUTO_ENTER && key != K_FORCE_CLOSE) { const int last = fields(); for (int i = 0; i < last; i++) { const TMask_field& f = fld(i); if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD)) { const TButton_field& b = (const TButton_field&)f; if (b.exit_key() == key) break; } } if (i >= last) return FALSE; } if (key == K_CTRL_ENTER || key == K_AUTO_ENTER) key = K_ENTER; else if (key == K_FORCE_CLOSE) key = K_QUIT; if (key != K_ESC && key != K_QUIT && key != K_DEL && key != K_F9) { bool ok = check_current_field(); if (ok) ok = check_fields(); if (!ok) return FALSE; } return TWindow::stop_run(key); } void TMask::on_button(short) { /* Non devo fare niente !!! non essendo una TWindow */ } // @doc EXTERNAL // @mfunc Assegna una azione al tasto non standard // // @rdesc Ritrna se e' stto effetuato una azione: // // @flag TRUE | Era prevista una azione collegata al tasto ed e' stata eseguita // @flag FALSE | Non era prevista nessuna azione collegata al tasto bool TMask::on_key( KEY key) // @parm Tasto premuto sulla maschera // @comm Controlla se il tasto e' tra quelli standard previsti dalla maschera corrente, in caso // contrario ne assegna una azione { if (_handler) { const bool cont = _handler(*this, key); if (!cont) return FALSE; } switch(key) { case K_AUTO_ENTER: case K_CTRL_ENTER: case K_QUIT: case K_ESC: stop_run(key); break; case K_PREV: if (fld(_focus).on_key(K_TAB)) next_page(-1); break; case K_NEXT: if (fld(_focus).on_key(K_TAB)) next_page(+1); break; case K_F1: #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT if (fexist("prassi.hlp")) { struct MULTIGUY { UINT mkSize; BYTE mkKeylist; char mkKeyphrase[16]; } mk; TFilename topic(source_file()); topic.ext(""); mk.mkSize = sizeof(MULTIGUY); mk.mkKeylist = 'M'; strcpy(mk.mkKeyphrase, topic); TFilename hlp("prassi.hlp"); const TString16 mod(topic.left(2)); if (mod != "ba") hlp.insert(mod, 0); HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); next_page(0); } #endif break; case K_F12: post_error_message(format("Lettura = %ld\n" "Creazione = %ld\n" "Inizializzazione = %ld\n", _total_time-_build_time, _build_time, _init_time), 1); break; default: if (key > K_CTRL) { key -= K_CTRL; if (key >= K_F1 && key <= K_F12) { const int page = key - K_F1; if (page < _pages && fld(_focus).on_key(K_TAB)) show_page(page); } else { for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD)) { TButton_field& b = (TButton_field&)f; if (b.virtual_key() == key) { f.on_key(K_SPACE); break; } } } } } } return TRUE; } bool TMask::on_dirty(TMask_field&) { return TRUE; } TMask_field* TMask::parse_field(TScanner& scanner) { const TString& k = scanner.key(); if (k == "ST") return new TEdit_field(this); if (k == "NU") return new TReal_field(this); if (k == "DA") return new TDate_field(this); if (k == "BO") return new TBoolean_field(this); if (k == "TE") return new TText_field(this); if (k == "BU") return new TButton_field(this); if (k == "GR") return new TGroup_field(this); if (k == "LI") return new TList_field(this); if (k == "RA") return new TRadio_field(this); if (k == "ME") return new TMemo_field(this); if (k == "ZO") return new TZoom_field(this); if (k == "BR") return new TBrowsefile_field(this); if (k == "SP") { _sheets++; return new TSheet_field(this); } return NULL; } // @doc EXTERNAL // @mfunc Legge la pagina dal file // // @rdesc Ritorna l'handle della finestra creata WINDOW TMask::read_page( TScanner& scanner, // @parm File dal quale leggere la pagina bool toolbar) // @parm Indica se e' la toolbar // @comm Il parametro

e' utilizzato per indicare se la pagina deve essere visualizzata // a tutto schermo (TRUE) oppure no { static int tooly; static RCT rect; TString title(scanner.string()); RCT r; if (toolwin()) { scanner.line(); xvt_rect_set(&r, 0, 0, 0, tooly); } else { scanner.rectangle(r); if (toolbar) { tooly = r.top; } else { if (_pages == 0) { if (!is_sheetmask()) rect = r; } else r = rect; } } bool orecchie = _pagewin[0] != NULL_WIN || toolwin(); if (!orecchie && !toolbar) // Controlla se la maschera ha piu' di una pagina { const streampos pos = scanner.tellg(); // Memorizza posizione dello scanner while (TRUE) { const TString& l = scanner.line(); if (l.empty() || l == "ENDMASK") // Fine maschera break; if (l.compare("PA", 2, TRUE) == 0) // Ho trovato un'altra pagina! { orecchie = TRUE; // Quindi devo metterci le orecchie break; } } scanner.seekg(pos); // Ripristina posizione dello scanner } WINDOW w; if (toolbar || toolwin()) { w = create_interface(NULL_WIN, 0, r.top, 0, toolbar ? 0 : tooly, title, this, orecchie); } else { w = create_interface(NULL_WIN, r.left, r.top, r.right, r.bottom, title, this, orecchie); } while (scanner.popkey() != "EN") { TMask_field* f = parse_field(scanner); #ifdef DBG if (f == NULL) { const int f = fields(); TString e("Unknown control at position "); e << f; if (f > 0) e << ".\nLast good one was " << fld(f-1).dlg() << ": " << fld(f-1).prompt(); yesnofatal_box(e); while (scanner.popkey() != "EN"); } #endif if (f != NULL) { const long start = clock(); f->construct(scanner, w); _field.add(f); _build_time += clock()-start; } } return w; } bool TMask::check_current_field() const { bool ok = TRUE; if (_focus >= 0) { TMask_field& ff = fld(_focus); if (ff.focusdirty()) ok = ff.on_key(K_TAB); } return ok; } // @doc EXTERNAL // @mfunc Mostra la prossima/precedente pagina void TMask::next_page( int p) // @parm Pagina alla quale saltare // @comm Il valore

puo' assumere i seguenti valori: // // @flag -1 | Mostra la pagina precedente // @flag 0 | Mostra la pagina corrente // @flag +1 | Mostra la pagina successiva // @flag 1000+n | Mostra la pagina n-esima { const int prev = _page; // Previous page if (p != 0) { const int k = (p < 1000) ? _page+p : p-1000; if (k < 0 || k >= _pages || !page_enabled(k)) { beep(); return; } _page = k; } else { if (_page < 0 || _page >= _pages) _page = 0; } if (_page != prev) { xvt_vobj_set_visible(win(), TRUE); if (prev >= 0) xvt_vobj_set_visible(_pagewin[prev], FALSE); } TMask_field& ff = fld(_focus); if (ff.parent() != win() || !ff.active()) { _focus = find_first_active(win()); if (_focus < 0 && toolwin() != NULL_WIN) _focus = find_first_active(toolwin()); } if (_focus >= 0) { TMask_field& ff = fld(_focus); if (ff.active()) ff.highlight(); } TWindow::set_focus(); } void TMask::show_page(int p) { CHECKD(p >= 0 && p < _pages, "Pagina errata ", p); next_page(1000 + p); } void TMask::reset(short fld_id) { if (fld_id <= 0) { const int gr = -fld_id; for (int f = fields()-1; f >= 0; f--) { TMask_field& c = fld(f); if (gr == 0 || c.in_group(gr)) { c._flags.dirty = c._flags.focusdirty = FALSE; c.reset(); } } } else field(fld_id).reset(); } const TString& TMask::get(short fld_id) const { const TString& s = field(fld_id).get(); return s; } long TMask::get_long(short fld_id) const { const TString& s = field(fld_id).get(); return atol(s); } bool TMask::get_bool(short fld_id) const { const TString& s = field(fld_id).get(); return s.not_empty(); } real TMask::get_real(short fld_id) const { const TString& s = field(fld_id).get(); return real(s); } TDate TMask::get_date(short fld_id) const { const TString& s = field(fld_id).get(); return TDate(s); } // @doc EXTERNAL // @mfunc Setta il campo con un valore void TMask::set( short fld_id, // @parm Identificatore del campo da settare const char* s, // @parm Stringa da assegnare al campo bool hit) // @parm Indica se occorre rifare i controlli una volta settato il campo // con il nuovo valore (default FALSE) // @parm long | n | Numero da asegnare al campo // @syntax set(short fld_id, const char *s, bool hit); // @syntax set(short fld_id, long n, bool hit); { TMask_field& f = field(fld_id); f.set(s); if (hit && (f.active() || f.ghost())) { f.set_dirty(); f.on_hit(); } } void TMask::set(short fld_id, long n, bool hit) { char s[16]; sprintf(s, "%ld", n); set(fld_id, s, hit); } void TMask::set(short fld_id, const real& n, bool hit) { CHECK(field(fld_id).is_kind_of(CLASS_REAL_FIELD), "Can't set a real value in a non-number field"); set(fld_id, n.string(), hit); } void TMask::set(short fld_id, const TDate& d, bool hit) { CHECK(field(fld_id).is_kind_of(CLASS_DATE_FIELD), "Can't set a date in a non-date field"); set(fld_id, d.string(), hit); } // @doc EXTERNAL // @mfunc Permette di attivare/disattivare tutta la pagina void TMask::activate( bool on) // @parm Indica l'operazione da svolgere sul campo: // // @flag TRUE | Attiva la pagina(default) // @flag FALSE | Disattiva la pagina { TWindow::activate(on); if (toolwin() != NULL_WIN) xvt_vobj_set_visible(toolwin(), on); } // @doc EXTERNAL // @mfunc Abilita/disabilita un campo void TMask::enable( short fld_id, // @parm Identificatore del campo da abilitare (-1 tutti i campi) bool on) // @parm Indica l'operazione da svolgere sul campo: // // @flag TRUE | Abilita il campo (default) // @flag FALSE | Disabilita il campo { if (fld_id <= 0) { const int gr = -fld_id; for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) f.enable(on); } } else field(fld_id).enable(on); } void TMask::enable_default(short fld_id) { if (fld_id <= 0) { const int gr = -fld_id; for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) f.enable_default(); } } else field(fld_id).enable_default(); } byte TMask::num_keys() const { word max = 0; for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f.is_editable()) { word k = ((TEditable_field&)f).last_key(); if (k > max) max = k; } } return max; } // @doc EXTERNAL // @mfunc Abilita/disabilita i campi di una chiave sulla maschera void TMask::enable_key( byte key, // @parm Chiave di cui abilitare il campo bool on) // @parm Indica l'operazione da svolgere sul tasto: // // @flag TRUE | Abilita il campo (default) // @flag FALSE | Disabilita il campo { for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f.in_key(key)) { if (on) { f.enable_default(); if (!f.shown()) f.show_default(); } else f.disable(); } } } // @doc EXTERNAL // @mfunc Ritorna il l'identificatore di un campo della chiave

// // @rdesc Ritorna l'identificatore del campo cercato TEditable_field* TMask::get_key_field( byte key, // @parm Chiave di cui controllare l'esistenza bool first) const // @parm Indica se la ricerca dev partire dell'inizio. Assume i valori: // // @flag TRUE | Comincia la ricerca dal primo campo della maschera // @flag FALSE | Comincia la ricerca dal campo attuale nella maschera { static int last = 0; if (first) last = 0; const int max = fields(); for (int i = last; i < max; i++) { TMask_field& f = fld(i); if (f.in_key(key)) { last = i+1; return (TEditable_field*)&f; } } return NULL; } bool TMask::key_valid(int key) const { const int max = fields(); for (short f = 0; f < max; f++) { TMask_field& c = fld(f); if (c.is_editable() && c.shown()) { TEditable_field& e = (TEditable_field&)c; if (e.required() && e.in_key(key)) { if (e.empty()) return FALSE; } } } return TRUE; } // @doc EXTERNAL // @mfunc Permette di mostrare/nascondere un campo void TMask::show( short fld_id, // @parm Campo da mostrare/nascondere (default -1) bool on) // @parm Indica l'operazione da svolgere sul campo: // // @flag TRUE | Mostra il campo(default) // @flag FALSE | Nasconde il campo // @comm Se

e' -1 allora permette di operare su tutti i campi della maschera { if (fld_id <= 0) { const int gr = -fld_id; for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) f.show(on); } } else field(fld_id).show(on); } // @doc EXTERNAL // @mfunc Rimette lo stato di default del campo void TMask::show_default( short fld_id) // @parm Identificatore del campo da risettare (default -1) // @comm Se

Assume il valore -1 vuole dire che vengono risettati tutti i campi della amschera { if (fld_id <= 0) { for (int i = fields()-1; i >= 0; i--) fld(i).show_default(); } else field(fld_id).show_default(); } void TMask::autoload(const TRelation& r) { const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (f.is_editable()) ((TEditable_field&)f).autoload(r); } } void TMask::autosave(TRelation& r) const { const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (f.is_editable()) { TEditable_field& e = (TEditable_field&)f; if (e.field() != NULL) { bool save = f.shown(); if (!save) { e.autoload(r); save = f.empty(); } if (save) e.autosave(r); } } } } void TMask::on_firm_change() { TString firm; firm << main_app().get_firm(); for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f._flags.firm) { f.set(firm); f.check(STARTING_CHECK); f.on_hit(); } } } void TMask::on_idle() { if (_focus >= 0 && _focus < fields()) { if (fld(_focus).is_operable()) { TOperable_field& s = (TOperable_field&)fld(_focus); s.on_idle(); if (_msg_field > 0) { TMask_field& f = field(_msg_field); _msg_field = 0; if (_msg_key > 0) f.on_key(_msg_key); } } if (_error_severity > 0) { switch(_error_severity) { case 2: warning_box("%s", (const char*)_error_message); break; case 3: error_box("%s", (const char*)_error_message); break; default: message_box("%s", (const char*)_error_message); break; } _error_severity = 0; set_focus(); } if (_test_fld >= 0) { const TOperable_field & f = focus_field(); if (_last_test != f.dlg()) { TEditable_field & e = (TEditable_field &) field(_test_fld); if (!f.in_key(0) || !e.has_a_common_key(f)) { e.test_key_complete(FALSE); _test_fld = -1; } _last_test = f.dlg(); } } } } // @doc EXTERNAL // @mfunc Permette di mandare un tasto ad un campo void TMask::send_key( KEY key, // @parm Codice del tasto da spedire short to, // @parm Identificatore del campo che deve ricevere TMask_field* from) // @parm Campo che spedisce il tasto { if (to == 0) { WINDOW w = from ? from->parent() : _pagewin[0]; dispatch_e_char(w, key); return; } if (to > 0) { if (to == DLG_PAGE) { CHECK(from, "You should specify a sender!"); const int p = find_parent_page(*from)+1; CHECKD(p > 0 && p < _pages, "You should specify a good page, not ", p); key -= K_CTRL+K_SHIFT; enable_page(p, key == 's' || key == 'e'); } else { const int pos = id2pos(to); if (pos >= 0) { if (_msg_field > 0) on_idle(); _msg_field = to; _msg_key = key; } #ifdef DBG else yesnofatal_box("Can't send key %u to field %d", key, to); #endif } } else { const int gr = -to; for (int i = fields()-1; i >= 0; i--) { TMask_field& campo = fld(i); if (campo.in_group(gr)) campo.on_key(key); } } } // @doc EXTERNAL // @mfunc Permette di mandare un handler ad controllo o ad una maschera void TMask::set_handler( short fld_id, // @parm Identificatere del campo che deve ricevere l'handler CONTROL_HANDLER handler) // @parm Handler da spedire al campo // @parm MASK_HANDLER | handler | Handler da spedire alla maschera // @syntax set_handler(short fld_id, CONTROL_HANDLER handler); // @syntax set_handler(MASK_HANDLER handler); // // @comm Nel primo caso viene mandato un al campo indicato // da

, mentre nel secondo viene mandato un // alla maschera corrente { TMask_field& f = field(fld_id); CHECKD(f.is_operable(), "Can't set an handler to non-operable field ", fld_id); ((TOperable_field&)f).set_handler(handler); } void TMask::set_handler(MASK_HANDLER handler) { _handler = handler; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo testo alla maschera // // @rdesc Ritorna l'handle del campo creato TMask_field& TMask::add_static ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) const char* flags) // @parm Flag di controllo del campo (deafult "") // @xref // { TText_field* f = new TText_field(this); f->construct(id, prompt, x, y, 0, _pagewin[page], flags); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo stringa alla maschera // // @rdesc Ritorna l'handle del campo creato TEdit_field& TMask::add_string ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dim, // @parm Lunghezza del campo sulla maschera const char* flags, // @parm Flag di controllo del campo (defailt "") int width) // @parm Lunghezza totale del campo stringa (default 0) // @xref // { TEdit_field* f = new TEdit_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags, width); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo bottone alla maschera // // @rdesc Ritorna l'handle del campo creato TButton_field& TMask::add_button ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dx, // @parm Larghezza del campo (in caratteri, defailt 9) int dy, // @parm Altezza del campo (in caratteri, default 1) const char* flags, // @parm Flag di controllo del campo (default "") short bmpup, // @parm Icona normale short bmpdn) // @parm Icona premuta // @xref // { TButton_field* f = new TButton_field(this); f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); if (bmpup > 0) f->set_bmp(bmpup, bmpdn); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo boolean alla maschera // // @rdesc Ritorna il descrittore del campo aggiunto TBoolean_field& TMask::add_boolean ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) const char* flags) // @parm Flag di controllo del campo (default "") // @xref // { TBoolean_field* f = new TBoolean_field(this); f->construct(id, prompt, x, y, strlen(prompt), _pagewin[page], flags); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo numerico alla maschera // // @rdesc Ritorna l'handle del campo creato TReal_field& TMask::add_number ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dim, // @parm Lunghezza del campo sulla maschera const char* flags, // @parm Flag di controllo del campo (default "") int ndec) // @parm Numero di decimali (default 0) // @xref // { TReal_field* f = new TReal_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags, ndec); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo data alla maschera // // @rdesc Ritorna l'handle del campo creato TDate_field& TMask::add_date ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) const char* flags) // @parm Flag di controllo del campo (default "") // @xref // { TDate_field* f = new TDate_field(this); f->construct(id, prompt, x, y, 10, _pagewin[page], flags); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo lista alla maschera // // @rdesc Ritorna l'handle del campo creato TList_field& TMask::add_list ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dim, // @parm Lunghezza del campo sulla maschera const char* flags, // @parm Flag di controllo del campo (default "") const char* codes, // @parm tokenstring con i codici (NULL def.) const char* items) // @parm tokenstring con gli items (NULL def.) // @xref // { TList_field* f = new TList_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags); f->replace_items(codes,items); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo radio button alla maschera // // @rdesc Ritorna l'handle del campo creato TRadio_field& TMask::add_radio( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dx, // @parm Larghezza del campo (in caratteri) const char* codes, // @parm Array di codici delle voci const char* items, // @parm Array di prompt delle voci const char* flags) // @parm Flag di controllo del campo (default "") // @xref // { TRadio_field* f = new TRadio_field(this); f->replace_items(codes, items); f->construct(id, prompt, x, y, dx, _pagewin[page], flags, dx); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo zoom alla maschera // // @rdesc Ritorna l'handle del campo creato TZoom_field& TMask::add_zoom ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dim, // @parm Lunghezza del campo sulla maschera const char* flags, // @parm Flag di controllo del campo (defailt "") int width) // @parm Lunghezza totale del campo stringa (default 0) // @xref // { TZoom_field* f = new TZoom_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags, width); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Aggiunge runtime un campo memo alla maschera // // @rdesc Ritorna l'handle del campo creato TMemo_field& TMask::add_memo( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo int x, // @parm Coordinata x (in caratteri) int y, // @parm Coordinata y (in caratteri) int dx, // @parm Larghezza del campo (in caratteri, deafilt 78) int dy, // @parm Altezza del campo (in caratteri, default 4) const char* flags) // @parm Flag di controllo del campo (default "") // @xref // { TMemo_field* f = new TMemo_field(this); f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); _field.add(f); return *f; } // @doc EXTERNAL // @mfunc Salva i valori dei campi della maschera sul file di salvataggio // // @rdesc Ritorna il risultato dell'operazione: // // @flag TRUE | Se l'operazione e' avvenuta corretamente // @flag FALSE | Se non si riesce a creare il file di salvataggio bool TMask::save( bool append) const // @parm Indica se creare il file o appendere (TRUE) le informazioni // ad uno gia' esistente (FALSE, default). { FILE* f = fopen(_workfile, append ? "a" : "w"); if (f == NULL) return yesnofatal_box("Non posso aprire %s ", (const char*) _workfile); const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& c = fld(i); if (c.is_editable()) fprintf(f, "%d|%s\n", c.dlg(), (const char*)c.get()); } fprintf(f, "[EOM]\n"); fclose(f); return TRUE; } // @doc EXTERNAL // @mfunc Legge i valori dei campi della maschera da file di salvataggioo // // @rdesc Ritorna il risultato dell'operazione: // // @flag TRUE | Se l'operazione e' avvenuta corretamente // @flag FALSE | Se non si riesce a leggere il file di salvataggio bool TMask::load( bool reset) // @parm Indica la posizione di lettura del file: // // @flag TRUE | Comincia la lettura dell'inizio // @flag FALSE | Comincia la lettura dalla posizione corrente dell'offset { FILE* f = fopen(_workfile, "r"); if (f == NULL) return FALSE; if (reset) _lastpos = 0; fseek(f, _lastpos, SEEK_SET); TToken_string t(256); while (fgets((char*)(const char*)t, t.size(), f) != NULL && t != "[EOM]") { if (t.not_empty()) { t.cut(t.len() - 1); const int pos = id2pos(t.get_int(0)); if (pos >= 0) fld(pos).set(t.get()); } } _lastpos = ftell(f); fclose(f); return TRUE; } // @doc EXTERNAL // @mfunc Copia i valori dei campi dalla maschera

// void TMask::copy_values( const TMask& m) // @parm Maschera sorgente { reset(); const int nfields = fields(); for (int i = 0; i < nfields; i++) { TMask_field& dest_field = fld( i ); if (dest_field.is_editable() ) { const int pos = m.id2pos(dest_field.dlg()); if (pos >= 0) { const TMask_field& source_field = m.fld(pos); dest_field.set( source_field.get( ) ); } } } } const char* TMask::get_caption() const { char* title = &__tmp_string[512]; xvt_vobj_get_title(_pagewin[0], title, 80); return title; } void TMask::set_caption(const char* c) { TToken_string captions(c); for (int p = 0; p < _pages; p++) { const char* cap = captions.get(); if (cap == NULL) cap = captions.get(0); xvt_vobj_set_title(_pagewin[p], (char*)cap); const int pos = id2pos(DLG_PAGETAGS + 100 * p); if (pos >= 0) { TPage_field& tag = (TPage_field&)fld(pos); tag.set_prompt(c); } } } void TMask::post_error_message(const char* msg, int sev) { CHECK(sev > 0 && msg, "Bad error message posted"); if (_error_severity > 0) // C'e' gia' un messaggio d'errore in coda on_idle(); _error_message = msg; _error_severity = sev; } // @doc EXTERNAL // @mfunc Setta il valore attuale della valuta void TMask::set_exchange( bool show_value, // @parm Indica se il deve essere visibile l'importo in valuta const real& n) // @parm Indica il cambio attuale della valuta { const real nuo = (n.sign() <= 0) ? _exchange : n; main_app().begin_wait(); for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f.is_operable()) { TOperable_field& o = (TOperable_field&)f; if (o.exchangeable() || o.is_kind_of(CLASS_SHEET_FIELD)) o.exchange(show_value, nuo); } } _exchange = nuo; // Update current exchange main_app().end_wait(); }