campo-sirio/ba/ba2700.cpp
guy 6fb77b6d8b Patch level : 10.0
Files correlati     : ba0.exe ba0200a.msk ba4200b.msk
Ricompilazione Demo : [ ]
Commento            :
Aggiunta possibilita' di kill dei sottoprocessi del menu principale
Riallineati alcuni campi delle maschere ba0200a e ba4200b


git-svn-id: svn://10.65.10.50/trunk@20083 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-02-09 10:08:20 +00:00

897 lines
20 KiB
C++
Executable File

#include <applicat.h>
#include <assoc.h>
#include <automask.h>
#include <config.h>
#include <colors.h>
#include <defmask.h>
#include <diction.h>
#include <progind.h>
#include <scanner.h>
#include <utility.h>
#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)
{
TFilename n(orig); n.lower();
const char* src = n.name();
if (_src.get_pos(src) < 0)
_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 << " <entry>" << endl;
out << " <ita>" << txt2xml(_ita) << "</ita>" << endl;
out << " <eng>" << txt2xml(_eng) << "</eng>" << endl;
if (_max_length > 0)
out << " <max>" << _max_length << "</max>" << endl;
out << " <src>" << txt2xml(_src) << "</src>" << endl;
out << " </entry>" << 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();
void zap_sources(const char * module);
void pack();
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;
for (int c = 0; scan.ok(); c++)
{
TString& line = scan.line();
if (line.empty())
break;
if (c % 100 == 0)
pi.setstatus((long)scan.tellg());
line.trim();
if (line.starts_with("<ita>"))
{
const int eoi = line.find("</ita>");
ita = xml2txt(line.sub(5, eoi));
} else
if (line.starts_with("<eng>") && ita.not_empty())
{
const int eoe = line.find("</eng>");
TString& eng = xml2txt(line.sub(5, eoe));
if (eng.blank())
set_translation(ita, "???");
else
set_translation(ita, eng.trim());
}
if (line.starts_with("<max>") && ita.not_empty())
{
const int eom = line.find("</max>");
const int len = atoi(line.sub(5, eom));
update_max_length(ita, len);
}
if (line.starts_with("<src>") && ita.not_empty())
{
TDictionary_entry& entry = get_entry(ita);
const int eos = line.find("</src>");
entry.set_sources(xml2txt(line.sub(5, eos)));
}
}
_save_needed = false;
}
return ok;
}
void TDictionary::zap_sources(const char * module)
{
TProgind pi(items(), "Azzeramento sorgenti", false, true);
TPointer_array& ref = sorted();
const bool zap = module == NULL || *module == '\0';
for (int i = 0; i < ref.items(); i++)
{
pi.addstatus(1);
TDictionary_entry& e = (TDictionary_entry&)ref[i];
if (zap)
e._src.cut(0);
else
{
TToken_string new_src;
FOR_EACH_TOKEN(e._src, tok)
{
if (strncmp(tok, module, 2) != 0)
new_src.add(tok);
}
e._src = new_src;
}
}
}
void TDictionary::pack()
{
TProgind pi(items(), "Compattamento dizionario", false, true);
FOR_EACH_ASSOC_OBJECT((*this), h, k, o)
{
pi.addstatus(1);
const TDictionary_entry& e = (const TDictionary_entry&)*o;
if (e._src.blank())
{
remove(k);
_save_needed = true;
_sort_needed = true;
}
}
}
bool TDictionary::write()
{
TProgind pi(items(), "Salvataggio dizionario", false, true);
TPointer_array& ref = sorted();
ofstream outf(_filename);
outf << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" << endl;
outf << "<dictionary>" << endl;
for (int i = 0; i < ref.items(); i++)
{
pi.addstatus(1);
const TDictionary_entry& e = (const TDictionary_entry&)ref[i];
outf << e;
}
outf << "</dictionary>" << 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;
bool _filtered;
bool _errors;
bool _new;
TToken_string _modules;
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();
bool check_translation(const TString & ita, const TString & eng, const char tag);
bool good_translation(const TString & ita, const TString & eng, const TString & src, int
maxlen);
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()
{
TMask m("ba2700a");
if (m.run() == K_ENTER)
{
const TString4 module = m.get(F_MODULE);
TString16 mask = module;
const bool delete_obs = m.get_bool(F_DELETE_OBS);
if (delete_obs)
_dictionary.zap_sources(module);
mask << "*.msk";
bool go = read_txt_files(mask);
if (go)
{
mask = module; mask << "*.frm";
go = read_txt_files(mask);
}
if (go)
{
mask = module; mask << "*.men";
go = read_txt_files(mask);
}
if (go) go = read_txt_files("res/resource.ini");
if (go)
{
if (module.full())
mask = module;
else
mask = "??";
mask << "?.exe";
go = read_bin_files(mask);
}
if (delete_obs)
_dictionary.pack();
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");
}
bool TDictionary_mask::check_translation(const TString & ita, const TString & eng, const char tag)
{
bool ok = true;
int p_ita = ita.find(tag);
int p_eng = eng.find(tag);
while (ok && (p_ita >= 0) && (p_eng >= 0))
{
ok = (p_ita >= 0) && (p_eng >= 0) && (ita[p_ita + 1] == eng[p_eng + 1]);
if (ok)
{
p_ita = ita.find(tag, p_ita + 1);
p_eng = eng.find(tag, p_eng + 1);
}
}
ok &= ((p_ita < 0) && (p_eng <0));
#ifdef DBG
if (!ok)
int i = 0;
#endif
return ok;
}
bool TDictionary_mask::good_translation(const TString & ita, const TString & eng, const TString & src, int maxlen)
{
if (ita.find('#') >= 0 || eng.find('#') >= 0)
return false;
if (ita.find('&') >= 0 || eng.find('&') >= 0)
return false;
if (!check_translation(ita, eng, '@'))
return false;
if (src.find(".exe") > 0 && !check_translation(ita, eng, '%'))
return false;
if (maxlen > 0)
if (eng.len() > maxlen)
return false;
return true;
}
void TDictionary_mask::fill_chapter()
{
const char letter = get(F_ALFABETO)[0];
const bool chk_modules = _modules.full();
TString_array modules;
TToken_string str;
FOR_EACH_TOKEN(_modules, m)
{
str = m;
if (str.find('*') < 0)
{
str.insert("*");
str << '*';
}
modules.add(str);
}
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)
{
const bool good = good_translation(e._ita, e._eng, e._src, e._max_length);
const bool translated = e._eng != "???";
const bool not_error = good || !translated;
if (_filtered)
{
bool skip = false;
if (_errors)
skip |= !chk_modules && good && translated;
else
skip |= !good;
if (_new)
{
if (_errors)
skip |= !chk_modules && good && translated;
else
skip |= !chk_modules && translated;
}
else
skip |= !translated;
if (!skip && chk_modules)
{
if (not_error && _errors)
continue;
if (translated && _new)
continue;
FOR_EACH_ARRAY_ROW(modules, i, m)
{
skip = !e._src.match((const char *) *m);
if (!skip)
break;
}
}
if (skip)
continue;
}
TToken_string& row = s.row(-1);
row = e._ita;
row.add(e._eng);
row.add(e._max_length);
row.add(e._src);
if (!good || !translated)
s.set_back_and_fore_color(REQUIRED_BACK_COLOR, COLOR_RED, s.items() - 1);
else
s.set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, s.items() - 1);
}
}
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();
send_key(K_SPACE, F_ALFABETO);
}
break;
case DLG_FILTER:
if (e == fe_button)
{
TMask m("ba2700b");
m.set(F_FILTER, _filtered);
m.set(F_ERRORS_ONLY, _errors);
m.set(F_NEW, _new);
m.set(F_MODULE, _modules);
if (m.run())
{
_filtered = m.get_bool(F_FILTER);
_errors = m.get_bool(F_ERRORS_ONLY);
_new = m.get_bool(F_NEW);
_modules = m.get(F_MODULE);
}
send_key(K_SPACE, F_ALFABETO);
}
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);
const TString src = row.get(3);
_dictionary.set_translation(ita, eng);
if (len > 0 && eng.len() > len)
warning_box("La traduzione e' lunga %d caratteri (max. %d)!", eng.len(), len);
if (!good_translation(ita, eng, src, len) || eng == "???")
s.set_back_and_fore_color(REQUIRED_BACK_COLOR, COLOR_RED, jolly);
else
s.set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, jolly);
s.force_update(jolly);
}
break;
case DLG_USER:
if (e == fe_button)
{
TMask & sms = o.mask();
if (sms.is_running())
sms.set(F_ENG, sms.get(F_ITA));
else
{
TSheet_field* s = (TSheet_field*)sms.get_sheet();
const int nrow = s->selected();
TToken_string& row = s->row(nrow);
const TString ita = row.get(0);
row.add(ita, 1);
s->force_update(nrow);
}
}
break;
default:
break;
}
return true;
}
TDictionary_mask::TDictionary_mask()
: _filtered(false), _errors(false), _new(false), _modules("", ',')
{
// 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;
}