#include #include #include #include #include #include #include #include #include #include #include const char* TTransaction::build_rowkey(const char * table, int row) const { TString& tmp = get_tmp_string(); tmp << table; if (row > 0) tmp << format(",%03d", row); return tmp; } const char * TTransaction::get_rowkey_logicnum(const TString & var) const { const int pos = var.find(","); if (pos > 0) return var.left(pos); return var; } int TTransaction::get_rowkey_row(const TString & var) const { const int pos = var.find(","); if (pos > 0) return atoi(var.mid(pos + 1)); return 0; } const char* TTransaction::build_varkey(const char* var, int index) const { if (index >= 0) { TString& tmp = get_tmp_string(); tmp << var << '(' << index << ')'; return tmp; } return var; } int TTransaction::get_varkey_index(const TString & var) const { const int pos = var.find(","); if (pos > 0) return atoi(var.mid(pos + 1)); return -1; } const char * TTransaction::get_varkey_name(const TString & var) const { const int pos = var.find(","); if (pos > 0) return var.left(pos); return var; } TTransaction & TTransaction::copy(const TTransaction & t) { _head = t._head; _rows = t._rows; _file = t._file; _type = t._type; _executer = t._executer; return *this; } // @doc EXTERNAL // @mfunc Controlla se esite una variabile // // @rdesc Ritorna i seguenti valori: // // @flag true | Se la variabile esiste // @flag false | Se la variabile non esiste bool TTransaction::exist( const char* var, // @parm Nome della variabile int index, // @parm Indice dell'elemento dell'array (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga // @comm Se

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

. { const char* key = build_varkey(var, index); if (!table || *table == '\0') return _head.is_key(key); else { const char* rowkey = build_rowkey(table, row); TAssoc_array * row_data = (TAssoc_array *)_rows.objptr(rowkey); if (row_data != nullptr) return row_data->is_key(key); } return false; } // @doc EXTERNAL // @mfunc Elimina una variabile // // @rdesc Ritorna i seguenti valori: // // @flag TRUE | Se la variabile esiteva // @flag FALSE | Se la variabile non esiteva bool TTransaction::remove( const char* var, // @parm Nome della variabile int index, // @parm Indice dell'elemento dell'array (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga // @comm Se

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

. { const char* key = build_varkey(var, index); bool ok = false; if (!table || *table == '\0') ok = _head.remove(key); else { const char* rowkey = build_rowkey(table, row); TAssoc_array * row_data = (TAssoc_array *)_rows.objptr(rowkey); if (row_data != nullptr) ok = row_data->remove(key); } return ok; } // @doc EXTERNAL // @mfunc Elimina una serie di variabili dal paragrafo corrente // // @rdesc Ritorna i seguenti valori: // // @flag TRUE | Se la variabile esiteva // @flag FALSE | Se la variabile non esiteva bool TTransaction::remove_array( const char* var, // @parm Nome della variabile const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga // @comm Viene cancellata l'aray di variabili passata in

. { bool ok = false; TString_array arr; TString80 s = var; s << '('; if (!table || *table == '\0') { _head.get_keys(arr); FOR_EACH_ARRAY_ROW(arr, r, str) { if (str->starts_with(s)) { ok = remove(*str, r, nullptr); } } } else { const char* rowkey = build_rowkey(table, row); TAssoc_array * row_data = (TAssoc_array *)_rows.objptr(rowkey); if (row_data != nullptr) { row_data->get_keys(arr); FOR_EACH_ARRAY_ROW(arr, r, str) { if (str->starts_with(s)) ok = remove(*str, r, table); } } } return ok; } void TTransaction::remove_all() { _head.destroy(); _rows.destroy(); } // @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 //

