diff --git a/ba/ba1101.cpp b/ba/ba1101.cpp index c417add3e..5614d3d97 100755 --- a/ba/ba1101.cpp +++ b/ba/ba1101.cpp @@ -192,7 +192,7 @@ bool TRec_sheet::key_notify(TSheet_field& f, int r, KEY k) if (k == K_INS) { const int items = f.items(); - if (f.items() >= 8) return FALSE; + if (items >= 8) return FALSE; } else if (k == K_CTRL + K_INS) diff --git a/ba/ba2.cpp b/ba/ba2.cpp index 1088d4726..cda8eaafe 100755 --- a/ba/ba2.cpp +++ b/ba/ba2.cpp @@ -13,6 +13,7 @@ int main(int argc, char** argv) case 3: ba2400(argc, argv); break; case 4: ba2500(argc, argv); break; case 5: ba2600(argc, argv); break; + case 6: ba2700(argc, argv); break; default: ba2100(argc, argv); break; } exit(0); diff --git a/ba/ba2.h b/ba/ba2.h index d4f6cb442..6228c1349 100755 --- a/ba/ba2.h +++ b/ba/ba2.h @@ -7,6 +7,7 @@ int ba2300(int argc, char* argv[]); int ba2400(int argc, char* argv[]); int ba2500(int argc, char* argv[]); int ba2600(int argc, char* argv[]); +int ba2700(int argc, char* argv[]); #endif // __BA2_H diff --git a/ba/ba2700.cpp b/ba/ba2700.cpp new file mode 100755 index 000000000..2414c6ef6 --- /dev/null +++ b/ba/ba2700.cpp @@ -0,0 +1,659 @@ +#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 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; +} diff --git a/ba/ba2700.h b/ba/ba2700.h new file mode 100755 index 000000000..81932b4e9 --- /dev/null +++ b/ba/ba2700.h @@ -0,0 +1,10 @@ +#define F_FILENAME 201 +#define F_ALFABETO 202 +#define F_ENTRIES 203 +#define F_TOTAL 204 +#define F_CAPITOLO 210 + +#define F_ITA 101 +#define F_ENG 102 +#define F_MAX 103 +#define F_SRC 104 diff --git a/ba/ba2700.uml b/ba/ba2700.uml new file mode 100755 index 000000000..9cb4f50bb --- /dev/null +++ b/ba/ba2700.uml @@ -0,0 +1,109 @@ +#include "ba2700.h" + +TOOLBAR "" 0 -2 0 2 + +BUTTON DLG_SAVEREC 10 2 +BEGIN + PROMPT -13 -11 "" + PICTURE BMP_SAVEREC + PICTURE BMP_SAVERECDN +END + +BUTTON DLG_ELABORA 10 2 +BEGIN + PROMPT -23 -11 "&Elabora" + PICTURE BMP_ELABORA +END + +BUTTON DLG_QUIT 10 2 +BEGIN + PROMPT -33 -11 "" +END + +ENDPAGE + +PAGE "Gestione Dizionario" -1 -1 78 20 + +GROUPBOX DLG_NULL 78 4 +BEGIN + PROMPT 1 0 "" +END + +STRING F_FILENAME 60 +BEGIN + PROMPT 2 1 "Dizionario " +END + +LIST F_ALFABETO 1 +BEGIN + PROMPT 2 2 "Iniziale " +END + +NUMBER F_ENTRIES 6 +BEGIN + PROMPT 32 2 "Elementi " + FLAGS "D" +END + +NUMBER F_TOTAL 6 +BEGIN + PROMPT 60 2 "Totale " + FLAGS "D" +END + +SPREADSHEET F_CAPITOLO +BEGIN + PROMPT 0 4 "" + ITEM "Italiano@50" + ITEM "Traduzione@50" + ITEM "Max." + ITEM "Sorgente@50" +END + +ENDPAGE + +ENDMASK + +PAGE "Riga 1" -1 -1 80 14 + +MEMO F_ITA 78 5 +BEGIN + PROMPT 1 0 "@bItaliano" + FLAGS "D" +END + +MEMO F_ENG 78 5 +BEGIN + PROMPT 1 5 "@bTraduzione" +END + +NUMBER F_MAX 3 +BEGIN + PROMPT 57 5 "Lunghezza massima " + FLAGS "DU" +END + +MEMO F_SRC 78 3 +BEGIN + PROMPT 1 10 "@bSorgenti" + FLAGS "D" +END + +BUTTON DLG_OK 10 2 +BEGIN + PROMPT -13 -1 "" +END + +BUTTON DLG_DELREC 10 2 +BEGIN + PROMPT -23 -1 "" +END + +BUTTON DLG_CANCEL 10 2 +BEGIN + PROMPT -33 -1 "" +END + +ENDPAGE + +ENDMASK