#include #include #include #include #include #include #include #include #include extern "C" { int rename(const char*, const char*); }; // @doc INTERNAL // @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: file %s, vicino alla riga %ud: %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; } // @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); TFixed_string l(__tmp_string, sizeof(__tmp_string)); TString80 cnf; 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(); if (_file[0] > 'B' || _file[1] != ':') // Non creare il .bak su dischetto { 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 } // @doc EXTERNAL void TConfig::set_paragraph(const char* section) { if (section != NULL && section != _paragraph) { if (_dirty) _write_file(); _paragraph = section; _dirty = FALSE; _read_paragraph(); } } // @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

e' = 0 viene costruito il nome dell'elemento // dell'array da cercare, diversamente viene cercata la variabile // normale passata in

. { if (index >= 0) { TString80 vvar(var); vvar << '(' << index << ')'; return _data.is_key(vvar); } return _data.is_key(var); } // @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 //

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

= 0 viene appeso al nome della variabile per // implementare un array. // Il paragrafo passato in

diventa quello attivo. // // @xref // { 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; } // @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 //

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

= 0 viene appeso al nome variabile per // implementare un array. // Il paragrafo passato in

diventa quello attivo. // // @xref // { const char* n = get(var,section,index); if (*n) def = atol(n); else set(var, format("%ld", def), section, TRUE, index); return def; } // @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 //

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 e ne ritorna un intero. // Passando

= 0 viene appeso al nome variabile per // implementare un array. // Il paragrafo passato in

diventa quello attivo. // // @xref // { return (int)get_long(var, section, index, def); } // @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

| 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 . // Passando

= 0 viene appeso al nome variabile per // implementare un array. // Il paragrafo passato in

diventa quello attivo. // // @xref // { if (def) strcpy(__tmp_string, "X"); else *__tmp_string = '\0'; const TString& s = get(var, section, index, __tmp_string).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; } // @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

= 0 viene appeso al nome variabile per // implementare un array. // Il paragrafo passato in

diventa quello attivo. // // @xref // { 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); set(var, format("%d,%d,%d", r, g, b), section, TRUE, index); } return def; } // @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

== TRUE crea il paragrafo e la variabile se non esistono; // altrimenti da' errore. // Passando

= 0 viene appeso al nome variabile per // implementare un array. // Il paragrafo passato in

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); } // @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

diventa quello attivo. // 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 INTERNAL // @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

e cerca il paragrafo

. 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(); } // @doc EXTERNAL 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: _file = "prassis.ini"; break; case CONFIG_USER: case CONFIG_STAMPE: _file = firm2dir(0); if (_file.not_empty()) { for (int i = _file.len()-1; i >= 0; i--) if (_file[i] == '/' || _file[i] == '\\') break; _file.cut(i+1); } _file << "config"; if (!fexist(_file)) make_dir(_file); switch (which_config) { 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"; 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(); }