diff --git a/include/alex.cpp b/include/alex.cpp index 18f0cd1f1..ca115103e 100755 --- a/include/alex.cpp +++ b/include/alex.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include @@ -275,7 +274,12 @@ void TAVM_list_window::update() if (var.is_string() && var.as_string()[0] != '#') str.cut(0) << '"' << var.as_string() << '"'; else - str = var.as_string(); + { + if (var.is_null()) + str = "NULL"; + else + str = var.as_string(); + } } else if (co == avm_call_word) { @@ -332,7 +336,13 @@ void TAVM_stack_window::update() if (_stack != NULL) { for (int i = 0; i < _stack->items(); i++) - printat(0, i, _stack->peek(i).as_string()); + { + const TVariant& var = _stack->peek(i); + if (var.is_null()) + printat(0, i, "NULL"); + else + printat(0, i, var.as_string()); + } } } @@ -421,7 +431,7 @@ TMask_field* TAVM_monitor::parse_field(TScanner& scanner) TAVM_monitor::TAVM_monitor() { - read_mask("ba8304", 0, -1); + read_mask("ba8300m", 0, -1); set_handlers(); } @@ -461,10 +471,10 @@ public: const TString& get_last_error() const { return _last_error; } bool compile(istream& instr, TBytecode& bc); - bool execute(const TBytecode& bc, ostream* outstr = NULL); + bool execute(const TBytecode& bc); void do_restart(bool cold); bool do_include(const char* fname); - TVariant& do_fetch(const TString& name); + void do_fetch(const TString& name); void do_add(); void do_store(const TString& name); void set_interactive(bool inter) { _interactive = inter; } @@ -758,7 +768,7 @@ bool TAVM::do_include(const char* fname) } // Mette sullo stack il valore della variabile name -TVariant& TAVM::do_fetch(const TString& name) +void TAVM::do_fetch(const TString& name) { if (name[0] == '#') { @@ -774,7 +784,6 @@ TVariant& TAVM::do_fetch(const TString& name) else _stack.push(NULL_VARIANT); } - return _stack.peek(); } void TAVM::do_add() @@ -960,7 +969,7 @@ void TAVM::execute(const TAVM_op& op) break; case avm_plus_store: { - const TString& name = _stack.pop().as_string(); + const TString name = _stack.pop().as_string(); do_fetch(name); do_add(); do_store(name); @@ -1033,7 +1042,7 @@ void TAVM::execute(const TAVM_op& op) } } -bool TAVM::execute(const TBytecode& cmdline, ostream* outstr) +bool TAVM::execute(const TBytecode& cmdline) { const TBytecode* old_bc = _bc; const int old_ip = _ip; @@ -1043,8 +1052,6 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr) _bc = &cmdline; _ip = 0; - if (outstr != NULL) - _outstr = outstr; while (_bc != NULL) { while (_ip >= _bc->items()) // Fine funzione @@ -1169,9 +1176,9 @@ bool TAlex_virtual_machine::compile(istream& instr, TBytecode& bc) return avm().compile(instr, bc); } -bool TAlex_virtual_machine::execute(const TBytecode& bc, ostream& outstr) +bool TAlex_virtual_machine::execute(const TBytecode& bc) { - return avm().execute(bc, &outstr); + return avm().execute(bc); } bool TAlex_virtual_machine::compile(const char* cmd, TBytecode& bc) @@ -1180,14 +1187,6 @@ bool TAlex_virtual_machine::compile(const char* cmd, TBytecode& bc) return compile(instr, bc); } -bool TAlex_virtual_machine::execute(const TBytecode& bc, TString& outs) -{ - char* buf = outs.get_buffer(); - memset(buf, 0, outs.size()); - ostrstream outstr(buf, outs.size()); - return execute(bc, outstr); -} - void TAlex_virtual_machine::warm_restart() // Ripartenza a caldo { avm().do_restart(false); @@ -1267,6 +1266,12 @@ bool TAlex_virtual_machine::include(const char* fname) return avm().do_include(fname); } +void TAlex_virtual_machine::include_libraries(bool reload) +{ + if (reload || !defined("2DUP")) + include("alex.alx"); +} + void TAlex_virtual_machine::set_interactive(bool inter) { avm().set_interactive(inter); } diff --git a/include/alex.h b/include/alex.h index 83772d311..092009a26 100755 --- a/include/alex.h +++ b/include/alex.h @@ -31,11 +31,14 @@ public: class TBytecode : public TArray { - TString _name; + TString _name, _lib; public: void set_name(const char* name) { _name = name; } const TString& name() const { return _name; } + + void set_library(const char* lib) { _lib = lib; } + const TString& library() const { return _lib; } }; // ALEX = Another Language EXtension @@ -54,13 +57,14 @@ public: virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack); virtual bool get_usr_val(const TString& name, TVariant& var) const; virtual bool set_usr_val(const TString& name, const TVariant& var); + virtual void include_libraries(bool reload = false); const TString& get_last_error() const; bool compile(istream& instr, TBytecode& bc); bool compile(const char* cmd, TBytecode& bc); - bool execute(const TBytecode& bc, ostream& outstr); - bool execute(const TBytecode& bc, TString& outstr); + bool execute(const TBytecode& bc); bool include(const char* fname); + void warm_restart(); void cold_restart(); void set_interactive(bool inter); diff --git a/include/array.cpp b/include/array.cpp index 2e19f7725..35b95af5c 100755 --- a/include/array.cpp +++ b/include/array.cpp @@ -177,26 +177,7 @@ bool TArray::destroy( return _items < old; } - -TArray::TArray(int arraysize) - : _data(NULL), _size(0), _items(0), _next(0) -{ - if (arraysize) - resize(arraysize); -} - -TArray::TArray() - : _data(NULL), _size(0), _items(0), _next(0) -{ -} - -TArray::TArray(const TArray& a) - : _data(NULL), _size(0), _items(0), _next(0) -{ - (*this) = a; -} - -TArray& TArray::operator= (const TArray& a) +void TArray::copy(const TArray& a) { destroy(); if (size() < a.size()) @@ -217,7 +198,29 @@ TArray& TArray::operator= (const TArray& a) } _items = ( int )a.items(); _next = ( int )a._next; - +} + +TArray::TArray(int arraysize) + : _data(NULL), _size(0), _items(0), _next(0) +{ + if (arraysize) + resize(arraysize); +} + +TArray::TArray() + : _data(NULL), _size(0), _items(0), _next(0) +{ +} + +TArray::TArray(const TArray& a) + : _data(NULL), _size(0), _items(0), _next(0) +{ + copy(a); +} + +TArray& TArray::operator= (const TArray& a) +{ + copy(a); return *this; } diff --git a/include/array.h b/include/array.h index 92b715704..73cc370c1 100755 --- a/include/array.h +++ b/include/array.h @@ -112,6 +112,7 @@ protected: // @cmember Modifica la dimensione dell'array. void resize(int newdim); + void copy(const TArray& a); // @access Public Member public: @@ -143,7 +144,6 @@ public: // @cmember Ritorna numero di oggetti nell'array virtual int items( ) const { return _items; } - // @cmember Ritorna il primo elemento dell'array virtual TObject* first_item( ); @@ -168,7 +168,7 @@ public: // @cmember Ritorna l'oggetto nella posizione index TObject* objptr(int index) const ; // @cmember Assegna all'array l'oggetto passato - TArray& operator= (const TArray& a); + TArray& operator=(const TArray& a); // @cmember Rimuove uno o tutti (default) gli elementi virtual bool destroy(int index = -1, bool pack = FALSE); diff --git a/include/expr.cpp b/include/expr.cpp index 346d0279b..41d8a578b 100755 --- a/include/expr.cpp +++ b/include/expr.cpp @@ -422,7 +422,7 @@ void TExpression::eval() case _not: { real & r1 = evalstack.peek_real(); - r1 = (r1 == ZERO) ? 1.0 : 0.0; + r1 = (r1 == ZERO) ? UNO : ZERO; } break; case _equal: diff --git a/include/recarray.cpp b/include/recarray.cpp index aaee71b86..c3d872146 100755 --- a/include/recarray.cpp +++ b/include/recarray.cpp @@ -781,6 +781,24 @@ const TRectype& TDB_cache::get(const char* table, const char* key) return get(file, tabkey); } +const TRectype& TDB_cache::get(const TRectype& curr) +{ + const int num = curr.num(); + if (num == LF_TAB || num == LF_TABCOM) + return get(curr.get("COD"), curr.get("CODTAB")); + + const RecDes& recd = *curr.rec_des(); // Descrizione del record della testata + const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave + TToken_string key; + for (int i = 0; i < kd.NkFields; i++) // Riempie la chiave selezionata + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd.Fd[nf]; + key.add(curr.get(rf.Name)); + } + return get(num, key); +} + bool TDB_cache::discard(int file, const char* key) { return rec_cache(file).discard(key); diff --git a/include/recarray.h b/include/recarray.h index 5c645c6e1..d4d626cd1 100755 --- a/include/recarray.h +++ b/include/recarray.h @@ -228,7 +228,7 @@ public: const TString& get(const char* chiave, const char* campo); // @cmember ritorna il record con una determinata chiave numerica const TRectype& get(long chiave); - const TString& get(long chiave, const char* campo) ; + const TString& get(long chiave, const char* campo); TRecord_cache(int num, int key = 1); TRecord_cache(TLocalisamfile *f, int key = 1); @@ -252,6 +252,7 @@ public: const TRectype& get(int file, long key) { return rec_cache(file).get(key); } const TRectype& get(const char* table, const char* key); + const TRectype& get(const TRectype& key); const TString& get(int file, const char* key, const char * campo) { return get(file, key).get(campo); } diff --git a/include/recset.cpp b/include/recset.cpp index cebe40166..e5a727a5a 100755 --- a/include/recset.cpp +++ b/include/recset.cpp @@ -104,9 +104,9 @@ TDate TVariant::as_date() const { if (_type == _datefld) return *(TDate*)_ptr; - - const TDate d(as_int()); - return d; + if (_type == _intfld || _type == _realfld) + return TDate(as_int()); + return TDate(as_string()); } long TVariant::as_int() const @@ -127,7 +127,7 @@ bool TVariant::as_bool() const { bool ok = false; if (_type == _alfafld) - ok = strchr("XY", as_string()[0]) != NULL; + ok = strchr("1XY", as_string()[0]) != NULL; else ok = as_int() != 0; return ok; @@ -323,15 +323,16 @@ int TTable_names::logic_num(const TString& name) if (name[0] == '%' && name.len() == 4) return LF_TABCOM; - if (name.len() == 3) - return LF_TAB; - TString* str = (TString*)_names.objptr(name); if (str == NULL) { fill(); str = (TString*)_names.objptr(name); } + + if (str == NULL && name.len() == 3) + return LF_TAB; + return str == NULL ? 0 : atoi(*str); } @@ -1808,7 +1809,7 @@ const TVariant& TISAM_recordset::get(int logic, const char* fldname) const name.cut(colon); } - const TRectype& rec = _relation->curr(logic); + const TRectype& rec = relation()->curr(logic); const TFieldtypes ft = rec.type(name); if (ft == _nullfld) @@ -1897,22 +1898,9 @@ const TRecordset_column_info& TISAM_recordset::column_info(size_t i) const return (const TRecordset_column_info&)_column[i]; } -TRecnotype TISAM_recordset::current_row() const +TCursor* TISAM_recordset::cursor() const { - return _cursor != NULL ? _cursor->pos() : -1; -} - -bool TISAM_recordset::ask_variables(bool all) -{ - bool ok = TRecordset::ask_variables(all); - if (ok) - reset(); - return ok; -} - -TRecnotype TISAM_recordset::items() const -{ - if (_cursor == NULL) + if (_cursor == NULL && !_use.blank()) { TString use; parsed_text(use); TPerformance_profiler prof("ISAM query"); @@ -1929,24 +1917,49 @@ TRecnotype TISAM_recordset::items() const _cursor->freeze(); } } + return _cursor; +} - return _cursor != NULL ? _cursor->items() : 0; +TRelation* TISAM_recordset::relation() const +{ + cursor(); + return _relation; +} + +TRecnotype TISAM_recordset::current_row() const +{ + TCursor* c = cursor(); + return c != NULL ? c->pos() : -1; +} + +bool TISAM_recordset::ask_variables(bool all) +{ + bool ok = TRecordset::ask_variables(all); + if (ok) + reset(); + return ok; +} + +TRecnotype TISAM_recordset::items() const +{ + TCursor* c = cursor(); + return c != NULL ? c->items() : -1; } unsigned int TISAM_recordset::columns() const { - if (_cursor == NULL) - items(); + cursor(); return _column.items(); } bool TISAM_recordset::move_to(TRecnotype pos) { - bool ok = _cursor != NULL; + TCursor* c = cursor(); + bool ok = c != NULL; if (ok) { - *_cursor = pos; + *c = pos; ok = pos >= 0 && pos < items(); } return ok; diff --git a/include/recset.h b/include/recset.h index 4b9c1ab45..499065e0e 100755 --- a/include/recset.h +++ b/include/recset.h @@ -1,12 +1,8 @@ #ifndef __RECORDSET_H #define __RECORDSET_H -#ifndef __ASSOC_H -#include -#endif - -#ifndef __RECTYPES_H -#include +#ifndef __ISAM_H +#include #endif #ifndef __SHEET_H @@ -178,9 +174,12 @@ class TISAM_recordset : public TRecordset TArray _column; // Column infos protected: + TCursor* cursor() const; + TRelation* relation() const; + void reset(); TVariant& get_tmp_var() const; - const TVariant& get(int logic, const char* field) const; + virtual const TVariant& get(int logic, const char* field) const; public: void set(const char* use); diff --git a/include/relation.cpp b/include/relation.cpp index 6a2a42c3f..8c42a0820 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -605,8 +605,7 @@ int TRelation::position_rels( TString expr(80); // Stringa di lavoro per la valutazione delle espressioni _errors = NOERR; - - + const int primo = first < 0 ? 0 : first; const int ultimo = first < 0 && (-first) < _reldefs.items() ? -first : _reldefs.items(); @@ -615,10 +614,12 @@ int TRelation::position_rels( { TRelationdef& rd = reldef(i); + if (primo > 0 && rd.link() < primo) + continue; // Inutile spostare file collegati a record precedenti + TLocalisamfile& from = file(rd.num()); TLocalisamfile& to = file(rd.link()); from.zero(); // Azzera il record corrente (tutti se TSortedfile) - if (to.curr().empty()) continue; diff --git a/include/report.cpp b/include/report.cpp index 514cd454f..556398232 100755 --- a/include/report.cpp +++ b/include/report.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -150,32 +151,7 @@ TReport_font::~TReport_font() /////////////////////////////////////////////////////////// // TReport_expr /////////////////////////////////////////////////////////// - -class TReport_expr : public TExpression -{ - TReport& _report; - TVariant _var; - -protected: - virtual int parse_user_func(const char* name, int nparms) const; - virtual void evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const; - bool is_numeric(const char* str) const; - -public: - TReport_expr(TReport& rep, const char* exp); - const TVariant& as_variant(TFieldtypes ft); -}; - -int TReport_expr::parse_user_func(const char* name, int nparms) const -{ - return -1; -} - -void TReport_expr::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const -{ -} - -bool TReport_expr::is_numeric(const char* str) const +static bool is_a_number(const char* str) { if (str == NULL || *str == '\0' || *str == '0') return false; // Se comincia per zero va preservato! @@ -194,6 +170,29 @@ bool TReport_expr::is_numeric(const char* str) const return true; } +class TReport_expr : public TExpression +{ + TReport& _report; + TVariant _var; + +protected: + virtual int parse_user_func(const char* name, int nparms) const; + virtual void evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const; + +public: + TReport_expr(TReport& rep, const char* exp); + const TVariant& as_variant(TFieldtypes ft); +}; + +int TReport_expr::parse_user_func(const char* name, int nparms) const +{ + return -1; +} + +void TReport_expr::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const +{ +} + const TVariant& TReport_expr::as_variant(TFieldtypes ft) { set_type(ft == _alfafld || ft == _nullfld ? _strexpr : _numexpr); @@ -251,7 +250,7 @@ TReport_image_cache::TReport_image_cache() : TCache(7) void advanced_draw_rect(TWindow& win, const RCT& r, int border, COLOR fore, COLOR back) { const bool has_pen = border > 0; - const bool has_brush = color_distance(back, COLOR_WHITE) != 0; + const bool has_brush = (back & 0xFFFFFF) != (COLOR_WHITE & 0xFFFFFF); if (has_pen || has_brush) { if (has_pen) @@ -491,7 +490,7 @@ TPoint TReport_section::compute_size() const for (int i = 0; i < items(); i++) { const TReport_field& rf = field(i); - if (rf.shown()) + if (rf.active() && rf.shown()) { const TRectangle r = rf.get_draw_rect(); if (_size.x <= 0 && r.right() > s.x) // Richiesto calcolo larghezza @@ -528,7 +527,7 @@ void TReport_section::draw(TWindow& win, TReport_draw_mode rdm) const bool TReport_section::load_fields() { - const bool ok = active() || shown(); + const bool ok = active(); if (ok) { for (int i = 0; i < items(); i++) @@ -545,12 +544,11 @@ bool TReport_section::execute_prescript() bool ok = true; if (active()) { - TString80 str; if (items() > 0) report().set_curr_field(&field(0)); else report().set_curr_field(NULL); - ok = _prescript.execute(report(), str); + ok = _prescript.execute(report()); } for (int i = 0; i < items(); i++) { @@ -569,10 +567,7 @@ bool TReport_section::execute_postscript() f.execute_postscript(); } if (active()) - { - TString80 str; - ok = _postscript.execute(report(), str); - } + ok = _postscript.execute(report()); return ok; } @@ -597,6 +592,8 @@ void TReport_section::save(TXmlItem& root) const item.SetAttr("hidden_if_needed", hidden_if_needed()); item.SetAttr("pagebreak", _page_break); item.SetAttr("keep_with_next", keep_with_next()); + if (condition().not_empty()) + item.AddChild("condition") << condition(); if (grouped_by().not_empty()) item.AddChild("groupby") << grouped_by(); if (has_font()) @@ -627,6 +624,16 @@ void TReport_section::load(const TXmlItem& sec) if (font.load(sec)) set_font(font); + if (level() > 0) + { + const TXmlItem* cnd = sec.FindFirstChild("condition"); + if (cnd != NULL) + { + TString str; + cnd->GetEnclosedText(str); + set_condition(str); + } + } if (level() > 1) { const TXmlItem* gb = sec.FindFirstChild("groupby"); @@ -698,13 +705,6 @@ TString& TReport_script::translate_message(TReport& rep) const { cmd = msg.left(comma); args = msg.mid(comma+1); - if (args[0] != '#') // Controlla se c'e' bisogno di un # all'inizio - { - char type; - int level, id; - if (rep.parse_field(args.get(0), type, level, id) >= 2) - args.insert("#"); - } } else { @@ -718,8 +718,25 @@ TString& TReport_script::translate_message(TReport& rep) const if (rep.defined(cmd)) { TString& alx = msg_empty ? empty_alex : alex; + TString arg; for (int i = args.items()-1; i >= 0; i--) - alx << args.get(i) << ' '; + { + arg = args.get(i); + // Controlla se c'e' bisogno di un # all'inizio + if (arg[0] != '#' && arg[0] != '"' && !is_a_number(arg)) + { + char type; + int level, id; + if (i == 0 && rep.parse_field(arg, type, level, id) >= 3) + arg.insert("#"); + else + { + arg.insert("\""); + arg << '"'; + } + } + alx << arg << ' '; + } alx << cmd << ' '; } else @@ -774,7 +791,7 @@ bool TReport_script::compile(TReport& rep) return good; } -bool TReport_script::execute(TReport& rep, TString& output) +bool TReport_script::execute(TReport& rep) { bool good = true; if (ok()) @@ -782,7 +799,7 @@ bool TReport_script::execute(TReport& rep, TString& output) if (_bc == NULL) good = compile(rep); if (good) - good = rep.execute(*_bc, output); + good = rep.execute(*_bc); } return good; } @@ -792,10 +809,9 @@ bool TReport_script::execute(TReport_field& rf) bool good = true; if (ok()) { - TString str; TReport& rep = rf.section().report(); rep.set_curr_field(&rf); - good = execute(rep, str); + good = execute(rep); } return good; } @@ -862,20 +878,21 @@ void TReport_field::offset(const TPoint& pt) void TReport_field::set_draw_pos(long x, long y) { - _rct_draw.x = x; - _rct_draw.y = y; + _draw_rct.x = x; + _draw_rct.y = y; } void TReport_field::set_draw_size(long w, long h) { - _rct_draw.set_width(w); - _rct_draw.set_height(h); + _draw_rct.set_width(w); + _draw_rct.set_height(h); } void TReport_field::compute_draw_rect() const { - TRectangle& rct = ((TReport_field*)this)->_rct_draw; - rct = get_rect(); + TRectangle& rct = ((TReport_field*)this)->_draw_rct; + rct = _rct; + if (type() == 'S') { if (rct.width() <= 0) @@ -1044,11 +1061,16 @@ bool TReport_field::load_field() } else section().report().evaluate(_field, _var, ft); + + if (_var.is_empty() && _alt_field.not_empty()) + section().report().evaluate(_alt_field, _var, ft); } else _var.set_null(); } - compute_draw_rect(); + _draw_rct = _rct; + _draw_hidden = _hidden; + _draw_deactivated = _deactivated; return ok; } @@ -1056,14 +1078,17 @@ bool TReport_field::load_field() bool TReport_field::execute_prescript() { bool ok = true; - if (active()) + if (!draw_deactivated()) + { ok = _prescript.execute(*this); + compute_draw_rect(); + } return ok; } bool TReport_field::execute_postscript() { - return deactivated() || _postscript.execute(*this); + return draw_deactivated() || _postscript.execute(*this); } void TReport_field::draw_rect(TWindow& win) const @@ -1089,6 +1114,7 @@ void TReport_field::draw_text(TWindow& win, const char* text, TReport_draw_mode xvt_font_copy(lnkfont, font().get_xvt_font(win), XVT_FA_ALL); xvt_font_set_style(lnkfont, XVT_FS_UNDERLINE); xvt_dwin_set_font(win.win(), lnkfont); + xvt_font_destroy(lnkfont); win.set_color(link_color(), back_color()); } else @@ -1097,7 +1123,7 @@ void TReport_field::draw_text(TWindow& win, const char* text, TReport_draw_mode win.set_color(fore_color(), back_color()); } - if (rct.height() > 100) + if (rct.height() > 100) // Devo scrivere piu' righe? { const unsigned columns = rct.width() / 100; int rows = rct.height() / 100; @@ -1199,13 +1225,22 @@ const TString& TReport_field::formatted_text() const case 'P': case 'V': { - TString& tmp = get_tmp_string(); TCurrency cur; get_currency(cur); + TString& tmp = get_tmp_string(); tmp = cur.string(true); return tmp; } break; default: + if (_picture.not_empty()) + { + TString& tmp = get_tmp_string(); + if (_picture.find('#') >= 0) + tmp.picture(_picture, _var.as_string()); + else + tmp << _picture << ' ' << _var.as_string(); + return tmp; + } return _var.as_string(); } return EMPTY_STRING; @@ -1213,15 +1248,11 @@ const TString& TReport_field::formatted_text() const void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const { - if (rdm != rdm_edit && (hidden() || deactivated())) - return; - - if (rdm == rdm_edit) - compute_draw_rect(); - PAT_STYLE back_pattern = PAT_HOLLOW; + if (rdm == rdm_edit) { + compute_draw_rect(); if (hidden() || deactivated()) { if (hidden() && deactivated()) @@ -1230,6 +1261,11 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const back_pattern = hidden() ? PAT_FDIAG : PAT_BDIAG; } } + else + { + if (draw_hidden() || draw_deactivated()) + return; + } switch (_type) { @@ -1343,7 +1379,7 @@ void TReport_field::set_groups(const TString& groups) const TString& TReport_field::groups() const { TString& str = get_tmp_string(); - str << _groups; + str << _groups; str.trim(); return str; } @@ -1367,7 +1403,7 @@ void TReport_field::save(TXmlItem& root) const set_num_attr(fld, "height", rct.height(), 100); fld.SetAttr("hidden", _hidden); fld.SetAttr("deactivated", _deactivated); - fld.SetAttr("zeroes_hidden", _hide_zeroes); + fld.SetAttr("hide_zero", _hide_zeroes); set_col_attr(fld, "bg_color", back_color(), COLOR_WHITE); set_col_attr(fld, "fg_color", fore_color(), COLOR_BLACK); if (has_font()) @@ -1394,6 +1430,8 @@ void TReport_field::save(TXmlItem& root) const fld.SetAttr("link", link()); if (field().not_empty()) fld.AddChild("source") << field(); + if (alternate_field().not_empty()) + fld.AddChild("alt_source") << alternate_field(); _prescript.save(fld, "prescript"); _postscript.save(fld, "postscript"); @@ -1421,10 +1459,10 @@ bool TReport_field::load(const TXmlItem& fld) set_row(get_num_attr(fld, "y")); set_width(get_num_attr(fld, "width")); set_height(get_num_attr(fld, "height", 100)); - _rct_draw = _rct; + _draw_rct = _rct; show(!fld.GetBoolAttr("hidden")); activate(!fld.GetBoolAttr("deactivated")); - hide_zeroes(fld.GetBoolAttr("zeroes_hidden")); + hide_zeroes(fld.GetBoolAttr("hide_zero")); set_border(fld.GetIntAttr("border")); set_back_color(get_col_attr(fld, "bg_color", COLOR_WHITE)); set_fore_color(get_col_attr(fld, "fg_color", COLOR_BLACK)); @@ -1505,7 +1543,7 @@ TReport_field::TReport_field(TReport_section* sec) { set_pos(0,0); set_size(1600,100); - _rct_draw = _rct; + _draw_rct = _rct; } TReport_field::TReport_field(const TReport_field& rf) : _font(NULL) @@ -1667,19 +1705,27 @@ int TReport::parse_field(const char* code, char& type, int& level, int& id) cons if (isdigit(code[0]) || strncmp(code, "THIS", 4) == 0) // Niente sezione davanti { + if (strchr(code, '.') != NULL) + return 0; // Mi sono confuso con un a campo su file, es: 34.CODART + TReport_field* rf = curr_field(); if (rf != NULL) { type = rf->section().type(); level = rf->section().level(); } - id = atoi(code); + if (code[0] == 'T') + id = rf->id(); + else + id = atoi(code); } else { type = code[0]; if (type != 'H' && type != 'B' && type != 'F') // Non comincia con un codice sezione return 0; + if (!isdigit(code[1])) // Non c'e' il livello + return 0; level = atoi((const char*)code + 1); TReport_section* sec = find_section(type, level); @@ -1724,7 +1770,7 @@ bool TReport::evaluate(const char* expr, TVariant& var, TFieldtypes force_type) if (e.numvar() == 1) { const TFixed_string name(e.varname(0)); - if (name == expr) + if (name == expr) { if (get_usr_val(name, var)) { @@ -1807,17 +1853,28 @@ bool TReport::load(const char* fname) } _include = xml.GetAttr("libraries"); - FOR_EACH_TOKEN(_include, lib) - { - TFilename libname = lib; - libname.trim(); - if (libname.find('.') < 0) - libname.ext("alx"); - include(libname); - } + include_libraries(); _prescript.load(xml, "prescript"); _postscript.load(xml, "postscript"); + + _params.destroy(); + const TXmlItem* params = xml.FindFirstChild("parameters"); + if (params != NULL) + { + TToken_string tok, str; + for (int i = 0; i < params->GetChildren(); i++) + { + const TXmlItem* item = params->GetChild(i); + tok = item->GetAttr("name"); + if (!tok.blank()) + { + item->GetEnclosedText(str); + tok.add(str); + _params.add(tok); + } + } + } } return ok; } @@ -1854,6 +1911,17 @@ bool TReport::save(const char* fname) const _prescript.save(xml, "prescript"); _postscript.save(xml, "postscript"); + if (_params.items() > 0) // Salva lista dei parametri se necessario + { + TXmlItem& params = xml.AddChild("parameters"); + FOR_EACH_ARRAY_ROW(_params, i, str) if (!str->empty_items()) + { + TXmlItem& item = params.AddChild("item"); + item.SetAttr("name", str->get(0)); + item << str->get(); + } + } + xml.Save(fname); } return ok; @@ -1892,8 +1960,7 @@ bool TReport::execute_prescript() warm_restart(); if (_prescript.ok()) { - TString80 str; - ok = _prescript.execute(*this, str); + ok = _prescript.execute(*this); if (recordset() != NULL) recordset()->ask_variables(false); } @@ -1919,8 +1986,7 @@ bool TReport::execute_prescript() bool TReport::execute_postscript() { - TString80 str; - return _postscript.execute(*this, str); + return _postscript.execute(*this); } bool TReport::get_report_field(const TString& name, TVariant& var) const @@ -2016,8 +2082,8 @@ size_t TReport::get_usr_words(TString_array& words) const const char* const name[] = { "***", "DISABLE", "ENABLE", "GET_POS", - "GET_SIZE", "HIDE", "RUN_FORM", "SET_BACK_COLOR", "SET_FORE_COLOR", - "SET_POS", "SET_SIZE", "SHOW", NULL + "GET_SIZE", "HIDE", "ISAM_READ", "RUN_FORM", "SET_BACK_COLOR", "SET_FORE_COLOR", + "SET_POS", "SET_SIZE", "SHOW", "TABLE_READ", NULL }; size_t i; for (i = 0; name[i] != NULL; i++) @@ -2026,10 +2092,10 @@ size_t TReport::get_usr_words(TString_array& words) const } static void do_show(TReport_field& rf, void* jolly) -{ rf.show(jolly != NULL); } +{ rf.set_draw_hidden(jolly == NULL); } static void do_enable(TReport_field& rf, void* jolly) -{ rf.activate(jolly != NULL); } +{ rf.set_draw_deactivated(jolly == NULL); } static void do_set_pos(TReport_field& rf, void* jolly) { @@ -2144,6 +2210,95 @@ KEY TReport::run_form(const TString& maskname) return key; } +void TReport::do_isam_read_output(const TRectype& file, TToken_string& out) +{ + TVariant var; + TString curr; + FOR_EACH_TOKEN(out, tok) + { // scansione sugli elementi dell'output + curr = tok; + int posrv = 0; + const int poseq= curr.find('='); // divide la stringa corrente in lvalue e rvalue + if (poseq > 0) + { + posrv = poseq+1; + if (curr[posrv] == '=') + posrv++; + } + if (poseq < 0) + { + const TFieldref fr(curr, 0); + const TVariant var = fr.read(file); // preleva il nome del campo del file e lo legge dal record + curr_field()->set(var); // setta il campo corrente + } + else + { + const TString& fld = curr.left(poseq); // preleva il nome del campo del form alla sinistra dell'uguale + TReport_field* dest = field(fld); + if (dest != NULL) + { + const TFieldref fr(curr.mid(posrv), 0); + const TVariant var = fr.read(file); // preleva il nome del campo del file e lo legge dal record + dest->set(var); // setta il campo corrente + } + } + } +} + +void TReport::msg_isam_read(TVariant_stack& stack) +{ + const TString& f_code = stack.pop().as_string(); // prende il codice del file da leggere + const int logicnum = table2logic(f_code); + if (logicnum < LF_USER) + return; // File sconosciuto + + TRectype keyrec(logicnum); + if (logicnum == LF_TAB || logicnum == LF_TABCOM) + keyrec.put("COD", f_code); + + TToken_string in(stack.pop().as_string(), '!'); + TVariant var; + TString curr; + + FOR_EACH_TOKEN(in, tok) + { // scansione sugli elementi dell'input + curr = tok; + const int poseq= curr.find('='); // divide la stringa corrente in lvalue e rvalue + int posrv = poseq+1; + if (curr[posrv] == '=') + posrv++; + + evaluate(curr.mid(posrv), var, _alfafld); + const TString& fld = curr.left(poseq); // preleva il nome del campo del file alla sinistra dell'uguale + keyrec.put(fld, var.as_string()); // scrive il risultato dell'espressione nel campo del file + } + + const TRectype& file = cache().get(keyrec); + if (!file.empty()) + { + TToken_string out(stack.pop().as_string(), '!'); + do_isam_read_output(file, out); + } +} + +void TReport::msg_table_read(TVariant_stack& stack) +{ + const TString& t_code = stack.pop().as_string(); // prende il codice della tabella da leggere + const int logicnum = table2logic(t_code); + if (logicnum == LF_TAB || logicnum == LF_TABCOM) + { + const TString& codtab = stack.pop().as_string(); + TVariant var; + evaluate(codtab, var, _alfafld); + const TRectype& file = cache().get(t_code, var.as_string()); + if (!file.empty()) + { + TToken_string out(stack.pop().as_string(), '!'); + do_isam_read_output(file, out); + } + } +} + bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack) { switch (opcode) @@ -2183,26 +2338,29 @@ bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack) case 6: // HIDE do_message(stack.pop(), do_show, NULL); break; - case 7: // RUN_FORM + case 7: // ISAM_READ + msg_isam_read(stack); + break; + case 8: // RUN_FORM { const TString& msk = stack.pop().as_string(); const KEY key = run_form(msk); stack.push(key); } break; - case 8: // SET_BACK_COLOR + case 9: // SET_BACK_COLOR { const COLOR rgb = stack.pop().as_color(); do_message(stack.pop(), do_set_back_color, (void*)rgb); } break; - case 9: // SET_FORE_COLOR + case 10: // SET_FORE_COLOR { const COLOR rgb = stack.pop().as_color(); do_message(stack.pop(), do_set_fore_color, (void*)rgb); } break; - case 10: // SET_POS + case 11: // SET_POS { const TVariant& fld = stack.pop(); const real y = stack.pop().as_real() * CENTO; @@ -2211,7 +2369,7 @@ bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack) do_message(fld, do_set_pos, (void*)&pt); } break; - case 11: // SET_SIZE + case 12: // SET_SIZE { const TVariant& fld = stack.pop(); const real h = stack.pop().as_real() * CENTO; @@ -2220,9 +2378,12 @@ bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack) do_message(fld, do_set_size, (void*)&sz); } break; - case 12: // SHOW + case 13: // SHOW do_message(stack.pop(), do_show, (void*)1); break; + case 14: // TABLE_READ + msg_table_read(stack); + break; default: return false; } @@ -2248,12 +2409,24 @@ bool TReport::on_link(const TReport_link& lnk) return false; } +void TReport::include_libraries(bool reload) +{ + TAlex_virtual_machine::include_libraries(reload); + if (reload || !defined("MESSAGE_ALIGN")) + include("report.alx"); + FOR_EACH_TOKEN(_include, lib) + { + TFilename libname = lib; + libname.trim(); + if (libname.find('.') < 0) + libname.ext("alx"); + include(libname); + } +} + TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL), _include(15, ',') { _expressions.set_report(this); - - include("report.alx"); // Include base libraries - _prescript.set_description("PRESCRIPT"); _postscript.set_description("POSTSCRIPT"); } diff --git a/include/report.h b/include/report.h index bc74d98b3..d17ef299d 100755 --- a/include/report.h +++ b/include/report.h @@ -117,7 +117,7 @@ public: void set_description(const char* d) { _desc = d; } bool compile(TReport& report); - bool execute(TReport& report, TString& output); + bool execute(TReport& report); bool execute(TReport_field& rf); void save(TXmlItem& root, const char* tag) const; @@ -143,7 +143,7 @@ class TReport_section : public TArray int _level; // 0,1,2,... TPoint _pos; // Posizione assoluta in centesimi, default (0,0) TPoint _size; // Dimensioni in centesimi, default (0,0) - TString _groupby; + TString _condition, _groupby; bool _page_break, _hidden_if_needed, _keep_with_next; bool _hidden, _deactivated; TReport_script _prescript, _postscript; @@ -179,9 +179,12 @@ public: bool page_break() const { return _page_break; } void force_page_break(bool pb) { _page_break = pb; } + const TString& condition() const { return _condition; } + void set_condition(const char* str) { _condition = str; } + const TString& grouped_by() const { return _groupby; } void group_by(const char* gb) { _groupby = gb; } - + bool hidden_if_needed() const { return _hidden_if_needed; } void hide_if_needed(bool h) { _hidden_if_needed = h; } bool keep_with_next() const { return _keep_with_next; } @@ -222,12 +225,13 @@ class TReport_field : public TSortable TReport_section* _section; int _id; char _type; // Text, String, Numeric, Price, Valuta, Date, Line, Rectangle, Image - TRectangle _rct, _rct_draw; // In centesimi + TRectangle _rct; // In centesimi COLOR _fgcolor, _bgcolor; short _border; char _halign, _valign; TBit_array _groups; - TString _picture, _field, _codval, _link; + TString _picture, _codval, _link; + TString _field, _alt_field; TVariant _var; TReport_script _prescript, _postscript; TToken_string _list; // Elementi di un campo lista @@ -235,6 +239,9 @@ class TReport_field : public TSortable TReport_font* _font; bool _hidden, _deactivated, _hide_zeroes, _selected; + TRectangle _draw_rct; // In centesimi + bool _draw_hidden, _draw_deactivated; + protected: virtual const char* class_name() const { return "ReportField"; } virtual int compare(const TSortable& s) const; @@ -261,6 +268,9 @@ public: const TString& field() const { return _field; } void set_field(const char* str) { _field = str; } + + const TString& alternate_field() const { return _alt_field; } + void set_alternate_field(const char* str) { _alt_field = str; } const TVariant& get() const { return _var; } void set(const char* str); @@ -286,10 +296,6 @@ public: void set_height(long dy) { _rct.set_height(dy); } const TRectangle& get_rect() const { return _rct; } - void set_draw_pos(long x, long y); - void set_draw_size(long x, long y); - const TRectangle& get_draw_rect() const { return _rct_draw; } - bool hidden() const { return _hidden; } bool shown() const { return !hidden(); } void show(bool on) { _hidden = !on; } @@ -301,6 +307,15 @@ public: bool zeroes_hidden() const { return _hide_zeroes; } void hide_zeroes(bool hz) { _hide_zeroes = hz; } + bool draw_hidden() const { return _draw_hidden; } + bool draw_deactivated() const { return _draw_deactivated; } + void set_draw_hidden(bool h) { _draw_hidden = h; } + void set_draw_deactivated(bool d) { _draw_deactivated = d; } + + void set_draw_pos(long x, long y); + void set_draw_size(long x, long y); + const TRectangle& get_draw_rect() const { return _draw_rct; } + void set_groups(const TString& groups); const TString& groups() const; bool in_group(int group) const; @@ -376,6 +391,7 @@ class TReport : public TAlex_virtual_machine int _lpi; // Lines per inch TToken_string _include; TReport_script _prescript, _postscript; + TString_array _params; TRecordset* _recordset; TReport_expr_cache _expressions; TReport_image_cache _images; @@ -391,6 +407,10 @@ protected: KEY run_form(const TString& msk); bool do_message(const TVariant& var, FLDMSG_FUNC msg, void* jolly); + + void do_isam_read_output(const TRectype& rec, TToken_string& out); + void msg_isam_read(TVariant_stack& stack); + void msg_table_read(TVariant_stack& stack); void build_section_key(char type, int level, TString& key) const; short get_num_attr(const TXmlItem& item, const char* attr, short def = 0) const; @@ -430,8 +450,12 @@ public: bool execute_prescript(); bool execute_postscript(); + const TString_array& params() const { return _params; } + void set_params(const TString_array& p) { _params = p; } + void set_libraries(const char* inc) { _include = inc; } TToken_string& get_libraries() { return _include; } + virtual void include_libraries(bool reload = false); void set_description(const char* d) { _description = d; } const TString& description() const { return _description; } diff --git a/include/reprint.cpp b/include/reprint.cpp index 7acf549d5..78c7ce582 100755 --- a/include/reprint.cpp +++ b/include/reprint.cpp @@ -732,6 +732,16 @@ long TReport_printer::print_section(TReport_section& rs) return 0; rs.load_fields(); + + // Non sono sicuro se vada prima di load_fields o dopo execute_prescript + if (rs.condition().not_empty()) + { + TVariant var; + _report.evaluate(rs.condition(), var, _nullfld); + if (!var.as_bool()) + return 0; + } + rs.execute_prescript(); const long height = rs.compute_size().y; // Compute size after the initilization script! @@ -842,7 +852,7 @@ bool TReport_printer::print_loop() _delta.y += print_section('H', g); } } - + // Stampa di tutti i body for (int b = 1; b <= max_body; b++) { const int dy = print_section('B', b); @@ -878,7 +888,31 @@ bool TReport_printer::print_loop() } if (rex->eof()) - print_section('F', 1); + { + TReport_section* fl = _report.find_section('F',1); + if (fl != NULL) // Gestione footer last (se esite) + { + const int fy = fl->pos().y; + if (fy > 0) // Ha una coordinata y imposta + { + if (fy < _delta.y) // Sono gia' andato oltre quindi salto pagina + { + close_page(); + open_page(); + } + _delta.x = 0; + _delta.y = fy; + + // Azzero temporaneamente le dimensioni del footer per evitare salti pagina + const int lfp = _logical_foot_pos; + _logical_foot_pos = _logical_page_height; + print_section(*fl); + _logical_foot_pos = lfp; + } + else + print_section(*fl); // Stampa normale + } + } _is_last_page = true; close_page(); } diff --git a/include/strings.cpp b/include/strings.cpp index b0b457679..f176e95a3 100755 --- a/include/strings.cpp +++ b/include/strings.cpp @@ -427,6 +427,9 @@ const TString& TString::left( // @rdesc Ritorna l'indirizzo della stringa contenente i

