#include #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT #include #else #include #endif #include #include #include #include #include #include #include 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(); if (fexist(_file)) { while (access(_file, 02) != 0) message_box("Il file %s e' gia' in uso", (const char*)_file); } 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

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

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

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 { 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 //

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

= 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 = *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 //

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

| 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 // { 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; } COLOR RGB2COLOR(unsigned char red, unsigned char green, unsigned char blue) { COLOR def = MAKE_COLOR(red, green, blue); // Se nel colore non compare l'indice cerca di calcolarlo const byte color_index = byte(def >> 12); if (color_index < 0x1 || color_index > 0xF) { const COLOR native_color[11] = { COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_CYAN, COLOR_MAGENTA, COLOR_YELLOW, COLOR_BLACK, COLOR_DKGRAY, COLOR_GRAY, COLOR_LTGRAY, COLOR_WHITE }; for (int c = 0; c < 11; c++) { if (def == (native_color[c] & 0x00FFFFFF)) // Confronta solo la terna R,G,B { def = native_color[c]; break; } } } return def; } // @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

= 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 byte r = (byte)s.get_int(); const byte g = (byte)s.get_int(); const byte b = (byte)s.get_int(); def = RGB2COLOR(r, g, b); } else { int r, g, b; RGB_COLOR(def, r, g, b); TString16 d; d.format("%d,%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

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

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 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

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(); } 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(); } const TAssoc_array& TConfig::list_variables(const char* section) { set_paragraph(section); return _data; } 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; case CONFIG_USER: { TString16 u = user(); if (u.blank()) u = "PRASSI"; else u.upper(); _file.add(u); _file.ext("ini"); if (u != "PRASSI" && !fexist(_file)) { TFilename prassi = _file.path(); prassi.add("prassi.ini"); fcopy(prassi, _file); } } break; default: 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(); }