diff --git a/include/automask.cpp b/include/automask.cpp index 956ff0fa2..cfdf5c7a8 100755 --- a/include/automask.cpp +++ b/include/automask.cpp @@ -60,15 +60,10 @@ TField_event TAutomask::key2event(TMask_field& f, KEY key) const if (!f.is_edit()) { const TMask& wm = f.mask(); - if (wm.is_running()) - { - if (f.is_kind_of(CLASS_BUTTON_FIELD)) - fe = fe_button; - else - fe = fe_modify; - } + if (f.is_kind_of(CLASS_BUTTON_FIELD)) + fe = fe_button; else - fe = fe_init; + fe = wm.is_running() ? fe_modify : fe = fe_init; } break; case K_ENTER: diff --git a/include/config.cpp b/include/config.cpp index 60577234f..7cb556077 100755 --- a/include/config.cpp +++ b/include/config.cpp @@ -113,7 +113,7 @@ void TConfig::_write_file() bool skip = FALSE, done = FALSE, skip_empty = TRUE; - while (!in.eof()) + while (in && !in.eof()) { in.getline(l.get_buffer(), l.size()); l.trim(); diff --git a/include/controls.cpp b/include/controls.cpp index 4e7e39092..8241109b3 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -293,21 +293,13 @@ void customize_colors() FOCUS_COLOR = colors.get_color("Focus", NULL, -1, FOCUS_COLOR); FOCUS_BACK_COLOR = colors.get_color("FocusBack", NULL, -1, FOCUS_BACK_COLOR); TOOL_BACK_COLOR = colors.get_color("ToolBack", NULL, -1, MASK_DARK_COLOR); - CAMPI_SCAVATI = colors.get_bool("Campi3D", NULL, -1, (bool)CAMPI_SCAVATI); - AUTOSELECT = colors.get_bool("AutoSelect", NULL, -1, (bool)AUTOSELECT); + CAMPI_SCAVATI = colors.get_bool("Campi3D", NULL, -1, CAMPI_SCAVATI); + AUTOSELECT = colors.get_bool("AutoSelect", NULL, -1, AUTOSELECT); - xi_set_pref(XI_PREF_NATIVE_CTRLS, FALSE); - 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_set_pref(XI_PREF_COLOR_DISABLED, DISABLED_COLOR); -#ifdef XI_R4 - xi_set_pref(XI_PREF_COMBO_ICON, ICO_COMBO); -#else - xi_set_pref(XI_PREF_COMBO_ICON, COMBO_ICON); -#endif BTN_BACK_COLOR = colors.get_color("ButtonBack", NULL, -1, BTN_BACK_COLOR); aga_set_pref(AGA_PREF_BTN_COLOR_CTRL, BTN_BACK_COLOR); @@ -330,7 +322,15 @@ void init_controls() { xi_set_font_id(xvt_load_default_font()); + xi_set_pref(XI_PREF_NATIVE_CTRLS, FALSE); + xi_set_pref(XI_PREF_3D_LOOK, TRUE); xi_set_pref(XI_PREF_CARET_WIDTH, 2); +#ifdef XI_R4 + xi_set_pref(XI_PREF_COMBO_ICON, ICO_COMBO); + xi_set_pref(XI_PREF_OPTIMIZE_CELL_REQUESTS, TRUE); +#else + xi_set_pref(XI_PREF_COMBO_ICON, COMBO_ICON); +#endif xi_init(); @@ -1205,19 +1205,25 @@ void TField_control::create(WINDOW win, short cid, 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) + + if (height == 1) { - f->button = TRUE; - f->pixel_button_distance = 1; + f->auto_tab = TRUE; + if (button) + { + f->button = TRUE; + f->pixel_button_distance = 1; + } } - if (height != 1) // E' un multiline, quindi setto il rettangolo + else // E' un multiline, quindi setto il rettangolo { f->xi_rct.top = rct.top; f->xi_rct.bottom = rct.bottom; f->xi_rct.right = rct.right; f->xi_rct.left = rct.left; + f->cr_ok = TRUE; + f->var_len_text = TRUE; } XI_OBJ* itf = get_interface(win); diff --git a/include/dongle.cpp b/include/dongle.cpp index 3ff8f8d13..527f3deb0 100755 --- a/include/dongle.cpp +++ b/include/dongle.cpp @@ -204,17 +204,17 @@ bool TDongle::hardlock_login(bool test_all_keys) if (test_all_keys) { HL_LOGOUT(); - if (HL_LOGIN(AGAADR, DONT_CARE, REFKEY, VERKEY) == STATUS_OK) + if (HL_LOGIN(AGAADR, LOCAL_DEVICE, REFKEY, VERKEY) == STATUS_OK) _type = _aga_dongle; else { HL_LOGOUT(); - if (HL_LOGIN(PRASSIADR, DONT_CARE, REFKEY, VERKEY) == STATUS_OK) + if (HL_LOGIN(PRASSIADR, LOCAL_DEVICE, REFKEY, VERKEY) == STATUS_OK) _type = _prassi_dongle; else { HL_LOGOUT(); - if (HL_LOGIN(PROCOMADR, DONT_CARE, REFKEY, VERKEY) == STATUS_OK) + if (HL_LOGIN(PROCOMADR, LOCAL_DEVICE, REFKEY, VERKEY) == STATUS_OK) _type = _procom_dongle; } } diff --git a/include/execp.cpp b/include/execp.cpp index 8c0033c4c..98ddc8107 100755 --- a/include/execp.cpp +++ b/include/execp.cpp @@ -2,6 +2,7 @@ #include #include #include +#include // @doc EXTERNAL @@ -53,50 +54,6 @@ word TExternal_app::run( xvt_fsys_set_dir(&d); } -/* Gestione programmi spezzati - if (our_app) - { - TString parms(_path); - TString new_suffix; - int p = parms.find(' '); - - if (p < 0) - { - parms = ""; - new_suffix = "_0"; - } - else - { - parms = parms.mid(p + 1); - p = parms.find(' '); - if (p >= 0) - new_suffix = parms.left(p); - else new_suffix = parms; - if (new_suffix[0] == '-') new_suffix[0] = '_'; - else new_suffix = "__"; - } - - TFilename newpath(dir); - - if (newpath.not_empty()) - newpath << '/'; - newpath << name << new_suffix; - newpath.ext("exe"); - if (fexist(newpath)) - { - newpath.ext(""); - newpath << parms; - path = newpath; - if (utente) -#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32 - path << " /u" << user(); -#else - path << " -u" << user(); -#endif - - } - } -*/ if (!async) safely_close_closeable_isamfiles(); @@ -124,6 +81,31 @@ word TExternal_app::run( return _exitcode; } +bool TExternal_app::can_run() const +{ + TRecord_cache users(LF_USER); + TToken_string perm(4096, '\n'), row(80); + for (TString16 u = user(); + u.not_empty() && !users.already_loaded(u); + u = users.get(u, "GROUPNAME")) + { + perm = users.get(u, "PERMISSION"); + if (!perm.blank()) + { + FOR_EACH_TOKEN(perm, tok) + { + row = tok; + if (_path == row.get(0)) // Il nome corrisponde + { + if (*row.get(1) == 'N') + return FALSE; + } + } + } + } + return TRUE; +} + TExternal_app::TExternal_app(const char* p) : _path(p), _exitcode(0) { diff --git a/include/execp.h b/include/execp.h index ddd3e5fcd..899aa8ef6 100755 --- a/include/execp.h +++ b/include/execp.h @@ -32,6 +32,8 @@ protected: // @access Public Member public: + // @cmember Controlla se l'utente puo' eseguire il programma + bool can_run() const; // @cmember Esegue il processo word run(bool async = FALSE, byte user = TRUE, bool iconize = TRUE, bool show = TRUE); // @cmember Ritorna l'ultimo codice di uscita diff --git a/include/expr.cpp b/include/expr.cpp index e6d84b117..8bd976554 100755 --- a/include/expr.cpp +++ b/include/expr.cpp @@ -84,7 +84,6 @@ const real& TVararray::getnum(const char* name) for (int i = items()-1; i >= 0; i--) { const TVar* var = (const TVar*)objptr(i); - CHECKS(var, "Variabile NULLA ", name); if (strcmp(var->getname(), name) == 0) return var->number(); } @@ -92,16 +91,19 @@ const real& TVararray::getnum(const char* name) return ZERO; } - const real& TVararray::getnum(int varnum) { - if (varnum >= items()) - fatal_box("invalid variable number : %d", varnum); - return ((TVar*)objptr(varnum))->number(); + const TVar* var = (const TVar*)objptr(varnum); + if (var == NULL) + { + NFCHECK("Invalid variable number : %d", varnum); + return ZERO; + } + return var->number(); } -const char* TVararray::getstring(const char* name) +const TString& TVararray::getstring(const char* name) { for (int i = items()-1; i >= 0; i--) { @@ -110,19 +112,17 @@ const char* TVararray::getstring(const char* name) return var->string(); } NFCHECK("Unknown variable : %s", name); - return ""; + return EMPTY_STRING; } - -const char* TVararray::getstring(int varnum) +const TString& TVararray::getstring(int varnum) { - if (varnum < 0 || varnum >= items()) + const TVar* var = (const TVar*)objptr(varnum); + if (var == NULL) { NFCHECK("Invalid variable number : %d", varnum); - return ""; + return EMPTY_STRING; } - const TVar* var = (const TVar*)objptr(varnum); - CHECKD(var, "Variabile nulla: ", varnum); return var->string(); } @@ -130,13 +130,46 @@ const char* TVararray::getstring(int varnum) // TEval_stack /////////////////////////////////////////////////////////// +void TEval_stack::push(const real& r) +{ + if (_data.items() > _sp) + { + _sp++; + peek_real() = r; + } + else + TStack::push(r); +} + +void TEval_stack::push(const TString& s) +{ + if (_data.items() > _sp) + { + _sp++; + peek_string() = s; + } + else + TStack::push(s); +} + +void TEval_stack::push(const char* s) +{ + if (_data.items() > _sp) + { + _sp++; + peek_string() = s; + } + else + TStack::push(new TString80(s)); +} + real& TEval_stack::pop_real() { TObject& o = pop(); if (o.class_id() == CLASS_STRING) { real* r = new real((TString&)o); - push(r); + TStack::push(r); return (real&)pop(); } return (real&)o; @@ -149,7 +182,7 @@ real& TEval_stack::peek_real() { pop(); real* r = new real((TString&)o); - push(r); + TStack::push(r); return *r; } return (real&)o; @@ -161,8 +194,8 @@ TString& TEval_stack::pop_string() if (o.class_id() == CLASS_STRING) return (TString&)o; - TString* s = new TString(((real&)o).string()); - push(s); + TString* s = new TString80(((real&)o).string()); + TStack::push(s); return (TString&)pop(); } @@ -173,11 +206,23 @@ TString& TEval_stack::peek_string() return (TString&)o; pop(); - TString* s = new TString(((real&)o).string()); - push(s); + TString* s = new TString80(((real&)o).string()); + TStack::push(s); return *s; } +bool TEval_stack::pop_bool() +{ + TObject& o = pop(); + if (o.class_id() == CLASS_STRING) + { + const real r = (TString&)o; + return !r.is_zero(); + } + return !((real&)o).is_zero(); +} + + /////////////////////////////////////////////////////////// // TExpression @@ -192,12 +237,7 @@ TExpression::TExpression(const char* expression, TTypeexp type, bool ignore_err) _val = ZERO; _dirty = TRUE; _type = type; - if (!compile(_original, type)) - { - TString msg(256); - msg.format("Wrong expression : %s", expression); - print_error(msg); - } + compile(_original, type); } @@ -254,12 +294,12 @@ void TExpression::print_on(ostream& out) const void TExpression::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp curtype) const { NFCHECK("Unknown function %d.", index); - for ( int i = nparms ; i > 0; i--) + for (int i = nparms ; i > 0; i--) stack.pop(); if (curtype == _numexpr) stack.push(ZERO); else - stack.push(TString("")); + stack.push(""); } void TExpression::setvar(const char* varname, const real& val) @@ -383,9 +423,8 @@ void TExpression::eval() { if (!evalstack.peek_real().is_zero()) { - if (_ignore_error) - _error=1; - else + _error=1; + if (!_ignore_error) print_error("Divisione per zero!"); } } @@ -401,16 +440,16 @@ void TExpression::eval() break; case _and: { - const real & r2 = evalstack.pop_real(); - real & r1 = evalstack.peek_real(); - r1 = (!r1.is_zero() && !r2.is_zero()) ? 1.0 : 0.0; + const bool r2 = evalstack.pop_bool(); + const bool r1 = evalstack.pop_bool(); + evalstack.push(real(r1 && r2 ? 1.0 : 0.0)); } break; case _or: { - const real & r2 = evalstack.pop_real(); - real & r1 = evalstack.peek_real(); - r1 = (r1 != ZERO || r2 != ZERO) ? 1.0 : 0.0; + const bool r2 = evalstack.pop_bool(); + const bool r1 = evalstack.pop_bool(); + evalstack.push(real(r1 || r2 ? 1.0 : 0.0)); } break; case _not: @@ -435,9 +474,9 @@ void TExpression::eval() break; case _match: { - const TString & s2 = evalstack.pop_string(); - const TString & s1 = evalstack.pop_string(); - evalstack.push(real((s1.match(s2)) ? 1.0 : 0.0)); + const TString& s2 = evalstack.pop_string(); + const TString& s1 = evalstack.pop_string(); + evalstack.push(real(s1.match(s2) ? 1.0 : 0.0)); } break; case _noteq: @@ -523,9 +562,8 @@ void TExpression::eval() real& r = evalstack.peek_real(); if (r < ZERO) { - if (_ignore_error) - _error=1; - else + _error=1; + if (!_ignore_error) print_error("Radice negativa!"); r = -r; } @@ -662,8 +700,8 @@ void TExpression::eval() { const TString & s1 = evalstack.pop_string(); const TString & s2 = evalstack.pop_string(); - const real & cond = evalstack.pop_real(); - evalstack.push(cond.is_zero() ? s1 : s2); + const bool cond = evalstack.pop_bool(); + evalstack.push(cond ? s2 : s1); } else { @@ -1151,7 +1189,7 @@ bool TExpression::set(const char* expression, TTypeexp type) return compile(_original, type); } -bool TExpression::compile(const char* expression, TTypeexp type) +bool TExpression::compile(const TString& expression, TTypeexp type) { _error=0; _user_func_defined = FALSE; @@ -1159,13 +1197,25 @@ bool TExpression::compile(const char* expression, TTypeexp type) _type = type; _val = ZERO; _code.clear(); - if (*_s == '\0') + if (expression.blank()) return TRUE; TCodesym currsym = __gettoken(); - if (currsym == _invalid) - return FALSE; - return __expression(currsym) == _endsym; + bool ok = currsym != _invalid; + if (ok) + ok = __expression(currsym) == _endsym; + if (!ok) + { + _error = 2; + if (!_ignore_error) + { + TString msg; + msg << "Wrong expression : " << _original; + print_error(msg); + } + } + + return ok; } const char* TExpression::last_token() const diff --git a/include/expr.h b/include/expr.h index 9fb6e5890..da064a5f5 100755 --- a/include/expr.h +++ b/include/expr.h @@ -179,7 +179,7 @@ public: const real& number() const { return _val.number();} // @cmember Ritorna il valore come stringa - const char* string() const + const TString& string() const { return _val.string();} // @cmember Costruttore, inizializza simbolo con "invalid", valore a nullvalue @@ -292,7 +292,7 @@ public: const real& number() const { return _val.number();} // @cmember Ritorna il valore stringa della variabile - const char* string() const + const TString& string() const { return _val.string();} // @cmember Costruttore (assegna "" al campo

ed il valore nulltvalue al campo

) @@ -353,9 +353,9 @@ public: // @cmember Ritorna il valore della variabile di posto