caratteri da sinistra { + if (count <= 0) + return EMPTY_STRING; + TString& spark = get_tmp_string(); spark = _str; spark.cut(count); @@ -493,6 +496,44 @@ const TString& TString::sub( return mid(from, count); } +const TString& TString::after(char c) const +{ + const int pos = find(c); + if (pos >= 0) + return mid(pos+1); + return EMPTY_STRING; +} + +const TString& TString::after(const char* str) const +{ + if (str && *str) + { + const int pos = find(str); + if (pos >= 0) + return mid(pos+strlen(str)); + } + return EMPTY_STRING; +} + +const TString& TString::before(char c) const +{ + const int pos = find(c); + if (pos >= 0) + return left(pos); + return *this; +} + +const TString& TString::before(const char* str) const +{ + if (str && *str) + { + const int pos = find(str); + if (pos >= 0) + return left(pos); + } + return *this; +} + // Certified 100% TString& TString::cut(int n) { diff --git a/include/strings.h b/include/strings.h index d68e692b4..531f8bff6 100755 --- a/include/strings.h +++ b/include/strings.h @@ -116,6 +116,12 @@ public: const TString& sub(int from, int to = -1) const; // @cmember Ritorna l'oggetto TString composto dai count caratteri da destra const TString& right(int count) const; + // @cmember Ritorna l'oggetto TString dopo la string passata + const TString& after(char c) const; + const TString& after(const char* str) const; + // @cmember Ritorna l'oggetto TString prima della string passata + const TString& before(char c) const; + const TString& before(const char* str) const; // @cmember Ritorna un oggetto TString temporaneo composto dai count caratteri da sinistra TString sleft(int count) const diff --git a/include/xml.cpp b/include/xml.cpp index b9aa072ad..c286beb7b 100755 --- a/include/xml.cpp +++ b/include/xml.cpp @@ -170,7 +170,7 @@ TXmlItem& TXmlItem::SetAttr(const char* strAttr, bool b) bool TXmlItem::GetBoolAttr(const char* strAttr) const { - return !GetAttr(strAttr).blank(); + return GetIntAttr(strAttr, 0) != 0; } int TXmlItem::GetChildren() const