Files correlati : Ricompilazione Demo : [ ] Commento :corretta chiamata dei MENU_ITEM con MENU_ITEM_ID git-svn-id: svn://10.65.10.50/trunk@18339 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1124 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1124 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | |
| #include <expr.h>
 | |
| #include <msksheet.h>
 | |
| #include <progind.h>
 | |
| #include <relation.h>
 | |
| #include <sheet.h>
 | |
| #include <tabutil.h>
 | |
| #include <urldefid.h>
 | |
| #include <viswin.h>
 | |
| 
 | |
| #include "ve4.h"
 | |
| #include "ve4100.h"
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TTable_expression
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TTable_expression : public TExpression
 | |
| { 
 | |
|   static TArray _expr;
 | |
|   static const TRelation* _rel;
 | |
|   static TViswin* _win;
 | |
|   static bool _errors;
 | |
|   
 | |
| protected:
 | |
|   virtual bool print_error(const char* msg) const;
 | |
|   virtual int parse_user_func(const char* name, int nparms) const;
 | |
|   virtual void evaluate_user_func(int index, int nparms,
 | |
|                                   TEval_stack& stack, TTypeexp curtype) const;
 | |
|   virtual bool user_func_dirty() const;                                
 | |
| 
 | |
|   bool error_box(const char* fmt, ...) const;
 | |
|   const TRelation& get_relation() const { CHECK(_rel, "NULL relation"); return *_rel; }
 | |
|   
 | |
|   // Cerca il record dato il file->campo.  Usata da get_field e put_field.
 | |
|   TRectype* field2rec(TString& var) const;
 | |
|   // Converte un nome di funzione in indice
 | |
|   int name2index(const char* name) const;
 | |
| 
 | |
| public:
 | |
|   static void load_table(bool force = FALSE);
 | |
|   static void set_relation(const TRelation* rel) { _rel = rel; load_table(); }
 | |
|   static void set_window(TViswin* win) { _win = win; }
 | |
|   static void reset_errors() { _errors = FALSE; }
 | |
|   static bool errors_found() { return _errors; }
 | |
| 
 | |
|   int str2file(const TString& s) const;
 | |
|   const char* get_field(const char* f) const;
 | |
|   void set_field(const char* field, const char* val) const;
 | |
|   
 | |
|   TTable_expression() { }
 | |
|   virtual ~TTable_expression() { }
 | |
| };
 | |
|   
 | |
| TArray           TTable_expression::_expr;  
 | |
| const TRelation* TTable_expression::_rel = NULL;  
 | |
| TViswin*         TTable_expression::_win = NULL;  
 | |
| bool             TTable_expression::_errors = FALSE;  
 | |
|   
 | |
| void TTable_expression::load_table(bool force)
 | |