-esimo const real& getnum(int varnum); // @cmember Ritorna il nome della variabile con nome

- const char* getstring(const char* varname); + const TString& getstring(const char* varname); // @cmember Ritorna il nome della variabile di posto

-esimo - const char* getstring(int varnum); + const TString& getstring(int varnum); // @cmember Ritorna il numero di variabili utilizzate int numvar() const @@ -371,10 +371,15 @@ public: class TEval_stack : public TStack { public: + void push(const real& r); + void push(const TString& s); + void push(const char* s); + real& pop_real(); real& peek_real(); TString& pop_string(); TString& peek_string(); + bool pop_bool(); }; // @doc EXTERNAL @@ -385,11 +390,12 @@ public: // @base public | TObject class TExpression : public TObject -// @author:(INTERNAL) Sandro +// @author:(INTERNAL) Alex // @access:(INTERNAL) Private Member { - + // @access Protected Member +protected: // @cmember:(INTERNAL) Array di codice TCodearray _code; // @cmember:(INTERNAL) Array di variabili @@ -431,7 +437,7 @@ protected: // @cmember Esegue la compilazione di un una funzione TCodesym __function(int nparms = -1, bool fixed_num = TRUE); // @cmember Compila l'espressione - bool compile(const char* expression, TTypeexp type); + bool compile(const TString& expression, TTypeexp type); protected: // TObject // @cmember Stampa l'espressione su