const TString& TTransaction::get( const char* var, // @parm Variabile della quale ritornare il valore int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) const // @parm riga // @comm Passando

= 0 viene appeso al nome della variabile per // implementare un array. // @xref // { const char* key = build_varkey(var, index); const TString* val = nullptr; if (!table || *table == '\0') val = (TString*)_head.objptr(key); else { const char* rowkey = build_rowkey(table, row); TAssoc_array * row_data = (TAssoc_array *)_rows.objptr(rowkey); if (row_data != nullptr) val = (TString*) row_data->objptr(key); } if (val == nullptr) // Se non la trova inserisci il default val = &EMPTY_STRING; return *val; } // @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 TTransaction::get_bool( const char* var, // @parm Variabile della quale ritornare il valore int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) const // @parm riga // @comm Viene chiamata la funzione . // Passando

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

diventa quello attivo. // // @xref // { bool yes = false; TString& s = (TString &) get(var, index, table, row); if (s.full()) { s.upper(); yes = s == "X" || s == "Y" || s == "1" || s == "ON" || s == "YES" || s == "OK" || s == "TRUE"; } return yes; } // @doc EXTERNAL // @mfunc Ritorna il valore del colore settato nella variabile nella // sezione corrente o in quella specificata COLOR TTransaction::get_color( const char* var, // @parm Variabile della quale ritornare il valore int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) const // @parm riga // @comm Passando

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

diventa quello attivo. // // @xref // { TToken_string s(get(var, index, table, row), ','); COLOR col = COLOR_BLACK; if (s.full()) { if (s.find(',') > 0) { const byte r = (byte)s.get_int(); const byte g = (byte)s.get_int(); const byte b = (byte)s.get_int(); col = RGB2COLOR(r, g, b); } else { col = atol(s); if (col == 0L) col = COLOR_BLACK; } } return col; } // @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 TTransaction::set( const char* var, // @parm Nome della variabile da settare const char* value, // @parm Stringa da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { // @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. const char* key = build_varkey(var, index); TString* val = nullptr; bool itwas = false; if (!table || *table == '\0') { val = (TString*)_head.objptr(key); itwas = val != nullptr; if (itwas) { const TFixed_string str(value); // Se la variabile esisteva ed aveva un valore diverso ... if (*val != str && !(str.blank() && val->empty())) { *val = str; // ... allora la sostituisco ... val->trim(); } } else { // Se la variabile non esisteva allora la aggiungo e metto a dirty. val = new TString(value); val->trim(); itwas = _head.add(key, val, true); } } else { const char* rowkey = build_rowkey(table, row); TAssoc_array * row_data = (TAssoc_array *)_rows.objptr(rowkey); if (_executer.blank()) _executer = table; if (row_data == nullptr) _rows.add(rowkey, row_data = new TAssoc_array, true); if (row_data != nullptr) { val = (TString*)row_data->objptr(key); itwas = val != nullptr; if (itwas) { const TFixed_string str(value); // Se la variabile esisteva ed aveva un valore diverso ... if (*val != str && !(str.blank() && val->empty())) { *val = str; // ... allora la sostituisco ... val->trim(); } } else { // Se la variabile non esisteva allora la aggiungo e metto a dirty. val = new TString(value); val->trim(); itwas = row_data->add(key, val, true); } } } return itwas; } bool TTransaction::set( const char* var, // @parm Nome della variabile da settare long value, // @parm Stringa da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { TString16 t; t << value; return set(var, t, index, table, row); } bool TTransaction::set( const char* var, // @parm Nome della variabile da settare real value, // @parm Stringa da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { TString40 t; t << value; return set(var, t, index, table, row); } bool TTransaction::set( const char* var, // @parm Nome della variabile da settare int value, // @parm Stringa da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { TString16 t; t << value; return set(var, t, index, table, row); } bool TTransaction::set( const char* var, // @parm Nome della variabile da settare bool value, // @parm Stringa da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { TString16 t; t << value ? "X" : " "; return set(var, t, index, table, row); } bool TTransaction::set( const char* var, // @parm Nome della variabile da settare COLOR col, // @parm Colore da assegnare alla variabile int index, // @parm Eventuale indice della variabile (default -1) const char * table, // @parm testata(TRANSACTION_HEADER) o tabella/file int row) // @parm riga { TString16 t; t.format("%d,%d,%d", XVT_COLOR_GET_RED(col), XVT_COLOR_GET_GREEN(col), XVT_COLOR_GET_BLUE(col)); return set(var, t, index, table, row); } bool TTransaction::read_ini() { remove_all(); if (_file.exist()) { TConfig cnf(_file, "Transaction"); TString_array paragraphs; cnf.list_paragraphs(paragraphs); FOR_EACH_ARRAY_ROW(paragraphs, r, para) { TAssoc_array & vars = cnf.list_variables(*para); TString table; int row = 0; if (*para != "Transaction") { table = get_rowkey_logicnum(*para); row = get_rowkey_row(*para); } FOR_EACH_ASSOC_OBJECT(vars, obj, k, itm) { const TString key(k); int index = get_varkey_index(key); TString name = get_varkey_name(key); set(name, cnf.get(name, *para, index), index, table, row); } } return true; } return false; } bool TTransaction::read_xml() { remove_all(); if (_file.exist()) { TXmlItem xml; xml.Load(_file); TXmlItem * child = xml.GetChild(0); if (child->GetTag() == "Transaction") { const int nrows = child->GetChildren(); TString_array vars; child->ListAttrs(vars); FOR_EACH_ARRAY_ROW(vars, r, str) { int index = get_varkey_index(*str); TString name = get_varkey_name(*str); set(name, child->GetAttr(*str), index, nullptr); } for(int n = 0; n < nrows; n++) { TXmlItem * child_row = child->GetChild(n); const TString row_name = child_row->GetTag(); TString logicnum = get_rowkey_logicnum(row_name); const int row = get_rowkey_row(row_name); child_row->ListAttrs(vars); FOR_EACH_ARRAY_ROW(vars, r1, str) { int index = get_varkey_index(*str); TString name = get_varkey_name(*str); set(name, child_row->GetAttr(*str), index, logicnum, row); } } } return true; } return false; } void TTransaction::write_ini_row_para(TConfig & cnf, const TString & rowkey, bool exec) { TString_array arr; TAssoc_array & row = *((TAssoc_array *)_rows.objptr(rowkey)); cnf.set_paragraph(rowkey); row.get_keys(arr); FOR_EACH_ARRAY_ROW(arr, r1, str) { int index = get_varkey_index(*str); const TString name = get_varkey_name(*str); cnf.set(name, *((TString *)row.objptr(*str)), nullptr, true, index); } } bool TTransaction::write_ini() { bool ok = _head.items() > 0 && _rows.items(); if (ok) { TString_array arr; TConfig cnf(_file, "Transaction"); TString_array row_arr; _head.get_keys(arr); cnf.set("Version", "2.0"); FOR_EACH_ARRAY_ROW(arr, r, str) { int index = get_varkey_index(*str); const TString name = get_varkey_name(*str); cnf.set(name, *((TString *)_head.objptr(*str)), nullptr, true, index); } _rows.get_keys(row_arr); write_ini_row_para(cnf, _executer); row_arr.sort(); FOR_EACH_ARRAY_ROW(row_arr, r1, rowkey) write_ini_row_para(cnf, *rowkey, false); } else _file.fremove(); return ok; } void TTransaction::write_xml_row_para(TXmlItem & xml, const TString & rowkey, bool exec) { TString_array arr; TAssoc_array & row = *((TAssoc_array *)_rows.objptr(rowkey)); TXmlItem & child = xml.AddChild(rowkey); row.get_keys(arr); FOR_EACH_ARRAY_ROW(arr, r1, str) { TXmlItem & child_row = xml.AddChild(rowkey); row.get_keys(arr); FOR_EACH_ARRAY_ROW(arr, r1, str) child.AddEnclosedText(*str, *((TString *)row.objptr(*str))); } } bool TTransaction::write_xml() { bool ok = _head.items() > 0 && _rows.items(); if (ok) { TString_array arr; TXmlItem xml; TString_array row_arr; TXmlItem & child = xml.AddChild("Transaction"); _head.get_keys(arr); child.AddEnclosedText("Version", "2.0"); FOR_EACH_ARRAY_ROW(arr, r, str) child.AddEnclosedText(*str, *((TString *)_head.objptr(*str))); _rows.get_keys(row_arr); row_arr.sort(); write_xml_row_para(xml, _executer); FOR_EACH_ARRAY_ROW(row_arr, r1, rowkey) write_xml_row_para(xml, *rowkey, false); xml.Save(_file); } else _file.fremove(); return ok; } const char * TTransaction::record_header() const { TString &str = get_tmp_string(2569); int logicnum = atoi(_executer); if (logicnum == 0) logicnum = table2logic(_executer); TToken_string keyfields(prefix().get_keyexpr(logicnum), '+'); str = "Record "; FOR_EACH_STR_TOKEN(keyfields, fld) if (fld.full()) str << fld << " = " << get(fld, -1, _executer) << " "; return str; } bool TTransaction::get_errors(TString_array & errors) const { TString error = get("ErrorMsg", 0, nullptr); errors.destroy(); for (int i = 0; error.full(); error = get("ErrorMsg", ++i, nullptr)) errors.add(error); return errors.items() > 0; } bool TTransaction::get_warnings(TString_array & warnings) const { TString warning = get("WarningMsg", 0, nullptr); warnings.destroy(); for (int i = 0; warning.full(); warning = get("WarningMsg", i++, nullptr)) warnings.add(warning); return warnings.items() > 0; } bool TTransaction::read() { if (_type == ini_transaction) return read_ini(); else return read_xml(); } bool TTransaction::write() { if (_type == ini_transaction) return write_ini(); else return write_xml(); } bool file2app(TString & file ,TString& app) { TString16 appname; appname << "Edit_" << file; app = ini_get_string(CONFIG_INSTALL, "ba7", appname); if (app.empty()) { if (isdigit(file[0])) { const int filenum = atoi(file); if (filenum >= LF_USER && filenum < prefix().items()) { TLocalisamfile isf(filenum); isf.get_relapp(app); } } else { const int len = file.len(); if (len == 3 || (len == 4 && file[0] == '%')) { TTable table(file); table.get_relapp(app); } else if (len >= 4 && file[0] == '&') { TModule_table tabmod(file); tabmod.get_relapp(app); } } } return app.full(); } void execute_transactions(TArray & transactions, TLog_report & log, bool interactive, const char * msg) { TString prog_msg(msg); if (transactions.items() > 0) { TBit_array processed; const int first = transactions.first(); const int last = transactions.last(); while (true) { int i = first; TTransaction t = (TTransaction &)transactions[i]; TString table = t.executer(); int logicnum = atoi(table); while (processed[i]) i++; if (i > last) break; if (table.full()) { TFilename pref = t.name(); pref.ext(""); while (isdigit(pref[pref.len() - 1])) pref.rtrim(1); while (i >= 0) { if (t.executer() == table && t.name().starts_with(pref)) { t.write(); processed.set(i); } i = transactions.succ(i); while (processed[i]) i++; if (i > last) break; t = (TTransaction &)transactions[i]; } TString app; if (file2app(table, app)) { TFilename filemask(pref); TString_array files; filemask << "*" << "." << t.ext(); app << (interactive ? " -i" : " -b") << filemask; if (prog_msg.full()) app << " -m\"" << prog_msg << "\""; app << " -u" << user(); TExternal_app cmd(app); cmd.run(); list_files(filemask, files); FOR_EACH_ARRAY_ROW(files, r, str) { TTransaction t(*str); TString_array msgs; log.log(0, t.record_header()); t.get_warnings(msgs); FOR_EACH_ARRAY_ROW(msgs, nm, msg) log.log(1, *msg); if (t.result_ok()) log.log(0, "Eseguita"); else { t.get_errors(msgs); FOR_EACH_ARRAY_ROW(msgs, nm, msg) log.log(2, *msg); } } remove_files(filemask, false); } else { TString msg(TR("Esecutore sconosciuto per le transazioni sul file ")); msg << (logicnum == 0) ? t.executer() : prefix().description(logicnum); log.log(2, msg); } } } } }