diff --git a/include/applicat.cpp b/include/applicat.cpp index 637c02116..370152450 100755 --- a/include/applicat.cpp +++ b/include/applicat.cpp @@ -389,7 +389,10 @@ const char* TApplication::get_module_name() const if (ok) ok = has_module(aut); if (!ok) - fatal_box("Il modulo '%s' non e' autorizzato", module); + { + error_box("Il modulo '%s' non e' autorizzato", module); + module = ""; + } return module; } @@ -480,8 +483,11 @@ void TApplication::run(int argc, char* argv[], const char* title) } set_perms(); + const TFixed_string mod(get_module_name()); + if (mod.empty()) return; + TString80 caption; - caption << "PRASSI S.p.A. - " << get_module_name(); + caption << "PRASSI S.p.A. - " << mod; static XVT_CONFIG cfg; cfg.base_appl_name = (char*)base.name(); diff --git a/include/checks.cpp b/include/checks.cpp index 3eac07ca7..8fad7cbd3 100755 --- a/include/checks.cpp +++ b/include/checks.cpp @@ -39,6 +39,8 @@ int fatal_box(const char* fmt, ...) if (xvt_running()) main_app().stop_run(); + else + exit(1); #else beep(); if (xvt_running()) xvt_fatal("%s", msg); diff --git a/include/controls.cpp b/include/controls.cpp index 8f3e3991a..c61cb85db 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -706,6 +706,8 @@ protected: public: TPage_button(WINDOW parent, byte flag); + byte get_flag() const { return _flag; } + void set_flag(byte f); }; TPage_button::TPage_button(WINDOW parent, byte flag) : _flag(flag) @@ -728,8 +730,15 @@ void TPage_button::mouse_up() void TPage_button::update() const { - TControl::update(); - cpb_win_picture_draw_at(_hdc, cpb[BMP_BOOK1 + _flag -1], 0, 0); + TControl::update(); + if (_flag) + cpb_win_picture_draw_at(_hdc, cpb[BMP_BOOK1 + _flag -1], 0, 0); +} + +void TPage_button::set_flag(byte f) +{ + _flag = f; + update(); } /////////////////////////////////////////////////////////// @@ -752,6 +761,8 @@ protected: public: TTag_button(WINDOW parent, byte p, byte tot); + byte get_pages() const { return _pages; } + void set_pages(byte p); }; TTag_button::TTag_button(WINDOW parent, byte p, byte tot) @@ -809,7 +820,8 @@ void TTag_button::update() const void TTag_button::mouse_down(PNT where) { _curr = where.h / width; - if (_curr >= _pages) _curr = _pages-1; + if (_curr >= _pages) _curr = _pages-1; else + if (_curr < 0) _curr = 0; } void TTag_button::mouse_up() @@ -818,6 +830,12 @@ void TTag_button::mouse_up() dispatch_e_char(_parent, K_CTRL + K_F1 + _curr); } +void TTag_button::set_pages(byte p) +{ + _pages = p; + update(); +} + /////////////////////////////////////////////////////////// // Checkbox /////////////////////////////////////////////////////////// @@ -1024,3 +1042,23 @@ TControl* TControl::WINDOW2TControl(WINDOW win) CHECK(model && *model, "Can't get the model from a window"); return *model; } + +void xvt_change_page_tags(WINDOW pag, bool on, WINDOW tag, byte p) +{ + if (pag != NULL_WIN) + { + TPage_button* pb = (TPage_button*)TControl::WINDOW2TControl(pag); + byte f = pb->get_flag(); + if (on) f |= 0x1; + else f &= 0x2; + pb->set_flag(f); + } + + if (tag != NULL_WIN) + { + TTag_button* pt = (TTag_button*)TControl::WINDOW2TControl(tag); + pt->set_pages(p); + } +} + + diff --git a/include/controls.h b/include/controls.h index cb25bc11e..cbbdb63f5 100755 --- a/include/controls.h +++ b/include/controls.h @@ -11,7 +11,8 @@ WINDOW xvt_create_checkbox( WINDOW parent, long flags, long app_data, - int id); + int id + ); WINDOW xvt_create_radiobutton( short left, short top, short right, short bottom, @@ -19,7 +20,8 @@ WINDOW xvt_create_checkbox( WINDOW parent, long flags, long app_data, - int id); + int id + ); WINDOW xvt_create_pushbutton( short left, short top, short right, short bottom, @@ -27,7 +29,8 @@ WINDOW xvt_create_checkbox( WINDOW parent, long flags, long app_data, - int id); + int id + ); WINDOW xvt_create_text( short left, short top, short right, short bottom, @@ -35,7 +38,8 @@ WINDOW xvt_create_checkbox( WINDOW parent, long flags, long app_data, - int id); + int id + ); WINDOW xvt_create_groupbox( short left, short top, short right, short bottom, @@ -43,7 +47,8 @@ WINDOW xvt_create_checkbox( WINDOW parent, long flags, long app_data, - int id); + int id + ); void free_controls_bmp(); @@ -51,7 +56,6 @@ WINDOW xvt_create_checkbox( // Custom control /////////////////////////////////////////////////////////// - class TControl { WINDOW _win; diff --git a/include/mask.cpp b/include/mask.cpp index 1d2f96c93..48eb6a5e7 100755 --- a/include/mask.cpp +++ b/include/mask.cpp @@ -162,15 +162,19 @@ void TMask::handler(WINDOW win, EVENT* ep) void TMask::init_mask(int mode) { _sheets = _pages = 0; // Azzera numero pagine e sheets - _enabled = 0xffff; // Abilita tutte le pagine + + _enabled.set(MAX_PAGES); + _enabled.set(); // Abilita tutte le pagine + _focus = _first_focus = 0; // Nessuno ha il focus _page = -1; // Nessuna pagina corrente _handler = NULL; // Nessun handler utente _mode = mode; // Inizializza modo _exchange = 1.0; // Il cambio per la valuta e' la lira - for (int i = 0; i <= MAX_PAGES; i++) - _pagewin[i] = NULL_WIN; // Azzera le finestre delle varie pagine + memset(_pagewin, 0, sizeof(_pagewin)); + memset(_pagepag, 0, sizeof(_pagepag)); + memset(_pagetag, 0, sizeof(_pagetag)); } @@ -236,14 +240,14 @@ void TMask::add_buttons() for (int p = 0; p < _pages; p++) { if (_pages > 1) - { - const byte flag = (p < _pages-1 ? 0x1 : 0x0) | (p > 0 ? 0x2 : 0x0); - xvt_create_control(WC_PUSHBUTTON, 0,0,1,1, "", - _pagewin[p], flag, 0, DLG_PAGE); + { + const long flags = (p < _pages-1 ? 0x1 : 0x0) | (p > 0 ? 0x2 : 0x0); + _pagepag[p] = xvt_create_control(WC_PUSHBUTTON, 0, 0, 1, 1, "", + _pagewin[p], flags, 0, DLG_PAGE); } if (toolwin()) - xvt_create_control(WC_PUSHBUTTON, 0,0,0,1, "", - _pagewin[p], p, _pages, DLG_PAGETAGS); + _pagetag[p] = xvt_create_control(WC_PUSHBUTTON, 0, 0, 0, 1, "", + _pagewin[p], p, _pages, DLG_PAGETAGS); } #else if (toolwin()) @@ -384,23 +388,31 @@ void TMask::load_checks() const } } -void TMask::enable_page(int page, bool on) +// Dis/abilita una pagina e tutte le successive +void TMask::enable_page(byte page, bool on) { - int first = (page >= 0) ? page : 1; - int last = (page >= 0) ? page+1 : _pages; - - for (int p = first; p < last; p++) + CHECK(page > 0, "Can't enable/disable first page"); + + if (_enabled[page] != on) { - const word n = 1 << p; - if (on) _enabled |= n; - else _enabled &= ~n; + for (byte i = page; i < _pages; i++) + _enabled.set(i, on); + +#if XVT_OS == XVT_OS_WIN + const byte p = on ? _pages : page; + for (i = 0; i < page-1; i++) + xvt_change_page_tags(NULL_WIN, FALSE, _pagetag[i], p); + + xvt_change_page_tags(_pagepag[page-1], on, _pagetag[page-1], p); +#endif } } -bool TMask::page_enabled(int page) const +// Controlla lo stato di abilitazione di una pagina +// Certified 100% +bool TMask::page_enabled(byte page) const { - const unsigned long n = 1 << page; - return (_enabled & n) > 0; + return _enabled[page]; } @@ -426,7 +438,7 @@ void TMask::start_run() for (i = 0; i < max; i++) { TMask_field& f = fld(i); - if (mode() == MODE_QUERY && f.is_edit() && f.in_key(1) && + if (query_mode() && f.is_edit() && f.in_key(1) && !f.automagic() && !f.get().empty()) { f.set_dirty(TRUE); @@ -497,7 +509,7 @@ void TMask::get_mask_fields() int TMask::id2pos(short id) const { - const int MAX_FIELDS = 128; + const int MAX_FIELDS = 256; static byte positions[MAX_FIELDS]; // 100 <= id < MAX_FIELDS const int max = fields(); @@ -1124,26 +1136,34 @@ void TMask::autosave(TRelation* r) const } } -void TMask::send_key(KEY key, short to) const +void TMask::send_key(KEY key, short to, TMask_field* from) { if (to == 0) - { - WINDOW w = win(); - if (w == NULL_WIN) w = _pagewin[0]; + { + WINDOW w = from ? from->parent() : _pagewin[0]; dispatch_e_char(w, key); return; } if (to > 0) - { - const int pos = id2pos(to); - if (pos >= 0) - fld(pos).on_key(key); -#ifdef DBG + { + if (to == DLG_PAGE) + { + CHECK(from, "You should specify a sender!"); + const int p = find_parent_page(*from)+1; + CHECKD(p > 0 && p < _pages, "You should specify a good page, not ", p); + key -= K_CTRL+K_SHIFT; + enable_page(p, key == 's' || key == 'e'); + } else - if (mode() != MODE_SEARCH) + { + const int pos = id2pos(to); + if (pos >= 0) fld(pos).on_key(key); +#ifdef DBG + else yesnofatal_box("Can't send key %u to field %d", key, to); -#endif +#endif + } } else { diff --git a/include/mask.h b/include/mask.h index e7d29e434..1df686704 100755 --- a/include/mask.h +++ b/include/mask.h @@ -30,11 +30,13 @@ class TMask : public TWindow // @DPRIV enum { MAX_PAGES = 12 }; // Massimo numero di pagine nella maschera WINDOW _pagewin[MAX_PAGES+1]; // Windows of the pages - + WINDOW _pagepag[MAX_PAGES]; // Windows of pgup/pgdn + WINDOW _pagetag[MAX_PAGES]; // Windows of pagetags + int _pages; // Number of pages of the mask int _page; // Current page - word _enabled; // Are pages enabled (bit field) + TBit_array _enabled; // Are pages enabled int _mode; // Mode of the mask TArray _field; // Fields in the mask @@ -150,9 +152,9 @@ public: void disable(short fld_id) { enable(fld_id, FALSE); } void enable_default(short fld_id = -1); - void enable_page(int p, bool on = TRUE); - void disable_page(int p) { enable_page(p, FALSE); } - bool page_enabled(int p) const; + void enable_page(byte p, bool on = TRUE); + void disable_page(byte p) { enable_page(p, FALSE); } + bool page_enabled(byte p) const; byte num_keys() const; void enable_key(byte key, bool on = TRUE); @@ -170,7 +172,7 @@ public: void autoload(const TRelation* = NULL); void autosave(TRelation* = NULL) const; - void send_key(KEY key, short id) const; + void send_key(KEY key, short id, TMask_field* from = NULL); void set_handler(short fld_id, CONTROL_HANDLER handler); void set_handler(MASK_HANDLER handler); void set_workfile(const char* workfile) { _workfile = workfile; _lastpos = 0L;} diff --git a/include/maskfld.cpp b/include/maskfld.cpp index a8cc3756e..1c289dba2 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -1,3049 +1,3055 @@ -// $Id: maskfld.cpp,v 1.48 1994-11-15 17:14:22 guy Exp $ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if XVT_OS == XVT_OS_WIN -#include -#endif - -HIDDEN const int MAXSTR = 128; -HIDDEN char __fpark[MAXSTR]; // Temporary for get/set window data -HIDDEN TFixed_string fpark(__fpark, MAXSTR); - -/////////////////////////////////////////////////////////// -// Field Flags -/////////////////////////////////////////////////////////// - -// Certified 100% -TMask_field::TField_Flags::TField_Flags() -{ - automagic = persistent = FALSE; - enabled = enable_default = TRUE; - showed = show_default = TRUE; - uppercase = rightjust = FALSE; - zerofilled = FALSE; - dirty = focusdirty = FALSE; - roman = exchange = FALSE; - firm = ghost = FALSE; - password = FALSE; -} - -// Certified 100% -char TMask_field::TField_Flags::update(const char* s) -{ - const char* kk = s; - for (; *s; s++) - switch(toupper(*s)) - { - case '*': - password = TRUE; break; - case 'A': - automagic = persistent = TRUE; break; - case 'D': - enable_default = enabled = FALSE; break; - case 'F': - firm = persistent = TRUE; break; - case 'G': - ghost = TRUE; break; - case 'H': - show_default = showed = FALSE; break; - case 'M': - roman = TRUE; break; - case 'P': - persistent = TRUE; break; - case 'R': - rightjust = TRUE; break; - case 'U': - uppercase = TRUE; break; - case 'V': - exchange = TRUE; break; - case 'Z': - zerofilled = TRUE; break; - default : -#ifdef DBG - yesnofatal_box("FLAG sconosciuto in %s: %c", kk, *s); -#endif - break; - } - return *s; -} - - -/////////////////////////////////////////////////////////// -// TMask_field -/////////////////////////////////////////////////////////// - -int TMask_field::_x; // Position of the field -int TMask_field::_y; -int TMask_field::_width; -TFixed_string TMask_field::_prompt(__fpark, MAXSTR); // Prompt of the field - -TMask_field::TMask_field(TMask* m) -: _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), - _keys(0), _groups(0), _help(0), _handler(NULL), - _validate_func(-1), _validate_parms(1), _field(NULL) -{} - -// Certified 100% -TMask_field::~TMask_field() -{ - if (_field) delete _field; -} - - -// Certified 100% -bool TMask_field::is_edit() const -{ - const word c = class_id(); - return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD; -} - - -// Certified 100% -const char* TMask_field::class_name() const -{ return "Field"; } - - -// Certified 100% -word TMask_field::class_id() const -{ return CLASS_FIELD; } - - -// Certified 100% -bool TMask_field::ok() const -{ return win() != NULL_WIN && dlg() >= -1; } - - -// Certified 100% -void TMask_field::parse_head(TScanner&) -{} - - -// Certified 100% -short TMask_field::atodlg(const char* s) const -{ - short d = s ? atoi(s) : 0; - -#ifdef DBG - if (d == 0 || d < -1 || d > 1000) - { - yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); - d = -1; - } -#endif - - return d; -} - -void TMask_field::construct(short id, const char* prompt, int x, int y, - int len, WINDOW parent, const char* flags, int width) -{ - _x = x; _y = y; - _prompt = prompt; - _size = len; - if (class_id() == CLASS_REAL_FIELD) - { - ((TReal_field*)this)->set_decimals(width); - _width = _size; - } - else _width = width < 1 ? _size : width; - _dlg = id; - _flags.update(flags); - - create(parent); -} - - -void TMask_field::construct(TScanner& scanner, WINDOW parent) -{ - _dlg = atodlg(scanner.pop()); - parse_head(scanner); - _prompt.cut(0); - - scanner.popkey(); // BEGIN -#ifdef DBG - if (scanner.key() != "BE") - { - yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); - scanner.push(); - } -#endif - - while(scanner.popkey() != "EN") // END of control - parse_item(scanner); - create(parent); -} - -bool TMask_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PR") // PROMPT - { - _x = scanner.integer(); - _y = scanner.integer(); - _prompt = scanner.string(); - return TRUE; - } - - if (scanner.key() == "FL") // FLAG - { - const char* f = scanner.string(); - return _flags.update(f) == '\0'; - } - - if (scanner.key() == "FI") // FIELD - { - CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); - _field = new TFieldref(scanner.line(), 0); - return TRUE; - } - - if (scanner.key() == "HE") // HELP - { - _help = scanner.string(); - return TRUE; - } - - if (scanner.key() == "KE") // KEY - { - _keys.set(scanner.line()); - _keys.set(0L); - return TRUE; - } - - if (scanner.key() == "ME") - { - if (_message.objptr(0) == 0) - _message.add(new TToken_string(64), 0); - TToken_string& ts = (TToken_string&)_message[0]; - ts.add(scanner.line().strip_spaces()); - return TRUE; - } - - if (scanner.key() == "GR") - { - _groups.set(scanner.line()); - return TRUE; - } - - return FALSE; -} - - -long TMask_field::default_flags() const -{ - long f = CTL_FLAG_NATIVE_JUST; - - if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; - if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; - - return f; -} - -// Certified 100% -WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy, - const char* title, WINDOW parent, - long flags) -{ - _win = xvt_create_control(ct, - _x, _y, dx, dy, - (char*)title, - parent, - flags | default_flags(), - PTR_LONG(this), - _dlg); - - return _win; -} - - -// Certified 100% -WINDOW TMask_field::parent() const -{ return get_parent(win()); } - - -// Certified 90% -int TMask_field::create_prompt(WINDOW parent, int width, int heigth) -{ - const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; - if (width < 1) width = strlen(_prompt); - _prompt.rtrim(); // Could save some bytes - - if (width) - { - // Static controls shouldn't be grayed - const long flags = default_flags() & (~CTL_FLAG_DISABLED); -#if XVT_OS == XVT_OS_WIN - char* k = strchr(_prompt, '~'); - if (k != NULL) *k = '&'; -#endif - _promptwin = xvt_create_control - ( - wt, - _x, _y, width, heigth, - _prompt, - parent, - flags, - 0L, - -1 - ); - } - return width; -} - - -// Certified 100% -void TMask_field::destroy() -{ - if (_win) - { close_window(_win); _win = NULL_WIN; } - if (_promptwin) - { close_window(_promptwin); _promptwin = NULL_WIN; } -} - - -// Certified 100% -void TMask_field::create(WINDOW parent) -{ - _width = strlen(_prompt); - if (_width) - wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); -} - - -// Certified 100% -void TMask_field::enable(bool on) -{ - const word c = class_id(); - if (c != CLASS_FIELD) - { - enable_window(_win, on); - _flags.enabled = on; - } -} - - -// Certified 100% -void TMask_field::enable_default() -{ - const bool ed = _flags.enable_default; - enable(ed); -} - - -// Certified 100% -void TMask_field::show(bool on) -{ - show_window(_win, on); - if (_promptwin != NULL_WIN) - show_window(_promptwin, on); - _flags.showed = on; -} - - -// Certified 100% -void TMask_field::show_default() -{ - const bool sd = _flags.show_default; - show(sd); -} - - -// Certified 100% -bool TMask_field::active() const -{ - return enabled() && showed() && class_id() != CLASS_FIELD; -}; - - -// Certified 90% -word TMask_field::last_key() const -{ - long u = _keys.last_one(); - if (u < 0) u = 0; - return (word)u; -} - -void TMask_field::set_dirty(bool d) -{ -#ifdef DBG - if (dlg() == 103) - d *= 1; -#endif - - if (_flags.dirty > TRUE && d == FALSE) - return; - _flags.dirty = d; - set_focusdirty(d); -} - - - -// Certified 99% -const char* TMask_field::get_window_data() const -{ - get_title(win(), __fpark, MAXSTR); - return __fpark; -} - - -// Certified 99% -void TMask_field::set_window_data(const char* data) -{ - if (data != NULL) - set_title(win(), (char*)data); -} - - -// Certified 100% -void TMask_field::set_field_data(const char*) -{} - - -// Certified 100% -const char* TMask_field::get_field_data() const -{ return NULL; } - - -const char* TMask_field::picture_data(const char* data, bool video) -{ - fpark = data; - if (video) - { - fpark.trim(); - if (_flags.uppercase) fpark.upper(); - } - return fpark; -} - - -// Certified 90% -const char* TMask_field::prompt() const -{ - if (_promptwin != NULL_WIN) - _prompt = xvt_get_title(_promptwin); - else - _prompt = ""; - - return _prompt; -} - - -// Certified 100% -void TMask_field::reset() -{ - if (!_flags.persistent && class_id() != CLASS_FIELD) - set(""); -} - - -// Certified 100% -void TMask_field::set_prompt(const char* p) -{ - if (_promptwin != NULL_WIN) - set_title(_promptwin, (char*) p); -} - - -void TMask_field::set(const char* s) -{ - if (mask().is_running()) - { - set_window_data(s); - set_dirty(); - } - else - set_field_data(s); -} - -TString& TMask_field::get() const -{ - static TString80 gpark; - - if (mask().is_running()) - gpark = get_window_data(); - else - gpark = get_field_data(); - - return gpark.trim(); -} - - -void TMask_field::undo() -{ - set_window_data(get_field_data()); -} - - -bool TMask_field::autoload(const TRelation* r) -{ - if (_field) - { - set(_field->read(r)); - return TRUE; - } - return FALSE; -} - - -bool TMask_field::autosave(TRelation* r) const -{ - if (_field) - { - _field->write(get(), r); - return TRUE; - } - return FALSE; -} - - -// Certified 50% -HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) -{ -#ifdef DBG - if (f.class_id() != CLASS_LIST_FIELD) - { - error_box("Can't add/delete items of non list-box field %d", f.dlg()); - return; - } -#endif - TList_field& l = (TList_field&)f; - - TToken_string item(16); - item = msg.get(); - if (add) item.add(msg.get()); - item.strip("\"'"); - if (add) - l.add_item(item); - else - l.delete_item(item); -} - - -// Certified 90% -HIDDEN const char* copy_value(TToken_string& msg, const TString& val) -{ - int from = msg.get_int()-1; - int to = -1; - if (from < 0) from = 0; - else to = msg.get_int(); - return val.sub(from, to); -} - - -// Certified 50% -bool TMask_field::do_message(int num) -{ - const int MAX_CMD = 14; - static const char* commands[MAX_CMD] = - { - "ADD", // 0 - "CLEAR", // 1 - "CO", // 2 - "DEL", // 3 - "DIRTY", // 4 - "DISABLE", // 5 - "ENABLE", // 6 - "ENABLEDEF", // 7 - "EXIT", // 8 - "HIDE", // 9 - "PUSH", // 10 - "RESET", // 11 - "SHOW", // 12 - "UNDO" // 13 - }; - - TToken_string* message = (TToken_string*)_message.objptr(num); - if (message == NULL || message->empty()) return FALSE; - - TToken_string msg(16, ','); - TString80 value; - - for (const char* m = message->get(0); m && *m; m = message->get()) - { - KEY key = 0; - msg = m; - value = msg.get(); - value.trim(); - const char* dlg = msg.get(); - - int cmd = -1; - if (isalpha(value[0])) // binary search - { - int f = 0, l = MAX_CMD-1; - while (TRUE) - { - cmd = (f+l)>>1; - const int cmp = strcmp(value, commands[cmd]); - if (cmp == 0) break; - if (cmp > 0) f = cmd+1; - else l = cmd-1; - if (f > l) - { - cmd = -1; - break; - } - } - } - - if (cmd == 8) - { - mask().stop_run(atoi(dlg)); - continue; - } - - short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; - bool broadcast = dlg && strchr(dlg, '@'); - if (value[0] == '"') value = value.strip("\"'"); - else switch (cmd) - { - case 0: - modify_list(TRUE, mask().field(fld), msg); continue; - case 1: - key = 11000+'c'; break; - case 2: - value = copy_value(msg, get()); break; - case 3: - modify_list(FALSE, mask().field(fld), msg); continue; - case 4: - mask().field(fld).set_dirty(); continue; - case 5: - key = 11000+'d'; break; - case 6: - key = 11000+'e'; break; - case 7: - key = 11000+'E'; break; - case 9: - key = 11000+'h'; break; - case 10: - key = K_SPACE; break; - case 11: - key = K_F2; break; - case 12: - key = 11000+'s'; break; - case 13: - key = K_F3; break; - default: - key = atoi(value); - break; - } - - if (key) - { - if (key > 0) - { - if (broadcast) fld = -fld; - mask().send_key(key, fld); - } - } - else - { - // Setta a value il campo fld solo se ha un valore diverso da value - if (broadcast) - { - for (int i = 0; i < mask().fields(); i++) - { - TMask_field& f = mask().fld(i); - if (f.in_group((int)fld)) - { - const char* prev = f.get(); - if (value != prev) - { - f.set(value); - if (f.showed() || f.ghost()) - f.on_hit(); - } - } - } - } - else - { - TMask_field& f = mask().field(fld); - const char* prev = f.get(); - if (value != prev) - { - f.set(value); - if (f.showed() || f.ghost()) - f.on_hit(); - } - } - } - } - - return TRUE; -} - - -// Certified 90% -bool TMask_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - do_message(0); - return TRUE; -} - - -bool TMask_field::to_check(KEY k, bool checkrun) const -{ - bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); - - if (!yes && checkrun) - yes = k == K_TAB && !mask().is_running(); - - return yes; -} - -// Certified 90% -bool TMask_field::on_key(KEY key) -{ - if (key > 11000) - { - switch(key-11000) - { - case 'E': - enable_default(); break; - case 'c': - reset(); on_hit(); - case 'd': - disable(); break; - case 'e': - enable(); break; - case 'h': - hide(); break; - case 's': - show(); break; -#ifdef DBG - default : - return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); -#endif - } - return TRUE; - } - - switch(key) - { - case K_SPACE: - set_dirty(); - break; - case K_PREV: - case K_NEXT: - dispatch_e_char(parent(), key); - break; - case K_F1: - if (_help.not_empty()) - message_box(_help); - else - beep(); - break; - case K_F2: - if (is_edit()) set(""); - else reset(); - set_dirty(); - break; - case K_F3: - undo(); - set_dirty(); - break; - default: - break; - } - - if (_handler) - return _handler(*this, key); - - return TRUE; -} - - -void TMask_field::set_focus() const -{ - const bool force = mask().is_running(); - mask().set_focus_win(win(), force); -} - -HIDDEN char* const _msg = &__tmp_string[512]; -#define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) - -bool TMask_field::error_box(const char* fmt, ...) const -{ - build_msg(); - if (mask().is_sheetmask() && !mask().is_running()) - { - xvt_statbar_set(_msg); - beep(); - } - else - { - set_focus(); - ::error_box("%s", _msg); - set_focus(); - } - return FALSE; -} - -bool TMask_field::message_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - ::message_box("%s", _msg); - set_focus(); - return FALSE; -} - -bool TMask_field::warning_box(const char* fmt, ...) const -{ - build_msg(); - - if (mask().is_sheetmask() && !mask().is_running()) - { - xvt_statbar_set(_msg); - beep(); - } - else - { - set_focus(); - ::warning_box("%s", _msg); - set_focus(); - } - return FALSE; -} - -bool TMask_field::yesno_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const bool yes = ::yesno_box("%s", _msg); - set_focus(); - return yes; -} - -KEY TMask_field::yesnocancel_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const KEY k = ::yesnocancel_box("%s", _msg); - set_focus(); - return k; -} - -/////////////////////////////////////////////////////////// -// TList_sheet -/////////////////////////////////////////////////////////// - -// Certified 100% -TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) -: _fld(f), _row(-1) -{ - _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); -} - -// Certified 100% -TList_sheet::~TList_sheet() -{ - delete _sheet; -} - -// Certified 100% -TMask_field& TList_sheet::field(short id) const -{ return field().mask().field(id); } - - -// Certified 100% -void TList_sheet::read_item(TScanner& scanner) -{ - TToken_string ts(scanner.string()); - _sheet->add(ts); -} - - -// Certified 100% -void TList_sheet::parse_input(TScanner& scanner) -{ - _inp_id.add(scanner.pop()); -} - - -// Certified 100% -void TList_sheet::parse_output(TScanner& scanner) -{ - _out_id.add(scanner.pop()); -} - -// il numero di riga selezionata -int TList_sheet::do_input() -{ - if (_inp_id.empty()) return -2; // List empty! - - _inp_id.restart(); - TToken_string rowsel(80); - - for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) - { - if (*fld == '"') - { - rowsel.add(fld+1); - if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1); - } - else - { - const short id = _fld->atodlg(fld); - if (id > 0) rowsel.add(field().mask().get(id)); - else rowsel.add(""); - } - } - - TString80 fd, it; - for (int i = 0 ; i < _sheet->items(); i++) - { - TToken_string& ts =_sheet->row(i); - - ts.restart(); - for ( const char* item = rowsel.get(0); item ; item = rowsel.get()) - { - it = item; it.trim(); - fd = ts.get(); fd.trim(); - if (fd != it) break; - } - if (!item) return i; - } - - return -1; // Value not found! -} - - -// Certified 50% -void TList_sheet::do_output(CheckTime t) -{ - if (_row < 0 || t == FINAL_CHECK) - return; - - _out_id.restart(); - TToken_string& rowsel = _sheet->row(_row); - rowsel.restart(); - for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) - { - const short id = _fld->atodlg(fld); - if (t != STARTING_CHECK || field().field() == NULL) - { - TMask_field& f = field(id); - f.set(rowsel.get()); - if (field().dlg() != id) - f.on_hit(); - } - } -} - - -// Certified 100% -KEY TList_sheet::run() -{ - _row = do_input(); - - _sheet->select(_row); - - const KEY k = _sheet->run(); - - switch (k) - { - case K_ENTER: - _row = (int)_sheet->selected(); - do_output(); - break; - default: - break; - } - - return k; -} - - -// Certified 100% -bool TList_sheet::check(CheckTime t) -{ - const bool passed = (_row = do_input()) != -1; - if (passed) do_output(t); - return passed; -} - - -/////////////////////////////////////////////////////////// -// TBrowse -/////////////////////////////////////////////////////////// - -// Certified 100% -TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) -: _relation(r), _cursor(new TCursor (r, filter, key)), - _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) -{} - - -// Certified 100% -TBrowse::TBrowse(TEdit_field* f, TCursor* c) -: _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) -{} - - -// Certified 100% -TBrowse::~TBrowse() -{ - if (_relation) - { - delete _relation; - delete _cursor; - } -} - - -// Certified 100% -void TBrowse::parse_display(TScanner& scanner) -{ - const char* s; - s = scanner.string(); - _head.add(s); - s = scanner.line(); - _items.add(s); -} - - -void TBrowse::parse_input(TScanner& scanner) -{ - const char* s = scanner.pop(); - _inp_fn.add(s); - - s = scanner.pop(); - if (*s == '"') // Constant string - { - scanner.push(); - _inp_id.add(scanner.line()); - } - else // Field on the mask - { - TString80 str(s); - if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field - else scanner.push(); - _inp_id.add(str); - } -} - - -void TBrowse::parse_output(TScanner& scanner) -{ - const char* s = scanner.pop(); -#ifdef DBG - field().atodlg(s); -#endif - _out_id.add(s); - s = scanner.pop(); - _out_fn.add(s); -} - - -bool TBrowse::parse_copy(const TString& what, const TBrowse& b) -{ - const bool all = what == "AL"; - if (all || what == "US") - { - set_insert(b.get_insert()); - _filter = b.get_filter(); - if (field()._warning.empty()) - field()._warning = b.field()._warning; - if (!all) return TRUE; - } - if (all || what == "IN") - { - _inp_id = b._inp_id; - _inp_fn = b._inp_fn; - if (!all) return TRUE; - } - if (all || what == "DI") - { - _head = b._head; - _items = b._items; - if (!all) return TRUE; - } - if (all || what == "OU") - { - _out_id = b._out_id; - _out_fn = b._out_fn; - _secondary = TRUE; - } - return TRUE; -} - - -void TBrowse::parse_join(TScanner& scanner) -{ - TString80 j(scanner.pop()); // File or table - - CHECKS(_relation, "Can't join to NULL relation ", (const char*)j); - - int to; - if (scanner.popkey() == "TO") // TO keyword - { - const char* t = scanner.pop(); - to = name2log(t); - } - else - { - to = 0; // _relation->lfile()->num(); - scanner.push(); - } - - int key = 1; - if (scanner.popkey() == "KE") - key = scanner.integer(); - else scanner.push(); - - byte alias = 0; - if (scanner.popkey() == "AL") - alias = scanner.integer(); - else scanner.push(); - - TToken_string exp(80); - if (scanner.pop() == "INTO") - { - const char* r = scanner.pop(); - while (strchr(r, '=') != NULL) - { - exp.add(r); - r = scanner.pop(); - } - } - scanner.push(); - -#ifdef DBG - if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); -#endif - - if (isdigit(j[0])) - _relation->add(atoi(j), exp, key, to, alias); // join file - else - { -#ifdef DBG - if (j.len() > 4) - yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); - else -#endif - _relation->add(j, exp, key, to, alias); // join table - } -} - - -void TBrowse::parse_insert(TScanner& scanner) -{ - const TString16 key(scanner.popkey()); - - if (key == "NO") _insert = ""; - else - { - if (key == "RU") - { - _insert = "R"; - _insert << scanner.line(); - } - else - { - _insert = "M"; - _insert << scanner.line(); - } - _insert.trim(); - } -} - - -// Certified 100% -TMask_field& TBrowse::field(short n) const -{ return _fld->mask().field(n); } - - -// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro -int TBrowse::inputs() -{ - int inp = 0; - for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) - { - if (*fld != '"' && strchr(fld, '@') == NULL) - inp++; - } - return inp; -} - -// Ritorna il numero di campi non vuoti e non filtrati -int TBrowse::do_input(bool filter) -{ - int ne = 0; - if (_inp_id.empty()) return ne; - - TRectype& cur = _cursor->curr(); - - cur.zero(); - TRectype filtrec(cur); - - _inp_id.restart(); - _inp_fn.restart(); - - TString80 val; // Value to output - bool tofilter; - - for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) - { - if (*fld == '"') - { - val = (fld+1); - if (val.not_empty()) val.rtrim(1); - tofilter = filter; - } - else - { - const short id = _fld->atodlg(fld); - const bool filter_flag = strchr(fld, '@') != NULL; - tofilter = filter && filter_flag; - val = field(id).get(); - if (field(id).is_edit() && val.not_empty() && !filter_flag) - ne++; // Increment not empty fields count - } - - TFieldref fldref(_inp_fn.get(), 0); // Output field - fldref.write(val, _cursor->relation()); - if (tofilter) - { - if (val.empty()) val.fill('~', fldref.len(cur)); - fldref.write(val, filtrec); - } - } - - if (!filter) return ne; - - TString work(_filter.size()); - for (int i = 0; _filter[i]; i++) - { - if (_filter[i] == '"') - { - do - { - work << _filter[i++]; - } while (_filter[i] && _filter[i] != '"'); - work << '"'; - if (!_filter[i]) break; - } - else - if (_filter[i] == '#') - { - work << '"' << field(atoi(&_filter[++i])).get() << '"'; - while (isspace(_filter[i])) i++; - while (isdigit(_filter[i])) i++; - i--; - } - else work << _filter[i]; - } - - _cursor->setfilter(work); - _cursor->setregion(filtrec, filtrec); - - return ne; -} - - -void TBrowse::do_output(CheckTime t) -{ - if (t == FINAL_CHECK) - return; - - TString80 sum; - TToken_string flds(24, '+'); - - _out_fn.restart(); - for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) - { - const short id = field().atodlg(fld); - TMask_field& f = field(id); - - flds = _out_fn.get(); - if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) - { - sum.cut(0); - for(const char* fr = flds.get(0); fr; fr = flds.get()) - { - const char* val; - if (*fr == '"') - { - const TString80 v(fr); - val = v.mid(1, v.len()-2); - } - else - { - const TFieldref fld(fr, 0); - val = fld.read(_cursor->relation()); - } - sum << val; - } - - f.set(sum); - if (field().dlg() != id) - f.on_hit(); - } - } -} - - -void TBrowse::do_clear() -{ - for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) - { - TMask_field& f = field(atoi(fld)); - if (f.field() == NULL && _inp_id.get_pos(fld) < 0) - f.reset(); - } -} - - - -bool TBrowse::do_insert() -{ - bool ok = FALSE; - TString80 app; - - if (_insert[0] == 'M') - { - TString80 nm(_insert.mid(1)); - if (strncmp(nm, "BATB", 4) == 0) // Programma gestione tabelle - app = format("ba3 -0 %s", (const char*)nm.mid(4)); - // Obbligatorio usare la format globale - else // Programma generico di browse/edit - app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); - // Obbligatorio usare la format globale - } - else - { - app = _insert.mid(1); - } - -#if XVT_OS == XVT_OS_WIN - if (strnicmp(app, main_app().name(), 3) == 0) - app.insert("a", 3); -#endif - - TMailbox mail; - TMessage msg(cmd2name(app), MSG_AI, ""); - mail.send(msg); - - TExternal_app a(app); - a.run(); - - if (mail.check()) - { - TMessage* rcv = mail.next_s(MSG_AI); - if (rcv != NULL) _rec = atoi(rcv->body()); - if (_rec > 0) - { - _cursor->file().readat(_rec); - ok = _cursor->ok(); - if (ok) do_output(); -#ifdef DBG - else error_box("Selezione da programma esterno errata"); -#endif - } - } - return ok; -} - - -TToken_string& TBrowse::create_siblings(TToken_string& siblings) -{ - const TMask& mask = field().mask(); - siblings = ""; // Azzera la lista dei campi associati - - // if (!mask.is_running()) return siblings; - - TBit_array key(4); // Elenco delle chiavi gia' utilizzate - key.set(_cursor->key()); - - // Scorre la lista dei campi di output - int n = 0; - for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) - { - const short id = _fld->atodlg(i); - const TMask_field& f = mask.field(id); - if (!f.showed() || !f.is_edit()) // Scarta i campi non editabili - continue; - const TEdit_field& e = (const TEdit_field&)f; - const TBrowse* b = e.browse(); - if (b == NULL) - continue; // Scarta i campi senza ricerca - - const TCursor* c = b->cursor(); - - // Considera ricerche sullo stesso file ma con chiave diversa - if (c->file().num() == _cursor->file().num() && - (key[c->key()] == FALSE || id == _fld->dlg())) - { - const TString16 fn(_out_fn.get(n)); // Legge nome del campo su file - const int pos = _items.get_pos(fn); // Determina header corrispondente - if (pos >= 0) - { - siblings.add(id); - const char* h = _head.get(pos); - siblings.add(h); - const int et = siblings.find('@'); - if (et > 0) siblings.cut(et); - key.set(c->key()); // Marca la chiave come usata - } - } - } - - return siblings; -} - - -KEY TBrowse::run() -{ - do_input(TRUE); - _cursor->read(_isgteq); - - TString80 caption; - const TLocalisamfile& f = _cursor->file(); - if (f.tab()) - { - TFilename name("batb"); - name << _cursor->file().name() << ".msk"; - if (fexist(name.lower())) - { - TScanner m(name); - while (m.line().left(2) != "PA"); // Find PAGE - const int apicia = m.token().find('"')+1; - const int apicic = m.token().find('"', apicia); - caption = m.token().sub(apicia, apicic); - } - else - { - caption = name.mid(4); - caption.cut(caption.find('.')); - caption.insert("Tabella ", 0); - } - } - else - caption = f.description(); - if (!isalnum(caption[0])) - caption = "Selezione"; - - KEY k = K_ESC; - long selected = 0; - - TToken_string siblings; - create_siblings(siblings); - -{ - TToken_string* sib = siblings.empty() ? NULL : &siblings; - byte buttons = 0; - if (_insert.not_empty()) - { - TFilename path; - if (_insert[0] == 'M') - path = "ba3 -0"; - else - { - path = _insert.mid(1); - if (main_app().name() != cmd2name(path)) // Se non lancerei me stesso e ... - { - TExternal_app a(path); - if (a.can_run()) buttons = 1; // ... se c'e' memoria - } - } - } - - TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); - k = s.run(); - selected = s.selected(); -} - -switch (k) -{ - case K_INS: - k = do_insert() ? K_ENTER : K_ESC; - break; - case K_ENTER: - *_cursor = selected; - do_output(); - break; -default: - if (k >= K_CTRL) - { - const short id = siblings.get_int((k - K_CTRL) << 1); - TEdit_field& ef = (TEdit_field&)_fld->mask().field(id); - ef.set_focus(); - ef.mask().send_key(k = K_F9, 0); - } - break; -} - -return k; -} - -bool TBrowse::check(CheckTime t) -{ - bool passed = TRUE; - - if (_secondary == TRUE && t != RUNNING_CHECK) - return TRUE; - - // if (_checked && t == FINAL_CHECK) - // return TRUE; - // _checked = TRUE; - - if (_fld->check_type() != CHECK_NONE) - { - const TMaskmode mode = (TMaskmode)field().mask().mode(); - - CheckType chk = _fld->check_type(); - const int ne = do_input(TRUE); - if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL; - if (ne || chk == CHECK_REQUIRED) - { - _cursor->setkey(); - _cursor->file().read(_isequal); - passed = _cursor->ok(); - - if (t != FINAL_CHECK) - { - if (passed) - { - _cursor->repos(); - do_output(t); - } - else - { - do_clear(); - _fld->set_dirty(3); - } - } - } - else - if (t != FINAL_CHECK) do_clear(); - } - // _checked = passed; - return passed; -} - -bool TBrowse::empty_check() -{ - const TMaskmode mode = (TMaskmode)field().mask().mode(); - const bool no_check = mode == MODE_SEARCH || field().mask().query_mode(); - - if ( no_check || _fld->check_type() == CHECK_NONE || - _fld->check_type() == CHECK_NORMAL) - return TRUE; - else - return do_input() > 0; -} - - -/////////////////////////////////////////////////////////// -// TEdit_field -/////////////////////////////////////////////////////////// - -TEdit_field::TEdit_field(TMask* mask) -: TMask_field(mask), _browse(NULL), _sheet(NULL), - _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(TRUE), - _forced(FALSE) -{} - -TEdit_field::~TEdit_field() -{ - if (_browse) delete _browse; else - if (_sheet) delete _sheet; -} - -word TEdit_field::class_id() const -{ return CLASS_EDIT_FIELD; } - - -void TEdit_field::enable(bool on) -{ - TMask_field::enable(on); - if (_buttonwin != NULL_WIN) - show_window(_buttonwin, on && check_enabled() && showed()); -} - -void TEdit_field::show(bool on) -{ - TMask_field::show(on); - if (_buttonwin != NULL_WIN) - show_window(_buttonwin, on && check_enabled() && enabled()); -} - - -void TEdit_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); -#ifdef DBG - if (_size < 1) - { - _size = 8; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); - } -#endif - _width = scanner.integer(); - if (_width == 0) _width = _size; -} - - -const TBrowse* TEdit_field::get_browse(TScanner& scanner) const -{ - const int id = scanner.integer(); - const TEdit_field& f = mask().efield(id); - const TBrowse* b = (const TBrowse*)f.browse(); -#ifdef DBG - if (b == NULL) - yesnofatal_box("La USE del campo %d e' nulla e non puo' essere copiata nel campo %d", id, dlg()); -#endif - return b; -} - - -bool TEdit_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PI") // PICTURE - { - _picture = scanner.string(); -#ifdef DBG - if (_picture == "." && _size > 9 && _size != 15) - ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", - dlg(), (const char*)_prompt); -#endif - return TRUE; - } - - if (scanner.key() == "CH") - { - scanner.pop(); - if (scanner.key() == "NO") _check = CHECK_NORMAL; - else if (scanner.key() == "RE") _check = CHECK_REQUIRED; - else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;} - else _check = CHECK_NONE; - return TRUE; - } - - if (scanner.key() == "US") // USE - { -#ifdef DBG - if (_browse != NULL) - return error_box("USE duplicata nel campo %d", dlg()); -#endif - - int key = 1; - TRelation* r; - - const int logicnum = scanner.integer(); - TString16 tabmaskname; - - if (logicnum > 0) - r = new TRelation(logicnum); - else - { - tabmaskname = scanner.pop(); -#ifdef DBG - if (tabmaskname.len() > 4) - return error_box("'%s' non e' una tabella valida: %d", - (const char*)tabmaskname, dlg()); -#endif - r = new TRelation(tabmaskname); - } - - if (scanner.popkey() == "KE") - { - key = scanner.integer(); -#ifdef DBG - if (key < 1) - { - yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); - key = 1; - } -#endif - } - else scanner.push(); - - const char* filter = ""; - if (scanner.popkey() == "SE") - filter = (const char*)scanner.line(); - else - scanner.push(); - - _browse = new TBrowse(this, r, key, filter); - - if (tabmaskname.not_empty()) - { - if (strncmp(main_app().name(), "ba3", 3) != 0) - { - tabmaskname.insert("MBATB", 0); - _browse->set_insert(tabmaskname); - } - } - - return TRUE; - } - - if (scanner.key() == "CO") // Copyuse - { - const TString16 what(scanner.popkey()); - - const TBrowse* b = get_browse(scanner); - if (b == NULL) return FALSE; - - if (what == "US" || what == "AL") - _browse = new TBrowse(this, b->cursor()); - - if (_browse) - return _browse->parse_copy(what, *b); - -#ifdef DBG - return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); -#endif - } - - if (scanner.key() == "JO") - { -#ifdef DBG - if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); -#endif - _browse->parse_join(scanner); - return TRUE; - } - - if (scanner.key() == "SH") // SHEET - { -#ifdef DBG - if (_sheet) return error_box("SHEET duplicato nel campo %d", dlg()); -#endif - _sheet = new TList_sheet(this, _prompt, scanner.string()); - return TRUE; - } - - if (scanner.key() == "IT") // ITEM - { -#ifdef DBG - if (_sheet == NULL) return error_box("ITEM senza SHEET nel campo %d", dlg()); -#endif - _sheet->read_item(scanner); - return TRUE; - } - - if (scanner.key() == "IN") - { - if (_browse) _browse->parse_input(scanner); else - if (_sheet) _sheet->parse_input(scanner); -#ifdef DBG - else error_box("INPUT senza USE o SHEET nel campo %d", dlg()); -#endif - return TRUE; - } - - if (scanner.key() == "DI") - { -#ifdef DBG - if(!_browse) return error_box("DISPLAY senza USE nel campo %d", dlg()); -#endif - _browse->parse_display(scanner); - return TRUE; - } - - if (scanner.key() == "OU") - { - if (_browse) _browse->parse_output(scanner); - else if (_sheet) _sheet->parse_output(scanner); -#ifdef DBG - else return error_box("OUTPUT senza USE nel campo %d", dlg()); -#endif - return TRUE; - } - - if (scanner.key() == "AD") - { -#ifdef DBG - if(!_browse) return error_box("ADD senza USE nel campo %d", dlg()); -#endif - _browse->parse_insert(scanner); - return TRUE; - } - - if (scanner.key() == "VA") - { - const char* n = scanner.pop(); - _validate_func = isdigit(*n) ? atoi(n) : -1; -#ifdef DBG - if (_validate_func < 0) - return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); -#endif - - const int _nparms = scanner.integer(); -#ifdef DBG - if (_nparms < 0) - return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d", dlg()); -#endif - - for(int i = 0; i < _nparms; i++) - _validate_parms.add(scanner.operand()); - - return TRUE; - } - - if (scanner.key() == "WA") - { - _warning = scanner.string(); - return TRUE; - } - if (scanner.key() == "ME") - { - TFixed_string l(scanner.line().strip_spaces()); - int m = 0; - if (l[0] == '0') - { - l.ltrim(1); - l.ltrim(); - m = 1; - } - if (_message.objptr(m) == 0) - _message.add(new TToken_string(64), m); - TToken_string& ts = (TToken_string&)_message[m]; - ts.add(l); - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - - -void TEdit_field::create(WINDOW parent) -{ - const int len = create_prompt(parent); - - long bandiere = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; - if (_flags.uppercase) bandiere |= CTL_FLAG_MAC_GENEVA9; - if (_flags.password) bandiere |= CTL_FLAG_MAC_MONACO9; - - _x += len; - -#if XVTWS == WMWS - const int delta = 2; -#else - const int delta = 1; -#endif - - wincreate(WC_EDIT, _width+delta, 1, _str, parent, bandiere); - -#if XVT_OS == XVT_OS_WIN - HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW); - SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo -#endif - - if (_browse || _sheet) - { - long flags = default_flags(); - if (flags & CTL_FLAG_DISABLED) - { - flags &= ~CTL_FLAG_DISABLED; - flags |= CTL_FLAG_INVISIBLE; - } - _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, - 2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9); - } -} - -void TEdit_field::destroy() -{ - if (_buttonwin) - { close_window(_buttonwin); _buttonwin = NULL_WIN; } - TMask_field::destroy(); -} - - -void TEdit_field::set_window_data(const char* data) -{ - TMask_field::set_window_data(format(data)); -} - - -void TEdit_field::set_field_data(const char* data) -{ _str = data; } - -const char* TEdit_field::get_field_data() const -{ return _str; } - - -const char* TEdit_field::format(const char* d) -{ - fpark = d; - fpark.trim(); - - if (fpark.not_empty()) - { - if (fpark.len() > _size) - { -#ifdef DBG - yesnofatal_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size); -#endif - fpark.cut(_size); - } - - if (_flags.uppercase) - fpark.upper(); - - if (_flags.zerofilled) - fpark.right_just(_size, '0'); - else - if (_flags.rightjust) - fpark.right_just(_size); - } - - return fpark; -} - - -const char* TEdit_field::picture_data(const char* data, bool video) -{ - if (video) - { - data = format(data); - set_title(win(), (char*)data); - return get_window_data(); - } - - set_window_data(data); - TMask_field::get_window_data(); - fpark.trim(); - return fpark; -} - - -bool TEdit_field::validate(KEY k) -{ - return ::validate(_validate_func, *this, k, _validate_parms); -} - -// Certified 90% -bool TEdit_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - if (_message.objptr(1) && get() == "") do_message(1); - else do_message(0); - return TRUE; -} - -bool TEdit_field::on_key(KEY key) -{ - switch(key) - { - case K_TAB: - if (_validate_func == AUTOEXIT_FUNC || - _validate_func == NUMCALC_FUNC || - _validate_func == STRCALC_FUNC) - set_focusdirty(); // Forza validate - if (to_check(K_TAB, TRUE)) - { - set(get()); - bool ok = validate(key); // Check validation expression - - if (!ok) - { - if (_warning.not_empty()) error_box(_warning); - return FALSE; - } - - TMask& m = mask(); - const bool query = m.query_mode(); - - if (_sheet) ok = query || _sheet->check(); // Check consistency - else - if (check_enabled() && _browse && (!query || forced())) - ok = _browse->check(); - - if (!ok) - { - if (_warning.not_empty()) error_box(_warning); - else -#ifdef DBG - error_box("Valore del campo %d non valido: %s", dlg(), (const char*)get()); -#else - error_box("Valore non valido: %s", (const char*)get()); -#endif - return FALSE; - } - - ok = on_hit(); - if (!ok) - return FALSE; - - if (query && required() && in_key(0)) - { - const byte keys = m.num_keys(); - - for (int i = 1; i <= keys; i++) - if (in_key(i) && m.key_valid(i)) - { - for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) - m.field(fld).set_dirty(FALSE); - dispatch_e_char(get_parent(win()), K_AUTO_ENTER); - break; - } - } - return TRUE; - } - break; - case K_ENTER: - if (field() != NULL || mask().mode() == NO_MODE) - { - if (focusdirty()) set(get()); - - bool ok = validate(K_ENTER); // Check validation expression - if (!ok) - { - if (_warning.not_empty()) error_box(_warning); - return FALSE; - } - - const bool query = mask().query_mode(); - - // check consistency - if (_sheet) ok = query || _sheet->check(FINAL_CHECK); - else if (_browse && check_enabled()) - { - if (!query || forced()) - { - if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency - else ok = _browse->empty_check(); - } - } - else - ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); - - if (!ok) - { - if (_warning.not_empty()) error_box(_warning); - else error_box("Valore del campo %d non valido: '%s'", dlg(), (const char*)get()); - return FALSE; - } - } - break; - case K_F9: - if (check_enabled()) - { - if (dirty()) set(get()); - KEY k = K_ESC; - if (_browse) k = _browse->run(); - else if (_sheet) k = _sheet->run(); - else beep(); - if (mask().is_running() && k != K_F9) set_focus(); - if (k == K_ENTER) - { - set_dirty(); - if (mask().is_running()) - mask().send_key(K_TAB, 0); - else - on_hit(); - return TRUE; - } - else - return FALSE; - } - break; - default: - break; - } - - return TMask_field::on_key(key); -} - - -bool TEdit_field::has_check() const -{ - if (_browse) return check_type() != CHECK_NONE; - return _sheet != NULL; -} - -bool TEdit_field::check(CheckTime t) -{ - if (check_enabled() || (t == STARTING_CHECK && showed())) - { - if (_browse) return _browse->check(t); else - if (_sheet) return _sheet->check(t); - } - return TRUE; -} - -void TEdit_field::enable_check(bool on) -{ - _check_enabled = on; - if (_buttonwin != NULL_WIN) - show_window(_buttonwin, on); -} - - -/////////////////////////////////////////////////////////// -// Boolean_field -/////////////////////////////////////////////////////////// - - -TBoolean_field::TBoolean_field(TMask* m) -: TMask_field(m), _on(FALSE) -{} - - -word TBoolean_field::class_id() const -{ return CLASS_BOOLEAN_FIELD; } - - -void TBoolean_field::create(WINDOW parent) -{ - wincreate(WC_CHECKBOX, strlen(_prompt)+4, 1, _prompt, parent, 0); -} - - -const char* TBoolean_field::get_window_data() const -{ - CHECK(win(), "Control window not initialized"); - fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; - fpark[1] = '\0'; - return fpark; -} - - -void TBoolean_field::set_window_data(const char* data) -{ - CHECK(win(), "Control window not initialized"); - - if (data == NULL) data = ""; - const bool b = toupper(*data) == 'X'; - xvt_check_box(win(), b); -} - - -void TBoolean_field::set_field_data(const char* data) -{ - if (data == NULL) data = ""; - _on = toupper(*data) == 'X'; -} - -const char* TBoolean_field::get_field_data() const -{ - return _on ? "X" : " "; -} - - -bool TBoolean_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "ME") - { - const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE - - if (_message.items() == 0) - { - _message.add(new TToken_string(16)); - _message.add(new TToken_string(16)); - } - TToken_string& ts = (TToken_string&)_message[tf]; - ts.add(scanner.line().strip_spaces()); - - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - -void TBoolean_field::enable(bool on) -{ - _flags.enabled = on; - xvt_enable_control(_win, on); -} - - -bool TBoolean_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, K_SPACE); - if (!ok) return FALSE; - } - const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; - do_message(n); - return TRUE; -} - -bool TBoolean_field::on_key(KEY key) -{ - if (key == K_SPACE) - { - on_hit(); - set_dirty(); - return TRUE; - } - return TMask_field::on_key(key); -} - -/////////////////////////////////////////////////////////// -// Button_field -/////////////////////////////////////////////////////////// - -TButton_field::TButton_field(TMask* m) -: TMask_field(m) -{ - _flags.persistent = TRUE; -} - - -word TButton_field::class_id() const -{ return CLASS_BUTTON_FIELD; } - -void TButton_field::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - if (_width < 1) _width = 9; - _size = scanner.integer(); // Height - if (_size < 1) _size = 1; -} - - -bool TButton_field::parse_item(TScanner& scanner) -{ - return TMask_field::parse_item(scanner); -} - - -void TButton_field::create(WINDOW parent) -{ - long flags = CTL_FLAG_CENTER_JUST; - - switch (dlg()) - { - case DLG_OK: - if (_prompt.empty()) - _prompt = "Conferma"; - _virtual_key = _exit_key = K_ENTER; - flags |= CTL_FLAG_DEFAULT; - break; - case DLG_CANCEL: - if (_prompt.empty()) - _prompt = "Annulla"; - _virtual_key = _exit_key = K_ESC; - break; - case DLG_DELREC: - _virtual_key = 'E'; - _exit_key = K_DEL; - break; - case DLG_PRINT: - if (_prompt.empty()) - _prompt = "Stampa"; - _virtual_key = 'S'; - _exit_key = K_ENTER; - break; - case DLG_QUIT: - if (_prompt.empty()) - _prompt = "Fine"; - _virtual_key = K_F4; - _exit_key = K_QUIT; - break; - default: - { - _exit_key = 0; - TToken_string* message = (TToken_string*)_message.objptr(0); - if (message != NULL) - { - TToken_string msg(message->get(0), ','); - const TFixed_string m(msg.get(0)); - if (m == "EXIT") - _exit_key = msg.get_int(); - else - if (msg.get_int() == 0) _exit_key = atoi(m); - } - const int n = _prompt.find('~'); - _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; - } - break; - } - - -#if XWTWS == WMWS - _prompt.center_just(_width); -#endif - - wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); -} - -void TButton_field::enable(bool on) -{ - _flags.enabled = on; - xvt_enable_control(_win, on); -} - -void TButton_field::show(bool on) -{ - TMask_field::show(on); -} - - -bool TButton_field::on_key(KEY key) - -{ - if (key == K_SPACE) - { - on_hit(); - return TRUE; - } - return TMask_field::on_key(key); -} - -/////////////////////////////////////////////////////////// -// Date_field -/////////////////////////////////////////////////////////// - -word TDate_field::class_id() const -{ return CLASS_DATE_FIELD; } - -void TDate_field::create(WINDOW w) -{ - TEdit_field::create(w); - if (automagic()) - { - TDate d(TODAY); - set(d.string()); - } -} - -void TDate_field::parse_head(TScanner&) {} - -TDate_field::TDate_field(TMask* m) : TEdit_field(m) -{ - _size = _width = 10; -} - - -bool TDate_field::on_key(KEY key) -{ - if (to_check(key)) - { - TFixed_string data(get_window_data(), 15); - data.trim(); - if (data.not_empty()) - { - bool changed = FALSE; - if (isdigit(data[0])) - { - if (data.len() == 6) // Fix century (for this millenium only) - { - data.insert("19", 4); - changed = TRUE; - } - for (int meno = 2; meno <= 5; meno += 3) - if (data[meno] != '-') - { - data.insert("-", meno); - changed = TRUE; - } - if (data.len() == 8) // Fix century (for this millenium only) - { - data.insert("19", 6); - changed = TRUE; - } - } - else - { - TDate g(TODAY); - data.upper(); - if (data == "IERI") - { - --g; - changed = TRUE; - } - else - if (data == "DOMANI") - { - ++g; - changed = TRUE; - } - TString16 gstring(g.string()); - if (data == "PRIMO") - { - gstring.overwrite("01-01", 0); - changed = TRUE; - } - else - if (data == "ULTIMO") - { - gstring.overwrite("31-12", 0); - changed = TRUE; - } - else - if (data == "OGGI") changed = TRUE; - if (changed) data = gstring; - } - - TDate d(data); - if (!d.ok()) - { - // error_box("La data deve essere nel formato gg-mm-aaaa"); - error_box("Data errata o formato non valido"); - return FALSE; - } - else - if (changed) - TMask_field::set_window_data(d.string()); - } - } - - return TEdit_field::on_key(key); -} - -const char * TDate_field::get_window_data() const -{ - const char * data = TEdit_field::get_window_data(); - if (roman()) - { - const TDate d(data); - data = d.string(ANSI); - } - return data; -} - - -void TDate_field::set_window_data(const char * data) -{ - if (roman()) - { - const TDate d(data); - data = d.string(); - } - TEdit_field::set_window_data(data); -} - -/////////////////////////////////////////////////////////// -// Real_field -/////////////////////////////////////////////////////////// - -TReal_field::TReal_field(TMask* m) : TEdit_field(m) -{} - -word TReal_field::class_id() const -{ return CLASS_REAL_FIELD; } - -void TReal_field::create(WINDOW w) -{ - TEdit_field::create(w); - - if (_flags.firm) - set(::format("%ld", main_app().get_firm())); else - if (automagic()) - { - TDate d(TODAY); - set(::format("%d", d.year())); - } -} - -bool TReal_field::on_key(KEY key) -{ - if (to_check(key)) - { - if (roman()) - { - const int r = atoi(get_window_data()); - if (r < 0) return error_box("Numero romano errato"); - } - else - { - const char* n = get(); - if (*n && !real::is_real(n)) - return error_box("Valore numerico non valido"); - if (_flags.uppercase && real(n).sign() < 0) - return error_box("Il numero deve essere positivo"); - } - } - - return TEdit_field::on_key(key); -} - -void TReal_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); - -#ifdef DBG - if (_size < 1) - { - _size = 9; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); - } -#endif - - _width = _size; - _decimals = scanner.integer(); -} - -void TReal_field::set_window_data(const char* data) -{ - if (data == NULL) data = ""; - - if (roman()) - { - data = itor(atoi(data)); - TMask_field::set_window_data(data); - } - else - { - real n(data); - if (!n.is_zero()) - { - if (exchangeable() && decimals()) - { - const real& e = mask().exchange(); - n /= e; - } - if (_picture.empty()) - data = n.stringa(_size, _decimals); - else - data = n.string(_picture); - } - else data = ""; - TEdit_field::set_window_data(data); - } -} - -const char* TReal_field::get_window_data() const -{ - TEdit_field::get_window_data(); - if (roman()) - { - int r = atoi(fpark); - if (r == 0) r = rtoi(fpark); - if (r > 0) - { - int s = decimals(); - if (s < 1) s = 4; - if (_flags.zerofilled) - fpark.format("%0*d", s, r); - else - fpark.format("%*d", s, r); - } - else fpark.cut(0); - } - else - { - fpark = real::ita2eng(fpark); - if (exchangeable() && decimals()) - { - real n(fpark); - const real& e = mask().exchange(); - n *= e; - if (n.is_zero()) fpark.cut(0); - else fpark = n.string(); - } - } - - return fpark; -} - -void TReal_field::set_decimals(int d) -{ - _decimals = d; - if (_picture[0] == '.') - { - if (d > 0) _picture.format(".%d", d); - else _picture = "."; - } -} - - -void TReal_field::exchange(bool show_value, const real& nuo) -{ - const int dec = show_value ? 2 : 0; // Quanti decimali voglio - const bool value = decimals() != 0; // Sono attualmente in valuta ? - - if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito! - - if (mask().is_running()) - { - const char* n = get_window_data(); - if (*n) - { - const real& vec = mask().exchange(); - real r(n); - if (!show_value) - r *= nuo; - r /= vec; - r.round(dec); - set_decimals(dec); - TEdit_field::set_window_data(r.string(_picture)); - } - } - - if (decimals() != dec) - set_decimals(dec); -} - -/////////////////////////////////////////////////////////// -// List_field -/////////////////////////////////////////////////////////// - -TList_field::TList_field(TMask* m) : TMask_field(m) -{} - -word TList_field::class_id() const -{ - return CLASS_LIST_FIELD; -} - - -void TList_field::read_item(TScanner& scanner) -{ - TToken_string ts(scanner.string()); - _codes.add(ts.get()); - _values.add(ts.get()); - - ts = ""; - while (scanner.popkey() == "ME") - ts.add(scanner.line().strip_spaces()); - scanner.push(); - - _message.add(ts); -} - - -void TList_field::parse_head(TScanner& scanner) -{ - _size = scanner.integer(); - _width = scanner.integer(); - if (_width < 1) _width = _size+3; -} - - -bool TList_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "IT") // ITEM - { - read_item(scanner); - return TRUE; - } - - if (scanner.key() == "LI") // LISTITEM - { - TScanner sc(scanner.pop()); - while (sc.popkey() == "IT") // ITEM - read_item(sc); - return TRUE; - } - - return TMask_field::parse_item(scanner); -} - - -int TList_field::items() const -{ - return _codes.items(); -} - -void TList_field::add_item(const char* s) -{ - TToken_string t(s); - const TString16 item(t.get()); - const int pos = _codes.get_pos(item); - - if (pos < 0 ) - { - _codes.add(item); - win_list_add(win(), -1, (char*)t.get()); - } -} - - -void TList_field::delete_item(const char* s) -{ - TString16 t(s); - const int pos = _codes.get_pos(t); - - if (pos >= 0 ) - { - _codes.destroy(pos); - win_list_delete(win(), pos); - if (mask().is_running()) - { - win_list_set_sel(win(), 0, TRUE); - if (showed()) on_hit(); - } - } -} - - -void TList_field::add_list() -{ - if (roman() && _codes.items() < 12) - { - TString csafe, vsafe; - if (atoi(_codes) > 0) - { - csafe = _codes; _codes = ""; - vsafe = _values; _values = ""; - } - _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); - _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); - _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); - if (atoi(csafe) > 0) - { - _codes.add(csafe); - _values.add(vsafe); - if (_message.objptr(0)) - { - _message.add(_message[0], _codes.items()-1); - _message.add(NULL, 0); - } - } - } - - SLIST lst = slist_new(); - for (const char* item = _values.get(0); item; item = _values.get()) - slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L); - win_list_add(win(), -1, (char*)lst); - slist_dispose(lst); - - const char* init = ""; - if (roman() && automagic()) - init = format("%02d", TDate(TODAY).month()); - set_field_data(init); -} - - -void TList_field::replace_items(const char* codes, const char* values) -{ - _codes = codes; - _values = values; - - if (win() != NULL_WIN) - { - win_list_clear(win()); - add_list(); - current(0); - } -} - - -void TList_field::create(WINDOW parent) -{ - const int len = create_prompt(parent); - _x += len; - - wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); - add_list(); -} - - -int TList_field::str2curr(const char* data) -{ - TString16 str(data); - - if (roman() && str.len() < 2) - str.insert("0",0); - if (_flags.uppercase) - str.upper(); - - int i = str.not_empty() ? _codes.get_pos(str) : 0; - - if (i < 0) // Se non trova il codice ritenta dopo trim - { - for (i = 0; str[i] == '0' || str[i] == ' '; i++); - if (i > 0) - { - str.ltrim(i); - i = _codes.get_pos(str); - } - } - - if (i < 0) - { - if (items() && str.not_empty()) - yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", - data, prompt(), dlg()); - i = 0; - } - return i; -} - - -void TList_field::set_window_data(const char* data) -{ - CHECKD(win(), "Control window not initialized ", dlg()); - const int i = str2curr(data); - current(i); -} - - -void TList_field::current(int n) -{ - win_list_set_sel(win(), n, TRUE); -} - -int TList_field::current() const -{ - const int sel = win_list_get_sel_index(win()); -#ifdef DBG - if (sel < 0 && items() > 0) - error_box("Lista senza selezione nel campo %d", dlg()); -#endif - return sel; -} - -const char* TList_field::get_window_data() const -{ - const int c = current(); - const char* v = ((TList_field*)this)->_codes.get(c); - return v; -} - -void TList_field::set_field_data(const char* data) -{ - _str = data; - if (_str.not_empty()) - { - const int i = _codes.get_pos(_str); - if (i < 0) - _str = _codes.get(0); - } - else - _str = _codes.get(0); -} - -bool TList_field::on_hit() -{ - if (_handler) - { - bool ok = _handler(*this, K_SPACE); - if (!ok) return FALSE; - } - const int n = mask().is_running() ? current() : str2curr(_str); - do_message(n); - return TRUE; -} - -const char* TList_field::get_field_data() const -{ - return _str; -} - -bool TList_field::on_key(KEY key) -{ - if (key >= '0' && key <= 'z') - { - const int index = win_list_get_sel_index(win()); - CHECK(index >= 0, "List with no selection!"); - int newindex = -1; - -#if XVTWS == WMWS - if (key >= 'A' && key <= 'z') - { - for (int i = index+1; i != index; i++) - { - char item[16]; - bool flag; - - do - { - flag = win_list_get_elt(win(), i, item, 16); - if (!flag) - { - CHECK(i, "La lista e' vuota!"); - i = -1; - break; - } - } while (!flag); - if (flag && toupper(*item) == toupper(key)) - { - newindex = i; - break; - } - } // for - } // alphabetic -#endif - - if (key >= '0' && key <= '9') - { - newindex = (key == '0') ? 10 : key - '1'; - if (newindex > items()) - { - newindex = -1; - beep(); - } - } - - if (newindex >= 0) - { - win_list_suspend(win()); - win_list_set_sel(win(), index, FALSE); - win_list_set_sel(win(), newindex, TRUE); - win_list_resume(win()); - } - } // alphanumeric - -#if XVTWS == VMWS - if (key == K_TAB && class_id() == CLASS_LIST_FIELD) - dispacth_e_char(win(), K_F9); -#endif - - if (key == K_SPACE) on_hit(); - - return TMask_field::on_key(key); -} - - -/////////////////////////////////////////////////////////// -// TRadio_field -/////////////////////////////////////////////////////////// - -TRadio_field::TRadio_field(TMask* mask) -: TList_field(mask), _nitems(0), _active_item(0) -{} - - -word TRadio_field::class_id() const -{ - return CLASS_RADIO_FIELD; -} - - -void TRadio_field::create(WINDOW parent) -{ - const short id = dlg(); // Salva il control id - const int items = _codes.items(); - - if (_prompt.not_empty()) - { - const int dy = _flags.zerofilled ? 3 : items+2; - create_prompt(parent, _width, dy); - } - _x++; _y++; - _values.restart(); - - const char* s; - - const int width = _flags.zerofilled ? (_width-2)/items-1 : _width-2; - for(_nitems = 0; (s = _values.get()) != NULL; _nitems++) - { - CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); - - wincreate(WC_RADIOBUTTON, width, 1, s, parent,0); - _radio_ctl_win[_nitems] = _win; - _dlg += 1000; - - if (_flags.zerofilled) - _x += width+1; - else - _y++; - } - _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug - - _dlg = id; // Ripristina control id - - set_field_data(""); -} - -void TRadio_field::destroy() -{ - if (_promptwin) - { close_window(_promptwin); _promptwin = NULL_WIN; } - - for(int i = 0; i < _nitems; i++) - { - close_window(_radio_ctl_win[i]); - _radio_ctl_win[i] = NULL_WIN; - } -} - - -int TRadio_field::current() const -{ - const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); - return c; -} - - -void TRadio_field::current(int n) -{ - _active_item = n; - xvt_check_radio_button(win(), _radio_ctl_win, _nitems); -} - - -void TRadio_field::check_radiobutton(WINDOW checked) -{ - for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); - CHECK(i < _nitems, "Trying to check an invalid radio button"); - current(i); -} - - -void TRadio_field::enable(bool on) -{ - _flags.enabled = on; - for(int i = 0; i < _nitems; i++) - xvt_enable_control(_radio_ctl_win[i], on); -} - - -void TRadio_field::show(bool on) -{ - if (_promptwin) - show_window(_promptwin, on); - - for(int i = 0; i < _nitems; i++) - show_window(_radio_ctl_win[i], on); - _flags.showed = on; -} - -// Return TRUE if focus has left the radio -bool TRadio_field::move_focus(int d) -{ - const int act = _active_item + d; - if (act >= _nitems || act < 0) - { - _active_item = current(); - return TRUE; - } - xvt_set_front_control(_radio_ctl_win[_active_item = act]); - return FALSE; -} - - -/////////////////////////////////////////////////////////// -// TGroup_field -/////////////////////////////////////////////////////////// - -TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) -{ - _flags.persistent = TRUE; -} - -// _size means _heigth -void TGroup_field::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - _size = scanner.integer(); -} - - -void TGroup_field::create(WINDOW parent) -{ - const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; - wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); -} - +// $Id: maskfld.cpp,v 1.49 1994-11-16 15:50:57 guy Exp $ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if XVT_OS == XVT_OS_WIN +#include +#endif + +HIDDEN const int MAXSTR = 128; +HIDDEN char __fpark[MAXSTR]; // Temporary for get/set window data +HIDDEN TFixed_string fpark(__fpark, MAXSTR); + +/////////////////////////////////////////////////////////// +// Field Flags +/////////////////////////////////////////////////////////// + +// Certified 100% +TMask_field::TField_Flags::TField_Flags() +{ + automagic = persistent = FALSE; + enabled = enable_default = TRUE; + showed = show_default = TRUE; + uppercase = rightjust = FALSE; + zerofilled = FALSE; + dirty = focusdirty = FALSE; + roman = exchange = FALSE; + firm = ghost = FALSE; + password = FALSE; +} + +// Certified 100% +char TMask_field::TField_Flags::update(const char* s) +{ + const char* kk = s; + for (; *s; s++) + switch(toupper(*s)) + { + case '*': + password = TRUE; break; + case 'A': + automagic = persistent = TRUE; break; + case 'D': + enable_default = enabled = FALSE; break; + case 'F': + firm = persistent = TRUE; break; + case 'G': + ghost = TRUE; break; + case 'H': + show_default = showed = FALSE; break; + case 'M': + roman = TRUE; break; + case 'P': + persistent = TRUE; break; + case 'R': + rightjust = TRUE; break; + case 'U': + uppercase = TRUE; break; + case 'V': + exchange = TRUE; break; + case 'Z': + zerofilled = TRUE; break; + default : +#ifdef DBG + yesnofatal_box("FLAG sconosciuto in %s: %c", kk, *s); +#endif + break; + } + return *s; +} + + +/////////////////////////////////////////////////////////// +// TMask_field +/////////////////////////////////////////////////////////// + +int TMask_field::_x; // Position of the field +int TMask_field::_y; +int TMask_field::_width; +TFixed_string TMask_field::_prompt(__fpark, MAXSTR); // Prompt of the field + +TMask_field::TMask_field(TMask* m) +: _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), + _keys(0), _groups(0), _help(0), _handler(NULL), + _validate_func(-1), _validate_parms(1), _field(NULL) +{} + +// Certified 100% +TMask_field::~TMask_field() +{ + if (_field) delete _field; +} + + +// Certified 100% +bool TMask_field::is_edit() const +{ + const word c = class_id(); + return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD; +} + + +// Certified 100% +const char* TMask_field::class_name() const +{ return "Field"; } + + +// Certified 100% +word TMask_field::class_id() const +{ return CLASS_FIELD; } + + +// Certified 100% +bool TMask_field::ok() const +{ return win() != NULL_WIN && dlg() >= -1; } + + +// Certified 100% +void TMask_field::parse_head(TScanner&) +{} + + +// Certified 100% +short TMask_field::atodlg(const char* s) const +{ + short d = s ? atoi(s) : 0; + +#ifdef DBG + if (d == 0 || d < -1 || d > 1000) + { + yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); + d = -1; + } +#endif + + return d; +} + +void TMask_field::construct(short id, const char* prompt, int x, int y, + int len, WINDOW parent, const char* flags, int width) +{ + _x = x; _y = y; + _prompt = prompt; + _size = len; + if (class_id() == CLASS_REAL_FIELD) + { + ((TReal_field*)this)->set_decimals(width); + _width = _size; + } + else _width = width < 1 ? _size : width; + _dlg = id; + _flags.update(flags); + + create(parent); +} + + +void TMask_field::construct(TScanner& scanner, WINDOW parent) +{ + _dlg = atodlg(scanner.pop()); + parse_head(scanner); + _prompt.cut(0); + + scanner.popkey(); // BEGIN +#ifdef DBG + if (scanner.key() != "BE") + { + yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); + scanner.push(); + } +#endif + + while(scanner.popkey() != "EN") // END of control + parse_item(scanner); + create(parent); +} + +bool TMask_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PR") // PROMPT + { + _x = scanner.integer(); + _y = scanner.integer(); + _prompt = scanner.string(); + return TRUE; + } + + if (scanner.key() == "FL") // FLAG + { + const char* f = scanner.string(); + return _flags.update(f) == '\0'; + } + + if (scanner.key() == "FI") // FIELD + { + CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); + _field = new TFieldref(scanner.line(), 0); + return TRUE; + } + + if (scanner.key() == "HE") // HELP + { + _help = scanner.string(); + return TRUE; + } + + if (scanner.key() == "KE") // KEY + { + _keys.set(scanner.line()); + _keys.set(0L); + return TRUE; + } + + if (scanner.key() == "ME") + { + if (_message.objptr(0) == 0) + _message.add(new TToken_string(64), 0); + TToken_string& ts = (TToken_string&)_message[0]; + ts.add(scanner.line().strip_spaces()); + return TRUE; + } + + if (scanner.key() == "GR") + { + _groups.set(scanner.line()); + return TRUE; + } + + return FALSE; +} + + +long TMask_field::default_flags() const +{ + long f = CTL_FLAG_NATIVE_JUST; + + if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; + if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; + + return f; +} + +// Certified 100% +WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy, + const char* title, WINDOW parent, + long flags) +{ + _win = xvt_create_control(ct, + _x, _y, dx, dy, + (char*)title, + parent, + flags | default_flags(), + PTR_LONG(this), + _dlg); + + return _win; +} + + +// Certified 100% +WINDOW TMask_field::parent() const +{ return get_parent(win()); } + + +// Certified 90% +int TMask_field::create_prompt(WINDOW parent, int width, int heigth) +{ + const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; + if (width < 1) width = strlen(_prompt); + _prompt.rtrim(); // Could save some bytes + + if (width) + { + // Static controls shouldn't be grayed + const long flags = default_flags() & (~CTL_FLAG_DISABLED); +#if XVT_OS == XVT_OS_WIN + char* k = strchr(_prompt, '~'); + if (k != NULL) *k = '&'; +#endif + _promptwin = xvt_create_control + ( + wt, + _x, _y, width, heigth, + _prompt, + parent, + flags, + 0L, + -1 + ); + } + return width; +} + + +// Certified 100% +void TMask_field::destroy() +{ + if (_win) + { close_window(_win); _win = NULL_WIN; } + if (_promptwin) + { close_window(_promptwin); _promptwin = NULL_WIN; } +} + + +// Certified 100% +void TMask_field::create(WINDOW parent) +{ + _width = strlen(_prompt); + if (_width) + wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); +} + + +// Certified 100% +void TMask_field::enable(bool on) +{ + const word c = class_id(); + if (c != CLASS_FIELD) + { + enable_window(_win, on); + _flags.enabled = on; + } +} + + +// Certified 100% +void TMask_field::enable_default() +{ + const bool ed = _flags.enable_default; + enable(ed); +} + + +// Certified 100% +void TMask_field::show(bool on) +{ + show_window(_win, on); + if (_promptwin != NULL_WIN) + show_window(_promptwin, on); + _flags.showed = on; +} + + +// Certified 100% +void TMask_field::show_default() +{ + const bool sd = _flags.show_default; + show(sd); +} + + +// Certified 100% +bool TMask_field::active() const +{ + return enabled() && showed() && class_id() != CLASS_FIELD; +}; + + +// Certified 90% +word TMask_field::last_key() const +{ + long u = _keys.last_one(); + if (u < 0) u = 0; + return (word)u; +} + +void TMask_field::set_dirty(bool d) +{ +#ifdef DBG + if (dlg() == 103) + d *= 1; +#endif + + if (_flags.dirty > TRUE && d == FALSE) + return; + _flags.dirty = d; + set_focusdirty(d); +} + + + +// Certified 99% +const char* TMask_field::get_window_data() const +{ + get_title(win(), __fpark, MAXSTR); + return __fpark; +} + + +// Certified 99% +void TMask_field::set_window_data(const char* data) +{ + if (data != NULL) + set_title(win(), (char*)data); +} + + +// Certified 100% +void TMask_field::set_field_data(const char*) +{} + + +// Certified 100% +const char* TMask_field::get_field_data() const +{ return NULL; } + + +const char* TMask_field::picture_data(const char* data, bool video) +{ + fpark = data; + if (video) + { + fpark.trim(); + if (_flags.uppercase) fpark.upper(); + } + return fpark; +} + + +// Certified 90% +const char* TMask_field::prompt() const +{ + if (_promptwin != NULL_WIN) + _prompt = xvt_get_title(_promptwin); + else + _prompt = ""; + + return _prompt; +} + + +// Certified 100% +void TMask_field::reset() +{ + if (!_flags.persistent && class_id() != CLASS_FIELD) + set(""); +} + + +// Certified 100% +void TMask_field::set_prompt(const char* p) +{ + if (_promptwin != NULL_WIN) + set_title(_promptwin, (char*) p); +} + + +void TMask_field::set(const char* s) +{ + if (mask().is_running()) + { + set_window_data(s); + set_dirty(); + } + else + set_field_data(s); +} + +TString& TMask_field::get() const +{ + static TString80 gpark; + + if (mask().is_running()) + gpark = get_window_data(); + else + gpark = get_field_data(); + + return gpark.trim(); +} + + +void TMask_field::undo() +{ + set_window_data(get_field_data()); +} + + +bool TMask_field::autoload(const TRelation* r) +{ + if (_field) + { + set(_field->read(r)); + return TRUE; + } + return FALSE; +} + + +bool TMask_field::autosave(TRelation* r) const +{ + if (_field) + { + _field->write(get(), r); + return TRUE; + } + return FALSE; +} + + +// Certified 50% +HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) +{ +#ifdef DBG + if (f.class_id() != CLASS_LIST_FIELD) + { + error_box("Can't add/delete items of non list-box field %d", f.dlg()); + return; + } +#endif + TList_field& l = (TList_field&)f; + + TToken_string item(16); + item = msg.get(); + if (add) item.add(msg.get()); + item.strip("\"'"); + if (add) + l.add_item(item); + else + l.delete_item(item); +} + + +// Certified 90% +HIDDEN const char* copy_value(TToken_string& msg, const TString& val) +{ + int from = msg.get_int()-1; + int to = -1; + if (from < 0) from = 0; + else to = msg.get_int(); + return val.sub(from, to); +} + +void TMask_field::send_key(KEY k, short to) +{ + mask().send_key(k, to, this); +} + + +// Certified 90% +bool TMask_field::do_message(int num) +{ + const int MAX_CMD = 14; + static const char* commands[MAX_CMD] = + { + "ADD", // 0 + "CLEAR", // 1 + "CO", // 2 + "DEL", // 3 + "DIRTY", // 4 + "DISABLE", // 5 + "ENABLE", // 6 + "ENABLEDEF", // 7 + "EXIT", // 8 + "HIDE", // 9 + "PUSH", // 10 + "RESET", // 11 + "SHOW", // 12 + "UNDO" // 13 + }; + + TToken_string* message = (TToken_string*)_message.objptr(num); + if (message == NULL || message->empty()) return FALSE; + + TToken_string msg(16, ','); + TString80 value; + + for (const char* m = message->get(0); m && *m; m = message->get()) + { + KEY key = 0; + msg = m; + value = msg.get(); + value.trim(); + const char* dlg = msg.get(); + + int cmd = -1; + if (isalpha(value[0])) // binary search + { + int f = 0, l = MAX_CMD-1; + while (TRUE) + { + cmd = (f+l)>>1; + const int cmp = strcmp(value, commands[cmd]); + if (cmp == 0) break; + if (cmp > 0) f = cmd+1; + else l = cmd-1; + if (f > l) + { + cmd = -1; + break; + } + } + } + + if (cmd == 8) + { + mask().stop_run(atoi(dlg)); + continue; + } + + short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; + bool broadcast = dlg && strchr(dlg, '@'); + if (value[0] == '"') value = value.strip("\"'"); + else switch (cmd) + { + case 0: + modify_list(TRUE, mask().field(fld), msg); continue; + case 1: + key = 11000+'c'; break; + case 2: + value = copy_value(msg, get()); break; + case 3: + modify_list(FALSE, mask().field(fld), msg); continue; + case 4: + mask().field(fld).set_dirty(); continue; + case 5: + key = 11000+'d'; break; + case 6: + key = 11000+'e'; break; + case 7: + key = 11000+'E'; break; + case 9: + key = 11000+'h'; break; + case 10: + key = K_SPACE; break; + case 11: + key = K_F2; break; + case 12: + key = 11000+'s'; break; + case 13: + key = K_F3; break; + default: + key = atoi(value); + break; + } + + if (key) + { + if (key > 0) + { + if (broadcast) fld = -fld; + send_key(key, fld); + } + } + else + { + // Setta a value il campo fld solo se ha un valore diverso da value + if (broadcast) + { + for (int i = 0; i < mask().fields(); i++) + { + TMask_field& f = mask().fld(i); + if (f.in_group((int)fld)) + { + const char* prev = f.get(); + if (value != prev) + { + f.set(value); + if (f.showed() || f.ghost()) + f.on_hit(); + } + } + } + } + else + { + TMask_field& f = mask().field(fld); + const char* prev = f.get(); + if (value != prev) + { + f.set(value); + if (f.showed() || f.ghost()) + f.on_hit(); + } + } + } + } + + return TRUE; +} + + +// Certified 90% +bool TMask_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); + if (!ok) return FALSE; + } + do_message(0); + return TRUE; +} + + +bool TMask_field::to_check(KEY k, bool checkrun) const +{ + bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); + + if (!yes && checkrun) + yes = k == K_TAB && !mask().is_running(); + + return yes; +} + +// Certified 90% +bool TMask_field::on_key(KEY key) +{ + if (key > 11000) + { + switch(key-11000) + { + case 'E': + enable_default(); break; + case 'c': + reset(); on_hit(); + case 'd': + disable(); break; + case 'e': + enable(); break; + case 'h': + hide(); break; + case 's': + show(); break; +#ifdef DBG + default : + return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); +#endif + } + return TRUE; + } + + switch(key) + { + case K_SPACE: + set_dirty(); + break; + case K_PREV: + case K_NEXT: + send_key(key, 0); + break; + case K_F1: + if (_help.not_empty()) + message_box(_help); + else + beep(); + break; + case K_F2: + if (is_edit()) set(""); + else reset(); + set_dirty(); + break; + case K_F3: + undo(); + set_dirty(); + break; + default: + break; + } + + if (_handler) + return _handler(*this, key); + + return TRUE; +} + + +void TMask_field::set_focus() const +{ + const bool force = mask().is_running(); + mask().set_focus_win(win(), force); +} + +HIDDEN char* const _msg = &__tmp_string[512]; +#define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) + +bool TMask_field::error_box(const char* fmt, ...) const +{ + build_msg(); + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + set_focus(); + ::error_box("%s", _msg); + set_focus(); + } + return FALSE; +} + +bool TMask_field::message_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + ::message_box("%s", _msg); + set_focus(); + return FALSE; +} + +bool TMask_field::warning_box(const char* fmt, ...) const +{ + build_msg(); + + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + set_focus(); + ::warning_box("%s", _msg); + set_focus(); + } + return FALSE; +} + +bool TMask_field::yesno_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + const bool yes = ::yesno_box("%s", _msg); + set_focus(); + return yes; +} + +KEY TMask_field::yesnocancel_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + const KEY k = ::yesnocancel_box("%s", _msg); + set_focus(); + return k; +} + +/////////////////////////////////////////////////////////// +// TList_sheet +/////////////////////////////////////////////////////////// + +// Certified 100% +TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) +: _fld(f), _row(-1) +{ + _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); +} + +// Certified 100% +TList_sheet::~TList_sheet() +{ + delete _sheet; +} + +// Certified 100% +TMask_field& TList_sheet::field(short id) const +{ return field().mask().field(id); } + + +// Certified 100% +void TList_sheet::read_item(TScanner& scanner) +{ + TToken_string ts(scanner.string()); + _sheet->add(ts); +} + + +// Certified 100% +void TList_sheet::parse_input(TScanner& scanner) +{ + _inp_id.add(scanner.pop()); +} + + +// Certified 100% +void TList_sheet::parse_output(TScanner& scanner) +{ + _out_id.add(scanner.pop()); +} + +// il numero di riga selezionata +int TList_sheet::do_input() +{ + if (_inp_id.empty()) return -2; // List empty! + + _inp_id.restart(); + TToken_string rowsel(80); + + for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) + { + if (*fld == '"') + { + rowsel.add(fld+1); + if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1); + } + else + { + const short id = _fld->atodlg(fld); + if (id > 0) rowsel.add(field().mask().get(id)); + else rowsel.add(""); + } + } + + TString80 fd, it; + for (int i = 0 ; i < _sheet->items(); i++) + { + TToken_string& ts =_sheet->row(i); + + ts.restart(); + for ( const char* item = rowsel.get(0); item ; item = rowsel.get()) + { + it = item; it.trim(); + fd = ts.get(); fd.trim(); + if (fd != it) break; + } + if (!item) return i; + } + + return -1; // Value not found! +} + + +// Certified 50% +void TList_sheet::do_output(CheckTime t) +{ + if (_row < 0 || t == FINAL_CHECK) + return; + + _out_id.restart(); + TToken_string& rowsel = _sheet->row(_row); + rowsel.restart(); + for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) + { + const short id = _fld->atodlg(fld); + if (t != STARTING_CHECK || field().field() == NULL) + { + TMask_field& f = field(id); + f.set(rowsel.get()); + if (field().dlg() != id) + f.on_hit(); + } + } +} + + +// Certified 100% +KEY TList_sheet::run() +{ + _row = do_input(); + + _sheet->select(_row); + + const KEY k = _sheet->run(); + + switch (k) + { + case K_ENTER: + _row = (int)_sheet->selected(); + do_output(); + break; + default: + break; + } + + return k; +} + + +// Certified 100% +bool TList_sheet::check(CheckTime t) +{ + const bool passed = (_row = do_input()) != -1; + if (passed) do_output(t); + return passed; +} + + +/////////////////////////////////////////////////////////// +// TBrowse +/////////////////////////////////////////////////////////// + +// Certified 100% +TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) +: _relation(r), _cursor(new TCursor (r, filter, key)), + _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) +{} + + +// Certified 100% +TBrowse::TBrowse(TEdit_field* f, TCursor* c) +: _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) +{} + + +// Certified 100% +TBrowse::~TBrowse() +{ + if (_relation) + { + delete _relation; + delete _cursor; + } +} + + +// Certified 100% +void TBrowse::parse_display(TScanner& scanner) +{ + const char* s; + s = scanner.string(); + _head.add(s); + s = scanner.line(); + _items.add(s); +} + + +void TBrowse::parse_input(TScanner& scanner) +{ + const char* s = scanner.pop(); + _inp_fn.add(s); + + s = scanner.pop(); + if (*s == '"') // Constant string + { + scanner.push(); + _inp_id.add(scanner.line()); + } + else // Field on the mask + { + TString80 str(s); + if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field + else scanner.push(); + _inp_id.add(str); + } +} + + +void TBrowse::parse_output(TScanner& scanner) +{ + const char* s = scanner.pop(); +#ifdef DBG + field().atodlg(s); +#endif + _out_id.add(s); + s = scanner.pop(); + _out_fn.add(s); +} + + +bool TBrowse::parse_copy(const TString& what, const TBrowse& b) +{ + const bool all = what == "AL"; + if (all || what == "US") + { + set_insert(b.get_insert()); + _filter = b.get_filter(); + if (field()._warning.empty()) + field()._warning = b.field()._warning; + if (!all) return TRUE; + } + if (all || what == "IN") + { + _inp_id = b._inp_id; + _inp_fn = b._inp_fn; + if (!all) return TRUE; + } + if (all || what == "DI") + { + _head = b._head; + _items = b._items; + if (!all) return TRUE; + } + if (all || what == "OU") + { + _out_id = b._out_id; + _out_fn = b._out_fn; + _secondary = TRUE; + } + return TRUE; +} + + +void TBrowse::parse_join(TScanner& scanner) +{ + TString80 j(scanner.pop()); // File or table + + CHECKS(_relation, "Can't join to NULL relation ", (const char*)j); + + int to; + if (scanner.popkey() == "TO") // TO keyword + { + const char* t = scanner.pop(); + to = name2log(t); + } + else + { + to = 0; // _relation->lfile()->num(); + scanner.push(); + } + + int key = 1; + if (scanner.popkey() == "KE") + key = scanner.integer(); + else scanner.push(); + + byte alias = 0; + if (scanner.popkey() == "AL") + alias = scanner.integer(); + else scanner.push(); + + TToken_string exp(80); + if (scanner.pop() == "INTO") + { + const char* r = scanner.pop(); + while (strchr(r, '=') != NULL) + { + exp.add(r); + r = scanner.pop(); + } + } + scanner.push(); + +#ifdef DBG + if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); +#endif + + if (isdigit(j[0])) + _relation->add(atoi(j), exp, key, to, alias); // join file + else + { +#ifdef DBG + if (j.len() > 4) + yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); + else +#endif + _relation->add(j, exp, key, to, alias); // join table + } +} + + +void TBrowse::parse_insert(TScanner& scanner) +{ + const TString16 key(scanner.popkey()); + + if (key == "NO") _insert = ""; + else + { + if (key == "RU") + { + _insert = "R"; + _insert << scanner.line(); + } + else + { + _insert = "M"; + _insert << scanner.line(); + } + _insert.trim(); + } +} + + +// Certified 100% +TMask_field& TBrowse::field(short n) const +{ return _fld->mask().field(n); } + + +// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro +int TBrowse::inputs() +{ + int inp = 0; + for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) + { + if (*fld != '"' && strchr(fld, '@') == NULL) + inp++; + } + return inp; +} + +// Ritorna il numero di campi non vuoti e non filtrati +int TBrowse::do_input(bool filter) +{ + int ne = 0; + if (_inp_id.empty()) return ne; + + TRectype& cur = _cursor->curr(); + + cur.zero(); + TRectype filtrec(cur); + + _inp_id.restart(); + _inp_fn.restart(); + + TString80 val; // Value to output + bool tofilter; + + for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) + { + if (*fld == '"') + { + val = (fld+1); + if (val.not_empty()) val.rtrim(1); + tofilter = filter; + } + else + { + const short id = _fld->atodlg(fld); + const bool filter_flag = strchr(fld, '@') != NULL; + tofilter = filter && filter_flag; + val = field(id).get(); + if (field(id).is_edit() && val.not_empty() && !filter_flag) + ne++; // Increment not empty fields count + } + + TFieldref fldref(_inp_fn.get(), 0); // Output field + fldref.write(val, _cursor->relation()); + if (tofilter) + { + if (val.empty()) val.fill('~', fldref.len(cur)); + fldref.write(val, filtrec); + } + } + + if (!filter) return ne; + + TString work(_filter.size()); + for (int i = 0; _filter[i]; i++) + { + if (_filter[i] == '"') + { + do + { + work << _filter[i++]; + } while (_filter[i] && _filter[i] != '"'); + work << '"'; + if (!_filter[i]) break; + } + else + if (_filter[i] == '#') + { + work << '"' << field(atoi(&_filter[++i])).get() << '"'; + while (isspace(_filter[i])) i++; + while (isdigit(_filter[i])) i++; + i--; + } + else work << _filter[i]; + } + + _cursor->setfilter(work); + _cursor->setregion(filtrec, filtrec); + + return ne; +} + + +void TBrowse::do_output(CheckTime t) +{ + if (t == FINAL_CHECK) + return; + + TString80 sum; + TToken_string flds(24, '+'); + + _out_fn.restart(); + for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) + { + const short id = field().atodlg(fld); + TMask_field& f = field(id); + + flds = _out_fn.get(); + if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) + { + sum.cut(0); + for(const char* fr = flds.get(0); fr; fr = flds.get()) + { + const char* val; + if (*fr == '"') + { + const TString80 v(fr); + val = v.mid(1, v.len()-2); + } + else + { + const TFieldref fld(fr, 0); + val = fld.read(_cursor->relation()); + } + sum << val; + } + + f.set(sum); + if (field().dlg() != id) + f.on_hit(); + } + } +} + + +void TBrowse::do_clear() +{ + for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) + { + TMask_field& f = field(atoi(fld)); + if (f.field() == NULL && _inp_id.get_pos(fld) < 0) + f.reset(); + } +} + + + +bool TBrowse::do_insert() +{ + bool ok = FALSE; + TString80 app; + + if (_insert[0] == 'M') + { + TString80 nm(_insert.mid(1)); + if (strncmp(nm, "BATB", 4) == 0) // Programma gestione tabelle + app = format("ba3 -0 %s", (const char*)nm.mid(4)); + // Obbligatorio usare la format globale + else // Programma generico di browse/edit + app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); + // Obbligatorio usare la format globale + } + else + { + app = _insert.mid(1); + } + +#if XVT_OS == XVT_OS_WIN + if (strnicmp(app, main_app().name(), 3) == 0) + app.insert("a", 3); +#endif + + TMailbox mail; + TMessage msg(cmd2name(app), MSG_AI, ""); + mail.send(msg); + + TExternal_app a(app); + a.run(); + + if (mail.check()) + { + TMessage* rcv = mail.next_s(MSG_AI); + if (rcv != NULL) _rec = atoi(rcv->body()); + if (_rec > 0) + { + _cursor->file().readat(_rec); + ok = _cursor->ok(); + if (ok) do_output(); +#ifdef DBG + else error_box("Selezione da programma esterno errata"); +#endif + } + } + return ok; +} + + +TToken_string& TBrowse::create_siblings(TToken_string& siblings) +{ + const TMask& mask = field().mask(); + siblings = ""; // Azzera la lista dei campi associati + + // if (!mask.is_running()) return siblings; + + TBit_array key(4); // Elenco delle chiavi gia' utilizzate + key.set(_cursor->key()); + + // Scorre la lista dei campi di output + int n = 0; + for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) + { + const short id = _fld->atodlg(i); + const TMask_field& f = mask.field(id); + if (!f.showed() || !f.is_edit()) // Scarta i campi non editabili + continue; + const TEdit_field& e = (const TEdit_field&)f; + const TBrowse* b = e.browse(); + if (b == NULL) + continue; // Scarta i campi senza ricerca + + const TCursor* c = b->cursor(); + + // Considera ricerche sullo stesso file ma con chiave diversa + if (c->file().num() == _cursor->file().num() && + (key[c->key()] == FALSE || id == _fld->dlg())) + { + const TString16 fn(_out_fn.get(n)); // Legge nome del campo su file + const int pos = _items.get_pos(fn); // Determina header corrispondente + if (pos >= 0) + { + siblings.add(id); + const char* h = _head.get(pos); + siblings.add(h); + const int et = siblings.find('@'); + if (et > 0) siblings.cut(et); + key.set(c->key()); // Marca la chiave come usata + } + } + } + + return siblings; +} + + +KEY TBrowse::run() +{ + do_input(TRUE); + _cursor->read(_isgteq); + + TString80 caption; + const TLocalisamfile& f = _cursor->file(); + if (f.tab()) + { + TFilename name("batb"); + name << _cursor->file().name() << ".msk"; + if (fexist(name.lower())) + { + TScanner m(name); + while (m.line().left(2) != "PA"); // Find PAGE + const int apicia = m.token().find('"')+1; + const int apicic = m.token().find('"', apicia); + caption = m.token().sub(apicia, apicic); + } + else + { + caption = name.mid(4); + caption.cut(caption.find('.')); + caption.insert("Tabella ", 0); + } + } + else + caption = f.description(); + if (!isalnum(caption[0])) + caption = "Selezione"; + + KEY k = K_ESC; + long selected = 0; + + TToken_string siblings; + create_siblings(siblings); + +{ + TToken_string* sib = siblings.empty() ? NULL : &siblings; + byte buttons = 0; + if (_insert.not_empty()) + { + TFilename path; + if (_insert[0] == 'M') + path = "ba3 -0"; + else + { + path = _insert.mid(1); + if (main_app().name() != cmd2name(path)) // Se non lancerei me stesso e ... + { + TExternal_app a(path); + if (a.can_run()) buttons = 1; // ... se c'e' memoria + } + } + } + + TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); + k = s.run(); + selected = s.selected(); +} + +switch (k) +{ + case K_INS: + k = do_insert() ? K_ENTER : K_ESC; + break; + case K_ENTER: + *_cursor = selected; + do_output(); + break; +default: + if (k >= K_CTRL) + { + const short id = siblings.get_int((k - K_CTRL) << 1); + TEdit_field& ef = (TEdit_field&)_fld->mask().field(id); + ef.set_focus(); + ef.send_key(k = K_F9, 0); + } + break; +} + +return k; +} + +bool TBrowse::check(CheckTime t) +{ + bool passed = TRUE; + + if (_secondary == TRUE && t != RUNNING_CHECK) + return TRUE; + + // if (_checked && t == FINAL_CHECK) + // return TRUE; + // _checked = TRUE; + + if (_fld->check_type() != CHECK_NONE) + { + const TMaskmode mode = (TMaskmode)field().mask().mode(); + + CheckType chk = _fld->check_type(); + const int ne = do_input(TRUE); + if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL; + if (ne || chk == CHECK_REQUIRED) + { + _cursor->setkey(); + _cursor->file().read(_isequal); + passed = _cursor->ok(); + + if (t != FINAL_CHECK) + { + if (passed) + { + _cursor->repos(); + do_output(t); + } + else + { + do_clear(); + _fld->set_dirty(3); + } + } + } + else + if (t != FINAL_CHECK) do_clear(); + } + // _checked = passed; + return passed; +} + +bool TBrowse::empty_check() +{ + const TMaskmode mode = (TMaskmode)field().mask().mode(); + const bool no_check = mode == MODE_SEARCH || field().mask().query_mode(); + + if ( no_check || _fld->check_type() == CHECK_NONE || + _fld->check_type() == CHECK_NORMAL) + return TRUE; + else + return do_input() > 0; +} + + +/////////////////////////////////////////////////////////// +// TEdit_field +/////////////////////////////////////////////////////////// + +TEdit_field::TEdit_field(TMask* mask) +: TMask_field(mask), _browse(NULL), _sheet(NULL), + _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(TRUE), + _forced(FALSE) +{} + +TEdit_field::~TEdit_field() +{ + if (_browse) delete _browse; else + if (_sheet) delete _sheet; +} + +word TEdit_field::class_id() const +{ return CLASS_EDIT_FIELD; } + + +void TEdit_field::enable(bool on) +{ + TMask_field::enable(on); + if (_buttonwin != NULL_WIN) + show_window(_buttonwin, on && check_enabled() && showed()); +} + +void TEdit_field::show(bool on) +{ + TMask_field::show(on); + if (_buttonwin != NULL_WIN) + show_window(_buttonwin, on && check_enabled() && enabled()); +} + + +void TEdit_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); +#ifdef DBG + if (_size < 1) + { + _size = 8; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + } +#endif + _width = scanner.integer(); + if (_width == 0) _width = _size; +} + + +const TBrowse* TEdit_field::get_browse(TScanner& scanner) const +{ + const int id = scanner.integer(); + const TEdit_field& f = mask().efield(id); + const TBrowse* b = (const TBrowse*)f.browse(); +#ifdef DBG + if (b == NULL) + yesnofatal_box("La USE del campo %d e' nulla e non puo' essere copiata nel campo %d", id, dlg()); +#endif + return b; +} + + +bool TEdit_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PI") // PICTURE + { + _picture = scanner.string(); +#ifdef DBG + if (_picture == "." && _size > 9 && _size != 15) + ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", + dlg(), (const char*)_prompt); +#endif + return TRUE; + } + + if (scanner.key() == "CH") + { + scanner.pop(); + if (scanner.key() == "NO") _check = CHECK_NORMAL; + else if (scanner.key() == "RE") _check = CHECK_REQUIRED; + else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;} + else _check = CHECK_NONE; + return TRUE; + } + + if (scanner.key() == "US") // USE + { +#ifdef DBG + if (_browse != NULL) + return error_box("USE duplicata nel campo %d", dlg()); +#endif + + int key = 1; + TRelation* r; + + const int logicnum = scanner.integer(); + TString16 tabmaskname; + + if (logicnum > 0) + r = new TRelation(logicnum); + else + { + tabmaskname = scanner.pop(); +#ifdef DBG + if (tabmaskname.len() > 4) + return error_box("'%s' non e' una tabella valida: %d", + (const char*)tabmaskname, dlg()); +#endif + r = new TRelation(tabmaskname); + } + + if (scanner.popkey() == "KE") + { + key = scanner.integer(); +#ifdef DBG + if (key < 1) + { + yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); + key = 1; + } +#endif + } + else scanner.push(); + + const char* filter = ""; + if (scanner.popkey() == "SE") + filter = (const char*)scanner.line(); + else + scanner.push(); + + _browse = new TBrowse(this, r, key, filter); + + if (tabmaskname.not_empty()) + { + if (strncmp(main_app().name(), "ba3", 3) != 0) + { + tabmaskname.insert("MBATB", 0); + _browse->set_insert(tabmaskname); + } + } + + return TRUE; + } + + if (scanner.key() == "CO") // Copyuse + { + const TString16 what(scanner.popkey()); + + const TBrowse* b = get_browse(scanner); + if (b == NULL) return FALSE; + + if (what == "US" || what == "AL") + _browse = new TBrowse(this, b->cursor()); + + if (_browse) + return _browse->parse_copy(what, *b); + +#ifdef DBG + return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); +#endif + } + + if (scanner.key() == "JO") + { +#ifdef DBG + if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); +#endif + _browse->parse_join(scanner); + return TRUE; + } + + if (scanner.key() == "SH") // SHEET + { +#ifdef DBG + if (_sheet) return error_box("SHEET duplicato nel campo %d", dlg()); +#endif + _sheet = new TList_sheet(this, _prompt, scanner.string()); + return TRUE; + } + + if (scanner.key() == "IT") // ITEM + { +#ifdef DBG + if (_sheet == NULL) return error_box("ITEM senza SHEET nel campo %d", dlg()); +#endif + _sheet->read_item(scanner); + return TRUE; + } + + if (scanner.key() == "IN") + { + if (_browse) _browse->parse_input(scanner); else + if (_sheet) _sheet->parse_input(scanner); +#ifdef DBG + else error_box("INPUT senza USE o SHEET nel campo %d", dlg()); +#endif + return TRUE; + } + + if (scanner.key() == "DI") + { +#ifdef DBG + if(!_browse) return error_box("DISPLAY senza USE nel campo %d", dlg()); +#endif + _browse->parse_display(scanner); + return TRUE; + } + + if (scanner.key() == "OU") + { + if (_browse) _browse->parse_output(scanner); + else if (_sheet) _sheet->parse_output(scanner); +#ifdef DBG + else return error_box("OUTPUT senza USE nel campo %d", dlg()); +#endif + return TRUE; + } + + if (scanner.key() == "AD") + { +#ifdef DBG + if(!_browse) return error_box("ADD senza USE nel campo %d", dlg()); +#endif + _browse->parse_insert(scanner); + return TRUE; + } + + if (scanner.key() == "VA") + { + const char* n = scanner.pop(); + _validate_func = isdigit(*n) ? atoi(n) : -1; +#ifdef DBG + if (_validate_func < 0) + return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); +#endif + + const int _nparms = scanner.integer(); +#ifdef DBG + if (_nparms < 0) + return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d", dlg()); +#endif + + for(int i = 0; i < _nparms; i++) + _validate_parms.add(scanner.operand()); + + return TRUE; + } + + if (scanner.key() == "WA") + { + _warning = scanner.string(); + return TRUE; + } + if (scanner.key() == "ME") + { + TFixed_string l(scanner.line().strip_spaces()); + int m = 0; + if (l[0] == '0') + { + l.ltrim(1); + l.ltrim(); + m = 1; + } + if (_message.objptr(m) == 0) + _message.add(new TToken_string(64), m); + TToken_string& ts = (TToken_string&)_message[m]; + ts.add(l); + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + + +void TEdit_field::create(WINDOW parent) +{ + const int len = create_prompt(parent); + + long bandiere = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; + if (_flags.uppercase) bandiere |= CTL_FLAG_MAC_GENEVA9; + if (_flags.password) bandiere |= CTL_FLAG_MAC_MONACO9; + + _x += len; + +#if XVTWS == WMWS + const int delta = 2; +#else + const int delta = 1; +#endif + + wincreate(WC_EDIT, _width+delta, 1, _str, parent, bandiere); + +#if XVT_OS == XVT_OS_WIN + HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW); + SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo +#endif + + if (_browse || _sheet) + { + long flags = default_flags(); + if (flags & CTL_FLAG_DISABLED) + { + flags &= ~CTL_FLAG_DISABLED; + flags |= CTL_FLAG_INVISIBLE; + } + _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, + 2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9); + } +} + +void TEdit_field::destroy() +{ + if (_buttonwin) + { close_window(_buttonwin); _buttonwin = NULL_WIN; } + TMask_field::destroy(); +} + + +void TEdit_field::set_window_data(const char* data) +{ + TMask_field::set_window_data(format(data)); +} + + +void TEdit_field::set_field_data(const char* data) +{ _str = data; } + +const char* TEdit_field::get_field_data() const +{ return _str; } + + +const char* TEdit_field::format(const char* d) +{ + fpark = d; + fpark.trim(); + + if (fpark.not_empty()) + { + if (fpark.len() > _size) + { +#ifdef DBG + yesnofatal_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size); +#endif + fpark.cut(_size); + } + + if (_flags.uppercase) + fpark.upper(); + + if (_flags.zerofilled) + fpark.right_just(_size, '0'); + else + if (_flags.rightjust) + fpark.right_just(_size); + } + + return fpark; +} + + +const char* TEdit_field::picture_data(const char* data, bool video) +{ + if (video) + { + data = format(data); + set_title(win(), (char*)data); + return get_window_data(); + } + + set_window_data(data); + TMask_field::get_window_data(); + fpark.trim(); + return fpark; +} + + +bool TEdit_field::validate(KEY k) +{ + return ::validate(_validate_func, *this, k, _validate_parms); +} + +// Certified 90% +bool TEdit_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); + if (!ok) return FALSE; + } + if (_message.objptr(1) && get() == "") do_message(1); + else do_message(0); + return TRUE; +} + +bool TEdit_field::on_key(KEY key) +{ + switch(key) + { + case K_TAB: + if (_validate_func == AUTOEXIT_FUNC || + _validate_func == NUMCALC_FUNC || + _validate_func == STRCALC_FUNC) + set_focusdirty(); // Forza validate + if (to_check(K_TAB, TRUE)) + { + set(get()); + bool ok = validate(key); // Check validation expression + + if (!ok) + { + if (_warning.not_empty()) error_box(_warning); + return FALSE; + } + + TMask& m = mask(); + const bool query = m.query_mode(); + + if (_sheet) ok = query || _sheet->check(); // Check consistency + else + if (check_enabled() && _browse && (!query || forced())) + ok = _browse->check(); + + if (!ok) + { + if (_warning.not_empty()) error_box(_warning); + else +#ifdef DBG + error_box("Valore del campo %d non valido: %s", dlg(), (const char*)get()); +#else + error_box("Valore non valido: %s", (const char*)get()); +#endif + return FALSE; + } + + ok = on_hit(); + if (!ok) + return FALSE; + + if (query && required() && in_key(0)) + { + const byte keys = m.num_keys(); + + for (int i = 1; i <= keys; i++) + if (in_key(i) && m.key_valid(i)) + { + for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) + m.field(fld).set_dirty(FALSE); + // dispatch_e_char(get_parent(win()), K_AUTO_ENTER); + mask().stop_run(K_AUTO_ENTER); + break; + } + } + return TRUE; + } + break; + case K_ENTER: + if (field() != NULL || mask().mode() == NO_MODE) + { + if (focusdirty()) set(get()); + + bool ok = validate(K_ENTER); // Check validation expression + if (!ok) + { + if (_warning.not_empty()) error_box(_warning); + return FALSE; + } + + const bool query = mask().query_mode(); + + // check consistency + if (_sheet) ok = query || _sheet->check(FINAL_CHECK); + else if (_browse && check_enabled()) + { + if (!query || forced()) + { + if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency + else ok = _browse->empty_check(); + } + } + else + ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); + + if (!ok) + { + if (_warning.not_empty()) error_box(_warning); + else error_box("Valore del campo %d non valido: '%s'", dlg(), (const char*)get()); + return FALSE; + } + } + break; + case K_F9: + if (check_enabled()) + { + if (dirty()) set(get()); + KEY k = K_ESC; + if (_browse) k = _browse->run(); + else if (_sheet) k = _sheet->run(); + else beep(); + if (mask().is_running() && k != K_F9) set_focus(); + if (k == K_ENTER) + { + set_dirty(); + if (mask().is_running()) + send_key(K_TAB, 0); + else + on_hit(); + return TRUE; + } + else + return FALSE; + } + break; + default: + break; + } + + return TMask_field::on_key(key); +} + + +bool TEdit_field::has_check() const +{ + if (_browse) return check_type() != CHECK_NONE; + return _sheet != NULL; +} + +bool TEdit_field::check(CheckTime t) +{ + if (check_enabled() || (t == STARTING_CHECK && showed())) + { + if (_browse) return _browse->check(t); else + if (_sheet) return _sheet->check(t); + } + return TRUE; +} + +void TEdit_field::enable_check(bool on) +{ + _check_enabled = on; + if (_buttonwin != NULL_WIN) + show_window(_buttonwin, on); +} + + +/////////////////////////////////////////////////////////// +// Boolean_field +/////////////////////////////////////////////////////////// + + +TBoolean_field::TBoolean_field(TMask* m) +: TMask_field(m), _on(FALSE) +{} + + +word TBoolean_field::class_id() const +{ return CLASS_BOOLEAN_FIELD; } + + +void TBoolean_field::create(WINDOW parent) +{ + wincreate(WC_CHECKBOX, strlen(_prompt)+4, 1, _prompt, parent, 0); +} + + +const char* TBoolean_field::get_window_data() const +{ + CHECK(win(), "Control window not initialized"); + fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; + fpark[1] = '\0'; + return fpark; +} + + +void TBoolean_field::set_window_data(const char* data) +{ + CHECK(win(), "Control window not initialized"); + + if (data == NULL) data = ""; + const bool b = toupper(*data) == 'X'; + xvt_check_box(win(), b); +} + + +void TBoolean_field::set_field_data(const char* data) +{ + if (data == NULL) data = ""; + _on = toupper(*data) == 'X'; +} + +const char* TBoolean_field::get_field_data() const +{ + return _on ? "X" : " "; +} + + +bool TBoolean_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "ME") + { + const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE + + if (_message.items() == 0) + { + _message.add(new TToken_string(16)); + _message.add(new TToken_string(16)); + } + TToken_string& ts = (TToken_string&)_message[tf]; + ts.add(scanner.line().strip_spaces()); + + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + +void TBoolean_field::enable(bool on) +{ + _flags.enabled = on; + xvt_enable_control(_win, on); +} + + +bool TBoolean_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, K_SPACE); + if (!ok) return FALSE; + } + const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; + do_message(n); + return TRUE; +} + +bool TBoolean_field::on_key(KEY key) +{ + if (key == K_SPACE) + { + on_hit(); + set_dirty(); + return TRUE; + } + return TMask_field::on_key(key); +} + +/////////////////////////////////////////////////////////// +// Button_field +/////////////////////////////////////////////////////////// + +TButton_field::TButton_field(TMask* m) +: TMask_field(m) +{ + _flags.persistent = TRUE; +} + + +word TButton_field::class_id() const +{ return CLASS_BUTTON_FIELD; } + +void TButton_field::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + if (_width < 1) _width = 9; + _size = scanner.integer(); // Height + if (_size < 1) _size = 1; +} + + +bool TButton_field::parse_item(TScanner& scanner) +{ + return TMask_field::parse_item(scanner); +} + + +void TButton_field::create(WINDOW parent) +{ + long flags = CTL_FLAG_CENTER_JUST; + + switch (dlg()) + { + case DLG_OK: + if (_prompt.empty()) + _prompt = "Conferma"; + _virtual_key = _exit_key = K_ENTER; + flags |= CTL_FLAG_DEFAULT; + break; + case DLG_CANCEL: + if (_prompt.empty()) + _prompt = "Annulla"; + _virtual_key = _exit_key = K_ESC; + break; + case DLG_DELREC: + _virtual_key = 'E'; + _exit_key = K_DEL; + break; + case DLG_PRINT: + if (_prompt.empty()) + _prompt = "Stampa"; + _virtual_key = 'S'; + _exit_key = K_ENTER; + break; + case DLG_QUIT: + if (_prompt.empty()) + _prompt = "Fine"; + _virtual_key = K_F4; + _exit_key = K_QUIT; + break; + default: + { + _exit_key = 0; + TToken_string* message = (TToken_string*)_message.objptr(0); + if (message != NULL) + { + TToken_string msg(message->get(0), ','); + const TFixed_string m(msg.get(0)); + if (m == "EXIT") + _exit_key = msg.get_int(); + else + if (msg.get_int() == 0) _exit_key = atoi(m); + } + const int n = _prompt.find('~'); + _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; + } + break; + } + + +#if XWTWS == WMWS + _prompt.center_just(_width); +#endif + + wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); +} + +void TButton_field::enable(bool on) +{ + _flags.enabled = on; + xvt_enable_control(_win, on); +} + +void TButton_field::show(bool on) +{ + TMask_field::show(on); +} + + +bool TButton_field::on_key(KEY key) + +{ + if (key == K_SPACE) + { + on_hit(); + return TRUE; + } + return TMask_field::on_key(key); +} + +/////////////////////////////////////////////////////////// +// Date_field +/////////////////////////////////////////////////////////// + +word TDate_field::class_id() const +{ return CLASS_DATE_FIELD; } + +void TDate_field::create(WINDOW w) +{ + TEdit_field::create(w); + if (automagic()) + { + TDate d(TODAY); + set(d.string()); + } +} + +void TDate_field::parse_head(TScanner&) {} + +TDate_field::TDate_field(TMask* m) : TEdit_field(m) +{ + _size = _width = 10; +} + + +bool TDate_field::on_key(KEY key) +{ + if (to_check(key)) + { + TFixed_string data(get_window_data(), 15); + data.trim(); + if (data.not_empty()) + { + bool changed = FALSE; + if (isdigit(data[0])) + { + if (data.len() == 6) // Fix century (for this millenium only) + { + data.insert("19", 4); + changed = TRUE; + } + for (int meno = 2; meno <= 5; meno += 3) + if (data[meno] != '-') + { + data.insert("-", meno); + changed = TRUE; + } + if (data.len() == 8) // Fix century (for this millenium only) + { + data.insert("19", 6); + changed = TRUE; + } + } + else + { + TDate g(TODAY); + data.upper(); + if (data == "IERI") + { + --g; + changed = TRUE; + } + else + if (data == "DOMANI") + { + ++g; + changed = TRUE; + } + TString16 gstring(g.string()); + if (data == "PRIMO") + { + gstring.overwrite("01-01", 0); + changed = TRUE; + } + else + if (data == "ULTIMO") + { + gstring.overwrite("31-12", 0); + changed = TRUE; + } + else + if (data == "OGGI") changed = TRUE; + if (changed) data = gstring; + } + + TDate d(data); + if (!d.ok()) + { + // error_box("La data deve essere nel formato gg-mm-aaaa"); + error_box("Data errata o formato non valido"); + return FALSE; + } + else + if (changed) + TMask_field::set_window_data(d.string()); + } + } + + return TEdit_field::on_key(key); +} + +const char * TDate_field::get_window_data() const +{ + const char * data = TEdit_field::get_window_data(); + if (roman()) + { + const TDate d(data); + data = d.string(ANSI); + } + return data; +} + + +void TDate_field::set_window_data(const char * data) +{ + if (roman()) + { + const TDate d(data); + data = d.string(); + } + TEdit_field::set_window_data(data); +} + +/////////////////////////////////////////////////////////// +// Real_field +/////////////////////////////////////////////////////////// + +TReal_field::TReal_field(TMask* m) : TEdit_field(m) +{} + +word TReal_field::class_id() const +{ return CLASS_REAL_FIELD; } + +void TReal_field::create(WINDOW w) +{ + TEdit_field::create(w); + + if (_flags.firm) + set(::format("%ld", main_app().get_firm())); else + if (automagic()) + { + TDate d(TODAY); + set(::format("%d", d.year())); + } +} + +bool TReal_field::on_key(KEY key) +{ + if (to_check(key)) + { + if (roman()) + { + const int r = atoi(get_window_data()); + if (r < 0) return error_box("Numero romano errato"); + } + else + { + const char* n = get(); + if (*n && !real::is_real(n)) + return error_box("Valore numerico non valido"); + if (_flags.uppercase && real(n).sign() < 0) + return error_box("Il numero deve essere positivo"); + } + } + + return TEdit_field::on_key(key); +} + +void TReal_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); + +#ifdef DBG + if (_size < 1) + { + _size = 9; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + } +#endif + + _width = _size; + _decimals = scanner.integer(); +} + +void TReal_field::set_window_data(const char* data) +{ + if (data == NULL) data = ""; + + if (roman()) + { + data = itor(atoi(data)); + TMask_field::set_window_data(data); + } + else + { + real n(data); + if (!n.is_zero()) + { + if (exchangeable() && decimals()) + { + const real& e = mask().exchange(); + n /= e; + } + if (_picture.empty()) + data = n.stringa(_size, _decimals); + else + data = n.string(_picture); + } + else data = ""; + TEdit_field::set_window_data(data); + } +} + +const char* TReal_field::get_window_data() const +{ + TEdit_field::get_window_data(); + if (roman()) + { + int r = atoi(fpark); + if (r == 0) r = rtoi(fpark); + if (r > 0) + { + int s = decimals(); + if (s < 1) s = 4; + if (_flags.zerofilled) + fpark.format("%0*d", s, r); + else + fpark.format("%*d", s, r); + } + else fpark.cut(0); + } + else + { + fpark = real::ita2eng(fpark); + if (exchangeable() && decimals()) + { + real n(fpark); + const real& e = mask().exchange(); + n *= e; + if (n.is_zero()) fpark.cut(0); + else fpark = n.string(); + } + } + + return fpark; +} + +void TReal_field::set_decimals(int d) +{ + _decimals = d; + if (_picture[0] == '.') + { + if (d > 0) _picture.format(".%d", d); + else _picture = "."; + } +} + + +void TReal_field::exchange(bool show_value, const real& nuo) +{ + const int dec = show_value ? 2 : 0; // Quanti decimali voglio + const bool value = decimals() != 0; // Sono attualmente in valuta ? + + if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito! + + if (mask().is_running()) + { + const char* n = get_window_data(); + if (*n) + { + const real& vec = mask().exchange(); + real r(n); + if (!show_value) + r *= nuo; + r /= vec; + r.round(dec); + set_decimals(dec); + TEdit_field::set_window_data(r.string(_picture)); + } + } + + if (decimals() != dec) + set_decimals(dec); +} + +/////////////////////////////////////////////////////////// +// List_field +/////////////////////////////////////////////////////////// + +TList_field::TList_field(TMask* m) : TMask_field(m) +{} + +word TList_field::class_id() const +{ + return CLASS_LIST_FIELD; +} + + +void TList_field::read_item(TScanner& scanner) +{ + TToken_string ts(scanner.string()); + _codes.add(ts.get()); + _values.add(ts.get()); + + ts = ""; + while (scanner.popkey() == "ME") + ts.add(scanner.line().strip_spaces()); + scanner.push(); + + _message.add(ts); +} + + +void TList_field::parse_head(TScanner& scanner) +{ + _size = scanner.integer(); + _width = scanner.integer(); + if (_width < 1) _width = _size+3; +} + + +bool TList_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "IT") // ITEM + { + read_item(scanner); + return TRUE; + } + + if (scanner.key() == "LI") // LISTITEM + { + TScanner sc(scanner.pop()); + while (sc.popkey() == "IT") // ITEM + read_item(sc); + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + + +int TList_field::items() const +{ + return _codes.items(); +} + +void TList_field::add_item(const char* s) +{ + TToken_string t(s); + const TString16 item(t.get()); + const int pos = _codes.get_pos(item); + + if (pos < 0 ) + { + _codes.add(item); + win_list_add(win(), -1, (char*)t.get()); + } +} + + +void TList_field::delete_item(const char* s) +{ + TString16 t(s); + const int pos = _codes.get_pos(t); + + if (pos >= 0 ) + { + _codes.destroy(pos); + win_list_delete(win(), pos); + if (mask().is_running()) + { + win_list_set_sel(win(), 0, TRUE); + if (showed()) on_hit(); + } + } +} + + +void TList_field::add_list() +{ + if (roman() && _codes.items() < 12) + { + TString csafe, vsafe; + if (atoi(_codes) > 0) + { + csafe = _codes; _codes = ""; + vsafe = _values; _values = ""; + } + _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); + _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); + _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); + if (atoi(csafe) > 0) + { + _codes.add(csafe); + _values.add(vsafe); + if (_message.objptr(0)) + { + _message.add(_message[0], _codes.items()-1); + _message.add(NULL, 0); + } + } + } + + SLIST lst = slist_new(); + for (const char* item = _values.get(0); item; item = _values.get()) + slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L); + win_list_add(win(), -1, (char*)lst); + slist_dispose(lst); + + const char* init = ""; + if (roman() && automagic()) + init = format("%02d", TDate(TODAY).month()); + set_field_data(init); +} + + +void TList_field::replace_items(const char* codes, const char* values) +{ + _codes = codes; + _values = values; + + if (win() != NULL_WIN) + { + win_list_clear(win()); + add_list(); + current(0); + } +} + + +void TList_field::create(WINDOW parent) +{ + const int len = create_prompt(parent); + _x += len; + + wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); + add_list(); +} + + +int TList_field::str2curr(const char* data) +{ + TString16 str(data); + + if (roman() && str.len() < 2) + str.insert("0",0); + if (_flags.uppercase) + str.upper(); + + int i = str.not_empty() ? _codes.get_pos(str) : 0; + + if (i < 0) // Se non trova il codice ritenta dopo trim + { + for (i = 0; str[i] == '0' || str[i] == ' '; i++); + if (i > 0) + { + str.ltrim(i); + i = _codes.get_pos(str); + } + } + + if (i < 0) + { + if (items() && str.not_empty()) + yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", + data, prompt(), dlg()); + i = 0; + } + return i; +} + + +void TList_field::set_window_data(const char* data) +{ + CHECKD(win(), "Control window not initialized ", dlg()); + const int i = str2curr(data); + current(i); +} + + +void TList_field::current(int n) +{ + win_list_set_sel(win(), n, TRUE); +} + +int TList_field::current() const +{ + const int sel = win_list_get_sel_index(win()); +#ifdef DBG + if (sel < 0 && items() > 0) + error_box("Lista senza selezione nel campo %d", dlg()); +#endif + return sel; +} + +const char* TList_field::get_window_data() const +{ + const int c = current(); + const char* v = ((TList_field*)this)->_codes.get(c); + return v; +} + +void TList_field::set_field_data(const char* data) +{ + _str = data; + if (_str.not_empty()) + { + const int i = _codes.get_pos(_str); + if (i < 0) + _str = _codes.get(0); + } + else + _str = _codes.get(0); +} + +bool TList_field::on_hit() +{ + if (_handler) + { + bool ok = _handler(*this, K_SPACE); + if (!ok) return FALSE; + } + const int n = mask().is_running() ? current() : str2curr(_str); + do_message(n); + return TRUE; +} + +const char* TList_field::get_field_data() const +{ + return _str; +} + +bool TList_field::on_key(KEY key) +{ + if (key >= '0' && key <= 'z') + { + const int index = win_list_get_sel_index(win()); + CHECK(index >= 0, "List with no selection!"); + int newindex = -1; + +#if XVTWS == WMWS + if (key >= 'A' && key <= 'z') + { + for (int i = index+1; i != index; i++) + { + char item[16]; + bool flag; + + do + { + flag = win_list_get_elt(win(), i, item, 16); + if (!flag) + { + CHECK(i, "La lista e' vuota!"); + i = -1; + break; + } + } while (!flag); + if (flag && toupper(*item) == toupper(key)) + { + newindex = i; + break; + } + } // for + } // alphabetic +#endif + + if (key >= '0' && key <= '9') + { + newindex = (key == '0') ? 10 : key - '1'; + if (newindex > items()) + { + newindex = -1; + beep(); + } + } + + if (newindex >= 0) + { + win_list_suspend(win()); + win_list_set_sel(win(), index, FALSE); + win_list_set_sel(win(), newindex, TRUE); + win_list_resume(win()); + } + } // alphanumeric + +#if XVTWS == VMWS + if (key == K_TAB && class_id() == CLASS_LIST_FIELD) + dispacth_e_char(win(), K_F9); +#endif + + if (key == K_SPACE) on_hit(); + + return TMask_field::on_key(key); +} + + +/////////////////////////////////////////////////////////// +// TRadio_field +/////////////////////////////////////////////////////////// + +TRadio_field::TRadio_field(TMask* mask) +: TList_field(mask), _nitems(0), _active_item(0) +{} + + +word TRadio_field::class_id() const +{ + return CLASS_RADIO_FIELD; +} + + +void TRadio_field::create(WINDOW parent) +{ + const short id = dlg(); // Salva il control id + const int items = _codes.items(); + + if (_prompt.not_empty()) + { + const int dy = _flags.zerofilled ? 3 : items+2; + create_prompt(parent, _width, dy); + } + _x++; _y++; + _values.restart(); + + const char* s; + + const int width = _flags.zerofilled ? (_width-2)/items-1 : _width-2; + for(_nitems = 0; (s = _values.get()) != NULL; _nitems++) + { + CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); + + wincreate(WC_RADIOBUTTON, width, 1, s, parent,0); + _radio_ctl_win[_nitems] = _win; + _dlg += 1000; + + if (_flags.zerofilled) + _x += width+1; + else + _y++; + } + _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug + + _dlg = id; // Ripristina control id + + set_field_data(""); +} + +void TRadio_field::destroy() +{ + if (_promptwin) + { close_window(_promptwin); _promptwin = NULL_WIN; } + + for(int i = 0; i < _nitems; i++) + { + close_window(_radio_ctl_win[i]); + _radio_ctl_win[i] = NULL_WIN; + } +} + + +int TRadio_field::current() const +{ + const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); + return c; +} + + +void TRadio_field::current(int n) +{ + _active_item = n; + xvt_check_radio_button(win(), _radio_ctl_win, _nitems); +} + + +void TRadio_field::check_radiobutton(WINDOW checked) +{ + for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); + CHECK(i < _nitems, "Trying to check an invalid radio button"); + current(i); +} + + +void TRadio_field::enable(bool on) +{ + _flags.enabled = on; + for(int i = 0; i < _nitems; i++) + xvt_enable_control(_radio_ctl_win[i], on); +} + + +void TRadio_field::show(bool on) +{ + if (_promptwin) + show_window(_promptwin, on); + + for(int i = 0; i < _nitems; i++) + show_window(_radio_ctl_win[i], on); + _flags.showed = on; +} + +// Return TRUE if focus has left the radio +bool TRadio_field::move_focus(int d) +{ + const int act = _active_item + d; + if (act >= _nitems || act < 0) + { + _active_item = current(); + return TRUE; + } + xvt_set_front_control(_radio_ctl_win[_active_item = act]); + return FALSE; +} + + +/////////////////////////////////////////////////////////// +// TGroup_field +/////////////////////////////////////////////////////////// + +TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) +{ + _flags.persistent = TRUE; +} + +// _size means _heigth +void TGroup_field::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + _size = scanner.integer(); +} + + +void TGroup_field::create(WINDOW parent) +{ + const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; + wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); +} + diff --git a/include/maskfld.h b/include/maskfld.h index cdab9d1de..9fdfc844f 100755 --- a/include/maskfld.h +++ b/include/maskfld.h @@ -1,4 +1,4 @@ -/* $Id: maskfld.h,v 1.10 1994-11-15 17:14:28 guy Exp $ */ +/* $Id: maskfld.h,v 1.11 1994-11-16 15:51:01 guy Exp $ */ #ifndef __MASKFLD_H #define __MASKFLD_H @@ -187,6 +187,7 @@ public: const TFieldref* field() const { return _field; } void set_focus() const; + void send_key(KEY k, short to); // set focus, message-box, set focus bool message_box(const char* fmt, ...) const; diff --git a/include/prassi.ver b/include/prassi.ver index 2b2f55dd9..0704a4464 100755 --- a/include/prassi.ver +++ b/include/prassi.ver @@ -1 +1 @@ -#define VERSION 1.16 +#define VERSION 1.15 diff --git a/include/relapp.cpp b/include/relapp.cpp index f9e99cbeb..59c475510 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -1,4 +1,4 @@ -// $Id: relapp.cpp,v 1.28 1994-11-15 11:23:19 guy Exp $ +// $Id: relapp.cpp,v 1.29 1994-11-16 15:51:05 guy Exp $ #include #include #include @@ -712,7 +712,6 @@ bool TRelation_application::main_loop() // Dis/abilita cambio ditta enable_menu_item(M_FILE_NEW, (_mask->mode() == MODE_QUERY)); - k = _mask->run(); // Seleziona il cursore a clessidra se necessario diff --git a/include/xvtility.h b/include/xvtility.h index 75b442931..97c730a03 100755 --- a/include/xvtility.h +++ b/include/xvtility.h @@ -24,7 +24,8 @@ WINDOW xvt_create_window(WIN_TYPE wt, const char* caption, WINDOW parent, long flags, EVENT_HANDLER eh, - long app_data); + long app_data + ); WINDOW xvt_create_control(WIN_TYPE wt, short x, short y, short dx, short dy, @@ -32,7 +33,8 @@ WINDOW xvt_create_window(WIN_TYPE wt, WINDOW parent, long flags, long app_data, - int id); + int id + ); WINDOW xvt_create_statbar(); void xvt_statbar_set(const char* text, bool def = FALSE); @@ -53,6 +55,7 @@ WINDOW xvt_create_window(WIN_TYPE wt, bool xvt_get_checked_state(WINDOW win); void xvt_check_radio_button(WINDOW win, const WINDOW* ctls, int count); int xvt_get_checked_radio(const WINDOW* ctls, int count); + void xvt_change_page_tags(WINDOW pag, bool on, WINDOW tag, byte p); bool xvt_test_menu_tag(MENU_TAG tag); @@ -60,9 +63,6 @@ WINDOW xvt_create_window(WIN_TYPE wt, PAT_STYLE trans_brush(char p); PEN_STYLE trans_pen (char p); - - /* @END */ - extern short CHARX, CHARY, BASEY, ROWY; /* @END */