Files correlati : Ricompilazione Demo : [ ] Commento : aggiunte xvt_chr_is_digit, xvt_chr_is_alpha e xvt_chr_is_alnum git-svn-id: svn://10.65.10.50/trunk@14717 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			5328 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			5328 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #define XI_INTERNAL           
 | |
| #include <xinclude.h>
 | |
| 
 | |
| #include <automask.h>
 | |
| #include <colors.h>
 | |
| #include <controls.h>
 | |
| #include <diction.h>
 | |
| #include <execp.h>
 | |
| #include <expr.h>
 | |
| #include <msksheet.h>
 | |
| #include <prefix.h> 
 | |
| #include <recarray.h>
 | |
| #include <recset.h>
 | |
| #include <relapp.h>
 | |
| #include <relation.h>
 | |
| #include <sheet.h>
 | |
| #include <tabutil.h>
 | |
| #include <text.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h>
 | |
| #include <validate.h>
 | |
| #include <xvtility.h>
 | |
| 
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @func HIDDEN void | smart_trim | Elimina gli spazi iniziali e/o finali da un stringa
 | |
| HIDDEN void smart_trim(
 | |
|             TString & s, // @parm Stringa
 | |
|             byte mode    // @parm operazione da effettuare ( 0 = nessuna operazione
 | |
|                          //       1 = trimma a sinistra
 | |
|                          //       2 = trimma a destra
 | |
|                          //       3 = trimma da entrambi i lati
 | |
|                        )
 | |
| 
 | |
