456 lines
12 KiB
C++
Executable File
456 lines
12 KiB
C++
Executable File
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifndef FOXPRO
|
|
#include <xvt.h>
|
|
#endif
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
#include <direct.h>
|
|
#include <io.h>
|
|
#define F_OK 0
|
|
#else
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
// @doc EXTERNAL
|
|
|
|
// @func Permette di rimuovere un file (chiama unlink)
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione
|
|
//
|
|
// @flag 0 | Se l'operazione ha successo
|
|
// @flag -1 | Se l'operazione non e' riuscita. Viene inoltre settata la variabile
|
|
// <p errno> con la causa dell'insuccesso
|
|
int remove(
|
|
const char* path) // @parm Nome del file da eliminare (non valgono i caratteri jolly)
|
|
{ return unlink(path); }
|
|
|
|
#endif
|
|
|
|
#define __UTILITY_CPP
|
|
#include <utility.h>
|
|
|
|
// @func Permette di copiare un file
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione:
|
|
//
|
|
// @flag TRUE | Se l'operazione e' stata effettuata con successo
|
|
// @flag FALSE | Se l'operazione non e' stata effettuata con successo
|
|
bool fcopy(
|
|
const char* orig, // @parm Nome del file di origine
|
|
const char* dest, // @parm Nome del file di destinazione
|
|
bool append) // @parm Controllo per aggiungere il contenuto del
|
|
// file <p dest> in coda al file <p orig> (default FALSE)
|
|
|
|
// @comm Nel caso vengano ravvisati degli errori durante l'operazione vengono
|
|
// creati dei box di comunicazione che indicano la causa del problema
|
|
{
|
|
const char* wflag;
|
|
#if XVT_OS == XVT_OS_WIN
|
|
const char* const rflag = "rb";
|
|
if (append)
|
|
wflag = "ab";
|
|
else
|
|
wflag = "wb";
|
|
#else
|
|
const char* const rflag = "r";
|
|
if (append)
|
|
wflag = "a";
|
|
else
|
|
wflag = "w";
|
|
#endif
|
|
|
|
FILE* i = fopen(orig, rflag);
|
|
if (!i) return error_box("Impossibile leggere il file %s", orig);
|
|
|
|
FILE* o = fopen(dest, wflag);
|
|
CHECKS(o, "Impossibile scrivere il file ", dest);
|
|
|
|
const word size = 16*1024;
|
|
TString buffer(size);
|
|
|
|
bool ok = TRUE;
|
|
while (ok)
|
|
{
|
|
const word letti = fread((char*)(const char*)buffer, 1, size, i);
|
|
ok = fwrite((char*)(const char*)buffer, 1, letti, o) == letti;
|
|
if (letti < size) break;
|
|
}
|
|
|
|
if (!ok) error_box("Errore di scrittura: probabile disco pieno!");
|
|
|
|
fclose(o);
|
|
fclose(i);
|
|
|
|
return ok;
|
|
}
|
|
|
|
// @func Controlla l'esistenza di un file
|
|
//
|
|
// @rdesc Ritrona i seguenti valori:
|
|
//
|
|
// @flag TRUE | Se il file esiste
|
|
// @flag FALSE | Se il file non esiste
|
|
bool fexist(
|
|
const char* file) // @parm Nome del file di cui contrallarne l'esistenza
|
|
{
|
|
return access(file, F_OK) == 0;
|
|
}
|
|
|
|
// @func Permette di creare una directory
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione
|
|
//
|
|
// @flag TRUE | Se l'operazione e' avvenuta con successo
|
|
// @flag FALSE | Se l'operazione non e' riuscita
|
|
bool make_dir(
|
|
const char* dir) // @parm Nome della directory da creare
|
|
{
|
|
int res =
|
|
#if XVT_OS==XVT_OS_WIN
|
|
mkdir(dir);
|
|
#else
|
|
mkdir(dir, 0777);
|
|
#endif
|
|
return res == 0;
|
|
}
|
|
|
|
#ifndef FOXPRO
|
|
|
|
// @func Setta la token string modificando la lista dei file formata con caratteri jolly
|
|
// in lista con caratteri estesi
|
|
//
|
|
// @rdesc Ritorna il numero di file che soddisfano la condizione passata (numero di elementi
|
|
// della token string)
|
|
int list_files(
|
|
TToken_string& filelist) // @parm Stringa contenente la condizione di estrazione
|
|
// della lista dei file
|
|
|
|
// @comm Per comodita' la lista desiderata vine anch'essa messa in <p filelist> in quanto e'
|
|
// gia' costruita
|
|
{
|
|
TFilename dir(filelist.get(0));
|
|
for (int i = dir.len()-1; i >= 0; i--)
|
|
if (dir[i] == '/' || dir[i] == '\\') break;
|
|
|
|
const TString16 mask(dir.mid(i+1));
|
|
dir.cut(i > 0 ? i : 0);
|
|
|
|
xvt_fsys_save_dir();
|
|
DIRECTORY directory; xvt_fsys_convert_str_to_dir((char*)(const char*)dir, &directory);
|
|
BOOLEAN ok = xvt_fsys_set_dir(&directory);
|
|
if (!ok) fatal_box ("Impossibile entrare in %s", (const char*)dir);
|
|
|
|
SLIST files = xvt_fsys_list_files("", (char*)(const char*)mask, FALSE);
|
|
|
|
const int count = xvt_slist_count(files);
|
|
filelist.spaces(count*12);
|
|
filelist.cut(0);
|
|
|
|
for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e))
|
|
{
|
|
char* f = xvt_slist_get(files, e, NULL);
|
|
if (dir.not_empty())
|
|
{
|
|
filelist.add(dir);
|
|
filelist << '/' << f;
|
|
}
|
|
else
|
|
filelist.add(f);
|
|
}
|
|
|
|
xvt_slist_destroy(files);
|
|
xvt_fsys_restore_dir();
|
|
|
|
return count;
|
|
}
|
|
|
|
#endif
|
|
|
|
// Certified 99%
|
|
// @func Permette di ritornare una stringa formata da parametri
|
|
//
|
|
// @rdesc Ritorna la stringa desiderata
|
|
char* format(
|
|
const char* fmt, // @parm Formato che deve essere dato alla stringa
|
|
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
|
|
|
// @comm Il funzionamento e' come la <f sprintf> del C, solo che non e' necessario passare la
|
|
// stringa di destinazione alla funzione
|
|
{
|
|
va_list pars;
|
|
|
|
va_start(pars, fmt);
|
|
const int tot = vsprintf(__tmp_string, fmt, pars);
|
|
va_end(pars);
|
|
|
|
CHECK(tot >= 0 && tot < sizeof(__tmp_string)-1, "Ue'! Ma quanto scrivi?");
|
|
return(__tmp_string);
|
|
}
|
|
|
|
|
|
// @func Converte la coppia nome-parametro in una stringa che identifica il programma
|
|
//
|
|
// @rdesc Ritorna la stringa identificante il programma
|
|
const char* cmd2name(
|
|
const char* argv0, // @parm Nome del programma
|
|
const char* argv1) // @parm Nome del parametro (default "")
|
|
{
|
|
TFilename app(argv0);
|
|
app = app.name();
|
|
if (argv1 && *argv1) app << ' ' << argv1;
|
|
else app << " -0";
|
|
app.lower();
|
|
|
|
const int par = app.find(" -");
|
|
const int num = par > 0 ? atoi(app.mid(par+2))+1 : 1;
|
|
|
|
const char c = (num > 9) ? ('a'+num-10) : ('0'+num);
|
|
app.cut(3);
|
|
app << c << "00";
|
|
|
|
return strcpy(__tmp_string, app);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Conversione in cifre romane
|
|
///////////////////////////////////////////////////////////
|
|
|
|
HIDDEN const char * cifre_romane = "IVXLCDM@";
|
|
HIDDEN const int valori_cifre [] = { 1, 5, 10, 50, 100, 500, 1000, -1 };
|
|
|
|
HIDDEN int ctoi(char c)
|
|
{
|
|
if (c == '\0') return 0;
|
|
|
|
c = toupper(c);
|
|
for (int i = 0; cifre_romane[i]; i++)
|
|
if (cifre_romane[i] == c) return valori_cifre[i];
|
|
|
|
return -1;
|
|
}
|
|
// @func Converte una cifra romana in intero normale
|
|
//
|
|
// @rdesc Ritorna l'equivalente in numeri della cifra romane
|
|
int rtoi(
|
|
const char * val) // @parm Stringa contenente la cifra scritta in numeri romani
|
|
{
|
|
if (val == NULL) return 0;
|
|
|
|
int tot = 0;
|
|
int value = ctoi (val[0]);
|
|
for (int i = 1; value > 0; i++)
|
|
{
|
|
const int next_val = ctoi(val[i]);
|
|
if (value < next_val) tot -= value;
|
|
else tot += value;
|
|
value = next_val;
|
|
}
|
|
|
|
return (value == 0) ? tot : -1;
|
|
}
|
|
|
|
// @func Converte un numero intero nell'equivalente cifra romana
|
|
//
|
|
// @rdesc Ritorna una stringa contenente la cifra romana
|
|
const char* itor(
|
|
int num) // @parm Intero da convertire in cifra romana
|
|
{
|
|
HIDDEN char roman_string[16];
|
|
int cifra = 0;
|
|
|
|
for (int pos = 7; pos--;)
|
|
{
|
|
int val = valori_cifre[pos];
|
|
int quanti = num / val;
|
|
if (quanti < 4)
|
|
{
|
|
if ((pos & 1) && quanti == 1 && (num/valori_cifre[pos-1]) == 9)
|
|
{
|
|
roman_string[cifra++] = cifre_romane[pos-1];
|
|
roman_string[cifra++] = cifre_romane[pos+1];
|
|
val = valori_cifre[pos-1];
|
|
quanti = 9;
|
|
}
|
|
else for (int i = 0; i < quanti; i++)
|
|
roman_string[cifra++] = cifre_romane[pos];
|
|
}
|
|
else
|
|
{
|
|
roman_string[cifra++] = cifre_romane[pos];
|
|
roman_string[cifra++] = cifre_romane[pos+1];
|
|
}
|
|
|
|
num -= quanti * val;
|
|
}
|
|
|
|
roman_string[cifra] = '\0';
|
|
return roman_string;
|
|
}
|
|
|
|
// @func Permette di codificare i caratteri di escape
|
|
//
|
|
// @rdesc Ritorna il carattere codificato
|
|
const char *esc(
|
|
const char* s) // @parm Carattere da codificare
|
|
|
|
// @comm Viene utilizzata soprattuto in UNIX.
|
|
{
|
|
const char *s1 = s;
|
|
char *s2 = __tmp_string;
|
|
int base;
|
|
|
|
while (*s1)
|
|
{
|
|
if (*s1 == '\\')
|
|
{
|
|
s1++;
|
|
switch (tolower(*s1))
|
|
{
|
|
case 'b' : *s2++ = '\b'; break;
|
|
case 'e' : *s2++ = '\033'; break;
|
|
case 'f' : *s2++ = '\f'; break;
|
|
case 'n' : *s2++ = '\n'; break;
|
|
case 'r' : *s2++ = '\r'; break;
|
|
case 't' : *s2++ = '\t'; break;
|
|
default :
|
|
{
|
|
if (isdigit(*s1))
|
|
{
|
|
if (*s1 == '0')
|
|
{
|
|
s1++;
|
|
if (tolower(*s1) == 'x')
|
|
{
|
|
s1++;
|
|
base = 16;
|
|
}
|
|
else base = 8;
|
|
}
|
|
else base = 10;
|
|
*s2 = 0;
|
|
char c = tolower(*s1);
|
|
while (isdigit(c) || (base == 16 && c >= 'a' && c <= 'f'))
|
|
{
|
|
*s2 *= base;
|
|
if (isdigit(*s1)) *s2 += (*s1 - 48);
|
|
else *s2 += (*s1 - 'a' + 10) & 0x0F;
|
|
s1++;
|
|
c = tolower(*s1);
|
|
}
|
|
s2++; s1--;
|
|
}
|
|
else *s2++ = *s1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (*s1 == '^')
|
|
{
|
|
s1++;
|
|
*s2++ = (tolower(*s1) - 'a' + 1);
|
|
}
|
|
else *s2++ = *s1 ;
|
|
s1++;
|
|
}
|
|
*s2 = '\0';
|
|
return(__tmp_string);
|
|
}
|
|
|
|
HIDDEN const char * const key = "QSECOFR-";
|
|
|
|
// @func Permette di criptare una parola
|
|
//
|
|
// @rdesc Ritorna la stringa criptata
|
|
const char * encode(
|
|
const char * data) // @parm Stringa da criptare
|
|
|
|
// @xref <f decode>
|
|
{
|
|
for (int i = 0; data[i]; i++)
|
|
__tmp_string[i] = data[i] + (i < 8 ? key[i] : data[i - 8]);
|
|
__tmp_string[i] = '\0';
|
|
return __tmp_string;
|
|
}
|
|
|
|
// @func Permette di decodificare una stringa criptata
|
|
//
|
|
// @rdesc Ritorna la stringa in chiaro
|
|
const char * decode(
|
|
const char * data) // @parm Stringa criptata da tradurre
|
|
|
|
// @xref <f encode>
|
|
{
|
|
for (int i = 0; data[i]; i++)
|
|
__tmp_string[i] = data[i] - (i < 8 ? key[i] : __tmp_string[i - 8]);
|
|
__tmp_string[i] = '\0';
|
|
return __tmp_string;
|
|
}
|
|
|
|
#if XVT_OS != XVT_OS_WIN
|
|
|
|
// @func Permette di confrontare due stringhe ignorando la differenza
|
|
// tra lettere maiuscole o minuscole
|
|
//
|
|
// @rdesc Ritorna il risultato dell'operazione:
|
|
//
|
|
// @flag 0 | Se le stringhe sono uguali
|
|
// @flag >0 | Se le stringhe sono differenti. Il numero indica la lettera diversa
|
|
int stricmp(
|
|
const char* s1, // @parm Prima stringa da confrontare
|
|
const char* s2) // @parm Seconda stringa da confrontare
|
|
{
|
|
for(int d = 0 ; (d = toupper(*s1)-toupper(*s2)) == 0; s1++, s2++)
|
|
if (*s1 == '\0' && *s2 == '\0')
|
|
return 0;
|
|
return d;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef __WATCOMC__
|
|
// @func Costruisce il percorso per un file temporaneo
|
|
//
|
|
// @rdesc Ritorna il nome assoluto del file temporaneo
|
|
char * tempnam(
|
|
const char * dir , // @parm Nome della directory nel quale inserire il file temporaneo
|
|
const char * prefix) // @parm Evenutale prefisso da dare al file temporaneo
|
|
|
|
// @comm Il nome della directory viene letto dalla variabile d'ambiente chiamata
|
|
// TMP, solo nel caso questa non esista viene utilizzato il nome passato
|
|
// in <p dir>.
|
|
// <nl>E' definita solo nel caso si utilizzi il WATCOM C/C++.
|
|
|
|
{
|
|
TFilename tmpdir(getenv("TMP"));
|
|
static word counter = 1;
|
|
|
|
if (tmpdir.empty() || !fexist(tmpdir))
|
|
{
|
|
tmpdir = dir;
|
|
if (tmpdir.empty() || !fexist(tmpdir))
|
|
tmpdir = "";
|
|
}
|
|
if (is_not_slash(tmpdir.right(1)[0]))
|
|
tmpdir << '/';
|
|
tmpdir << prefix ;
|
|
const int lastpos = tmpdir.len() ;
|
|
tmpdir << format("%ud", counter);
|
|
|
|
while (!fexist(tmpdir))
|
|
{
|
|
counter++;
|
|
if (counter == 0) counter = 1;
|
|
tmpdir.cut(lastpos);
|
|
tmpdir << format("%ud", counter);
|
|
}
|
|
return strdup(tmpdir);
|
|
}
|
|
#endif
|
|
|