| { 
 | |
|   if (_expr.items() == 0 || force)
 | |
|   {   
 | |
|     TString n(15), e(127);
 | |
|     TTable expr("%FRM");
 | |
|     for (expr.first(); !expr.eof(); expr.next())
 | |
|     {
 | |
|       n = expr.get("CODTAB");
 | |
|       e = expr.get("S1");
 | |
|       e << expr.get("S2");
 | |
|       const TTypeexp t = expr.get_bool("B0") ? _strexpr : _numexpr;
 | |
|       
 | |
|       TTable_expression* te = new TTable_expression;
 | |
|       THash_object* o = new THash_object(n, te);
 | |
|       const int index = _expr.add(o);
 | |
|       if (!te->set(e, t))
 | |
|       {
 | |
|         te->error_box("La funzione %s contiene un simbolo errato: %s",
 | |
|                       (const char*)n, te->last_token());
 | |
|         te->set("", t);  
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TTable_expression::user_func_dirty() const
 | |
| {
 | |
|   return _errors || TExpression::user_func_dirty();
 | |
| }
 | |
| 
 | |
| bool TTable_expression::print_error(const char* msg) const
 | |
| {   
 | |
|   if (_win)            
 | |
|   {
 | |
|     TString s(256);
 | |
|     s << "@b$[r,w]" << msg;
 | |
|     _win->add_line(s);
 | |
|   }  
 | |
|   else
 | |
|     ::error_box("%s", msg);
 | |
|   return _errors = TRUE;  
 | |
| }
 | |
| 
 | |
| bool TTable_expression::error_box(const char* fmt, ...) const
 | |
| {
 | |
|   char msg[256];
 | |
|   va_list argptr;
 | |
|   va_start(argptr,fmt);
 | |
|   vsprintf(msg, fmt, argptr);
 | |
|   va_end(argptr);
 | |
|   return print_error(msg);
 | |
| }
 | |
| 
 | |
| int TTable_expression::str2file(const TString& str) const
 | |
| {
 | |
|   int ln = -1;
 | |
|   if (isdigit(str[0]))
 | |
|   {
 | |
|     ln = atoi(str);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     const char* const s = "AUDCR";
 | |
|     const int logicnum[] = { LF_ANAMAG, LF_UMART, LF_DESLIN, LF_CONDV, LF_RCONDV, 0 };
 | |
|     const char* p = strchr(s, toupper(str[0]));
 | |
|     ln = p != NULL ? logicnum[p-s] : -1;
 | |
|   }
 | |
| 
 | |
|   return ln;
 | |
| } 
 | |
| 
 | |
| TRectype* TTable_expression::field2rec(TString& var) const
 | |
| {
 | |
|   int logicnum = 0;
 | |
|   var.upper();
 | |
|   const int arrow = var.find("->");
 | |
|   if (arrow > 0)
 | |
|   {
 | |
|     logicnum = str2file(var);
 | |
|     var = var.mid(arrow+2);
 | |
|   }  
 | |
|   
 | |
|   TRectype* rec = NULL;
 | |
|   if (logicnum >= 0 && get_relation().exist(logicnum))
 | |
|     rec = &get_relation().curr(logicnum);
 | |
|   else
 | |
|     error_box("Il campo '%s' non appartiene alla relazione.", (const char*)var);
 | |
|   return rec;  
 | |
| }
 | |
| 
 | |
| const char* TTable_expression::get_field(const char* f) const
 | |
| {
 | |
|   TString var(f);
 | |
|   const TRectype* rec = field2rec(var);
 | |
|   const char* val = "";
 | |
|   if (rec != NULL)
 | |
|   {              
 | |
|     if (rec->exist(var))
 | |
|       val = rec->get(var);
 | |
|     else
 | |
|       error_box("Il campo '%s' non appartiene al file %d.", (const char*)var, rec->num());
 | |
|   }  
 | |
|   return val;  
 | |
| } 
 | |
| 
 | |
| void TTable_expression::set_field(const char* f, const char* v) const
 | |
| {
 | |
|   TString var(f);
 | |
|   TRectype* rec = field2rec(var);
 | |
|   if (rec != NULL)
 | |
|     rec->put(var, v);
 | |
| } 
 | |
| 
 | |
| int TTable_expression::name2index(const char* name) const
 | |
| {                               
 | |
|   if (_expr.items() == 0)
 | |
|     load_table();
 | |
|   
 | |
|   TString code(name); code.upper();
 | |
|   int index;
 | |
|   
 | |
|   for (index = _expr.items()-1; index >= 0; index--)
 | |
|   {
 | |
|     const THash_object& h = (const THash_object&)_expr[index];
 | |
|     if (h.key() == code)
 | |
|       break;
 | |
|   }            
 | |
|   
 | |
|   if (index < 0)
 | |
|   {
 | |
|     TTable expr("%FRM");
 | |
|     expr.put("CODTAB", code);
 | |
|     if (expr.read() == NOERR)
 | |
|     {
 | |
|       TString e(127);
 | |
|       e = expr.get("S1"); e << expr.get("S2");
 | |
|       const TTypeexp t = expr.get_bool("B0") ? _numexpr : _strexpr;
 | |
|       TTable_expression* te = new TTable_expression;
 | |
|       if (te->set(e, t))
 | |
|       {
 | |
|         THash_object* o = new THash_object(code, te);
 | |
|         index = _expr.add(o);
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         delete te;
 | |
|         index = -2;
 | |
|       }  
 | |
|     }  
 | |
|   }   
 | |
|   return index;
 | |
| }
 | |
| 
 | |
| int TTable_expression::parse_user_func(const char* name, int nparms) const
 | |
| {                 
 | |
|   const int index = name2index(name);
 | |
|   switch(index)
 | |
|   {
 | |
|   case -1:
 | |
|     error_box("Funzione non riconosciuta: %s.", name);
 | |
|     break;
 | |
|   case -2:
 | |
|     error_box("La funzione %s contiene un simbolo errato: %s.",
 | |
|               name, last_token());
 | |
|     break;
 | |
|   default:
 | |
|     break;                
 | |
|   }
 | |
|   return index;
 | |
| }
 | |
| 
 | |
| void TTable_expression::evaluate_user_func(int index, int nparms, 
 | |
|                                            TEval_stack& stack, TTypeexp curtype) const
 | |
| {                        
 | |
|   THash_object* ho = (THash_object*)_expr.objptr(index);
 | |
|   TTable_expression& expr = (TTable_expression&)ho->obj();
 | |
|   
 | |
|   // Assegna i valori a tutte le variabili dell'espressione
 | |
|   for (int v = expr.numvar()-1; v >= 0; v--)
 | |
|   {
 | |
|     const char* var = expr.varname(v);
 | |
|     if (var[0] == '#')  // Parametro della funzione
 | |
|     {
 | |
|       const int n = atoi(var+1);
 | |
|       if (n > 0 && n <= nparms)
 | |
|       {
 | |
|         const TObject& o = stack.peek(nparms-n);
 | |
|         if (o.class_id() == CLASS_STRING)
 | |
|           expr.setvar(var, (const TString&)o);
 | |
|         else  
 | |
|           expr.setvar(var, (const real&)o);
 | |
|       }
 | |
|       else
 | |
|         error_box("Parametro non valido: %s", (const char*)var);
 | |
|     }
 | |
|     else
 | |
|     { 
 | |
|       const char* val = get_field(var);
 | |
|       if (curtype == _numexpr)                             
 | |
|         expr.setvar(var, real(val));
 | |
|       else
 | |
|         expr.setvar(var, val);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   // Toglie i parametri dallo stack
 | |
|   for (int p = nparms; p > 0; p--)
 | |
|     stack.pop();
 | |
|   
 | |
|   // Mette il risultato sullo stack
 | |
|   if (curtype == _numexpr)
 | |
|     stack.push((const real&)expr);
 | |
|   else  
 | |
|     stack.push((const TString&)expr);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Maschera ricalcolo di magazzino
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TRicalcolo_mask : public TMask
 | |
| {              
 | |
|   TArray _rel, _des;
 | |
|   int _cur_file;  
 | |
|   TToken_string _key_expr;
 | |
|   
 | |
|   TRelation* _relation; 
 | |
|   TCursor* _cursor;
 | |
|   
 | |
| protected:  
 | |
|   bool test_formula(TMask_field& f) const;
 | |
| 
 | |
|   static bool file_handler   (TMask_field& f, KEY k);
 | |
|   static bool key_handler    (TMask_field& f, KEY k);
 | |
|   static bool filter_handler (TMask_field& f, KEY k);
 | |
|   static bool field_handler  (TMask_field& f, KEY k);
 | |
|   static bool fromto_handler (TMask_field& f, KEY k);
 | |
|   static bool formula_handler(TMask_field& f, KEY k);
 | |
|   
 | |
|   bool gestione_um(char tipo) const;
 | |
|   TRelation_description& get_des() const;
 | |
|   TRelation&      get_rel() const;
 | |
|   const TRectype& get_rec() const;
 | |
|   const RecDes&   get_rec_des() const;
 | |
|   TToken_string&  get_key_expr(int k);     
 | |
|   
 | |
|   TRelation& create_relation();
 | |
|   TCursor& create_cursor();
 | |
| 
 | |
| public:
 | |
|   bool elabora();
 | |
|   
 | |
|   TRicalcolo_mask();
 | |
|   virtual ~TRicalcolo_mask() { }
 | |
| };
 | |
| 
 | |
| TRicalcolo_mask::TRicalcolo_mask()
 | |
|                : TMask("ve4100"), _cur_file(0), _relation(NULL), _cursor(NULL)
 | |
| {
 | |
|   const int lf[] = { LF_ANAMAG, LF_UMART, LF_DESLIN, LF_CONDV, LF_RCONDV, 0 };
 | |
|   for (int i = 0; lf[i]; i++)                   
 | |
|   {                                   
 | |
|     TRelation* rel = new TRelation(lf[i]);
 | |
|     _rel.add(rel);
 | |
|     _des.add(new TRelation_description(*rel));
 | |
|   }     
 | |
|   
 | |
|   set_handler(F_FILE, file_handler);
 | |
|   set_handler(F_KEY, key_handler);
 | |
|   set_handler(F_FILTER, filter_handler);
 | |
|   
 | |
|   TSheet_field& fields = (TSheet_field&)field(F_FIELDS);
 | |
|   TMask& fsm = fields.sheet_mask();
 | |
|   fsm.set_handler(F_FIELD, field_handler);
 | |
|   fsm.set_handler(F_FROM, fromto_handler);
 | |
|   fsm.set_handler(F_TO, fromto_handler);
 | |
|   
 | |
|   TSheet_field& outputs = (TSheet_field&)field(F_OUTPUTS);
 | |
|   TMask& osm = outputs.sheet_mask();
 | |
|   osm.set_handler(F_FIELD, field_handler);
 | |
|   osm.set_handler(F_FORMULA, formula_handler);
 | |
|   outputs.row(-1);    // Aggiunge comunque una riga vuota;
 | |
|   osm.force_update();
 | |
| } 
 | |
| 
 | |
| TRelation_description& TRicalcolo_mask::get_des() const
 | |
| {
 | |
|   return (TRelation_description&)_des[_cur_file];
 | |
| }
 | |
| 
 | |
| TRelation& TRicalcolo_mask::get_rel() const
 | |
| {
 | |
|   return (TRelation&)_rel[_cur_file];
 | |
| }
 | |
| 
 | |
| const TRectype& TRicalcolo_mask::get_rec() const
 | |
| {
 | |
|   return get_rel().lfile().curr();
 | |
| }
 | |
| 
 | |
| const RecDes& TRicalcolo_mask::get_rec_des() const
 | |
| {     
 | |
|   return get_rec().rec_des();
 | |
| }
 | |
| 
 | |
| TToken_string& TRicalcolo_mask::get_key_expr(int key)
 | |
| {    
 | |
|   _key_expr.cut(0);
 | |
|   if (key > 0)
 | |
|   {
 | |
|     const RecDes& rd = get_rec_des();
 | |
|     const KeyDes& kd = rd.Ky[key-1];
 | |
|     for (int i = 0; i < kd.NkFields; i++)
 | |
|     {
 | |
|       const int nf = kd.FieldSeq[i] % MaxFields;
 | |
|       const RecFieldDes& rf = rd.Fd[nf];  
 | |
|       _key_expr.add(rf.Name);
 | |
|     }
 | |
|   }  
 | |
|   return _key_expr;
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::gestione_um(char tipo) const
 | |
| {
 | |
|   const char* const lco = "LCO";
 | |
|   int i;
 | |
| 
 | |
|   for (i = 0; i < 3 && toupper(tipo) != lco[i]; i++);
 | |
|   CHECK(i < 3, "Gestione unita' di misura errata");
 | |
|   TConfig ve(CONFIG_DITTA, "ve");
 | |
|   return ve.get_bool("GESUM", NULL, i+1);
 | |
| }
 | |
| 
 | |
| TRelation& TRicalcolo_mask::create_relation()
 | |
| {
 | |
|   const int logicnum = get_rec().num();   // Numero logico del file principale
 | |
|   if (_relation) 
 | |
|     delete _relation;
 | |
|   _relation = new TRelation(logicnum);
 | |
|   
 | |
|   const TString& unita_misura = get(F_UNITA_MISURA);
 | |
|   const TString& lingua       = get(F_LINGUA);
 | |
|   
 | |
|   const TString& tipo_lco     = get(F_TIPO_LCO);  // Listini, contratti, offerte
 | |
|   const TString& cat_ven      = get(F_CAT_VEN);
 | |
|   const TString& tipo_cf      = get(F_TIPO_CF);
 | |
|   const TString& codice_cf    = get(F_CODICE_CF);
 | |
|   const TString& codice_lco   = get(F_CODICE_LCO);
 | |
|   
 | |
|   TString condv_expr;
 | |
|   if (cat_ven.not_empty() && codice_cf.not_empty() && codice_lco.not_empty())
 | |
|   {
 | |
|     condv_expr << "TIPO=\""      << tipo_lco << '"'; 
 | |
|     condv_expr << "|CATVEN=\""   << cat_ven << '"';
 | |
|     condv_expr << "|TIPOCF=\""   << tipo_cf << '"';
 | |
|     condv_expr << "|CODCF=\""    << codice_cf << '"';
 | |
|     condv_expr << "|COD=\""      << codice_lco << '"';
 | |
|   }
 | |
|   
 | |
|   TString expr(48); 
 | |
|   
 | |
|   switch (logicnum)
 | |
|   {       
 | |
|   case LF_ANAMAG:
 | |
|     {
 | |
|       expr = "CODART=CODART";
 | |
|       if (unita_misura.not_empty())
 | |
|       {
 | |
|         expr << "|UM=\"" << unita_misura << '"'; 
 | |
|         _relation->add(LF_UMART, expr, 2);
 | |
|       }
 | |
|       else  
 | |
|         _relation->add(LF_UMART, expr, 1);
 | |
| 
 | |
|       if (lingua.not_empty())
 | |
|       {
 | |
|         expr = "CODART=CODART";
 | |
|         expr << "|CODLIN=\"" << lingua << '"'; 
 | |
|         _relation->add(LF_DESLIN, expr, 2);
 | |
|       }  
 | |
|       
 | |
|       if (condv_expr.not_empty())
 | |
|       {
 | |
|         _relation->add(LF_CONDV, condv_expr, 1);
 | |
|         
 | |
|         if (unita_misura.not_empty())
 | |
|         {
 | |
|           expr = condv_expr;
 | |
|           expr << "|TIPORIGA=\"A\"";
 | |
|           expr << "|CODRIGA=CODART";
 | |
|           expr << "|UM=\"" << unita_misura << '"';
 | |
|           _relation->add(LF_RCONDV, expr, 1);
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|     break;   
 | |
|   case LF_UMART:
 | |
|     {
 | |
|       _relation->add(LF_ANAMAG, "CODART=CODART", 1);
 | |
| 
 | |
|       if (lingua.not_empty())
 | |
|       {
 | |
|         expr = "CODART=CODART";
 | |
|         expr << "|CODLIN=\"" << lingua << '"'; 
 | |
|         _relation->add(LF_DESLIN, expr, 2);
 | |
|       }  
 | |
|       
 | |
|       if (condv_expr.not_empty())
 | |
|       {
 | |
|         _relation->add(LF_CONDV, condv_expr, 1);
 | |
|         expr = condv_expr;
 | |
|         expr << "|TIPORIGA=\"A\"";
 | |
|         expr << "|CODRIGA=CODART";
 | |
|         expr << "|UM=UM";
 | |
|         _relation->add(LF_RCONDV, expr, 1);
 | |
|       }
 | |
|     }  
 | |
|     break;   
 | |
|   case LF_DESLIN:
 | |
|     {
 | |
|       _relation->add(LF_ANAMAG, "CODART=CODART", 1);
 | |
| 
 | |
|       expr = "CODART=CODART";
 | |
|       if (unita_misura.not_empty())
 | |
|       {
 | |
|         expr << "|UM=\"" << unita_misura << '"'; 
 | |
|         _relation->add(LF_UMART, expr, 2);
 | |
|       }
 | |
|       else  
 | |
|         _relation->add(LF_UMART, expr, 1);
 | |
|       
 | |
|       if (condv_expr.not_empty())
 | |
|       {
 | |
|         _relation->add(LF_CONDV, condv_expr, 1);
 | |
| 
 | |
|         if (unita_misura.not_empty())
 | |
|         {                            
 | |
|           expr = condv_expr;
 | |
|           expr << "|TIPORIGA=\"A\"";
 | |
|           expr << "|CODRIGA=CODART";
 | |
|           expr << "|UM=\"" << unita_misura << '"';
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|     break;   
 | |
|   case LF_RCONDV:
 | |
|     {
 | |
|       _relation->add(LF_ANAMAG, "CODART=CODRIGA", 1);
 | |
|       
 | |
|       if (gestione_um(tipo_lco[0]))
 | |
|         _relation->add(LF_UMART, "CODART=CODRIGA|UM=UM", 2);
 | |
| 
 | |
|       if (lingua.not_empty())
 | |
|       {
 | |
|         expr = "CODART=CODRIGA";
 | |
|         expr << "|CODLIN=\"" << lingua << '"'; 
 | |
|         _relation->add(LF_DESLIN, expr, 2);
 | |
|       }  
 | |
|       
 | |
|       _relation->add(LF_RCONDV, "TIPO=TIPO|CATVEN=CATVEN|TIPOCF=TIPOCF|CODCF=CODCF|COD=COD", 1);    
 | |
|     }
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   return *_relation;
 | |
| }
 | |
| 
 | |
| TCursor& TRicalcolo_mask::create_cursor()
 | |
| {
 | |
|   TString filter = get(F_FILTER); filter.strip("\n");
 | |
|     
 | |
|   int key = get_int(F_KEY);
 | |
|     
 | |
|   TRectype start(get_rec()), stop(get_rec());
 | |
|   start.zero(); stop.zero(); 
 | |
|     
 | |
|   TToken_string& key_des = get_key_expr(key);
 | |
|     
 | |
|   TSheet_field& fs = (TSheet_field&)field(F_FIELDS);
 | |
|   TString16 field;
 | |
|   TString val;
 | |
|   
 | |
|   // I primi campi corrispondono alla chiave selezionata?
 | |
|   bool key_seq_from = key > 0;  
 | |
|   bool key_seq_to = key > 0;
 | |
|   
 | |
|   for (int r = 0; r < fs.items(); r++)
 | |
|   { 
 | |
|     TToken_string& row = fs.row(r);
 | |
|     field = row.get(0);
 | |
|     if (field.not_empty())
 | |
|     {
 | |
|       val = row.get();           // Limite inferiore
 | |
|       if (!val.blank())
 | |
|       {
 | |
|         if (key_seq_from && key_des.get_pos(field) == r) 
 | |
|           start.put(field, val);
 | |
|         else
 | |
|         {
 | |
|           key_seq_from = FALSE;
 | |
|           if (filter.not_empty()) filter << "&&";
 | |
|           filter << '(' << field << ">=\"" <<  val << "\")";
 | |
|         }  
 | |
|       }
 | |
|       else
 | |
|         key_seq_from = FALSE;  
 | |
| 
 | |
|       val = row.get();           // Limite superiore
 | |
|       if (!val.blank())
 | |
|       {
 | |
|         if (key_seq_to && key_des.get_pos(field) == r) 
 | |
|           stop.put(field, val);
 | |
|         else
 | |
|         {
 | |
|           key_seq_to = FALSE;
 | |
|           if (filter.not_empty()) filter << "&&";
 | |
|           filter << '(' << field << "<=\"" <<  val << "\")";
 | |
|         }  
 | |
|       }
 | |
|       else
 | |
|         key_seq_to = FALSE;  
 | |
|     }  
 | |
|     else 
 | |
|       key_seq_from = key_seq_to = FALSE;
 | |
|   }
 | |
|     
 | |
|   if (key <= 0) 
 | |
|     key = 1;   
 | |
|   
 | |
|   if (_cursor)
 | |
|     delete _cursor;
 | |
|   _cursor = new TCursor(&create_relation(), "", key, &start, &stop);
 | |
|   _cursor->setfilter(filter, filter.find("->") > 0);  // Update relation when needed
 | |
|   return *_cursor;
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::file_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
 | |
|   if (k == K_SPACE && m.is_running())
 | |
|   {
 | |
|     const int n = atoi(f.get());
 | |
|     if (n != m._cur_file)
 | |
|     {
 | |
|       m._cur_file = n;
 | |
|       const RecDes& rd = m.get_rec_des();
 | |
|       const int keys = rd.NKeys;
 | |
| 
 | |
|       TToken_string codes(16);
 | |
|       TToken_string values(80);
 | |
|       TString16 tmp;
 | |
|       codes.add(0);
 | |
|       values.add("Nessuna");
 | |
|       for (int k = 1; k <= keys; k++)
 | |
|       { 
 | |
|         codes.add(k);
 | |
|         tmp.format("Chiave %d", k);
 | |
|         values.add(tmp);
 | |
|       }
 | |
| 
 | |
|       TList_field& lk = m.lfield(F_KEY);
 | |
|       lk.replace_items(codes, values);
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| } 
 | |
| 
 | |
| bool TRicalcolo_mask::key_handler(TMask_field& f, KEY k)
 | |
| {             
 | |
|   if (k == K_SPACE)
 | |
|   {                           
 | |
|     TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
 | |
|     TSheet_field& sheet = (TSheet_field&)m.field(F_FIELDS);
 | |
|     if (m.is_running() || sheet.items() == 0)
 | |
|     {
 | |
|       const int cur_key = atoi(f.get());
 | |
|       TToken_string& key_expr = m.get_key_expr(cur_key);
 | |
|       const bool empty = key_expr.empty_items();
 | |
|       int first_enabled = 0;
 | |
|     
 | |
|       TString_array& sa = sheet.rows_array();
 | |
|       sa.destroy();                     
 | |
|       if (empty)
 | |
|       {
 | |
|         for (int i = 4; i >= 0; i--)
 | |
|           sa.add("");
 | |
|       }  
 | |
|       else
 | |
|       {  
 | |
|         TRelation_description& des = m.get_des();
 | |
|         for (TString field = key_expr.get(0); !field.blank(); field = key_expr.get())
 | |
|         {
 | |
|           const int r = sa.add(field);
 | |
|           sa.row(r).add(des.get_field_description(field), F_DESCR-F_FIELD);
 | |
|         }  
 | |
|         if (des.file_num() == LF_CONDV || des.file_num() == LF_RCONDV)
 | |
|         {
 | |
|           first_enabled = 4;
 | |
|           TToken_string& row = sa.row(0);
 | |
|           const TString& lco = m.get(F_TIPO_LCO);
 | |
|           row.add(lco, 1);
 | |
|           row.add(lco, 2);
 | |
|         }  
 | |
|       } 
 | |
|       
 | |
|       for (int r = sa.items()-1; r >= 0; r--)
 | |
|         sheet.enable_cell(0, -1, r >= first_enabled);   
 | |
|       
 | |
|       sheet.force_update();
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::test_formula(TMask_field& f) const
 | |
| {
 | |
|   TString filter(f.get()); filter.strip("\n");
 | |
|   TTable_expression expr;
 | |
|   bool ok = expr.set(filter, _strexpr);
 | |
|   if (ok)
 | |
|   {    
 | |
|     TString var;
 | |
|     for (int v = expr.numvar()-1; v >= 0; v--)
 | |
|     {
 | |
|       int logicnum = 0;
 | |
|       var = expr.varname(v); var.upper();
 | |
|       const int arrow = var.find("->");
 | |
|       if (arrow >= 0)
 | |
|       {
 | |
|         logicnum = expr.str2file(var);
 | |
|         var = var.mid(arrow+2);
 | |
|       }             
 | |
|       if (logicnum >= 0)
 | |
|       {
 | |
|         if (logicnum == 0)
 | |
|           ok = get_rec().exist(var);
 | |
|         else
 | |
|         {  
 | |
|           TLocalisamfile lf(logicnum);
 | |
|           ok = lf.curr().exist(var);
 | |
|         }  
 | |
|       }
 | |
|       else
 | |
|         ok = FALSE;  
 | |
|       if (!ok)
 | |
|       {       
 | |
|         f.error_box("Il campo '%s' non esiste!", (const char*)expr.varname(v));
 | |
|         break;
 | |
|       }       
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|     f.error_box("Simbolo non riconosciuto: '%s'", expr.last_token());
 | |
|   return ok;  
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::filter_handler(TMask_field& f, KEY k)
 | |
| {  
 | |
|   bool ok = TRUE;
 | |
|   if (f.to_check(k))
 | |
|   { 
 | |
|     TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
 | |
|     ok = m.test_formula(f);
 | |
|   }  
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::field_handler(TMask_field& f, KEY k)
 | |
| {     
 | |
|   bool ok = TRUE;      
 | |
|   switch (k)
 | |
|   {       
 | |
|   case K_TAB:
 | |
|   case K_ENTER:
 | |
|     if (!f.empty() && f.to_check(k))
 | |
|     {                         
 | |
|       const TSheet_field& s = *f.mask().get_sheet();
 | |
|       TRicalcolo_mask& rm = (TRicalcolo_mask&)s.mask();
 | |
|       const TRectype& rec = rm.get_rec();        
 | |
|       const TString16 field = f.get();
 | |
|       if (!rec.exist(field))
 | |
|         ok = f.error_box("Il campo '%s' non esiste.", (const char*)field);
 | |
|       if (ok && s.dlg() == F_OUTPUTS)  
 | |
|       {
 | |
|         TToken_string& ke = rm.get_key_expr(1);
 | |
|         if (ke.get_pos(field) >= 0)
 | |
|           ok = f.error_box("Non e' possibile modificare un campo chiave.");
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   case K_F9:
 | |
|     {                                                      
 | |
|       TMask& m = f.mask();
 | |
|       TRicalcolo_mask& rm = (TRicalcolo_mask&)m.get_sheet()->mask();
 | |
|       TRelation_description& rd = rm.get_des();
 | |
|       if (rd.choose_field(f.get()))
 | |
|       {
 | |
|         f.set(rd.field_name());
 | |
|         m.set(F_DESCR, rd.field_desc());
 | |
|       }  
 | |
|     }
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| HIDDEN void swap_tokens(TToken_string& str, int p1, int p2)
 | |
| {
 | |
|   const TString16 s1 = str.get(p1);
 | |
|   const TString16 s2 = str.get(p2);
 | |
|   str.add(s1, p2);
 | |
|   str.add(s2, p1);
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::fromto_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   bool ok = TRUE;
 | |
|   if (f.to_check(k))
 | |
|   {                        
 | |
|     const TMask& m = f.mask();
 | |
|     const TString& field = m.get(F_FIELD);
 | |
|     if (field.not_empty())
 | |
|     {
 | |
|       TRicalcolo_mask& rm = (TRicalcolo_mask&)m.get_sheet()->mask();
 | |
|       const TRectype& rec = rm.get_rec();        
 | |
|       const int max = rec.length(field);
 | |
|       if (f.get().len() > max)
 | |
|       {
 | |
|         TString msg(32); msg = "Inserire ";
 | |
|         if (max > 1) msg << max; else msg << "un";
 | |
|         msg << " caratter" << (max > 1 ? 'i' : 'e') << " al massimo.";
 | |
|         ok = f.error_box(msg); 
 | |
|       }                   
 | |
|     }  
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (k == K_F9)
 | |
|     {             
 | |
|       const TMask& m = f.mask();
 | |
|       TSheet_field& s = *m.get_sheet();
 | |
|       TRicalcolo_mask& rm = (TRicalcolo_mask&)s.mask();
 | |
|       TRelation& rel = rm.get_rel();       
 | |
|       TRectype& rec = rel.curr();
 | |
|       TRelation_description& des = rm.get_des();
 | |
|       
 | |
|       const TString title = des.file_desc();
 | |
|       
 | |
|       TToken_string fields(256), head(256);
 | |
|       TString tmp;
 | |
|       for (int i = 0; i < rec.items(); i++)
 | |
|       { 
 | |
|         tmp = rec.fieldname(i);
 | |
|         fields.add(tmp);  
 | |
|         
 | |
|         int lun = rec.length(tmp);
 | |
|         bool right = FALSE;
 | |
|         switch(rec.type(tmp))
 | |
|         {          
 | |
|         case _alfafld:
 | |
|         case _memofld:            
 | |
|           if (lun > 50) lun = 50;
 | |
|           break;
 | |
|         case _charfld:
 | |
|         case _boolfld:
 | |
|           break;       
 | |
|         case _datefld:
 | |
|           lun = 10;
 | |
|           break;  
 | |
|         default:
 | |
|           right = TRUE;
 | |
|           break;
 | |
|         }
 | |
|         tmp.lower(); tmp[0] = toupper(tmp[0]);
 | |
|         if (lun > tmp.len())
 | |
|         {
 | |
|           tmp << '@' << lun;
 | |
|           if (right) tmp << 'R';
 | |
|         }  
 | |
|         else
 | |
|         {
 | |
|           if (right)
 | |
|             tmp << "@R";
 | |
|         }    
 | |
|         head.add(tmp);
 | |
|       }        
 | |
|       
 | |
|       const int key = rm.get_int(F_KEY);
 | |
|       if (key > 0)
 | |
|       {
 | |
|         TToken_string& key_des = rm.get_key_expr(key);
 | |
|         int pos = 0;
 | |
|         for (TString c = key_des.get(0); c.not_empty(); c = key_des.get(), pos++)
 | |
|         {
 | |
|           const int p = fields.get_pos(c);
 | |
|           if (p != pos)
 | |
|           {
 | |
|             swap_tokens(fields, p, pos);
 | |
|             swap_tokens(head, p, pos);
 | |
|           }  
 | |
|         }
 | |
|       }
 | |
|       
 | |
|       TEdit_field& e = (TEdit_field&)f;
 | |
|  
 | |
|       TToken_string siblings;
 | |
|       siblings.add(e.dlg());
 | |
|       tmp = fields.get(0);
 | |
|       tmp = des.get_field_description(tmp);
 | |
|       if (tmp.len() > 30)
 | |
|       {
 | |
|         tmp.cut(27);
 | |
|         tmp << "...";
 | |
|       }  
 | |
|       siblings.add(tmp);
 | |
| 
 | |
|       TCursor cur(&rel, "", key > 0 ? key : 1);
 | |
|       TBrowse_sheet sheet(&cur, fields, title, head, 0, e, siblings);
 | |
|       if (sheet.run() == K_ENTER)
 | |
|       {
 | |
|         const TString16 field = s.row(s.selected()).get(0);
 | |
|         if (field.not_empty())
 | |
|         {                    
 | |
|           const TRectype& rec = cur.curr();
 | |
|           if (rec.exist(field))
 | |
|           {
 | |
|             cur = sheet.selected();
 | |
|             f.set(rec.get(field));
 | |
|           }  
 | |
|         }  
 | |
|       }
 | |
|     }
 | |
|   }  
 | |
|   return ok;   
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::formula_handler(TMask_field& f, KEY k)
 | |
| {  
 | |
|   bool ok = TRUE;
 | |
|   if (f.to_check(k))
 | |
|   { 
 | |
|     TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask().get_sheet()->mask();
 | |
|     ok = m.test_formula(f);
 | |
|   }  
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Ciclo principale di elaborazione
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| HIDDEN bool rewrite_cursor(TCursor& cur)
 | |
| {
 | |
|   bool ok = cur.lock(_lock) == NOERR;
 | |
|   if (ok)
 | |
|   {
 | |
|     ok = cur.relation()->rewrite() == NOERR;   
 | |
|     cur.lock(_unlock);
 | |
|   }  
 | |
|   if (!ok)
 | |
|     error_box("Impossibile aggiornare il record %ld.", cur.pos());
 | |
|   return ok;  
 | |
| }
 | |
| 
 | |
| bool TRicalcolo_mask::elabora()
 | |
| {
 | |
|   TString16 var;                   // Nome di campo
 | |
|   TString val(80);                 // Valore di campo
 | |
|   TString line(128);               // Linea di testo
 | |
| 
 | |
|   TIndwin iw(48, "Inizializzazione ...", TRUE, FALSE, 48);
 | |
|   begin_wait();
 | |
| 
 | |
|   TCursor& cur = create_cursor();  // Crea e filtra il cursore principale
 | |
|   
 | |
|   TSheet_field& osf = (TSheet_field&)field(F_OUTPUTS);
 | |
|   TArray expr;
 | |
|   for (int r = 0; r < osf.items(); r++)  
 | |
|   {                         
 | |
|     TToken_string& riga = osf.row(r);
 | |
|     var = riga.get(0);              
 | |
|     if (var.not_empty())
 | |
|     {
 | |
|       TTypeexp tipo = _strexpr;
 | |
|       switch(cur.curr().type(var))
 | |
|       {
 | |
|         case _alfafld:
 | |
|         case _datefld:
 | |
|         case _memofld:
 | |
|           tipo = _strexpr;
 | |
|           break;
 | |
|         default:  
 | |
|           tipo = _numexpr;
 | |
|           break;     
 | |
|       }    
 | |
|       line = riga.get(2);
 | |
|       TTable_expression* e = new TTable_expression;
 | |
|       e->set(line, tipo);
 | |
|       expr.add(e);
 | |
|     }
 | |
|   }  
 | |
|   TToken_string& key_expr = get_key_expr(cur.key());     
 | |
|     
 | |
|   TViswin vw(NULL, "Ricalcolo valori", FALSE, TRUE, FALSE, 0, 0, 0, 0, FALSE);
 | |
| 
 | |
|   iw.close_modal();
 | |
|   end_wait();
 | |
|   
 | |
|   if (iw.iscancelled())           
 | |
|     return FALSE;
 | |
| 
 | |
|   TTable_expression::set_relation(cur.relation());
 | |
|   TTable_expression::set_window(&vw);
 | |
|   TTable_expression::reset_errors();
 | |
| 
 | |
|   vw.maximize();
 | |
|   vw.open_modal();
 | |
|   
 | |
|   bool ok = TRUE;
 | |
|   
 | |
|   const TRecnotype items = cur.items();
 | |
|   cur.freeze();
 | |
|   for (cur = 0; cur.pos() < items; ++cur)           
 | |
|   { 
 | |
|     line.format("#@b%7ld@r - ", cur.pos()+1);
 | |
|     const TRectype& curr = cur.curr();
 | |
|     for (const char* f = key_expr.get(0); f; f = key_expr.get())
 | |
|       line << curr.get(f) << ' ';
 | |
|     vw.add_line(line);
 | |
|     
 | |
|     for (int r = 0; r < osf.items(); r++)  
 | |
|     {
 | |
|       var = osf.row(r).get(0);              
 | |
|       if (var.not_empty())
 | |
|       {
 | |
|         TTable_expression& e = (TTable_expression&)expr[r];
 | |
|         for (int v = e.numvar()-1; v >= 0; v--)
 | |
|         {
 | |
|           var = e.varname(v);
 | |
|           val = e.get_field(var);
 | |
|           if (e.type() == _numexpr)                             
 | |
|             e.setvar(var, real(val));
 | |
|           else
 | |
|             e.setvar(var, val);
 | |
|         }
 | |
|         var = osf.row(r).get(0);
 | |
|         val = e;
 | |
|         
 | |
|         if (e.errors_found())
 | |
|           ok = FALSE;
 | |
|         else  
 | |
|           cur.curr().put(var, val);
 | |
|   
 | |
|         line.format("- %-10s = %s", (const char*)var, (const char*)val);  
 | |
|         vw.add_line(line);
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   TTable_expression::set_relation(NULL);
 | |
|   TTable_expression::set_window(NULL);
 | |
| 
 | |
|   vw.close_print();
 | |
|   vw.run();
 | |
|   vw.close_modal();
 | |
|   
 | |
|   if (get_bool(F_SAVE))
 | |
|   {      
 | |
|     TString msg(80);
 | |
|     if (!ok)
 | |
|       msg = "Sono stati riscontrati degli errori di calcolo:\n";
 | |
|     msg << "Si desidera aggiornare effettivamente l'archivio?";
 | |
|     ok = yesno_box(msg);
 | |
|     if (ok)
 | |
|     {
 | |
|       TTextfile& txt = vw.text();
 | |
|       
 | |
|       TProgind piw(txt.lines(), "Aggiornamento archivio", FALSE, TRUE, 48);
 | |
|       
 | |
|       bool do_rewrite = FALSE;
 | |
|       long pos = 0;
 | |
|       cur = 0L;
 | |
|       for (long r = 0; r < txt.lines(); r++)
 | |
|       {   
 | |
|         piw.addstatus(1);
 | |
|         line = txt.line(r);
 | |
|         if (line[0] == '#' && sscanf(line, "#%ld", &pos) == 1)
 | |
|         {                      
 | |
|           if (do_rewrite)
 | |
|           {
 | |
|             rewrite_cursor(cur);
 | |
|             do_rewrite = FALSE;
 | |
|           }
 | |
|           cur = pos-1;  // pos a video = 1 -> pos cursore = pos-1 = 0)
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           if (line[0] == '-' && sscanf(line, "- %s =", var.get_buffer()) == 1)
 | |
|           {
 | |
|             const char* equal = strchr(line, '=');
 | |
|             if (equal)
 | |
|             {
 | |
|               val = equal+2; 
 | |
|               cur.curr().put(var, val);
 | |
|               do_rewrite = TRUE;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       if (do_rewrite)
 | |
|         rewrite_cursor(cur);
 | |
|     }
 | |
|   }
 | |
|   cur.freeze(FALSE);
 | |
|   
 | |
|   return TRUE;           
 | |
| }    
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Ricalcolo di magazzino
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TRicalcola_application : public TApplication
 | |
| {   
 | |
| protected:
 | |
|   virtual bool menu(MENU_TAG);
 | |
|   virtual bool create();
 | |
|   
 | |
| public:
 | |
|   // @cmember Disabilita la verifica del modulo in chiave
 | |
|   virtual bool check_autorization() const 
 | |
|   {return FALSE;}
 | |
|   TRicalcola_application() { }
 | |
|   virtual ~TRicalcola_application() { }
 | |
| };
 | |
| 
 | |
| bool TRicalcola_application::create()
 | |
| {
 | |
|   dispatch_e_menu(MENU_ITEM_ID(1));
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TRicalcola_application::menu(MENU_TAG)
 | |
| {
 | |
|   TRicalcolo_mask m;
 | |
|   m.open();
 | |
|   while (m.run() == K_ENTER)
 | |
|     m.elabora();
 | |
|   m.close();
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| int ve4100(int argc, char* argv[])
 | |
| {              
 | |
|   TRicalcola_application r;
 | |
|   r.run(argc, argv, "Ricalcolo valori");
 | |
|   return 0;
 | |
| }
 |