#include #include #include #include #include #include #include #include #include #define NULL_PAGE 256 HIDDEN const char* const MASK_EXT = "msk"; /////////////////////////////////////////////////////////// // TMask methods /////////////////////////////////////////////////////////// HIDDEN bool moving_focus = FALSE; // @mfunc Controlla se e' possibile dare il focus alla finestra

// // @rdesc Ritorna la possibilita' di lasciare il focus // // @flag TRUE | Se e' possibile cedere il focus a

// @flag FALSE | Se non e' possibile cedere il focus a

bool TMask::test_focus_change( WINDOW next) // @parm Finestra che dovrebbe ricevere il focus // @comm Controlla se il contenuto del campo attuale e' valido e quindi puo' perdere il focus { bool ok = TRUE; TMask_field& prev = fld(_focus); _next_fld = next == NULL_WIN ? DLG_NULL : fld(find_field_win(next)).dlg(); if (prev.win() != next) { ok = prev.test_focus_change(); if (!ok) // Test if previous field agrees ... { set_focus(); prev.set_focusdirty(FALSE); } else { if ( prev.focusdirty() ) ok = on_dirty( prev ); } } return ok; } void TMask::control_handler(EVENT* ep) { const WINDOW win = ep->v.ctl.ci.win; const WIN_TYPE type = ep->v.ctl.ci.type; TMask_field* f = (TMask_field*)xvt_vobj_get_data(win); CHECK(f != NULL, "Invalid field pointer in control"); if (type == WC_CHECKBOX) { if (test_focus_change(win)) { xvt_check_box(win, !xvt_get_checked_state(win)); set_focus_win(win, FALSE); f->on_key(K_SPACE); } return; } if (type == WC_RADIOBUTTON) { if (moving_focus == FALSE) { if (test_focus_change(f->win())) { ((TRadio_field*)f)->check_radiobutton(win); set_focus_win(win, FALSE); f->on_key(K_SPACE); } } else moving_focus = FALSE; return; } if (type == WC_PUSHBUTTON) { if (test_focus_change(win)) { set_focus_win(win, FALSE); f->on_hit(); } return; } if (type == WC_LISTBUTTON) { if (test_focus_change(win)) { set_focus_win(win, FALSE); f->on_key(K_SPACE); } return; } if (ep->v.ctl.ci.v.edit.focus_change) { if (ep->v.ctl.ci.v.edit.active) { if (test_focus_change(win)) { set_focus_win(win, FALSE); f->set_focusdirty(FALSE); } } } else { // Contents of control were changed f->on_key(K_SPACE); } } void TMask::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_UPDATE: #if XVT_OS == XVT_OS_WIN if (win != toolwin()) { xvt_dwin_clear(win, MASK_BACK_COLOR); RCT r; xvt_vobj_get_client_rect(win, &r); r.right--; r.bottom--; xvt_draw_rect(win, r, MASK_LIGHT_COLOR, MASK_DARK_COLOR, 1); } else xvt_dwin_clear(win, MASK_DARK_COLOR); xvt_tx_process_event(win, ep); #else xvt_dwin_clear(win, MASK_BACK_COLOR); #endif update(); return; case E_COMMAND: if (ep->v.cmd.tag == M_FILE_NEW) on_firm_change(); break; case E_CONTROL: switch(ep->v.ctl.id) { case DLG_OK: if (test_focus_change(ep->v.ctl.ci.win)) stop_run(K_AUTO_ENTER); break; case DLG_CANCEL : stop_run(K_ESC); break; case DLG_QUIT : stop_run(K_FORCE_CLOSE); break; case DLG_F9: { WINDOW w = ep->v.ctl.ci.win; TMask_field* f = (TMask_field*)xvt_vobj_get_data(w); w = f->win(); if (test_focus_change(w)) f->on_key(K_F9); // Attiva ricerca sul campo associato al bottone } break; default: control_handler(ep); break; } break; default: if (_focus >= 0 && _focus < fields() && fld(_focus).class_id() == CLASS_MEMO_FIELD) { bool ok = TRUE; if (ep->type == E_CHAR) { const KEY k = e_char_to_key(ep); ok = k != K_TAB && k != K_BTAB; if (ok) fld(_focus).set_dirty(); } if (ok) { ok = xvt_tx_process_event(win, ep) == TRUE; if (ok) return; } } break; } TWindow::handler(win, ep); } void TMask::init_mask() { _sheets = _pages = 0; // Azzera numero pagine e sheets _enabled.set(MAX_PAGES); _enabled.set(); // Abilita tutte le pagine _focus = _first_focus = 0; // Nessuno 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 memset(_pagewin, 0, sizeof(_pagewin)); memset(_pagepag, 0, sizeof(_pagepag)); memset(_pagetag, 0, sizeof(_pagetag)); } 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(xpos, ypos, cols, rows, title, WSF_CLOSE, WD_MODAL); set_win(NULL_WIN); add_buttons(); } // @doc INTERNAL // @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 // @comm Permette di aggiornare i tempi di caricamento della maschera stessa { if (max <= 0) max = MAX_PAGES; _source_file = name; _source_file.ext(MASK_EXT); _source_file.lower(); TScanner scanner(_source_file); _sheetmask = num > 0; long start_t = clock(); while (clock() == start_t) continue; // Attende scatto timer start_t = clock(); if (!_sheetmask) _total_time = _build_time = _init_time = 0; for (int i = 0; i < num; i++) { while (scanner.ok()) if (scanner.line() == "ENDMASK") break; } init_mask(); main_app().begin_wait(); while (scanner.ok() && scanner.popkey() != "EN") { if (scanner.key() == "PA") { CHECKD(_pages < MAX_PAGES, "Maschera con troppe pagine: ", _pages); _pagewin[_pages++] = read_page(scanner, FALSE); 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 < 1) fatal_box("Impossibile leggere la maschera %s", name); add_buttons(); if (!_sheetmask) _total_time = clock()-start_t; main_app().end_wait(); } void TMask::add_buttons() { #if XVT_OS == XVT_OS_WIN for (int p = 0; p < _pages; p++) { if (_pages > 1) { const long flags = (p < _pages-1 ? 0x1 : 0x0) | (p > 0 ? 0x2 : 0x0); _pagepag[p] = xvt_create_control(WC_PUSHBUTTON, 0, 0, 1, 1, "", _pagewin[p], flags, 0, DLG_PAGE); } if (toolwin()) _pagetag[p] = xvt_create_control(WC_PUSHBUTTON, 0, 0, 0, 1, "", _pagewin[p], p, _pages, DLG_PAGETAGS); } #else if (toolwin()) { TString80 t; for (int p = 0; p < _pages; p++) t << ' ' << p+1; t << ' '; for (p = 0; p < _pages; p++) { const int k = p*2; t[k] = '['; t[k+2] = ']'; RCT r; xvt_rect_set(&r, 0, 0, t.size()*CHARX, CHARY); xvt_ctl_create(WC_TEXT, &r, t, _pagewin[p], 0, 0, DLG_NULL); t[k] = ' '; } } #endif } TMask::TMask(const char* maskname, int num, int max) : _should_check(TRUE) { if (maskname && *maskname) read_mask(maskname, num, max); } TMask::~TMask() { for (int p = 0; p <= MAX_PAGES; p++) if (_pagewin[p]) { xvt_vobj_destroy(_pagewin[p]); _pagewin[p] = NULL_WIN; } } void TMask::open() { set_mask_fields(); _focus = first_focus(0); if (toolwin() && _focus < 1) _focus = find_first_field(_pagewin[0], +1); if (!_open || _page != 0) { _open = TRUE; if (toolwin()) xvt_vobj_set_visible(toolwin(), TRUE); next_page(0); } else { set_focus(); } } int TMask::first_focus(short id) { static int tempfirstfocus = 0; int f = _first_focus; if (id == 0) { if (tempfirstfocus) { f = tempfirstfocus; if (fld(f).dirty() == FALSE) fld(f).set_dirty(); } tempfirstfocus = 0; } else { if (id > 0) { _first_focus = id2pos(id); tempfirstfocus = 0; } else tempfirstfocus = id2pos(-id); } return f; } bool TMask::can_be_closed() const { bool ok = TRUE; if (!query_mode() && is_running() && 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); } void TMask::set_mask_fields() const { for (int i = 0; i < fields(); i++) { TMask_field& f = fld(i); const word id = f.class_id(); if (id != CLASS_FIELD && id != CLASS_BUTTON_FIELD) f.set_window_data(f.get_field_data()); } } short TMask::dirty() const { const int max = fields(); for (int i = 0; i < max; i++) { const TMask_field& f = fld(i); const word id = f.class_id(); if (f.dirty() && id != CLASS_FIELD && id != CLASS_BUTTON_FIELD && f.active()) return f.dlg(); } return 0; } void TMask::load_checks() const { if (_should_check) { const int max = fields(); for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if (f.has_check()) f.check(STARTING_CHECK); } } } // @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); #if XVT_OS == XVT_OS_WIN const byte p = on ? _pages : page; for (i = 0; i < page-1; i++) xvt_change_page_tags(NULL_WIN, FALSE, _pagetag[i], p); xvt_change_page_tags(_pagepag[page-1], on, _pagetag[page-1], p); #endif } } // Controlla lo stato di abilitazione di una pagina // Certified 100% bool TMask::page_enabled(byte page) const { return _enabled[page]; } void TMask::start_run() { const long start = clock(); load_checks(); _should_check = TRUE; const int max = fields(); _next_fld = DLG_NULL; for (int i = 0; i < max; i++) { TMask_field& f = fld(i); if ((f.active() || f.ghost()) && f.class_id() != CLASS_BUTTON_FIELD && f.dirty() <= TRUE) { f.set_dirty(FALSE); f.on_hit(); // Lancia messaggio di inizializzazione } } // Make sure that "nearly" all fields are clean! for (i = 0; i < max; i++) { TMask_field& f = fld(i); if (query_mode() && f.is_edit() && f.in_key(1) && !f.automagic() && !f.get().empty()) { f.set_dirty(TRUE); } else { if (f.dirty() == TRUE) f.set_dirty(FALSE); } } _init_time = clock()-start; } 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); if (!f.active()) continue; // 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 sheets if (f.on_key(K_ENTER) == FALSE) { if (is_open()) f.set_focus(); return FALSE; } } return TRUE; } void TMask::get_mask_fields() { for (int i = 0; i < fields(); i++) { TMask_field& f = fld(i); const char* fd = f.get_field_data(); if (fd != NULL) // NULL per testi fissi, bottoni e sheets { const char* wd = f.get_window_data(); CHECKD(wd, "NULL window data in field ", f.dlg()); if (f.dirty() == TRUE) { if (strcmp(wd, fd) == 0) f.set_dirty(FALSE); } f.set_field_data(wd); } } } // @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; } int TMask::find_field_win(WINDOW win) const { if (fld(_focus).win() == win) return _focus; const int max = fields(); for (int i = 0; i < max; i++) if (fld(i).win() == win) return i; #ifdef DBG yesnofatal_box("Can't find the field given the child window"); #endif return 0; } // @mfunc Setta il focus al campo la cui finestra e'

