55a36762ef
checks.cpp Tolto include windows.h colors.cpp Tolto include windows.h controls.cpp Aggiunto cambiamento del font runtime dei TText_control execp.cpp Tolto include windows.h form.cpp Tolto include windows.h mask.cpp Corretta formattazione di due righe maskfld.cpp Aggiunto messaggio CHECK msksheet.cpp Tolto include windows.h relapp.cpp Tolto include windows.h strings.pp Corretto CHECK della TFixed_string::format() viswin.cpp Tolto include windows.h window.cpp Tolto include windows.h xvtility.cpp Corretto calcolo altezza righe delle maschere git-svn-id: svn://10.65.10.50/trunk@4085 c028cbd2-c16b-5b4b-a496-9718f37d4682
566 lines
16 KiB
C++
Executable File
566 lines
16 KiB
C++
Executable File
#include <direct.h>
|
|
#include <al.h>
|
|
|
|
#define XVT_INCL_NATIVE
|
|
#define STRICT
|
|
|
|
#include <archives.h>
|
|
#include <config.h>
|
|
#include <isam.h>
|
|
#include <mask.h>
|
|
#include <prefix.h>
|
|
#include <progind.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TProgress_win declaration
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
class TProgress_win : public TMask
|
|
{
|
|
ALWindowsMessage* _monitor;
|
|
TArchive* _arc;
|
|
|
|
protected:
|
|
static bool cancel_handler(TMask_field&, KEY k);
|
|
|
|
public:
|
|
ALWindowsMessage* monitor() const { return _monitor; }
|
|
|
|
TProgress_win(const char* title, TArchive* = NULL);
|
|
~TProgress_win();
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TArchive
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Funzione per richiedere all'utente il dischetto e per controllare la
|
|
// corretta sequenza dei dischetti da inserire
|
|
//
|
|
// @rdesc Ritorna il puntatore al file presente (o meno) sul dischetto
|
|
FILE* TArchive::ask_disk(
|
|
TFilename& name, // @parm Nome del file da creare/cercare su disco
|
|
int disk, // @parm Numero progressivo del set
|
|
char floppy, // @parm Drive sul quale effettuare l'operazione (A, B, C, ...)
|
|
bool lettura) const // @parm Indica il modo di apertura del file:
|
|
//
|
|
// @flag TRUE | Apre il file in lettura
|
|
// @flag FALSE | Apre il file in scrittura
|
|
{
|
|
TFilename prev(name);
|
|
prev.ext(format("%03d", disk-1)); // File precedente
|
|
bool first = TRUE;
|
|
do
|
|
{
|
|
if (first)
|
|
{
|
|
message_box("Inserire il disco %d nel drive %c:", disk, floppy);
|
|
first = FALSE;
|
|
}
|
|
else
|
|
{
|
|
const bool ok = yesno_box("Inserire il disco %d nel drive %c\n"
|
|
"Estrarre il disco %d e continuare?", disk, floppy, disk-1);
|
|
if (!ok) return NULL;
|
|
}
|
|
} while (fexist(prev)); // Non facciamo i furbetti!
|
|
|
|
name.ext(format("%03d", disk)); // File attuale
|
|
|
|
FILE* f = NULL;
|
|
bool retry = TRUE;
|
|
while (retry)
|
|
{
|
|
f = fopen(name, lettura ? "rb" : "wb");
|
|
if (f == NULL)
|
|
retry = yesno_box("Il file %s non e' accessibile: riprovare?", (const char*)name);
|
|
else
|
|
{
|
|
setvbuf(f, NULL, _IOFBF, BUFSIZE);
|
|
retry = FALSE;
|
|
}
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
long TArchive::fsize(FILE* f) const
|
|
{
|
|
CHECK(f, "Can't measure NULL file");
|
|
fseek(f, 0, SEEK_END);
|
|
const long s = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
return s;
|
|
}
|
|
|
|
int TArchive::build_backup_list(long firm, TString_array& fl) const
|
|
{
|
|
fl.destroy();
|
|
if (firm < 0L)
|
|
{
|
|
fl.add(firm2dir(0L));
|
|
TLocalisamfile ditte(LF_NDITTE);
|
|
for (int err = ditte.first(); err == NOERR; err = ditte.next())
|
|
{
|
|
const char* dir = firm2dir(ditte.get_long("CODDITTA"));
|
|
if (fexist(dir))
|
|
fl.add(dir);
|
|
}
|
|
|
|
TFilename name(firm2dir(-1)); // __ptprf
|
|
name.add("config"); // Aggiungi configurazioni
|
|
if (fexist(name))
|
|
fl.add(name);
|
|
}
|
|
else
|
|
fl.add(firm2dir(firm));
|
|
|
|
return fl.items();
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Costruisce la lista delle directory da scompattare
|
|
//
|
|
// @rdesc Ritorna il numero di direttori da ripristinare
|
|
int TArchive::build_restore_list(
|
|
long firm, // @parm Ditta di cui effettuare il salvataggio
|
|
char floppy, // @parm Floppy su cui effettuare il backup
|
|
TString_array& fl) const // @parm Nomi dei direttori da ripristinare
|
|
{
|
|
if (firm < 0) // Crea lista automaticamente
|
|
{
|
|
TFilename name("a:/backup.ini"); name[0] = floppy;
|
|
TConfig ini(name);
|
|
const int max = ini.list_paragraphs(fl); // Lista degli archivi
|
|
for (int i = max-1; i >= 0; i--)
|
|
{
|
|
const int disk = ini.get_int("Disk", fl.row(i));
|
|
if (disk == 1)
|
|
{
|
|
firm = atol(fl.row(i));
|
|
fl.add(firm2dir(firm), i); // Aggiungi gli archivi che iniziano qui
|
|
}
|
|
else fl.destroy(i, TRUE); // Elimina gli archivi che non iniziano qui
|
|
}
|
|
|
|
name = firm2dir(-1); // __ptprf
|
|
name.add("config"); // Aggiungi configurazioni
|
|
fl.add(name);
|
|
}
|
|
else
|
|
{
|
|
fl.destroy();
|
|
fl.add(firm2dir(firm)); // Inserisci solo una ditta (o COM)
|
|
}
|
|
|
|
return fl.items();
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Spezza il file in modo da farlo stare sul dischetto
|
|
//
|
|
// @rdesc Ritorna se e' riuscito a spezzare il file
|
|
bool TArchive::fsplit(
|
|
const char* filename, // @parm Nome del file da spezare
|
|
char floppy, // @parm Floppy su cui scaricare il file
|
|
const char* desc) const // @parm Descrizione dell'archivio
|
|
{
|
|
const TFilename from(filename); // File da splittare
|
|
|
|
FILE* i = fopen(from, "rb"), *o = NULL;
|
|
if (i == NULL) return error_box("Impossibile aprire il file '%s'", from);
|
|
setvbuf(i, NULL, _IOFBF, BUFSIZE);
|
|
|
|
const long tot = fsize(i);
|
|
long scritti=0;
|
|
|
|
TFilename work;
|
|
work << floppy << ":/" << from.name(); // File su dischetto
|
|
|
|
TString256 msg("Archiviazione di "); msg << work << " (" << (tot/1024) << "K)";
|
|
TProgind w(tot, msg, TRUE, TRUE, 40);
|
|
|
|
int disk = 0;
|
|
TString buffer(BUFSIZE);
|
|
|
|
bool ok = TRUE;
|
|
while (ok)
|
|
{
|
|
const size_t letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
|
|
|
|
if (o != NULL)
|
|
ok = (letti > 0) ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE;
|
|
else
|
|
ok = FALSE;
|
|
|
|
if (!ok)
|
|
{
|
|
|
|
if (o != NULL)
|
|
{
|
|
chsize(fileno(o),scritti); // Must truncate output file or some information will be rewritten on next disk!
|
|
scritti = 0; // Reset count bytes written to disk.
|
|
fclose(o);
|
|
}
|
|
o = ask_disk(work, ++disk, floppy, FALSE);
|
|
ok = o != NULL;
|
|
if (ok)
|
|
{
|
|
TFilename parag(work.name()); parag.ext("");
|
|
TFilename ini("a:/backup.ini"); ini[0] = floppy;
|
|
|
|
if (fexist(ini))
|
|
{
|
|
TConfig c(ini, parag);
|
|
const int d = c.get_int("Disk");
|
|
if (d == disk)
|
|
{
|
|
ok = yesno_box("Il disco %d contiene gia' un backup del direttorio %s del %s"
|
|
"\nSi desidera continuare?",
|
|
disk, (const char*)parag, (const char*)c.get("Date"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FILE* i = fopen(ini, "w"); // Crea il file backup.ini per evitare messaggi
|
|
fclose(i);
|
|
}
|
|
if (!ok) break;
|
|
|
|
TConfig c(ini, parag);
|
|
const char* oggi = TDate(TODAY).string();
|
|
c.set("Size", tot , NULL, TRUE);
|
|
c.set("Disk", disk, NULL, TRUE);
|
|
c.set("Description", desc, NULL, TRUE);
|
|
c.set("Date", oggi, NULL, TRUE);
|
|
|
|
ok = (letti > 0) ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE;
|
|
if (!ok) error_box("Impossibile scrivere i dati sul dischetto");
|
|
else
|
|
scritti +=letti;
|
|
}
|
|
}
|
|
else
|
|
scritti += letti;
|
|
w.addstatus(letti);
|
|
if (ok)
|
|
ok = !w.iscancelled();
|
|
if (letti < BUFSIZE)
|
|
break;
|
|
}
|
|
|
|
fclose(i);
|
|
if (o != NULL) fclose(o);
|
|
|
|
return ok;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Ricostruisce il file spezzato
|
|
//
|
|
// @rdesc Ritorna se e' riuscito a ricostruire il file
|
|
bool TArchive::fbuild(
|
|
const char* filename, // @parm Nome del file da ricostrutire
|
|
char floppy) const // @parm Floppy da cui recupare i pezzi del file
|
|
{
|
|
const TFilename work(filename);
|
|
|
|
FILE* o = fopen(work, "wb"), *i = NULL;
|
|
if (o == NULL)
|
|
return error_box("Impossibile creare il file '%s'", (const char*)work);
|
|
setvbuf(o, NULL, _IOFBF, BUFSIZE);
|
|
|
|
long totale = 0L; // Bytes letti
|
|
long max = 1440000L; // Bytes da leggere
|
|
TFilename name; // Nome del file su dischetto
|
|
name << floppy << ":/" << work.name();
|
|
|
|
TString256 msg("Ripristino da "); msg << name;
|
|
TProgind w(max, msg, TRUE, TRUE, 32);
|
|
|
|
int disk = 0;
|
|
TString buffer(BUFSIZE);
|
|
|
|
bool ok = TRUE;
|
|
while (ok)
|
|
{
|
|
size_t letti = 0;
|
|
if (i != NULL)
|
|
{
|
|
letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
|
|
ok = letti > 0;
|
|
}
|
|
else
|
|
ok = FALSE;
|
|
|
|
if (!ok) // Richiedi nuovo disco
|
|
{
|
|
if (i != NULL) fclose(i);
|
|
i = ask_disk(name, ++disk, floppy, TRUE);
|
|
ok = i != NULL;
|
|
if (ok)
|
|
{
|
|
if (disk == 1)
|
|
{
|
|
TFilename ini("a:/backup.ini"); ini[0] = floppy;
|
|
if (fexist(ini))
|
|
{
|
|
TFilename parag(name.name()); parag.ext("");
|
|
TConfig c(ini, parag);
|
|
max = c.get_long("Size");
|
|
}
|
|
else ok = yesno_box("Manca il file %s: continuare ugualmente?", (const char*)ini);
|
|
}
|
|
w.setmax(max);
|
|
|
|
if (ok) // Leggi primo blocco di bytes
|
|
{
|
|
letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
|
|
ok = letti > 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ok) // La lettura e stata fatta bene
|
|
{
|
|
ok = fwrite((char*)(const char*)buffer, 1, letti, o) == letti;
|
|
if (ok)
|
|
{
|
|
w.addstatus(letti);
|
|
totale += letti;
|
|
ok = !w.iscancelled();
|
|
}
|
|
else error_box("Impossibile scrivere i dati sul file %s", (const char*)work);
|
|
}
|
|
|
|
if (!ok || totale == max) // Esci in caso di errore o se hai finito
|
|
break;
|
|
}
|
|
|
|
fclose(o);
|
|
if (i != NULL) fclose(i);
|
|
|
|
return ok;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Effettua il backup della ditta o della directory
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione
|
|
bool TArchive::backup(
|
|
const char* dir, // @parm Directory di cui effettuare il backup
|
|
char floppy, // @parm Floppy su cui effettuare il backup
|
|
const char* desc, // @parm Descrizione da assegnare al backup
|
|
bool pr_set) // @parm Se TRUE setta il prefix come vuoto (default TRUE)
|
|
// @parm long | firm | Ditta di cui effettuare il backup
|
|
|
|
// @syntax bool backup(const char* dir, char floppy, const char* desc, bool pr_set);
|
|
// @syntax bool backup(long firm, char floppy, const char* desc, bool pr_set);
|
|
|
|
// @comm Il parametro <p pr_set> e' utilizzato per evitare errori di riaperture di files.
|
|
|
|
{
|
|
const TString16 old(prefix().name());
|
|
if (pr_set)
|
|
prefix().set(NULL);
|
|
|
|
xvt_fsys_save_dir();
|
|
chdir(dir);
|
|
|
|
const TFilename d(dir);
|
|
const TString16 name(d.name());
|
|
TFilename work; work.tempdir(); work.add(name); work.ext("gal");
|
|
|
|
_arc = new ALArchive(work);
|
|
|
|
TString256 title("Archiviazione di "); title << name;
|
|
TProgress_win w(title, this);
|
|
ALEntryList list(w.monitor());
|
|
_arc->AddWildCardFiles(list, "*.*");
|
|
|
|
w.open_modal();
|
|
_arc->Create( list );
|
|
w.close_modal();
|
|
|
|
bool ok = _arc->mStatus == AL_SUCCESS;
|
|
if (ok)
|
|
ok = fsplit(work, floppy, desc);
|
|
else
|
|
error_box("Compressione degli archivi errata o incompleta:\n%s",
|
|
_arc->mStatus.GetStatusDetail());
|
|
|
|
delete _arc; _arc = NULL;
|
|
|
|
remove(work);
|
|
xvt_fsys_restore_dir();
|
|
if (pr_set)
|
|
prefix().set(old);
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TArchive::backup(long firm, char floppy, const char* desc, bool pr_set)
|
|
{
|
|
TString_array fl;
|
|
const int num_ditte = build_backup_list(firm, fl);
|
|
|
|
bool ok = TRUE;
|
|
for (int f = 0; f < num_ditte; f++)
|
|
{
|
|
ok = backup(fl.row(f), floppy, desc, pr_set);
|
|
if (!ok) break;
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Effettua il restore della ditta o dell directory
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione
|
|
bool TArchive::restore(
|
|
const char* dir, // @parm Directory di cui effettuare il restore
|
|
char floppy, // @parm Floppy da cui leggere i dati
|
|
bool tmp, // @parm Directory temporanea da utilizzare
|
|
bool pr_set) // @parm Se TRUE setta il prefix come vuoto (default TRUE)
|
|
|
|
// @syntax bool restore(const char* dir, char floppy, bool temp, bool pr_set);
|
|
// @syntax bool restore(long firm, char floppy, bool temp, bool pr_set);
|
|
|
|
// @comm Il parametro <p pr_set> e' utilizzato per evitare errori di riaperture di files.
|
|
|
|
{
|
|
TFilename work;
|
|
if (tmp)
|
|
work.tempdir();
|
|
else
|
|
work = dir;
|
|
|
|
TFilename output(dir);
|
|
output = output.name(); output.ext("gal");
|
|
|
|
if (!yesno_box("Attenzione l'archivio sul disco %c: verra' ripristinato\n"
|
|
"nel direttorio %s. Continuare?", floppy, (const char*)work))
|
|
return FALSE;
|
|
|
|
xvt_fsys_save_dir();
|
|
bool ok = chdir(work) == 0;
|
|
if (!ok)
|
|
{
|
|
ok = yesno_box("Non esiste il direttorio %s: si desidera crearlo?", (const char*)work);
|
|
if (ok)
|
|
{
|
|
make_dir(work);
|
|
ok = chdir(work) == 0;
|
|
}
|
|
if (!ok)
|
|
return error_box("Impossibile accedere a %s", (const char*)work);
|
|
}
|
|
|
|
const TString16 old(prefix().name());
|
|
if(pr_set)
|
|
prefix().set(NULL);
|
|
|
|
ok = fbuild(output, floppy);
|
|
|
|
if (ok)
|
|
{
|
|
_arc = new ALArchive(output);
|
|
|
|
TProgress_win w("Ripristino", this);
|
|
ALEntryList list(w.monitor());
|
|
_arc->ReadDirectory(list);
|
|
|
|
w.open_modal();
|
|
_arc->Extract( list );
|
|
|
|
ok = _arc->mStatus == AL_SUCCESS;
|
|
if (!ok) error_box("Ripristino degli archivi errato o incompleto:\n%s",
|
|
_arc->mStatus.GetStatusString());
|
|
w.close_modal();
|
|
delete _arc; _arc = NULL;
|
|
|
|
remove(output);
|
|
}
|
|
|
|
xvt_fsys_restore_dir();
|
|
if(pr_set)
|
|
prefix().set(old);
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TArchive::restore(long firm, char floppy, bool temp, bool pr_set)
|
|
{
|
|
TString_array fl;
|
|
const int num_ditte = build_restore_list(firm, floppy, fl);
|
|
|
|
bool ok = TRUE;
|
|
for (int f = 0; f < num_ditte; f++)
|
|
{
|
|
ok = restore(fl.row(f), floppy, temp, pr_set);
|
|
if (!ok) break;
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
void TArchive::stop_job()
|
|
{
|
|
if (_arc != NULL)
|
|
_arc->GetStorageObject()->mStatus.SetError(AL_USER_ABORT, "Interrotto dall'utente");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TProgress_win implementation
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TProgress_win::TProgress_win(const char* title, TArchive* arc)
|
|
: TMask(title, 1, 60, 6), _arc(arc)
|
|
{
|
|
RCT rct;
|
|
xvt_rect_set(&rct, CHARX, CHARY, 58*CHARX, 5*CHARY/2);
|
|
WINDOW wtxt = xvt_ctl_create(WC_EDIT, &rct, "", win(), CTL_FLAG_DISABLED, (long)this, 101);
|
|
xvt_rect_set(&rct, 28*CHARX, 3*CHARY, 33*CHARX, 9*CHARY/2);
|
|
WINDOW wnum = xvt_ctl_create(WC_EDIT, &rct, "", win(), CTL_FLAG_DISABLED, (long)this, 102);
|
|
|
|
add_button(DLG_USER, 0, "Cancel", -11, -1, 10, 2, "", BMP_CANCEL);
|
|
set_handler(DLG_USER, cancel_handler);
|
|
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
HWND txt = (HWND)xvt_vobj_get_attr(wtxt, ATTR_NATIVE_WINDOW);
|
|
HWND num = (HWND)xvt_vobj_get_attr(wnum, ATTR_NATIVE_WINDOW);
|
|
_monitor = new ALWindowsMessage(AL_MONITOR_OBJECTS, txt, AL_SEND_RATIO, num);
|
|
#endif
|
|
}
|
|
|
|
TProgress_win::~TProgress_win()
|
|
{
|
|
if (_monitor) delete _monitor;
|
|
}
|
|
|
|
bool TProgress_win::cancel_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TProgress_win& m = (TProgress_win&)f.mask();
|
|
if (m._arc != NULL)
|
|
m._arc->stop_job();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|