#include #include #include #include #include #include #include #include #include #include "ba2.h" #include "ba2700.h" /////////////////////////////////////////////////////////// // TDictionary_entry /////////////////////////////////////////////////////////// class TDictionary_entry : public TSortable { public: TString _ita, _eng; TToken_string _src; int _max_length; virtual int compare(const TSortable& obj) const; virtual void print_on(ostream& out) const; void set_translation(const char* eng) { _eng = eng; } void add_source(const char* orig); void set_sources(const char* orig); void update_max_length(int len); TDictionary_entry(const char* ita) : _ita(ita), _eng("???"), _src(12, ','), _max_length(0) { } }; void TDictionary_entry::add_source(const char* orig) { if (_src.items() < 8) { TFilename n(orig); n.lower(); const char* src = n.name(); if (_src.get_pos(src)) _src.add(src); } } void TDictionary_entry::set_sources(const char* orig) { _src = orig; } void TDictionary_entry::update_max_length(int len) { if (len > 0 && (_max_length <= 0 || len < _max_length)) _max_length = len; } int TDictionary_entry::compare(const TSortable& obj) const { const TDictionary_entry& e = (const TDictionary_entry&)obj; return _ita.compare(e._ita, -1, true); } void TDictionary_entry::print_on(ostream& out) const { out << " " << endl; out << " " << txt2xml(_ita) << "" << endl; out << " " << txt2xml(_eng) << "" << endl; if (_max_length > 0) out << " " << _max_length << "" << endl; out << " " << txt2xml(_src) << "" << endl; out << " " << endl; } /////////////////////////////////////////////////////////// // TDictionary /////////////////////////////////////////////////////////// class TDictionary : public TAssoc_array { TFilename _filename; TPointer_array _sort; bool _sort_needed, _save_needed; public: TDictionary_entry& get_entry(const char* ita); TPointer_array& sorted(); void set_translation(const char* ita, const char* eng); void update_max_length(const char* ita, int len); bool read(const char* fname); bool write(); bool write_if_needed(); TDictionary() : _sort_needed(false), _save_needed(false) { } }; TDictionary_entry& TDictionary::get_entry(const char* ita) { TDictionary_entry* entry = (TDictionary_entry*)objptr(ita); if (entry == NULL) { entry = new TDictionary_entry(ita); add(ita, entry); _sort_needed = _save_needed = true; } return *entry; } void TDictionary::set_translation(const char* ita, const char* eng) { TDictionary_entry& entry = get_entry(ita); entry.set_translation(eng); _save_needed = true; } void TDictionary::update_max_length(const char* ita, int len) { TDictionary_entry& entry = get_entry(ita); entry.update_max_length(len); _save_needed = true; } bool TDictionary::read(const char* fname) { _filename = fname; bool ok = _filename.exist(); if (ok) { TProgind pi(fsize(_filename), "Lettura dizionario", false, true); destroy(); TScanner scan(_filename); TString ita; while (scan.ok()) { TString& line = scan.line(); if (line.empty()) break; pi.setstatus(scan.tellg()); line.trim(); if (line.starts_with("")) { const int eoi = line.find(""); ita = xml2txt(line.sub(5, eoi)); } else if (line.starts_with("") && ita.not_empty()) { const int eoe = line.find(""); const TString& eng = xml2txt(line.sub(5, eoe)); set_translation(ita, eng); } if (line.starts_with("") && ita.not_empty()) { const int eom = line.find(""); const int len = atoi(line.sub(5, eom)); update_max_length(ita, len); } if (line.starts_with("") && ita.not_empty()) { TDictionary_entry& entry = get_entry(ita); const int eos = line.find(""); entry.set_sources(xml2txt(line.sub(5, eos))); } } _save_needed = false; } return ok; } bool TDictionary::write() { TProgind pi(items(), "Salvataggio dizionario", false, true); TPointer_array& ref = sorted(); ofstream outf(_filename); outf << "" << endl; outf << "" << endl; for (int i = 0; i < ref.items(); i++) { pi.addstatus(1); const TDictionary_entry& e = (const TDictionary_entry&)ref[i]; outf << e; } outf << "" << endl; _save_needed = false; return true; } bool TDictionary::write_if_needed() { bool ok = _save_needed; if (ok) { ok = yesno_box("Si desidera registrare le modifiche al dizionario %s?", (const char*)_filename); if (ok) ok = write(); } return ok; } static int sort_entries(const TObject** o1, const TObject** o2) { const TDictionary_entry* e1 = (const TDictionary_entry*)*o1; const TDictionary_entry* e2 = (const TDictionary_entry*)*o2; return e1->compare(*e2); } TPointer_array& TDictionary::sorted() { if (_sort_needed) { _sort.destroy(); FOR_EACH_ASSOC_OBJECT((*this), h, k, o) _sort.add(o); _sort.sort(sort_entries); _sort_needed = false; } return _sort; } /////////////////////////////////////////////////////////// // TDictionary_mask /////////////////////////////////////////////////////////// class TDictionary_mask : public TAutomask { TDictionary _dictionary; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); const TString& get_dictionary_name() const; void set_dictionary_name(const char* name); bool is_a_word(const TString& ita) const; void add_line(const TString& ita, const char* origin); void read_txt_file(const char* fname, int filetype); bool read_txt_files(const char* msk); bool read_bin_file(const char* fname); bool read_bin_files(const char* msk); void build_dictionary(); bool read_dictionary(); void fill_index(); void fill_chapter(); public: TDictionary_mask(); ~TDictionary_mask(); }; const TString& TDictionary_mask::get_dictionary_name() const { TConfig ini("servers/servers.ini", "Dictionary"); TFilename n = ini.get("Dictionary"); if (n.is_relative_path()) n.insert("servers/"); TString& tmp = get_tmp_string(); tmp = n; return tmp; } void TDictionary_mask::set_dictionary_name(const char* name) { TFilename n(name); if (n.starts_with("servers")) n.ltrim(); TConfig ini("servers/servers.ini", "Dictionary"); ini.set("Dictionary", n); } bool TDictionary_mask::read_dictionary() { _dictionary.write_if_needed(); const TFilename fname = get_dictionary_name(); const bool ok = _dictionary.read(fname); fill_index(); fill_chapter(); return ok; } bool TDictionary_mask::is_a_word(const TString& ita) const { for (int i = 0; ita[i]; i++) { if (isalpha(ita[i])) { if (i == 0 || ita[i-1] != '@') return true; } } return false; } inline bool valid_char(char c) { return isalnum(c) || strchr("@%'", c); } void TDictionary_mask::add_line(const TString& ita, const char* origin) { int prefix = 0, suffix = 0; for (prefix = 0; ita[prefix] != '\0' && !valid_char(ita[prefix]); prefix++); for (suffix = ita.len()-1; suffix > prefix && !valid_char(ita[suffix]); suffix--); const TString& text = ita.sub(prefix, suffix+1); if (is_a_word(text)) { TDictionary_entry& entry = _dictionary.get_entry(text); entry.add_source(origin); int spaces = 0; for (int i = ita.len()-1; i > 0 && ita[i] == ' '; i--, spaces++); if (spaces > 0) entry.update_max_length(text.len() + spaces); } } void TDictionary_mask::read_txt_file(const char* fname, int filetype) { TScanner scan(fname); TString ita; while (scan.ok()) { TString& line = scan.line(); if (line.empty()) break; line.trim(); bool good = false; switch (filetype) { case 1: good = line.starts_with("IT") || line.starts_with("PA") || line.starts_with("PR") || line.starts_with("WA") || line.starts_with("DI"); break; case 2: good = line.starts_with("IT") || line.starts_with("PR"); break; case 3: good = line.starts_with("Caption ") || line.starts_with("Item_"); break; case 4: good = line.starts_with("Item_"); if (good) { TToken_string str(line); line.cut(0); line << "PR \"" << str.get(1) << '"'; } break; default: break; } if (good) { int apicia = 0, apicic = 0; if (filetype == 1 && line.starts_with("DI")) { const int at = line.find('@'); if (at > 0) line[at] = '"'; } if (filetype <= 2 && line.starts_with("IT")) { apicia = line.find('|'); if (apicia < 0) apicia = line.find('"'); const int at = line.find('@', apicia+1); const int ap = line.find('"', apicia+1); apicic = (at > 0 && at < ap) ? at : ap; } else { apicia = line.find('"'); apicic = line.find('"', apicia+1); } if (apicic > apicia) { ita = line.sub(apicia+1, apicic); if (filetype <= 2 && line.starts_with("PR")) { if (ita[0] == '@') ita.ltrim(2); if (ita[0] == '$') { const int closed = ita.find(']'); ita.ltrim(closed+1); } if (filetype == 1 || filetype == 4) ita.strip("~&"); } add_line(ita, fname); } } } } bool TDictionary_mask::read_txt_files(const char* msk) { TString_array arr; list_files(msk, arr); TString msg; msg << "Scansione files " << msk; TProgind pi(arr.items(), msg, true, true); TString strmsk(msk); strmsk.upper(); int filetype = 0; if (strmsk.find(".MSK") > 0) filetype = 1; else if (strmsk.find(".FRM") > 0) filetype = 2; else if (strmsk.find(".MEN") > 0) filetype = 3; if (strmsk.find(".INI") > 0) filetype = 4; bool finished = true; FOR_EACH_ARRAY_ROW(arr, i, row) { pi.addstatus(1); if (pi.iscancelled()) { finished = false; break; } TFilename n = *row; read_txt_file(n, filetype); n.custom_path(); if (n != *row) read_txt_file(n, filetype); } return finished; } bool TDictionary_mask::read_bin_file(const char* fname) { TProgind bi(fsize(fname), fname, true, true); const int match[4] = { 3, 2, 1, 0 }; int counter = 0; bool finished = true; TString ita(1024); ifstream scan(fname, ios::binary); while (!scan.eof()) { bi.addstatus(1); const int ch = scan.get(); if (ch == EOF) break; if (counter < 4) { if (ch == match[counter]) counter++; else counter = 0; } else { const int index = counter-4; if (index == 0) { ita.cut(0); if (bi.iscancelled()) { finished = false; break; } } ita << char(ch); if (ch == 0) { if (index > 0) add_line(ita, fname); counter = 0; } else counter++; } } return finished; } bool TDictionary_mask::read_bin_files(const char* msk) { TString_array arr; list_files(msk, arr); TString msg; msg << "Scansione programmi " << msk; TProgind pi(arr.items(), msg, false, true); FOR_EACH_ARRAY_ROW(arr, i, row) { pi.addstatus(1); if (!read_bin_file(*row)) break; } return true; } void TDictionary_mask::build_dictionary() { bool go = read_txt_files("*.msk"); if (go) go = read_txt_files("*.frm"); if (go) go = read_txt_files("*.men"); if (go) go = read_txt_files("res/resource.ini"); if (go) go = read_bin_files("???.exe"); fill_index(); fill_chapter(); } void TDictionary_mask::fill_index() { TToken_string letters = " "; char last_letter = ' '; TPointer_array& ref = _dictionary.sorted(); for (int i = 0; i < ref.items(); i++) { const TDictionary_entry& entry = (const TDictionary_entry&)ref[i]; const char letter = toupper(entry._ita[0]); if (letter != last_letter) { last_letter = letter; letters.add(letter); } } set(F_TOTAL, ref.items()); TList_field& alfabeto = (TList_field&)field(F_ALFABETO); alfabeto.replace_items(letters, letters); alfabeto.set("A"); } void TDictionary_mask::fill_chapter() { const char letter = get(F_ALFABETO)[0]; TSheet_field& s = sfield(F_CAPITOLO); s.destroy(); TPointer_array& ref = _dictionary.sorted(); for (int i = 0; i < ref.items(); i++) { const TDictionary_entry& e = (const TDictionary_entry&)ref[i]; if (toupper(e._ita[0]) == letter) { TToken_string& row = s.row(-1); row = e._ita; row.add(e._eng); row.add(e._max_length); row.add(e._src); } } s.force_update(); set(F_ENTRIES, s.items()); enable(DLG_SAVEREC, ref.items() > 0); } bool TDictionary_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_FILENAME: if (e == fe_init) { o.set(get_dictionary_name()); read_dictionary(); } if (e == fe_modify) { const TFilename n = o.get(); if (n.exist()) { set_dictionary_name(n); o.set(get_dictionary_name()); read_dictionary(); } else return error_box("File assente"); } break; case F_ALFABETO: if (e == fe_modify) fill_chapter(); break; case DLG_SAVEREC: if (e == fe_button) _dictionary.write(); break; case DLG_ELABORA: if (e == fe_button) build_dictionary(); break; case F_CAPITOLO: if (e == se_query_add) return false; if (e == se_notify_modify) { TSheet_field& s = (TSheet_field&)o; TToken_string& row = s.row(jolly); const TString& ita = row.get(0); const TString& eng = row.get(1); const int len = row.get_int(2); _dictionary.set_translation(ita, eng); if (len > 0 && eng.len() > len) warning_box("La traduzione e' lunga %d caratteri (max. %d)!", eng.len(), len); } break; default: break; } return true; } TDictionary_mask::TDictionary_mask() { // Allarga numero di riga degli spreadsheet TSheet_field::set_line_number_width(4); // Simula lettura ed inizilizzazione della Automak read_mask("ba2700", 0, MAX_PAGES); set_handlers(); } TDictionary_mask::~TDictionary_mask() { _dictionary.write_if_needed(); } class TDictionary_manager : public TSkeleton_application { public: virtual void main_loop(); }; void TDictionary_manager::main_loop() { TDictionary_mask dm; dm.run(); } int ba2700(int argc, char* argv[]) { TDictionary_manager a; a.run(argc, argv, TR("Creazione dizionario")); return 0; }