void TMask::set_focus_win( WINDOW win, // @parm Finestra del controllo che riceve il focus bool force) // @parm Forza la chiamata alla // @comm Il parametro

puo' assumere i seguenti valori: // // @flag TRUE | Se occorre attivare il focus interno (quello di Windows e' automatico) // @flag FALSE | Se non occorre attivare il focus interno (e' possibile conoscere il focus // interno della classe) { _focus = find_field_win(win); if (force) set_focus(); } 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 Ritorna il prossimo campo attivabile // // @rdesc Riorna il numero del campo cercato int TMask::find_active_field( int first, // @parm Campo da cui cominciare la ricerca int dir) const // @parm Direzione della ricerca. Puo assumere i valori: // // @flag +1 | Ricerca in avanti // @flag -1 | Ricerca in dietro // @comm Serve per la ricerca del campo attivabil al momento della pressione dei tasti // TAB (o ENTER) e SHIFT+TAB { const int max = fields()-1; WINDOW w, old = fld(_focus).parent(); for (int i = first; ; i += dir) { if (i > max) i = 0; else if (i < 0) i = max; if (fld(i).active() && page_enabled(find_parent_page(fld(i)))) { w = fld(i).parent(); break; } } if (w != old) { int p = _page; if (old == toolwin()) { if (dir > 0) { if (++p >= _pages) p = 0; } } else { if (dir < 0) { if (--p < 0) p = _pages-1; } else p = MAX_PAGES; } w = _pagewin[p]; i = find_first_field(w, dir); } return i; } void TMask::set_focus() { _focus = find_active_field(_focus, +1); const TMask_field& f = fld(_focus); const int page = find_parent_page(f); if (page != _page && page != MAX_PAGES) { const WINDOW pw = win(); // previous window _page = page; // update page number xvt_vobj_set_visible(win(), TRUE); // show new page if (pw) xvt_vobj_set_visible(pw, FALSE); // hide old page } f.highlight(); } // @mfunc Muove il focus al prossimo o al precedente controllo valido void TMask::move_focus_field( int d) // @parm Indica lo spostamento relativo del focus rispetto // al campo attuale: // // @flag +1 | Si sposta sul campo successivo // @flag -1 | Si sposta sul campo precedente // // @comm E' possibile che il parametro

