campo-sirio/include/config.cpp

228 lines
5.5 KiB
C++
Executable File

#include <stdlib.h>
#include <applicat.h>
#include <config.h>
#include <utility.h>
#include <scanner.h>
// questo sara' il principale, per ora non c'e'
#define CONFIG_FILE "prassi.ini"
// file parametri studio (uno per studio, per ora e' il principale)
#define CONFIG_FILE_STUDIO "prassis.ini"
// file parametri ditta (uno per ditta)
#define CONFIG_FILE_DITTA "prassid.ini"
extern "C"
{
int rename(const char*, const char*);
};
bool TConfig::_read_paragraph()
// ritorna TRUE se il paragrafo c'era, FALSE altrimenti
{
bool itwas = FALSE;
_data.destroy();
TScanner scan(_file);
if (scan.paragraph(_paragraph))
{
itwas = TRUE;
// populate array
TString l, key, val;
for (;;)
{
l = scan.line();
if (l[0] == '#') continue;
if (l == "" || l[0] == '[') break;
int ind = l.find('=');
if (ind == -1)
{
warning_box("Errore configurazione: file %s, vicino a riga %ud",
(const char*)_file, scan.linenum());
continue;
}
key = l.left(ind); key.trim();
val = l.mid(ind+1); val.trim();
// sostituzione abilitata
_data.add(key,val,TRUE);
}
}
return itwas;
}
void TConfig::_write_paragraph(ofstream& out)
{
_data.restart();
TString cnf(16);
cnf << '[' << _paragraph << ']';
out << cnf << '\n';
for (int i = 0; i < _data.items(); i++)
{
THash_object* o = _data.get_hashobj();
out << o->key() << "\t= " << (TString&)(o->obj()) << '\n';
}
out << '\n';
}
void TConfig::_write_file()
{
ifstream in(_file);
TFilename temp;
temp.temp("__tmp__.cnf");
ofstream out(temp);
TFixed_string l(__tmp_string, sizeof(__tmp_string));
TString cnf(16);
cnf << '[' << _paragraph << ']';
bool skip = FALSE, done = FALSE;
while (!in.eof())
{
in.getline(__tmp_string,sizeof(__tmp_string)-1);
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();
TFilename bak(_file); bak.ext("bak");
rename(_file,bak);
fcopy(temp,_file);
remove(temp);
}
void TConfig::_check_paragraph(const char* section)
{
if (section != NULL && section != _paragraph)
{
if (_dirty) _write_file();
_paragraph = section;
_dirty = FALSE;
_read_paragraph();
}
}
TString& TConfig::get(const char* var, const char* section, int index)
{
// ritorna valore di variabile nella sezione corrente o in
// quella specificata
static TFixed_string s(__tmp_string, 256);
TString vvar(var); if (index != -1) vvar << '(' << index << ')';
_check_paragraph(section);
if (_data.is_key(vvar))
s = (TString&)_data[vvar];
else
{
#ifdef DBG
error_box("Can't find '%s' in section '%s' of '%s'",
var, (const char*)_paragraph, (const char*)_file);
#endif
s = "";
}
return s;
}
long TConfig::get_long(const char* var, const char* section, int index)
{
return atol(get(var,section,index));
}
bool TConfig::get_bool(const char* var, const char* section, int index)
{
const TString& s = get(var, section, index).upper();
return s != "" && (s == "X" || s == "ON" || s == "YES" || s == "OK" || s == "TRUE");
}
bool TConfig::set(const char* var, const char* value, const char* section,
bool force, int index)
{
// setta variabile nella sezione corrente o specificata
// se force == TRUE crea la variabile se non esiste; altrimenti
// da' errore; ritorna TRUE se la variabile c'era, FALSE diversamente
_check_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)
{
TString t; t << value;
return set(var,t,section,force,index);
}
word TConfig::items(const char* var, const char* section)
{
_check_paragraph(section);
TString vvar(16);
for (int cnt = 0; /* uncazzo */ ;cnt++)
{
vvar = var; vvar << '(' << cnt << ')';
if (!_data.is_key(var))
break;
}
return cnt;
}
TConfig::TConfig(int which_config, const char* paragraph) :
_paragraph(paragraph), _dirty(FALSE), _ispresent(FALSE)
{
if (which_config < CONFIG_STUDIO) _file = CONFIG_FILE;
else
if (which_config == CONFIG_STUDIO) _file = CONFIG_FILE_STUDIO;
else
{
_file.format("%s/%s", MainApp()->get_firm_dir(), CONFIG_FILE_DITTA);
if (!fexist(_file))
{
fcopy(CONFIG_FILE_DITTA, _file);
if (!fexist(_file))
fatal_box("Impossibile aprire la configurazione %s",
which_config < CONFIG_STUDIO ? "generale" :
which_config == CONFIG_STUDIO ? "di studio" : "della ditta");
}
}
if (_paragraph.empty())
{
_paragraph = MainApp()->name();
_paragraph.cut(2);
}
_ispresent = _read_paragraph();
}
TConfig::~TConfig()
{
// il distruttore riscrive il file con le modifiche se necessario
if (_dirty) _write_file();
}