diff --git a/include/alex.cpp b/include/alex.cpp index e518b0e8f..d7e8e4cf1 100755 --- a/include/alex.cpp +++ b/include/alex.cpp @@ -1,85 +1,17 @@ #include #include +#include #include #include +#include #include #include #include -#include #include +#include #include -TVariant& TVariant_stack::peek(int depth) -{ - const int sp = _sp-depth-1; - return sp >= 0 ? (TVariant&)_var[sp] : (TVariant &)NULL_VARIANT; -} - -bool TVariant_stack::drop() -{ - if (_sp > 0) - { - _sp--; - return true; - } - return false; -} - -TVariant& TVariant_stack::pop() -{ - TVariant& var = peek(0); - drop(); - return var; -} - -void TVariant_stack::roll(int depth) -{ - const int sp = _sp-depth-1; - if (sp >= 0) - { - TObject* var = _var.remove(sp, true); - _var.insert(var, _sp-1); - } -} - -void TVariant_stack::push(const TVariant& var) -{ - if (_var.objptr(_sp) == NULL) - _var.add(var, _sp); - else - (TVariant&)_var[_sp] = var; - _sp++; -} - -void TVariant_stack::push(long n) -{ - const TVariant var(n); - push(var); -} - -void TVariant_stack::push(const real& n) -{ - const TVariant var(n); - push(var); -} - -void TVariant_stack::push(const char* str) -{ - const TVariant var(str); - push(var); -} - -void TVariant_stack::reset() -{ - _sp = 0; -} - -bool TVariant_stack::overflow() const -{ - return _sp > 2048; -} - /////////////////////////////////////////////////////////// // TAVM_op /////////////////////////////////////////////////////////// @@ -391,15 +323,17 @@ TField_window* TAVM_stack_field::create_window(int x, int y, int dx, int dy, WIN class TAVM_monitor : public TAutomask { + TAVM_list_window *_lw; + TAVM_stack_window *_sw, *_rw; + protected: - TMask_field* parse_field(TScanner& scanner); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual bool on_key(KEY k); public: - TAVM_list_window& monitor() { return (TAVM_list_window&)((TAVM_list_field&)field(101)).win(); } - TAVM_stack_window& stacker() { return (TAVM_stack_window&)((TAVM_list_field&)field(102)).win(); } - TAVM_stack_window& rstacker() { return (TAVM_stack_window&)((TAVM_list_field&)field(103)).win(); } + TAVM_list_window& monitor() const { return *_lw; } + TAVM_stack_window& stacker() const { return *_sw; } + TAVM_stack_window& rstacker() const { return *_rw; } TAVM_monitor(); }; @@ -421,18 +355,25 @@ bool TAVM_monitor::on_key(KEY k) return TAutomask::on_key(k); } -TMask_field* TAVM_monitor::parse_field(TScanner& scanner) +TAVM_monitor::TAVM_monitor() : TAutomask("Monitor", 1, 50, 20) { - if (scanner.token().starts_with("LI")) - return new TAVM_list_field(this); - if (scanner.token().starts_with("ST")) - return new TAVM_stack_field(this); - return TAutomask::parse_field(scanner); -} + TWindowed_field* wf = new TAVM_list_field(this); + wf->create(101, 0, 0, 24, -3); add_field(wf); + _lw = (TAVM_list_window*)&wf->win(); + + TWindowed_field* sf = new TAVM_stack_field(this); + sf->create(102, 27, 0, -3, 10); add_field(sf); + _sw = (TAVM_stack_window*)&sf->win(); + + TWindowed_field* rf = new TAVM_stack_field(this); + rf->create(103, 27, 11, -3, -3); add_field(rf); + _rw = (TAVM_stack_window*)&rf->win(); + + add_button(DLG_NEXTREC, 0, "", -14, -1, 10, 2, "", 124).set_exit_key(K_F11); + add_button(DLG_LASTREC, 0, "", -24, -1, 10, 2, "", 1671).set_exit_key(K_F10); + add_button(DLG_ELABORA, 0, "", -34, -1, 10, 2, "", BMP_LASTREC).set_exit_key(K_F5); + add_button(DLG_QUIT, 0, "", -44, -1, 10, 2).set_exit_key(K_QUIT); -TAVM_monitor::TAVM_monitor() -{ - read_mask("ba8300m", 0, -1); set_handlers(); } @@ -1040,6 +981,7 @@ bool TAVM::execute(const TBytecode& cmdline) { const TBytecode* old_bc = _bc; const int old_ip = _ip; + bool aborted = false; _stack.reset(); _rstack.reset(); @@ -1100,7 +1042,7 @@ bool TAVM::execute(const TBytecode& cmdline) op.set_auto_break(true); } break; - case K_QUIT: abort_printing(); + case K_QUIT: aborted = true; case K_F5 : _mon.close_modal(); break; default: break; } @@ -1118,7 +1060,7 @@ bool TAVM::execute(const TBytecode& cmdline) _bc = old_bc; _ip = old_ip; - return true; + return !aborted; } void TAVM::do_restart(bool cold) diff --git a/include/alex.h b/include/alex.h index 092009a26..804666555 100755 --- a/include/alex.h +++ b/include/alex.h @@ -1,32 +1,10 @@ #ifndef __ALEX_H #define __ALEX_H -#ifndef __RECORDSET_H -#include +#ifndef __VARIANT_H +#include #endif -class TVariant_stack : public TObject -{ - TArray _var; - int _sp; - -public: - int items() const { return _sp; } - bool drop(); - TVariant& pop(); - TVariant& peek(int depth = 0); - void roll(int depth); - - void push(const TVariant& var); - void push(long n); - void push(const real& n); - void push(const char* str); - void reset(); - bool overflow() const; - - TVariant_stack() : _sp(0) { } -}; - // Generic bytecode for any language class TBytecode : public TArray diff --git a/include/automask.cpp b/include/automask.cpp index b022e7a17..30af4f05b 100755 --- a/include/automask.cpp +++ b/include/automask.cpp @@ -165,7 +165,12 @@ void TAutomask::set_handlers() TAutomask::TAutomask(const char* name, int num) - : TMask(name, num) + : TMask(name, num) { set_handlers(); } + +TAutomask::TAutomask(const char* title, int pages, int cols, int rows, int xpos, int ypos) + : TMask(title, pages, cols, rows, xpos, ypos) +{ +} diff --git a/include/automask.h b/include/automask.h index 10c2bba81..39d2bb71b 100755 --- a/include/automask.h +++ b/include/automask.h @@ -28,6 +28,7 @@ public: TAutomask() { } TAutomask(const char* name, int num = 0); + TAutomask(const char* title, int pages, int cols, int rows, int xpos = -1, int ypos = -1); virtual ~TAutomask() { } }; diff --git a/include/checks.cpp b/include/checks.cpp index 92cf7bcf0..99ec541b2 100755 --- a/include/checks.cpp +++ b/include/checks.cpp @@ -3,7 +3,11 @@ #include #include +#ifdef WIN32 +#define buildmsg() char msg[256];va_list argptr;va_start(argptr,fmt);_vsnprintf(msg,sizeof(msg),fmt,argptr);va_end(argptr) +#else #define buildmsg() char msg[256];va_list argptr;va_start(argptr,fmt);vsprintf(msg,fmt,argptr);va_end(argptr) +#endif // @doc EXTERNAL diff --git a/include/maskfld.cpp b/include/maskfld.cpp index abce6a21a..5542e73ad 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -4954,12 +4954,17 @@ TField_window* TWindowed_field::create_window(int x, int y, int dx, int dy, WIND return new TField_window(x, y, dx, dy, parent, this); } +void TWindowed_field::create(short id, int x, int y, int dx, int dy, WINDOW parent) +{ + if (parent == NULL_WIN) + parent = mask().win(); + _dlg = id; + _win = create_window(x, y, dx, dy, parent); +} + void TWindowed_field::create(WINDOW parent) { - _dlg = _ctl_data._dlg; - _win = create_window(_ctl_data._x, _ctl_data._y, - _ctl_data._width, _ctl_data._height, - parent); + create(_ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._height, parent); } TWindowed_field::~TWindowed_field() diff --git a/include/maskfld.h b/include/maskfld.h index ace84c807..5b816d28e 100755 --- a/include/maskfld.h +++ b/include/maskfld.h @@ -1578,7 +1578,6 @@ protected: // TMask_field protected: virtual TField_window* create_window(int x, int y, int dx, int dy, WINDOW parent) pure; - public: // TMask_field virtual short dlg() const; virtual WINDOW parent() const { return win().parent(); } @@ -1589,8 +1588,10 @@ public: // TMask_field public: TField_window& win() const { CHECK(_win, "NULL Window in field"); return *_win; } - + TWindowed_field(TMask* m) : TOperable_field(m), _dlg(0), _win(NULL) { } + void create(short id, int x, int y, int dx, int dy, WINDOW parent = NULL_WIN); + virtual ~TWindowed_field(); }; diff --git a/include/recset.cpp b/include/recset.cpp index 7cfcff3ba..2e8f8fe3d 100755 --- a/include/recset.cpp +++ b/include/recset.cpp @@ -10,252 +10,6 @@ #include -/////////////////////////////////////////////////////////// -// TVariant -/////////////////////////////////////////////////////////// - -const TVariant NULL_VARIANT; - -void TVariant::set_null() -{ - if (_ptr != NULL) - { - if (_type != _nullfld && _type != _longfld) - delete (char *) _ptr; - _ptr = NULL; - } - _type = _nullfld; -} - -void TVariant::set(const char* str) -{ - if (str != NULL) - { - if (_type == _alfafld) - *((TString*)_ptr) = str; - else - { - set_null(); - _type = _alfafld; - _ptr = new TString(str); - } - } - else - set_null(); -} - -void TVariant::set(const real& r) -{ - if (_type == _realfld) - *((real*)_ptr) = r; - else - { - set_null(); - _type = _realfld; - _ptr = new real(r); - } -} - -void TVariant::set(const TDate& d) -{ - if (_type == _datefld) - *((TDate*)_ptr) = d; - else - { - set_null(); - _type = _datefld; - _ptr = new TDate(d); - } -} - -void TVariant::set(const long n) -{ - if (_type != _longfld) - set_null(); - _type = _longfld; - _ptr = (void*)n; -} - -bool TVariant::is_zero() const -{ - switch (_type) - { - case _datefld: return !as_date().ok(); - case _longfld: return _ptr == NULL; - case _realfld: return as_real().is_zero(); - case _alfafld: return real::is_null(as_string()); - default: break; - } - return true; -} - -bool TVariant::is_empty() const -{ - if (_type == _alfafld) - return as_string().empty(); - return is_zero(); -} - -TDate TVariant::as_date() const -{ - if (_type == _datefld) - return *(TDate*)_ptr; - if (_type == _intfld || _type == _realfld) - return TDate(as_int()); - return TDate(as_string()); -} - -long TVariant::as_int() const -{ - long n = 0; - switch(_type) - { - case _datefld: n = as_date().date2ansi(); break; - case _longfld: n = (long)_ptr; break; - case _realfld: n = as_real().integer(); break; - case _alfafld: n = atoi(as_string()); break; - default : break; - } - return n; -} - -bool TVariant::as_bool() const -{ - bool ok = false; - if (_type == _alfafld) - ok = strchr("1XY", as_string()[0]) != NULL; - else - ok = as_int() != 0; - 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) - return *(real*)_ptr; - switch(_type) - { - case _alfafld: return real(as_string()); break; - case _longfld: return real(as_int()); break; - default : break; - } - return ZERO; -} - -bool TVariant::as_string(TString& tmp) const -{ - tmp.cut(0); - switch(_type) - { - case _alfafld: tmp = *(TString*)_ptr; break; - case _datefld: tmp = as_date().string(); break; - case _longfld: tmp << as_int(); break; - case _realfld: tmp = as_real().string(); break; - default: break; - } - return !is_null(); -} - -const TString& TVariant::as_string() const -{ - if (_type == _alfafld) - return *(TString*)_ptr; - TString& tmp = get_tmp_string(); - as_string(tmp); - return tmp; -} - -void TVariant::convert_to(TFieldtypes ft) -{ - if (_type != ft) - { - switch (ft) - { - case _alfafld: set(as_string()); break; - case _datefld: set(as_date()); break; - case _longfld: set(as_int()); break; - case _realfld: set(as_real()); break; - default : set_null(); break; - } - } -} - -void TVariant::copy(const TVariant& var) -{ - switch (var._type) - { - case _datefld: set(var.as_date()); break; - case _longfld: set(var.as_int()); break; - case _realfld: set(var.as_real()); break; - case _alfafld: set(var.as_string()); break; - default : set_null(); break; - } -} - -int TVariant::compare(const TSortable& s) const -{ - const TVariant& var = (const TVariant&)s; - int cmp = 0; - switch (_type) - { - case _datefld: cmp = as_date() - var.as_date(); break; - case _longfld: cmp = as_int() - var.as_int(); break; - case _realfld: - { - const real n = as_real() - var.as_real(); - cmp = n.sign(); - } - break; - case _alfafld: cmp = as_string().compare(var.as_string()); break; - default : cmp = var.is_null() ? 0 : -1; - } - return cmp; -} - -TVariant& TVariant::add(const TVariant& var) -{ - switch (_type) - { - case _datefld: set(as_date() + var.as_int()); break; - case _longfld: set(as_int() + var.as_int()); break; - case _alfafld: *(TString*)_ptr << var.as_string(); break; - case _realfld: *(real*)_ptr += var.as_real(); break; - default: copy(var); break; - } - return *this; -} - -TVariant& TVariant::sub(const TVariant& var) -{ - switch (_type) - { - case _datefld: set(as_date() - var.as_int()); break; - case _longfld: - if (var.type() == _longfld) - { - set(as_int() - var.as_int()); - break; - } - // Fall down - default: - { - real n = as_real(); - n -= var.as_real(); - set(n); - } - break; - } - return *this; -} /////////////////////////////////////////////////////////// // TTable name converter diff --git a/include/recset.h b/include/recset.h index b11c21c8a..cbd44e517 100755 --- a/include/recset.h +++ b/include/recset.h @@ -9,6 +9,10 @@ #include #endif +#ifndef __VARIANT_H +#include +#endif + struct TRecordset_column_info : public TObject { TString _name; // Table.Column @@ -16,64 +20,6 @@ struct TRecordset_column_info : public TObject TFieldtypes _type; }; -/////////////////////////////////////////////////////////// -// TVariant -/////////////////////////////////////////////////////////// - -class TVariant : public TSortable -{ - TFieldtypes _type; - void* _ptr; - -protected: - virtual TObject* dup() const { return new TVariant(*this); } - void copy(const TVariant& var); - -public: - TFieldtypes type() const { return _type; } // Internal use only - bool is_string() const { return _type == _alfafld; } - bool is_empty() const; - bool is_null() const { return _type == _nullfld; } - bool is_zero() const; - void set_null(); - - void set(const char* str); - void set(const real& r); - void set(const long n); - void set(const TDate& d); - - TVariant& operator=(const TVariant& var) { copy(var); return *this; } - TVariant& operator=(const char* str) { set(str); return *this; } - TVariant& operator=(const real& r) { set(r); return *this; } - TVariant& operator=(const long n) { set(n); return *this; } - TVariant& operator=(const TDate& d) { set(d); return *this; } - - const TString& as_string() const; - bool as_string(TString& str) const; - real as_real() const; - long as_int() const; - TDate as_date() const; - bool as_bool() const; - COLOR as_color() const; - - void convert_to(TFieldtypes ft); - - virtual int compare(const TSortable& s) const; - TVariant& add(const TVariant& var); - TVariant& sub(const TVariant& var); - - TVariant() : _type(_nullfld), _ptr(NULL) { } - TVariant(const char* str) : _type(_alfafld), _ptr(new TString(str)) { } - TVariant(const real& num) : _type(_realfld), _ptr(new real(num)) { }; - TVariant(const TDate& d) : _type(_datefld), _ptr(new TDate(d)) { }; - TVariant(long num) : _type(_longfld), _ptr((void*)num) { }; - TVariant(bool ok) : _type(_longfld), _ptr((void*)ok) { }; - TVariant(const TVariant& var) : _type(_nullfld), _ptr(NULL) { copy(var); } - virtual ~TVariant() { set_null(); } -}; - -extern const TVariant NULL_VARIANT; - /////////////////////////////////////////////////////////// // TRecordset /////////////////////////////////////////////////////////// diff --git a/include/report.cpp b/include/report.cpp index 47048d277..538fab161 100755 --- a/include/report.cpp +++ b/include/report.cpp @@ -274,146 +274,6 @@ TReport_image_cache::TReport_image_cache() : TCache(7) { } -/////////////////////////////////////////////////////////// -// Utility -/////////////////////////////////////////////////////////// - -bool advanced_set_draw_tools(TWindow& win, int border, COLOR fore, COLOR back) -{ - const bool has_pen = border > 0; - const bool has_brush = (back & 0xFFFFFF) != (COLOR_WHITE & 0xFFFFFF); - const bool visible = has_pen || has_brush; - if (visible) - { - if (has_pen) - win.set_pen(fore, border, PAT_SOLID); - else - win.hide_pen(); - if (has_brush) - win.set_brush(back, PAT_SOLID); - else - win.hide_brush(); - } - return visible; -} - -void advanced_draw_rect(TWindow& win, const RCT& r, int border, COLOR fore, COLOR back) -{ - if (advanced_set_draw_tools(win, border, fore, back)) - xvt_dwin_draw_rect(win.win(), (RCT*)&r); -} - -void advanced_draw_justified_text(TWindow& win, const char* text, short x, short y, short dx) -{ - TString txt(text); txt.rtrim(); - int spaces = 0; - for (int s = 0; txt[s]; s++) - if (isspace(txt[s])) spaces++; - const int tw = xvt_dwin_get_text_width(win.win(), txt, -1); - if (tw < dx && spaces > 0) - { - txt << ' '; // Aggiunge spazio finale - const double kspc = double(dx - tw) / spaces; - int start = 0; - double kx = x; - for (int i = 0; txt[i]; i++) - { - if (isspace(txt[i])) - { - const bool last_word = txt[i+1] == '\0'; - const TString& parola = txt.sub(start, i + (last_word ? 0 : 1)); - const int lw = xvt_dwin_get_text_width(win.win(), parola, -1); - if (last_word) // ultima parola - kx = x+dx-lw; - xvt_dwin_draw_text(win.win(), int(kx+0.5), y, parola, -1); - kx += lw + kspc; - start = i+1; - } - } - } - else - xvt_dwin_draw_text(win.win(), x, y, text, -1); -} - -void advanced_draw_text(TWindow& win, const char* text, const RCT& r, - char halign, char valign) -{ - const short dx = r.right-r.left; - const short dy = r.bottom-r.top; - short x = r.left; - short y = r.bottom; - - if (halign != 'L') - { - const int tw = xvt_dwin_get_text_width(win.win(), text, -1); - switch (halign) - { - case 'C': x += (dx - tw)/2; break; - case 'R': x = r.right-tw; break; - default : break; - } - } - - // Text Height - int leading, ascent, descent; - xvt_dwin_get_font_metrics(win.win(), &leading, &ascent, &descent); - switch (valign) - { - case 'C': y -= (dy - ascent)/2; break; - case 'T': y = r.top + leading + ascent; break; - default : y -= descent; break; - } - - if (halign == 'J') - advanced_draw_justified_text(win, text, x, y, dx); - else - xvt_dwin_draw_text(win.win(), x, y, text, -1); -} - -void advanced_draw_paragraph(TWindow& win, TString& para, const RCT& rct, - char halign, char valign) -{ - const bool acapo = para.find('\n') >= 0; - - int leading, ascent, descent; - xvt_dwin_get_font_metrics(win.win(), &leading, &ascent, &descent); - const int ky = leading + ascent + descent; - - const int rct_height = rct.bottom - rct.top; - int rows = (rct_height+ky/2) / ky; - - if (acapo || rows > 1) // Devo scrivere piu' righe? - { - const int kx = xvt_dwin_get_text_width(win.win(), "ABCDEFGH", 8) / 8; - const unsigned columns = (rct.right - rct.left) / kx; - - TParagraph_string str(para, columns); - if (str.items() < rows) - rows = str.items(); - - int ybase = rct.top; - switch (valign) - { - case 'C': ybase += (rct_height - rows*ky) / 2; break; - case 'B': ybase += rct_height - rows*ky; break; - default : break; - } - - for (int row = 0; row < rows; row++) - { - RCT rctline = rct; - rctline.top = ybase + ky*row; - rctline.bottom = rctline.top + ky; - const char* line = str.get(); - if (halign == 'J' && (row == rows-1 || strlen(line) < columns/2)) - halign = 'L'; - advanced_draw_text(win, line, rctline, halign, 'T'); - } - } - else - advanced_draw_text(win, para, rct, halign, valign); -} - static void set_num_attr(TXmlItem& item, const char* attr, long num, short def = 0) { if (num != def) @@ -569,6 +429,14 @@ TPoint TReport_section::compute_size() const return TPoint(0,0); TPoint s = _size; + + // Lo sfondo occupa sempre tutta la pagina + if (type() == 'B' && level() == 0) + { + s.x = s.y = 19600; + return s; + } + if (_size.x <= 0 || _size.y <= 0) // Calcolo automatico necessario { for (int i = 0; i < items(); i++) @@ -588,6 +456,7 @@ TPoint TReport_section::compute_size() const if ((s.y % 100) != 0) // Arrotonda alla riga successiva s.y = (s.y / 100 + 1) * 100; } + return s; } @@ -622,18 +491,45 @@ bool TReport_section::execute_prescript() report().set_curr_field(NULL); ok = _prescript.execute(report()); } - for (int i = 0; i < items(); i++) + for (int i = 0; ok && i < items(); i++) { TReport_field& f = field(i); - f.execute_prescript(); + ok = f.execute_prescript(); } return ok; } +bool TReport_section::print_tools(TBook& book) const +{ + const bool has_pen = border() > 0; + const bool has_brush = pattern() >= PAT_SOLID && back_color() != COLOR_WHITE; + const bool visible = has_pen || has_brush; + if (visible) + { + book.set_pen(fore_color(), border()-1); + book.set_brush(back_color(), pattern()); + } + return visible; +} + void TReport_section::print(TBook& book) const { if (shown() && active()) { + if (print_tools(book)) + { + TRectangle rct; compute_rect(rct); + if (_size.x <= 0) + rct.set_width(book.logical_page_width()); + if (type() == 'B' && level() <= 0) + rct.set_height(book.logical_page_height()); + + if (radius() > 0) + book.draw_round_rectangle(rct, radius()); + else + book.draw_rectangle(rct); + } + for (int i = 0; i < items(); i++) { const TReport_field& f = field(i); @@ -671,6 +567,18 @@ void TReport_section::save(TXmlItem& root) const set_num_attr(item, "y", pos().y); set_num_attr(item, "width", width()); set_num_attr(item, "height", height()); + + set_col_attr(item, "bg_color", back_color(), COLOR_WHITE); + set_col_attr(item, "fg_color", fore_color(), COLOR_BLACK); + if (border() > 0) + { + item.SetAttr("border", border()); + if (radius() > 0) + item.SetAttr("radius", radius()); + } + if (pattern() != PAT_HOLLOW) + item.SetAttr("pattern", pattern()); + item.SetAttr("hidden", _hidden); item.SetAttr("deactivated", _deactivated); item.SetAttr("hidden_if_needed", hidden_if_needed()); @@ -699,6 +607,13 @@ void TReport_section::load(const TXmlItem& sec) _pos.y = get_num_attr(sec, "y"); set_width(get_num_attr(sec, "width")); set_height(get_num_attr(sec, "height")); + + set_border(sec.GetIntAttr("border")); + set_pattern((PAT_STYLE)sec.GetIntAttr("pattern", PAT_HOLLOW)); + set_radius(sec.GetIntAttr("radius")); + set_back_color(get_col_attr(sec, "bg_color", COLOR_WHITE)); + set_fore_color(get_col_attr(sec, "fg_color", COLOR_BLACK)); + force_page_break(sec.GetBoolAttr("pagebreak")); keep_with_next(sec.GetBoolAttr("keep_with_next")); hide_if_needed(sec.GetBoolAttr("hidden_if_needed")); @@ -751,7 +666,9 @@ void TReport_section::load(const TXmlItem& sec) TReport_section::TReport_section(TReport& r, char t, int l) : _report(r), _type(t), _level(l), _pos(0,0), _size(0,0), _page_break(false), _hidden_if_needed(false), - _repeat(false), _hidden(false), _deactivated(false), _font(NULL) + _repeat(false), _hidden(false), _deactivated(false), _font(NULL), + _bgcolor(COLOR_WHITE), _fgcolor(COLOR_BLACK), _pattern(PAT_HOLLOW), + _border(0), _radius(0) @@ -949,10 +866,23 @@ TReport_script::~TReport_script() struct TReport_array_item : public TObject { +protected: + virtual TObject* dup() const; + +public: TString _code, _value; TReport_script _script; }; +TObject* TReport_array_item::dup() const +{ + TReport_array_item* i = new TReport_array_item; + i->_code = _code; + i->_value = _value; + i->_script = _script; + return i; +} + /////////////////////////////////////////////////////////// // TReport_field /////////////////////////////////////////////////////////// @@ -1067,18 +997,19 @@ void TReport_field::copy(const TReport_field& rf) _rct = rf._rct; set_dynamic_height(rf.dynamic_height()); _fgcolor = rf._fgcolor; _bgcolor = rf._bgcolor; - _border = rf._border; + _border = rf._border; _radius = rf._radius; _pattern = rf._pattern; _halign = rf._halign; _valign = rf._valign; _picture = rf._picture; _field = rf._field; _hidden = rf.hidden(); _deactivated = rf.deactivated(); _hide_zeroes = rf._hide_zeroes; - _selected = false; + _field = rf._field; _alt_field = rf._alt_field; _prescript = rf._prescript; _postscript = rf._postscript; _list = rf._list; set_font(rf.font()); + _selected = false; } const char* TReport_field::type_name() const @@ -1226,9 +1157,14 @@ TReport_array_item* TReport_field::get_array_item() const return NULL; } +bool TReport_field::zeroes_hidden() const +{ + return _hide_zeroes && strchr("DNVP", _type) != NULL; +} + const TString& TReport_field::formatted_text() const { - if (_hide_zeroes && _var.is_zero()) + if (zeroes_hidden() && _var.is_zero()) return EMPTY_STRING; switch (type()) @@ -1306,12 +1242,12 @@ const TString& TReport_field::formatted_text() const bool TReport_field::print_tools(TBook& book) const { const bool has_pen = border() > 0; - const bool has_brush = (back_color() & 0xFFFFFF) != (COLOR_WHITE & 0xFFFFFF); + const bool has_brush = pattern() >= PAT_SOLID; const bool visible = has_pen || has_brush; if (visible) { book.set_pen(fore_color(), border()-1); - book.set_brush(back_color(), has_brush ? PAT_SOLID : PAT_HOLLOW); + book.set_brush(back_color(), pattern()); } return visible; } @@ -1319,7 +1255,12 @@ bool TReport_field::print_tools(TBook& book) const void TReport_field::print_rect(TBook& book) const { if (print_tools(book)) - book.draw_rectangle(get_draw_rect()); + { + if (radius() > 0) + book.draw_round_rectangle(get_draw_rect(), radius()); + else + book.draw_rectangle(get_draw_rect()); + } } void TReport_field::print(TBook& book) const @@ -1428,7 +1369,7 @@ void TReport_field::save(TXmlItem& root) const fld.SetAttr("dynamic_height", dynamic_height()); fld.SetAttr("hidden", _hidden); fld.SetAttr("deactivated", _deactivated); - fld.SetAttr("hide_zero", _hide_zeroes); + fld.SetAttr("hide_zero", zeroes_hidden()); set_col_attr(fld, "bg_color", back_color(), COLOR_WHITE); set_col_attr(fld, "fg_color", fore_color(), COLOR_BLACK); if (has_font()) @@ -1449,7 +1390,14 @@ void TReport_field::save(TXmlItem& root) const case 'C': fld.SetAttr("valign", "center"); break; default : break; }; - fld.SetAttr("border", border()); + if (border() > 0) + { + fld.SetAttr("border", border()); + if (radius() > 0) + fld.SetAttr("radius", radius()); + } + if (pattern() != PAT_SOLID) + fld.SetAttr("pattern", pattern()); fld.SetAttr("text", picture()); fld.SetAttr("codval", codval()); fld.SetAttr("link", link()); @@ -1491,6 +1439,8 @@ bool TReport_field::load(const TXmlItem& fld) activate(!fld.GetBoolAttr("deactivated")); hide_zeroes(fld.GetBoolAttr("hide_zero")); set_border(fld.GetIntAttr("border")); + set_pattern((PAT_STYLE)fld.GetIntAttr("pattern", PAT_SOLID)); + set_radius(fld.GetIntAttr("radius")); set_back_color(get_col_attr(fld, "bg_color", COLOR_WHITE)); set_fore_color(get_col_attr(fld, "fg_color", COLOR_BLACK)); set_horizontal_alignment(get_chr_attr(fld, "align", 'L')); @@ -1578,7 +1528,7 @@ int TReport_field::compare(const TSortable& s) const TReport_field::TReport_field(TReport_section* sec) : _section(sec), _id(0), _type('T'), _rct(0,0,1000,100), - _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE), + _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE), _radius(0), _pattern(PAT_SOLID), _border(0), _halign('L'), _valign('T'),_dynamic_height(false), _font(NULL), _hidden(false), _deactivated(false), _hide_zeroes(false), _selected(false) { } @@ -1721,7 +1671,7 @@ int TReport::parse_field(const char* code, char& type, int& level, int& id) cons return strchr(code, '@') != NULL ? 4 : 3; } -TReport_field* TReport::field(const TString& code) +TReport_field* TReport::field(const char* code) { char type = ' '; int level = -1, id = 0; @@ -1984,26 +1934,25 @@ bool TReport::get_report_field(const TString& name, TVariant& var) const else str++; } - const TFixed_string n(str); + + TReport_field* fld = ((TReport*)this)->field(str); + if (fld != NULL) + { + var = fld->get(); + return true; + } - if (n == "PAGE") + if (xvt_str_compare_ignoring_case(str, "PAGE") == 0) { var = _rep_page; return true; } else - if (n == "BOOK.PAGE") + if (xvt_str_compare_ignoring_case(str, "BOOKPAGE") == 0) { var = _book_page; return true; } - TReport_field* fld = ((TReport*)this)->field(n); - if (fld != NULL) - { - var = fld->get(); - return true; - } - return found; } diff --git a/include/report.h b/include/report.h index 1b7f53a97..c0ddb7c28 100755 --- a/include/report.h +++ b/include/report.h @@ -149,6 +149,9 @@ class TReport_section : public TArray TString _condition, _groupby; bool _page_break, _hidden_if_needed, _keep_with_next, _repeat; bool _hidden, _deactivated; + COLOR _fgcolor, _bgcolor; + int _border, _radius; + PAT_STYLE _pattern; TReport_script _prescript, _postscript; TReport_font* _font; @@ -156,6 +159,7 @@ class TReport_section : public TArray protected: virtual const char* class_name() const { return "ReportSection"; } TReport_section* father_section() const; + bool print_tools(TBook& book) const; public: virtual int add(TObject* obj); @@ -178,6 +182,18 @@ public: bool compute_rect(TRectangle& rct) const; const TPoint& pos() const { return _pos; } void set_pos(const TPoint& p) { _pos = p; } + + void set_fore_color(COLOR c) { _fgcolor = c; } + COLOR fore_color() const { return _fgcolor; } + void set_back_color(COLOR c) { _bgcolor = c; } + COLOR back_color() const { return _bgcolor; } + void set_border(int b) { _border = b; } + short border() const { return _border; } + void set_pattern(PAT_STYLE p) { _pattern = p; } + PAT_STYLE pattern() const { return _pattern; } + void set_radius(int r) { _radius = r; } + short radius() const { return _radius; } + bool page_break() const { return _page_break; } void force_page_break(bool pb) { _page_break = pb; } void set_repeat_on_page(bool r) { _repeat = r; } @@ -233,7 +249,8 @@ class TReport_field : public TSortable char _type; // Text, String, Numeric, Price, Valuta, Date, Line, Rectangle, Image TRectangle _rct; // In centesimi COLOR _fgcolor, _bgcolor; - short _border; + int _border, _radius; + PAT_STYLE _pattern; char _halign, _valign; bool _dynamic_height; TBit_array _groups; @@ -314,7 +331,7 @@ public: bool active() const { return !deactivated(); } void activate(bool on) { _deactivated = !on; } void deactivate() { activate(false); } - bool zeroes_hidden() const { return _hide_zeroes; } + bool zeroes_hidden() const; void hide_zeroes(bool hz) { _hide_zeroes = hz; } bool draw_hidden() const { return _draw_hidden; } @@ -339,8 +356,14 @@ public: void set_back_color(COLOR c) { _bgcolor = c; } COLOR back_color() const { return _bgcolor; } COLOR link_color() const; - void set_border(short b) { _border = b; } + + void set_border(int b) { _border = b; } short border() const { return _border; } + void set_pattern(PAT_STYLE p) { _pattern = p; } + PAT_STYLE pattern() const { return _pattern; } + void set_radius(int r) { _radius = r; } + short radius() const { return _radius; } + void set_horizontal_alignment(char a) { _halign = a; } char horizontal_alignment() const { return _halign; } void set_vertical_alignment(char a) { _valign = a; } @@ -355,10 +378,6 @@ public: bool selected() const { return _selected; } void offset(const TPoint& pt); -// virtual void draw_rect(TWindow& win) const; -// virtual void draw_text(TWindow& win, const char* text, TReport_draw_mode mode) const; -// virtual void draw(TWindow& win, TReport_draw_mode mode) const; - virtual bool print_tools(TBook& book) const; virtual void print_rect(TBook& book) const; virtual void print(TBook& book) const; @@ -484,18 +503,11 @@ public: TReport_field* curr_field() const { return _curr_field; } int parse_field(const char* code, char& type, int& level, int& id) const; - TReport_field* field(const TString& code); + TReport_field* field(const char* code); void destroy(); TReport(); virtual ~TReport(); }; -bool advanced_set_draw_tools(TWindow& win, int border, COLOR fore, COLOR back); -void advanced_draw_rect(TWindow& win, const RCT& r, int border, COLOR fore, COLOR back); -void advanced_draw_text(TWindow& win, const char* text, const RCT& r, - char halign, char valign); -void advanced_draw_paragraph(TWindow& win, TString& text, const RCT& r, - char halign, char valign); - #endif diff --git a/include/reprint.cpp b/include/reprint.cpp index 3a5fc7712..04c9f8e8c 100755 --- a/include/reprint.cpp +++ b/include/reprint.cpp @@ -11,6 +11,151 @@ static bool _print_aborted = false; +/////////////////////////////////////////////////////////// +// Utility +/////////////////////////////////////////////////////////// + +bool advanced_set_draw_tools(TWindow& win, PAT_STYLE pat, int border, COLOR fore, COLOR back) +{ + const bool has_pen = border > 0; + const bool has_brush = pat > PAT_HOLLOW && back != COLOR_WHITE; + const bool visible = has_pen || has_brush; + if (visible) + { + if (has_pen) + win.set_pen(fore, border, PAT_SOLID); + else + win.hide_pen(); + if (has_brush) + win.set_brush(back, pat); + else + win.hide_brush(); + } + return visible; +} + +void advanced_draw_rect(TWindow& win, const RCT& r, PAT_STYLE pat, int border, COLOR fore, COLOR back, int radius) +{ + if (advanced_set_draw_tools(win, pat, border, fore, back)) + { + if (radius > 0) + xvt_dwin_draw_roundrect(win.win(), &r, radius, radius); + else + xvt_dwin_draw_rect(win.win(), (RCT*)&r); + } +} + +void advanced_draw_justified_text(TWindow& win, const char* text, short x, short y, short dx) +{ + TString txt(text); txt.rtrim(); + int spaces = 0; + for (int s = 0; txt[s]; s++) + if (isspace(txt[s])) spaces++; + const int tw = xvt_dwin_get_text_width(win.win(), txt, -1); + if (tw < dx && spaces > 0) + { + txt << ' '; // Aggiunge spazio finale + const double kspc = double(dx - tw) / spaces; + int start = 0; + double kx = x; + for (int i = 0; txt[i]; i++) + { + if (isspace(txt[i])) + { + const bool last_word = txt[i+1] == '\0'; + const TString& parola = txt.sub(start, i + (last_word ? 0 : 1)); + const int lw = xvt_dwin_get_text_width(win.win(), parola, -1); + if (last_word) // ultima parola + kx = x+dx-lw; + xvt_dwin_draw_text(win.win(), int(kx+0.5), y, parola, -1); + kx += lw + kspc; + start = i+1; + } + } + } + else + xvt_dwin_draw_text(win.win(), x, y, text, -1); +} + +void advanced_draw_text(TWindow& win, const char* text, const RCT& r, + char halign, char valign) +{ + const short dx = r.right-r.left; + const short dy = r.bottom-r.top; + short x = r.left; + short y = r.bottom; + + if (halign != 'L') + { + const int tw = xvt_dwin_get_text_width(win.win(), text, -1); + switch (halign) + { + case 'C': x += (dx - tw)/2; break; + case 'R': x = r.right-tw; break; + default : break; + } + } + + // Text Height + int leading, ascent, descent; + xvt_dwin_get_font_metrics(win.win(), &leading, &ascent, &descent); + switch (valign) + { + case 'C': y -= (dy - ascent)/2; break; + case 'T': y = r.top + leading + ascent; break; + default : y -= descent; break; + } + + if (halign == 'J') + advanced_draw_justified_text(win, text, x, y, dx); + else + xvt_dwin_draw_text(win.win(), x, y, text, -1); +} + +void advanced_draw_paragraph(TWindow& win, TString& para, const RCT& rct, + char halign, char valign) +{ + const bool acapo = para.find('\n') >= 0; + + int leading, ascent, descent; + xvt_dwin_get_font_metrics(win.win(), &leading, &ascent, &descent); + const int ky = leading + ascent + descent; + + const int rct_height = rct.bottom - rct.top; + int rows = (rct_height+ky/2) / ky; + + if (acapo || rows > 1) // Devo scrivere piu' righe? + { + const int kx = xvt_dwin_get_text_width(win.win(), "ABCDEFGH", 8) / 8; + const unsigned columns = (rct.right - rct.left) / kx; + + TParagraph_string str(para, columns); + if (str.items() < rows) + rows = str.items(); + + int ybase = rct.top; + switch (valign) + { + case 'C': ybase += (rct_height - rows*ky) / 2; break; + case 'B': ybase += rct_height - rows*ky; break; + default : break; + } + + for (int row = 0; row < rows; row++) + { + RCT rctline = rct; + rctline.top = ybase + ky*row; + rctline.bottom = rctline.top + ky; + const char* line = str.get(); + if (halign == 'J' && (row == rows-1 || strlen(line) < columns/2)) + halign = 'L'; + advanced_draw_text(win, line, rctline, halign, 'T'); + } + } + else + advanced_draw_text(win, para, rct, halign, valign); +} + /////////////////////////////////////////////////////////// // TReport_link /////////////////////////////////////////////////////////// @@ -146,7 +291,7 @@ void TPrint_preview_window::update() if (pag.v < rct.bottom) rct.bottom = pag.v; hide_pen(); set_brush(COLOR_WHITE); - xvt_dwin_draw_rect(win(), &rct); + xvt_dwin_draw_rect(win(), &rct); // Disegna foglio bianco if (_grid) { @@ -243,9 +388,9 @@ void TPrint_preview_window::handler(WINDOW win, EVENT* ep) { case E_MOUSE_MOVE: if (find_link(ep->v.mouse.where) != NULL) - xvt_win_set_cursor(win, CURSOR_CROSS); + xvt_win_set_cursor(win, 8004); // Ditino else - xvt_win_set_cursor(win, CURSOR_ARROW); + xvt_win_set_cursor(win, CURSOR_ARROW); // Freccia break; case E_MOUSE_DOWN: if (ep->v.mouse.button == 0) @@ -279,8 +424,8 @@ void TPrint_preview_window::handler(WINDOW win, EVENT* ep) processed = _page < _book->pages(); if (processed) _page = _book->pages(); break; - case POPUP_ZOOMIN : if (_zoom < 300) { _zoom += 25; update_scroll_range(); } break; - case POPUP_ZOOMOUT: if (_zoom > 50) { _zoom -= 25; update_scroll_range(); } break; + case POPUP_ZOOMIN : if (_zoom < 300) { _zoom += 10; update_scroll_range(); } break; + case POPUP_ZOOMOUT: if (_zoom > 50) { _zoom -= 10; update_scroll_range(); } break; case POPUP_GRID : _grid = !_grid; break; default:processed = false; break; } @@ -680,6 +825,12 @@ void TBook::draw_rectangle(const TRectangle& r) *_out << "" << endl; } +void TBook::draw_round_rectangle(const TRectangle& r, int radius) +{ + define_frame(r); + *_out << "" << endl; +} + void TBook::draw_ellipse(const TRectangle& r) { define_frame(r); @@ -808,18 +959,19 @@ bool TBook::print_page(TWindow& win, size_t page) if (!stringona.blank() && rct.right > rct.left) // Possono esserci campi chiave nascosti { + WINDOW w = win.win(); DRAW_CTOOLS dct; - xvt_dwin_get_draw_ctools(win.win(), &dct); + xvt_dwin_get_draw_ctools(w, &dct); - XVT_FNTID oldfont = xvt_dwin_get_font(win.win()); + XVT_FNTID oldfont = xvt_dwin_get_font(w); XVT_FNTID newfont = xvt_font_create(); xvt_font_copy(newfont, oldfont, XVT_FA_ALL); xvt_font_set_style(newfont, xvt_font_get_style(oldfont) | XVT_FS_UNDERLINE); - xvt_dwin_set_font(win.win(), newfont); + xvt_dwin_set_font(w, newfont); win.set_color(COLOR_BLUE, dct.back_color); advanced_draw_text(win, stringona, rct, _horizontal_alignment, _vertical_alignment); win.set_color(dct.fore_color, dct.back_color); - xvt_dwin_set_font(win.win(), oldfont); + xvt_dwin_set_font(w, oldfont); } } } @@ -830,7 +982,7 @@ bool TBook::print_page(TWindow& win, size_t page) COLOR col = COLOR_BLACK; PAT_STYLE pat = PAT_SOLID; sscanf(str, "", &col, &pat); - if (pat == PAT_HOLLOW) + if (pat <= PAT_HOLLOW || col == COLOR_WHITE) win.hide_brush(); else win.set_brush(col, pat); @@ -897,6 +1049,14 @@ bool TBook::print_page(TWindow& win, size_t page) xvt_dwin_draw_rect(win.win(), &rct); continue; } + if (str.starts_with("") { TString stringona; @@ -1323,7 +1483,12 @@ long TReport_book::print_section(TReport_section& rs) return 0; } - rs.execute_prescript(); + if (!rs.execute_prescript()) + { + _print_aborted = true; + return 0; + } + const long height = rs.compute_size().y; // Compute size after the initilization script! if (height > 0) // Has some visible fields @@ -1350,7 +1515,8 @@ long TReport_book::print_section(TReport_section& rs) _page_break_allowed = true; } - rs.execute_postscript(); + if (!rs.execute_postscript()) + _print_aborted = true; return height; } @@ -1588,11 +1754,3 @@ TReport_book::TReport_book(const char* name) { } -/////////////////////////////////////////////////////////// -// Remote control interface -/////////////////////////////////////////////////////////// - -void abort_printing() -{ _print_aborted = true; } - - diff --git a/include/reprint.h b/include/reprint.h index ecf472ce6..7032be097 100755 --- a/include/reprint.h +++ b/include/reprint.h @@ -41,6 +41,7 @@ public: void set_text_color(COLOR fore, COLOR back = COLOR_WHITE, bool opaque = false); void set_text_align(char halign ='L', char valign = 'T'); void draw_rectangle(const TRectangle& rect); + void draw_round_rectangle(const TRectangle& rect, int radius); void draw_ellipse(const TRectangle& rect); void draw_line(const TRectangle& rect); void draw_image(const TRectangle& rect, const char* filename); @@ -53,6 +54,8 @@ public: size_t pages() const { return _pages; } virtual int lpi() const { return 6; } virtual int cpi() const { return 10; } + virtual int logical_page_width() const { return page_size().x * cpi() / page_res().x * 100; } + virtual int logical_page_height() const { return page_size().y * lpi() / page_res().y * 100; } virtual bool print_page(TWindow& win, size_t page); virtual bool on_link(const TReport_link&) { return false; } @@ -94,11 +97,18 @@ public: virtual int lpi() const; virtual int cpi() const; + virtual int logical_page_width() const { return _logical_page_width; } + virtual int logical_page_height() const { return _logical_page_height; } virtual bool print(size_t pagefrom = 0, size_t pageto = 0, size_t copies = 0); TReport_book(const char* name = NULL); }; -void abort_printing(); +bool advanced_set_draw_tools(TWindow& win, PAT_STYLE pat, int border, COLOR fore, COLOR back); +void advanced_draw_rect(TWindow& win, const RCT& r, PAT_STYLE pat, int border, COLOR fore, COLOR back, int radius); +void advanced_draw_text(TWindow& win, const char* text, const RCT& r, + char halign, char valign); +void advanced_draw_paragraph(TWindow& win, TString& text, const RCT& r, + char halign, char valign); #endif diff --git a/include/variant.cpp b/include/variant.cpp new file mode 100755 index 000000000..7d9d04264 --- /dev/null +++ b/include/variant.cpp @@ -0,0 +1,323 @@ +#include +#include + +/////////////////////////////////////////////////////////// +// TVariant +/////////////////////////////////////////////////////////// + +const TVariant NULL_VARIANT; + +void TVariant::set_null() +{ + if (_ptr != NULL) + { + if (_type != _nullfld && _type != _longfld) + delete (char *) _ptr; + _ptr = NULL; + } + _type = _nullfld; +} + +void TVariant::set(const char* str) +{ + if (str != NULL) + { + if (_type == _alfafld) + *((TString*)_ptr) = str; + else + { + set_null(); + _type = _alfafld; + _ptr = new TString(str); + } + } + else + set_null(); +} + +void TVariant::set(const real& r) +{ + if (_type == _realfld) + *((real*)_ptr) = r; + else + { + set_null(); + _type = _realfld; + _ptr = new real(r); + } +} + +void TVariant::set(const TDate& d) +{ + if (_type == _datefld) + *((TDate*)_ptr) = d; + else + { + set_null(); + _type = _datefld; + _ptr = new TDate(d); + } +} + +void TVariant::set(const long n) +{ + if (_type != _longfld) + set_null(); + _type = _longfld; + _ptr = (void*)n; +} + +bool TVariant::is_zero() const +{ + switch (_type) + { + case _datefld: return !as_date().ok(); + case _longfld: return _ptr == NULL; + case _realfld: return as_real().is_zero(); + case _alfafld: return real::is_null(as_string()); + default: break; + } + return true; +} + +bool TVariant::is_empty() const +{ + if (_type == _alfafld) + return as_string().empty(); + return is_zero(); +} + +TDate TVariant::as_date() const +{ + if (_type == _datefld) + return *(TDate*)_ptr; + if (_type == _intfld || _type == _realfld) + return TDate(as_int()); + return TDate(as_string()); +} + +long TVariant::as_int() const +{ + long n = 0; + switch(_type) + { + case _datefld: n = as_date().date2ansi(); break; + case _longfld: n = (long)_ptr; break; + case _realfld: n = as_real().integer(); break; + case _alfafld: n = atoi(as_string()); break; + default : break; + } + return n; +} + +bool TVariant::as_bool() const +{ + bool ok = false; + if (_type == _alfafld) + ok = strchr("1XY", as_string()[0]) != NULL; + else + ok = as_int() != 0; + 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) + return *(real*)_ptr; + switch(_type) + { + case _alfafld: return real(as_string()); break; + case _longfld: return real(as_int()); break; + default : break; + } + return ZERO; +} + +bool TVariant::as_string(TString& tmp) const +{ + tmp.cut(0); + switch(_type) + { + case _alfafld: tmp = *(TString*)_ptr; break; + case _datefld: tmp = as_date().string(); break; + case _longfld: tmp << as_int(); break; + case _realfld: tmp = as_real().string(); break; + default: break; + } + return !is_null(); +} + +const TString& TVariant::as_string() const +{ + if (_type == _alfafld) + return *(TString*)_ptr; + TString& tmp = get_tmp_string(); + as_string(tmp); + return tmp; +} + +void TVariant::convert_to(TFieldtypes ft) +{ + if (_type != ft) + { + switch (ft) + { + case _alfafld: set(as_string()); break; + case _datefld: set(as_date()); break; + case _longfld: set(as_int()); break; + case _realfld: set(as_real()); break; + default : set_null(); break; + } + } +} + +void TVariant::copy(const TVariant& var) +{ + switch (var._type) + { + case _datefld: set(var.as_date()); break; + case _longfld: set(var.as_int()); break; + case _realfld: set(var.as_real()); break; + case _alfafld: set(var.as_string()); break; + default : set_null(); break; + } +} + +int TVariant::compare(const TSortable& s) const +{ + const TVariant& var = (const TVariant&)s; + int cmp = 0; + switch (_type) + { + case _datefld: cmp = as_date() - var.as_date(); break; + case _longfld: cmp = as_int() - var.as_int(); break; + case _realfld: + { + const real n = as_real() - var.as_real(); + cmp = n.sign(); + } + break; + case _alfafld: cmp = as_string().compare(var.as_string()); break; + default : cmp = var.is_null() ? 0 : -1; + } + return cmp; +} + +TVariant& TVariant::add(const TVariant& var) +{ + switch (_type) + { + case _datefld: set(as_date() + var.as_int()); break; + case _longfld: set(as_int() + var.as_int()); break; + case _alfafld: *(TString*)_ptr << var.as_string(); break; + case _realfld: *(real*)_ptr += var.as_real(); break; + default: copy(var); break; + } + return *this; +} + +TVariant& TVariant::sub(const TVariant& var) +{ + switch (_type) + { + case _datefld: set(as_date() - var.as_int()); break; + case _longfld: + if (var.type() == _longfld) + { + set(as_int() - var.as_int()); + break; + } + // Fall down + default: + { + real n = as_real(); + n -= var.as_real(); + set(n); + } + break; + } + return *this; +} + +/////////////////////////////////////////////////////////// +// TVariant_stack +/////////////////////////////////////////////////////////// + +TVariant& TVariant_stack::peek(int depth) +{ + const int sp = _sp-depth-1; + return sp >= 0 ? (TVariant&)_var[sp] : (TVariant &)NULL_VARIANT; +} + +bool TVariant_stack::drop() +{ + if (_sp > 0) + { + _sp--; + return true; + } + return false; +} + +TVariant& TVariant_stack::pop() +{ + TVariant& var = peek(0); + drop(); + return var; +} + +void TVariant_stack::roll(int depth) +{ + const int sp = _sp-depth-1; + if (sp >= 0) + { + TObject* var = _var.remove(sp, true); + _var.insert(var, _sp-1); + } +} + +void TVariant_stack::push(const TVariant& var) +{ + if (_var.objptr(_sp) == NULL) + _var.add(var, _sp); + else + (TVariant&)_var[_sp] = var; + _sp++; +} + +void TVariant_stack::push(long n) +{ + const TVariant var(n); + push(var); +} + +void TVariant_stack::push(const real& n) +{ + const TVariant var(n); + push(var); +} + +void TVariant_stack::push(const char* str) +{ + const TVariant var(str); + push(var); +} + +void TVariant_stack::reset() +{ + _sp = 0; +} + +bool TVariant_stack::overflow() const +{ + return _sp > 2048; +} diff --git a/include/variant.h b/include/variant.h new file mode 100755 index 000000000..4715f98f9 --- /dev/null +++ b/include/variant.h @@ -0,0 +1,98 @@ +#ifndef __VARIANT_H +#define __VARIANT_H + +#ifndef __DATE_H +#include +#endif + +#ifndef __REAL_H +#include +#endif + +#ifndef __RECTYPES_H +#include +#endif + +/////////////////////////////////////////////////////////// +// TVariant +/////////////////////////////////////////////////////////// + +class TVariant : public TSortable +{ + TFieldtypes _type; + void* _ptr; + +protected: + virtual TObject* dup() const { return new TVariant(*this); } + void copy(const TVariant& var); + +public: + TFieldtypes type() const { return _type; } // Internal use only + bool is_string() const { return _type == _alfafld; } + bool is_empty() const; + bool is_null() const { return _type == _nullfld; } + bool is_zero() const; + void set_null(); + + void set(const char* str); + void set(const real& r); + void set(const long n); + void set(const TDate& d); + + TVariant& operator=(const TVariant& var) { copy(var); return *this; } + TVariant& operator=(const char* str) { set(str); return *this; } + TVariant& operator=(const real& r) { set(r); return *this; } + TVariant& operator=(const long n) { set(n); return *this; } + TVariant& operator=(const TDate& d) { set(d); return *this; } + + const TString& as_string() const; + bool as_string(TString& str) const; + real as_real() const; + long as_int() const; + TDate as_date() const; + bool as_bool() const; + unsigned long as_color() const; + + void convert_to(TFieldtypes ft); + + virtual int compare(const TSortable& s) const; + TVariant& add(const TVariant& var); + TVariant& sub(const TVariant& var); + + TVariant() : _type(_nullfld), _ptr(NULL) { } + TVariant(const char* str) : _type(_alfafld), _ptr(new TString(str)) { } + TVariant(const real& num) : _type(_realfld), _ptr(new real(num)) { }; + TVariant(const TDate& d) : _type(_datefld), _ptr(new TDate(d)) { }; + TVariant(long num) : _type(_longfld), _ptr((void*)num) { }; + TVariant(bool ok) : _type(_longfld), _ptr((void*)ok) { }; + TVariant(const TVariant& var) : _type(_nullfld), _ptr(NULL) { copy(var); } + virtual ~TVariant() { set_null(); } +}; + +extern const TVariant NULL_VARIANT; + +class TVariant_stack : public TObject +{ + TArray _var; + int _sp; + +public: + int items() const { return _sp; } + bool drop(); + TVariant& pop(); + TVariant& peek(int depth = 0); + void roll(int depth); + + void push(const TVariant& var); + void push(long n); + void push(const real& n); + void push(const char* str); + void reset(); + bool overflow() const; + + TVariant_stack() : _sp(0) { } +}; + + +#endif +