assuma valori diversi da -1 o +1. In questo caso // sposta il focus di piu' di una posizione. { TMask_field& f = fld(_focus); if (f.class_id() == CLASS_RADIO_FIELD) { TRadio_field& radio = (TRadio_field&)f; moving_focus = TRUE; bool cont = radio.move_focus(d); moving_focus = FALSE; if (!cont) return; } const int focus = find_active_field(_focus+d, d); if (!test_focus_change(fld(focus).win())) return; if (fld(focus).parent() == f.parent() || check_current_page()) _focus = focus; set_focus(); } // @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

. // Nela 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(); bool found = FALSE; for (int i = 0; i < last; i++) { const TMask_field& f = fld(i); if (f.class_id() != CLASS_BUTTON_FIELD) continue; const TButton_field& b = (const TButton_field&)f; if (b.exit_key() == key) { if (b.active()) { found = TRUE; break; } } } if (!found) { #ifdef DBG return error_box("Non e' attivo il bottone associato a %d", key); #else return FALSE; #endif } } 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) { const bool ok = check_fields(); if (!ok) return FALSE; } if (is_running()) // Gestisce correttamenete le maschere chiuse { get_mask_fields(); _next_fld = DLG_NULL; } return TWindow::stop_run(key); } // @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) { 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_UP: case K_BTAB: case K_SHIFT_TAB: case K_LEFT: move_focus_field(-1); break; case K_DOWN: case K_TAB: case K_RIGHT: case K_ENTER: move_focus_field(+1); break; case K_PREV: next_page(-1); break; case K_NEXT: next_page(+1); break; case K_F12: message_box("Lettura = %ld\n" "Creazione = %ld\n" "Inizializzazione = %ld", _total_time-_build_time, _build_time, _init_time); break; default: if (key > K_CTRL) { key -= K_CTRL; if (key >= K_F1 && key <= K_F12) next_page(1000 + key - K_F1); else { for (int i = 0; i < fields(); i++) { TMask_field& f = fld(i); if (f.class_id() != CLASS_BUTTON_FIELD || !f.active()) continue; TButton_field& b = (TButton_field&)f; if (b.virtual_key() == key) { bool ok = b.dlg() == DLG_CANCEL || b.dlg() == DLG_QUIT || b.dlg() == DLG_F9; if (!ok) ok = test_focus_change(b.win()); if (ok) f.on_key(K_SPACE); break; } } } } else return fld(_focus).on_key(key); } return TRUE; } bool TMask::on_dirty(TMask_field&) { return TRUE; } TMask_field* TMask::parse_field(TScanner& scanner) { if (scanner.key() == "ST") return new TEdit_field(this); if (scanner.key() == "NU") return new TReal_field(this); if (scanner.key() == "DA") return new TDate_field(this); if (scanner.key() == "BO") return new TBoolean_field(this); if (scanner.key() == "LI") return new TList_field(this); if (scanner.key() == "BU") return new TButton_field(this); if (scanner.key() == "TE") return new TMask_field(this); if (scanner.key() == "RA") return new TRadio_field(this); if (scanner.key() == "GR") return new TGroup_field(this); if (scanner.key() == "SP") { _sheets++; return new TSheet_field(this); } if (scanner.key() == "BR") return new TBrowsefile_field(this); if (scanner.key() == "ME") return new TMemo_field(this); return NULL; } // @mfunc Legge la pagina dal file // // @rdesc Ritorna l'andle della finestra creata WINDOW TMask::read_page( TScanner& scanner, // @parm File dal quale leggere la pagina bool toolbar) // @parm Indica se esiste 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; TString80 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) rect = r; else r = rect; } } WINDOW w; if (toolbar || toolwin()) { w = create(0, r.top, 0, r.bottom, title, toolbar ? 0 : WSF_INVISIBLE, W_PLAIN); } else { w = create(r.left, r.top, r.right, r.bottom, title, WSF_CLOSE | WSF_INVISIBLE, WD_MODAL); } while (scanner.popkey() != "EN") { TMask_field* f = parse_field(scanner); #ifdef DBG if (f == NULL) { const int f = fields(); TString256 e("Unknown control at pos."); e << f; if (f) e << ". Last good was " << fld(f-1).dlg() << ": " << fld(f-1).prompt(); fatal_box(e); } #endif const long start = clock(); f->construct(scanner, w); _field.add(f); _build_time += clock()-start; } set_win(NULL_WIN); return w; } // @mfunc Ritorna la posizione del primo campo attivo nella direzione specificata // // @rdesc Ritorna il primo campo attivo int TMask::find_first_field( WINDOW w, // @parm handle della finestra (pagina) nel quale cercare int dir) const // @parm Direzione di ricerca. Puo' assumere i valori: // // @flag +1 | Direzione in avanti // @flag -1 | Direzione in dietro { const int last = fields()-1; const int fi = (dir > 0) ? 0 : last; const int la = last-fi; for (int i = fi; i != la; i += dir) { const TMask_field& f = fld(i); if (f.parent() == w && f.active()) break; } return i; } bool TMask::check_current_page() { if (!test_focus_change()) return FALSE; /* if (sheets() > 0) return TRUE; const int last = fields(); const WINDOW page = win(); for (int i = 0; i < last; i++) { TMask_field& f = fld(i); if (f.parent() == page && f.active() && f.on_key(K_ENTER) == FALSE) return FALSE; } */ return TRUE; } // @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) { if (check_current_page() == FALSE) // New style return; const int k = (p < 1000) ? _page+p : p-1000; if (k < 0 || k >= _pages || !page_enabled(k)) { beep(); return; } _page = k; } else _page = 0; if (_page != prev) { const WINDOW w = _pagewin[_page]; xvt_vobj_set_visible(w, TRUE); if (prev >= 0) { xvt_vobj_set_visible(_pagewin[prev], FALSE); _focus = find_first_field(w, +1); } } set_focus(); } void TMask::reset(short fld_id) { if (fld_id < 1) { for (int f = 0; f < fields(); f++) { TMask_field& c = fld(f); c._flags.dirty = FALSE; c.reset(); } } else field(fld_id).reset(); } void TMask::undo(short fld_id) { if (fld_id < 1) { for (int f = 0; f < fields(); f++) fld(f).undo(); } else field(fld_id).undo(); } const TString& TMask::get(short fld_id) const { return field(fld_id).get(); } long TMask::get_long(short fld_id) const { return atol(field(fld_id).get()); } bool TMask::get_bool(short fld_id) const { return field(fld_id).get().not_empty(); } // @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.on_hit(); } void TMask::set(short fld_id, long n, bool hit) { char s[16]; sprintf(s, "%ld", n); set(fld_id, s, hit); } // @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); } // @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 = 0; i < fields(); 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 < 1) { for (int i = 0; i < fields(); i++) fld(i).enable_default(); } else field(fld_id).enable_default(); } byte TMask::num_keys() const { word max = 0; for (int i = 0; i < fields(); i++) { word k = fld(i).last_key(); if (k > max) max = k; } return max; } // @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 = 0; i < fields(); i++) if (fld(i).in_key(key)) { if (on) { fld(i).enable_default(); if (!fld(i).shown()) fld(i).show_default(); } else fld(i).disable(); } } // @mfunc Ritorna il l'identificatore di un campo della chiave