| {
 | |
|   switch (mode)
 | |
|   {
 | |
|     case  1: s.ltrim(); break;
 | |
|     case  2: s.rtrim(); break;
 | |
|     case  3: s.trim(); break;
 | |
|     default: break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Field Flags
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field::TField_Flags::TField_Flags()
 | |
| {
 | |
|   automagic = persistent   = FALSE;
 | |
|   enabled = enable_default = TRUE;
 | |
|   shown = show_default     = TRUE;
 | |
|   uppercase = rightjust    = FALSE;
 | |
|   zerofilled = button      = FALSE;
 | |
|   dirty = focusdirty       = FALSE;
 | |
|   roman = read_only        = FALSE;
 | |
|   firm = ghost             = FALSE;
 | |
|   password                 = FALSE;
 | |
|   trim                     = 3;
 | |
|   pipeallowed              = FALSE;    
 | |
|   user                     = FALSE;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| char TMask_field::TField_Flags::update(const char* f, bool reset)
 | |
| {
 | |
| 	const char * s;
 | |
|   for (s = f; *s; s++)
 | |
|     switch(*s)
 | |
|     {
 | |
|     case '#':
 | |
|       trim = 2; break;
 | |
|     case '@':
 | |
|       trim = 1; break;
 | |
|     case ' ':  
 | |
|     case '_':
 | |
|       trim = 0; break;  
 | |
|     case '*':
 | |
|       password = !reset; break;
 | |
|     case 'A':
 | |
|       automagic = persistent = !reset; break;
 | |
|     case 'B':
 | |
|       button = !reset; break;
 | |
|     case 'D': 
 | |
|       enable_default = enabled = reset; break;
 | |
|     case 'F': 
 | |
|       firm = persistent = !reset; break;
 | |
|     case 'G': 
 | |
|       ghost = !reset; break;
 | |
|     case 'H': 
 | |
|       show_default  = shown = reset; break;
 | |
|     case 'I': 
 | |
|       break; // reserved for sheetfield insert
 | |
| 	  case 'L': 
 | |
| 			read_only = reset; break;
 | |
|     case 'M': 
 | |
|       roman = !reset; break;
 | |
|     case 'P': 
 | |
|       persistent = !reset; break;
 | |
|     case 'R': 
 | |
|       rightjust = !reset; break;
 | |
|     case 'T': 
 | |
|       user = !reset; break;
 | |
|     case 'U': 
 | |
|       uppercase = !reset; break;
 | |
|     case 'Z': 
 | |
|       zerofilled = !reset; break;
 | |
|     default :  
 | |
|       break;
 | |
|     }
 | |
|   return *s;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TMask_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TMask_field::TControl_data TMask_field::_ctl_data;
 | |
| 
 | |
| void TMask_field::TControl_data::reset()
 | |
| {
 | |
|   _dlg = -1;
 | |
|   _x = _y = -1;
 | |
|   _width = 0;
 | |
|   _height = 1;
 | |
|   _size = 0;
 | |
|   _decimals = 0;
 | |
|   _bmp_up = _bmp_dn = 0;
 | |
|   _prompt.cut(0);
 | |
|   _flags.cut(0);
 | |
|   _park.spaces(256);
 | |
|   _park.cut(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::update_flags(const char* f, bool reset)
 | |
| {
 | |
|   _flags.update(f, reset);
 | |
|   show(shown());
 | |
|   enable(enabled());                                    
 | |
| }
 | |
| 
 | |
| TMask_field::TMask_field(TMask* m)
 | |
|            : _mask(m), _groups(NULL), _ctl(NULL)
 | |
| {
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field::~TMask_field()
 | |
| {
 | |
|   if (_ctl) delete _ctl;
 | |
|   if (_groups) delete _groups;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| const char* TMask_field::class_name() const
 | |
| { return "Field"; }
 | |
| 
 | |
| // Certified 100%
 | |
| word TMask_field::class_id() const
 | |
| { return CLASS_FIELD; }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_FIELD || TObject::is_kind_of(cid); }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::ok() const
 | |
| { return _ctl != NULL; }
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::parse_head(TScanner&)
 | |
| {}                                                  
 | |
| 
 | |
| short TMask_field::dlg() const 
 | |
| { 
 | |
|   return _ctl ? _ctl->id() : _ctl_data._dlg; 
 | |
| }
 | |
| 
 | |
| void TMask_field::highlight() const
 | |
| { 
 | |
| #ifdef DBG
 | |
|   yesnofatal_box("Can't set the focus to non-operable field %d", dlg());
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TMask_field::set_focus() const
 | |
| {                                                
 | |
| #ifdef DBG
 | |
|   yesnofatal_box("Can't set the focus to non-operable field %d", dlg());
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TMask_field::set_justify(bool r) 
 | |
| { 
 | |
|   _flags.rightjust = r;
 | |
|   if (_ctl)
 | |
|     _ctl->set_rjust(r);
 | |
| }
 | |
| 
 | |
| void TMask_field::set_read_only(bool r) 
 | |
| { 
 | |
| 	_flags.read_only = r && !in_key(1);
 | |
| 	if (_ctl)
 | |
| 		_ctl->set_read_only(_flags.read_only);
 | |
| }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // Certified 100%     
 | |
| // @mfunc Converte una stringa in un identificatore di campo.
 | |
| short TMask_field::atodlg(
 | |
|   const char* s) const       // @parm stringa da convertire in numero
 | |
| // @comm  In modo DBG controlla anche che sia un numero valido
 | |
| {
 | |
|   short d = s ? atoi(s) : 0;
 | |
| 
 | |
| #ifdef DBG
 | |
|   if (d == 0 || d < -1 || d > 1000)
 | |
|   {
 | |
|     yesnofatal_box("Identificatore non valido nel campo %d: '%s'", _ctl_data._dlg, s);
 | |
|     d = DLG_NULL;
 | |
|   }
 | |
| #endif  
 | |
| 
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Costruisce il campo
 | |
| void TMask_field::construct(
 | |
|   short id,            // @parm Identificatore del campo
 | |
|   const char* prompt,  // @parm Prompt del campo
 | |
|   int x,               // @parm Posizione in x (in caratteri) del campo nella maschera
 | |
|   int y,               // @parm Posizione in y (in caratteri) del campo nella maschera
 | |
|   int len,             // @parm Lunghezza del buffer campo
 | |
|   WINDOW parent,       // @parm Finestra padre alla quale assegnare il campo
 | |
|   const char* flags,   // @parm Flags del campo (default "")
 | |
|   int width)           // @parm Lunghezza a video del campo
 | |
|   // @parm TScanner& | scanner | File dal quale leggere leggere le informazioni
 | |
| 
 | |
|   // @syntax void construct(TScanner& scanner, WINDOW parent);  
 | |
|   // @syntax void construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags, int width);
 | |
|   //                            
 | |
|   // @comm E' possibile costruire il campo leggendo direttamente dal file, oppure passare alla funzione
 | |
|   //                     tutti i parametri necessari alla definizione del campo stesso
 | |
| {          
 | |
|   _ctl_data.reset();
 | |
|   _ctl_data._x = x; 
 | |
|   _ctl_data._y = y;
 | |
|   _ctl_data._prompt = prompt;
 | |
|   _ctl_data._size = len;
 | |
|   switch(class_id())
 | |
|   {
 | |
|   case CLASS_REAL_FIELD:
 | |
|     ((TReal_field*)this)->set_decimals(width);
 | |
|     _ctl_data._width = len;
 | |
|     break;          
 | |
|   case CLASS_BUTTON_FIELD:
 | |
|     _ctl_data._height = len;
 | |
|     _ctl_data._width = width <= 0 ? 12 : width;
 | |
|     break;
 | |
|   case CLASS_MEMO_FIELD:
 | |
|   case CLASS_TREE_FIELD:
 | |
|     _ctl_data._height = len;
 | |
|     _ctl_data._width  = width;
 | |
|     _ctl_data._size   = len * width;
 | |
|     break;  
 | |
|   default: 
 | |
|     _ctl_data._width = width == 0 ? len : width;
 | |
|     break;
 | |
|   }  
 | |
|   
 | |
|   _ctl_data._dlg = id;
 | |
|   
 | |
|   _ctl_data._flags = flags;
 | |
|   _flags.update(flags);
 | |
| 
 | |
|   create(parent);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::construct(TScanner& scanner, WINDOW parent)
 | |
| { 
 | |
|   _ctl_data.reset();
 | |
|   _ctl_data._dlg = atodlg(scanner.pop());
 | |
| 
 | |
|   parse_head(scanner);
 | |
|   
 | |
|   scanner.popkey();                 // BEGIN
 | |
| #ifdef DBG 
 | |
|   if (scanner.key() != "BE")          
 | |
|   {
 | |
|     NFCHECK("Testata errata o BEGIN mancante nel campo %d", _ctl_data._dlg);
 | |
|     scanner.push();
 | |
|   }
 | |
|   if (_ctl_data._dlg > 0)
 | |
|   {              
 | |
|     const TMask& m = mask();
 | |
|     for (int f = m.fields()-1; f >= 0; f--)
 | |
|     {                                       
 | |
|       const TMask_field& mf = m.fld(f);
 | |
|       if (mf.dlg() == _ctl_data._dlg && mf.parent() == parent)
 | |
|         NFCHECK("Esistono due campi con identificatore %d", _ctl_data._dlg);
 | |
|     }
 | |
|   }      
 | |
| #endif          
 | |
| 
 | |
|   while(scanner.popkey() != "EN")       // END of control
 | |
|     parse_item(scanner);
 | |
| 
 | |
|   create(parent);
 | |
| }
 | |
| 
 | |
| void TMask_field::destroy()
 | |
| {
 | |
|   _ctl->destroy();
 | |
| }
 | |
| 
 | |
| void TMask_field::set_group(byte group) 
 | |
| { 
 | |
|   if (_groups == NULL) 
 | |
|     _groups = new TBit_array;
 | |
|   _groups->set(long(group)); 
 | |
|   _groups->set(0L);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TMask_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PR")                    // PROMPT
 | |
|   {
 | |
|     _ctl_data._x      = scanner.integer();
 | |
|     _ctl_data._y      = scanner.integer();
 | |
|     _ctl_data._prompt = dictionary_translate_prompt(scanner.string(), is_editable() ? 0 : -1);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "FL")                    // FLAGS
 | |
|   {
 | |
|     const char* f = scanner.string();
 | |
|     if (_flags.update(f) == '\0')
 | |
|       _ctl_data._flags << f;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "GR")
 | |
|   {        
 | |
|     if (_groups == NULL)
 | |
|       _groups = new TBit_array;
 | |
|     _groups->set(scanner.line());
 | |
|     
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   NFCHECK("'%s' Token non riconosciuto nel campo %d: %s", 
 | |
|           (const char*)scanner.token(), (int)dlg(), (const char*)_ctl_data._prompt);
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| WINDOW TMask_field::parent() const
 | |
| {             
 | |
|   CHECK(_ctl, "Can't get the parent of a NULL control");
 | |
|   return _ctl->parent(); 
 | |
| }
 | |
| 
 | |
| RCT& TMask_field::get_rect(RCT& r) const
 | |
| {
 | |
|   if (_ctl) _ctl->get_rect(r);
 | |
|   else memset(&r, 0, sizeof(r));
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| void TMask_field::set_rect(const RCT& r)
 | |
| {
 | |
|   if (_ctl) _ctl->set_rect(r);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Abilita/disabilita il campo (lo rende scrivibile)
 | |
| void TMask_field::enable(
 | |
|   bool on) // @parm Operazione da svolgere:
 | |
|   //
 | |
|   // @flag TRUE | Abilita il campo (default)
 | |
|   // @flag FALSE | Disabilita il campo
 | |
| {
 | |
|   _flags.enabled = on;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::enable_default()
 | |
| {
 | |
|   const bool ed = _flags.enable_default;
 | |
|   enable(ed);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Permette di rendere visibile/invisibile un campo
 | |
| void TMask_field::show(
 | |
|   bool on) // @parm Operazione da svolgere:
 | |
|   //
 | |
|   // @flag TRUE | Rendere visibile il campo (default)
 | |
|   // @flag FALSE | Rendere invisibile il campo
 | |
| {
 | |
|   if (_ctl) 
 | |
|   {
 | |
|     _ctl->show(on);
 | |
|     _flags.shown = on;
 | |
|   }  
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::show_default()
 | |
| {          
 | |
|   const bool sd = _flags.show_default;
 | |
|   show(sd);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::active() const
 | |
| {
 | |
|   return is_operable() && enabled() && shown() && !read_only();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::set_dirty(byte d) 
 | |
| {                
 | |
|   if (_flags.dirty == 3)
 | |
|   {
 | |
|     if (d == FALSE)     // Non permette di annullare il dirty dei campi errati
 | |
|       return;
 | |
|   }    
 | |
| #ifdef DBG
 | |
|   if (d == 3)
 | |
|     _flags.dirty = d;   // Riga per breakpoint
 | |
| #endif  
 | |
|   _flags.dirty = d; 
 | |
|   set_focusdirty(d != 0); 
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| const char* TMask_field::prompt() const
 | |
| {
 | |
|   return _ctl ? _ctl->caption() : "";
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::reset()
 | |
| {                      
 | |
|   if (!_flags.persistent)
 | |
|     set("");
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::set_prompt(const char* p)
 | |
| {                           
 | |
|   if (_ctl) _ctl->set_caption(p);
 | |
| }
 | |
| 
 | |
| int TMask_field::page() const
 | |
| {
 | |
| 	return _mask->win2page(parent());
 | |
| }
 | |
| 
 | |
| void TMask_field::set(const char*)
 | |
| { 
 | |
| }
 | |
| 
 | |
| void TMask_field::set(long n)
 | |
| {
 | |
|   char s[16]; sprintf(s, "%ld", n);
 | |
|   set(s);
 | |
| }
 | |
| 
 | |
| const TString& TMask_field::get() const
 | |
| {        
 | |
|   return _ctl_data._park.cut(0);
 | |
| }
 | |
| 
 | |
| void TMask_field::set_default(const char*)
 | |
| { 
 | |
|   NFCHECK("Only loadables can have a default"); 
 | |
| }
 | |
| 
 | |
| const TString& TMask_field::get_default() const
 | |
| { 
 | |
|   NFCHECK("Only loadables can have a default");
 | |
|   return EMPTY_STRING; 
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Verifica se il campo deve essere sottoposto a check
 | |
| //
 | |
| // @rdesc Ritorna il risultato:
 | |
| //
 | |
| // @flag TRUE | Se il campo e' da sottoporre a check
 | |
| // @flag FALSE | Se il campo non e' da sottoporre check
 | |
| bool TMask_field::to_check(
 | |
|   KEY k,               // @parm Tasto da passare al campo come simulazione di inizio controllo
 | |
|   bool checkrun) const // @parm Permette di ritornare TRUE se la maschera e' in start_run() mode
 | |
| {   
 | |
|   bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty());
 | |
|   
 | |
|   if (!yes && checkrun)
 | |
|     yes = k == K_TAB && !mask().is_running();
 | |
|   
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| void TMask_field::send_key(KEY k, short to) 
 | |
| { 
 | |
|   _mask->send_key(k, to, this); 
 | |
| }
 | |
| 
 | |
| void TMask_field::check_type(CheckType)
 | |
| { CHECK(0, "Can't set check type to non-edit field"); }
 | |
| 
 | |
| 
 | |
| void TMask_field::set_handler(CONTROL_HANDLER)
 | |
| { CHECK(0, "Can't set the handler to a TMask_field"); }
 | |
| 
 | |
| 
 | |
| bool TMask_field::on_hit()
 | |
| { 
 | |
|   CHECK(0, "Can't hit non-operable field"); 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::on_key(KEY key)
 | |
| {
 | |
| #ifdef DBG  
 | |
|   if (key > (K_CTRL+K_SPACE))
 | |
|     return error_box("Tasto ignorato %d", key);
 | |
| #endif      
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| #define build_msg() char* _msg = (char*)(const char*)_ctl_data._park;va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr)
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Crea una error-box relativo al campo (chiama <f error_box>)
 | |
| //
 | |
| // @rdesc Ritorna sempre FALSE
 | |
| bool TMask_field::error_box(
 | |
|   const char* fmt,  // @parm Formato della stringa da scrivere
 | |
|   ...) const        // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
 | |
|   
 | |
|   // @comm Se il campo e'       uno sheet viene aggiornata la barra di stato, altrimenti
 | |
|   //             viene creata una finestra di errore normale.
 | |
|   
 | |
| {
 | |
|   build_msg();
 | |
|   if (mask().is_sheetmask() && !mask().is_running())
 | |
|   {                    
 | |
|     xvt_dm_post_speech(_msg, 0, TRUE);
 | |
|     xvtil_statbar_set(_msg);
 | |
|     beep();
 | |
|   }  
 | |
|   else
 | |
|   {
 | |
|     mask().post_error_message(_msg, 3);
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| bool TMask_field::message_box(const char* fmt, ...) const
 | |
| {            
 | |
|   build_msg();
 | |
|   mask().post_error_message(_msg, 1);
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Crea una warning-box relativo al campo (chiama <f warning_box>)
 | |
| //
 | |
| // @rdesc Ritorna sempre FALSE
 | |
| bool TMask_field::warning_box(
 | |
|   const char* fmt,  // @parm Formato della stringa da scrivere
 | |
|   ...) const        // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
 | |
|   
 | |
|   // @comm Se il campo e'       uno sheet viene aggiornata la barra di stato, altrimenti
 | |
|   //             viene creata una finestra di warning normale.
 | |
| {                         
 | |
|   build_msg();
 | |
|   
 | |
|   if (mask().is_sheetmask() && !mask().is_running())
 | |
|   {
 | |
|     xvt_dm_post_speech(_msg, 1, TRUE);
 | |
|     xvtil_statbar_set(_msg);
 | |
|     beep();
 | |
|   }  
 | |
|   else
 | |
|   {
 | |
|     mask().post_error_message(_msg, 2);
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| bool TMask_field::yesno_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   set_focus();
 | |
|   build_msg();
 | |
|   const bool yes = ::yesno_box("%s", _msg);
 | |
|   set_focus();
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| KEY TMask_field::yesnocancel_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   set_focus();
 | |
|   build_msg();
 | |
|   const KEY k = ::yesnocancel_box("%s", _msg);
 | |
|   set_focus();
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TText_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| word TText_field::class_id() const
 | |
| { return CLASS_TEXT_FIELD; }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TText_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_TEXT_FIELD || TMask_field::is_kind_of(cid); }
 | |
| 
 | |
| // Certified 100%
 | |
| void TText_field::create(WINDOW parent)
 | |
| {
 | |
|   _ctl = new TText_control(parent, _ctl_data._dlg,
 | |
|                            _ctl_data._x, _ctl_data._y,  
 | |
|                            0, 1, 
 | |
|                            _ctl_data._flags, _ctl_data._prompt);
 | |
| }
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TGroup_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| word TGroup_field::class_id() const
 | |
| { return CLASS_GROUPBOX_FIELD; }
 | |
| 
 | |
| TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask)
 | |
| {
 | |
|   _flags.persistent = TRUE;
 | |
| }
 | |
| 
 | |
| // _size means _heigth
 | |
| void TGroup_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._width = scanner.integer();
 | |
|   _ctl_data._size  = scanner.integer();
 | |
| }
 | |
| 
 | |
| void TGroup_field::create(WINDOW parent)
 | |
| {
 | |
|   _ctl = new TGroupbox_control(parent, _ctl_data._dlg,
 | |
|                                _ctl_data._x, _ctl_data._y,  
 | |
|                                _ctl_data._width, _ctl_data._size, 
 | |
|                                _ctl_data._flags, _ctl_data._prompt);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TOperable_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TOperable_field::TOperable_field(TMask* m)
 | |
|                : TMask_field(m), _message(NULL), _handler(NULL)
 | |
| { }               
 | |
| 
 | |
| TOperable_field::~TOperable_field()
 | |
| { 
 | |
|   if (_message) delete _message;
 | |
| }               
 | |
| 
 | |
| TToken_string* TOperable_field::message(int m, bool crea)
 | |
| { 
 | |
|   TToken_string* msg = _message ? _message->rowptr(m) : NULL; 
 | |
|   if (msg == NULL && crea)
 | |
|   {
 | |
|     if (_message == NULL) 
 | |
|       _message = new TString_array(2);
 | |
|     msg = new TToken_string(16);
 | |
|     _message->add(msg, m);
 | |
|   }
 | |
|   return msg;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TOperable_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "HE")                    // HELP
 | |
|   {
 | |
|     scanner.string();                           // Ignored from this version
 | |
|     return TRUE;
 | |
|   } 
 | |
|   
 | |
|   if (scanner.key() == "ME")
 | |
|   {
 | |
|     const TString& m = scanner.line().trim(); // Togli spazi
 | |
|     message(0, TRUE)->add(m);
 | |
|     return TRUE;
 | |
|   }
 | |
|   
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| void TOperable_field::set_focus() const
 | |
| {                                                
 | |
|   mask().set_focus_field(dlg());
 | |
| }  
 | |
| 
 | |
| // Certified 100%
 | |
| bool TOperable_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_OPERABLE_FIELD || TMask_field::is_kind_of(cid); }
 | |
| 
 | |
| void TOperable_field::enable(bool on)
 | |
| {                                                
 | |
|   TMask_field::enable(on);
 | |
|   if (_ctl) _ctl->enable(on);
 | |
| }  
 | |
| 
 | |
| bool TOperable_field::on_key(
 | |
|   KEY key) // @parm Tasto notificato
 | |
| { 
 | |
|   switch(key)
 | |
|   {  
 | |
|   case K_F11:
 | |
|     {          
 | |
|       TString msg;
 | |
|       msg << "Identificatore: " << dlg() << '\n'
 | |
|           << "Maschera: " << mask().source_file() << '\n';
 | |
|       if (field() != NULL)
 | |
|         msg << "Campo: " << *field();
 | |
|       message_box(msg);
 | |
|     }  
 | |
|     break;
 | |
|   case K_CTRL + K_TAB:
 | |
|     mask().notify_focus_field(dlg());    
 | |
|     return handler(key);
 | |
|   default:   
 | |
|     return handler(key);
 | |
|   }
 | |
|   return TMask_field::on_key(key);
 | |
| }
 | |
| 
 | |
|   
 | |
| // Certified 50%
 | |
| HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg)
 | |
| {
 | |
| #ifdef DBG
 | |
|   if (f.class_id() != CLASS_LIST_FIELD)
 | |
|   {
 | |
|     yesnofatal_box("Can't add/delete items of non list-box field %d", f.dlg());
 | |
|     return;
 | |
|   }  
 | |
| #endif  
 | |
|   TList_field& l = (TList_field&)f;
 | |
|   
 | |
|   TToken_string item(16); 
 | |
|   item = msg.get(); 
 | |
|   if (add) item.add(msg.get()); 
 | |
|   item.strip("\"'");
 | |
|   if (add)
 | |
|     l.add_item(item);
 | |
|   else
 | |
|     l.delete_item(item);  
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 99%
 | |
| HIDDEN const char* copy_value(TToken_string& msg, const TString& val)
 | |
| {
 | |
|   int from = msg.get_int()-1;
 | |
|   int to = -1;
 | |
|   if (from < 0) from = 0;
 | |
|   else to = msg.get_int();
 | |
|   return val.sub(from, to);
 | |
| }
 | |
| 
 | |
| HIDDEN void run_app(TMask& mask, TToken_string& msg)
 | |
| {
 | |
|   TFilename a;
 | |
|   
 | |
|   for (const char* m = msg.get(1); m; m = msg.get())
 | |
|   {
 | |
|     if (a.not_empty())                    
 | |
|       a << ' ';
 | |
|     
 | |
|     for (const char* f = m; *f; f++)
 | |
|     {
 | |
|       if (*f == '#') 
 | |
|       {
 | |
|         const int id = atoi(++f);
 | |
|         a << mask.get(id);
 | |
|         break;
 | |
|       }
 | |
|       else
 | |
|         a << *f;
 | |
|     }  
 | |
|   }
 | |
|   TExternal_app app(a);
 | |
|   app.run();
 | |
|   mask.set_focus();
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TOperable_field::do_message(int num)
 | |
| {               
 | |
|   const int MAX_CMD = 18;
 | |
|   static const char* commands[MAX_CMD] =
 | |
|   {
 | |
|     "ADD",         //  0
 | |
|     "CHECK",       //  1
 | |
|     "CLEAR",       //  2
 | |
|     "CO",          //  3
 | |
|     "DEL",         //  4
 | |
|     "DIRTY",       //  5
 | |
|     "DISABLE",     //  6
 | |
|     "ENABLE",      //  7
 | |
|     "ENABLEDEF",   //  8 
 | |
|     "EXIT",        //  9
 | |
|     "HIDE",        // 10 
 | |
|     "NORMAL",      // 11
 | |
|     "PUSH",        // 12
 | |
|     "REQUIRED",    // 13
 | |
|     "RESET",       // 14
 | |
|     "RU",          // 15  
 | |
|     "SHOW",        // 16
 | |
|     "TAB",         // 17       
 | |
|     };
 | |
|                                
 | |
|   TToken_string* mess = message(num);
 | |
|   if (mess == NULL || mess->empty()) 
 | |
|     return FALSE;
 | |
| 
 | |
|   TToken_string msg(16, ',');
 | |
|   TString256 value;
 | |
| 
 | |
|   for (const char* m = mess->get(0); m && *m; m = mess->get())
 | |
|   {
 | |
|     KEY key = 0;
 | |
|     msg = m;
 | |
|     value = msg.get();
 | |
|     const char* dlg = msg.get();
 | |
|     
 | |
|     int cmd = -1;
 | |
|     if (isalpha(value[0]))                       // binary search
 | |
|     {         
 | |
|       int f = 0, l = MAX_CMD-1;                    
 | |
|       while (TRUE)
 | |
|       {
 | |
|         cmd = (f+l)>>1;                          
 | |
|         const int cmp = strcmp(value, commands[cmd]);
 | |
|         if (cmp == 0) break;
 | |
|         if (cmp > 0) f = cmd+1;
 | |
|         else         l = cmd-1;
 | |
|         if (f > l) 
 | |
|         {
 | |
|           cmd = -1;
 | |
|           break;
 | |
|         }  
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (cmd == 9)
 | |
|     {
 | |
|       mask().stop_run(atoi(dlg));
 | |
|       continue;
 | |
|     } else 
 | |
|       if (cmd == 15)
 | |
|       {
 | |
|         run_app(mask(), msg); 
 | |
|         continue;
 | |
|       }  
 | |
| 
 | |
|     short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0;
 | |
|     const bool broadcast = dlg && strchr(dlg, '@');
 | |
|     if (broadcast) fld = -fld;
 | |
|     
 | |
|     if (value[0] == '"') 
 | |
|       value = value.strip("\"'");
 | |
|     else switch (cmd)
 | |
|     {
 | |
|     case 0:
 | |
|       modify_list(TRUE, mask().field(fld), msg); 
 | |
|       continue;
 | |
|     case 1:
 | |
|       mask().field(fld).set_dirty();
 | |
|       mask().field(fld).on_key(K_TAB);
 | |
|       continue;
 | |
|     case 2:
 | |
|       mask().disable(fld); 
 | |
|       mask().reset(fld);
 | |
|       continue; 
 | |
|     case 3:
 | |
|       value = copy_value(msg, get()); break;
 | |
|     case 4:
 | |
|       modify_list(FALSE, mask().field(fld), msg); continue;
 | |
|     case 5:
 | |
|       mask().field(fld).set_dirty(); continue;
 | |
|     case 6:
 | |
|       mask().disable(fld); continue;
 | |
|     case 7:
 | |
|       mask().enable(fld); continue;
 | |
|     case 8:
 | |
|       mask().enable_default(fld); continue;
 | |
|     case 10:
 | |
|       mask().hide(fld); continue;
 | |
|     case 11:
 | |
|       mask().field(fld).check_type(CHECK_NORMAL); continue;
 | |
|     case 12:
 | |
|       mask().field(fld).on_hit(); continue;
 | |
|     case 13:
 | |
|       mask().field(fld).check_type(CHECK_REQUIRED); continue;
 | |
|     case 14:
 | |
|       key = K_F2; break;
 | |
|     case 16:
 | |
|       mask().show(fld); continue;
 | |
|     case 17:
 | |
|       mask().field(fld).on_key(K_TAB); continue;
 | |
|     default:                        
 | |
|       key = atoi(value);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (key)
 | |
|     {
 | |
|       if (key > 0)
 | |
|         send_key(key, fld);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       // Setta a value il campo fld solo se ha un valore diverso da value
 | |
|       if (broadcast)
 | |
|       {    
 | |
|         const int max = mask().fields();
 | |
|         for (int i = 0; i < max; i++)
 | |
|         {
 | |
|           TMask_field& f = mask().fld(i);
 | |
|           if (f.in_group((int)-fld))
 | |
|           {
 | |
|             const TString& prev = f.get();
 | |
|             if (value != prev)
 | |
|             {
 | |
|               f.set(value);
 | |
|               if (f.shown() || f.ghost())
 | |
|                 f.on_hit();
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         TMask_field& f = mask().field(fld);
 | |
|         const char* prev = f.get();
 | |
|         if (value != prev)
 | |
|         {
 | |
|           f.set(value);
 | |
|           if (f.shown() || f.ghost())
 | |
|             f.on_hit();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| void TOperable_field::highlight() const
 | |
| {
 | |
|   if (_ctl) _ctl->set_focus();
 | |
| }
 | |
| 
 | |
| bool TOperable_field::handler(KEY k)
 | |
| { 
 | |
|   bool ok = TRUE;
 | |
|   if (_handler)
 | |
|     ok = _handler(*this, k);
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TOperable_field::on_hit()
 | |
| {   
 | |
|   const bool ok = handler(K_SPACE);
 | |
|   if (ok && has_message())
 | |
|     do_message(0);
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TLoadable_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| bool TLoadable_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "DE")                    // DEFAULT
 | |
|   {
 | |
|     set_default(scanner.line());
 | |
|     return TRUE;
 | |
|   }
 | |
|   return TOperable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| // @cmember Ritorna il valore di default del campo
 | |
| const TString& TLoadable_field::get_default() const 
 | |
| { return _default; }
 | |
| 
 | |
| // @cmember Imposta il valore di default del campo
 | |
| void TLoadable_field::set_default(const char* def) 
 | |
| { _default = def; }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Button_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TButton_field::TButton_field(TMask* m)
 | |
|              : TOperable_field(m)
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| word TButton_field::class_id() const
 | |
| { return CLASS_BUTTON_FIELD; }
 | |
| 
 | |
| bool TButton_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_BUTTON_FIELD || TOperable_field::is_kind_of(cid); }
 | |
| 
 | |
| void TButton_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._width = scanner.integer();
 | |
|   if (_ctl_data._width <= 0) _ctl_data._width = 10;
 | |
|   _ctl_data._height  = scanner.integer(); // Height
 | |
|   if (_ctl_data._height <= 0) _ctl_data._height = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TButton_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PI")
 | |
|   {        
 | |
|     const short bmp = (short)scanner.integer();
 | |
|     if (_ctl_data._bmp_up == 0)
 | |
|       _ctl_data._bmp_up = bmp;
 | |
|     else  
 | |
|       _ctl_data._bmp_dn = bmp;
 | |
|     return bmp > 0;
 | |
|   }
 | |
|   return TOperable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TButton_field::create(WINDOW parent)
 | |
| {
 | |
|   _exit_key = 0;
 | |
|   _virtual_key = 0;
 | |
|   switch (dlg())
 | |
|   {
 | |
|   case DLG_OK:
 | |
|     if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Conferma")
 | |
|       _ctl_data._prompt = BR("~Conferma", _ctl_data._width);   
 | |
|     _exit_key = K_ENTER;
 | |
|     if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("~Conferma", _ctl_data._width))
 | |
|       _ctl_data._bmp_up = BMP_OK;
 | |
|     break;
 | |
|   case DLG_CANCEL:
 | |
|     if (_ctl_data._prompt.empty())
 | |
|       _ctl_data._prompt = BR("Annulla", _ctl_data._width);
 | |
|     _virtual_key = _exit_key = K_ESC;
 | |
|     if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("Annulla", _ctl_data._width))
 | |
|       _ctl_data._bmp_up = BMP_CANCEL;
 | |
|     break;
 | |
|   case DLG_DELREC:  
 | |
|     if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Elimina")
 | |
|       _ctl_data._prompt = BR("~Elimina", _ctl_data._width); 
 | |
|     _exit_key = K_DEL;
 | |
|     if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == BR("~Elimina", _ctl_data._width))     
 | |
|     {
 | |
|       _ctl_data._bmp_up = BMP_DELREC; 
 | |
|       _ctl_data._bmp_dn = BMP_DELRECDN;
 | |
|     }  
 | |
|     break;
 | |
|   case DLG_PRINT:
 | |
|     if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Stampa")
 | |
|       _ctl_data._prompt = BR("~Stampa", _ctl_data._width); 
 | |
|     _exit_key = K_ENTER;
 | |
|     if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == BR("~Stampa", _ctl_data._width))     
 | |
|       _ctl_data._bmp_up = BMP_PRINT;
 | |
|     break;
 | |
|   case DLG_QUIT:
 | |
|     if (_ctl_data._prompt.empty())
 | |
|       _ctl_data._prompt = BR("Fine", _ctl_data._width); 
 | |
|     _virtual_key = K_F4;
 | |
|     _exit_key = K_QUIT;                 
 | |
|     if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == BR("Fine", _ctl_data._width))     
 | |
|     {
 | |
|       _ctl_data._bmp_up = BMP_QUIT;
 | |
|       _ctl_data._bmp_dn = BMP_QUITDN;
 | |
|     }  
 | |
|     break;
 | |
|   case DLG_SELECT:
 | |
|     if (_ctl_data._bmp_up <= 0)
 | |
|       _ctl_data._bmp_up = BMP_SELECT;
 | |
|     _exit_key = K_ENTER;
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   _ctl = new TPushbutton_control(parent, _ctl_data._dlg,
 | |
|                                  _ctl_data._x, _ctl_data._y, 
 | |
|                                  _ctl_data._width+2, _ctl_data._height,
 | |
|                                  _ctl_data._flags, _ctl_data._prompt,
 | |
|                                  _ctl_data._bmp_up, _ctl_data._bmp_dn);
 | |
| 
 | |
|   TToken_string* mess = message(0);
 | |
|   if (mess)
 | |
|   {
 | |
|     TToken_string msg(mess->get(0), ','); 
 | |
|     const TString m(msg.get(0));
 | |
|     if (m == "EXIT")
 | |
|     {
 | |
|       _exit_key = msg.get_int();
 | |
|       if (_exit_key == 0)
 | |
|         _exit_key = ((TPushbutton_control*)_ctl)->mnemonic();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (msg.get_int() == 0) 
 | |
|         _exit_key = atoi(m);
 | |
|     }
 | |
|   } 
 | |
|   
 | |
|   if (_virtual_key == 0)
 | |
|   { 
 | |
|     char acc = ((TPushbutton_control*)_ctl)->mnemonic();
 | |
|     _virtual_key = (acc > ' ') ? toupper(acc) : _exit_key;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TButton_field::on_key(KEY key)
 | |
| {  
 | |
|   bool ok = TRUE;
 | |
|   if (key == K_SPACE)   
 | |
|   {
 | |
|     if (dlg() != DLG_CANCEL && dlg() != DLG_QUIT)
 | |
|     {
 | |
|       const TMask& m = mask();
 | |
|       if (parent() == m.toolwin())
 | |
|         ok = m.focus_field().on_key(K_TAB);
 | |
|     }
 | |
|     if (ok)
 | |
|     {
 | |
|       if (xvt_vobj_get_attr(NULL_WIN, ATTR_SPEECH_MODE) & (1<<7))
 | |
|       {
 | |
|         TString str = prompt();
 | |
|         str.strip("~");
 | |
|         xvt_dm_post_speech(str, 7, TRUE);
 | |
|       }
 | |
| 
 | |
|       ok = on_hit();
 | |
|       if (ok && _exit_key > 0 && !has_message())
 | |
|         mask().stop_run(_exit_key);
 | |
|     }    
 | |
|   }  
 | |
|   else
 | |
|     ok = TOperable_field::on_key(key);
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| void TButton_field::set_bmp(short up, short dn)
 | |
| {
 | |
|   ((TPushbutton_control*)_ctl)->set_bmp(up, dn);
 | |
| }
 | |
| 
 | |
| void TButton_field::set_central_icon(unsigned icon)
 | |
| {
 | |
|   ((TPushbutton_control*)_ctl)->set_icon(icon);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TEditable_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TEditable_field::TEditable_field(TMask* m)
 | |
|                : TLoadable_field(m), _field(NULL), _prompt(NULL), _keys(NULL),
 | |
|                  _warning(NULL), _drivers(NULL), _userdata(NULL), _validate(NULL)
 | |
| { }
 | |
| 
 | |
| 
 | |
| TEditable_field::~TEditable_field()
 | |
| {
 | |
|   if (_prompt)   delete _prompt;
 | |
|   if (_field)    delete _field;
 | |
|   if (_keys)     delete _keys;
 | |
|   if (_validate) delete _validate;
 | |
|   if (_warning)  delete _warning;
 | |
|   if (_drivers)  delete _drivers;
 | |
|   if (_userdata) delete _userdata;
 | |
| }  
 | |
|  
 | |
| 
 | |
| void TEditable_field::set_warning(const char* w)
 | |
| {
 | |
|   if (_warning)
 | |
|     *_warning = w;
 | |
|   else
 | |
|     _warning = new TString(w);  
 | |
|   if (_warning->empty())
 | |
|   {
 | |
|     delete _warning;
 | |
|     _warning = NULL;
 | |
|   }  
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| const char* TEditable_field::prompt() const
 | |
| {
 | |
|   return _prompt ? _prompt->caption() : "";
 | |
| }
 | |
| 
 | |
| void TEditable_field::reset_driver(short id)  
 | |
| {      
 | |
|   if (_drivers != NULL)
 | |
|   {
 | |
|     if (id == 0)                             
 | |
|       _drivers->destroy();
 | |
|     else   
 | |
|     {
 | |
|       for (int f = _drivers->last(); f >= 0; f--)
 | |
|       {
 | |
|         const short fid = (short)_drivers->get_long(f);
 | |
|         if (fid == id)
 | |
|           _drivers->destroy(f, true);
 | |
|       }
 | |
|     }
 | |
|   }       
 | |
| }
 | |
| 
 | |
| bool TEditable_field::add_driver(short id)  
 | |
| {
 | |
|   if (id != 0)
 | |
|   {
 | |
|     if (_drivers == NULL)
 | |
|       _drivers = new TPointer_array;
 | |
|     _drivers->add_long(id);
 | |
|   }
 | |
| 
 | |
|   return id != 0;
 | |
| }  
 | |
| 
 | |
| TOperable_field* TEditable_field::get_driver(int n, bool test) const
 | |
| {
 | |
|   TOperable_field* driver = NULL;
 | |
|   if (_drivers != NULL)
 | |
|   {
 | |
|     const short id = (short)_drivers->get_long(n);
 | |
|     if (id != 0)
 | |
|     {
 | |
|       if (id < 0)
 | |
|       {
 | |
|         TSheet_field* sheet = mask().get_sheet();
 | |
|         if (sheet)
 | |
|         {
 | |
|           const int pos = sheet->mask().id2pos(-id);
 | |
|           if (pos >= 0)
 | |
|             driver = (TOperable_field*)&sheet->mask().fld(pos);
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         const int pos = mask().id2pos(id);
 | |
|         if (pos >= 0)
 | |
|         {
 | |
|           driver = (TOperable_field*)&mask().fld(pos);
 | |
|           if (test)
 | |
|           {
 | |
|             TString16 msg; msg.format("CHECK,%d", dlg());
 | |
|             TToken_string* tok = driver->message(0, false);
 | |
|             if (tok == NULL || tok->get_pos(msg) < 0)
 | |
|               driver->message(0, true)->add(msg);
 | |
|           }
 | |
|         }    
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return driver;
 | |
| }
 | |
| 
 | |
| TOperable_field* TEditable_field::driver(int n) const
 | |
| {
 | |
|   return get_driver(n, false);
 | |
| }
 | |
| 
 | |
| void TEditable_field::test_drivers() const
 | |
| {
 | |
|   if (_drivers != NULL)
 | |
|   {
 | |
|     for (int i = 0; i < _drivers->items(); i++)
 | |
|       get_driver(i, true);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Ritorna il messaggio d'errore associato al campo
 | |
| const char* TEditable_field::get_warning() const
 | |
| { return _warning ? (const char*)*_warning : ""; }
 | |
| 
 | |
| bool TEditable_field::parse_item(TScanner& scanner)
 | |
| { 
 | |
|   const TString& k = scanner.key();
 | |
| 
 | |
|   if (k == "FI")                    // FIELD
 | |
|   {                                           
 | |
|     set_field(scanner.line());
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (k == "KE")                    // KEY
 | |
|   {
 | |
|     if (_keys == NULL)
 | |
|       _keys = new TBit_array;
 | |
|     _keys->set(scanner.line());
 | |
|     _keys->set(0L);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (k == "DR")                    // DRIVENBY
 | |
|   {
 | |
|     TToken_string lista(scanner.line(), ' ');
 | |
|     FOR_EACH_TOKEN(lista, tok)
 | |
|     {
 | |
|       const short id = atoi(tok);
 | |
|       add_driver(id);
 | |
|     }
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (k == "CU")                    // CUSTOM DATA
 | |
|   { 
 | |
|     if (_userdata == NULL)
 | |
|       _userdata = new TToken_string(scanner.string());
 | |
|     else  
 | |
|       _userdata->add(scanner.string());
 | |
|     return TRUE;
 | |
|   }     
 | |
|   
 | |
|   if (scanner.key() == "VA")
 | |
|   {                    
 | |
| #ifdef DBG  
 | |
|     if (_validate)
 | |
|       return yesnofatal_box("VALIDATE duplicata nel campo %d", _ctl_data._dlg);
 | |
| #endif    
 | |
|     _validate = new TValidation_data;
 | |
| 
 | |
|     const char* n = scanner.pop();
 | |
|     _validate->_func = isdigit(*n) ? atoi(n) : -1;
 | |
| #ifdef DBG    
 | |
|     if (_validate->_func < 0)
 | |
|       return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", 
 | |
|                             n, _ctl_data._dlg);
 | |
| #endif
 | |
| 
 | |
|     const int nparms = scanner.integer();
 | |
| #ifdef DBG    
 | |
|     if (nparms < 0 || nparms > 100)
 | |
|       return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", 
 | |
|                             _ctl_data._dlg, nparms);
 | |
| #endif
 | |
|     
 | |
|     for (int i = 0; i < nparms; i++)
 | |
|       _validate->_parms.add(scanner.operand());
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "WA")
 | |
|   {             
 | |
| 		const char* msg = dictionary_translate(scanner.string());
 | |
|     set_warning(msg);
 | |
|     return TRUE;
 | |
|   }
 | |
|   
 | |
|   return TLoadable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| void TEditable_field::set_key(byte key) 
 | |
| {        
 | |
|   if (_keys == NULL)
 | |
|     _keys = new TBit_array;
 | |
|   _keys->set(long(key)); 
 | |
|   _keys->set(0L);
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| word TEditable_field::last_key() const
 | |
| {
 | |
|   long u = _keys ? _keys->last_one() : 0;
 | |
|   if (u < 0) u = 0;
 | |
|   return (word)u;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| word TEditable_field::first_key() const
 | |
| {
 | |
|   if (_keys == NULL)
 | |
|     return 0;
 | |
|   const int last = last_key();
 | |
|   int i;
 | |
|   for (i = 1; i <= last; i++)
 | |
|     if (in_key(i) == TRUE)
 | |
|       break;
 | |
|   return (word)i;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TEditable_field::has_a_common_key(const TMask_field & f) const
 | |
| 
 | |
| {              
 | |
|   const int last = last_key();
 | |
|   for (int i = 1; i <= last; i++)
 | |
|     if (in_key(i) && f.in_key(i))
 | |
|       return TRUE;
 | |
|   return FALSE;
 | |
| } 
 | |
| 
 | |
| bool TEditable_field::test_key_complete(bool normal) const
 | |
| {
 | |
|   TMask& m = mask();
 | |
|   for (int k = 1; k <= MAX_KEYS; k++)
 | |
|   {
 | |
|     if (in_key(k) && m.key_valid(k))
 | |
|     {
 | |
|       bool complete = true;
 | |
|       for (TEditable_field* e = m.get_key_field(k, TRUE); e; e = m.get_key_field(k, FALSE))
 | |
|       {
 | |
|         e->set_focusdirty(FALSE);       
 | |
|         if (e->is_edit())
 | |
|           complete &= e->required();     
 | |
|       }                           
 | |
|       if (normal && !complete)
 | |
|         m.set_test_field(dlg());           
 | |
|       else
 | |
|         m.stop_run(K_AUTO_ENTER);
 | |
|       return true;
 | |
|     }
 | |
|   }  
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| void TEditable_field::reset_key(byte key)
 | |
| {        
 | |
|   if (_keys)
 | |
|   {
 | |
|     _keys->reset(long(key));
 | |
|     if (key == 0 || last_key() == 0)       
 | |
|     {
 | |
|       delete _keys;         // Se non ci sono piu' chiavi azzera tutto
 | |
|       _keys = NULL;
 | |
|     }  
 | |
|   }  
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Chiama l' eventuale funzione di validazione
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell funzione di validazione:
 | |
| //
 | |
| // @flag TRUE | Se la validata ha avuto successo
 | |
| // @flag FALSE | Se la validata no ha avuto successo
 | |
| bool TEditable_field::validate(
 | |
|   KEY k) // @parm Tasto da passare alla funzione di validazione
 | |
| {              
 | |
|   bool ok = TRUE;
 | |
|   if (_validate)
 | |
|     ok = ::validate(_validate->_func, *this, k, _validate->_parms);
 | |
|   return ok;  
 | |
| }               
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Crea il prompt del controllo
 | |
| //
 | |
| // @rdesc Ritorna la lunghezza del prompt creato
 | |
| word TEditable_field::create_prompt(
 | |
|   WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo
 | |
|   word width,     // @parm Larghezza del controllo
 | |
|   word height)    // @parm Altezza del controllo
 | |
| {
 | |
|   if (_ctl_data._prompt.not_empty())
 | |
|   {
 | |
|     TString flags;
 | |
|     if (hidden()) flags << 'H';
 | |
| 
 | |
|     if (height < 3)
 | |
|     {                          
 | |
|       width = _ctl_data._prompt.len();
 | |
|       word i;
 | |
|       for (i = 0; i < width && _ctl_data._prompt[(int)i] == '@'; i += 2);
 | |
|       width -= i;
 | |
|       _prompt = new TText_control(parent, -1, _ctl_data._x, _ctl_data._y, 
 | |
|                                   0, 1, flags, _ctl_data._prompt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (right_justified()) flags << 'R';
 | |
|       _prompt = new TGroupbox_control(parent, -1, _ctl_data._x, _ctl_data._y, 
 | |
|                                       width, height, flags, _ctl_data._prompt);
 | |
|     }                              
 | |
|   }
 | |
| 
 | |
|   return width;
 | |
| }
 | |
| 
 | |
| void TEditable_field::show(bool on)
 | |
| {
 | |
|   TOperable_field::show(on);
 | |
|   if (_prompt) _prompt->show(on);
 | |
| }
 | |
| 
 | |
| void TEditable_field::set_prompt(const char* p)
 | |
| {        
 | |
|   if (_prompt)
 | |
|     _prompt->set_caption(p);
 | |
|   else
 | |
|     NFCHECK("Can't set prompt to control %d", dlg());
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| void TEditable_field::set_field(const TString& fr)
 | |
| {
 | |
|   if (_field != NULL)           
 | |
|   {
 | |
|     if (fr.blank()) 
 | |
|     {
 | |
|       delete _field;
 | |
|       _field = NULL;
 | |
|     }
 | |
|     else
 | |
|       *_field = fr;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (!fr.blank()) 
 | |
|       _field = new TFieldref(fr, 0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| // Legge il valore attuale del campo in formato RAW
 | |
| const TString& TEditable_field::get() const
 | |
| {
 | |
|   return _str;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| // Aggiusta un valore letto da file in formato RAW
 | |
| const char* TEditable_field::reformat(const char* data) const
 | |
| {
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| // Certified 100%                  
 | |
| // Setta il valore RAW e WIN del campo con un valore RAW
 | |
| void TEditable_field::set(const char* data)
 | |
| {
 | |
|   _str = reformat(data);
 | |
|   const char* val = raw2win(_str);
 | |
|   set_window_data(val);  
 | |
|   
 | |
|   const TMask& m = mask();
 | |
|   if (m.is_running() || m.is_sheetmask())            
 | |
|     set_dirty();
 | |
| }
 | |
| 
 | |
| // Certified 100%                  
 | |
| // Converte da formato RAW a formato WIN
 | |
| const char* TEditable_field::raw2win(const char* data) const
 | |
| {
 | |
|   return reformat(data);
 | |
| }
 | |
| 
 | |
| // Certified 100%                  
 | |
| // Converte da formato WIN a formato RAW
 | |
| const char* TEditable_field::win2raw(const char* data) const
 | |
| {
 | |
|   return reformat(data);
 | |
| }
 | |
| 
 | |
| bool TEditable_field::autosave(TRelation& r) 
 | |
| {
 | |
|   if (_field)
 | |
|     _field->write(get(), r);
 | |
|   return _field != NULL;
 | |
| }
 | |
| 
 | |
| bool TEditable_field::autoload(const TRelation& r)
 | |
| {
 | |
|   if (_field)
 | |
|     set(_field->read(r));
 | |
|   return _field != NULL;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Boolean_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TBoolean_field::TBoolean_field(TMask* m)
 | |
|               : TEditable_field(m)
 | |
| {}
 | |
| 
 | |
| word TBoolean_field::class_id() const
 | |
| { return CLASS_BOOLEAN_FIELD; }
 | |
| 
 | |
| bool TBoolean_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_BOOLEAN_FIELD || TEditable_field::is_kind_of(cid); }
 | |
| 
 | |
| void TBoolean_field::create(WINDOW parent)
 | |
| {             
 | |
|   _ctl = new TCheckbox_control(parent, _ctl_data._dlg,
 | |
|                                _ctl_data._x, _ctl_data._y, 0,
 | |
|                                _ctl_data._flags, _ctl_data._prompt);
 | |
| }
 | |
| 
 | |
| void TBoolean_field::set_prompt(const char* p)
 | |
| {
 | |
|   _ctl->set_caption(p);
 | |
| }
 | |
| 
 | |
| const char* TBoolean_field::reformat(const char* data) const
 | |
| {
 | |
|   return (data && *data > ' ' && *data != '0' && *data != 'N') ? "X" : ""; 
 | |
| }
 | |
| 
 | |
| void TBoolean_field::set_window_data(const char* data)
 | |
| { 
 | |
|   if (_ctl)
 | |
|     ((TCheckbox_control*)_ctl)->check(*data > ' ');
 | |
| }
 | |
| 
 | |
| TString& TBoolean_field::get_window_data()
 | |
| { 
 | |
|   const bool on = _ctl ? ((TCheckbox_control*)_ctl)->checked() : FALSE;
 | |
|   _str = on ? "X" : "";
 | |
|   return _str;
 | |
| }
 | |
| 
 | |
| bool TBoolean_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "ME")
 | |
|   {
 | |
|     const bool tf = scanner.integer() ? TRUE : FALSE;   // Message TRUE or FALSE
 | |
|     TToken_string* ts = message(tf, TRUE);
 | |
|     ts->add(scanner.line().strip_spaces());
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TEditable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| bool TBoolean_field::on_hit()
 | |
| {                          
 | |
|   const bool ok = handler(K_SPACE);
 | |
|   if (ok)
 | |
|   {
 | |
|     const bool on = get() == "X";
 | |
|     do_message(on);
 | |
|   }  
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TBoolean_field::on_key(KEY key)
 | |
| {
 | |
|   switch (key)
 | |
|   { 
 | |
|     case K_SPACE: 
 | |
|       get_window_data();
 | |
|       set_dirty();
 | |
|       on_hit();
 | |
|       return TRUE;
 | |
|       break;
 | |
|     case K_F2:  
 | |
| 			if (!read_only())
 | |
| 			{
 | |
| 				set(""); 
 | |
| 				set_dirty();
 | |
| 			}
 | |
|       return TRUE;
 | |
|       break;
 | |
|     default:
 | |
|       return TEditable_field::on_key(key);
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TCheckbutton_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Copiato da TButton::parse_item
 | |
| void TCheckbutton_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._width = scanner.integer();
 | |
|   if (_ctl_data._width <= 0) _ctl_data._width = 10;
 | |
|   _ctl_data._height  = scanner.integer(); // Height
 | |
|   if (_ctl_data._height <= 0) _ctl_data._height = 1;
 | |
| }
 | |
| 
 | |
| // Copiato da TButton::parse_item
 | |
| bool TCheckbutton_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PI")
 | |
|   {        
 | |
|     const short bmp = (short)scanner.integer();
 | |
|     if (_ctl_data._bmp_up == 0)
 | |
|       _ctl_data._bmp_up = bmp;
 | |
|     else  
 | |
|       _ctl_data._bmp_dn = bmp;
 | |
|     return bmp > 0;
 | |
|   }
 | |
|   return TOperable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| void TCheckbutton_field::create(WINDOW parent)
 | |
| {
 | |
|   _ctl = new TCheckbutton_control(parent, _ctl_data._dlg,
 | |
|                                  _ctl_data._x, _ctl_data._y, 
 | |
|                                  _ctl_data._width+2, _ctl_data._height,
 | |
|                                  _ctl_data._flags, _ctl_data._prompt,
 | |
|                                  _ctl_data._bmp_up, _ctl_data._bmp_dn);
 | |
| }
 | |
| 
 | |
| TCheckbutton_field::TCheckbutton_field(TMask* mask) : TBoolean_field(mask)
 | |
| { }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TBrowse_button
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TBrowse_button::TBrowse_button(TEdit_field* f) 
 | |
|               : _fld(f)
 | |
| { }
 | |
|   
 | |
| TBrowse_button::~TBrowse_button()
 | |
| {
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TEditable_field& TBrowse_button::field(short id) const
 | |
| {
 | |
|   if (id > 0)
 | |
|   {
 | |
|     TMask_field& f = _fld->mask().field(id); 
 | |
|     CHECKD(f.is_editable(), "Can't use in a browse the field ", id);
 | |
|     return (TEditable_field&)f;
 | |
|   }
 | |
|   return *_fld;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TList_sheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
 | |
|            : TBrowse_button(f), _row(-1), _caption(caption), _head(head)
 | |
| { }
 | |
| 
 | |
| // Certified 100%
 | |
| TList_sheet::~TList_sheet()
 | |
| { }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::parse_input(TScanner& scanner)
 | |
| {
 | |
|   _inp_id.add(scanner.pop());
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::parse_item(TScanner& scanner)
 | |
| {
 | |
|   _data.add(new TToken_string(scanner.string()));
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::parse_output(TScanner& scanner)
 | |
| {
 | |
|   _out_id.add(scanner.pop());
 | |
| }
 | |
| 
 | |
| // il numero di riga selezionata
 | |
| int TList_sheet::do_input()
 | |
| {
 | |
|   if (_inp_id.empty_items()) 
 | |
|     return -2;          // List empty!
 | |
| 
 | |
|   _inp_id.restart();
 | |
|   TToken_string rowsel(80);
 | |
| 
 | |
|   for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
 | |
|   {
 | |
|     if (*fld == '"')
 | |
|     {
 | |
|       rowsel.add(fld+1);
 | |
|       if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const short id = field().atodlg(fld);
 | |
|       if (id > 0)
 | |
|       { 
 | |
|         const TMask_field& f = field(id);
 | |
|         if (f.class_id() == CLASS_ZOOM_FIELD)
 | |
|         {
 | |
|           const TZoom_field& z = (TZoom_field&)f;
 | |
|           rowsel.add(z.get_first_line());
 | |
|         }
 | |
|         else
 | |
|            rowsel.add(f.get());
 | |
|       }
 | |
|       else rowsel.add("");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TString fd, it;
 | |
|   for (int i = 0 ; i < _data.items(); i++)
 | |
|   {
 | |
|     TToken_string& ts =_data.row(i);
 | |
| 
 | |
|     ts.restart();
 | |
|     const char * item;
 | |
|     for (item = rowsel.get(0); item ; item = rowsel.get())
 | |
|     {
 | |
|       it = item; it.trim();
 | |
|       fd = ts.get(); fd.trim();
 | |
|       if (fd != it) break;
 | |
|     }
 | |
|     if (!item) return i;
 | |
|   }
 | |
| 
 | |
|   return -1;                 // Value not found!
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 50%
 | |
| void TList_sheet::do_output(CheckTime t)
 | |
| {
 | |
|   if (_row < 0 || t == FINAL_CHECK) 
 | |
|     return;
 | |
|   
 | |
|   _out_id.restart();
 | |
|   TToken_string& rowsel = _data.row(_row);
 | |
|   rowsel.restart();
 | |
|   for (const char* fld = _out_id.get(); fld; fld = _out_id.get())
 | |
|   {
 | |
|     const short id = field().atodlg(fld);
 | |
|     TMask_field& f = field(id);
 | |
|     const char* val = rowsel.get();
 | |
| 		if (t != STARTING_CHECK || f.field() == NULL)
 | |
| 		{           
 | |
| 			const bool hit = f.get() != val;
 | |
| 			f.set(val);
 | |
| 			if (field().dlg() != id && hit)
 | |
| 			{
 | |
| 				f.on_hit();
 | |
| 				if (t == RUNNING_CHECK)
 | |
| 					f.check();
 | |
| 			}
 | |
| 		}
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| KEY TList_sheet::run()
 | |
| {
 | |
|   TArray_sheet sci(3, 3, -3, -3, _caption, _head);
 | |
|   sci.rows_array() = _data;
 | |
| 
 | |
|   _row = do_input();
 | |
|   sci.select(_row);
 | |
|   const KEY k = sci.run();
 | |
| 
 | |
|   switch (k)
 | |
|   {
 | |
|   case K_ENTER:
 | |
|     _row = (int)sci.selected();
 | |
|     do_output();
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TList_sheet::check(CheckTime t)
 | |
| {                                       
 | |
|   _row = do_input();
 | |
|   bool passed = _row != -1;
 | |
|   if (passed) 
 | |
|     do_output(t);
 | |
|   else
 | |
|   {  
 | |
|     switch(field().check_type())
 | |
|     {
 | |
|     case CHECK_SEARCH: passed = TRUE; break;
 | |
|     default: break;
 | |
|     }
 | |
|   }
 | |
|   return passed;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TBrowse
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter)
 | |
|        : TBrowse_button(f),
 | |
|          _relation(r), _cursor(new TCursor (r, "", key)),
 | |
|          _filter(filter), _secondary(FALSE)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::TBrowse(TEdit_field* f, TCursor* c)
 | |
|        : TBrowse_button(f),
 | |
|          _relation(NULL), _cursor(c), _secondary(FALSE)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::~TBrowse()
 | |
| {
 | |
|   // Se e' stato usato il primo costruttore devo distruggere la relazione ed il cursore
 | |
|   if (_relation)
 | |
|   {
 | |
|     delete _cursor;
 | |
|     delete _relation;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TBrowse::parse_display(TScanner& scanner)
 | |
| {              
 | |
|   const char* s = scanner.string();
 | |
|   _head.add(dictionary_translate_header(s));
 | |
|   s = scanner.line();
 | |
|   _items.add(s);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_input(TScanner& scanner)
 | |
| {
 | |
|   const char* s = scanner.pop();
 | |
|   _inp_fn.add(s);
 | |
| 
 | |
|   s = scanner.pop();
 | |
|   if (*s == '"')        // Constant string
 | |
|   {
 | |
|     scanner.push();
 | |
|     TString& str = scanner.line();
 | |
|     _inp_id.add(str);
 | |
|   }
 | |
|   else            // Field on the mask
 | |
|   {                   
 | |
|     CHECKS(_inp_id.get_pos(s) < 0, "Duplicate input field ", s);
 | |
|     _inp_id.add(s);
 | |
|     if (scanner.popkey() == "SE") 
 | |
|       _inp_id << '@';       // Special FILTERing field
 | |
|     else 
 | |
|       scanner.push();
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_output(TScanner& scanner)
 | |
| {
 | |
|   const char* s = scanner.pop();
 | |
| #ifdef DBG      
 | |
|   field().atodlg(s);
 | |
| #endif  
 | |
|   _out_id.add(s);
 | |
|   s = scanner.pop();
 | |
|   _out_fn.add(s);  
 | |
|   _secondary = FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TBrowse::parse_copy(const TString& what, const TBrowse& b)
 | |
| {
 | |
|   const bool all = what == "AL";
 | |
|   if (all || what == "US")
 | |
|   {
 | |
|     set_insert(b.get_insert());
 | |
|     _filter = b.get_filter();
 | |
|     if (!field().has_warning() && b.field().has_warning()) 
 | |
|       field().set_warning(b.field().get_warning());
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "IN")
 | |
|   {
 | |
|     _inp_id = b._inp_id;
 | |
|     _inp_fn = b._inp_fn;
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "DI")
 | |
|   {
 | |
|     _head = b._head;
 | |
|     _items = b._items;
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "OU")
 | |
|   {
 | |
|     _out_id = b._out_id;
 | |
|     _out_fn = b._out_fn;
 | |
|     _secondary = b.field().has_check();
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_join(TScanner& scanner)
 | |
| {
 | |
|   TString80 j(scanner.pop());             // File or table
 | |
| 
 | |
|   CHECKS(_relation, "Can't join to NULL relation ", (const char*)j);
 | |
| 
 | |
|   int to;
 | |
|   if (scanner.popkey() == "TO")         // TO keyword
 | |
|   {
 | |
|     const char* t = scanner.pop();
 | |
|     to = name2log(t);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     to = 0;                  // _relation->lfile()->num();
 | |
|     scanner.push();
 | |
|   }
 | |
| 
 | |
|   int key = 1;
 | |
|   if (scanner.popkey() == "KE")
 | |
|     key = scanner.integer();
 | |
|   else scanner.push();
 | |
| 
 | |
|   int alias = 0;
 | |
|   if (scanner.popkey() == "AL")
 | |
|     alias = scanner.integer();
 | |
|   else scanner.push();
 | |
| 
 | |
|   TToken_string exp(80);
 | |
|   if (scanner.pop() == "INTO")
 | |
|   {
 | |
|     const char* r = scanner.pop();
 | |
|     while (strchr(r, '=') != NULL)
 | |
|     {
 | |
|       exp.add(r);
 | |
|       r = scanner.pop();
 | |
|     }
 | |
|   }
 | |
|   scanner.push();
 | |
| 
 | |
| #ifdef DBG      
 | |
|   if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
 | |
| #endif  
 | |
|                
 | |
|   if (isdigit(j[0]))
 | |
|     _relation->add(atoi(j), exp, key, to, alias);   // join file
 | |
|   else
 | |
|   {
 | |
| #ifdef DBG      
 | |
|     if (j.len() > 4)
 | |
|       yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j);
 | |
|     else  
 | |
| #endif          
 | |
|       _relation->add(j, exp, key, to, alias);      // join table
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_insert(TScanner& scanner)
 | |
| {
 | |
|   const TString& key = scanner.popkey();
 | |
|   _insert.cut(0);
 | |
|   if (key != "NO")
 | |
|   {
 | |
|     _insert << key[0] << scanner.line();
 | |
|     _insert.trim();
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro
 | |
| int TBrowse::input_fields()
 | |
| {
 | |
|   int inp = 0;
 | |
|   for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get())
 | |
|   {                                             
 | |
|     if (*fld != '"' && strchr(fld, '@') == NULL)
 | |
|     {
 | |
|       TMask_field& f = field(field().atodlg(fld));
 | |
|       if (f.active() && f.is_editable())
 | |
|         inp++;
 | |
|     }    
 | |
|   }
 | |
|   return inp;    
 | |
| }
 | |
| 
 | |
| const char* TBrowse::get_input_fields() const
 | |
| {
 | |
|   return _inp_id;
 | |
| }
 | |
| 
 | |
| const char* TBrowse::get_input_field_names() const
 | |
| {
 | |
|   return _inp_fn;
 | |
| }
 | |
| 
 | |
| const char* TBrowse::get_output_fields() const
 | |
| {
 | |
|   return _out_id;
 | |
| }
 | |
| 
 | |
| const char* TBrowse::get_output_field_names() const
 | |
| {
 | |
|   return _out_fn;
 | |
| }
 | |
| 
 | |
| // @doc INTERNAL
 | |
| 
 | |
| // @mfunc Ritorna il numero di campi non vuoti e non filtrati
 | |
| //
 | |
| // @rdesc Numero di campi non vuoti e non filtrati
 | |
| int TBrowse::do_input(
 | |
|   bool filter) // @parm Indica se effettuare il filtro sulla selezione
 | |
| 
 | |
|   // @comm Questa funzione serve ai <c TCursor_sheet>
 | |
| {
 | |
|   int ne = 0;
 | |
|   if (_inp_id.empty()) 
 | |
|     return ne;
 | |
| 
 | |
|   TRectype& cur = _cursor->curr();
 | |
|   cur.zero();
 | |
|   TRectype filtrec(cur);
 | |
| 
 | |
|   _inp_id.restart();
 | |
|   _inp_fn.restart();
 | |
| 
 | |
|   TString val;                  // Value to output
 | |
|   bool tofilter = false;
 | |
| 
 | |
|   for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
 | |
|   {
 | |
|     if (*fld == '"')
 | |
|     {
 | |
|       val = (fld+1);
 | |
|       if (val.not_empty()) val.rtrim(1);
 | |
|       tofilter = filter;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const TMask_field* campf = NULL;
 | |
| 
 | |
|       if (*fld == '-')
 | |
|       {
 | |
|         TSheet_field* sheet = field().mask().get_sheet();
 | |
|         if (sheet != NULL)
 | |
|         {
 | |
|           const short id = atoi(fld+1);
 | |
|           campf = &sheet->mask().field(id);
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         const short id  = field().atodlg(fld);
 | |
|         campf = &field(id);
 | |
|       }
 | |
| 
 | |
|       if (campf != NULL)
 | |
|       {
 | |
|         const TMask_field& f = *campf;
 | |
|         val = f.get();
 | |
|       
 | |
|         if (f.class_id() == CLASS_DATE_FIELD && f.right_justified())
 | |
|         {
 | |
|           const TDate d(val);
 | |
|           val = d.string(ANSI);
 | |
|         }
 | |
|       
 | |
|         const bool filter_flag = strchr(fld, '@') != NULL;
 | |
|         tofilter = filter && filter_flag;
 | |
|         if (f.is_edit() && val.not_empty() && !filter_flag) 
 | |
|           ne++;          // Increment not empty fields count
 | |
|       }
 | |
|     }
 | |
|     TFieldref fldref(_inp_fn.get(), 0); // Output field
 | |
|     fldref.write(val, *_cursor->relation());
 | |
|     if (tofilter)
 | |
|     {
 | |
| 			const int len = fldref.len(cur);
 | |
| 
 | |
|       if (val.len() < len	&& cur.type(fldref.name()) == _alfafld)
 | |
|         val.rpad(len, '~');
 | |
|       fldref.write(val, filtrec);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!filter) 
 | |
|     return ne;
 | |
| 
 | |
|   TString work(_filter.size());
 | |
|   bool filter_update = FALSE;
 | |
|   
 | |
|   for (int i = 0; _filter[i]; i++)
 | |
|   {
 | |
|     if (_filter[i] == '"')
 | |
|     { 
 | |
|       do
 | |
|       {
 | |
|         work << _filter[i++];
 | |
|       } while (_filter[i] && _filter[i] != '"');
 | |
|       work << '"';
 | |
|       if (!_filter[i]) break;
 | |
|     }
 | |
|     else
 | |
|       if (_filter[i] == '#')
 | |
|       {
 | |
|         work << '"' << field(atoi(&_filter[++i])).get() << '"';
 | |
|         while (isspace(_filter[i])) i++;
 | |
|         while (isdigit(_filter[i])) i++;
 | |
|         i--;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         work << _filter[i];
 | |
|         if (_filter[i] == '-' && _filter[i + 1] == '>')
 | |
|           filter_update = true; 
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   _cursor->setfilter(work, filter_update);
 | |
|   _cursor->setregion(filtrec, filtrec);
 | |
| 
 | |
|   return ne;
 | |
| }
 | |
| 
 | |
| static TBit_array s_checked;
 | |
| static short s_checking = 0;
 | |
| 
 | |
| void TBrowse::do_output(CheckTime t)
 | |
| {                   
 | |
|   if (t == FINAL_CHECK) 
 | |
|     return;
 | |
| 
 | |
|   const bool master = s_checking == 0;  
 | |
|   if (master)  
 | |
|   {
 | |
|     s_checking = field().dlg();
 | |
|     s_checked.reset();
 | |
|     // Rendo intoccabili i campi del MIO output
 | |
|     for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
 | |
|     {
 | |
|       const short id = field().atodlg(fld);
 | |
|       s_checked.set(id);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TString sum;
 | |
|   TToken_string flds(24, '+');
 | |
|   
 | |
|   const TRelation& relation = *_cursor->relation();
 | |
|   
 | |
|   TBit_array spotted;
 | |
|   
 | |
|   _out_fn.restart();   
 | |
|   const char* fld;
 | |
|   for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
 | |
|   {
 | |
|     const short id = field().atodlg(fld);
 | |
|     TMask_field& f = field(id);
 | |
| 
 | |
|     flds = _out_fn.get();
 | |
|     
 | |
|     bool do_that = t != STARTING_CHECK || f.field() == NULL || (f.mask().mode() == MODE_INS && !f.in_key(0));
 | |
|     if (do_that && main_app().class_id() == CLASS_RELATION_APPLICATION)  
 | |
|     {
 | |
|       // Considera a parte l'inizializzazione delle transazioni!
 | |
|       // Non sovrascrivere con degli output campi che potrebbero essere riempiti dal .ini
 | |
|       if (!f.empty() && f.field() != NULL)
 | |
|       {
 | |
|         const TMask& m = f.mask();
 | |
|         if (!m.is_running() && m.get_sheet() == NULL) // Maschera principale chiusa
 | |
|         {
 | |
|           const TRelation_application& ra = (const TRelation_application&)main_app();
 | |
|           if (ra.is_transaction())
 | |
|             do_that = false;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (do_that)
 | |
|     {
 | |
|       sum.cut(0);
 | |
|       for(const char* fr = flds.get(0); fr; fr = flds.get())
 | |
|       {  
 | |
|         if (*fr == '"')
 | |
|         {       
 | |
|           sum << (fr+1);
 | |
|           sum.rtrim(1);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           const TFieldref fld(fr, 0);
 | |
|           sum << fld.read(relation);
 | |
|         }  
 | |
|       }
 | |
|                     
 | |
|       bool hit = FALSE;
 | |
|       if (master)
 | |
|       {     
 | |
|         f.set(sum);
 | |
|         hit = id != s_checking; // Il mio handler viene fatto nella on_key
 | |
|       }
 | |
|       else
 | |
|       {     
 | |
|         if (!s_checked[id])
 | |
|         {
 | |
|           f.set(sum);
 | |
|           s_checked.set(id);
 | |
|           hit = TRUE;
 | |
|         }  
 | |
|       }
 | |
|       spotted.set(id, hit);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
 | |
|   {
 | |
|     const short id = field().atodlg(fld);
 | |
|     if (spotted[id])
 | |
|     {
 | |
|       TMask_field& f = field(id);
 | |
|       f.check();
 | |
|       f.on_hit();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (master)
 | |
|     s_checking = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::do_clear(CheckTime t)
 | |
| {            
 | |
|   const bool master = s_checking == 0;  
 | |
|   if (master)  
 | |
|   {
 | |
|     s_checking = field().dlg();
 | |
|     s_checked.reset();
 | |
|     // Rendo intoccabili i campi del MIO input
 | |
|     for (const char* fld = _inp_id.get(0); fld && *fld; fld = _inp_id.get())
 | |
|     {         
 | |
|       if (isdigit(*fld))
 | |
|       {
 | |
|         const short id = field().atodlg(fld);
 | |
|         s_checked.set(id);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get())
 | |
|   {                      
 | |
|     const short id = field().atodlg(fld);
 | |
|     TMask_field& f = field(atoi(fld));
 | |
|     if (f.field() == NULL && field().dlg() != id &&
 | |
|         !s_checked[id] && _inp_id.get_pos(fld) < 0) 
 | |
|     {
 | |
|       f.reset();
 | |
|       s_checked.set(id);
 | |
|       f.on_hit();
 | |
|       f.check(t);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   if (master)  
 | |
|     s_checking = 0;  
 | |
| }
 | |
| 
 | |
| bool TBrowse::do_link(bool insert)
 | |
| {
 | |
|   bool ok = FALSE;
 | |
|   TString app;
 | |
| 
 | |
|   if (_insert[0] == 'M')
 | |
|   {
 | |
|     TString nm(_insert.mid(1));
 | |
|     if (nm.compare("tb", 2, TRUE) == 0)    // Programma gestione tabelle
 | |
|       _cursor->file().get_relapp(app);
 | |
|     else                              // Programma generico di browse/edit
 | |
|       app.format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num());
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     app = _insert.mid(1);
 | |
|   }
 | |
|   if (app.find('#') >=  0)
 | |
|   {
 | |
|     TString w(app);
 | |
|     app = "";
 | |
|     for (const char* f = w; *f; f++)
 | |
|     {
 | |
|       if (*f == '#') 
 | |
|       {
 | |
|         const int id = atoi(++f);
 | |
|         app << field(id).get();
 | |
|         while (isspace(*f)) ++f;
 | |
|         while (isdigit(*f)) ++f; 
 | |
|         if (*f)
 | |
|           app << ' ' << *f;
 | |
|         else 
 | |
|           break;
 | |
|       }            
 | |
|       else
 | |
|         app << *f;
 | |
|     }
 | |
|   } 
 | |
|   
 | |
|   TFilename msg; msg.temp("msg");
 | |
|   app << " /i" << msg;
 | |
| 
 | |
|   if (insert)
 | |
|   {
 | |
|     TConfig ini(msg, "Transaction");
 | |
|     ini.set("Action", TRANSACTION_RUN);
 | |
|   }
 | |
|   else
 | |
|   {  
 | |
|     TConfig ini(msg, "Transaction");
 | |
|     ini.set("Action", TRANSACTION_LINK);
 | |
| 
 | |
|     TString8 paragraph; paragraph << _cursor->file().num();
 | |
|     ini.set_paragraph(paragraph);
 | |
| 
 | |
|     // Uso sempre la chiave 1 per collegarmi agli altri programmi
 | |
|     const TRelation& rel = *_cursor->relation();
 | |
|     const RecDes* recd = rel.curr().rec_des(); // Descrizione del record della testata
 | |
|     const KeyDes& kd = recd->Ky[0];            // Elenco dei campi della chiave 1
 | |
|     TString inp_val;
 | |
|     for (int i = 0; i < kd.NkFields; i++)
 | |
|     {                        
 | |
|       const int nf = kd.FieldSeq[i] % MaxFields;
 | |
|       const RecFieldDes& rf = recd->Fd[nf];  
 | |
|       const TFieldref fldref(rf.Name, 0);
 | |
|       inp_val = fldref.read(rel);
 | |
|       fldref.write(ini, paragraph, inp_val);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TExternal_app a(app);
 | |
|   a.run();
 | |
|   field().mask().set_focus();
 | |
| 
 | |
|   if (msg.not_empty())
 | |
|   {
 | |
|     TConfig ini(msg, "Transaction");
 | |
|     _rec = ini.get_long("Record");
 | |
|     if (_rec > 0 || !insert)   // Modifica o cancellazione
 | |
|       _cursor->update();       // Forza ricalcolo cursore
 | |
|     if (_rec >= 0)
 | |
|     {
 | |
|       _cursor->file().readat(_rec);
 | |
|       ok = _cursor->ok();
 | |
|       if (ok) 
 | |
|       {
 | |
|         rec_cache(_cursor->file().num()).notify_change();  // Svuota eventule cache
 | |
|         do_output();
 | |
|       }    
 | |
|     }
 | |
|     ::remove(msg);
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| TToken_string& TBrowse::create_siblings(TToken_string& siblings)
 | |
| {
 | |
|   siblings = "";                      // Azzera la lista dei campi associati
 | |
|   
 | |
|   TBit_array key(4);                  // Elenco delle chiavi gia' utilizzate
 | |
|   key.set(_cursor->key());
 | |
| 
 | |
|   TString fn;                         // Nome campo
 | |
|   
 | |
|   // Scorre la lista dei campi di output
 | |
|   int n = 0;  
 | |
|   for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++)
 | |
|   {
 | |
|     const short id = field().atodlg(i);
 | |
|     const TEditable_field& f = field(id);
 | |
|     if (!f.active() || !f.is_edit())  // Scarta i campi non editabili
 | |
|       continue;
 | |
|     const TEdit_field& e = (const TEdit_field&)f;
 | |
|     const TBrowse* b = e.browse();
 | |
|     if (b == NULL) 
 | |
|       continue;                       // Scarta i campi senza ricerca
 | |
|     
 | |
|     const TCursor* c = b->cursor();  
 | |
|     
 | |
|     // Considera ricerche sullo stesso file ma con chiave diversa
 | |
|     if (c->file().num() == _cursor->file().num() && 
 | |
|         (key[c->key()] == FALSE || id == field().dlg()))      
 | |
|     {
 | |
|       fn = _out_fn.get(n);                    // Legge nome del campo su file          
 | |
|       int pos = _items.get_pos(fn);           // Determina header corrispondente
 | |
|       if (pos < 0)                            // Se non lo trova identico ...
 | |
|       {
 | |
|         const int q = fn.find('[');
 | |
|         if (q > 0)
 | |
|         {
 | |
|           fn.cut(q);
 | |
|           pos = _items.get_pos(fn);           // ... ritenta senza parentesi
 | |
|         }
 | |
|       }
 | |
|       if (pos >= 0)
 | |
|       {
 | |
|         siblings.add(id);
 | |
|         const char* h = _head.get(pos); 
 | |
|         siblings.add(h);
 | |
|         const int et = siblings.find('@');
 | |
|         if (et > 0) siblings.cut(et);
 | |
|         key.set(c->key());                    // Marca la chiave come usata
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   return siblings;
 | |
| }
 | |
| 
 | |
| 
 | |
| KEY TBrowse::run()
 | |
| {          
 | |
|   begin_wait();
 | |
|   
 | |
|   do_input(TRUE);
 | |
|   _cursor->read(_isgteq);
 | |
| 
 | |
|   //const TLocalisamfile& f = _cursor->file();
 | |
|   //TString caption(prefix().description(f.name()));
 | |
|   TString caption(_cursor->file().description());
 | |
|   if (!isalnum(caption[0])) 
 | |
|     caption = "Selezione";
 | |
|   
 | |
|   KEY k = K_ESC;
 | |
|   long selected = 0;
 | |
| 
 | |
|   TToken_string siblings, vals; 
 | |
|   create_siblings(siblings);                            
 | |
|   
 | |
|   {
 | |
|     byte buttons = 0;
 | |
|     if (_insert.not_empty())
 | |
|     {   
 | |
|       // Mette il bottone di gestione, a meno che ...   
 | |
|       if (_cursor->items() == 0) 
 | |
|         buttons = 2; // Non mette il bottone collega se non ci sono elementi
 | |
|       else 
 | |
|         buttons = 3; 
 | |
|     
 | |
|       if (_insert[0] == 'M' || _insert[0] == 'R')
 | |
|       {          
 | |
|         const TString& maskname = field().mask().source_file();
 | |
|         if (maskname.mid(2,2).compare("tb", 2, TRUE) == 0 && field().in_key(0))
 | |
|         {
 | |
|           const char* tabname = _cursor->file().name();
 | |
|           if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0) 
 | |
|             buttons = 0;
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|   
 | |
|     for (const char* i = _inp_id.get(0); i; i = _inp_id.get())
 | |
|     {            
 | |
|       if (*i != '\0' && *i != '"' && strchr(i, '@') == NULL)
 | |
|       {
 | |
|         const short id = field().atodlg(i);
 | |
|         const TEditable_field& f = field(id);
 | |
|         if (f.active() && f.is_editable()) 
 | |
|         {           
 | |
|           vals.add(i);
 | |
|           vals.add(f.get());               
 | |
|           vals.add((int)f.dirty());
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|   
 | |
|     end_wait();
 | |
|   
 | |
|     TBrowse_sheet s(_cursor, _items, caption, _head, buttons, &field(), siblings);
 | |
|     k = s.run();
 | |
|     selected = s.selected();
 | |
|   }
 | |
| 
 | |
|   switch (k)
 | |
|   {                
 | |
|     case K_CTRL+'G':    
 | |
|       *_cursor = selected;
 | |
|       k = do_link(FALSE) ? K_ENTER : K_ESC;
 | |
|       break;  
 | |
|     case K_INS:
 | |
|       k = do_link(TRUE) ? K_ENTER : K_ESC;
 | |
|       break;
 | |
|     case K_ENTER:
 | |
|       *_cursor = selected;
 | |
|       do_output();
 | |
|       break;
 | |
|     default:
 | |
|       {
 | |
|         for (const char* i = vals.get(0); i && *i; i = vals.get())
 | |
|         {
 | |
|           const short id = field().atodlg(i);
 | |
|           TEditable_field& f = field(id);
 | |
|           f.set(vals.get());
 | |
|           f.set_dirty(vals.get_int());
 | |
|         }
 | |
|       }
 | |
|       if (k >= K_CTRL)
 | |
|       {
 | |
|         TMask& m = field().mask();                          
 | |
|         const int tag = k - K_CTRL - K_F1;
 | |
|         const short id = siblings.get_int(tag * 2);
 | |
|         TEdit_field& ef = m.efield(id);
 | |
|         ef.set_focus();
 | |
|         k = K_F9;
 | |
|         if (m.is_running())
 | |
|           m.send_key(k, id);
 | |
|       }
 | |
|       break;
 | |
|   }
 | |
|     
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| bool TBrowse::check(CheckTime t)
 | |
| {
 | |
|   bool passed = TRUE;
 | |
| 
 | |
|   if (_secondary == TRUE && t != RUNNING_CHECK)
 | |
|     return TRUE;
 | |
| 
 | |
|   CheckType chk = field().check_type();
 | |
|   if (chk != CHECK_NONE)
 | |
|   {
 | |
|     const TMaskmode mode = (TMaskmode)field().mask().mode();
 | |
|     if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY))
 | |
|       chk = CHECK_NORMAL;
 | |
|     
 | |
|     const int ne = do_input(TRUE);
 | |
|     if (ne || chk == CHECK_REQUIRED)
 | |
|     {               
 | |
|       passed = _cursor->test() == NOERR;
 | |
| 
 | |
|       if (t != FINAL_CHECK)
 | |
|       {
 | |
|         if (passed)
 | |
|         {           
 | |
|           _cursor->repos();
 | |
|           do_output(t);
 | |
|         }
 | |
|         else 
 | |
|         {    
 | |
|           if (chk == CHECK_SEARCH)
 | |
|           {   
 | |
|             passed = TRUE;
 | |
|           }
 | |
|           else
 | |
|           {
 | |
|             do_clear(t);
 | |
|             if (!field().mask().query_mode() && field().check_enabled())
 | |
|               field().set_dirty(3);
 | |
|           }    
 | |
|         }  
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         if (chk == CHECK_SEARCH)
 | |
|           passed = TRUE;
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {         
 | |
|       if (chk == CHECK_SEARCH)
 | |
|         passed = TRUE;
 | |
|       else
 | |
|       {  
 | |
|         if (t != FINAL_CHECK) 
 | |
|           do_clear(t);
 | |
|       }  
 | |
|     }  
 | |
|   }
 | |
|   return passed;
 | |
| }
 | |
| 
 | |
| bool TBrowse::empty_check()
 | |
| {
 | |
|   if (field().mask().query_mode() || field().check_type() != CHECK_REQUIRED)
 | |
|     return TRUE;
 | |
|   else
 | |
|     return do_input() > 0;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TFile_select
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TFile_select::TFile_select(TEdit_field* ef, const char* filter)
 | |
| : TBrowse_button(ef), _filter(filter)
 | |
| { }
 | |
| 
 | |
| void TFile_select::parse_input(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
| 
 | |
| void TFile_select::parse_output(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
|           
 | |
| KEY TFile_select::run()
 | |
| {
 | |
|   DIRECTORY savedir;
 | |
|   FILE_SPEC fs;
 | |
| 
 | |
|   xvt_fsys_get_dir(&savedir);
 | |
|   xvt_fsys_get_dir(&fs.dir);
 | |
| 
 | |
|   strcpy(fs.type, _filter.ext());
 | |
|   strcpy(fs.name, field().get());
 | |
|   strcpy(fs.creator, "AGA");
 | |
| 
 | |
|   bool good = xvt_dm_post_file_open(&fs, (char*)field().prompt()) == FL_OK;
 | |
|   xvt_fsys_set_dir(&savedir);
 | |
| 
 | |
|   if (good)
 | |
|   {
 | |
|     good = _filter.empty() || xvt_str_match(fs.name, _filter, false);
 | |
|     if (good)
 | |
|     {
 | |
|       TFilename path;
 | |
|       xvt_fsys_convert_dir_to_str(&fs.dir, path.get_buffer(), path.size());
 | |
|       path.add(fs.name);
 | |
|       field().set(path);
 | |
|     }
 | |
|     else
 | |
|       field().error_box(TR("Il nome non corrisponde a %s"), _filter.get_buffer());
 | |
|   }
 | |
|   return good ? K_ENTER : K_ESC;
 | |
| }
 | |
| 
 | |
| 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() || xvt_str_match(name, _filter, false);
 | |
|   if (ok && field().roman())  // Must exist
 | |
|     ok = name.exist();
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TDir_select
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TDir_select::TDir_select(TEdit_field* ef) : TBrowse_button(ef)
 | |
| { }
 | |
| 
 | |
| void TDir_select::parse_input(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
| 
 | |
| void TDir_select::parse_output(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
|           
 | |
| KEY TDir_select::run()
 | |
| {
 | |
|   DIRECTORY savedir;
 | |
|   xvt_fsys_get_dir(&savedir);
 | |
| 
 | |
| 	DIRECTORY dir;
 | |
| 	xvt_fsys_convert_str_to_dir(field().get(), &dir);
 | |
|   bool good = xvt_dm_post_dir_sel(&dir) == FL_OK;
 | |
|   xvt_fsys_set_dir(&savedir);
 | |
| 
 | |
|   if (good)
 | |
|   {
 | |
|     TFilename path;
 | |
|     xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size());
 | |
|     field().set(path);
 | |
|   }
 | |
|   return good ? K_ENTER : K_ESC;
 | |
| }
 | |
| 
 | |
| bool TDir_select::check(CheckTime ct)
 | |
| {
 | |
|   const TFilename name = field().get();
 | |
|   if (ct != STARTING_CHECK && name.empty() && 
 | |
|       field().check_type() == CHECK_REQUIRED)
 | |
|     return false;
 | |
|   bool ok = true;
 | |
|   if (field().roman())  // Must exist
 | |
|     ok = name.exist();
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TProfile_select
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TProfile_select::TProfile_select(TEdit_field* ef)
 | |
| : TBrowse_button(ef)
 | |
| { }
 | |
| 
 | |
| void TProfile_select::parse_input(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
| 
 | |
| void TProfile_select::parse_output(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
| 
 | |
| HIDDEN int get_profile_desc(TConfig& cfg, void* jolly)
 | |
| {
 | |
|   const int num = atoi(cfg.get_paragraph());
 | |
|   if (num > 0)
 | |
|   {
 | |
|     TString_array& p = *(TString_array*)jolly;
 | |
|     TToken_string* str = new TToken_string;
 | |
|     str->format("%4d", num);
 | |
|     str->add(cfg.get("Description"));
 | |
|     p.add(str);
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| int TProfile_select::get_descriptions(TString_array& a) const
 | |
| {
 | |
|   TFilename profname; 
 | |
|   field().mask().make_profile_name(profname);
 | |
|   TConfig prof(profname);
 | |
|   a.destroy();
 | |
|   prof.for_each_paragraph(get_profile_desc, &a);
 | |
|   a.sort();
 | |
|   return a.items();
 | |
| }
 | |
|           
 | |
| KEY TProfile_select::run()
 | |
| {                 
 | |
|   TArray_sheet p(3, 3, -3, -3, "Profili", "Codice@6R|Descrizione@60", 0x6, 2);
 | |
|   const short id = DLG_USER+1;
 | |
|   TEdit_field& prompt = p.add_string(id, 0, "Salva con nome ", 1, 0, 60);
 | |
|   p.add_button(DLG_SAVEREC, "~Registra", K_CTRL+'r', BMP_SAVEREC, BMP_SAVERECDN);
 | |
|   prompt.set(field().get());
 | |
|   
 | |
|   TMask& m = field().mask();
 | |
|   TFilename profname; m.make_profile_name(profname);
 | |
|   
 | |
|   bool running = TRUE;
 | |
|   KEY key;
 | |
|   while (running)
 | |
|   {
 | |
|     p.destroy();  
 | |
|     TString_array& a = p.rows_array(); 
 | |
|     get_descriptions(a);
 | |
|     p.field(DLG_SAVEREC).enable(a.items()>0);
 | |
|     FOR_EACH_ARRAY_ROW_BACK(a, r, row)
 | |
|       if (field().get() == row->get(1)) break;
 | |
|     if (r)
 | |
|       p.select(r);
 | |
|   
 | |
|     key = p.run();
 | |
|     switch(key)
 | |
|     {       
 | |
|     case K_ENTER:      
 | |
|       { 
 | |
|         const int num = p.row().get_int(0);
 | |
|         TString16 para; para << m.load_profile(num);
 | |
|         prompt.set(p.row().get(1));
 | |
|         running = FALSE;
 | |
|       }
 | |
|       break;
 | |
|     case K_CTRL+'r':             
 | |
|       {    
 | |
|         const TString& name = p.get(id);
 | |
|         FOR_EACH_ARRAY_ROW_BACK(a, r, row)
 | |
|           if (r != p.selected() && name == row->get(1)) break;
 | |
|         if (r < 0)
 | |
|         {
 | |
|           const int num = p.row().get_int(0);
 | |
|           m.save_profile(num, name);
 | |
|           running = FALSE;
 | |
|         }
 | |
|         else
 | |
|           error_box("Esiste gia' un profilo di nome\n%s", 
 | |
|                     (const char*)name);
 | |
|       }
 | |
|       break;
 | |
|     case K_INS:
 | |
|       {
 | |
|         const TString& name = p.get(id);
 | |
|         if (!name.blank())
 | |
|         {
 | |
|           FOR_EACH_ARRAY_ROW_BACK(a, r, row)
 | |
|             if (name == row->get(1)) break;
 | |
|           if (r < 0)  
 | |
|           {
 | |
|             TString16 para; para << m.save_profile(-1, name);
 | |
|             field().set(name);
 | |
|             running = FALSE;
 | |
|           }
 | |
|           else
 | |
|             error_box("Esiste gia' un profilo di nome\n%s", 
 | |
|                       (const char*)name);
 | |
|         }
 | |
|         else
 | |
|           error_box("E' necessario dare un nome al profilo");
 | |
|       }
 | |
|       break;
 | |
|     case K_DEL:
 | |
|       {                                 
 | |
|         TString16 para; para << p.row().get_int(0);
 | |
|         const TString desc = p.row().get(1);
 | |
|         TConfig prof(profname, para);
 | |
|         if (yesno_box("Confermare la cancellazione del profilo %s\n%s", 
 | |
|                       (const char*)para, (const char*)desc))
 | |
|           prof.remove_all();
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       running = FALSE;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   field().set(prompt.get());
 | |
|   return key;
 | |
| }
 | |
| 
 | |
| bool TProfile_select::check(CheckTime ct)
 | |
| {            
 | |
|   switch (ct)
 | |
|   {
 | |
|   case STARTING_CHECK:
 | |
|     {     
 | |
|       TMask& m = field().mask();
 | |
|       TFilename name; m.make_profile_name(name);
 | |
|       TString16 para; para << m.load_profile();
 | |
|       TConfig ini(name, para);
 | |
|       field().set(ini.get("Description"));
 | |
|     }
 | |
|     break;
 | |
|   case RUNNING_CHECK:
 | |
|     if (!field().empty())
 | |
|     { 
 | |
|       const TString& name = field().get();
 | |
|       TString_array a;
 | |
|       get_descriptions(a);               
 | |
|       FOR_EACH_ARRAY_ROW_BACK(a, r, row)      
 | |
|       {
 | |
|         if (name == row->get(1))
 | |
|         {       
 | |
|           field().mask().load_profile(row->get_int(0));
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       if (r < 0)  
 | |
|         return field().error_box("Profilo inesistente");
 | |
|     }
 | |
|     break;
 | |
|   case FINAL_CHECK:
 | |
|     if (!field().active())
 | |
|     {
 | |
|       TMask& m = field().mask();
 | |
|       m.save_profile();
 | |
|     }
 | |
|     break;  
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TReport_select
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TReport_select::TReport_select(TEdit_field* ef, const char* library)
 | |
| : TBrowse_button(ef), _library(library)
 | |
| { }
 | |
| 
 | |
| void TReport_select::parse_input(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
| 
 | |
| void TReport_select::parse_output(TScanner& scanner)
 | |
| {
 | |
|   scanner.pop();
 | |
| }
 | |
|           
 | |
| KEY TReport_select::run()
 | |
| {
 | |
|   TFilename path;
 | |
|   if (select_custom_file(path, "rep", _library))
 | |
|   {
 | |
|     path = path.name();
 | |
|     path.ext("");
 | |
|     field().set(path);
 | |
|   }
 | |
| 
 | |
|   return path.not_empty() ? K_ENTER : K_ESC;
 | |
| }
 | |
| 
 | |
| bool TReport_select::check(CheckTime ct)
 | |
| {
 | |
|   TFilename name = field().get();
 | |
|   if (ct != STARTING_CHECK && name.empty() && 
 | |
|       field().check_type() == CHECK_REQUIRED)
 | |
|     return false;
 | |
| 
 | |
|   bool ok = true;
 | |
|   if (field().roman())  // Must exist
 | |
|     ok = name.custom_path();
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TEdit_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TEdit_field::TEdit_field(TMask* mask)
 | |
| : TEditable_field(mask), _check(CHECK_NONE),
 | |
|   _forced(FALSE), _check_enabled(FALSE), _browse(NULL)
 | |
| { }
 | |
| 
 | |
| TEdit_field::~TEdit_field()
 | |
| {
 | |
|   if (_browse) delete _browse;
 | |
| }
 | |
| 
 | |
| word TEdit_field::class_id() const
 | |
| { return CLASS_EDIT_FIELD; }
 | |
| 
 | |
| 
 | |
| void TEdit_field::set_len(short w)
 | |
| {
 | |
| }
 | |
| 
 | |
| void TEdit_field::set_width(short width, short dwidth)
 | |
| {
 | |
| 
 | |
|   RCT rect;
 | |
|   get_rect(rect);
 | |
|   rect.right= rect.left+width;
 | |
|   set_rect(rect);
 | |
| } 
 | |
| 
 | |
| 
 | |
| void TEdit_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._size  = scanner.integer();
 | |
| #ifdef DBG  
 | |
|   if (_ctl_data._size <= 0)
 | |
|   {
 | |
|     _ctl_data._size = 8;
 | |
|     NFCHECK("Il campo %d ha dimensione nulla: uso %d", 
 | |
|              _ctl_data._dlg, _ctl_data._size);
 | |
|   }
 | |
| #endif
 | |
|   _ctl_data._width = scanner.integer();
 | |
|   if (_ctl_data._width == 0) 
 | |
|     _ctl_data._width = _ctl_data._size;
 | |
| }
 | |
| 
 | |
| 
 | |
| const TBrowse* TEdit_field::parse_browse(TScanner& scanner) const
 | |
| {
 | |
|   const int id = scanner.integer();
 | |
|   const TEdit_field& f = mask().efield(id);
 | |
|   const TBrowse* b = f.browse();
 | |
|   return b;
 | |
| }
 | |
| 
 | |
| bool TEdit_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PI")            // PICTURE
 | |
|   {
 | |
|     _picture = scanner.string();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "CH")
 | |
|   { 
 | |
|     const TString& ct = scanner.popkey();
 | |
|     if (ct == "NO") _check = CHECK_NORMAL; else 
 | |
|     if (ct == "RE") _check = CHECK_REQUIRED; else 
 | |
|     if (ct == "FO") { _check = CHECK_REQUIRED; _forced = TRUE; } else 
 | |
|     if (ct == "SE") _check = CHECK_SEARCH;
 | |
|     else _check = CHECK_NONE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "US")            // USE
 | |
|   {
 | |
| #ifdef DBG  
 | |
|     if (_browse != NULL)
 | |
|       return yesnofatal_box("USE duplicata nel campo %d", dlg());
 | |
| #endif
 | |
|     
 | |
|     int key = 1;
 | |
|     TRelation* r = NULL;
 | |
| 
 | |
|     const int logicnum = scanner.integer();
 | |
|     TString16 tabmaskname;
 | |
| 
 | |
|     if (logicnum > 0) 
 | |
|     {
 | |
|       TDir d; d.get(logicnum);
 | |
|       if (fexist(d.filename()))        // Controlla l'esistenza del file
 | |
|         r = new TRelation(logicnum);
 | |
| #ifdef DBG  
 | |
|       else      
 | |
|         yesnofatal_box("Impossibile creare una USE sul file %s",d.filename());
 | |
| #endif
 | |
|     }  
 | |
|     else
 | |
|     {
 | |
|       tabmaskname  = scanner.pop();
 | |
| #ifdef DBG  
 | |
|       if (tabmaskname.len() > 4)
 | |
|         return yesnofatal_box("'%s' non e' una tabella valida: %d",
 | |
|                               (const char*)tabmaskname, dlg());
 | |
| #endif
 | |
|       TDir d; d.get(TTable::name2log(tabmaskname));
 | |
|       if (fexist(d.filename()))        // Controlla l'esistenza del file
 | |
|         r = new TRelation(tabmaskname);
 | |
|     }
 | |
| 
 | |
|     if (scanner.popkey() == "KE")
 | |
|     {
 | |
|       key = scanner.integer();
 | |
| #ifdef DBG  
 | |
|       if (key < 1 || key > MAX_KEYS)
 | |
|       {
 | |
|         yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg());
 | |
|         key = 1;
 | |
|       }
 | |
| #endif      
 | |
|     }
 | |
|     else scanner.push();
 | |
| 
 | |
|     TString filter;
 | |
|     if (scanner.popkey() == "SE")
 | |
|       filter = (const char*)scanner.line();
 | |
|     else
 | |
|       scanner.push();
 | |
|     
 | |
|     if (r != NULL)    
 | |
|     {
 | |
|       _browse = new TBrowse(this, r, key, filter); // create browse with no filter ...
 | |
| 
 | |
|       // ... complete relation by parsing all Join items ...
 | |
|       while (scanner.popkey() == "JO")
 | |
|       {
 | |
|         if (browse()) 
 | |
|           browse()->parse_join(scanner);
 | |
|         else
 | |
|           scanner.line();
 | |
|       }
 | |
|       scanner.push();
 | |
|       
 | |
|       if (tabmaskname.not_empty())
 | |
|       {
 | |
|         tabmaskname.insert("MTB", 0);
 | |
|         browse()->set_insert(tabmaskname);
 | |
|       }
 | |
|       _check_enabled = TRUE;
 | |
|     }  
 | |
|     else
 | |
|     {
 | |
|       while (scanner.popkey() == "JO")
 | |
|         scanner.line();               
 | |
|       scanner.push();
 | |
|     }
 | |
|     
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "CO")                    // Copyuse
 | |
|   {
 | |
|     const TString16 what(scanner.popkey());
 | |
|     const TBrowse* b = parse_browse(scanner);
 | |
| 
 | |
|     CHECK(b,"Impossibile copiare la browse da un campo visto che quel campo non l'ha" );
 | |
|     if (b)
 | |
|     {
 | |
|       if (what == "US" || what == "AL")
 | |
|       {
 | |
|         if (_browse == NULL)
 | |
|           _browse = new TBrowse(this, b->cursor());
 | |
|         else
 | |
|           NFCHECK("COPY USE e USE nel campo %d", _ctl_data._dlg);
 | |
|       }        
 | |
|   
 | |
|       if (_browse) 
 | |
|       {
 | |
|         _check_enabled = TRUE;
 | |
|         return browse()->parse_copy(what, *b);
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|       NFCHECK("Il campo %d non puo' copiare la browse da chi non ce l'ha", _ctl_data._dlg);
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "SH")            // SHEET
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_browse) 
 | |
|       NFCHECK("SHEET duplicato nel campo %d", _ctl_data._dlg);
 | |
| #endif
 | |
|     _browse = new TList_sheet(this, _ctl_data._prompt, scanner.string()); 
 | |
|     _check_enabled = TRUE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "FS")            // FSELECT
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_browse) 
 | |
|       NFCHECK("FSELECT duplicato nel campo %d", _ctl_data._dlg);
 | |
| #endif
 | |
|     _browse = new TFile_select(this, scanner.string()); 
 | |
|     _check_enabled = TRUE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "DS")            // DSELECT
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_browse) 
 | |
|       NFCHECK("DSELECT duplicato nel campo %d", _ctl_data._dlg);
 | |
| #endif
 | |
|     _browse = new TDir_select(this); 
 | |
|     _check_enabled = TRUE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "PS")            // PSELECT
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_browse) 
 | |
|       NFCHECK("PSELECT duplicato nel campo %d", _ctl_data._dlg);
 | |
| #endif
 | |
|     _browse = new TProfile_select(this); 
 | |
|     _check_enabled = TRUE;
 | |
|     set_default("NONE");
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "RS")            // RSELECT
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_browse) 
 | |
|       NFCHECK("RSELECT duplicato nel campo %d", _ctl_data._dlg);
 | |
| #endif
 | |
|     _browse = new TReport_select(this, scanner.string()); 
 | |
|     _check_enabled = TRUE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "IT")            // ITEM
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (sheet() == NULL) 
 | |
|       return yesnofatal_box("ITEM senza SHEET nel campo %d", _ctl_data._dlg);
 | |
|     else  
 | |
| #endif    
 | |
|     sheet()->parse_item(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "IN")
 | |
|   {
 | |
|     if (_browse) 
 | |
|       _browse->parse_input(scanner);
 | |
|     else
 | |
|       scanner.line();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "DI")
 | |
|   {
 | |
|     if (browse()) 
 | |
|       browse()->parse_display(scanner);
 | |
|     else
 | |
|       scanner.line();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "OU")
 | |
|   {
 | |
|     if (_browse) 
 | |
|       _browse->parse_output(scanner);
 | |
|     else
 | |
|       scanner.line();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "AD")
 | |
|   {
 | |
|     if (browse()) 
 | |
|       browse()->parse_insert(scanner);
 | |
|     else
 | |
|       scanner.line();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "ME")
 | |
|   {                
 | |
|     TString& l = scanner.line().strip_spaces();
 | |
|     int m = 0;
 | |
|     if (l[0] == '0')
 | |
|     {            
 | |
|       l.ltrim(1);
 | |
|       l.ltrim();    
 | |
|       m = 1;
 | |
|     }                      
 | |
|     message(m, TRUE)->add(l);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TEditable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| void TEdit_field::set_background()
 | |
| {
 | |
| 	COLOR c = NORMAL_BACK_COLOR;
 | |
| 	if (enabled())
 | |
| 	{
 | |
| 		int status = required() ? 1 : 0;
 | |
| 		
 | |
| 		if (read_only())
 | |
| 			status |= 2;
 | |
| 		switch (status)
 | |
| 		{
 | |
| 			case 1:
 | |
| 				if (NORMAL_BACK_COLOR != REQUIRED_BACK_COLOR)
 | |
| 					c = REQUIRED_BACK_COLOR;
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				c = blend_colors(DISABLED_BACK_COLOR, NORMAL_BACK_COLOR, 0.5);
 | |
| 				break;
 | |
| 			case 3:
 | |
| 				c = blend_colors(DISABLED_BACK_COLOR, REQUIRED_BACK_COLOR, 0.5);
 | |
| 				break;
 | |
| 			default:
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 	((TField_control*)_ctl)->set_back_color(c);
 | |
| 	if (_browse)
 | |
|     ((TField_control*)_ctl)->show_button(active());
 | |
| }
 | |
| 
 | |
| void TEdit_field::check_type(CheckType c)
 | |
| { 
 | |
| 	_check = c; 
 | |
| 	set_background();
 | |
| }
 | |
| 
 | |
| void TEdit_field::set_read_only(bool r) 
 | |
| { 
 | |
| 	if (r != read_only())
 | |
| 	{
 | |
| 		TMask_field::set_read_only(r);
 | |
| 		const bool ok = r == read_only();
 | |
| 		if (ok)
 | |
| 		{
 | |
| 			set_background();
 | |
| 			if (_browse && _browse->is_browse())
 | |
| 			{
 | |
| 				TToken_string out_ids(((TBrowse *)_browse)->get_output_fields());
 | |
| 				TMask & m = mask();
 | |
| 				FOR_EACH_TOKEN(out_ids, fld)
 | |
| 					m.field(atoi(fld)).set_read_only(r);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| // Filtro magico sulle ditte esistenti
 | |
| HIDDEN bool firm_filter(const TRelation* rel)
 | |
| {
 | |
|   const long firm = rel->curr().get_long("CODDITTA");
 | |
|   return prefix().exist(firm);
 | |
| }
 | |
| 
 | |
| void TEdit_field::create(WINDOW parent)
 | |
| {
 | |
|   const int len = create_prompt(parent, 0, 0);
 | |
|   
 | |
|   _size = _ctl_data._size;
 | |
|   _ctl_data._x += len;
 | |
|   
 | |
|   if (_browse)                // Decide se attivare o meno il bottone di ricerca
 | |
|     _ctl_data._flags << 'B';
 | |
|   
 | |
|   _ctl = new TField_control(parent, _ctl_data._dlg,
 | |
|                             _ctl_data._x, _ctl_data._y, 
 | |
|                             _ctl_data._width, _ctl_data._size,
 | |
|                             _ctl_data._flags, "");
 | |
|   
 | |
|   if (_browse && !enabled_default())
 | |
|     ((TField_control*)_ctl)->show_button(false);
 | |
| 
 | |
|   if (_browse && validate_func() == 24)
 | |
|   {
 | |
|     TCursor* cursor = browse()->cursor();
 | |
|     if (cursor)
 | |
|     {
 | |
|       const int logicnum = cursor->file().num();
 | |
|       if (logicnum == LF_NDITTE)
 | |
|         cursor->set_filterfunction(firm_filter);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 	if (required())
 | |
| 		check_type(CHECK_REQUIRED);  // Force color change
 | |
| }
 | |
| 
 | |
| const char* TEdit_field::reformat(const char* str) const
 | |
| {
 | |
|   TString& s = _ctl_data._park;
 | |
|   s = str;
 | |
|   const byte trim_mode = _flags.trim;
 | |
|   
 | |
|   smart_trim(s, trim_mode);
 | |
| 
 | |
|   if (s.not_empty())
 | |
|   {            
 | |
|     word len = s.len();
 | |
|     if (len > size())
 | |
|     {
 | |
| #ifdef DBG      
 | |
|       yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), str, _size);
 | |
| #endif      
 | |
|       s.cut(len = size());
 | |
|     }
 | |
| 
 | |
|     if (_flags.zerofilled)
 | |
|     {                     
 | |
|       if  (len < size())
 | |
|       {
 | |
|         if (isdigit(s[0]) && real::is_natural(s))
 | |
|           s.right_just(size(), '0');
 | |
|       }
 | |
|       const char * w;
 | |
|       for (w = (const char *) s; *w == '0'; w++) ;
 | |
|       if (*w == '\0')
 | |
|         s.cut(0);
 | |
|     }
 | |
|     
 | |
|     if (_flags.rightjust && !(trim_mode & 1) && !s.blank())
 | |
|       s.right_just(size());
 | |
| 
 | |
|     if (_flags.uppercase)
 | |
|       s.upper();
 | |
|   } 
 | |
|   
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| const char* TEdit_field::raw2win(const char* raw) const
 | |
| {
 | |
|   return reformat(raw);
 | |
| }
 | |
| 
 | |
| const char* TEdit_field::win2raw(const char* win) const
 | |
| {
 | |
|   return reformat(win);
 | |
| }
 | |
| 
 | |
| void TEdit_field::set_window_data(const char* data)
 | |
| {                 
 | |
|   _ctl->set_caption(data);
 | |
| }
 | |
| 
 | |
| void TEdit_field::autoselect(bool on)
 | |
| {
 | |
|   _ctl->autoselect(on);
 | |
| }
 | |
| 
 | |
| TString& TEdit_field::get_window_data()
 | |
| {
 | |
|   _str = win2raw(_ctl->caption());
 | |
|   return _str;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TEdit_field::on_hit()
 | |
| {              
 | |
|   const int vf = validate_func();
 | |
|   if (vf >= 0)
 | |
|   {               
 | |
|     if (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC || vf == 21)
 | |
|     {
 | |
|       const bool ok = validate(K_TAB);     // Check validation expression
 | |
|       if (!ok) return FALSE;
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   const bool ok = handler(K_TAB);
 | |
|   if (ok && has_message())
 | |
|   {
 | |
|     if (empty() && message(1)) 
 | |
|       do_message(1);
 | |
|     else 
 | |
|       do_message(0);
 | |
|   }
 | |
|   return ok;
 | |
| } 
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Mostra un messaggio di errore di default per il campo
 | |
| //
 | |
| // @rdesc Ritorna sempre FALSE
 | |
| bool TEdit_field::default_error_box() const
 | |
| 
 | |
| // @comm Se il campo non possiede un warning particolare chiama la <f error_box>
 | |
| //       indicando genericamente che il valore immesso non e' valido, altrimenti
 | |
| //       riporta il warning associato al campo
 | |
| {                 
 | |
|   if (!has_warning()) 
 | |
|   {                   
 | |
|     const TString p(prompt());
 | |
|     if (isalnum(p[0]))
 | |
|     {
 | |
|       const TString val(get());
 | |
|       
 | |
|       error_box(TR("Valore non valido per %s: %s"), (const char*)p, (const char*)val);
 | |
|     }
 | |
|     else  
 | |
|       error_box(TR("Valore non valido: %s"), (const char*)get());
 | |
|   }    
 | |
|   else
 | |
|     error_box(get_warning());
 | |
|   return FALSE;  
 | |
| }
 | |
| 
 | |
| bool TEdit_field::autosave(TRelation& r) 
 | |
| {
 | |
|   if (_flags.user)         
 | |
|     _str = user();
 | |
|   return TEditable_field::autosave(r);
 | |
| }
 | |
| 
 | |
| bool TEdit_field::on_key(KEY key)
 | |
| {            
 | |
|   const int vf = validate_func();
 | |
|   
 | |
|   switch(key)
 | |
|   {  
 | |
|   case K_CTRL+K_TAB:
 | |
|     set_focusdirty(FALSE);
 | |
|     break;              
 | |
|   case K_TAB:    
 | |
|   /*          
 | |
|     if (vf >= 0 &&  (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC))
 | |
|       set_focusdirty();            // Forza validate
 | |
|   */      
 | |
| 
 | |
|     if (to_check(K_TAB, TRUE))
 | |
|     {
 | |
|       if (class_id() == CLASS_EDIT_FIELD) // Altrimenti l'ha gia' fatto
 | |
|       {
 | |
|         const TString& raw = get_window_data();
 | |
|         set_window_data(raw2win(raw));
 | |
|       }
 | |
|       
 | |
|       bool ok = validate(key);     // Check validation expression
 | |
|       if (!ok)
 | |
|       {      
 | |
|         if (has_warning()) 
 | |
|           default_error_box();
 | |
|         return FALSE;
 | |
|       }
 | |
| 
 | |
|       TMask& m = mask();
 | |
|       const bool query = m.query_mode();
 | |
|       const bool vuoto = empty();
 | |
|       
 | |
|       if (_browse)
 | |
|       {          
 | |
|         if (browse()) 
 | |
|         {
 | |
| //          if (check_enabled() && (!query || forced()) && vf != 21) 
 | |
|           if (check_enabled() && vf != 21)
 | |
|           { 
 | |
|             if (!query || forced()) 
 | |
|               ok = _browse->check();                                
 | |
|             else
 | |
|               _browse->check();                                
 | |
|           }                    
 | |
|         }    
 | |
|         else
 | |
|         {
 | |
|           ok = query || _browse->check();  // Check consistency
 | |
|         }  
 | |
|       }                   
 | |
|       if (ok) 
 | |
|         ok = on_hit();
 | |
|       else           
 | |
|       {
 | |
|         if (vuoto)
 | |
|           ok = TRUE;
 | |
|         else
 | |
|           default_error_box();       
 | |
|       }
 | |
|       
 | |
|       if (ok)
 | |
|       {                
 | |
|         set_focusdirty(FALSE);
 | |
|         if (query && m.is_running() && in_key(0))
 | |
|           test_key_complete();
 | |
|       }
 | |
|       else
 | |
|         set_focusdirty(!vuoto);
 | |
|       
 | |
|       return ok;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       TMask& m = mask();
 | |
|       bool ok = handler(K_TAB);
 | |
|       if (ok && m.query_mode() && m.is_running() && in_key(0))
 | |
|         test_key_complete();
 | |
|       return ok;
 | |
|     }
 | |
|     break;
 | |
|   case K_ENTER:
 | |
| //    if (field() != NULL || mask().mode() == NO_MODE)
 | |
|     {
 | |
|       bool ok = validate(K_ENTER);                           // Check validation expression
 | |
|       if (!ok)
 | |
|       {
 | |
|         if (has_warning()) 
 | |
|           default_error_box();
 | |
|         return FALSE;
 | |
|       }
 | |
|       
 | |
|       if (!mask().query_mode() /* || forced() */)
 | |
|       {
 | |
|         ok = !(check_type() == CHECK_REQUIRED && empty());
 | |
|         // check consistency
 | |
|         if (ok && _browse)
 | |
|         {
 | |
|           if (browse())
 | |
|           {
 | |
|             if (ok && check_enabled() && vf != 21) // 21 = NOT_EMPTY_CHECK_FIELD
 | |
|             {
 | |
|               if (dirty()) ok = browse()->check(FINAL_CHECK);     // Check consistency
 | |
|               else ok = browse()->empty_check();
 | |
|             }
 | |
|           }
 | |
|           else
 | |
|             ok = _browse->check(FINAL_CHECK);  
 | |
| 
 | |
|         }
 | |
|         if (!ok) return default_error_box();
 | |
|       }  
 | |
|     }
 | |
|     break;
 | |
|   case K_F2:
 | |
| 		if (!read_only())
 | |
| 			set("");
 | |
|     break;
 | |
|   case K_F9:
 | |
|     if (!read_only())
 | |
| 		{
 | |
| 			if (check_enabled())
 | |
| 			{  
 | |
| 				if (focusdirty()) 
 | |
| 					get_window_data();
 | |
| 
 | |
| 				KEY k = K_ESC;
 | |
| 				if (_browse) k = _browse->run();
 | |
| 				else beep();
 | |
| 
 | |
| 				if (k != K_F9) 
 | |
| 					set_focus();
 | |
|       
 | |
| 				if (k == K_ENTER)
 | |
| 				{     
 | |
| 					bool ok = TRUE; 
 | |
| 
 | |
| 					set_dirty();                       
 | |
| 					// Controlla i validate che non vengono fatti da on_hit
 | |
| 					const int vf = validate_func(); 
 | |
| 					if (vf >= 0 && vf != AUTOEXIT_FUNC && vf != NUMCALC_FUNC &&
 | |
| 							vf != STRCALC_FUNC && vf != 21)
 | |
| 					{    
 | |
| 						ok = validate(K_TAB);
 | |
| 						if (!ok && has_warning())
 | |
| 							default_error_box();
 | |
| 					}
 | |
|         
 | |
| 					// Esegue handler
 | |
| 					if (ok)
 | |
| 						ok = on_hit();
 | |
|           
 | |
| 					if (ok)
 | |
| 					{
 | |
| 						TMask & m = mask();
 | |
| 						if (m.is_running())   
 | |
| 						{                     
 | |
| 							set_focusdirty(FALSE);       // Evita doppia esecuzione handlers!
 | |
| 							if (m.query_mode() && in_key(0))
 | |
| 								test_key_complete();
 | |
| 							if (m.is_running())
 | |
| 							{                 
 | |
| 								set_focusdirty(FALSE);
 | |
| 								send_key(K_TAB, 0);        // Passa al campo successivo
 | |
| 							}  
 | |
| 						}
 | |
| 					}
 | |
| 					return ok;
 | |
| 				} 
 | |
| 				else 
 | |
| 					return FALSE;
 | |
| 			}
 | |
| 			else
 | |
| 				if (_browse == NULL && has_button())
 | |
| 				{
 | |
| 					if (focusdirty()) 
 | |
| 						get_window_data();
 | |
| 					return handler(K_F9);
 | |
| 				}  
 | |
| 		}
 | |
|     break;                
 | |
|   case K_CTRL+K_SPACE:
 | |
|     set_dirty(TRUE);
 | |
|     return handler(K_SPACE);
 | |
|   default:   
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return TEditable_field::on_key(key);
 | |
| }
 | |
| 
 | |
| // @mfunc Controlla se il campo ha la necessita' di eseguire una ricerca sul cursore o
 | |
| //        sulla tabella associata al momento della sua inizializzazione
 | |
| //
 | |
| // @rdesc Ritorna TRUE se il campo ha un TArray_sheet associato oppure un TCursor_sheet 
 | |
| //        con check_type non nullo.
 | |
| bool TEdit_field::has_check() const
 | |
| {          
 | |
|   bool ok = FALSE;
 | |
|   if (_browse)
 | |
|     ok = browse() == NULL || check_type() != CHECK_NONE;
 | |
|   return ok;  
 | |
| }
 | |
| 
 | |
| bool TEdit_field::check(CheckTime t)
 | |
| {                
 | |
|   bool ok = TRUE;
 | |
|   if (check_enabled() || (t == STARTING_CHECK && shown()))
 | |
|   {                        
 | |
|     if (_browse && validate_func() != 21)
 | |
|       ok = _browse->check(t);
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| void TEdit_field::set_query_button(TBrowse_button * brw) 
 | |
| {
 | |
|   if (_browse) 
 | |
|     delete _browse;
 | |
|   _browse=brw;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| void TEdit_field::enable(bool on)
 | |
| {
 | |
|   TEditable_field::enable(on);
 | |
| 	set_background();
 | |
| }
 | |
| 
 | |
| // @mfunc Permette di abilitare/disabilitare un check di un campo
 | |
| void TEdit_field::enable_check(
 | |
|   bool on) // @parm Operazione da svolgere
 | |
|   //
 | |
|   // @flag TRUE | Abilita il check del campo (default)
 | |
|   // @flag FALSE | Disabilita il check del campo
 | |
| {
 | |
|   _check_enabled = on;
 | |
|   ((TField_control*)_ctl)->show_button(on && active());
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Date_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TDate_field::TDate_field(TMask* m) : TEdit_field(m)
 | |
| { }
 | |
| 
 | |
| word TDate_field::class_id() const
 | |
| { return CLASS_DATE_FIELD; }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TDate_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_DATE_FIELD || TEdit_field::is_kind_of(cid); }
 | |
| 
 | |
| void TDate_field::create(WINDOW w)
 | |
| {
 | |
|   // Elimina il flag R che si interpreta come salva in formato ANSI 
 | |
|   _ctl_data._flags.strip("AR");    
 | |
|   
 | |
|   TEdit_field::create(w);
 | |
|   if (automagic())
 | |
|   {
 | |
|     TDate d(TODAY);
 | |
|     set(d.string());
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TDate_field::parse_head(TScanner&) 
 | |
| {
 | |
|   _ctl_data._size = _ctl_data._width = 10;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Permette di formattare la data secondo i flag correnti
 | |
| //
 | |
| // @rdesc Ritorna la data formattata
 | |
| const char* TDate_field::win2raw(
 | |
|   const char* datum) const // @parm Stringa contenenete la data da formattare
 | |
|   
 | |
|   // @comm Permette di gestire anche alcuni date particolari come:
 | |
|   //
 | |
|   // @flag IERI | Inserisce la data del giorno precedente a quella del sistema
 | |
|   // @flag OGGI | Inserisce la data del sistema
 | |
|   // @flag DOMANI | Inserisce la data del giorno successivo a quella del sistema
 | |
|   // @flag PRIMO | Primo giorno dell'anno (01-01-aa)
 | |
|   // @flag PASQUA | Giorno di pasqua
 | |
|   // @flag ANGELO | Lunedi' dell'angelo
 | |
|   // @flag NATALE | Giorno di natale (25-12-aa)
 | |
|   // @flag ULTIMO | Ultimo giorno dell'anno (31-12-aa)
 | |
| { 
 | |
|   TString& s = _ctl_data._park;
 | |
|   s = datum; s.trim();
 | |
|   if (s.not_empty())
 | |
|   {
 | |
|     if (isdigit(s[0]) && s.len() < 10)
 | |
|     {                   
 | |
|       long d;
 | |
|       int m, y;
 | |
|       const int items = sscanf(s, "%ld-%d-%d", &d, &m, &y);
 | |
|       switch(items)
 | |
|       {      
 | |
|       case 1:              
 | |
|         d = atoi(s.left(2));
 | |
|         m = atoi(s.mid(2, 2)); 
 | |
|         y = atoi(s.mid(4));
 | |
|         break;
 | |
|       case 2:  
 | |
|         y = 0;
 | |
|         break;
 | |
|       case 3: 
 | |
|         break;
 | |
|       default:            
 | |
|         d = 0;
 | |
|         break;
 | |
|       }
 | |
|       if (d > 0)
 | |
|       {
 | |
|         if (m <= 0 || y <= 0)
 | |
|         {
 | |
|           const TDate oggi(TODAY);
 | |
|           if (m <= 0) 
 | |
|             m = oggi.month();
 | |
|           if (y <= 0) 
 | |
|             y = oggi.year();
 | |
|         }  
 | |
|         if (y < 100) 
 | |
|           y += (y <= 10) ? 2000 : 1900;
 | |
|         s.format("%02d-%02d-%4d", int(d), m, y);
 | |
|       }  
 | |
|     }
 | |
|     else
 | |
|     {          
 | |
|       bool ok = TRUE;
 | |
|       TDate g(TODAY);
 | |
|       s.upper();
 | |
|       if (s[0] == 'I') // "IERI"
 | |
|       {
 | |
|         --g;
 | |
|       } else
 | |
|       if (s[0] == 'D') // "DOMANI"
 | |
|       {
 | |
|         ++g;
 | |
|       } else
 | |
|       if (s.starts_with("PO")) // "POSDOMANI"
 | |
|       {
 | |
|         g += 2;
 | |
|       } else
 | |
|       if (s.starts_with("PA")) // s == "PASQUA"
 | |
| 			{
 | |
| 				g.set_easter();
 | |
| 			} else
 | |
|       if (s.starts_with("AN")) // s == "ANGELO"
 | |
| 			{
 | |
| 				g.set_easter();
 | |
| 				++g;
 | |
| 			} else
 | |
|       if (s[0] == 'A') // s == "ALTROIERI"
 | |
|       {
 | |
|         g -= 2;
 | |
|       } else
 | |
|       if (s[0] == 'P') // s == "PRIMO"
 | |
|       {
 | |
|         g.set_month(1);
 | |
|         g.set_day(1);
 | |
|       } else
 | |
|       if (s[0] == 'N') // s == "NATALE"
 | |
|       {
 | |
|         g.set_month(12);
 | |
|         g.set_day(25);
 | |
|       } else
 | |
|       if (s[0] == 'U') //s == "ULTIMO"
 | |
|       { 
 | |
|         g.set_month(12);
 | |
|         g.set_day(31);
 | |
|       } else
 | |
|       if (s[0] != 'O')  // s != "OGGI"
 | |
|         ok = FALSE;
 | |
|       if (ok)
 | |
|         s = g.string();  
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| const char* TDate_field::reformat(const char* str) const
 | |
| {                
 | |
|   TString& s = _ctl_data._park;
 | |
|   s = str;
 | |
|   if (s.len() == 8) 
 | |
|     s = TDate(str).string();
 | |
|   else
 | |
|     if (s.blank())
 | |
|       s.cut(0);  
 | |
|   return s;  
 | |
| }
 | |
| 
 | |
| const char* TDate_field::raw2win(
 | |
|   const char* datum) const // @parm Stringa contenenete la data da formattare
 | |
| {
 | |
|   return reformat(datum);  
 | |
| }
 | |
| 
 | |
| bool TDate_field::on_key(KEY key)
 | |
| {
 | |
|   if (to_check(key))
 | |
|   {
 | |
|     const TString& data = get_window_data();  
 | |
|     if (data.not_empty())        // data not empty
 | |
|     { 
 | |
|       if (!TDate::isdate(data))
 | |
|       {
 | |
|         error_box("Data errata o formato non valido");
 | |
|         return FALSE;
 | |
|       }
 | |
|       else
 | |
|         set_window_data(data);
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (key == K_F9 && browse() == NULL)
 | |
|     {
 | |
|       RCT rct; get_rect(rct);
 | |
|       const PNT pos = { rct.top, rct.right };
 | |
| 
 | |
|       TDate olddate;
 | |
|       const TString& data = get_window_data();
 | |
|       if (TDate::isdate(data))
 | |
|         olddate = TDate(data);
 | |
|       
 | |
|       long ansidate = olddate.date2ansi();
 | |
|       ansidate = xvt_dm_post_choose_date(parent(), pos, ansidate);
 | |
|       const TDate newdate(ansidate);
 | |
|       if (newdate != olddate)
 | |
|         set(newdate.string());
 | |
|       return true;
 | |
|     }
 | |
|     if (_ctl->is_edit_key(key))
 | |
|     {                                                          
 | |
|       const bool ok = strchr("-0123456789ADEGILMNOPRSTUadegilmnoprstu", key) != NULL;
 | |
|       if (!ok) beep();
 | |
|       return ok;   
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TEdit_field::on_key(key);
 | |
| }
 | |
| 
 | |
| bool TDate_field::autosave(TRelation& r) 
 | |
| {         
 | |
|   if (field())
 | |
|   {
 | |
|     const char* td = get();
 | |
| 
 | |
|     if (right_justified())
 | |
|     {
 | |
|       TDate d(td);
 | |
|       td = d.string(ANSI);
 | |
|     }
 | |
|     field()->write(td, r);
 | |
|     return TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Real_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TReal_field::TReal_field(TMask* m) : TEdit_field(m)
 | |
| { }
 | |
| 
 | |
| word TReal_field::class_id() const
 | |
| { return CLASS_REAL_FIELD; }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TReal_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_REAL_FIELD || TEdit_field::is_kind_of(cid); }
 | |
| 
 | |
| void TReal_field::create(WINDOW w)
 | |
| { 
 | |
|   _ctl_data._flags.strip("AFM");
 | |
|   if (!roman())
 | |
|     _ctl_data._flags << 'R';     // Forza l'allineamento a destra per i numeri
 | |
|   
 | |
|   TEdit_field::create(w);
 | |
|   
 | |
|   if (_flags.firm)      
 | |
|   {
 | |
|     TMask_field::set(prefix().get_codditta()); 
 | |
|   }
 | |
|   else
 | |
|     if (automagic())
 | |
|       TMask_field::set(TDate(TODAY).year());
 | |
| }
 | |
| 
 | |
| bool TReal_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PI")            // PICTURE
 | |
|   {
 | |
|     _picture = scanner.string();
 | |
|     if (_decimals == 0)
 | |
|     {
 | |
|       if (_picture[0] == '.')
 | |
|         _decimals = atoi(&_picture[1]);
 | |
|       else
 | |
|       {  
 | |
|         const int comma = _picture.find(',');
 | |
|         if (comma >= 0)
 | |
|           _decimals = _picture.len() - comma - 1;
 | |
|       }    
 | |
|     }  
 | |
|     return TRUE;
 | |
|   }
 | |
|   
 | |
|   return TEdit_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| const char* TReal_field::reformat(const char* data) const
 | |
| {
 | |
|   TString& str = _ctl_data._park;
 | |
|   
 | |
|   if (!real::is_null(data))
 | |
|   {       
 | |
|     str = data;
 | |
|     if (_flags.zerofilled)
 | |
|     {  
 | |
|       word s = size();
 | |
|       if (roman())
 | |
|       {
 | |
|         s = decimals();
 | |
|         if (s <= 0) s = 4;
 | |
|       }
 | |
|       str.right_just(s, '0');
 | |
|     }  
 | |
|   }
 | |
|   else
 | |
|     str.cut(0);
 | |
|   return str;  
 | |
| }
 | |
| 
 | |
| bool TReal_field::on_key(KEY key)
 | |
| {
 | |
|   if (to_check(key))
 | |
|   {
 | |
|     const TString& n = get_window_data();
 | |
|     if (roman())
 | |
|     {
 | |
|       const int r = atoi(n);
 | |
|       if (r < 0) return error_box("Numero romano errato");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (!real::is_real(n))
 | |
|         return error_box("Valore numerico non valido");
 | |
|       if (_flags.uppercase && real(n).sign() < 0)
 | |
|         return error_box("Il numero deve essere positivo");
 | |
|       
 | |
|       if (key == K_TAB && _flags.firm)
 | |
|       {                         
 | |
|         const long f = atol(n);
 | |
|         if (f > 0 && prefix().exist(f))
 | |
|           prefix().set_codditta(f);
 | |
|       }  
 | |
|     }
 | |
|     set_window_data(raw2win(n));
 | |
|   } 
 | |
|   else
 | |
|   {
 | |
|     if (_ctl->is_edit_key(key))
 | |
|     {                                                          
 | |
|       bool ok = TRUE;
 | |
|       switch (key)                                     
 | |
|       {                 
 | |
|         case '.': 
 | |
|           ok = !(_flags.zerofilled || _flags.roman || size() < 4); 
 | |
|           break;
 | |
|         case ',': 
 | |
|           ok = _decimals > 0; 
 | |
|           break;
 | |
|         case '-': 
 | |
|           ok = !_flags.uppercase; 
 | |
|           break;
 | |
|         default : 
 | |
|           if (_flags.roman)
 | |
|             ok = strchr("0123456789IVXLCDMivxlcdm", key) != NULL; 
 | |
|           else
 | |
|             ok = strchr("0123456789", key) != NULL; 
 | |
|           break;
 | |
|       }      
 | |
|       if (!ok)
 | |
|         beep();  
 | |
|       return ok;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TEdit_field::on_key(key);
 | |
| }
 | |
| 
 | |
| void TReal_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._size  = scanner.integer();
 | |
| 
 | |
| #ifdef DBG      
 | |
|   if (_ctl_data._size <= 0)
 | |
|   {
 | |
|     _ctl_data._size = 9;
 | |
|     yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", _ctl_data._dlg, _ctl_data._size);
 | |
|   }
 | |
| #endif
 | |
|   
 | |
|   _ctl_data._width = _ctl_data._size;
 | |
|   _decimals = scanner.integer();
 | |
| }
 | |
| 
 | |
| const char* TReal_field::raw2win(const char* data) const
 | |
| {           
 | |
|   TString& s = _ctl_data._park;
 | |
|   
 | |
|   if (data == NULL) data = "";
 | |
|   
 | |
|   if (roman())
 | |
|   {
 | |
|     s = itor(atoi(data));
 | |
|   }
 | |
|   else
 | |
|   { 
 | |
|     if (!real::is_null(data))
 | |
|     {
 | |
|       real n(data);
 | |
|       if (_picture.empty())
 | |
|       {
 | |
|         if (_flags.zerofilled)
 | |
|           s = n.stringa(_size, _decimals, '0');
 | |
|         else
 | |
|           s = n.stringa(0, _decimals);  
 | |
|       }  
 | |
|       else
 | |
|       {
 | |
|         s = n.string(_picture);
 | |
|       }  
 | |
|       const int extra = s.len() - _size;
 | |
|       if (extra > 0)
 | |
|         s.ltrim(extra);
 | |
|     } 
 | |
|     else 
 | |
|       s.cut(0);
 | |
|   } 
 | |
|   
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| const char* TReal_field::win2raw(const char* data) const
 | |
| {
 | |
|   TString& str = _ctl_data._park;
 | |
| 
 | |
|   if (roman())
 | |
|   {
 | |
|     int r = atoi(data);    
 | |
|     if (r == 0)            // Se non e' scritto in arabo converti da romano
 | |
|       r = rtoi(data);
 | |
|     if (r > 0)
 | |
|     {
 | |
|       int d = decimals();
 | |
|       if (d < 1) d = 4;
 | |
|       if (_flags.zerofilled)
 | |
|         str.format("%0*d", d, r);
 | |
|       else
 | |
|         str.format("%*d", d, r);
 | |
|     }
 | |
|     else 
 | |
|       str.cut(0);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     real n(real::ita2eng(data));
 | |
|     if (n.is_zero()) 
 | |
|       str.cut(0);
 | |
|     else 
 | |
|     {
 | |
|       if (_flags.zerofilled)
 | |
|         str = n.string(_size, _decimals, '0');
 | |
|       else
 | |
|         str = n.string();
 | |
|     }
 | |
|   }     
 | |
| 
 | |
|   return str;
 | |
| } 
 | |
| 
 | |
| void TReal_field::set_decimals(int d) 
 | |
| { 
 | |
|   _decimals = d; 
 | |
|   if (_picture[0] == '.')
 | |
|   {
 | |
|     if (d > 0) _picture.format(".%d", d);
 | |
|     else _picture = ".";
 | |
|   }                           
 | |
|   else  
 | |
|   {              
 | |
|     if (_picture.not_empty())
 | |
|     {
 | |
|       const int pdot = _picture.find(',');
 | |
|       if (pdot >= 0)
 | |
|         _picture.cut(pdot);
 | |
|       if (d > 0)
 | |
|       {
 | |
|         _picture << ',';
 | |
|         while (d-- > 0)          
 | |
|           _picture << '@';
 | |
|       }                   
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Currency_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| #include <currency.h>
 | |
| 
 | |
| // Certified 100%
 | |
| word TCurrency_field::class_id() const
 | |
| { return CLASS_CURRENCY_FIELD; }
 | |
| 
 | |
| // Certified 100%
 | |
| bool TCurrency_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_CURRENCY_FIELD || TEdit_field::is_kind_of(cid); }
 | |
| 
 | |
| TCurrency& TCurrency_field::get_currency(TCurrency& cur) const
 | |
| {
 | |
|   const real num(get());
 | |
|   const char* value = NULL;
 | |
|   real exchange;
 | |
|   exchange_type et = _exchange_undefined;
 | |
|   const TMask_field* d0 = driver(0);
 | |
|   if (d0)
 | |
|   {
 | |
|     value = d0->get();
 | |
|     const TMask_field* d1 = driver(1);
 | |
|     if (d1)
 | |
|     {
 | |
|       exchange = real(d1->get());
 | |
|       const TMask_field* d2 = driver(2);
 | |
|       if (d2)
 | |
|         et = d2->get().blank() ? _exchange_base : _exchange_contro;
 | |
|     }
 | |
|   }    
 | |
|   
 | |
|   cur.set_num(num);
 | |
|   cur.force_value(value, exchange, et);
 | |
|   cur.set_price(_flags.uppercase != 0);
 | |
|   return cur;
 | |
| }
 | |
| 
 | |
| void TCurrency_field::set(const TCurrency& cur, bool hit)
 | |
| {
 | |
|   TMask_field* d0 = (TMask_field*)driver(0);
 | |
|   if (d0) d0->set(cur.get_value());
 | |
|   const real& num = cur.get_num();
 | |
|   if (num.is_zero())
 | |
|     TEdit_field::set("");
 | |
|   else  
 | |
|     TEdit_field::set(num.string());
 | |
|   if (hit)
 | |
|     on_hit();
 | |
| }
 | |
| 
 | |
| const char* TCurrency_field::reformat(const char* data) const
 | |
| {
 | |
|   return real::is_null(data) ? "" : data;
 | |
| }
 | |
| 
 | |
| const char* TCurrency_field::raw2win(const char* data) const
 | |
| {
 | |
|   const real num = data;
 | |
|   if (num == ZERO)
 | |
|     return "";
 | |
|   const TMask_field* d0 = driver(0);
 | |
|   const char* value = d0 ? (const char*)d0->get() : NULL;
 | |
|   const bool price = _flags.uppercase != 0;
 | |
|   TCurrency cur(num, value, ZERO, _exchange_undefined, price);
 | |
| 
 | |
|   TString& s = _ctl_data._park;
 | |
|   s = cur.string(TRUE);
 | |
|   const int extra = s.len() - size();
 | |
|   if (extra > 0) s.ltrim(extra);
 | |
| 
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| const char* TCurrency_field::win2raw(const char* data) const
 | |
| {
 | |
|   TString& str = _ctl_data._park;
 | |
| 	str = data;
 | |
|   str.strip("."); str.replace(',', '.');
 | |
|   bool is_formula = FALSE;
 | |
|   for (int i = 0; str[i]; i++)
 | |
|   {
 | |
|     if (strchr("0123456789.", str[i]) == NULL)
 | |
|     {
 | |
|       is_formula = TRUE;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   real num;
 | |
|   if (is_formula)
 | |
|   {
 | |
|     TExpression e(str, _numexpr, TRUE);
 | |
|     for (int i = e.numvar()-1; i >= 0; i--)
 | |
|     {
 | |
|       TMask_field* f = mask().find_by_fieldname(e.varname(i));
 | |
|       if (f) 
 | |
|         e.setvar(i, f->get());
 | |
|     }
 | |
|     num = e.as_real();
 | |
|   }
 | |
|   else
 | |
|     num = real(str);
 | |
|   if (num.is_zero())
 | |
|     str.cut(0);
 | |
|   else  
 | |
|   {
 | |
|     const TMask_field* d0 = driver(0);
 | |
|     const char* value = d0 ? (const char*)d0->get() : NULL;
 | |
|     const bool price = _flags.uppercase != 0;
 | |
|     TCurrency cur(num, value, ZERO, _exchange_undefined, price);
 | |
|     str = cur.get_num().string();
 | |
|   }
 | |
|   return str;
 | |
| }
 | |
| 
 | |
| bool TCurrency_field::on_key(KEY key)
 | |
| {            
 | |
|   if (key == K_TAB && focusdirty())
 | |
|   {
 | |
|     const TString& raw = get_window_data();
 | |
|     set_window_data(raw2win(raw));
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (_ctl->is_edit_key(key))
 | |
|     {                                                          
 | |
|       bool ok = TRUE;
 | |
|       switch (key)                                     
 | |
|       {                 
 | |
|         case '-': 
 | |
|           ok = !_flags.uppercase; 
 | |
|           break;
 | |
|         default : 
 | |
|           ok = strchr("0123456789.,+*-/()", key) != NULL; 
 | |
|           break;
 | |
|       }      
 | |
|       if (!ok)
 | |
|         beep();  
 | |
|       return ok;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TEdit_field::on_key(key);
 | |
| }
 | |
| 
 | |
| bool TCurrency_field::autosave(TRelation& r) 
 | |
| {
 | |
|   return  TEditable_field::autosave(r);
 | |
| }
 | |
| 
 | |
| bool TCurrency_field::autoload(const TRelation& r)
 | |
| {
 | |
|   return TEditable_field::autoload(r);
 | |
| }
 | |
| 
 | |
| void TCurrency_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   int size = scanner.integer();
 | |
|   if (size <= 0)
 | |
|     size = 18;
 | |
|   _ctl_data._size = _ctl_data._width = size;
 | |
| }
 | |
| 
 | |
| void TCurrency_field::create(WINDOW w)
 | |
| {
 | |
|   _ctl_data._flags.strip("AMZ");
 | |
|   _ctl_data._flags << 'R';
 | |
|   TEdit_field::create(w);
 | |
| }
 | |
| 
 | |
| TCurrency_field::TCurrency_field(TMask* m) 
 | |
|                : TEdit_field(m)
 | |
| { 
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // List_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TList_field::TList_field(TMask* m) 
 | |
|            : TEditable_field(m), _size(0)
 | |
| { }
 | |
| 
 | |
| word TList_field::class_id() const
 | |
| { return CLASS_LIST_FIELD; }
 | |
| 
 | |
| 
 | |
| void TList_field::read_item(TScanner& scanner)
 | |
| {
 | |
|   TToken_string ts(scanner.string());
 | |
|   _codes.add(ts.get());
 | |
|   
 | |
|   const char* v = dictionary_translate_prompt(ts.get(), _ctl_data._width);
 | |
|   _values.add(v);
 | |
|   
 | |
|   CHECKS(v == NULL || strlen(v) <= (word)_ctl_data._width, "List item is too long:", v);
 | |
| 
 | |
|   ts.cut(0);
 | |
|   while (scanner.popkey() == "ME")
 | |
|     ts.add(scanner.line().strip_spaces());
 | |
|   scanner.push();
 | |
|   *message(-1, TRUE) = ts;
 | |
| }
 | |
| 
 | |
| void TList_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._size = scanner.integer();
 | |
|   _ctl_data._width = scanner.integer();
 | |
|   if (_ctl_data._width == 0) 
 | |
|     _ctl_data._width = _ctl_data._size;
 | |
| }
 | |
| 
 | |
| bool TList_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "IT")            // ITEM
 | |
|   {
 | |
|     read_item(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TEditable_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| int TList_field::items() const
 | |
| {
 | |
|   return _codes.items();
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiunge delle voci al list sheet
 | |
| void TList_field::add_item(   
 | |
|   const char* s) // @parm Voci da aggiungere
 | |
|   
 | |
|   // @comm Se il parametro <p s> e' passato con il formato di una <c TToken_string> 
 | |
|   // composta da codice|descrizione
 | |
| {
 | |
|   TToken_string t(s);         
 | |
|   TString item(t.get());
 | |
|   const int pos = _codes.get_pos(item);
 | |
|   
 | |
|   if (pos < 0)
 | |
|   {                                         
 | |
|     _codes.add(item);
 | |
|     item = t.get();
 | |
|     _values.add(item);
 | |
|     ((TListbox_control*)_ctl)->set_values(_codes, _values);
 | |
|   }     
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::delete_item(const char* s)
 | |
| {
 | |
|   const TString t(s);         
 | |
|   const int pos = _codes.get_pos(t);
 | |
|   
 | |
|   if (pos >= 0 )
 | |
|   {                                         
 | |
|     _codes.destroy(pos);
 | |
|     _values.destroy(pos);
 | |
|     ((TListbox_control*)_ctl)->set_values(_codes, _values);
 | |
|     
 | |
|     if (pos == current())
 | |
|     {
 | |
|       current(0);
 | |
|       if (active() || ghost()) 
 | |
|         on_hit();
 | |
|     }
 | |
|   }     
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::add_list()
 | |
| {
 | |
|   if (roman() && _codes.items() < 12)
 | |
|   {
 | |
|     TString csafe, vsafe;
 | |
|     if (atoi(_codes) > 0)
 | |
|     {
 | |
|       csafe = _codes; _codes = "";
 | |
|       vsafe = _values; _values = "";
 | |
|     }
 | |
|     for (int i = 1; i <= 12; i++)
 | |
| 		{
 | |
| 			char num[4]; sprintf(num, "%02d", i);
 | |
| 			_codes.add(num);
 | |
| 			_values.add(itom(i));
 | |
| 		}
 | |
| 
 | |
|     if (atoi(csafe) > 0)
 | |
|     {
 | |
|       _codes.add(csafe);
 | |
|       _values.add(vsafe);
 | |
|       if (message(0))
 | |
|       {
 | |
|         *message(_codes.items()-1, TRUE) = *message(0);
 | |
|         message(0)->cut(0);
 | |
|       }
 | |
|     }
 | |
|   }   
 | |
|   ((TListbox_control*)_ctl)->set_values(_codes, _values);
 | |
| 
 | |
|   if (roman() && automagic())
 | |
|   {
 | |
|     const char* init = format("%02d", TDate(TODAY).month());
 | |
|     set(init);
 | |
|   }
 | |
|   else
 | |
|     current(0);
 | |
| }                                                                    
 | |
| 
 | |
| 
 | |
| const char* TList_field::win2raw(const char* data) const
 | |
| {                                                     
 | |
|   // fool the compiler to keep const
 | |
|   TToken_string& codes = ((TList_field*)this)->_codes;
 | |
|   TToken_string& value = ((TList_field*)this)->_values;
 | |
|                 
 | |
|   _ctl_data._park = data;                       // data puo' venire da una TToken_string::get
 | |
|   int pos = 0;
 | |
|   
 | |
|   if (_ctl_data._park.len() > 2)                // E' veramente una descrizione
 | |
|     pos = value.get_pos(_ctl_data._park);
 | |
|   else                                          // Oppure e' un codice
 | |
|     pos = codes.get_pos(_ctl_data._park);
 | |
|   
 | |
|   if (pos < 0 && _ctl_data._park.blank())
 | |
|   {              
 | |
|     _ctl_data._park = codes.get(0);             // Uso codes come riferimento per blank
 | |
|     if (_ctl_data._park.blank())
 | |
|       pos = 0;
 | |
|   }  
 | |
|   
 | |
|   CHECKS(pos >= 0, "Unknown listbox value:", data);
 | |
|   return codes.get(pos);              
 | |
| }
 | |
| 
 | |
| const char* TList_field::raw2win(const char* data) const
 | |
| {
 | |
|   // fool the compiler to keep const
 | |
|   TToken_string& codes = ((TList_field*)this)->_codes;
 | |
|   TToken_string& value = ((TList_field*)this)->_values;
 | |
|   
 | |
|   _ctl_data._park = data;                       // data puo' venire da una TToken_string::get
 | |
|   int pos = codes.get_pos(_ctl_data._park);
 | |
|   if (pos < 0 && _ctl_data._park.blank())
 | |
|   {              
 | |
|     _ctl_data._park = codes.get(0);
 | |
|     if (_ctl_data._park.blank())
 | |
|       pos = 0;
 | |
|   }  
 | |
|   CHECKS(pos >= 0, "Unknown listbox code:", (const char*)_ctl_data._park);
 | |
|   return value.get(pos);              
 | |
| }
 | |
| 
 | |
| bool TList_field::select_by_ofs(int n)
 | |
| {
 | |
|   const bool changed = ((TListbox_control*)_ctl)->select_by_ofs(n);
 | |
|   if (changed)
 | |
|     _str = _codes.get(current());
 | |
|   return changed;  
 | |
| }
 | |
| 
 | |
| bool TList_field::select_by_initial(char c)
 | |
| {
 | |
|   const bool changed = ((TListbox_control*)_ctl)->select_by_initial(c);
 | |
|   if (changed)
 | |
|     _str = _codes.get(current());
 | |
|   return changed;  
 | |
| }                                            
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Sostituisce alle voci correnti quelle passate come parametri
 | |
| void TList_field::replace_items(
 | |
|   const char* codes,  // @parm Codici da sostituire ai correnti
 | |
|   const char* values) // @parm Voci da sostituire a quelle correnti
 | |
| 
 | |
|   // @comm I parametri <p codes> e <p values> devono essere TToken_string se lo voci da sostiutire
 | |
|   //                     sono piu' di una
 | |
| {
 | |
|   _codes = codes;
 | |
|   _values = values;
 | |
|   if (_ctl)
 | |
|     add_list();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::create(WINDOW parent)
 | |
| {
 | |
|   const int len = create_prompt(parent, 0, 0);
 | |
|   _ctl_data._x += len;
 | |
|   
 | |
|   _size = _ctl_data._width;
 | |
|   
 | |
|   _ctl = new TListbox_control(parent, _ctl_data._dlg,
 | |
|                             _ctl_data._x, _ctl_data._y,
 | |
|                             _ctl_data._width,
 | |
|                             _ctl_data._flags, _ctl_data._prompt, 
 | |
|                             _codes, _values);
 | |
|   add_list();
 | |
| }
 | |
| 
 | |
| int TList_field::str2curr(const char* data)
 | |
| {
 | |
|   TString str(data);
 | |
| 
 | |
|   if (roman() && str.len() < 2)
 | |
|     str.insert("0",0);
 | |
|   if (_flags.uppercase)
 | |
|     str.upper();        
 | |
| 
 | |
|   int i = str.blank() ? 0 : _codes.get_pos(str);
 | |
|   if (i < 0)      // Se non trova il codice ritenta dopo trim
 | |
|   {
 | |
|     for (i = 0; str[i] == '0' || str[i] == ' '; i++);
 | |
|     if (i > 0)
 | |
|     {
 | |
|       str.ltrim(i);
 | |
|       i = _codes.get_pos(str);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (i < 0)
 | |
|   {
 | |
|     if (shown() || ghost())
 | |
|     {
 | |
|       if (items() && str.not_empty())
 | |
|         NFCHECK("'%s' non e' un valore valido per il campo %s: %d",
 | |
|                 data, prompt(), dlg());
 | |
|     }
 | |
|     i = 0;
 | |
|   }
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| void TList_field::reset()
 | |
| {         
 | |
|   if (!_flags.persistent)
 | |
|     current(0);
 | |
| }
 | |
| 
 | |
| void TList_field::set(const char* data)
 | |
| {
 | |
|   const int i = str2curr(data);
 | |
|   current(i);
 | |
|   set_dirty();
 | |
| }
 | |
| 
 | |
| void TList_field::set_window_data(const char* data)
 | |
| {                                      
 | |
|   NFCHECK(0,"So' passato da 'sta stronza!!!");
 | |
|   const int i = str2curr(win2raw(data));
 | |
|   current(i);
 | |
| }
 | |
| 
 | |
| void TList_field::current(int n)
 | |
| {                 
 | |
|   if (_ctl)     
 | |
|     ((TListbox_control*)_ctl)->select(n);
 | |
|   _str = _codes.get(n);
 | |
|   _str.trim();
 | |
| }
 | |
| 
 | |
| int TList_field::current() const
 | |
| {                                                       
 | |
|   int c;
 | |
|   if (_ctl)
 | |
|     c = ((TListbox_control*)_ctl)->selected();
 | |
|   else
 | |
|     c = ((TList_field*)this)->_codes.get_pos(_str);   // Fool the compiler for const sake
 | |
|   return c;   
 | |
| }
 | |
| 
 | |
| TString& TList_field::get_window_data()
 | |
| {                                    
 | |
|   const int c = current();
 | |
|   _str = ((TList_field*)this)->_codes.get(c);
 | |
|   _str.trim();
 | |
|   return _str;
 | |
| }
 | |
| 
 | |
| bool TList_field::on_hit()
 | |
| {
 | |
|   const bool ok = handler(K_SPACE);
 | |
|   if (ok)
 | |
|   {
 | |
|     const int n = current();
 | |
|     do_message(n);
 | |
|   }  
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TList_field::on_key(KEY key)
 | |
| {                 
 | |
|   switch(key)
 | |
|   {         
 | |
|   case K_CTRL+K_TAB:
 | |
|     set_focusdirty(FALSE);
 | |
|     break;              
 | |
|   case K_SPACE:
 | |
|     get_window_data();
 | |
|     set_dirty();
 | |
|     return on_hit();
 | |
|   case K_F2:  
 | |
| 		if (!read_only())
 | |
| 			current(0);
 | |
|     break;
 | |
|   default: 
 | |
|     if (to_check(key, TRUE) || key == K_ENTER)
 | |
|     {         
 | |
|       bool ok = TRUE;
 | |
|       if (validate_func() >= 0)
 | |
|       {
 | |
|         ok = validate(key);
 | |
|         if (!ok) 
 | |
|         {
 | |
|           if (has_warning()) 
 | |
|             return error_box(get_warning());
 | |
|         }    
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   }  
 | |
|   return TEditable_field::on_key(key);
 | |
| }
 | |
|            
 | |
| // Certified 100%
 | |
| bool TList_field::is_kind_of(word cid) const
 | |
| { return cid == CLASS_LIST_FIELD || TEditable_field::is_kind_of(cid); }
 | |
| 
 | |
|            
 | |
|            
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRadio_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TRadio_field::TRadio_field(TMask* mask)
 | |
|             : TList_field(mask)
 | |
| { }
 | |
| 
 | |
| // Annulla _ctl altrimenti verrebbe cancellato due volte essendo anche nell'array
 | |
| TRadio_field::~TRadio_field()
 | |
| { }
 | |
| 
 | |
| 
 | |
| word TRadio_field::class_id() const
 | |
| {
 | |
|   return CLASS_RADIO_FIELD;
 | |
| }
 | |
| 
 | |
| void TRadio_field::create(WINDOW parent)
 | |
| {
 | |
|   const int items = _codes.items();
 | |
|   if (_ctl_data._prompt.not_empty())
 | |
|   {
 | |
|     const word dy = _flags.zerofilled ? 3 : items+2;
 | |
|     create_prompt(parent, _ctl_data._width, dy);
 | |
|   }
 | |
|   
 | |
|   _ctl = new TRadiobutton_control(parent, _ctl_data._dlg, 
 | |
|                                   _ctl_data._x + 1, _ctl_data._y + 1, 
 | |
|                                   _ctl_data._width - 2, _flags.zerofilled ? 1 : items,
 | |
|                                   _ctl_data._flags, _values);
 | |
|   current(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRadio_field::current() const
 | |
| {
 | |
|   int c;
 | |
|   if (_ctl)
 | |
|     c = ((TRadiobutton_control*)_ctl)->get_checked();
 | |
|   else
 | |
|     c = TList_field::current(); 
 | |
|   return c;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::current(int n)
 | |
| {
 | |
|   if (_ctl)
 | |
|     ((TRadiobutton_control*)_ctl)->check_button(n);
 | |
|   _str = _codes.get(n);
 | |
|   _str.trim();
 | |
| }
 | |
| 
 | |
| bool TRadio_field::select_by_initial(char c)
 | |
| {
 | |
|   for (int i = _values.items()-1; i >= 0; i--)
 | |
|   {
 | |
|     const char* tok = _values.get(i);
 | |
|     if (toupper(*tok) == toupper(c) && _str != _codes.get(i))
 | |
|     {
 | |
|       current(i);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;  
 | |
| }                                            
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TMemo_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TMemo_field::TMemo_field(TMask* mask) : TEdit_field(mask)
 | |
| {
 | |
| }
 | |
| 
 | |
| TMemo_field::~TMemo_field()
 | |
| {                     
 | |
| }
 | |
| 
 | |
| void TMemo_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._width  = scanner.integer();
 | |
|   _ctl_data._height = scanner.integer();
 | |
| }
 | |
| 
 | |
| void TMemo_field::create(WINDOW parent)
 | |
| {                     
 | |
|   create_prompt(parent, 0, 1);  
 | |
|   
 | |
|   if (_ctl_data._height > 1)
 | |
|     _ctl_data._height--;
 | |
|   
 | |
|   _size = 8192;
 | |
|   _ctl = new TMultiline_control(parent, _ctl_data._dlg, 
 | |
|                                 _ctl_data._x, _ctl_data._y+1,
 | |
|                                 _ctl_data._width, _ctl_data._height, _size,
 | |
|                                 _ctl_data._flags, "");
 | |
| }           
 | |
| 
 | |
| // Certified 100%
 | |
| // Aggiusta un valore letto da file in formato RAW
 | |
| const char* TMemo_field::reformat(const char* data) const
 | |
| {
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| 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;         
 | |
|     
 | |
|   TString& s = _ctl_data._park;
 | |
|   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)
 | |
| {
 | |
|   if (k == K_ENTER || k == K_TAB && focusdirty())
 | |
|     get_window_data();
 | |
|   return TEdit_field::on_key(k);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Zoom_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TZoom_field::TZoom_field(TMask* mask) 
 | |
|            : TEdit_field(mask)
 | |
| {
 | |
| } 
 | |
| 
 | |
| TZoom_field::~TZoom_field( )
 | |
| {
 | |
| } 
 | |
| 
 | |
| void TZoom_field::create(WINDOW parent)
 | |
| {
 | |
|   _ctl_data._flags << 'B';
 | |
|   TEdit_field::create(parent);
 | |
| }
 | |
| 
 | |
| class TZoom_mask : public TAutomask
 | |
| {
 | |
| 
 | |
| protected:
 | |
| 	virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | |
| 
 | |
| public:
 | |
|   TZoom_mask(const char * prompt);
 | |
|   virtual ~TZoom_mask() {}
 | |
| };
 | |
| 
 | |
| bool TZoom_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | |
| { 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| TZoom_mask::TZoom_mask(const char * prompt) : TAutomask("Zoom", 1, 72, 18)
 | |
| {
 | |
| 	const bool select = AUTOSELECT;
 | |
| 	AUTOSELECT = false;
 | |
| 	AUTOEND = true;
 | |
| 	add_memo(101, 0, prompt, 1, 0, -1, -3);
 | |
| 	add_button(DLG_OK,     0, "", -12, -1, 10, 2);
 | |
| 	add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
 | |
| 	AUTOEND = false;
 | |
| 	AUTOSELECT = select;
 | |
| 	set_handlers();
 | |
| }
 | |
| 
 | |
| bool TZoom_field::on_key( KEY key )
 | |
| { 
 | |
|   static KEY __k = '\0';
 | |
| 	switch (key)
 | |
|   {
 | |
|   case K_TAB:
 | |
|     if (focusdirty())
 | |
|       get_window_data();
 | |
|     break;
 | |
|   case K_F9:
 | |
|     if (browse() != NULL)
 | |
|       break;
 | |
|   case K_F8:  
 | |
| 		{
 | |
| 			get_window_data();
 | |
| 			TZoom_mask m(prompt());
 | |
| 
 | |
| 			if (__k)
 | |
| 			{
 | |
| 				_str << (const char) __k;
 | |
| 				__k = '\0';
 | |
| 			}
 | |
| 			m.set(101, _str);
 | |
| 
 | |
| 			if (m.run() == K_ENTER && !read_only())
 | |
| 			{
 | |
| 				_str = m.get(101);
 | |
| 				set_window_data(raw2win(_str));
 | |
| 			}
 | |
| 			return TRUE;
 | |
| 		}
 | |
| 	  break;
 | |
|   default:
 | |
| 		if (AUTOZOOM && xvt_chr_is_alnum(key))
 | |
| 		{
 | |
| 			get_window_data();
 | |
| 			if (_str.len() >= size())
 | |
| 			{
 | |
| 				__k = key;
 | |
| 				if (mask().is_running())
 | |
| 					on_key(K_F8);
 | |
| 				else
 | |
| 				{
 | |
| 					TSheet_field * s = mask().get_sheet();
 | |
| 					if (s != NULL)
 | |
| 						dispatch_e_char(s->mask().win(), K_F8);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
|     break;
 | |
|   }  
 | |
|   return TEdit_field::on_key(key);  
 | |
| } 
 | |
| 
 | |
| // Certified 100%
 | |
| // Aggiusta un valore letto da file in formato RAW
 | |
| const char* TZoom_field::reformat(const char* data) const
 | |
| {
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| const char* TZoom_field::raw2win(const char* data) const
 | |
| {     
 | |
|   TFixed_string str(data);
 | |
|   int a_capo = str.find('\n');
 | |
|   
 | |
|   if (a_capo < 0 || a_capo > (int)size())
 | |
|     a_capo = min((int)size(), str.len());
 | |
|   
 | |
|   const char c = str[a_capo];
 | |
|   str[a_capo] = '\0';
 | |
|   _ctl_data._park = str;
 | |
|   str[a_capo] = c;
 | |
|   return _ctl_data._park;
 | |
| }
 | |
| 
 | |
| const char* TZoom_field::win2raw(const char* data) const
 | |
| {                
 | |
|   TString& str = _ctl_data._park;
 | |
|   str = data;                         
 | |
|   
 | |
|   // Elimino improbabili righe successive da data
 | |
|   int a_capo = str.find('\r');        
 | |
|   if (a_capo >= 0) str.cut(a_capo);
 | |
|   
 | |
|   // Aggiungo le righe del memo a partire dalla seconda
 | |
|   a_capo = _str.find('\n');
 | |
|   if (a_capo < 0 || a_capo > (int)size())
 | |
|     a_capo = min((int) size(), _str.len());
 | |
|   const char* d = _str;
 | |
|   str << (d+a_capo);
 | |
|   
 | |
|   return str;  
 | |
| }
 | |
| 
 | |
| const char* TZoom_field::get_first_line() const 
 | |
| { return raw2win(_str); }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TField_window
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef INCL_XI 
 | |
| extern "C"
 | |
| {
 | |
|   void xi_draw_3d_rect( WINDOW win, RCT* rctp, BOOLEAN well, int height, 
 | |
|                         COLOR color_light, COLOR color_ctrl, COLOR color_dark );
 | |
| }
 | |
| #endif                    
 | |
| 
 | |
| void TField_window::handler(WINDOW win, EVENT* ep)
 | |
| {
 | |
|   switch (ep->type)
 | |
|   {                
 | |
|     case E_FOCUS:
 | |
|       if (ep->v.active)
 | |
|       {
 | |
|         WINDOW parent = xvt_vobj_get_parent(win);
 | |
|         XI_OBJ* itf = xi_get_itf((XinWindow)parent);
 | |
|         xi_set_focus(itf);
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       break;  
 | |
|   }
 | |
|   TScroll_window::handler(win, ep);
 | |
| }
 | |
| 
 | |
| bool TField_window::on_key(KEY k)
 | |
| {             
 | |
|   if (k == K_TAB || k == K_BTAB || k == K_F3 || k == K_F4)
 | |
|   { 
 | |
|     const TMask& m = _owner->mask();
 | |
|     const short id = _owner->dlg();
 | |
|     const int start = m.id2pos(id);
 | |
|     const int dir = (k == K_TAB || k == K_F3) ? +1 : -1;
 | |
|     
 | |
|     int pos = start;
 | |
|     while (TRUE)
 | |
|     { 
 | |
|       pos += dir;
 | |
|       if (pos < 0) pos = m.fields()-1;
 | |
|       if (pos >= m.fields()) pos = 0;
 | |
|       if (pos == start)
 | |
|         break;
 | |
|       TMask_field& f = m.fld(pos);
 | |
|       if (f.is_operable())
 | |
|       {
 | |
|         f.set_focus();
 | |
|         return TRUE;
 | |
|       }  
 | |
|     }  
 | |
|   }
 | |
|   return TScroll_window::on_key(k);
 | |
| }
 | |
| 
 | |
| void TField_window::update()
 | |
| {  
 | |
|   const WINDOW me = win();
 | |
|   if (CAMPI_SCAVATI)
 | |
|   { 
 | |
|     const WINDOW pa = parent();
 | |
|     RCT rct; xvt_vobj_get_outer_rect(me, &rct);
 | |
|     rct.left -= 2; rct.top -= 2; rct.right += 2; rct.bottom += 2;
 | |
|     xi_draw_3d_rect((XinWindow)pa, (XinRect *) &rct, TRUE, 2,  // qui
 | |
|                     MASK_LIGHT_COLOR, MASK_BACK_COLOR, MASK_DARK_COLOR);
 | |
|   }
 | |
|   xvt_dwin_clear(me, NORMAL_BACK_COLOR);
 | |
|   set_font();
 | |
| }
 | |
| 
 | |
| TField_window::TField_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) 
 | |
|              : _owner(owner)
 | |
| { 
 | |
|   if (owner)
 | |
|   {
 | |
|     create(x, y, dx, dy, "", WSF_HSCROLL | WSF_VSCROLL, W_PLAIN, parent);
 | |
|     activate(owner->enabled());
 | |
|     if (owner->shown()) 
 | |
|       open();
 | |
|   }    
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TWindowed field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| void TWindowed_field::enable(bool on)
 | |
| {
 | |
|   TOperable_field::enable(on);
 | |
|   if (_win) 
 | |
|     _win->activate(on);
 | |
| }
 | |
| 
 | |
| void TWindowed_field::show(bool on)
 | |
| {
 | |
|   TOperable_field::show(on);  
 | |
|   if (_win && _win->is_open() != on)
 | |
|   {
 | |
|     if (on) 
 | |
|       _win->open();
 | |
|     else               
 | |
|       _win->close();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TWindowed_field::highlight() const
 | |
| {
 | |
|   if (_win && active())
 | |
|     _win->set_focus();
 | |
| }
 | |
| 
 | |
| RCT& TWindowed_field::get_rect(RCT& r) const
 | |
| {
 | |
|   if (_win)
 | |
|     xvt_vobj_get_outer_rect(_win->win(), &r);
 | |
|   else
 | |
|     xvt_rect_set_empty(&r);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| void TWindowed_field::set_rect(const RCT& r)
 | |
| {
 | |
|   if (_win)
 | |
|     xvt_vobj_move(_win->win(), (RCT*)&r);
 | |
| }
 | |
| 
 | |
| short TWindowed_field::dlg() const 
 | |
| { 
 | |
|   return _dlg ? _dlg : _ctl_data._dlg; 
 | |
| }
 | |
| 
 | |
| void TWindowed_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _ctl_data._width  = scanner.integer();
 | |
|   _ctl_data._height = scanner.integer();
 | |
| }
 | |
| 
 | |
| TField_window* TWindowed_field::create_window(int x, int y, int dx, int dy, WINDOW parent) 
 | |
| {                                                       
 | |
|   // Must be always overridden and look like this
 | |
|   return new TField_window(x, y, dx, dy, parent, this);
 | |
| }
 | |
| 
 | |
| void TWindowed_field::create(short id, int x, int y, int dx, int dy, WINDOW parent)
 | |
| {
 | |
|   if (parent == NULL_WIN)
 | |
|     parent = mask().win();
 | |
|   _dlg = id;
 | |
|   _win = create_window(x, y, dx, dy, parent);
 | |
| }
 | |
| 
 | |
| void TWindowed_field::create(WINDOW parent)
 | |
| {        
 | |
|   create(_ctl_data._dlg, _ctl_data._x, _ctl_data._y, _ctl_data._width, _ctl_data._height, parent);
 | |
| }
 | |
| 
 | |
| TWindowed_field::~TWindowed_field() 
 | |
| { 
 | |
|   if (_win) 
 | |
|     delete _win; 
 | |
| }
 | |
| 
 |