From 80b7a2bc865e920a008356c96add4498d9832a6a Mon Sep 17 00:00:00 2001 From: guy Date: Wed, 8 May 1996 11:09:13 +0000 Subject: [PATCH] Nuova versione campi a video git-svn-id: svn://10.65.10.50/trunk@2783 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/applicat.cpp | 51 +- include/applicat.h | 6 +- include/array.cpp | 23 +- include/browfile.h | 2 +- include/brwapp.cpp | 26 +- include/checks.h | 10 +- include/classes.h | 65 +- include/confapp.cpp | 52 +- include/config.cpp | 29 +- include/controls.cpp | 2593 +++++++++++++++++------------ include/controls.h | 402 +++-- include/default.url | 2 +- include/defmask.h | 2 +- include/files.cpp | 9 +- include/form.cpp | 2 +- include/golem.cpp | 2 +- include/isam.cpp | 9 +- include/isam.h | 4 +- include/mask.cpp | 1363 +++++++--------- include/mask.h | 175 +- include/maskfld.cpp | 3705 ++++++++++++++++++++---------------------- include/maskfld.h | 1197 +++++++------- include/msksheet.cpp | 1167 +++++-------- include/msksheet.h | 27 +- include/object.cpp | 16 +- include/object.h | 4 + include/prefix.cpp | 7 +- include/progind.cpp | 78 +- include/progind.h | 20 +- include/real.cpp | 22 +- include/real.h | 9 +- include/relapp.cpp | 249 +-- include/relapp.h | 30 +- include/relation.cpp | 29 +- include/relation.h | 8 +- include/scanner.h | 2 +- include/sheet.cpp | 1646 ++++++++++--------- include/sheet.h | 257 +-- include/stdtypes.cpp | 12 +- include/strings.cpp | 17 +- include/strings.h | 2 +- include/text.cpp | 59 +- include/text.h | 11 +- include/toolbar.h | 46 +- include/urldefid.h | 2 + include/validate.cpp | 29 +- include/value.h | 2 +- include/viswin.cpp | 392 ++--- include/viswin.h | 34 +- include/window.cpp | 83 +- include/window.h | 36 +- include/xvtility.cpp | 595 ++----- include/xvtility.h | 30 +- 53 files changed, 7266 insertions(+), 7384 deletions(-) diff --git a/include/applicat.cpp b/include/applicat.cpp index 6cd331cf9..c1c037f72 100755 --- a/include/applicat.cpp +++ b/include/applicat.cpp @@ -1,7 +1,7 @@ -#include - #include +#include + #if XVT_OS == XVT_OS_WIN #define STRICT #include @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -162,11 +163,13 @@ long XVT_CALLCONV1 TApplication::task_eh(WINDOW win, EVENT *ep) switch (ep->type) { case E_CREATE: + customize_controls(TRUE); create_backdrop(); #if defined(DBG) && XVT_OS == XVT_OS_SCOUNIX message_box("Attach to process %d ...", getpid()); #endif do_events(); + break; #if XVT_OS == XVT_OS_WIN case E_UPDATE: @@ -481,8 +484,8 @@ void TApplication::run( cfg.taskwin_title = (char*)(const char*)caption; cfg.menu_bar_ID = TASK_MENUBAR+addbar; cfg.about_box_ID = 0; - - customize_controls(TRUE); + + xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_PM_DRAWABLE_TWIN, TRUE); _application = this; xvt_app_create(argc, argv, 0L, task_eh, &cfg); @@ -543,6 +546,17 @@ void TApplication::dispatch_e_menu(MENU_TAG item) #endif } +// @cmember Setta il cursore a clessidra (To be removed soon) +void TApplication::begin_wait() +{ + ::begin_wait(); +} + +// @cmember Setta il cursore standard (To be removed soon) +void TApplication::end_wait() +{ + ::end_wait(); +} bool TApplication::has_module(int module, int checktype) const { @@ -647,7 +661,7 @@ bool TApplication::config() // carica campi for (int i = 0; i < m.fields(); i++) { - TMask_field& f = m.fld(i); + TEditable_field& f = (TEditable_field&)m.fld(i); const TFieldref* fref = f.field(); if (fref != NULL) { @@ -669,7 +683,7 @@ bool TApplication::config() // aggiusta campi for (i = 0; i < m.fields(); i++) { - TMask_field& f = m.fld(i); + TEditable_field& f = (TEditable_field&)m.fld(i); if (f.dirty()) { const TFieldref* fref = f.field(); @@ -684,31 +698,6 @@ bool TApplication::config() return ok; } -// @doc INTERNAL -// @mfunc Cambia il cursore del mouse -void TApplication::set_cursor( - bool w) // @parm Indica il tipo di cursore da utilizzare: - // - // @flag TRUE | Cursore a clessidra per le wait - // @flag FALSE | Cursore a frecca normale -{ - static int _count = 0; - - if (w) - { - if (_count == 0) - xvt_win_set_cursor(TASK_WIN, CURSOR_WAIT); - _count++; - } - else - { - _count--; - CHECK(_count >= 0, "end_wait without matching begin_wait"); - if (_count == 0) - xvt_win_set_cursor(TASK_WIN, CURSOR_ARROW); - } -} - // @doc EXTERNAL // @mfunc Controlla se al programma corrente e' concesso cambiare ditta da menu. diff --git a/include/applicat.h b/include/applicat.h index c817f07d4..187d5542f 100755 --- a/include/applicat.h +++ b/include/applicat.h @@ -173,11 +173,9 @@ public: { return _waiting; } // @cmember Setta il cursore a clessidra - void begin_wait() - { set_cursor(TRUE); } + void begin_wait(); // @cmember Setta il cursore standard - void end_wait() - { set_cursor(FALSE); } + void end_wait(); // @cmember Interfaccia runtime del menu' della finestra principale??? bool add_menu(TString_array& menu, MENU_TAG id = 0); diff --git a/include/array.cpp b/include/array.cpp index adfa4241d..6bdf6eb8b 100755 --- a/include/array.cpp +++ b/include/array.cpp @@ -1,16 +1,15 @@ #include #include -#include #include void TContainer::for_each( OPERATION_FUNCTION op ) { - TObject* curr = first_item( ); - while( curr ) + TObject* curr = first_item(); + while(curr) { - op( *curr ); - curr = succ_item( ); + op(*curr); + curr = succ_item(); } } @@ -166,7 +165,7 @@ bool TArray::destroy( if (index < 0) { - for (int i = size(); i--;) if (_data[i] != NULL) + for (int i = size()-1; i >= 0; i--) if (_data[i] != NULL) { delete _data[i]; _data[i] = NULL; @@ -183,16 +182,20 @@ bool TArray::destroy( } -TArray::TArray(int arraysize) : _size(0), _items(0), _next(0), _data(NULL) +TArray::TArray(int arraysize) + : _size(0), _items(0), _next(0), _data(NULL) { - if (arraysize) resize(arraysize); + if (arraysize) + resize(arraysize); } -TArray::TArray() : _size(0), _items(0), _next(0), _data(NULL) +TArray::TArray() + : _size(0), _items(0), _next(0), _data(NULL) { } -TArray::TArray(const TArray& a) : _size(0), _items(0), _next(0), _data(NULL) +TArray::TArray(const TArray& a) + : _size(0), _items(0), _next(0), _data(NULL) { (*this) = a; } diff --git a/include/browfile.h b/include/browfile.h index 9a4646a1d..2dbd5aed1 100755 --- a/include/browfile.h +++ b/include/browfile.h @@ -14,7 +14,7 @@ class TViswin; // dal testo ritornato typedef const char* (*MASK_LINKHANDLER)(TMask&, int, const char*, bool doubleclick); -class TBrowsefile_field : public TMask_field +class TBrowsefile_field : public TOperable_field { friend class TViswin; diff --git a/include/brwapp.cpp b/include/brwapp.cpp index df1b2a53c..8794f344b 100755 --- a/include/brwapp.cpp +++ b/include/brwapp.cpp @@ -1,6 +1,5 @@ #include #include -#include /////////////////////////////////////////////////////////// // TBrowse_application @@ -90,17 +89,20 @@ bool TBrowse_application::main_loop() curr_mask().close_modal(); curr_mask().set_mode(NO_MODE); - - if (recins > 0 && autoins_caller().not_empty()) - { - TMessage msg(autoins_caller(), MSG_AI, format("%ld", recins)); - msg.send(); + + if (recins > 0) + { + TString16 ri; ri << recins; + if (autoins_caller().not_empty()) + { + TMessage msg(autoins_caller(), MSG_AI, ri); + msg.send(); + } + if (lnflag()) + { + TMessage msg(autoins_caller(), MSG_LN, ri); + msg.send(); + } } - if (recins > 0 && lnflag()) - { - TMessage msg(autoins_caller(), MSG_LN, format("%ld", recins)); - msg.send(); - } - return k != K_QUIT; } diff --git a/include/checks.h b/include/checks.h index 14ac70ca1..17914d818 100755 --- a/include/checks.h +++ b/include/checks.h @@ -66,11 +66,19 @@ extern "C" { // // @xref +// @doc EXTERNAL + +// @msg CHECKD | Macro che richiama una per stampare messaggi d'errore a video +#define NFCHECK yesnofatal_box + + // @xref + #else #define CHECK(p, m) #define CHECKS(p, m, s) -#define CHECKD(p, m, d) +#define CHECKD(p, m, d) +#define NFCHECK 1 ? 0 : yesnofatal_box #endif diff --git a/include/classes.h b/include/classes.h index 269550378..074d96f16 100755 --- a/include/classes.h +++ b/include/classes.h @@ -6,40 +6,49 @@ // @END // @M -#define CLASS_OBJECT 1 -#define CLASS_ERROR 0 -#define CLASS_SORTABLE 2 +#define CLASS_ERROR 0 +#define CLASS_OBJECT 1 +#define CLASS_SORTABLE 2 -#define CLASS_STRING 10 -#define CLASS_FIXED_STRING 11 -#define CLASS_FILENAME 12 -#define CLASS_TOKEN_STRING 13 +#define CLASS_STRING 10 +#define CLASS_FIXED_STRING 11 +#define CLASS_FILENAME 12 +#define CLASS_TOKEN_STRING 13 -#define CLASS_APPLICATION 40 -#define CLASS_PRINT_APPLICATION 41 +#define CLASS_APPLICATION 20 +#define CLASS_RELATION_APPLICATION 21 +#define CLASS_PRINT_APPLICATION 22 -#define CLASS_PRINTROW 50 -#define CLASS_PRINTER 51 +#define CLASS_PRINTER 50 +#define CLASS_PRINTROW 51 -#define CLASS_CONTAINER 100 -#define CLASS_ARRAY 101 -#define CLASS_STACK 102 +#define CLASS_CONTAINER 100 +#define CLASS_ARRAY 101 +#define CLASS_STACK 102 -#define CLASS_FIELD 20 -#define CLASS_EDIT_FIELD 21 -#define CLASS_REAL_FIELD 22 -#define CLASS_DATE_FIELD 23 -#define CLASS_BOOLEAN_FIELD 24 -#define CLASS_LIST_FIELD 25 -#define CLASS_RADIO_FIELD 26 -#define CLASS_BUTTON_FIELD 27 -#define CLASS_SHEET_FIELD 28 -#define CLASS_BROWSEFILE_FIELD 29 -#define CLASS_MEMO_FIELD 30 -#define CLASS_ZOOM_FIELD 31 - -#define CLASS_GOLEM 200 +#define CLASS_WINDOW 200 +#define CLASS_SHEET 201 +#define CLASS_MASK 210 +#define CLASS_FIELD 220 +#define CLASS_TEXT_FIELD 221 +#define CLASS_LINE_FIELD 222 +#define CLASS_RECTANGLE_FIELD 223 +#define CLASS_GROUPBOX_FIELD 224 +#define CLASS_OPERABLE_FIELD 230 +#define CLASS_BUTTON_FIELD 231 +#define CLASS_SHEET_FIELD 232 +#define CLASS_BROWSEFILE_FIELD 233 +#define CLASS_MEMO_FIELD 234 +#define CLASS_ZOOM_FIELD 235 +#define CLASS_EDITABLE_FIELD 240 +#define CLASS_BOOLEAN_FIELD 241 +#define CLASS_LIST_FIELD 242 +#define CLASS_RADIO_FIELD 243 +#define CLASS_EDIT_FIELD 244 +#define CLASS_REAL_FIELD 245 +#define CLASS_DATE_FIELD 246 +#define CLASS_GOLEM 900 // @END #endif // __CLASSES_H diff --git a/include/confapp.cpp b/include/confapp.cpp index 8e6b89502..fa55bc9a0 100755 --- a/include/confapp.cpp +++ b/include/confapp.cpp @@ -1,10 +1,7 @@ #include -#include -#include #include #include - -#define comunque +#include bool TConfig_application::create() { @@ -69,20 +66,17 @@ void TConfig_application::do_config(int m) TMask m(maskname); // carica campi - for (int i = 0; i < m.fields(); i++) - { + const int max = m.fields(); + for (int i = 0; i < max; i++) + { TMask_field& f = m.fld(i); - const TFieldref* fref = f.field(); - if (fref != NULL) + if (f.field() != NULL) { - const char* fname = fref->name(); - if (fname != NULL) - { - TString& oldvl = cnf.get(fname); - if (!oldvl.empty()) - f.set(oldvl); - } - } + const char* fname = f.field()->name(); + TString& oldvl = cnf.get(fname); + if (!oldvl.empty()) + f.set(oldvl); + } } // run mask @@ -97,33 +91,29 @@ void TConfig_application::do_config(int m) if (k == K_ENTER || k == K_QUIT) { // aggiusta campi - for (i = 0; i < m.fields(); i++) + for (i = 0; i < max; i++) { TMask_field& f = m.fld(i); - if (f.dirty()) + if (f.dirty() && f.field()) { - const TFieldref* fref = f.field(); - if (fref != NULL) - { - const char* fname = fref->name(); - const char* value = f.get(); - const char* oldvl = cnf.get(fname); + const char* fname = f.field()->name(); + const char* value = f.get(); + const char* oldvl = cnf.get(fname); - if (!tosave) - tosave = yesno_box("Modifiche non registrate. Salvare?"); + if (!tosave) + tosave = yesno_box("Modifiche non registrate. Salvare?"); - if (!tosave) break; + if (!tosave) break; - if (postprocess_config_changed(par,fname, oldvl,value)) - cnf.set(fname, value, NULL, TRUE); - } + if (postprocess_config_changed(par, fname, oldvl, value)) + cnf.set(fname, value, NULL, TRUE); } } } else break; } if (k == K_QUIT) - break comunque; + break; } else { diff --git a/include/config.cpp b/include/config.cpp index 5cab3017b..057f5fa6e 100755 --- a/include/config.cpp +++ b/include/config.cpp @@ -90,14 +90,14 @@ void TConfig::_write_file() temp.temp("cnf"); ofstream out(temp); - TFixed_string l(__tmp_string, sizeof(__tmp_string)); - TString80 cnf; cnf << '[' << _paragraph << ']'; + TString l(256); + TString cnf(16); cnf << '[' << _paragraph << ']'; bool skip = FALSE, done = FALSE; while (!in.eof()) { - in.getline(__tmp_string,sizeof(__tmp_string)-1); + in.getline((char*)(const char*)l, l.size()); l.trim(); if (cnf == l) @@ -232,7 +232,10 @@ long TConfig::get_long( if (*n) def = atol(n); else - set(var, format("%ld", def), section, TRUE, index); + { + TString16 d; d << def; + set(var, d, section, TRUE, index); + } return def; } @@ -261,8 +264,11 @@ char TConfig::get_char( const char* n = get(var,section,index); if (*n) def = *n; - else - set(var, format("%c", def), section, TRUE, index); + else + { + const char d[2] = { def, '\0' }; + set(var, d, section, TRUE, index); + } return def; } @@ -314,11 +320,9 @@ bool TConfig::get_bool( // // @xref // -{ - if (def) strcpy(__tmp_string, "X"); - else *__tmp_string = '\0'; - - const TString& s = get(var, section, index, __tmp_string).upper(); +{ + const TString16 d(def ? "X" : ""); + const TString& s = get(var, section, index, d).upper(); return s != "" && (s == "X" || s == "ON" || s == "YES" || s == "OK" || s == "TRUE"); } @@ -359,7 +363,8 @@ COLOR TConfig::get_color( else { int r, g, b; RGB_COLOR(def, r, g, b); - set(var, format("%d,%d,%d", r, g, b), section, TRUE, index); + TString16 d; d << r << ',' << g << ',' << b; + set(var, d, section, TRUE, index); } return def; } diff --git a/include/controls.cpp b/include/controls.cpp index cace2809e..b24bf8945 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -1,21 +1,46 @@ -extern "C" -{ -#include -#include -} - -#if XVT_OS != XVT_OS_WIN -#error "This file should be compiled for Windows only" +#if XVT_OS == XVT_OS_WIN +#define STRICT +#include #endif #include +#include #include +#include #include -#include #include -#define STRICT -#include +#ifndef STX_DATA +// Very deep hacking +typedef struct _stx_data +{ + int cid; + WINDOW win; + RCT rct; + unsigned long attrib; +} STX_DATA; + +#endif + +#define CAMPI_SCAVATI FALSE + +HIDDEN int X_FU_MULTIPLE = 0; +HIDDEN int Y_FU_MULTIPLE = 0; +HIDDEN const int ITF_CID = 30000; + +KEY TControl::xiev_to_key(const XI_EVENT* xiev) +{ + KEY key = xiev->v.chr.ch; + if (key < K_INS || key > K_HELP) + { + if (xiev->v.chr.shift && (key < ' ' || key >= K_UP)) key += K_SHIFT; + if (xiev->v.chr.control && key >= ' ') key += K_CTRL; + } + return key; +} + + +// @doc INTERNAL /////////////////////////////////////////////////////////// // TPicture_array @@ -26,12 +51,11 @@ class TPicture_array : public TArray public: TImage& add(short id, bool convert = FALSE); - //TImage& image(short id) { return (TImage&)operator[](id); } const TImage& image(short id) const { return (const TImage&)operator[](id); } bool exist(short id) const { return objptr(id) != NULL; } TPicture_array() : TArray(128) {} - ~TPicture_array() {} + virtual ~TPicture_array() {} }; TImage& TPicture_array::add(short id, bool convert) @@ -43,264 +67,682 @@ TImage& TPicture_array::add(short id, bool convert) i = new TImage(id); TArray::add(i, id); if (convert) - i->convert_to_default_colors(); + i->convert_transparent_color(); } return *i; } /////////////////////////////////////////////////////////// -// Static data and functions +// Utility functions /////////////////////////////////////////////////////////// -HIDDEN TControl* creating = NULL; -HIDDEN long ctl_flags; -HIDDEN WINDOW _hdc; -HIDDEN RCT _client; -HIDDEN TPicture_array cpb; +HIDDEN TPicture_array* _picture = NULL; +HIDDEN XVT_FNTID DEF_FONT = NULL; +HIDDEN XVT_FNTID FAT_FONT = NULL; -HIDDEN void get_geometry(WINDOW win) +XVT_FNTID xvt_default_font(bool bold) { - xvt_vobj_get_client_rect(win, &_client); - _client.right--; _client.bottom--; - _hdc = win; + if (DEF_FONT == NULL) + { + DEF_FONT = xvt_dwin_get_font(TASK_WIN); + FAT_FONT = xvt_dwin_get_font(TASK_WIN); + +#if XVT_OS == XVT_OS_WIN + HFONT NormalFont = (HFONT)GetStockObject(ANSI_FIXED_FONT); + LOGFONT LogFont; + GetObject(NormalFont, sizeof(LOGFONT), &LogFont); + + TConfig font(CONFIG_USER, "Font"); + CHARY = (int)font.get_long("Height"); + if (CHARY > 0) + { + LogFont.lfHeight = CHARY; + LogFont.lfWeight = font.get_int("Weight"); + LogFont.lfPitchAndFamily = font.get_int("Pitch"); + strcpy(LogFont.lfFaceName, font.get("Name")); + } + else + { + LogFont.lfHeight = CHARY = 10; + LogFont.lfWeight = 300; // Normal weight + } + NormalFont = CreateFontIndirect(&LogFont); + + TToken_string desc(128, '/'); + desc.add("WIN01"); // 0 + desc.add(LogFont.lfHeight); // 1 + desc.add(LogFont.lfWidth); // 2 + desc.add(LogFont.lfEscapement); // 3 + desc.add(LogFont.lfOrientation); // 4 + desc.add(LogFont.lfWeight); // 5 + desc.add(LogFont.lfItalic); // 6 + desc.add(LogFont.lfUnderline); + desc.add(LogFont.lfStrikeOut); + desc.add(LogFont.lfCharSet); + desc.add(LogFont.lfOutPrecision); + desc.add(LogFont.lfClipPrecision); + desc.add(LogFont.lfQuality); + desc.add(LogFont.lfPitchAndFamily); + desc.add(LogFont.lfFaceName); + + xvt_font_set_native_desc(DEF_FONT, (char*)(const char*)desc); + CHECK(xvt_font_has_valid_native_desc(DEF_FONT), "Bad font description"); + xvt_font_map_using_default(DEF_FONT); + CHECK(xvt_font_is_mapped(DEF_FONT), "Can't map native font"); + xvt_dwin_set_font(TASK_WIN, DEF_FONT); + + desc.add(600, 5); + xvt_font_set_native_desc(FAT_FONT, (char*)(const char*)desc); + CHECK(xvt_font_has_valid_native_desc(FAT_FONT), "Bad font description"); + xvt_font_map_using_default(FAT_FONT); + CHECK(xvt_font_is_mapped(FAT_FONT), "Can't map native font"); + // Get true text size + TEXTMETRIC tm; + HDC hdc = (HDC)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_GRAPHIC_CONTEXT); + GetTextMetrics(hdc, &tm); + + const int COLX = GetSystemMetrics(SM_CXSCREEN) / 80; + CHARX = tm.tmAveCharWidth+1; + if (CHARX > COLX) CHARX = COLX; + + CHARY = tm.tmHeight; + BASEY = tm.tmAscent; + if (CHARY > ROWY-2) CHARY = ROWY-2; +#endif + } + + return bold ? FAT_FONT : DEF_FONT; } -HIDDEN void set_creation_args(WIN_CREATION_ARGS *a) -{ - long& flags = a->win_flags; - if (ctl_flags & CTL_FLAG_DISABLED) flags |= WSF_DISABLED; - if (ctl_flags & CTL_FLAG_INVISIBLE) flags |= WSF_INVISIBLE; +static byte event_map[XIE_COL_SIZE+1]; +enum event_action { a_ignore, a_xvt, a_xvt_post, a_obj, a_child, a_update, a_select }; - switch(creating->id()) +void init_controls() +{ + xi_set_font_id(xvt_default_font()); + xi_set_pref(XI_PREF_NATIVE_CTRLS, FALSE); + xi_set_pref(XI_PREF_AUTOSEL_ON_MOUSE, TRUE); + xi_set_pref(XI_PREF_CARET_WIDTH, 2); + xi_set_pref(XI_PREF_3D_LOOK, TRUE); + xi_set_pref(XI_PREF_COLOR_LIGHT, MASK_LIGHT_COLOR); + xi_set_pref(XI_PREF_COLOR_CTRL, MASK_BACK_COLOR); + xi_set_pref(XI_PREF_COLOR_DARK, MASK_DARK_COLOR); + xi_init(); + + event_map[XIE_CHAR_FIELD] = a_obj; + event_map[XIE_DBL_FIELD] = a_obj; + event_map[XIE_CHG_FIELD] = a_obj; + event_map[XIE_OFF_FIELD] = a_obj; + event_map[XIE_ON_FIELD] = a_obj; + event_map[XIE_OFF_GROUP] = a_ignore; + event_map[XIE_ON_GROUP] = a_ignore; + event_map[XIE_OFF_FORM] = a_ignore; + event_map[XIE_ON_FORM] = a_ignore; + event_map[XIE_VIR_PAN] = a_ignore; + event_map[XIE_XVT_EVENT] = a_xvt; + event_map[XIE_XVT_POST_EVENT] = a_xvt_post; + event_map[XIE_INIT] = a_ignore; + event_map[XIE_BUTTON] = a_obj; + event_map[XIE_CHAR_CELL] = a_child; + event_map[XIE_CLEANUP] = a_ignore; + event_map[XIE_CLOSE] = a_ignore; + event_map[XIE_COMMAND] = a_ignore; + event_map[XIE_DBL_CELL] = a_child; + event_map[XIE_GET_FIRST] = a_obj; + event_map[XIE_GET_LAST] = a_obj; + event_map[XIE_GET_NEXT] = a_obj; + event_map[XIE_GET_PERCENT] = a_obj; + event_map[XIE_GET_PREV] = a_obj; + event_map[XIE_CELL_REQUEST] = a_obj; + event_map[XIE_CHG_CELL] = a_child; + event_map[XIE_OFF_CELL] = a_child; + event_map[XIE_ON_CELL] = a_child; + event_map[XIE_OFF_ROW] = a_child; + event_map[XIE_ON_ROW] = a_child; + event_map[XIE_OFF_COLUMN] = a_ignore; + event_map[XIE_ON_COLUMN] = a_ignore; + event_map[XIE_OFF_LIST] = a_obj; + event_map[XIE_ON_LIST] = a_obj; + event_map[XIE_REC_ALLOCATE] = a_ignore; + event_map[XIE_REC_FREE] = a_ignore; + event_map[XIE_ROW_SIZE] = a_ignore; + event_map[XIE_SELECT] = a_select; + event_map[XIE_UPDATE] = a_update; + event_map[XIE_COL_DELETE] = a_ignore; + event_map[XIE_COL_MOVE] = a_ignore; + event_map[XIE_COL_SIZE] = a_ignore; + + if (_picture == NULL) + _picture = new TPicture_array; +} + +void free_controls() +{ + if (_picture) { - case -2: - flags |= WSF_DISABLED; + delete _picture; + _picture = NULL; + } + if (DEF_FONT) + { + xvt_font_destroy(DEF_FONT); + DEF_FONT = NULL; + } + if (FAT_FONT) + { + xvt_font_destroy(FAT_FONT); + FAT_FONT = NULL; + } +} + +/////////////////////////////////////////////////////////// +// Interface creation +/////////////////////////////////////////////////////////// + +HIDDEN void xi_event_handler(XI_OBJ *itf, XI_EVENT *xiev); + +WINDOW create_interface(WINDOW parent, short x, short y, short dx, short dy, + const char* caption, TWindow* msk, bool tag) +{ + if (parent == NULL_WIN) + parent = TASK_WIN; + + const bool normal = dx != 0; // Non e' a tutto schermo + + short left = x * CHARX; + short top = y * ROWY; + short width = dx * CHARX; + short height = dy * ROWY; + + if (x <= 0 || y <= 0 || dx <= 0 || dy <= 0) + { + RCT max; xvt_vobj_get_client_rect(parent, &max); + if (parent == TASK_WIN) + max.bottom -= 26; // Non contare la status bar + + if (dy <= 0) + height = max.bottom - top + dy * ROWY; + + if (dx <= 0) + { + width = max.right - left + dx * CHARX; + if (!tag && dx == 0 && y > 0) // Aggiusta toolbar + top++; + } + + if (x < 0) left = (max.right - width) >> 1; + if (y < 0) top = (max.bottom - height) >> 1; + } + RCT r; xvt_rect_set(&r, left, top, left+width, top+height); + + const WIN_TYPE wt = normal ? W_DOC : W_PLAIN; + long wsf = WSF_INVISIBLE | WSF_NO_MENUBAR; + + WINDOW win = xvt_win_create(wt, &r, (char*)caption, NULL, parent, wsf, + EM_ALL, (EVENT_HANDLER)xi_event, (long)msk); + CHECK(win, "Can't create an XVT window for an interface"); + + XI_OBJ_DEF* def = xi_create_itf_def(ITF_CID, xi_event_handler, &r, (char*)caption, (long)msk); + CHECK(def, "Can't define an interface"); + + def->v.itf->automatic_back_color = FALSE; + def->v.itf->back_color = MASK_BACK_COLOR; + def->v.itf->tab_on_enter = TRUE; + def->v.itf->win = win; + + XI_OBJ* itf = xi_create(NULL, def); + CHECK(itf, "Can't create an interface"); + + xi_dequeue(); + xi_tree_free(def); + + if (Y_FU_MULTIPLE == 0) + { + RCT max; xvt_vobj_get_client_rect(TASK_WIN, &max); + xi_pu_to_fu(itf, (PNT*)&max, 2); + X_FU_MULTIPLE = max.right / 80; + Y_FU_MULTIPLE = max.bottom / 25; + + PNT f1 = { XI_FU_MULTIPLE, XI_FU_MULTIPLE }; + xi_fu_to_pu(itf, &f1, 1); + const int spacing = ROWY - f1.v; + if (spacing > 0) + xi_set_pref(XI_PREF_VERT_PIXEL_SPACING, spacing); + } + + if (tag) + { + XI_RCT rct; xi_get_xi_rct(itf, &rct); + rct.top += Y_FU_MULTIPLE; // Lascia lo spazio per i Bottoni di cambio pagina + + def = xi_add_rect_def(NULL, DLG_PAGETAGS, &rct, XI_ATR_VISIBLE, 0, 0); + XI_OBJ* obj = xi_create(itf, def); + CHECK(obj, "Can't create page rectangle"); + + // Fa coincidere esattamente il rettangolo con la finestra che lo contiene + RCT& rect = obj->v.rect->rct; + const int oldy = rect.top; + xvt_vobj_get_client_rect(win, &rect); + rect.top = oldy; + + xi_dequeue(); + xi_tree_free(def); + } + + return win; +} + +void attach_interface(WINDOW win, COLOR back) +{ + xvt_win_set_handler(win, (EVENT_HANDLER)xi_event); + RCT rc; xvt_vobj_get_client_rect(win, &rc); + WINDOW wp = xvt_vobj_get_parent(win); + xvt_vobj_translate_points(win, wp, (PNT*)&rc, 2); + char caption[80]; xvt_vobj_get_title(win, caption, 80); + TWindow* parent = (TWindow*)xvt_vobj_get_data(win); + XI_OBJ_DEF* def = xi_create_itf_def(ITF_CID, xi_event_handler, &rc, caption, (long)parent); + CHECK(def, "Can't define an interface"); + + def->v.itf->automatic_back_color = FALSE; + def->v.itf->back_color = back; + def->v.itf->tab_on_enter = TRUE; + def->v.itf->win = win; + + XI_OBJ* itf = xi_create(NULL, def); + CHECK(itf, "Can't create an interface"); + + xi_dequeue(); + xi_tree_free(def); +} + +HIDDEN void xi_event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + static bool notify_xvt = TRUE; + + TControl* ctl = NULL; + + switch (event_map[xiev->type]) + { + case a_obj: + ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj); + break; + case a_child: + ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj->parent); + break; + case a_update: + { + int num; + XI_OBJ** button = xi_get_member_list(itf, &num); + for (int i = num-1; i >= 0; i--) + { + XI_OBJ* b = button[i]; + if (b->type == XIT_BTN && b->v.btn->drawable) + { + if (xvt_rect_intersect(NULL, &b->v.btn->rct, &xiev->v.xvte.v.update.rct)) + { + TPushbutton_control* p = (TPushbutton_control*)b->app_data; + p->update(); + } + } + } + } + break; + case a_select: + if (xiev->v.xi_obj->type == XIT_LIST) + ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj); + else + ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj->parent); + break; + case a_xvt: + { + XI_OBJ* fo = xi_get_focus(itf); + if (xiev->v.xvte.type == E_CHAR && fo != NULL && fo->type == XIT_CELL) + ctl = (TControl*)xi_get_app_data(fo->parent); + } + break; + case a_xvt_post: + if (notify_xvt) + { + TWindow* w = (TWindow*)xi_get_app_data(itf); + CHECK(w, "Can't send XVT event to a null window"); + w->handler(w->win(), &xiev->v.xvte); + } + else + notify_xvt = TRUE; + break; + default: break; - default:break; } -} - -void xvt_draw_rect(WINDOW win, const RCT& rect, COLOR lt, COLOR rb, short depth) -{ - RCT r = rect; - - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = lt; - - for (short d = 0; d < depth;) + + if (ctl != NULL) { - xvt_dwin_set_cpen(win, &pen); - - PNT p; // Current vertex of the rectangle - - bool drawed = FALSE; - if (lt != COLOR_LTGRAY) + const bool ok = ctl->event_handler(itf, xiev); + if (!ok) { - p.h = r.left; p.v = r.bottom; - xvt_dwin_draw_set_pos(win, p); - - p.v = r.top; - xvt_dwin_draw_line(win, p); - p.h = r.right; - xvt_dwin_draw_line(win, p); - drawed = TRUE; - } - - if (rb != COLOR_LTGRAY) - { - if (pen.color != rb) - { - pen.color = rb; - xvt_dwin_set_cpen(win, &pen); - } - if (!drawed) - { - p.h = r.right; p.v = r.top; - xvt_dwin_draw_set_pos(win, p); - } - p.v = r.bottom; - xvt_dwin_draw_line(win, p); - p.h = r.left; - xvt_dwin_draw_line(win, p); - } - - if (++d < depth) - { - r.left++; r.top++; - r.right--; r.bottom--; - } + xiev->refused = TRUE; + if (xiev->type == XIE_CHAR_FIELD || xiev->type == XIE_CHAR_CELL || + xiev->type == XIE_XVT_EVENT) + notify_xvt = FALSE; + } } -} +} + +/////////////////////////////////////////////////////////// +// TControl +/////////////////////////////////////////////////////////// // @doc INTERNAL -// @mfunc Crea il controllo -void TControl::create( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* title, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - short id) // @parm Identificatore assegnato -{ - bool bold = FALSE; - _color = NORMAL_COLOR; - _backcolor = MASK_BACK_COLOR; - - while (*title == '@' || *title == '$') - { - switch (*title++) - { - case '@': - if (toupper(*title) == 'B') bold = TRUE; - break; - case '$': - title++; // Skip [ - if (isalpha(*title)) - _color = trans_color(*title); - else - { - int r = 0, g = 0, b = 0; - sscanf(title, "%d,%d,%d", &r, &g, &b); - _color = MAKE_COLOR(r, g, b); - } - while (*title != ']') // Find ] - { - CHECK(*title, "Bad prompt color format"); - title++; - } - break; - default: - break; - } - title++; - } - - const int prop_count = 1; - const char* prop_list[prop_count+1] = { title, NULL }; - - _id = id; - _disabled = (flags & CTL_FLAG_DISABLED) != 0; - _checked = (flags & CTL_FLAG_CHECKED) != 0; - _multiple = (flags & CTL_FLAG_MULTIPLE) != 0; - _focused = FALSE; - _caption = title; _caption.strip("~"); - - creating = this; - ctl_flags = flags; - _win = xvtcm_create(id, left, top, right, bottom, - prop_count, (char**)prop_list, parent, - 0, 0, NULL, handler, set_creation_args); - CHECKD(_win, "Can't create control ", id); - - creating = NULL; - xvt_vobj_set_data(_win, app_data); - xvt_set_font(_win, "", int(bold ? XVT_FS_BOLD : XVT_FS_NONE)); -} - +TControl::TControl() + : _obj(NULL), _fld(NULL) +{} // Virtual destructor needed to make derived descrutors live! TControl::~TControl() {} +XI_OBJ* TControl::get_interface(WINDOW win) const +{ + XI_OBJ* itf; + if (win == NULL_WIN) + { + CHECK(_obj, "Can't get the interface from NULL XI object"); + itf = _obj->itf; + } + else + { + itf = xi_get_itf(win); + CHECK(itf, "Can't get the interface from a window"); + } + return itf; +} -long XVT_CALLCONV1 TControl::handler(WINDOW win, EVENT* ep) +void TControl::set_tab_cid(short cid) { - HIDDEN bool tracking = FALSE; - HIDDEN bool pressed = FALSE; - - if (ep->type == E_CREATE) - xvtcm_eh_start(win, ep); - - TControl** model = (TControl**)xvtcm_get_model(win, sizeof(TControl*)); - CHECK(model, "Can't get the model"); - - TControl*& cc = *model; - if (ep->type == E_CREATE) + CHECK(_obj, "Can't update tab_cid of a NULL control"); + switch(_obj->type) { - CHECK(creating, "Can't create a NULL control"); - cc = creating; + case XIT_BTN: + _obj->v.btn->tab_cid = cid; break; + case XIT_CONTAINER: + _obj->v.container->tab_cid = _obj->cid; + if (_obj->nbr_children > 0) + _obj->children[_obj->nbr_children-1]->v.btn->tab_cid = cid; + break; + case XIT_FIELD: + _obj->v.field->tab_cid = cid; + _obj->parent->v.form->tab_cid = _obj->parent->cid; + break; + case XIT_LIST: + _obj->v.list->tab_cid = cid; break; + default: + NFCHECK(0, "Can't set tab_cid to a static control: ", _obj->cid); break; } - CHECK(cc, "Can't handle a NULL control"); +} - if (creating == NULL) switch(ep->type) + +TControl& TControl::find_operable_ctl(bool forward) const +{ + int num; + XI_OBJ** child = xi_get_member_list(get_interface(), &num); + const int first = forward ? 0 : num-2; + const int last = forward ? num-1 : -1; + const int delta = forward ? +1 : -1; + XI_OBJ* obj = NULL; + for (int c = first; c != last && obj == NULL; c += delta) { - case E_FOCUS: - cc->focus((bool)ep->v.active); - case E_UPDATE: - cc->update(); - break; - case E_MOUSE_DOWN: - xvt_win_trap_pointer(win); - tracking = pressed = TRUE; - cc->mouse_down(ep->v.mouse.where); - break; - case E_CHAR: + const XI_OBJ_TYPE t = child[c]->type; + if (t == XIT_FORM || t == XIT_BTN || t == XIT_LIST || t == XIT_CONTAINER) + obj = child[c]; + } + TControl* ctl = obj == NULL ? (TControl*)this : (TControl*)xi_get_app_data(obj); + CHECK(ctl, "Can't update NULL control"); + return *ctl; +} + +void TControl::update_tab_cid() +{ + TControl& lc = find_operable_ctl(FALSE); + lc.set_tab_cid(id()); + + const TControl& fc = find_operable_ctl(TRUE); + set_tab_cid(fc.id()); +} + + +void TControl::coord2rct(WINDOW win, short x, short y, short dx, short dy, XI_RCT& rct) const +{ + // Spazio da lasciare prima di toccare i bordi + const int X_FU_DELTA = 2; + const int Y_FU_DELTA = 1; + + XI_OBJ* itf = get_interface(win); + + // Se ci sono i tab controls sulla pagina salta una riga + if (y >= 0) + { + int num; + XI_OBJ** child = xi_get_member_list(itf, &num); + if (num > 0 && child[0]->cid == DLG_PAGETAGS) + y++; + } + + RCT max; xvt_vobj_get_client_rect(win, &max); + xi_pu_to_fu(itf, (PNT*)&max, 2); + const int& MAXX = max.right; + const int& MAXY = max.bottom; + + int width = XI_FU_MULTIPLE; + if (dx > 0) + width = dx * XI_FU_MULTIPLE; + + int height = XI_FU_MULTIPLE; + if (dy > 1) + height += (dy-1) * Y_FU_MULTIPLE; + + if (x < 0) { - const KEY key = e_char_to_key(ep); - switch(key) + x = -x; + if (x > 10) { - case K_SPACE: - cc->mouse_up(); - break; - default: - dispatch_e_char(xvt_vobj_get_parent(win), key); - break; + const int num = x / 10 -1; + const int tot = x % 10; + const int spc = (MAXX - tot*width) / (tot+1); + rct.left = spc + num * (spc+width); } + else + rct.left = MAXX - width - x * XI_FU_MULTIPLE; } - break; - case E_MOUSE_MOVE: - if (tracking) + else + { + rct.left = (x+1) * XI_FU_MULTIPLE; + + if (dx > 0 && MAXX > 80 * XI_FU_MULTIPLE) + rct.left += (MAXX - 80 * XI_FU_MULTIPLE) / 2; + } + + if (y < 0) + { + y = -y; + if (y > 10) { - RCT r; - xvt_vobj_get_client_rect(win, &r); - if (xvt_rect_has_point(&r, ep->v.mouse.where)) + const int num = y / 10 -1; + const int tot = y % 10; + const int spc = (MAXY - tot*height) / (tot+1); + rct.top = spc + num * (spc+height); + } + else + rct.top = MAXY - height - (y-1) * Y_FU_MULTIPLE - Y_FU_DELTA; + } + else + rct.top = y * Y_FU_MULTIPLE + Y_FU_DELTA; + + if (dx > 0) + rct.right = rct.left + width; + else + rct.right = MAXX + (dx-1) * XI_FU_MULTIPLE - X_FU_DELTA; + + if (dy > 0) + rct.bottom = rct.top + height; + else + rct.bottom = MAXY + dy * Y_FU_MULTIPLE - X_FU_DELTA; +} + +RCT& TControl::get_rect(RCT& r) const +{ + xi_get_rect(_obj, &r); + return r; +} + +void TControl::set_rect(const RCT&) +{ + CHECK(0, "Can't set_rect to generic TControl"); +} + +unsigned long TControl::flags2attr(const char* flags) const +{ + unsigned long attrib = XI_ATR_VISIBLE | XI_ATR_ENABLED; + for (const char* f = flags; *f; f++) + { + switch(toupper(*f)) + { + case '*': attrib |= XI_ATR_PASSWORD; break; + case 'C': attrib |= XI_ATR_HCENTER; break; + case 'D': attrib &= ~XI_ATR_ENABLED; break; + case 'H': attrib &= ~XI_ATR_VISIBLE; break; + case 'R': attrib |= XI_ATR_RJUST; break; + default : break; + } + } + return attrib; +} + +const char* TControl::parse_caption(const char* cap, bool& bold, COLOR& color) const +{ + bold = FALSE; + color = NORMAL_COLOR; + for (const char* t = cap; *t == '@' || *t == '$'; t++) + { + if (*t == '@') + { + const char code = toupper(*(t+1)); + if (code == 'B') { - if (!pressed) - { - cc->mouse_down(ep->v.mouse.where); - pressed = TRUE; - } + bold = TRUE; + t++; } else { - if (pressed) - { - cc->update(); - pressed = FALSE; - } - } + NFCHECK(0, "Bad character after @ in prompt"); + break; + } } - break; - case E_MOUSE_UP: - if (tracking) - { - xvt_win_release_pointer(); - tracking = FALSE; - if (pressed) + else + { + if (*(t+1) == '[') { - cc->mouse_up(); - pressed = FALSE; - } + t += 2; // Skip [ + if (isalpha(*t)) + color = trans_color(*t); + else + { + int r = 0, g = 0, b = 0; + sscanf(t, "%d,%d,%d", &r, &g, &b); + color = MAKE_COLOR(r, g, b); + } + while (*t && *t != ']') t++; + } + else + { + NFCHECK(0, "Bad character after $ in prompt"); + break; + } } - break; - case E_DESTROY: - delete *model; - *model = NULL; - xvtcm_eh_end(win, ep); - break; - default: - break; } + return t; +} - return 0L; +WINDOW TControl::parent() const +{ + return xi_get_window(_obj->itf); +} + +void TControl::set_focus() const +{ + xi_set_focus(_obj); +} + +bool TControl::notify_key(KEY k) +{ + bool ok = TRUE; + + if (_fld == NULL) + { + TWindow* msk = (TWindow*)xi_get_app_data(get_interface()); + CHECK(msk, "Can't get TMask from XI interface"); + if (msk->is_kind_of(CLASS_MASK)) + { + const TMask& m = (TMask&)*msk; + const int pos = m.id2pos(id()); + if (pos >= 0) + _fld = &m.fld(pos); + } + } + if (_fld) + ok = _fld->on_key(k); + + return ok; +} + +bool TControl::is_edit_key(KEY k) const +{ + return k >= ' ' && k < 255 && k != K_DEL; +} + +bool TControl::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TRUE; + return ok; +} + +void TControl::change_attrib(unsigned long mask, bool on, XI_OBJ* obj) +{ + if (obj == NULL) obj = _obj; + const unsigned long old_attr = xi_get_attrib(obj); + unsigned long attr = old_attr; + if (on) attr |= mask; + else attr &= ~mask; + if (attr != old_attr) // C'e' un vero cambiamento d'attributo + { + // Se la finestra e' chiusa e il campo e un bottone o e' editabile allora cambia l'attributo + // senza ridisegnare il campo, il che provocherebbe problemi di funzionamento degli sheet + if (_obj->type == XIT_BTN || _obj->type == XIT_FIELD) + { + const TWindow* w = (const TWindow*)_obj->itf->app_data; + if (!w->is_open()) + { + if (_obj->type == XIT_FIELD) + ((STX_DATA*)_obj->v.field->stx)->attrib = attr; + else + _obj->v.btn->attrib = attr; + return; + } + } + // Usa tranquillamente il metodo ortodosso + xi_set_attrib(obj, attr); + } +} + +// @doc INTERNAL + +// @mfunc Mostra/Nasconde il controllo +void TControl::show( + bool on) // @parm Operazione da svolgere sul controllo: + // @flag TRUE | Il controllo viene mostrato + // @flag FALSE | Il controllo viene nascosto +{ + change_attrib(XI_ATR_VISIBLE, on); } // @doc INTERNAL @@ -308,857 +750,944 @@ long XVT_CALLCONV1 TControl::handler(WINDOW win, EVENT* ep) // @mfunc Abilita/disabilita il controllo void TControl::enable( bool on) // @parm Operazione da svolgere sul controllo: - // @flag TRUE | Il controllo viene abilitato - // @flag FALSE | Il controllo viene disabilitato + // @flag TRUE | Il controllo viene abilitato + // @flag FALSE | Il controllo viene disabilitato { - if (on == disabled()) - { - _disabled = !on; - update(); - xvt_vobj_set_enabled(win(), on); - } + change_attrib(XI_ATR_ENABLED, on); +} + +// @mfunc Abilita/disabilita l'autoselezione del testo +void TControl::autoselect(bool on) +{ + change_attrib(XI_ATR_AUTOSELECT, on); } // @doc INTERNAL -// @mfunc Setta se il controllo debba avere un check -void TControl::check( - bool on) // @parm Puo' assumere i seguenti valori: - // @flag TRUE | Se il controllo deve avere un check - // @flag FALSE | Se il controllo non deve avere un check +const char* TControl::caption() const { - _checked = on; + const char* c = xi_get_text(_obj, NULL, 512); + return c; } -void TControl::update() const +void TControl::set_caption(const char* c) { - if (_win != _hdc) - get_geometry(_win); - xvt_dwin_clear(_hdc, _backcolor); - xvt_dwin_set_fore_color(_hdc, disabled() ? DISABLED_COLOR : color()); -} - -void TControl::set_caption(const char* t) -{ - _caption = t; - update(); + xi_set_text(_obj, (char*)c); } /////////////////////////////////////////////////////////// // TText /////////////////////////////////////////////////////////// -class TText : public TControl -{ -protected: - virtual WIN_TYPE type() const { return WC_TEXT; } - virtual void update() const; +TText_control::TText_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text) +{ + bool bold; + COLOR color; + TString t = parse_caption(text, bold, color); + t.rtrim(); + if (width <= 0) + { + width = t.len(); + if (bold) + width = 4 * width / 3; + } + XI_RCT rct; coord2rct(win, left, top, width, height, rct); + const unsigned long attrib = flags2attr(flags); + XI_OBJ_DEF* def = xi_add_text_def(NULL, cid, &rct, attrib, (char*)(const char*)t); + CHECKS(def, "Can't create the definition of TText_control:", text); + def->v.text->fore_color = color; + if (bold) + def->v.text->font_id = xvt_default_font(TRUE); + _obj = xi_create(get_interface(win), def); + CHECKS(_obj, "Can't create TText_control ", text); -public: - TText(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); -}; - -TText::TText(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -{ - create(left, top+1, right, bottom-1, caption, parent, flags, app_data, id); + xi_dequeue(); + xi_tree_free(def); } -void TText::update() const +void TText_control::set_caption(const char* text) { - TControl::update(); - xvt_dwin_set_fore_color(_hdc, color()); - xvt_dwin_draw_text(_hdc, _client.left, _client.top+BASEY, (char*)caption(), -1); + bool bold; + COLOR color; + const char* c = parse_caption(text, bold, color); + xi_set_text(_obj, (char*)c); + _obj->v.text->fore_color = color; +} + + +/////////////////////////////////////////////////////////// +// TGroupbox_control +/////////////////////////////////////////////////////////// + +TGroupbox_control::TGroupbox_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text) + : TText_control(win, cid, left, top, width, 1, flags, text) +{ + XI_RCT rct; coord2rct(win, left, top, width, height, rct); + rct.top += XI_FU_MULTIPLE; + rct.bottom -= Y_FU_MULTIPLE / 2; + + XI_OBJ_DEF* def = xi_add_rect_def(NULL, cid, &rct, XI_ATR_VISIBLE, 0, 0); // Ignore colors + CHECKS(def, "Can't create the definition of TGroupbox_control ", text); + def->v.rect->hilight_color = MASK_LIGHT_COLOR; + def->v.rect->back_color = MASK_BACK_COLOR; + def->v.rect->shadow_color = MASK_DARK_COLOR; + def->v.rect->well = strchr(flags, 'R') ? FALSE : TRUE; + _rct = xi_create(get_interface(win), def); + CHECKD(_rct, "Can't create Groupbox_control ", cid); + + xi_dequeue(); + xi_tree_free(def); +} + +void TGroupbox_control::show(bool on) +{ + TText_control::show(on); + change_attrib(XI_ATR_VISIBLE, on, _rct); } /////////////////////////////////////////////////////////// -// TGroup +// TField /////////////////////////////////////////////////////////// -class TGroup : public TText +static bool in_create = FALSE; + +TField_control::TField_control(WINDOW win, short cid, + short left, short top, short width, short maxlen, + const char* flags, const char* text) +{ + const bool button = strchr(flags, 'B') != NULL; + create(win, cid, left, top, width, 1, maxlen, flags, text, button); +} + +void TField_control::create(WINDOW win, short cid, + short left, short top, short width, short height, short maxlen, + const char* flags, const char* text, bool button) { -protected: - virtual WIN_TYPE type() const { return WC_GROUPBOX; } - virtual void update() const; - void draw_round_rect(const RCT& r, COLOR c) const; + in_create = TRUE; + + const short fcid = cid + 1000; + XI_OBJ_DEF* frm_def = xi_add_form_def(NULL, fcid, fcid); + frm_def->app_data = (long)this; -public: - TGroup(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); -}; + XI_RCT rct; coord2rct(win, left, top, width, height, rct); + unsigned long attrib = flags2attr(flags) | XI_ATR_AUTOSELECT; + if (!CAMPI_SCAVATI) + attrib |= XI_ATR_BORDER; + if (maxlen > width) + attrib |= XI_ATR_AUTOSCROLL; + + XI_OBJ_DEF* def = xi_add_field_def(frm_def, cid, + rct.top, rct.left, + width * XI_FU_MULTIPLE - 3*XI_FU_MULTIPLE/4, + attrib, cid, maxlen+1, + NORMAL_COLOR, NORMAL_BACK_COLOR, + NORMAL_COLOR, DISABLED_BACK_COLOR, + FOCUS_COLOR); + + def->app_data = (long)this; + XI_FIELD_DEF* f = def->v.field; + f->well = CAMPI_SCAVATI; + f->auto_tab = TRUE; + f->active_back_color = FOCUS_BACK_COLOR; + if (button) + { + f->button = TRUE; + f->pixel_button_distance = 4; + } + if (rct.bottom - rct.top > Y_FU_MULTIPLE) + f->xi_rct = rct; -TGroup::TGroup(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -: TText(left, top, right, bottom, caption, parent, flags | CTL_FLAG_DISABLED, app_data, - (id < 0) ? -2 : id) + XI_OBJ* itf = get_interface(win); + XI_OBJ* form = xi_create(itf, frm_def); + CHECKD(form, "Can't create the form for field ", cid); + _obj = xi_get_obj(form, cid); + CHECKD(_obj, "Can't create field ", cid); + + update_tab_cid(); + + xi_dequeue(); + xi_tree_free(frm_def); + + in_create = FALSE; +} + +void TField_control::show_button(bool on) +{ + XI_FIELD_DATA* f = _obj->v.field; + if (f->button != on) + { + f->button = on; + xi_invalidate_rect(parent(), &f->btn_rct); + } +} + +bool TField_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + if (in_create) + return FALSE; + + bool ok = TRUE; + + switch(xiev->type) + { + case XIE_OFF_FIELD: + ok = notify_key(K_TAB); + break; + case XIE_ON_FIELD: + notify_key(K_CTRL+K_TAB); + break; + case XIE_DBL_FIELD: + notify_key(K_F9); + break; + case XIE_CHAR_FIELD: + { + KEY k = xiev_to_key(xiev); + if (k == K_PREV || k == K_NEXT || (k >= K_CTRL+K_F1 && k <= K_CTRL+K_F12)) + k = K_TAB; + if (k == K_TAB || is_edit_key(k) || (k > K_F1 && k < K_F12)) + ok = notify_key(k); + } + break; + case XIE_CHG_FIELD: + notify_key(K_CTRL+K_SPACE); + break; + case XIE_BUTTON: + notify_key(K_F9); + break; + default: + ok = TControl::event_handler(itf, xiev); + break; + } + return ok; +} + +void TField_control::set_focus() const +{ + TControl::set_focus(); +} + +/////////////////////////////////////////////////////////// +// TMultiline_control +/////////////////////////////////////////////////////////// +TMultiline_control::TMultiline_control(WINDOW win, short cid, + short left, short top, + short width, short height, short maxlen, + const char* flags, const char* text) +{ + create(win, cid, left, top, width, height, maxlen, flags, text, FALSE); +} + +/////////////////////////////////////////////////////////// +// TButton_control +/////////////////////////////////////////////////////////// + +void TButton_control::create(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, + WIN_TYPE wc, XI_OBJ* container) +{ + bool bold; + COLOR color; + TString txt(text); txt.strip("&~"); + const char* t = parse_caption(txt, bold, color); + if (width <= 0) width = strlen(t)+3; + + RCT rct; coord2rct(win, left, top, width, height, rct); + if (cid == DLG_F9) + { + rct.left++; + rct.top--; + rct.right++; + } + + const unsigned long attrib = flags2attr(flags); + XI_OBJ_DEF* def = xi_add_button_def(NULL, cid, &rct, attrib, (char*)t, cid); + CHECKD(def, "Can't create the interface of TButton_control ", cid); + def->v.btn->fore_color = color; + def->app_data = (long)this; + switch (wc) + { + case WC_PUSHBUTTON : def->v.btn->type = XIBT_BUTTON; break; + case WC_CHECKBOX : def->v.btn->type = XIBT_CHECKBOX; break; + case WC_RADIOBUTTON: def->v.btn->type = XIBT_RADIOBTN; break; + default : def->v.btn->type = XIBT_TABBTN; break; + } + + if (container == NULL) + container = get_interface(win); + _obj = xi_create(container, def); + CHECKD(_obj, "Can't create TButton_control ", cid); + + xi_dequeue(); + xi_tree_free(def); + + update_tab_cid(); +} + +XI_BTN_TYPE TButton_control::button_type() const +{ + return _obj->v.btn->type; +} + +XI_OBJ* TButton_control::container() const +{ + return _obj->parent; +} + +void TButton_control::check(bool on) +{ + xi_check(_obj, on); +} + +bool TButton_control::checked() const +{ + return xi_is_checked(_obj) ? TRUE : FALSE; +} + +bool TButton_control::toggle() +{ + const bool on = !checked(); + check(on); + return on; +} + +void TButton_control::set_rect(const RCT& r) +{ + _obj->v.btn->rct = r; +} + +bool TButton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TRUE; + + if (xiev->type == XIE_BUTTON) + { + if (xi_move_focus(_obj)) + { + switch (_obj->v.btn->type) + { + case XIBT_CHECKBOX: + case XIBT_BUTTON_CHECKBOX: + toggle(); + break; + default: + break; + } + ok = notify_key(K_SPACE); + } + else + ok = FALSE; + } + else + ok = TControl::event_handler(itf, xiev); + + return ok; +} + +/////////////////////////////////////////////////////////// +// TPushbutton_control +/////////////////////////////////////////////////////////// + +TPushbutton_control::TPushbutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, + short bmp_up, short bmp_dn) + : _bmp_up(bmp_up), _bmp_dn(bmp_dn) + +{ + if (bmp_up > 0) + text = ""; + create(win, cid, left, top, width, height, flags, text, WC_PUSHBUTTON, NULL); + set_bmp(bmp_up, bmp_dn); +} + +void TPushbutton_control::set_bmp(short bmp_up, short bmp_dn) +{ + if (bmp_up > 0) + { + _obj->v.btn->drawable = TRUE; + _picture->add(_bmp_up = bmp_up, TRUE); + if (bmp_dn > 0) + _picture->add(_bmp_dn = bmp_dn, TRUE); + else + _bmp_dn = _bmp_up; + if (_obj->v.btn->text) + *_obj->v.btn->text = '\0'; + } + else + { + _obj->v.btn->drawable = FALSE; + _bmp_up = _bmp_dn = 0; + } +} + +void TPushbutton_control::update() +{ + const long attrib = xi_get_attrib(_obj); + if (attrib & XI_ATR_VISIBLE) + { + const short bmp = (_bmp_dn > 0 && _obj->v.btn->down) ? _bmp_dn : _bmp_up; + if (bmp > 0) + { + const TImage& i = _picture->image(bmp); + const RCT& rct = _obj->v.btn->rct; + int x = rct.left + (rct.right - rct.left - i.width()) / 2; + int y = rct.top + (rct.bottom - rct.top - i.height()) / 2; + if (_obj->v.btn->down) + { + x += 2; + y += 2; + } + + const WINDOW w = parent(); + i.draw(w, x, y); + if (!(attrib & XI_ATR_ENABLED)) + { + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = MASK_BACK_COLOR; + xvt_dwin_set_cpen(w, &pen); + for (int py = y + i.height(); py >= y; py -= 2) + { + PNT p; p.v = py; p.h = x; + xvt_dwin_draw_set_pos(w, p); + p.h += i.width(); + xvt_dwin_draw_line(w, p); + } + for (int px = x + i.width(); px >= x; px -= 2) + { + PNT p; p.v = y; p.h = px; + xvt_dwin_draw_set_pos(w, p); + p.h += i.height(); + xvt_dwin_draw_line(w, p); + } + } + } + } +} + +bool TPushbutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TButton_control::event_handler(itf, xiev); + + switch (xiev->type) + { + case XIE_BUTTON: + { + TWindow* w = (TWindow*)xi_get_app_data(get_interface()); + w->on_button(id()); + } + break; + default: + break; + } + + return ok; +} + +/////////////////////////////////////////////////////////// +// TCheckbox_control +/////////////////////////////////////////////////////////// + +TCheckbox_control::TCheckbox_control(WINDOW win, short cid, + short left, short top, short width, + const char* flags, const char* text) +{ create(win, cid, left, top, width, 1, flags, text, WC_CHECKBOX, NULL); } + +/////////////////////////////////////////////////////////// +// TRadiobutton_control +/////////////////////////////////////////////////////////// + +TRadiobutton_control::TRadiobutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text) +{ + TToken_string testo(text); testo.strip("&~"); + const int tot = testo.items(); + + const XI_CONTAINER_ORIENTATION orient = height == 1 ? XI_STACK_HORIZONTAL : XI_STACK_VERTICAL; + XI_RCT rct; coord2rct(win, left, top, width, height, rct); + + // Aggiusta rettangolo in modo da centrare i bottoni + const int extra = (rct.bottom - rct.top - tot * XI_FU_MULTIPLE) / 2; + if (extra > 0) + { + rct.top += extra; + rct.bottom -= extra; + } + + XI_OBJ_DEF* def = xi_add_container_def(NULL, cid, &rct, orient, cid); + def->app_data = (long)this; + + const unsigned long attrib = flags2attr(flags); + for (int b = 1; b <= tot; b++) + { + bool bold; + COLOR color; + const char* t = parse_caption(testo.get(), bold, color); + + const int next = cid + (b+1)*1000; + XI_OBJ_DEF* btn_def = xi_add_button_def(def, cid + b*1000, NULL, attrib, (char*)t, next); + CHECKD(btn_def, "Can't create definition for radio-button ", cid); + btn_def->app_data = (long)this; + + XI_BTN_DEF* btn = btn_def->v.btn; + btn->type = XIBT_RADIOBTN; + btn->fore_color = color; + btn->checked = b == 1; + } + + XI_OBJ* itf = get_interface(win); + _obj = xi_create(itf, def); + CHECKD(_obj, "Can't create radio-button container ", cid); + + update_tab_cid(); + + xi_dequeue(); + xi_tree_free(def); +} + +void TRadiobutton_control::show(bool on) +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + for (int c = children-1; c >= 0; c--) + change_attrib(XI_ATR_VISIBLE, on, child[c]); +} + +void TRadiobutton_control::enable(bool on) +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + for (int c = children-1; c >= 0; c--) + change_attrib(XI_ATR_ENABLED, on, child[c]); +} + +byte TRadiobutton_control::get_checked() const +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + for (int c = children-1; c > 0; c--) + if (xi_is_checked(child[c])) break; + return (byte)c; +} + +void TRadiobutton_control::check_button(byte c) +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + CHECKD(c < children, "This radio is rather old, it doesn't have button ", c); + if (!xi_is_checked(child[c])) + xi_check(child[c], TRUE); +} + +void TRadiobutton_control::show_button(byte c, bool on) +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + CHECKD(c < children, "This radio is rather old, it doesn't have button ", c); + change_attrib(XI_ATR_VISIBLE, on, child[c]); +} + +bool TRadiobutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TRUE; + if (xiev->type == XIE_BUTTON) + { + XI_OBJ* obj = xiev->v.xi_obj; // Elemento del gruppo di radio buttons da premere + if (xi_move_focus(obj)) // Tenta di dargli il focus + { + if (!xi_is_checked(obj)) // Se non e' gia' premuto ... + { + xi_check(obj, TRUE); // ... allora premilo e ... + ok = notify_key(K_SPACE); // ... avverti il mask_field proprietario + } + } + else + ok = FALSE; + } + else + ok = TButton_control::event_handler(itf, xiev); + return ok; +} + +void TRadiobutton_control::set_focus() const +{ + int children; + XI_OBJ** child = xi_get_member_list(_obj, &children); + for (int c = children-1; c > 0; c--) + if (xi_is_checked(child[c])) break; + xi_set_focus(child[c]); +} + + +/////////////////////////////////////////////////////////// +// TTagbutton_control +/////////////////////////////////////////////////////////// + + +TTagbutton_control::TTagbutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, int tag) +{ + XI_OBJ* itf = get_interface(win); + XI_RCT rct; xi_get_xi_rct(itf, &rct); + rct.bottom = rct.top + Y_FU_MULTIPLE; + XI_OBJ_DEF* cnt_def = xi_add_container_def(NULL, cid, &rct, XI_STACK_HORIZONTAL, cid); + cnt_def->app_data = (long)this; + + const unsigned long attrib = flags2attr(flags); + + TToken_string titolo(text); + const int tot = titolo.items(); + + for (int b = 1; b <= tot; b++) + { + bool bold; + COLOR color; + const char* t = parse_caption(titolo.get(), bold, color); + + const int next_bid = b == tot ? cid+1 : cid+b+1; + XI_OBJ_DEF* btn_def = xi_add_button_def(cnt_def, cid+b, NULL, attrib, (char*)t, next_bid); + btn_def->v.btn->type = XIBT_TABBTN; + btn_def->v.btn->fore_color = color; + btn_def->v.btn->checked = tag == b-1; + btn_def->app_data = (long)this; + } + + _obj = xi_create(itf, cnt_def); + CHECKD(_obj, "Can't create tab-button container ", cid); + + xi_dequeue(); + xi_tree_free(cnt_def); +} + +bool TTagbutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TRUE; + if (xiev->type = XIE_BUTTON) + { + XI_OBJ* obj = xiev->v.xi_obj; // Elemento del gruppo di radio buttons da premere + if (!xi_is_checked(obj)) // Se e' gia' selezionato ignoralo completamente + { + if (xi_move_focus(itf)) // Controlla se si puo' cambiare pagina + { + TWindow* w = (TWindow*)xi_get_app_data(itf); + KEY k = K_CTRL + K_F1 + xiev->v.xi_obj->cid - id() - 1; + w->on_key(k); + } + } + } + else + ok = TRadiobutton_control::event_handler(itf, xiev); + return ok; +} + + +/////////////////////////////////////////////////////////// +// TListbox_control +/////////////////////////////////////////////////////////// + +long TDropDownList::row2rec(int row) const +{ + int rows; + const long* handle = xi_get_list_info(_xi_lst, &rows); + + if (row < 0) row = 0; + else + if (row >= rows) + row = rows-1; + const long r = handle[row]; + CHECKD(r >= 0 && r < items(), "Sheet line out of range: ", row); + + return r; +} + +int TDropDownList::rec2row(long rec) const +{ + int rows; + const long* handle = xi_get_list_info(_xi_lst, &rows); + + int r = int(rec - handle[0]); + if (r < 0 || r >= rows) + r = -1; + + return r; +} + + +void TDropDownList::ddl_str_eh(XI_OBJ* itf, XI_EVENT* xiev) +{ + TDropDownList* ddl = (TDropDownList*)xi_get_app_data(itf); + const char* row = NULL; + long rec = 0l; + + if (!ddl->is_open()) return; + + switch(xiev->type) + { + case XIE_CELL_REQUEST: + rec = xiev->v.cell_request.rec; + row = ddl->item((int)rec); + strncpy(xiev->v.cell_request.s, (char *)row, xiev->v.cell_request.len); + xiev->v.cell_request.s[xiev->v.cell_request.len - 1] = '\0'; + break; + case XIE_GET_FIRST: + if (ddl->items() == 0) + xiev->refused = TRUE; + else + xiev->v.rec_request.data_rec = ddl->items() * xiev->v.rec_request.percent/100; + break; + case XIE_GET_LAST: + xiev->v.rec_request.data_rec = ddl->items() - 1; + break; + case XIE_GET_NEXT: + if (xiev->v.rec_request.spec_rec >= ddl->items()-1) + xiev->refused = TRUE; + else + xiev->v.rec_request.data_rec = xiev->v.rec_request.spec_rec + 1; + break; + case XIE_GET_PREV: + if (xiev->v.rec_request.spec_rec == 0) + xiev->refused = TRUE; + else + xiev->v.rec_request.data_rec = xiev->v.rec_request.spec_rec - 1; + break; + case XIE_GET_PERCENT: + if (ddl->items() > 1) + xiev->v.get_percent.percent = (int)((xiev->v.get_percent.record * 100l)/((long)ddl->items()-1l)); + break; + case XIE_DBL_CELL: + ddl->select((int)(ddl->row2rec(xiev->v.xi_obj->v.cell.row))); + ddl->close(); + break; + case XIE_ON_ROW: + if (ddl->displayed()) + ddl->select((int)(ddl->row2rec(xiev->v.xi_obj->v.row))); + break; + case XIE_XVT_EVENT: + if (xiev->v.xvte.type == E_FOCUS && xiev->v.xvte.v.active == FALSE) + ddl->close(); + else if (xiev->v.xvte.type == E_CHAR) + { + KEY k = xiev->v.xvte.v.chr.ch; + if (k == K_ENTER || k == K_ESC) + ddl->close(); + } + break; + case XIE_CHAR_CELL: // TBI: questa e' copiata da edit + break; + default: + break; + } +} + +void TDropDownList::close() +{ + if (_open) + { + _open = _displayed = FALSE; + xvt_vobj_destroy(xi_get_window(_xi_lst->itf)); + xvt_dwin_update (xi_get_window(_xi_obj->itf)); + } +} + +void TDropDownList::select(int i, bool force) +{ + if (force || i != _selected) + { + _selected = i; + xi_set_text(_xi_obj, (char*)_values.get(i)); + + if (!_in_cell) + { + TListbox_control* listbox = (TListbox_control *)xi_get_app_data(_xi_obj); + listbox->notify_key(K_SPACE); + } + } +} + +void TDropDownList::select_by_initial(char c) +{ + for (int i = 0; i < _values.items(); i++) + if (toupper(*(_values.get(i))) == toupper(c)) + { + select(i); + break; + } +} + +TDropDownList::TDropDownList(XI_OBJ* o, const char* values, int width, bool cell) + : _xi_obj(o), _values(values), _open(FALSE), _xi_lst(NULL), _width(width), + _displayed(FALSE), _in_cell(cell) {} -void TGroup::draw_round_rect(const RCT& r, COLOR c) const -{ - CPEN pen; - pen.width = 2; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = c; - xvt_dwin_set_cpen(_hdc, &pen); + +void TDropDownList::open() +{ + if (_open) return; + + XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID, (XI_EVENT_HANDLER)ddl_str_eh, NULL, "", + (long)this); + // qui si vedra' se e cosa modificare + itfdef->v.itf->automatic_back_color = TRUE; + // compute size of field with button + RCT r; xi_get_rect(_xi_obj, &r); + + if (_width == 0) // usually in spreadsheet cells + _width = (r.right - r.left)/XI_FU_MULTIPLE; + + int hei = items() <= 1 ? 2*XI_FU_MULTIPLE + 1 : (min(6,items()) * XI_FU_MULTIPLE) + 1; + XI_OBJ_DEF* lstdef = xi_add_list_def(itfdef, _xi_obj->cid+1000, 0, 0, hei, + XI_ATR_ENABLED|XI_ATR_VISIBLE, NORMAL_COLOR, NORMAL_BACK_COLOR, + DISABLED_COLOR, DISABLED_BACK_COLOR, FOCUS_COLOR, 0); - CBRUSH brush = { PAT_HOLLOW, MASK_BACK_COLOR }; - xvt_dwin_set_cbrush(_hdc, &brush); - xvt_dwin_draw_roundrect(_hdc, (RCT*)&r, ROWY, ROWY); -} + lstdef->v.list->active_back_color = FOCUS_BACK_COLOR; + lstdef->v.list->scroll_bar = items() > 6; + lstdef->v.list->no_heading = TRUE; + lstdef->v.list->no_horz_lines = TRUE; + lstdef->v.list->no_vert_lines = TRUE; + lstdef->v.list->resize_with_window = TRUE; + + int len; + + if (_in_cell) + len = items() <= 6 ? r.right - r.left - 2 : (_width-1) * XI_FU_MULTIPLE; + else + len = items() <= 6 ? _xi_obj->v.field->rct.right - _xi_obj->v.field->rct.left - 2 : + (_width-1) * XI_FU_MULTIPLE; + + XI_OBJ_DEF* coldef = xi_add_column_def(lstdef, _xi_obj->cid+2000, + XI_ATR_VISIBLE|XI_ATR_ENABLED|XI_ATR_READONLY, + 0, len, 80, ""); -void TGroup::update() const -{ - TText::update(); + coldef->v.column->column_platform = FALSE; - RCT r = _client; - r.top += CHARY; - r.right-=4; r.bottom-=ROWY/2; - if (multiple()) - { - r.left++; r.top++; r.right--; r.bottom--; - draw_round_rect(r, MASK_LIGHT_COLOR); - } + RCT l; xi_get_def_rect(lstdef, &l); + PNT p; p.h = r.left; + WINDOW pwin = xi_get_window(_xi_obj->itf); + RCT w; xvt_vobj_get_client_rect(pwin, &w); + // place rectangle + if (r.bottom + l.bottom - l.top <= w.bottom) + p.v = r.bottom; else { - xvt_draw_rect(_hdc, r, MASK_DARK_COLOR, MASK_LIGHT_COLOR); - } + p.v = r.top - l.bottom - l.top; + if (p.v < w.top) p.v = w.top; + } + RCT wr; + wr.left = p.h; wr.top = p.v; + xi_get_def_rect(lstdef, &l); + wr.right = wr.left + (l.right - l.left) -1; // r.right; + wr.bottom = wr.top + l.bottom - l.top; + int delta_x = _xi_obj->itf->v.itf->delta_x; + int delta_y = _xi_obj->itf->v.itf->delta_y; + wr.left -= delta_x; + wr.right -= delta_x; + wr.top -= delta_y; + wr.bottom -= delta_y; + + WINDOW win = xvt_win_create(W_PLAIN, &wr, "", 0, pwin, WSF_NO_MENUBAR, EM_ALL, + (EVENT_HANDLER)xi_event, 0L); + itfdef->v.itf->win = win; + itfdef->v.itf->rctp = ≀ + XI_OBJ* itfobj = xi_create(NULL, itfdef); + xi_tree_free(itfdef); + + CHECK(itfobj != NULL, "Oggetto del cazzo!"); + + _xi_lst = xi_get_obj(itfobj, _xi_obj->cid+1000); + + CHECK(_xi_lst != NULL, "Lista del cazzo!"); + + _open = TRUE; + xi_cell_request(_xi_lst); + xvt_scr_set_focus_vobj(win); + xvt_vobj_raise(win); + _displayed = TRUE; + xi_scroll_rec(_xi_lst, _selected, NORMAL_COLOR, XI_ATR_ENABLED, 0); + const int row = rec2row(_selected); + XI_OBJ cell; + XI_MAKE_CELL(&cell, _xi_lst, row, 0); + xi_set_focus(&cell); + xi_dequeue(); } -/////////////////////////////////////////////////////////// -// Button -/////////////////////////////////////////////////////////// - -class TButton : public TControl -{ -protected: - enum { DEPTH = 2 }; - - virtual WIN_TYPE type() const { return WC_PUSHBUTTON; } - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - virtual void check(bool on); - virtual void draw_pressed(bool pressed) const; - -public: - TButton(short left, short top, short right, short bottom, - const char* caption,WINDOW parent, - long flags, long app_data, short id); -}; - - -TButton::TButton(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -{ - create(left, top, right, bottom, caption, parent, flags, app_data, id); -} - - -void TButton::draw_pressed(bool pressed) const -{ - get_geometry(win()); - - xvt_dwin_clear(_hdc, COLOR_LTGRAY); - RCT r = _client; - xvt_draw_rect(_hdc, r, COLOR_BLACK, COLOR_BLACK); - - COLOR lt = pressed ? COLOR_GRAY : COLOR_WHITE; - COLOR rb = pressed ? COLOR_LTGRAY : COLOR_GRAY; - - for (int i = DEPTH; i--;) - { - r.left++; r.top++; r.right--; r.bottom--; - xvt_draw_rect(_hdc, r, lt, rb); - if (i == 1) lt = COLOR_LTGRAY; - } -} - - -void TButton::update() const -{ - TControl::update(); - draw_pressed(checked()); -} - -void TButton::mouse_down(PNT) -{ - draw_pressed(!checked()); -} - -void TButton::mouse_up() -{ - draw_pressed(checked()); - - EVENT e; // Notification message - e.type = E_CONTROL; - e.v.ctl.id = id(); - e.v.ctl.ci.type = type(); - e.v.ctl.ci.win = win(); - xvt_win_dispatch_event(xvt_vobj_get_parent(win()), &e); -} - -void TButton::check(bool on) -{ - TControl::check(on); - draw_pressed(on); -} - -/////////////////////////////////////////////////////////// -// TPush button -/////////////////////////////////////////////////////////// - -class TPush_button : public TButton -{ - short _picup, _picdn; - short _accel, _dx, _dy; - -protected: - void draw_pressed(bool pressed) const; - void update() const; - -public: - TPush_button(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); - virtual ~TPush_button(); -}; - -TPush_button::TPush_button(short left, short top, short right, short bottom, - const char* capt, WINDOW parent, - long flags, long app_data, short id) -: TButton(left-(id == DLG_F9), top, right, bottom, - capt, parent, flags, app_data, id), - _picup(0), _picdn(0) -{ - switch(id) - { - - case DLG_OK: - if (strcmp("Conferma", caption()) == 0) - capt = format("#%d", BMP_OK); - break; - case DLG_CANCEL: - if (strcmp("Annulla", caption()) == 0) - capt = format("#%d", BMP_CANCEL); - break; - case DLG_QUIT: - capt = format("#%d#%d", BMP_QUIT, BMP_QUITDN); - break; - case DLG_SELECT: - capt = format("#%d", BMP_SELECT); - break; - case DLG_DELREC: - capt = format("#%d#%d", BMP_DELREC, BMP_DELRECDN); - break; - case DLG_NEWREC: - if (strcmp("Nuovo", caption()) == 0) // Puo' essere Gestione - capt = format("#%d#%d", BMP_NEWREC, BMP_NEWRECDN); - break; - case DLG_STOPREC: - capt = format("#%d", BMP_STOPREC); - break; - /* - case DLG_FIRSTREC: - capt = format("#%d", BMP_FIRSTREC); - break; - case DLG_PREVREC: - capt = format("#%d", BMP_PREVREC); - break; - case DLG_NEXTREC: - capt = format("#%d", BMP_NEXTREC); - break; - case DLG_LASTREC: - capt = format("#%d", BMP_LASTREC); - break; - */ - case DLG_SAVEREC: - capt = format("#%d#%d", BMP_SAVEREC, BMP_SAVERECDN); - break; - case DLG_FINDREC: - capt = format("#%d", BMP_FINDREC); - break; - case DLG_F9: - if (*capt != '#') - capt = format("#%d", BMP_SEARCH); - break; - case DLG_F8: - if (*capt != '#') - capt = format("#%d", BMP_LENTE); - break; - case DLG_LINK: - if (strcmp("~Collega", caption()) == 0) - capt = format("#%d", BMP_LINK); - break; - case DLG_EDIT: - capt = format("#%d", BMP_EDIT); - break; - case DLG_PRINT: - capt = format("#%d", BMP_PRINT); - break; - case DLG_SETPRINT: - capt = format("#%d", BMP_SETPRINT); - break; - case DLG_RECALC: - capt = format("#%d", BMP_RECALC); - break; - default: - break; - } - - const int height = bottom-top; - const int width = right-left; - - const char* diesis = strchr(capt, '#'); - if (diesis != NULL) - { - _picup = atoi(++diesis); - const TImage& pic = cpb.add(_picup); - diesis = strchr(diesis, '#'); - if (diesis != NULL) - { - _picdn = atoi(++diesis); - cpb.add(_picdn); - } - - _dx = (width - pic.width()) >> 1; - _dy = (height - pic.height()) >> 1; - - _accel = -1; - } - else - { - TFixed_string c(capt); - _accel = c.find('~'); - if (_accel > 0) - _accel = xvt_dwin_get_text_width(win(), (char*)capt, _accel); - - _dx = (width - xvt_dwin_get_text_width(win(), (char*)caption(), -1)) >> 1; - _dy = (height- CHARY)/2 + BASEY - DEPTH; - } -} - -TPush_button::~TPush_button() -{ -} - -void TPush_button::draw_pressed(bool pressed) const -{ - TButton::draw_pressed(pressed); - - if (_picup) - { - const short pic = (pressed && _picdn) ? _picdn : _picup; - if (cpb.exist(pic)) - { - const TImage& i = cpb.image(pic); - RCT dst = i.rect(); - if (pressed) - xvt_rect_offset(&dst, _dx+DEPTH, _dy+DEPTH); - else - xvt_rect_offset(&dst, _dx, _dy); - i.draw(_hdc, dst); - } - } - else - { - const char* t = caption(); - - const short x = _dx + DEPTH*pressed; - const short y = _dy + DEPTH*pressed; - - xvt_dwin_set_fore_color(_hdc, COLOR_WHITE); - xvt_dwin_draw_text(_hdc, x+1, y+1, (char*)t, -1); - if (_accel >= 0) - xvt_dwin_draw_text(_hdc, x+_accel+1, y+1, "_", 1); - - const COLOR c = disabled() ? DISABLED_COLOR : color(); - xvt_dwin_set_fore_color(_hdc, c); - xvt_dwin_draw_text(_hdc, x, y, (char*)t, -1); - if (_accel >= 0) - xvt_dwin_draw_text(_hdc, x+_accel, y+0, "_", 1); - } -} - -void TPush_button::update() const -{ - draw_pressed(FALSE); - if (focused() && id() != DLG_F9) - { - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = COLOR_RED; - xvt_dwin_set_cpen(_hdc, &pen); - CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE }; - xvt_dwin_set_cbrush(_hdc, &brush); - xvt_dwin_draw_rect(_hdc, &_client); - } else - if (disabled() && _picup) - { - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = COLOR_LTGRAY; - xvt_dwin_set_cpen(_hdc, &pen); - - const int sx = _client.left+DEPTH+1; - const int sy = _client.top+DEPTH+1; - const int ex = _client.right-DEPTH-1; - const int ey = _client.bottom-DEPTH-1; - - for (int i = sx; i < ex; i += 2) +// ------------------------------------------------------------------ + +bool TListbox_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev) +{ + bool ok = TRUE; + switch (xiev->type) + { + case XIE_DBL_FIELD: + case XIE_BUTTON: + _ddl->open(); + break; + case XIE_CHAR_FIELD: { - PNT p = { sy, i }; - xvt_dwin_draw_set_pos(_hdc, p); - p.v = ey; - xvt_dwin_draw_line(_hdc, p); - } - for (i = sy; i < ey; i += 2) - { - PNT p = { i, sx }; - xvt_dwin_draw_set_pos(_hdc, p); - p.h = ex; - xvt_dwin_draw_line(_hdc, p); - } - } + const KEY k = xiev_to_key(xiev); + if (is_edit_key(k) && isalnum(k)) + _ddl->select_by_initial(k); + else if (k == K_F9) + _ddl->open(); + else if (k == K_RIGHT) // poor man's substitute for down arrow + { + if (selected() < items()-1) + select(selected() + 1); + } + else if (k == K_LEFT) // poor man's substitute for up arrow + { + if (selected() > 0) + select(selected() - 1); + } + xiev->refused = TRUE; + } + break; + case XIE_CHG_FIELD: + // Ignore changes: they are notified by the drop-down list + break; + default: + ok = TField_control::event_handler(itf, xiev); + break; + } + return ok; } -/////////////////////////////////////////////////////////// -// TPage_button -/////////////////////////////////////////////////////////// - -class TPage_button : public TControl -{ - enum { height = 19, width2 = 16, width = 32 }; - byte _flag; - -protected: - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - -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) -{ - RCT r; xvt_vobj_get_client_rect(parent, &r); - const int w = (flag == 3) ? width : width2; - if (flag == 2) r.right -= w; - - create(r.right-w, r.bottom-height, r.right, r.bottom, - "", parent, 0L, 0L, DLG_PAGE); - cpb.add(BMP_BOOK1 + flag -1, flag == 3); +void TListbox_control::select(int k) +{ + _ddl->select(k); } -void TPage_button::mouse_down(PNT where) +int TListbox_control::selected() const { - bool p; - switch (_flag) - { - case 1: - p = FALSE; break; - case 2: - p = TRUE; - default: - p = where.h < (width2); break; - } - check(p); + return _ddl->selected(); +} + +void TListbox_control::set_values(const char* val) +{ + _values = val; + _ddl->set_values(val); + _ddl->select(selected(), TRUE); } -void TPage_button::mouse_up() +TListbox_control::TListbox_control(WINDOW win, short cid, + short left, short top, short width, + const char* flags, const char* text, const char* values) + : TField_control(), _values(values) { - dispatch_e_char(xvt_vobj_get_parent(win()), checked() ? K_PREV : K_NEXT); + create(win, cid, left, top, width , 1, width, flags, text, TRUE); + _ddl = new TDropDownList(_obj, _values, width); + _ddl->select(0, TRUE); +} + +TListbox_control::~TListbox_control() +{ + delete _ddl; } - -void TPage_button::update() const -{ - TControl::update(); - if (_flag) - cpb.image(BMP_BOOK1 + _flag -1).draw(_hdc); -} - -void TPage_button::set_flag(byte f) -{ - _flag = f; - update(); -} - -/////////////////////////////////////////////////////////// -// TTag_button -/////////////////////////////////////////////////////////// - -class TTag_button : public TControl -{ - enum { height = 12, width = 32 }; - byte _curr; - byte _page; - byte _pages; - - WINDOW _parent; - -protected: - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - -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) -: _parent(parent), _page(p), _pages(tot), _curr(p) -{ - RCT r; xvt_vobj_get_client_rect(parent, &r); - create(0, 0, r.right, CHARY, "", parent,0L,0L, DLG_PAGETAGS); -} - -void TTag_button::update() const -{ - get_geometry(win()); - xvt_dwin_clear(_hdc, MASK_DARK_COLOR); - - for (int i = 0; i < _pages; i++) - { - RCT r; xvt_rect_set(&r, width*i, 0, width*(i+1), _client.bottom+4); - CBRUSH b = { PAT_SOLID, (i == _page) ? MASK_BACK_COLOR : MASK_DARK_COLOR}; - xvt_dwin_set_cbrush(_hdc, &b); - xvt_dwin_set_std_cpen(_hdc, TL_PEN_BLACK); - xvt_dwin_draw_rect(_hdc, &r); - - if (i == _page) - xvt_draw_rect(_hdc, r, MASK_LIGHT_COLOR, MASK_BACK_COLOR); - - char n[4]; sprintf(n, "%d", i+1); - xvt_dwin_set_fore_color(_hdc, color()); - xvt_dwin_draw_text(_hdc, (width-CHARX)/2 + i*width, BASEY, n, -1); - } - - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = MASK_LIGHT_COLOR; - xvt_dwin_set_cpen(_hdc, &pen); - - PNT p = { _client.bottom, 0 }; - xvt_dwin_draw_set_pos(_hdc, p); - p.h = width*_page; - xvt_dwin_draw_line(_hdc, p); - p.h += width+1; - xvt_dwin_draw_set_pos(_hdc, p); - p.h = _client.right; - xvt_dwin_draw_line(_hdc, p); -} - -void TTag_button::mouse_down(PNT where) -{ - _curr = where.h / width; - if (_curr >= _pages) _curr = _pages-1; else - if (_curr < 0) _curr = 0; -} - -void TTag_button::mouse_up() -{ - if (_curr != _page) - dispatch_e_char(_parent, K_CTRL + K_F1 + _curr); -} - -void TTag_button::set_pages(byte p) -{ - _pages = p; - update(); -} - -/////////////////////////////////////////////////////////// -// Checkbox -/////////////////////////////////////////////////////////// - -class TCheckbox : public TButton -{ -protected: - virtual WIN_TYPE type() const; - virtual void draw_pressed(bool pressed) const; - virtual void update() const; - - int radio() const { return multiple() ? 1 : 0; } - -public: - TCheckbox(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); - virtual ~TCheckbox(); -}; - -TCheckbox::TCheckbox( - short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -: TButton(left, top, right, bottom, - caption, parent, flags, app_data, id) -{ - if (!cpb.exist(BMP_CHECK_ON)) - { - TImage& i = cpb.add(BMP_CHECK_ON, TRUE); - - const short dx = 0; - const short dy = BASEY - i.height() + 2; - i.set_pos(dx, dy); - - cpb.add(BMP_CHECK_OFF, TRUE).set_pos(dx, dy); - cpb.add(BMP_RADIO_ON, TRUE).set_pos(dx, dy); - cpb.add(BMP_RADIO_OFF, TRUE).set_pos(dx, dy); - } -} - - -TCheckbox::~TCheckbox() -{ -} - - -WIN_TYPE TCheckbox::type() const -{ - return multiple() ? WC_RADIOBUTTON : WC_CHECKBOX; -} - - -void TCheckbox::draw_pressed(bool pressed) const -{ - get_geometry(win()); - short pic; - if (radio()) - pic = pressed ? BMP_RADIO_ON : BMP_RADIO_OFF; - else - pic = pressed ? BMP_CHECK_ON : BMP_CHECK_OFF; - - if (cpb.exist(pic)) - cpb.image(pic).draw(_hdc); -} - - -void TCheckbox::update() const -{ - TButton::update(); - - const int x = _client.left+20; - const int y = _client.top + BASEY; - - if (focused()) - { -#if XVT_OS == XVT_OS_WIN - RECT r; - r.left = x-2; r.top = _client.top; - r.right = _client.right-CHARX; r.bottom = y+3; - - HWND hwnd = (HWND)xvt_vobj_get_attr(_hdc, ATTR_NATIVE_WINDOW); - HDC hdc = GetDC(hwnd); - DrawFocusRect(hdc, &r); - ReleaseDC(hwnd, hdc); -#endif - } - - xvt_dwin_draw_text(_hdc, x, y, (char*)caption(), -1); -} - -/////////////////////////////////////////////////////////// -// User functions -/////////////////////////////////////////////////////////// - -// @doc INTERNAL - -// @func Permette di creare un Checkbox -// -// @rdesc Ritorna l'handle del controllo creato -WINDOW xvt_create_checkbox( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* caption, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - int id) // @parm Identificatore assegnato - -// @comm Il controllo si ditruggera' automagicamente alla fine della sua vita. -{ - TCheckbox* cb = new TCheckbox(left, top, right, bottom, - caption, parent, - flags, app_data, id); - - // It'll destroy itself automagically :-) - - return cb->win(); -} - -// @doc INTERNAL - -// @func Permette di creare un Radiobutton -// -// @rdesc Ritorna l'handle del controllo creato -WINDOW xvt_create_radiobutton( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* caption, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - int id) // @parm Identificatore assegnato - -// @comm Il controllo si ditruggera' automagicamente alla fine della sua vita. -{ - flags |= CTL_FLAG_MULTIPLE; - TCheckbox* cb = new TCheckbox(left, top, right, bottom, - caption, parent, - flags, app_data, id); - - // It'll destroy itself automagically :-) - return cb->win(); -} - -// @doc INTERNAL - -// @func Permette di creare un qualsiasi Bottone premibile -// -// @rdesc Ritorna l'handle del controllo creato -WINDOW xvt_create_pushbutton( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* caption, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - int id) // @parm Identificatore assegnato - -// @comm Il controllo si ditruggera' automagicamente alla fine della sua vita. -{ - TControl* pb; - - switch (id) - { - case DLG_PAGE: - pb = new TPage_button(parent, (byte)flags); - break; - case DLG_PAGETAGS: - pb = new TTag_button(parent, (byte)flags, (byte)app_data); - break; - default: - if (bottom-top > (CHARY<<1)) - { - top += BASEY>>1; - bottom -= BASEY>>1; - } - pb = new TPush_button(left, top, right, bottom, - caption, parent, - flags, app_data, id); - } - - // It'll destroy itself automagically :-) - return pb->win(); -} - -// @doc INTERNAL - -// @func Permette di creare un campo di solo Testo -// -// @rdesc Ritorna l'handle del controllo creato -WINDOW xvt_create_text( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* caption, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - int id) // @parm Identificatore assegnato - -// @comm Il controllo si ditruggera' automagicamente alla fine della sua vita. -{ - TText* cb = new TText(left, top, right, bottom, - caption, parent, - flags, app_data, id); - // It'll destroy itself automagically :-) - return cb->win(); -} - -// @doc INTERNAL - -// @func Permette di creare un Groupbox -// -// @rdesc Ritorna l'handle del controllo creato -WINDOW xvt_create_groupbox( - short left, // @parm Coordinata X di posizionamento (in pixel) - short top, // @parm Coordinata Y di posizionamento (in pixel) - short right, // @parm Larghezza (in pixel) - short bottom, // @parm Altezza (in pixel) - const char* caption, // @parm Prompt - WINDOW parent, // @parm Handle della finestra a cui apprtiene il controllo - long flags, // @parm Flags di configurazione - long app_data, // @parm Puntatore all'oggetto - int id) // @parm Identificatore assegnato - -// @comm Il controllo si ditruggera' automagicamente alla fine della sua vita. -{ - TGroup* cb = new TGroup(left, top, right, bottom, - caption, parent, - flags, app_data, id); - // It'll destroy itself automagically :-) - return cb->win(); -} - -// @doc INTERNAL - -// @func Dealloca le bitmab utilizzate per i controlli -void free_controls_bmp() -{ - cpb.destroy(); -} - - -TControl* TControl::WINDOW2TControl(WINDOW win) -{ - CHECK(win, "Can't get the control model from a NULL window"); - TControl** model = (TControl**)xvtcm_get_model(win, 0); - CHECK(model && *model, "Can't get the control 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 811f06459..945bbfb33 100755 --- a/include/controls.h +++ b/include/controls.h @@ -5,47 +5,23 @@ #include #endif -WINDOW xvt_create_checkbox( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id); +class TWindow; // __WINDOW_H +class TMask_field; // __MASKFLD_H -WINDOW xvt_create_radiobutton( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id); +#ifndef INCL_XI +#define XI_INTERNAL +#include +#endif -WINDOW xvt_create_pushbutton( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id); +void init_controls(); +void free_controls(); +XVT_FNTID xvt_default_font(bool bold = FALSE); -WINDOW xvt_create_text( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id); +WINDOW create_interface(WINDOW parent, short x, short y, short dx, short dy, + const char* caption, TWindow* mask, bool tags); -WINDOW xvt_create_groupbox( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id); +void attach_interface(WINDOW win, COLOR back = COLOR_WHITE); -void free_controls_bmp(); /////////////////////////////////////////////////////////// // Custom control @@ -53,107 +29,297 @@ void free_controls_bmp(); // @doc INTERNAL -// @class TControl | Classe per la creazione di controlli personalizzati -class TControl +// @class TControl | Classe per la creazione di controlli +class TControl : public TObject // @author:(INTERNAL) Guido // @access:(INTERNAL) Private Member { - // @cmember:(INTERNAL) Handle del controllo creato - WINDOW _win; - // @cmember:(INTERNAL) Iedntificatore assegnato al cotrollo - short _id; - // @cmember:(INTERNAL) Prompt del controllo - TString _caption; - // @cmember:(INTERNAL) Colore di foreground del controllo - COLOR _color; - // @cmember:(INTERNAL) Colore di background del controllo - COLOR _backcolor; - - // @cmember:(INTERNAL) Indica se il controllo e' disabilitato - bool _disabled : 1; - // @cmember:(INTERNAL) Indica se il controllo ha un check - bool _checked : 1; - // @cmember:(INTERNAL) Indica se il controllo ha il focus - bool _focused : 1; - // @cmember:(INTERNAL) Indica varie cose a seconda del tipo di controllo she si sta utilizzando - bool _multiple : 1; // @access Protected Member protected: - // @cmember E' l'handler del controllo - static long XVT_CALLCONV1 handler(WINDOW win, EVENT* ep); + // @cmember:(INTERNAL) Puntatore al controllo creato + XI_OBJ* _obj; - // @cmember Crea il controllo - void create(short left, short top, short right, short bottom, const char* caption, WINDOW parent, long flags, long app_data, short id); + // @cmember:(INTERNAL) Puntatore al TMask_field eventualmente associato + TMask_field* _fld; - // @cmember Ridisegna il controllo a video - virtual void update() const pure; - // @cmember Chiamate ogni volta che viene premuto il mouse sul controllo - virtual void mouse_down(PNT) - {}; - // @cmember Chiamate ogni volta che viene rialsciato il mouse sul controllo - virtual void mouse_up() - {}; - // @cmember Ritorna il tipo di finestra su cui si trova il controllo - virtual WIN_TYPE type() const - { return W_NO_BORDER; } + // @cmember Ricava l'interfaccia da una finestra + XI_OBJ* get_interface(WINDOW win = NULL_WIN) const; + + // @cmember Cerca un controllo operabile (in avanti o all'indietro) + TControl& find_operable_ctl(bool forward) const; + + // @cmember Setta l'identificatore del prossimo controllo per il tasto TAB + void set_tab_cid(short id); + + void coord2rct(WINDOW win, short left, short top, short width, short height, RCT& rct) const; + unsigned long flags2attr(const char* flags) const; + void update_tab_cid(); + const char* parse_caption(const char* cap, bool& bold, COLOR& color) const; + + void change_attrib(unsigned long attr, bool on, XI_OBJ* obj = NULL); + + bool notify_key(KEY k); // @access Public Member public: - // @cmember Ritorna il TControl dalla finestra del controllo - static TControl* WINDOW2TControl(WINDOW win); - // @cmember Distruttore. Necessariamente virtuale per derivare altri distruttori + TControl(); virtual ~TControl(); + + static KEY xiev_to_key(const XI_EVENT* xiev); + + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* ep); + + bool is_edit_key(KEY k) const; - // @cmember Ritorna l'handle del controllo - WINDOW win() const - { return _win; } // @cmember Ritorna l'identificatore assegnato al controllo - short id() const - { return _id; } + short id() const { return _obj->cid; } + WINDOW parent() const; + + XI_OBJ_TYPE type() const { return _obj->type; } + // @cmember Ritorna il prompt del controllo - const char* caption() const - { return _caption; } + const char* caption() const; // @cmember Setta il prompt del controllo - void set_caption(const char* c); + virtual void set_caption(const char* c); - // @cmember Ritorna il colore di forground del controllo - COLOR color() const - { return _color; } - // @cmember Setta il colore di forground del controllo - void set_color(COLOR c) - { _color = c; } - - // @cmember Ritorna il colore di background del controllo - COLOR back_color() const - { return _backcolor; } - // @cmember Setta il colore di background del controllo - void set_back_color(COLOR c) - { _backcolor = c; } - - // @cmember Ritorna se il controllo possiede un check - bool checked() const - { return _checked; } - // @cmember Setta se il controllo debba avere un check - virtual void check(bool on); - - // @cmember Ritorna se il controllo e' disabilitato - bool disabled() const - { return _disabled; } // @cmember Abilita/disabilita il controllo - void enable(bool on); - - // @cmember Ritorna se il controllo ha il focus - bool focused() const - { return _focused; } - // @cmember Setta il focus sul cursore (stessa sintassi di ) - void focus(bool on) - { _focused = on; } - - // @cmember Ritorna il contenuto della variabile - bool multiple() const - { return _multiple; } + virtual void enable(bool on = TRUE); + void disable() { enable(FALSE); } + + // @cmember Mostra/nasconde il controllo + virtual void show(bool on = TRUE); + void hide() { show(FALSE); } + + void autoselect(bool on); + + // @cmember Forza il focus al controllo + virtual void set_focus() const; + + RCT& get_rect(RCT& r) const; + virtual void set_rect(const RCT& r); + + bool on_key(KEY k); }; + +class TText_control : public TControl +{ +public: // TControl + virtual void set_caption(const char* text); + +public: + TText_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text); + virtual ~TText_control() {} +}; + + +class TGroupbox_control : public TText_control +{ + XI_OBJ* _rct; // Rettangolo del gruppo + +public: // TControl + virtual void show(bool on); + +public: + TGroupbox_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text); + virtual ~TGroupbox_control() {} +}; + +class TField_control : public TControl +{ +protected: + bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + + void create(WINDOW win, short cid, + short left, short top, + short width, short height, short maxlen, + const char* flags, const char* text, bool button); + + TField_control() {} + +public: + // @cmember Mostra o nasconde il bottone associato + void show_button(bool on); + + // @cmember Forza il focus al controllo + virtual void set_focus() const; + + TField_control(WINDOW win, short cid, + short left, short top, + short width, short maxlen, + const char* flags, const char* text); + virtual ~TField_control() {} +}; + +class TMultiline_control : public TField_control +{ +public: + TMultiline_control(WINDOW win, short cid, + short left, short top, + short width, short height, short maxlen, + const char* flags, const char* text); + virtual ~TMultiline_control() {} +}; + + + +class TButton_control : public TControl +{ +protected: + void create(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, + WIN_TYPE wc, XI_OBJ* container); + + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* ep); + +public: + virtual void set_rect(const RCT& r); + + bool checked() const; + void check(bool on = TRUE); + void uncheck() { check(FALSE); } + bool toggle(); + + XI_BTN_TYPE button_type() const; + XI_OBJ* container() const; + + TButton_control() {} + virtual ~TButton_control() {} +}; + +class TPushbutton_control : public TButton_control +{ + short _bmp_up, _bmp_dn; + +protected: + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + +public: + virtual void update(); + + void set_bmp(short up, short dn); + + TPushbutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, + short bmp_up = 0, short _bmp_dn = 0); + virtual ~TPushbutton_control() {} +}; + +class TRadiobutton_control : public TButton_control +{ +protected: // TControl + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + virtual void set_focus() const; + +protected: + TRadiobutton_control() { } // To be derived + +public: + // @cmember Abilita/disabilita il controllo + virtual void enable(bool on = TRUE); + // @cmember Mostra/nasconde il controllo + virtual void show(bool on = TRUE); + + byte get_checked() const; + void check_button(byte b); + + void show_button(byte b, bool on = TRUE); + void hide_button(byte b) { show_button(b, FALSE); } + + TRadiobutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text); + virtual ~TRadiobutton_control() {} +}; + +class TTagbutton_control : public TRadiobutton_control +{ +protected: // TControl + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + +public: + TTagbutton_control(WINDOW win, short cid, + short left, short top, short width, short height, + const char* flags, const char* text, int tag); + virtual ~TTagbutton_control() {} +}; + + +class TCheckbox_control : public TButton_control +{ +public: + TCheckbox_control(WINDOW win, short cid, + short left, short top, short width, + const char* flags, const char* text); + virtual ~TCheckbox_control() {} +}; + +class TDropDownList : public TObject +{ + + XI_OBJ* _xi_obj; + XI_OBJ* _xi_lst; + TToken_string _values; + int _selected; + int _width; + bool _open; + bool _displayed; + bool _in_cell; + + static void ddl_str_eh (XI_OBJ* itf, XI_EVENT* xiev); + + public: + + const int selected() const { return _selected; } + void select_by_initial(char c); + void open(); + void close(); + bool is_open() { return _open; } + bool displayed() { return _displayed; } + + const char* item(int i) { return _values.get(i); } + int items() const { return _values.items(); } + long row2rec(int) const; + int rec2row(long rec) const; + void select(int i, bool force = FALSE); + void set_values(const char* v) { _values = v; _selected = 0; } + + TDropDownList(XI_OBJ* o, const char* values, int wid, bool cell = FALSE); + virtual ~TDropDownList() {} +}; + +class TListbox_control : public TField_control +{ + friend class TDropDownList; + TDropDownList* _ddl; + TToken_string _values; + void drop_down(); + +protected: + + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + +public: + + void set_values(const char* c); + int selected() const; + int items() const { return _values.items(); } + void select(int i); + + TListbox_control(WINDOW win, short cid, + short left, short top, short width, + const char* flags, const char* text, const char* values); + virtual ~TListbox_control(); +}; + + + #endif diff --git a/include/default.url b/include/default.url index fdcf96c10..937491bfc 100755 --- a/include/default.url +++ b/include/default.url @@ -34,7 +34,7 @@ SUBMENU M_EDIT "~Edit" MENU MENU_VISWIN ITEM M_EDIT_CLIPBOARD "Interrompi\tESC" -ITEM M_EDIT_CUT "~Collega...\tCtrl+C" DISABLED +ITEM M_EDIT_CUT "Colle~ga...\tCtrl+G" DISABLED ITEM M_EDIT_PASTE "~Esporta...\tCtrl+E" ITEM M_EDIT_SEL_ALL "~Stampa... \tCtrl+S" DISABLED SEPARATOR diff --git a/include/defmask.h b/include/defmask.h index 2d2035651..79c9bef24 100755 --- a/include/defmask.h +++ b/include/defmask.h @@ -29,8 +29,8 @@ #define DLG_PRINT 24 /* TAG del bottone Stampa */ #define DLG_SETPRINT 25 /* TAG del bottone Imposta Stampa */ #define DLG_RECALC 26 /* TAG del bottone Ricalcola */ +#define DLG_F8 27 /* TAG del bottone */ #define DLG_USER 100 /* TAG del primo controllo definito dall'utente */ -#define DLG_F8 27 /* TAG del bottone */ /* @M Funzioni di libreria per i validate delle maschere diff --git a/include/files.cpp b/include/files.cpp index 6bd3c3f81..ef452d537 100755 --- a/include/files.cpp +++ b/include/files.cpp @@ -310,22 +310,19 @@ TTrec::~TTrec () delete _rec; } -int TTrec ::compare (const TSortable & a) const - +int TTrec::compare(const TSortable & a) const { const TTrec & r = (const TTrec &) a; const int res = memcmp ((const void *) _rec, (const void *) r._rec, sizeof (*_rec)); - return res; + return res; } -void TTrec::rehash () - +void TTrec::rehash() { setrdes (_rec); } TTrec & TTrec::operator = (const TTrec & b) - { _num = b._num; memcpy (_rec, b._rec, sizeof (*_rec)); diff --git a/include/form.cpp b/include/form.cpp index 5ab351771..60db4f250 100755 --- a/include/form.cpp +++ b/include/form.cpp @@ -1383,7 +1383,7 @@ bool TForm_string::read() const TRelation* r = form().relation(); CHECK(r, "Can't read from null relation"); for (int i = 0; i < _field.items() && *s == '\0'; i++) - s = field(i).read(r); + s = field(i).read(*r); set(s); } } diff --git a/include/golem.cpp b/include/golem.cpp index f8fb85e86..10b757dd9 100755 --- a/include/golem.cpp +++ b/include/golem.cpp @@ -182,7 +182,7 @@ bool TGolem::import() correct = fcopy(from, path(TRUE)); if (correct) { - msk.autosave(_golem); + msk.autosave(*_golem); int err = _golem->write(); if (err == _isreinsert) err = _golem->rewrite(); diff --git a/include/isam.cpp b/include/isam.cpp index 7ce91b2dc..eadba34b3 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -3055,7 +3055,7 @@ void TRecfield::set(int from, int to) CHECK(from >= 0, "Invalid Start"); _p = _rec->string() + rd->Fd[nf].RecOff + from; _dec = rd->Fd[nf].Dec; - _type = rd->Fd[nf].TypeF; + _type = (TFieldtypes)rd->Fd[nf].TypeF; if (to >= 0) { CHECK(from <= to && to <= rd->Fd[nf].Len, "Invalid Range"); @@ -3314,8 +3314,11 @@ TRecfield::operator TDate() const TRecfield::operator const char*() const -{ - __getfieldbuff( _len, _type, _p, _isam_string); +{ + if (_type == _memofld) + return _rec->get(_name); + + __getfieldbuff(_len, _type, _p, _isam_string); return _isam_string; } diff --git a/include/isam.h b/include/isam.h index 4e38bd3b0..e83783dff 100755 --- a/include/isam.h +++ b/include/isam.h @@ -658,7 +658,7 @@ class TSystemisamfile : public TIsamfile // @cmember:(INTERNAL) Esegue la conversione del file bool exec_convapp(long flev, const bool before); // @cmember:(INTERNAL) Esegue la conversione sui record del file (utilizzando le espressione definite - // in fconv.ini) + // in fconv.ini) void makelc(TRectype& rec); // @access Public Member @@ -806,7 +806,7 @@ class TRecfield : public TObject // @cmember:(INTERNAL) Numero di decimali del campo byte _dec; // @cmember:(INTERNAL) Tipo del campo - byte _type; + TFieldtypes _type; // @cmember:(INTERNAL) Setta il campo

-esimo con i valori di

-esimo void set(int from, int to); diff --git a/include/mask.cpp b/include/mask.cpp index e15584f59..045aaef9f 100755 --- a/include/mask.cpp +++ b/include/mask.cpp @@ -1,7 +1,14 @@ #include #include +#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include +#endif + #include +#include #include #include #include @@ -12,203 +19,14 @@ #define NULL_PAGE 256 HIDDEN const char* const MASK_EXT = "msk"; - -#ifdef DBG -extern unsigned long _alloc_count; -#endif + +HIDDEN short _msg_field = 0; +HIDDEN KEY _msg_key = 0; /////////////////////////////////////////////////////////// // TMask methods /////////////////////////////////////////////////////////// -HIDDEN bool moving_focus = FALSE; - -// @doc EXTERNAL - -// @mfunc Controlla se e' possibile dare il focus alla finestra

-// -// @rdesc Ritorna la possibilita' di lasciare il focus -// -// @flag TRUE | Se e' possibile cedere il focus a

-// @flag FALSE | Se non e' possibile cedere il focus a

-bool TMask::test_focus_change( - WINDOW next) // @parm Finestra che dovrebbe ricevere il focus - - // @comm Controlla se il contenuto del campo attuale e' valido e quindi puo' perdere il focus -{ - bool ok = TRUE; - - TMask_field& prev = fld(_focus); - _next_fld = next == NULL_WIN ? DLG_NULL : fld(find_field_win(next)).dlg(); - - if (prev.win() != next) - { - ok = prev.test_focus_change(); - if (!ok) // Test if previous field agrees ... - { - set_focus(); - prev.set_focusdirty(FALSE); - } - else - { - if ( prev.focusdirty() ) - ok = on_dirty( prev ); - } - - } - return ok; -} - -void TMask::control_handler(EVENT* ep) -{ - const WINDOW win = ep->v.ctl.ci.win; - const WIN_TYPE type = ep->v.ctl.ci.type; - - TMask_field* f = (TMask_field*)xvt_vobj_get_data(win); - CHECK(f != NULL, "Invalid field pointer in control"); - - if (type == WC_CHECKBOX) - { - if (test_focus_change(win)) - { - xvt_check_box(win, !xvt_get_checked_state(win)); - set_focus_win(win, FALSE); - f->on_key(K_SPACE); - } - return; - } - - if (type == WC_RADIOBUTTON) - { - if (moving_focus == FALSE) - { - if (test_focus_change(f->win())) - { - ((TRadio_field*)f)->check_radiobutton(win); - set_focus_win(win, FALSE); - f->on_key(K_SPACE); - } - } else moving_focus = FALSE; - return; - } - - if (type == WC_PUSHBUTTON) - { - if (test_focus_change(win)) - { - set_focus_win(win, FALSE); - f->on_hit(); - } - return; - } - - if (type == WC_LISTBUTTON) - { - if (test_focus_change(win)) - { - set_focus_win(win, FALSE); - f->on_key(K_SPACE); - } - return; - } - - if (ep->v.ctl.ci.v.edit.focus_change) - { - if (ep->v.ctl.ci.v.edit.active) - { - if (test_focus_change(win)) - { - set_focus_win(win, FALSE); - f->set_focusdirty(FALSE); - } - } - } - else - { // Contents of control were changed - f->on_key(K_SPACE); - } -} - -void TMask::handler(WINDOW win, EVENT* ep) -{ - switch (ep->type) - { - case E_UPDATE: -#if XVT_OS == XVT_OS_WIN - if (win != toolwin()) - { - xvt_dwin_clear(win, MASK_BACK_COLOR); - RCT r; xvt_vobj_get_client_rect(win, &r); r.right--; r.bottom--; - xvt_draw_rect(win, r, MASK_LIGHT_COLOR, MASK_DARK_COLOR, 1); - } - else xvt_dwin_clear(win, TOOL_BACK_COLOR); - xvt_tx_process_event(win, ep); -#else - xvt_dwin_clear(win, MASK_BACK_COLOR); -#endif - update(); - return; - case E_COMMAND: - if (ep->v.cmd.tag == M_FILE_NEW) - on_firm_change(); - break; - case E_CONTROL: - switch(ep->v.ctl.id) - { - case DLG_OK: - if (test_focus_change(ep->v.ctl.ci.win)) - stop_run(K_AUTO_ENTER); - break; - case DLG_CANCEL : - stop_run(K_ESC); - break; - case DLG_QUIT : - stop_run(K_FORCE_CLOSE); - break; - case DLG_F9: - { - WINDOW w = ep->v.ctl.ci.win; - TMask_field* f = (TMask_field*)xvt_vobj_get_data(w); - w = f->win(); - if (test_focus_change(w)) - f->on_key(K_F9); // Attiva ricerca sul campo associato al bottone - } - break; - case DLG_F8: - { - WINDOW w = ep->v.ctl.ci.win; - TMask_field* f = (TMask_field*)xvt_vobj_get_data(w); - w = f->win(); - if (test_focus_change(w)) - f->on_key(K_F8); // Attiva zoom sul campo associato al bottone - } - break; - default: - control_handler(ep); - break; - } - break; - default: - if (_focus >= 0 && _focus < fields() && fld(_focus).class_id() == CLASS_MEMO_FIELD) - { - bool ok = TRUE; - if (ep->type == E_CHAR) - { - const KEY k = e_char_to_key(ep); - ok = k != K_TAB && k != K_BTAB; - if (ok) fld(_focus).set_dirty(); - } - if (ok) - { - ok = xvt_tx_process_event(win, ep) == TRUE; - if (ok) return; - } - } - break; - } - TWindow::handler(win, ep); -} - void TMask::init_mask() { _sheets = _pages = 0; // Azzera numero pagine e sheets @@ -216,27 +34,28 @@ void TMask::init_mask() _enabled.set(MAX_PAGES); _enabled.set(); // Abilita tutte le pagine + _should_check = TRUE; - _focus = _first_focus = 0; // Nessuno ha il focus + _focus = _first_focus = 0; // Il primo ha il focus _page = -1; // Nessuna pagina corrente _handler = NULL; // Nessun handler utente _mode = NO_MODE; // Inizializza modo _exchange = 1.0; // Il cambio per la valuta e' la lira + + _error_severity = 0; + _test_fld = -1; memset(_pagewin, 0, sizeof(_pagewin)); - memset(_pagepag, 0, sizeof(_pagepag)); - memset(_pagetag, 0, sizeof(_pagetag)); } -TMask::TMask(const char* title, int pages, int cols, int rows, int xpos, - int ypos) +TMask::TMask(const char* title, int pages, int cols, int rows, + int xpos, int ypos) { init_mask(); for (_pages = 0; _pages < pages; _pages++) - _pagewin[_pages] = create(xpos, ypos, cols, rows, title, WSF_CLOSE, WD_MODAL); - set_win(NULL_WIN); - add_buttons(); + _pagewin[_pages] = create_interface(NULL_WIN, xpos, ypos, + cols, rows, title, this, pages > 1); } // @doc EXTERNAL @@ -246,8 +65,6 @@ void TMask::read_mask( const char* name, // @parm Nome della maschera da leggere (senza estensione) int num, // @parm Numero della maschera da leggere all'interno del file int max) // @parm Numero massimo di pagine che deve avere la maschera - - // @comm Permette di aggiornare i tempi di caricamento della maschera stessa { if (max <= 0) max = MAX_PAGES; @@ -262,14 +79,16 @@ void TMask::read_mask( if (num == 0) _total_time = _build_time = _init_time = 0; - + for (int i = 0; i < num; i++) { while (scanner.ok()) if (scanner.line() == "ENDMASK") break; } - + init_mask(); + + TToken_string captions(80); main_app().begin_wait(); while (scanner.ok() && scanner.popkey() != "EN") @@ -277,7 +96,13 @@ void TMask::read_mask( if (scanner.key() == "PA") { CHECKD(_pages < MAX_PAGES, "Maschera con troppe pagine: ", _pages); - _pagewin[_pages++] = read_page(scanner, FALSE); + WINDOW w = read_page(scanner, FALSE); + + char* title = &__tmp_string[512]; + xvt_vobj_get_title(w, title, 80); + captions.add(title); + + _pagewin[_pages++] = w; if (_pages >= max) break; } else @@ -288,10 +113,11 @@ void TMask::read_mask( } } - if (_pages < 1) + if (_pages <= 0) fatal_box("Impossibile leggere la maschera %s", name); - add_buttons(); + if (_pages > 1 || toolwin()) + add_tag_buttons(captions); if (num == 0) _total_time = clock()-start_t; @@ -299,45 +125,31 @@ void TMask::read_mask( main_app().end_wait(); } - -void TMask::add_buttons() -{ -#if XVT_OS == XVT_OS_WIN - for (int p = 0; p < _pages; p++) - { - if (_pages > 1) - { - 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()) - _pagetag[p] = xvt_create_control(WC_PUSHBUTTON, 0, 0, 0, 1, "", - _pagewin[p], p, _pages, DLG_PAGETAGS); - } -#else - if (toolwin()) - { - TString80 t; - for (int p = 0; p < _pages; p++) - t << ' ' << p+1; - t << ' '; - for (p = 0; p < _pages; p++) - { - const int k = p*2; - t[k] = '['; t[k+2] = ']'; - RCT r; xvt_rect_set(&r, 0, 0, t.size()*CHARX, CHARY); - xvt_ctl_create(WC_TEXT, &r, t, _pagewin[p], 0, 0, DLG_NULL); - t[k] = ' '; - } - } -#endif +void TMask::add_tag_button(byte pag, TToken_string& tags, byte sel) +{ + TTagbutton_control* tb = new TTagbutton_control(_pagewin[pag], 32000, 0, 0, 80, 1, "", tags, sel); + _pagetag.add(tb, pag); } +void TMask::add_tag_buttons(TToken_string& tags) +{ + for (byte p = 0; p < _pages; p++) + add_tag_button(p, tags, p); +} -TMask::TMask(const char* maskname, int num, int max) : _should_check(TRUE) +void TMask::add_default_tag_buttons() +{ + TToken_string tags(_pages * 6); + for (int p = 1; p <= _pages; p++) + { + tags.add("Pag."); + tags << p; + } + add_tag_buttons(tags); +} + +TMask::TMask(const char* maskname, int num, int max) { - if (maskname && *maskname) read_mask(maskname, num, max); } @@ -345,7 +157,7 @@ TMask::TMask(const char* maskname, int num, int max) : _should_check(TRUE) TMask::~TMask() { - for (int p = 0; p <= MAX_PAGES; p++) + for (int p = MAX_PAGES; p >= 0; p--) if (_pagewin[p]) { xvt_vobj_destroy(_pagewin[p]); @@ -353,62 +165,96 @@ TMask::~TMask() } } +word TMask::class_id() const +{ return CLASS_MASK; } + +bool TMask::is_kind_of(word c) const +{ + if (c == CLASS_MASK) + return TRUE; + return TWindow::is_kind_of(c); +} void TMask::open() -{ - set_mask_fields(); - - _focus = first_focus(0); - if (toolwin() && _focus < 1) - _focus = find_first_field(_pagewin[0], +1); - +{ if (!_open || _page != 0) { _open = TRUE; if (toolwin()) xvt_vobj_set_visible(toolwin(), TRUE); - show_page(0); - } - else - { - set_focus(); } + _focus = first_focus(0); + set_focus_field(focus_field().dlg()); } +int TMask::find_first_active(WINDOW p) const +{ + const int max = fields(); + for (int f = 0; f < max; f++) + { + TMask_field& c = fld(f); + if (c.active() && c.parent() == p) + return f; + } + return -1; +} int TMask::first_focus(short id) { - static int tempfirstfocus = 0; + static int tempfirstfocus = -1; int f = _first_focus; if (id == 0) { - if (tempfirstfocus) + if (tempfirstfocus >= 0) { f = tempfirstfocus; if (fld(f).dirty() == FALSE) fld(f).set_dirty(); } - tempfirstfocus = 0; + tempfirstfocus = -1; + if (f < 0) + f = _first_focus = find_first_active(_pagewin[0]); } else { if (id > 0) { _first_focus = id2pos(id); - tempfirstfocus = 0; + tempfirstfocus = -1; } else tempfirstfocus = id2pos(-id); } - + return f; } +void TMask::set_focus_field(short id) +{ + const int pos = id2pos(id); + CHECKD(pos >= 0, "Can't set focus to field ", id); + _focus = pos; + if (is_running()) + { + const TMask_field& f = fld(pos); + int p = find_parent_page(f); + if (p < 0 || p >= _pages || !page_enabled(p)) + p = 0; + show_page(p); + } +} + +void TMask::notify_focus_field(short id) +{ + const int pos = id2pos(id); + _focus = pos; +} + bool TMask::can_be_closed() const { bool ok = TRUE; - if (!query_mode() && is_running() && dirty()) + if (is_running() && (edit_mode() || insert_mode()) && dirty()) ok = yesno_box("Annullare i dati inseriti?"); return ok; } @@ -421,25 +267,13 @@ void TMask::close() if (_pagewin[p]) xvt_vobj_set_visible(_pagewin[p], FALSE); } -void TMask::set_mask_fields() const -{ - for (int i = 0; i < fields(); i++) - { - TMask_field& f = fld(i); - const word id = f.class_id(); - if (id != CLASS_FIELD && id != CLASS_BUTTON_FIELD) - f.set_window_data(f.get_field_data()); - } -} - short TMask::dirty() const -{ +{ const int max = fields(); for (int i = 0; i < max; i++) { const TMask_field& f = fld(i); - const word id = f.class_id(); - if (f.dirty() && id != CLASS_FIELD && id != CLASS_BUTTON_FIELD && f.active()) + if (f.dirty() && f.active()) return f.dlg(); } return 0; @@ -447,15 +281,12 @@ short TMask::dirty() const void TMask::load_checks() const { - if (_should_check) + const int max = fields(); + for (int i = 0; i < max; i++) { - const int max = fields(); - for (int i = 0; i < max; i++) - { - TMask_field& f = fld(i); - if (f.has_check()) - f.check(STARTING_CHECK); - } + TMask_field& f = fld(i); + if (f.has_check()) + f.check(STARTING_CHECK); } } @@ -474,15 +305,14 @@ void TMask::enable_page( if (_enabled[page] != on) { 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 + for (byte b = 0; b < _pages; b++) + { + TTagbutton_control& tag = (TTagbutton_control&)_pagetag[b]; + tag.show_button(i, on); + } + } } } @@ -499,30 +329,32 @@ bool TMask::page_enabled(byte p) const void TMask::start_run() { const long start = clock(); - - load_checks(); - _should_check = TRUE; - const int max = fields(); - - _next_fld = DLG_NULL; + + if (_should_check) + { + load_checks(); + + for (int i = 0; i < max; i++) + { + TMask_field& f = fld(i); + if (f.dirty() <= TRUE) + { + f.set_dirty(FALSE); + const bool op = f.is_operable() && !f.is_kind_of(CLASS_BUTTON_FIELD); + if (op && (f.active() || f.ghost())) + f.on_hit(); // Lancia messaggio di inizializzazione + } + } + } + _should_check = TRUE; + + // Make sure that "nearly" all fields are clean! for (int i = 0; i < max; i++) - { - TMask_field& f = fld(i); - if ((f.active() || f.ghost()) && - f.class_id() != CLASS_BUTTON_FIELD && f.dirty() <= TRUE) - { - f.set_dirty(FALSE); - f.on_hit(); // Lancia messaggio di inizializzazione - } - } - - // Make sure that "nearly" all fields are clean! - for (i = 0; i < max; i++) { TMask_field& f = fld(i); if (query_mode() && f.is_edit() && f.in_key(1) && - !f.automagic() && !f.get().empty()) + !f.automagic() && !f.empty()) { f.set_dirty(TRUE); } @@ -546,49 +378,35 @@ bool TMask::check_fields() for (int i = 0; i < max; i++) { TMask_field& f = fld(i); - - const bool on = f.class_id() == CLASS_SHEET_FIELD ? f.shown() : f.active(); - if (!on) continue; // Don't test inactive fields - if (f.parent() != curpage) + const bool on = f.active() || (f.shown() && f.is_kind_of(CLASS_SHEET_FIELD)); + if (on) // Don't test inactive fields { - const int pa = find_parent_page(f); - if (!page_enabled(pa)) - break; // Page disabled: end of test - curpage = f.parent(); // Update current page - } - - if (sheet) f.set_dirty(); // Force check in sheets - - if (f.on_key(K_ENTER) == FALSE) - { - if (is_open()) f.set_focus(); - return FALSE; - } + if (f.parent() != curpage) + { + const int pa = find_parent_page(f); + if (!page_enabled(pa)) + break; // Page disabled: end of test + curpage = f.parent(); // Update current page + } + + if (sheet) f.set_dirty(); // Force check in sheet masks + if (f.on_key(K_ENTER) == FALSE) + { + if (is_open()) + set_focus_field(f.dlg()); + return FALSE; + } + } } return TRUE; } - -void TMask::get_mask_fields() +void TMask::check_field( short fld_id ) { - for (int i = 0; i < fields(); i++) - { - TMask_field& f = fld(i); - const char* fd = f.get_field_data(); - if (fd != NULL) // NULL per testi fissi, bottoni e sheets - { - const char* wd = f.get_window_data(); - CHECKD(wd, "NULL window data in field ", f.dlg()); - if (f.dirty() == TRUE) - { - if (strcmp(wd, fd) == 0) - f.set_dirty(FALSE); - } - f.set_field_data(wd); - } - } + field( fld_id ).on_hit(); + field( fld_id ).check(); } - + // @doc EXTERNAL // @mfunc Converte un identificatore di campo nella sua posizione @@ -656,39 +474,8 @@ TEdit_field& TMask::efield(short id) const } -int TMask::find_field_win(WINDOW win) const -{ - if (fld(_focus).win() == win) - return _focus; - - const int max = fields(); - for (int i = 0; i < max; i++) - if (fld(i).win() == win) return i; - -#ifdef DBG - yesnofatal_box("Can't find the field given the child window"); -#endif - return 0; -} - // @doc EXTERNAL -// @mfunc Setta il focus al campo la cui finestra e'

-void TMask::set_focus_win( - WINDOW win, // @parm Finestra del controllo che riceve il focus - bool force) // @parm Forza la chiamata alla - - // @comm Il parametro

puo' assumere i seguenti valori: - // - // @flag TRUE | Se occorre attivare il focus interno (quello di Windows e' automatico) - // @flag FALSE | Se non occorre attivare il focus interno (e' possibile conoscere il focus - // interno della classe) -{ - _focus = find_field_win(win); - if (force) set_focus(); -} - - int TMask::find_parent_page(const TMask_field& f) const { const WINDOW pw = f.parent(); @@ -697,110 +484,6 @@ int TMask::find_parent_page(const TMask_field& f) const return MAX_PAGES; // Toolbar button } -// @doc EXTERNAL - -// @mfunc Ritorna il prossimo campo attivabile -// -// @rdesc Riorna il numero del campo cercato -int TMask::find_active_field( - int first, // @parm Campo da cui cominciare la ricerca - int dir) const // @parm Direzione della ricerca. Puo assumere i valori: - // - // @flag +1 | Ricerca in avanti - // @flag -1 | Ricerca in dietro - - // @comm Serve per la ricerca del campo attivabil al momento della pressione dei tasti - // TAB (o ENTER) e SHIFT+TAB -{ - const int max = fields()-1; - WINDOW w, old = fld(_focus).parent(); - - for (int i = first; ; i += dir) - { - if (i > max) i = 0; - else if (i < 0) i = max; - if (fld(i).active() && page_enabled(find_parent_page(fld(i)))) - { - w = fld(i).parent(); - break; - } - } - - if (w != old) - { - int p = _page; - if (old == toolwin()) - { - if (dir > 0) - { if (++p >= _pages) p = 0; } - } - else - { - if (dir < 0) - { if (--p < 0) p = _pages-1; } - else p = MAX_PAGES; - } - w = _pagewin[p]; - i = find_first_field(w, dir); - } - return i; -} - -void TMask::set_focus() -{ - _focus = find_active_field(_focus, +1); - const TMask_field& f = fld(_focus); - const int page = find_parent_page(f); - - if (page != _page && page != MAX_PAGES) - { - const WINDOW pw = win(); // previous window - _page = page; // update page number - xvt_vobj_set_visible(win(), TRUE); // show new page - if (pw) xvt_vobj_set_visible(pw, FALSE); // hide old page - } - - f.highlight(); -} - -// @doc EXTERNAL - -// @mfunc Muove il focus al prossimo o al precedente controllo valido -void TMask::move_focus_field( - int d) // @parm Indica lo spostamento relativo del focus rispetto - // al campo attuale: - // - // @flag +1 | Si sposta sul campo successivo - // @flag -1 | Si sposta sul campo precedente - // - // @comm E' possibile che il parametro

assuma valori diversi da -1 o +1. In questo caso - // sposta il focus di piu' di una posizione. - -{ - - TMask_field& f = fld(_focus); - if (f.class_id() == CLASS_RADIO_FIELD) - { - TRadio_field& radio = (TRadio_field&)f; - moving_focus = TRUE; - bool cont = radio.move_focus(d); - moving_focus = FALSE; - if (!cont) return; - } - - const int focus = find_active_field(_focus+d, d); - - if (!test_focus_change(fld(focus).win())) - return; - - if (fld(focus).parent() == f.parent() || check_current_page()) - _focus = focus; - - set_focus(); -} - -// @doc EXTERNAL - // @mfunc Forza la chiusura della maschera // // @rdesc Ritorna il risultato dell'operazione: @@ -811,49 +494,35 @@ bool TMask::stop_run( KEY key) // @parm Tasto che deve provocare la chiusura // @comm Permette di chiudere la maschera come se l'utente avesse premuto il tasto

. - // Nela caso la maschera non si chiuda (es. un check fallito), ritorna FALSE. + // Nel caso la maschera non si chiuda (es. un check fallito), ritorna FALSE. { if (key != K_AUTO_ENTER && key != K_FORCE_CLOSE) { const int last = fields(); - bool found = FALSE; for (int i = 0; i < last; i++) { const TMask_field& f = fld(i); - if (f.class_id() != CLASS_BUTTON_FIELD) continue; - const TButton_field& b = (const TButton_field&)f; - if (b.exit_key() == key) + if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD)) { - if (b.active()) - { - found = TRUE; + const TButton_field& b = (const TButton_field&)f; + if (b.exit_key() == key) break; - } - } + } } - if (!found) - { -#ifdef DBG - return error_box("Non e' attivo il bottone associato a %d", key); -#else + if (i >= last) return FALSE; -#endif - } } if (key == K_CTRL_ENTER || key == K_AUTO_ENTER) key = K_ENTER; else if (key == K_FORCE_CLOSE) key = K_QUIT; if (key != K_ESC && key != K_QUIT && key != K_DEL && key != K_F9) - { - const bool ok = check_fields(); + { + bool ok = check_current_field(); + if (ok) + ok = check_fields(); if (!ok) return FALSE; } - if (is_running()) // Gestisce correttamenete le maschere chiuse - { - get_mask_fields(); - _next_fld = DLG_NULL; - } return TWindow::stop_run(key); } @@ -874,7 +543,7 @@ bool TMask::on_key( { if (_handler) { - bool cont = _handler(*this, key); + const bool cont = _handler(*this, key); if (!cont) return FALSE; } @@ -886,36 +555,46 @@ bool TMask::on_key( case K_ESC: stop_run(key); break; - case K_UP: - case K_BTAB: - case K_SHIFT_TAB: - case K_LEFT: - move_focus_field(-1); - break; - case K_DOWN: - case K_TAB: - case K_RIGHT: - case K_ENTER: - move_focus_field(+1); - break; case K_PREV: - next_page(-1); + if (fld(_focus).on_key(K_TAB)) + next_page(-1); break; case K_NEXT: - next_page(+1); + if (fld(_focus).on_key(K_TAB)) + next_page(+1); + break; + case K_F1: +#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT + if (fexist("prassi.hlp")) + { + struct MULTIGUY + { + UINT mkSize; + BYTE mkKeylist; + char mkKeyphrase[16]; + } mk; + + TFilename topic(source_file()); topic.ext(""); + mk.mkSize = sizeof(MULTIGUY); + mk.mkKeylist = 'M'; + strcpy(mk.mkKeyphrase, topic); + + TFilename hlp("prassi.hlp"); + const TString16 mod(topic.left(2)); + if (mod != "ba") hlp.insert(mod, 0); + + HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); + WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); + next_page(0); + } +#endif break; case K_F12: - message_box("Lettura = %ld\n" - "Creazione = %ld\n" - "Inizializzazione = %ld\n" -#ifdef DBG - "Allocazioni = %lu\n" -#endif - , _total_time-_build_time, _build_time, _init_time -#ifdef DBG - , _alloc_count -#endif - ); + post_error_message(format("Lettura = %ld\n" + "Creazione = %ld\n" + "Inizializzazione = %ld\n", + _total_time-_build_time, _build_time, _init_time), + 1); break; default: if (key > K_CTRL) @@ -924,29 +603,26 @@ bool TMask::on_key( if (key >= K_F1 && key <= K_F12) { const int page = key - K_F1; - if (page < _pages) - show_page(key - K_F1); + if (page < _pages && fld(_focus).on_key(K_TAB)) + show_page(page); } else { - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); - if (f.class_id() != CLASS_BUTTON_FIELD || !f.active()) continue; - TButton_field& b = (TButton_field&)f; - if (b.virtual_key() == key) + if (f.class_id() == CLASS_BUTTON_FIELD && f.active()) { - bool ok = b.dlg() == DLG_CANCEL || b.dlg() == DLG_QUIT || b.dlg() == DLG_F9; - if (!ok) ok = test_focus_change(b.win()); - if (ok) + TButton_field& b = (TButton_field&)f; + if (b.virtual_key() == key) + { f.on_key(K_SPACE); - break; - } + break; + } + } } } } - else - return fld(_focus).on_key(key); } return TRUE; @@ -959,28 +635,31 @@ bool TMask::on_dirty(TMask_field&) TMask_field* TMask::parse_field(TScanner& scanner) -{ - if (scanner.key() == "ST") return new TEdit_field(this); - if (scanner.key() == "ZO") return new TZoom_field(this); - if (scanner.key() == "NU") return new TReal_field(this); - if (scanner.key() == "DA") return new TDate_field(this); - if (scanner.key() == "BO") return new TBoolean_field(this); - if (scanner.key() == "LI") return new TList_field(this); - if (scanner.key() == "BU") return new TButton_field(this); - if (scanner.key() == "TE") return new TMask_field(this); - if (scanner.key() == "RA") return new TRadio_field(this); - if (scanner.key() == "GR") return new TGroup_field(this); - if (scanner.key() == "SP") +{ + const TString& k = scanner.key(); + if (k == "ST") return new TEdit_field(this); + if (k == "NU") return new TReal_field(this); + if (k == "DA") return new TDate_field(this); + if (k == "BO") return new TBoolean_field(this); + if (k == "TE") return new TText_field(this); + if (k == "BU") return new TButton_field(this); + if (k == "GR") return new TGroup_field(this); + if (k == "LI") return new TList_field(this); + if (k == "RA") return new TRadio_field(this); + if (k == "ME") return new TMemo_field(this); + if (k == "ZO") return new TZoom_field(this); +/* Guy + if (k == "BR") return new TBrowsefile_field(this); +*/ + if (k == "SP") { _sheets++; return new TSheet_field(this); } - if (scanner.key() == "BR") return new TBrowsefile_field(this); - if (scanner.key() == "ME") return new TMemo_field(this); return NULL; } - + // @doc EXTERNAL // @mfunc Legge la pagina dal file @@ -996,7 +675,7 @@ WINDOW TMask::read_page( static int tooly; static RCT rect; - TString80 title(scanner.string()); + TString title(scanner.string()); RCT r; if (toolwin()) @@ -1008,7 +687,7 @@ WINDOW TMask::read_page( { scanner.rectangle(r); if (toolbar) - { + { tooly = r.top; } else @@ -1017,94 +696,72 @@ WINDOW TMask::read_page( else r = rect; } } - + + bool orecchie = _pagewin[0] != NULL_WIN || toolwin(); + if (!orecchie && !toolbar) + { + const streampos pos = scanner.tellg(); + const TString& l = scanner.line(); + while (l != "EN" && l.not_empty()) + { + if (l == "PA") + { + orecchie = TRUE; + break; + } + scanner.line(); + } + scanner.seekg(pos); + } + WINDOW w; - if (toolbar || toolwin()) { - w = create(0, r.top, 0, toolbar ? 0 : tooly, - title, toolbar ? 0 : WSF_INVISIBLE, W_PLAIN); + w = create_interface(NULL_WIN, 0, r.top, 0, toolbar ? 0 : tooly, title, this, orecchie); } - else + else { - w = create(r.left, r.top, r.right, r.bottom, - title, WSF_CLOSE | WSF_INVISIBLE, WD_MODAL); + w = create_interface(NULL_WIN, r.left, r.top, r.right, r.bottom, title, this, orecchie); } while (scanner.popkey() != "EN") { - TMask_field* f = parse_field(scanner); #ifdef DBG if (f == NULL) - { + { const int f = fields(); - TString256 e("Unknown control at pos."); e << f; - if (f) e << ". Last good was " << fld(f-1).dlg() << ": " << fld(f-1).prompt(); - fatal_box(e); + TString e("Unknown control at position "); e << f; + if (f > 0) e << ".\nLast good one was " << fld(f-1).dlg() << ": " << fld(f-1).prompt(); + yesnofatal_box(e); + while (scanner.popkey() != "EN"); } #endif - - const long start = clock(); - - f->construct(scanner, w); - _field.add(f); - - if (toolbar) - f->set_back_color(TOOL_BACK_COLOR); - - _build_time += clock()-start; - + + if (f != NULL) + { + const long start = clock(); + + f->construct(scanner, w); + _field.add(f); + + _build_time += clock()-start; + } } - set_win(NULL_WIN); return w; } -// @doc EXTERNAL - -// @mfunc Ritorna la posizione del primo campo attivo nella direzione specificata -// -// @rdesc Ritorna il primo campo attivo -int TMask::find_first_field( - WINDOW w, // @parm handle della finestra (pagina) nel quale cercare - int dir) const // @parm Direzione di ricerca. Puo' assumere i valori: - // - // @flag +1 | Direzione in avanti - // @flag -1 | Direzione in dietro +bool TMask::check_current_field() const { - const int last = fields()-1; - const int fi = (dir > 0) ? 0 : last; - const int la = last-fi; - for (int i = fi; i != la; i += dir) + bool ok = TRUE; + if (_focus >= 0) { - const TMask_field& f = fld(i); - if (f.parent() == w && f.active()) break; - } - return i; -} - - -bool TMask::check_current_page() -{ - if (!test_focus_change()) - return FALSE; - /* - - if (sheets() > 0) - return TRUE; - - const int last = fields(); - const WINDOW page = win(); - - for (int i = 0; i < last; i++) - { - TMask_field& f = fld(i); - if (f.parent() == page && f.active() && f.on_key(K_ENTER) == FALSE) - return FALSE; - } - */ - return TRUE; + TMask_field& ff = fld(_focus); + if (ff.focusdirty()) + ok = ff.on_key(K_TAB); + } + return ok; } // @doc EXTERNAL @@ -1124,9 +781,6 @@ void TMask::next_page( if (p != 0) { - if (check_current_page() == FALSE) // New style - return; - const int k = (p < 1000) ? _page+p : p-1000; if (k < 0 || k >= _pages || !page_enabled(k)) { @@ -1138,21 +792,32 @@ void TMask::next_page( if (_page != prev) { - const WINDOW w = _pagewin[_page]; - xvt_vobj_set_visible(w, TRUE); + xvt_vobj_set_visible(win(), TRUE); if (prev >= 0) - { xvt_vobj_set_visible(_pagewin[prev], FALSE); - _focus = find_first_field(w, +1); - } } + + TMask_field& ff = fld(_focus); + if (ff.parent() != win() || !ff.active()) + { + _focus = find_first_active(win()); + if (_focus < 0 && toolwin() != NULL_WIN) + _focus = find_first_active(toolwin()); + } - set_focus(); + if (_focus >= 0) + { + TMask_field& ff = fld(_focus); + if (ff.active()) + ff.highlight(); + } + + TWindow::set_focus(); } void TMask::show_page(int p) { - CHECKD(p >= 0 && p < _pages, "Pagina del cazzo", p); + CHECKD(p >= 0 && p < _pages, "Pagina errata ", p); next_page(1000 + p); } @@ -1160,27 +825,20 @@ void TMask::reset(short fld_id) { if (fld_id <= 0) { - for (int f = 0; f < fields(); f++) + const int gr = -fld_id; + for (int f = fields()-1; f >= 0; f--) { TMask_field& c = fld(f); - c._flags.dirty = c._flags.focusdirty = FALSE; - c.reset(); + if (gr == 0 || c.in_group(gr)) + { + c._flags.dirty = c._flags.focusdirty = FALSE; + c.reset(); + } } } else field(fld_id).reset(); } - -void TMask::undo(short fld_id) -{ - if (fld_id < 1) - { - for (int f = 0; f < fields(); f++) - fld(f).undo(); - } else field(fld_id).undo(); -} - - const TString& TMask::get(short fld_id) const { const TString& s = field(fld_id).get(); @@ -1279,7 +937,7 @@ void TMask::enable( if (fld_id <= 0) { const int gr = -fld_id; - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) @@ -1292,21 +950,32 @@ void TMask::enable( void TMask::enable_default(short fld_id) { - if (fld_id < 1) + if (fld_id <= 0) { - for (int i = 0; i < fields(); i++) - fld(i).enable_default(); - } else field(fld_id).enable_default(); + const int gr = -fld_id; + for (int i = fields()-1; i >= 0; i--) + { + TMask_field& f = fld(i); + if (gr == 0 || f.in_group(gr)) + f.enable_default(); + } + } + else + field(fld_id).enable_default(); } byte TMask::num_keys() const { word max = 0; - for (int i = 0; i < fields(); i++) - { - word k = fld(i).last_key(); - if (k > max) max = k; + for (int i = fields()-1; i >= 0; i--) + { + TMask_field& f = fld(i); + if (f.is_editable()) + { + word k = ((TEditable_field&)f).last_key(); + if (k > max) max = k; + } } return max; } @@ -1322,17 +991,21 @@ void TMask::enable_key( // @flag FALSE | Disabilita il campo { - for (int i = 0; i < fields(); i++) - if (fld(i).in_key(key)) + for (int i = fields()-1; i >= 0; i--) + { + TMask_field& f = fld(i); + if (f.in_key(key)) { if (on) { - fld(i).enable_default(); - if (!fld(i).shown()) - fld(i).show_default(); + f.enable_default(); + if (!f.shown()) + f.show_default(); } - else fld(i).disable(); + else + f.disable(); } + } } // @doc EXTERNAL @@ -1340,7 +1013,7 @@ void TMask::enable_key( // @mfunc Ritorna il l'identificatore di un campo della chiave

// // @rdesc Ritorna l'identificatore del campo cercato -short TMask::get_key_field( +TEditable_field* TMask::get_key_field( byte key, // @parm Chiave di cui controllare l'esistenza bool first) const // @parm Indica se la ricerca dev partire dell'inizio. Assume i valori: // @@ -1350,38 +1023,35 @@ short TMask::get_key_field( static int last = 0; if (first) last = 0; - - for (int i = last; i < fields(); i++) - { - if (fld(i).in_key(key)) + + const int max = fields(); + for (int i = last; i < max; i++) + { + TMask_field& f = fld(i); + if (f.in_key(key)) { last = i+1; - return fld(i).dlg(); + return (TEditable_field*)&f; } } - return -1; + return NULL; } bool TMask::key_valid(int key) const { - for (short f = 0; f < fields(); f++) + const int max = fields(); + for (short f = 0; f < max; f++) { TMask_field& c = fld(f); - if (c.required() && c.shown() && c.in_key(key)) + if (c.is_editable() && c.shown()) { - const TString & value = c.get(); - if (c.class_id() == CLASS_REAL_FIELD) + TEditable_field& e = (TEditable_field&)c; + if (e.required() && e.in_key(key)) { - real z(value); - if (z.is_zero()) - { - c.reset(); + if (e.empty()) return FALSE; - } - } - if (value.empty()) - return FALSE; + } } } return TRUE; @@ -1403,7 +1073,7 @@ void TMask::show( if (fld_id <= 0) { const int gr = -fld_id; - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (gr == 0 || f.in_group(gr)) @@ -1423,44 +1093,50 @@ void TMask::show_default( { if (fld_id <= 0) { - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) fld(i).show_default(); } else field(fld_id).show_default(); } -void TMask::autoload(const TRelation* r) +void TMask::autoload(const TRelation& r) { - const int max = fields(); - for (int i = 0; i < max; i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); - if (f.field() != NULL) - f.autoload(r); - } + if (f.is_editable()) + ((TEditable_field&)f).autoload(r); + } } -void TMask::autosave(TRelation* r) const +void TMask::autosave(TRelation& r) const { - const int max = fields(); - for (int i = 0; i < max; i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); - const TFieldref* fr =f.field(); - if (fr != NULL) + if (f.is_editable()) { - if (f.shown() || *fr->read(r) == '\0') - f.autosave(r); - } + TEditable_field& e = (TEditable_field&)f; + if (e.field() != NULL) + { + bool save = f.shown(); + if (!save) + { + e.autoload(r); + save = f.empty(); + } + if (save) + e.autosave(r); + } + } } } void TMask::on_firm_change() { - TString16 firm; firm << main_app().get_firm(); - - for (int i = 0; i < fields(); i++) + TString firm; firm << main_app().get_firm(); + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); if (f._flags.firm) @@ -1477,11 +1153,41 @@ void TMask::on_idle() { if (_focus >= 0 && _focus < fields()) { - const word acqua = fld(_focus).class_id(); - if (acqua == CLASS_SHEET_FIELD) + if (fld(_focus).is_operable()) { - TSheet_field& s = (TSheet_field&)fld(_focus); + TOperable_field& s = (TOperable_field&)fld(_focus); s.on_idle(); + + if (_msg_field > 0) + { + TMask_field& f = field(_msg_field); + _msg_field = 0; + if (_msg_key > 0) + f.on_key(_msg_key); + } + } + if (_error_severity > 0) + { + switch(_error_severity) + { + case 2: + warning_box("%s", (const char*)_error_message); break; + case 3: + error_box("%s", (const char*)_error_message); break; + default: + message_box("%s", (const char*)_error_message); break; + } + _error_severity = 0; + set_focus(); + } + if (_test_fld >= 0) + { + TEditable_field & e = (TEditable_field &) field(_test_fld); + if (!fld(_focus).in_key(e.first_key())) + { + e.test_key_complete(FALSE); + _test_fld = -1; + } } } } @@ -1514,7 +1220,13 @@ void TMask::send_key( else { const int pos = id2pos(to); - if (pos >= 0) fld(pos).on_key(key); + if (pos >= 0) + { + if (_msg_field > 0) + on_idle(); + _msg_field = to; + _msg_key = key; + } #ifdef DBG else yesnofatal_box("Can't send key %u to field %d", key, to); @@ -1524,7 +1236,7 @@ void TMask::send_key( else { const int gr = -to; - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& campo = fld(i); if (campo.in_group(gr)) @@ -1548,8 +1260,10 @@ void TMask::set_handler( // da

, mentre nel secondo viene mandato un // alla maschera corrente -{ - field(fld_id).set_handler(handler); +{ + TMask_field& f = field(fld_id); + CHECKD(f.is_operable(), "Can't set an handler to non-operable field ", fld_id); + ((TOperable_field&)f).set_handler(handler); } void TMask::set_handler(MASK_HANDLER handler) @@ -1562,7 +1276,7 @@ void TMask::set_handler(MASK_HANDLER handler) // @mfunc Aggiunge runtime un campo testo alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_static ( +TMask_field& TMask::add_static ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1573,10 +1287,10 @@ WINDOW TMask::add_static ( // @xref // { - TMask_field* f = new TMask_field(this); - f->construct(id, prompt, x, y, strlen(prompt), _pagewin[page], flags); + TText_field* f = new TText_field(this); + f->construct(id, prompt, x, y, 0, _pagewin[page], flags); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL @@ -1584,7 +1298,7 @@ WINDOW TMask::add_static ( // @mfunc Aggiunge runtime un campo stringa alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_string ( +TEdit_field& TMask::add_string ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1597,36 +1311,38 @@ WINDOW TMask::add_string ( // @xref // { - TEdit_field* f = new TEdit_field(this); + TEdit_field* f = new TEdit_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags, width); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL -// @mfunc Aggiunge runtime un campo lista alla maschera +// @mfunc Aggiunge runtime un campo bottone alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_list ( - short id, // @parm Numero identificatore del campo da aggiungere - int page, // @parm Pagina nel quale aggiungere il campo +TButton_field& TMask::add_button ( + short id, // @parm Numero identificatore del campo da aggiungere + int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo - int x, // @parm Coordinata x (in caratteri) - int y, // @parm Coordinata y (in caratteri) - int dim, // @parm Lunghezza del campo sulla maschera + int x, // @parm Coordinata x (in caratteri) + int y, // @parm Coordinata y (in caratteri) + int dx, // @parm Larghezza del campo (in caratteri, defailt 9) + int dy, // @parm Altezza del campo (in caratteri, default 1) const char* flags, // @parm Flag di controllo del campo (default "") - const char* codes, // @parm tokenstringa con i codici (NULL def.) - const char* items) // @parm tokenstringa con gli items (NULL def.) + short bmpup, // @parm Icona normale + short bmpdn) // @parm Icona premuta - // @xref - // -{ - TList_field* f = new TList_field(this); - f->construct(id, prompt, x, y, dim, _pagewin[page], flags); - f->replace_items(codes,items); + // @xref + // +{ + TButton_field* f = new TButton_field(this); + f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); + if (bmpup > 0) + f->set_bmp(bmpup, bmpdn); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL @@ -1634,7 +1350,7 @@ WINDOW TMask::add_list ( // @mfunc Aggiunge runtime un campo boolean alla maschera // // @rdesc Ritorna il descrittore del campo aggiunto -WINDOW TMask::add_boolean ( +TBoolean_field& TMask::add_boolean ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1648,31 +1364,7 @@ WINDOW TMask::add_boolean ( TBoolean_field* f = new TBoolean_field(this); f->construct(id, prompt, x, y, strlen(prompt), _pagewin[page], flags); _field.add(f); - return f->win(); -} - -// @doc EXTERNAL - -// @mfunc Aggiunge runtime un campo zoom alla maschera -// -// @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_zoom ( - short id, // @parm Numero identificatore del campo da aggiungere - int page, // @parm Pagina nel quale aggiungere il campo - const char* prompt, // @parm Prompt del campo - int x, // @parm Coordinata x (in caratteri) - int y, // @parm Coordinata y (in caratteri) - int dim, // @parm Lunghezza del campo sulla maschera - const char* flags, // @parm Flag di controllo del campo (defailt "") - int width) // @parm Lunghezza totale del campo stringa (default 0) - - // @xref - // -{ - TZoom_field* f = new TZoom_field(this); - f->construct(id, prompt, x, y, dim, _pagewin[page], flags, width); - _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL @@ -1680,7 +1372,7 @@ WINDOW TMask::add_zoom ( // @mfunc Aggiunge runtime un campo numerico alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_number ( +TReal_field& TMask::add_number ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1696,7 +1388,7 @@ WINDOW TMask::add_number ( TReal_field* f = new TReal_field(this); f->construct(id, prompt, x, y, dim, _pagewin[page], flags, ndec); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL @@ -1704,7 +1396,7 @@ WINDOW TMask::add_number ( // @mfunc Aggiunge runtime un campo data alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_date ( +TDate_field& TMask::add_date ( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1718,31 +1410,33 @@ WINDOW TMask::add_date ( TDate_field* f = new TDate_field(this); f->construct(id, prompt, x, y, 10, _pagewin[page], flags); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL -// @mfunc Aggiunge runtime un campo bottone alla maschera +// @mfunc Aggiunge runtime un campo lista alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_button ( - short id, // @parm Numero identificatore del campo da aggiungere - int page, // @parm Pagina nel quale aggiungere il campo +TList_field& TMask::add_list ( + short id, // @parm Numero identificatore del campo da aggiungere + int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo - int x, // @parm Coordinata x (in caratteri) - int y, // @parm Coordinata y (in caratteri) - int dx, // @parm Larghezza del campo (in caratteri, defailt 9) - int dy, // @parm Altezza del campo (in caratteri, default 1) - const char* flags) // @parm Flag di controllo del campo (default "") + int x, // @parm Coordinata x (in caratteri) + int y, // @parm Coordinata y (in caratteri) + int dim, // @parm Lunghezza del campo sulla maschera + const char* flags, // @parm Flag di controllo del campo (default "") + const char* codes, // @parm tokenstring con i codici (NULL def.) + const char* items) // @parm tokenstring con gli items (NULL def.) - // @xref - // + // @xref + // { - TButton_field* f = new TButton_field(this); - f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); + TList_field* f = new TList_field(this); + f->construct(id, prompt, x, y, dim, _pagewin[page], flags); + f->replace_items(codes,items); _field.add(f); - return f->win(); + return *f; } // @doc EXTERNAL @@ -1750,7 +1444,7 @@ WINDOW TMask::add_button ( // @mfunc Aggiunge runtime un campo radio button alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_radio( +TRadio_field& TMask::add_radio( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1768,7 +1462,32 @@ WINDOW TMask::add_radio( f->replace_items(codes, items); f->construct(id, prompt, x, y, dx, _pagewin[page], flags, dx); _field.add(f); - return ((TMask_field*)f)->win(); + return *f; +} + + +// @doc EXTERNAL + +// @mfunc Aggiunge runtime un campo zoom alla maschera +// +// @rdesc Ritorna l'handle del campo creato +TZoom_field& TMask::add_zoom ( + short id, // @parm Numero identificatore del campo da aggiungere + int page, // @parm Pagina nel quale aggiungere il campo + const char* prompt, // @parm Prompt del campo + int x, // @parm Coordinata x (in caratteri) + int y, // @parm Coordinata y (in caratteri) + int dim, // @parm Lunghezza del campo sulla maschera + const char* flags, // @parm Flag di controllo del campo (defailt "") + int width) // @parm Lunghezza totale del campo stringa (default 0) + + // @xref + // +{ + TZoom_field* f = new TZoom_field(this); + f->construct(id, prompt, x, y, dim, _pagewin[page], flags, width); + _field.add(f); + return *f; } // @doc EXTERNAL @@ -1776,7 +1495,7 @@ WINDOW TMask::add_radio( // @mfunc Aggiunge runtime un campo memo alla maschera // // @rdesc Ritorna l'handle del campo creato -WINDOW TMask::add_memo( +TMemo_field& TMask::add_memo( short id, // @parm Numero identificatore del campo da aggiungere int page, // @parm Pagina nel quale aggiungere il campo const char* prompt, // @parm Prompt del campo @@ -1792,12 +1511,12 @@ WINDOW TMask::add_memo( TMemo_field* f = new TMemo_field(this); f->construct(id, prompt, x, y, dy, _pagewin[page], flags, dx); _field.add(f); - return ((TMask_field*)f)->win(); + return *f; } // @doc EXTERNAL -// @mfunc Permette di salvare il file di salvataggio +// @mfunc Salva i valori dei campi della maschera sul file di salvataggio // // @rdesc Ritorna il risultato dell'operazione: // @@ -1808,16 +1527,17 @@ bool TMask::save( // ad uno gia' esistente (FALSE, default). { - FILE* f = fopen((const char *) _workfile, append ? "a" : "w"); + FILE* f = fopen(_workfile, append ? "a" : "w"); if (f == NULL) return yesnofatal_box("Non posso aprire %s ", (const char*) _workfile); - - for (int i = 0; i < fields(); i++) - { - const short id = fld(i).dlg(); - if (id >= 100) - fprintf(f, "%d|%s\n", id, (const char*) fld(i).get()); + + const int max = fields(); + for (int i = 0; i < max; i++) + { + TMask_field& c = fld(i); + if (c.is_editable()) + fprintf(f, "%d|%s\n", c.dlg(), (const char*)c.get()); } fprintf(f, "[EOM]\n"); fclose(f); @@ -1827,7 +1547,7 @@ bool TMask::save( // @doc EXTERNAL -// @mfunc Permette di leggere il file di salvataggio +// @mfunc Legge i valori dei campi della maschera da file di salvataggioo // // @rdesc Ritorna il risultato dell'operazione: // @@ -1840,23 +1560,20 @@ bool TMask::load( // @flag FALSE | Comincia la lettura dalla posizione corrente dell'offset { - FILE* f = fopen((const char *) _workfile, "r"); + FILE* f = fopen(_workfile, "r"); if (f == NULL) return FALSE; if (reset) _lastpos = 0; fseek(f, _lastpos, SEEK_SET); TToken_string t(256); - char s[256]; - while (fgets(s, 255, f) != NULL && strncmp(s, "[EOM]", 5) != 0) + while (fgets((char*)(const char*)t, t.size(), f) != NULL && t != "[EOM]") { - if (*s) s[strlen(s) - 1] = '\0'; - t = s; - const short id = t.get_int(); - if (id >= 100) + if (t.not_empty()) { - const int pos = id2pos(id); + t.cut(t.len() - 1); + const int pos = id2pos(t.get_int(0)); if (pos >= 0) fld(pos).set(t.get()); - } + } } _lastpos = ftell(f); fclose(f); @@ -1864,6 +1581,33 @@ bool TMask::load( } +// @doc EXTERNAL + +// @mfunc Copia i valori dei campi dalla maschera

+// +void TMask::copy_values( + const TMask& m) // @parm Maschera sorgente + +{ + reset(); + const int nfields = fields(); + for (int i = 0; i < nfields; i++) + { + TMask_field& dest_field = fld( i ); + + if (dest_field.is_editable() ) + { + const int pos = m.id2pos(dest_field.dlg()); + if (pos >= 0) + { + const TMask_field& source_field = m.fld(pos); + dest_field.set( source_field.get( ) ); + } + } + } +} + + const char* TMask::get_caption() const { char* title = &__tmp_string[512]; @@ -1877,6 +1621,14 @@ void TMask::set_caption(const char* c) xvt_vobj_set_title(_pagewin[p], (char*)c); } +void TMask::post_error_message(const char* msg, int sev) +{ + CHECK(sev > 0 && msg, "Bad error message posted"); + if (_error_severity > 0) // C'e' gia' un messaggio d'errore in coda + on_idle(); + _error_message = msg; + _error_severity = sev; +} // @doc EXTERNAL @@ -1888,12 +1640,15 @@ void TMask::set_exchange( const real nuo = (n.sign() <= 0) ? _exchange : n; main_app().begin_wait(); - for (int i = 0; i < fields(); i++) + for (int i = fields()-1; i >= 0; i--) { TMask_field& f = fld(i); - const word id = f.class_id(); - if (id == CLASS_SHEET_FIELD || id == CLASS_REAL_FIELD && f.exchangeable()) - f.exchange(show_value, nuo); + if (f.is_operable()) + { + TOperable_field& o = (TOperable_field&)f; + if (o.exchangeable() || o.is_kind_of(CLASS_SHEET_FIELD)) + o.exchange(show_value, nuo); + } } _exchange = nuo; // Update current exchange diff --git a/include/mask.h b/include/mask.h index 06398c140..71b6b35ef 100755 --- a/include/mask.h +++ b/include/mask.h @@ -22,12 +22,11 @@ typedef bool (*MASK_HANDLER)(TMask& mask, KEY key); // @enum Modalita' di utilizzo della maschera corrente enum TMaskmode { NO_MODE, // @emem Nessun modo - MODE_INS , // @emem Modalita' di inserimento dati - MODE_MOD , // @emem Modalita' di modifca dati - MODE_VIS , // @emem Modalita' di visualizzaione dati MODE_QUERY, // @emem Modalita' di richiesta chiave - MODE_QUERYINS }; // @emem Modalita' di richiesta chiave e inserimento dati - + MODE_QUERYINS, // @emem Modalita' di richiesta chiave e inserimento dati + MODE_INS , // @emem Modalita' di inserimento dati + MODE_MOD // @emem Modalita' di modifca dati +}; // @doc EXTERNAL @@ -37,18 +36,19 @@ enum TMaskmode { class TMask : public TWindow { // @author:(INTERNAL) Guido + + // @access Protected Member + protected: + + // @ccost:(INTERNAL) MAX_PAGES | 16 | Massimo numero di pagine nella maschera + enum { MAX_PAGES = 16 }; // @access:(INTERNAL) Private Member + private: - // @ccost:(INTERNAL) MAX_PAGES | 12 | Massimo numero di pagine nella maschera - enum { MAX_PAGES = 12 }; // @cmember:(INTERNAL) Windows delle pagine WINDOW _pagewin[MAX_PAGES+1]; - // @cmember:(INTERNAL) Windows per pgup/pgdn - WINDOW _pagepag[MAX_PAGES]; - // @cmember:(INTERNAL) Windows di numeri pagina - WINDOW _pagetag[MAX_PAGES]; - + // @cmember:(INTERNAL) Numero di pagine della maschera int _pages; // @cmember:(INTERNAL) Pagina corrente @@ -63,13 +63,9 @@ class TMask : public TWindow // @cmember:(INTERNAL) Primo controllo che deve ricevere il focus int _first_focus; - // @cmember:(INTERNAL) Controllo che possiede il focus + int _focus; - // @cmember:(INTERNAL) Controllo che deve ricevere il focus - int _next_fld; - // @cmember:(INTERNAL) Numero di sheet contenuti nella maschera - int _sheets; // @cmember:(INTERNAL) Puntatore allo sheet che contiene la maschera (puo' essere NULL) TSheet_field* _sheet; @@ -80,7 +76,6 @@ class TMask : public TWindow TFilename _source_file; // @cmember:(INTERNAL) Nome del file di salvataggio in cui sono scaricati i valori della maschera TFilename _workfile; - // @cmember:(INTERNAL) Ultimo offset letto nel file di salvataggio long _lastpos; @@ -88,6 +83,9 @@ class TMask : public TWindow real _exchange; // @cmember:(INTERNAL) Controlla se la maschera deve fare i controlli iniziali di validita' dei campi bool _should_check; + + int _error_severity; + TString _error_message; // @cmember:(INTERNAL) Tempo totale di caricamento della maschera long _total_time; @@ -96,17 +94,17 @@ class TMask : public TWindow // @cmember:(INTERNAL) Tempo di inizializzazione della maschera long _init_time; + // @cmember:(INTERNAL) numeri pagina + TArray _pagetag; + + // @cmember:(INTERNAL) identificatore del campo da testare per l'autopremimento + short _test_fld; + // @access Protected Member protected: - // @cmember Ritorna la finestra della pagina corrente (Usare con attenzione) - WINDOW win() const - { return _page < 0 ? _pagewin[0] : _pagewin[_page]; } - // @cmember Ritorna il numero di campi nella finestra - int find_field_win(WINDOW win) const; - - // @cmember Aggiorna i controlli a video con i valori iniziali della maschera - void set_mask_fields() const; + // @cmember:(INTERNAL) Numero di sheet contenuti nella maschera + int _sheets; // @cmember Legge i controlli relativi ad un campo void load_checks() const; @@ -121,65 +119,75 @@ protected: WINDOW read_page(TScanner& scanner, bool toolbar = FALSE); // @cmember Legge la maschera da file void read_mask(const char* name, int num, int max); - // @cmember Permette di aggiungere sulla maschera tutti i bottoni per la - // navigazione tra le pagine - void add_buttons(); + + // @cmember Aggiunge i tags ad una pagina + void add_tag_button(byte pag, TToken_string& tags, byte sel); + // @cmember Aggiunge alla maschera tutti i bottoni per la navigazione tra le pagine + void add_tag_buttons(TToken_string& tags); + + // @cmember Ritorna il numero del primo campo attivo della pagina con finestra

+ int find_first_active(WINDOW w) const; // @cmember Ritorna il numero della finestra padre del campo

int find_parent_page(const TMask_field& f) const; - // @cmember Ritorna la posizione del primo campo attivo nella direzione specificata - int find_first_field(WINDOW w, int dir) const; - // @cmember Ritorna il prossimo campo attivabile - int find_active_field(int first, int dir) const; - // @cmember Controlla tutti i campi della pagina corrente - bool check_current_page(); + // @cmember Esegue i check del campo corrente + bool check_current_field() const; // @cmember Mostra la prossima/precedente pagina void next_page(int p); // @cmember Ritorna il numero della pagina corrente int curr_page() const { return _page; } - - // @cmember Controlla se e' possibile dare il focus alla finestra

(TRUE se possibile) - bool test_focus_change(WINDOW next = NULL_WIN); - // @cmember Funzione chiamata ogni volta che arriva un evento e lo gestisce - void control_handler(EVENT* ep); - // @cmember Gestisce gli eventi XVT diretti alla pagina corrente della maschera - virtual void handler(WINDOW win, EVENT* ep); + // @cmember Costruttore (crea una maschera vuota\) + TMask() { init_mask();} // @access Public Member public: // @cmember Costruttore (crea la maschera leggendo la descrizione dal file .msk) - TMask(const char* name, int num = 0, int max = MAX_PAGES); + TMask(const char* title, int num = 0, int max = MAX_PAGES); // @cmember Costruttore (crea una maschera vuota con i parametri dati) TMask(const char* title, int pages, int cols, int rows, int xpos = -1, int ypos = -1); // @cmember Distruttore virtual ~TMask(); + + // @cmember Ritorna l'identificatore della classe maschera + virtual word class_id() const; + + // @cmember Ritorna TRUE se la maschera deriva dalla classe

+ virtual bool is_kind_of(word c) const; + + // @cmember Ritorna la finestra della pagina corrente (Usare con attenzione) + WINDOW win() const + { return _page < 0 ? _pagewin[0] : _pagewin[_page]; } // @cmember Ritorna il nome del file contentente la maschera const TFilename& source_file() const { return _source_file; } + + // @cmember Aggiunge alla maschera tutti i bottoni Pag. n + void add_default_tag_buttons(); // @cmember Aggiunge runtime un campo testo alla maschera - WINDOW add_static (short id, int page, const char* prompt, int x, int y, const char* flags = ""); + TMask_field& add_static (short id, int page, const char* prompt, int x, int y, const char* flags = ""); // @cmember Aggiunge runtime un campo stringa alla maschera - WINDOW add_string (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0); + TEdit_field& add_string (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0); + // @cmember Aggiunge runtime un campo numerico alla maschera - WINDOW add_number (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int ndec = 0); + TReal_field& add_number (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int ndec = 0); // @cmember Aggiunge runtime un campo data alla maschera - WINDOW add_date (short id, int page, const char* prompt, int x, int y, const char* flags = ""); + TDate_field& add_date (short id, int page, const char* prompt, int x, int y, const char* flags = ""); // @cmember Aggiunge runtime un campo bottone alla maschera - WINDOW add_button (short id, int page, const char* prompt, int x, int y, int dx = 9, int dy = 1, const char* flags = ""); + TButton_field& add_button (short id, int page, const char* prompt, int x, int y, int dx = 9, int dy = 1, const char* flags = "", short bmpup = 0, short bmpdn = 0); // @cmember Aggiunge runtime un campo boolean alla maschera - WINDOW add_boolean (short id, int page, const char* prompt, int x, int y, const char* flags = ""); + TBoolean_field& add_boolean (short id, int page, const char* prompt, int x, int y, const char* flags = ""); // @cmember Aggiunge runtime un campo radio button alla maschera - WINDOW add_radio(short id, int page, const char* prompt, int x, int y, int dx, const char* codes, const char* items, const char* flags = ""); + TRadio_field& add_radio(short id, int page, const char* prompt, int x, int y, int dx, const char* codes, const char* items, const char* flags = ""); // @cmember Aggiunge runtime un campo memo alla maschera - WINDOW add_memo (short id, int page, const char* prompt, int x, int y, int dx = 78, int dy = 4, const char* flags = ""); + TMemo_field& add_memo (short id, int page, const char* prompt, int x, int y, int dx = 78, int dy = 4, const char* flags = ""); // @cmember Aggiunge runtime un campo zoom alla maschera - WINDOW add_zoom (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0); + TZoom_field& add_zoom (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0); // @cmember Aggiunge runtime un campo lista alla maschera - WINDOW add_list (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", const char* codes = NULL, const char* items = NULL); + TList_field& add_list (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", const char* codes = NULL, const char* items = NULL); // @cmember Ritorna il numero di campi della maschera int fields() const @@ -194,6 +202,13 @@ public: // @cmember Ritorna la modalita' corrente di utilizzo della maschera int mode() const { return _mode; } + + // @cmember Setta la chiave da testare per l'autopremimento + void set_test_field(int id) + { if (_test_fld < 0) _test_fld = id; } + + void set_focus_field(short id); + void notify_focus_field(short id); // @cmember Setta il valore attuale della valuta void set_exchange(bool show_value, const real& nuo); @@ -203,8 +218,8 @@ public: // @cmember Controlla i campi di una maschera (TRUE se tutti validi) bool check_fields(); - // @cmember Mette il contenuto dei campi a video in stringhe interne - void get_mask_fields(); + // @cmember Esegue il check e i messaggi sul campo

della maschera + virtual void check_field( short fld_id ); // @cmember Forza la chiusura della maschera virtual bool stop_run(KEY key); // @cmember Controlla se la maschera puo' essere chiusa (TRUE se puo' esserlo) @@ -219,9 +234,6 @@ public: // @cmember Converte un identificatore di campo nella sua posizione int id2pos(short id) const; - // @cmember Ritorna l'id del campo che sta prendendo il focus, DLG_NULL se non esiste - short next_fld() const - { return _next_fld;} // @cmember Ritorna il campo i-esimo della maschera TMask_field& fld(int i) const { return (TMask_field&)_field[i]; } @@ -255,15 +267,11 @@ public: // @cmember Indica quale campo deve ricevere per primo il focus nella maschera int first_focus(short id); - // @cmember Setta il focus al campo corrente - void set_focus(); - // @cmember Muove il focus al prossimo o al precedente controllo valido - void move_focus_field(int num); - // @cmember Setta il focus al campo la cui finestra e'

- void set_focus_win(WINDOW win, bool force); + // @cmember Ritorna il numero del controllo che possiede il focus - TMask_field& focus_field() const - { return fld(_focus); } + TOperable_field& focus_field() const + { return (TOperable_field&)fld(_focus); } + // @cmember Disabilita la lettura dei check della maschera void disable_starting_check() { _should_check = FALSE;} @@ -282,7 +290,7 @@ public: void disable(short fld_id) { enable(fld_id, FALSE); } // @cmember Riporta il cmpo allo stato di abilitazione iniziale - void enable_default(short fld_id = -1); + void enable_default(short fld_id = 0); // @cmember Forza la visualizzazione della pagina p void show_page(int p); @@ -302,28 +310,26 @@ public: void disable_key(byte key) { enable_key(key, FALSE); } // @cmember Ritorna il l'identificatore di un campo della chiave

- short get_key_field(byte key, bool first) const; + TEditable_field* get_key_field(byte key, bool first) const; // @cmember Controlla se la chiave

ha un valore significativo // (TRUE se il valore e' valido) bool key_valid(int key) const; - // @cmember Permette di mostrare/nascondere un campo + // @cmember Permette di mostrare/nascondere un campo (chiama ) virtual void show(short fld_id = -1, bool on = TRUE); // @cmember Permette di nascondere un campo (chiama ) - void hide(short fld_id = -1) + void hide(short fld_id = 0) { show(fld_id, FALSE); } // @cmember Rimette lo stato di default del campo - void show_default(short fld_id = -1); + void show_default(short fld_id = 0); - // @cmember Rimette lo stato di default del campo - void reset(short fld_id = -1); - // @cmember Riporta il valori originali nel campo - void undo(short fld_id = -1); + // @cmember Azzera il campo + void reset(short fld_id = 0); // @cmember Legge, dalla relazione

, i valori del campo con specifica FIELD - void autoload(const TRelation*); + void autoload(const TRelation& r); // @cmember Scrive, dalla relazione

, i valori del campo con specifica FIELD - void autosave(TRelation*) const; + void autosave(TRelation& r) const; // @cmember Permette di mandare un tasto ad un campo void send_key(KEY key, short id, TMask_field* from = NULL); @@ -334,10 +340,12 @@ public: // @cmember Permette di settare il nome del file di salvataggio void set_workfile(const char* workfile) { _workfile = workfile; _lastpos = 0L;} - // @cmember Permette di salvare il file di salvataggio + // @cmember Salva i valori dei campi della maschera sul file di salvataggio bool save(bool append = FALSE) const; - // @cmember Permette di leggere il file di salvataggio + // @cmember Legge i valori dei campi della maschera da file di salvataggio bool load(bool reset = FALSE); + // @cmember Copia i valori dei campi dalla maschera

+ void copy_values(const TMask &m); // @cmember Ritorna il primo campo dirty short dirty() const; @@ -371,15 +379,16 @@ public: virtual const char* get_caption() const; // @cmember Setta il titolo della maschera virtual void set_caption(const char* c); + + // @cmember Mostra un messaggio d'errore appena possibile + void post_error_message(const char* msg, int severity); - // @cmember Viene eseguita se il campo viene modificato??? - virtual bool on_dirty(TMask_field& c ); + // @cmember Viene eseguita se il campo viene modificato + virtual bool on_dirty(TMask_field& c); // @cmember Ritorna la finestra della toolbar WINDOW toolwin() const { return _pagewin[MAX_PAGES]; } - - }; #endif // __MASK_H diff --git a/include/maskfld.cpp b/include/maskfld.cpp index 0b52aee87..eabf3a3b2 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -20,8 +21,6 @@ #include -HIDDEN TString256 fpark; - // @doc INTERNAL // @mfunc Elimina gli spazi iniziali e/o finali da un stringa @@ -37,16 +36,14 @@ HIDDEN void smart_trim( { switch (mode) { - case 1 : - s.ltrim(); break; - case 2 : - s.rtrim(); break; - case 3 : - s.trim(); break; - default: - break; + case 1: s.ltrim(); break; + case 2: s.rtrim(); break; + case 3: s.trim(); break; + default: break; } } + + /////////////////////////////////////////////////////////// // Field Flags /////////////////////////////////////////////////////////// @@ -71,7 +68,7 @@ TMask_field::TField_Flags::TField_Flags() char TMask_field::TField_Flags::update(const char* f) { for (const char* s = f; *s; s++) - switch(toupper(*s)) + switch(*s) { case '#': trim = 2; break; @@ -116,56 +113,91 @@ char TMask_field::TField_Flags::update(const char* f) // TMask_field /////////////////////////////////////////////////////////// -int TMask_field::_x; // Position of the field -int TMask_field::_y; -int TMask_field::_width; -TString80 TMask_field::_prompt; +TMask_field::TControl_data TMask_field::_ctl_data; + +void TMask_field::TControl_data::reset() +{ + _dlg = -1; + _x = _y = -1; + _width = 0; + _height = 1; + _size = 0; + _decimals = 0; + _bmp_up = _bmp_dn = 0; + _prompt.cut(0); + _flags.cut(0); + _park.cut(0); +} + 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) + : _mask(m), _ctl(NULL), _groups(NULL) { - _x = -1; - _y = -1; } // Certified 100% TMask_field::~TMask_field() { - if (_field) delete _field; + if (_ctl) delete _ctl; + if (_groups) delete _groups; } // 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::is_kind_of(word cid) const +{ return cid == CLASS_FIELD || TObject::is_kind_of(cid); } // Certified 100% bool TMask_field::ok() const -{ return win() != NULL_WIN && dlg() >= -1; } - +{ return _ctl != NULL; } // Certified 100% void TMask_field::parse_head(TScanner&) {} +short TMask_field::dlg() const +{ + return _ctl ? _ctl->id() : _ctl_data._dlg; +} -// Certified 100% -short TMask_field::atodlg(const char* s) const +void TMask_field::highlight() const +{ +#ifdef DBG + yesnofatal_box("Can't set the focus to non-operable field %d", dlg()); +#endif +} + +void TMask_field::set_focus() const +{ +#ifdef DBG + yesnofatal_box("Can't set the focus to non-operable field %d", dlg()); +#endif +} + + + +// @doc INTERNAL + +// Certified 100% +// @mfunc Converte una stringa in un identificatore di campo. +short TMask_field::atodlg( + const char* s) const // @parm stringa da convertire in numero +// @comm In modo DBG controlla anche che sia un numero valido { 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; + yesnofatal_box("Identificatore non valido nel campo %d: '%s'", _ctl_data._dlg, s); + d = DLG_NULL; } #endif @@ -180,10 +212,10 @@ void TMask_field::construct( const char* prompt, // @parm Prompt del campo int x, // @parm Posizione in x (in caratteri) del campo nella maschera int y, // @parm Posizione in y (in caratteri) del campo nella maschera - int len, // @parm Lunghezza vidibile del campo + int len, // @parm Lunghezza del buffer campo WINDOW parent, // @parm Finestra padre alla quale assegnare il campo const char* flags, // @parm Flags del campo (default "") - int width) // @parm Lunghezza del campo + int width) // @parm Lunghezza a video del campo // @parm TScanner& | scanner | File dal quale leggere leggere le informazioni // @syntax void construct(TScanner& scanner, WINDOW parent); @@ -191,17 +223,35 @@ void TMask_field::construct( // // @comm E' possibile costruire il campo leggendo direttamente dal file, oppure passare alla funzione // tutti i parametri necessari alla definizione del campo stesso -{ - _x = x; _y = y; - _prompt = prompt; - _size = len; - if (class_id() == CLASS_REAL_FIELD) +{ + _ctl_data.reset(); + _ctl_data._x = x; + _ctl_data._y = y; + _ctl_data._prompt = prompt; + _ctl_data._size = len; + switch(class_id()) { + case CLASS_REAL_FIELD: ((TReal_field*)this)->set_decimals(width); - _width = _size; - } - else _width = width < 1 ? _size : width; - _dlg = id; + _ctl_data._width = len; + break; + case CLASS_BUTTON_FIELD: + _ctl_data._height = len; + _ctl_data._width = width <= 0 ? 12 : width; + break; + case CLASS_MEMO_FIELD: + _ctl_data._height = len; + _ctl_data._width = width; + _ctl_data._size = len * width; + break; + default: + _ctl_data._width = width == 0 ? len : width; + break; + } + + _ctl_data._dlg = id; + + _ctl_data._flags = flags; _flags.update(flags); create(parent); @@ -209,221 +259,87 @@ void TMask_field::construct( void TMask_field::construct(TScanner& scanner, WINDOW parent) -{ - _dlg = atodlg(scanner.pop()); +{ + _ctl_data.reset(); + _ctl_data._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); + yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _ctl_data._dlg); scanner.push(); } #endif while(scanner.popkey() != "EN") // END of control parse_item(scanner); + create(parent); } -void TMask_field::set_back_color(COLOR c) const -{ - xvt_set_ctrl_back_color(win(), c); +void TMask_field::set_group(byte group) +{ + if (_groups == NULL) + _groups = new TBit_array; + _groups->set(long(group)); + _groups->set(0L); } + bool TMask_field::parse_item(TScanner& scanner) { if (scanner.key() == "PR") // PROMPT { - _x = scanner.integer(); - _y = scanner.integer(); - _prompt = scanner.string(); + _ctl_data._x = scanner.integer(); + _ctl_data._y = scanner.integer(); + _ctl_data._prompt = scanner.string(); return TRUE; } - if (scanner.key() == "FL") // FLAG + if (scanner.key() == "FL") // FLAGS { 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() == "CU") // CUSTOM DATA - { - _userdata.add(scanner.string()); - 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()); + if (_flags.update(f) == '\0') + _ctl_data._flags << f; return TRUE; } if (scanner.key() == "GR") - { - _groups.set(scanner.line()); - 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 || _nparms > 100) - return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", dlg(), _nparms); -#endif - - for(int i = 0; i < _nparms; i++) - _validate_parms.add(scanner.operand()); - - return TRUE; - } - - if (scanner.key() == "WA") - { - _warning = scanner.string(); + { + if (_groups == NULL) + _groups = new TBit_array; + _groups->set(scanner.line()); + return TRUE; } + NFCHECK("'%s' Token non riconosciuto nel campo %d: %s", + (const char*)scanner.token(), (int)dlg(), (const char*)_ctl_data._prompt); 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% -// @doc EXTERNAL - -// @mfunc Crea la finestra del controllo -// -// @rdesc Ritorna la finestra creata -WINDOW TMask_field::wincreate( - WIN_TYPE ct, // @parm Tipo di finestra da creare - short dx, // @parm Larghezza iniziale della finestra - short dy, // @parm Altezza iniziale della finestra - const char* title, // @parm Titolo della finestra - WINDOW parent, // @parm Finestra padre di quella da creare - long flags) // @parm fleg della finestra -{ - _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 xvt_vobj_get_parent(win()); } - - -// Certified 90% -// @doc EXTERNAL - -// @mfunc Crea il prompt del controllo -// -// @rdesc Ritorna la lunghezza del prompt creato -int TMask_field::create_prompt( - WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo - int width, // @parm Larghezza del controllo - int heigth) // @parm Altezza del controllo -{ - const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; - if (width < 1) width = _prompt.len() - (_prompt[0] == '@' ? 2 : 0); - _prompt.rtrim(); // Could save some bytes - - if (width) - { - const long flags = default_flags() & (~CTL_FLAG_DISABLED); // Static controls shouldn't be grayed - -#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT - const int k = _prompt.find('~'); - if (k >= 0) _prompt[k] = '&'; -#endif - _promptwin = xvt_create_control - ( - wt, - _x, _y, width, heigth, - _prompt, - parent, - flags, - 0L, - -1 - ); - } - if (_x == -1 && _y == -1) - { - _x = 1; - _y = 30; - } - return width; +{ + CHECK(_ctl, "Can't get the parent of a NULL control"); + return _ctl->parent(); } - -// Certified 100% -void TMask_field::destroy() +RCT& TMask_field::get_rect(RCT& r) const { - if (_win) - { xvt_vobj_destroy(_win); _win = NULL_WIN; } - if (_promptwin) - { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } + if (_ctl) _ctl->get_rect(r); + else memset(&r, 0, sizeof(r)); + return r; } - -// Certified 100% -void TMask_field::create(WINDOW parent) +void TMask_field::set_rect(const RCT& r) { - _width = _prompt.len(); - if (_width) - wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); + if (_ctl) _ctl->set_rect(r); } - // Certified 100% // @doc EXTERNAL @@ -434,12 +350,7 @@ void TMask_field::enable( // @flag TRUE | Abilita il campo (default) // @flag FALSE | Disabilita il campo { - const word c = class_id(); - if (c != CLASS_FIELD) - { - xvt_vobj_set_enabled(_win, on); - _flags.enabled = on; - } + _flags.enabled = on; } @@ -461,10 +372,11 @@ void TMask_field::show( // @flag TRUE | Rendere visibile il campo (default) // @flag FALSE | Rendere invisibile il campo { - xvt_vobj_set_visible(_win, on); - if (_promptwin != NULL_WIN) - xvt_vobj_set_visible(_promptwin, on); - _flags.shown = on; + if (_ctl) + { + _ctl->show(on); + _flags.shown = on; + } } @@ -479,25 +391,7 @@ void TMask_field::show_default() // Certified 100% bool TMask_field::active() const { - return enabled() && shown() && 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; -} - - -// Certified 90% -void TMask_field::reset_key(byte key) -{ - CHECK(key>0, "Can't reset key 0"); - _keys.reset(long(key)); - if (last_key()==0) _keys.reset(0L); + return is_operable() && enabled() && shown(); } @@ -511,158 +405,312 @@ void TMask_field::set_dirty(bool d) -// Certified 99% -const char* TMask_field::get_window_data() const -{ - return xvt_vobj_get_title(win(), (char*)(const char*)fpark, fpark.size()); -} - - -// Certified 99% -void TMask_field::set_window_data(const char* data) -{ - if (data != NULL) - xvt_vobj_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; } - // @doc EXTERNAL -// @mfunc Permette di dare la stessa formattazione del campo della maschera -// -// @rdesc Ritorna la stringa formattata -const char* TMask_field::picture_data( - const char* data, // @parm Stringa da dare il formato - bool video) const // @parm Se TRUE permette di visualizzare la stringa a video - - // @comm Utilizzata soprattutto dagli sheet che in questo modo possono formattare - // il contenuto delle celle con lo stesso formato deglia altri campi della maschera - // dell stesso tipo. -{ - if (video) - { - fpark = data; - const byte t = _flags.trim; - smart_trim(fpark, t); - if (_flags.uppercase) - fpark.upper(); - return fpark; - } - return data; -} - -// Certified 90% +// Certified 100% const char* TMask_field::prompt() const { - if (_promptwin != NULL_WIN) - _prompt = xvt_get_title(_promptwin); - else - _prompt = ""; - - return _prompt; -} - -// Certified 90% -void TMask_field::set_field(const TString& fr) -{ - if (_field != NULL) - *_field = fr; - else - _field = new TFieldref(fr, 0); + return _ctl ? _ctl->caption() : ""; } // Certified 100% void TMask_field::reset() -{ - if (!_flags.persistent && class_id() != CLASS_FIELD) +{ + if (!_flags.persistent) set(""); } - -// Certified 00% +// Certified 100% void TMask_field::set_prompt(const char* p) { - WINDOW w = _promptwin != NULL_WIN ? _promptwin : _win; - - word style = XVT_FS_NONE; - for (const char* s = p; *s == '@'; s++) - { - s++; - switch(toupper(*s)) - { - case 'B': style |= XVT_FS_BOLD; break; - case 'U': style |= XVT_FS_UNDERLINE; break; - default : CHECKS(0, "Invalid prompt style ", s); break; - } - } - xvt_set_font(w, "", style, style != XVT_FS_NONE ? CHARY-12 : 0); - xvt_vobj_set_title(w, (char*)p); + if (_ctl) _ctl->set_caption(p); } -void TMask_field::set(const char* s) -{ - if (mask().is_running()) - { - set_window_data(s); - set_dirty(); - } - else - set_field_data(s); +void TMask_field::set(const char*) +{ } -TString& TMask_field::get() const +void TMask_field::set(long n) { - static TString gpark; - if (mask().is_running()) - gpark = get_window_data(); - else - gpark = get_field_data(); + char s[16]; sprintf(s, "%ld", n); + set(s); +} + +const TString& TMask_field::get() const +{ + return _ctl_data._park.cut(0); +} + +// @doc EXTERNAL + +// @mfunc Permette di spedire il check +// +// @rdesc Ritorna il risultato del check: +// +// @flag TRUE | Se il check ha dato esito positivo +// @flag FALSE | Se il check ha dato esito negativo +bool TMask_field::to_check( + KEY k, // @parm Tasto da passare al campo come simulazione di inizio controllo + bool checkrun) const // @parm Permette di testare sanche e la maschera e' in esecuzione +{ + bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); - const byte t = _flags.trim; - smart_trim(gpark, t); - return gpark; + if (!yes && checkrun) + yes = k == K_TAB && !mask().is_running(); + + return yes; } - -void TMask_field::undo() -{ - set_window_data(get_field_data()); +void TMask_field::send_key(KEY k, short to) +{ + _mask->send_key(k, to, this); } +void TMask_field::check_type(CheckType) +{ CHECK(0, "Can't set check type to non-edit field"); } -bool TMask_field::autoload(const TRelation* r) -{ - if (_field) - { - set(_field->read(r)); - return TRUE; - } + +void TMask_field::set_handler(CONTROL_HANDLER) +{ CHECK(0, "Can't set the handler to a TMask_field"); } + + +bool TMask_field::on_hit() +{ + CHECK(0, "Can't hit non-operable field"); return FALSE; } -bool TMask_field::autosave(TRelation* r) const +// Certified 90% +bool TMask_field::on_key(KEY key) { - if (_field) + switch(key) { - _field->write(get(), r); - return TRUE; + case K_F11: + { + TString msg(80); + msg = "State utilizzando il campo "; + msg << dlg() << " della maschera " << mask().source_file(); + if (field() != NULL) + msg << "\ncorrispondente al campo su record " << *field(); + message_box(msg); + } + break; + case K_F2: + reset(); + set_dirty(); + break; + default: +#ifdef DBG + if (key > K_CTRL) + error_box("Tasto ignorato %d", key); +#endif + break; + } + + return TRUE; +} + +#define build_msg() char* _msg = (char*)(const char*)_ctl_data._park;va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) + +// @doc EXTERNAL + +// @mfunc Crea una error-box relativo al campo (chiama ) +// +// @rdesc Ritorna sempre FALSE +bool TMask_field::error_box( + const char* fmt, // @parm Formato della stringa da scrivere + ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti + // viene creata una finestra di errore normale. + +{ + build_msg(); + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + mask().post_error_message(_msg, 3); } return FALSE; } +bool TMask_field::message_box(const char* fmt, ...) const +{ + build_msg(); + mask().post_error_message(_msg, 1); + return FALSE; +} +// @doc EXTERNAL + +// @mfunc Crea una warning-box relativo al campo (chiama ) +// +// @rdesc Ritorna sempre FALSE +bool TMask_field::warning_box( + const char* fmt, // @parm Formato della stringa da scrivere + ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ + // @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti + // viene creata una finestra di warning normale. +{ + build_msg(); + + if (mask().is_sheetmask() && !mask().is_running()) + { + xvt_statbar_set(_msg); + beep(); + } + else + { + mask().post_error_message(_msg, 2); + } + return FALSE; +} + +bool TMask_field::yesno_box(const char* fmt, ...) const +{ + set_focus(); + build_msg(); + const bool yes = ::yesno_box("%s", _msg); + highlight(); + return yes; +} + +KEY TMask_field::yesnocancel_box(const char* fmt, ...) const +{ + build_msg(); + set_focus(); + const KEY k = ::yesnocancel_box("%s", _msg); + highlight(); + return k; +} + +/////////////////////////////////////////////////////////// +// TText_field +/////////////////////////////////////////////////////////// + +// Certified 100% +word TText_field::class_id() const +{ return CLASS_TEXT_FIELD; } + +// Certified 100% +bool TText_field::is_kind_of(word cid) const +{ return cid == CLASS_TEXT_FIELD || TMask_field::is_kind_of(cid); } + +// Certified 100% +void TText_field::create(WINDOW parent) +{ + _ctl = new TText_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, + 0, 1, + _ctl_data._flags, _ctl_data._prompt); +} +/////////////////////////////////////////////////////////// +// TGroup_field +/////////////////////////////////////////////////////////// + +TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) +{ + _flags.persistent = TRUE; +} + +// _size means _heigth +void TGroup_field::parse_head(TScanner& scanner) +{ + _ctl_data._width = scanner.integer(); + _ctl_data._size = scanner.integer(); +} + +void TGroup_field::create(WINDOW parent) +{ + _ctl = new TGroupbox_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, + _ctl_data._width, _ctl_data._size, + _ctl_data._flags, _ctl_data._prompt); +} + +/////////////////////////////////////////////////////////// +// TOperable_field +/////////////////////////////////////////////////////////// + +TOperable_field::TOperable_field(TMask* m) + : TMask_field(m), _handler(NULL), _message(NULL) +{ } + +TOperable_field::~TOperable_field() +{ + if (_message) delete _message; +} + +TToken_string* TOperable_field::message(int m, bool crea) +{ + TToken_string* msg = _message ? _message->rowptr(m) : NULL; + if (msg == NULL && crea) + { + if (_message == NULL) + _message = new TString_array(2); + msg = new TToken_string(16); + _message->add(msg, m); + } + return msg; +} + + +bool TOperable_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "HE") // HELP + { + scanner.string(); // Ignored from this version + return TRUE; + } + + if (scanner.key() == "ME") + { + const TString& m = scanner.line().strip_spaces(); + message(0, TRUE)->add(m); + return TRUE; + } + + return TMask_field::parse_item(scanner); +} + +void TOperable_field::set_focus() const +{ + mask().set_focus_field(dlg()); +} + +void TOperable_field::enable(bool on) +{ + TMask_field::enable(on); + if (_ctl) _ctl->enable(on); +} + +bool TOperable_field::on_key( + KEY key) // @parm Tasto notificato +{ + if (key == K_CTRL + K_TAB) + { + mask().notify_focus_field(dlg()); + return TRUE; + } + + if (key == K_ENTER) + { + const bool ok = handler(K_ENTER); + return ok; + } + + return TMask_field::on_key(key); +} + + // Certified 50% HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) { @@ -722,17 +770,10 @@ HIDDEN void run_app(TMask& mask, TToken_string& msg) mask.set_focus(); } - -void TMask_field::send_key(KEY k, short to) -{ - mask().send_key(k, to, this); -} - - // Certified 90% -bool TMask_field::do_message(int num) +bool TOperable_field::do_message(int num) { - const int MAX_CMD = 17; + const int MAX_CMD = 16; static const char* commands[MAX_CMD] = { "ADD", // 0 @@ -751,16 +792,16 @@ bool TMask_field::do_message(int num) "RESET", // 13 "RU", // 14 "SHOW", // 15 - "UNDO" // 16 }; - - TToken_string* message = (TToken_string*)_message.objptr(num); - if (message == NULL || message->empty()) return FALSE; + + TToken_string* mess = message(num); + if (mess == NULL || mess->empty()) + return FALSE; TToken_string msg(16, ','); TString256 value; - for (const char* m = message->get(0); m && *m; m = message->get()) + for (const char* m = mess->get(0); m && *m; m = mess->get()) { KEY key = 0; msg = m; @@ -798,14 +839,18 @@ bool TMask_field::do_message(int num) } short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; - bool broadcast = dlg && strchr(dlg, '@'); + const bool broadcast = dlg && strchr(dlg, '@'); + if (broadcast) fld = -fld; + 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; + mask().disable(fld); + mask().reset(fld); + continue; case 2: value = copy_value(msg, get()); break; case 3: @@ -813,25 +858,23 @@ bool TMask_field::do_message(int num) case 4: mask().field(fld).set_dirty(); continue; case 5: - key = 11000+'d'; break; + mask().disable(fld); continue; case 6: - key = 11000+'e'; break; - case 7: - key = 11000+'E'; break; + mask().enable(fld); continue; + case 7: + mask().enable_default(fld); continue; case 9: - key = 11000+'h'; break; + mask().hide(fld); continue; case 10: - mask().efield(fld).check_type(CHECK_NORMAL); continue; + mask().field(fld).check_type(CHECK_NORMAL); continue; case 11: key = K_SPACE; break; case 12: - mask().efield(fld).check_type(CHECK_REQUIRED); continue; + mask().field(fld).check_type(CHECK_REQUIRED); continue; case 13: key = K_F2; break; case 15: - key = 11000+'s'; break; - case 16: - key = K_F3; break; + mask().show(fld); continue; default: key = atoi(value); break; @@ -840,22 +883,20 @@ bool TMask_field::do_message(int num) 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++) + { + const int max = mask().fields(); + for (int i = 0; i < max; i++) { TMask_field& f = mask().fld(i); - if (f.in_group((int)fld)) + if (f.in_group((int)-fld)) { - const char* prev = f.get(); + const TString& prev = f.get(); if (value != prev) { f.set(value); @@ -882,273 +923,586 @@ bool TMask_field::do_message(int num) return TRUE; } - -bool TMask_field::test_focus_change() -{ - bool ok = TRUE; - if (focusdirty()) ok = on_key(K_TAB); // Comportamento normale - else if (is_edit() && in_key(1)) ok = on_hit(); // Serve per eseguire gli handler autoprementi - return ok; +void TOperable_field::highlight() const +{ + if (_ctl) _ctl->set_focus(); } - -// Certified 90% -bool TMask_field::on_hit() -{ +bool TOperable_field::handler(KEY k) +{ + bool ok; if (_handler) - { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - do_message(0); - return TRUE; -} - -// @doc EXTERNAL - -// @mfunc Permette di spedire il check -// -// @rdesc Ritorna il risultato del check: -// -// @flag TRUE | Se il check ha dato esito positivo -// @flag FALSE | Se il check ha dato esito negativo -bool TMask_field::to_check( - KEY k, // @parm Tasto da passare al campo come simulazione di inizio controllo - bool checkrun) const // @parm Permette di testare sanche e la maschera e' in esecuzione -{ - bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); - - if (!yes && checkrun) - yes = k == K_TAB && !mask().is_running(); - - return yes; + ok = _handler(*this, k); + else + ok = TRUE; + return ok; } // 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; - } +bool TOperable_field::on_hit() +{ + const bool ok = handler(K_SPACE); + if (ok && has_message()) + do_message(0); + return ok; +} - switch(key) +/////////////////////////////////////////////////////////// +// Button_field +/////////////////////////////////////////////////////////// + +TButton_field::TButton_field(TMask* m) + : TOperable_field(m) +{ +} + + +word TButton_field::class_id() const +{ return CLASS_BUTTON_FIELD; } + +bool TButton_field::is_kind_of(word cid) const +{ return cid == CLASS_BUTTON_FIELD || TOperable_field::is_kind_of(cid); } + +void TButton_field::parse_head(TScanner& scanner) +{ + _ctl_data._width = scanner.integer(); + if (_ctl_data._width <= 0) _ctl_data._width = 10; + _ctl_data._height = scanner.integer(); // Height + if (_ctl_data._height <= 0) _ctl_data._height = 1; +} + + +bool TButton_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PI") + { + const short bmp = (short)scanner.integer(); + if (_ctl_data._bmp_up == 0) + _ctl_data._bmp_up = bmp; + else + _ctl_data._bmp_dn = bmp; + return bmp > 0; + } + return TOperable_field::parse_item(scanner); +} + + +void TButton_field::create(WINDOW parent) +{ + _exit_key = 0; + _virtual_key = 0; + switch (dlg()) { - case K_SPACE: - set_dirty(); + case DLG_OK: + if (_ctl_data._prompt.empty()) + _ctl_data._prompt = "Conferma"; + _virtual_key = _exit_key = K_ENTER; + if (_ctl_data._bmp_up == 0) + _ctl_data._bmp_up = BMP_OK; break; - case K_PREV: - case K_NEXT: - send_key(key, 0); + case DLG_CANCEL: + if (_ctl_data._prompt.empty()) + _ctl_data._prompt = "Annulla"; + _virtual_key = _exit_key = K_ESC; + if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == "Annulla") + _ctl_data._bmp_up = BMP_CANCEL; break; - case K_F1: -#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT - if (fexist("prassi.hlp")) + case DLG_DELREC: + if (_ctl_data._prompt.empty()) + _ctl_data._prompt = "Elimina"; + _virtual_key = 'E'; + _exit_key = K_DEL; + if (_ctl_data._bmp_up == 0) { - struct MULTIGUY - { - UINT mkSize; - BYTE mkKeylist; - char mkKeyphrase[16]; - } mk; - - TFilename topic(mask().source_file()); topic.ext(""); - mk.mkSize = sizeof(MULTIGUY); - mk.mkKeylist = 'M'; - strcpy(mk.mkKeyphrase, topic); - - TFilename hlp("prassi.hlp"); - const TString16 mod(topic.left(2)); - if (mod != "ba") hlp.insert(mod, 0); - - HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); - WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); - set_focus(); - break; - } -#endif - case K_SHIFT+K_F1: - if (_help.not_empty()) - message_box(_help); - else - beep(); - set_focus(); + _ctl_data._bmp_up = BMP_DELREC; + _ctl_data._bmp_dn = BMP_DELRECDN; + } break; - case K_F11: - { - const char* c = ""; - if (field()) - c = field()->name(); - message_box("State utilizzando il campo %d della maschera '%s'\n" - "corrispondente al campo su file '%s'", - dlg(), (const char*)mask().source_file(), c); - set_focus(); - } + case DLG_PRINT: + if (_ctl_data._prompt.empty()) + _ctl_data._prompt = "Stampa"; + _virtual_key = 'S'; + _exit_key = K_ENTER; + if (_ctl_data._bmp_up <= 0) + _ctl_data._bmp_up = BMP_PRINT; break; - - case K_F2: - if (is_edit()) set(""); - else reset(); - set_dirty(); + case DLG_QUIT: + if (_ctl_data._prompt.empty()) + _ctl_data._prompt = "Fine"; + _virtual_key = K_F4; + _exit_key = K_QUIT; + if (_ctl_data._bmp_up <= 0) + { + _ctl_data._bmp_up = BMP_QUIT; + _ctl_data._bmp_dn = BMP_QUITDN; + } break; - case K_F3: - undo(); - set_dirty(); + case DLG_SELECT: + if (_ctl_data._bmp_up <= 0) + _ctl_data._bmp_up = BMP_SELECT; + _exit_key = K_ENTER; break; default: break; } - if (_handler) - return _handler(*this, key); - - return TRUE; -} - -void TMask_field::highlight() const -{ - xvt_scr_set_focus_vobj(win()); -} - -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) - -// @doc EXTERNAL - -// @mfunc Crea una error-box relativo al campo (chiama ) -// -// @rdesc Ritorna sempre FALSE -bool TMask_field::error_box( - const char* fmt, // @parm Formato della stringa da scrivere - ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

+ TToken_string* mess = message(0); + if (mess) + { + TToken_string msg(mess->get(0), ','); + const TString m(msg.get(0)); + if (m == "EXIT") + _exit_key = msg.get_int(); + else + if (msg.get_int() == 0) _exit_key = atoi(m); + } + if (_virtual_key == 0) + { + const int n = _ctl_data._prompt.find('~'); + _virtual_key = (n >= 0) ? toupper(_ctl_data._prompt[n+1]) : _exit_key; + } - // @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti - // viene creata una finestra di errore normale. - -{ - build_msg(); - if (mask().is_sheetmask() && !mask().is_running()) - { - xvt_statbar_set(_msg); - beep(); + _ctl = new TPushbutton_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, + _ctl_data._width+2, _ctl_data._height, + _ctl_data._flags, _ctl_data._prompt, + _ctl_data._bmp_up, _ctl_data._bmp_dn); +} + +bool TButton_field::on_key(KEY key) +{ + bool ok = TRUE; + if (key == K_SPACE) + { + ok = on_hit(); + if (ok && _exit_key > 0 && message(0) == NULL) + mask().stop_run(_exit_key); } else + ok = TOperable_field::on_key(key); + return ok; +} + +void TButton_field::set_bmp(short up, short dn) +{ + ((TPushbutton_control*)_ctl)->set_bmp(up, dn); +} + +/////////////////////////////////////////////////////////// +// TEditable_field +/////////////////////////////////////////////////////////// + +TEditable_field::TEditable_field(TMask* m) + : TOperable_field(m), _prompt(NULL), _field(NULL), _keys(NULL), + _validate(NULL), _warning(NULL) +{ } + + +TEditable_field::~TEditable_field() +{ + if (_prompt) delete _prompt; + if (_field) delete _field; + if (_keys) delete _keys; + if (_validate) delete _validate; + if (_warning) delete _warning; +} + + +void TEditable_field::set_warning(const char* w) +{ + if (_warning) + *_warning = w; + else + _warning = new TString(w); + if (_warning->empty()) { - set_focus(); - ::error_box("%s", _msg); - set_focus(); + delete _warning; + _warning = NULL; + } +} + +// Certified 100% +const char* TEditable_field::prompt() const +{ + return _prompt ? _prompt->caption() : ""; +} + + +// Ritorna il messaggio d'errore associato al campo +const char* TEditable_field::get_warning() const +{ return _warning ? (const char*)*_warning : ""; } + +bool TEditable_field::parse_item(TScanner& scanner) +{ + const TString& k = scanner.key(); + + if (k == "FI") // FIELD + { + set_field(scanner.line()); + return TRUE; } + + if (k == "KE") // KEY + { + if (_keys == NULL) + _keys = new TBit_array; + _keys->set(scanner.line()); + _keys->set(0L); + return TRUE; + } + + if (k == "CU") // CUSTOM DATA + { + if (_userdata == NULL) + _userdata = new TToken_string(scanner.string()); + else + _userdata->add(scanner.string()); + return TRUE; + } + + if (scanner.key() == "VA") + { +#ifdef DBG + if (_validate) + return yesnofatal_box("VALIDATE duplicata nel campo %d", _ctl_data._dlg); +#endif + _validate = new TValidation_data; + + 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, _ctl_data._dlg); +#endif + + const int nparms = scanner.integer(); +#ifdef DBG + if (nparms < 0 || nparms > 100) + return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", + _ctl_data._dlg, nparms); +#endif + + for (int i = 0; i < nparms; i++) + _validate->_parms.add(scanner.operand()); + + return TRUE; + } + + if (scanner.key() == "WA") + { + set_warning(scanner.string()); + return TRUE; + } + + return TOperable_field::parse_item(scanner); +} + +void TEditable_field::set_key(byte key) +{ + if (_keys == NULL) + _keys = new TBit_array; + _keys->set(long(key)); + _keys->set(0L); +} + +// Certified 90% +word TEditable_field::last_key() const +{ + long u = _keys ? _keys->last_one() : 0; + if (u < 0) u = 0; + return (word)u; +} + +// Certified 90% +word TEditable_field::first_key() const +{ + long u = _keys ? _keys->first_one() : 0; + if (u < 0) u = 0; + return (word)u; +} + +bool TEditable_field::test_key_complete(bool normal) const +{ + TMask& m = mask(); + for (int k = 1; k <= MAX_KEYS; k++) + { + if (in_key(k) && m.key_valid(k)) + { + bool complete = TRUE; + for (TEditable_field* e = m.get_key_field(k, TRUE); e; e = m.get_key_field(k, FALSE)) + { + e->set_dirty(FALSE); + if ((e->class_id() != CLASS_LIST_FIELD) && + (e->class_id() != CLASS_BOOLEAN_FIELD)) + complete &= (e->required()); + } + if (normal && !complete) + m.set_test_field(dlg()); + else + m.stop_run(K_AUTO_ENTER); + return TRUE; + } + } return FALSE; } -bool TMask_field::message_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - ::message_box("%s", _msg); - set_focus(); - return FALSE; +// Certified 90% +void TEditable_field::reset_key(byte key) +{ + if (_keys) + { + _keys->reset(long(key)); + if (key == 0 || last_key() == 0) + { + delete _keys; // Se non ci sono piu' chiavi azzera tutto + _keys = NULL; + } + } } // @doc EXTERNAL -// @mfunc Crea una warning-box relativo al campo (chiama ) +// @mfunc Chiama l' eventuale funzione di validazione // -// @rdesc Ritorna sempre FALSE -bool TMask_field::warning_box( - const char* fmt, // @parm Formato della stringa da scrivere - ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

- - // @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti - // viene creata una finestra di warning normale. -{ - build_msg(); - - if (mask().is_sheetmask() && !mask().is_running()) +// @rdesc Ritorna il risultato dell funzione di validazione: +// +// @flag TRUE | Se la validata ha avuto successo +// @flag FALSE | Se la validata no ha avuto successo +bool TEditable_field::validate( + KEY k) // @parm Tasto da passare alla funzione di validazione +{ + bool ok = TRUE; + if (_validate) + ok = ::validate(_validate->_func, *this, k, _validate->_parms); + return ok; +} + + +// Certified 90% +// @doc EXTERNAL + +// @mfunc Crea il prompt del controllo +// +// @rdesc Ritorna la lunghezza del prompt creato +word TEditable_field::create_prompt( + WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo + word width, // @parm Larghezza del controllo + word height) // @parm Altezza del controllo +{ + if (_ctl_data._prompt.not_empty()) { - xvt_statbar_set(_msg); - beep(); - } - else - { - set_focus(); - ::warning_box("%s", _msg); - set_focus(); + TString flags; + if (hidden()) flags << 'H'; + + if (height < 3) + { + width = _ctl_data._prompt.len(); + for (word i = 0; i < width && _ctl_data._prompt[(int)i] == '@'; i += 2); + width -= i; + _prompt = new TText_control(parent, -1, _ctl_data._x, _ctl_data._y, + 0, 1, flags, _ctl_data._prompt); + } + else + { + if (right_justified()) flags << 'R'; + _prompt = new TGroupbox_control(parent, -1, _ctl_data._x, _ctl_data._y, + width, height, flags, _ctl_data._prompt); + } } - return FALSE; + + return width; } -bool TMask_field::yesno_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const bool yes = ::yesno_box("%s", _msg); - set_focus(); - return yes; +void TEditable_field::show(bool on) +{ + TOperable_field::show(on); + if (_prompt) _prompt->show(on); } -KEY TMask_field::yesnocancel_box(const char* fmt, ...) const -{ - set_focus(); - build_msg(); - const KEY k = ::yesnocancel_box("%s", _msg); - set_focus(); - return k; +void TEditable_field::set_prompt(const char* p) +{ + CHECKD(_prompt, "Can't set prompt to control", dlg()); + _prompt->set_caption(p); +} + +// Certified 90% +void TEditable_field::set_field(const TString& fr) +{ + if (_field != NULL) + *_field = fr; + else + _field = new TFieldref(fr, 0); +} + + +// Certified 100% +// Legge il valore attuale del campo in formato RAW +const TString& TEditable_field::get() const +{ + return _str; +} + +// Certified 100% +// Aggiusta un valore letto da file in formato RAW +const char* TEditable_field::reformat(const char* data) const +{ + return data; +} + +// Certified 100% +// Setta il valore RAW e WIN del campo con un valore RAW +void TEditable_field::set(const char* data) +{ + _str = reformat(data); + const TString& val = raw2win(_str); + set_window_data(val); +} + +// Certified 100% +// Converte da formato RAW a formato WIN +const char* TEditable_field::raw2win(const char* data) const +{ + return reformat(data); +} + +// Certified 100% +// Converte da formato WIN a formato RAW +const char* TEditable_field::win2raw(const char* data) const +{ + return reformat(data); +} + +bool TEditable_field::autosave(TRelation& r) const +{ + if (_field) + _field->write(get(), r); + return _field != NULL; +} + +bool TEditable_field::autoload(const TRelation& r) +{ + if (_field) + set(_field->read(r)); + return _field != NULL; +} + +/////////////////////////////////////////////////////////// +// Boolean_field +/////////////////////////////////////////////////////////// + +TBoolean_field::TBoolean_field(TMask* m) + : TEditable_field(m) +{} + +word TBoolean_field::class_id() const +{ return CLASS_BOOLEAN_FIELD; } + + +void TBoolean_field::create(WINDOW parent) +{ + _ctl = new TCheckbox_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, 0, + _ctl_data._flags, _ctl_data._prompt); +} + +void TBoolean_field::set_prompt(const char* p) +{ + _ctl->set_caption(p); +} + +const char* TBoolean_field::reformat(const char* data) const +{ + return (data && *data > ' ') ? "X" : ""; +} + +void TBoolean_field::set_window_data(const char* data) +{ + if (_ctl) + ((TCheckbox_control*)_ctl)->check(*data > ' '); +} + +TString& TBoolean_field::get_window_data() +{ + const bool on = _ctl ? ((TCheckbox_control*)_ctl)->checked() : FALSE; + _str = on ? "X" : ""; + return _str; +} + +bool TBoolean_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "ME") + { + const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE + TToken_string* ts = message(tf, TRUE); + ts->add(scanner.line().strip_spaces()); + return TRUE; + } + + return TEditable_field::parse_item(scanner); +} + +bool TBoolean_field::on_hit() +{ + const bool ok = handler(K_SPACE); + if (ok) + { + const bool on = get() == "X"; + do_message(on); + } + return ok; +} + +bool TBoolean_field::on_key(KEY key) +{ + if (key == K_SPACE) + { + get_window_data(); + set_dirty(); + on_hit(); + return TRUE; + } + return TEditable_field::on_key(key); +} + +/////////////////////////////////////////////////////////// +// TBrowse_button +/////////////////////////////////////////////////////////// + +TBrowse_button::TBrowse_button(TEdit_field* f) + : _fld(f) +{ } + +TBrowse_button::~TBrowse_button() +{ +} + +// Certified 100% +TEditable_field& TBrowse_button::field(short id) const +{ + if (id > 0) + { + TMask_field& f = _fld->mask().field(id); + CHECKD(f.is_editable(), "Can't use in a browse the field ", id); + return (TEditable_field&)f; + } + return *_fld; } /////////////////////////////////////////////////////////// // TList_sheet /////////////////////////////////////////////////////////// +// @doc EXTERNAL + // 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); -} + : TBrowse_button(f), _row(-1), _caption(caption), _head(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% @@ -1157,6 +1511,11 @@ void TList_sheet::parse_input(TScanner& scanner) _inp_id.add(scanner.pop()); } +// Certified 100% +void TList_sheet::parse_item(TScanner& scanner) +{ + _data.add(new TToken_string(scanner.string())); +} // Certified 100% void TList_sheet::parse_output(TScanner& scanner) @@ -1167,7 +1526,8 @@ void TList_sheet::parse_output(TScanner& scanner) // il numero di riga selezionata int TList_sheet::do_input() { - if (_inp_id.empty()) return -2; // List empty! + if (_inp_id.empty_items()) + return -2; // List empty! _inp_id.restart(); TToken_string rowsel(80); @@ -1181,26 +1541,26 @@ int TList_sheet::do_input() } else { - const short id = _fld->atodlg(fld); + const short id = field().atodlg(fld); if (id > 0) { - TMask_field& tempf = field().mask().field(id); - if ( tempf.class_id() == CLASS_ZOOM_FIELD ) + const TMask_field& f = field(id); + if (f.class_id() == CLASS_ZOOM_FIELD) { - TZoom_field& tempz = ( TZoom_field & ) tempf; - rowsel.add( tempz.get_first_line( ) ); + const TZoom_field& z = (TZoom_field&)f; + rowsel.add(z.get_first_line()); } else - rowsel.add(field().mask().get(id)); + rowsel.add(f.get()); } else rowsel.add(""); } } - TString80 fd, it; - for (int i = 0 ; i < _sheet->items(); i++) + TString fd, it; + for (int i = 0 ; i < _data.items(); i++) { - TToken_string& ts =_sheet->row(i); + TToken_string& ts =_data.row(i); ts.restart(); for ( const char* item = rowsel.get(0); item ; item = rowsel.get()) @@ -1223,11 +1583,11 @@ void TList_sheet::do_output(CheckTime t) return; _out_id.restart(); - TToken_string& rowsel = _sheet->row(_row); + TToken_string& rowsel = _data.row(_row); rowsel.restart(); for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) { - const short id = _fld->atodlg(fld); + const short id = field().atodlg(fld); TMask_field& f = field(id); const char* val = rowsel.get(); if (t != STARTING_CHECK || f.field() == NULL) @@ -1243,16 +1603,17 @@ void TList_sheet::do_output(CheckTime t) // Certified 100% KEY TList_sheet::run() { + TArray_sheet sci(3, 3, -3, -3, _caption, _head); + sci.rows_array() = _data; + _row = do_input(); - - _sheet->select(_row); - - const KEY k = _sheet->run(); + sci.select(_row); + const KEY k = sci.run(); switch (k) { case K_ENTER: - _row = (int)_sheet->selected(); + _row = (int)sci.selected(); do_output(); break; default: @@ -1265,8 +1626,9 @@ KEY TList_sheet::run() // Certified 100% bool TList_sheet::check(CheckTime t) -{ - const bool passed = (_row = do_input()) != -1; +{ + _row = do_input(); + const bool passed = _row != -1; if (passed) do_output(t); return passed; } @@ -1278,24 +1640,27 @@ bool TList_sheet::check(CheckTime t) // 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) + : TBrowse_button(f), + _relation(r), _cursor(new TCursor (r, filter, key)), + _filter(filter), _secondary(FALSE) {} // Certified 100% TBrowse::TBrowse(TEdit_field* f, TCursor* c) -: _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) + : TBrowse_button(f), + _relation(NULL), _cursor(c), _secondary(FALSE) {} // Certified 100% TBrowse::~TBrowse() { + // Se e' stato usato il primo costruttore per cui devo distruggere la relazione ed il cursore if (_relation) { - delete _relation; delete _cursor; + delete _relation; } } @@ -1332,10 +1697,9 @@ void TBrowse::parse_input(TScanner& scanner) } else // Field on the mask { - TString80 str(s); - if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field + _inp_id.add(s); + if (scanner.popkey() == "SE") _inp_id << '@'; // Special FILTERing field else scanner.push(); - _inp_id.add(str); } } @@ -1359,8 +1723,8 @@ bool TBrowse::parse_copy(const TString& what, const TBrowse& b) { set_insert(b.get_insert()); _filter = b.get_filter(); - if (field()._warning.empty()) - field()._warning = b.field()._warning; + if (!field().has_warning() && b.field().has_warning()) + field().set_warning(b.field().get_warning()); if (!all) return TRUE; } if (all || what == "IN") @@ -1454,24 +1818,33 @@ void TBrowse::parse_insert(TScanner& scanner) } } -// 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 TBrowse::input_fields() { int inp = 0; for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) { - - if (*fld != '"' && strchr(fld, '@') == NULL && field(atoi(fld)).is_edit()) - inp++; + if (*fld != '"' && strchr(fld, '@') == NULL) + { + TMask_field& f = field(f.atodlg(fld)); + if (f.active() && f.is_editable()) + inp++; + } } return inp; } +const char* TBrowse::get_input_fields() const +{ + return _inp_id; +} + +const char* TBrowse::get_output_fields() const +{ + return _out_id; +} + + // @doc INTERNAL // @mfunc Ritorna il numero di campi non vuoti e non filtrati @@ -1506,7 +1879,7 @@ int TBrowse::do_input( } else { - const short id = _fld->atodlg(fld); + const short id = field().atodlg(fld); const bool filter_flag = strchr(fld, '@') != NULL; tofilter = filter && filter_flag; val = field(id).get(); @@ -1523,7 +1896,7 @@ int TBrowse::do_input( } TFieldref fldref(_inp_fn.get(), 0); // Output field - fldref.write(val, _cursor->relation()); + fldref.write(val, *_cursor->relation()); if (tofilter) { if (val.empty()) val.fill('~', fldref.len(cur)); @@ -1591,7 +1964,7 @@ void TBrowse::do_output(CheckTime t) else { const TFieldref fld(fr, 0); - sum << fld.read(_cursor->relation()); + sum << fld.read(*_cursor->relation()); } } @@ -1614,14 +1987,14 @@ void TBrowse::do_clear() } -bool TBrowse::do_insert() +bool TBrowse::do_link(bool insert) { bool ok = FALSE; - TString80 app; + TString app; if (_insert[0] == 'M') { - TString80 nm(_insert.mid(1)); + TString nm(_insert.mid(1)); if (nm.compare("batb", 4, TRUE) == 0) // Programma gestione tabelle app = format("ba3 -0 %s", (const char*)nm.mid(4)); // Obbligatorio usare la format globale @@ -1629,26 +2002,20 @@ bool TBrowse::do_insert() app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); // Obbligatorio usare la format globale } - else if (_insert[0] == 'G') - { - TGolem golem(&_insert[1], atol(field().get())); - const bool ok = golem.edit(); - return ok ? TRUE : error_box("Impossibile modificare l'oggetto"); - } else { app = &_insert[1]; } if (app.find('#') != -1) { - TString80 w(app); + TString w(app); app = ""; for (const char* f = w; *f; f++) { if (*f == '#') { const int id = atoi(++f); - app << _fld->mask().get(id); + app << field(id).get(); while (isspace(*f)) ++f; while (isdigit(*f)) ++f; if (*f) @@ -1661,16 +2028,51 @@ bool TBrowse::do_insert() } } TMailbox mail; - TMessage msg(app, MSG_AI, ""); - mail.send(msg); + if (insert) + { + TMessage msg(app, MSG_AI, ""); + mail.send(msg); + } + else + { + TToken_string body; + + body.add(_cursor->key()); + _inp_fn.restart(); + for (const char* i = _inp_id.get(0); i; i = _inp_id.get()) + { + + if (*i == '"') + { + TString s(++i); + + s.rtrim(1); + body.add(s); + _inp_fn.get(); + } + else + { + const short id = field().atodlg(i); + const TEditable_field& f = field(id); + + if (f.shown() && f.is_editable()) // ??? + { + TFieldref fldref(_inp_fn.get(), 0); + body.add(fldref.read(*_cursor->relation())); + } + } + } + TMessage msg(app, MSG_LN, body); + mail.send(msg); + } TExternal_app a(app); a.run(); - _fld->mask().set_focus(); + field().mask().set_focus(); if (mail.check()) { - TMessage* rcv = mail.next_s(MSG_AI); + TMessage* rcv = mail.next_s(insert ? MSG_AI : MSG_LN); if (rcv != NULL) _rec = atoi(rcv->body()); if (_rec > 0) { @@ -1691,8 +2093,6 @@ 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()); @@ -1700,8 +2100,8 @@ TToken_string& TBrowse::create_siblings(TToken_string& siblings) 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); + const short id = field().atodlg(i); + const TEditable_field& f = field(id); if (!f.shown() || !f.is_edit()) // Scarta i campi non editabili continue; const TEdit_field& e = (const TEdit_field&)f; @@ -1710,12 +2110,13 @@ TToken_string& TBrowse::create_siblings(TToken_string& siblings) continue; // Scarta i campi senza ricerca const TCursor* c = b->cursor(); + TString fn; // Considera ricerche sullo stesso file ma con chiave diversa if (c->file().num() == _cursor->file().num() && - (key[c->key()] == FALSE || id == _fld->dlg())) + (key[c->key()] == FALSE || id == field().dlg())) { - TString16 fn(_out_fn.get(n)); // Legge nome del campo su file + fn = _out_fn.get(n); // Legge nome del campo su file int pos = _items.get_pos(fn); // Determina header corrispondente if (pos < 0) // Se non lo trova identico ... { @@ -1757,22 +2158,24 @@ KEY TBrowse::run() TToken_string siblings; create_siblings(siblings); + TToken_string vals; { - TToken_string* sib = siblings.empty() ? NULL : &siblings; byte buttons = 0; if (_insert.not_empty()) { - buttons = 1; // Mette il bottone di gestione, a meno che ... - + buttons = 3; // Mette il bottone di gestione, a meno che ... +/* if (_insert[0] == 'G') // Gestione Golem { buttons |= 2; } else - { - const TString& maskname = _fld->mask().source_file(); - if (maskname.compare("batb", 4, TRUE) == 0 && _fld->in_key(0)) +*/ + if (_insert[0] != 'G') + { + const TString& maskname = field().mask().source_file(); + if (maskname.compare("batb", 4, TRUE) == 0 && field().in_key(0)) { const char* tabname = _cursor->file().name(); if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0) @@ -1780,41 +2183,81 @@ KEY TBrowse::run() } } } - - TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); + for (const char* i = _inp_id.get(0); i; i = _inp_id.get()) + { + if (*i != '"' && strchr(i, '@') == NULL) + { + const short id = field().atodlg(i); + const TEditable_field& f = field(id); + if (f.active() && f.is_editable()) + { + vals.add(i); + vals.add(f.get()); + vals.add((int)f.dirty()); + } + } + } + + + TBrowse_sheet s(_cursor, _items, caption, _head, buttons, &field(), siblings); k = s.run(); selected = s.selected(); } switch (k) - { - case K_INS: + { + case K_CTRL+'G': if (_insert[0] == 'G') + { field().set(format("%ld", selected+1)); - k = do_insert() ? K_ENTER : K_ESC; + TGolem golem(&_insert[1], atol(field().get())); + k = golem.edit() ? K_ENTER : K_ESC; + if (k = K_ESC) + error_box("Impossibile modificare l'oggetto"); + } + else + { + *_cursor = selected; + k = do_link(FALSE) ? K_ENTER : K_ESC; + } break; - case K_CTRL+'N': + case K_INS: + if (_insert[0] == 'G') { TGolem gol(&_insert[1], 0); if (gol.import()) field().set(format("%ld", gol.id())); + k = K_ENTER; } - k = K_ENTER; + else + k = do_link(TRUE) ? K_ENTER : K_ESC; break; case K_ENTER: *_cursor = selected; do_output(); break; + case K_ESC: + { + for (const char* i = vals.get(0); i; i = vals.get()) + { + const short id = field().atodlg(i); + TEditable_field& f = field(id); + f.set(vals.get()); + f.set_dirty(vals.get_int()); + } + } + break; default: if (k >= K_CTRL) { - const TMask& m = _fld->mask(); - const short id = siblings.get_int((k - K_CTRL) << 1); + TMask& m = field().mask(); + const int tag = k - K_CTRL - K_F1; + const short id = siblings.get_int(tag * 2); TEdit_field& ef = m.efield(id); ef.set_focus(); k = K_F9; if (m.is_running()) - ef.send_key(k, 0); + m.send_key(k, id); } break; } @@ -1829,11 +2272,11 @@ bool TBrowse::check(CheckTime t) if (_secondary == TRUE && t != RUNNING_CHECK) return TRUE; - if (_fld->check_type() != CHECK_NONE) + if (field().check_type() != CHECK_NONE) { const TMaskmode mode = (TMaskmode)field().mask().mode(); - CheckType chk = _fld->check_type(); + CheckType chk = field().check_type(); if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY)) chk = CHECK_NORMAL; @@ -1860,8 +2303,8 @@ bool TBrowse::check(CheckTime t) else { do_clear(); - if (!_fld->mask().query_mode() && _fld->check_enabled()) - _fld->set_dirty(3); + if (!field().mask().query_mode() && field().check_enabled()) + field().set_dirty(3); } } } @@ -1887,7 +2330,7 @@ bool TBrowse::check(CheckTime t) bool TBrowse::empty_check() { - if (field().mask().query_mode() || _fld->check_type() != CHECK_REQUIRED) + if (field().mask().query_mode() || field().check_type() != CHECK_REQUIRED) return TRUE; else return do_input() > 0; @@ -1899,56 +2342,41 @@ bool TBrowse::empty_check() /////////////////////////////////////////////////////////// TEdit_field::TEdit_field(TMask* mask) -: TMask_field(mask), _browse(NULL), _sheet(NULL), - _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(FALSE), - _forced(FALSE) -{} +: TEditable_field(mask), _browse(NULL), + _check(CHECK_NONE), _check_enabled(FALSE), _forced(FALSE) +{ } TEdit_field::~TEdit_field() { - if (_browse) delete _browse; else - if (_sheet) delete _sheet; + if (_browse) delete _browse; } word TEdit_field::class_id() const { return CLASS_EDIT_FIELD; } -void TEdit_field::enable(bool on) -{ - TMask_field::enable(on); - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on && check_enabled() && shown()); -} - -void TEdit_field::show(bool on) -{ - TMask_field::show(on); - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on && check_enabled() && enabled()); -} - - void TEdit_field::parse_head(TScanner& scanner) { - _size = scanner.integer(); + _ctl_data._size = scanner.integer(); #ifdef DBG - if (_size < 1) + if (_ctl_data._size <= 0) { - _size = 8; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + _ctl_data._size = 8; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", + _ctl_data._dlg, _ctl_data._size); } #endif - _width = scanner.integer(); - if (_width == 0) _width = _size; + _ctl_data._width = scanner.integer(); + if (_ctl_data._width == 0) + _ctl_data._width = _ctl_data._size; } -const TBrowse* TEdit_field::get_browse(TScanner& scanner) const +const TBrowse* TEdit_field::parse_browse(TScanner& scanner) const { const int id = scanner.integer(); const TEdit_field& f = mask().efield(id); - const TBrowse* b = (const TBrowse*)f.browse(); + const TBrowse* b = 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()); @@ -1956,17 +2384,11 @@ const TBrowse* TEdit_field::get_browse(TScanner& scanner) const 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; } @@ -2031,7 +2453,7 @@ bool TEdit_field::parse_item(TScanner& scanner) if (tabmaskname.not_empty()) { tabmaskname.insert("MBATB", 0); - _browse->set_insert(tabmaskname); + browse()->set_insert(tabmaskname); } _check_enabled = TRUE; @@ -2042,18 +2464,18 @@ bool TEdit_field::parse_item(TScanner& scanner) { 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) + const TBrowse* b = parse_browse(scanner); + if (b) { - _check_enabled = TRUE; - return _browse->parse_copy(what, *b); + if (what == "US" || what == "AL") + _browse = new TBrowse(this, b->cursor()); + + if (_browse) + { + _check_enabled = TRUE; + return browse()->parse_copy(what, *b); + } } - #ifdef DBG return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); #endif @@ -2062,18 +2484,21 @@ bool TEdit_field::parse_item(TScanner& scanner) if (scanner.key() == "JO") { #ifdef DBG - if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); + if(browse() == NULL) + return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); + else #endif - _browse->parse_join(scanner); + browse()->parse_join(scanner); return TRUE; } if (scanner.key() == "SH") // SHEET { #ifdef DBG - if (_sheet) return yesnofatal_box("SHEET duplicato nel campo %d", dlg()); + if (_browse) + return yesnofatal_box("SHEET duplicato nel campo %d", _ctl_data._dlg); #endif - _sheet = new TList_sheet(this, _prompt, scanner.string()); + _browse = new TList_sheet(this, _ctl_data._prompt, scanner.string()); _check_enabled = TRUE; return TRUE; } @@ -2081,18 +2506,21 @@ bool TEdit_field::parse_item(TScanner& scanner) if (scanner.key() == "IT") // ITEM { #ifdef DBG - if (_sheet == NULL) return yesnofatal_box("ITEM senza SHEET nel campo %d", dlg()); + if (sheet() == NULL) + return yesnofatal_box("ITEM senza SHEET nel campo %d", _ctl_data._dlg); + else #endif - _sheet->read_item(scanner); + sheet()->parse_item(scanner); return TRUE; } if (scanner.key() == "IN") { - if (_browse) _browse->parse_input(scanner); else - if (_sheet) _sheet->parse_input(scanner); + if (_browse) + _browse->parse_input(scanner); #ifdef DBG - else yesnofatal_box("INPUT senza USE o SHEET nel campo %d", dlg()); + else + yesnofatal_box("INPUT senza USE o SHEET nel campo %d", _ctl_data._dlg); #endif return TRUE; } @@ -2100,18 +2528,21 @@ bool TEdit_field::parse_item(TScanner& scanner) if (scanner.key() == "DI") { #ifdef DBG - if(!_browse) return yesnofatal_box("DISPLAY senza USE nel campo %d", dlg()); + if(!browse()) + return yesnofatal_box("DISPLAY senza USE nel campo %d", _ctl_data._dlg); + else #endif - _browse->parse_display(scanner); + browse()->parse_display(scanner); return TRUE; } if (scanner.key() == "OU") { - if (_browse) _browse->parse_output(scanner); - else if (_sheet) _sheet->parse_output(scanner); + if (_browse) + _browse->parse_output(scanner); #ifdef DBG - else return yesnofatal_box("OUTPUT senza USE nel campo %d", dlg()); + else + return yesnofatal_box("OUTPUT senza USE nel campo %d", dlg()); #endif return TRUE; } @@ -2119,15 +2550,17 @@ bool TEdit_field::parse_item(TScanner& scanner) if (scanner.key() == "AD") { #ifdef DBG - if(!_browse) return yesnofatal_box("ADD senza USE nel campo %d", dlg()); + if(browse() == NULL) + return yesnofatal_box("ADD senza USE nel campo %d", dlg()); + else #endif - _browse->parse_insert(scanner); + browse()->parse_insert(scanner); return TRUE; } if (scanner.key() == "ME") { - TFixed_string l(scanner.line().strip_spaces()); + TString& l = scanner.line().strip_spaces(); int m = 0; if (l[0] == '0') { @@ -2135,175 +2568,115 @@ bool TEdit_field::parse_item(TScanner& scanner) 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); + message(m, TRUE)->add(l); return TRUE; } - return TMask_field::parse_item(scanner); + return TEditable_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; + const int len = create_prompt(parent, 0, 0); - _x += len; - - -#if XVT_OS == XVT_OS_SCOUNIX - 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 || XVT_OS == XVT_OS_NT - HWND hwnd = (HWND)xvt_vobj_get_attr(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; - } - - TString16 ico("*"); - if (_browse && _browse->get_insert()[0] == 'G') - { - const char* g = _browse->get_insert(); - TGolem golem(g+1, 0); - ico.format("#%d", golem.icon()); - } - _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, - 2, 1, ico, parent, flags, PTR_LONG(this), DLG_F9); - } + _size = _ctl_data._size; + _ctl_data._x += len; + + if (_browse) // Decide se attivare o meno il bottone di ricerca + _ctl_data._flags << 'B'; + + _ctl = new TField_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, + _ctl_data._width+1, _ctl_data._size, + _ctl_data._flags, ""); + + if (_browse && !enabled_default()) + ((TField_control*)_ctl)->show_button(FALSE); } -void TEdit_field::set_back_color(COLOR c) const -{ - if (_promptwin != NULL_WIN) - xvt_set_ctrl_back_color(_promptwin, c); -} - - -void TEdit_field::destroy() +const char* TEdit_field::reformat(const char* str) const { - if (_buttonwin) - { xvt_vobj_destroy(_buttonwin); _buttonwin = NULL_WIN; } - TMask_field::destroy(); -} + TString& s = _ctl_data._park; + s = str; + const byte trim_mode = _flags.trim; + smart_trim(s, trim_mode); - -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) const -{ - fpark = d; - - const byte t = _flags.trim; - smart_trim(fpark, t); - - if (fpark.not_empty()) + if (s.not_empty()) { - int len = fpark.len(); - if (len > _size) + word len = s.len(); + if (len > size()) { #ifdef DBG - yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), (const char*)fpark, _size); + yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), str, _size); #endif - fpark.cut(len = _size); + s.cut(len = size()); } - if (len < _size) + if (len < size()) { if (_flags.zerofilled) { - if (isdigit(fpark[0]) && real::is_real(fpark)) - fpark.right_just(_size, '0'); + if (isdigit(s[0]) && real::is_natural(s)) + s.right_just(size(), '0'); } - else - if (_flags.rightjust) - fpark.right_just(_size); } - + if (_flags.uppercase) - fpark.upper(); - - if (!_flags.pipeallowed) - { - for (int p = 0; fpark[p]; p++) - if (fpark[p] == '|') fpark[p] = '/'; - } - } - - return fpark; + s.upper(); + } + + return s; } - - -const char* TEdit_field::picture_data(const char* data, bool video) const -{ - format(data); // Scrive in fpark la stringa formattata - return fpark; +const char* TEdit_field::raw2win(const char* raw) const +{ + return reformat(raw); } -// @doc EXTERNAL +const char* TEdit_field::win2raw(const char* win) const +{ + return reformat(win); +} -// @mfunc Chiama l' eventuale funzione di validazione -// -// @rdesc Ritorna il risultato dell funzione di validazione: -// -// @flag TRUE | Se la validata ha avuto successo -// @flag FALSE | Se la validata no ha avuto successo -bool TEdit_field::validate( - KEY k) // @parm Tasto da passare alla funzione di validazione +void TEdit_field::set_window_data(const char* data) { - return _validate_func < 0 ? TRUE : ::validate(_validate_func, *this, k, _validate_parms); + _ctl->set_caption(data); +} + +void TEdit_field::autoselect(bool on) +{ + _ctl->autoselect(on); +} + +TString& TEdit_field::get_window_data() +{ + _str = win2raw(_ctl->caption()); + return _str; } // Certified 90% bool TEdit_field::on_hit() -{ - if (_validate_func >= 0 && - (_validate_func == AUTOEXIT_FUNC || - _validate_func == NUMCALC_FUNC || - _validate_func == STRCALC_FUNC)) - { - set(get()); - bool ok = validate(is_edit() ? K_TAB : K_SPACE); // Check validation expression - if (!ok) return FALSE; +{ + const int vf = validate_func(); + if (vf >= 0) + { + if (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC) + { + const bool ok = validate(K_TAB); // Check validation expression + if (!ok) return FALSE; + } } - if (_handler) + + const bool ok = handler(K_TAB); + if (ok && has_message()) { - bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); - if (!ok) return FALSE; - } - if (_message.objptr(1) && get().empty()) do_message(1); - else do_message(0); - return TRUE; + if (empty() && message(1)) + do_message(1); + else + do_message(0); + } + return ok; } // @doc EXTERNAL @@ -2317,86 +2690,90 @@ bool TEdit_field::default_error_box() const // indicando genericamente che il valore immesso non e' valido, altrimenti // riporta il warning associato al campo { - if (_warning.empty()) - { - const char* p = prompt(); + if (!has_warning()) + { + const TString p(prompt()); if (isalnum(p[0])) - error_box("Valore non valido per %s: '%s'", p, (const char*)get()); + { + const TString val(get()); + + error_box("Valore non valido per %s: %s", (const char*)p, (const char*)val); + } else - error_box("Valore non valido: '%s'", (const char*)get()); + error_box("Valore non valido: %s", (const char*)get()); } else - error_box(_warning); + error_box(get_warning()); return FALSE; } - -HIDDEN void test_key_complete(const TMask_field& f) -{ - TMask& m = f.mask(); - const byte keys = m.num_keys(); - for (int i = 1; i <= keys; i++) - { - if (f.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); - m.stop_run(K_AUTO_ENTER); - break; - } - } -} - bool TEdit_field::on_key(KEY key) -{ +{ + const int vf = validate_func(); + switch(key) - { + { + case K_CTRL+K_TAB: + set_focusdirty(FALSE); + break; case K_TAB: - if (_validate_func >= 0 && - (_validate_func == AUTOEXIT_FUNC || - _validate_func == NUMCALC_FUNC || - _validate_func == STRCALC_FUNC)) + if (vf >= 0 && (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC)) set_focusdirty(); // Forza validate if (to_check(K_TAB, TRUE)) { - set(get()); - bool ok = validate(key); // Check validation expression - - if (!ok) + if (class_id() == CLASS_EDIT_FIELD) // Altrimenti l'ha gia' fatto { - if (_warning.not_empty()) + const TString& raw = get_window_data(); + set_window_data(raw2win(raw)); + } + + bool ok = validate(key); // Check validation expression + if (!ok) + { + if (has_warning()) default_error_box(); return FALSE; } TMask& m = mask(); const bool query = m.query_mode(); - - if (_sheet) ok = query || _sheet->check(); // Check consistency + + if (_browse) + { + if (sheet()) + { + ok = query || sheet()->check(); // Check consistency + } + else + { + if (check_enabled() && (!query || forced()) && vf != 21) + ok = browse()->check(); + } + } + if (ok) + ok = on_hit(); + else + default_error_box(); + + if (ok) + { + set_focusdirty(FALSE); + if (query && m.is_running() && in_key(0)) + test_key_complete(); + } else - if (_browse && check_enabled() && (!query || forced()) && _validate_func != 21) - ok = _browse->check(); + set_focusdirty(!empty()); - if (!ok) return default_error_box(); - - ok = on_hit(); - if (!ok) return FALSE; - - if (query && required() && in_key(0)) - test_key_complete(*this); - - return TRUE; + return ok; } 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()) + if (has_warning()) default_error_box(); return FALSE; } @@ -2404,51 +2781,53 @@ bool TEdit_field::on_key(KEY key) const bool query = mask().query_mode(); // check consistency - if (_sheet) - ok = query || _sheet->check(FINAL_CHECK); - else + if (_browse) { - ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); - if (_browse && ok && - check_enabled() && - _validate_func != 21 && // 21 = NOT_EMPTY_CHECK_FIELD - (!query || forced())) + if (sheet()) + ok = query || sheet()->check(FINAL_CHECK); + else { - if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency - else ok = _browse->empty_check(); + ok = query || !(check_type() == CHECK_REQUIRED && empty()); + if (ok && check_enabled() && vf != 21 && // 21 = NOT_EMPTY_CHECK_FIELD + (!query || forced())) + { + if (dirty()) ok = browse()->check(FINAL_CHECK); // Check consistency + else ok = browse()->empty_check(); + } } + if (!ok) return default_error_box(); } - if (!ok) - return default_error_box(); } break; case K_F9: if (check_enabled()) { enable_check(FALSE); - if (dirty()) set(get()); + if (focusdirty()) + get_window_data(); + KEY k = K_ESC; if (_browse) k = _browse->run(); - else - if (_sheet) k = _sheet->run(); - else beep(); + else beep(); + if (k != K_F9) set_focus(); enable_check(TRUE); if (k == K_ENTER) { set_dirty(); - on_hit(); + on_hit(); + TMask & m = mask(); - if (mask().is_running()) + if (m.is_running()) { - if (mask().query_mode() && required() && in_key(0)) + set_focusdirty(FALSE); // Evita doppia esecuzione handlers! + if (m.query_mode() && in_key(0)) { - test_key_complete(*this); // Controlla autopremimento + test_key_complete(); } else { - set_focusdirty(FALSE); // Evita doppia esecuzione handlers! send_key(K_TAB, 0); // Passa al campo successivo } } @@ -2457,34 +2836,50 @@ bool TEdit_field::on_key(KEY key) else return FALSE; } - break; + break; + case K_CTRL+K_SPACE: + set_dirty(TRUE); + return handler(K_SPACE); default: break; } - return TMask_field::on_key(key); + return TEditable_field::on_key(key); } - +// @mfunc Controlla se il campo ha la necessita' di eseguire una ricerca sul cursore o +// sulla tabella associata al momento della sua inizializzazione +// +// @rdesc Ritorna TRUE se il campo ha un TArray_sheet associato oppure un TCursor_sheet +// con check_type non nullo. bool TEdit_field::has_check() const -{ - if (_browse) return check_type() != CHECK_NONE; - return _sheet != NULL; +{ + bool ok = FALSE; + if (_browse) + ok = browse() == NULL || check_type() != CHECK_NONE; + return ok; } bool TEdit_field::check(CheckTime t) { bool ok = TRUE; if (check_enabled() || (t == STARTING_CHECK && shown())) - { - if (_browse) ok = (_validate_func == 21) || _browse->check(t); - else if (_sheet) ok = _sheet->check(t); + { + if (_browse && validate_func() != 21) + ok = _browse->check(t); } return ok; } // @doc EXTERNAL +void TEdit_field::enable(bool on) +{ + TEditable_field::enable(on); + if (_browse) + ((TField_control*)_ctl)->show_button(on); +} + // @mfunc Permette di abilitare/disabilitare un check di un campo void TEdit_field::enable_check( bool on) // @parm Operazione da svolgere @@ -2493,255 +2888,25 @@ void TEdit_field::enable_check( // @flag FALSE | Disabilita il check del campo { _check_enabled = on; - if (_buttonwin != NULL_WIN) - xvt_vobj_set_visible(_buttonwin, on); + ((TField_control*)_ctl)->show_button(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, _prompt.len()+3, 1, _prompt, parent, 0); -} - -void TBoolean_field::set_back_color(COLOR c) const -{ - xvt_set_ctrl_back_color(win(), c); -} - -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) -{ - if (scanner.key() == "PI") - { - const int bmp = scanner.integer(); - _prompt << '#' << bmp; - return bmp > 0; - } - 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: - if (_prompt.empty()) - _prompt = "Elimina"; - _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 - const int diesis = _prompt.find('#'); - if (diesis > 0) _prompt.cut(diesis); - _prompt.center_just(_width); -#endif - - wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); -} - -void TButton_field::set_back_color(COLOR c) const -{} - - -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; - } - else - { - if (key == K_ENTER) - xvt_kill_focus(win()); - } - return TMask_field::on_key(key); -} - /////////////////////////////////////////////////////////// // Date_field /////////////////////////////////////////////////////////// +TDate_field::TDate_field(TMask* m) : TEdit_field(m) +{ } + word TDate_field::class_id() const { return CLASS_DATE_FIELD; } void TDate_field::create(WINDOW w) { + // Elimina il flag R che si interpreta come salva in formato ANSI + _ctl_data._flags.strip("AR"); + TEdit_field::create(w); if (automagic()) { @@ -2750,24 +2915,9 @@ void TDate_field::create(WINDOW w) } } -void TDate_field::parse_head(TScanner&) {} - -TDate_field::TDate_field(TMask* m) : TEdit_field(m) +void TDate_field::parse_head(TScanner&) { - _size = _width = 10; -} - - -const char* TDate_field::get_window_data() const -{ - TString16 str = TEdit_field::get_window_data(); - return format_data(str); -} - -void TDate_field::set_window_data(const char* data) -{ - const TDate d(data); - TEdit_field::set_window_data(d.string()); + _ctl_data._size = _ctl_data._width = 10; } // @doc EXTERNAL @@ -2775,9 +2925,8 @@ void TDate_field::set_window_data(const char* data) // @mfunc Permette di formattare la data secondo i flag correnti // // @rdesc Ritorna la data formattata -const char* TDate_field::format_data( - const char* datum, // @parm Stringa contenenete la data da formattare - bool* ch) const // @parm Indica se e' stata cambiato il formato rispetto alla stringa passsata +const char* TDate_field::win2raw( + const char* datum) const // @parm Stringa contenenete la data da formattare // @comm Permette di gestire anche alcuni date particolari come: // @@ -2787,80 +2936,84 @@ const char* TDate_field::format_data( // @flag PRIMO | Primo giorno dell'anno (01-01-aa) // @flag ULTIMO | Ultimo giorno dell'anno (31-12-aa) // @flag NATALE | Giorno di natale (25-12-aa) -{ - bool changed = FALSE; - fpark = datum; - fpark.trim(); - if (fpark.not_empty()) +{ + TString& s = _ctl_data._park; + s = datum; s.trim(); + if (s.not_empty()) { - if (isdigit(fpark[0])) + if (isdigit(s[0]) && s.len() < 10) { - for (int meno = 2; meno <= 5; meno += 3) - if (fpark[meno] != '-') + for (int meno = 2; meno <= 5 && meno < s.size(); meno += 3) + if (s[meno] != '-') { - fpark.insert("-", meno); - changed = TRUE; + s.insert("-", meno); } - if (fpark.len() == 8) // Fix century (for this millenium only) + if (s.len() == 8) // Fix century (for this millenium only) { - fpark.insert("19", 6); - changed = TRUE; + s.insert("19", 6); } } else - { + { + bool ok = TRUE; TDate g(TODAY); - fpark.upper(); - if (fpark == "IERI") + s.upper(); + if (s == "IERI") { --g; - changed = TRUE; - } - else - if (fpark == "DOMANI") - { - ++g; - changed = TRUE; - } - TString16 gstring(g.string()); - if (fpark == "PRIMO") + } else + if (s == "DOMANI") { - gstring.overwrite("01-01", 0); - changed = TRUE; - } - else - if (fpark == "NATALE") - { - gstring.overwrite("25-12", 0); - changed = TRUE; - } - else - if (fpark == "ULTIMO") - { - gstring.overwrite("31-12", 0); - changed = TRUE; - } - else - if (fpark == "OGGI") - changed = TRUE; - if (changed) fpark = gstring; + ++g; + } else + if (s == "POSDOMANI") + { + g += 2; + } else + if (s == "PRIMO") + { + g.set_month(1); + g.set_day(1); + } else + if (s == "NATALE") + { + g.set_month(12); + g.set_day(25); + } else + if (s == "ULTIMO") + { + g.set_month(12); + g.set_day(31); + } else + if (s != "OGGI") + ok = FALSE; + if (ok) + s = g.string(); } } - if (ch) - *ch = changed; - return fpark; + return s; +} + +const char* TDate_field::reformat(const char* str) const +{ + if (strlen(str) == 8) + str = TDate(str).string(); + return str; +} + +const char* TDate_field::raw2win( + const char* datum) const // @parm Stringa contenenete la data da formattare +{ + return reformat(datum); } bool TDate_field::on_key(KEY key) { if (to_check(key)) { - bool changed = FALSE; - - const char* data = format_data(get(), &changed); - - if (*data) // data not empty + const TString& data = get_window_data(); + if (data.not_empty()) // data not empty { if (!TDate::isdate(data)) { @@ -2868,59 +3021,59 @@ bool TDate_field::on_key(KEY key) return FALSE; } else - if (changed) - TMask_field::set_window_data(data); + set_window_data(data); + } + } + else + { + if (_ctl->is_edit_key(key)) + { + const bool ok = strchr("-0123456789ADEGILMNOPRSTUadegilmnoprstu", key) != NULL; + if (!ok) beep(); + return ok; } } return TEdit_field::on_key(key); } -bool TDate_field::autosave(TRelation* r) const +bool TDate_field::autosave(TRelation& r) const { - const char* td = get(); - if (right_justified()) - { - TDate d(td); - td = d.string(ANSI); - } if (field()) { + const char* td = get(); + if (right_justified()) + { + TDate d(td); + td = d.string(ANSI); + } field()->write(td, r); return TRUE; } return FALSE; } -const char* TDate_field::picture_data(const char* data, bool video) const -{ - return video ? format_data(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) -{ +{ + _ctl_data._flags.strip("AFM"); + _ctl_data._flags << 'R'; TEdit_field::create(w); - _flags.rightjust = TRUE; - if (_flags.firm) - set(::format("%ld", main_app().get_firm())); + if (_flags.firm) + TMask_field::set(main_app().get_firm()); else if (automagic()) - { - TDate d(TODAY); - set(::format("%d", d.year())); - } + TMask_field::set(TDate(TODAY).year()); } bool TReal_field::parse_item(TScanner& scanner) @@ -2928,7 +3081,7 @@ bool TReal_field::parse_item(TScanner& scanner) if (scanner.key() == "PI") // PICTURE { _picture = scanner.string(); - if (_picture.not_empty() && _decimals == 0) + if (_decimals == 0) { if (_picture[0] == '.') _decimals = atoi(&_picture[1]); @@ -2940,9 +3093,9 @@ bool TReal_field::parse_item(TScanner& scanner) } } #ifdef DBG - if (_size > 9 && _size != 15) + if (_ctl_data._size > 9 && _ctl_data._size != 15) ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", - dlg(), (const char*)_prompt); + _ctl_data._dlg, (const char*)_ctl_data._prompt); #endif return TRUE; } @@ -2950,46 +3103,83 @@ bool TReal_field::parse_item(TScanner& scanner) return TEdit_field::parse_item(scanner); } -bool TReal_field::autoload(const TRelation* r) +const char* TReal_field::reformat(const char* data) const { - const bool ok = TMask_field::autoload(r); - if (ok && _flags.zerofilled && _str.not_empty()) - { - int s = size(); - if (roman()) - { - s = decimals(); - if (s < 1) s = 4; - } - _str.right_just(s, '0'); - } + TString& str = _ctl_data._park; - return ok; + if (!real::is_null(data)) + { + str = data; + if (_flags.zerofilled) + { + word s = size(); + if (roman()) + { + s = decimals(); + if (s <= 0) s = 4; + } + str.right_just(s, '0'); + } + } + else + str.cut(0); + return str; } + bool TReal_field::on_key(KEY key) { if (to_check(key)) { + const TString& n = get_window_data(); if (roman()) { - const int r = atoi(get_window_data()); + const int r = atoi(n); if (r < 0) return error_box("Numero romano errato"); } else { - const char* n = get(); - if (*n && !real::is_real(n)) + if (!real::is_real(n)) return error_box("Valore numerico non valido"); - if (_flags.uppercase && *n == '-') + if (_flags.uppercase && real(n).sign() < 0) return error_box("Il numero deve essere positivo"); - if (_flags.firm) + + if (key == K_TAB && _flags.firm) { const long f = atol(n); if (f > 0 && prefix().exist(f)) main_app().set_firm(f); } } + set_window_data(raw2win(n)); + } + else + { + if (_ctl->is_edit_key(key)) + { + bool ok = TRUE; + switch (key) + { + case '.': + ok = !(_flags.zerofilled || _flags.roman || size() < 4); + break; + case ',': + ok = _decimals > 0; + break; + case '-': + ok = !_flags.uppercase; + break; + default : + if (_flags.roman) + ok = strchr("0123456789IVXLCDMivxlcdm", key) != NULL; + else + ok = strchr("0123456789", key) != NULL; + break; + } + if (!ok) + beep(); + return ok; + } } return TEdit_field::on_key(key); @@ -2997,33 +3187,35 @@ bool TReal_field::on_key(KEY key) void TReal_field::parse_head(TScanner& scanner) { - _size = scanner.integer(); + _ctl_data._size = scanner.integer(); #ifdef DBG - if (_size < 1) + if (_ctl_data._size <= 0) { - _size = 9; - yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); + _ctl_data._size = 9; + yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", _ctl_data._dlg, _ctl_data._size); } #endif - _width = _size; + _ctl_data._width = _ctl_data._size; _decimals = scanner.integer(); } -void TReal_field::set_window_data(const char* data) -{ +const char* TReal_field::raw2win(const char* data) const +{ + TString& s = _ctl_data._park; + if (data == NULL) data = ""; - + if (roman()) { - data = itor(atoi(data)); + s = itor(atoi(data)); } else { - real n(data); - if (!n.is_zero()) + if (!real::is_null(data)) { + real n(data); if (exchangeable() && decimals()) { const real& e = mask().exchange(); @@ -3031,109 +3223,73 @@ void TReal_field::set_window_data(const char* data) } if (_picture.empty()) { - const char pad = _flags.zerofilled ? '0' : ' '; - data = n.stringa(_size, _decimals, pad); + if (_flags.zerofilled) + s = n.stringa(_size, _decimals, '0'); + else + s = n.stringa(0, _decimals); } else { - fpark = n.string(_picture); - fpark.right_just(_size); - data = fpark; + s = n.string(_picture); } } - else data = ""; - } - TMask_field::set_window_data(data); + else + s.cut(0); + } + + return s; } -const char* TReal_field::get_window_data() const +const char* TReal_field::win2raw(const char* data) const { - TEdit_field::get_window_data(); + TString& str = _ctl_data._park; + if (roman()) { - int r = atoi(fpark); - if (r == 0) r = rtoi(fpark); + int r = atoi(data); + if (r == 0) // Se non e' scritto in arabo converti da romano + r = rtoi(data); if (r > 0) { - int s = decimals(); - if (s < 1) s = 4; + int d = decimals(); + if (d < 1) d = 4; if (_flags.zerofilled) - fpark.format("%0*d", s, r); + str.format("%0*d", d, r); else - fpark.format("%*d", s, r); + str.format("%*d", d, r); } - else fpark.cut(0); + else + str.cut(0); } else { - fpark = real::ita2eng(fpark); + real n(real::ita2eng(data)); if (exchangeable() && decimals()) { - real n(fpark); const real& e = mask().exchange(); n *= e; - if (n.is_zero()) fpark.cut(0); - else fpark = n.string(); + } + if (n.is_zero()) + str.cut(0); + else + { + if (_flags.zerofilled) + str = n.string(_size, _decimals, '0'); + else + str = n.string(); } } - return fpark; + return str; } -// Certified 100% -void TReal_field::set_field_data(const char* n) -{ - if (n && *n) - { - real num(n); - if (num.is_zero()) - n = ""; - else - { - fpark = num.string(0, decimals()); - if (_flags.zerofilled) - fpark.right_just(_size, '0'); - n = fpark; - } - } - TEdit_field::set_field_data(n); -} - -const char* TReal_field::picture_data(const char* data, bool video) const -{ - if (video) - { - fpark = real::ita2eng(data); - if (fpark.not_empty() && _flags.zerofilled) - fpark.right_just(_size, '0'); - } - else - { - const real n(data); - if (!n.is_zero()) - { - if (_picture.empty()) - { - const char pad = _flags.zerofilled ? '0' : ' '; - fpark = n.stringa(_size, _decimals, pad); - } - else - fpark = n.string(_picture); - } - else - fpark.cut(0); - } - - return fpark.trim(); -} - void TReal_field::set_decimals(int d) { _decimals = d; if (_picture[0] == '.') { - if (d) _picture.format(".%d", d); + if (d > 0) _picture.format(".%d", d); else _picture = "."; } } @@ -3170,13 +3326,11 @@ void TReal_field::exchange(bool show_value, const real& nuo) // List_field /////////////////////////////////////////////////////////// -TList_field::TList_field(TMask* m) : TMask_field(m) -{} +TList_field::TList_field(TMask* m) : TEditable_field(m) +{ } word TList_field::class_id() const -{ - return CLASS_LIST_FIELD; -} +{ return CLASS_LIST_FIELD; } void TList_field::read_item(TScanner& scanner) @@ -3189,19 +3343,17 @@ void TList_field::read_item(TScanner& scanner) while (scanner.popkey() == "ME") ts.add(scanner.line().strip_spaces()); scanner.push(); - - _message.add(ts); + *message(-1, TRUE) = ts; } - void TList_field::parse_head(TScanner& scanner) { - _size = scanner.integer(); - _width = scanner.integer(); - if (_width < 1) _width = _size+3; + _ctl_data._size = scanner.integer(); + _ctl_data._width = scanner.integer(); + if (_ctl_data._width == 0) + _ctl_data._width = _ctl_data._size; } - bool TList_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") // ITEM @@ -3210,18 +3362,9 @@ bool TList_field::parse_item(TScanner& 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); + return TEditable_field::parse_item(scanner); } - int TList_field::items() const { return _codes.items(); @@ -3237,30 +3380,34 @@ void TList_field::add_item( // aggiunte tante voci quanti sono gli elementi. { TToken_string t(s); - const TString16 item(t.get()); + const TString item(t.get()); const int pos = _codes.get_pos(item); - if (pos < 0 ) + if (pos < 0) { _codes.add(item); - xvt_list_add(win(), -1, (char*)t.get()); + _values.add(t.get()); + ((TListbox_control*)_ctl)->set_values(_values); } } void TList_field::delete_item(const char* s) { - TString16 t(s); + const TString t(s); const int pos = _codes.get_pos(t); if (pos >= 0 ) { _codes.destroy(pos); - xvt_list_rem(win(), pos); - if (mask().is_running()) + _values.destroy(pos); + ((TListbox_control*)_ctl)->set_values(_values); + + if (pos == current()) { - xvt_list_set_sel(win(), 0, TRUE); - if (shown()) on_hit(); + current(0); + if (active() || ghost()) + on_hit(); } } } @@ -3277,30 +3424,28 @@ void TList_field::add_list() 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"); + _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno|" + "Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); if (atoi(csafe) > 0) { _codes.add(csafe); _values.add(vsafe); - if (_message.objptr(0)) + if (message(0)) { - _message.add(_message[0], _codes.items()-1); - _message.add(NULL, 0); + *message(_codes.items()-1, TRUE) = *message(0); + message(0)->cut(0); } } - } + } + ((TListbox_control*)_ctl)->set_values(_values); - SLIST lst = xvt_slist_create(); - for (const char* item = _values.get(0); item; item = _values.get()) - xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); - xvt_list_add(win(), -1, (char*)lst); - xvt_slist_destroy(lst); - - const char* init = ""; if (roman() && automagic()) - init = format("%02d", TDate(TODAY).month()); - set_field_data(init); + { + const char* init = format("%02d", TDate(TODAY).month()); + set(init); + } + else + current(0); } // @doc EXTERNAL @@ -3316,30 +3461,23 @@ void TList_field::replace_items( _codes = codes; _values = values; - if (win() != NULL_WIN) - { - xvt_list_clear(win()); + if (_ctl) 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); + const int len = create_prompt(parent, 0, 0); + _ctl_data._x += len; + + _ctl = new TListbox_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y, + _ctl_data._width, + _ctl_data._flags, _ctl_data._prompt, _values); add_list(); } - -void TList_field::set_back_color(COLOR c) const -{ - if (_promptwin != NULL_WIN) - xvt_set_ctrl_back_color(_promptwin, c); -} - + int TList_field::str2curr(const char* data) { @@ -3375,142 +3513,76 @@ int TList_field::str2curr(const char* data) 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) -{ - xvt_list_set_sel(win(), n, TRUE); +{ + ((TListbox_control*)_ctl)->select(n); + _str = _codes.get(n); } int TList_field::current() const { - const int sel = xvt_list_get_sel_index(win()); -#ifdef DBG - if (sel < 0 && items() > 0) - error_box("Lista senza selezione nel campo %d", dlg()); -#endif - return sel; + return ((TListbox_control*)_ctl)->selected(); } -const char* TList_field::get_window_data() const +TString& TList_field::get_window_data() { const int c = current(); - const char* v = ((TList_field*)this)->_codes.get(c); - return v; -} - -void TList_field::set_field_data(const char* data) -{ - const int i = str2curr(data); - _str = _codes.get(i); + _str = ((TList_field*)this)->_codes.get(c); + return _str; } bool TList_field::on_hit() { - if (_handler) + const bool ok = handler(K_SPACE); + if (ok) { - 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; + const int n = current(); + do_message(n); + } + return ok; } bool TList_field::on_key(KEY key) { - if (key >= '0' && key <= 'z') + if (key == K_SPACE) { - const int index = current(); - CHECK(index >= 0, "List with no selection!"); - int newindex = -1; - -#if XVT_OS == XVT_OS_SCOUNIX - if (key >= 'A' && key <= 'z') + get_window_data(); + on_hit(); + } + else + if (validate_func() >= 0 && (key == K_TAB || key == K_ENTER)) { - for (int i = index+1; i != index; i++) + const bool ok = validate(key); + if (!ok) { - char item[16]; - bool flag; - - do - { - flag = xvt_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 (has_warning()) + return error_box(get_warning()); + } } - - if (newindex >= 0) - current(newindex); - /* - { - xvt_list_suspend(win()); - xvt_list_set_sel(win(), index, FALSE); - xvt_list_set_sel(win(), newindex, TRUE); - xvt_list_resume(win()); - } - */ - } - -#if XVT_OS == XVT_OS_SCOUNIX - if (key == K_TAB && class_id() == CLASS_LIST_FIELD) - dispacth_e_char(win(), K_F9); -#endif - - if (_validate_func >= 0 && (key == K_TAB || key == K_ENTER)) - { - const bool ok = ::validate(_validate_func, *this, key, _validate_parms); - if (!ok) - { - if (_warning.not_empty()) - return error_box(_warning); - } - } - - if (key == K_SPACE) on_hit(); - - return TMask_field::on_key(key); + return TEditable_field::on_key(key); } + +// Certified 100% +bool TList_field::is_kind_of(word cid) const +{ return cid == CLASS_LIST_FIELD || TEditable_field::is_kind_of(cid); } - + + /////////////////////////////////////////////////////////// // TRadio_field /////////////////////////////////////////////////////////// TRadio_field::TRadio_field(TMask* mask) -: TList_field(mask), _nitems(0), _active_item(0) -{} + : TList_field(mask) +{ } + +// Annulla _ctl altrimenti verrebbe cancellato due volte essendo anche nell'array +TRadio_field::~TRadio_field() +{ } word TRadio_field::class_id() const @@ -3521,447 +3593,190 @@ word TRadio_field::class_id() const void TRadio_field::create(WINDOW parent) { - const short id = dlg(); // Salva il control id const int items = _codes.items(); - - if (_prompt.not_empty()) + if (_ctl_data._prompt.not_empty()) { - const int dy = _flags.zerofilled ? 3 : items+2; - create_prompt(parent, _width, dy); + const word dy = _flags.zerofilled ? 3 : items+2; + create_prompt(parent, _ctl_data._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::set_back_color(COLOR c) const -{ - TList_field::set_back_color(c); - xvt_set_ctrl_back_color(win(), c); -} - - -void TRadio_field::destroy() -{ - if (_promptwin) - { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } - - for(int i = 0; i < _nitems; i++) - { - xvt_vobj_destroy(_radio_ctl_win[i]); - _radio_ctl_win[i] = NULL_WIN; - } + _ctl = new TRadiobutton_control(parent, _ctl_data._dlg, + _ctl_data._x + 1, _ctl_data._y + 1, + _ctl_data._width - 2, _flags.zerofilled ? 1 : items, + _ctl_data._flags, _values); + reset(); } int TRadio_field::current() const { - const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); + const int c = ((TRadiobutton_control*)_ctl)->get_checked(); return c; } void TRadio_field::current(int n) { - _active_item = n; - xvt_check_radio_button(win(), _radio_ctl_win, _nitems); + ((TRadiobutton_control*)_ctl)->check_button(n); } -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) - xvt_vobj_set_visible(_promptwin, on); - - for(int i = 0; i < _nitems; i++) - xvt_vobj_set_visible(_radio_ctl_win[i], on); - _flags.shown = on; -} - -// @doc EXTERNAL - -// @mfunc Sposta il focus dal radio button -// -// @rdesc Ritorna TRUE se il focus ha lasciato il radio button -bool TRadio_field::move_focus( - int d) // @parm Numero di posizioni di spostamento del focus - - // @comm Poiche' la gestione dei radio button e' gestita direttamente da Windows - // in caso si prema TAB o SHIF+TAB all'interno si passa da una voce - // all'altra e non al campo successivo o precedente. -{ - 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); -} - -void TGroup_field::set_back_color(COLOR c) const -{ - xvt_set_ctrl_back_color(win(), c); -} - -void TGroup_field::set_window_data(const char* data) -{ xvt_set_title(win(), data); } - -void TGroup_field::set_field_data(const char* data) -{ xvt_set_title(win(), data); } - /////////////////////////////////////////////////////////// // TMemo_field /////////////////////////////////////////////////////////// -TMemo_field::TMemo_field(TMask* mask) : TMask_field(mask), _te(BAD_TXEDIT), _data( "", '\n' ) +TMemo_field::TMemo_field(TMask* mask) : TEdit_field(mask) { } TMemo_field::~TMemo_field() { - _te = BAD_TXEDIT; } void TMemo_field::parse_head(TScanner& scanner) { - _width = scanner.integer(); - _size = scanner.integer(); + _ctl_data._width = scanner.integer(); + _ctl_data._height = scanner.integer(); } void TMemo_field::create(WINDOW parent) { - const short dx = _width; - const short dy = _size-1; - - TMask_field::create(parent); - - WIN_DEF wd; - wd.wtype = WO_TE; - wd.rct = resize_rect(_x, _y+1, dx, dy, WC_EDIT, parent); - wd.text = NULL; - wd.units = U_PIXELS; - wd.v.tx.attrib = TX_NOMENU | TX_BORDER | TX_AUTOVSCROLL | TX_WRAP; - wd.v.tx.font_id = xvt_dwin_get_font(TASK_WIN); - wd.v.tx.margin = wd.rct.right - wd.rct.left; - wd.v.tx.limit = 256; - wd.v.tx.tx_id = dlg(); - _te = xvt_tx_create_def(&wd, parent, NULL); - CHECK(_te != BAD_TXEDIT, "Can't create a memo field"); + create_prompt(parent, 0, 1); - enable_default(); // Setta colori default + if (_ctl_data._height > 1) + _ctl_data._height--; + + _size = 8192; + _ctl = new TMultiline_control(parent, _ctl_data._dlg, + _ctl_data._x, _ctl_data._y+1, + _ctl_data._width, _ctl_data._height, _size, + _ctl_data._flags, ""); +} + +// Certified 100% +// Aggiusta un valore letto da file in formato RAW +const char* TMemo_field::reformat(const char* data) const +{ + return data; } -void TMemo_field::highlight() const +const char* TMemo_field::raw2win(const char* data) const { - xvt_tx_set_active(_te); + if (strchr(data, '\n') == NULL) + return data; + + TString& s = _ctl_data._park; + s = data; + for (int i = 0; s[i]; i++) + if (s[i] == '\n') s[i] = '\r'; + return s; +} + +const char* TMemo_field::win2raw(const char* data) const +{ + if (strchr(data, '\r') == NULL) + return data; + _ctl_data._park = data; + for (char* s = (char*)(const char*)_ctl_data._park; *s; s++) + if (*s == '\r') *s = '\n'; + return _ctl_data._park; } bool TMemo_field::on_key(KEY k) { - return TMask_field::on_key(k); + if (k == K_TAB && focusdirty()) + get_window_data(); + return TEdit_field::on_key(k); } -void TMemo_field::enable(bool on) + +/////////////////////////////////////////////////////////// +// Zoom_field +/////////////////////////////////////////////////////////// + +TZoom_field::TZoom_field(TMask* mask) + : TEdit_field(mask) { - TMask_field::enable( TRUE ); - - unsigned attr = xvt_tx_get_attr(_te); - if (on) - { - xvt_tx_set_colors(_te, NORMAL_COLOR, COLOR_BLACK, NORMAL_BACK_COLOR); - attr &= ~TX_READONLY; - } - else - { - xvt_tx_set_colors(_te, DISABLED_COLOR, COLOR_BLACK, DISABLED_BACK_COLOR); - attr |= TX_READONLY; - } - xvt_tx_set_attr(_te, attr); -} - -void TMemo_field::show(bool on) -{ - TMask_field::show(on); -} - -/* - bool TMemo_field::autoload(const TRelation* r) - { - const TFieldref* f = field(); - xvt_tx_clear(_te); - if (f != NULL) - { - TToken_string data( r->lfile( f->file( ) ).get( f->name( ) ), '\n' ); - xvt_tx_suspend(_te); - for (T_LNUM i = 0; i < (T_LNUM)data.items( ); i++) - xvt_tx_add_par(_te, i, ( char * )data.get( i ) ); - xvt_tx_resume(_te); - return i > 0; - } - return FALSE; - } - - bool TMemo_field::autosave(TRelation* r) const - { - const TFieldref* f = field(); - if (dirty() && f != NULL) - { - const T_PNUM num_par = xvt_tx_get_num_pars(_te); - TToken_string data( "", '\n' ); - TString par(256); - TString256 line; - - for (T_PNUM p = 0; p < num_par; p++) - { - par.cut(0); - const T_LNUM lines = xvt_tx_get_num_par_lines(_te, p); - for (T_LNUM l = 0; l < lines; l++) - { - unsigned len; - xvt_tx_get_line(_te, p, A_LOCK, l, &len); - const char* s = xvt_tx_get_line(_te, p, A_GET, l, &len); - CHECK(s, "Null memo line"); - line.strncpy(s, len); - xvt_tx_get_line(_te, p, A_UNLOCK, l, &len); - - if (par.not_empty()) par << ' '; - par << line; - } - data.add(par); - } - r->lfile(f->file()).put( f->name(), data ); - return num_par > 0; - } - return FALSE; - } - */ - -void TMemo_field::set_window_data(const char* data) -{ - TToken_string realdata( data, '\n' ); - xvt_tx_clear(_te); - xvt_tx_suspend(_te); - for (T_LNUM i = 0; i < (T_LNUM)realdata.items( ); i++) - xvt_tx_add_par(_te, i, ( char * )realdata.get( i ) ); - xvt_tx_resume(_te); -} - -const char* TMemo_field::get_window_data() const -{ - const T_PNUM num_par = xvt_tx_get_num_pars(_te); - TToken_string data( "", '\n' ); - TString par(256); - TString256 line; - - for (T_PNUM p = 0; p < num_par; p++) - { - par.cut(0); - const T_LNUM lines = xvt_tx_get_num_par_lines(_te, p); - for (T_LNUM l = 0; l < lines; l++) - { - unsigned len; - xvt_tx_get_line(_te, p, A_LOCK, l, &len); - const char* s = xvt_tx_get_line(_te, p, A_GET, l, &len); - CHECK(s, "Null memo line"); - line.strncpy(s, len); - xvt_tx_get_line(_te, p, A_UNLOCK, l, &len); - if (par.not_empty()) par << ' '; - par << line; - } - data.add(par); - } - return data; -} - -void TMemo_field::set_field_data(const char* data ) -{ - _data = data; -} - -const char* TMemo_field::get_field_data() const -{ - return _data; -} - - -void TZoom_field::set_window_data( const char* data ) -{ - TToken_string getfl( data, '\n' ); - TString spark( getfl.get( 0 ) ); - TEdit_field::set_window_data( spark ); - // set_first_line( spark ); -} - -const char* TZoom_field::get_window_data( ) const -{ - TToken_string& m = (TToken_string&)_memo; - const int pos = m.find('\n'); - TString park; - if (pos >= 0) - park=&(m[pos+1]); - m = TEdit_field::get_window_data(); - if (pos >= 0 ) - m << '\n' << park; - return _memo; -} - -void TZoom_field::set_field_data( const char* data ) -{ - _memo = data; -} - -const char* TZoom_field::get_field_data( ) const -{ - return _memo; -} - -bool TZoom_field::on_key( KEY key ) -{ - if ( key == K_F8 ) - { - set_first_line( get_window_data( ) ); - TMask m( "Zoom", 1, 72, 15 ); - m.add_memo( 101, 0, prompt(), 2, 2, 68, 10 ); - m.add_button( DLG_OK, 0, "", -12, 13, 9, 2 ); - m.add_button( DLG_CANCEL, 0, "", -22, 13, 9, 2 ); - m.set( 101, _memo ); - if ( m.run( ) != K_ESC ) - { - _memo = m.get(101); - TString line(get_first_line()); - if (line.len() > size()) line.cut(size()); - set_window_data( line ); - } - } - return TEdit_field::on_key( key ); -} - -void TZoom_field::enable(bool on) -{ - TEdit_field::enable(on); - if (_buttonzoom != NULL_WIN) - xvt_vobj_set_visible(_buttonzoom, on && shown()); -} - -void TZoom_field::show(bool on) -{ - TEdit_field::show(on); - if (_buttonzoom != NULL_WIN) - xvt_vobj_set_visible(_buttonzoom, on && enabled()); -} - -TZoom_field::TZoom_field( TMask* mask ) : TEdit_field( mask ), _memo( "", '\n' ) -{ - } TZoom_field::~TZoom_field( ) { - } - -const char *TZoom_field::get_first_line( ) -{ - return _memo.get( 0 ); -} - -void TZoom_field::set_first_line( const char * c ) -{ - TToken_string gfl( c, '\n' ); - TString spark( gfl.get( 0 ) ); - TString park; - const int pos = _memo.find('\n'); - if (pos >= 0) - park=&(_memo[pos+1]); - _memo = spark; - if (pos >= 0 ) - _memo << '\n' << park; - // _memo.destroy( 1 ); -} - void TZoom_field::create(WINDOW parent) { - TEdit_field::create( parent ); - -#if XVT_OS == XVT_OS_SCOUNIX - int delta = 2; -#else - int delta = 1; -#endif - - if (_browse || _sheet) delta += 2; - _buttonzoom = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, - 2, 1, "Z", parent, default_flags(), PTR_LONG(this), DLG_F8); + _ctl_data._flags << 'B'; + TEdit_field::create(parent); } -void TZoom_field::destroy() +bool TZoom_field::on_key( KEY key ) +{ + switch (key) + { + case K_TAB: + if (focusdirty()) + get_window_data(); + break; + case K_F9: + if (has_query()) + break; + case K_F8: + { + get_window_data(); + TMask m("Zoom", 1, 72, 18); + m.add_memo(101, 0, prompt(), 1, 0, -1, -3); + m.add_button(DLG_OK, 0, "Conferma", -12, -1, 9, 2); + m.add_button(DLG_CANCEL, 0, "Annulla", -22, -1, 9, 2); + m.set(101, _str); + if (m.run() != K_ESC) + { + _str = m.get(101); + set_window_data(raw2win(_str)); + } + return TRUE; + } + break; + default: + break; + } + return TEdit_field::on_key(key); +} + +// Certified 100% +// Aggiusta un valore letto da file in formato RAW +const char* TZoom_field::reformat(const char* data) const { - if (_buttonzoom) - { xvt_vobj_destroy(_buttonzoom); _buttonwin = NULL_WIN; } - TEdit_field::destroy(); + return data; } +const char* TZoom_field::raw2win(const char* data) const +{ + char* n = strchr(data, '\n'); + if (n != NULL) *n = '\0'; + _ctl_data._park = data; + if (n != NULL) *n = '\n'; + return _ctl_data._park; +} + +const char* TZoom_field::win2raw(const char* data) const +{ + TString& str = _ctl_data._park; + str = data; + + // Elimino improbabili righe successive da data + int a_capo = str.find('\r'); + if (a_capo >= 0) str.cut(a_capo); + + // Aggiungo le righe del memo a partire dalla seconda + a_capo = _str.find('\n'); + if (a_capo >= 0) + { + const char* d = _str; + str << (d+a_capo); + } + + return str; +} + +const char* TZoom_field::get_first_line() const +{ return raw2win(_str); } diff --git a/include/maskfld.h b/include/maskfld.h index a6882249e..5dbf88c92 100755 --- a/include/maskfld.h +++ b/include/maskfld.h @@ -13,17 +13,18 @@ #include #endif -class TMask_field; +class TControl; // __CONTROL_H +class TText_control; +class TPushbutton_control; -class TRelation; // __RELATION_H +class TRelation; // __RELATION_H class TCursor; class TFieldref; + class TArray_sheet; // __SHEET_H -// @doc EXTERNAL +class TMask_field; // Convenience -// @type CONTROL_HANDLER | Prototipo funzione per gestire i tasti speciali all'interno di un controllo -typedef bool (*CONTROL_HANDLER)(TMask_field& field, KEY key); // @doc EXTERNAL @@ -42,6 +43,9 @@ enum CheckTime { RUNNING_CHECK, // @emem Check chiamato mentra la maschera sta andando STARTING_CHECK, // @emem Check chiamato al caricamento della maschera FINAL_CHECK }; // @emem Check chiamato quando la maschera si sta fermando + +// @type CONTROL_HANDLER | Prototipo funzione per gestire i tasti speciali all'interno di un controllo +typedef bool (*CONTROL_HANDLER)(TMask_field& field, KEY key); // @doc EXTERNAL @@ -51,8 +55,6 @@ enum CheckTime { // @base public | TObject class TMask_field : public TObject // @author:(INTERNAL)Guido - - { // @cfriend TMask friend class TMask; @@ -61,50 +63,34 @@ class TMask_field : public TObject // @cmember:(INTERNAL) Maschera all'interno del quale e' contenuto il campo TMask* _mask; - // @cmember:(INTERNAL) Messaggio di help del campo - TString _help; - // @cmember:(INTERNAL) Campo corrispondente sul file - TFieldref* _field; - // @cmember:(INTERNAL) Chiave al quale appartiene il campo - TBit_array _keys; - // @cmember:(INTERNAL) Gruppo al quale appartiene il campo - TBit_array _groups; - // @cmember:(INTERNAL) Stringa definibile dall'utilizzatore della classe da utilizzare a piacimento - TToken_string _userdata; + // @cmember:(INTERNAL) Gruppi cui appartiene il campo + TBit_array* _groups; // @access Protected Member protected: - // @cmember Coordinata x del controllo (in caratteri) - static int _x; - // @cmember Coordinata y del controllo (in caratteri) - static int _y; - // @cmember Dimensione del controllo (in caratteri) - static int _width; - // @cmember Prompt del controllo - static TString80 _prompt; - // @cmember Handler del controllo - CONTROL_HANDLER _handler; - - // @cmember Massima lunghezza del campo - int _size; - - // @cmember Finestra del controllo (not its parent!) - WINDOW _win; - // @cmember Finestra del prompt del controllo - WINDOW _promptwin; - // @cmember Identificatore del controllo - short _dlg; - - // @cmember Identificatore della funzione di validazione - int _validate_func; - // @cmember Parametri da passara alla funzione di validazione - TArray _validate_parms; - // @cmember Warning da segnalare in caso di dato errato del campo - TString _warning; - // @cmember Messaggi da mandare in caso di modifica del controllo - TArray _message; + // @cmember Controllo vero e proprio + TControl* _ctl; + // @cmember + // @comm Struttura usata solo durante la creazione di un controllo + struct TControl_data + { + short _dlg; // Identifier + short _x, _y; // Position + short _width; // Width + short _height; // Height + word _size; // Buffer size + short _decimals; // Precision + TString _prompt; // Prompt + TString _flags; // Flags + short _bmp_up; // Bitmap up + short _bmp_dn; // Bitmap down + TToken_string _park; // Work string + void reset(); + }; + static TControl_data _ctl_data; + // @cmember | _flags | | Flag indicante lo stato del campo struct TField_Flags { @@ -127,7 +113,6 @@ protected: bool zerofilled : 1; bool pipeallowed : 1; - TField_Flags(); char update(const char*); } _flags; @@ -137,58 +122,37 @@ protected: // @cmember Costruisce il campo con i suoi parametri void construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags = "", int width = 0); - // @cmember Ritorna la finestra di appartenenza del campo - virtual WINDOW win() const - { return _win; } - - // @cmember Crea la finestra del controllo - WINDOW wincreate(WIN_TYPE ct, short dx, short dy, const char* title, WINDOW parent, long flags); - // @cmember Crea il prompt del controllo - int create_prompt(WINDOW parent, int width = 0, int heigth = 1); - - // @cmember Ritorna i flags nativi di default del campo - long default_flags() const; - // @cmember Legge la testata del controllo dal file .msk

virtual void parse_head(TScanner& scanner); // @cmember Legge una riga di definizione del controllo dal file .msk

virtual bool parse_item(TScanner& scanner); // @cmember Crea il controllo (chiama ) - virtual void create(WINDOW parent); - // @cmember Distrugge il contrllo - virtual void destroy(); + virtual void create(WINDOW parent) pure; + // @cmember Setta il focus sul campo virtual void highlight() const; - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; - // @cmember Permette di settare il valore del cambio del campo - virtual void exchange(bool show_value, const real& n) - {} - - // @cmember Esegue il messaggio

-esimo sul campo - bool do_message(int n); + // @cmember Manda al campo

un tasto (chiama ) + void send_key(KEY k, short to); // @access Public Member +public: // TObject + virtual bool is_kind_of(word cid) const; + public: - // @cmember Converte una stringa in un identificatore del controllo + // @cmember Converte una stringa in un identificatore di controllo short atodlg(const char* s) const; // @cmember Ritorna la finestra padre WINDOW parent() const; + RCT& get_rect(RCT& r) const; + void set_rect(const RCT& r); + // @cmember Ritorna l'identificatore del controllo - short dlg() const - { return _dlg; } + short dlg() const; + // @cmember Controlla se si tratta di un controllo corretto virtual bool ok() const; @@ -215,6 +179,10 @@ public: // @cmember Verifica la giustificazione a destra del campo bool right_justified() const { return _flags.rightjust; } + + // @cmember Ritorna TRUE se il campo e' in maiuscolo + bool uppercase() const + { return _flags.uppercase; } // @cmember Verifica la allowance of the pipe bool pipe_allowed() const @@ -229,10 +197,6 @@ public: // @cmember Ritorna l'identificatore della classe virtual word class_id() const; - // @cmember Ritorna la massima lunghezza della stringa - int size() const - { return _size; } - // @cmember Ritorna TRUE se il campo e' un numero romano bool roman() const { return _flags.roman; } @@ -245,23 +209,30 @@ public: // @cmember Ritorna TRUE se si tratta di campo in valuta bool exchangeable() const { return _flags.exchange; } - + + // @cmember Controlla se il campo appartiene ad un achiave di ricerca + virtual bool in_key(byte) const + { return FALSE; } // @cmember Controlla se il campo ha un check virtual bool has_check() const { return FALSE;} // @cmember Controlla se il campo ha una richiesta virtual bool has_query() const { return FALSE;} - // @cmember Controlla se il campo ha un messaggio - virtual bool has_message() const - { return _message.items() > 0; } + // @cmember Ritorna il campo corrispondente su record + virtual const TFieldref* field() const + { return NULL; } + // @cmember Ritorna il tipo di checktype del campo + virtual void check_type(CheckType); + // @cmember Ritorna lo stato di checktype del campo virtual CheckType check_type() const { return CHECK_NONE; } // @cmember Ritorna TRUE se il checktype del campo e

bool required() const { return check_type() == CHECK_REQUIRED; } + // @cmember Controlla la validita' del campo virtual bool check(CheckTime = RUNNING_CHECK) { return TRUE;} @@ -271,6 +242,7 @@ public: // @cmember Abilita/disabilita il campo (lo rende scrivibile) virtual void enable(bool on = TRUE); + // @cmember Abilita/disabilita il campo (chiama ) void disable() { enable(FALSE); } @@ -291,6 +263,10 @@ public: // @cmember Ritorna TRUE se il campo e' visibile bool shown() const { return _flags.shown; } + // @cmember Ritorna TRUE se il campo e' nascosto + bool hidden() const + { return !shown(); } + // @cmember Rimette lo stato di in/visibilta' del campo a seconda di come era // settato sul file void show_default(); @@ -299,79 +275,52 @@ public: bool active() const; // @cmember Setta l'handler del controllo - void set_handler(CONTROL_HANDLER handler) - { _handler = handler; } - + virtual void set_handler(CONTROL_HANDLER); + + // @cmember Ritorna TRUE se il campo e' di tipo operable + virtual bool is_operable() const { return FALSE; } + // @cmember Ritorna TRUE se il campo e' di tipo editable + virtual bool is_editable() const { return FALSE; } // @cmember Ritorna TRUE se il campo e' di tipo edit virtual bool is_edit() const { return FALSE; } + // @cmember Permette di spedire il check bool to_check(KEY k, bool checkrun = FALSE) const; // @cmember Gestisce la chiamata all'handler del campo virtual bool on_hit(); + // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY key); - // @cmember Serve per eseguire gli handler autoprementi (TRUE se il focus e' cambiato) - virtual bool test_focus_change(); // @cmember Setta il contenuto del campo inserendo la stringa

- void set(const char* s); + virtual void set(const char* s); + + // @cmember Setta il contenuto del campo inserendo in numero

+ void set(long n); + // @cmember Ritorna il contenuto del campo - TString& get() const; + virtual const TString& get() const; - // @cmember Ritorna il valore di _userdata - TToken_string& custom_data() - { return _userdata; }; - - // @cmember Permette di dare la stessa formattazione del campo della maschera - virtual const char* picture_data(const char* data, bool video) const; - // @cmember Ritorna il warning del campo - virtual const char* warning() const - { return _warning;} - - // @cmember Legge dalla relazione il valore del campo - virtual bool autoload(const TRelation* r = NULL); - // @cmember Scrive sulla relazione il valore del campo - virtual bool autosave(TRelation* r = NULL) const; - - // @cmember Riporta il valore iniziale del campo (annulla le modifiche) - void undo(); - - // @cmember Ritorna uil prompt del cmpo - const char* prompt() const; + virtual bool empty() const { return FALSE; } + + // @cmember Ritorna la dimensione del buffer associato al campo + virtual word size() const { return 0; } + + // @cmember Ritorna il prompt del campo + virtual const char* prompt() const; // @cmember Setta il prompt del campo - void set_prompt(const char* p); - - // @cmember Controlla se il campo appartiene alla chiave

(TRUE se appartiene) - bool in_key(byte key) const - { return _keys[key]; } - // @cmember Setta il campo alla chiave

- void set_key(byte key) - { _keys.set(long(key)); _keys.set(0L);} - // @cmember Rimuove il campo dalla chiave

- void reset_key(byte key); - // @cmember Ritorna l'ultima chiave di appartenenza del campo - word last_key() const; + virtual void set_prompt(const char* p); // @cmember Controlla se il campo appartiene al gurppo

(TRUE se appartiene) bool in_group(byte group) const - { return _groups[group]; } + { return _groups ? (*_groups)[group] : FALSE; } // @cmember Assegna il campo al grupo

- void set_group(byte group) - { _groups.set(long(group)); _groups.set(0L);} - - // @cmember Ritorna il nome del campo corrsipondente sul file - const TFieldref* field() const - { return _field; } - // @cmember Setta il nome del campo corrsipondente sul file - void set_field(const TString& fr); - - // @cmember Setta il focus sul campo - void set_focus() const; - // @cmember Manda al campo l'identificatore di un tasto (chiama ) - void send_key(KEY k, short to); + void set_group(byte group); - // set focus, message-box, set focus + // @cmember Setta il focus al campo + virtual void set_focus() const; + // @cmember Crea una message-box relativo al campo (chiama ) bool message_box(const char* fmt, ...) const; // @cmember Crea una warning-box relativo al campo (chiama ) @@ -382,7 +331,7 @@ public: bool yesno_box(const char* fmt, ...) const; // @cmember Crea una yesnocancel-box relativo al campo (chiama ) KEY yesnocancel_box(const char* fmt, ...) const; - + // @cmember Ritorna un reference alla maschera di appartenenza del campo TMask& mask() const { return *_mask; } @@ -420,138 +369,397 @@ public: // @doc EXTERNAL -// @class TEdit_field | Classe per la definizione dei campi editabili + +class TText_field : public TMask_field +{ +protected: + virtual void create(WINDOW parent); + +public: // TObject + word class_id() const; + bool is_kind_of(word cid) const; + +public: + TText_field(TMask* m) : TMask_field(m) {} + virtual ~TText_field() {} +}; + +// @doc EXTERNAL + +// @class TGroup_field | Classe per la gestione del disegno dei group box // // @base public | TMask_field -class TEdit_field : public TMask_field - +class TGroup_field : public TMask_field +// @author:(INTERNAL) Guido { - // @cfriend TBrowse - friend class TBrowse; - // @cfriend TList_sheet - friend class TList_sheet; - // @cfriend TBrowse_sheet - friend class TBrowse_sheet; - // @access Protected Member protected: - // @cmember Valore del campo - TString _str; - // @cmember Formato che deve avere il campo - TString _picture; - // @cmember Accettabilita' di valori nulli - CheckType _check; - // @cmember Controllo da effettuare anche in - bool _forced; - // @cmember Controllo abilitato - bool _check_enabled; - // @cmember Oggetto che contiene la ricerca e il controllo del campo - TBrowse* _browse; - // @cmember Oggetto che contiene la ricerca e il controllo del campo - TList_sheet* _sheet; - // @cmember Finestra del bottone di ricerca del campo - WINDOW _buttonwin; + // @cmember Legge un item del controllo dal file

+ virtual void parse_head(TScanner& scanner); + // @cmember Crea il controllo + virtual void create(WINDOW parent); - // @cmember Ritorna la browse - const TBrowse* get_browse(TScanner& scanner) const; + // @access Public Member +public: + // @cmember Costruttore + TGroup_field(TMask* mask); + virtual ~TGroup_field() {} +}; + + +class TOperable_field : public TMask_field +{ + // @cmember Comandi da eseguire in caso di modifica del campo + TString_array* _message; + + // @cmember Handler del controllo + CONTROL_HANDLER _handler; + +protected: // TMask_field + bool handler(KEY k); + + virtual bool parse_item(TScanner& scanner); + virtual bool is_operable() const { return TRUE; } + virtual bool on_hit(); + + TToken_string* message(int m, bool crea = FALSE); + + // @cmember Setta il focus sul campo + virtual void highlight() const; + +public: + + // @cmember Esegue processo in background + virtual void on_idle() {} + + // @cmember Esegue il messaggio

-esimo sul campo + bool do_message(int n); + + // @cmember Controlla se il campo ha un messaggio + virtual bool has_message() const + { return _message != NULL; } + + // @cmember Setta l'handler del controllo + virtual void set_handler(CONTROL_HANDLER handler) + { _handler = handler; } + + // @cmember Setta il focus al campo + virtual void set_focus() const; + + // @cmember Gestisce il tasto

+ virtual bool on_key(KEY k); + + // @cmember Abilita/disabilita il campo (lo rende scrivibile) (vedi ) + virtual void enable(bool on = TRUE); + + // @cmember Setta il valore del cambio nel campo + virtual void exchange(bool, const real&) { } + + TOperable_field(TMask* m); + virtual ~TOperable_field(); +}; + +// @doc EXTERNAL + +// @class TButton_field | Classe per la gestione dei campi bottone +// +// @base public | TMask_field +class TButton_field : public TOperable_field + +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Member + + // @cmember:(INTERNAL) Valore della combinazione di tasti che sostituisce il bottone + KEY _virtual_key; + // @cmember:(INTERNAL) Tasto generato quando viene premuto il bottone che si sta gestendo + KEY _exit_key; + + // @access Protected Member +protected: // @cmember Ritorna l'identificatore della classe virtual word class_id() const; - // @cmember Legge la testata del controllo dal file

- virtual void parse_head(TScanner& scanner); - // @cmember Legge un item del controllo dal file

- virtual bool parse_item(TScanner& scanner); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - virtual bool is_edit() const { return TRUE; } + // @cmember Ritorna TRUE se il controllo deriva dalla classe cid + virtual bool is_kind_of(word cid) const; // @cmember Crea il controllo virtual void create(WINDOW parent); - // @cmember Distrugge il contrllo - virtual void destroy(); - // @cmember Chiama l' eventuale funzione di validazione - bool validate(KEY k); + // @cmember Legge un item del controllo dal file

+ void parse_head(TScanner& scanner); + // @cmember Legge un item del controllo dal file

+ bool parse_item(TScanner& scanner); - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; - // @cmember Mostra un messaggio di errore di default per il campo - bool default_error_box() const; + // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) + virtual bool on_key(KEY key); - // @access Public Member public: + // @cmember Ritorna il valore della combinazione di tasti che sostiutiscono il bottone + KEY virtual_key() const + { return _virtual_key; } + // @cmember Ritorna il valore del tasto di uscita + KEY exit_key() const + { return _exit_key; } + + void set_hot_key(KEY k) { _virtual_key = _exit_key = k; } + void set_bmp(short up, short dn); + + // @cmember Costruttore + TButton_field(TMask* mask); + virtual ~TButton_field() {} +}; + +class TEditable_field : public TOperable_field +{ + // @cmember Campo su file + TFieldref* _field; + + // @cmember:(INTERNAL) Prompt del campo + TText_control* _prompt; + + // @cmember:(INTERNAL) Chiave al quale appartiene il campo + TBit_array* _keys; + + // @cmember Messaggi da mandare in caso di errore sul campo + TString* _warning; + + // @cmember:(INTERNAL) Stringa definibile dall'utilizzatore della classe da utilizzare a piacimento + TToken_string* _userdata; + + struct TValidation_data + { + // @cmember Identificatore della funzione di validazione + int _func; + // @cmember Parametri da passara alla funzione di validazione + TArray _parms; + }; + TValidation_data* _validate; + +protected: // TMask_field + virtual bool parse_item(TScanner& scanner); + +protected: + // @cmember Valore corrente del campo + TString _str; + + word create_prompt(WINDOW parent, word width, word heigth); + + virtual const char* reformat(const char* data) const; + virtual TString& get_window_data() pure; + virtual void set_window_data(const char* data) pure; + + int validate_func() const { return _validate ? _validate->_func : -1; } + +public: // TMask_field + // @cmember Ritorna il prompt del campo + virtual const char* prompt() const; + +public: + bool test_key_complete(bool normal = TRUE) const; + // @cmember Controlla se il campo appartiene alla chiave

(TRUE se appartiene) + bool in_key(byte key) const + { return _keys ? (*_keys)[key] : FALSE; } + // @cmember Setta il campo alla chiave

+ void set_key(byte key); + // @cmember Rimuove il campo dalla chiave

+ void reset_key(byte key); + // @cmember Ritorna l'ultima chiave di appartenenza del campo + word last_key() const; + // @cmember Ritorna l'ultima chiave di appartenenza del campo + word first_key() const; + + // @cmember Ritorna il nome del campo corrsipondente sul file + virtual const TFieldref* field() const + { return _field; } + // @cmember Setta il nome del campo corrsipondente sul file + void set_field(const TString& fr); + + // @cmember Legge dalla relazione il valore del campo + bool autoload(const TRelation& r); + + // @cmember Scrive sulla relazione il valore del campo + virtual bool autosave(TRelation& r) const; + + // @cmember Chiama l' eventuale funzione di validazione + bool validate(KEY k); + + bool has_warning() const { return _warning != NULL; } + void set_warning(const char* w); + const char* get_warning() const; + + virtual void show(bool on); + + virtual void set_prompt(const char* p); + + // @cmember Setta il contenuto del campo inserendo la stringa

+ virtual void set(const char* s); + + // @cmember Ritorna il contenuto del campo + virtual const TString& get() const; + + // @cmember Trasforma una stringa su file una rappresentabile a video + virtual const char* raw2win(const char* r) const; + + // @cmember Trasforma una stringa a video in un valore su file + virtual const char* win2raw(const char* w) const; + + // @cmember Ritorna TRUE se il campo e' di tipo editable + virtual bool is_editable() const { return TRUE; } + + TEditable_field(TMask* m); + virtual ~TEditable_field(); +}; + + +// @doc EXTERNAL + +// @class TBoolean_field | Classe per la gestione dei campi boolean (check box) +// +// @base public | TEditable_field +class TBoolean_field : public TEditable_field + +// @author:(INTERNAL) Guido +{ + // @access Protected Member +protected: // TMask_field + // @cmember Ritorna l'identificatore della classe + virtual word class_id() const; + + // @cmember Crea il controllo + virtual void create(WINDOW parent); + + // @cmember Legge un item del controllo dal file

+ virtual bool parse_item(TScanner& scanner); + +protected: // TOperable // @cmember Gestisce la chiamata all'handler del campo virtual bool on_hit(); // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY key); - // @cmember Controlla se il campo ha un check - virtual bool has_check() const; - // @cmember Controlla se il campo ha una ricerca - virtual bool has_query() const - { return _browse || _sheet;} - // @cmember Permette di dare la stessa formattazione del campo della maschera - // (vedi ) - virtual const char* picture_data(const char* data, bool video) const; - // @cmember Permette di rendere visibile/invisibile un campo (vedi ) - virtual void show(bool on = TRUE); - // @cmember Abilita/disabilita il campo (lo rende scrivibile) (vedi ) - virtual void enable(bool on = TRUE); - // @cmember Ritorna il tipo di check assegnato al campo (vedi ) - virtual CheckType check_type() const - { return _check; } - // @cmember Setta il tipo di check da assegnare al campo (vedi ) - void check_type(CheckType c) - { _check = c; } - - // @cmember Controlla se un campo e' forced - bool forced() const - { return _forced;} - // @cmember Esegue il controllo - virtual bool check(CheckTime = RUNNING_CHECK); - // @cmember Ritorna l'oggetto _browse - TBrowse* browse() const - { return _browse;} - // @cmember Ritorna l'oggetto _sheet - TList_sheet* sheet() const - { return _sheet;} - // @cmember Permette di abilitare/disabilitare un check di un campo - void enable_check(bool on = TRUE) ; - // @cmember Controlla se un campo ha abilitato o disabilitato i check (TRUE se abilitato) - bool check_enabled() const - { return _check_enabled;} - - // @cmember Ritorna

formattato secondo i flags settati del campo - const char* format(const char* data) const; - // @cmember Ritorna la picture del campo - const char* picture() const - { return _picture; } +protected: // TEditable + // @cmember Riaggiusta una stringa in formato RAW + virtual const char* reformat(const char* raw) const; + virtual TString& get_window_data(); + virtual void set_window_data(const char* data); + virtual void set_prompt(const char* p); + + // @access Public Members +public: // @cmember Costruttore - TEdit_field(TMask* mask); + TBoolean_field(TMask* mask); + // @cmember Distruttore - virtual ~TEdit_field(); + virtual ~TBoolean_field() {} +}; + + +/////////////////////////////////////////////////////////// +// TBrowse_button +/////////////////////////////////////////////////////////// + +class TEdit_field; + +class TBrowse_button : public TObject +{ + TEdit_field* _fld; + +protected: + // @cmember Ritorna il primo valore di

+ TEdit_field& field() const + { return *_fld; } + + // @cmember Ritorna il campo

-esimo + TEditable_field& field(short id) const; + +public: + // @cmember Controlla la sintassi della input del campo e ne setta i membri + virtual void parse_input(TScanner& scanner) pure; + + // @cmember Controlla la sintassi della output del campo e ne setta i membri + virtual void parse_output(TScanner& scanner) pure; + + virtual KEY run() pure; + + // @cmember Controlla la validita' del campo + virtual bool check(CheckTime = RUNNING_CHECK) pure; + + virtual bool is_browse() const { return FALSE; } + + TBrowse_button(TEdit_field* f); + virtual ~TBrowse_button(); }; /////////////////////////////////////////////////////////// // TBrowse /////////////////////////////////////////////////////////// + +// @class TList_sheet | Classe per la gestione dei list sheet +class TList_sheet : public TBrowse_button +// @author:(INTERNAL) Guido +{ + // @access:(INTERNAL) Private Memeber + // @cmember:(INTERNAL) Numero di riga corrente dello sheet + int _row; + + // @cmember:(INTERNAL) Titolo dello sheet + TString _caption; + + // @cmember:(INTERNAL) Testate delle colonne dello sheet + TToken_string _head; + + // @cmember:(INTERNAL) Righe dello sheet + TString_array _data; + + // @cmember:(INTERNAL) Campi di input sulla maschera + TToken_string _inp_id; + + // @cmember:(INTERNAL) Campi di output sulla maschera + TToken_string _out_id; + + // @access Protected Member +protected: + // @cmember Ritorna il numero di riga selezionata + int do_input(); + // @cmember Scrive l'output della ricerca sulla maschera + void do_output(CheckTime = RUNNING_CHECK); + + // @cmember Controlla la sintassi della input del campo e ne setta i membri + void parse_input(TScanner& scanner); + // @cmember Controlla la sintassi della output del campo e ne setta i membri + void parse_output(TScanner& scanner); + + // @access Public Memeber +public: + // @cmember Legge dal file gli item dello sheet + void parse_item(TScanner& scanner); + + // @cmember Controlla la validita' del campo + virtual bool check(CheckTime = RUNNING_CHECK); + + // @cmember Esegue la ricerca. Torna il tasto che ha terminato la ricerca + virtual KEY run(); + + TString_array& rows_array() { return _data; } + + // @cmember Costruttore + TList_sheet(TEdit_field* f, const char* caption, const char* head); + // @cmember Distruttore + virtual ~TList_sheet(); +}; + // @doc INTERNAL // @class TBrowse | Classe per la definizione dei campi con ricerca -class TBrowse +class TBrowse : public TBrowse_button // @author:(INTERNAL) Guido { // @access:(INTERNAL) Private Member - // @cmember:(INTERNAL) Campo che possiode lo sheet - TEdit_field* _fld; // @cmember:(INTERNAL) Relazione della ricerca TRelation* _relation; // @cmember:(INTERNAL) Cursore sulla relazione @@ -582,26 +790,32 @@ class TBrowse // @access Protected Member protected: - // @cmember Scrive l'output della ricerca sulla maschera - void do_output(CheckTime = RUNNING_CHECK); // @cmember Azzera i campi di output sulla maschera void do_clear(); // @cmember Chiama la maschera di gestione della ricerca - bool do_insert(); + bool do_link(bool insert); - // @cmember Ritorna il campo

-esimo - TMask_field& field(short n) const; - // @cmember !!!!!!piu' d'uno + // @cmember Crea lista identificatori di ricerca TToken_string& create_siblings(TToken_string& siblings); // @access Public Member public: // @cmember Ritorna il numero di inputs senza contare quelli che funzionano // solo da filtro - int inputs(); + int input_fields(); + + // @cmember Ritorna la lista completa dei campi di input + const char* get_input_fields() const; + + // @cmember Ritorna la lista completa dei campi di output + const char* get_output_fields() const; + // @cmember Ritorna il numero di campi non vuoti e non filtrati int do_input(bool filter = FALSE); + // @cmember Scrive l'output della ricerca sulla maschera + void do_output(CheckTime = RUNNING_CHECK); + // @cmember Costruttore TBrowse(TEdit_field* f, TRelation* r, int key = 1, const char* filter = ""); // @cmember Costruttore @@ -632,10 +846,6 @@ public: const TString& get_filter() const { return _filter;} - // @cmember Ritorna il primo valore di

- TEdit_field& field() const - { return *_fld; } - // @cmember Controlla la validita' del campo bool check(CheckTime = RUNNING_CHECK); // @cmember Controlla se il campo puo' essere vuoto @@ -655,71 +865,136 @@ public: // @cmember Ritorna il valore di

bool secondary() const { return _secondary;} + + virtual bool is_browse() const { return TRUE; } // @cmember Esegue la ricerca. Torna il tasto che ha terminato la ricerca - KEY run(); + virtual KEY run(); }; -/////////////////////////////////////////////////////////// -// TList_sheet -/////////////////////////////////////////////////////////// // @doc EXTERNAL -// @class TList_sheet | Classe per la gestione dei list sheet -class TList_sheet -// @author:(INTERNAL) Guido +// @class TEdit_field | Classe per la definizione dei campi editabili +// +// @base public | TEditable_field +class TEdit_field : public TEditable_field { - // @access:(INTERNAL) Private Memeber - - // @cmember:(INTERNAL) Campo che possiede lo sheet - TEdit_field* _fld; - // @cmember:(INTERNAL) Sheet con i dati - TArray_sheet* _sheet; - // @cmember:(INTERNAL) Numero di righe dello sheet - int _row; - - // @cmember:(INTERNAL) Campi di input sulla maschera - TToken_string _inp_id; - // @cmember:(INTERNAL) Campi di output sulla maschera - TToken_string _out_id; - // @access Protected Member protected: - // @cmember Ritorna il numero di riga selezionata - int do_input(); - // @cmember Scrive l'output della ricerca sulla maschera - void do_output(CheckTime = RUNNING_CHECK); - // @cmember Chiamata dal tasto Gestione. Non essendo presente nei list_sheet non fa niente - bool do_insert(); - // @cmember Ritorna il campo

- TMask_field& field(short id) const; + // @cmember Formato che deve avere il campo + TString _picture; + + // @cmember Dimensione del buffer del campo + word _size; + + // @cmember Accettabilita' di valori nulli + CheckType _check; + // @cmember Controllo da effettuare anche in + bool _forced; + // @cmember Controllo abilitato + bool _check_enabled; - // @access Public Memeber + // @cmember Oggetto che contiene la ricerca e il controllo del campo + TBrowse_button* _browse; + + // @cmember Ritorna la browse + const TBrowse* parse_browse(TScanner& scanner) const; + + // @cmember Ritorna l'identificatore della classe + virtual word class_id() const; + // @cmember Legge la testata del controllo dal file

+ virtual void parse_head(TScanner& scanner); + // @cmember Legge un item del controllo dal file

+ virtual bool parse_item(TScanner& scanner); + + // @cmember Crea il controllo + virtual void create(WINDOW parent); + + // @cmember Ritorna

formattato secondo i flags settati del campo + virtual const char* reformat(const char* data) const; + + // @cmember Scrive il valore del campo direttamente sulla finestra del controllo + virtual void set_window_data(const char* data); + + // @cmember Mostra un messaggio di errore di default per il campo + bool default_error_box() const; + + // @access Public Member public: + // @cmember Gestisce la chiamata all'handler del campo + virtual bool on_hit(); + // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) + virtual bool on_key(KEY key); + // @cmember Controlla se il campo ha un check + virtual bool has_check() const; + // @cmember Controlla se il campo ha una ricerca + virtual bool has_query() const + { return _browse != NULL;} + + // @cmember Ritorna TRUE se il campo e' di tipo edit + virtual bool is_edit() const { return TRUE; } + + // @cmember Legge il valore del campo direttamente dalla finestra del controllo + virtual TString& get_window_data(); + + // @cmember Converte da campo a video + virtual const char* raw2win(const char* r) const; + + // @cmember Converte da video a campo + virtual const char* win2raw(const char* w) const; + + // @cmember Ritorna TRUE se il campo e' vuoto + virtual bool empty() const { return _str.empty(); } + + // @cmember Ritorna la dimensione del buffer associato al campo + virtual word size() const { return _size; } + + // @cmember Ritorna il tipo di check assegnato al campo (vedi ) + virtual CheckType check_type() const + { return _check; } + + // @cmember Setta il tipo di check da assegnare al campo (vedi ) + void check_type(CheckType c) + { _check = c; } + + // @cmember Controlla se un campo e' forced + bool forced() const + { return _forced;} + + // @cmember Esegue il controllo + virtual bool check(CheckTime = RUNNING_CHECK); + // @cmember Ritorna l'oggetto _browse + + // @cmember Ritorna l'oggetto _browse + TBrowse* browse() const + { return (_browse && _browse->is_browse()) ? (TBrowse*)_browse : NULL; } + + // @cmember Ritorna l'oggetto _sheet + TList_sheet* sheet() const + { return (_browse && !_browse->is_browse()) ? (TList_sheet*)_browse : NULL;} + + // @cmember Permette di abilitare/disabilitare il campo + virtual void enable(bool on = TRUE); + + // @cmember Permette di abilitare/disabilitare il check del campo + void enable_check(bool on = TRUE) ; + + // @cmember Attiva o no la selezione automatica del testo + void autoselect(bool on); + + // @cmember Controlla se un campo ha abilitato o disabilitato il check (TRUE se abilitato) + bool check_enabled() const + { return _check_enabled;} + + // @cmember Ritorna la picture del campo + const char* picture() const + { return _picture; } + // @cmember Costruttore - TList_sheet(TEdit_field* f, const char* caption, const char* head); + TEdit_field(TMask* mask); // @cmember Distruttore - ~TList_sheet(); - - // @cmember Controlla la sintassi della input del campo e ne setta i membri - void parse_input(TScanner& scanner); - // @cmember Legge dal file gli item dello sheet - void read_item(TScanner& scanner); - // @cmember Controlla la sintassi della output del campo e ne setta i membri - void parse_output(TScanner& scanner); - // @cmember Ritorna il valore della variabile

- TArray_sheet* sheet() - { return _sheet; } - // @cmember Ritorna il prim valore della variabile

- TEdit_field& field() const - { return *_fld; } - - // @cmember Controlla la validita' del campo - bool check(CheckTime = RUNNING_CHECK); - - // @cmember Esegue la ricerca. Torna il tasto che ha terminato la ricerca - KEY run(); + virtual ~TEdit_field(); }; // @doc EXTERNAL @@ -736,32 +1011,30 @@ class TReal_field : public TEdit_field int _decimals; // @access Protected Member -protected: +protected: // TMask_field // @cmember Ritorna l'identificatore della calsse virtual word class_id() const; - - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Scrive il valore interno del campo - virtual void set_field_data(const char* n); - - // @cmember Setta il valore del cambio nel campo - virtual void exchange(bool show_value, const real& n); - - virtual const char* picture_data(const char* data, bool video) const; - // @cmember Crea il controllo virtual void create(WINDOW parent); + // @cmember Legge un item del controllo dal file .msk

virtual void parse_head(TScanner& scanner); // @cmember Legge una riga di definizione del controllo dal file .msk

virtual bool parse_item(TScanner& scanner); + +protected: // TEditable_field + virtual const char* reformat(const char* data) const; + + virtual const char* win2raw(const char* data) const; + + virtual const char* raw2win(const char* data) const; + // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY key); - // @cmember Legge dalla relazione il valore del campo - virtual bool autoload(const TRelation* r); + +protected: + // @cmember Setta il valore del cambio nel campo + virtual void exchange(bool show_value, const real& n); // @access Public Member public: @@ -773,6 +1046,8 @@ public: // @cmember Costruttore TReal_field(TMask* mask); + // @cmember Distruttore + virtual ~TReal_field() { } }; // @doc EXTERNAL @@ -785,84 +1060,48 @@ class TDate_field : public TEdit_field // @author:(INTERNAL) Guido { // @access Protected Member -protected: - // @cmember Permette di formattare la data secondo i flag correnti - const char* format_data(const char* data, bool* changed=NULL) const; - +protected: // TMask_field // @cmember Ritorna l'identificatore della classe virtual word class_id() const; // @cmember Crea il controllo virtual void create(WINDOW parent); + +protected: // TOperable_field // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY key); - // @cmember Permette di dare la stessa formattazione del campo della maschera - // (vedi ) - virtual const char* picture_data(const char* data, bool video) const; - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); + +protected: // TEditable_field + // @cmember Converte una eventuale data ANSI in formato gg-mm-aaaa + const char* reformat(const char* str) const; + + // @cmember Converte l'input dell'utente in una data + virtual const char* win2raw(const char* data) const; + + // @cmember Formatta una data normale o ANSI in gg-mm-aaaa + virtual const char* raw2win(const char* data) const; + // @cmember Scrive sulla relazione il valore del campo gestendo formato ANSI - virtual bool autosave(TRelation* r = NULL) const; + virtual bool autosave(TRelation& r) const; // @access Public Member public: // @cmember Legge un item del controllo dal file

void parse_head(TScanner& scanner); + // @cmember Costruttore TDate_field(TMask* mask); + + // @cmember Distruttore + virtual ~TDate_field() { } }; -// @doc EXTERNAL - -// @class TBoolean_field | Classe per la gestione dei campi boolean (check box) -// -// @base public | TMask_field -class TBoolean_field : public TMask_field - -// @author:(INTERNAL) Guido -{ - // @access Protected Member -protected: - // @cmember Indica se il campo e' selezionato o no - bool _on; - - // @cmember Ritorna l'identificatore della classe - virtual word class_id() const; - - // @cmember Crea il controllo - virtual void create(WINDOW parent); - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data = NULL); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; - // @cmember Legge un item del controllo dal file

- virtual bool parse_item(TScanner& scanner); - // @cmember Abilita/Disabilita il campo (vedi ) - virtual void enable(bool on); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - // @cmember Gestisce la chiamata all'handler del campo - virtual bool on_hit(); - // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) - virtual bool on_key(KEY key); - - // @access Public Members -public: - // @cmember Costruttore - TBoolean_field(TMask* mask); -}; // @doc EXTERNAL // @class TList_field | Classe per la gestione dei campi lista (list box) // -// @base public | TMask_field -class TList_field : public TMask_field +// @base public | TEditable_field +class TList_field : public TEditable_field // @author:(INTERNAL) Guido { // @access Private Member @@ -876,8 +1115,6 @@ protected: TToken_string _values; // @cmember Lista dei codice delle voci TToken_string _codes; - // @cmember Valore del campo - TString _str; // @cmember Ritorna l'identificatore della classe virtual word class_id() const; @@ -885,11 +1122,7 @@ protected: // @cmember Scrive il valore del campo direttamente dalla finestra del controllo virtual void set_window_data(const char* data); // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data = NULL); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; + virtual TString& get_window_data(); // @cmember Crea il controllo virtual void create(WINDOW parent); @@ -905,20 +1138,19 @@ protected: virtual bool on_hit(); // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY key); + // @cmember Legge dal file gli item dello sheet virtual void read_item(TScanner& scanner); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - // @cmember Legge un item del controllo dal file

+ // @cmember Legge la testata del controllo dal file

virtual void parse_head(TScanner& scanner); + // @cmember Legge un item del controllo dal file

virtual bool parse_item(TScanner& scanner); // @access Public Member -public: - // @cmember Costruttore - TList_field(TMask* mask); +public: + const char* get_values() const { return _values; } // @cmember Sostituisce alle voci correnti quelle passate come parametri virtual void replace_items(const char* codes, const char* values); // @cmember Aggiunge una voce @@ -927,6 +1159,12 @@ public: virtual void delete_item(const char* code); // @cmember Ritorna il numero di voci presenti int items() const; + // @cmember Tipo + virtual bool is_kind_of(word cid) const; + + // @cmember Costruttore + TList_field(TMask* mask); + virtual ~TList_field() {} }; // @doc EXTERNAL @@ -937,172 +1175,62 @@ public: class TRadio_field : public TList_field // @author:(INTERNAL) Guido { - // @access:(INTERNAL) Private Member - - // @ccost:(INTERNAL) MAX_RADIO | 8 | Numero massimo di opzioni di un radio button - enum { MAX_RADIO = 8 }; - // @cmember:(INTERNAL) Numero di opzioni presenti nel radio button - int _nitems; - // @cmember:(INTERNAL) Numero della voce attiva nel radio button - int _active_item; - // @cmember:(INTERNAL) Finestre delle righe del radiobutton - WINDOW _radio_ctl_win[MAX_RADIO]; - // @access Protected Member protected: // @cmember Ritorna l'identificatore della classe virtual word class_id() const; // @cmember Crea il controllo virtual void create(WINDOW parent); - // @cmember Distrugge il contrllo - virtual void destroy(); // @cmember Permette di abilitare/disabilitare il radio button (vedi ) - virtual void enable(bool on); - // @cmember Permette di mostrare/nascondere il radio button (vedi ) - virtual void show(bool on); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; // @cmember Setta la voce corrente virtual void current(int n); // @cmember Ritorna la voce corrente virtual int current() const; - // @cmember Ritorna la finestra della voce selezionata - WINDOW win() const - { return _radio_ctl_win[_active_item]; } // @access Public Member public: // @cmember Costruttore TRadio_field(TMask* mask); - - // @cmember Seleziona usando

la voce corrente - void check_radiobutton(WINDOW checked); - // @cmember Sposta il focus dal radio button - bool move_focus(int d); + // @cmember Distruttore + virtual ~TRadio_field(); }; -// @doc EXTERNAL - -// @class TButton_field | Classe per la gestione dei campi bottone -// -// @base public | TMask_field -class TButton_field : public TMask_field - -// @author:(INTERNAL) Guido -{ - // @access:(INTERNAL) Private Member - - // @cmember:(INTERNAL) Valore della combinazione di tasti che sostituisce il bottone - KEY _virtual_key; - // @cmember:(INTERNAL) Tasto generato quando viene premuto il bottone che si sta gestendo - KEY _exit_key; - - // @access Protected Member -protected: - // @cmember Ritorna l'identificatore della classe - virtual word class_id() const; - // @cmember Crea il controllo - virtual void create(WINDOW parent); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - - // @cmember Legge un item del controllo dal file

- void parse_head(TScanner& scanner); - // @cmember Legge un item del controllo dal file

- bool parse_item(TScanner& scanner); - // @cmember Permette di abilitare/disabilitare il bottone (vedi ) - virtual void enable(bool); - // @cmember Permette di mostrare/nascondere il bottone (vedi ) - virtual void show(bool); - // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) - virtual bool on_key(KEY key); - -public: - // @cmember Costruttore - TButton_field(TMask* mask); - // @cmember Ritorna il valore della combinazione di tasti che sostiutiscono il bottone - KEY virtual_key() const - { return _virtual_key; } - // @cmember Ritorna il valore del tasto di uscita - KEY exit_key() const - { return _exit_key; } -}; - -// @doc EXTERNAL - -// @class TGroup_field | Classe per la gestione del disegno dei group box -// -// @base public | TMask_field -class TGroup_field : public TMask_field -// @author:(INTERNAL) Guido -{ - // @access Protected Member -protected: - // @cmember Legge un item del controllo dal file

- virtual void parse_head(TScanner& scanner); - // @cmember Crea il controllo - virtual void create(WINDOW parent); - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data); - // @cmember Setta il colore dello sfondo - virtual void set_back_color(COLOR c) const; - - // @access Public Member -public: - // @cmember Costruttore - TGroup_field(TMask* mask); -}; // @doc EXTERNAL // @class TMemo_field | Classe per la gestione dei campi memo // // @base public | TMask_field -class TMemo_field : public TMask_field +class TMemo_field : public TEdit_field // @author:(INTERNAL) Guido { // @access:(INTERNAL) Private Member - // @cmember:(INTERNAL) Oggetto text che contiene il valore del campo memo - TXEDIT _te; - // @cmember:(INTERNAL) Contenuto del campo memo - TToken_string _data; - // @access Protected Member -protected: +protected: // TObject // @cmember Ritorna l'identificatore della classe virtual word class_id() const { return CLASS_MEMO_FIELD; } // @cmember Ritorna il nome della classe virtual const char* class_name() const { return "MEMO"; } + +protected: // TMask_field // @cmember Crea il controllo virtual void create(WINDOW parent); // @cmember Legge un item del controllo dal file

virtual void parse_head(TScanner& scanner); - // @cmember Setta il focus sul campo - virtual void highlight() const; - - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data = NULL); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; - - - // @cmember Permette di abilitare/disabilitare il campo (vedi ) - virtual void enable(bool on); - // @cmember Permette di mostrare/nascondere il campo (vedi ) - virtual void show(bool on); - // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) +protected: // TEditable_field + // Gestisce solo l'acquisto e la perdita del focus virtual bool on_key(KEY k); + // @cmember Non fa' nulla + virtual const char* reformat(const char* data) const; + // @cmember Trasforma i '\n' in '\r' + virtual const char* raw2win(const char* data) const; + // @cmember Trasforma i '\r' in '\n' + virtual const char* win2raw(const char* data) const; // @access Public Member public: @@ -1120,17 +1248,8 @@ public: class TZoom_field : public TEdit_field // @author:(INTERNAL) Guido { - // @access:(INTERNAL) Private Member - - // @cmember:(INTERNAL) ??? - TToken_string _memo; - - // @cmember:(INTERNAL) Finestra del bottone per lo zoom del campo - WINDOW _buttonzoom; - // @access Protected Member protected: - // @cmember Ritorna l'identificatore della classe virtual word class_id() const { return CLASS_ZOOM_FIELD; }; @@ -1138,41 +1257,33 @@ protected: virtual const char* class_name() const { return "ZOOM"; } - // @cmember Scrive il valore del campo direttamente dalla finestra del controllo - virtual void set_window_data(const char* data); - // @cmember Legge il valore del campo direttamente dalla finestra del controllo - virtual const char* get_window_data() const; - // @cmember Scrive il valore del campo - virtual void set_field_data(const char* data); - // @cmember Legge il valore del campo - virtual const char* get_field_data() const; - // @cmember ??? - void set_first_line( const char * c ); - +protected: // @cmember Crea il controllo virtual void create(WINDOW parent); - // @cmember Distrugge il contrllo - virtual void destroy(); + + // @cmember Gestisce tasti inviati al controllo + virtual bool on_key(KEY key); +protected: + // @cmember Non fa' nulla + virtual const char* reformat(const char* data) const; + + // @cmember Trasforma

in una riga sola + virtual const char* raw2win(const char* data) const; + + // @cmember Trasforma la riga

nell'intero memo + virtual const char* win2raw(const char* data) const; // @access Public Member -public: - // @cmember Permette di rendere visibile/invisibile un campo (vedi ) - virtual void show(bool on = TRUE); - // @cmember Abilita/disabilita il campo (lo rende scrivibile) (vedi ) - virtual void enable(bool on = TRUE); - // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) - const char * get_first_line( ); - virtual bool on_key(KEY key); +public: + const char* get_first_line() const; + // @cmember Costruttore TZoom_field(TMask* mask); // @cmember Distruttore virtual ~TZoom_field(); }; - - - #endif // __MASKFLD_H diff --git a/include/msksheet.cpp b/include/msksheet.cpp index a5a94f800..21c2a6001 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -1,14 +1,10 @@ +#include +#include +#include #include #include #include -const short FIRST_FIELD = 101; - -#if XVT_OS == XVT_OS_WIN - -#include -#include -#include /////////////////////////////////////////////////////////// // TSpreadsheet @@ -20,7 +16,7 @@ const short FIRST_FIELD = 101; // di una maschera // // @base public | TWindow -class TSpreadsheet : public TWindow +class TSpreadsheet : public TControl { // @author:(INTERNAL) Guido @@ -29,12 +25,6 @@ class TSpreadsheet : public TWindow // @access:(INTERNAL) Private Member - enum { - // @ccost:(INTERNAL) ITF_CID | 0 | Identifica l'interfaccia dello spreadsheet - ITF_CID = 0, - // @ccost:(INTERNAL) LIST_CID | 1 | Identifica il contenuto dello spreadsheet - LIST_CID = 1 }; - // @cmember:(INTERNAL) Array di TToken_strings contenenti le righe TString_array _str; // @cmember:(INTERNAL) Array delle colonne disattivate (solo visualizzazione) @@ -46,27 +36,14 @@ class TSpreadsheet : public TWindow TMask _mask; // @cmember:(INTERNAL) Numero di colonne presenti nello spreadsheet int _columns; - // @cmember:(INTERNAL) Trucco per evitare che lo sheet prenda il focus tutte le volte che parte la maschera - bool _firstfocus; // @cmember:(INTERNAL) Indica se e' attivo lo spreadsheet bool _active; - // @cmember:(INTERNAL) Puntatore al contenuto dello spreadsheet - XI_OBJ *_list; - // @cmember:(INTERNAL) Puntatore all'interfaccia dello spreadsheet - XI_OBJ *_itf; - // @cmember:(INTERNAL) Funzione per la gestione di una riga dello sheet (vedi ) SPREADSHEET_NOTIFY _notify; - // @cmember:(INTERNAL) Funzione per l'apertura della maschera di edit della riga - // (vedi ) - SPREADSHEET_GETMASK _getmask; - - // @cmember:(INTERNAL) Campo che possiede lo spreadsheet - TSheet_field* _owner; - + // @cmember:(INTERNAL) Campo corrente che si sta editando - TMask_field* _edit_field; + TOperable_field* _edit_field; // @cmember:(INTERNAL) Coordinata della riga della cella corrente int _cur_row; // @cmember:(INTERNAL) Numero del record sul file al quale fa riferimento la cella corrente @@ -91,7 +68,7 @@ class TSpreadsheet : public TWindow // @access Protected Member protected: //@cmember Gestisce gli eventi delle celle (chiamata dal ) - void list_handler(XI_EVENT* xiev); + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); //@cmember Copia una cella nel corrispondente campo della maschera e ne ritorna il contenuto const char* copy_cell2field(XI_OBJ* cell = NULL); @@ -101,18 +78,18 @@ protected: // @cmember Ritorna il campo della maschera corrispondente alla cella dello // spreadsheet indicata da

- TMask_field* col2field(int pos) const; + TOperable_field* col2field(int pos) const; // @cmember Ritorna il campo della maschera corrispondente alla cella dello // spreadsheet indicata da

(chiama ) - TMask_field* cell2field(const XI_OBJ* cell) const; + TOperable_field* cell2field(const XI_OBJ* cell) const; // @cmember Ritorna la posizione della colonna con identificatore

int cid2col(short cid) const; // @cmember Ritorna la colonna corrispondente al campo

della maschera - int field2col(const TMask_field* f) const; + int field2col(const TOperable_field* f) const; // @cmember Aggiorna il record sullo spreadsheet void update_rec(int rec); - TMask_field* field(short id) const; + TOperable_field* field(short id) const; // @cmember Converte il numero del record nel corrispondente numero della riga int rec2row(int rec); @@ -134,12 +111,16 @@ protected: void on_idle(); // @cmember Cerca la colonna col - XI_OBJ* TSpreadsheet::find_column(int col) const; + XI_OBJ* find_column(int col) const; + + TSheet_field& owner() const { return (TSheet_field&)*_fld; } // @access Public Member public: // @cmember Modifica a video la riga - void update(int row); + void update(int row); + // @cmember Ritorna la disabilitazione della colonna

+ bool column_disabled(int col) { return _column_disabled[col]; } // @cmember Ritorna il contenuto della riga

-esima TToken_string& row(int n) @@ -172,7 +153,7 @@ public: // @cmember Sposta la colonna dalla posizione

alla posizione //

void move_column(const int fromindex, const int toindex) const; - // @cmember Permette di invertire la posiozne di due colonne + // @cmember Permette di invertire la posizione di due colonne void swap_columns(const int fromid, const int toid) const; // @cmember Permette di invertire la posiozne di due righe void swap_rows(const int fromindex, const int toindex); @@ -217,10 +198,10 @@ public: // @cmember Controlla se e' stato modificato una cella dello spreadsheet bool dirty() const - { return _owner->dirty(); } + { return owner().dirty(); } // @cmember Permette di indicare se e' stata modificata una cella dello spreadsheet void set_dirty(bool spork = TRUE) - { _owner->set_dirty(spork); } + { owner().set_dirty(spork); } // @cmember Ritorna il valore della variabile active bool active() const @@ -228,60 +209,42 @@ public: // @cmember Ritorna se e' possibile lasciare il focus dallo spreadsheet (TRUE se e' possibile) bool test_focus_change(); - // @cmember Setta il membro

on il valore

- void set_getmask(SPREADSHEET_GETMASK n) - { _getmask = n; } - // @cmember Setta il membro

on il valore

void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } // @cmember Costruttore - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, const char* head, WINDOW parent, TSheet_field* owner); + TSpreadsheet(WINDOW parent, short dlg, short x, short y, short dx, short dy, const char* maskname, int maskno, const char* head, TSheet_field* owner); // @cmember Distruttore virtual ~TSpreadsheet(); }; -// Certified 100% -void TSpreadsheet::init() -{ - static bool first = TRUE; - if (!first) return; - - XVT_FNTID font = xvt_dwin_get_font(TASK_WIN); - xi_set_font_id(font); - - xi_init(); - xi_set_pref(XI_PREF_3D_LOOK, TRUE); - first = FALSE; -} - // @doc INTERNAL // @mfunc Costruttore TSpreadsheet::TSpreadsheet( + WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet + short dlg, // @parm Identificatore del campo short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet short dx, // @parm Larghezza (in caratteri) dello spreasheet short dy, // @parm Lunghezza (in caratteri) dello spreasheet const char* maskname, // @parm Nome del file della maschera int maskno, // @parm Numero identificativo della maschera nel file - const char* head, // @parm Titolo della maschera - WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet + const char* head, // @parm Titolo delle colonne TSheet_field* o) // @parm Indica il campo della maschera che contiene lo spreadsheet -: _mask(maskname, maskno), _notify(NULL), _getmask( NULL ), _owner(o), +: + _mask(maskname, maskno), _notify(NULL), _cur_row(0), _cur_col(1), _cur_rec(0), _edit_field(NULL), _active(TRUE), _row_dirty(FALSE), _check_enabled(TRUE), - _firstfocus(FALSE), _needs_update(-1) { const int NUMBER_WIDTH = 3; const int MAX_COL = 32; int m_width[MAX_COL], v_width[MAX_COL]; int fixed_columns = 1; // Number of fixed columns - - init(); + TControl::_fld = o; sheet_mask().set_sheet(o); // Calcolo larghezza massima tabella @@ -297,34 +260,32 @@ TSpreadsheet::TSpreadsheet( CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); const int cid = FIRST_FIELD+i; // Column & Field ID - const TMask_field* f = field(cid); // Field on mask + const TOperable_field* f = field(cid); // Field on mask CHECKD(f, "The spreadsheet mask needs ALSO field ", cid); - TString80 testa(h); + TString testa(h); const int at = testa.find('@'); - int m, v; // Memory and video width + int m = f->size(); // Memory width + int v = m; // Video width if (at >= 0) { const TString& wi = testa.mid(at+1); - m = atoi(wi); + v = atoi(wi); if (wi.find('F') >= 0) { fixed_columns++; - f_width += m+1; + f_width += v+1; } testa.cut(at); - v = max(at, m+(f->has_query() ? 1 : 0)); + v = max(at, v+(f->has_query() ? 1 : 0)); } else { - m = testa.len(); - v = m+(f->has_query() ? 1 : 0); + v = max(testa.len(), m+(f->has_query() ? 1 : 0)); } - - if (f->is_edit()) - m = f->size(); if (v > 69) v = 69; + m = f->size(); m_width[i] = m+1; // m = number of allowed chars v_width[i] = v+1; // v = width of column @@ -336,84 +297,55 @@ TSpreadsheet::TSpreadsheet( } _columns = i; - if (x < 0) x = 0; - if (y < 0) y = 0; - if (dx == 0) - { - dx = tot_width; - if (dx > 76) dx = -x; - } - - RCT rct = resize_rect(x, y, dx, dy, WO_TE, parent); -#ifndef XI_FU_MULTIPLE - rct.bottom -= 12 ; - rct.right -= 28; -#endif - - if ((f_width+max_width)*CHARX > rct.right) + RCT rct; coord2rct(parent, x, y, dx, dy, rct); + rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar + + // Controlla se ci sono troppe colonne fisse + if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right) fixed_columns = 1; + + XI_OBJ* itf = get_interface(parent); - XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID, - (XI_EVENT_HANDLER)xiev_handler, &rct, (char*)maskname, - PTR_LONG(this)); - itfdef->v.itf->automatic_back_color = FALSE; - itfdef->v.itf->back_color = MASK_BACK_COLOR; - -#ifdef XI_FU_MULTIPLE - const short work_dx = ((rct.right - rct.left) * XI_FU_MULTIPLE) / CHARX - 3 * XI_FU_MULTIPLE; - const short work_dy = ((rct.bottom - rct.top ) * XI_FU_MULTIPLE) / CHARY - 2 * XI_FU_MULTIPLE - 6; - - XI_OBJ_DEF* listdef = xi_add_list_def(itfdef, LIST_CID, - 0, 0, work_dy, //rct.bottom-rct.top, + XI_OBJ_DEF* listdef = xi_add_list_def(NULL, dlg, + rct.top, rct.left, rct.bottom-rct.top, XI_ATR_ENABLED | XI_ATR_VISIBLE, NORMAL_COLOR, NORMAL_BACK_COLOR, // normal NORMAL_COLOR, DISABLED_BACK_COLOR, // disabled FOCUS_COLOR, // active - LIST_CID); -#else - XI_OBJ_DEF* listdef = xi_add_list_def(itfdef, LIST_CID, - 0, 0, rct.bottom-rct.top, - XI_ATR_ENABLED | XI_ATR_VISIBLE, - NORMAL_COLOR, NORMAL_BACK_COLOR, // normal - NORMAL_COLOR, DISABLED_BACK_COLOR, // disabled - FOCUS_COLOR, // active - LIST_CID); -#endif - listdef->v.list->sizable_columns = TRUE; - listdef->v.list->movable_columns = TRUE; - listdef->v.list->scroll_bar = TRUE; - listdef->v.list->scroll_bar_button = TRUE; - listdef->v.list->fixed_columns = fixed_columns; -#ifdef XI_FU_MULTIPLE - listdef->v.list->width = work_dx; -#else - listdef->v.list->width = rct.right-rct.left; -#endif - listdef->v.list->min_cell_height = CHARY; - listdef->v.list->min_heading_height = CHARY; - listdef->v.list->white_space_color = MASK_DARK_COLOR; - listdef->v.list->active_back_color = FOCUS_BACK_COLOR; + 0); + CHECK(listdef, "Can't create spreadsheet definition"); + listdef->app_data = (long)this; + XI_LIST_DEF* l = listdef->v.list; + l->width = rct.right - rct.left; + l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()); + l->sizable_columns = TRUE; + l->movable_columns = TRUE; + l->scroll_bar = TRUE; + l->scroll_bar_button = TRUE; + l->fixed_columns = fixed_columns; + l->active_back_color = FOCUS_BACK_COLOR; + l->white_space_color = MASK_DARK_COLOR; + + // Definizione della prima colonna (numero di riga) word attr = XI_ATR_RJUST; if (sheet_mask().id2pos(FIRST_FIELD -1) != -1) attr |= XI_ATR_SELECTABLE; -#ifdef XI_FU_MULTIPLE - XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, attr, 0, NUMBER_WIDTH * XI_FU_MULTIPLE, NUMBER_WIDTH+1, + XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, attr, 0, + NUMBER_WIDTH * XI_FU_MULTIPLE, NUMBER_WIDTH+1, attr & XI_ATR_SELECTABLE ? "X" : ""); -#else - XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, attr, 0, NUMBER_WIDTH, NUMBER_WIDTH+1, - attr & XI_ATR_SELECTABLE ? "X" : ""); - -#endif + + coldef->app_data = (long)this; coldef->v.column->heading_platform = TRUE; coldef->v.column->column_platform = TRUE; if (attr & XI_ATR_SELECTABLE) { coldef->v.column->icon_rid = ICO_SEARCH; - coldef->v.column->icon_x = coldef->v.column->icon_y = 2; - listdef->v.list->min_heading_height = 20; + coldef->v.column->icon_x = 2; + if (listdef->v.list->min_heading_height < 20) + listdef->v.list->min_heading_height = 20; } else coldef->v.column->center_heading = TRUE; @@ -421,12 +353,13 @@ TSpreadsheet::TSpreadsheet( for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) { - const TString80 testo(h); + const TString testo(h); const int cid = FIRST_FIELD+i; // Column & Field ID - const TMask_field* f = field(cid); // Field on mask + const TOperable_field* f = field(cid); // Field on mask const int acqua = f->class_id(); - long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL; + long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL | + XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT; switch (acqua) { case CLASS_EDIT_FIELD: @@ -436,60 +369,38 @@ TSpreadsheet::TSpreadsheet( case CLASS_REAL_FIELD: flags |= XI_ATR_RJUST; break; - case CLASS_BUTTON_FIELD: - flags |= XI_ATR_SELECTABLE; - break; default: break; } - if (f->active()) flags |= XI_ATR_ENABLED | XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT; + if (f->active()) flags |= XI_ATR_ENABLED; else _column_disabled.set(i); -#ifdef XI_FU_MULTIPLE - coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i] * XI_FU_MULTIPLE, m_width[i], + coldef = xi_add_column_def(listdef, cid, flags, cid, + v_width[i] * XI_FU_MULTIPLE, m_width[i], (char*)(const char*)testo); -#else - coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i], m_width[i], - (char*)(const char*)testo); -#endif + + coldef->app_data = (long)this; coldef->v.column->heading_platform = TRUE; coldef->v.column->center_heading = TRUE; } - RCT itfrct; - xi_get_def_rect(itfdef, &itfrct); - xvt_rect_offset(&itfrct, rct.left, rct.top); - itfrct.bottom++; - - WINDOW win = xvt_win_create(W_NO_BORDER, &itfrct, "", 0, parent, - 0, EM_ALL, (EVENT_HANDLER)xi_event, 0L); - CHECK(win, "Can't create a window for the spreadsheet"); - - set_win(win); // Set TWindow::_win - itfdef->v.itf->win = win; // Link interface to win - // Create the whole thing! - _itf = xi_create(XI_NULL_OBJ, itfdef); - _list = xi_get_obj(_itf, LIST_CID); - - xi_dequeue(); // Flush events - xi_tree_free(itfdef); // Free definitions + _obj = xi_create(itf, listdef); + xi_dequeue(); // Flush events in XOL + xi_tree_free(listdef); // Free definitions + + CHECKD(_obj, "Can't create spreadsheet ", owner().dlg()); + + update_tab_cid(); } TSpreadsheet::~TSpreadsheet() { - if (_getmask != NULL) - _getmask(0, _mask, TRUE); // Distrugge la maschera customizzata - - set_win(NULL_WIN); } TMask& TSpreadsheet::sheet_mask() const { - TMask& m = ((TSpreadsheet*)this)->_mask; - if (_getmask != NULL && _cur_rec >= 0 && _cur_rec < items()) - return *_getmask((int)_cur_rec, m, FALSE); - return m; + return ((TSpreadsheet*)this)->_mask; } @@ -497,7 +408,7 @@ TMask& TSpreadsheet::sheet_mask() const int TSpreadsheet::row2rec(int& row) { int rows; - const long* handle = xi_get_list_info(_list, &rows); + const long* handle = xi_get_list_info(_obj, &rows); if (row < 0) row = 0; @@ -518,7 +429,7 @@ int TSpreadsheet::row2rec(int& row) int TSpreadsheet::rec2row(int record) { int rows; - const long* rec = xi_get_list_info(_list, &rows); + const long* rec = xi_get_list_info(_obj, &rows); int r = int(record - rec[0]); if (r < 0 || r >= rows) r = -1; @@ -528,16 +439,16 @@ int TSpreadsheet::rec2row(int record) // Retrieves the corresponding field of the mask from a spredsheet cell -TMask_field* TSpreadsheet::col2field(int pos) const +TOperable_field* TSpreadsheet::col2field(int pos) const { int num; - XI_OBJ** column = xi_get_member_list(_list, &num); + XI_OBJ** column = xi_get_member_list(_obj, &num); CHECKD(pos >= 0 && pos < num, "Bad column number", pos); - TMask_field* good = NULL; + TOperable_field* good = NULL; for (short id = column[pos]->cid; ; id += 100) { - TMask_field* f = field(id); + TOperable_field* f = field(id); if (f == NULL) break; // Search failed good = f; // We've found a field with the proper ID ... if (f->active()) break; // ... and it's active: end of search @@ -549,7 +460,7 @@ TMask_field* TSpreadsheet::col2field(int pos) const // Retrieves the corresponding field of the mask from a spredsheet cell -TMask_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const +TOperable_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const { return col2field(cell->v.cell.column); } @@ -558,16 +469,16 @@ int TSpreadsheet::cid2col(short cid) const { CHECKD(cid >= FIRST_FIELD, "Bad column id ", cid); int num; - XI_OBJ** column = xi_get_member_list(_list, &num); + XI_OBJ** column = xi_get_member_list(_obj, &num); for (int c = num-1; c > 1; c--) { if (column[c]->cid == cid) - break; + return c; } - return c; + return 0; } -int TSpreadsheet::field2col(const TMask_field* f) const +int TSpreadsheet::field2col(const TOperable_field* f) const { const short cid = FIRST_FIELD + (f->dlg() % 100) - 1; return cid2col(cid); @@ -579,12 +490,12 @@ void TSpreadsheet::update_rec(int rec) if (riga >= 0) { const bool has_focus = rec == selected() && - mask().focus_field().dlg() == _owner->dlg(); + mask().focus_field().dlg() == owner().dlg(); if (has_focus) - xi_set_focus(_itf); + xi_set_focus(get_interface()); XI_OBJ row; - XI_MAKE_ROW(&row, _list, riga); + XI_MAKE_ROW(&row, _obj, riga); xi_cell_request(&row); // Update internal values if (has_focus) @@ -604,7 +515,7 @@ int TSpreadsheet::find_enabled_column(int rec, int colonna, int direction) const CHECKD(direction == +1 || direction == -1, "Bad column search direction", direction); int num; - XI_OBJ** column = xi_get_member_list(_list, &num); + XI_OBJ** column = xi_get_member_list(_obj, &num); if (colonna <= 0 || colonna >= num) colonna = 1; @@ -630,8 +541,7 @@ int TSpreadsheet::find_enabled_column(int rec, int colonna, int direction) const // riga (da 0), colonna (0 = numero, 1 = prima cella, ...) void TSpreadsheet::set_focus_cell(int riga, int colonna) { - xvt_scr_set_focus_vobj(win()); - mask().set_focus_win(win(), FALSE); + xi_set_focus(get_interface()); const int rec = row2rec(riga); colonna = find_enabled_column(rec, colonna, +1); @@ -639,7 +549,7 @@ void TSpreadsheet::set_focus_cell(int riga, int colonna) if (colonna > 0) { XI_OBJ cell; - XI_MAKE_CELL(&cell, _list, riga, colonna); + XI_MAKE_CELL(&cell, _obj, riga, colonna); xi_set_focus(&cell); _edit_field = col2field(_cur_col = colonna); @@ -647,7 +557,7 @@ void TSpreadsheet::set_focus_cell(int riga, int colonna) { _cur_rec = rec; _cur_row = riga; - str2mask(_cur_rec); +/* Guy! str2mask(_cur_rec); */ _row_dirty = FALSE; } } @@ -670,7 +580,7 @@ int TSpreadsheet::insert( if (ininsert || items() >= 999) return -1; - if (rec < 0 && items() > 0 && !_owner->append() ) + if (rec < 0 && items() > 0 && !owner().append() ) rec = _cur_rec + 1; ininsert = TRUE; @@ -680,8 +590,8 @@ int TSpreadsheet::insert( if (ok) { _disabled.insert(NULL, r); - xi_insert_row(_list, INT_MAX); - xi_cell_request(_list); + xi_insert_row(_obj, INT_MAX); + xi_cell_request(_obj); // Notifica che l'inserimento è terminato notify(r, K_CTRL + K_INS); @@ -748,23 +658,23 @@ void TSpreadsheet::update( { if (rec < 0) { - xi_cell_request(_list); // Update cell values + xi_cell_request(_obj); // Update cell values int num = 0; - const long* handle = xi_get_list_info(_list, &num); + const long* handle = xi_get_list_info(_obj, &num); int first = 0, last = 0; - bool scroll = items() == 0; // || !_owner->mask().is_running(); + bool scroll = items() == 0; // || !owner().mask().is_running(); if (!scroll) { - xi_get_visible_rows(_list, &first, &last); + xi_get_visible_rows(_obj, &first, &last); scroll = items() < handle[first]; } if (scroll) - xi_scroll(_list, XI_SCROLL_FIRST); + xi_scroll(_obj, XI_SCROLL_FIRST); else - xi_scroll_rec(_list, handle[first], NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); + xi_scroll_rec(_obj, handle[first], NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); _needs_update = -1; // Clear pending row update } @@ -776,30 +686,15 @@ void TSpreadsheet::update( void TSpreadsheet::notify_change() { if (!_row_dirty) - { + { + /* Guy! */ + str2mask(_cur_rec); notify(_cur_rec, K_SPACE); _row_dirty = TRUE; set_dirty(); } } - -bool TSpreadsheet::test_focus_change() -{ - bool ok = dirty() != 3; - if (ok && _row_dirty) - ok = xi_move_focus(_itf) ? TRUE : FALSE; - return ok; -} - - -HIDDEN void XVT_CALLCONV1 xiev_handler(XI_OBJ *itf, XI_EVENT *xiev) -{ - TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf); - CHECK(es, "NULL Edit sheet in xi event"); - es->list_handler(xiev); -} - const char* TSpreadsheet::copy_cell2field(XI_OBJ* cell) { const char* txt; @@ -807,17 +702,19 @@ const char* TSpreadsheet::copy_cell2field(XI_OBJ* cell) if (cell == NULL) { XI_OBJ cella; - XI_MAKE_CELL(&cella, _list, _cur_row, _cur_col); + XI_MAKE_CELL(&cella, _obj, _cur_row, _cur_col); txt = xi_get_text(&cella, NULL, -1); } else txt = xi_get_text(cell, NULL, -1); - - const char* val = _edit_field->picture_data(txt, TRUE); - _edit_field->set(val); - _edit_field->set_dirty(); // Get it dirty! - return val; + if (_edit_field->is_editable()) + { + const TString& val = ((TEditable_field*)_edit_field)->win2raw(txt); + _edit_field->set(val); + _edit_field->set_dirty(); // Get it dirty! + } + return _edit_field->get(); } bool TSpreadsheet::off_cell_handler(XI_OBJ *cell) @@ -836,9 +733,11 @@ bool TSpreadsheet::off_cell_handler(XI_OBJ *cell) } // Certified 75% -void TSpreadsheet::list_handler(XI_EVENT *xiev) +bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev) { - static KEY _lastab = K_TAB; + static KEY _lastab = K_TAB; + + BOOLEAN& refused = xiev->refused; switch (xiev->type) { @@ -850,7 +749,7 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) xiev->v.rec_request.data_rec = n; } else - xiev->refused = TRUE; + refused = TRUE; break; case XIE_GET_LAST: xiev->v.rec_request.data_rec = items()-1; @@ -860,7 +759,7 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) { const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ; if (n < 0 || n >= items()) - xiev->refused = TRUE; + refused = TRUE; else xiev->v.rec_request.data_rec = n; } @@ -879,22 +778,25 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) if (rec < items()) { const int col = cid - FIRST_FIELD; - TMask_field* f = field(cid); - - src = row(rec).get(col); // Set value for cell - - if (f->is_edit()) + const TOperable_field* f = field(cid); + if (f->is_editable()) { + const TEditable_field* e = (const TEditable_field*)f; + src = row(rec).get(col); // Set value for cell if (src && *src) - src = f->picture_data(src, FALSE); // Get formatted string - if (f->has_query()) - { - xiev->v.cell_request.button = TRUE; - xiev->v.cell_request.button_on_focus = TRUE; - } - } - if (cell_disabled(rec, col)) - xiev->v.cell_request.back_color = DISABLED_BACK_COLOR; + src = e->raw2win(src); // Get formatted string + + if (cell_disabled(rec, col)) + xiev->v.cell_request.back_color = DISABLED_BACK_COLOR; + else + if (e->has_query() || e->is_kind_of(CLASS_LIST_FIELD)) + // il bottone manda F9 da gestire -- li' vedi se CELL ha il RCT giusto + // per posizione e poi gestisci usando il listfield + { + xiev->v.cell_request.button = TRUE; + xiev->v.cell_request.button_on_focus = TRUE; + } + } } } else @@ -907,6 +809,7 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) { const int len = xiev->v.cell_request.len; strncpy(dst, src, len); + dst[len-1] = '\0'; } else *dst = '\0'; @@ -922,10 +825,13 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) break; case XIE_BUTTON: if (xiev->v.xi_obj->type == XIT_CELL) - dispatch_e_char(win(), K_F9); + dispatch_e_char(parent(), K_F9); else if (xiev->v.xi_obj->type == XIT_LIST) - insert(-1); + { + owner().mask().notify_focus_field(owner().dlg()); + insert(-1); + } break; case XIE_SELECT: if (xiev->v.xi_obj->type == XIT_ROW) @@ -942,17 +848,15 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) on_idle(); // Forces update delayed by str2mask } - const TMask& sm = sheet_mask(); - const int button_pos = sm.id2pos(FIRST_FIELD-1); + const int button_pos = sheet_mask().id2pos(FIRST_FIELD-1); if (button_pos >= 0) { - TMask_field& button = sm.fld(button_pos); + TMask_field& button = sheet_mask().fld(button_pos); if (button.active()) { - if (!sm.is_running()) - str2mask(_cur_rec); + str2mask(_cur_rec); button.on_hit(); - if (sm.dirty()) + if (sheet_mask().dirty()) { notify_change(); mask2str(_cur_rec); @@ -960,9 +864,9 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) } } _check_enabled = TRUE; - _owner->highlight(); + owner().highlight(); } - xiev->refused = TRUE; + refused = TRUE; break; case XIE_DBL_CELL: { @@ -1002,40 +906,25 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) } break; case XIE_ON_LIST: - if (_firstfocus) // Trick to avoid the sheet to keep the focus forever ... - { // .. it costed me two day worth of hard work! - xiev->refused = TRUE; - _firstfocus = FALSE; - } - else - { - TMask_field& prev = mask().focus_field(); - - if (prev.test_focus_change()) - mask().set_focus_win(win(), FALSE); - else - { - xiev->refused = TRUE; - mask().set_focus(); - } - } + owner().mask().notify_focus_field(owner().dlg()); break; case XIE_OFF_LIST: on_idle(); break; case XIE_ON_ROW: if (_check_enabled) - { + { + // Setta _cur_rec in base a alla riga e cella correnti set_pos(xiev->v.xi_obj->v.row, _cur_col); if (_cur_rec < items() && notify(_cur_rec, K_TAB)) { - str2mask(_cur_rec); + /* Guy! str2mask(_cur_rec); */ _row_dirty = FALSE; } else { _cur_row = _cur_rec = 0; - xiev->refused = TRUE; + refused = TRUE; } } break; @@ -1058,10 +947,10 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) } else { - xiev->refused = TRUE; + refused = TRUE; } } - if (!xiev->refused) + if (!refused) { // Notifica l'abbandono della riga notify(_cur_rec, K_CTRL+K_TAB); @@ -1072,7 +961,7 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) case XIE_ON_CELL: if (_check_enabled) { - TMask_field* f = cell2field(xiev->v.xi_obj); + TOperable_field* f = cell2field(xiev->v.xi_obj); const int logical_column = (f->dlg()-FIRST_FIELD) % 100; const int physical_column = xiev->v.xi_obj->v.cell.column; if (cell_disabled(_cur_rec, logical_column)) // If the cell is disabled ... @@ -1081,11 +970,10 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) const int nex = find_enabled_column(_cur_rec, physical_column, dir); if (nex > 0) // If at least one enabled cell exists { - // _edit_field = NULL; set_focus_cell(_cur_row, nex); } else - xiev->refused = TRUE; + refused = TRUE; } else { @@ -1100,7 +988,7 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) { _check_enabled = FALSE; XI_OBJ* cell = xiev->v.xi_obj; - xiev->refused = !off_cell_handler(cell); + refused = !off_cell_handler(cell); _check_enabled = TRUE; } break; @@ -1113,46 +1001,13 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) break; case XIE_CLEANUP: break; - case XIE_XVT_EVENT: - { - EVENT* ep = &xiev->v.xvte; - switch (ep->type) + case XIE_CHAR_CELL: + if (_edit_field) { - case E_FOCUS: - if (_check_enabled && ep->v.active == FALSE) - { - if (!mask().is_running()) - _row_dirty = _cell_dirty = FALSE; - - const bool ok = (bool)xi_move_focus(_itf); - if (!ok) - { - set_dirty(3); - xiev->refused = TRUE; - } - } - break; - case E_CHAR: - if (_edit_field) + const KEY k = xiev_to_key(xiev); + switch(k) { - const KEY k = e_char_to_key(ep); - switch(k) - { - case K_ROWEDIT: - xiev->type = XIE_DBL_CELL; - xiev->v.xi_obj = NULL; - list_handler( xiev ); - break; - case K_TAB: - case K_BTAB: - _lastab = k; - break; - case K_UP: - case K_DOWN: - _lastab = (_cur_col == 2) ? K_BTAB : K_TAB; - break; case K_F1: - case K_SHIFT+K_F1: _check_enabled = FALSE; // Disable checks _edit_field->on_key(k); set_focus_cell(_cur_row, _cur_col); @@ -1161,7 +1016,11 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) case K_F8: case K_F9: if (_edit_field != NULL) + { + /* Guy! */ + notify_change(); copy_cell2field(); + } case K_F2: case K_F3: case K_F11: @@ -1169,17 +1028,37 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) { _check_enabled = FALSE; // Disable checks notify_change(); - const bool ok = _edit_field->on_key(k); - if (!ok && k == K_F9) // Ricerca non completata? + // gestione F9: listbox ok = TRUE e gestione specifica + // MAKE_CELL per beccare la cella + + bool ok = TRUE; + + if (_edit_field->is_kind_of(CLASS_LIST_FIELD) && k == K_F9) + { + XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, _cur_row, _cur_col); + // droppagiu' + TList_field& lst = (TList_field&)(*_edit_field); + TDropDownList ddl(&cell, lst.get_values(), 0, TRUE); + ddl.open(); + while (ddl.is_open()) + do_events(); + } + else // edit_field { - _edit_field = &sheet_mask().focus_field(); - const int col = field2col(_edit_field); - if (col != _cur_col) // Ricerca alternativa + ok = _edit_field->on_key(k); + + if (!ok && k == K_F9) // Ricerca non completata? { - _cur_col = col; - dispatch_e_char(win(), K_F9); - } - } + _edit_field = &sheet_mask().focus_field(); + const int col = field2col(_edit_field); + + if (col != _cur_col) // Ricerca alternativa + { + _cur_col = col; + dispatch_e_char(parent(), K_F9); + } + } + } if (ok) { mask2str(_cur_rec); @@ -1191,59 +1070,94 @@ void TSpreadsheet::list_handler(XI_EVENT *xiev) case K_PREV: case K_NEXT: case K_ESC: - if (xi_move_focus(_itf)) + if (xi_move_focus(get_interface())) dispatch_e_char(parent(), k); break; case K_ENTER: - case K_SHIFT+K_ENTER: - if (xi_move_focus(_itf)) - dispatch_e_char(parent(), k == K_ENTER ? K_TAB : K_BTAB); + case K_SHIFT+K_ENTER: + case K_CTRL+K_ENTER: + if (xi_move_focus(get_interface())) + dispatch_e_char(parent(), (k == K_ENTER || k == K_CTRL+K_ENTER) ? K_TAB : K_BTAB); break; case K_CTRL+K_PREV: - xi_scroll(_list, XI_SCROLL_PGUP); + xi_scroll(_obj, XI_SCROLL_PGUP); break; case K_CTRL+K_NEXT: - xi_scroll(_list, XI_SCROLL_PGDOWN); + xi_scroll(_obj, XI_SCROLL_PGDOWN); break; case K_CTRL+K_HOME: - xi_scroll(_list, XI_SCROLL_FIRST); + xi_scroll(_obj, XI_SCROLL_FIRST); break; case K_CTRL+K_END: - xi_scroll(_list, XI_SCROLL_LAST); + xi_scroll(_obj, XI_SCROLL_LAST); break; default: + if (is_edit_key(k) && !_edit_field->on_key(k)) + { + refused = TRUE; + beep(); + } break; - } } - break; - default: - break; + } + break; + case XIE_XVT_EVENT: + if (xiev->v.xvte.type == E_CHAR) + { + const KEY k = e_char_to_key(&xiev->v.xvte); + switch (k) + { + case K_ROWEDIT: + xiev->type = XIE_DBL_CELL; + xiev->v.xi_obj = NULL; + event_handler(itf, xiev); + break; + case K_TAB: + case K_BTAB: + _lastab = k; + break; + case K_UP: + case K_DOWN: + _lastab = (_cur_col == 2) ? K_BTAB : K_TAB; + break; + case K_ENTER: + case K_SHIFT+K_ENTER: + if (xi_move_focus(get_interface())) + dispatch_e_char(parent(), k == K_ENTER ? K_TAB : K_BTAB); + break; + case K_ESC: + if (xi_move_focus(get_interface())) + dispatch_e_char(parent(), k); + default: + break; + } } - } break; default: break; } + + return !refused; } void TSpreadsheet::activate(bool on) { _active = on; - const dword old = xi_get_attrib(_list); + const dword old = xi_get_attrib(_obj); dword att = on ? (old & ~XI_ATR_NAVIGATE) : (old | XI_ATR_NAVIGATE); if (old != att) { int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); + XI_OBJ** columns = xi_get_member_list(_obj, &num); - xi_move_focus(_itf); // Set focus to interface + xi_move_focus(get_interface()); // Set focus to interface if (on) att |= XI_ATR_TABWRAP; else att &= ~XI_ATR_TABWRAP; - xi_set_attrib(_list, att); + xi_set_attrib(_obj, att); for (int col = 1; col < num; col++) { @@ -1269,19 +1183,19 @@ void TSpreadsheet::select(int rec, bool scrollto) if (!scrollto) { int rows; - const long* handle = xi_get_list_info(_list, &rows); + const long* handle = xi_get_list_info(_obj, &rows); int first = 0, last = 0; - xi_get_visible_rows(_list, &first, &last); + xi_get_visible_rows(_obj, &first, &last); scrollto = rec < handle[first] || rec > handle[last]; } if (scrollto) - xi_scroll_rec(_list, rec, NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); + xi_scroll_rec(_obj, rec, NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); const int row = rec2row(rec); - const bool has_focus = mask().focus_field().dlg() == _owner->dlg(); + const bool has_focus = mask().focus_field().dlg() == owner().dlg(); if (has_focus) { _cur_rec = -1; @@ -1322,7 +1236,7 @@ XI_OBJ* TSpreadsheet::find_column( col = FIRST_FIELD + (col % 100) -1; int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); + XI_OBJ** columns = xi_get_member_list(_obj, &num); for (int c = num-1; c > 0; c--) { if (columns[c]->cid == col) @@ -1338,133 +1252,6 @@ XI_OBJ* TSpreadsheet::find_column( return columns[c]; } -#else - -#include - -/////////////////////////////////////////////////////////// -// TSpreadsheet -/////////////////////////////////////////////////////////// - -class TSpreadsheet : public TArray_sheet -{ - TMask _mask; - SPREADSHEET_NOTIFY _notify; - // Matteo - SPREADSHEET_GETMASK _getmask; - - TSheet_field * _owner; - - TBit_array _column_disabled; - TArray _disabled; // Array di TBit_array - -protected: - virtual bool on_key(KEY key); - KEY edit(int n, KEY tasto); - bool notify(int r, KEY k); - - TMask_field* field(short id) const; - -public: - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, - const char* head, WINDOW parent, TSheet_field * o); - - TMask& sheet_mask() const { return ((TSpreadsheet*)this)->_mask; } - TMask& mask() const; - - void swap_columns(const int fromid, const int toid) const; - void swap_rows( const int fromindex, const int toindex); - - void set_getmask(SPREADSHEET_GETMASK n) { _getmask = n; } - - void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } - void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork);} - bool dirty() const { return _owner->dirty(); } - bool test_focus_change() { return TRUE; } - - void mask2str(int riga); - void str2mask(int riga); - - void enable_column(int col, bool on); - // Matteo - void delete_column( const int col ) const; - void move_column( const int fromindex, const int toindex ) const; - void set_column_width( const int col, const int width ) const; - void set_column_header( const int col, const TString& header ) const; - void set_column_justify(int col, bool right); - - void enable_cell(int row, int column, bool on = TRUE); - bool cell_disabled(int row, int column) const; - virtual ~TSpreadsheet() {} -}; - -TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, - const char* maskname, int maskno, - const char* head, WINDOW parent, - TSheet_field* o) -: TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), _owner(o), - _mask(maskname, maskno), _notify(NULL), _getmask( NULL ) -{ - sheet_mask().set_sheet(o); -} - -bool TSpreadsheet::on_key(KEY k) -{ - switch(k) - { - case K_CTRL_ENTER: - case K_ESC: - mask().send_key(k, 0); - return TRUE; - case K_ENTER: // Selezione riga per editing - if (items() < 1) k = K_INS; // Se vuoto crea riga da editare - case K_INS: - case 'A': // Aggiunge dopo - case 'I': // Aggiunge prima - { - int n = (int)selected(); - if (k != K_ENTER) - { - if (k == K_INS) n = (int)items(); else // Aggiunge alla fine - if (k == 'A') n++; - - if (n < 0) n = 0; else - if (n > (int)items()) n = (int)items(); // Controlla range n - - if (notify(n, K_INS) == FALSE) // Chiede l'ok alla applicazione - return FALSE; - - insert(TToken_string(80), n); // Aggiunge una riga vuota - k = K_INS; // Inserimento in corso - } - - notify(n, K_TAB); // Notifica selezione - notify(n, K_SPACE); // Notifica inizio cambiamento - k = edit(n, k); // Edita riga selezionata o creata - if (k == K_ENTER) - notify(n, K_ENTER); // Notifica avvenuto cambiamento - - xvt_vobj_raise(win()); // Aggiorna sheet a video - open(); - } - break; - case K_TAB: - case K_BTAB: - case K_SHIFT_TAB: - dispatch_e_char(xvt_vobj_get_parent(win()), k); - return TRUE; - default: - break; - } - - return TArray_sheet::on_key(k); -} - -#endif - -/////////////////////////////////////////////////////////// -// Metodi di TSpreadsheet comuni a tutte le piattaforme -/////////////////////////////////////////////////////////// TMask& TSpreadsheet::mask() const { @@ -1474,63 +1261,26 @@ TMask& TSpreadsheet::mask() const // Ritorna il campo con l'identificatore dato della maschera dello sheet -TMask_field* TSpreadsheet::field(short id) const +TOperable_field* TSpreadsheet::field(short id) const { const int pos = sheet_mask().id2pos(id); - return pos < 0 ? NULL : &sheet_mask().fld(pos); + return pos < 0 ? NULL : (TOperable_field*)&sheet_mask().fld(pos); } // Ricopia i campi della maschera nel record dato ed aggiorna il display void TSpreadsheet::mask2str(int rec) { - const TMask& m = sheet_mask(); TToken_string& r = row(rec); - r.cut(0); - for (short id = FIRST_FIELD; ; id++) - { - int pos = m.id2pos(id); - if (pos < 0) break; - - for(int dlg = id; pos >= 0; pos = m.id2pos(dlg += 100)) - { - const TMask_field& f = m.fld(pos); - if (f.shown() || f.ghost()) - { - r.add(f.get()); -#if XVT_OS == XVT_OS_WIN - if (active()) - { - const int col = id-FIRST_FIELD; - if (!_column_disabled[col]) - { - const bool on = f.enabled(); - enable_cell(rec, col, on); - } - } -#endif - break; - } - } - if (pos < 0) - { -#ifdef DBG - yesnofatal_box("Mask2str: Non e' visibile il campo %d", dlg); -#endif - r.add(" "); - } - } -#if XVT_OS == XVT_OS_WIN + + owner().mask2row(rec, r); + if (_needs_update != rec) { if (_needs_update >= 0) - { - // Double update! - update_rec(_needs_update); - } + update_rec(_needs_update); // Double update! _needs_update = rec; } -#endif } @@ -1564,11 +1314,7 @@ void TSpreadsheet::enable_cell( _disabled.destroy(row, FALSE); // Let's save some memory! else { -#if XVT_OS == XVT_OS_WIN ba->set(_columns); // Force right array size -#else - ba->set(32); // Force array size -#endif ba->set(); // Set all bits } } @@ -1588,7 +1334,7 @@ void TSpreadsheet::enable_column( col = cid2col(col); const bool change = _column_disabled[col] == on; _column_disabled.set(col, !on); -#if XVT_OS == XVT_OS_WIN + if (change) { XI_OBJ* column = find_column(col); @@ -1596,39 +1342,32 @@ void TSpreadsheet::enable_column( if (on) attr |= XI_ATR_ENABLED; else attr &= ~XI_ATR_ENABLED; -// xi_move_focus(_itf); // Set focus to interface xi_set_attrib(column, attr); // Set new attributes update(-1); } -#endif } void TSpreadsheet::delete_column( const int col ) const { -#if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_delete( column ); -#endif } void TSpreadsheet::move_column( const int fromindex, const int toindex) const { -#if XVT_OS == XVT_OS_WIN int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); + XI_OBJ** columns = xi_get_member_list(_obj, &num); CHECKD(fromindex+1 < num, "Can't move column ", fromindex); XI_OBJ* column = columns[fromindex+1]; xi_move_column( column, toindex ); -#endif } void TSpreadsheet::swap_columns(const int fromid, const int toid) const { -#if XVT_OS == XVT_OS_WIN int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); + XI_OBJ** columns = xi_get_member_list(_obj, &num); XI_OBJ* from_column = XI_NULL_OBJ; XI_OBJ* to_column = XI_NULL_OBJ; @@ -1653,38 +1392,30 @@ void TSpreadsheet::swap_columns(const int fromid, const int toid) const CHECKD(to_pos, "Can't swap column ", toid); xi_move_column(from_column, to_pos); xi_move_column(to_column, from_pos); -#endif } void TSpreadsheet::swap_rows( const int fromindex, const int toindex) { -#if XVT_OS == XVT_OS_WIN _str.swap(fromindex, toindex); _disabled.swap(fromindex, toindex); -#endif } void TSpreadsheet::set_column_width(const int col, const int width) const { -#if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_set_column_width(column, width); // Force redraw -#endif } void TSpreadsheet::set_column_header(const int col, const TString& header) const { -#if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_set_text(column, (char *)(const char *)header ); RCT r; xi_get_rect(column, &r); xi_set_column_width(column, (r.right-r.left+1) / CHARX); // Force redraw -#endif } void TSpreadsheet::set_column_justify(int col, bool right) { -#if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); dword attr = xi_get_attrib(column); if (right) @@ -1693,7 +1424,6 @@ void TSpreadsheet::set_column_justify(int col, bool right) attr &= ~XI_ATR_RJUST; xi_set_attrib(column, attr); // Set new attribute update(-1); -#endif } // Certified 99% @@ -1733,111 +1463,26 @@ void TSpreadsheet::str2mask(int riga) } TToken_string& r = row(riga); - TString val(80); - TMask& m = sheet_mask(); - const int campi = m.fields(); - - for (int i = 0; i < campi; i++) - { - TMask_field& f = m.fld(i); - const short id = f.dlg(); - if (id >= FIRST_FIELD) - { - const int index = (id % 100)-1; - val = r.get(index); - f.set(val); - const bool on = active() && !cell_disabled(riga, index); - if (f.enabled() != on) - f.enable(on); - } - } - - for (i = 0; i < campi; i++) - { - TMask_field& f = m.fld(i); - const short id = f.dlg(); - if (id >= FIRST_FIELD && - f.class_id() != CLASS_BUTTON_FIELD && - (f.active() || f.ghost())) - { - if (f.has_check()) - f.check(STARTING_CHECK); - f.set_dirty(FALSE); - f.on_hit(); - } - } - - for (i = 0; i < campi; i++) - { - TMask_field& f = m.fld(i); - const short id = f.dlg(); - if (id > FIRST_FIELD) - { - if (f.dirty() == TRUE) - f.set_dirty(FALSE); - } - } - - m.set_caption(format("Riga %d", riga+1)); + owner().row2mask(riga, r); } // Certified 100% bool TSpreadsheet::notify(int rec, KEY k) { - const bool ok = _notify ? _notify(*_owner, rec, k) : TRUE; + const bool ok = _notify ? _notify(owner(), rec, k) : TRUE; if (k == K_ENTER) set_dirty(ok ? TRUE : 3); return ok; } // Certified 99% -#if XVT_OS != XVT_OS_WIN -KEY TSpreadsheet::edit(int n, KEY tasto) -#else - KEY TSpreadsheet::edit(int n) -#endif +KEY TSpreadsheet::edit(int n) { - KEY k; - const int olditems = (int)items(); str2mask(n); + KEY k = owner().run_editmask(n); - if( _getmask ) - { - TMask& totalmask = sheet_mask(); - TMask& usermask = *_getmask( n, totalmask, FALSE ); - - // Carico la maschera dell'utente con la maschera totale - for( int i = 0; i < usermask.fields(); i ++ ) - { - TMask_field& dest_field = usermask.fld( i ); - if ( dest_field.dlg( ) > 100 ) - { - const TMask_field& source_field = totalmask.field( dest_field.dlg( ) ); - dest_field.set( source_field.get( ) ); - } - } - k = usermask.run(); - if (k == K_ENTER) - // Carico la maschera totale con la maschera dell'utente - for( i = 0; i < usermask.fields(); i ++ ) - { - const TMask_field& source_field = usermask.fld( i ); - if ( source_field.dlg( ) > 100 ) - { - TMask_field& dest_field = totalmask.field( source_field.dlg() ); - dest_field.set( source_field.get( ) ); - } - } - _getmask( n, totalmask, TRUE ); - - } - else - { - k = sheet_mask().run(); // Esegue la maschera dello sheet - } - if (active) { if (k == K_ENTER) @@ -1860,11 +1505,7 @@ KEY TSpreadsheet::edit(int n, KEY tasto) else if (k == K_ESC) { -#if XVT_OS == XVT_OS_WIN str2mask(n); // Ripristina valori precedenti -#else - if (tasto == K_INS) destroy(n); -#endif } } } @@ -1878,8 +1519,8 @@ KEY TSpreadsheet::edit(int n, KEY tasto) // Certified 100% TSheet_field::TSheet_field(TMask* m) -: TMask_field(m), _sheet(NULL), _append(TRUE) -{} + : TOperable_field(m), _append(TRUE) +{ } // Certified 100% word TSheet_field::class_id() const @@ -1887,18 +1528,20 @@ word TSheet_field::class_id() const return CLASS_SHEET_FIELD; } +bool TSheet_field::is_kind_of(word cid) const +{ return cid == CLASS_SHEET_FIELD || TOperable_field::is_kind_of(cid); } + // Certified 100% TSheet_field::~TSheet_field() { - CHECK(_sheet, "Can't delete NULL sheet"); - delete _sheet; } // Certified 100% void TSheet_field::reset() { - _sheet->destroy(); - _sheet->sheet_mask().reset(); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->destroy(); + s->sheet_mask().reset(); set_dirty(); // Reset any error (dirty = 3) set_dirty(mask().is_running()); // Set dirty state based on mask status force_update(); @@ -1907,14 +1550,15 @@ void TSheet_field::reset() // Certified 100% void TSheet_field::destroy(int r, bool update_sheet) { - _sheet->destroy(r, update_sheet); + ((TSpreadsheet*)_ctl)->destroy(r, update_sheet); } void TSheet_field::parse_head(TScanner& scanner) { - _width = scanner.integer(); - _size = scanner.integer(); - if (_size == 0) _size = -1; + _ctl_data._width = scanner.integer(); + _ctl_data._height = scanner.integer(); + if (_ctl_data._height == 0) + _ctl_data._height = -1; } @@ -1923,7 +1567,7 @@ bool TSheet_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") { - _head.add(scanner.string()); + _ctl_data._park.add(scanner.string()); return TRUE; } return TMask_field::parse_item(scanner); @@ -1931,13 +1575,13 @@ bool TSheet_field::parse_item(TScanner& scanner) // Certified 100% void TSheet_field::create(WINDOW parent) -{ +{ const TMask& m = mask(); - _sheet = new TSpreadsheet(_x, _y, _width, _size, m.source_file(), - m.sheets(), _head, parent, this); + const TString head(_ctl_data._park); + _ctl = new TSpreadsheet(parent, dlg(), _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._height, + m.source_file(), m.sheets(), head, this); - _win = _sheet->win(); - xvt_vobj_set_visible(_win, shown()); + _ctl->show(shown()); if (!_flags.enable_default) { _flags.enabled = TRUE; // Lo sheet e' sempre operabile anche se non editabile @@ -1949,17 +1593,18 @@ void TSheet_field::create(WINDOW parent) // Certified 100% TString_array& TSheet_field::rows_array() const { - return _sheet->rows_array(); + return ((TSpreadsheet*)_ctl)->rows_array(); } // Certified 100% // Ritorna l'indice della prima riga vuota dello sheet int TSheet_field::first_empty() const -{ - const int max = (int)_sheet->items(); +{ + TSpreadsheet* s = (TSpreadsheet*)_ctl; + const int max = (int)s->items(); for (int n = 0; n < max; n++) - if (_sheet->row(n).empty_items()) + if (s->row(n).empty_items()) break; return n; } @@ -1976,17 +1621,16 @@ TToken_string& TSheet_field::row( // @comm Se il parametro

e maggiore del numero massimo di righe presenti // o minore di 0 viene aggiunta una riga vuota in fondo allo spreadsheet // (viene chiamata la ) -{ - const int max = (int)_sheet->items(); +{ + TSpreadsheet* s = (TSpreadsheet*)_ctl; + const int max = (int)s->items(); if (n < 0 || n >= max) { if (n < 0) n = first_empty(); if (n >= max) - { - n = (int)_sheet->add(new TToken_string(80)); - } + n = (int)s->add(new TToken_string(80)); } - return _sheet->row(n); + return s->row(n); } // @doc EXTERNAL @@ -1999,57 +1643,51 @@ void TSheet_field::force_update( // nello spreadsheet { -#if XVT_OS == XVT_OS_WIN - _sheet->update(r); -#else - _sheet->open(); -#endif + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->update(r); } int TSheet_field::items() const -{ - return (int)_sheet->items(); +{ + TSpreadsheet* s = (TSpreadsheet*)_ctl; + return (int)s->items(); } int TSheet_field::selected() const { - return (int)_sheet->selected(); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + return (int)s->selected(); } void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) { - _sheet->set_notify(n); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->set_notify(n); } -void TSheet_field::set_getmask(SPREADSHEET_GETMASK n) -{ - _sheet->set_getmask( n ); -} - - // Certified 50% void TSheet_field::highlight() const { - TMask_field::highlight(); -#if XVT_OS == XVT_OS_WIN - if (_sheet->_check_enabled) - { - int rows; xi_get_list_info(_sheet->_list, &rows); +// TEditable_field::highlight(); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + if (s->_check_enabled) + { + int rows; xi_get_list_info(s->_obj, &rows); if (rows > 0) { - if (_sheet->notify(_sheet->_cur_rec, K_TAB)) + if (s->notify(s->_cur_rec, K_TAB)) { - _sheet->set_focus_cell(_sheet->_cur_row, _sheet->_cur_col); - _sheet->str2mask(selected()); + s->set_focus_cell(s->_cur_row, s->_cur_col); + s->str2mask(selected()); } } } -#endif } void TSheet_field::enable(bool on) { - _sheet->activate(on); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->activate(on); } bool TSheet_field::enabled() const @@ -2059,49 +1697,58 @@ bool TSheet_field::enabled() const void TSheet_field::enable_column(int column, bool on) { - _sheet->enable_column(column, on); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->enable_column(column, on); } void TSheet_field::enable_cell(int row, int column, bool on) { - _sheet->enable_cell(row, column, on); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->enable_cell(row, column, on); } bool TSheet_field::cell_disabled(int row, int column) const { - return _sheet->cell_disabled(row, column); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + return s->cell_disabled(row, column); } // Matteo void TSheet_field::delete_column( const int col ) const { - _sheet->delete_column( col ); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->delete_column( col ); } void TSheet_field::move_column( const int fromindex, const int toindex ) const { - _sheet->move_column(fromindex, toindex); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->move_column(fromindex, toindex); } void TSheet_field::swap_columns(const int fromid, const int toid) const { - _sheet->swap_columns(fromid, toid); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->swap_columns(fromid, toid); } void TSheet_field::swap_rows( const int fromindex, const int toindex) { - _sheet->swap_rows(fromindex, toindex); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->swap_rows(fromindex, toindex); } void TSheet_field::set_column_width( const int col, const int width ) const { - _sheet->set_column_width(col, width); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->set_column_width(col, width); } void TSheet_field::set_column_header( const int col, const TString& header ) const { - _sheet->set_column_header(col, header); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->set_column_header(col, header); } void TSheet_field::set_column_justify(int col, bool right) @@ -2109,12 +1756,15 @@ void TSheet_field::set_column_justify(int col, bool right) if (col < FIRST_FIELD) col += FIRST_FIELD; sheet_mask().field(col).set_justify(right); - _sheet->set_column_justify(col, right); + + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->set_column_justify(col, right); } TMask& TSheet_field::sheet_mask() const { - return _sheet->sheet_mask(); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + return s->sheet_mask(); } bool TSheet_field::on_hit() @@ -2129,52 +1779,33 @@ bool TSheet_field::on_hit() void TSheet_field::select(int r, bool scrollto) { -#if XVT_OS == XVT_OS_WIN - _sheet->select(r, scrollto); -#else - _sheet->select(r); -#endif + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->select(r, scrollto); } - -bool TSheet_field::test_focus_change() -{ - return _sheet->test_focus_change(); -} - bool TSheet_field::on_key(KEY k) { - if (k == K_ENTER) - { - if (!test_focus_change()) - return FALSE; - } - if (k == K_TAB && !focusdirty() && items() > 0) { select(0); } -#if XVT_OS == XVT_OS_WIN if (k == K_ROWEDIT && items() > 0) { select(items()-1); XI_EVENT xie; xie.type = XIE_DBL_CELL; xie.v.xi_obj = NULL; - _sheet->list_handler( &xie ); + _ctl->event_handler(NULL, &xie); return TRUE; } -#endif - return TMask_field::on_key(k); + return TOperable_field::on_key(k); } void TSheet_field::on_idle() { -#if XVT_OS == XVT_OS_WIN - _sheet->on_idle(); -#endif + ((TSpreadsheet*)_ctl)->on_idle(); } void TSheet_field::exchange(bool show_value, const real& nuo) @@ -2217,4 +1848,102 @@ void TSheet_field::exchange(bool show_value, const real& nuo) if (mask().is_running()) force_update(); +} + +// Ricopia i campi della maschera nel record dato +void TSheet_field::mask2row(int n, TToken_string & rec) +{ + const TMask& m = TSheet_field::sheet_mask(); + + rec.cut(0); + TSpreadsheet* s = (TSpreadsheet*)_ctl; + + for (short id = FIRST_FIELD; ; id++) + { + int pos = m.id2pos(id); + if (pos < 0) break; + + for(int dlg = id; pos >= 0; pos = m.id2pos(dlg += 100)) + { + const TMask_field& f = m.fld(pos); + if (f.shown() || f.ghost()) + { + rec.add(f.get()); + if (active()) + { + const int col = id-FIRST_FIELD; + + if (!s->column_disabled(col)) + { + const bool on = f.enabled(); + enable_cell(n, col, on); + } + } + break; + } + } + if (pos < 0) + { +#ifdef DBG + if (s->cid2col(id) > 0) + yesnofatal_box("Mask2str: Non e' visibile il campo %d", dlg); +#endif + rec.add(" "); + } + } } + + +// Ricopia i campi del record dato nella maschera +void TSheet_field::row2mask(int n, TToken_string & r) +{ + TString val(80); + + TMask& m = TSheet_field::sheet_mask(); + const int campi = m.fields(); + + for (int i = 0; i < campi; i++) + { + TMask_field& f = m.fld(i); + const short id = f.dlg(); + if (id >= FIRST_FIELD) + { + const int index = (id % 100)-1; + val = r.get(index); + f.set(val); + const bool on = active() && !cell_disabled(n, index); + if (f.enabled() != on) + f.enable(on); + } + } + + for (i = 0; i < campi; i++) + { + TMask_field& f = m.fld(i); + const short id = f.dlg(); + if (id >= FIRST_FIELD && + !f.is_kind_of(CLASS_BUTTON_FIELD) && + (f.active() || f.ghost())) + { + if (f.has_check()) + f.check(STARTING_CHECK); + f.set_dirty(FALSE); + f.on_hit(); + } + } + + for (i = 0; i < campi; i++) + { + TMask_field& f = m.fld(i); + const short id = f.dlg(); + if (id > FIRST_FIELD) + { + if (f.dirty() == TRUE) + f.set_dirty(FALSE); + } + } + + val.format("Riga %d", n+1); + m.set_caption(val); +} + diff --git a/include/msksheet.h b/include/msksheet.h index c4cad2f54..fe17ccb99 100755 --- a/include/msksheet.h +++ b/include/msksheet.h @@ -5,6 +5,7 @@ #include #endif +#define FIRST_FIELD 101 #define K_ROWEDIT ( K_CTRL + 'I' ) @@ -17,15 +18,10 @@ typedef bool (*SPREADSHEET_NOTIFY)(TSheet_field& s, int r, KEY k); // @doc EXTERNAL -// @type SPREADSHEET_GETMASK | Prototipo funzione che ritorna una maschera di edit diversa a seconda della riga -typedef TMask* (*SPREADSHEET_GETMASK)( int numriga, TMask& fullmask, bool destroy ); - -// @doc EXTERNAL - // @class TSheet_field | Classe per la gestione dei campi di uno spreadsheet // // @base public | TMask_field -class TSheet_field : public TMask_field +class TSheet_field : public TOperable_field { // @author:(INTERNAL) Guido @@ -34,10 +30,6 @@ class TSheet_field : public TMask_field // @access:(INTERNAL) Private Member - // @cmember:(INTERNAL) Spreadsheet di apprtenenza dei campi - TSpreadsheet* _sheet; - // @cmember:(INTERNAL) Intestazione di tutte le colonne - TToken_string _head; // @cmember:(INTERNAL) Indica se aggiungere a fondo dello spreadsheet o nella riga in cui ti trovi bool _append; @@ -45,12 +37,13 @@ class TSheet_field : public TMask_field protected: // @cmember Ritorna l'identificatore della classe virtual word class_id() const; + + virtual bool is_kind_of(word cid) const; + // @cmember Gestisce la chiamata all'handler del campo virtual bool on_hit(); // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY k); - // @cmember Ritorna TRUE se il campo puo' lasciare il focus - virtual bool test_focus_change(); // @cmember Legge la testata dello spreadsheet da

virtual void parse_head(TScanner& scanner); @@ -63,6 +56,10 @@ protected: virtual void highlight() const; // @cmember Permette di settare il valore del cambio del campo virtual void exchange(bool show_value, const real& n); + // @cmember Ricopia i campi della maschera nel record

-esimo + virtual void mask2row(int n, TToken_string & rec); + // @cmember Ricopia i campi del record

-esimo nella maschera + virtual void row2mask(int n, TToken_string & rec); // @access Public Member public: @@ -100,11 +97,11 @@ public: void force_update(int r = -1); // @cmember Ritorna la maschera corrispondente ad una riga dello spreadsheet - TMask& sheet_mask() const; + virtual TMask& sheet_mask() const; + // @cmember esegue la maschera di edit dello speadsheet; + virtual KEY run_editmask(int ) { return sheet_mask().run();} // @cmember Setta il membro

della classe void set_notify(SPREADSHEET_NOTIFY n); - // @cmember Setta il membro

della classe - void set_getmask(SPREADSHEET_GETMASK n); // @cmember Abilita/disabilita una colonna dello spreadsheet (vedi ) void enable_column(int col, bool on = TRUE); diff --git a/include/object.cpp b/include/object.cpp index d80e5555c..bc3e4451f 100755 --- a/include/object.cpp +++ b/include/object.cpp @@ -7,21 +7,23 @@ /////////////////////////////////////////////////////////// const char* TObject::class_name() const - { return "Object"; } word TObject::class_id() const - { return CLASS_OBJECT; } +bool TObject::is_kind_of(word cid) const +{ + return cid == CLASS_OBJECT; +} + bool TObject::ok() const - { return TRUE; } @@ -47,18 +49,22 @@ void TObject::print_on(ostream& out) const /////////////////////////////////////////////////////////// const char* TError_Object::class_name() const - { return "Error_Object"; } word TError_Object::class_id() const - { return CLASS_ERROR; } +bool TError_Object::is_kind_of(word cid) const +{ + return cid == CLASS_ERROR || TObject::is_kind_of(cid); +} + + bool TError_Object::ok() const diff --git a/include/object.h b/include/object.h index f84e50a1c..d253492a4 100755 --- a/include/object.h +++ b/include/object.h @@ -36,6 +36,8 @@ public: virtual const char* class_name() const; // @cmember Ritorna l'id della classe virtual word class_id() const; + // @cmember Controlla se si tratta di un oggetto derivato dalla classe

+ virtual bool is_kind_of(word cid) const; // @cmember Controlla se si tratta di un oggetto valido (sempre TRUE) virtual bool ok() const; // @cmember Duplica un'oggetto @@ -69,6 +71,8 @@ public: virtual const char* class_name() const; // @cmember Ritorna l'id della classe virtual word class_id() const; + // @cmember Controlla se si tratta di un oggetto derivato dalla classe

+ virtual bool is_kind_of(word cid) const; // @cmember Controlla se si tratta di un oggetto valido (sempre FALSE) virtual bool ok() const; diff --git a/include/prefix.cpp b/include/prefix.cpp index 836acb4b3..9b1d0b323 100755 --- a/include/prefix.cpp +++ b/include/prefix.cpp @@ -65,8 +65,11 @@ TPrefix& prefix() // @func Distrugge l'oggett in memoria void prefix_destroy() { - delete _prefhndl; - _prefhndl = NULL; + if (_prefhndl) + { + delete _prefhndl; + _prefhndl = NULL; + } } /////////////////////////////////////////////////////////// diff --git a/include/progind.cpp b/include/progind.cpp index 422391f94..68f01bfed 100755 --- a/include/progind.cpp +++ b/include/progind.cpp @@ -1,7 +1,8 @@ #include #include +#include +#include -const char* const CANCEL_TEXT = "Annulla"; const char* const TITLE_TEXT = "Attesa"; word TIndwin::measure_text(TToken_string& s, word& maxlen) const @@ -18,15 +19,12 @@ word TIndwin::measure_text(TToken_string& s, word& maxlen) const // Certified 70% TIndwin::TIndwin(long max, const char* txt, bool cancel, bool bar, int div) + : _text(NULL), _cancel(NULL), _bar(0), + _status(0L), _max(max), _flags(0x0) { - _cancel = _bar = _text = NULL_WIN; - - _status = 0l; - _max = max; if (_max <= 0) _max = 1; - _flags = 0x0; - TToken_string testo(txt, '\n'); + TToken_string testo(txt, '\r'); word maxlen = div; const word lines = measure_text(testo, maxlen); @@ -41,14 +39,22 @@ TIndwin::TIndwin(long max, const char* txt, bool cancel, bool bar, int div) } ver += cancel ? 3 : 0; - create(-1, -1, hor, ver, TITLE_TEXT); - + set_win(create_interface(TASK_WIN, -1, -1, hor, ver, TITLE_TEXT, this, FALSE)); + +/* RCT r; r.left = CHARX; r.top = CHARY; r.right = CHARX*(hor-2); r.bottom = r.top + lines*CHARY+4; _text = xvt_ctl_create(WC_TEXT, &r, (char*)txt, win(), CTL_FLAG_CENTER_JUST, 0l, DLG_NULL); +*/ + _text = new TField_control(win(), DLG_NULL, 1, 1, hor-2, lines, "CD", (char*)txt); if (cancel) + { +/* _cancel = xvt_create_control(WC_PUSHBUTTON, -11, -1, 9, 2, - CANCEL_TEXT, win(), 0, 0l, DLG_CANCEL); + "Annulla", win(), 0, 0l, DLG_CANCEL); +*/ + _cancel = new TPushbutton_control(win(), DLG_CANCEL, -11, -1, 10, 2, "", "Annulla", BMP_CANCEL); + } open_modal(); do_events(); } @@ -64,11 +70,16 @@ void TIndwin::set_text( // passato, quindi occorre dimensionare correttamente il primo passato // (es. inserire degli spazi) se se ne prevede uno piu' lungo. { - xvt_vobj_set_title(_text, (char*)t); + _text->set_caption(t); } TIndwin::~TIndwin() -{ close_modal(); } +{ + close_modal(); + + if (_text) delete _text; + if (_cancel) delete _cancel; +} bool TIndwin::can_be_closed() const { @@ -129,44 +140,29 @@ void TIndwin::update_bar() void TIndwin::update() { if (_bar) update_bar(); -} +} - -void TIndwin::handler(WINDOW w, EVENT* e) +bool TIndwin::on_key(KEY k) { - switch(e->type) + if (k == K_ESC && _cancel) { - case E_UPDATE: - xvt_dwin_clear(w, COLOR_WHITE); - update(); - return; - case E_CONTROL: - if (e->v.ctl.id == DLG_CANCEL) - dispatch_e_char(w, K_ESC); - break; - case E_CHAR: - // allowed only if cancel button is there - if (e->v.chr.ch == K_ESC) - { - if (_cancel) - { - _flags |= IND_CANCELLED; - check_stop(); - } - else return; - } - break; - default: - break; - } - TWindow::handler(w,e); + _flags |= IND_CANCELLED; + check_stop(); + } + return TRUE; +} + +void TIndwin::on_button(short id) +{ + if (id == DLG_CANCEL) + on_key(K_ESC); } // TProgind -------------------------------------------------------------- TProgind::TProgind(long max, const char* txt, bool cancel, bool bar, int div) -: TIndwin(max, txt, cancel, bar, div) + : TIndwin(max, txt, cancel, bar, div) {} // TTimerind ------------------------------------------------------------ diff --git a/include/progind.h b/include/progind.h index 4f1c5d354..83c6fd24c 100755 --- a/include/progind.h +++ b/include/progind.h @@ -2,12 +2,16 @@ #ifndef __PROGIND_H #define __PROGIND_H +#ifndef __STRINGS_H +#include +#endif + #ifndef __WINDOW_H #include #endif -#ifndef __STRINGS_H -#include +#ifndef __CONTROLS_H +class TControl; #endif // @doc EXTERNAL @@ -27,9 +31,9 @@ class TIndwin : public TWindow IND_FINISHED= 0x02 }; // @cmember:(INTERNAL) Testo da inserire nella finestra - WINDOW _text; + TControl* _text; // @cmember:(INTERNAL) Bottone "Annulla" - WINDOW _cancel; + TControl* _cancel; // @cmember:(INTERNAL) Movimento della barra e percentuale WINDOW _bar; // @cmember:(INTERNAL) Flag che indica quali operazioni sono state effettuate @@ -44,8 +48,12 @@ protected: // @cmember Ritorna il numero di linee necessarie per scrivere il testo nella finestra word measure_text(TToken_string& t, word& len) const; - // @cmember Gestisce gli eventi della finestra - virtual void handler(WINDOW w, EVENT* e); + // @cmember Gestisce gli eventi tasto della finestra + virtual bool on_key(KEY k); + + // @cmember Gestisce gli eventi bottone della finestra + virtual void on_button(short id); + // @cmember Aggiorna la barra di attesa (chiama update_bar) virtual void update(); diff --git a/include/real.cpp b/include/real.cpp index 57313d879..9a82fa50d 100755 --- a/include/real.cpp +++ b/include/real.cpp @@ -341,13 +341,13 @@ void real::trail( ) bool real::is_real (const char *s) { - bool ok = FALSE; + bool ok = TRUE; if (s) { while (*s == ' ') s++; // Remove leading spaces before atod - - ok = atod (__tmp_real.ptr (), (char *) s) != GM_NULL; + if (*s) + ok = atod (__tmp_real.ptr (), (char *) s) != GM_NULL; } return ok; } @@ -1155,6 +1155,22 @@ char *real::ita2eng (const char *s) return __string; } +bool real::is_null(const char *s) +{ + bool z = TRUE; + if (s != NULL) for (const char* n = s; *n; n++) + { + if (strchr("123456789", *n) != NULL) + { + z = FALSE; + break; + } + if (strchr(" ,-.0", *n) == NULL) + break; + } + return z; +} + bool real::is_natural (const char *s) { bool ok = s && *s != '\0'; diff --git a/include/real.h b/include/real.h index 7b5ad5ccc..d4a153f02 100755 --- a/include/real.h +++ b/include/real.h @@ -15,7 +15,7 @@ class real : public TObject // @comm Questa classe utilizza i long double definiti per Visual C++. Esiste un'altra classe -// real: per accedere scegliere il tasto successivo () dalla barra deo bottoni +// real: per accedere scegliere il tasto successivo () dalla barra deo bottoni // @author:(INTERNAL) Guido { @@ -50,7 +50,8 @@ public: static bool is_real(const char* n); // @cmember Controlla se si tratta di un numero naturale intero (TRUE se vero) static bool is_natural(const char* n); - + // @cmember Controlla se si tratta di uno zero (TRUE se vero) + static bool is_null(const char* n); // @cmember Trasforma un reale in stringa char* string(int len = 0, int dec = UNDEFINED, char pad = ' ') const; // @cmember Trasforma un reale in stringa (chiama ), ma @@ -140,7 +141,7 @@ long double abs(long double a) ; class real : public TObject // @comm Questa classe utilizza i DEC definiti per GREENLEAF. Esiste un'altra classe -// real: per accedere scegliere il tasto precedente () dalla barra deo bottoni +// real: per accedere scegliere il tasto precedente () dalla barra deo bottoni // @author:(INTERNAL) Guido { @@ -177,6 +178,8 @@ public: static bool is_real(const char* n); // @cmember Controlla se si tratta di un numero naturale intero (TRUE se vero) static bool is_natural(const char* n); + // @cmember Controlla se si tratta di uno zero (TRUE se vero) + static bool is_null(const char* n); // @cmember Ritorna l'indirizzo del numero reale DEC* ptr() const diff --git a/include/relapp.cpp b/include/relapp.cpp index eeb0aa80f..13e759bb0 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -9,105 +9,23 @@ #include #endif -/////////////////////////////////////////////////////////// -// Array delle chiavi della maschera di ricerca -/////////////////////////////////////////////////////////// - -// @doc INTERNAL - -// @class TChiave | Array delle chiavi della maschera di ricerca -// @base public | TObject -class TChiave : public TObject -// @author:(INTERNAL) Guido - -// @access:(INTERNAL) Private Member -{ - // @ccost:(INTERNAL) MAX | 16 | Numero massimo di chiavi della maschera di ricerca - enum { MAX = 16 }; - // @cmember:(INTERNAL) Posizione delle chiavi nella msachera di ricerca - int _pos[MAX]; - // @cmember:(INTERNAL) Numero di chiavi presenti nella maschera di ricerca - byte _num; - -// @access Public Member -public: - // @cmember Aggiunge una nuova chiave alla posizione

- void add(int p); - // @cmember Ritorna la posizione della chiave

-esima (-1 se non esiste) - int pos(byte n) const - { return (n >= _num) ? -1 : _pos[n]; } - // @cmember Ritorna il numero di chiavi attualmente presente nella maschera - byte items() const - { return _num; } - // @cmember Costruttore - TChiave() : _num(0) - {} - // @cmember Distruttore - virtual ~TChiave() - {} -}; - -void TChiave::add(int p) -{ - CHECKD(_num < MAX, "Too many fields in key : field n.", p); - _pos[_num++] = p; -} - -class TKey_array : public TArray -{ - const TMask* _mask; - -public: - TKey_array(const TMask* m); - virtual ~TKey_array() {} - - TChiave& key(byte k); -}; - -TChiave& TKey_array::key(byte k) -{ - k--; - TChiave* chiave = (TChiave*)objptr(k); - if (chiave == NULL) - { - chiave = new TChiave; - add(chiave, k); - } - return *chiave; -} - -TKey_array::TKey_array(const TMask* m) : _mask(m) -{ - const byte keys = m->num_keys(); - for (int f = 0; f < m->fields(); f++) - { - TMask_field& c = m->fld(f); - if (c.in_key(0)) - for (byte k = 1; k <= keys; k++) - if (c.in_key(k)) - key(k).add(f); - } -} - /////////////////////////////////////////////////////////// // TRelation_application /////////////////////////////////////////////////////////// TRelation_application::TRelation_application() -: _mask(NULL), _maskeys(NULL), _search_id(-1), _lnflag(FALSE) -{} + : _mask(NULL), _search_id(-1), _lnflag(FALSE) +{ } TRelation_application::~TRelation_application() -{ - if (_maskeys) delete _maskeys; -} +{ } void TRelation_application::setkey() { if (has_filtered_cursor()) { - TEdit_field* f = (TEdit_field*) get_search_field(); - TCursor* cur = f->browse()->cursor(); + TEdit_field& f = get_search_field(); + TCursor* cur = f.browse()->cursor(); cur->setkey(); return; } @@ -129,15 +47,14 @@ void TRelation_application::set_limits( { if (has_filtered_cursor()) { - TEdit_field* f = (TEdit_field*)get_search_field(); - CHECK(f, "Manca il campo di ricerca"); + TEdit_field& f = get_search_field(); - TBrowse* b = f->browse(); - TCursor* cur = b ? b->cursor() : NULL; + TBrowse* b = f.browse(); + TCursor* cur = b != NULL ? b->cursor() : NULL; if (cur) { cur->setkey(); - f->browse()->do_input(TRUE); + f.browse()->do_input(TRUE); if (cur->items() == 0) _first = _last = -1; else { @@ -186,7 +103,6 @@ bool TRelation_application::create() write_enable(); _mask = get_mask(MODE_QUERY); filter(); - _maskeys = new TKey_array(_mask); set_limits(); dispatch_e_menu(BAR_ITEM(1)); } @@ -204,7 +120,6 @@ bool TRelation_application::menu(MENU_TAG m) bool TRelation_application::destroy() { - if (_maskeys) delete _maskeys; user_destroy(); return TApplication::destroy(); } @@ -212,7 +127,7 @@ bool TRelation_application::destroy() void TRelation_application::set_fixed() { - TString256 s; + TString s; for (const char* f = _fixed.get(0); f && *f; f = _fixed.get()) { s = f; @@ -231,20 +146,15 @@ void TRelation_application::enable_query() const bool query = _mask->query_mode(); const bool keyon = query || get_relation()->status() == _isreinsert; - for (byte k = 1; k <= _maskeys->items(); k++) + for (int i = _mask->fields() - 1; i >= 0; i--) { - const TChiave& chiave = _maskeys->key(k); - for (int i = 0; i < chiave.items(); i++) + TMask_field& c = _mask->fld(i); + if (c.in_key(0) && c.enabled_default()) { - const int num = chiave.pos(i); - TMask_field& c = _mask->fld(num); - if (c.enabled_default()) - { - if (k == 1) - c.enable(keyon); - if (c.has_query()) - ((TEdit_field&)c).enable_check(query); - } + if (c.in_key(1)) + c.enable(keyon); + if (c.has_query()) + ((TEdit_field&)c).enable_check(query); } } @@ -331,8 +241,8 @@ int TRelation_application::set_mode(int mode) // @flag TRUE | Il campo chiave non e' vuoto // @flag FALSE | Non e' riuscii ad autonumerare il campo chiave bool TRelation_application::autonum( - TMask* m, // @parm Maschera a cui applicare l'autonumerazione - bool rec) // @parm Indica se registrare il record corrente + TMask* m, // @parm Maschera a cui applicare l'autonumerazione + bool rec) // @parm Indica se registrare il record corrente { TToken_string k(get_next_key()); @@ -346,8 +256,8 @@ bool TRelation_application::autonum( CHECKD (id > 0, "Identificatore di autonumerazione errato: ", id); const char* val = k.get(); TMask_field& f = m->field(id); - if (rec || f.get().empty()) f.set(val); - if (rec) f.autosave(get_relation()); + if (rec || f.empty()) f.set(val); + if (rec) ((TEditable_field&)f).autosave(*get_relation()); if (_renum_message.empty() || f.in_key(1)) _renum_message.format("Il documento e' stato registrato con :\n %s = %s", (const char *) f.prompt(), (const char *) f.get()); } @@ -358,10 +268,10 @@ bool TRelation_application::autonum( // @mfunc Entra in modo di ricerca void TRelation_application::query_mode( - bool pre_ins) // @parm Indica in quale modo andare: - // - // @flag TRUE | Entra in modo MODE_QUERY_INSERT - // @flag FALSE | Entra in modo MODE_QUERY (default) + bool pre_ins) // @parm Indica in quale modo andare: + // + // @flag TRUE | Entra in modo MODE_QUERY_INSERT + // @flag FALSE | Entra in modo MODE_QUERY (default) { TMask* old = _mask; const bool was_open = old != NULL && old->is_open(); @@ -375,8 +285,6 @@ void TRelation_application::query_mode( { if (was_open) _mask->open_modal(); - if (_maskeys) delete _maskeys; - _maskeys = new TKey_array(_mask); set_limits(); } @@ -424,8 +332,6 @@ void TRelation_application::insert_mode() _mask->load(); ::remove(workname); _mask->open_modal(); - delete _maskeys; - _maskeys = new TKey_array(_mask); } } else @@ -463,11 +369,7 @@ bool TRelation_application::modify_mode() _mask = get_mask(MODE_MOD); if (changing) - { _mask->open_modal(); - delete _maskeys; - _maskeys = new TKey_array(_mask); - } set_mode(MODE_MOD); @@ -484,18 +386,25 @@ bool TRelation_application::modify_mode() } -TMask_field* TRelation_application::get_search_field() const -{ - if (_search_id > 0) - return &_mask->field(_search_id); - - const TChiave& k = _maskeys->key(1); - for (int i = 0; i < k.items(); i++) - { - TMask_field* f = &_mask->fld(k.pos(i)); - if (f->required()) return f; +TEdit_field& TRelation_application::get_search_field() const +{ + short id = _search_id; + + if (id <= 0) + { + const int max = _mask->fields(); + for (int i = 0; i < max; i++) + { + const TMask_field& f = _mask->fld(i); + if (f.in_key(1) && f.required()) + { + id = f.dlg(); + break; + } + } } - return NULL; + + return _mask->efield(id); } bool TRelation_application::search_mode() @@ -503,7 +412,7 @@ bool TRelation_application::search_mode() if (_mask->mode() != MODE_QUERY) query_mode(); - TMask_field* prima = get_search_field(); + TEdit_field* prima = &get_search_field(); while (prima) { if (prima->on_key(K_F9)) @@ -513,7 +422,7 @@ bool TRelation_application::search_mode() } TMask_field* dopo = &_mask->focus_field(); - prima = (dopo == prima) ? NULL : dopo; + prima = (dopo == prima || !dopo->is_edit()) ? NULL : (TEdit_field*)dopo; } return FALSE; } @@ -524,25 +433,23 @@ bool TRelation_application::search_mode() // // @rdesc Ritorna se la chave esiste sul file bool TRelation_application::test_key( - byte k, // @parm Chiave da ricercare - bool err) // @parm Indica se visualizzare eventuali errori occorsi + byte k, // @parm Chiave da ricercare + bool err) // @parm Indica se visualizzare eventuali errori occorsi { - const TChiave& chiave = _maskeys->key(k); bool onereq = FALSE, onefill = FALSE; - for (int i = 0; i < chiave.items(); i++) + for (TEditable_field* e = _mask->get_key_field(k, TRUE); + e != NULL; + e = _mask->get_key_field(k, FALSE)) { - const int num = chiave.pos(i); - TMask_field& c = _mask->fld(num); - - if (c.required()) + if (e->required()) { onereq = TRUE; - if (c.get().empty()) + if (e->empty()) { if (err) { - _mask->first_focus(-c.dlg()); + _mask->first_focus(-e->dlg()); error_box("Manca un valore indispensabile per la ricerca"); } return FALSE; @@ -550,7 +457,7 @@ bool TRelation_application::test_key( } else /* if (k == 1 && !onereq && !onefill && c.get().not_empty()) */ - if (!onereq && !onefill && c.is_edit() && c.get().not_empty()) + if (!onereq && !onefill && e->is_edit() && !e->empty()) onefill = TRUE; } if (k == 1 && !onereq && !onefill) @@ -562,32 +469,21 @@ bool TRelation_application::test_key( return onefill || onereq; } -// Guy: doesn't change fields bool TRelation_application::find(byte k) { - if (changing_keys()) - { - delete _maskeys; - _maskeys= new TKey_array(_mask); - } - - const byte numkeys = _maskeys->items(); - if (k == 0) { - for (k = 1; k <= numkeys && !test_key(k, FALSE); k++); - if (k > numkeys) + for (k = 1; k <= MAX_KEYS && !test_key(k, FALSE); k++); + if (k > MAX_KEYS) return test_key(1, TRUE); } file().setkey(k); file().zero(); - const TChiave& chiave = _maskeys->key(k); - for (int i = 0; i < chiave.items(); i++) + for (TEditable_field* e = _mask->get_key_field(k, TRUE); e; e = _mask->get_key_field(k, FALSE)) { - const TMask_field& c = _mask->fld(chiave.pos(i)); - if (c.shown()) // Ignora campi invisibili - c.autosave(get_relation()); + if (e->shown()) // Ignora campi invisibili + e->autosave(*get_relation()); } const int err = file().read(_isequal); @@ -633,8 +529,11 @@ bool TRelation_application::save(bool check_dirty) { if (annulla) { - TString80 w(_mask->field(dirty).warning()); - if (w.empty()) w = "Campo inconsistente"; + TString w(80); + if (_mask->field(dirty).is_edit()) + w = _mask->efield(dirty).get_warning(); + if (w.empty()) + w = "Campo inconsistente"; w << ": si desidera "; switch (last) { @@ -734,7 +633,7 @@ bool TRelation_application::save(bool check_dirty) int TRelation_application::read(TMask& m) { - const TRelation *r = get_relation(); + const TRelation &r = *get_relation(); m.autoload(r); return NOERR; } @@ -742,19 +641,19 @@ int TRelation_application::read(TMask& m) int TRelation_application::write(const TMask& m) { - TRelation *r = get_relation(); + TRelation &r = *get_relation(); m.autosave(r); - r->write(); - return r->status(); + r.write(); + return r.status(); } int TRelation_application::rewrite(const TMask& m) { - TRelation *r = get_relation(); + TRelation& r = *get_relation(); m.autosave(r); - r->rewrite(); - return r->status(); + r.rewrite(); + return r.status(); } // @doc INTERNAL @@ -765,7 +664,7 @@ int TRelation_application::rewrite(const TMask& m) bool TRelation_application::relation_remove() // @comm Se la maschera e' in MODE_MOD non e' possibile cancellare il record e viene -// emesso un di errore. +// emesso un di errore. { CHECK(_mask->mode() == MODE_MOD, "You can call remove in MODE_MOD only"); TRelation *r = get_relation(); @@ -873,8 +772,8 @@ bool TRelation_application::main_loop() k = K_QUIT; } break; - case K_F9: - if (save(TRUE)) + case K_F9: + if (_mask->mode() == MODE_QUERY || save(TRUE)) search_mode(); break; default: diff --git a/include/relapp.h b/include/relapp.h index 0c1b37595..61c299148 100755 --- a/include/relapp.h +++ b/include/relapp.h @@ -13,8 +13,6 @@ #include #endif -class TKey_array; - // @doc EXTERNAL // @class TRelation_application | Classe per la gestione di una apllicazione di manutenzione di uno @@ -29,8 +27,6 @@ class TRelation_application : public TApplication { // @cmember:(INTERNAL) Maschera corrente dell'applicazione TMask* _mask; - // @cmember:(INTERNAL) Array di chiavi della maschera - TKey_array* _maskeys; // @cmember:(INTERNAL) Primo record TRecnotype _first; // @cmember:(INTERNAL) Ultimo record @@ -39,7 +35,7 @@ class TRelation_application : public TApplication int _search_id; // @cmember:(INTERNAL) Nome del programma chiamante - TString16 _autoins_caller; + TString _autoins_caller; // @cmember:(INTERNAL) Numero del record nuovo/editato long _recins; @@ -73,7 +69,7 @@ class TRelation_application : public TApplication // @cmember:(INTERNAL) Cancella il record corrente bool relation_remove(); // @cmember:(INTERNAL) Ritorna il campo di ricerca della maschera - TMask_field* get_search_field() const; + TEdit_field& get_search_field() const; // @cmember:(INTERNAL) Permette di autonumerare un record bool autonum(TMask* m, bool rec); @@ -128,19 +124,15 @@ protected: bool lnflag() const { return _lnflag;} // @cmember Indica se la futura ritornera' una maschera diversa - // dalla corrente. - // La richiesta della maschera da utilizzare per ogni fase di lavoro - // (ricerca, inserimento, modifica) avviene sempre in due tempi: e - // . Cio' serve per gestire correttamente le applicazioni - // con mashere multiple. + // dalla corrente. + // La richiesta della maschera da utilizzare per ogni fase di lavoro + // (ricerca, inserimento, modifica) avviene sempre in due tempi: e + // . Cio' serve per gestire correttamente le applicazioni + // con mashere multiple. virtual bool changing_mask(int mode) pure; // @cmember Richiede la maschera da usare virtual TMask* get_mask(int mode) pure; - // @cmember Forza la rigenerazione della lista interna di chiavi ad ogni - virtual bool changing_keys() const - { return FALSE; } - // @cmember Ritorna la relazione da modificare virtual TRelation* get_relation() const pure; // @cmember Legge dalla relazione i valori nella maschera

@@ -153,10 +145,10 @@ protected: virtual bool remove(); // @cmember Richiede una stringa nella forma CAMPO1VALORE1CAMPO2VALORE2... - // CAMPOnVALOREn contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE + // CAMPOnVALOREn contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE // che descrivono il prossimo codice libero da utilizzare per la autonumerazione. - // Nel caso di banale numerazione progressiva potrebbe essere implementata come - // return format("%d%s", F_NUM, get_relation()-items()); + // Nel caso di banale numerazione progressiva potrebbe essere implementata come + // return format("%d%s", F_NUM, get_relation()-items()); virtual const char* get_next_key() { return ""; } @@ -181,7 +173,7 @@ protected: virtual bool force_cursor_usage() const { return FALSE;} // @cmember Indica se abilitare/disabilitare la scrittura sul file - // principale (vedi ) + // principale (vedi ) virtual void write_enable(bool on = TRUE) { get_relation()->write_enable(0, on); } // @cmember Indica se disabilitare la scrittura sul file principale (vedi ) diff --git a/include/relation.cpp b/include/relation.cpp index cffdfbba8..476b2443c 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -873,14 +873,12 @@ int TRelation::remove(TDate& atdate) /////////////////////////////////////////////////////////// -HIDDEN bool __evalcondition(const TRelation* r,TExpression* cond) - +HIDDEN bool __evalcondition(const TRelation& r,TExpression* cond) { - for (int i = 0; i < cond->numvar(); i++) + for (int i = cond->numvar() - 1; i >= 0; i--) { const char* s = cond->varname(i); TFieldref f(s,0); - cond->setvar(i, f.read(r)); } return (bool) *cond; @@ -993,7 +991,7 @@ int TCursor::filtercursor(int pagecnt, TRecnotype* page) file().readat(rec,page[i]); if (update_relation()) _if->update(); if ((_filterfunction ? _filterfunction(_if) : TRUE ) && - (_fexpr ? __evalcondition(_if, _fexpr) : TRUE)) + (_fexpr ? __evalcondition(*_if, _fexpr) : TRUE)) { if (np < i) page[np] = page[i]; np++; @@ -1021,7 +1019,7 @@ bool TCursor::ok() const return FALSE; if (_filter_update || _filterfunction_update) _if->update(); if ((_filterfunction ? _filterfunction(_if) : TRUE ) && - (_fexpr ? __evalcondition(_if, _fexpr) : TRUE)) + (_fexpr ? __evalcondition(*_if, _fexpr) : TRUE)) return TRUE; return FALSE; } @@ -1186,7 +1184,6 @@ TRecnotype TCursor::read(TIsamop op, TReclock lockop, TDate& atdate) { _pos = _totrec - max + i; break; - } } if (_pos == -1) _pos = 0; @@ -1505,7 +1502,7 @@ int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page) file().readat(rec,page[i]); if (update_relation()) relation()->update(); if ((filterfunction() ? filterfunction()(relation()) : TRUE ) && - (expression() ? __evalcondition(relation(), expression()) : TRUE)) + (expression() ? __evalcondition(*relation(), expression()) : TRUE)) { if (np < i) page[np] = page[i]; np++; @@ -1522,7 +1519,7 @@ int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page) if (s.right(1) == "-" || s.right(1) == "+") s.cut(s.len()-1); TFieldref f(s,0); - TString sf=f.read(relation()); + TString sf=f.read(*relation()); TFieldtypes fld_type = file(f.file()).curr().type(f.name()); if (fld_type == _datefld) // Se il campo e' di tipo data, la converte in ANSI! { @@ -1737,18 +1734,16 @@ const char* TFieldref::read(const TRectype& rec) const return buffer; } -const char* TFieldref::read(const TRelation* r) const +const char* TFieldref::read(const TRelation& r) const { - CHECK(r != NULL, "Can't read field from NULL relation"); - const TRectype& rec = _id.empty() ? r->curr() : r->lfile(_id).curr(); + const TRectype& rec = _id.empty() ? r.curr() : r.lfile(_id).curr(); const char *s = read(rec); return s; } -void TFieldref::write(const char* val, TRelation* r) const +void TFieldref::write(const char* val, TRelation& r) const { - CHECK(r != NULL, "Can't write field on NULL relation"); - TRectype &rec = _id.empty() ? r->curr() : r->lfile(_id).curr(); + TRectype &rec = _id.empty() ? r.curr() : r.lfile(_id).curr(); write(val, rec); } @@ -1758,7 +1753,7 @@ void TFieldref::write(const char* val, TRectype& rec) const if (_fileid >= CNF_GENERAL) return; if (_from > 0) { - TString256 campo(rec.get(_name)); + TString campo(rec.get(_name)); campo.overwrite(val, _from); rec.put(_name, campo); } @@ -1795,7 +1790,7 @@ TRecord_array::TRecord_array(int logicnum, const char* numfield, int first) } TRecord_array::TRecord_array(const TRecord_array& a) -: TArray(a), _file(a._file), _offset(a._offset), _num(a._num) + : TArray(a), _file(a._file), _offset(a._offset), _num(a._num) {} void TRecord_array::set_key(TRectype* r) diff --git a/include/relation.h b/include/relation.h index 3eda8eb10..7360163c8 100755 --- a/include/relation.h +++ b/include/relation.h @@ -595,11 +595,11 @@ class TFieldref : public TObject protected: // @cmember Stampa l'oggetto virtual void print_on(ostream& out) const; + // @cmember Duplica l'oggetto TFieldref + virtual TObject* dup() const; // @access Public Memeber public: - // @cmember Duplica l'oggetto TFieldref - virtual TObject* dup() const; // @cmember Costruttore TFieldref(); // @cmember Costruttore @@ -640,11 +640,11 @@ public: // @cmember Ritorna la lunghezza del campo di

int len(TRectype &rec) const; // @cmember Cerca nella relazione il campo e ne ritorna il contenuto - const char* read(const TRelation*) const; + const char* read(const TRelation&) const; // @cmember Cerca nel record il campo e ne ritorna il contenuto const char* read(const TRectype&) const; // @cmember Cerca nella relazione il campo e vi scrive

- void write(const char* val, TRelation*) const; + void write(const char* val, TRelation&) const; // @cmember Cerca nel record il campo e vi scrive

void write(const char* val, TRectype& rec) const; }; diff --git a/include/scanner.h b/include/scanner.h index 903e2b183..21be169c5 100755 --- a/include/scanner.h +++ b/include/scanner.h @@ -18,7 +18,7 @@ // @class TScanner | Classe per le lettura e la traduzione dei file // // @base private | ifstream -class TScanner : private ifstream +class TScanner : public ifstream // @author:(INTERNAL) Guido { // @access:(INTERNAL) Private Member diff --git a/include/sheet.cpp b/include/sheet.cpp index 027d31c0e..7eab209ad 100755 --- a/include/sheet.cpp +++ b/include/sheet.cpp @@ -1,94 +1,667 @@ -#include #include -#include -#include +#include +#include #include #include #include #include +#include + +/////////////////////////////////////////////////////////// +// TSheet_control +/////////////////////////////////////////////////////////// + +class TSheet_control : public TControl +{ + enum { FIRST_FIELD = 101, MAX_COL = 128 }; + + TSheet* _sheet; + long _cur_rec; + + // @cmember:(INTERNAL) Tipo di ogni colonna + byte _type[MAX_COL]; + + // @cmember:(INTERNAL) Indica se e attivata la gestione dei check delle righe + bool _check_enabled; + + // @cmember:(INTERNAL) Array di righe attivate + TBit_array _checked; + + // @cmember:(INTERNAL) Array di righe disabilitate + TBit_array _disabled; + +protected: // TControl + //@cmember Gestisce gli eventi delle celle + virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev); + +protected: + long items() const { return _sheet->items(); } + TToken_string& row(long n) const { return _sheet->row(n); } + + int rec2row(long rec) const; + long row2rec(int row) const; + + void make_current(long rec); + +public: // TControl + virtual void set_rect(const RCT& r); + +public: + long selected() const { return _cur_rec; } + void select(long n); + void set_focus_rec(long rec); + + void enable_check(bool on) { _check_enabled = on && _type[0] == 'C'; } + bool check_enabled() const { return _check_enabled; } + void check(long n, bool on); + void toggle(long n); + bool checked(long n) const { return _checked[n]; } + long checked() const { return _checked.ones(); } + bool one_checked() const; + + int visible_rows() const; + + void enable_row(long r, bool on); + void disable_row(long r); + bool row_enabled(long n) const { return _disabled[n] == FALSE; } + bool one_enabled() const { return _disabled.first_one() < 0; } + + byte& column_type(int c) { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; } + + void update(long n = -1); + + TSheet_control(TSheet* sheet, short cid, + short x, short y, short dx, short dy, + const char* flags, const char* head); + virtual ~TSheet_control() {} +}; + + +TSheet_control::TSheet_control( + TSheet* sheet, // @parm Finestra alla quale appartiene lo spreadsheet + short cid, // @parm Identificatore + short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet + short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet + short dx, // @parm Larghezza (in caratteri) dello spreasheet + short dy, // @parm Lunghezza (in caratteri) dello spreasheet + const char* flags, // @parm Flags di abilitazione + const char* head) // @parm Titolo delle colonne + : _sheet(sheet), _cur_rec(0), _check_enabled(FALSE) + +{ + const int NUMBER_WIDTH = 7; + short v_width[MAX_COL]; + int fixed_columns = 1; // Number of fixed columns + + // Calcolo larghezza massima tabella + + TToken_string header(head); + TToken_string new_header(256); + int i = 0, tot_width = NUMBER_WIDTH+1; + int f_width = tot_width<<1; // Stima larghezza colonne fisse + int max_width = f_width; // Stima larghezza della colonna piu' grande + + for (const char* h = header.get(); h; h = header.get(), i++) + { + CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); + _type[i] = ' '; + TString testa(h); + const int at = testa.find('@'); + int v = testa.len(); // Video width + if (at >= 0) + { + const TString& wi = testa.mid(at+1); + v = atoi(wi); + if (wi.find('F') >= 0) + { + fixed_columns++; + f_width += v+1; + } + if (wi.find('R') >= 0) + _type[i] = 'R'; else + if (wi.find('M') >= 0) + _type[i] = 'M'; else + if (wi.find('C') >= 0) + _type[i] = 'C'; + + if (i == 0 && v <= 1) + { + _type[i] = 'C'; + _check_enabled = TRUE; + fixed_columns++; + f_width += v+1; + } + + testa.cut(at); + v = max(at, v); + } + + v_width[i] = v+1; // v = width of column + if (v >= max_width) max_width = v+1; + + tot_width += v_width[i]; + + new_header.add(testa); + } + const int _columns = i; + + WINDOW parent = sheet->win(); + + // Calcola rettangolo massimo per lo sheet + XI_RCT rct; coord2rct(parent, x, y, dx, dy, rct); + rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar + + // Controlla se ci sono troppe colonne fisse + if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right) + fixed_columns = 1; + + XI_OBJ* itf = get_interface(parent); + + XI_OBJ_DEF* listdef = xi_add_list_def(NULL, cid, + rct.top, rct.left, rct.bottom-rct.top, + XI_ATR_ENABLED | XI_ATR_VISIBLE | XI_ATR_NAVIGATE, + NORMAL_COLOR, NORMAL_BACK_COLOR, // normal + DISABLED_COLOR, DISABLED_BACK_COLOR, // disabled + FOCUS_COLOR, // active + 0); + + listdef->app_data = (long)this; + + XI_LIST_DEF* l = listdef->v.list; + l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()); + l->sizable_columns = TRUE; + l->movable_columns = TRUE; + l->fixed_columns = fixed_columns; + l->scroll_bar = TRUE; + l->scroll_bar_button = TRUE; + l->white_space_color = MASK_DARK_COLOR; + l->row_focus_border = TRUE; + + // Definizione della prima colonna (numero di riga) + const long attr = XI_ATR_VISIBLE | XI_ATR_RJUST | XI_ATR_SELECTABLE; + XI_OBJ_DEF* coldef = xi_add_column_def(listdef, FIRST_FIELD-1, attr, FIRST_FIELD, + NUMBER_WIDTH * XI_FU_MULTIPLE, NUMBER_WIDTH, ""); + + coldef->app_data = (long)this; + coldef->v.column->heading_platform = TRUE; + coldef->v.column->column_platform = TRUE; + coldef->v.column->center_heading = TRUE; + + for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) + { + const int cid = FIRST_FIELD+i; // Column & Field ID + long attr = XI_ATR_VISIBLE | XI_ATR_ENABLED | XI_ATR_AUTOSCROLL | XI_ATR_READONLY; + if (_type[i] == 'C') + attr |= XI_ATR_SELECTABLE; + if (_type[i] == 'R') + attr |= XI_ATR_RJUST; + coldef = xi_add_column_def(listdef, cid, attr, cid+1, + v_width[i] * XI_FU_MULTIPLE, v_width[i], (char*)h); + + coldef->app_data = (long)this; + coldef->v.column->heading_platform = TRUE; + coldef->v.column->center_heading = TRUE; + + if (i == 0 && _type[i] == 'C') + { + coldef->v.column->icon_rid = ICO_CHECK_ON; + if (l->min_heading_height < 20) + l->min_heading_height = 20; + } + } + + RCT rd; xi_get_def_rect(listdef, &rd); + if ((rd.right - rd.left) > (rct.right - rct.left)) + l->width = rct.right - rct.left; + + _obj = xi_create(itf, listdef); // Create the whole thing! + xi_dequeue(); // Flush events in XOL + xi_tree_free(listdef); // Free definitions + + CHECKD(_obj, "Can't create spreadsheet ", cid); + update_tab_cid(); + + // Se la finestra e' troppo grande riducila + RCT cli; xvt_vobj_get_client_rect(parent, &cli); + xi_get_rect(_obj, &rct); + + if (rct.right < cli.right - 2*XI_FU_MULTIPLE) + { + const int width = rct.right + 2*XI_FU_MULTIPLE; + cli.left = (cli.right - width) / 2; + cli.right = cli.left + width; + xvt_vobj_translate_points(parent, xvt_vobj_get_parent(parent), (PNT*)&cli, 2); + xvt_vobj_move(parent, &cli); + } +} + +void TSheet_control::set_rect(const RCT& r) +{ + const int width = r.right - r.left - 2*XI_FU_MULTIPLE; + const int height = r.bottom - r.top; + xi_set_list_size(_obj, height, width); +} + +// Converts a row number in the correspondig record number +int TSheet_control::rec2row(long record) const +{ + int rows; + const long* rec = xi_get_list_info(_obj, &rows); + int r = int(record - rec[0]); + if (r < 0 || r >= rows) + r = -1; + return r; +} + + +// Converts a row number in the correspondig record number +long TSheet_control::row2rec(int row) const +{ + int rows; + const long* handle = xi_get_list_info(_obj, &rows); + + if (row < 0) + row = 0; + else + { + if (row >= rows) + row = rows-1; + } + const long r = handle[row]; + CHECKD(r >= 0 && r < items(), "Sheet line out of range: ", row); + + return r; +} + +int TSheet_control::visible_rows() const +{ + return xi_get_visible_rows(_obj, NULL, NULL); +} + +void TSheet_control::update(long n) +{ + if (n >= 0) + { + const int riga = rec2row(n); + if (riga >= 0) + { + XI_OBJ row; + XI_MAKE_ROW(&row, _obj, riga); + xi_cell_request(&row); + } + } + else + { + xi_cell_request(_obj); + int num = 0; + const long* handle = xi_get_list_info(_obj, &num); + + bool scroll_first = items() == 0; // || !owner().mask().is_running(); + if (!scroll_first) + { + int first, last; + xi_get_visible_rows(_obj, &first, &last); + n = handle[first]; + scroll_first = n > items(); + } + + if (scroll_first) + xi_scroll(_obj, XI_SCROLL_FIRST); + else + xi_scroll_rec(_obj, n, FOCUS_COLOR, XI_ATR_ENABLED, 0); + } +} + +void TSheet_control::make_current(long rec) +{ + const long old = _cur_rec; + _cur_rec = rec; + + XI_OBJ o; + int row = rec2row(old); + if (row >= 0) + { + XI_MAKE_ROW(&o, _obj, row); + xi_cell_request(&o); + } + + row = rec2row(rec); + if (row >= 0) + { + XI_MAKE_ROW(&o, _obj, row); + xi_cell_request(&o); + } +} + +void TSheet_control::select(long rec) +{ + if (rec >= 0 && rec < items()) + xi_scroll_rec(_obj, rec, FOCUS_COLOR, XI_ATR_ENABLED, 0); + make_current(rec); +} + +void TSheet_control::set_focus_rec(long rec) +{ + if (rec < 0) + rec = selected(); + int r = rec2row(rec); + if (r < 0) + { + select(rec); + r = rec2row(rec); + } + XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, r, 1); + xi_set_focus(&cell); +} + +bool TSheet_control::one_checked() const +{ + bool yes = FALSE; + if (check_enabled()) + { + const long first = _checked.first_one(); + yes = first >= 0; + } + return yes; +} + +// @mfunc Permette di attivare/disattivare una riga +void TSheet_control::check( + long n, // @parm Numero della riga da attivare/disattivare + bool on) // @parm Operazione da effettuare sulla riga: + // + // @flag TRUE | Attiva la riga

.esima (default) + // @flag FALSE | Disattiva la riga

.esima +{ + if (n < 0) + { + if (on) + { + const long tot = items()-1; + _checked.set(tot); // Forza le dimensioni del bit array + _checked.set(); // Setta tutti i bit + + // Elimina bit in eccesso alla fine dell'array + for (long i = _checked.items()-1; i > tot; i--) + _checked.reset(i); + + // Elimina i bit corrispondenti a righe disabilitate + if (_disabled.first_one() >= 0) + { + for (long i = tot; i >= 0; i--) + if (_disabled[i]) _checked.reset(i); + } + } + else + _checked.reset(); + + XI_OBJ* column = xi_get_obj(_obj, FIRST_FIELD); + xi_cell_request(column); + } + else + { + if (!_disabled[n]) + _checked.set(n, on); + XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, rec2row(n), 1); + xi_cell_request(&cell); + } +} + +void TSheet_control::toggle(long n) +{ + check(n, !checked(n)); +} + +// @doc INTERNAL + +// @mfunc Abilita/disabilita una riga +void TSheet_control::enable_row( + long n, // @parm Numero della riga da abilitare/diabilitare (default -1) + bool on) // @parm Operazione da svolgere sulla riga + // + // @flag TRUE | Abilita la riga

-esima (default) + // @flag FALSE | Disabilita la riga

-esima + + // @comm Se

e' minore di 0 allora vengono abilitate/disabilitate tutte le righe +{ + if (n >= 0) + { + _disabled.set(n, !on); + } + else + { + if (on) + _disabled.reset(); + else + { + const long tot = items()-1; + _disabled.set(tot); // Forza le dimensioni del bit-array + _disabled.set(); // Disabilita tutte le righe + + // Resetta i bit in ecesso alla fine del bit-array + for (long i = _disabled.items()-1; i > tot; i--) + _disabled.reset(i); + } + } + update(n); +} + +// Certified 75% +bool TSheet_control::event_handler(XI_OBJ* itf, XI_EVENT *xiev) +{ + BOOLEAN& refused = xiev->refused; + + switch (xiev->type) + { + case XIE_GET_FIRST: + if (items() > 0L) + { + long n = items() * (long)xiev->v.rec_request.percent / 100L; + if (n < 0L) n = 0L; + xiev->v.rec_request.data_rec = n; + } + else + refused = TRUE; + break; + case XIE_GET_LAST: + xiev->v.rec_request.data_rec = items()-1; + break; + case XIE_GET_PREV: + case XIE_GET_NEXT: + { + const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ; + if (n < 0 || n >= items()) + refused = TRUE; + else + xiev->v.rec_request.data_rec = n; + } + break; + case XIE_CELL_REQUEST: + { + const long rec = xiev->v.cell_request.rec; + const char* src = NULL; + int nm; + XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm); + const int num = xiev->v.cell_request.col_nbr; + const int cid = obj[num]->cid; + + if (cid >= FIRST_FIELD) + { + if (rec < items()) + { + const int col = cid - FIRST_FIELD; + switch (_type[col]) + { + case 'C': // Set value for "checkable" cell + { + const bool on = checked(rec); + xiev->v.cell_request.icon_rid = on ? ICO_CHECK_ON : ICO_CHECK_OFF; + if (on) src = "X"; + } + break; + case 'M': // Set value for "roman" cell + src = itor(atoi(row(rec).get(col))); + break; + default: // Set value for "normal" cell + src = row(rec).get(col); + break; + } + if (rec == _cur_rec) + { + xiev->v.cell_request.color = FOCUS_COLOR; + xiev->v.cell_request.back_color = FOCUS_BACK_COLOR; + } + } + } + else + { + src = format("%ld", rec+1); + } + + char* dst = xiev->v.cell_request.s; + if (src && *src) + { + const int len = xiev->v.cell_request.len; + strncpy(dst, src, len); + dst[len-1] = '\0'; + } + else + *dst = '\0'; + } + break; + case XIE_DBL_CELL: + { + const long rec = row2rec(xiev->v.xi_obj->v.cell.row); + if (!_disabled[rec]) + { + make_current(rec); + _sheet->on_key(K_ENTER); + } + else + refused = TRUE; + } + break; + case XIE_ON_ROW: + { + const long rec = row2rec(xiev->v.xi_obj->v.row); + if (_disabled[rec]) + refused = TRUE; + else + make_current(rec); + } + break; + case XIE_GET_PERCENT: + { + const long rec = xiev->v.get_percent.record; + long n = items(); if (n <= 0) n = 1; + xiev->v.get_percent.percent = int(rec * 100L / n); + } + break; + case XIE_CHAR_CELL: + { + long rec = -1; + switch (xiev_to_key(xiev)) + { + case K_LHOME: + rec = 0; + break; + case K_PREV: + rec = _cur_rec - visible_rows(); + if (rec < 0) rec = 0; + break; + case K_NEXT: + rec = _cur_rec + visible_rows(); + if (rec >= items()) + rec = items()-1; + break; + case K_LEND: + rec = items()-1; + break; + default: + break; + } + if (rec >= 0) + { + _sheet->post_select(rec); + refused = TRUE; + } + } + break; + case XIE_SELECT: + if (xiev->v.xi_obj->type == XIT_ROW) + { + int num; + XI_OBJ ** column = xi_get_member_list(_obj, &num); + const int col = xiev->v.select.column; + + const int row = xiev->v.select.xi_obj->v.row; + const long rec = row2rec(row); + + if (column[col]->cid >= FIRST_FIELD) + { + toggle(rec); + XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, row, col); + xi_cell_request(&cell); + } + else + { + if (_cur_rec == rec) + _sheet->on_key(K_CTRL+'G'); + else + { + XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, row,1); + xi_set_focus(&cell); + } + make_current(rec); + } + } + refused = TRUE; + break; + case XIE_BUTTON: + if (xiev->v.xi_obj->type == XIT_LIST) + _sheet->on_key(K_INS); + break; + default: + break; + } + + return !refused; +} /////////////////////////////////////////////////////////// // TSheet /////////////////////////////////////////////////////////// - + TSheet::TSheet(short x, short y, short dx, short dy, - const char* title, const char* head, byte buttons, - long first, WINDOW parent) -: _curr(first), _last_update(-1), _checkable(FALSE), - _check_enabled(TRUE), _buttonmask(buttons) + const char* title, const char* head, + byte buttons, short sht_y) + : TMask(title, sht_y == 0 ? 1 : 2, dx, dy, x, y), + _parked(-1), _sheet(NULL), _select_row(-1) { - const char* g; + _sheet = new TSheet_control(this, 883, 1, sht_y, -1, -3, "", head); - TToken_string new_head(512); - TToken_string h(head); - TString item(80); - - for(_columns = 0; (g = h.get()) != NULL; _columns++) + if (!(buttons & 0x10)) add_button(DLG_SELECT, "Selezione", K_ENTER); + if (check_enabled()) { - CHECK(_columns < MAX_COL, "Too many columns in sheet "); - item = g; - - const int et = item.find('@'); - if (et >= 0) - { - const char t = item.right(1)[0]; - _type[_columns] = isalpha(t) ? toupper(t) : '\0'; - const int l = atoi(item.mid(et+1)); - item.cut(et); - if (_columns == 0 && et == 0 && l <= 1) - _checkable = _size[0] = 1; - else - _size[_columns] = l > 0 ? l : item.len(); - } - else - { - _size[_columns] = item.len(); - _type[_columns] = '\0'; - } - - item.trim(); - new_head.add(item); - } - set_row(new_head, -1); - - for (int i = 0; i < MAX_BUT; i++) _button[i] = NULL_WIN; - - if (parent == NULL_WIN) parent = TASK_WIN; - - long flags = WSF_CLOSE | WSF_SIZE | WSF_VSCROLL | WSF_HSCROLL ; - WIN_TYPE wt = W_DOC; - - if (parent != TASK_WIN) - { - wt = W_PLAIN; - flags = WSF_VSCROLL; - } - - if (dx == 0) // Compute window width - { - RCT r; xvt_vobj_get_client_rect(parent, &r); - dx = r.right/CHARX -6; - - const int larg = width(); - if (dx > larg) dx = larg; + add_button(DLG_USER, "Tutti", 0); + set_handler(DLG_USER, tutti_handler); } - if (dy == 0) dy = 20; // Compute window height - create(x, y, dx, dy, title, flags, wt, parent); - if (wt != W_PLAIN) // If normal sheet add buttons - { - _visible_rows = rows()- head_on() - 3; - - if (!(buttons & 0x10)) add_button(DLG_SELECT, "Selezione", K_ENTER); - if (_checkable) add_button(DLG_USER, "Tutti"); - if (buttons & 0x1) add_button(DLG_LINK, "Gestione", K_INS); - if (buttons & 0x2) add_button(DLG_NEWREC, "~Nuovo", K_CTRL+'N'); - if (buttons & 0x4) add_button(DLG_DELREC, "Elimina", K_DEL); - if (buttons & 0x8) add_button(DLG_QUIT, "Fine", K_ESC); - else add_button(DLG_CANCEL, "Annulla", K_ESC); - } + if (buttons & 0x1) add_button(DLG_LINK, "~Gestione", K_CTRL+'G'); + if (buttons & 0x2) add_button(DLG_NEWREC, "Nuovo", K_INS); + if (buttons & 0x4) add_button(DLG_DELREC, "Elimina", K_DEL); + if (buttons & 0x8) add_button(DLG_QUIT, "Fine", K_ESC); + else add_button(DLG_CANCEL, "Annulla", K_ESC); } +TSheet::~TSheet() +{ + delete _sheet; +} + +TSheet_control& TSheet::sheet() +{ return *_sheet; } + // @doc INTERNAL // @mfunc Aggiunge un bottone nella finestra @@ -96,263 +669,123 @@ void TSheet::add_button( short id, // @parm Identificatore del bottone da aggiungere const char* caption, // @parm Testo del bottone da aggiungere KEY key) // @parm Combinazione di tasti corrispondente -{ -#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT - const int BUT_HEIGHT = 2; -#else - const int BUT_HEIGHT = 1; -#endif - - WINDOW b = xvt_create_control(WC_PUSHBUTTON, 0, 0, 11, BUT_HEIGHT, caption, win(), 0, 0, id); - for (int i = 0; i < MAX_BUT; i++) - if (_button[i] == NULL_WIN) - { - _button[i] = b; - _key[i] = key; - break; - } +{ + TButton_field& butt = TMask::add_button(id, 0, caption, 0, -1, 11, 2, ""); + butt.set_hot_key(key); } void TSheet::repos_buttons() const -{ - for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++) - if (buttons == MAX_BUT-1) { buttons++; break; } - if (buttons == 0) return; +{ + if (_sheet == NULL) + return; // Sono ancora in fase di creazione: aspetta! + + RCT br; + int buttons = 0; + for (int f = fields()-1; f >= 0; f--) + { + TMask_field& c = fld(f); + if (c.is_kind_of(CLASS_BUTTON_FIELD)) + { + if (buttons == 0) + c.get_rect(br); + buttons++; + } else + if (c.is_edit()) + ((TEdit_field&)c).autoselect(FALSE); + } RCT wr; xvt_vobj_get_client_rect(win(), &wr); - RCT br; xvt_vobj_get_client_rect(_button[0], &br); - - int space = (wr.right - buttons * br.right) / (buttons+1); - if (space < 0) space = 0; - - int x = space; - const int y = wr.bottom - br.bottom-4; - for (int b = 0; b < buttons; b++, x += br.right+space) - { - RCT r; xvt_rect_set(&r, x, y, x+br.right, y+br.bottom); - xvt_vobj_move(_button[b], &r); - } -} - -void TSheet::open() -{ - set_scroll_max(width(), items()); - _last_update = -1; - - if (!is_visible(_curr)) set_first(_curr); - - if (buttons_on()) - { - // Abilita selezione se c'e' almeno un elemento - xvt_enable_control(_button[0], items() > 0 && _disabled.ones() < items()); + const short width = br.right - br.left; + const short height = br.bottom - br.top; - if (_checkable) - xvt_enable_control(_button[1], items() > 0 && _check_enabled); + int space = (wr.right - buttons * width) / (buttons+1); + if (space < 0) space = 0; + int x = space; + const int y = wr.bottom - height - XI_FU_MULTIPLE; - repos_buttons(); - } - TScroll_window::open(); - force_update(); -} - - -void TSheet::set_first(long n) -{ - update_thumb(-1, n); -} - - -void TSheet::set_row(const TToken_string& r, byte i) -{ - if (i > 64) i = 0; else i++; - _page.add(r, i); -} - -// @doc INTERNAL - -// @mfunc Crea la pagina -void TSheet::build_page( - long from) // @parm Numero della prima riga da visualizzare - - // @comm Carica le righe visibili -{ - const long f = (from < 0) ? first() : from; - - if (_last_update != f) - { - int r = visible_rows(); - if (f+r > items()) - r = int(items()-f); - if (r > 0) - page_build(f, r); - _last_update = f; - } -} - - -short TSheet::reserved_rows() const -{ - return buttons_on() ? 3 : 0; -} - - -void TSheet::handler(WINDOW win, EVENT* ep) -{ - switch(ep->type) - { - case E_FOCUS: - invert_row(selected()); - break; - case E_MOUSE_DOWN: - if (ep->v.mouse.button) - { - dispatch_e_char(win, K_ESC); - return; - } - case E_MOUSE_DBL: - { - const short y = ep->v.mouse.where.v / CHARY; - const short f = head_on() ? 1 : 0; - if (y >= f) - { - const long vec = selected(); - const long nuo = first()+y-f; - select(nuo); - if (ep->type == E_MOUSE_DBL) - dispatch_e_char(win, K_ENTER); - else if (vec == nuo) - { -// dispatch_e_char(win, K_SPACE); // Cosi' lo interpreta come spazio nel campo di edit!!! - TSheet::on_key(K_SPACE); // Mette l'eventuale segno di check - } - } - else - dispatch_e_char(win, y ? K_UP : K_PREV); - } - break; - case E_CONTROL: - switch(ep->v.ctl.id) - { - /* - case DLG_OK : - case DLG_SELECT: - dispatch_e_char(win, K_ENTER); break; - case DLG_CANCEL: - case DLG_QUIT : - dispatch_e_char(win, K_ESC); break; - case DLG_NEWREC: - dispatch_e_char(win, K_CTRL+'N'); break; - case DLG_LINK: - dispatch_e_char(win, K_INS); break; - case DLG_DELREC: - dispatch_e_char(win, K_DEL); break; - */ - case DLG_USER: - dispatch_e_char(win, one_checked() ? K_F2 : K_F3); break; - default: - { - const WINDOW b = ep->v.ctl.ci.win; - for (int i = 0; i < MAX_BUT; i++) - if (_button[i] == b) - { - // stop_run(_key[i]); - on_key(_key[i]); - return; - break; - } + for (f = 0; buttons > 0; f++) + { + TMask_field& c = fld(f); + if (c.is_kind_of(CLASS_BUTTON_FIELD)) + { + buttons--; + const PNT p = { y, x }; + xvt_rect_set_pos(&br, p); + c.set_rect(br); + x += space+width; } - break; - } - break; - case E_SIZE: - { - _last_update = -1; - _visible_rows = ep->v.size.height/CHARY - (head_on() ? 1 : 0); - if (buttons_on()) - { - _visible_rows -= reserved_rows(); - repos_buttons(); - } - force_update(); - } - break; - default: - break; - } - - TScroll_window::handler(win, ep); + } } -// @doc INTERNAL - -// @mfunc Converte le coordinate da logiche (caratteri) in coordinate fisiche (pixel) -// (vedi ) -// -// @rdesc Ritorna le coordinate fisiche cercate -PNT TSheet::log2dev( - long x, // @parm Coordinata X da convertire - long y) const // @parm Coordinata Y da convertire +void TSheet::start_run() { - if (autoscrolling()) x -= origin().x; - return TWindow::log2dev(x, y); + // Abilita selezione se c'e' almeno un elemento + const int pos = id2pos(DLG_SELECT); + if (pos >= 0) + fld(pos).enable(items() > 0 && _sheet->one_enabled()); + + _parked = -1; + + repos_buttons(); + _sheet->update(); } +long TSheet::selected() const +{ return _sheet->selected(); } + +bool TSheet::check_enabled() const +{ return _sheet->check_enabled(); } + +void TSheet::enable_check(bool on) +{ _sheet->enable_check(on); } + +void TSheet::check(long n, bool on) +{ _sheet->check(n, on); } + +bool TSheet::checked(long n) const +{ return _sheet->checked(n); } + +long TSheet::checked() const +{ return _sheet->checked(); } + +bool TSheet::one_checked() const +{ return _sheet->one_checked(); } + +void TSheet::enable_row(long r, bool on) +{ _sheet->enable_row(r, on); } + +bool TSheet::row_enabled(long r) const +{ return _sheet->row_enabled(r); } + bool TSheet::on_key(KEY key) { switch(key) { case K_ENTER: if (items() == 0) key = K_ESC; - if (selected() < 0 || _disabled[selected()]) + if (selected() < 0 || !_sheet->row_enabled(selected())) break; case K_ESC: stop_run(key); + break; case K_DEL: - if ((_buttonmask & 0x4) && items()) + if (items() && id2pos(DLG_DELREC) >= 0) stop_run(key); break; case K_INS: - if (_buttonmask & 0x1) + if (id2pos(DLG_NEWREC) >= 0) stop_run(key); break; - case K_CTRL+'N': - if (_buttonmask & 0x2) + case K_CTRL+'G': + if (id2pos(DLG_LINK) >= 0) stop_run(key); break; - case K_LHOME: - select(0); - return TRUE; - case K_LEND: - select(items()-1); - return TRUE; - case K_PREV: - select(selected()-visible_rows()); - return TRUE; - case K_UP: - select(selected()-1); - return TRUE; - case K_NEXT: - select(selected()+visible_rows()); - return TRUE; - case K_DOWN: - select(selected()+1); - return TRUE; - case K_CTRL+'P': - print(); - break; - default: - for (int i = 0; i < MAX_BUT; i++) - if (_key[i] == key) - { - if (key != K_ENTER || !_disabled[selected()]) - stop_run(key); - break; - } + default: break; } - if (_checkable && _check_enabled && items() > 0) - { + if (check_enabled() && items() > 0) + { switch(key) { case K_SPACE: @@ -368,33 +801,8 @@ bool TSheet::on_key(KEY key) break; } } - return TScroll_window::on_key(key); -} -// @doc INTERNAL - -// @mfunc Abilita/disabilita una riga -void TSheet::enable( - long n, // @parm Numero della riga da abilitare/diabilitare (default -1) - bool on) // @parm Operazione da svolgere sulla riga - // - // @flag TRUE | Abilita la riga

-esima (default) - // @flag FALSE | Disabilita la riga

-esima - - // @comm Se

e' minore di 0 allora vengono abilitate/disabilitate tutte le righe -{ - if (n >= 0) - _disabled.set(n, !on); - else - { - if (on) - _disabled.reset(); - else - { - _disabled.set(items()); - _disabled.set(); - } - } + return TRUE; } // @doc INTERNAL @@ -404,194 +812,29 @@ void TSheet::select( long n) // @parm Riga da selezionare (default -1) // @comm Se

assume un valore minore di 1 viene selezionata la prima riga. - // Nela caso si cerci di selezionare una riga maggiore di quelle presenti viene selezionata - // l'ultima. + // Nela caso si cerci di selezionare una riga maggiore di quelle presenti + // viene selezionata l'ultima. { - if (n < 0) n = 0; else - if (n >= items()) n = items()-1; + _sheet->select(n); +} - invert_row(_curr); - _curr = n; - - if (is_visible(_curr)) - invert_row(_curr); - else +void TSheet::post_select(long rec) +{ + _select_row = rec; +} + +void TSheet::on_idle() +{ + if (_select_row >= 0) { - const long s = (_curr < first()) ? _curr : _curr-visible_rows()+1; - set_first(s); - force_update(); + _sheet->select(_select_row); + _select_row = -1; + _sheet->set_focus_rec(-1); } } // @doc INTERNAL -// @mfunc Permette di attivare/disattivare una riga -void TSheet::check( - long n, // @parm Numero della riga da attivare/disattivare - bool on) // @parm Operazione da effettuare sulla riga: - // - // @flag TRUE | Attiva la riga

.esima (default) - // @flag FALSE | Disttiva la riga

.esima -{ - long s = selected(); - - if (n < 0) - { - if (on) - { - const long tot = items()-1; - _checked.set(tot); // Force the size of Bit_array - _checked.set(); - - // Elimina bit in eccesso alla fine dell'array - for (long i = _checked.items()-1; i > tot; i--) - _checked.reset(i); - - if (on && _disabled.first_one() >= 0) - { - for (long i = 0; i < items(); i++) - if (_disabled[i]) _checked.reset(i); - else s = i; - } - } - else - _checked.reset(); - } - else - { - if (!_disabled[n]) - _checked.set(n, on); - } - - force_update(); - select(s); -} - - -// Converte il numero di riga assoluto nell'indice dell'array _page -int TSheet::row_to_page(long n) const -{ - long i = (n < 0) ? 0L : n-first()+1; -#ifdef DBG - if (i < 0 || i > visible_rows()) - { - yesnofatal_box("Line out of screen: %ld", n); - i = 1; - } -#endif - return (int)i; -} - - -// Converte il numero di riga assoluto nella coordinata y sulla finestra -int TSheet::row_to_win(long n) const -{ - int y = row_to_page(n); - - if (y < 1) y = 0; else - if (!head_on()) y--; - - return y; -} - - -// Calcola la larghezza totale dello sheet virtuale -int TSheet::width() const -{ - int width = 0; - for (int c = 0; c < _columns; c++) - width += _size[c]+(c > 0); - return width; -} - -void TSheet::invert_row(long n) -{ - if (win() != NULL_WIN && is_visible(n)) - { - const short y = row_to_win(n); - autoscroll(FALSE); - invert_bar(0,y,columns(),y+1); - autoscroll(TRUE); - } -} - -// @doc INTERNAL - -// @mfunc Forza il ridisegno di una riga. -// -// @rdesc Ritorna se e' riuscito a fare il ridisegno (cioe' se la riga era visibile) -bool TSheet::update_row( - long n) // @parm Numero della riga da ridisegnare -{ - const int i = row_to_page(n); - if (i >= _page.items()) return FALSE; - TToken_string& t = _page.row(i); - t.restart(); - - const bool chk = n >= 0 && _checked[n] && !_disabled[n]; - bool changed = FALSE; - - if (chk) - { - set_color(FOCUS_COLOR, NORMAL_BACK_COLOR); - changed = TRUE; - } - else if (_disabled[n]) - { - set_color(DISABLED_COLOR, NORMAL_BACK_COLOR); - changed = TRUE; - } - - if (n < 0) - set_font("", XVT_FS_NONE, 0); - - int minx = (int)origin().x; - int maxx = minx + columns(); - minx -= 80; - - int x = 0; - const int y = row_to_win(n); - const char* s; - - for (int j = 0; x < maxx && (s = t.get()) != NULL; x += _size[j++]+1) if (x > minx) - { - int x1 = x; - if (n >= 0) - { - if (_checkable && j == 0) - { - s = chk ? "X" : " "; - } - switch (_type[j]) - { - case 'R': - x1 += _size[j]-strlen(s); // Allinea a destra - break; - case 'M': - s = itor(atoi(s)); // Numeri romani - break; - default: - break; - } - } - else - { - x1 += (_size[j]-strlen(s)) >> 1; // Centra le testate - } - - stringat(x1, y, s); - } - if (changed) - set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); - - if (n < 0) - set_font("", XVT_FS_NONE, 0); - - return TRUE; -} - -// @doc INTERNAL - // @mfunc Ritorna il contenuto di una riga // // @rdesc Ritorna la con tutti gli elemnti della riga @@ -602,101 +845,19 @@ TToken_string& TSheet::row( // selezionata. { if (n < 0) n = selected(); - - int idx = 1; -// if (!is_visible(n) || _last_update < 0) - if (_last_update < 0 || n < _last_update || n >= _last_update + _page.items() -1) - { -// if (_last_update < 0) -// set_scroll_max(width(), items()); - build_page(n); -// set_first(n); - } - else - idx = int(n - _last_update) + 1; -// const int idx = row_to_page(n); - return (TToken_string&)_page[idx]; + if (n != _parked) + get_row(_parked = n, _park); + return _park; } - -void TSheet::update() +bool TSheet::tutti_handler(TMask_field& f, KEY k) { - if (_last_update < 0) - { - set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); - set_pen(NORMAL_COLOR); - set_brush(NORMAL_BACK_COLOR); - set_font("", XVT_FS_NONE, 0); - _visible_rows = rows() - reserved_rows() - head_on(); + if (k == K_SPACE) + { + TSheet& s = (TSheet&)f.mask(); + s.check(-1, !s.one_checked()); } - - if (head_on()) - { - const int height = visible_rows()+1; - const int width = columns()+1; - short x = -1; - for (int c = 0; c < _columns; c++) - { - x += _size[c] + 1; - line(x,0,x,height); - } - autoscroll(FALSE); - set_brush(MASK_BACK_COLOR); - bar(0,0,width,1); - if (buttons_on()) - bar(0, height, width, height+reserved_rows()+1); - autoscroll(TRUE); - } - - build_page(); - if (head_on()) update_row(-1); - - long last = first() + visible_rows(); - if (last > items()) last = items(); - for (long n = first(); n < last; n++) update_row(n); - - if (xvt_scr_get_focus_vobj() == win()) - invert_row(selected()); -} - -void TSheet::print() -{ - TPrinter& pr = printer(); - TPrintrow row; - bool ok = pr.open(); - - main_app().begin_wait(); - - int step = visible_rows(); - for (long n = 0L; ok && n < items(); n += step) - { - set_first(n); - build_page(); - - if ((n+step) > items()) step = int(items()-n); - for (int i = 1; ok && i <= step; i++) - { - const char* s; - - TToken_string& t = (TToken_string&)_page[i]; - t.restart(); - - row.reset(); - for (int j = 0, x = 0; (s = t.get()) != NULL; x += _size[j++]+1) - row.put(s, x); - - ok = pr.print(row); - } - } - - main_app().end_wait(); - - if (ok) - { - pr.formfeed(); - pr.close(); - } - set_focus(); + return TRUE; } /////////////////////////////////////////////////////////// @@ -704,10 +865,9 @@ void TSheet::print() /////////////////////////////////////////////////////////// TArray_sheet::TArray_sheet(short x, short y, short dx, short dy, - const char* caption, const char* head, byte buttons, WINDOW parent) -: TSheet(x, y, dx, dy, caption, head, buttons, 0L, parent) + const char* caption, const char* head, byte buttons) + : TSheet(x, y, dx, dy, caption, head, buttons) { - select(0); } // Certified 90% @@ -717,17 +877,6 @@ bool TArray_sheet::destroy(int i) enable(-1); return _data.destroy(i, TRUE); } -// Certified 100% -// @doc EXTERNAL - -// @mfunc Copia le righe nella pagina da visualizzare -void TArray_sheet::page_build( - long first, // @parm Prima riga da visualizzare - byte num) // @parm Numero di righe da vsiualizzare -{ - for (byte i = 0; i < num; i++) - set_row(data(first+i), i); -} // @doc EXTERNAL @@ -741,22 +890,19 @@ long TArray_sheet::add( // @syntax add(const TToken_string& s) // @syntax add(const TToken_string* s) { - const long n = _data.add(s, -1); - set_scroll_max(-1, n); + const long n = _data.add(s); return n; } long TArray_sheet::add(TToken_string* s) { const long n = _data.add(s); - set_scroll_max(-1, n); return n; } long TArray_sheet::insert(const TToken_string& s, long n) { _data.insert(s, (int)n); - set_scroll_max(-1, items()); return n; } @@ -766,13 +912,16 @@ long TArray_sheet::insert(const TToken_string& s, long n) /////////////////////////////////////////////////////////// TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields, - const char* title, const char* head, byte buttons) -: TSheet(-1,-1, 0, 0, title,head,buttons,cursor->pos()), - _cursor(cursor), _records(cursor->items()) + const char* title, const char* head, + byte buttons, short sht_y) + : TSheet(sht_y ? 3 : 0, sht_y ? 3 : 0, sht_y ? -3 : 0, sht_y ? -3 : 0, + title, head, buttons, sht_y), + _cursor(cursor), _records(cursor->items()) { TToken_string fldlst(fields); int campo = 0; for (const char* t = fldlst.get(0); t; t = fldlst.get(), campo++) + { if (*t > ' ' && *t != '"') { const TFieldref fr(t, 0); @@ -783,10 +932,11 @@ TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields, const TFieldtypes tipo = rf->type(); if (tipo == _intfld || tipo == _longfld || tipo == _realfld) { - byte& c = column_flag(campo); + byte& c = sheet().column_type(campo); if (c == '\0') c = 'R'; // Allinea a destra tutti i campi numerici } } + } } @@ -794,28 +944,23 @@ KEY TCursor_sheet::run() { _records = _cursor->items(); _cursor->freeze(TRUE); + select(_cursor->pos()); const KEY k = TSheet::run(); _cursor->freeze(FALSE); return k; } -void TCursor_sheet::page_build(long first, byte rows) +void TCursor_sheet::get_row(long row, TToken_string& l) { - TToken_string l(256); - - *_cursor = (TRecnotype)first; - for (int r = 0; r < rows; r++, ++(*_cursor)) + *_cursor = (TRecnotype)row; + l.cut(0); + const int last = _fields.last(); + for (int i = 0; i <= last; i++) { - l.cut(0); - const int last = _fields.last(); - for (int i = 0; i <= last; i++) - { - const TRecfield* rf = (TRecfield*)_fields.objptr(i); - const char* s = rf ? (const char*)*rf : ""; - l.add(s); - } - set_row(l, r); + const TRecfield* rf = (TRecfield*)_fields.objptr(i); + const char* s = rf ? (const char*)*rf : ""; + l.add(s); } } @@ -823,163 +968,116 @@ void TCursor_sheet::page_build(long first, byte rows) // TBrowse_sheet /////////////////////////////////////////////////////////// +HIDDEN TBrowse_sheet* _cur_browse = NULL; + +bool TBrowse_sheet::browse_field_handler(TMask_field& f, KEY k) +{ + long rec = -1; + if (k == K_SPACE) + { + TEdit_field& e = _cur_browse->field(); // Campo padre dello sheet + TMask& m = e.mask(); // Maschera che contiene lo sheet + TMask_field& c = m.field(f.dlg()); // Campo corrispondente sulla maschera + + // Ricopia su campo maschera + if (f.is_edit()) + { + TEdit_field& ef = (TEdit_field&)f; + c.set(ef.get_window_data()); + } + else + c.set(f.get()); + + TBrowse* b = e.browse(); + b->do_input(FALSE); + rec = b->cursor()->read(_isgteq); + } else + if (k == K_F2) + rec = 0; + if (rec >= 0) + _cur_browse->select(rec); + return TRUE; +} + + TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons, - TEdit_field* f, TToken_string* s) -: TCursor_sheet(cursor, fields, title, head, buttons), _field(f) - + TEdit_field* f, TToken_string& sibling) + : TCursor_sheet(cursor, fields, title, head, buttons, f->browse()->input_fields()), + _field(f), _sel(0) { - if (field().browse()->inputs() == 1 && cursor->items() > 0) - { -#if XVT_OS == XVT_OS_SCOUNIX - const int s = f->size()+2; -#else - const int s = f->size()+1; -#endif - xvt_create_control(WC_EDIT, 1, -3, s, 1, f->get(), win(), - CTL_FLAG_DISABLED, 0L, DLG_EDIT); - } - - if (s && s->items() > 0) - { - int maxlen = 0; - SLIST lst = xvt_slist_create(); - for (const char* item = s->get(0); item; item = s->get()) + TToken_string ca; // Tag buttons + int n = 0; + for (const char* s = sibling.get(0); s && *s; s = sibling.get(), n++) + { + const short id = f->atodlg(s); + const char* pr = sibling.get(); + if (id == f->dlg()) { - item = s->get(); - const int len = strlen(item); - if (len > maxlen) maxlen = len; - xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); + _sel = n; } - - WINDOW listbox = xvt_create_control(WC_LISTBUTTON, f->size()+3, -3, maxlen+3, 3, - "", win(), 0, 0L, DLG_FINDREC); - xvt_list_add(listbox, -1, (char*)lst); - xvt_slist_destroy(lst); - - TString16 id; id << f->dlg(); - _sel = s->get_pos(id) >> 1; - xvt_list_set_sel(listbox, _sel, TRUE); - } -} - - -short TBrowse_sheet::reserved_rows() const -{ - return TSheet::reserved_rows() + 1; -} - - -void TBrowse_sheet::repos_buttons() const -{ - TSheet::repos_buttons(); // Repos toolbar - - RCT wr; xvt_vobj_get_client_rect(win(), &wr); // Get window size - - int left = CHARX; // left coord of next control to draw - - for (int i = 0; i < 2; i++) - { - const short id = i ? DLG_EDIT : DLG_FINDREC; - const WINDOW w = xvt_win_get_ctl(win(), id); - if (w != NULL_WIN) + ca.add(pr); + } + if (n > 0) + add_tag_button(0, ca, _sel); + + short y = 0; + ca = f->browse()->get_input_fields(); + for (const char* i = ca.get(0); i; i = ca.get()) + { + if (*i != '"' && strchr(i, '@') == NULL) { - RCT r; xvt_vobj_get_client_rect(w, &r); - r.left = left; - r.top = wr.bottom - 4*CHARY + 4; - r.right += r.left; - r.bottom += r.top; - xvt_vobj_move(w, &r); - left = r.right+CHARX; // Increase left coord - } - } + const TMask_field& c = f->mask().field(f->atodlg(i)); + if (c.is_editable() && c.active()) + { + TEditable_field* e = NULL; + TString80 p = c.prompt(); + // Toglie spazi e simboli iniziali dal prompt + for (int a = 0; p[a] && !isalnum(p[a]); a++); + p.ltrim(a); p.left_just(20); + switch (c.class_id()) + { + case CLASS_EDIT_FIELD: + e = &add_string(c.dlg(), 0, p, 1, y++, c.size(), ""); + break; + case CLASS_REAL_FIELD: + e = &add_number(c.dlg(), 0, p, 1, y++, c.size(), ""); + break; + case CLASS_DATE_FIELD: + e = &add_date (c.dlg(), 0, p, 1, y++, ""); + break; + default: + break; + } + if (e) + { + e->set_handler(browse_field_handler); + e->set(c.get()); + if (e->dlg() == f->dlg()) + first_focus(f->dlg()); + } + } + } + } } - bool TBrowse_sheet::on_key(KEY k) { - const WINDOW ctl = xvt_win_get_ctl(win(), DLG_EDIT); - const bool alnum = k >= ' ' && k < K_UP; - - if (ctl != NULL_WIN && (alnum || k == K_BACKSPACE || k == K_DEL)) - { - const long oldsel = selected(); - const bool corre = field().mask().is_running(); - const WINDOW fldwin = field().win(); - - TString80 old(corre ? field().get_window_data() : field().get_field_data()); - TString80 val(old.ltrim()); - - if (alnum) - { - if (val.len() >= field().size()) - val.cut(0); - if (field()._flags.uppercase && isalpha(k)) - k = toupper(k); - val << char(k); - } - else val.rtrim(1); - - if (corre) xvt_vobj_set_title(fldwin, (char*)(const char*)val); - else field().set_field_data(val); - - ((TBrowse*)field().browse())->do_input(FALSE); - cursor()->read(); - if (cursor()->file().bad()) - { - beep(); - val = old; - if (corre) xvt_vobj_set_title(fldwin, (char*)(const char*)val); - else field().set_field_data(val); - *cursor() = oldsel; - } - else - select(cursor()->pos()); - - if (ctl != NULL_WIN) - { - val = corre ? field().get_window_data() : field().get_field_data(); - xvt_vobj_set_title(ctl, (char*)(const char*)val); - } - return TRUE; - } - else - { - field().set(""); - if (ctl != NULL_WIN) xvt_vobj_set_title(ctl, ""); - } - + if (k >= K_CTRL+K_F1 && k < K_CTRL+K_F10) + { + const int what = k - K_CTRL - K_F1; + if (what >= 0 && what != _sel) + TWindow::stop_run(k); + return TRUE; + } return TSheet::on_key(k); } - -void TBrowse_sheet::handler(WINDOW win, EVENT* ep) -{ - if (ep->type == E_CONTROL && ep->v.ctl.id == DLG_FINDREC) - { - const int what = xvt_list_get_sel_index(ep->v.ctl.ci.win); - if (what >= 0 && what != _sel) - stop_run(K_CTRL + what); - else - set_focus(); - return; - } - TCursor_sheet::handler(win, ep); -} - - KEY TBrowse_sheet::run() -{ - const bool spork = field().dirty(); // Store field status - const TString80 old(field().get()); - +{ + _cur_browse = this; const KEY key = TCursor_sheet::run(); - - if (key != K_ENTER) - { - field().set(old); // Restore field status - field().set_dirty(spork); - } - + _cur_browse = NULL; return key; } + diff --git a/include/sheet.h b/include/sheet.h index 353375099..0d852cd99 100755 --- a/include/sheet.h +++ b/include/sheet.h @@ -1,163 +1,71 @@ #ifndef __SHEET_H #define __SHEET_H -#ifndef __STRINGS_H -#include +#ifndef __MASK_H +#include #endif -#ifndef __WINDOW_H -#include -#endif - -#ifndef __RELATION_H -class TCursor; -#endif - -#ifndef __MASKFLD_H -class TEdit_field; -#endif - - // @doc INTERNAL // @class TSheet | Classe per la definizione e la gestione degli sheet per le ricerche // // @base public | TScroll_window -class TSheet : public TScroll_window +class TSheet : public TMask // @author:(INTERNAL) Guido // @access:(INTERNAL) Privete Member { - // @ccost:(INTERNAL) MAX_BUT | 8 | Numero massimo di bottoni - enum { MAX_BUT = 8, - // @ccost:(INTERNAL) MAX_COL | 128 | Numero massimo di colonne - MAX_COL = 128 }; + friend class TSheet_control; - // @cmember:(INTERNAL) Array di stringhe con il contenuto dello sheet - TString_array _page; - - // @cmember:(INTERNAL) Numero di colonne dello sheet - byte _columns; - // @cmember:(INTERNAL) Dimensione di ogni colonna - byte _size[MAX_COL]; - // @cmember:(INTERNAL) Tipo di ogni colonne - byte _type[MAX_COL]; - // @cmember:(INTERNAL) Riga corrente - long _curr; - // @cmember:(INTERNAL) Indice della prima riga visibile - long _last_update; - - // @cmember:(INTERNAL) Numero di righe visibili - short _visible_rows; - - // @cmember:(INTERNAL) Indica se e' possibile inserire un check (X di selezione) sulle righe sheet - bool _checkable; - // @cmember:(INTERNAL) Indica se e attivata la gestione dei check delle righe - bool _check_enabled; - // @cmember:(INTERNAL) Array di righe attivate - TBit_array _checked; - // @cmember:(INTERNAL) Array di righe disabilitate - TBit_array _disabled; - - // @cmember:(INTERNAL) Handles dei bottoni presenti nella finestra - WINDOW _button[MAX_BUT]; - // @cmember:(INTERNAL) Tasto associato ad ogni bottone - KEY _key[MAX_BUT]; - // @cmember:(INTERNAL) Maschera di bit corrispondente ai bottoni standard - byte _buttonmask; + TSheet_control* _sheet; // Spreadsheet contenuto + TToken_string _park; // Ultima riga richiesta + long _parked; // Numero riga richiesta + long _select_row; // Riga da selezionare + // @access Protected Member -protected: - // @cmember Ritorna se il numero di colonne e' maggiore di 1 - bool head_on() const - { return _columns > 1; } - // @cmember Indica se esitono i bottoni in fondo - bool buttons_on() const - { return *_button != NULL_WIN; } - // @cmember Ritorna il numero di righe visibili - short visible_rows() const - { return _visible_rows; } - // @cmember Ritorna il numero di righe riservate ai bottoni - virtual short reserved_rows() const; - // @cmember Crea la pagina - void build_page(long first = -1); - - // @cmember Converte le coordinate da logiche (caratteri) in coordinate fisiche (pixel) - // (vedi ) - virtual PNT log2dev(long x, long y) const; - // @cmember Gestisce l'handler della finestra (vedi ) - virtual void handler(WINDOW win, EVENT* ep); - // @cmember Gestisce la pressione del tasto (vedi ) - virtual bool on_key(KEY); - // @cmember Fa' l'update della finestra (vedi ) - virtual void update(); - - // @cmember Setta il numero della prima riga dello sheet - void set_first(long n); - // @cmember Ritorna se la riga

-esima e' visibile - bool is_visible(long n) const - { return n >= first() && n < first()+visible_rows(); } - - // @cmember Calcola la larghezza totale dello sheet virtuale - int width() const; - // @cmember Converte il numero di riga

assoluto nell'indice dell'array

- int row_to_page(long n) const; - // @cmember Converte il numero di riga

assoluto nella coordinata y sulla finestra - int row_to_win(long n) const; - - // @cmember Ritorna il numero della prima riga - long first() const - { return origin().y; } - // @cmember Forza il ridisegno di una riga - bool update_row(long n); - // @cmember Permette di scriveiere in inverso la riga

-esima - void invert_row(long n); - - // @cmember Aggiunge una riga all'array di quelle visibile - void set_row(const TToken_string& row, byte n); +protected: // TMask + // @cmember Lavori in background + virtual void on_idle(); + static bool tutti_handler(TMask_field& f, KEY k); + +protected: + virtual void get_row(long r, TToken_string& row) { row.cut(0); } + virtual long get_items() const { return 0L; } + + TSheet_control& sheet(); + // @cmember Permette di riposizionare i bottoni all'interno della pagina virtual void repos_buttons() const; - - // @cmember Copia le righe nella pagina da visualizzare - virtual void page_build(long first, byte num) pure; - - // @cmember Stampa lo sheet - void print(); - + + void post_select(long rec); + // @access Public Member +public: // TWindow + // @cmember Gestisce la pressione del tasto (vedi ) + virtual bool on_key(KEY); + + // @cmember Inizializzazione + virtual void start_run(); + public: - // @cmember Costruttore - TSheet(short x,short y,short dx,short dy,const char* title,const char* head,byte buttons = 0,long first = 0L,WINDOW parent = NULL_WIN); - - // @cmember Mostra la finestra (vedi ) - virtual void open(); - // @cmember Aggiunge un bottone nella finestra - void add_button(short id, const char* caption, KEY key = K_ESC); + void add_button(short id, const char* caption, KEY key); // @cmember Ritorna il numero di elementi di

- virtual long items() const pure; + long items() const { return get_items(); } // @cmember Ritorna il contenuto di una riga - virtual TToken_string& row(long s = -1); + TToken_string& row(long s = -1); // @cmember Ritorna il numero della riga corrente - long selected() const - { return _curr; } + long selected() const; // @cmember Seleziona una riga facendola diventare corrente - void select(long n); + virtual void select(long n); - // @cmember Ritorna il tipo della colonna

-esima - byte column_flag(int c) const - { return _type[c]; } - // @cmember Ritorna il tipo della colonna

-esima (permette di modificarlo) - byte& column_flag(int c) - { return _type[c]; } - // @cmember Ritorna se la riga

-esima e' attivata - bool checked(long n) const - { return _checked[n]; } + bool checked(long n) const; // @cmember Permette di attivare/disattivare una riga void check(long n, bool on = TRUE); // @cmember Permette di disattivare una riga (chiama ) @@ -165,30 +73,33 @@ public: { check(n, FALSE); } // @cmember Permette di abilitare (

= TRUE) o disabilitare (

= FALSE) // la gestione dei check sullo sheet - void enable_check(bool yn = TRUE) - { _check_enabled = yn; } + void enable_check(bool on = TRUE); // @cmember Permette di disbilitare (

= FALSE) i check sullo sheet void disable_check() { enable_check(FALSE); } + // @cmember Ritorna TRUE se e' possibile mettere un check sulle righe + bool check_enabled() const; // @cmember Abilita/disabilita una riga - void enable(long n = -1, bool on = TRUE); + void enable_row(long n, bool on = TRUE); // @cmember Disabilita una riga (chiama ) - void disable(long n = -1) - { enable(n, FALSE); } - // @cmember Ritorna se e' abilitata la riiga

-esima - bool enabled(long n) const - { return !_disabled[n]; } - // @cmember Ritorna se e' disabilitata la riiga

-esima - bool disabled(long n) const - { return _disabled[n]; } + void disable_row(long n) + { enable_row(n, FALSE); } + // @cmember Ritorna se e' abilitata la riga

-esima + bool row_enabled(long n) const; - // @cmember Ritrna se esiston elementi attivati nello sheet (TRUE se esitono) - bool one_checked() const - { return _checked.first_one() != -1; } + // @cmember Ritorna se esistono elementi attivati nello sheet (TRUE se esitono) + bool one_checked() const; // @cmember Ritorna il numero di elementi attivati (vedi ) - long checked() const - { return _checked.ones(); } + long checked() const; + + // @cmember Costruttore + TSheet(short x, short y, short dx, short dy, + const char* title, const char* head, + byte buttons = 0, short sht_y = 0); + + // @cmember Distruttore + virtual ~TSheet(); }; // @doc EXTERNAL @@ -207,19 +118,23 @@ class TArray_sheet : public TSheet // @access Protected Member protected: - // @cmember Costruisce la pgaina (vedi ) - virtual void page_build(long first, byte num); // @cmember Ritorna il contenuto dell'elemento

-esimo TToken_string& data(long n) { return _data.row((int)n); } + + // @cmember Ritorna la riga n + virtual void get_row(long n, TToken_string& row) + { row = data(n); } + + // @cmember Ritorna il numero degli elemnti dello sheet + virtual long get_items() const + { return _data.items(); } // @access Public Member public: // @cmember Costruttore - TArray_sheet(short x, short y, short dx, short dy, const char* caption, const char* head, byte buttons = 0, WINDOW parent = NULL_WIN); - // @cmember Ritorna il numero degli elemnti dello sheet - virtual long items() const - { return _data.items(); } + TArray_sheet(short x, short y, short dx, short dy, + const char* caption, const char* head, byte buttons = 0); // @cmember Ritorna il contenuto dello sheet TString_array& rows_array() { return _data; } @@ -229,9 +144,6 @@ public: long add(TToken_string* s); // @cmember Inserisce un elemento nella posizione long insert(const TToken_string& s, long n); - // @cmember Ritorna la riga

-esima dell'array - virtual TToken_string& row(long s = -1) - { return (s < 0) ? data(selected()) : data(s); } // @cmember Azzera l'array dello sheet bool destroy(int i = -1); }; @@ -258,14 +170,16 @@ class TCursor_sheet : public TSheet // @access Protected Member protected: // TSheet - // @cmember Costruisce la pgaina (vedi ) - virtual void page_build(long first, byte rows); + // @cmember Ritorna il numero dei records del cursore + virtual long get_items() const + { return _records; } + + // @cmember Ritorna la riga n + virtual void get_row(long n, TToken_string& row); + // @access Public Member public: // TSheet - // @cmember Ritorna il numero dei records del cursore - virtual long items() const - { return _records; } // @cmember Lancia la finestra con lo sheet virtual KEY run(); @@ -277,7 +191,9 @@ public: { return _cursor; } // @cmember Costruttore - TCursor_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons = 0); + TCursor_sheet(TCursor* cursor, const char* fields, + const char* title, const char* head, + byte buttons = 0, short sht_y = 0); // @cmember Distruttore virtual ~TCursor_sheet() {} @@ -296,27 +212,29 @@ class TBrowse_sheet : public TCursor_sheet { // @cmember:(INTERNAL) Campi collegati ai campi editabili (vedi ) TEdit_field* const _field; - // @cmember:(INTERNAL) Riga selezionata + + // @cmember:(INTERNAL) Campo di ricerca attuale (Tag button selezionato) int _sel; - + + long _select_row; + // @access Protected Member protected: - // @cmember Gestisce l'handler della finestra (vedi ) - virtual void handler(WINDOW win, EVENT* ep); - // @cmember Ritorna il numero di righe riservate - virtual short reserved_rows() const; - // @cmember Permette di riposizionare i bottoni nella finestra - virtual void repos_buttons() const; // @cmember Gestisce la pressione del tasto (vedi ) virtual bool on_key(KEY k); + // @cmember Ritorna il campo a cui si riferisce lo sheet TEdit_field& field() { return *_field; } - + + static bool browse_field_handler(TMask_field& f, KEY k); + // @access Public Member public: // @cmember Costruttore - TBrowse_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons, TEdit_field* f, TToken_string* siblings = NULL); + TBrowse_sheet(TCursor* cursor, const char* fields, const char* title, + const char* head, byte buttons, + TEdit_field* f, TToken_string& siblings); // @cmember Distruttore virtual ~TBrowse_sheet() {} @@ -324,5 +242,4 @@ public: virtual KEY run(); }; - #endif diff --git a/include/stdtypes.cpp b/include/stdtypes.cpp index d459e9bbb..2a620ebba 100755 --- a/include/stdtypes.cpp +++ b/include/stdtypes.cpp @@ -100,10 +100,6 @@ void free_global_vars() #ifndef FOXPRO #include -#ifdef DBG -unsigned long _alloc_count = 0; -#endif - // @doc EXTERNAL // @func Operatore per la creazione di un oggetto (sostituisce operatore C++) @@ -112,7 +108,7 @@ unsigned long _alloc_count = 0; void* operator new(size_t size) // @comm Per maggiori informazioni fare riferimento all'omonimo comando sull'help -// in linea del C++. +// in linea del C++. // Questa funzione viene implementata se non si opera in ambiante FoxPro. { @@ -120,10 +116,6 @@ void* operator new(size_t size) if (mem == NULL) fatal_box("Out of memory: can't allocate %u bytes", size); -#ifdef DBG - _alloc_count++; -#endif - return mem; } // @doc EXTERNAL @@ -133,7 +125,7 @@ void operator delete( void* ptr) // @parm Puntatore all'oggetto da distruggere // @comm Per maggiori informazioni fare riferimento all'omonimo comando sull'help -// in linea del C++. +// in linea del C++. // Nel caso venga passato un puntatore NULL viene emesso un . // Questa funzione viene implementata se non si opera in ambiante FoxPro. diff --git a/include/strings.cpp b/include/strings.cpp index 3955d7f6d..24dab5c77 100755 --- a/include/strings.cpp +++ b/include/strings.cpp @@ -347,17 +347,16 @@ int TString::replace(char find_char, char replace_char) { const int l = len(); int n = 0; - - for (int i = 0; i> 12)) & 0x3FFF; + } return h; } diff --git a/include/strings.h b/include/strings.h index 4a2414720..fe87d151b 100755 --- a/include/strings.h +++ b/include/strings.h @@ -106,7 +106,7 @@ public: int find(char, int from = 0) const; // @cmember Ritorna la posizione della stringa s nell'oggetto TString int find(const char* s, int from = 0) const; - // @cmember Rimpiazza tutte le occorrenze del carattere find_char con il carattere replace_char. Ritorna il numero di sostituzioni effettuate. + // @cmember Sostituisce le occorrenze di

col carattere

int replace(char find_char, char replace_char); // @cmember Ritorna l'oggetto TString composto dai count caratteri da sinistra diff --git a/include/text.cpp b/include/text.cpp index 501951f13..6ef34b1d0 100755 --- a/include/text.cpp +++ b/include/text.cpp @@ -1,9 +1,9 @@ -#include -#include #include -#include -static char TEXT_TMP[512]; +#include +#include + +static char TEXT_TMP[513]; class _HotSpot : public TObject { @@ -57,7 +57,7 @@ style TTextfile::_trans_style (char ch) void TTextfile::_save_changes() { - main_app().begin_wait(); + begin_wait(); // fa i dovuti replace anche sul disco (solo replace di linee esistenti) long line = 0l; @@ -114,7 +114,7 @@ void TTextfile::_save_changes() _filename = oldfile; _instr = fopen(_filename, "a+"); - main_app().end_wait(); + end_wait(); } void TTextfile::_read_page (long n) @@ -464,7 +464,7 @@ int TTextfile::replace( bool sforating = FALSE; // here's a nice casin - while(i < 512) + while(i < 256) { if (!sforating) { @@ -741,18 +741,18 @@ bool TTextfile::write ( int endx = to == NULL ? -1 : (int) to->x; for (long j = starty; j <= endy; j++) { - s = line (j); + s = line(j); if (j == endy && endx == -1) - endx = s.len (); + endx = s.len(); if (j == starty && j == endy) - s = s.sub (startx, endx); + s = s.sub(startx, endx); else if (j == starty) - s = s.mid (startx); + s = s.mid(startx); else if (j == endy) - s = s.left (endx); + s = s.left(endx); - fprintf (fp, "%s\n", (const char *) s); + fprintf(fp, "%s\n", (const char *) s); } fclose (fp); } @@ -761,6 +761,37 @@ bool TTextfile::write ( return ok; } +// @doc EXTERNAL + +// @mfunc Scrive il testo da punto a punto (non formattato) su string_array +void TTextfile::write( + TString_array& arr, // @parm Array in cui scrivere il testo + TPoint * from, // @parm Punto da cui iniziare a scrivere il testo + TPoint * to) // @parm Punto a cui terminare di scrivere il testo +{ + arr.destroy(); + TString s(512); + long starty = from == NULL ? 0l : from->y; + int startx = from == NULL ? 0 : (int) from->x; + long endy = to == NULL ? _lines - 1l : to->y; + int endx = to == NULL ? -1 : (int) to->x; + for (long j = starty; j <= endy; j++) + { + s = line(j); + if (j == endy && endx == -1) + endx = s.len(); + + if (j == starty && j == endy) + s = s.sub(startx, endx); + else if (j == starty) + s = s.mid(startx); + else if (j == endy) + s = s.left(endx); + + arr.add(s); + } +} + void TTextfile::destroy () { CHECK (_istemp, "destroy() chiamata su testo permanente!"); @@ -793,7 +824,7 @@ TTextfile ::TTextfile (const char *file, int pagesize, direction preferred, bool interactive): _page_size (pagesize), _page (pagesize), _filename (file), _lines (0l), _index (NULL), _page_start (0l), _page_end (-1l), _direction (preferred), - _dirty (FALSE), _istemp (FALSE), _item (0), _line (512), _cur_line (-1), + _dirty (FALSE), _istemp (FALSE), _item (0), _line (256), _cur_line (-1), _hotspots (4), _accept (TRUE), _dirty_lines(pagesize), _interactive(interactive), _rel(NULL) diff --git a/include/text.h b/include/text.h index 0f9ab8dba..ed9723878 100755 --- a/include/text.h +++ b/include/text.h @@ -9,13 +9,12 @@ #include #endif -#ifndef __WINDOW_H -#include +#ifndef __RELATION_H +#include #endif -#ifndef __RELATION_H -//class TRelation; -#include +#ifndef __WINDOW_H +#include #endif // @doc INTERNAL @@ -175,6 +174,8 @@ public: // @cmember Scrive il testo (non formattato) su file bool write(const char* path, TPoint* from = NULL, TPoint* to = NULL); + // @cmember Scrive il testo (non formattato) su TString_array + void write(TString_array& a, TPoint* from = NULL, TPoint* to = NULL); // @cmember Disfa tutto e svuota il file void destroy(); diff --git a/include/toolbar.h b/include/toolbar.h index be6ff4fbc..1655e2ccd 100755 --- a/include/toolbar.h +++ b/include/toolbar.h @@ -1,36 +1,46 @@ -BUTTON DLG_SAVEREC 8 2 +BUTTON DLG_SAVEREC 10 2 BEGIN -PROMPT -16 -1 "~Registra" -MESSAGE EXIT,K_SAVE + PROMPT -16 -1 "~Registra" + MESSAGE EXIT,K_SAVE + PICTURE 103 + PICTURE 153 END -BUTTON DLG_NEWREC 8 2 +BUTTON DLG_NEWREC 10 2 BEGIN -PROMPT -26 -1 "~Nuovo" -MESSAGE EXIT,K_INS + PROMPT -26 -1 "~Nuovo" + MESSAGE EXIT,K_INS + PICTURE 105 + PICTURE 155 END -BUTTON DLG_DELREC 8 2 +BUTTON DLG_DELREC 10 2 BEGIN -PROMPT -36 -1 "~Elimina" -MESSAGE EXIT,K_DEL + PROMPT -36 -1 "~Elimina" + MESSAGE EXIT,K_DEL + PICTURE 104 + PICTURE 154 END -BUTTON DLG_FINDREC 8 2 +BUTTON DLG_FINDREC 10 2 BEGIN -PROMPT -46 -1 "Ri~cerca" -MESSAGE EXIT,K_F9 + PROMPT -46 -1 "Ri~cerca" + MESSAGE EXIT,K_F9 + PICTURE 126 END -BUTTON DLG_CANCEL 8 2 +BUTTON DLG_CANCEL 10 2 BEGIN -PROMPT -56 -1 "" -MESSAGE EXIT,K_ESC + PROMPT -56 -1 "~Annulla" + MESSAGE EXIT,K_ESC + PICTURE 102 END -BUTTON DLG_QUIT 8 2 +BUTTON DLG_QUIT 10 2 BEGIN -PROMPT -66 -1 "" -MESSAGE EXIT,K_QUIT + PROMPT -66 -1 "~Fine" + MESSAGE EXIT,K_QUIT + PICTURE 114 + PICTURE 164 END diff --git a/include/urldefid.h b/include/urldefid.h index 0f97e9452..5bce07169 100755 --- a/include/urldefid.h +++ b/include/urldefid.h @@ -28,6 +28,8 @@ #if XVT_OS == XVT_OS_WIN #define ICO_SEARCH 109 +#define ICO_CHECK_ON 110 +#define ICO_CHECK_OFF 111 #define BMP_OK 101 #define BMP_CANCEL 102 diff --git a/include/validate.cpp b/include/validate.cpp index 9bb2395b7..06581e181 100755 --- a/include/validate.cpp +++ b/include/validate.cpp @@ -74,8 +74,8 @@ HIDDEN bool _emptycopy_val(TMask_field& f, KEY) // @flag TRUE | Se il valore della Partita IVA assume un valore corretto // @flag FALSE | Se il valore della Partita IVA non puo' essere valido bool pi_check( - const char* st, // @parm Stato di assegnazione della Partita IVA - const char* paiva) // @parm Codice della Partita IVA da controllare + const char* st, // @parm Stato di assegnazione della Partita IVA + const char* paiva) // @parm Codice della Partita IVA da controllare { int tot = 0, y; TString16 stato (st); @@ -468,7 +468,7 @@ HIDDEN bool _mtcheck_val(TMask_field& f, KEY) d.read(); if (d.bad()) return TRUE; if (d.get_char(NDT_FREQVIVA) == 'M') return TRUE; - return month == 13 || (month % 3) == 0; + return month == 13 || (month % 3) == 0; } @@ -496,6 +496,7 @@ HIDDEN bool _autoexit_val(TMask_field& f, KEY key) if (!m.query_mode() || key == K_ENTER) return TRUE; +/* const int next = m.next_fld(); if (next != DLG_NULL && next != f.dlg() && m.field(next).in_key(0)) @@ -506,6 +507,7 @@ HIDDEN bool _autoexit_val(TMask_field& f, KEY key) if (f.in_key(k) && m.field(next).in_key(k)) return TRUE; } +*/ const int nparms = get_val_param_num(); bool one_not_empty = FALSE; @@ -624,11 +626,12 @@ HIDDEN bool _zerofill_val(TMask_field& f, KEY k) if (f.to_check(k)) { const int columns = atoi(get_val_param(0)); - TString& val = f.get(); + const TString& val = f.get(); if (val.len() < columns && real::is_natural(val)) - { - val.right_just(columns, '0'); - f.set(val); + { + TString z(val); + z.right_just(columns, '0'); + f.set(z); } } return TRUE; @@ -650,9 +653,11 @@ HIDDEN bool _not_empty_chkfld_val(TMask_field& f, KEY k) { bool ok = TRUE; if (f.to_check(k) && f.get().not_empty()) - { + { +/* TBrowse * b = ((TEdit_field&)f).browse(); if (b != NULL) ok = b->check(k == K_TAB ? RUNNING_CHECK : FINAL_CHECK); +*/ } return ok; } @@ -835,10 +840,10 @@ HIDDEN VAL_FUNC _global_val_func[MAX_FUNC] = // @flag TRUE | Il campo e' positivo al controllo // @flag FALSE | Il campo non ha i requisiti necessari per passare il controllo bool validate( - int fn, // @parm Numero della funzione da effettuare - TMask_field& f, // @parm Identificatore del campo da controllare - KEY k, // @parm Codice del tasto premuto sul campo - const TArray& parms) // @parm Array di paramtri per effettuare il controllo + int fn, // @parm Numero della funzione da effettuare + TMask_field& f, // @parm Identificatore del campo da controllare + KEY k, // @parm Codice del tasto premuto sul campo + const TArray& parms) // @parm Array di paramtri per effettuare il controllo { _parms = &parms; return (fn >= 0 && fn < MAX_FUNC) ? _global_val_func[fn](f, k) : TRUE; diff --git a/include/value.h b/include/value.h index 83d1d86dd..02827885a 100755 --- a/include/value.h +++ b/include/value.h @@ -1,4 +1,4 @@ -// $Id: value.h,v 1.3 1995-03-16 13:44:07 alex Exp $ +// $Id: value.h,v 1.4 1996-05-08 11:08:39 guy Exp $ // language types for Simulation and SimulationManager // ------------------------------------------------------------------------- diff --git a/include/viswin.cpp b/include/viswin.cpp index edc416125..9b1b56ed7 100755 --- a/include/viswin.cpp +++ b/include/viswin.cpp @@ -1,15 +1,13 @@ -#include - #include #include #include -#include +#include #include #include #include #include -#include #include +#include #include @@ -28,13 +26,12 @@ const int PRINT_HEIGHT = 10; #define DLG_PRINT_TITLE "~Stampa" #if XVT_OS == XVT_OS_WIN +#define STRICT #include +#endif + #define BACKGROUND (_toplevel ? MASK_BACK_COLOR : COLOR_GRAY) #define FOREGROUND (_toplevel ? COLOR_BLACK : COLOR_WHITE) -#else -#define BACKGROUND COLOR_BLACK -#define FOREGROUND COLOR_WHITE -#endif #define K_CTRL_DOWN (K_CTRL + K_DOWN) #define K_CTRL_UP (K_CTRL + K_UP) @@ -45,6 +42,7 @@ const int PRINT_HEIGHT = 10; #define K_ALT_RIGHT (K_CTRL + 'K') #define K_ALT_LEFT (K_CTRL + 'L') #define CTRL_C (K_CTRL + 'C') +#define CTRL_G (K_CTRL + 'G') #define CTRL_E (K_CTRL + 'E') #define CTRL_S (K_CTRL + 'S') #define CTRL_R (K_CTRL + 'R') @@ -177,7 +175,7 @@ void TViswin::build_index_menu() { BkDef& bkd = (BkDef&)(*_bookmarks)[i]; - tt = format("%d", bkd._id + 1000); + tt.format("%d", bkd._id + 1000); tt.add(bkd._txt); _BkMenuItem* bkit = new _BkMenuItem((const char*)tt); @@ -276,13 +274,13 @@ void TViswin::display_link (long y, long x1, long x2, const char *d) paint_link (y, x1, x2); _link_displayed = TRUE; if (in_update) return; -#if XVT_OS == XVT_OS_WIN + TString80 dd; dd.strncpy(d, 40); xvt_statbar_set(dd); -#endif - if (_link_button != -1) + + if (_link_button) { - if (_showbuts) xvt_enable_control (_link_button, TRUE); + if (_showbuts) _link_button->enable(); if (_toplevel) enable_menu_item(M_EDIT_CUT, TRUE); } if (!_toplevel && !_inside_linkexec) @@ -312,13 +310,13 @@ void TViswin::erase_link ( #if XVT_OS == XVT_OS_WIN if (!in_update) { - xvt_statbar_set (""); - xvt_statbar_refresh (); + xvt_statbar_set(""); + xvt_statbar_refresh(); } #endif - if (_link_button != -1) + if (_link_button) { - if (_showbuts) xvt_enable_control (_link_button, FALSE); + if (_showbuts) _link_button->disable(); if (_toplevel) enable_menu_item(M_EDIT_CUT, FALSE); } } @@ -508,13 +506,17 @@ void TViswin::erase_selection () if (_sel_displayed) paint_selection (); _sel_displayed = FALSE; + if (_toplevel) + enable_menu_item(M_EDIT_COPY, FALSE); } void TViswin::display_selection () { if (!_sel_displayed) paint_selection (); - _sel_displayed = TRUE; + _sel_displayed = TRUE; + if (_toplevel) + enable_menu_item(M_EDIT_COPY, TRUE); } // @doc INTERNAL @@ -575,73 +577,55 @@ void TViswin::shift_screen(scroll dir) // @mfunc Aggiunge un bottone alla finestra // -// @rdesc Ritorna l'handle del bottone aggiunto -WINDOW TViswin::add_button ( +// @rdesc Ritorna un puntatore al bottone (TControl) aggiunto +TPushbutton_control* TViswin::add_button ( short id, // @parm Identificatore del bottone da aggiungere - const char *caption) // @parm Testo del bottone da aggiungere + const char *caption, // @parm Testo del bottone da aggiungere + short bup, // @parm Identificatore della bitmap normale + short bdn) // @parm Identificatore della bitmap pramuta - // @comm Questa funzione aggiunge bottoni nella finestra oltre a quelli standard delle finestre - // di visualizazioni anteprima di stampa. Il limite dei bottoni da aggiungere e' dato - // dal

. + // @comm Aggiunge i bottoni nella finestra { - const int BUT_HEIGHT = -#if XVT_OS == XVT_OS_WIN - 2 -#else - 1 -#endif - ; - WINDOW b = xvt_create_control (WC_PUSHBUTTON, 0, 0, 11, - BUT_HEIGHT, caption, win (), 0, 0, id); - - for (int i = 0; i < MAXBUT; i++) - if (_button[i] == NULL_WIN) - { - _button[i] = b; - break; - } + TPushbutton_control* b = new TPushbutton_control(win(), id, -11, -1, 11, 2, "", + caption, bup, bdn); + _button.add(b); return b; } void TViswin::repos_buttons () -{ - if (!_toplevel) return; - for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++) - if (buttons == MAXBUT - 1) - { - buttons++; - break; - } - - if (buttons == 0) - return; - - autoscroll(FALSE); - set_mode(M_COPY); - set_brush(BACKGROUND); - bar(5, rows()-BUTTONROW_SIZE, columns()+1, rows()+1); - autoscroll(TRUE); - - RCT wr; - xvt_vobj_get_client_rect(win(), &wr); - RCT br; - xvt_vobj_get_client_rect(_button[0], &br); - - int space = (wr.right - buttons * br.right) / (buttons + 1); - if (space < 0) - space = 0; - - int x = space; - const int y = wr.bottom - br.bottom - 4; - for (int b = 0; b < buttons; b++, x += br.right + space) +{ + if (_toplevel) { - RCT r; - xvt_rect_set (&r, x, y, x + br.right, y + br.bottom); - xvt_vobj_move (_button[b], &r); - } +// autoscroll(FALSE); +// set_mode(M_COPY); +// set_brush(BACKGROUND); +// bar(5, rows()-BUTTONROW_SIZE, columns()+1, rows()+1); +// autoscroll(TRUE); + + for (int i = 0; i < _modules.items(); i++) + ((TImage&)_modules[i]).set_pos(4, 4+int(rows()-BUTTONROW_SIZE)*CHARY); - for (int i = 0; i < _modules.items(); i++) - ((TImage&)_modules[i]).set_pos(4, 4+int(rows()-BUTTONROW_SIZE)*CHARY); + const int buttons = _button.items(); + if (buttons > 0) + { + RCT br; ((TPushbutton_control&)_button[0]).get_rect(br); + const short width = br.right - br.left; + RCT wr; xvt_vobj_get_client_rect(win(), &wr); + int space = ((wr.right - wr.left) - buttons * (br.right-br.left)) / (buttons + 1); + if (space < 0) + space = 0; + + int x = space; + const int y = (wr.bottom - wr.top) - (br.bottom - br.top) - XI_FU_MULTIPLE; + for (int b = 0; b < buttons; b++) + { + const PNT p = { y, x }; + xvt_rect_set_pos(&br, p); + ((TPushbutton_control&)_button[b]).set_rect(br); + x += space + width; + } + } + } } void TViswin::open () @@ -1181,7 +1165,15 @@ void TViswin::paint_waitbar ( autoscroll (TRUE); #endif } - + +void TViswin::txt_clear(COLOR color) +{ + autoscroll(FALSE); + set_brush(color); + set_mode(M_COPY); + bar ((X_OFFSET-1), Y_OFFSET -1, columns()+1, rows()-BUTTONROW_SIZE); +} + void TViswin::update () { if (_scrolling) @@ -1194,26 +1186,26 @@ void TViswin::update () set_mode(M_COPY); if (_showbuts) { - set_brush (BACKGROUND); - bar ((X_OFFSET-1), rows()-BUTTONROW_SIZE, columns()+1, rows() + 1); +// set_brush (BACKGROUND); +// bar ((X_OFFSET-1), rows()-BUTTONROW_SIZE, columns()+1, rows() + 1); } if (_need_update) { check_link(); if (_isselection) erase_selection (); - clear(COLOR_WHITE); - set_mode (M_COPY); + txt_clear(COLOR_WHITE); +// set_mode (M_COPY); set_brush (BACKGROUND); - autoscroll (FALSE); +// autoscroll (FALSE); if (_rulers) { bar (0, 0, columns() + 1, 1); bar (0, 0, 5, rows() + 1); } - if (_showbuts) - bar ((X_OFFSET -1), rows()-BUTTONROW_SIZE, columns() + 1, rows() + 1); +// if (_showbuts) +// bar ((X_OFFSET -1), rows()-BUTTONROW_SIZE, columns() + 1, rows() + 1); //** if (_showbuts && _isopen) paint_waitbar (FALSE); #if XVT_OS == XVT_OS_WIN @@ -1266,8 +1258,7 @@ void TViswin::handler (WINDOW win, EVENT * ep) static bool ignore = FALSE; bool tlnk = FALSE; int kdiff; - long new_origin; - bool scrollated = FALSE; + long new_origin; switch (ep->type) { case E_USER: @@ -1289,7 +1280,7 @@ void TViswin::handler (WINDOW win, EVENT * ep) if (_txt.lines () > 1l) _need_update = FALSE; else - /*force_*/update (); + force_update (); } autoscroll (FALSE); _textrows = TEXTROWS; @@ -1310,7 +1301,7 @@ void TViswin::handler (WINDOW win, EVENT * ep) dispatch_e_char(win, K_ESC); break; case M_EDIT_CUT: // collega - dispatch_e_char(win, CTRL_C); + dispatch_e_char(win, CTRL_G); break; case M_EDIT_PASTE: // esporta dispatch_e_char(win, CTRL_E); @@ -1337,8 +1328,8 @@ void TViswin::handler (WINDOW win, EVENT * ep) #endif stop_run (K_ENTER); break; - case M_EDIT_COPY: // copia - // ??? + case M_EDIT_COPY: // copia nella clipboard + dispatch_e_char(win, CTRL_C); break; case M_EDIT_CLEAR: // annulla selezione dispatch_e_char(win,K_ENTER); @@ -1515,6 +1506,18 @@ void TViswin::handler (WINDOW win, EVENT * ep) break; case E_MOUSE_MOVE: { + /* + if (!_selecting && !_iscross) // no buttons pressed + { + p = ep->v.mouse.where; + if (in_text (p)) + { + p.x += (origin ().x - 6); + p.y += (origin ().y - 1); + check_link (&p); + } + } + */ if (_selecting || _iscross) { p = ep->v.mouse.where; @@ -1796,8 +1799,8 @@ void TViswin::handler (WINDOW win, EVENT * ep) // for failed scrollings if (!_selecting && _need_scroll == none) { - check_link(&_point); - display_point(); + check_link (&_point); + display_point (); } } break; @@ -1807,34 +1810,27 @@ void TViswin::handler (WINDOW win, EVENT * ep) if (_need_scroll != none) { _need_update = FALSE; - scrollated = TRUE; scroll tmp = _need_scroll; _need_scroll = none; shift_screen (tmp); if (!_selecting) { - check_link(&_point); - display_point(); + check_link (&_point); + display_point (); } if (_isselection) - display_selection(); + display_selection (); } if (ep->type != E_UPDATE || _need_update) - TWindow::handler(win, ep); + TWindow ::handler (win, ep); else if (ep->type == E_UPDATE) - { - if (!scrollated) - _need_update = TRUE; - update(); - if (scrollated) display_point(); - } + update (); } bool TViswin::on_key (KEY key) { EVENT_TYPE type = E_USER; - bool disp = FALSE; - + if (_istimer) return TRUE; _timer = xvt_timer_create (win (), 50l); @@ -1867,23 +1863,26 @@ bool TViswin::on_key (KEY key) check_link (&_point); } break; - case CTRL_C: + case CTRL_G: exec_link(); break; + case CTRL_C: + sel_to_clipboard(); + break; case CTRL_S: if (_isprint) stop_run(CTRL_S); break; case CTRL_R: _need_update = TRUE; - check_link(); - force_update(); - do_events(); - check_link(&_point); + check_link (); + force_update (); + do_events (); + check_link (&_point); break; case K_ESC: if (_isopen) - abort_print(); + abort_print (); else { @@ -1911,7 +1910,7 @@ bool TViswin::on_key (KEY key) } else { - if (_curbut == (_buttons - 1)) + if (_curbut == (_button.items() - 1)) _curbut = 0; else _curbut++; @@ -1920,32 +1919,32 @@ bool TViswin::on_key (KEY key) case K_BTAB: if (_curbut == 0) - _curbut = _buttons - 1; + _curbut = _button.items() - 1; else _curbut--; break; case K_SPACE: case K_CTRL_ENTER: if (_linkID != -1) - { exec_link(); - } +/* else if (_toplevel) dispatch_e_char (_button[_curbut], K_SPACE); +*/ break; case K_LHOME: _need_update = TRUE; update_thumb (0, 0); _point.set (0, 0); check_link (&_point); - force_update (); + force_update(); break; case K_LEND: _need_update = TRUE; update_thumb (0, _txt.lines () - _textrows); _point.set (0, _txt.lines () - 1); check_link (&_point); - force_update (); + force_update(); break; case K_RIGHT: case K_LEFT: @@ -2005,16 +2004,16 @@ bool TViswin::on_key (KEY key) dispatch_e_scroll (win(), K_TAB); break; case K_CTRL_UP: - disp = TRUE; dispatch_e_scroll (win(), K_UP); + dispatch_e_scroll (win(), K_UP); break; case K_CTRL_DOWN: - disp = TRUE; dispatch_e_scroll (win(), K_DOWN); + dispatch_e_scroll (win(), K_DOWN); break; case K_ALT_LEFT: - disp = TRUE; dispatch_e_scroll (win(), K_LEFT); + dispatch_e_scroll (win(), K_LEFT); break; case K_ALT_RIGHT: - disp = TRUE; dispatch_e_scroll (win(), K_RIGHT); + dispatch_e_scroll (win(), K_RIGHT); break; case K_UP: case K_SHIFT_UP: @@ -2068,7 +2067,7 @@ bool TViswin::on_key (KEY key) { _need_update = FALSE; if (need_paint_sel (FALSE)) - erase_selection (); + erase_selection(); update_thumb (--_point.x, origin ().y); _need_scroll = right; } @@ -2091,7 +2090,7 @@ bool TViswin::on_key (KEY key) if (key == K_SHIFT_DOWN) { if (need_paint_sel (FALSE)) - erase_selection (); + erase_selection(); if (!_selecting) { _sel_start = _point; @@ -2149,25 +2148,23 @@ bool TViswin::on_key (KEY key) } } else - beep (); + beep(); break; default: break; } if (_need_scroll != none) { - disp = TRUE; _need_update = FALSE; scroll tmp = _need_scroll; _need_scroll = none; - shift_screen (tmp); + shift_screen (tmp); } if (_isselection) display_selection (); check_link (&_point); - if (!disp) - update(); - else display_point(); + if (_need_update) force_update(); + else update(); } break; default: @@ -2176,7 +2173,45 @@ default: return TWindow::on_key (key); } -bool TViswin::call_editor () +void TViswin::sel_to_clipboard() +{ + TPoint p1, p2; + if (!_isselection) return; + adjust_selection (p1, p2); + + TString_array txt; + _txt.write(txt, &p1, &p2); + + long size = 0l; int eol_len = strlen(EOL_SEQ); + // open clipboard + xvt_cb_open(TRUE); + // allocate clipboard + for (int i = 0; i < txt.items(); i++) + size += txt.row(i).len() + eol_len; + char* p = (char*)xvt_cb_alloc_data(size); + if (p == NULL) + { + error_box("Impossibile allocare una clipboard di %ld bytes", size); + return; + } + // put data + for (i = 0; i < txt.items(); i++) + { + TString& s = txt.row(i); + for (int j = 0; j < s.len(); j++) + *p++ = s[j]; + for (j = 0; j < eol_len; j++) + *p++ = EOL_SEQ[j]; + } + if (!xvt_cb_put_data(CB_TEXT, NULL, size, (PICTURE)NULL)) + error_box("Errore di copiatura del testo nella clipboard"); + // free memory + xvt_cb_free_data(); + // close clipboard + xvt_cb_close(); +} + +bool TViswin::call_editor() { TConfig cnf (CONFIG_USER, "Link"); const TFilename editor (cnf.get ("txt", NULL, -1, "notepad")); @@ -2252,7 +2287,7 @@ void TViswin::close_print () { xvt_menu_set_item_title(win(), M_EDIT_QUIT, "Chiudi\tESC"); enable_menu_item(M_EDIT_CLIPBOARD, FALSE); - xvt_enable_control(_print_button, TRUE); + _print_button->enable(); enable_menu_item(M_EDIT_SEL_ALL, TRUE); // build bookmark menu tree _bookmarks = &(printer().get_bookmarks()); @@ -2399,17 +2434,17 @@ void TViswin::find_next() void TViswin::show_rulers (bool on) { - _rulers = on; - autoscroll (FALSE); + _rulers = on; + autoscroll(FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; - autoscroll (TRUE); + autoscroll(TRUE); refresh(); } // @doc INTERNAL -// @mfunc Indica se mostrare o no i bottoni della finestra di anteprima +// @mfunc Mostra/nasconde i bottoni della finestra di anteprima void TViswin::show_buttons( bool on) // @parm Indica l'operazione da svolgere: // @@ -2420,11 +2455,10 @@ void TViswin::show_buttons( autoscroll (FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; - autoscroll (TRUE); + autoscroll(TRUE); - for (int i = 0; i < _buttons; i++) - if (_button[i] != NULL_WIN) - xvt_vobj_set_visible(_button[i],on); + for (int i = 0; i < _button.items(); i++) + ((TPushbutton_control&)_button[i]).show(on); refresh(); } @@ -2444,11 +2478,11 @@ TViswin::TViswin(const char *fname, _link_displayed (FALSE), _point_displayed (FALSE), _selecting (FALSE), _scrolling (FALSE), _selflag (FALSE), _need_update (TRUE), _need_scroll (none), _multiple (FALSE), _rulers(rulers), _txt_to_find(64), - _frozen (FALSE), _brwfld(brwfld), _link_button(-1), + _frozen (FALSE), _brwfld(brwfld), _link_button(NULL), _print_button(NULL), _down_dir(TRUE), _showbuts(FALSE), _case_sensitive(FALSE), _menu_present(FALSE) { - main_app().begin_wait(); + begin_wait(); if (title == NULL) title = (fname ? fname : "Anteprima di stampa"); @@ -2459,9 +2493,6 @@ TViswin::TViswin(const char *fname, if (_isopen) _filename = _txt.name (); - for (int i = 0; i < MAXBUT; i++) - _button[i] = NULL_WIN; - if (parent == NULL_WIN) parent = TASK_WIN; @@ -2490,7 +2521,7 @@ TViswin::TViswin(const char *fname, maxalt = alt; #if XVT_OS == XVT_OS_WIN - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) _modules.add(new TImage(BMP_MODULE1 + i), i); _modules.add(new TImage(BMP_MODULE), i); #endif @@ -2502,16 +2533,20 @@ TViswin::TViswin(const char *fname, } WIN_TYPE rt = _toplevel ? W_DOC : W_PLAIN; - create (x, y, maxlarg, maxalt, title, flags, rt, parent, + create(x, y, maxlarg, maxalt, title, flags, rt, parent, _toplevel ? VISWIN_BAR : 0); + + attach_interface(win(), BACKGROUND); + set_opaque_text (TRUE); set_font (PRINT_FONT, XVT_FS_NONE, PRINT_HEIGHT); if (_toplevel) { + enable_menu_item(M_EDIT_COPY, FALSE); enable_menu_item(M_SHOW_RULERS, TRUE); enable_menu_item(M_SHOW_BUTTONS, TRUE); - check_menu_item(M_SHOW_RULERS, _rulers); + check_menu_item(M_SHOW_RULERS, _rulers); check_menu_item(M_SHOW_BUTTONS, _showbuts); enable_menu_item(M_EDIT_SEL_ALL, FALSE); } @@ -2520,32 +2555,24 @@ TViswin::TViswin(const char *fname, set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); - if (_toplevel) { - add_button (DLG_QUIT, DLG_QUIT_TITLE); - _buttons = 1; + add_button (DLG_QUIT, DLG_QUIT_TITLE, BMP_QUIT, BMP_QUITDN); if (_isedit) - { - add_button (DLG_EDIT, DLG_EDIT_TITLE); - _buttons++; - } + add_button (DLG_EDIT, DLG_EDIT_TITLE, BMP_EDIT); if (_islink) { - _link_button = add_button (DLG_LINK, DLG_LINK_TITLE); - _buttons++; - xvt_enable_control(_link_button, FALSE); + _link_button = add_button (DLG_LINK, DLG_LINK_TITLE, BMP_LINK); + _link_button->disable(); } if (_isprint) { - _print_button = add_button (DLG_PRINT, DLG_PRINT_TITLE); - xvt_enable_control(_print_button, FALSE); + _print_button = add_button (DLG_PRINT, DLG_PRINT_TITLE, BMP_PRINT); + _print_button->disable(); enable_menu_item(M_EDIT_SEL_ALL, FALSE); - _buttons++; } } - else _buttons = 0; _curbut = 0; @@ -2578,7 +2605,7 @@ TViswin::TViswin(const char *fname, _hotspots = &(_txt.hotspots()); - main_app().end_wait(); + end_wait(); } TViswin ::~TViswin () @@ -2590,7 +2617,7 @@ TViswin ::~TViswin () // Certified 100% TBrowsefile_field::TBrowsefile_field(TMask* m) -: TMask_field(m), _viswin(NULL), _m_link(FALSE), _background(36), _lh(NULL) +: TOperable_field(m), _viswin(NULL), _m_link(FALSE), _background(36), _lh(NULL) {} // Certified 100% @@ -2602,29 +2629,25 @@ word TBrowsefile_field::class_id() const // Certified 100% TBrowsefile_field::~TBrowsefile_field() { - CHECK(_viswin, "Can't delete NULL sheet"); delete _viswin; } void TBrowsefile_field::parse_head(TScanner& scanner) { - _width = scanner.integer(); - _size = scanner.integer(); + _ctl_data._width = scanner.integer(); + _ctl_data._size = scanner.integer(); } // Certified 100% void TBrowsefile_field::create(WINDOW parent) { - main_app().begin_wait(); - const TMask& m = mask(); - _viswin = new TViswin(_prompt, _prompt, FALSE, FALSE, FALSE, _x, _y, - _size, _width, _flags.rightjust ? TRUE : FALSE, parent, this); - _win = _viswin->win(); - xvt_vobj_set_enabled(_win, enabled()); - xvt_vobj_set_visible(_win, shown()); - - main_app().end_wait(); + _viswin = new TViswin(_ctl_data._prompt, _ctl_data._prompt, FALSE, FALSE, FALSE, + _ctl_data._x, _ctl_data._y, _ctl_data._size, _ctl_data._width, + _flags.rightjust ? TRUE : FALSE, parent, this); + WINDOW win = _viswin->win(); + xvt_vobj_set_enabled(win, enabled()); + xvt_vobj_set_visible(win, shown()); } @@ -2636,7 +2659,7 @@ long TBrowsefile_field::set_text(const char* file, const char* line) if (instr == NULL) fatal_box("File non trovato: %s", file); - main_app().begin_wait(); + begin_wait(); TString256 tmpp; long ret = -1l; @@ -2644,14 +2667,15 @@ long TBrowsefile_field::set_text(const char* file, const char* line) while (!feof(instr)) { - if (fgets(__tmp_string, sizeof (__tmp_string), instr) == NULL) - break; - if (__tmp_string[strlen(__tmp_string)-1] == '\n') - __tmp_string[strlen(__tmp_string)-1] = '\0'; - add_line(__tmp_string); + if (fgets((char*)(const char*)tmpp, tmpp.size(), instr) == NULL) + break; + + char& last = tmpp[tmpp.len()-1]; + if (last == '\n') last = '\0'; + + add_line(tmpp); if (line != NULL) { - tmpp = __tmp_string; if (tmpp.find(line) != -1) ret = lines; } @@ -2661,7 +2685,7 @@ long TBrowsefile_field::set_text(const char* file, const char* line) _viswin->close_print(); - main_app().end_wait(); + end_wait(); return ret; } @@ -2756,3 +2780,5 @@ long TBrowsefile_field::lines() { return _viswin->_txt.lines(); } + + diff --git a/include/viswin.h b/include/viswin.h index bdacfbe3a..39fc928f3 100755 --- a/include/viswin.h +++ b/include/viswin.h @@ -1,12 +1,12 @@ #ifndef __VISWIN_H #define __VISWIN_H -#ifndef __WINDOW_H -#include +#ifndef __CONTROLS_H +class TPushbutton_control; #endif -#ifndef __STRINGS_H -#include +#ifndef __WINDOW_H +#include #endif #ifndef __TEXTFILE_H @@ -30,8 +30,8 @@ class TViswin : public TScroll_window // @access:(INTERNAL) Private Member - // @ccost:(INTERNAL) MAXBUT | 4 | Numero massimo di bottoni disponibili nella pagina - enum { MAXBUT = 4, + + enum { // @ccost:(INTERNAL) MAXLEN | 256 | Lunghezza massima del modulo di stampa MAXLEN = 256, // @ccost:(INTERNAL) BUFFERSIZE | 256 | Dimensione del buffer di stampa @@ -84,16 +84,14 @@ class TViswin : public TScroll_window // @cmember:(INTERNAL) Flag per il disegno intelligente bool _wasneeded; // @cmember:(INTERNAL) Array di bottoni attivi nella finestra - WINDOW _button[MAXBUT]; + TArray _button; // @cmember:(INTERNAL) Bottone che ha il focus int _curbut; - // @cmember:(INTERNAL) Contatore di bottoni - int _buttons; // @cmember:(INTERNAL) Bottone Collega - WINDOW _link_button; + TPushbutton_control* _link_button; // @cmember:(INTERNAL) Bottone Stampa - WINDOW _print_button; + TPushbutton_control* _print_button; // @cmember:(INTERNAL) Numero di righe di testo long _textrows; @@ -147,7 +145,7 @@ class TViswin : public TScroll_window // link presenti sulla stessa riga anziche' solo il selezionato bool _multiple; // @cmember:(INTERNAL) Testo del link - TString80 _linktxt; + TString _linktxt; // @cmember:(INTERNAL) Identificatore del link int _linkID; // @cmember:(INTERNAL) Indica tutti i link della riga nel caso di link multiplo @@ -169,7 +167,10 @@ class TViswin : public TScroll_window bool _menu_present; // @cmember:(INTERNAL) Viene istanziato soltanto se e' usata come controllo - TBrowsefile_field* _brwfld; + TBrowsefile_field* _brwfld; + + // @cmember: (INTERNAL) Rettangolo finestra madre + RCT _wr; // @access Protected Member protected: @@ -183,6 +184,9 @@ protected: // @cmember Converte i caratteri in y in pixel int taby(int y) const; + // @cmember Cancella l'area di testo col colore

+ void txt_clear(COLOR c); + // @cmember Sposta lo schermo nella direzione

di 1 void shift_screen(scroll dir); // @cmember Disegna lo schermo sulla porzione corrente di testo @@ -208,11 +212,13 @@ protected: // @cmember Chiama l'editor selezionato nel file PRASSI.INI. Ritorna il risultato della // chiamata (TRUE se e' riuscito a chiamarlo) bool call_editor(); + // @cmember copia l'eventuale selezione nella clipboard + void sel_to_clipboard(); // @cmember Ritorna se in punto

e' nel testo mostrato bool in_text(const TPoint& p) const; // @cmember Aggiunge un bottone alla finestra - WINDOW add_button(short id, const char* caption); + TPushbutton_control* add_button(short id, const char* caption, short bup = 0, short bdn = 0); // @cmember Riposiziona i bottoni centrandoli a seconda di quanti sono presenti void repos_buttons(); // @cmember Assicura che la selezione rimanga nei limiti fisici del testo diff --git a/include/window.cpp b/include/window.cpp index 77bb2d1ad..0f13fd6e9 100755 --- a/include/window.cpp +++ b/include/window.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #define __WINDOW_CPP #include @@ -151,7 +151,7 @@ void TWindow_manager::destroy() void TWindow_manager::lock_handle() { CHECK(_lowhandle == NULL, "Can't relock low handle"); - _lowhandle = fopen("bagn001a.msk", "r"); + _lowhandle = fopen("con", "r"); CHECK(_lowhandle != NULL, "Can't lock low handle"); } @@ -458,7 +458,7 @@ void TImage::set_clut(byte n, COLOR c) // Certified 99% // @doc EXTERNAL -// @mfunc Setta i colori dell'immagine in modo da renderlo trasparente +// @mfunc Setta i colori dell'immagine in modo da renderla trasparente void TImage::convert_to_default_colors() // @comm Legge nell'immagine i colori CYAN e DARK_CYAN e li setta a seconda del colore @@ -485,6 +485,26 @@ void TImage::convert_to_default_colors() } } +// @mfunc Setta i colori dell'immagine in modo da renderla trasparente +void TImage::convert_transparent_color() + + // @comm Legge nell'immagine i pixel uguali a quello in alto a sinistra e li setta + // uguali allo sfondo delle maschere +{ + const COLOR trans = xvt_image_get_pixel(_image, 0, 0); + if (trans != MASK_BACK_COLOR && xvt_image_get_format(_image) == XVT_IMAGE_CL8) + { + short dx, dy; xvt_image_get_dimensions(_image, &dx, &dy); + for (short y = 0; y < dy; y++) for (short x = 0; x < dx; x++) + { + const COLOR c = xvt_image_get_pixel(_image, x, y); + if (c == trans) + xvt_image_set_pixel(_image, x, y, MASK_BACK_COLOR); + } + } +} + + /////////////////////////////////////////////////////////// // TWindow /////////////////////////////////////////////////////////// @@ -498,6 +518,8 @@ TWindow::TWindow() _running(FALSE), _pixmap(FALSE), _lastkey(0) {} +word TWindow::class_id() const +{ return CLASS_WINDOW; } long XVT_CALLCONV1 TWindow::window_handler(WINDOW win, EVENT* ep) { @@ -558,10 +580,11 @@ TWindow::~TWindow() void TWindow::open() { - CHECK(win() != NULL_WIN, "Can't open a NULL window"); - xvt_vobj_set_visible(win(), _open = TRUE); - xvt_scr_set_focus_vobj(win()); - xvt_vobj_raise(win()); + WINDOW w = win(); + CHECK(w != NULL_WIN, "Can't open a NULL window"); + xvt_vobj_set_visible(w, _open = TRUE); + xvt_scr_set_focus_vobj(w); + xvt_vobj_raise(w); } @@ -592,7 +615,7 @@ void TWindow::close_modal() bool TWindow::stop_run(KEY key) { _running = FALSE; - _lastkey = key; + _lastkey = key; return TRUE; } @@ -619,16 +642,35 @@ KEY TWindow::run() _running = TRUE; if (!was_open) open_modal(); - else open(); + else open(); while (_running) do_events(); if (!was_open) close_modal(); + do_events(); return last_key(); } +void TWindow::on_button(short dlg) +{ + switch(dlg) + { + case DLG_OK: + stop_run(K_ENTER); + break; + case DLG_CANCEL: + stop_run(K_ESC); + break; + case DLG_QUIT: + stop_run(K_QUIT); + break; + default: + break; + } +} + // @doc EXTERNAL // @mfunc Gestisce l'handler della finestra @@ -641,8 +683,11 @@ void TWindow::handler( case E_CLOSE: stop_run(K_ESC); break; + case E_CONTROL: + if (ep->v.ctl.ci.type == WC_PUSHBUTTON) + on_button(ep->v.ctl.id); + break; case E_UPDATE: - xvt_dwin_clear(win, NORMAL_BACK_COLOR); update(); break; case E_CHAR: @@ -676,18 +721,19 @@ WINDOW TWindow::parent() const void TWindow::set_focus() -{ - if (_win) +{ + WINDOW w = win(); + if (w) { - xvt_scr_set_focus_vobj(_win); - xvt_vobj_raise(_win); + xvt_scr_set_focus_vobj(w); + xvt_vobj_raise(w); } } void TWindow::iconize() const { -#if XVTWS != WMWS +#if XVT_OS == XVT_OS_WIN HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_MINIMIZE); #endif @@ -695,7 +741,7 @@ void TWindow::iconize() const void TWindow::maximize() const { -#if XVTWS != WMWS +#if XVT_OS == XVT_OS_WIN HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_SHOWMAXIMIZED); #else @@ -763,8 +809,9 @@ bool TWindow::restore_ctools() void TWindow::set_color(COLOR fore, COLOR back) { - xvt_dwin_set_fore_color(win(), fore); - xvt_dwin_set_back_color(win(), back); + WINDOW w = win(); + xvt_dwin_set_fore_color(w, fore); + xvt_dwin_set_back_color(w, back); } // @doc EXTERNAL diff --git a/include/window.h b/include/window.h index 058f1c3b1..accd1e816 100755 --- a/include/window.h +++ b/include/window.h @@ -9,8 +9,9 @@ #include #endif +#ifndef __STRINGS_H class TString_array; - +#endif void close_all_dialogs(); bool can_close(); @@ -114,8 +115,14 @@ public: const RCT& rect() const { return _src; } - // @cmember Setta i colori dell'immagine in modo da renderlo trasparente + // @cmember Setta i colori dell'immagine in modo da renderla trasparente + // usando i colori di default (di Morpurgo) void convert_to_default_colors(); + + // @cmember Setta i colori dell'immagine in modo da renderla trasparente + // usando l'angolo in alto a sinistra dell'imagine stessa + void convert_transparent_color(); + // @cmember Setta l'

.esime entry della paletta al colore

void set_clut(byte n, COLOR c); @@ -133,7 +140,7 @@ public: // @doc EXTERNAL // @class TWindow | Classe per la definizione di una finestra generica -class TWindow +class TWindow : public TObject { // @author:(INTERNAL) Guido @@ -191,9 +198,6 @@ protected: // @cmember Fa' l'update della finstra virtual void update() {} - // @cmember Gestisce la pressione del tasto - virtual bool on_key(KEY) - { return TRUE; } // @cmember Converte le coordinate logiche (caratteri) in coordinate fisiche (pixel) virtual PNT log2dev(long x, long y) const; @@ -206,14 +210,25 @@ public: TWindow(); // @cmember Distruttore virtual ~TWindow(); - - // @cmember Gestisce l'handeler della finestra + + // @cmember Ritorna l'identificatore della classe finestra + virtual word class_id() const; + + // @cmember Gestisce la pressione dei bottoni + virtual void on_button(short dlg); + + // @cmember Gestisce gli eventi della finestra virtual void handler(WINDOW win, EVENT* ep); + // @cmember Mette la finestra in primo piano virtual void set_focus(); // @cmember Ritorna il descrittore della finestra virtual WINDOW win() const - { return _win; } + { return _win; } + + // @cmember Gestisce la pressione del tasto + virtual bool on_key(KEY) + { return TRUE; } // @cmember Ritorna TRUE se la finestra e' aperta bool is_open() const @@ -270,7 +285,8 @@ public: void close_modal(); // @cmember Esegue la finestra - KEY run(); + virtual KEY run(); + // @cmember Ritorna l'ultimo tasto KEY last_key() const { return _lastkey; } diff --git a/include/xvtility.cpp b/include/xvtility.cpp index fc700dc95..ded2d7478 100755 --- a/include/xvtility.cpp +++ b/include/xvtility.cpp @@ -23,53 +23,13 @@ BOOLEAN error_hook(XVT_ERRMSG err, DATA_PTR) #endif } -HIDDEN XVT_FNTID DEF_FONT = NULL; -HIDDEN XVT_FNTID FAT_FONT = NULL; - -#if XVTWS == WMWS - -short CHARX = 8; -short CHARY = 8; -short BASEY = 8; -short ROWY = 8; - -COLOR MASK_BACK_COLOR = COLOR_WHITE; -COLOR MASK_LIGHT_COLOR = COLOR_WHITE; -COLOR MASK_DARK_COLOR = COLOR_BLUE; -COLOR NORMAL_COLOR = COLOR_BLACK; -COLOR NORMAL_BACK_COLOR = COLOR_WHITE; -COLOR DISABLED_COLOR = COLOR_GRAY; -COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR; -COLOR FOCUS_COLOR = COLOR_BLACK; -COLOR FOCUS_BACK_COLOR = COLOR_WHITE; - -#else +#if XVT_OS == XVT_OS_WIN +#define STRICT #include -#include - -HIDDEN COLORREF COLOR2RGB(COLOR c) -{ - const byte red = byte((c >> 16) & 0xFF); - const byte gre = byte((c >> 8) & 0xFF); - const byte blu = byte(c & 0xFF); - return RGB(red, gre, blu); -} - -HIDDEN COLOR RGB2COLOR(COLORREF c) -{ - const byte red = byte(c & 0xFF); - const byte gre = byte((c >> 8) & 0xFF); - const byte blu = byte((c >> 16) & 0xFF); - return XVT_MAKE_COLOR(red, gre, blu); -} - -#ifndef XVT_CALLCONV1 -#define XVT_CALLCONV1 -#endif extern "C" { - WINDOW XVT_CALLCONV1 xvtwi_hwnd_to_window(HWND); + WINDOW xvtwi_hwnd_to_window(HWND); #include } #include @@ -79,10 +39,6 @@ short ROWY = GetSystemMetrics(SM_CYSCREEN) / 25; short CHARY = 14; short BASEY = 12; -HIDDEN HFONT NormalFont = NULL; -HIDDEN LOGFONT LogFont; -HIDDEN int FontWeight; - COLOR MASK_BACK_COLOR = COLOR_DKCYAN; COLOR MASK_LIGHT_COLOR = COLOR_CYAN; COLOR MASK_DARK_COLOR = COLOR_GRAY; @@ -94,28 +50,18 @@ COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR; COLOR FOCUS_COLOR = NORMAL_COLOR; COLOR FOCUS_BACK_COLOR = COLOR_CYAN; -HIDDEN COLORREF MaskColor = COLOR2RGB(MASK_BACK_COLOR); -HIDDEN HBRUSH MaskBrush = 0 ; -HIDDEN COLORREF NormalForeColor = COLOR2RGB(NORMAL_COLOR); -HIDDEN COLORREF NormalBackColor = COLOR2RGB(NORMAL_BACK_COLOR); -HIDDEN HBRUSH NormalBrush = 0; -HIDDEN COLORREF FocusForeColor = COLOR2RGB(FOCUS_COLOR); -HIDDEN COLORREF FocusBackColor = COLOR2RGB(FOCUS_BACK_COLOR); -HIDDEN HBRUSH FocusBrush = 0; - const word WM_WAKEUP = RegisterWindowMessage("WAKEUP"); -#if XVT_OS == XVT_OS_WIN - // By Matt Pietrek bool allow_another_instance() { - HINSTANCE hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE); - - HMODULE hModuleSel = SELECTOROF( // Convert the HINSTANCE to an HMODULE - GlobalLock(GetModuleHandle((const char*)MAKELP(0,hInstance)))); - - if ( hModuleSel == 0 ) // Make sure we succeeded. + // Convert the HINSTANCE to an HMODULE + HINSTANCE hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE); + LPCSTR sModuleName = (LPCSTR)MAKELP(0, hInstance); + HMODULE hModule = GetModuleHandle(sModuleName); + void FAR* mem_handle = GlobalLock(hModule); + HMODULE hModuleSel = (HMODULE)SELECTOROF(mem_handle); + if (hModuleSel == 0) // Make sure we succeeded. return FALSE; // Make pointers to the resident names table and the OFSTRUCT @@ -157,10 +103,6 @@ bool allow_another_instance() return TRUE; } -#endif - - - static BOOLEAN event_hook(HWND hwnd, UINT msg, UINT wparam, @@ -169,107 +111,18 @@ static BOOLEAN event_hook(HWND hwnd, { switch(msg) { - case WM_SYSCOLORCHANGE: - Ctl3dColorChange(); - break; - case WM_CTLCOLOR: - { - const word type = HIWORD(lparam); - if (type == CTLCOLOR_LISTBOX || type == CTLCOLOR_EDIT || - type == CTLCOLOR_MSGBOX) - { - HWND hwnd = LOWORD(lparam); - HDC hdc = wparam; - - if (!IsWindowEnabled(hwnd)) // Campo disabilitato - { - if (type != CTLCOLOR_MSGBOX) - { - SetTextColor(hdc, NormalForeColor); - SetBkColor(hdc, MaskColor); - } - *ret = MaskBrush; - return FALSE; // Non fare altro - } - - bool focus = GetFocus() == hwnd; - if (type != CTLCOLOR_MSGBOX) - { - SetTextColor(hdc, focus ? FocusForeColor : NormalForeColor); - SetBkColor(hdc, focus ? FocusBackColor : NormalBackColor); - } - *ret = focus ? FocusBrush : NormalBrush; - return FALSE; // Non fare altro - } -#ifdef __CTL3D__ - else - { - *ret = Ctl3dCtlColorEx(msg, wparam, lparam); - return TRUE; - } -#else - -#endif - } - break; - case WM_COMMAND: - { - const word notify = HIWORD(lparam); - if (notify == EN_KILLFOCUS || notify == EN_SETFOCUS) - { - HWND hwnd = LOWORD(lparam); // Ridisegna BENE il campo - InvalidateRect(hwnd, NULL, TRUE); - } - } - break; - case WM_KEYDOWN: - if (wparam == VK_PRIOR || wparam == VK_NEXT || - wparam == VK_UP || wparam == VK_DOWN || - wparam == VK_F1 ) - { - KEY key = 0; - char name[16]; - GetClassName(hwnd, name, 5); - - if (stricmp(name, "Edit") == 0) switch(wparam) - { - case VK_PRIOR: - key = K_PREV; break; - case VK_NEXT: - key = K_NEXT; break; - case VK_UP: - key = K_UP; break; - case VK_DOWN: - key = K_DOWN; break; - default: - key = 0; break; - } - - if (wparam == VK_F1) - key = K_F1; - - if (key > 0) - { - WINDOW w = cur_win(); - if (w != NULL_WIN) - { - dispatch_e_char(w, key); - return FALSE; - } - } - } - break; case WM_MENUCHAR: - { - WINDOW w = cur_win(); - if (w != NULL_WIN) - { - const KEY key = toupper(wparam)+K_CTRL; - dispatch_e_char(w, key); - } - } + if (wparam >= 'A' && wparam <= 'z') + { + WINDOW w = cur_win(); + if (w != NULL_WIN) + { + const KEY key = toupper(wparam)+K_CTRL; + dispatch_e_char(w, key); + } + } break; - default: + default: if (msg == WM_WAKEUP && wparam == main_app().waiting()) main_app().wake_up(); break; @@ -278,22 +131,6 @@ static BOOLEAN event_hook(HWND hwnd, return TRUE; // Continua col processo normale } - -HIDDEN WIN_TYPE _wc_type = W_NONE; -HIDDEN long _bandiere = 0L; - -static void createwindow_hook(DWORD* exstyle, LPCSTR* classname, LPCSTR* windowname, DWORD* styl, - int* x, int* y, int* width, int* height, HWND* parent, HMENU* menu, - HINSTANCE inst, void **) -{ - if (_wc_type == WC_EDIT) - { - if (_bandiere & CTL_FLAG_MAC_MONACO9) - *exstyle |= ES_PASSWORD; - } - _wc_type = W_NONE; -} - #endif // @doc INTERNAL @@ -332,7 +169,6 @@ RCT& resize_rect( wt = WC_EDIT; } -#if XVT_OS == XVT_OS_WIN switch (wt) { case WC_EDIT : @@ -356,12 +192,6 @@ RCT& resize_rect( r.bottom = dy*ROWY-1; break; } -#else - r.left = x * CHARX; - r.top = y * CHARY; - r.right = dx * CHARX; - r.bottom = dy * CHARY; -#endif if (x < 0 || y < 0 || dx <= 0 || dy <= 0) { @@ -369,7 +199,7 @@ RCT& resize_rect( if (parent == NULL_WIN) parent = TASK_WIN; xvt_vobj_get_client_rect(parent, &pc); // Get parent window size const short MAXX = pc.right; - const short MAXY = pc.bottom - (parent == TASK_WIN ? 26 : 0); + const short MAXY = pc.bottom; if (x < 0) { @@ -427,7 +257,7 @@ void beep() class TEvent_manager { - enum { MAX = 2 }; + enum { MAX = 16 }; WINDOW _w[MAX]; EVENT _e[MAX]; int _begin, _end; @@ -504,6 +334,22 @@ KEY e_char_to_key( return key; } +// @doc EXTERNAL + +// @func Simula un evento + +void dispatch_event( + WINDOW win, // @parm Finestra destinataria dell'evento + const EVENT& e, // @parm Evento da generare + bool post) +{ + if (post) + EM.push(win, e); + else + xvt_win_dispatch_event(win, (EVENT*)&e); +} + + // @doc EXTERNAL // @func Simula la scelta di una voce di menu @@ -513,12 +359,11 @@ void dispatch_e_menu( // @xref { - EVENT e; - + EVENT e; memset(&e, 0, sizeof(e)); e.type = E_COMMAND; e.v.cmd.tag = item; e.v.cmd.shift = e.v.cmd.control = 0; - EM.push(win, e); + dispatch_event(win, e, TRUE); } // @doc EXTERNAL @@ -530,19 +375,19 @@ void dispatch_e_char( // @xref { - EVENT e; + EVENT e; memset(&e, 0, sizeof(e)); e.type = E_CHAR; - if (key > 10000) { e.v.chr.control = TRUE; key -= K_CTRL; } - else e.v.chr.control = FALSE; - - if (key > 1000) { e.v.chr.shift = TRUE; key -= K_SHIFT; } - else e.v.chr.shift = FALSE; - + if (key > K_CTRL) + { e.v.chr.control = TRUE; key -= K_CTRL; } + + if (key > K_SHIFT) + { e.v.chr.shift = TRUE; key -= K_SHIFT; } + e.v.chr.ch = short(key); - EM.push(win, e); + dispatch_event(win, e, TRUE); } // @doc EXTERNAL @@ -554,7 +399,7 @@ void dispatch_e_scroll( // @xref { - EVENT e; + EVENT e; memset(&e, 0, sizeof(e)); EVENT_TYPE& t = e.type; SCROLL_CONTROL& w = e.v.scroll.what; short& p = e.v.scroll.pos; @@ -609,7 +454,8 @@ void dispatch_e_scroll( break; }; - if (w != SC_NONE) xvt_win_dispatch_event(win, &e); + if (w != SC_NONE) + dispatch_event(win, e, FALSE); } // @doc INTERNAL @@ -644,128 +490,20 @@ void customize_controls( bool on) // @parm Permette di inizializzare (TRUE) o scaricare (FALSE) i parametri { - customize_colors(); if (on) { -#if XVTWS == WMWS - // xvt_vobj_set_attr(NULL_WIN,ATTR_CH_SHADOW,XVT_CH_SHADOW_WINDOW|XVT_CH_SHADOW_DIALOG); - xvt_vobj_set_attr(NULL_WIN, ATTR_CH_TOGGLE_COMBO, (long)K_F9); -#endif - #if XVT_OS == XVT_OS_WIN - xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_PM_DRAWABLE_TWIN, TRUE); xvt_vobj_set_attr(NULL_WIN,ATTR_EVENT_HOOK, (long)event_hook); - xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_CREATEWINDOW_HOOK, (long)createwindow_hook); - + xvt_vobj_set_attr(NULL_WIN,ATTR_ERRMSG_HANDLER, (long)error_hook); allow_another_instance(); - - HINSTANCE _hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE); - Ctl3dRegister(_hInstance); - Ctl3dAutoSubclass(_hInstance); - - MaskColor = COLOR2RGB(MASK_BACK_COLOR); - MaskBrush = CreateSolidBrush(MaskColor); - - NormalForeColor = COLOR2RGB(NORMAL_COLOR); - NormalBackColor = COLOR2RGB(NORMAL_BACK_COLOR); - NormalBrush = CreateSolidBrush(NormalBackColor); - - FocusForeColor = COLOR2RGB(FOCUS_COLOR); - FocusBackColor = COLOR2RGB(FOCUS_BACK_COLOR); - FocusBrush = CreateSolidBrush(FocusBackColor); #endif + customize_colors(); + init_controls(); } else { -#if XVT_OS == XVT_OS_WIN - HINSTANCE _hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE); - Ctl3dUnregister(_hInstance); - - DeleteObject(NormalFont); - DeleteObject(MaskBrush); - DeleteObject(NormalBrush); - DeleteObject(FocusBrush); - - free_controls_bmp(); -#endif - xvt_font_destroy(DEF_FONT); - xvt_font_destroy(FAT_FONT); + free_controls(); } - - if (on) xvt_vobj_set_attr(NULL_WIN,ATTR_ERRMSG_HANDLER, (long)error_hook); -} - -XVT_FNTID xvt_default_font() -{ - if (DEF_FONT == NULL) - { - DEF_FONT = xvt_dwin_get_font(TASK_WIN); - FAT_FONT = xvt_dwin_get_font(TASK_WIN); - -#if XVT_OS == XVT_OS_WIN - NormalFont = GetStockObject(ANSI_FIXED_FONT); - GetObject(NormalFont, sizeof(LOGFONT), &LogFont); - - TConfig font(CONFIG_USER, "Font"); - CHARY = (int)font.get_long("Height"); - if (CHARY > 0) - { - LogFont.lfHeight = CHARY; - LogFont.lfWeight = FontWeight = font.get_int("Weight"); - LogFont.lfPitchAndFamily = font.get_int("Pitch"); - strcpy(LogFont.lfFaceName, font.get("Name")); - } - else - { - LogFont.lfHeight = CHARY = 10; - FontWeight = 300; // Normal weight - } - NormalFont = CreateFontIndirect(&LogFont); - - TToken_string desc(128, '/'); - desc.add("WIN01"); // 0 - desc.add(LogFont.lfHeight); // 1 - desc.add(LogFont.lfWidth); // 2 - desc.add(LogFont.lfEscapement); // 3 - desc.add(LogFont.lfOrientation); // 4 - desc.add(LogFont.lfWeight); // 5 - desc.add(LogFont.lfItalic); // 6 - desc.add(LogFont.lfUnderline); - desc.add(LogFont.lfStrikeOut); - desc.add(LogFont.lfCharSet); - desc.add(LogFont.lfOutPrecision); - desc.add(LogFont.lfClipPrecision); - desc.add(LogFont.lfQuality); - desc.add(LogFont.lfPitchAndFamily); - desc.add(LogFont.lfFaceName); - - xvt_font_set_native_desc(DEF_FONT, (char*)(const char*)desc); - CHECK(xvt_font_has_valid_native_desc(DEF_FONT), "Bad font description"); - xvt_font_map_using_default(DEF_FONT); - CHECK(xvt_font_is_mapped(DEF_FONT), "Can't map native font"); - xvt_dwin_set_font(TASK_WIN, DEF_FONT); - - desc.add(600, 5); - xvt_font_set_native_desc(FAT_FONT, (char*)(const char*)desc); - CHECK(xvt_font_has_valid_native_desc(FAT_FONT), "Bad font description"); - xvt_font_map_using_default(FAT_FONT); - CHECK(xvt_font_is_mapped(FAT_FONT), "Can't map native font"); - // Get true text size - TEXTMETRIC tm; - HDC hdc = (HDC)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_GRAPHIC_CONTEXT); - GetTextMetrics(hdc, &tm); - - const int COLX = GetSystemMetrics(SM_CXSCREEN) / 80; - CHARX = tm.tmAveCharWidth+1; - if (CHARX > COLX) CHARX = COLX; - - CHARY = tm.tmHeight; - BASEY = tm.tmAscent; - if (CHARY > ROWY-2) CHARY = ROWY-2; -#endif - } - - return DEF_FONT; } // @doc INTERNAL @@ -779,12 +517,11 @@ void xvt_set_font( { CHECK(win != NULL_WIN, "Can't set the font in a NULL window"); -#if XVT_OS != XVT_OS_SCOUNIX if ((family == NULL || *family == '\0') && (style == XVT_FS_NONE || style == XVT_FS_BOLD) && dim == 0) { - xvt_dwin_set_font(win, (style == XVT_FS_NONE) ? DEF_FONT : FAT_FONT); + xvt_dwin_set_font(win, xvt_default_font(style != XVT_FS_NONE)); } else { @@ -799,9 +536,64 @@ void xvt_set_font( xvt_dwin_set_font(win, font); xvt_font_destroy(font); } -#endif } +void xvt_draw_rect(WINDOW win, const RCT& rect, COLOR lt, COLOR rb, short depth) +{ + RCT r = rect; + + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = lt; + + for (short d = 0; d < depth;) + { + xvt_dwin_set_cpen(win, &pen); + + PNT p; // Current vertex of the rectangle + + bool drawn = FALSE; + if (lt != COLOR_LTGRAY) + { + p.h = r.left; p.v = r.bottom; + xvt_dwin_draw_set_pos(win, p); + + p.v = r.top; + xvt_dwin_draw_line(win, p); + p.h = r.right; + xvt_dwin_draw_line(win, p); + drawn = TRUE; + } + + if (rb != COLOR_LTGRAY) + { + if (pen.color != rb) + { + pen.color = rb; + xvt_dwin_set_cpen(win, &pen); + } + if (!drawn) + { + p.h = r.right; p.v = r.top; + xvt_dwin_draw_set_pos(win, p); + } + p.v = r.bottom; + xvt_dwin_draw_line(win, p); + p.h = r.left; + xvt_dwin_draw_line(win, p); + } + + if (++d < depth) + { + r.left++; r.top++; + r.right--; r.bottom--; + } + } +} + + // @doc INTERNAL // @func Permette di creare una finestra @@ -867,83 +659,11 @@ WINDOW xvt_create_control( int id) // @parm Indentificatore del controlllo { RCT r = resize_rect(x, y, dx, dy, wt, parent); - WINDOW win = NULL_WIN; - -#if XVT_OS == XVT_OS_WIN - _wc_type = wt; - _bandiere = flags; - flags &= ~(CTL_FLAG_MAC_MONACO9 | CTL_FLAG_MAC_GENEVA9); - - if (wt == WC_PUSHBUTTON) - win = xvt_create_pushbutton(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - -#ifndef __CTL3D__ - if (wt == WC_CHECKBOX) - win = xvt_create_checkbox(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - - if (wt == WC_RADIOBUTTON) - win = xvt_create_radiobutton(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - - if (wt == WC_GROUPBOX) - { - win = xvt_create_groupbox(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - } - - if (wt == WC_TEXT) - { - win = xvt_create_text(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - } -#else - if (wt == WC_GROUPBOX) - { - win = xvt_create_text(r.left, r.top, r.right, r.top+CHARY, - caption, parent, 0, app_data, id); - } -#endif - -#endif - + while (*caption == '@') caption += 2; + WINDOW win = xvt_ctl_create(wt, &r, (char*)caption, parent, + flags, app_data, id); if (win == NULL_WIN) - { -#if XVT_OS == XVT_OS_SCOUNIX - if (wt == WC_PUSHBUTTON) - { - if (dy == 2) r.bottom -= ROWY; - if (id == DLG_F9) - { wt = WC_TEXT; r.right = r.left+CHARX; caption = "*"; } - else if (*caption == '*') caption = ""; - } -#endif - while (*caption == '@') caption += 2; - win = xvt_ctl_create(wt, &r, (char*)caption, parent, - flags, app_data, id); - - if (win == NULL_WIN) - fatal_box("Can't create control %d", id); - } - - -#if XVT_OS == XVT_OS_WIN -#ifdef __CTL3D__ - if (wt != WC_PUSHBUTTON) -#else - if (wt == WC_EDIT || wt == WC_LISTBUTTON) -#endif - { - HWND hwnd = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); - SendMessage(hwnd, WM_SETFONT, NormalFont, FALSE); - if (_bandiere & CTL_FLAG_MAC_MONACO9) - SendMessage(hwnd, EM_SETPASSWORDCHAR, (WORD)'#', 0); -#ifdef __CTL3D__ - Ctl3dSubclassCtl(hwnd); -#endif - } -#endif + fatal_box("Can't create control %d: '%s'", id, caption); return win; } @@ -958,13 +678,8 @@ const char* xvt_get_title( // @xref { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - const TControl* c = TControl::WINDOW2TControl(win); - return c->caption(); -#else xvt_vobj_get_title(win, __tmp_string, 80); return __tmp_string; -#endif } // @doc INTERNAL @@ -976,12 +691,7 @@ void xvt_set_title( // @xref { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->set_caption(cap); -#else xvt_vobj_set_title(win, (char*)cap); -#endif } // @doc INTERNAL @@ -990,10 +700,6 @@ void xvt_set_title( void xvt_set_front_control( WINDOW win) // @parm Finestra nella quale abilitare il focus { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->focus(TRUE); -#endif xvt_scr_set_focus_vobj(win); } @@ -1003,10 +709,6 @@ void xvt_set_front_control( void xvt_kill_focus( WINDOW win) // @parm Finestra nella quale togliere il focus { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->focus(FALSE); -#endif } // @doc INTERNAL @@ -1016,12 +718,7 @@ void xvt_enable_control( WINDOW win, // @parm Finestra all'interno della quale abilitare il controllo bool on) // @parm Abilita (TRUE) o disabilita (FALSE) il controllo { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->enable(on); -#else xvt_vobj_set_enabled(win, on); -#endif } // @doc INTERNAL @@ -1031,12 +728,7 @@ void xvt_check_box( WINDOW win, // @parm Finestra all'interno della quale abilitare il check box bool on) // @parm Permette di inizializzare (TRUE) o scaricare (FALSE) i parametri { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = (TControl*)TControl::WINDOW2TControl(win); - c->check(on); -#else xvt_ctl_set_checked(win, on); -#endif } // @doc INTERNAL @@ -1050,12 +742,7 @@ void xvt_check_box( bool xvt_get_checked_state( WINDOW win) // @parm Finestra di cui si vuole conoscere lo stato { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - return c->checked(); -#else return xvt_ctl_is_checked(win) ? TRUE : FALSE; -#endif } // @doc INTERNAL @@ -1066,12 +753,7 @@ void xvt_check_radio_button( const WINDOW* ctls, // @parm Array di stringhe contenenti le scelte del radiobutton int count) // @parm Numero di elementi del radiobutton { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - for (int i = 0; i < count; i++) - xvt_check_box(ctls[i], ctls[i] == win); -#else xvt_ctl_check_radio_button(win, (WINDOW*)ctls, count); -#endif } // @doc INTERNAL @@ -1084,13 +766,6 @@ int xvt_get_checked_radio( int count) // @parm Numero di elemnti del radiobutton { - for (int i = 0; i < count; i++) - if (xvt_get_checked_state(ctls[i])) return i; - -#ifdef DBG - error_box("Accendi la tua radio per favore!"); -#endif - return 0; } @@ -1102,10 +777,6 @@ void xvt_set_ctrl_back_color( WINDOW win, // @parm Finestra di cui si vuole cambiare lo sfondo COLOR col) // @parm Colore dello sfondo { -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = (TControl*)TControl::WINDOW2TControl(win); - c->set_back_color(col); -#endif } @@ -1172,7 +843,7 @@ void xvt_statbar_set( // @doc INTERNAL -// @func Permette di aggiornare il titolo alla barra di stato presente +// @func Permette di cambiare il titolo alla barra di stato presente void xvt_statbar_refresh() // @xref @@ -1261,6 +932,38 @@ COLOR trans_color( return col; } +// @doc INTERNAL +// @mfunc Cambia il cursore del mouse +HIDDEN void set_cursor( + bool w) // @parm Indica il tipo di cursore da utilizzare: + // + // @flag TRUE | Cursore a clessidra per le wait + // @flag FALSE | Cursore a frecca normale +{ + static int _count = 0; + + if (w) + { + if (_count == 0) + xvt_win_set_cursor(TASK_WIN, CURSOR_WAIT); + _count++; + } + else + { + _count--; + CHECK(_count >= 0, "end_wait without matching begin_wait"); + if (_count == 0) + xvt_win_set_cursor(TASK_WIN, CURSOR_ARROW); + } +} + +void begin_wait() +{ set_cursor(TRUE); } + +void end_wait() +{ set_cursor(FALSE); } + + // @doc INTERNAL // @func Permette di converitire lo stile del pattern in attributi grafici da diff --git a/include/xvtility.h b/include/xvtility.h index f9463e9cb..f50bebf70 100755 --- a/include/xvtility.h +++ b/include/xvtility.h @@ -29,44 +29,26 @@ WINDOW xvt_create_window long app_data ); - WINDOW xvt_create_control - ( - WIN_TYPE wt, - short x, short y, short dx, short dy, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id - ); - WINDOW xvt_create_statbar(); void xvt_statbar_set(const char* text, bool def = FALSE); void xvt_statbar_refresh(); void beep(); void do_events(); + void customize_colors(); void customize_controls(bool on); + KEY e_char_to_key(const EVENT* ep); + void dispatch_event(WINDOW win, const EVENT& e, bool post); void dispatch_e_menu(WINDOW win, MENU_TAG item); void dispatch_e_char(WINDOW win, KEY key); void dispatch_e_scroll(WINDOW win, KEY key); + + void begin_wait(); + void end_wait(); void xvt_set_font(WINDOW win, const char* family, int style, int dim = 0); - XVT_FNTID xvt_default_font(); - - void xvt_set_front_control(WINDOW win); - void xvt_kill_focus(WINDOW win); - const char* xvt_get_title(WINDOW win); - void xvt_set_title(WINDOW win, const char* title); - void xvt_enable_control(WINDOW win, bool on); - void xvt_check_box(WINDOW win, bool on); - 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_set_ctrl_back_color(WINDOW win, COLOR col); - void xvt_change_page_tags(WINDOW pag, bool on, WINDOW tag, byte p); bool xvt_test_menu_tag(MENU_TAG tag);