#include #include #include #include #include #include #include #include #include #include typedef bool (*VAL_FUNC)(TEdit_field&, KEY k); HIDDEN const TArray* _parms; HIDDEN int get_val_param_num() { return _parms->items(); } HIDDEN const char* get_val_param(int i) { return i < _parms->items() ? (const char*)((const TString&) (*_parms)[i]):"" ; } HIDDEN bool _expr_val(TEdit_field& f, KEY) { TTypeexp type = atoi(get_val_param(0)) == 0 ? _numexpr :_strexpr; TExpression e(get_val_param(1), type); for (int i = 0 ; i < e.numvar(); i++) { const char* s = e.varname(i); if (s[0] != '#') { TString80 err; err << "Non trovo la variabile " << s << " in " << e; return f.error_box((const char*)err); } s++; const int fldid = atoi(s); if (type == _numexpr) { const real r(fldid == 0 ? f.get() : f.mask().get(fldid)); e.setvar(i, r); } else { const char* v = fldid == 0 ? f.get() : f.mask().get(fldid); e.setvar(i, v); } } return bool(e); } HIDDEN bool _emptycopy_val(TEdit_field& f, KEY) { if (f.get().empty()) { const short id = atoi(get_val_param(0)); const TFixed_string val(f.mask().get(id)); if (val.not_empty()) { f.set(val); f.on_hit(); } } return TRUE; } bool pi_check(const char * st, const char * paiva) { int tot = 0, y; TString16 stato (st); TString16 pi (paiva); if ((stato.not_empty()) && (stato != "IT")) return TRUE; if (pi.empty()) return TRUE; if (pi.len() != 11) return FALSE; for (int i = 0; i <= 9; i++) { if ((i + 1) & 0x0001) tot += (pi[i] - '0'); else { y = (pi[i] - '0') * 2; if (y >= 10) { tot += (y / 10); y = y % 10; } tot += y; } } y = 10 - (tot % 10); if (y == 10) y = 0; bool ok = (pi[10] == (y + '0')); return ok; } // Controlla la partita iva se e' non vuota ed italiana HIDDEN bool _pi_val(TEdit_field& f, KEY) { if (f.mask().query_mode()) return TRUE; TString16 stato(f.mask().get(atoi(get_val_param(0)))), pi(f.get()); if (stato.not_empty() && stato != "IT") return TRUE; if (pi.empty()) return TRUE; if (pi.len() != 11) { f.error_box("Lunghezza partita IVA diversa da 11"); return FALSE; } bool ok = pi_check (stato, pi); if (!ok) { if(f.dirty()) { ok = f.yesno_box("Partita IVA errata, la accetto ugualmente?"); if (ok) f.set_dirty(FALSE); } else ok = TRUE; // Era gia' errata e la ho accettata } return ok; } HIDDEN bool __cf_check (const char * codcf) { const TString16 cf (codcf); if (cf.len() != 16) return FALSE; const TFixed_string tab("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); int tot = 0, y; byte val[36][2]; val[0][0] = 0; val[0][1] = 1; val[1][0] = 1; val[1][1] = 0; val[2][0] = 2; val[2][1] = 5; val[3][0] = 3; val[3][1] = 7; val[4][0] = 4; val[4][1] = 9; val[5][0] = 5; val[5][1] = 13; val[6][0] = 6; val[6][1] = 15; val[7][0] = 7; val[7][1] = 17; val[8][0] = 8; val[8][1] = 19; val[9][0] = 9; val[9][1] = 21; val[10][0] = 10; val[10][1] = 2; val[11][0] = 11; val[11][1] = 4; val[12][0] = 12; val[12][1] = 18; val[13][0] = 13; val[13][1] = 20; val[14][0] = 14; val[14][1] = 11; val[15][0] = 15; val[15][1] = 3; val[16][0] = 16; val[16][1] = 6; val[17][0] = 17; val[17][1] = 8; val[18][0] = 18; val[18][1] = 12; val[19][0] = 19; val[19][1] = 14; val[20][0] = 20; val[20][1] = 16; val[21][0] = 21; val[21][1] = 10; val[22][0] = 22; val[22][1] = 22; val[23][0] = 23; val[23][1] = 25; val[24][0] = 24; val[24][1] = 24; val[25][0] = 25; val[25][1] = 23; val[26][0] = 0; val[26][1] = 1; val[27][0] = 1; val[27][1] = 0; val[28][0] = 2; val[28][1] = 5; val[29][0] = 3; val[29][1] = 7; val[30][0] = 4; val[30][1] = 9; val[31][0] = 5; val[31][1] = 13; val[32][0] = 6; val[32][1] = 15; val[33][0] = 7; val[33][1] = 17; val[34][0] = 8; val[34][1] = 19; val[35][0] = 9; val[35][1] = 21; for (int i = 0; i <= 14; i++) { y = tab.find(cf[i]); if (y >= 0) tot += val[y][(i + 1) & 0x1]; } const bool ok = (cf[15] == (tot % 26) + 'A'); return ok; } bool cf_check (const char * stato, const char * codcf) { TString16 cf (codcf); if (cf.empty()) return TRUE; const bool ok = (cf.len() == 11 && isdigit(cf[0])) ? pi_check(stato, cf) : __cf_check(cf); return ok; } HIDDEN bool _cf_val(TEdit_field& f, KEY key) { if (f.mask().query_mode()) return TRUE; const TString16 cf(f.get()); bool ok = TRUE; if (cf.empty()) return TRUE; if (cf.len() == 11 && isdigit(cf[0])) { TString16 stato(f.mask().get(atoi(get_val_param(0)))); if (stato.not_empty() && stato != "IT") return TRUE; ok = pi_check (stato, cf); } else ok = __cf_check(cf); if (!ok) { if(f.dirty()) { ok = f.yesno_box("Codice fiscale errato: lo accetto ugualmente?"); if (ok) f.set_dirty(FALSE); } else ok = TRUE; // Era gia' errato al caricamento quindi lo accetto } return ok; } HIDDEN bool _xt_pi_val(TEdit_field& f, KEY key) { TMask& m = f.mask(); if (m.query_mode()) return TRUE; TString16 value(f.get()); if (value.empty()) return f.error_box("Partita IVA obbligatoria"); const TString16 stato(m.get(atoi(get_val_param(0)))); if (stato.not_empty() && stato != "IT") return TRUE; if (!_pi_val(f, key)) return FALSE; TLocalisamfile c(LF_COMUNI); const int pi = atoi(value.mid(7,3)); for (int i = 1 ; i < 3; i++) { const int comune = atoi(get_val_param(i)); if (comune) { const TString16 com(m.get(comune)); // Comune residenza fiscale e residenza if (com.not_empty()) { c.zero(); c.put("COM", com); if (c.read() == NOERR) { const int s1 = c.get_int("UFFIVA1"); const int s2 = c.get_int("UFFIVA2"); const int s3 = c.get_int("UFFIVA3"); if (pi != s1 && pi != s2 && pi != s3) { const char* ui = format("%03d", s1); if (f.yesno_box("Ufficio IVA della partita IVA non congruente: correggere in %s?", ui)) { value.overwrite(ui, 7); f.set(value); } } break; } } } } return TRUE; } HIDDEN bool _xtz_pi_val(TEdit_field& f, KEY key) { if (f.mask().query_mode()) return TRUE; TString16 pi(f.get()); if (pi.empty()) return TRUE; return _xt_pi_val(f, key); } HIDDEN bool _xt_cf_val(TEdit_field& f, KEY key) { if (f.mask().query_mode()) return TRUE; TString16 cf(f.get()); if (cf.empty()) return f.error_box("Codice fiscale obbligatorio"); if (!_cf_val(f, key)) return FALSE; if (cf.len() == 11 && isdigit(cf[0])) { // if (!_xt_pi_val(f, key)) return FALSE; // TString16 stato(f.mask().get(atoi(get_val_param(0)))); // if ((stato.not_empty()) && (stato != "IT")) return TRUE; return TRUE; } bool passed = __cf_check(cf); if (!passed) return TRUE; TMask& m = f.mask(); TMask_field& fld_sex = m.field(atoi(get_val_param(1))); TMask_field& fld_dat = m.field(atoi(get_val_param(2))); TMask_field& fld_com = m.field(atoi(get_val_param(3))); const char sesso = fld_sex.get()[0]; TString16 data(fld_dat.get()); TString16 com(fld_com.get()); TString16 wm("LMNPQRSTUV"); int p; if ((p = wm.find(cf[6])) != -1) cf[6] = '0' + p; if ((p = wm.find(cf[7])) != -1) cf[7] = '0' + p; if ((p = wm.find(cf[9])) != -1) cf[9] = '0' + p; if ((p = wm.find(cf[10])) != -1) cf[10] = '0' + p; if ((p = wm.find(cf[12])) != -1) cf[12] = '0' + p; if ((p = wm.find(cf[13])) != -1) cf[13] = '0' + p; if ((p = wm.find(cf[14])) != -1) cf[14] = '0' + p; int gn = atoi(cf.mid(9,2)); if ((sesso == 'F' && gn < 40) || (sesso == 'M' && gn > 40)) { passed = fld_sex.yesno_box("Sesso non congruente al codice fiscale:\n" "correzione automatica?"); if (passed) fld_sex.set(sesso == 'M' ? "F" : "M"); else return TRUE; } if (gn > 40) gn -= 40; // Aggiusta giorno di nascita delle donne // Controllo data di nascita wm = "ABCDEHLMPRST"; if (data.not_empty()) { const TDate d(data); int err = 0; if ((d.year() % 100) != atoi(cf.mid(6, 2))) err = 1; if (wm[d.month() - 1] != cf[8]) err = 2; if (d.day() != gn) err = 3; if (err != 0) { const char* const what = err==1 ? "Anno" : (err==2 ? "Mese" : "Giorno"); passed = fld_dat.yesno_box("%s di nascita non congruente al codice fiscale: correzione automatica?", what); if (passed) data = ""; else return TRUE; } } if (data.empty()) { const int mn = wm.find(cf[8]) + 1; if (mn > 0) { const TDate d(gn, mn, 1900 + atoi(cf.mid(6, 2))); fld_dat.set(d.string()); } } // Controllo del comune di nascita const char* const codcom = cf.mid(11, 4); if (com.not_empty() && com != codcom) { passed = fld_com.yesno_box("Comune non congruente al codice fiscale: correzione automatica?"); if (passed) com = ""; else return TRUE; } if (com.empty()) { fld_com.set(codcom); fld_com.on_key(K_TAB); } return TRUE; } HIDDEN bool _xtz_cf_val(TEdit_field& f, KEY key) { if (f.mask().query_mode()) return TRUE; const char* cf = f.get(); return (*cf == '\0') ? TRUE : _xt_cf_val(f, key); } HIDDEN bool _notempty_val(TEdit_field& f, KEY) { return f.mask().query_mode() || f.get().not_empty(); } HIDDEN bool _date_cmp(TEdit_field& f, KEY) { TFixed_string s(f.get()); if (s.empty()) return TRUE; TDate d0(s), d1(f.mask().get(atoi(get_val_param(1)))); TFixed_string op(get_val_param(0)); if (op == "==") return d0 == d1; if (op == "!=") return d0 != d1; if (op == ">") return d0 > d1; if (op == "<") return d0 < d1; if (op == ">=") return d0 >= d1; if (op == "<=") return d0 <= d1; #ifdef DBG f.error_box("Bad date operator '%s' in field %d", (const char*) op, f.dlg()); #endif return FALSE; } HIDDEN bool _fixlen_val(TEdit_field& f, KEY) { const TFixed_string s(f.get()); if (s.empty()) return TRUE; const int length = atoi(get_val_param(0)); const bool ok = s.len() == length; if (!ok) f.error_box("Lunghezza errata: deve essere %d", length); return ok; } HIDDEN bool _mtcheck_val(TEdit_field& f, KEY) { const int month = atoi(f.get()); if (month < 1 || month > 13) return FALSE; TLocalisamfile d(LF_NDITTE); d.zero(); d.put(NDT_CODDITTA, main_app().get_firm()); d.read(); if (d.bad()) return TRUE; if (d.get_char(NDT_FREQVIVA) == 'M') return TRUE; return month == 13 || (month % 3) == 0; } HIDDEN bool _reqif_val(TEdit_field& f, KEY k) { if (k == K_ENTER) { if (f.get().not_empty()) return TRUE; const int nparms = get_val_param_num(); for (int i = 0 ; i < nparms; i++) { const short id = atoi(get_val_param(i)); if (id > 0 && f.mask().get(id).not_empty()) return FALSE; } } return TRUE; } HIDDEN bool _autoexit_val(TEdit_field& f, KEY key) { TMask& m = f.mask(); if (m.mode() != MODE_QUERY) return TRUE; const int next = m.next_fld(); if (next != DLG_NULL && next != f.dlg() && m.field(next).in_key(0)) { const byte last = m.num_keys(); for (byte k = 1; k <= last; k++) if (f.in_key(k) && m.field(next).in_key(k)) return TRUE; } const int nparms = get_val_param_num(); bool one_not_empty = FALSE; for (int i = nparms; i-- > 0;) { const short id = f.atodlg(get_val_param(i)); const TMask_field& c = f.mask().field(id); const bool empty = c.get().empty(); if (empty) { if (c.check_type() != CHECK_NONE || one_not_empty) return TRUE; } else one_not_empty = TRUE; } if (key == K_TAB) { if (one_not_empty) f.mask().stop_run(K_AUTO_ENTER); } return TRUE; } HIDDEN bool _numcalc_val(TEdit_field& f, KEY k) { if (k != K_TAB) return TRUE; TExpression e(get_val_param(0), _numexpr); for (int i = 0 ; i < e.numvar(); i++) { const char* s = e.varname(i); if (s[0] != '#') { TString80 err; err << "Cannot load variable " << s << " in " << e; return f.error_box((const char*)err); } s++; const int fldid = atoi(s); e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); } const TFixed_string s((const char*)e); f.set(s); return TRUE; } HIDDEN bool _strcalc_val(TEdit_field& f, KEY k) { if (k != K_TAB) return TRUE; TExpression e(get_val_param(0), _strexpr); for (int i = 0 ; i < e.numvar(); i++) { const char* s = e.varname(i); if (s[0] != '#') { TString80 err; err << "Cannot load variable " << s << " in " << e; return f.error_box((const char*)err); } s++; const int fldid = atoi(s); e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); } TFixed_string s((const char*) e); f.set(s); return TRUE; } HIDDEN bool _onereq_val(TEdit_field& f, KEY k) { if (k != K_ENTER) return TRUE; const TMask& m = f.mask(); if (m.mode() == MODE_QUERY) return TRUE; const int nparms = get_val_param_num(); for (int i = 0; i < nparms ; i++) { const char* s = m.get(atoi(get_val_param(i))); if (*s) return TRUE; } return FALSE; } HIDDEN bool _chkfld_val(TEdit_field& f, KEY k) { if (f.to_check(k)) { const int fldid = atoi(get_val_param(0)); if (fldid == THIS_FIELD) { if (!f.required() && f.get().empty()) return TRUE; else return f.check(); } TMask_field & chkfld = f.mask().field(fldid); chkfld.set(f.get()); return chkfld.check(); } return TRUE; } HIDDEN bool _filename_val(TEdit_field& f, KEY) { const TFilename fn(f.get()); return fn.ok(); } HIDDEN bool _zerofill_val(TEdit_field& f, KEY k) { if (f.to_check(k)) { const int columns = atoi(get_val_param(0)); TString& val = f.get(); if (val.len() < columns && real::is_natural(val)) { val.right_just(columns, '0'); f.set(val); } } return TRUE; } HIDDEN bool _alpha_val(TEdit_field& f, KEY k) { if (f.to_check(k)) { const TString& s = f.get(); for (int i = 0; s[i]; i++) if (!isalpha(s[i])) return error_box("Sono ammessi solo caratteri alfabetici"); } return TRUE; } HIDDEN bool _not_empty_chkfld_val(TEdit_field& f, KEY k) { const bool ok = (f.to_check(k) && f.get().not_empty()) ? f.check() : TRUE; return ok; } #define MAX_FUNC 22 HIDDEN VAL_FUNC _global_val_func[MAX_FUNC] = { _expr_val, _emptycopy_val, _pi_val, _cf_val, _notempty_val, _date_cmp, _xt_pi_val, _xt_cf_val, _xtz_pi_val, _xtz_cf_val, _fixlen_val, _mtcheck_val, _reqif_val, _autoexit_val, _numcalc_val, _strcalc_val, _onereq_val, _chkfld_val, _filename_val, _zerofill_val, _alpha_val, _not_empty_chkfld_val }; bool validate(int fn, TEdit_field& f, KEY k, const TArray& parms) { _parms = &parms; return (fn >= 0 && fn < MAX_FUNC) ? _global_val_func[fn](f, k) : TRUE; }