// $Id: maskfld.cpp,v 1.16 1994-09-09 15:05:23 alex Exp $ #include #include #include #include #include #include #include #include #include #include #include #include #include #if XVT_OS == XVT_OS_WIN #include #endif HIDDEN const int MAXSTR = 128; HIDDEN char __fpark[MAXSTR]; // Temporary for get/set window data HIDDEN TFixed_string fpark(__fpark, MAXSTR); /////////////////////////////////////////////////////////// // Field Flags /////////////////////////////////////////////////////////// // Certified 100% TMask_field::TField_Flags::TField_Flags() { automagic = persistent = FALSE; enabled = enable_default = TRUE; showed = show_default = TRUE; uppercase = rightjust = FALSE; zerofilled = FALSE; dirty = focusdirty = FALSE; roman = exchange = FALSE; firm = ghost = FALSE; } // Certified 100% char TMask_field::TField_Flags::update(const char* s) { const char* kk = s; for (; *s; s++) switch(toupper(*s)) { case 'A': automagic = persistent = TRUE; break; case 'D': enable_default = enabled = FALSE; break; case 'F': firm = persistent = TRUE; break; case 'G': ghost = TRUE; break; case 'H': show_default = showed = FALSE; break; case 'M': roman = TRUE; break; case 'P': persistent = TRUE; break; case 'R': rightjust = TRUE; break; case 'U': uppercase = TRUE; break; case 'V': exchange = TRUE; break; case 'Z': zerofilled = TRUE; break; #ifdef DBG default : ::warning_box("FLAG sconosciuto in %s: %c", kk, *s); break; #endif } return *s; } /////////////////////////////////////////////////////////// // TMask_field /////////////////////////////////////////////////////////// int TMask_field::_x; // Position of the field int TMask_field::_y; int TMask_field::_width; TFixed_string TMask_field::_prompt(__fpark, MAXSTR); // Prompt of the field TMask_field::TMask_field(TMask* m) : _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), _keys(0), _groups(0), _help(0), _handler(NULL), _validate_func(-1), _validate_parms(1), _field(NULL) {} // Certified 100% TMask_field::~TMask_field() { if (_field) delete _field; } // Certified 100% bool TMask_field::is_edit() const { const word c = class_id(); return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD; } // Certified 100% const char* TMask_field::class_name() const { return "Field"; } // Certified 100% word TMask_field::class_id() const { return CLASS_FIELD; } // Certified 100% bool TMask_field::ok() const { return win() != NULL_WIN && dlg() >= -1; } // Certified 100% void TMask_field::parse_head(TScanner&) {} // Certified 100% short TMask_field::atodlg(const char* s) const { short d = s ? atoi(s) : 0; #ifdef DBG if (d == 0 || d < -1 || d > 1000) { yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); d = -1; } #endif return d; } void TMask_field::construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags, int width) { _x = x; _y = y; _prompt = prompt; _size = len; if (class_id() == CLASS_REAL_FIELD) { ((TReal_field*)this)->set_decimals(width); _width = _size; } else _width = width < 1 ? _size : width; _dlg = id; _flags.update(flags); create(parent); } void TMask_field::construct(TScanner& scanner, WINDOW parent) { _dlg = atodlg(scanner.pop()); parse_head(scanner); _prompt.cut(0); scanner.popkey(); // BEGIN #ifdef DBG if (scanner.key() != "BE") { yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); scanner.push(); } #endif while(scanner.popkey() != "EN") // END of control parse_item(scanner); create(parent); } bool TMask_field::parse_item(TScanner& scanner) { if (scanner.key() == "PR") // PROMPT { _x = scanner.integer(); _y = scanner.integer(); _prompt = scanner.string(); return TRUE; } if (scanner.key() == "FL") // FLAG { const char* f = scanner.string(); return _flags.update(f) == '\0'; } if (scanner.key() == "FI") // FIELD { CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); _field = new TFieldref(scanner.line(), 0); return TRUE; } if (scanner.key() == "HE") // HELP { _help = scanner.string(); return TRUE; } if (scanner.key() == "KE") // KEY { _keys.set(scanner.line()); _keys.set(0L); return TRUE; } if (scanner.key() == "ME") { if (_message.objptr(0) == 0) _message.add(new TToken_string(64), 0); TToken_string& ts = (TToken_string&)_message[0]; ts.add(scanner.line().strip_spaces()); return TRUE; } if (scanner.key() == "GR") { _groups.set(scanner.line()); return TRUE; } return FALSE; } long TMask_field::default_flags() const { long f = CTL_FLAG_NATIVE_JUST; if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; return f; } // Certified 100% WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy, const char* title, WINDOW parent, long flags) { _win = xvt_create_control(ct, _x, _y, dx, dy, (char*)title, parent, flags | default_flags(), PTR_LONG(this), _dlg); return _win; } // Certified 100% WINDOW TMask_field::parent() const { return get_parent(win()); } // Certified 90% int TMask_field::create_prompt(WINDOW parent, int width, int heigth) { const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; if (width < 1) width = strlen(_prompt); _prompt.rtrim(); // Could save some bytes if (width) { // Static controls shouldn't be grayed const long flags = default_flags() & (~CTL_FLAG_DISABLED); #if XVT_OS == XVT_OS_WIN char* k = strchr(_prompt, '~'); if (k != NULL) *k = '&'; #endif _promptwin = xvt_create_control ( wt, _x, _y, width, heigth, _prompt, parent, flags, 0L, -1 ); } return width; } // Certified 100% void TMask_field::destroy() { if (_win) { close_window(_win); _win = NULL_WIN; } if (_promptwin) { close_window(_promptwin); _promptwin = NULL_WIN; } } // Certified 100% void TMask_field::create(WINDOW parent) { _width = strlen(_prompt); if (_width) wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); } // Certified 100% void TMask_field::enable(bool on) { const word c = class_id(); if (c != CLASS_FIELD) { enable_window(_win, on); _flags.enabled = on; } } // Certified 100% void TMask_field::enable_default() { const bool ed = _flags.enable_default; enable(ed); } // Certified 100% void TMask_field::show(bool on) { show_window(_win, on); if (_promptwin != NULL_WIN) show_window(_promptwin, on); _flags.showed = on; } // Certified 100% void TMask_field::show_default() { const bool sd = _flags.show_default; show(sd); } // Certified 100% bool TMask_field::active() const { return enabled() && showed() && class_id() != CLASS_FIELD; }; // Certified 90% word TMask_field::last_key() const { long u = _keys.last_one(); if (u < 0) u = 0; return (word)u; } // Certified 99% const char* TMask_field::get_window_data() const { get_title(win(), __fpark, MAXSTR); return __fpark; } // Certified 99% void TMask_field::set_window_data(const char* data) { if (data != NULL) set_title(win(), (char*)data); } // Certified 100% void TMask_field::set_field_data(const char*) {} // Certified 100% const char* TMask_field::get_field_data() const { return NULL; } const char* TMask_field::picture_data(const char* data, bool video) { fpark = data; if (video) { fpark.trim(); if (_flags.uppercase) fpark.upper(); } return fpark; } // Certified 90% const char* TMask_field::prompt() const { if (_promptwin != NULL_WIN) _prompt = xvt_get_title(_promptwin); else _prompt = ""; return _prompt; } // Certified 100% void TMask_field::reset() { if (!_flags.persistent && class_id() != CLASS_FIELD) set(""); } // Certified 100% void TMask_field::set_prompt(const char* p) { if (_promptwin != NULL_WIN) set_title(_promptwin, (char*) p); } void TMask_field::set(const char* s) { if (mask().is_running()) { set_window_data(s); set_dirty(); } else set_field_data(s); } TString& TMask_field::get() const { static TString80 gpark; if (mask().is_running()) gpark = get_window_data(); else gpark = get_field_data(); return gpark.trim(); } void TMask_field::undo() { set_window_data(get_field_data()); } bool TMask_field::autoload(const TRelation* r) { if (_field) { set(_field->read(r)); return TRUE; } return FALSE; } bool TMask_field::autosave(TRelation* r) const { if (_field) { _field->write(get(), r); return TRUE; } return FALSE; } // Certified 50% HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) { #ifdef DBG if (f.class_id() != CLASS_LIST_FIELD) { error_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 90% HIDDEN const char* copy_value(TToken_string& msg, const TString& val) { int from = msg.get_int()-1; int to = 0; if (from < 0) from = 0; else to = msg.get_int(); return val.sub(from, to); } // Certified 50% bool TMask_field::do_message(int num) { const int MAX_CMD = 14; static const char* commands[MAX_CMD] = { "ADD", // 0 "CLEAR", // 1 "CO", // 2 "DEL", // 3 "DIRTY", // 4 "DISABLE", // 5 "ENABLE", // 6 "ENABLEDEF", // 7 "EXIT", // 8 "HIDE", // 9 "PUSH", // 10 "RESET", // 11 "SHOW", // 12 "UNDO" // 13 }; TToken_string* message = (TToken_string*)_message.objptr(num); if (message == NULL || message->empty()) return FALSE; TToken_string msg(16, ','); TString value(16); for (const char* m = message->get(0); m && *m; m = message->get()) { KEY key = 0; msg = m; value = msg.get(); value.trim(); const char* dlg = msg.get(); int cmd = -1; if (isalpha(value[0])) // binary search { int f = 0, l = MAX_CMD-1; while (TRUE) { cmd = (f+l)>>1; const int cmp = strcmp(value, commands[cmd]); if (cmp == 0) break; if (cmp > 0) f = cmd+1; else l = cmd-1; if (f > l) { cmd = -1; break; } } } if (cmd == 8) { mask().stop_run(atoi(dlg)); continue; } short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; bool broadcast = dlg && strchr(dlg, '@'); if (value[0] == '"') value = value.strip("\"'"); else switch (cmd) { case 0: modify_list(TRUE, mask().field(fld), msg); continue; case 1: key = 11000+'c'; break; case 2: value = copy_value(msg, get()); break; case 3: modify_list(FALSE, mask().field(fld), msg); continue; case 4: mask().field(fld).set_dirty(); continue; case 5: key = 11000+'d'; break; case 6: key = 11000+'e'; break; case 7: key = 11000+'E'; break; case 9: key = 11000+'h'; break; case 10: key = K_SPACE; break; case 11: key = K_F2; break; case 12: key = 11000+'s'; break; case 13: key = K_F3; break; default: key = atoi(value); break; } if (key) { if (key > 0) { if (broadcast) fld = -fld; mask().send_key(key, fld); } } else { // Setta a value il campo fld solo se ha un valore diverso da value if (broadcast) { for (int i = 0; i < mask().fields(); i++) { TMask_field& f = mask().fld(i); if (f.in_group((int)fld)) { const char* prev = f.get(); if (value != prev) { f.set(value); if (f.showed() || 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.showed() || f.ghost()) f.on_hit(); } } } } return TRUE; } // Certified 90% bool TMask_field::on_hit() { if (_handler) { bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); if (!ok) return FALSE; } do_message(0); return TRUE; } bool TMask_field::to_check(KEY k, bool checkrun) const { bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); if (!yes && checkrun) yes = k == K_TAB && !mask().is_running(); return yes; } // Certified 90% bool TMask_field::on_key(KEY key) { if (key > 11000) { switch(key-11000) { case 'E': enable_default(); break; case 'c': reset(); on_hit(); case 'd': disable(); break; case 'e': enable(); break; case 'h': hide(); break; case 's': show(); break; #ifdef DBG default : return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); #endif } return TRUE; } switch(key) { case K_SPACE: set_dirty(); break; case K_PREV: case K_NEXT: dispatch_e_char(parent(), key); break; case K_F1: if (_help.not_empty()) message_box(_help); else beep(); break; case K_F2: reset(); set_dirty(); break; case K_F3: undo(); set_dirty(); break; default: break; } if (_handler) return _handler(*this, key); return TRUE; } void TMask_field::set_focus() const { const bool force = mask().is_running(); mask().set_focus_win(win(), force); } HIDDEN char* const _msg = &__tmp_string[512]; #define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) bool TMask_field::error_box(const char* fmt, ...) const { build_msg(); if (mask().is_running()) { set_focus(); ::error_box("%s", _msg); set_focus(); } else { xvt_statbar_set(_msg); beep(); } return FALSE; } bool TMask_field::message_box(const char* fmt, ...) const { set_focus(); build_msg(); ::message_box("%s", _msg); set_focus(); return FALSE; } bool TMask_field::warning_box(const char* fmt, ...) const { build_msg(); if (mask().is_running()) { set_focus(); ::warning_box("%s", _msg); set_focus(); } else { xvt_statbar_set(_msg); beep(); } return FALSE; } bool TMask_field::yesno_box(const char* fmt, ...) const { set_focus(); build_msg(); const bool yes = ::yesno_box("%s", _msg); set_focus(); return yes; } KEY TMask_field::yesnocancel_box(const char* fmt, ...) const { set_focus(); build_msg(); const KEY k = ::yesnocancel_box("%s", _msg); set_focus(); return k; } /////////////////////////////////////////////////////////// // TList_sheet /////////////////////////////////////////////////////////// // Certified 100% TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) : _fld(f), _row(-1) { _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); } // Certified 100% TList_sheet::~TList_sheet() { delete _sheet; } // Certified 100% TMask_field& TList_sheet::field(short id) const { return field().mask().field(id); } // Certified 100% void TList_sheet::read_item(TScanner& scanner) { TToken_string ts(scanner.string()); _sheet->add(ts); } // Certified 100% void TList_sheet::parse_input(TScanner& scanner) { _inp_id.add(scanner.pop()); } // Certified 100% void TList_sheet::parse_output(TScanner& scanner) { _out_id.add(scanner.pop()); } // il numero di riga selezionata int TList_sheet::do_input() { if (_inp_id.empty()) return -1; _inp_id.restart(); TToken_string rowsel(80); for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { rowsel.add(fld+1); if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1); } else { const short id = _fld->atodlg(fld); if (id > 0) rowsel.add(field().mask().get(id)); else rowsel.add(""); } } TString80 fd, it; for (int i = 0 ; i < _sheet->items(); i++) { TToken_string& ts =_sheet->row(i); ts.restart(); for ( const char* item = rowsel.get(0); item ; item = rowsel.get()) { it = item; it.trim(); fd = ts.get(); fd.trim(); if (fd != it) break; } if (!item) return i; } return -1; } // Certified 50% void TList_sheet::do_output(CheckTime t) { if (_row == -1 || t == FINAL_CHECK) return; _out_id.restart(); TToken_string& rowsel = _sheet->row(_row); rowsel.restart(); for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) { const short id = _fld->atodlg(fld); if (t != STARTING_CHECK || field().field() == NULL) { TMask_field& f = field(id); f.set(rowsel.get()); if (field().dlg() != id) f.on_hit(); } } } // Certified 100% KEY TList_sheet::run() { _row = do_input(); _sheet->select(_row); const KEY k = _sheet->run(); switch (k) { case K_ENTER: _row = (int)_sheet->selected(); do_output(); break; default: break; } return k; } // Certified 100% bool TList_sheet::check(CheckTime t) { const bool passed = (_row = do_input()) != -1; if (passed) do_output(t); return passed; } /////////////////////////////////////////////////////////// // TBrowse /////////////////////////////////////////////////////////// // Certified 100% TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) : _relation(r), _cursor(new TCursor (r, filter, key)), _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) {} // Certified 100% TBrowse::TBrowse(TEdit_field* f, TCursor* c) : _relation(NULL), _cursor(c), _fld(f) {} // Certified 100% TBrowse::~TBrowse() { if (_relation) { delete _relation; delete _cursor; } } // Certified 100% void TBrowse::parse_display(TScanner& scanner) { const char* s; s = scanner.string(); _head.add(s); s = scanner.line(); _items.add(s); } void TBrowse::parse_input(TScanner& scanner) { const char* s = scanner.pop(); _inp_fn.add(s); s = scanner.pop(); if (*s == '"') // Constant string { scanner.push(); _inp_id.add(scanner.line()); } else // Field on the mask { TString80 str(s); if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field else scanner.push(); _inp_id.add(str); } } void TBrowse::parse_output(TScanner& scanner) { const char* s = scanner.pop(); #ifdef DBG field().atodlg(s); #endif _out_id.add(s); s = scanner.pop(); _out_fn.add(s); } bool TBrowse::parse_copy(const TString& what, const TBrowse* b) { const bool all = what == "AL"; if (all || what == "US") { set_insert(b->get_insert()); _filter = b->get_filter(); if (!all) return TRUE; } if (all || what == "IN") { _inp_id = b->_inp_id; _inp_fn = b->_inp_fn; if (!all) return TRUE; } if (all || what == "DI") { _head = b->_head; _items = b->_items; if (!all) return TRUE; } if (all || what == "OU") { _out_id = b->_out_id; _out_fn = b->_out_fn; _secondary = TRUE; } return TRUE; } void TBrowse::parse_join(TScanner& scanner) { TString80 j(scanner.pop()); // File or table CHECKS(_relation, "Can't join to NULL relation ", (const char*)j); int to; if (scanner.popkey() == "TO") // TO keyword { const char* t = scanner.pop(); to = name2log(t); } else { to = 0; // _relation->lfile()->num(); scanner.push(); } int key = 1; if (scanner.popkey() == "KE") key = scanner.integer(); else scanner.push(); byte alias = 0; if (scanner.popkey() == "AL") alias = scanner.integer(); else scanner.push(); TToken_string exp(80); if (scanner.pop() == "INTO") { const char* r = scanner.pop(); while (strchr(r, '=') != NULL) { exp.add(r); r = scanner.pop(); } } scanner.push(); #ifdef DBG if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); #endif if (isdigit(j[0])) _relation->add(atoi(j), exp, key, to, alias); // join file else { #ifdef DBG if (j.len() > 4) yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); else #endif _relation->add(j, exp, key, to, alias); // join table } } void TBrowse::parse_insert(TScanner& scanner) { if (scanner.popkey() == "RU") { _insert = "R"; _insert << scanner.line(); } else { _insert = "M"; _insert << scanner.line(); } _insert.trim(); } // Certified 100% TMask_field& TBrowse::field(short n) const { return _fld->mask().field(n); } // Ritorna il numero di campi non vuoti e non filtrati int TBrowse::do_input(bool filter) { int ne = 0; if (_inp_id.empty()) return ne; TRectype& cur = _cursor->curr(); cur.zero(); TRectype filtrec(cur); _inp_id.restart(); _inp_fn.restart(); TString80 val; // Value to output bool tofilter; for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { val = (fld+1); if (val.not_empty()) val.rtrim(1); tofilter = filter; } else { const short id = _fld->atodlg(fld); const bool filter_flag = strchr(fld, '@') != NULL; tofilter = filter && filter_flag; val = field(id).get(); if (field(id).is_edit() && val.not_empty() && !filter_flag) ne++; // Increment not empty fields count } TFieldref fldref(_inp_fn.get(), 0); // Output field fldref.write(val, _cursor->relation()); if (tofilter) { if (val.empty()) val.fill('~', fldref.len(cur)); fldref.write(val, filtrec); } } if (!filter) return ne; TString work(_filter.size()); for (int i = 0; _filter[i]; i++) { if (_filter[i] == '"') { do { work << _filter[i++]; } while (_filter[i] && _filter[i] != '"'); work << '"'; if (!_filter[i]) break; } else if (_filter[i] == '#') { work << '"' << field(atoi(&_filter[++i])).get() << '"'; while (isspace(_filter[i])) i++; while (isdigit(_filter[i])) i++; i--; } else work << _filter[i]; } _cursor->setfilter(work); _cursor->setregion(filtrec, filtrec); return ne; } void TBrowse::do_output(CheckTime t) { if (t == FINAL_CHECK) return; TString80 sum; TToken_string flds(24, '+'); _out_fn.restart(); for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) { const short id = field().atodlg(fld); TMask_field& f = field(id); flds = _out_fn.get(); if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) { sum.cut(0); for(const char* fr = flds.get(); fr; fr = flds.get()) { TFieldref fld(fr, 0); const char* val = fld.read(_cursor->relation()); sum << val; } f.set(sum); if (field().dlg() != id) f.on_hit(); } } } void TBrowse::do_clear() { for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) { TMask_field& f = field(atoi(fld)); if (f.field() == NULL && _inp_id.get_pos(fld) < 0) f.reset(); } } bool TBrowse::do_insert() { bool ok = FALSE; TString80 app; if (_insert[0] == 'M') { TString80 nm(_insert.mid(1)); if (strncmp(nm, "BATB", 4) == 0) // Programma gestione tabelle app = format("ba3 -0 %s", (const char*)nm.mid(4)); // Obbligatorio usare la format globale else // Programma generico di browse/edit app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file()->num()); // Obbligatorio usare la format globale } else { app = _insert.mid(1); #if XVT_OS == XVT_OS_WIN if (strnicmp(app, MainApp()->name(), 3) == 0) app.insert("a", 3); #endif } TMailbox mail; TMessage msg(cmd2name(app), MSG_AI, ""); mail.send(msg); TExternal_app a(app); a.run(); if (mail.check()) { TMessage* rcv = mail.next_s(MSG_AI); if (rcv != NULL) _rec = atoi(rcv->body()); if (_rec > 0) { _cursor->file()->readat(_rec); ok = _cursor->ok(); if (ok) do_output(); #ifdef DBG else error_box("Selezione da programma esterno errata"); #endif } } return ok; } TToken_string& TBrowse::create_siblings(TToken_string& siblings) { const TMask& mask = field().mask(); siblings = ""; // Azzera la lista dei campi associati if (!mask.is_running()) return siblings; // Non saprei come fare TBit_array key(4); // Elenco delle chiavi gia' utilizzate // 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 = atoi(i); const TMask_field& f = mask.field(id); if (!f.showed() || !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 (improbabile) const TCursor* c = b->cursor(); // Considera ricerche sullo stesso file ma con chiave diversa if (c && c->file()->num() == _cursor->file()->num() && key[c->key()] == FALSE) { const TString16 fn(_out_fn.get(n)); // Legge nome del campo su file const int pos = _items.get_pos(fn); // Determina header corrispondente if (pos >= 0) { siblings.add(id); const char* h = _head.get(pos); siblings.add(h); const int et = siblings.find('@'); if (et > 0) siblings.cut(et); key.set(c->key()); // Marca la chiave come usata } } } return siblings; } KEY TBrowse::run() { do_input(TRUE); _cursor->read(); const char* caption = field().prompt(); if (!isalnum(*caption)) caption = "Selezione"; KEY k = K_ESC; long selected = 0; TToken_string siblings; create_siblings(siblings); { TToken_string* sib = siblings.empty() ? NULL : &siblings; const byte buttons = _insert.empty() ? 0 : 1; TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); k = s.run(); selected = s.selected(); } switch (k) { case K_INS: k = do_insert() ? K_ENTER : K_ESC; break; case K_ENTER: *_cursor = selected; do_output(); break; default: if (k >= K_CTRL) { const short id = siblings.get_int((k - K_CTRL) << 1); TEdit_field& ef = (TEdit_field&)_fld->mask().field(id); if (ef.mask().is_running()) ef.set_focus(); else ef.mask().first_focus(-ef.dlg()); ef.mask().send_key(k = K_F9, 0); } break; } return k; } bool TBrowse::check(CheckTime t) { bool passed = TRUE; if (_secondary && t != RUNNING_CHECK) return TRUE; // if (_checked && t == FINAL_CHECK) // return TRUE; // _checked = TRUE; if (_fld->check_type() != CHECK_NONE) { const TMaskmode mode = (TMaskmode)field().mask().mode(); CheckType chk = _fld->check_type(); const int ne = do_input(TRUE); if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL; if (ne || chk == CHECK_REQUIRED) { _cursor->setkey(); _cursor->file()->read(_isequal); passed = _cursor->ok(); if (t != FINAL_CHECK) { if (passed) { _cursor->repos(); do_output(t); } else { do_clear(); _fld->set_dirty(2); } } } else if (t != FINAL_CHECK) do_clear(); } // _checked = passed; return passed; } bool TBrowse::empty_check() { const TMaskmode mode = (TMaskmode)field().mask().mode(); const bool no_check = mode == MODE_SEARCH || field().mask().query_mode(); if ( no_check || _fld->check_type() == CHECK_NONE || _fld->check_type() == CHECK_NORMAL) return TRUE; else return do_input() > 0; } /////////////////////////////////////////////////////////// // TEdit_field /////////////////////////////////////////////////////////// TEdit_field::TEdit_field(TMask* mask) : TMask_field(mask), _browse(NULL), _sheet(NULL), _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(TRUE), _forced(FALSE) {} TEdit_field::~TEdit_field() { if (_browse) delete _browse; else if (_sheet) delete _sheet; } word TEdit_field::class_id() const { return CLASS_EDIT_FIELD; } void TEdit_field::enable(bool on) { TMask_field::enable(on); if (_buttonwin != NULL_WIN) show_window(_buttonwin, on && _check_enabled && showed()); } void TEdit_field::show(bool on) { TMask_field::show(on); if (_buttonwin != NULL_WIN) show_window(_buttonwin, on && _check_enabled && enabled()); } void TEdit_field::parse_head(TScanner& scanner) { _size = scanner.integer(); if (_size < 1) { _size = 8; error_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); } _width = scanner.integer(); if (_width == 0) _width = _size; } const TBrowse* TEdit_field::get_browse(TScanner& scanner) const { const int id = scanner.integer(); TMask_field& m = mask().field(id); if (!m.is_edit()) { error_box("Il campo %d non puo' fare una COPY del campo %d", dlg(), id); return NULL; } TEdit_field& f = (TEdit_field&)m ; TBrowse* b = (TBrowse*) f.browse(); if (b == NULL) error_box("La USE del campo %d non puo' essere copiata da %d", id, dlg()); return b; } bool TEdit_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") // PICTURE { _picture = scanner.string(); return TRUE; } if (scanner.key() == "CH") { scanner.pop(); if (scanner.key() == "NO") _check = CHECK_NORMAL; else if (scanner.key() == "RE") _check = CHECK_REQUIRED; else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;} else _check = CHECK_NONE; return TRUE; } if (scanner.key() == "US") // USE { if (_browse != NULL) return error_box("USE duplicata nel campo %d", dlg()); int key = 1; TRelation* r; const int logicnum = scanner.integer(); TString16 tabmaskname; if (logicnum > 0) r = new TRelation(logicnum); else { tabmaskname = scanner.pop(); if (tabmaskname.len() > 4) return error_box("'%s' non e' una tabella valida: %d", (const char*)tabmaskname, dlg()); r = new TRelation(tabmaskname); } if (scanner.popkey() == "KE") { key = scanner.integer(); if (key < 1) { error_box("Chiave %d non valida nella USE del campo %d", key, dlg()); key = 1; } } else scanner.push(); const char* filter = ""; if (scanner.popkey() == "SE") filter = (const char*)scanner.line(); else scanner.push(); _browse = new TBrowse(this, r, key, filter); if (tabmaskname.not_empty()) { if (strncmp(MainApp()->name(), "ba3", 3) != 0) { tabmaskname.insert("MBATB", 0); _browse->set_insert(tabmaskname); } } return TRUE; } if (scanner.key() == "CO") // Copyuse { const TString16 what(scanner.popkey()); const TBrowse* b = get_browse(scanner); #ifdef DBG if (b == NULL) return yesnofatal_box("Impossibile COPYare la browse nel campo %d", dlg()); #endif if (what == "US" || what == "AL") _browse = new TBrowse(this, b->cursor()); if (_browse) return _browse->parse_copy(what, b); #ifdef DBG return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); #endif } if (scanner.key() == "JO") { #ifdef DBG if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); #endif _browse->parse_join(scanner); return TRUE; } if (scanner.key() == "SH") // SHEET { if (_sheet) return error_box("SHEET duplicato nel campo %d", dlg()); _sheet = new TList_sheet(this, _prompt, scanner.string()); return TRUE; } if (scanner.key() == "IT") // ITEM { if (_sheet == NULL) return error_box("ITEM senza SHEET nel campo %d", dlg()); _sheet->read_item(scanner); return TRUE; } if (scanner.key() == "IN") { if (_browse) _browse->parse_input(scanner); else if (_sheet) _sheet->parse_input(scanner); else error_box("INPUT senza USE o SHEET nel campo %d", dlg()); return TRUE; } if (scanner.key() == "DI") { if(!_browse) return error_box("DISPLAY senza USE nel campo %d", dlg()); _browse->parse_display(scanner); return TRUE; } if (scanner.key() == "OU") { if (_browse) _browse->parse_output(scanner); else if (_sheet) _sheet->parse_output(scanner); else return error_box("OUTPUT senza USE nel campo %d", dlg()); return TRUE; } if (scanner.key() == "AD") { if(!_browse) return error_box("ADD senza USE nel campo %d", dlg()); _browse->parse_insert(scanner); return TRUE; } if (scanner.key() == "VA") { const char* n = scanner.pop(); _validate_func = isdigit(*n) ? atoi(n) : -1; if (_validate_func < 0) return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); const int _nparms = scanner.integer(); if (_nparms < 0) return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d", dlg()); for(int i = 0; i < _nparms; i++) _validate_parms.add(scanner.operand()); return TRUE; } if (scanner.key() == "WA") { _warning = scanner.string(); return TRUE; } if (scanner.key() == "ME") { TFixed_string l(scanner.line().strip_spaces()); int m = 0; if (l[0] == '0') { l.ltrim(1); l.ltrim(); m = 1; } if (_message.objptr(m) == 0) _message.add(new TToken_string(64), m); TToken_string& ts = (TToken_string&)_message[m]; ts.add(l); return TRUE; } return TMask_field::parse_item(scanner); } void TEdit_field::create(WINDOW parent) { const int len = create_prompt(parent); long align = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; _x += len; #if XVTWS == WMWS const int delta = 2; #else const int delta = 1; #endif wincreate(WC_EDIT, _width+delta, 1, _str, parent, align); #if XVT_OS == XVT_OS_WIN HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW); SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo long style = GetWindowLong(hwnd, GWL_STYLE); if (_flags.uppercase) style != ES_UPPERCASE; // Edit in maiuscolo SetWindowLong(hwnd, GWL_STYLE, style); #endif if (_browse || _sheet) { long flags = default_flags(); if (flags & CTL_FLAG_DISABLED) { flags &= ~CTL_FLAG_DISABLED; flags |= CTL_FLAG_INVISIBLE; } _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, 2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9); } } void TEdit_field::destroy() { if (_buttonwin) { close_window(_buttonwin); _buttonwin = NULL_WIN; } TMask_field::destroy(); } void TEdit_field::set_window_data(const char* data) { TMask_field::set_window_data(format(data)); } void TEdit_field::set_field_data(const char* data) { _str = data; } const char* TEdit_field::get_field_data() const { return _str; } const char* TEdit_field::format(const char* d) { fpark = d; fpark.trim(); if (fpark.not_empty()) { if (fpark.len() > _size) { #ifdef DBG error_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size); #endif fpark.cut(_size); } if (_flags.uppercase) fpark.upper(); if (_flags.zerofilled) fpark.right_just(_size, '0'); else if (_flags.rightjust) fpark.right_just(_size); } return fpark; } const char* TEdit_field::picture_data(const char* data, bool video) { if (video) { set_title(win(), (char*)data); return get_window_data(); } set_window_data(data); TMask_field::get_window_data(); fpark.trim(); return fpark; } bool TEdit_field::validate(KEY k) { return ::validate(_validate_func, *this, k, _validate_parms); } // Certified 90% bool TEdit_field::on_hit() { if (_handler) { bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); if (!ok) return FALSE; } if (_message.objptr(1) && get() == "") do_message(1); else do_message(0); return TRUE; } bool TEdit_field::on_key(KEY key) { switch(key) { case K_TAB: if (_validate_func == AUTOEXIT_FUNC || _validate_func == NUMCALC_FUNC || _validate_func == STRCALC_FUNC) set_focusdirty(); if (to_check(K_TAB, TRUE)) { set(get()); bool ok = validate(key); // Check validation expression if (!ok) { if (_warning.not_empty()) error_box(_warning); return FALSE; } TMask& m = mask(); const bool query = m.query_mode(); if (_sheet) ok = query || _sheet->check(); // Check consistency else if (check_enabled() && _browse && (!query || forced())) ok = _browse->check(); // Check consistency if (!ok) { if (_warning.not_empty()) error_box(_warning); else error_box("Valore non consistente: %s", (const char*)get()); return FALSE; } ok = on_hit(); if (!ok) return FALSE; if (query && required() && in_key(0)) { const byte keys = m.num_keys(); for (int i = 1; i <= keys; i++) if (in_key(i) && m.key_valid(i)) { for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) m.field(fld).set_dirty(FALSE); dispatch_e_char(get_parent(win()), K_AUTO_ENTER); break; } } return TRUE; } break; case K_ENTER: if (field() != NULL || mask().mode() == NO_MODE) { if (focusdirty()) set(get()); bool ok = validate(K_ENTER); // Check validation expression if (!ok) { if (_warning.not_empty()) error_box(_warning); return FALSE; } const bool query = mask().query_mode(); // check consistency if (_sheet) ok = query || _sheet->check(FINAL_CHECK); else if (_browse && check_enabled()) { if (!query || forced()) { if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency else ok = _browse->empty_check(); } } else ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); if (!ok) { if (_warning.not_empty()) error_box(_warning); else error_box("Campo non consistente: '%s'", (const char*)get()); return FALSE; } } break; case K_F9: if (check_enabled()) { if (dirty()) set(get()); KEY k = K_ESC; if (_browse) k = _browse->run(); else if (_sheet) k = _sheet->run(); else beep(); if (mask().is_running() && k != K_F9) set_focus(); if (k == K_ENTER) { set_dirty(); if (mask().is_running()) mask().send_key(K_TAB, 0); else on_hit(); return TRUE; } else return FALSE; } break; default: break; } return TMask_field::on_key(key); } bool TEdit_field::has_check() const { if (_browse) return check_type() != CHECK_NONE; return _sheet != NULL; } bool TEdit_field::check(CheckTime t) { if (check_enabled() || (t == STARTING_CHECK && showed())) { if (_browse) return _browse->check(t); else if (_sheet) return _sheet->check(t); } return TRUE; } void TEdit_field::enable_check(bool on) { _check_enabled = on; if (_buttonwin != NULL_WIN) show_window(_buttonwin, on); } /////////////////////////////////////////////////////////// // Boolean_field /////////////////////////////////////////////////////////// TBoolean_field::TBoolean_field(TMask* m) : TMask_field(m), _on(FALSE) {} word TBoolean_field::class_id() const { return CLASS_BOOLEAN_FIELD; } void TBoolean_field::create(WINDOW parent) { wincreate(WC_CHECKBOX, strlen(_prompt)+4, 1, _prompt, parent, 0); } const char* TBoolean_field::get_window_data() const { CHECK(win(), "Control window not initialized"); fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; fpark[1] = '\0'; return fpark; } void TBoolean_field::set_window_data(const char* data) { CHECK(win(), "Control window not initialized"); if (data == NULL) data = ""; const bool b = toupper(*data) == 'X'; xvt_check_box(win(), b); } void TBoolean_field::set_field_data(const char* data) { if (data == NULL) data = ""; _on = toupper(*data) == 'X'; } const char* TBoolean_field::get_field_data() const { return _on ? "X" : " "; } bool TBoolean_field::parse_item(TScanner& scanner) { if (scanner.key() == "ME") { const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE if (_message.items() == 0) { _message.add(new TToken_string(16)); _message.add(new TToken_string(16)); } TToken_string& ts = (TToken_string&)_message[tf]; ts.add(scanner.line().strip_spaces()); return TRUE; } return TMask_field::parse_item(scanner); } void TBoolean_field::enable(bool on) { _flags.enabled = on; xvt_enable_control(_win, on); } bool TBoolean_field::on_hit() { if (_handler) { bool ok = _handler(*this, K_SPACE); if (!ok) return FALSE; } const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; do_message(n); return TRUE; } bool TBoolean_field::on_key(KEY key) { if (key == K_SPACE) { on_hit(); set_dirty(); return TRUE; } return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // Button_field /////////////////////////////////////////////////////////// TButton_field::TButton_field(TMask* m) : TMask_field(m) { _flags.persistent = TRUE; } word TButton_field::class_id() const { return CLASS_BUTTON_FIELD; } void TButton_field::parse_head(TScanner& scanner) { _width = scanner.integer(); if (_width < 1) _width = 9; _size = scanner.integer(); // Height if (_size < 1) _size = 1; } bool TButton_field::parse_item(TScanner& scanner) { return TMask_field::parse_item(scanner); } void TButton_field::create(WINDOW parent) { long flags = CTL_FLAG_CENTER_JUST; switch (dlg()) { case DLG_OK: if (_prompt.empty()) _prompt = "Conferma"; _virtual_key = _exit_key = K_ENTER; flags |= CTL_FLAG_DEFAULT; break; case DLG_CANCEL: if (_prompt.empty()) _prompt = "Annulla"; _virtual_key = _exit_key = K_ESC; break; case DLG_DELREC: _virtual_key = 'E'; _exit_key = K_DEL; break; case DLG_QUIT: if (_prompt.empty()) _prompt = "Fine"; _virtual_key = K_F4; _exit_key = K_QUIT; break; default: { _exit_key = 0; TToken_string* message = (TToken_string*)_message.objptr(0); if (message != NULL) { TToken_string msg(message->get(0), ','); const TFixed_string m(msg.get(0)); if (m == "EXIT") _exit_key = msg.get_int(); else if (msg.get_int() == 0) _exit_key = atoi(m); } const int n = _prompt.find('~'); _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; } break; } #if XWTWS == WMWS _prompt.center_just(_width); #endif wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); } void TButton_field::enable(bool on) { _flags.enabled = on; xvt_enable_control(_win, on); } void TButton_field::show(bool on) { TMask_field::show(on); } bool TButton_field::on_key(KEY key) { if (key == K_SPACE) { on_hit(); return TRUE; } return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // Date_field /////////////////////////////////////////////////////////// word TDate_field::class_id() const { return CLASS_DATE_FIELD; } void TDate_field::create(WINDOW w) { TEdit_field::create(w); if (automagic()) { TDate d(TODAY); set(d.string()); } } void TDate_field::parse_head(TScanner&) {} TDate_field::TDate_field(TMask* m) : TEdit_field(m) { _size = _width = 10; } bool TDate_field::on_key(KEY key) { if (to_check(key)) { TFixed_string data(get_window_data(), 15); data.trim(); if (data.not_empty() || required()) { bool changed = FALSE; if (isdigit(data[0])) { if (data.len() == 6) // Fix century (for this millenium only) { data.insert("19", 4); changed = TRUE; } for (int meno = 2; meno <= 5; meno += 3) if (data[meno] != '-') { data.insert("-", meno); changed = TRUE; } if (data.len() == 8) // Fix century (for this millenium only) { data.insert("19", 6); changed = TRUE; } } else { TDate g(TODAY); data.upper(); if (data == "IERI") --g; else if (data == "DOMANI") ++g; TString16 gstring(g.string()); if (data == "PRIMO") { gstring.overwrite("01-01", 0); } else if (data == "ULTIMO") { gstring.overwrite("31-12", 0); } data = gstring; changed = TRUE; } TDate d(data); if (!d.ok()) { // error_box("La data deve essere nel formato gg-mm-aaaa"); error_box("Data errata o formato non valido"); return FALSE; } else if (changed) TMask_field::set_window_data(d.string()); } } return TEdit_field::on_key(key); } /////////////////////////////////////////////////////////// // Real_field /////////////////////////////////////////////////////////// TReal_field::TReal_field(TMask* m) : TEdit_field(m) {} word TReal_field::class_id() const { return CLASS_REAL_FIELD; } void TReal_field::create(WINDOW w) { TEdit_field::create(w); if (_flags.firm) set(::format("%ld", MainApp()->get_firm())); else if (automagic()) { TDate d(TODAY); set(::format("%d", d.year())); } } bool TReal_field::on_key(KEY key) { if (to_check(key)) { if (roman()) { const int r = atoi(get_window_data()); if (r < 0) return error_box("Numero romano errato"); } else { const char* n = get(); if (*n && !real::is_real(n)) return error_box("Numero non valido"); const int segno = real(n).sign(); if (required() && segno == 0 && !mask().query_mode()) return error_box("Manca un valore indispensabile"); if (_flags.uppercase && segno < 0) return error_box("Il numero deve essere positivo"); } } return TEdit_field::on_key(key); } void TReal_field::parse_head(TScanner& scanner) { _size = scanner.integer(); #ifdef DBG if (_size < 1) { _size = 9; yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); } #endif _width = _size; _decimals = scanner.integer(); } void TReal_field::set_window_data(const char* data) { if (data == NULL) data = ""; if (roman()) { data = itor(atoi(data)); TMask_field::set_window_data(data); } else { real n(data); if (!n.is_zero()) { if (_flags.exchange) { const real& e = mask().exchange(); if (e != 1.0) n /= e; } if (_picture.empty()) data = n.stringa(_size, _decimals); else data = n.string(_picture); } else data = ""; TEdit_field::set_window_data(data); } } const char* TReal_field::get_window_data() const { TEdit_field::get_window_data(); if (roman()) { int r = atoi(fpark); if (r == 0) r = rtoi(fpark); if (r > 0) { int s = decimals(); if (s < 1) s = 4; if (_flags.zerofilled) fpark.format("%0*d", s, r); else fpark.format("%*d", s, r); } else fpark.cut(0); } else { fpark = real::ita2eng(fpark); if (_flags.exchange) { const real& e = mask().exchange(); if (e != 1.0) { real n(fpark); n *= e; if (n.is_zero()) fpark.cut(0); else fpark = n.string(); } } } return fpark; } void TReal_field::set_decimals(int d) { _decimals = d; if (_picture[0] == '.') { if (d > 0) _picture.format(".%d", d); else _picture = "."; } } void TReal_field::exchange(const real& vec, const real& nuo) { const int dec = (nuo != 1.0) ? 2 : 0; if (decimals() != dec) set_decimals(dec); else if (dec == 2) return; if (mask().is_running()) { const char* n = real::ita2eng(TEdit_field::get_window_data()); if (*n) { real r(n); r *= vec; r /= nuo; r.round(dec); TEdit_field::set_window_data(r.string(_picture)); } } } /////////////////////////////////////////////////////////// // List_field /////////////////////////////////////////////////////////// TList_field::TList_field(TMask* m) : TMask_field(m) {} word TList_field::class_id() const { return CLASS_LIST_FIELD; } void TList_field::read_item(TScanner& scanner) { TToken_string ts(scanner.string()); _codes.add(ts.get()); _values.add(ts.get()); ts = ""; while (scanner.popkey() == "ME") ts.add(scanner.line().strip_spaces()); scanner.push(); _message.add(ts); } void TList_field::parse_head(TScanner& scanner) { _size = scanner.integer(); _width = scanner.integer(); if (_width < 1) _width = _size+3; } bool TList_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") // ITEM { read_item(scanner); return TRUE; } if (scanner.key() == "LI") // LISTITEM { TScanner sc(scanner.pop()); while (sc.popkey() == "IT") // ITEM read_item(sc); return TRUE; } return TMask_field::parse_item(scanner); } int TList_field::items() const { return _codes.items(); } void TList_field::add_item(const char* s) { TToken_string t(s); const TString16 item(t.get()); const int pos = _codes.get_pos(item); if (pos < 0 ) { _codes.add(item); win_list_add(win(), -1, (char*)t.get()); } } void TList_field::delete_item(const char* s) { TString16 t(s); const int pos = _codes.get_pos(t); if (pos >= 0 ) { _codes.destroy(pos); win_list_delete(win(), pos); if (mask().is_running()) { win_list_set_sel(win(), 0, TRUE); if (showed()) on_hit(); } } } void TList_field::add_list() { if (roman() && _codes.items() < 12) { TString csafe, vsafe; if (atoi(_codes) > 0) { csafe = _codes; _codes = ""; vsafe = _values; _values = ""; } _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); if (atoi(csafe) > 0) { _codes.add(csafe); _values.add(vsafe); if (_message.objptr(0)) { _message.add(_message[0], _codes.items()-1); _message.add(NULL, 0); } } } SLIST lst = slist_new(); for (const char* item = _values.get(0); item; item = _values.get()) slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L); win_list_add(win(), -1, (char*)lst); slist_dispose(lst); const char* init = ""; if (roman() && automagic()) init = format("%02d", TDate(TODAY).month()); set_field_data(init); } void TList_field::replace_items(const char* codes, const char* values) { _codes = codes; _values = values; if (win() != NULL_WIN) { win_list_clear(win()); add_list(); current(0); } } void TList_field::create(WINDOW parent) { const int len = create_prompt(parent); _x += len; wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); add_list(); } int TList_field::str2curr(const char* data) { TString16 str(data); if (roman() && str.len() < 2) str.insert("0",0); if (_flags.uppercase) str.upper(); int i = str.not_empty() ? _codes.get_pos(str) : 0; if (i < 0) // Se non trova il codice ritenta dopo trim { for (i = 0; str[i] == '0' || str[i] == ' '; i++); if (i > 0) { str.ltrim(i); i = _codes.get_pos(str); } } if (i < 0) { if (items() && str.not_empty()) yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", data, prompt(), dlg()); i = 0; } return i; } void TList_field::set_window_data(const char* data) { CHECKD(win(), "Control window not initialized ", dlg()); const int i = str2curr(data); current(i); } void TList_field::current(int n) { win_list_set_sel(win(), n, TRUE); } int TList_field::current() const { const int sel = win_list_get_sel_index(win()); #ifdef DBG if (sel < 0 && items() > 0) error_box("Lista senza selezione nel campo %d", dlg()); #endif return sel; } const char* TList_field::get_window_data() const { const int c = current(); const char* v = ((TList_field*)this)->_codes.get(c); return v; } void TList_field::set_field_data(const char* data) { if (data == NULL || *data == '\0') data = _codes.get(0); _str = data; } bool TList_field::on_hit() { if (_handler) { bool ok = _handler(*this, K_SPACE); if (!ok) return FALSE; } const int n = mask().is_running() ? current() : str2curr(_str); do_message(n); return TRUE; } const char* TList_field::get_field_data() const { return _str; } bool TList_field::on_key(KEY key) { if (key >= '0' && key <= 'z') { const int index = win_list_get_sel_index(win()); CHECK(index >= 0, "List with no selection!"); int newindex = -1; #if XVTWS == WMWS if (key >= 'A' && key <= 'z') { for (int i = index+1; i != index; i++) { char item[16]; bool flag; do { flag = win_list_get_elt(win(), i, item, 16); if (!flag) { CHECK(i, "La lista e' vuota!"); i = -1; break; } } while (!flag); if (flag && toupper(*item) == toupper(key)) { newindex = i; break; } } // for } // alphabetic #endif if (key >= '0' && key <= '9') { newindex = (key == '0') ? 10 : key - '1'; if (newindex > items()) { newindex = -1; beep(); } } if (newindex >= 0) { win_list_suspend(win()); win_list_set_sel(win(), index, FALSE); win_list_set_sel(win(), newindex, TRUE); win_list_resume(win()); } } // alphanumeric #if XVTWS == VMWS if (key == K_TAB && class_id() == CLASS_LIST_FIELD) dispacth_e_char(win(), K_F9); #endif if (key == K_SPACE) on_hit(); return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // TRadio_field /////////////////////////////////////////////////////////// TRadio_field::TRadio_field(TMask* mask) : TList_field(mask), _nitems(0), _active_item(0) {} word TRadio_field::class_id() const { return CLASS_RADIO_FIELD; } void TRadio_field::create(WINDOW parent) { const short id = dlg(); // Salva il control id if (_prompt.not_empty()) { const int dy = _codes.items()+2; create_prompt(parent, _width, dy); } _x++; _y++; _values.restart(); const char* s; for(_nitems = 0; (s = _values.get()) != NULL; _nitems++, _y++) { CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); wincreate(WC_RADIOBUTTON, _width-2, 1, s, parent,0); _radio_ctl_win[_nitems] = _win; _dlg += 1000; } _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug _dlg = id; // Ripristina control id set_field_data(""); } void TRadio_field::destroy() { if (_promptwin) { close_window(_promptwin); _promptwin = NULL_WIN; } for(int i = 0; i < _nitems; i++) { close_window(_radio_ctl_win[i]); _radio_ctl_win[i] = NULL_WIN; } } int TRadio_field::current() const { const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); return c; } void TRadio_field::current(int n) { _active_item = n; xvt_check_radio_button(win(), _radio_ctl_win, _nitems); } void TRadio_field::check_radiobutton(WINDOW checked) { for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); CHECK(i < _nitems, "Trying to check an invalid radio button"); current(i); } void TRadio_field::enable(bool on) { _flags.enabled = on; for(int i = 0; i < _nitems; i++) xvt_enable_control(_radio_ctl_win[i], on); } void TRadio_field::show(bool on) { if (_promptwin) show_window(_promptwin, on); for(int i = 0; i < _nitems; i++) show_window(_radio_ctl_win[i], on); _flags.showed = on; } // Return TRUE if focus has left the radio bool TRadio_field::move_focus(int d) { const int act = _active_item + d; if (act >= _nitems || act < 0) { _active_item = current(); return TRUE; } xvt_set_front_control(_radio_ctl_win[_active_item = act]); return FALSE; } /////////////////////////////////////////////////////////// // TGroup_field /////////////////////////////////////////////////////////// TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) { _flags.persistent = TRUE; } // _size means _heigth void TGroup_field::parse_head(TScanner& scanner) { _width = scanner.integer(); _size = scanner.integer(); } void TGroup_field::create(WINDOW parent) { const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); }