From 47c3c3483b64fafe5d8358e6347f6f1659fc59a2 Mon Sep 17 00:00:00 2001 From: guy Date: Tue, 6 Apr 2004 16:06:26 +0000 Subject: [PATCH] Patch level : 2.1 nopatch Files correlati : ba8.exe Ricompilazione Demo : [ ] Commento : Aggiunta gestione semplici messaggi git-svn-id: svn://10.65.10.50/trunk@11939 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- ba/ba8201.cpp | 9 + ba/ba8201.h | 1 + ba/ba8300.cpp | 45 ++++- ba/ba8300.h | 5 +- ba/ba8300b.uml | 29 +-- ba/ba8301.cpp | 2 +- ba/ba8302.cpp | 538 ++++++++++++++++++++++++++++++++----------------- ba/ba8302.h | 58 ++++-- ba/ba8303.cpp | 103 +++++++--- ba/ba8303.uml | 7 + ba/ba8304.cpp | 277 +++++++++++++++++++++---- ba/ba8304.h | 16 +- 12 files changed, 790 insertions(+), 300 deletions(-) diff --git a/ba/ba8201.cpp b/ba/ba8201.cpp index a41d31cd6..780651f97 100755 --- a/ba/ba8201.cpp +++ b/ba/ba8201.cpp @@ -107,6 +107,15 @@ bool TVariant::as_bool() const return ok; } +COLOR TVariant::as_color() const +{ + const unsigned long rgb = as_int(); + unsigned char r = XVT_COLOR_GET_RED(rgb); + unsigned char g = XVT_COLOR_GET_GREEN(rgb); + unsigned char b = XVT_COLOR_GET_BLUE(rgb); + return MAKE_COLOR(r, g, b); +} + real TVariant::as_real() const { if (_type == _realfld) diff --git a/ba/ba8201.h b/ba/ba8201.h index 1438c925f..5b66119a3 100755 --- a/ba/ba8201.h +++ b/ba/ba8201.h @@ -53,6 +53,7 @@ public: long as_int() const; TDate as_date() const; bool as_bool() const; + COLOR as_color() const; void convert_to(TFieldtypes ft); diff --git a/ba/ba8300.cpp b/ba/ba8300.cpp index 9e18c2704..c608270d3 100755 --- a/ba/ba8300.cpp +++ b/ba/ba8300.cpp @@ -162,6 +162,7 @@ class TReport_field_mask : public TFont_button_mask { protected: + void vedo_non_vedo(); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual void update(); @@ -207,10 +208,32 @@ void TReport_field_mask::update() } } +void TReport_field_mask::vedo_non_vedo() +{ + const char type = get(F_TYPE)[0]; + const bool is_text = strchr("DNPSTV", type) != NULL; + + show(F_HIDE_ZEROES, strchr("NPV", type) != NULL), + show(F_HALIGN, is_text); + show(F_VALIGN, is_text); + show(F_TEXT, is_text); + show(F_FGCOLOR, type != 'I'); + show(F_BGCOLOR, type != 'L' && type != 'I'); + show(F_FONT_SELECT, is_text); + show(F_SOURCE, (is_text || type == 'I') && type != 'T'); + + if (is_running()) + force_update(); +} + bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { + case F_TYPE: + if (e == fe_init || e == fe_modify) + vedo_non_vedo(); + break; case F_X: case F_Y: case F_DX: @@ -244,7 +267,7 @@ bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long void TReport_field_mask::set_field(const TReport_field& rf) { char str[2] = { rf.type(), '\0' }; - set(F_TYPE, str); + set(F_TYPE, str, true); const TRectangle& r = rf.get_rect(); set(F_ID, rf.id()); @@ -254,6 +277,7 @@ void TReport_field_mask::set_field(const TReport_field& rf) set_num(F_DY, r.height()); set(F_HIDDEN, rf.hidden() ? "X" : ""); set(F_DISABLED, rf.deactivated() ? "X" : ""); + set(F_HIDE_ZEROES, rf.zeroes_hidden() ? "X" : ""); str[0] = rf.horizontal_alignment(); set(F_HALIGN, str); str[0] = rf.vertical_alignment(); @@ -276,6 +300,8 @@ void TReport_field_mask::get_field(TReport_field& rf) const rf.set_size(get_num(F_DX), get_num(F_DY)); rf.show(!get_bool(F_HIDDEN)); rf.activate(!get_bool(F_DISABLED)); + rf.hide_zeroes(get_bool(F_HIDE_ZEROES)); + rf.set_horizontal_alignment(get(F_HALIGN)[0]); rf.set_vertical_alignment(get(F_VALIGN)[0]); rf.set_border(get_int(F_BORDER)); @@ -749,7 +775,11 @@ void TReport_mask::edit_field(TReport_field& rf) break; default: break; } - update_report(); + if (key != K_ESC) + { + rf.section().sort(); + update_report(); + } } void TReport_mask::fields_properties() @@ -882,6 +912,14 @@ bool TReport_mask::on_field_event(TOperable_field& o, TField_event e, long jolly switch (o.dlg()) { case F_CODICE: + if (e == fe_init) + { + if (main_app().argc() >= 3) + { + set(F_CODICE, main_app().argv(2)); + load_report(); + } + } if (e == fe_button) { if (select_report()) @@ -1013,9 +1051,6 @@ TReport_mask::TReport_mask() : _tree(_report), _is_dirty(false) TReport_drawer& rd = (TReport_drawer&)field(F_REPORT); rd.set_report(&_report); - - if (main_app().argc() >= 2) - set(F_REPORT, main_app().argv(2), true); } /////////////////////////////////////////////////////////// diff --git a/ba/ba8300.h b/ba/ba8300.h index 51fb5e2d6..f141cabcc 100755 --- a/ba/ba8300.h +++ b/ba/ba8300.h @@ -25,8 +25,9 @@ #define F_FONT_SELECT 122 #define F_HIDDEN 123 #define F_DISABLED 124 -#define F_PRESCRIPT 125 -#define F_POSTSCRIPT 126 +#define F_HIDE_ZEROES 125 +#define F_PRESCRIPT 126 +#define F_POSTSCRIPT 127 #define F_LEVEL 130 #define F_GROUP_BY 131 diff --git a/ba/ba8300b.uml b/ba/ba8300b.uml index bffb9f02e..6215727c3 100755 --- a/ba/ba8300b.uml +++ b/ba/ba8300b.uml @@ -6,21 +6,15 @@ LIST F_TYPE 1 16 BEGIN PROMPT 2 1 "Tipo " ITEM "T|Testo" - MESSAGE SHOW,1@|HIDE,F_SOURCE ITEM "S|Stringa" - MESSAGE SHOW,1@ ITEM "N|Numero" - MESSAGE SHOW,1@ + ITEM "V|Valuta" + ITEM "P|Prezzo" ITEM "D|Data" - MESSAGE SHOW,1@ - ITEM "L|Linea" - MESSAGE HIDE,1@ - ITEM "R|Rettangolo" - MESSAGE HIDE,1@ - ITEM "E|Ellisse" - MESSAGE HIDE,1@ ITEM "I|Immagine" - MESSAGE HIDE,1@|SHOW,F_SOURCE + ITEM "L|Linea" + ITEM "R|Rettangolo" + ITEM "E|Ellisse" END GROUPBOX DLG_NULL 70 5 @@ -60,14 +54,18 @@ END BOOLEAN F_HIDDEN BEGIN - PROMPT 41 2 "Nascosto" + PROMPT 39 2 "Nascosto" END BOOLEAN F_DISABLED BEGIN - PROMPT 41 3 "Disattivato" + PROMPT 39 3 "Disattivato" END +BOOLEAN F_HIDE_ZEROES +BEGIN + PROMPT 51 2 "Nascosto se zero" +END GROUPBOX DLG_NULL 70 8 BEGIN @@ -81,7 +79,6 @@ BEGIN ITEM "R|Destra" ITEM "C|Centrato" ITEM "J|Giustificato" - GROUP 1 END LIST F_VALIGN 1 12 @@ -90,7 +87,6 @@ BEGIN ITEM "T|Alto" ITEM "C|Centrato" ITEM "B|Basso" - GROUP 1 END BUTTON F_FGCOLOR 14 1 @@ -106,7 +102,6 @@ END BUTTON F_FONT_SELECT 14 2 BEGIN PROMPT 2 9 "~Font" - GROUP 1 END LIST F_BORDER 1 12 @@ -120,13 +115,11 @@ END ZOOM F_TEXT 58 BEGIN PROMPT 1 13 "Testo " - GROUP 1 END ZOOM F_SOURCE 58 BEGIN PROMPT 1 14 "Sorgente " - GROUP 1 END BUTTON DLG_CANCEL 10 2 diff --git a/ba/ba8301.cpp b/ba/ba8301.cpp index 97e5b1f3c..997bca1be 100755 --- a/ba/ba8301.cpp +++ b/ba/ba8301.cpp @@ -730,12 +730,12 @@ TPoint TReport_window::dev2log(const PNT& pt) const void TReport_window::draw_grid() { clear(COLOR_WHITE); - set_pen(MAKE_COLOR(232,232,232)); const int max = 192; const int k = 100; for (int i = 1; i < max; i++) { + set_pen(i%10 ? MAKE_COLOR(232,232,232) : COLOR_LTGRAY); line(0, i*k, max*k, i*k); line(i*k, 0, i*k, max*k); } diff --git a/ba/ba8302.cpp b/ba/ba8302.cpp index 75ca4633c..e4dcaf2a7 100755 --- a/ba/ba8302.cpp +++ b/ba/ba8302.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "ba8201.h" @@ -56,29 +57,32 @@ XVT_FNTID TReport_font::get_xvt_font(const TWindow& win) const xvt_font_set_size(fontid, nSize); xvt_font_set_style(fontid, _style); - if (_fontid != NULL) - xvt_font_destroy(_fontid); - - TReport_font& my = *(TReport_font*)this; - my._fontid = fontid; - my._win_mapped = win.win(); - xvt_dwin_get_font_metrics(_win_mapped, &my._leading, &my._ascent, &my._descent); + TReport_font& myself = *(TReport_font*)this; + myself.unmap(); + myself._fontid = fontid; + myself._win_mapped = win.win(); + xvt_dwin_get_font_metrics(_win_mapped, &myself._leading, &myself._ascent, &myself._descent); } return _fontid; } +void TReport_font::unmap() +{ + if (_fontid != NULL) + { + xvt_font_destroy(_fontid); + _fontid = NULL; + } + _win_mapped = NULL_WIN; +} + void TReport_font::create(const char* name, int size, XVT_FONT_STYLE_MASK style) { _name = name; _size = size; _style = style; _cpi = 120 / _size; - if (_fontid != NULL) - { - xvt_font_destroy(_fontid); - _fontid = NULL; - _win_mapped = NULL_WIN; - } + unmap(); } void TReport_font::copy(const TReport_font& font) @@ -141,8 +145,7 @@ TReport_font::TReport_font(const TReport_font& f) : _fontid(NULL), _win_mapped(N TReport_font::~TReport_font() { - if (_fontid != NULL) - xvt_font_destroy(_fontid); + unmap(); } /////////////////////////////////////////////////////////// @@ -213,15 +216,35 @@ TReport_expr::TReport_expr(TReport& rep, const char* exp) } -TObject* TExpression_cache::key2obj(const char* key) +TObject* TReport_expr_cache::key2obj(const char* key) { return new TReport_expr(*_report, key); } -TReport_expr& TExpression_cache::operator[](const char* key) +TReport_expr& TReport_expr_cache::operator[](const char* key) { return *(TReport_expr*)objptr(key); } +TObject* TReport_image_cache::key2obj(const char* key) +{ + TImage* img = NULL; + + TFilename pathname = key; + if (pathname.custom_path()) + img = new TImage(pathname); + + return img; +} + +TImage* TReport_image_cache::image(const TString& key) +{ + return (TImage*)objptr(key); +} + +TReport_image_cache::TReport_image_cache() : TCache(7) +{ +} + /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// @@ -276,6 +299,52 @@ void advanced_draw_text(TWindow& win, const char* text, const RCT& r, xvt_dwin_draw_text(win.win(), x, y, text, -1); } +static void set_num_attr(TXmlItem& item, const char* attr, long num, short def = 0) +{ + if (num != def) + { + const real n = num / CENTO; + item.SetAttr(attr, n.string()); + } +} + +static void set_col_attr(TXmlItem& item, const char* attr, COLOR col, COLOR def = COLOR_BLACK) +{ + if (color_distance(col, def) != 0) + { + TString16 str; + str.format("#%06X", col & 0xFFFFFF); + item.SetAttr(attr, str); + } +} + +static short get_num_attr(const TXmlItem& item, const char* attr, short def = 0) +{ + const TString& str = item.GetAttr(attr); + if (str.not_empty()) + { + real n = str; n *=CENTO ; + def = (short)n.integer(); + } + return def; +} + +static COLOR get_col_attr(const TXmlItem& item, const char* attr, COLOR col) +{ + const TString& str = item.GetAttr(attr); + if (str[0] == '#') + sscanf(str, "#%X", &col); + return col; +} + +static char get_chr_attr(const TXmlItem& item, const char* attr, char c) +{ + const TString& str = item.GetAttr(attr); + if (str[0] > ' ') + c = toupper(str[0]); + return c; +} + /////////////////////////////////////////////////////////// // TReport_section /////////////////////////////////////////////////////////// @@ -317,6 +386,14 @@ void TReport_section::set_font(const TReport_font& f) _font = new TReport_font(f); } +void TReport_section::unmap_font() +{ + if (_font != NULL) + _font->unmap(); + for (int i = last(); i >= 0; i--) + field(i).unmap_font(); +} + int TReport_section::add(TObject* obj) { TReport_field* rf = (TReport_field*)obj; @@ -388,6 +465,20 @@ void TReport_section::draw(TWindow& win, TReport_draw_mode rdm) const } } +bool TReport_section::load_fields() +{ + const bool ok = active() || shown(); + if (ok) + { + for (int i = 0; i < items(); i++) + { + TReport_field& f = field(i); + f.load_field(); + } + } + return ok; +} + bool TReport_section::execute_prescript() { bool ok = true; @@ -432,6 +523,8 @@ void TReport_section::save(TXmlItem& root) const } item.SetAttr("type", tipo); item.SetAttr("level", level()); + set_num_attr(item, "width", width()); + set_num_attr(item, "height", height()); item.SetAttr("hidden", _hidden); item.SetAttr("deactivated", _deactivated); item.SetAttr("hidden_if_needed", hidden_if_needed()); @@ -452,6 +545,8 @@ void TReport_section::save(TXmlItem& root) const void TReport_section::load(const TXmlItem& sec) { + set_width(get_num_attr(sec, "width")); + set_height(get_num_attr(sec, "height")); force_page_break(sec.GetBoolAttr("pagebreak")); hide_if_needed(sec.GetBoolAttr("hidden_if_needed")); show(!sec.GetBoolAttr("hidden")); @@ -618,6 +713,12 @@ void TReport_field::set_font(const TReport_font& f) _font = new TReport_font(f); } +void TReport_field::unmap_font() +{ + if (_font != NULL) + _font->unmap(); +} + void TReport_field::copy(const TReport_field& rf) { _section = rf._section; @@ -630,6 +731,7 @@ void TReport_field::copy(const TReport_field& rf) _picture = rf._picture; _field = rf._field; _hidden = rf.hidden(); _deactivated = rf.deactivated(); + _hide_zeroes = rf._hide_zeroes; _selected = false; set_font(rf.font()); } @@ -644,9 +746,11 @@ const char* TReport_field::type_name() const case 'I': n = "Immagine"; break; case 'L': n = "Linea"; break; case 'N': n = "Numero"; break; + case 'P': n = "Prezzo"; break; case 'R': n = "Rettangolo"; break; case 'S': n = "Stringa"; break; case 'T': n = "Testo"; break; + case 'V': n = "Valuta"; break; default : break; } return n; @@ -658,7 +762,10 @@ TFieldtypes TReport_field::var_type() const switch (_type) { case 'D': ft = _datefld; break; + case 'P': // Prezzo + case 'V': // Valuta case 'N': ft = _realfld; break; + case 'I': case 'S': ft = _alfafld; break; default : ft = _nullfld; break; } @@ -677,9 +784,10 @@ void TReport_field::set(const TVariant& var) _var.convert_to(var_type()); } -bool TReport_field::execute_prescript() +bool TReport_field::load_field() { - if (!_field.blank()) + const bool ok = !_field.blank(); + if (ok) { const TFieldtypes ft = var_type(); if (ft != _nullfld) @@ -687,6 +795,11 @@ bool TReport_field::execute_prescript() else _var.set_null(); } + return ok; +} + +bool TReport_field::execute_prescript() +{ bool ok = true; if (active()) ok = _prescript.execute(*this); @@ -756,6 +869,29 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const } } break; + case 'I': + { + RCT r; win.log2dev(get_rect(), r); + TReport& rep = section().report(); + if (rdm == rdm_edit) + { + TVariant var; + section().report().evaluate(_field, var, _alfafld); + const TString& name = var.as_string(); + const TImage* img = rep.image(name); + if (img != NULL && img->ok()) + img->draw(win.win(), r); + } + else + { + const TString& name = get().as_string(); + const TImage* img = rep.image(name); + if (img != NULL && img->ok()) + img->draw(win.win(), r); + } + draw_rect(win); + } + break; case 'L': { win.set_pen(fore_color(), border()); @@ -764,9 +900,13 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const back_pattern = PAT_HOLLOW; } break; - case 'I': case 'R': draw_rect(win); break; case 'T': draw_text(win, _picture); break; + case 'N': + case 'P': + case 'V': + if (zeroes_hidden() && _var.as_real().is_zero()) + break; default : if (rdm == rdm_edit) { @@ -802,23 +942,17 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const } } -static void set_num_attr(TXmlItem& item, const char* attr, long num, short def = 0) -{ - if (num != def) - { - const real n = num / CENTO; - item.SetAttr(attr, n.string()); - } -} +void TReport_field::set_group(int group) +{ _groups.set(group); } -static void set_col_attr(TXmlItem& item, const char* attr, COLOR col, COLOR def = COLOR_BLACK) -{ - if (color_distance(col, def) != 0) - { - TString16 str; - str.format("#%06X", col & 0xFFFFFF); - item.SetAttr(attr, str); - } +void TReport_field::reset_group(int group) +{ _groups.reset(group); } + +bool TReport_field::in_group(int group) const +{ + if (group <= 0) + return _groups.first_one() > 0; + return _groups[group]; } void TReport_field::save(TXmlItem& root) const @@ -834,10 +968,17 @@ 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); set_col_attr(fld, "bg_color", back_color(), COLOR_WHITE); set_col_attr(fld, "fg_color", fore_color(), COLOR_BLACK); if (has_font()) font().save(fld); + if (in_group(0)) + { + TString str; + str << _groups; + fld.AddChild("groups") << str; + } switch (horizontal_alignment()) { @@ -860,32 +1001,6 @@ void TReport_field::save(TXmlItem& root) const _postscript.save(fld, "postscript"); } -static short get_num_attr(const TXmlItem& item, const char* attr, short def = 0) -{ - const TString& str = item.GetAttr(attr); - if (str.not_empty()) - { - real n = str; n *=CENTO ; - def = (short)n.integer(); - } - return def; -} - -static COLOR get_col_attr(const TXmlItem& item, const char* attr, COLOR col) -{ - const TString& str = item.GetAttr(attr); - if (str[0] == '#') - sscanf(str, "#%X", &col); - return col; -} - -static char get_chr_attr(const TXmlItem& item, const char* attr, char c) -{ - const TString& str = item.GetAttr(attr); - if (str[0] > ' ') - c = toupper(str[0]); - return c; -} bool TReport_field::load(const TXmlItem& fld) { @@ -897,6 +1012,7 @@ bool TReport_field::load(const TXmlItem& fld) set_height(get_num_attr(fld, "height", 100)); show(!fld.GetBoolAttr("hidden")); activate(!fld.GetBoolAttr("deactivated")); + hide_zeroes(fld.GetBoolAttr("zeroes_hidden")); 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)); @@ -909,16 +1025,39 @@ bool TReport_field::load(const TXmlItem& fld) TReport_font font; if (font.load(fld)) set_font(font); + + TXmlItem* grp = fld.FindFirst("groups"); + if (grp != NULL) + { + TString str; grp->GetEnclosedText(str); + istrstream ins(str.get_buffer(), str.size()); + ins >> _groups; + } + _prescript.load(fld, "prescript"); _postscript.load(fld, "postscript"); return true; } +int TReport_field::compare(const TSortable& s) const +{ + const TReport_field& rf = (TReport_field&)s; + + int cmp = _rct.y - rf._rct.y; + if (cmp == 0) + { + cmp = _rct.x - rf._rct.x; + if (cmp == 0) + cmp = _id - rf._id; + } + return cmp; +} + TReport_field::TReport_field(TReport_section* sec) : _section(sec), _id(0), _type('T'), _font(NULL), _halign('L'), _valign('T'), - _selected(false), _hidden(false), _deactivated(false), + _selected(false), _hidden(false), _deactivated(false), _hide_zeroes(false), _border(0), _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE) { set_pos(0,0); @@ -936,76 +1075,6 @@ TReport_field::~TReport_field() delete _font; } -/////////////////////////////////////////////////////////// -// TReport_field_ref -/////////////////////////////////////////////////////////// - -struct TReport_field_ref : public TObject -{ - char _sectype; - int _seclevel; - int _fldid; // -1 = section; 0 = curent field; >0 = normal field - int _fldpos; // array position -}; - -TObject* TField_cache::key2obj(const char* key) -{ - const TFixed_string code(key); - - TReport_field_ref* rf = new TReport_field_ref; - rf->_sectype = ' '; - rf->_seclevel = rf->_fldid = rf->_fldpos = -1; - - const char* strid = ""; - const int dot = code.find('.'); - if (dot == 2) - { - rf->_sectype = code[0]; - if (isdigit(code[1])) - rf->_seclevel = atoi((const char*)code + 1); - strid = (const char*)code+3; - } - else - strid = code; - if (*strid > ' ') - { - rf->_fldid = atoi(strid); - TReport_section& sec = _report->section(rf->_sectype, rf->_seclevel); - rf->_fldpos = sec.find_field_pos(rf->_fldid); - } - - return rf; -} - -TReport_field* TField_cache::operator[](const char* key) -{ - TReport_field_ref& ref = *(TReport_field_ref*)objptr(key); - - if (ref._fldid <= 0) - return _report->curr_field(); - - char typ = ref._sectype; - int lev = ref._seclevel; - if (typ <= ' ' || lev < 0) - { - TReport_field* cf = _report->curr_field(); - if (typ <= ' ') typ = cf->section().type(); - if (lev < 0) lev = cf->section().level(); - } - TReport_section& sec = _report->section(typ, lev); - TReport_field* fld = NULL; - if (ref._fldpos >= 0 && ref._fldpos < sec.items()) - { - fld = &sec.field(ref._fldpos); - if (fld->id() == ref._fldid) - return fld; - } - ref._fldpos = sec.find_field_pos(ref._fldid); - fld = ref._fldpos >= 0 ? &sec.field(ref._fldpos) : NULL; - - return fld; -} - /////////////////////////////////////////////////////////// // TReport /////////////////////////////////////////////////////////// @@ -1079,22 +1148,34 @@ TReport_section& TReport::section(char type, int level) TReport_field* TReport::field(const TString& code) { - return _fields[code]; -} - -bool TReport::evaluate_atom(const char* atom, TVariant& var) -{ - const TFixed_string name(atom); // skip # - - if (name == "PAGE") + TReport_field* rf = NULL; + if (isdigit(code[0]) || code == "THIS") // Campo singolo, es: 101 o THIS { - var = curr_page(); - return true; + rf = curr_field(); + if (rf != NULL) + { + if (code != "THIS") + rf = rf->section().find_field(atoi(code)); + } } - - const TReport_field* fld = field(name); - var = fld != NULL ? fld->get() : NULL_VARIANT; - return fld != NULL; + else + { + const char type = code[0]; + if (type != 'H' && type != 'B' && type != 'F') // Non comincia con un codsice sezione + return NULL; + const int dot = code[2] == '.' ? 2 : (code[3] == '.' ? 3 : -1); + if (dot <= 0) + return NULL; + + const int level = atoi((const char*)code + 1); + TReport_section* sec = find_section(type, level); + if (sec != NULL) + { + const int id = atoi((const char*)code + dot + 1); + rf = sec->find_field(id); + } + } + return rf; } bool TReport::evaluate(const char* expr, TVariant& var, TFieldtypes force_type) @@ -1107,37 +1188,36 @@ bool TReport::evaluate(const char* expr, TVariant& var, TFieldtypes force_type) const char* name = e.varname(0); if (*name == '#' && strcmp(name, expr) == 0) { - const bool ok = evaluate_atom(name+1, var); - if (force_type != _nullfld) - var.convert_to(force_type); - return ok; + const TFixed_string usr(name+1); + if (get_usr_val(usr, var)) + { + if (force_type != _nullfld) + var.convert_to(force_type); + return true; + } } } for (int i = 0; i < e.numvar(); i++) { const char* name = e.varname(i); + bool ok = false; if (name[0] == '#') { - evaluate_atom(name, var); - if (var.type() == _alfafld) - e.setvar(i, var.as_string()); - else - e.setvar(i, var.as_real()); + const TFixed_string usr(name+1); + ok = get_usr_val(usr, var); } else { - if (_recordset != NULL) - { - const TVariant& var = _recordset->get(name); - if (var.type() == _realfld || var.type() == _longfld) - e.setvar(i, var.as_real()); - else - e.setvar(i, var.as_string()); - } - else - e.setvar(i, name); + const TFixed_string usr(name); + ok = get_usr_val(usr, var); } + if (!ok) + var = name; + if (var.type() == _alfafld) + e.setvar(i, var.as_string()); + else + e.setvar(i, var.as_real()); } const TFieldtypes ft = force_type != _nullfld ? force_type : var.type(); @@ -1234,43 +1314,134 @@ bool TReport::save(const char* fname) const return ok; } -bool TReport::get_usr_val(const TString& name, TVariant& var) const +void TReport::unmap_font() { - return ((TReport*)this)->evaluate(name, var, _nullfld); + _font.unmap(); + FOR_EACH_ASSOC_OBJECT(_sections, h, k, o) + { + TReport_section& sec = *(TReport_section*)o; + sec.unmap_font(); + } } -bool TReport::set_usr_val(const TString& name, const TVariant& var) +bool TReport::execute_prescript() { - return false; + TString80 str; + return _prescript.execute(*this, str); } +bool TReport::execute_postscript() +{ + TString80 str; + return _postscript.execute(*this, str); +} + +bool TReport::get_usr_val(const char* code, TVariant& var) const +{ + const TFixed_string name(*code != '#' ? code : (code+1)); + + TReport_field* fld = ((TReport*)this)->field(name); + if (fld != NULL) + { + var = fld->get(); + return true; + } + + if (name == "PAGE") + { + var = curr_page(); + return true; + } + + if (_recordset != NULL) + { + var = _recordset->get(name); + if (!var.is_null()) + return true; + } + + return TAlex_virtual_machine::get_usr_val(name, var); +} + +bool TReport::set_usr_val(const char* code, const TVariant& var) +{ + const TFixed_string name(*code != '#' ? code : (code+1)); + TReport_field* fld = field(name); + if (fld != NULL) + { + fld->set(var); + return true; + } + return TAlex_virtual_machine::set_usr_val(name, var); +} unsigned int TReport::compile_usr_word(const TString& name) const { - if (name == "GET_FIELD") - return 1; - if (name == "SET_FIELD") - return 2; - return 0; + const char* const names[5] = { NULL, "GET_RECT", "SET_BACK_COLOR", "SET_FORE_COLOR", "SET_RECT" }; + int i; + for (i = 4; i > 0; i--) + if (name == names[i]) + break; + return i; +} + +TReport_field* TReport::var2field(const TVariant& var) +{ + const TString& code = var.as_string(); + if (code[0] == '#') + { + const TFixed_string ref((const char*)code + 1); + return field(ref); + } + return field(code); } bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack) { switch (opcode) { - case 1: + case 1: // GET_RECT { - TVariant& var = stack.peek(); - evaluate(var.as_string(), var, _nullfld); + const TReport_field* fld = var2field(stack.pop()); + real x, y, w, h; + if (fld != NULL) + { + const TRectangle& r = fld->get_rect(); + x = r.x / CENTO; y = r.y / CENTO; + w = r.width() / CENTO; h = r.height() / CENTO; + } + stack.push(x); stack.push(y); + stack.push(w); stack.push(h); } break; - case 2: + case 2: // SET_BACK_COLOR { - TVariant& var = stack.pop(); - TVariant& val = stack.pop(); - TReport_field* fld = field(var.as_string()); + TReport_field* fld = var2field(stack.pop()); + const COLOR rgb = stack.pop().as_color(); if (fld != NULL) - fld->set(val); + fld->set_back_color(rgb); + } + break; + case 3: // SET_FORE_COLOR + { + TReport_field* fld = var2field(stack.pop()); + const COLOR rgb = stack.pop().as_color(); + if (fld != NULL) + fld->set_fore_color(rgb); + } + break; + case 4: // SET_RECT + { + TReport_field* fld = var2field(stack.pop()); + const real h = stack.pop().as_real() * CENTO; + const real w = stack.pop().as_real() * CENTO; + const real y = stack.pop().as_real() * CENTO; + const real x = stack.pop().as_real() * CENTO; + if (fld != NULL) + { + fld->set_pos(x.integer(), y.integer()); + fld->set_size(w.integer(), h.integer()); + } } break; default: @@ -1283,7 +1454,6 @@ TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL) { // Brutte inizializzazioni, ma inevitabili _expressions.set_report(this); - _fields.set_report(this); } TReport::~TReport() diff --git a/ba/ba8302.h b/ba/ba8302.h index 922f36dee..f8edcd6f3 100755 --- a/ba/ba8302.h +++ b/ba/ba8302.h @@ -5,6 +5,10 @@ #include #endif +#ifndef __IMAGE_H +#include +#endif + #ifndef __WINDOW_H #include #endif @@ -47,6 +51,8 @@ public: XVT_FONT_STYLE_MASK style() const { return _style; } int cpi() const { return _cpi; } XVT_FNTID get_xvt_font(const TWindow& win) const; + void unmap(); + int leading() const { return _leading; } int ascent() const { return _ascent; } int descent() const { return _descent; } @@ -70,7 +76,7 @@ class TReport_field; class TReport_expr; -class TExpression_cache : public TCache +class TReport_expr_cache : public TCache { TReport* _report; @@ -81,20 +87,17 @@ public: TReport_expr& operator[](const char* key); void set_report(TReport* rep) { _report = rep; } - TExpression_cache() : _report(NULL) { } + TReport_expr_cache() : _report(NULL) { } }; -class TField_cache : public TCache +class TReport_image_cache : public TCache { - TReport* _report; - protected: virtual TObject* key2obj(const char* key); public: - TReport_field* operator[](const char* key); - void set_report(TReport* rep) { _report = rep; } - TField_cache() : _report(NULL) { } + TImage* image(const TString& name); + TReport_image_cache(); }; /////////////////////////////////////////////////////////// @@ -190,7 +193,9 @@ public: bool has_font() const { return _font != NULL; } const TReport_font& font() const; void set_font(const TReport_font& f); + void unmap_font(); + bool load_fields(); bool execute_prescript(); bool execute_postscript(); void draw(TWindow& win, TReport_draw_mode mode) const; @@ -202,23 +207,25 @@ public: virtual ~TReport_section(); }; -class TReport_field : public TObject +class TReport_field : public TSortable { TReport_section* _section; int _id; - char _type; // Text, String, Numeric, Date, Line, Rectangle, Image + char _type; // Text, String, Numeric, Price, Valuta, Date, Line, Rectangle, Image TRectangle _rct; // In centesimi COLOR _fgcolor, _bgcolor; short _border; char _halign, _valign; + TBit_array _groups; TString _picture, _field; TVariant _var; TReport_script _prescript, _postscript; TReport_font* _font; - bool _hidden, _deactivated, _selected; + bool _hidden, _deactivated, _hide_zeroes, _selected; protected: + virtual int compare(const TSortable& s) const; void copy(const TReport_field& rf); TFieldtypes var_type() const; @@ -226,12 +233,13 @@ public: virtual TObject* dup() const { return new TReport_field(*this); } TReport_field& operator=(const TReport_field& rf) { copy(rf); return *this; } - TReport_section& section() { return *_section; } + TReport_section& section() const { return *_section; } void set_section(TReport_section* sec) { _section = sec; } bool has_font() const { return _font != NULL; } const TReport_font& font() const; void set_font(const TReport_font& f); + void unmap_font(); const TString& picture() const { return _picture; } void set_picture(const char* str) { _picture = str; } @@ -243,6 +251,7 @@ public: void set(const char* str); void set(const TVariant& var); + bool load_field(); bool execute_prescript(); bool execute_postscript(); @@ -267,6 +276,12 @@ public: bool active() const { return !deactivated(); } void activate(bool on) { _deactivated = !on; } void deactivate() { activate(false); } + bool zeroes_hidden() const { return _hide_zeroes; } + void hide_zeroes(bool hz) { _hide_zeroes = hz; } + + void set_group(int group); + void reset_group(int group); + bool in_group(int group) const; void set_fore_color(COLOR c) { _fgcolor = c; } COLOR fore_color() const { return _fgcolor; } @@ -307,17 +322,19 @@ class TReport : public TAlex_virtual_machine TString _description; TReport_font _font; int _lpi; // Lines per inch + TReport_script _prescript, _postscript; TRecordset* _recordset; - TExpression_cache _expressions; - TField_cache _fields; + TReport_expr_cache _expressions; + TReport_image_cache _images; word _curr_page; TReport_field* _curr_field; protected: virtual unsigned int compile_usr_word(const TString& name) const; 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 bool get_usr_val(const char* name, TVariant& var) const; + virtual bool set_usr_val(const char* name, const TVariant& var); + TReport_field* var2field(const TVariant& var); 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; @@ -333,6 +350,7 @@ public: const TReport_font& font() const { return _font; } void set_font(const TReport_font& f) { _font = f; } + void unmap_font(); int cpi() const { return _font.cpi(); } int lpi() const { return _lpi; } @@ -344,8 +362,16 @@ public: bool evaluate_atom(const char* atom, TVariant& var); bool evaluate(const char* expr, TVariant& var, TFieldtypes force_type); + const TString& prescript() const { return _prescript.get(); } + void set_prescript(const char* src) { _prescript.set(src); } + const TString& postscript() const { return _postscript.get(); } + void set_postscript(const char* src) { _postscript.set(src); } + bool execute_prescript(); + bool execute_postscript(); + void set_description(const char* d) { _description = d; } const TString& description() const { return _description; } + TImage* image(const TString& name) { return _images.image(name); } const TFilename& filename() const { return _path; } bool save(const char* fname) const; diff --git a/ba/ba8303.cpp b/ba/ba8303.cpp index 872169639..68088afbb 100755 --- a/ba/ba8303.cpp +++ b/ba/ba8303.cpp @@ -18,6 +18,7 @@ class TPrint_preview_window : public TField_window int _zoom; protected: + void page_select(); void popup_menu(EVENT* ep); virtual void handler(WINDOW win, EVENT* ep); virtual void update(); @@ -34,8 +35,13 @@ public: PNT TPrint_preview_window::log2dev(long lx, long ly) const { PNT pnt; - pnt.h = short(lx * _zoom / 100); - pnt.v = short(ly * _zoom / 100); + pnt.h = short(lx * _zoom / 1000); + pnt.v = short(ly * _zoom / 1000); + + const TPoint orig = origin(); + pnt.h -= short(orig.x); + pnt.v -= short(orig.y); + return pnt; } @@ -47,9 +53,10 @@ void TPrint_preview_window::update() #define POPUP_FIRST 20883 #define POPUP_PREV 20884 #define POPUP_NEXT 20885 -#define POPUP_LAST 20886 -#define POPUP_ZOOMIN 20887 -#define POPUP_ZOOMOUT 20888 +#define POPUP_SEARCH 20886 +#define POPUP_LAST 20887 +#define POPUP_ZOOMIN 20888 +#define POPUP_ZOOMOUT 20889 void TPrint_preview_window::popup_menu(EVENT* ep) { @@ -60,13 +67,27 @@ void TPrint_preview_window::popup_menu(EVENT* ep) menu[2].tag = POPUP_NEXT; menu[2].text = (char*)TR("Avanti"); menu[2].enabled = _last == 0 || _page < _last; menu[3].tag = POPUP_LAST; menu[3].text = (char*)TR("Ultima"); menu[3].enabled = true; menu[4].tag = -1; menu[4].separator = true; - menu[5].tag = POPUP_ZOOMIN; menu[5].text = (char*)TR("Zoom +"); menu[5].enabled = _zoom < 200; + menu[5].tag = POPUP_ZOOMIN; menu[5].text = (char*)TR("Zoom +"); menu[5].enabled = _zoom < 300; menu[6].tag = POPUP_ZOOMOUT; menu[6].text = (char*)TR("Zoom -"); menu[6].enabled = _zoom > 75; const PNT& p = ep->v.mouse.where; xvt_menu_popup(menu, win(), p, XVT_POPUP_CENTER, 0); } +void TPrint_preview_window::page_select() +{ + TMask m("Ricerca", 1, 28, 4); + m.add_number(101, 0, "Pagina ", 1, 1, 4, "U").check_type(CHECK_REQUIRED); + m.add_button(DLG_OK, 0, "", -12, -1, 10, 2); + m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2); + if (m.run()) + { + _page = m.get_int(101); + if (_last > 0 && _page > _last) + _page = _last; + } +} + void TPrint_preview_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) @@ -82,6 +103,7 @@ void TPrint_preview_window::handler(WINDOW win, EVENT* ep) { case POPUP_FIRST : _page = 1; break; case POPUP_PREV : if (_page > 1) _page--; break; + case POPUP_SEARCH : page_select(); break; case POPUP_NEXT : if (_last == 0 || _page < _last) _page++; break; case POPUP_LAST : if (_last == 0) @@ -91,7 +113,7 @@ void TPrint_preview_window::handler(WINDOW win, EVENT* ep) } _page = _last; break; - case POPUP_ZOOMIN : if (_zoom < 200) { _zoom += 25; } break; + case POPUP_ZOOMIN : if (_zoom < 300) { _zoom += 25; } break; case POPUP_ZOOMOUT: if (_zoom > 75) { _zoom -= 25; } break; default:processed = false; break; } @@ -127,6 +149,8 @@ TPrint_preview_window::TPrint_preview_window(int x, int y, int dx, int dy, WINDO TWindowed_field* owner, TPage_printer* printer) : TField_window(x, y, dx, dy, parent, owner), _printer(printer), _page(1), _last(0), _zoom(100) { + const TPoint ps = printer->page_size(); + set_scroll_max(ps.x/4, ps.y/4); } /////////////////////////////////////////////////////////// @@ -170,6 +194,8 @@ bool TPreview_mask::on_key(KEY k) { switch (k) { + case '+' : + case '-' : case K_HOME : case K_LHOME: case K_LEFT : @@ -186,13 +212,17 @@ bool TPreview_mask::on_key(KEY k) bool TPreview_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { - switch (o.dlg()) + if (e == fe_button) { - case DLG_FIRSTREC: dispatch_e_menu(_printer->win(), POPUP_FIRST); break; - case DLG_PREVREC : dispatch_e_menu(_printer->win(), POPUP_PREV); break; - case DLG_NEXTREC : dispatch_e_menu(_printer->win(), POPUP_NEXT); break; - case DLG_LASTREC : dispatch_e_menu(_printer->win(), POPUP_LAST); break; - default: break; + switch (o.dlg()) + { + case DLG_FIRSTREC: dispatch_e_menu(_printer->win(), POPUP_FIRST); break; + case DLG_PREVREC : dispatch_e_menu(_printer->win(), POPUP_PREV); break; + case DLG_FINDREC : dispatch_e_menu(_printer->win(), POPUP_SEARCH);break; + case DLG_NEXTREC : dispatch_e_menu(_printer->win(), POPUP_NEXT); break; + case DLG_LASTREC : dispatch_e_menu(_printer->win(), POPUP_LAST); break; + default: break; + } } return true; } @@ -402,10 +432,6 @@ void TPage_printer::print_page(word page) bool TPage_printer::preview() { - _preview_mask = new TPreview_mask(this); - TPrint_preview_field& pf = (TPrint_preview_field&)_preview_mask->field(DLG_USER); - _preview_window = &pf.win(); - TPrinter& p = printer(); _rcd = p.get_printrcd(); if (!xvt_print_is_valid(_rcd)) @@ -415,21 +441,20 @@ bool TPage_printer::preview() if (_ph <= 0) return error_box("Risoluzione stampante NULLA"); - RCT rct; pf.get_rect(rct); - const long page_height = rct.bottom - rct.top; - const long page_width = rct.right - rct.left; - const long page_res = page_height * _pvr / _ph; - _ph = page_height; - _pw = page_width; - _pvr = _phr = page_res; + _preview_mask = new TPreview_mask(this); + TPrint_preview_field& pf = (TPrint_preview_field&)_preview_mask->field(DLG_USER); + _preview_window = &pf.win(); set_win(_preview_window->win()); _pagefrom = _pageto = _page = 1; - _preview_mask->run(); + const KEY key = _preview_mask->run(); set_win(NULL_WIN); delete _preview_mask; _preview_mask = NULL; + + if (key == K_INS) + print(); return true; } @@ -505,11 +530,11 @@ bool TReport_printer::open_page() if (ok && preview_mode()) // Clear page needed { clear(COLOR_WHITE); - set_pen(MAKE_COLOR(232,232,232)); const int max = 192; const int k = 100; for (int i = 1; i < max; i++) { + set_pen((i%10) ? MAKE_COLOR(232,232,232) : COLOR_LTGRAY); line(0, i*k, max*k, i*k); line(i*k, 0, i*k, max*k); } @@ -543,6 +568,7 @@ bool TReport_printer::close_page() long TReport_printer::print_section(TReport_section& rs) { + rs.load_fields(); rs.execute_prescript(); const long height = rs.compute_size().y; // Compute size after the initilization script! @@ -584,6 +610,8 @@ bool TReport_printer::print_loop() const long logical_footer_height = _report.section('F',0).compute_size().y; _logical_foot_pos = _logical_page_height - logical_footer_height; + _report.unmap_font(); // Gestire bene le riscalature + TString_array oldgroup, newgroup; const int max_group = _report.find_max_level('H'); if (max_group >= 2) @@ -595,10 +623,14 @@ bool TReport_printer::print_loop() _is_last_page = false; open_page(); + bool aborted = false; for (bool ok = rex.move_to(0); ok; ok = rex.move_next()) { if (_pageto >= _pagefrom && _page > _pageto) // out of range + { + aborted = true; break; + } if (max_group >= 2) // Gestione raggruppamenti { @@ -609,7 +641,7 @@ bool TReport_printer::print_loop() const TString& expr = _report.section('H', g).grouped_by(); _report.evaluate(expr, var, _alfafld); newgroup.add(var.as_string(), g); - if (newgroup.row(g) != oldgroup.row(g)) + if (newgroup.row(g) != oldgroup.row(g) || rex.current_row() == 0) changed = g; } if (changed) @@ -628,10 +660,19 @@ bool TReport_printer::print_loop() for (int b = 1; b <= max_body; b++) _delta.y += print_section('B', b); } - if (rex.eof()) - print_section('F', 1); - _is_last_page = true; - close_page(); + if (!aborted) + { + if (max_group >= 2) // Devo stampare tutte le code dei raggrupamenti + { + for (int g = 2; g <= max_group; g++) + _delta.y += print_section('F', g); + } + + if (rex.eof()) + print_section('F', 1); + _is_last_page = true; + close_page(); + } _lastprinted = _page; return true; diff --git a/ba/ba8303.uml b/ba/ba8303.uml index 4b4118576..478651ce4 100755 --- a/ba/ba8303.uml +++ b/ba/ba8303.uml @@ -1,5 +1,12 @@ TOOLBAR "Toolbar" 0 -2 0 2 +BUTTON DLG_PRINT 10 2 +BEGIN + PROMPT -16 -1 "~Stampa" + PICTURE BMP_PRINT + MESSAGE EXIT,K_INS +END + BUTTON DLG_PREVREC 3 BEGIN PROMPT -46 -2 "" diff --git a/ba/ba8304.cpp b/ba/ba8304.cpp index c298498f3..371f4205e 100755 --- a/ba/ba8304.cpp +++ b/ba/ba8304.cpp @@ -1,10 +1,7 @@ #include #include -#include -#include -#include - +#include #include "ba8304.h" TVariant& TVariant_stack::peek(int depth) @@ -13,29 +10,64 @@ TVariant& TVariant_stack::peek(int depth) return sp >= 0 ? (TVariant&)_var[sp] : NULL_VARIANT; } +bool TVariant_stack::drop() +{ + if (_sp > 0) + { + _sp--; + return true; + } + return false; +} + TVariant& TVariant_stack::pop() { - TVariant& var = peek(); - if (_sp > 0) - _sp--; + TVariant& var = peek(0); + drop(); return var; } -void TVariant_stack::push(const TVariant& var) +void TVariant_stack::roll(int depth) +{ + const int sp = _sp-depth-1; + if (sp >= 0) + { + TObject* var = _var.remove(sp); + _var.insert(var, _sp-1); + } +} + +bool TVariant_stack::push(const TVariant& var) { if (_var.objptr(_sp) == NULL) _var.add(var, _sp); else (TVariant&)_var[_sp] = var; _sp++; + return _sp < 1024; +} + +bool TVariant_stack::push(long n) +{ + const TVariant var(n); + return push(var); +} + +bool TVariant_stack::push(const real& n) +{ + const TVariant var(n); + return push(var); } /////////////////////////////////////////////////////////// // TAVM_op /////////////////////////////////////////////////////////// -enum AVM_opcode { avm_nop, avm_add, avm_dot, avm_dup, avm_push, avm_sub, - avm_usrget, avm_usrset, avm_usrword }; +enum AVM_opcode { avm_nop, avm_add , avm_div , avm_dot, + avm_cmp_eq, avm_cmp_gt, avm_cmp_gteq, avm_cmp_lt, avm_cmp_lteq, avm_cmp_noteq, + avm_drop, avm_dup, + avm_fetch, avm_if, avm_push, avm_rot, avm_store, + avm_sub, avm_swap, avm_then, avm_usrword }; class TAVM_op : public TObject { @@ -87,6 +119,7 @@ protected: public: const TString& get_last_error() const { return _last_error; } + bool compile_legacy_message(istream& instr, TBytecode& bytecode); bool compile(istream& instr, TBytecode& bc); bool execute(const TBytecode& bc, ostream& outstr); @@ -108,28 +141,41 @@ bool TAVM::get_token(istream& instr, TString& str) const char c; instr.get(c); str << c; - char* buf = str.get_buffer()+1; - const int bufsize = str.size()-1; if (c == '"') { + char* buf = str.get_buffer()+1; + const int bufsize = str.size()-1; instr.getline(buf, bufsize, '"'); str << '"'; } else - instr.getline(buf, bufsize, ' '); + { + instr.get(c); + while (!isspace(c) && c != EOF) + { + str << c; + instr.get(c); + } + } return *str > ' '; } AVM_opcode TAVM::token2opcode(const TString& str) const { - const char* AVM_TOKENS[4] = { - "+", "-", ".", + const char* AVM_TOKENS[19] = { + "+", "-", ".", "!", "@", "/", + "=", "<>", ">", "<", ">=", "<=", + "DROP", "DUP", "IF", "ROT", "SWAP", + "THEN", NULL }; - AVM_opcode AVM_OPCODES[4] = { - avm_add, avm_sub, avm_dot, + AVM_opcode AVM_OPCODES[19] = { + avm_add, avm_sub, avm_dot, avm_store, avm_fetch, avm_div, + avm_cmp_eq, avm_cmp_noteq, avm_cmp_gt, avm_cmp_lt, avm_cmp_gteq, avm_cmp_lteq, + avm_drop, avm_dup, avm_if, avm_rot, avm_swap, + avm_then, avm_nop }; @@ -145,8 +191,15 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode) { TString str(256); bytecode.destroy(); - bytecode.set_language("Alex"); - while (get_token(instr, str)) + + bool ok = get_token(instr, str); + if (ok && str == "MESSAGE") + { + instr.seekg(0); + return compile_legacy_message(instr, bytecode); + } + + while (ok) { TAVM_op* op = NULL; if (str[0] == '"') @@ -154,25 +207,46 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode) str.rtrim(1); str.ltrim(1); op = new TAVM_op(avm_push, str); } else - if (str[0] == '@') // Address of field? - { - str.ltrim(1); - op = new TAVM_op(avm_push, str); - } else if (isdigit(str[0])) { const real r(str); op = new TAVM_op(avm_push, r); } else - if (str[0] == '#') + if (str[0] == '#') // User variable { - op = new TAVM_op(avm_usrget, str); + op = new TAVM_op(avm_push, str); } else { const AVM_opcode oc = token2opcode(str); if (oc != avm_nop) - op = new TAVM_op(oc); + { + switch (oc) + { + case avm_then: + { + for (int i = bytecode.last(); i >= 0; i--) + { + TAVM_op& ifop = (TAVM_op&)bytecode[i]; + if (ifop.op() == avm_if && ifop.var().is_null()) + { + ifop.var() = bytecode.size(); + break; + } + } + if (i < 0) + { + _last_error = "THEN without matching IF"; + log_error(_last_error); + return false; + } + } + break; + default: + op = new TAVM_op(oc); + break; + } + } else { const unsigned int oc = _vm->compile_usr_word(str); @@ -188,6 +262,7 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode) log_error(_last_error); return false; } + ok = get_token(instr, str); } return true; } @@ -208,9 +283,99 @@ bool TAVM::execute(const TBytecode& bc, ostream& outstr) v0.add(v1); } break; + case avm_cmp_eq: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 == v1); + } + break; + case avm_cmp_gt: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 > v1); + } + break; + case avm_cmp_gteq: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 >= v1); + } + break; + case avm_cmp_lt: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 < v1); + } + break; + case avm_cmp_lteq: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 <= v1); + } + break; + case avm_cmp_noteq: + { + const TVariant& v0 = _stack.pop(); + const TVariant& v1 = _stack.pop(); + _stack.push(v0 != v1); + } + break; + case avm_div: + { + const real& r0 = _stack.pop().as_real(); + const real& r1 = _stack.pop().as_real(); + real n; + if (!r0.is_zero()) + n = r1 / r0; + const TVariant var(n); + _stack.push(var); + } + break; case avm_dot: outstr << _stack.pop().as_string(); break; + case avm_drop: _stack.drop(); break; case avm_dup: _stack.push(_stack.peek()); break; + case avm_fetch: + { + const TString& name = _stack.pop().as_string(); + TVariant var; + if (name[0] == '#') + _vm->get_usr_val(name, var); + else + { + // TBI: Get global var + } + _stack.push(var); + } + break; + case avm_if: + if (!_stack.pop().as_bool()) + { + ip = op.var().as_int(); + jumped_elsewhere = true; + } + break; case avm_push: _stack.push(op.var()); break; + case avm_rot: _stack.roll(2); break; + case avm_store: + { + const TString& name = _stack.pop().as_string(); + const TVariant& var = _stack.pop(); + if (name[0] == '#') + { + const TFixed_string usr((const char*)name+1); + _vm->set_usr_val(usr, var); + } + else + { + // TBI: Set global var + } + } + break; case avm_sub : { const TVariant& v1 = _stack.pop(); @@ -218,13 +383,7 @@ bool TAVM::execute(const TBytecode& bc, ostream& outstr) v0.sub(v1); } break; - case avm_usrget: - { - const TString& name = op.var().as_string(); - TVariant var; _vm->get_usr_val(name, var); - _stack.push(var); - } - break; + case avm_swap: _stack.roll(1); break; case avm_usrword: _vm->execute_usr_word(op.var().as_int(), _stack); break; default: _last_error << "Bad op code: " << op.op() << '\n'; @@ -237,6 +396,30 @@ bool TAVM::execute(const TBytecode& bc, ostream& outstr) return true; } +bool TAVM::compile_legacy_message(istream& instr, TBytecode& bytecode) +{ + TToken_string line(1024); + while (instr.getline(line.get_buffer(), line.size())) if (line.starts_with("MESSAGE ")) + { + line.ltrim(8); line.trim(); + const bool msg_empty = line.starts_with("EMPTY "); + if (msg_empty) + { + line.ltrim(6); + line.trim(); + } + TToken_string cmd(80, ','); + FOR_EACH_TOKEN(line, tok) + { + cmd = tok; + if (cmd.starts_with("CO")) + { + } + } + } + return true; +} + /////////////////////////////////////////////////////////// // TAlex_virtual_machine /////////////////////////////////////////////////////////// @@ -276,13 +459,35 @@ bool TAlex_virtual_machine::execute(const TBytecode& bc, TString& outs) return execute(bc, outstr); } -bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) const +bool TAlex_virtual_machine::get_usr_val(const char* code, TVariant& var) const { + const TFixed_string name(*code != '#' ? code : code+1); + if (name == "DATE") + { + const TDate oggi(TODAY); + var.set(oggi); + return true; + } + if (name == "FIRM") + { + var.set(prefix().get_codditta()); + return true; + } + if (name == "STUDY") + { + var.set(firm2dir(-1)); + return true; + } return false; } -bool TAlex_virtual_machine::set_usr_val(const TString& name, const TVariant& var) +bool TAlex_virtual_machine::set_usr_val(const char* code, const TVariant& var) { + const TFixed_string name(*code != '#' ? code : code+1); + if (name == "FIRM") + { + return prefix().set_codditta(var.as_int()); + } return false; } diff --git a/ba/ba8304.h b/ba/ba8304.h index 33e3e83c0..65cd3eb90 100755 --- a/ba/ba8304.h +++ b/ba/ba8304.h @@ -12,9 +12,15 @@ class TVariant_stack : public TObject public: int items() const { return _sp; } - void push(const TVariant& var); + bool drop(); TVariant& pop(); TVariant& peek(int depth = 0); + void roll(int depth); + + bool push(const TVariant& var); + bool push(long n); + bool push(const real& n); + TVariant_stack() : _sp(0) { } }; @@ -22,13 +28,9 @@ public: class TBytecode : public TArray { - TString16 _language; TString _name; public: - void set_language(const char* lang) { _language = lang; } - const TString& language() const { return _language; } - const set_name(const char* name) { _name = name; } const TString& name() const { return _name; } }; @@ -44,8 +46,8 @@ class TAlex_virtual_machine : public TObject public: virtual unsigned int compile_usr_word(const TString& name) const; 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 bool get_usr_val(const char* name, TVariant& var) const; + virtual bool set_usr_val(const char* name, const TVariant& var); const TString& get_last_error() const; bool compile(istream& instr, TBytecode& bc);