(serve per implementare l'insertore) @@ -488,7 +494,7 @@ public: bool set(const char* expression, TTypeexp type = _numexpr); const char* last_token() const; // @cmember Ritorna l'espressione originale - const char * string() const { return _original; } + const char* string() const { return _original; } // @cmember Ritorna eventuali errori int error() {return _error;} diff --git a/include/golem.cpp b/include/golem.cpp index 2cf1b182b..818916caf 100755 --- a/include/golem.cpp +++ b/include/golem.cpp @@ -1,4 +1,5 @@ #define STRICT +#define WIN32_EXTRA_LEAN #define XVT_INCL_NATIVE #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include @@ -660,9 +662,37 @@ TGolem_field::~TGolem_field() { } /////////////////////////////////////////////////////////// -// Mail message +// MAPI session /////////////////////////////////////////////////////////// +class TMAPI_session : public TObject +{ + HINSTANCE _hlibMAPI; + LHANDLE _hSession; + LONG _hWnd; + +protected: + bool load_mapi(); + void unload_mapi(); + +public: + operator LHANDLE() const { return _hSession; } + LONG hWnd() const { return _hWnd; } + + bool open(); + + bool send(MapiMessage& msg, FLAGS flags = MAPI_DIALOG); + bool remove(const TString& id); + + void close(); + + virtual bool ok() const + { return _hlibMAPI != NULL && _hSession != NULL; } + + TMAPI_session(); + virtual ~TMAPI_session(); +}; + #ifdef _WIN32 const char* const szMAPIDLL = "MAPI32.DLL"; const int MAPI_USE_DEFAULT = 0; @@ -670,8 +700,6 @@ TGolem_field::~TGolem_field() const char* const szMAPIDLL = "MAPI.DLL"; #endif -static HINSTANCE _hlibMAPI = NULL; - LPMAPILOGON lpfnMAPILogon = NULL; LPMAPILOGOFF lpfnMAPILogoff = NULL; LPMAPISENDMAIL lpfnMAPISendMail = NULL; @@ -685,7 +713,7 @@ LPMAPIADDRESS lpfnMAPIAddress = NULL; LPMAPIDETAILS lpfnMAPIDetails = NULL; LPMAPIRESOLVENAME lpfnMAPIResolveName = NULL; -bool TMail_message::load_mapi(void) +bool TMAPI_session::load_mapi() { if (_hlibMAPI) // Check in already loaded return TRUE; @@ -719,84 +747,160 @@ bool TMail_message::load_mapi(void) return TRUE; } -void TMail_message::unload_mapi() +void TMAPI_session::unload_mapi() { - if (_hlibMAPI) + if (_hlibMAPI) { FreeLibrary(_hlibMAPI); _hlibMAPI = NULL; } } -bool TMail_message::send() -{ - TWait_cursor hourglass; - bool ok = load_mapi(); - if (!ok) - return error_box("Impossibile inizializzare MAPI"); - - LHANDLE lhSession = 0; - ULONG err = lpfnMAPILogon(0L, "", "", - MAPI_LOGON_UI | MAPI_USE_DEFAULT, - 0L, &lhSession); - if (err == SUCCESS_SUCCESS) - { - const int MAX_RECIPIENTS = _recipients.items() + _copy_recipients.items() + 1; - MapiRecipDesc* msgRecipient = new MapiRecipDesc[MAX_RECIPIENTS]; - memset(msgRecipient, 0, MAX_RECIPIENTS*sizeof(MapiRecipDesc)); - - int nr = 0; - if (_sender.not_empty()) - { - msgRecipient[nr].ulRecipClass = MAPI_ORIG; - msgRecipient[nr++].lpszName = _sender.get_buffer(); - } - FOR_EACH_ARRAY_ROW(_recipients, rec, recipient) - { - msgRecipient[nr].ulRecipClass = MAPI_TO; - msgRecipient[nr++].lpszName = recipient->get_buffer(); - } - FOR_EACH_ARRAY_ROW(_copy_recipients, cc_rec, cc_recipient) - { - msgRecipient[nr].ulRecipClass = MAPI_CC; - msgRecipient[nr++].lpszName = cc_recipient->get_buffer(); - } - - const int MAX_ATTACHMENTS = _attachments.items() + 1; - MapiFileDesc* msgAttachment = new MapiFileDesc[MAX_ATTACHMENTS]; - memset(msgAttachment, 0, MAX_ATTACHMENTS*sizeof(MapiFileDesc)); - int na = 0; - FOR_EACH_ARRAY_ROW(_attachments, att, attachment) - { - TString80 tmp; tmp.spaces(32); - *this << '\n' << tmp; - msgAttachment[na].nPosition = len()-1; - msgAttachment[na++].lpszPathName = attachment->get_buffer(); - } +bool TMAPI_session::open() +{ + if (_hSession == NULL) + { + TWait_cursor hourglass; + if (!load_mapi()) + return error_box("Impossibile inizializzare MAPI"); - MapiMessage msgSend; - memset(&msgSend, 0, sizeof(MapiMessage)); - msgSend.lpszNoteText = get_buffer(); - msgSend.lpszSubject = _subject.get_buffer(); - msgSend.nRecipCount = nr; - msgSend.lpRecips = msgRecipient; - msgSend.nFileCount = na; - msgSend.lpFiles = msgAttachment; - - err = lpfnMAPISendMail(lhSession, 0, &msgSend, MAPI_DIALOG, 0L); - - delete msgRecipient; - delete msgAttachment; + FLAGS flags = MAPI_USE_DEFAULT | MAPI_LOGON_UI; + ULONG err = lpfnMAPILogon(_hWnd, "", "", flags, 0L, &_hSession); - err = lpfnMAPILogoff(lhSession, 0L, 0L, 0L); + if (err != SUCCESS_SUCCESS) + return error_box("Impossibile collegarsi a MAPI: %lu", err); + + _hWnd = xvt_vobj_get_attr(cur_win(), ATTR_NATIVE_WINDOW); + } + return TRUE; +} + +void TMAPI_session::close() +{ + if (_hlibMAPI) + { + if (_hSession) + { + lpfnMAPILogoff(_hSession, _hWnd, 0L, 0L); + _hSession = NULL; + } + unload_mapi(); + } +} + +bool TMAPI_session::send(MapiMessage& msg, FLAGS flags) +{ + bool ok = FALSE; + if (open()) + { + LONG err = lpfnMAPISendMail(_hSession, _hWnd, &msg, flags, 0L); + if (err == SUCCESS_SUCCESS) + ok = TRUE; + else + error_box("Can't send mail message: %ld", err); } - else - ok = error_box("Impossibile collegarsi a MAPI"); - - unload_mapi(); return ok; } +bool TMAPI_session::remove(const TString& id) +{ + bool ok = FALSE; + if (open()) + { + LONG err = lpfnMAPIDeleteMail(_hSession, _hWnd, + (char*)(const char*)id, 0L, 0L); + if (err == SUCCESS_SUCCESS) + ok = TRUE; + else + error_box("Can't delete mail message: %ld", err); + } + return ok; +} + +TMAPI_session::TMAPI_session() + : _hlibMAPI(NULL), _hSession(NULL), _hWnd(NULL) +{ } + +TMAPI_session::~TMAPI_session() +{ close(); } + +/////////////////////////////////////////////////////////// +// TMail_message +/////////////////////////////////////////////////////////// + +bool TMail_message::send(TMAPI_session& lhSession, bool hide_ui) +{ + const int MAX_RECIPIENTS = _recipients.items() + _copy_recipients.items() + 1; + MapiRecipDesc* msgRecipient = new MapiRecipDesc[MAX_RECIPIENTS]; + memset(msgRecipient, 0, MAX_RECIPIENTS*sizeof(MapiRecipDesc)); + + int nr = 0; + if (_sender.not_empty()) + { + msgRecipient[nr].ulRecipClass = MAPI_ORIG; + msgRecipient[nr++].lpszName = _sender.get_buffer(); + } + FOR_EACH_ARRAY_ROW(_recipients, rec, recipient) + { + msgRecipient[nr].ulRecipClass = MAPI_TO; + msgRecipient[nr].lpszName = recipient->get_buffer(); + nr++; + } + FOR_EACH_ARRAY_ROW(_copy_recipients, cc_rec, cc_recipient) + { + msgRecipient[nr].ulRecipClass = MAPI_CC; + msgRecipient[nr].lpszName = cc_recipient->get_buffer(); + nr++; + } + + const int MAX_ATTACHMENTS = _attachments.items() + 1; + MapiFileDesc* msgAttachment = new MapiFileDesc[MAX_ATTACHMENTS]; + memset(msgAttachment, 0, MAX_ATTACHMENTS*sizeof(MapiFileDesc)); + int na = 0; + FOR_EACH_ARRAY_ROW(_attachments, att, attachment) + { + TString80 tmp; tmp.spaces(32); + *this << '\n' << tmp; + msgAttachment[na].nPosition = len()-1; + msgAttachment[na].lpszPathName = attachment->get_buffer(); + na++; + } + + MapiMessage msgSend; + memset(&msgSend, 0, sizeof(MapiMessage)); + msgSend.lpszNoteText = empty() ? NULL : get_buffer(); + msgSend.lpszSubject = _subject.empty() ? NULL : _subject.get_buffer(); + msgSend.nRecipCount = nr; + msgSend.lpRecips = nr == 0 ? NULL : msgRecipient; + msgSend.nFileCount = na; + msgSend.lpFiles = na == 0 ? NULL : msgAttachment; + + bool ok = lhSession.send(msgSend, hide_ui ? 0 : MAPI_DIALOG); + + delete msgRecipient; + delete msgAttachment; + + return ok; +} + +bool TMail_message::send(bool hide_ui) +{ + TMAPI_session lhSession; // Open MAPI session + return send(lhSession, hide_ui); +} + +bool TMail_message::remove(TMAPI_session& lhSession) +{ + bool ok = _id.not_empty() && lhSession.remove(_id); + return ok; +} + +bool TMail_message::remove() +{ + TMAPI_session lhSession; // Open MAPI session + return remove(lhSession); +} + bool TMail_message::add_recipient_ex(const char* recipient, int type) { TFilename rec(recipient); @@ -821,13 +925,147 @@ bool TMail_message::add_recipient_ex(const char* recipient, int type) return ok; } +// Certified 99% +void TMail_message::set_date_time(const char* str) +{ + if (str == NULL) + str = ""; + + int anno, mese, giorno; + int ora = 12, minuto = 0, secondo = 0; + const int num = sscanf(str, "%d/%d/%d %d:%d:%d", + &anno, &mese, &giorno, &ora, &minuto, &secondo); + if (num >= 3) + { + _date = TDate(giorno, mese, anno); + _hms = ora*10000L + minuto*100L + secondo; + } + else + { + _date = TODAY; + _hms = 0; + } +} + +// Certified 100% +const TString& TMail_message::recipient(int n) const +{ + if (n >= 0 && n < recipients()) + return _recipients.row(n); + return EMPTY_STRING; +} + TMail_message::TMail_message(const char* recipient, const char* subject, const char* text, const char* sender) - : TString(text), _subject(subject), _sender(sender) + : TString(text), _subject(subject), _sender(sender), _hms(0) { add_recipient(recipient); } +/////////////////////////////////////////////////////////// +// TMail_messages +/////////////////////////////////////////////////////////// + +TMail_messages::TMail_messages() +{ } + +int TMail_messages::get(const char* senderFilter, + const char* subjectFilter, + const char* bodyFilter, + bool attach, bool mark) +{ + TMAPI_session lhSession; + if (!lhSession.open()) + return 0; + + TString str_msg_id(512); // Accept MAPI_LONG_MSGID + char* msg_id = str_msg_id.get_buffer(); + + LONG err = lpfnMAPIFindNext(lhSession, lhSession.hWnd(), NULL, NULL, + MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID, + 0, msg_id); + + FLAGS flags = 0; + if (!mark) flags |= MAPI_PEEK; + if (!attach) flags |= MAPI_SUPPRESS_ATTACH; + + while (err == SUCCESS_SUCCESS) + { + MapiMessage FAR* pMessage = NULL; + err = lpfnMAPIReadMail(lhSession, lhSession.hWnd(), msg_id, + flags, 0, &pMessage); + + if (err == SUCCESS_SUCCESS) + { + const char* id = NULL; + const char* sender = NULL; + const char* subject = NULL; + const char* body = NULL; + const char* recipient = NULL; + + bool should_add = TRUE; + if (should_add) + { + const MapiRecipDesc* pSender = pMessage->lpOriginator; + sender = pSender->lpszName; + if (senderFilter && *senderFilter) + should_add = stricmp(senderFilter, sender) == 0; + } + + if (should_add) + { + subject = pMessage->lpszSubject; + if (subjectFilter && *subjectFilter) + { + const unsigned lenFilter = strlen(subjectFilter); + should_add = strncmp(subject, subjectFilter, lenFilter) == 0; + } + } + + if (should_add) + { + body = pMessage->lpszNoteText; + if (bodyFilter && *bodyFilter) + should_add = strstr(body, bodyFilter) != NULL; + } + + if (should_add) + { + TMail_message* msg = new TMail_message(recipient, subject, body, sender); + msg->set_date_time(pMessage->lpszDateReceived); + msg->set_id(msg_id); + add(msg); + } + + lpfnMAPIFreeBuffer(pMessage); + } + + err = lpfnMAPIFindNext(lhSession, lhSession.hWnd(), NULL, + msg_id, MAPI_LONG_MSGID, 0, msg_id); + } + + return items(); +} + +bool TMail_messages::send(bool hide_ui) +{ + TMAPI_session lhSession; + bool ok = TRUE; + for (int i = 0; i < items(); i++) + ok &= msg(i).send(lhSession, hide_ui); + return ok; +} + +bool TMail_messages::remove() +{ + TMAPI_session lhSession; + bool ok = TRUE; + for (int i = 0; ok && i < items(); i++) + ok &= msg(i).remove(lhSession); + return ok; +} + + /////////////////////////////////////////////////////////// // Obsolete DDE management /////////////////////////////////////////////////////////// diff --git a/include/golem.h b/include/golem.h index aaa433f7c..d109fbe20 100755 --- a/include/golem.h +++ b/include/golem.h @@ -1,6 +1,10 @@ #ifndef __GOLEM_H #define __GOLEM_H +#ifndef __DATE_H +#include +#endif + #ifndef __STRINGS_H #include #endif @@ -9,17 +13,23 @@ bool goto_url(const char* url); bool edit_url(const char* url); bool print_url(const char* url); +class TMAPI_session; + class TMail_message : public TString { TString_array _recipients, _copy_recipients, _attachments; TString _subject; TString _sender; + TString _id; + TDate _date; + long _hms; protected: - bool load_mapi(); - void unload_mapi(); - bool add_recipient_ex(const char* recipient, int type); + +public: // Semiprotected: You don't have access to TMAPI_session + bool send(TMAPI_session& lhSession, bool hide_ui = FALSE); + bool remove(TMAPI_session& lhSession); public: bool add_recipient(const char* address) { return add_recipient_ex(address, 0); } @@ -27,17 +37,49 @@ public: bool add_copy_recipient(const char* address) { return add_recipient_ex(address, 1); } bool attach(const char* filename) { return add_recipient_ex(filename, 2); } void set_sender(const char* address) { _sender = address; _sender.trim(); } + void set_id(const char* id) { _id = id; } TString& operator = (const char* msg) { set(msg); return *this; } TString& operator = (const TString& msg) { set(msg); return *this; } - bool send(); + bool send(bool hide_ui = FALSE); + bool remove(); + + const TString& sender() const { return _sender; } + const TString& subject() const { return _subject; } + const TString& id() const { return _id; } + + void set_date_time(const char* date_time); + const TDate& date() const { return _date; } + long time() const { return _hms; } + + int recipients() const { return _recipients.items(); } + const TString& recipient(int n = 0) const; - TMail_message(const char* recipient, const char* subject = NULL, + TMail_message(const char* recipient = NULL, const char* subject = NULL, const char* text = NULL, const char* sender = NULL); virtual ~TMail_message() { } }; +class TMail_messages : public TArray +{ +public: + int get(const char* sender = NULL, const char* subject = NULL, + const char* body = NULL, bool attachments = FALSE, bool mark_as_read = FALSE); + + bool send(bool hide_ui = TRUE); + bool remove(); + + TMail_message& msg(int i) + { return (TMail_message&)(*this)[i]; } + + const TMail_message& msg(int i) const + { return (const TMail_message&)(*this)[i]; } + + TMail_messages(); + virtual ~TMail_messages() { } +}; + // @doc EXTERNAL // @class TDDE | Classe per la gestione del DDE diff --git a/include/isam.cpp b/include/isam.cpp index 6316b5f1f..c32426d79 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -1192,6 +1192,35 @@ bool TBaseisamfile::is_changed_since(long clk) const return clk < last; } +struct TCallbackFileinfo +{ + TString16 _var; + TFilename _app; +}; + +HIDDEN int find_relapp(TConfig& cfg, void* jolly) +{ + TCallbackFileinfo& info = *((TCallbackFileinfo*)jolly); + if (cfg.exist(info._var)) + { + info._app = cfg.get(info._var); + return info._app.not_empty(); + } + return FALSE; +} + +bool TBaseisamfile::get_relapp(TString& app) const +{ + TConfig ini("install.ini"); + TCallbackFileinfo fi; + fi._var.format("Edit_%d", num()); + ini.for_each_paragraph(find_relapp, &fi); + if (fi._app.not_empty()) + app = fi._app; + return app.not_empty(); +} + + /////////////////////////////////////////////////////////// // TLocalisamfile /////////////////////////////////////////////////////////// @@ -2372,7 +2401,7 @@ TRectype::TRectype(const TRectype& r) { if (r._memo_data) { - init_memo(); + init_memo(r._memo_recno); // ?? *_memo_data = *r._memo_data; CHECK(r._memo_dirty, "memo_dirty NULL con memo_data valido"); *_memo_dirty= *r._memo_dirty; diff --git a/include/isam.h b/include/isam.h index 608136618..0219383a4 100755 --- a/include/isam.h +++ b/include/isam.h @@ -284,7 +284,6 @@ protected: // @access Protected Member protected: // @cmember:(INTERNAL) IO su file: -// int _next(word lockop = _nolock); virtual int _read(TRectype& rec, word op = _isequal, word lockop = _nolock); virtual int _readat(TRectype& rec, TRecnotype nrec, word lockop = _nolock); virtual int _write(const TRectype& rec); @@ -497,6 +496,8 @@ public: TRectype& operator =(const TRectype& rec) { return curr() = rec;} + virtual bool get_relapp(TString& app) const; + // @cmember Notifica che il file e' stato modificato void notify_change() const; // @cmember Testa se il file e' cambiato dal ciclo di clock

diff --git a/include/isamrpc.cpp b/include/isamrpc.cpp index 334be9abc..d0c4f6b8f 100755 --- a/include/isamrpc.cpp +++ b/include/isamrpc.cpp @@ -4,9 +4,6 @@ #include #define NO_MFC -#define CObject TObject -#define CString TString -#define CStringArray TString_array #include static TSocketClient* _client = NULL; @@ -317,8 +314,8 @@ bool http_dir(const char* server, const char* remote_dir, TString_array& list) bool ok = connection != 0; if (ok) { - ok = client.HttpGetDir(remote_dir, list) != 0; - client.RemoveConnection(connection); + ok = client.HttpGetDir(remote_dir, list) != 0; + client.RemoveConnection(connection); } return ok; diff --git a/include/maskfld.cpp b/include/maskfld.cpp index add0e0b59..72a1287ff 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -1397,8 +1397,10 @@ void TEditable_field::show(bool on) void TEditable_field::set_prompt(const char* p) { - CHECKD(_prompt, "Can't set prompt to control", dlg()); - _prompt->set_caption(p); + if (_prompt) + _prompt->set_caption(p); + else + NFCHECK("Can't set prompt to control %d", dlg()); } // Certified 90% @@ -2184,6 +2186,7 @@ bool TBrowse::do_link(bool insert) if (_insert[0] == 'M') { +/* TString nm(_insert.mid(1)); if (nm.compare("tb", 2, TRUE) == 0) // Programma gestione tabelle { @@ -2205,6 +2208,8 @@ bool TBrowse::do_link(bool insert) app = "ba3 -3 "; app << nm << ' ' << _cursor->file().num(); } +*/ + _cursor->file().get_relapp(app); } else { @@ -2575,9 +2580,12 @@ KEY TFile_select::run() return good ? K_ENTER : K_ESC; } -bool TFile_select::check(CheckTime) +bool TFile_select::check(CheckTime ct) { const TFilename name = field().get(); + if (ct != STARTING_CHECK && name.empty() && + field().check_type() == CHECK_REQUIRED) + return FALSE; bool ok = _filter.empty() || name.match(_filter); if (ok && field().roman()) // Must exist ok = name.exist(); @@ -4292,6 +4300,13 @@ const char* TMemo_field::reformat(const char* data) const const char* TMemo_field::raw2win(const char* data) const { +#ifdef XI_R4 + if (strchr(data, '\r') == NULL) + return data; + TString& s = _ctl_data._park; + s = data; + s.replace('\r', '\n'); +#else if (strchr(data, '\n') == NULL) return data; @@ -4299,17 +4314,22 @@ const char* TMemo_field::raw2win(const char* data) const s = data; for (int i = 0; s[i]; i++) if (s[i] == '\n') s[i] = '\r'; +#endif return s; } const char* TMemo_field::win2raw(const char* data) const { +#ifdef XI_R4 + return data; +#else 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; +#endif } bool TMemo_field::on_key(KEY k) diff --git a/include/maskfld.h b/include/maskfld.h index d170bbb42..27a3519be 100755 --- a/include/maskfld.h +++ b/include/maskfld.h @@ -949,6 +949,8 @@ public: // @cmember Controlla la validita' del campo virtual bool check(CheckTime = RUNNING_CHECK); + virtual bool is_filesel() const { return TRUE; } + TFile_select(TEdit_field* ef, const char* filter); virtual ~TFile_select() { } }; diff --git a/include/msksheet.cpp b/include/msksheet.cpp index 1bfeb9fb5..8d4f9815a 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -199,6 +199,8 @@ public: // @cmember Permette di invertire la posizione di due righe void swap_rows(const int fromindex, const int toindex); + // @cmember L'utente ha salvato la disposizione delle colonne? + bool user_saved_columns_order() const; // @cmember Salva la disposizione delle colonne void save_columns_order() const; // @cmember Salva la disposizione delle colonne @@ -723,7 +725,7 @@ int TSpreadsheet::insert( if (ok) { - TToken_string* toktok = new TToken_string(80); + TToken_string* toktok = new TToken_string(80, owner().separator()); r = _str.insert(toktok, rec); _property.insert(NULL, r, TRUE); // Crea lo spazio necessario per le proprieta' @@ -1948,6 +1950,15 @@ HIDDEN TFilename& field2parag(const TMask_field& f, TFilename& name) return name; } +bool TSpreadsheet::user_saved_columns_order() const +{ + TFilename parag; field2parag(owner(), parag); + TConfig config(CONFIG_USER, parag); // Apre il file di configurazione + const int index = owner().dlg(); + TToken_string order = config.get("Browse", NULL, index); + return !order.empty_items(); +} + void TSpreadsheet::save_columns_order() const { if (_save_columns_order) @@ -2142,8 +2153,9 @@ KEY TSpreadsheet::edit(int n) // Certified 100% TSheet_field::TSheet_field(TMask* m) : TLoadable_field(m), _append(TRUE), - _enable_autoload(FALSE),_sheetfile(NULL),_linee_rec(NULL),_external_record(FALSE), - _userput(NULL),_userget(NULL) + _enable_autoload(FALSE),_sheetfile(NULL),_linee_rec(NULL), + _external_record(FALSE), _userput(NULL),_userget(NULL), + _separator('|') { } @@ -2211,9 +2223,17 @@ bool TSheet_field::parse_item(TScanner& scanner) if (scanner.key() == "FL") // FLAGS { - TString16 flags(scanner.string()); - _enable_autoload=(flags.find("A")>=0); - _append=(flags.find("I")<0); + const char* flags = scanner.string(); + for (const char* f = flags; *f; f++) + { + switch(*f) + { + case 'A': _enable_autoload = TRUE; break; + case 'I': _append = FALSE; break; + case '|': _separator = '¦'; break; + default : break; + } + } return TRUE; } if (scanner.key() == "US") // USE @@ -2343,7 +2363,7 @@ TToken_string& TSheet_field::row( { if (n < 0) n = first_empty(); if (n >= max) - n = (int)s->add(new TToken_string(80)); + n = (int)s->add(new TToken_string(80, _separator)); } return s->row(n); } @@ -2477,6 +2497,18 @@ void TSheet_field::swap_columns(const int fromid, const int toid) const s->swap_columns(fromid, toid); } +bool TSheet_field::user_saved_columns_order() const +{ + TSpreadsheet* s = (TSpreadsheet*)_ctl; + return s->user_saved_columns_order(); +} + +void TSheet_field::set_columns_order(TToken_string* order) +{ + TSpreadsheet* s = (TSpreadsheet*)_ctl; + s->set_columns_order(order); +} + void TSheet_field::swap_rows( const int fromindex, const int toindex) { TSpreadsheet* s = (TSpreadsheet*)_ctl; diff --git a/include/msksheet.h b/include/msksheet.h index 3d485fca5..2962d8b4e 100755 --- a/include/msksheet.h +++ b/include/msksheet.h @@ -49,6 +49,9 @@ class TSheet_field : public TLoadable_field // @cmember:(INTERNAL) Indica se aggiungere a fondo dello spreadsheet o nella riga in cui ti trovi bool _append; + // @cmember:(INTERNAL) Separatore delle TToken_string + char _separator; + // @cmember:(INTERNAL) Flag di autoload bool _enable_autoload; // @cmember:(INTERNAL) Campi di input sulla maschera (key field names) @@ -136,6 +139,8 @@ public: const char* cell(int r, int c) { const char*v=row(r).get(c); return v ? v: " "; } + char separator() const { return _separator; } + // @cmember Ritorna la prima riga vuota nello spreadsheet int first_empty() const; // @cmember Ritorna il numero di righe presenti nello spreadsheet @@ -198,6 +203,11 @@ public: // @cmember Permette di invertire la posizione di due righe void swap_rows( const int fromindex, const int toindex ) ; + // @cmember Controlla se l'utente ha salvato la disposizione delle colonne + bool user_saved_columns_order() const; + // @cmember Setta la disposizione delle colonne + void set_columns_order(TToken_string* order = NULL); + // @cmember Setta la larghezza della colonna void set_column_width( const int col, const int width ) const; // @cmember Setta il titolo della colonna diff --git a/include/netsock.cpp b/include/netsock.cpp index 09eca972b..cabb9a211 100755 --- a/include/netsock.cpp +++ b/include/netsock.cpp @@ -516,14 +516,25 @@ TConnection* TSocketClient::OnQueryConnection(const char* service, TConnection* pConnection = NULL; if (cur_socket == NULL) - { + { + int porta = service != NULL ? atoi(service) : 0; + TString strServer = server; - if (strServer.compare("http://", 7, TRUE) == 0) - strServer.ltrim(7); + int pos = strServer.find("://"); + if (pos > 0) + strServer.ltrim(pos+3); + + pos = strServer.rfind(':'); + if (pos > 0) + { + porta = atoi(strServer.mid(pos+1)); + strServer.cut(pos); + } + if (strServer.empty() || stricmp(strServer, "localhost") == 0) strServer = "127.0.0.1"; - cur_socket = new skstream(strServer, (skstream::service)atoi(service)); + cur_socket = new skstream(strServer, (skstream::service)porta); if (cur_socket->is_open()) pConnection = OnCreateConnection((DWORD)cur_socket); @@ -586,35 +597,51 @@ BYTE* TSocketClient::GetBuffer(DWORD& dwSize) return m_pData; } -BOOL TSocketClient::HttpGetFile(const char* remote, const char* local) +BOOL TSocketClient::WriteLine(DWORD, const char* str) { if (!cur_socket->is_open()) return FALSE; - + + if (str && *str) + { + cur_socket->sync(); + cur_socket->write(str, strlen(str)); + cur_socket->flush(); + } + + return cur_socket->good(); +} + +BOOL TSocketClient::ReadLine(DWORD, TString& str) +{ + char *buf = str.get_buffer(4096); + cur_socket->getline(buf, str.size(), '\n'); + return TRUE; +} + +BOOL TSocketClient::HttpGetFile(const char* remote, const char* local) +{ BOOL ok = FALSE; - TString buf(4096); + TString buf; buf << "GET " << remote << " HTTP/1.0\r\n\r\n"; - cur_socket->sync(); - cur_socket->write(buf, buf.len()); - cur_socket->flush(); - if (cur_socket->good()) + if (WriteLine(0, buf)) { const clock_t start = clock(); long size = 0; for (int r = 0; !cur_socket->eof(); r++) { - cur_socket->getline(buf.get_buffer(), buf.size(), '\n'); + ReadLine(0, buf); if (buf.blank()) break; if (r == 0 && buf.find("404") > 0) return FALSE; // File not found if (buf.compare("Content-length:", 15, TRUE) == 0) { - const int colon = buf.find(':'); - size = atol(buf.mid(colon+1)); + const int colon = buf.find(':'); + size = atol(buf.mid(colon+1)); } } ofstream outfile(local, ios::out | ios::binary); @@ -676,7 +703,7 @@ BOOL TSocketClient::HttpGetDir(const char* remote, TString_array& list) if (ok) { ifstream s(local); - TString riga(1024); + TString riga; while (!s.eof()) { s.getline(riga.get_buffer(), riga.size()); diff --git a/include/netsock.h b/include/netsock.h index edb124e68..f0fa8d719 100755 --- a/include/netsock.h +++ b/include/netsock.h @@ -53,6 +53,9 @@ public: virtual void ReleaseBuffer(); virtual BOOL IsOk() const { return TRUE; } + BOOL WriteLine(DWORD id, const char* str); + BOOL ReadLine(DWORD id, TString& str); + BOOL HttpGetFile(const char* remote, const char* local); BOOL HttpGetDir(const char* remote, TString_array& list); diff --git a/include/netutils.h b/include/netutils.h index 8b3fae653..35b36d8e8 100755 --- a/include/netutils.h +++ b/include/netutils.h @@ -5,6 +5,9 @@ #define BOOL int #define BYTE unsigned char #define DWORD unsigned long +#define CObject TObject +#define CString TString +#define CStringArray TString_array #include "assoc.h" #endif diff --git a/include/os_dep.h b/include/os_dep.h index 6745ae8f1..f2d4b9ca4 100755 --- a/include/os_dep.h +++ b/include/os_dep.h @@ -9,7 +9,7 @@ #include #endif -enum os_type { os_Unknown, os_Windows, os_Win32s, os_Windows95, os_WindowsNT }; +enum os_type { os_Unknown, os_Windows, os_Win32s, os_Windows95, os_Windows98, os_WindowsNT }; os_type os_get_type(); void os_post_menu_event(WINDOW win, MENU_TAG tag); diff --git a/include/os_win16.cpp b/include/os_win16.cpp index d0f78011c..6b4496442 100755 --- a/include/os_win16.cpp +++ b/include/os_win16.cpp @@ -592,12 +592,12 @@ void os_set_event_hook() long twin_style = WSF_ICONIZABLE | WSF_CLOSE | WSF_SIZE; const int scx = GetSystemMetrics(SM_CXSCREEN); - if (scx == 640 && os_get_type() == os_Windows95) + static RCT rct; + if (scx <= 640 && os_get_type() >= os_Windows95) { const int scy = GetSystemMetrics(SM_CYSCREEN); const int bcx = GetSystemMetrics(SM_CXFRAME); const int bcy = GetSystemMetrics(SM_CYFRAME); - static RCT rct; rct.left = -bcx; rct.top = GetSystemMetrics(SM_CYCAPTION)-bcy-1; rct.right = scx+bcx; @@ -605,7 +605,20 @@ void os_set_event_hook() xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); } else - twin_style |= WSF_MAXIMIZED; + { + TConfig cfg(CONFIG_USER, "Colors"); + const int res = cfg.get_int("Resolution"); + if (res >= 640 && res < scx) + { + rct.left = 0; + rct.top = GetSystemMetrics(SM_CYCAPTION); + rct.right = res + 2*GetSystemMetrics(SM_CXFRAME); + rct.bottom = (res * 3) / 4 + 2*GetSystemMetrics(SM_CYFRAME); + xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); + } + else + twin_style |= WSF_MAXIMIZED; + } xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, twin_style); } diff --git a/include/os_win32.cpp b/include/os_win32.cpp index b68bf6e61..9ce80c416 100755 --- a/include/os_win32.cpp +++ b/include/os_win32.cpp @@ -1,5 +1,5 @@ #define XVT_INCL_NATIVE -#define WIN32_EXTRA_LEAN +#define WIN32_LEAN_AND_MEAN #include #include @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -429,12 +430,12 @@ void os_set_event_hook() long twin_style = WSF_ICONIZABLE | WSF_CLOSE | WSF_SIZE; const int scx = GetSystemMetrics(SM_CXSCREEN); - if (scx == 640) + static RCT rct; + if (scx <= 640 && os_get_type() >= os_Windows95) { const int scy = GetSystemMetrics(SM_CYSCREEN); const int bcx = GetSystemMetrics(SM_CXFRAME); const int bcy = GetSystemMetrics(SM_CYFRAME); - static RCT rct; rct.left = -bcx; rct.top = GetSystemMetrics(SM_CYCAPTION)-bcy-1; rct.right = scx+bcx; @@ -442,7 +443,20 @@ void os_set_event_hook() xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); } else - twin_style |= WSF_MAXIMIZED; + { + TConfig cfg(CONFIG_USER, "Colors"); + const int res = cfg.get_int("Resolution"); + if (res >= 640 && res < scx) + { + rct.left = 0; + rct.top = GetSystemMetrics(SM_CYCAPTION); + rct.right = res + 2*GetSystemMetrics(SM_CXFRAME); + rct.bottom = (res * 3) / 4 + 2*GetSystemMetrics(SM_CYFRAME); + xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); + } + else + twin_style |= WSF_MAXIMIZED; + } xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, twin_style); } diff --git a/include/postman.cpp b/include/postman.cpp new file mode 100755 index 000000000..f40f00a38 --- /dev/null +++ b/include/postman.cpp @@ -0,0 +1,401 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////// +// TRecipient +/////////////////////////////////////////////////////////// + +class TRecipient : public TObject +{ + TString _address; + TString _group; + TString _expr; + +public: + const TString& address() const { return _address; } + const TString& group() const { return _group; } + void add_expr(char op, const TString& expr); + bool can_receive(const TRectype& rec) const; + + virtual bool ok() const + { return _address.not_empty() && _expr.not_empty(); } + + TRecipient(const TToken_string& str); + virtual ~TRecipient() { } +}; + +TRecipient::TRecipient(const TToken_string& str) +{ + str.get(0, _address); + str.get(1, _group); +} + +void TRecipient::add_expr(char op, const TString& expr) +{ + if (_expr.not_empty()) + _expr << (op == 'A' ? "AND" : "OR"); + + if (expr.blank()) + _expr << 1; + else + _expr << '(' << expr << ')'; +} + +bool TRecipient::can_receive(const TRectype& rec) const +{ + TExpression e(_expr, _strexpr, TRUE); + for (int v = 0; v < e.numvar(); v++) + { + const char* name = e.varname(v); + if (rec.exist(name)) + e.setvar(name, rec.get(name)); + else + e.setvar(name, ""); + } + bool yes = e.as_bool(); + return yes; +} + +/////////////////////////////////////////////////////////// +// TPostman +/////////////////////////////////////////////////////////// + +class TPostman : public TObject +{ + long _firm; + bool _recipients_ok; + TArray _recipient; + TAssoc_array _expr; + +protected: + void test_firm(); + + TRecipient& recipient(int r) const + { return (TRecipient&)_recipient[r]; } + + void add_expr(const TString& addr, + char op, const TString& expr); + + void load_filters(); + +public: + bool can_dispatch_transaction(const TRectype& rec); + bool dispatch_transaction(const TRectype& rec, + const TFilename& name); + + TExpression* get_filter_expr(const char* flt); + const char* get_filter(const char* flt); + bool user_can(const char* flt, const TRelation* rel); + + TPostman(); + virtual ~TPostman() { } +}; + +void TPostman::test_firm() +{ + const long firm = prefix().get_codditta(); + if (firm != _firm) + { + _firm = firm; + _recipients_ok = FALSE; + } +} + +void TPostman::add_expr(const TString& addr, + char op, const TString& expr) +{ + for (int r = _recipient.last(); r >= 0; r--) + { + TRecipient& rec = recipient(r); + if (rec.address() == addr) + { + rec.add_expr(op, expr); + break; + } + else + { + if (rec.group() == addr) + rec.add_expr(op, expr); + } + } +} + +bool TPostman::can_dispatch_transaction(const TRectype& rec) +{ + test_firm(); + if (!_recipients_ok) + { + _recipients_ok = TRUE; + _recipient.destroy(); + + TConfig cfg(CONFIG_DITTA, "MailTransactions"); + TToken_string str; + TString addr, opr, expr; + + // Costruisce la lista dei destinatari + for (int r = 0; cfg.exist("Recipient", r); r++) + { + str = cfg.get("Recipient", NULL, r); + TRecipient* rcp = new TRecipient(str); + _recipient.add(rcp); + } + + // Costruisce i filtri per i destinatari + for (int f = 0; cfg.exist("Filter", f); f++) + { + str = cfg.get("Filter", NULL, f); + const int num = str.get_int(1); + if (num != rec.num()) continue; + + str.get(0, addr); + str.get(2, opr); + str.get(3, expr); + add_expr(addr, opr[0], expr); + } + + // Elimina destinatari inutili + for (int d = _recipient.last(); d >= 0; d--) + { + if (!recipient(d).ok()) + _recipient.destroy(d, TRUE); + } + } + return _recipient.items() > 0; +} + +bool TPostman::dispatch_transaction(const TRectype& rec, + const TFilename& name) +{ + bool ok = can_dispatch_transaction(rec); + if (ok) + { + TToken_string dest; + for (int r = 0; r < _recipient.items(); r++) + { + const TRecipient& a = recipient(r); + if (a.can_receive(rec)) + dest.add(a.address()); + } + + ok = dest.items() > 0; + if (ok) + { + TMail_message msg(dest.get(0)); + for (const char* r = dest.get(1); r; r = dest.get()) + msg.add_copy_recipient(r); + + TScanner trans(name); + while (trans.good()) + { + TString& line = trans.line(); + msg << line << '\n'; + } + ok = msg.send(TRUE); + } + } + return ok; +} + +void TPostman::load_filters() +{ + TRecord_cache users(LF_USER); + TToken_string perm(4096, '\n'); + TAuto_token_string row(80); + + // Costruisce il nome dell'applicazione principale + TFilename app(main_app().argv(0)); + app.ext(""); + app = app.name(); + + for (int a = 1; a < main_app().argc(); a++) + { + row = main_app().argv(a); + if (row[0] != '/') + app << ' ' << row; + else + break; + } + + // Stringhe delle espressioni i filtro + TAssoc_array expr; + + // Scandisce l'albero degli utenti/gruppi + for (TString16 u = user(); + u.not_empty() && !users.already_loaded(u); + u = users.get(u, "GROUPNAME")) + { + perm = users.get(u, "PERMISSION"); // Permessi del nodo corrente + if (!perm.blank()) + { + FOR_EACH_TOKEN(perm, tok) + { + row = tok; + const TString80 appmod = row.get(0); + const bool is_mod = appmod.len() == 2; + // Il programma corrisponde + if ((is_mod && app.compare(appmod, 2, TRUE) == 0) || + app.compare(appmod, -1, TRUE) == 0) + { + TString80 key = row.get(); key.trim(); // Tipo di filtro + if (is_mod) key << "-MOD"; + row = row.get(); row.trim(); // Espressione di filtro + if (key.not_empty() && row.not_empty() && row != "1") + { + key.upper(); + TString* str = (TString*)expr.objptr(key); + if (str == NULL) + { + str = new TString(row); // Crea una nuova stringa + expr.add(key, str); + } + else + { // Somma alla stringa precendente + if (*str != "0") // Se sono FALSE lasciami stare + { + if (row != "0") // Se aggiungo qualcosa di non ovvio + { + str->insert("(", 0); + *str << ")AND("; + *str << row << ')'; + } + else + *str = "0"; + } + } + } + } + } + } + } + + // Trasforma le stringhe in espressioni + TString esp, mod; + FOR_EACH_ASSOC_STRING(expr, hash, key, str) + { + mod = key; + if (mod.find("-MOD") < 0) + { + mod << "-MOD"; + const TString* modexp = (const TString*)expr.objptr(mod); + if (modexp != NULL && *modexp != "1") + { + if (*modexp != "0") + { + esp.cut(0); + esp << '(' << *modexp << ")AND(" << str << ')'; + } + else + esp = "0"; + } + else + esp = str; + + TExpression* e = new TExpression(esp, _strexpr, TRUE); + _expr.add(key, e); + } + } + + // Inserisce un elemento fasullo per segnalare l'avvenuta lettura + if (_expr.items() == 0) + _expr.add("", NULL); +} + +TExpression* TPostman::get_filter_expr(const char* flt) +{ + if (_expr.items() == 0) + load_filters(); + TString80 f(flt); f.upper(); + TExpression* e = (TExpression*)_expr.objptr(f); + return e; +} + +const char* TPostman::get_filter(const char* flt) +{ + TExpression* e = get_filter_expr(flt); + return e ? e->string() : NULL; +} + +bool TPostman::user_can(const char* flt, const TRelation* rel) +{ + bool yes_he_can = TRUE; + TExpression* e = get_filter_expr(flt); + if (e != NULL) + { + if (rel != NULL) + { + for (int i = e->numvar()-1; i >= 0; i--) + { + const TString& name = e->varname(i); + const TFieldref ref(name, 0); + const TString& val = ref.read(*rel); + e->setvar(name, val); + } + yes_he_can = e->as_bool(); + } + else + { + if (e->numvar() == 0) + yes_he_can = e->as_bool(); + } + } + return yes_he_can; +} + +TPostman::TPostman() : _firm(-1), _recipients_ok(FALSE) +{ +} + +TPostman& postman() +{ + static TPostman* _postman = NULL; + if (_postman == NULL) + _postman = new TPostman; + return *_postman; +} + +/////////////////////////////////////////////////////////// +// Public interface +/////////////////////////////////////////////////////////// + +bool can_dispatch_transaction(const TRectype& rec) +{ + return postman().can_dispatch_transaction(rec); +} + +bool dispatch_transaction(const TRectype& rec, const TFilename& name) +{ + return postman().dispatch_transaction(rec, name); +} + +const char* get_user_filter(const char* flt) +{ + return postman().get_filter(flt); +} + +const char* get_user_read_filter() +{ + return get_user_filter("Lettura"); +} + +const char* get_user_write_filter() +{ + return get_user_filter("Scrittura"); +} + +bool user_can_read(const TRelation* rel) +{ + return postman().user_can("Lettura", rel); +} + +bool user_can_write(const TRelation* rel) +{ + return user_can_read(rel) && postman().user_can("Scrittura", rel); +} + + diff --git a/include/postman.h b/include/postman.h new file mode 100755 index 000000000..8ab4f8beb --- /dev/null +++ b/include/postman.h @@ -0,0 +1,28 @@ +#ifndef __POSTMAN_H +#define __POSTMAN_H + +#ifndef __ISAM_H +class TRectype; +#endif + +#ifndef __RELATION_H +class TRelation; +#endif + +#ifndef __STRINGS_H +class TFilename; +#endif + +// Mail management +bool can_dispatch_transaction(const TRectype& rec); +bool dispatch_transaction(const TRectype& rec, const TFilename& ini); + +// Permission management +const char* get_user_filter(const char* flt); +const char* get_user_read_filter(); +const char* get_user_write_filter(); + +bool user_can_read(const TRelation* rel); +bool user_can_write(const TRelation* rel); + +#endif \ No newline at end of file diff --git a/include/recarray.cpp b/include/recarray.cpp index 7c7283967..05b21f9a1 100755 --- a/include/recarray.cpp +++ b/include/recarray.cpp @@ -504,13 +504,24 @@ void TFile_cache::flush() // Needed by read/write cache } +bool TFile_cache::already_loaded(const char* code) const +{ + return _cache.objptr(code) != NULL; +} + +bool TFile_cache::already_loaded(long code) const +{ + TString16 str; str << code; + return already_loaded(str); +} + const TObject& TFile_cache::query(const char* code) { - test_firm(); - _error = NOERR; _code = code; + test_firm(); + TObject* obj = _cache.objptr(_code); if (obj == NULL) { diff --git a/include/recarray.h b/include/recarray.h index aa9e2011c..2bdf2f09b 100755 --- a/include/recarray.h +++ b/include/recarray.h @@ -170,6 +170,9 @@ public: const int key_number() const { return _key; } + bool already_loaded(const char* code) const; + bool already_loaded(long code) const; + long items() const { return _cache.items(); } diff --git a/include/relapp.cpp b/include/relapp.cpp index 7a3a22b97..3d88c0950 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -1,10 +1,11 @@ +#include #include #include +#include #include #include #include #include -#include #include /////////////////////////////////////////////////////////// @@ -32,6 +33,39 @@ void TRelation_application::setkey() } +void TRelation_application::set_key_filter() +{ + TString rf = get_user_read_filter(); rf.trim(); + if (rf.not_empty()) + { + TString expr; + for (int f = _mask->fields()-1; f >= 0; f--) + { + TMask_field& fld= _mask->fld(f); + if (fld.is_edit() && fld.in_key(0)) + { + TBrowse* b = ((TEdit_field&)fld).browse(); + if (b) + { + expr = b->get_filter(); + if (expr.find(rf) < 0) + { + if (expr.not_empty()) + { + expr.insert("(", 0); + expr << ")AND(" << rf << ')'; + } + else + expr = rf; + b->set_filter(expr); + } + } + } + } + } +} + + // @doc INTERNAL // @mfunc Setta i limiti @@ -101,6 +135,7 @@ bool TRelation_application::create() write_enable(); _mask = get_mask(MODE_QUERY); filter(); + set_key_filter(); set_limits(); } return TSkeleton_application::create(); @@ -158,20 +193,22 @@ void TRelation_application::enable_query() void TRelation_application::set_toolbar(bool all) { - const int mode = _mask->mode(); - int pos; - if (all) { - pos = _mask->id2pos(DLG_SAVEREC); + bool can_edit = !_mask->query_mode(); + if (can_edit) + can_edit = user_can_write(get_relation()); + + int pos = _mask->id2pos(DLG_SAVEREC); if (pos >= 0) - _mask->fld(pos).enable(mode != MODE_QUERY); + _mask->fld(pos).enable(can_edit); pos = _mask->id2pos(DLG_DELREC); if (pos >= 0) { - bool enabdel = mode != MODE_INS; - if (mode == MODE_MOD) + const int mode = _mask->mode(); + bool enabdel = mode != MODE_INS && can_edit; + if (enabdel && mode == MODE_MOD) { TRelation& r = *get_relation(); const TRecnotype oldpos = r.lfile().recno(); @@ -188,7 +225,11 @@ void TRelation_application::set_toolbar(bool all) pos = _mask->id2pos(DLG_NEWREC); if (pos >= 0) - _mask->fld(pos).enable(mode == MODE_QUERY || _lnflag == 0 ); + { + bool enabins = (_mask->query_mode() || _lnflag == 0) && + user_can_write(NULL); + _mask->fld(pos).enable(enabins); + } } enable_query(); @@ -252,8 +293,10 @@ bool TRelation_application::autonum( if (!get_next_key(k)) { k = get_next_key(); +/* if (k.not_empty()) NFCHECK("La 'const char* get_next_key()' verra' sostituita dalla 'bool get_next_key(TToken_string&)'"); +*/ } if (!rec && !m->query_mode()) @@ -331,7 +374,21 @@ void TRelation_application::insert_mode() query_insert_mode(); return; } - + + TRelation* r = get_relation(); + for (int f = _mask->fields()-1; f >= 0; f--) + { + TMask_field& fld = _mask->fld(f); + if (fld.is_loadable() && fld.shown() && fld.in_key(0)) + ((TLoadable_field&)fld).autosave(*r); + } + if (!user_can_write(r)) + { + error_box("L'utente %s non puo' inserire questo documento", + (const char*)user()); + return; + } + const bool changing = changing_mask(MODE_INS); TFilename workname; workname.temp("msk"); if (changing) @@ -351,7 +408,7 @@ void TRelation_application::insert_mode() } set_mode(MODE_INS); - get_relation()->zero(); // Azzera tutta la relazione! + r->zero(); // Azzera tutta la relazione! init_insert_mode(*_mask); @@ -362,7 +419,13 @@ void TRelation_application::insert_mode() bool TRelation_application::modify_mode() { - int err = get_relation()->read(_isequal, _testandlock); + TRelation* rel = get_relation(); + if (!user_can_read(rel)) + return warning_box("I dati non sono accessibili per l'utente %s", + (const char*)user()); + + const TReclock block = user_can_write(rel) ? _testandlock : _nolock; + int err = rel->read(_isequal, block); if (err != NOERR) { if (err == _islocked) @@ -391,7 +454,7 @@ bool TRelation_application::modify_mode() return FALSE; } - get_relation()->save_status(); + rel->save_status(); init_modify_mode(*_mask); // ....possibilmente spostare questa chiamata ..... @@ -681,7 +744,7 @@ bool TRelation_application::save(bool check_dirty) } was_dirty = FALSE; - begin_wait(); + TWait_cursor hourglass; if (mode == MODE_INS) { bool changed = TRUE; @@ -718,12 +781,12 @@ bool TRelation_application::save(bool check_dirty) get_relation()->restore_status(); err = rewrite(*_mask); } - end_wait(); switch(err) { case NOERR: _recins = get_relation()->lfile().recno(); + mask2mail(*_mask); break; case _isreinsert: warning_box("Esiste gia' un documento con la stessa chiave"); @@ -833,16 +896,20 @@ bool TRelation_application::remove() { TMask &m=*_mask; int err = get_relation()->remove(); - const int max = m.fields(); - for (int i = 0; i < max; i++) + for (int i = 0; i < m.fields(); i++) { if (m.fld(i).is_sheet()) { TSheet_field& f = (TSheet_field& )m.fld(i); - if (f.record()&& !f.external_record()) - err|=f.record()->remove(); + if (f.record() && !f.external_record()) + err |= f.record()->remove(); } } + if (err == NOERR) + { + m.set_mode(NO_MODE); + mask2mail(m); + } return err == NOERR; } @@ -935,8 +1002,10 @@ void TRelation_application::main_loop() } else { - if (find(0)) modify_mode(); - else insert_mode(); + if (find(0)) + modify_mode(); + else + insert_mode(); } if (_curr_trans_mode == TM_AUTOMATIC) _mask->send_key(K_CTRL+'R', 0); @@ -1347,8 +1416,8 @@ void TRelation_application::edit_mask2ini() { if (_trans_ini.row(_trans_counter).not_empty()) { - TString head; - head.format("%d", get_relation()->lfile().num()); + TString16 head; + head << get_relation()->lfile().num(); TConfig ini(_trans_ini.row(_trans_counter), head); mask2ini(*_mask, ini); } @@ -1356,19 +1425,52 @@ void TRelation_application::edit_mask2ini() void TRelation_application::mask2ini(const TMask& m, TConfig& ini) { - ini.set("Firm", get_firm(), "Transaction"); - TString16 defpar; defpar << get_relation()->lfile().num(); - TString str(80); + + ini.set("Firm", get_firm(), "Transaction"); for (int f = m.fields()-1; f >= 0; f--) { TMask_field& campo = m.fld(f); if (campo.field() && campo.shown()) { - str = campo.get(); + const TString& str = campo.get(); campo.field()->write(ini, defpar, str); } } ini.set_paragraph(defpar); } +bool TRelation_application::mask2mail(const TMask& m) +{ + if (::can_dispatch_transaction(get_relation()->curr())) + { + TWait_cursor hourglass; + TFilename ininame; ininame.temp(); + if (!ininame.exist()) // Test qualunque per usare {} + { + TConfig ini(ininame, "Transaction"); + const char* action = ""; + char mode[2] = { TM_AUTOMATIC, '\0' }; + switch (m.mode()) + { + case NO_MODE: + action = TRANSACTION_DELETE; + break; + case MODE_MOD: + action = TRANSACTION_MODIFY; + break; + default: + action = TRANSACTION_INSERT; + break; + } + ini.set("Action", action); + ini.set("Mode", mode); + mask2ini(m, ini); + } + ::dispatch_transaction(get_relation()->curr(), ininame); + ::remove(ininame); + } + return TRUE; +} + + diff --git a/include/relapp.h b/include/relapp.h index 9d6adac73..68251932b 100755 --- a/include/relapp.h +++ b/include/relapp.h @@ -85,6 +85,8 @@ private: // @cmember:(INTERNAL) Seleziona il nuovo modo e ritorna il vecchio int set_mode(int mode); + // @Setta i filtri di lettura + void set_key_filter(); // @cmember:(INTERNAL) Setta i limiti void set_limits(byte what = 0x3); // @cmember:(INTERNAL) Posiziona l'applicazione in modo richiesta/inserimento (chiama ) @@ -221,6 +223,7 @@ protected: void edit_mask2ini(); virtual void ini2mask(TConfig& ini, TMask& m, bool query); virtual void mask2ini(const TMask& m, TConfig& ini); + virtual bool mask2mail(const TMask& m); // @access Public Member public: diff --git a/include/relation.cpp b/include/relation.cpp index 1bea71635..2a0c53f6b 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -914,7 +914,7 @@ HIDDEN bool __evalcondition(const TRelation& r,TExpression* cond, const TArray & // f = cond->varname(i); cond->setvar(i, (const char *) (TRecfield &)frefs[i]); } - return (bool) *cond; + return cond->as_bool(); } // @doc EXTERNAL @@ -1903,10 +1903,12 @@ void TFieldref::write(TConfig& ini, const char* defpar, const char* val) const return; const char* para = _id.empty() ? defpar : _id; - if (_from > 0) + if (_from > 0 || _to > 0) { buffer = ini.get(_name, para); - buffer.overwrite(val, _from); + buffer.overwrite(val, _from + buffer[0] == '"'); + if (buffer[0] == ' ') // Metto le virgolette + { buffer.insert("\"", 0); buffer << '"'; } ini.set(_name, buffer, para); } else diff --git a/include/sheet.cpp b/include/sheet.cpp index 40e70fc5d..73ed52c37 100755 --- a/include/sheet.cpp +++ b/include/sheet.cpp @@ -618,7 +618,7 @@ void TSheet_control::load_columns_order(const TMask_field& field) void TSheet_control::align_column(int c, bool right) { XI_OBJ* column = find_column(c); - CHECK(column, "Can't find numeric column"); + CHECKD(column, "Can't find numeric column ", c); dword attr = xi_get_attrib(column); if (right) attr |= XI_ATR_RJUST; diff --git a/include/stack.h b/include/stack.h index 99e7cdf19..508236815 100755 --- a/include/stack.h +++ b/include/stack.h @@ -16,6 +16,7 @@ class TStack : public TObject // @access:(INTERNAL) Private Member { +protected: // @cmember:(INTERNAL) Dati dello stack TArray _data; // @cmember:(INTERNAL) Puntatore alla cima dello stack diff --git a/include/strings.cpp b/include/strings.cpp index c47b68b6c..dd0ce27a7 100755 --- a/include/strings.cpp +++ b/include/strings.cpp @@ -434,6 +434,8 @@ int TString::find(const char* s, int from) const bool TString::match(const char* pat) const { + if (pat == NULL || *pat =='\0') + return empty(); return ::match(pat, _str); } @@ -1709,6 +1711,28 @@ void TToken_string::destroy(int n) restart(); } +/////////////////////////////////////////////////////////// +// TAuto_token_string +/////////////////////////////////////////////////////////// + +TAuto_token_string& TAuto_token_string::create(const char* ts) +{ + // Copia la stringa + set(ts); + + // Calcola il separatore + for (const char* s = ts; *s; s++) + { + if (strchr("|¦\t\n^;,!&+", *s) != NULL) + { + separator(*s); + break; + } + } + + return *this; +} + /////////////////////////////////////////////////////////// // Paragraph string /////////////////////////////////////////////////////////// diff --git a/include/strings.h b/include/strings.h index 25d47ced9..615e508c5 100755 --- a/include/strings.h +++ b/include/strings.h @@ -1,7 +1,7 @@ #ifndef __STRINGS_H #define __STRINGS_H -#ifndef __STRING_H +#ifndef _INC_STRING #include #endif @@ -311,6 +311,9 @@ class TString16 : public TFixed_string // @access Public Member public: + // @cmember Duplica una stringa di 16 caratteri + virtual TObject* dup() const { return new TString16(_str16); } + // @cmember Costruttore TString16(const char* s = "") : TFixed_string(_str16, 17) { set(s); } @@ -350,6 +353,9 @@ class TString80 : public TFixed_string char _str80[81]; public: + // @cmember Duplica una stringa di 80 caratteri + virtual TObject* dup() const { return new TString80(_str80); } + TString80(const char* s = "") : TFixed_string(_str80, 81) { set(s); } TString80(const TString& s) : TFixed_string(_str80, 81) { set(s); } TString80(const TString80& s) : TFixed_string(_str80, 81) { set(s); } @@ -373,6 +379,9 @@ class TString256 : public TFixed_string char _str256[257]; public: + // @cmember Duplica una stringa di 256 caratteri + virtual TObject* dup() const { return new TString256(_str256); } + TString256(const char* s = "") : TFixed_string(_str256, 257) { set(s); } TString256(const TString& s) : TFixed_string(_str256, 257) { set(s); } TString256(const TString256& s) : TFixed_string(_str256, 257) { set(s); } @@ -548,10 +557,28 @@ public: #define FOR_EACH_TOKEN_STRING(__tok, __count, __str) \ TString __str; \ for (int __count = 0; __tok.get(__count, __str); __count++) + +/////////////////////////////////////////////////////////// +// Mitica token string che sceglie da sola il separatore +/////////////////////////////////////////////////////////// +class TAuto_token_string : public TToken_string +{ +protected: + TAuto_token_string& create(const char* ts); + +public: + TAuto_token_string& operator=(const char* ts) { return create(ts); } + TAuto_token_string& operator=(const TString& ts) { return create(ts); } + TAuto_token_string& operator=(const TToken_string& ts) { return create(ts); } + TAuto_token_string& operator=(const TAuto_token_string& ts) { return create(ts); } + TAuto_token_string(int sz = 50) : TToken_string(sz) { } + TAuto_token_string(const char* ts) { create(ts); } + virtual ~TAuto_token_string() { } +}; /////////////////////////////////////////////////////////// -// DES Paragraph +// TParagraph_string /////////////////////////////////////////////////////////// // @doc EXTERNAL @@ -643,15 +670,15 @@ const TToken_string& empty_string(); #define FOR_EACH_ARRAY_ROW(__arr, __r, __riga) \ TToken_string* __riga; \ - for (int __r = __arr.first(); \ - __riga = (TToken_string*)__arr.objptr(__r); \ - __r = __arr.succ(__r)) + for (int __r = (__arr).first(); \ + __riga = (TToken_string*)(__arr).objptr(__r); \ + __r = (__arr).succ(__r)) #define FOR_EACH_ARRAY_ROW_BACK(__arr, __r, __riga) \ TToken_string* __riga; \ - for (int __r = __arr.last(); \ - __riga = (TToken_string*)__arr.objptr(__r); \ - __r = __arr.pred(__r)) + for (int __r = (__arr).last(); \ + __riga = (TToken_string*)(__arr).objptr(__r); \ + __r = (__arr).pred(__r)) const char SLASH = #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32 diff --git a/include/tabutil.cpp b/include/tabutil.cpp index 257d18db7..83d607adf 100755 --- a/include/tabutil.cpp +++ b/include/tabutil.cpp @@ -2,6 +2,8 @@ #define __TABUTIL_CPP #include + +#include #include #include #include @@ -189,16 +191,70 @@ void TTable::load_module_description() _module = "ba"; } -const char* TTable::module() +const char* TTable::module() { if (!_des_mod_loaded) load_module_description(); return _module; } -const char* TTable::description() +const char* TTable::description() { if (!_des_mod_loaded) load_module_description(); return _description; } + +struct TCallbackTableinfo +{ + TString16 _var1, _var2; + TString16 _module; + TFilename _app; +}; + +HIDDEN int find_relapp(TConfig& cfg, void* jolly) +{ + TCallbackTableinfo& info = *((TCallbackTableinfo*)jolly); + if (cfg.get_paragraph().compare(info._module, 2, TRUE) == 0) + { + for (int v = 1; v <= 2; v++) + { + const TString& var = v == 1 ? info._var1 : info._var2; + if (cfg.exist(var)) + { + info._app = cfg.get(var); + return info._app.not_empty(); + } + } + } + return FALSE; +} + +bool TTable::get_relapp(TString& app) const +{ + TConfig ini("install.ini"); + TCallbackTableinfo fi; + fi._var1.format("Edit_%d", num()); + fi._var2.format("Edit_%d", num() == LF_TAB ? LF_TABCOM : LF_TAB); + fi._module = ((TTable*)this)->module(); + ini.for_each_paragraph(find_relapp, &fi); + + if (fi._app.not_empty()) + app = fi._app; + else + { + app = "ba3 -0"; + if (fi._module.compare("ba", 2, TRUE) != 0) + { + TConfig c(CONFIG_STUDIO, fi._module); + if (c.exist("TabPrg")) + app = c.get("TabPrg"); + } + app << ' '; + if (num() == LF_TABCOM) + app << '%'; + app << _tabname; + } + return app.not_empty(); +} + diff --git a/include/tabutil.h b/include/tabutil.h index e722fc96a..8dda6a679 100755 --- a/include/tabutil.h +++ b/include/tabutil.h @@ -52,6 +52,8 @@ public: // @cmember Distruttore virtual ~TTable(); + virtual bool get_relapp(TString& app) const; + // @cmember Ritorna il numero logico della tabella

static int name2log(const char* tabname); }; diff --git a/include/tree.cpp b/include/tree.cpp index 058451bb3..75522a5f4 100755 --- a/include/tree.cpp +++ b/include/tree.cpp @@ -226,11 +226,14 @@ bool TTree::expanded() const bool TTree::expand() { - TString str; - curr_id(str); - bool ok = !_expanded.is_key(str) && has_son(); + bool ok = enabled() && has_son(); if (ok) - _expanded.add(str); + { + TString str; curr_id(str); + ok = !_expanded.is_key(str); + if (ok) + _expanded.add(str); + } return ok; } @@ -394,7 +397,7 @@ bool TObject_tree::expanded() const bool TObject_tree::expand() { - bool ok = _current && _current->_son && !_current->_expanded; + bool ok = _current && _current->_son && !_current->_expanded && enabled(); if (ok) _current->_expanded = TRUE; return ok; @@ -507,7 +510,7 @@ bool TObject_tree::create_root() bool TObject_tree::add_son(TObject* obj) { bool ok = FALSE; - if (_current) + if (_root) { TTree_node*& curson = _current->_son; TTree_node* newson = new TTree_node; @@ -701,6 +704,7 @@ class TNode_info : public TSortable { public: bool _valid : 1; + bool _enabled : 1; bool _expandable : 1; bool _expanded : 1; TString _id; @@ -711,6 +715,7 @@ public: const TNode_info& operator =(const TNode_info& ni) { _valid = ni._valid; + _enabled = ni._enabled; _expanded = ni._expanded; _expandable = ni._expandable; _id = ni._id; @@ -884,21 +889,16 @@ bool TTree_window::callback_draw_node(TTree& node, void* jolly, word when) { node.curr_id(ui->_str); const bool is_selected = ui->_str == ui->_curr_info->_id; + const bool is_enabled = node.enabled(); int text_len = 0; if (node.get_description(ui->_str)) { text_len = ui->_str.len(); if (is_selected) - { ui->_win->set_color(FOCUS_COLOR, FOCUS_BACK_COLOR); - ui->_win->set_opaque_text(TRUE); - } + else + ui->_win->set_color(is_enabled ? NORMAL_COLOR : DISABLED_COLOR, NORMAL_BACK_COLOR); ui->_win->stringat(int(ui->_x+2), int(ui->_y), ui->_str); - if (is_selected) - { - ui->_win->set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); - ui->_win->set_opaque_text(FALSE); - } } const int ry = int(ui->_y - ui->_firsty); @@ -923,14 +923,28 @@ bool TTree_window::callback_draw_node(TTree& node, void* jolly, word when) TImage* bmp = node.image(is_selected); if (bmp) - bmp->draw(win, p.h, p.v + (_row_height - bmp->height()) / 2); + { + const int x = p.h; + const int y = p.v + (_row_height - bmp->height()) / 2; + if (is_enabled) + bmp->draw(win, x, y); + else + { + TImage dis(*bmp); + for (int j = dis.height()-1; j >= 0; j--) + for (int i = dis.width() - (j&1 ? 2 : 1); i >= 0; i-=2) + dis.set_pixel(i, j, NORMAL_BACK_COLOR); + dis.draw(win, x, y); + } + } TNode_info& ni = (*ui->_node_info)[ry]; node.curr_id(ni._id); - ni._valid = TRUE; - ni._startx = ui->_x; - ni._endx = ui->_x + text_len + 2; - ni._expandable = node.has_son(); + ni._valid = TRUE; + ni._startx = ui->_x; + ni._endx = ui->_x + text_len + 2; + ni._enabled = is_enabled; + ni._expandable = is_enabled && node.has_son(); if (ni._expandable) { ni._plusx = ui->_x - TABX + 1; @@ -1051,6 +1065,7 @@ void TTree_window::update() } _node_info.reset(); + set_opaque_text(TRUE); word flags = SCAN_PRE_ORDER | SCAN_IN_ORDER | SCAN_IGNORING_UNEXPANDED; if (_hide_leaves) flags |= SCAN_IGNORING_LEAVES; diff --git a/include/tree.h b/include/tree.h index 68d26a1f0..0ce93ec7e 100755 --- a/include/tree.h +++ b/include/tree.h @@ -64,6 +64,8 @@ public: virtual bool expand_all(); virtual bool shrink_all(); virtual TImage* image(bool selected) const; + virtual bool enabled() const { return TRUE; } + bool disabled() const { return !enabled(); } virtual bool scan_depth_first(NODE_HANDLER nh, void* jolly, word flags = SCAN_PRE_ORDER); virtual bool scan_breadth_first(NODE_HANDLER nh, void* jolly, word flags = SCAN_PRE_ORDER); diff --git a/include/window.cpp b/include/window.cpp index ff75c92cd..5424dfb77 100755 --- a/include/window.cpp +++ b/include/window.cpp @@ -367,6 +367,13 @@ TImage::TImage(short id) : _image(NULL) TImage::TImage(const TImage& im, short w, short h) : _image(NULL) { const XVT_IMAGE_FORMAT fmt = xvt_image_get_format(im._image); + if (w < 0 || h < 0) + { + short iw, ih; + xvt_image_get_dimensions(im._image, &iw, &ih); + if (w < 0) w = iw; + if (h < 0) h = ih; + } set(xvt_image_create(fmt, w, h, NULL)); if (ok()) @@ -482,6 +489,16 @@ void TImage::set_clut(byte n, COLOR c) xvt_image_set_clut(_image, n, c); } +void TImage::set_pixel(int x, int y, COLOR col) +{ + xvt_image_set_pixel(_image, x, y, col); +} + +COLOR TImage::get_pixel(int x, int y) const +{ + return xvt_image_get_pixel(_image, x, y); +} + // Certified 99% // @doc EXTERNAL @@ -520,7 +537,7 @@ void TImage::convert_transparent_color(COLOR transparent) { if (_image) { - const COLOR trans = xvt_image_get_pixel(_image, 0, 0) & 0x00FFFFFF; + const COLOR trans = get_pixel(0, 0) & 0x00FFFFFF; if (trans != (transparent & 0x00FFFFFF) && xvt_image_get_format(_image) == XVT_IMAGE_CL8) { diff --git a/include/window.h b/include/window.h index e1593b4e8..c5eb83d03 100755 --- a/include/window.h +++ b/include/window.h @@ -89,6 +89,10 @@ public: void draw(WINDOW w, const RCT& dst) const; // @cmember Disegna l'immagine sulla finestra void draw(WINDOW w, const RCT& dst, const RCT& src) const; + // @cmember Setta un pixel + void set_pixel(int x, int y, COLOR c); + // @cmember Legge un pixel + COLOR get_pixel(int x, int y) const; // @cmember Setta l'immagine e le sue dimensioni XVT_IMAGE set(XVT_IMAGE i); @@ -127,7 +131,7 @@ public: // @cmember Costruttore. Viene passato l'identificatore dell'immagine sul file di risorsa TImage(short id); // @cmember Costruttore. Viene passata l'immagine e le sue diemsioni - TImage(const TImage& i, short width, short height); + TImage(const TImage& i, short width = -1, short height = -1); // @cmember Costruttore. Viene passata l'immagine e le sue diemsioni TImage(short width, short height, XVT_IMAGE_FORMAT fmt = XVT_IMAGE_CL8); // @cmember Distruttore