#include "calib01.h" #include "calibmsk.h" #include #include /////////////////////////////////////////////////////////// // TAnal_tree /////////////////////////////////////////////////////////// struct TAnal_tree_pos : public TObject { TRecnotype _recno; TToken_string _key; void as_string(TString& id) const; int level() const { return _key.items(); } void reset(); }; void TAnal_tree_pos::as_string(TString& id) const { id.format("%ld|%s", _recno, (const char*)_key); } void TAnal_tree_pos::reset() { _recno = 0; _key.cut(0); } class TAnal_tree : public TBidirectional_tree { TLocalisamfile* _file; const TArray& _key1_fields; const TArray& _key2_fields; TAnal_tree_pos _curr; protected: virtual void node2id(const TObject* node, TString& id) const; virtual bool goto_firstson(); virtual bool goto_rbrother(); virtual bool goto_node(const TString &id); virtual TObject* curr_node() const; virtual bool goto_father(); virtual bool goto_lbrother(); virtual bool get_description(TString& desc) const; protected: void update_curr(); const char* get_key_field(int key = 1) const; int level_of(const TToken_string& key) const; int level_of_file() const; const TToken_string& curr_of_file() const; int curr_level() const; int max_level() const; const TToken_string& father_of(const TToken_string& key) const; const TToken_string& father_of_file() const; bool repos() const; public: virtual bool goto_root(); TAnal_tree(int logicnum, const char* tabname, const TArray& key1, const TArray& key2); virtual ~TAnal_tree(); }; /////////////////////////////////////////////////////////// // TAnal_msk /////////////////////////////////////////////////////////// #define F_TREE 99 short TAnal_msk::get_field_id(int n, int k) const { short id = 0; if (n >= 0 && n < fieldrefs(1)) { if (k == 2) id = F_DES1+n; else id = F_KEY1+n; } return id; } bool TAnal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_TREE: if (e == fe_select) { if (edit_mode() && !dirty()) set_mode(MODE_QUERY); if (query_mode()) { const TTree_field& fld = (const TTree_field&)o; const TTree& tree = *fld.tree(); TToken_string curr; tree.curr_id(curr); for (int i = 0; ; i++) { const short id = get_field_id(i); if (id <= 0) break; const char* tok = curr.get(i+1); TEdit_field& e = efield(id); e.set(tok); e.show(); } stop_run(K_AUTO_ENTER); } else beep(0); } break; default: break; } return true; } int TAnal_msk::compute_offset() const { int delta = 0; RCT rct; xvt_vobj_get_client_rect(TASK_WIN, &rct); if (rct.right > 720) delta = (rct.right - 720) / 2 / CHARX; return delta; } void TAnal_msk::read(const char* name) { const int delta = compute_offset(); if (delta > 0) { const TFilename outname = "anal.msk"; TFilename inpname = name; inpname.ext("msk"); inpname.custom_path(); ofstream out(outname); TString line; int status = 0; TScanner inp(inpname); while (!inp.eof()) { line = inp.line(); switch (status) { case 0: if (line.starts_with("PA")) status = 1; // Ho trovato la prima pagina break; case 1: if (line.starts_with("PR")) // Ho trovato un prompt sulla prima pagina { TToken_string l(line, ' '); int x = l.get_int(1); if (x >= 0) { x += delta; l.add(x, 1); line = l; } } else if (line.starts_with("PA")) // Ho finito la prima pagina { status = 2; } break; default: break; } out << line << endl; } out.close(); read_mask(outname, 0, 0); xvt_fsys_removefile(outname); } else read_mask(name, 0, 0); create_key_fields(); create_tree_field(); } int TAnal_msk::create_key_fields() { return 0; } short TAnal_msk::create_tree_field() { short id = 0; const int delta = compute_offset(); if (delta > 0) { id = F_TREE; add_tree(id, 0, 0, 1, (delta-1)*2, -1); TAnal_tree* t = new TAnal_tree(get_logicnum(), get_tabname(), _key1_fields, _key2_fields); tfield(id).set_tree(t); t->goto_root(); t->expand(); } set_handlers(); return id; } void TAnal_msk::update_tree_field() { const int pos = id2pos(F_TREE); if (pos >= 0) { TTree_field& t = tfield(F_TREE); t.win().force_update(); } } void TAnal_msk::add_fieldref(const char* name, int from, int to, int key) { TArray& a = key == 1 ? _key1_fields : _key2_fields; TString80 str; str << name; if (from > 0) str << '[' << from << ',' << to << ']'; TFieldref* fr = new TFieldref(str, get_logicnum()); a.add(fr); } int TAnal_msk::fieldrefs(int k) const { const TArray& a = k == 1 ? _key1_fields : _key2_fields; return a.items(); } const TFieldref& TAnal_msk::fieldref(int n, int k) const { const TArray& a = k == 1 ? _key1_fields : _key2_fields; return (const TFieldref&)a[n]; } const TToken_string& TAnal_msk::get_key_value(const TRectype& rec, int c) const { TToken_string& val = get_tmp_string(); const int tot = fieldrefs(c); for (int i = 0; i < tot; i++) { const TFieldref& field = fieldref(i, c); val.add(field.read(rec)); } return val; } const TToken_string& TAnal_msk::get_key_value(int c) const { TToken_string& val = get_tmp_string(); for (TEditable_field* f = get_key_field(c, true); f != NULL; f = get_key_field(c, false)) { val.add(f->get()); } return val; } /////////////////////////////////////////////////////////// // TAnal_tree /////////////////////////////////////////////////////////// const TToken_string& TAnal_tree::curr_of_file() const { TToken_string& k = get_tmp_string(); const TRectype& rec = _file->curr(); for (int i = 0; i < max_level(); i++) { const TFieldref& fld = (const TFieldref&)_key1_fields[i]; k.add(fld.read(rec)); } for (int j = k.len()-1; j >= 0; j--) { if (k[j] == ' ' || k[j] == k.separator()) k.cut(j); else break; } return k; } int TAnal_tree::level_of(const TToken_string& k) const { return k.items(); } int TAnal_tree::level_of_file() const { const TToken_string& str = curr_of_file(); return level_of(str); } int TAnal_tree::curr_level() const { return level_of(_curr._key); } int TAnal_tree::max_level() const { return _key1_fields.items(); } const TToken_string& TAnal_tree::father_of(const TToken_string& key) const { const int pos = key.rfind(key.separator()); if (pos <= 0) return EMPTY_STRING; TToken_string& k = get_tmp_string(); k = key.left(pos); return k; } const TToken_string& TAnal_tree::father_of_file() const { const TToken_string& k = curr_of_file(); return father_of(k); } void TAnal_tree::update_curr() { _curr._key = curr_of_file(); if (_curr._key.not_empty()) _curr._recno = _file->recno(); else _curr.reset(); } bool TAnal_tree::repos() const { bool ok = false; if (_curr.level() > 0) { if (_file->recno() != _curr._recno) ok = ((TLocalisamfile*)_file)->readat(_curr._recno) == NOERR; else ok = true; } return ok; } void TAnal_tree::node2id(const TObject* node, TString& id) const { const TAnal_tree_pos* pos = (const TAnal_tree_pos*)node; pos->as_string(id); } bool TAnal_tree::goto_root() { const bool ok = _file->first() == NOERR; if (ok) update_curr(); else _curr.reset(); return ok; } bool TAnal_tree::goto_firstson() { bool ok = _curr.level() < max_level() && repos(); if (ok) { ok = _file->next() == NOERR; if (ok) { ok = father_of_file() == _curr._key; if (ok) update_curr(); } } return ok; } bool TAnal_tree::goto_rbrother() { bool ok = false; if (repos()) { const TToken_string curr_father = father_of(_curr._key); while (_file->next() == NOERR) { const int lev = level_of_file(); if (lev > _curr.level()) continue; const TToken_string& next_father = father_of_file(); ok = next_father == curr_father; break; } if (ok) update_curr(); } return ok; } bool TAnal_tree::goto_node(const TString &id) { const TRecnotype rec = atol(id); const int err = _file->readat(rec); if (err == NOERR) update_curr(); return err == NOERR; } bool TAnal_tree::goto_father() { const int lev = _curr.level(); bool ok = lev > 1; if (ok) { TRectype& rec = _file->curr(); rec.zero(); for (int i = 0; i < lev-1; i++) { const char* val = _curr._key.get(i); const TFieldref& fld = (const TFieldref&)_key1_fields[i]; fld.write(val, rec); } ok = _file->read() == NOERR; if (ok) update_curr(); } return ok; } bool TAnal_tree::goto_lbrother() { bool ok = false; if (repos()) { const TString curr_father = father_of(_curr._key); while (_file->prev() == NOERR) { const int lev = level_of_file(); if (lev > _curr.level()) continue; const TString& next_father = father_of_file(); ok = next_father == curr_father; break; } if (ok) update_curr(); } return ok; } TObject* TAnal_tree::curr_node() const { return (TObject*)&_curr; } bool TAnal_tree::get_description(TString& desc) const { const bool ok = repos(); if (ok) { const int lev = _curr.level(); if (lev > 0) { const TFieldref& fld1 = (const TFieldref&)_key1_fields[lev-1]; const TFieldref& fld2 = (const TFieldref&)_key2_fields[0]; desc = fld1.read(_file->curr()); desc << ' ' << fld2.read(_file->curr()); } } return ok; } TAnal_tree::TAnal_tree(int logicnum, const char* tabname, const TArray& key1, const TArray& key2) : _key1_fields(key1), _key2_fields(key2) { if (tabname && *tabname) _file = new TTable(tabname); else _file = new TLocalisamfile(logicnum); } TAnal_tree::~TAnal_tree() { delete _file; } /////////////////////////////////////////////////////////// // TSimple_anal_msk /////////////////////////////////////////////////////////// const char* TSimple_anal_msk::get_key_fieldname(int k) const { const int logic = get_logicnum(); const RecDes& rd = prefix().get_recdes(logic); CHECKD(k > 0 && k <= rd.NKeys, "Invalid key ", k); const KeyDes& ky = rd.Ky[k-1]; const int idx = (logic == LF_TAB || logic == LF_TABCOM) ? 1 : 0; const int pos = ky.FieldSeq[idx] % MaxFields; return rd.Fd[pos].Name; } void TSimple_anal_msk::append_select_clause(ostream& out, int level) const { const TFieldref& key = fieldref(level-1, 1); TString str; str << " SE STR("; if (level > 1) str << "(NUM(LEN(" << key.name() << "))>" << key.from() << ')'; // SE LEN(CODCONTO)>=4 if (level < fieldrefs()) { if (level > 1) str << "&&"; str << "(NUM(LEN(" << key.name() << "))<=" << key.to() << ')'; // SE LEN(CODCONTO)<=7 } str << ')'; out << str << endl; } void TSimple_anal_msk::create_key_browse(TEdit_field& kfld, int level, TConfig& cfg) { TFilename tmp; tmp.temp(); ofstream out(tmp); const int logic = get_logicnum(); out << "US "; if (logic == LF_TAB || logic == LF_TABCOM) out << get_tabname(); else out << get_logicnum(); out << " KE 1"; append_select_clause(out, level); out << "KE 1" << endl; for (int i = 1; i <= level; i++) { const TString& picture = cfg.get(get_key_var(), NULL, i); const TString& prompt = cfg.get(get_des_var(), NULL, i); const TFieldref& field = fieldref(i-1, 1); const int length = field.to() - field.from(); out << "IN " << field << ' ' << get_field_id(i-1, 1) << endl; out << "DI \"" << prompt << '@' << length << "\" " << field << endl; out << "OU " << get_field_id(i-1, 1) << ' ' << field << endl; if (i == level) out << "FI " << field << endl; } const TFieldref& field = fieldref(0, 2); out << "DI \"Descrizione@50\" " << fieldref(0, 2) << endl; out << "OU " << get_field_id(level-1, 2) << ' ' << field << endl; out << "CH " << (level == 1 ? "RE" : "NO") << endl; out << "EN" << endl; out.close(); TScanner scan(tmp); while (scan.pop() != "EN") kfld.parse_item(scan); xvt_fsys_removefile(tmp); } void TSimple_anal_msk::create_des_browse(TEdit_field& kfld, int level, TConfig& cfg) { TString key2; key2 << fieldref(0, 2); TFilename tmp; tmp.temp(); ofstream out(tmp); const int logic = get_logicnum(); out << "US "; if (logic == LF_TAB || logic == LF_TABCOM) out << get_tabname(); else out << get_logicnum(); out << " KE 2"; append_select_clause(out, level); out << "KE 2" << endl; out << "DI \"Descrizione@50\" " << key2 << endl; out << "IN " << key2 << ' ' << kfld.dlg() << endl; out << "OU " << kfld.dlg() << ' ' << key2 << endl; int from = 1, to = 1; for (int i = 1; i <= level; i++) { const TString& picture = cfg.get(get_key_var(), NULL, i); const TString& prompt = cfg.get(get_des_var(), NULL, i); const TFieldref& field = fieldref(i-1, 1); const int length = field.to() - field.from(); out << "DI \"" << prompt << '@' << length << "\" " << field << endl; out << "OU " << get_field_id(i-1, 1) << ' ' << field << endl; from = to+1; } out << "CH NO" << endl; out << "EN" << endl; out.close(); TScanner scan(tmp); while (scan.pop() != "EN") kfld.parse_item(scan); xvt_fsys_removefile(tmp); } int TSimple_anal_msk::create_key_fields() { TConfig cfg(CONFIG_DITTA, "ca"); const char* keyvar = get_key_var(); const char* desvar = get_des_var(); int maxkeylen = 0, maxdeslen = 0; int level; int from = 1, to = 1; for (level = 1; ; level++) { const TString& prompt = cfg.get(desvar, NULL, level); if (prompt.blank()) break; const TString& picture = cfg.get(keyvar, NULL, level); const int keylen = picture.len(); const int deslen = prompt.len(); if (keylen > maxkeylen) maxkeylen = keylen; if (deslen > maxdeslen) maxdeslen = deslen; to = from+keylen-1; add_fieldref(get_key_fieldname(1), from, to, 1); from = to+1; } add_fieldref(get_key_fieldname(2), 0, 0, 2); maxdeslen++; const int tab0 = compute_offset()+2; const int tab1 = tab0 + maxdeslen + maxkeylen + 4; int i; for (i = 1; i < level; i++) { const short kid = get_field_id(i-1, 1); CHECKD(kid > 100, "Invalid field id:", kid); const TString& picture = cfg.get(keyvar, NULL, i); TString80 prompt = cfg.get(desvar, NULL, i); prompt.left_just(maxdeslen); TEdit_field& kfld = add_string(kid, 0, prompt, tab0, i, picture.len(), "BU"); create_key_browse(kfld, i, cfg); } for (i = 1; i < level; i++) { const short did = get_field_id(i-1, 2); TEdit_field& dfld = add_string(did, 0, "", tab1, i, 50, "B", 72+tab0-tab1); create_des_browse(dfld, i, cfg); } return level; } /////////////////////////////////////////////////////////// // TAnal_app /////////////////////////////////////////////////////////// void TAnal_app::init_key_fields() const { int maxlev = 0; for (maxlev = 0; maxlev < 4; maxlev++) { const short id = _msk->get_field_id(maxlev, 1); if (id <= 0 || _msk->id2pos(id) < 0) break; _msk->disable(id); const short did = _msk->get_field_id(maxlev, 2); _msk->disable(did); } for (int i = maxlev-1; i >= 0; i--) { const short id = _msk->get_field_id(i, 1); TEdit_field& e = _msk->efield(id); const short did = _msk->get_field_id(i, 2); TEdit_field& d = _msk->efield(did); if (e.empty()) { e.hide(); d.hide(); } else { TString key2; key2 << _msk->fieldref(0, 2); e.show(); e.check(STARTING_CHECK); d.show(); d.set_field(key2); d.enable(); d.enable_check(false); break; } } } TRelation* TAnal_app::create_relation() const { return new TRelation(_msk->get_logicnum()); } bool TAnal_app::user_create() { _msk = create_mask(); _rel = create_relation(); return true; } void TAnal_app::init_query_mode(TMask& mask) { TAnal_msk& m = (TAnal_msk&)mask; for (int i = 0; ; i++) { const short id = m.get_field_id(i, 1); if (id <= 0 || m.id2pos(id) < 0) break; TEdit_field& e = m.efield(id); e.show(); e.enable(); const short did = m.get_field_id(i, 2); TEdit_field& d = m.efield(did); d.show(); d.enable(); d.set_field(EMPTY_STRING); d.enable_check(); } } void TAnal_app::init_modify_mode(TMask& m) { init_key_fields(); } void TAnal_app::init_insert_mode(TMask& m) { init_key_fields(); } int TAnal_app::write(const TMask& m) { _msk->update_tree_field(); return TRelation_application::write(m); } int TAnal_app::rewrite(const TMask& m) { _msk->update_tree_field(); return TRelation_application::rewrite(m); } bool TAnal_app::user_destroy() { if (_msk != NULL) delete _msk; if (_rel != NULL) delete _rel; return true; }