// // @rdesc Ritorna l'identificatore del campo cercato short 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; for (int i = last; i < fields(); i++) { if (fld(i).in_key(key)) { last = i+1; return fld(i).dlg(); } } return -1; } bool TMask::key_valid(int key) const { for (short f = 0; f < fields(); f++) { TMask_field& c = fld(f); if (c.in_key(key) && c.required()) { const TString & value = c.get(); if (c.class_id() == CLASS_REAL_FIELD) { real z(value); if (z.is_zero()) { c.reset(); return FALSE; } } if (value.empty()) return FALSE; } } return TRUE; } // @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 = 0; i < fields(); i++) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) f.show(on); } } else field(fld_id).show(on); } // @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 = 0; i < fields(); 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.field() != NULL) 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); const TFieldref* fr =f.field(); if (fr != NULL) { if (f.shown() || *fr->read(r) == '\0') f.autosave(r); } } } void TMask::on_firm_change() { TString16 firm; firm << main_app().get_firm(); for (int i = 0; i < fields(); 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()) { const word acqua = fld(_focus).class_id(); if (acqua == CLASS_SHEET_FIELD) { TSheet_field& s = (TSheet_field&)fld(_focus); s.on_idle(); } } } // @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) fld(pos).on_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 = 0; i < fields(); i++) { TMask_field& campo = fld(i); if (campo.in_group(gr)) campo.on_key(key); } } } // @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 { field(fld_id).set_handler(handler); } void TMask::set_handler(MASK_HANDLER handler) { _handler = handler; } // @mfunc Aggiunge runtime un campo testo alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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 // { TMask_field* f = new TMask_field(this); f->construct(id, prompt, x, y, strlen(prompt), _pagewin[page], flags); _field.add(f); return f->win(); } // @mfunc Aggiunge runtime un campo stringa alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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->win(); } // @mfunc Aggiunge runtime un campo numerico alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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->win(); } // @mfunc Aggiunge runtime un campo data alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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->win(); } // @mfunc Aggiunge runtime un campo bottone alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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 "") // @xref // { TButton_field* f = new TButton_field(this); f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); _field.add(f); return f->win(); } // @mfunc Aggiunge runtime un campo radio button alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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 ((TMask_field*)f)->win(); } // @mfunc Aggiunge runtime un campo memo alla maschera // // @rdesc Ritorna l'handle del campo creato WINDOW 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 ((TMask_field*)f)->win(); } // @mfunc Permette di salvare il 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((const char *) _workfile, append ? "a" : "w"); if (f == NULL) return yesnofatal_box("Non posso aprire %s ", (const char*) _workfile); for (int i = 0; i < fields(); i++) { const short id = fld(i).dlg(); if (id >= 100) fprintf(f, "%d|%s\n", id, (const char*) fld(i).get()); } fprintf(f, "[EOM]\n"); fclose(f); return TRUE; } // @mfunc Permette di leggere il file di salvataggio // // @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((const char *) _workfile, "r"); if (f == NULL) return FALSE; if (reset) _lastpos = 0; fseek(f, _lastpos, SEEK_SET); TToken_string t(256); char s[256]; while (fgets(s, 255, f) != NULL && strncmp(s, "[EOM]", 5) != 0) { if (*s) s[strlen(s) - 1] = '\0'; t = s; const short id = t.get_int(); if (id >= 100) { const int pos = id2pos(id); if (pos >= 0) fld(pos).set(t.get()); } } _lastpos = ftell(f); fclose(f); return TRUE; } 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) { for (int p = 0; p < _pages; p++) xvt_vobj_set_title(_pagewin[p], (char*)c); } // @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 = 0; i < fields(); i++) { TMask_field& f = fld(i); const word id = f.class_id(); if (id == CLASS_SHEET_FIELD || id == CLASS_REAL_FIELD && f.exchangeable()) f.exchange(show_value, nuo); } _exchange = nuo; // Update current exchange main_app().end_wait(); }