campo-sirio/include/config.cpp

566 lines
16 KiB
C++
Raw Normal View History

#include <xvt.h>
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
#include <io.h>
#else
#include <stdio.h>
#endif
#include <stdlib.h>
#include <applicat.h>
#include <config.h>
#include <date.h>
#include <scanner.h>
#include <prefix.h>
#include <utility.h>
extern "C"
{
int rename(const char*, const char*);
};
// @doc EXTERNAL
// @mfunc Legge i dati del paragrafo
//
// @rdesc Ritorna i seguenti valori:
//
// @flag TRUE | Se il paragrafo c'ere
// @flag FALSE | Se il pragarafo non e' esitente
bool TConfig::_read_paragraph()
// @comm Legge il contenuto di tutte le variabili del paragrafo attivo
{
bool itwas = FALSE;
_data.destroy();
TScanner scan(_file);
if (scan.paragraph(_paragraph))
{
itwas = TRUE;
// populate array
TString key, val;
for (;;)
{
const TString& l = scan.line();
if (l == "" || l[0] == '[') break; // Fine paragrafo
if (l[0] == '#' || l[0] == '/') continue; // Riga di commento
const int ind = l.find('=');
if (ind == -1)
{
error_box("Errore configurazione:\n file %s, vicino alla riga %u\n %s",
(const char*)_file, scan.linenum(), (const char*)l);
continue;
}
key = l.left(ind); key.trim();
val = l.mid(ind+1); val.trim();
if (val[0] == '%')
{
if (val == "%yr%") val.format("%04d", TDate(TODAY).year()); else
if (val == "%frm%") val.format("%05ld", prefix().get_codditta());
}
// sostituzione abilitata
_data.add(key,val,TRUE);
}
}
return itwas;
}
// @doc EXTERNAL
// @mfunc Scrive i dati del paragrafo
void TConfig::_write_paragraph(
ofstream& out) // @parm Indirizzo dell'utput sul quale scrivere il paragrafo
// @comm Scrive le variabili del paragrafo attivo. Nel caso il paragrafo non
// era presente viene aggiunto nel file.
{
_data.restart();
out << '[' << _paragraph << ']' << endl;
for (int i = 0; i < _data.items(); i++)
{
THash_object* o = _data.get_hashobj();
out << o->key() << "\t= " << (TString&)(o->obj()) << '\n';
}
out << endl;
}
void TConfig::_write_file()
{
ifstream in(_file);
TFilename temp;
temp.temp("cnf");
ofstream out(temp);
TString l(1024);
TString80 cnf; cnf << '[' << _paragraph << ']';
bool skip = FALSE, done = FALSE;
while (!in.eof())
{
in.getline((char *) (const char *) l, l.size());
l.trim();
if (cnf == l)
{
// write paragraph and all variables
_write_paragraph(out);
skip = TRUE; done = TRUE;
}
else
{
if (skip) skip = l[0] != '[';
if (!skip) out << l << '\n';
}
}
// new paragraph
if (!done) _write_paragraph(out);
out.close(); in.close();
while (access(_file, 02) != 0)
message_box("Il file %s e' gia' in uso", (const char*)_file);
/*
TFilename bak(_file); bak.ext("bak");
rename(_file, bak);
*/
fcopy(temp, _file); // Copia dalla tempdir al nuovo .ini
remove(temp); // Cancella file temporaneo
}
void TConfig::set_paragraph(const char* section)
{
if (section != NULL && section != _paragraph)
{
if (_dirty) _write_file();
_paragraph = section;
_dirty = FALSE;
_read_paragraph();
}
}
// @doc EXTERNAL
// @mfunc Controlla se esite una variabile nel paragrafo attivo
//
// @rdesc Ritorna i seguenti valori:
//
// @flag TRUE | Se la variabile esite
// @flag FALSE | Se la variabile non esite
bool TConfig::exist(
const char* var, // @parm Nome della variabile
int index) // @parm Indice dell'elemento dell'array (default -1)
// @comm Se <p index> e' <gt>= 0 viene costruito il nome dell'elemento
// dell'array da cercare, diversamente viene cercata la variabile
// normale passata in <p var>.
{
if (index >= 0)
{
TString80 vvar(var);
vvar << '(' << index << ')';
return _data.is_key(vvar);
}
return _data.is_key(var);
}
// @doc EXTERNAL
// @mfunc Ritorna il valore della variabile nella sezione corrente o in
// quella specificata
//
// @rdesc Ritorna la stringa contenuta nella variabile, se questa esiste, altrimenti
// il valore di default che dovrebbe assumere determinato dal parametro
// <p def>
TString& TConfig::get(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
const char* def) // @parm Valore default della varaibile (default "")
// @comm Passando <p index> <gt>= 0 viene appeso al nome della variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get_long> <mf TConfig::get_int> <mf TConfig::get_bool>
// <mf TConfig::get_color>
{
HIDDEN TString256 s;
const char* v = var;
if (index >= 0) // Mette indice tra parentesi
{
s = var;
s << '(' << index << ')';
v = s;
}
set_paragraph(section);
if (_data.is_key(v))
s = (TString&)_data[v];
else
{
s = def;
if (s.not_empty())
set(var, def, section, TRUE, index);
}
return s;
}
// @doc EXTERNAL
// @mfunc Ritorna il valore della variabile nella sezione corrente o in
// quella specificata
//
// @rdesc Ritorna il numero contenuto nella variabile, se questa esiste, altrimenti
// il valore di default che dovrebbe assumere determinato dal parametro
// <p def>
long TConfig::get_long(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
long def) // @parm Valore default della varaibile (default 0L)
// @comm Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get> <mf TConfig::get_int> <mf TConfig::get_bool>
// <mf TConfig::get_color>
{
const char* n = get(var,section,index);
if (*n)
def = atol(n);
else
{
TString16 d; d << def;
set(var, d, section, TRUE, index);
}
return def;
}
// @doc EXTERNAL
// @mfunc Ritorna il valore della variabile nella sezione corrente o in
// quella specificata
//
// @rdesc Ritorna il primo carattere della variabile, se questa esiste, altrimenti
// il valore di default che dovrebbe assumere determinato dal parametro
// <p def>
char TConfig::get_char(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
char def) // @parm Valore default della varaibile (default ' ')
// @comm Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get> <mf TConfig::get_int> <mf TConfig::get_bool>
// <mf TConfig::get_color>
{
const char* n = get(var,section,index);
if (*n)
def = *n;
else
{
const char d[2] = { def, '\0' };
set(var, d, section, TRUE, index);
}
return def;
}
// @doc EXTERNAL
// @mfunc Ritorna il valore della variabile nella sezione corrente o in
// quella specificata
//
// @rdesc Ritorna l'intero contenuto nella variabile, se questa esiste, altrimenti
// il valore di default che dovrebbe assumere determinato dal parametro
// <p def>
int TConfig::get_int(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
int def) // @parm Valore default della varaibile (default 0)
// @comm Chiama la funzione <mf TConfig::get_long> e ne ritorna un intero.
// <nl>Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get> <mf TConfig::get_long> <mf TConfig::get_bool>
// <mf TConfig::get_color>
{
return (int)get_long(var, section, index, def);
}
// @doc EXTERNAL
// @mfunc Ritorna il valore della variabile nella sezione corrente o in
// quella specificata
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se la varabile e' settata con X
// @flag FALSE | Se la varabile nen e' settata con X
// @flag <p def> | Se la varabile non esiste
bool TConfig::get_bool(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
bool def) // @parm Valore default della varaibile (default FALSE)
// @comm Viene chiamata la funzione <mf TConfig::get>.
// <nl>Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get> <mf TConfig::get_long> <mf TConfig::get_int>
// <mf TConfig::get_color>
{
const TString16 d(def ? "X" : "");
const TString& s = get(var, section, index, d).upper();
return s != "" && (s == "X" || s == "ON" || s == "YES" || s == "OK" || s == "TRUE");
}
HIDDEN void RGB_COLOR(COLOR c, int& r, int& g, int& b)
{
r = int(c >> 16) & 0xFF;
g = int(c >> 8) & 0xFF;
b = int(c) & 0xFF;
}
// @doc EXTERNAL
// @mfunc Ritorna il valore del colore settato nella variabile nella
// sezione corrente o in quella specificata
COLOR TConfig::get_color(
const char* var, // @parm Variabile della quale ritornare il valore
const char* section, // @parm Sezione della varaibile (default NULL)
int index, // @parm Eventuale indice della varaibailie (default -1)
COLOR def) // @parm Valore default della varaibile (default 0)
// @comm Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
//
// @xref <mf TConfig::get> <mf TConfig::get_long> <mf TConfig::get_int>
// <mf TConfig::get_bool>
{
const char* c = get(var, section, index);
if (*c)
{
TToken_string s(c, ',');
const int r = s.get_int();
const int g = s.get_int();
const int b = s.get_int();
def = MAKE_COLOR(r, g, b);
}
else
{
int r, g, b; RGB_COLOR(def, r, g, b);
TString16 d; d << r << ',' << g << ',' << b;
set(var, d, section, TRUE, index);
}
return def;
}
// @doc EXTERNAL
// @mfunc Setta la variabile nella sezione corrente o specificata
//
// @rdesc Ritorna i seguenti valori:
//
// @flag TRUE | Se la variabile era gia' esistente
// @flag FALSE | Se la variabile non era gia' esistente
bool TConfig::set(
const char* var, // @parm Nome della variabile da settare
const char* value, // @parm Stringa da assegnare alla variabile
const char* section, // @parm Nome del paragrafo a cui appartiene la variabile
bool force, // @parm Per la creazione di una variabile inesistente
int index) // @parm Eventuale indice della variabile
// @parm long | value | Valore da assegnare alla variabile
{
// @syntax set(const char* var, const char* value, const char* section, bool force, int index);
// @syntax set(const char* var, long value, const char* section, bool force, int index);
//
// @comm Se <p force> == TRUE crea il paragrafo e la variabile se non esistono;
// altrimenti da' errore.
// <nl>Passando <p index> <gt>= 0 viene appeso al nome variabile per
// implementare un array.
// <nl>Il paragrafo passato in <p section> diventa quello attivo.
set_paragraph(section);
TString vvar(var); if (index != -1) vvar << '(' << index << ')';
bool itwas = _data.is_key(vvar);
if (itwas && !force)
warning_box("Tentativo di ridefinizione simbolo: %s", (const char*)vvar);
else
{
_dirty = TRUE;
_data.add(vvar, new TString(value), force);
}
return itwas;
}
bool TConfig::set(const char* var, long value, const char* section,
bool force, int index)
{
TString16 t; t << value;
return set(var,t,section,force,index);
}
// @doc EXTERNAL
// @mfunc Ritorna quanti elementi dell'array nominato sono presenti nella
// sezione indicata.
word TConfig::items(
const char* var, // @parm Nome dell'array
const char* section) // @parm Sezione indicata
// @comm Il paragrafo passato in <p section> diventa quello attivo.
// <nl>Possono esserci dei "buchi" causati da set() errate
{
set_paragraph(section);
TString vvar(16);
for (int cnt = 0; /* uncazzo */ ;cnt++)
{
vvar = var; vvar << '(' << cnt << ')';
if (!_data.is_key(var))
break;
}
return cnt;
}
// @doc EXTERNAL
// @mfunc Inizializza il paragrafo leggendo dal file i dati
void TConfig::init(
const char *fn, // @parm Nome del file da leggere
const char* pa) // @parm Nome del paragrafo da utilizzare
// @comm Apre il file <p fn> e cerca il paragrafo <p pa>. Se il file non esiste
// viene creato con il paragrafo passato.
{
_file = fn;
_paragraph = pa;
_dirty = FALSE;
if (!fexist(_file))
{
warning_box("Creazione del file di configurazione %s", fn );
ofstream c(fn);
c.close();
}
if (_paragraph.empty())
{
_paragraph = main_app().name();
_paragraph.cut(2);
}
_ispresent = _read_paragraph();
}
int TConfig::list_paragraphs(TString_array& pl)
{
TScanner s(_file);
pl.destroy();
while (s.line().not_empty())
if (s.token()[0] == '[')
{
TToken_string* p = new TToken_string(s.token());
p->strip("[]");
pl.add(p);
}
return pl.items();
}
int TConfig::list_variables(TString_array& vl, bool value, const char* section)
{
set_paragraph(section);
vl.destroy();
_data.restart();
for (int i = 0; i < _data.items(); i++)
{
THash_object* o = _data.get_hashobj();
TToken_string* t = new TToken_string(o->key());
if (value) t->add((TString&)(o->obj()));
vl.add(t);
}
return vl.items();
}
TConfig::TConfig(int which_config, const char* paragraph)
{
switch (which_config)
{
case CONFIG_DITTA:
_file << main_app().get_firm_dir() << '/' << "prassid.ini";
if (!fexist(_file)) fcopy("prassid.ini", _file);
break;
case CONFIG_STUDIO:
case CONFIG_USER:
case CONFIG_STAMPE:
_file = firm2dir(-1); // Directory dati
_file.add("config");
if (!fexist(_file))
make_dir(_file);
switch (which_config)
{
case CONFIG_STUDIO:
_file.add("prassis.ini");
if (!fexist(_file)) fcopy("prassis.ini", _file);
break;
case CONFIG_STAMPE:
_file.add("print.ini");
break;
default:
if (user().not_empty())
_file.add(user());
else
_file.add("prassi");
_file.ext("ini");
break;
}
break;
case CONFIG_FCONV:
_file = "fconv.ini";
break;
case CONFIG_GOLEM:
_file.add("golem.ini");
break;
default:
_file = "prassi.ini";
CHECK(0, "Chi ca$$o usa prassi.ini?");
break;
}
init(_file, paragraph);
}
TConfig::TConfig(const char *fn, const char* pa)
{ init(fn, pa); }
TConfig::~TConfig()
{
// il distruttore riscrive il file con le modifiche se necessario
if (_dirty) _write_file();
}