#include "calib01.h" #include "calibmsk.h" #include #include /////////////////////////////////////////////////////////// // TMultilevel_code_info /////////////////////////////////////////////////////////// int TMultilevel_code_info::levels() const { return _picture.items(); } const TString& TMultilevel_code_info::picture(int level) const { return _picture.row(level); } bool TMultilevel_code_info::is_numeric_picture(int level) const { const TString& pic = picture(level); if (pic.blank()) return false; for (int i = 0; pic[i]; i++) if (pic[i] != '0' && pic[i] != '9') return false; return true; } int TMultilevel_code_info::len(int level) const { return picture(level).len(); } const TString& TMultilevel_code_info::prompt(int level) const { return _prompt.row(level); } const TFieldref& TMultilevel_code_info::fieldref(int level, int key) const { const TArray& a = key == 1 ? _key1_fields : _key2_fields; const TFieldref& fr = (const TFieldref&)a[level]; return fr; } const char* TMultilevel_code_info::get_key_fieldname(int k) const { const RecDes& rd = prefix().get_recdes(_logicnum); CHECKD(k > 0 && k <= rd.NKeys, "Invalid key ", k); const KeyDes& ky = rd.Ky[k-1]; const int idx = (_logicnum == LF_TAB || _logicnum == LF_TABCOM) ? 1 : 0; const int pos = ky.FieldSeq[idx] % MaxFields; return rd.Fd[pos].Name; } bool TMultilevel_code_info::get_cfg_vars(TString& key, TString& des) const { switch (_logicnum) { case LF_PCONANA: key = "Pdci"; des = "PdciDes"; break; case LF_CDC : key = "CdC"; des = "CdCDes"; break; case LF_COMMESSE:key = "Cms"; des = "CmsDes"; break; case LF_FASI : key = "Fsc"; des = "FscDes"; break; default: break; } return key.not_empty(); } void TMultilevel_code_info::add_fieldref(int k, int from, int to) { TArray& a = k == 1 ? _key1_fields : _key2_fields; TString80 str = get_key_fieldname(k); if (from > 0) str << '[' << from << ',' << to << ']'; TFieldref* fr = new TFieldref(str, _logicnum); a.add(fr); } TMultilevel_code_info::TMultilevel_code_info(int logicnum) : _logicnum(logicnum) { if (logicnum == LF_PCON) { _key1_fields.add(new TFieldref(PCN_GRUPPO, LF_PCON)); _picture.add("999"); _prompt.add("Gruppo"); _key1_fields.add(new TFieldref(PCN_CONTO, LF_PCON)); _picture.add("999"); _prompt.add("Conto"); _key1_fields.add(new TFieldref(PCN_SOTTOCONTO, LF_PCON)); _picture.add("999999"); _prompt.add("Sottoconto"); _key2_fields.add(new TFieldref(PCN_DESCR, LF_PCON)); } else { TConfig cfg(CONFIG_DITTA); TString16 keyvar, desvar; get_cfg_vars(keyvar, desvar); int from = 1, to = 1; for (int level = 1; ; level++) { const TString& prompt = cfg.get(desvar, NULL, level); if (prompt.blank()) break; _prompt.add(prompt); const TString& picture = cfg.get(keyvar, NULL, level); _picture.add(picture); const int keylen = picture.len(); to = from+keylen-1; add_fieldref(1, from, to); from = to+1; } add_fieldref(2, 0, 0); } } const TMultilevel_code_info& multilevel_code_info(int logicnum) { static TArray* cache = NULL; if (cache == NULL) cache = new TArray; TMultilevel_code_info* info = (TMultilevel_code_info*)cache->objptr(logicnum); if (info == NULL) { info = new TMultilevel_code_info(logicnum); cache->add(info, logicnum); } return *info; } bool ca_test_multilevel_field(TEdit_field& fld, int level) { const int logic = fld.browse()->cursor()->curr().num(); const TMultilevel_code_info& info = multilevel_code_info(logic); const TString& pic = info.picture(level); const TString& val = fld.get(); bool ok = val.len() <= pic.len(); for (int i = 0; val[i] && ok; i++) { const char v = val[i]; const char p = pic[i]; switch (p) { case 'A': ok = (v >= '0' && v <= '9') || (v >= 'A' && v <= 'Z'); break; case '0': case '9': ok = v >= '0' && v <= '9'; break; default : break; } } if (!ok) { TString msg; msg << TR("Il codice non rispetta il formato impostato nella configurazione") << '\n' << val << " <> " << pic; return fld.error_box(msg); } return ok; } /////////////////////////////////////////////////////////// // 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; 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(); 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); virtual ~TAnal_tree(); }; /////////////////////////////////////////////////////////// // TAnal_msk /////////////////////////////////////////////////////////// #define F_TREE 99 short TSimple_anal_msk::get_field_id(int n, int k) const { short id = 0; if (n >= 0 && n < fieldrefs(1)) { if (k == 1) id = F_KEY1+n; else id = F_DES1+n; } return id; } bool TSimple_anal_msk::test_key_field(short id) { TEdit_field& fld = efield(id); const int level = id - F_KEY1; return ca_test_multilevel_field(fld, level); } bool TSimple_anal_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; case F_KEY1: case F_KEY2: case F_KEY3: case F_KEY4: if (e == fe_modify || e == fe_close) return test_key_field(o.dlg()); break; default: break; } return true; } int TSimple_anal_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 TSimple_anal_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); set_source_file(name); } else read_mask(name, 0, 0); create_key_fields(); create_tree_field(); } short TSimple_anal_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()); tfield(id).set_tree(t); t->goto_root(); t->expand(); } set_handlers(); return id; } void TSimple_anal_msk::update_tree_field() { const int pos = id2pos(F_TREE); if (pos >= 0) { TTree_field& t = tfield(F_TREE); t.win().force_update(); } } int TSimple_anal_msk::fieldrefs(int k) const { int n = 1; if (k == 1) { const TMultilevel_code_info& mci = multilevel_code_info(get_logicnum()); n = mci.levels(); } return n; } const TFieldref& TSimple_anal_msk::fieldref(int n, int k) const { const TMultilevel_code_info& mci = multilevel_code_info(get_logicnum()); return mci.fieldref(n, k); } const TToken_string& TSimple_anal_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& TSimple_anal_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; } 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); 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) { TFilename tmp; tmp.temp(); ofstream out(tmp); const int logic = get_logicnum(); out << "US " << get_logicnum() << " KE 1"; append_select_clause(out, level); out << "KE 1" << endl; const TMultilevel_code_info& mci = multilevel_code_info(logic); for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i, 1); const int length = field.to() - field.from(); out << "IN " << field << ' ' << get_field_id(i, 1) << endl; out << "DI \"" << prompt << '@' << length << "\" " << field << endl; out << "OU " << get_field_id(i, 1) << ' ' << field << endl; if (i == level) out << "FI " << field << endl; } const TFieldref& field = mci.fieldref(0, 2); out << "DI \"" << TR("Descrizione") << "@50\" " << field << endl; out << "OU " << get_field_id(level, 2) << ' ' << field << endl; out << "CH " << (level == 0 ? "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) { TString key2; key2 << fieldref(0, 2); TFilename tmp; tmp.temp(); ofstream out(tmp); const int logic = get_logicnum(); out << "US " << get_logicnum() << " KE 2"; append_select_clause(out, level); out << "KE 2" << endl; out << "IN " << key2 << ' ' << kfld.dlg() << endl; out << "DI \"" << TR("Descrizione") << "@50\" " << key2 << endl; out << "OU " << kfld.dlg() << ' ' << key2 << endl; const TMultilevel_code_info& mci = multilevel_code_info(logic); for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i, 1); const int length = field.to() - field.from(); out << "DI \"" << prompt << '@' << length << "\" " << field << endl; out << "OU " << get_field_id(i, 1) << ' ' << field << endl; } 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() { const TMultilevel_code_info& mci = multilevel_code_info(get_logicnum()); int maxkeylen = 0, maxdeslen = 0; for (int level = 0; level < mci.levels(); level++) { const TString& prompt = mci.prompt(level); const int deslen = prompt.len(); const int keylen = mci.len(level); if (deslen > maxdeslen) maxdeslen = deslen; if (keylen > maxkeylen) maxkeylen = keylen; } maxdeslen++; const int tab0 = compute_offset()+2; const int tab1 = tab0 + maxdeslen + maxkeylen + 4; int i; for (i = 0; i < level; i++) { const short kid = get_field_id(i, 1); CHECKD(kid > 100, "Invalid field id:", kid); const TString& picture = mci.picture(i); TString80 prompt = mci.prompt(i); prompt.left_just(maxdeslen); TEdit_field* kfld = NULL; const char* flags = picture[0] == '0' ? "BUZ" : "BU"; if (mci.is_numeric_picture(i)) // Numeric kfld = &add_number(kid, 0, prompt, tab0, i+1, picture.len(), flags); else kfld = &add_string(kid, 0, prompt, tab0, i+1, picture.len(), flags); create_key_browse(*kfld, i); } for (i = 0; i < level; i++) { const short did = get_field_id(i, 2); TEdit_field& dfld = add_string(did, 0, "", tab1, i+1, 50, "B", 72+tab0-tab1); create_des_browse(dfld, i); } return level; } /////////////////////////////////////////////////////////// // TAnal_tree /////////////////////////////////////////////////////////// const TToken_string& TAnal_tree::curr_of_file() const { const TMultilevel_code_info& mci = multilevel_code_info(_file->num()); const TRectype& rec = _file->curr(); TToken_string& k = get_tmp_string(); for (int i = 0; i < mci.levels(); i++) { const TFieldref& fld = mci.fieldref(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 { const TMultilevel_code_info& mci = multilevel_code_info(_file->num()); return mci.levels(); } 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(); const TMultilevel_code_info& mci = multilevel_code_info(_file->num()); for (int i = 0; i < lev-1; i++) { const char* val = _curr._key.get(i); const TFieldref& fld = mci.fieldref(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 TMultilevel_code_info& mci = multilevel_code_info(_file->num()); const TFieldref& fld1 = mci.fieldref(lev-1, 1); const TFieldref& fld2 = mci.fieldref(0, 2); const TRectype& rec = _file->curr(); desc = fld1.read(rec); desc << ' ' << fld2.read(rec); } } return ok; } TAnal_tree::TAnal_tree(int logicnum) { _file = new TLocalisamfile(logicnum); } TAnal_tree::~TAnal_tree() { delete _file; } /////////////////////////////////////////////////////////// // 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) { TSimple_anal_msk& m = (TSimple_anal_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; } /////////////////////////////////////////////////////////// // TAnal_mov /////////////////////////////////////////////////////////// int TAnal_mov::read(long numreg, word lock) { put("NUMREG", numreg); return TMultiple_rectype::read(_isequal, lock); } TAnal_mov::TAnal_mov(long numreg) : TMultiple_rectype(LF_MOVANA) { add_file(LF_RMOVANA, "NUMRIG"); if (numreg > 0) read (numreg); } /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// void ca_append_select_clause(ostream& out, int level, int logic) { TString str; if (logic == LF_PCON) { switch (level) { case 0: str = "CONTO==\"\""; break; case 1: str = "SOTTOCONTO==\"\""; break; default: break; } } else { const TMultilevel_code_info& mci = multilevel_code_info(logic); const TFieldref& key = mci.fieldref(level); str << "STR("; if (level > 1) str << "(NUM(LEN(" << key.name() << "))>" << key.from() << ')'; // SE LEN(CODCONTO)>=4 if (level < mci.levels()) { if (level > 1) str << "&&"; str << "(NUM(LEN(" << key.name() << "))<=" << key.to() << ')'; // SE LEN(CODCONTO)<=7 } str << ')'; } if (str.not_empty()) out << " SE " << str << endl; } void ca_append_run_clause(ostream& out, int logicnum) { const TRectype r(logicnum); TString app; r.get_relapp(app); if (app.not_empty()) out << "AD RU " << app << endl; } void ca_create_browse1(TEdit_field& kfld, int level, int logic, short key_id, short des_id) { const TMultilevel_code_info& mci = multilevel_code_info(logic); TFilename tmp; tmp.temp(); ofstream out(tmp); out << "US " << logic << endl; ca_append_select_clause(out, level, logic); ca_append_run_clause(out, logic); for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i); const int length = field.to() - field.from(); out << "IN " << field << ' ' << (key_id+i) << endl; out << "DI \"" << prompt; if (length > prompt.len()) out << '@' << length; out << "\" " << field << endl; out << "OU " << (key_id+i) << ' ' << field << endl; } const TFieldref& field = mci.fieldref(0, 2); out << "DI \"" << TR("Descrizione") << "@50\" " << field << endl; out << "OU " << (des_id+level) << ' ' << field << endl; out << "CH RE" << endl; //out << "FI " << mci.fieldref(level) << endl; out << "EN" << endl; out.close(); TScanner scan(tmp); while (scan.pop() != "EN") kfld.parse_item(scan); xvt_fsys_removefile(tmp); } void ca_create_browse2(TEdit_field& kfld, int level, int logic, short key_id, short des_id) { const TMultilevel_code_info& mci = multilevel_code_info(logic); const TFieldref& field = mci.fieldref(0, 2); TString str2; str2 << field; TFilename tmp; tmp.temp(); ofstream out(tmp); out << "US " << logic << " KE 2" << endl; ca_append_select_clause(out, level, logic); ca_append_run_clause(out, logic); out << "IN " << str2 << ' ' << kfld.dlg() << endl; out << "DI \"" << TR("Descrizione") << "@50\" " << str2 << endl; out << "OU " << kfld.dlg() << ' ' << str2 << endl; for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i); const int length = field.to() - field.from(); out << "DI \"" << prompt; if (length > prompt.len()) { out << '@' << length; if (mci.is_numeric_picture(i)) out << 'R'; } out << "\" " << field << endl; out << "OU " << (key_id+i) << ' ' << field << endl; } 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 ca_create_fields(TMask& msk, int logicnum, int x, int y, short key_id, short des_id) { const TMultilevel_code_info& mci = multilevel_code_info(logicnum); int maxkeylen = 0, maxdeslen = 0; for (int level = 0; level < mci.levels(); level++) { const TString& prompt = mci.prompt(level); const TString& picture = mci.picture(level); const int keylen = picture.len(); const int deslen = prompt.len(); if (keylen > maxkeylen) maxkeylen = keylen; if (deslen > maxdeslen) maxdeslen = deslen; } maxdeslen++; const int tab0 = x; const int tab1 = tab0 + maxdeslen + maxkeylen + 4; for (int i = 0; i < mci.levels(); i++) { const short kid = key_id+i; const TString& picture = mci.picture(i); TString80 prompt = mci.prompt(i); prompt.left_just(maxdeslen); const char* flags = picture[0] == '0' ? "BUZ" : "BU"; TEdit_field* kfld = NULL; if (mci.is_numeric_picture(i)) // Numeric kfld = &msk.add_number(kid, 0, prompt, tab0, y+i, picture.len(), flags); else kfld = &msk.add_string(kid, 0, prompt, tab0, y+i, picture.len(), flags); ca_create_browse1(*kfld, i, logicnum, key_id, des_id); kfld->set_group(2); const short did = des_id+i; TEdit_field& dfld = msk.add_string(did, 0, "", tab1, y+i, 50, "B", 72+tab0-tab1); ca_create_browse2(dfld, i, logicnum, key_id, des_id); dfld.set_group(2); } return mci.levels(); }