#include #include #include #include #include #include #include #include "ba1.h" #include "ba1600.h" #include "ba1700a.h" HIDDEN int compare_version(const TString& v1, const TString& v2) { TString16 ver1(v1), ver2(v2); ver1.trim(); if (ver1.len() == 4) ver1.insert((v1[0] == '9') ? "19" : "20", 0); ver2.trim(); if (ver2.len() == 4) ver2.insert((v2[0] == '9') ? "19" : "20", 0); return ver1.compare(ver2, -1, TRUE); } /////////////////////////////////////////////////////////// // Maschera principale /////////////////////////////////////////////////////////// class TInstaller_mask : public TMask { protected: static bool update_handler(TMask_field& fld, KEY key); static bool path_handler(TMask_field& fld, KEY key); static bool sheet_notify(TSheet_field& s, int r, KEY k); static bool install_handler(TMask_field& fld, KEY key); bool add_module(TConfig& ini, const TString& module) const; void update_version(); bool do_process(TAuto_token_string& commands) const; bool pre_process(TInstall_ini& ini, const char* module) const; bool post_process(TInstall_ini& ini, const char* module) const; public: bool autoload(); bool install(const TString& module); TInstaller_mask(); virtual ~TInstaller_mask() { } }; // Copia nello sheet i dati di un modulo prendendoli da un .ini bool TInstaller_mask::add_module(TConfig& ini, const TString& module) const { bool ok = ini.set_paragraph(module); if (ok) { TSheet_field& sheet = sfield(F_SHEET); TToken_string& row = sheet.row(-1); row = ini.get("Descrizione"); row.add(module); row.add(ini.get("Versione")); row.add(ini.get("Data")); } return ok; } void TInstaller_mask::update_version() { TInstall_ini ini; TSheet_field& sheet = sfield(F_SHEET); FOR_EACH_SHEET_ROW_BACK(sheet, m, row) { const TString16 module = row->get(1); ini.set_paragraph(module); const TString16 newver = row->get(2); const TString16 oldver = ini.get("Versione"); row->add(oldver, 4); row->add(ini.get("Data"), 5); const int cmp = compare_version(newver, oldver); if (cmp > 0) sheet.set_back_and_fore_color(FOCUS_BACK_COLOR, NORMAL_COLOR, m); if (cmp == 0) sheet.set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, m); if (cmp < 0) sheet.set_back_and_fore_color(DISABLED_BACK_COLOR, NORMAL_COLOR, m); } sheet.force_update(); } // Cerca nel percorso specificato sulla maschera tutti i possibili files .ini // utilizzabili per un'installazione e li inserisce nello spreadsheet bool TInstaller_mask::autoload() { const TString& path = get(F_PATH); if (!fexist(path)) return error_box("Specificare un percorso valido"); TWait_cursor hourglass; TSheet_field& sheet = sfield(F_SHEET); sheet.destroy(); TFilename ininame; ininame = path; ininame.add(TInstall_ini::default_name()); TString_array modules; if (fexist(ininame)) { TInstall_ini ini(ininame); ini.list_paragraphs(modules); FOR_EACH_ARRAY_ROW_BACK(modules, i, row) { const TString& module = *row; if (module.len() == 2 && module != "xx") add_module(ini, module); } } else { ininame = path; ininame.add("??inst.ini"); list_files(ininame, modules); FOR_EACH_ARRAY_ROW_BACK(modules, m, row) { TString& ininame = *row; ininame.lower(); const int pos = ininame.find("inst.ini"); CHECKS(pos > 2, "Invalid installation configuration: ", (const char*)ininame); const TString16 module = ininame.mid(pos-2, 2); TConfig ini(ininame, module); add_module(ini, module); } } sheet.rows_array().sort(); const bool ok = sheet.items() > 0; if (ok) update_version(); else sheet.error_box("Non e' stato trovato nessun modulo da installare\n" "in %s", (const char*)path); return ok; } bool TInstaller_mask::do_process(TAuto_token_string& commands) const { bool ok = TRUE; TFilename cmd; for (const char* c = commands.get(0); c && ok; c = commands.get()) { cmd = c; if (!cmd.blank()) { TWait_cursor hourglass; TExternal_app app(cmd); ok = app.run() == 0; } } return ok; } bool TInstaller_mask::pre_process(TInstall_ini& ini, const char* module) const { bool ok = TRUE; TInstall_ini cur_ini; TAuto_token_string altri(ini.get("Moduli", module)); altri.add("ba"); // La base e' obbligatoria per tutti TString submodule, curver, reqver; for (const char* mod = altri.get(0); mod && ok; mod = altri.get()) { submodule = mod; submodule.cut(2); reqver = ini.get("Versione", submodule); curver = cur_ini.get("Versione", submodule); ok = compare_version(reqver, curver) <= 0; if (!ok) { TString msg; msg << "L'installazione del modulo " << module << " richiede\nla versione " << reqver << " del sottomodulo " << submodule; error_box(msg); } } if (ok) { TAuto_token_string commands(ini.get("PreProcess", module)); ok = do_process(commands); } return ok; } bool TInstaller_mask::post_process(TInstall_ini& ini, const char* module) const { TAuto_token_string commands(ini.get("PostProcess", module)); return do_process(commands); } bool TInstaller_mask::install(const TString& module) { TWait_cursor hourglass; bool ok = FALSE; const TString& path = get(F_PATH); TFilename ininame = path; ininame.add(module); ininame << "inst.ini"; if (fexist(ininame)) { TInstall_ini ini(ininame); const int dischi = ini.get_int("Dischi", module); ok = dischi > 0; if (!ok) { return error_box("Impossibile determinare il numero dei dischetti"); } else { ok = pre_process(ini, module); if (!ok) return FALSE; } TProgind pi(dischi, "Decompressione in corso...", FALSE, TRUE); TFilename cmdline; for (int d = 1; d <= dischi && ok; d++) { cmdline = path; cmdline.add(module); cmdline << "inst" << d; cmdline.ext("zip"); ok = fexist(cmdline); while (!ok) { message_box("Inserire il disco %d di %d del modulo\n%s", d, dischi, (const char*)ini.get("Descrizione")); ok = fexist(cmdline); if (!ok) { if (!yesno_box("Impossibile trovare %s\nSi desidera riprovare?", (const char*)cmdline)) break; } } if (ok) { struct _diskfree_t drive; _dos_getdiskfree(0, &drive); const long required = fsize(cmdline) * (dischi-d+1) * 3; const unsigned requested_clusters = unsigned(required / drive.sectors_per_cluster / drive.bytes_per_sector) + 1; if (requested_clusters >= drive.avail_clusters) { ok = yesno_box("Lo spazio su disco potrebbe essere insufficiente:\n" "Si desidera continuare ugualmente?"); } } if (ok) { TWait_cursor hourglass; cmdline.insert("unzip.pif -o ", 0); TExternal_app app(cmdline); ok = app.run(FALSE, FALSE, FALSE, FALSE) == 0; pi.addstatus(1); } } if (ok) { post_process(ini, module); ini.export_module_paragraphs(module, ini.default_name()); } } else { ininame = path; ininame.add(TInstall_ini::default_name()); ok = fexist(ininame); if (ok) { TInstall_ini ini(ininame); TString_array list; const int files = ini.build_list(module, list); if (files > 0) { ok = pre_process(ini, module); if (ok) { TProgind pi(files, "Copia in corso...", FALSE, TRUE); TFilename src, dst; for (int f = 0; f < files && ok; f++) { pi.addstatus(1); dst = list.row(f).get(0); src = path; src.add(dst); ok = fcopy(src, dst); } } if (ok) { ini.export_module_paragraphs(module, ini.default_name()); post_process(ini, module); } } } } if (ok) { TInstall_ini ini; ini.set("DiskPath", path); ini.set("Data", TDate(TODAY), module); } // Non spostare nell'if precedente if (ok) update_version(); return ok; } bool TInstaller_mask::update_handler(TMask_field& fld, KEY key) { if (key == K_SPACE) { TInstaller_mask& m = (TInstaller_mask&)fld.mask(); m.autoload(); } return TRUE; } bool TInstaller_mask::path_handler(TMask_field& fld, KEY key) { bool ok = TRUE; if (key == K_TAB && fld.focusdirty()) { TString path = fld.get(); if (path.len() == 2 && isalpha(path[0]) && path[1] == ':') { path << SLASH; fld.set(path); } if (fexist(path)) update_handler(fld, K_SPACE); else ok = fld.error_box("Specificare un percorso valido"); } return ok; } bool TInstaller_mask::sheet_notify(TSheet_field& s, int r, KEY k) { bool ok = TRUE; if (k == K_INS) // Impedisci l'inserimento di nuove righe ok = FALSE; return ok; } bool TInstaller_mask::install_handler(TMask_field& fld, KEY key) { bool ok = TRUE; if (key == K_SPACE) { TMask& m = fld.mask(); const TString& modulo = m.get(S_MODULE); const TString& newver = m.get(S_NEW_VERSION); const TString& oldver = m.get(S_CUR_VERSION); const int cmp = compare_version(oldver, newver); if (cmp < 0) ok = yesno_box("Si desidera installare la versione %s?", (const char*)newver); if (cmp == 0) ok = yesno_box("Si desidera reinstallare la versione %s?", (const char*)newver); if (cmp > 0) ok = yesno_box("Si desidera ritornare alla versione %s?\n" "Attenzione: non e' garantito il corretto\n" "funzionamento di tutti i programmi!", (const char*)oldver); if (ok) { TInstaller_mask& im = (TInstaller_mask&)m.get_sheet()->mask(); im.install(modulo); } } return ok; } TInstaller_mask::TInstaller_mask() : TMask("ba1700a") { set_handler(F_PATH, path_handler); set_handler(F_UPDATE, update_handler); TSheet_field& sheet = sfield(F_SHEET); sheet.set_notify(sheet_notify); sheet.disable(); TMask& m = sheet.sheet_mask(); m.set_handler(S_INSTALL, install_handler); TInstall_ini ini; TFilename path = ini.get("DiskPath"); set(F_PATH, path); const char lettera = toupper(path[0]); const bool floppy = (path.len() > 1) && path[1] == ':' && (lettera == 'A' || lettera == 'B'); if (path.not_empty() && !floppy) autoload(); DIRECTORY dir; xvt_fsys_get_dir(&dir); xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size()); set(F_CURPATH, path); } /////////////////////////////////////////////////////////// // Programma principale /////////////////////////////////////////////////////////// class TInstaller : public TSkeleton_application { protected: virtual bool use_files() const { return FALSE; } virtual void main_loop(); }; void TInstaller::main_loop() { TInstaller_mask m; m.load(); m.run(); } int ba1700(int argc, char* argv[]) { TInstaller app; app.run(argc, argv, "Installer"); return 0; }