2967 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2967 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //      $Id: maskfld.cpp,v 1.29 1994-10-14 17:55:57 alex Exp $
 | |
| #include <xvt.h>
 | |
| 
 | |
| #include <applicat.h>
 | |
| #include <defmask.h>
 | |
| #include <execp.h>
 | |
| #include <mailbox.h>
 | |
| #include <sheet.h>
 | |
| #include <mask.h>
 | |
| #include <relation.h>
 | |
| #include <tabutil.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h>
 | |
| #include <validate.h>
 | |
| #include <xvtility.h>
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
| #include <windows.h>
 | |
| #endif
 | |
| 
 | |
| HIDDEN const int MAXSTR = 128;
 | |
| HIDDEN char __fpark[MAXSTR];            // Temporary for get/set window data
 | |
| HIDDEN TFixed_string fpark(__fpark, MAXSTR);
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Field Flags
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field::TField_Flags::TField_Flags()
 | |
| {
 | |
|   automagic = persistent   = FALSE;
 | |
|   enabled = enable_default = TRUE;
 | |
|   showed  = show_default   = TRUE;
 | |
|   uppercase = rightjust    = FALSE;
 | |
|   zerofilled               = FALSE;
 | |
|   dirty = focusdirty       = FALSE;
 | |
|   roman = exchange         = FALSE;
 | |
|   firm = ghost             = FALSE;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| char TMask_field::TField_Flags::update(const char* s)
 | |
| {
 | |
|   const char* kk = s;
 | |
|   for (; *s; s++)
 | |
|     switch(toupper(*s))
 | |
|     {
 | |
|     case 'A':
 | |
|       automagic = persistent = TRUE; break;
 | |
|     case 'D': 
 | |
|       enable_default = enabled = FALSE; break;
 | |
|     case 'F': 
 | |
|       firm = persistent = TRUE; break;
 | |
|     case 'G': 
 | |
|       ghost = TRUE; break;
 | |
|     case 'H': 
 | |
|       show_default  = showed = FALSE; break;
 | |
|     case 'M': 
 | |
|       roman = TRUE; break;
 | |
|     case 'P': 
 | |
|       persistent = TRUE; break;
 | |
|     case 'R': 
 | |
|       rightjust = TRUE; break;
 | |
|     case 'U': 
 | |
|       uppercase = TRUE; break;
 | |
|     case 'V': 
 | |
|       exchange = TRUE; break;
 | |
|     case 'Z': 
 | |
|       zerofilled = TRUE; break;
 | |
| #ifdef DBG                      
 | |
|       default : ::warning_box("FLAG sconosciuto in %s: %c", kk, *s); break;
 | |
| #endif                          
 | |
|     }
 | |
|   return *s;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TMask_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| int TMask_field::_x;          // Position of the field
 | |
| int TMask_field::_y;
 | |
| int TMask_field::_width;
 | |
| TFixed_string TMask_field::_prompt(__fpark, MAXSTR);           // Prompt of the field
 | |
| 
 | |
| TMask_field::TMask_field(TMask* m)
 | |
| : _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0),
 | |
|   _keys(0), _groups(0), _help(0), _handler(NULL),
 | |
|   _validate_func(-1), _validate_parms(1), _field(NULL)
 | |
| {}
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field::~TMask_field()
 | |
| {
 | |
|   if (_field) delete _field;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::is_edit() const
 | |
| {
 | |
|   const word c = class_id();
 | |
|   return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| const char* TMask_field::class_name() const
 | |
| { return "Field"; }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| word TMask_field::class_id() const
 | |
| { return CLASS_FIELD; }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::ok() const
 | |
| { return win() != NULL_WIN && dlg() >= -1; }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::parse_head(TScanner&)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| short TMask_field::atodlg(const char* s) const
 | |
| {
 | |
|   short d = s ? atoi(s) : 0;
 | |
| 
 | |
| #ifdef DBG
 | |
|   if (d == 0 || d < -1 || d > 1000)
 | |
|   {
 | |
|     yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s);
 | |
|     d = -1;
 | |
|   }
 | |
| #endif  
 | |
| 
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| void TMask_field::construct(short id, const char* prompt, int x, int y,
 | |
|                             int len, WINDOW parent, const char* flags, int width)
 | |
| {
 | |
|   _x = x; _y = y;
 | |
|   _prompt = prompt;
 | |
|   _size = len;
 | |
|   if (class_id() == CLASS_REAL_FIELD)
 | |
|   {
 | |
|     ((TReal_field*)this)->set_decimals(width);
 | |
|     _width = _size;
 | |
|   }
 | |
|   else _width = width < 1 ? _size : width;
 | |
|   _dlg = id;
 | |
|   _flags.update(flags);
 | |
| 
 | |
|   create(parent);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::construct(TScanner& scanner, WINDOW parent)
 | |
| {
 | |
|   _dlg = atodlg(scanner.pop());
 | |
|   parse_head(scanner);
 | |
|   _prompt.cut(0);
 | |
|   
 | |
|   scanner.popkey();                 // BEGIN
 | |
| #ifdef DBG  
 | |
|   if (scanner.key() != "BE")          
 | |
|   {
 | |
|     yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg);
 | |
|     scanner.push();
 | |
|   }
 | |
| #endif          
 | |
| 
 | |
|   while(scanner.popkey() != "EN")       // END of control
 | |
|     parse_item(scanner);
 | |
|   create(parent);
 | |
| }
 | |
| 
 | |
| bool TMask_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PR")                    // PROMPT
 | |
|   {
 | |
|     _x = scanner.integer();
 | |
|     _y  = scanner.integer();
 | |
|     _prompt = scanner.string();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "FL")                    // FLAG
 | |
|   {
 | |
|     const char* f = scanner.string();
 | |
|     return _flags.update(f) == '\0';
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "FI")                    // FIELD
 | |
|   {
 | |
|     CHECKD(_field == NULL, "Only one FIELD, please: ", dlg());
 | |
|     _field = new TFieldref(scanner.line(), 0);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "HE")                    // HELP
 | |
|   {
 | |
|     _help = scanner.string();
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "KE")                    // KEY
 | |
|   {
 | |
|     _keys.set(scanner.line());
 | |
|     _keys.set(0L);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "ME")
 | |
|   {
 | |
|     if (_message.objptr(0) == 0)
 | |
|       _message.add(new TToken_string(64), 0);
 | |
|     TToken_string& ts = (TToken_string&)_message[0];
 | |
|     ts.add(scanner.line().strip_spaces());
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "GR")
 | |
|   {
 | |
|     _groups.set(scanner.line());
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| long TMask_field::default_flags() const
 | |
| {
 | |
|   long f = CTL_FLAG_NATIVE_JUST;
 | |
| 
 | |
|   if (_flags.show_default == FALSE)   f |= CTL_FLAG_INVISIBLE;
 | |
|   if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED;
 | |
| 
 | |
|   return f;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy,
 | |
|                               const char* title, WINDOW parent,
 | |
|                               long flags)
 | |
| {
 | |
|   _win = xvt_create_control(ct,
 | |
|                             _x, _y, dx, dy,
 | |
|                             (char*)title,
 | |
|                             parent,
 | |
|                             flags | default_flags(),
 | |
|                             PTR_LONG(this),
 | |
|                             _dlg);
 | |
| 
 | |
|   return _win;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| WINDOW TMask_field::parent() const
 | |
| { return get_parent(win()); }
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| int TMask_field::create_prompt(WINDOW parent, int width, int heigth)
 | |
| {
 | |
|   const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX;
 | |
|   if (width < 1) width = strlen(_prompt);
 | |
|   _prompt.rtrim();              // Could save some bytes
 | |
| 
 | |
|   if (width)
 | |
|   {
 | |
|     // Static controls shouldn't be grayed
 | |
|     const long flags = default_flags() & (~CTL_FLAG_DISABLED);
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|     char* k = strchr(_prompt, '~');
 | |
|     if (k != NULL) *k = '&';
 | |
| #endif
 | |
|     _promptwin = xvt_create_control
 | |
|       (
 | |
|        wt,
 | |
|        _x, _y, width, heigth,
 | |
|        _prompt,
 | |
|        parent,
 | |
|        flags,
 | |
|        0L,
 | |
|        -1
 | |
|        );
 | |
|   }
 | |
|   return width;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::destroy()
 | |
| {
 | |
|   if (_win)
 | |
|   { close_window(_win); _win = NULL_WIN; }
 | |
|   if (_promptwin)
 | |
|   { close_window(_promptwin); _promptwin = NULL_WIN; }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::create(WINDOW parent)
 | |
| {
 | |
|   _width = strlen(_prompt);
 | |
|   if (_width)
 | |
|     wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::enable(bool on)
 | |
| {
 | |
|   const word c = class_id();
 | |
|   if (c != CLASS_FIELD)
 | |
|   {
 | |
|     enable_window(_win, on);
 | |
|     _flags.enabled = on;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::enable_default()
 | |
| {
 | |
|   const bool ed = _flags.enable_default;
 | |
|   enable(ed);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::show(bool on)
 | |
| {
 | |
|   show_window(_win, on);
 | |
|   if (_promptwin != NULL_WIN)
 | |
|     show_window(_promptwin, on);
 | |
|   _flags.showed = on;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::show_default()
 | |
| {          
 | |
|   const bool sd = _flags.show_default;
 | |
|   show(sd);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TMask_field::active() const
 | |
| {
 | |
|   return enabled() && showed() && class_id() != CLASS_FIELD;
 | |
| };
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| word TMask_field::last_key() const
 | |
| {
 | |
|   long u = _keys.last_one();
 | |
|   if (u < 0) u = 0;
 | |
|   return (word)u;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 99%
 | |
| const char* TMask_field::get_window_data() const
 | |
| {
 | |
|   get_title(win(), __fpark, MAXSTR);
 | |
|   return __fpark;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 99%
 | |
| void TMask_field::set_window_data(const char* data)
 | |
| {
 | |
|   if (data != NULL)
 | |
|     set_title(win(), (char*)data);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::set_field_data(const char*)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| const char* TMask_field::get_field_data() const
 | |
| { return NULL; }
 | |
| 
 | |
| 
 | |
| const char* TMask_field::picture_data(const char* data, bool video)
 | |
| {            
 | |
|   fpark = data;
 | |
|   if (video) 
 | |
|   {
 | |
|     fpark.trim();
 | |
|     if (_flags.uppercase) fpark.upper();
 | |
|   }  
 | |
|   return fpark;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| const char* TMask_field::prompt() const
 | |
| {
 | |
|   if (_promptwin != NULL_WIN)
 | |
|     _prompt = xvt_get_title(_promptwin);
 | |
|   else
 | |
|     _prompt = "";
 | |
| 
 | |
|   return _prompt;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::reset()
 | |
| {
 | |
|   if (!_flags.persistent && class_id() != CLASS_FIELD)
 | |
|     set("");
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TMask_field::set_prompt(const char* p)
 | |
| {
 | |
|   if (_promptwin != NULL_WIN)
 | |
|     set_title(_promptwin, (char*) p);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::set(const char* s)
 | |
| {
 | |
|   if (mask().is_running())
 | |
|   {
 | |
|     set_window_data(s);
 | |
|     set_dirty();
 | |
|   }
 | |
|   else
 | |
|     set_field_data(s);
 | |
| }
 | |
| 
 | |
| TString& TMask_field::get() const
 | |
| {
 | |
|   static TString80 gpark;
 | |
| 
 | |
|   if (mask().is_running())
 | |
|     gpark = get_window_data();
 | |
|   else
 | |
|     gpark = get_field_data();
 | |
| 
 | |
|   return gpark.trim();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::undo()
 | |
| {
 | |
|   set_window_data(get_field_data());
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TMask_field::autoload(const TRelation* r)
 | |
| {
 | |
|   if (_field)
 | |
|   {
 | |
|     set(_field->read(r));
 | |
|     return TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TMask_field::autosave(TRelation* r) const
 | |
| {
 | |
|   if (_field)
 | |
|   {
 | |
|     _field->write(get(), r);
 | |
|     return TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 50%
 | |
| HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg)
 | |
| {
 | |
| #ifdef DBG
 | |
|   if (f.class_id() != CLASS_LIST_FIELD)
 | |
|   {
 | |
|     error_box("Can't add/delete items of non list-box field %d", f.dlg());
 | |
|     return;
 | |
|   }  
 | |
| #endif  
 | |
|   TList_field& l = (TList_field&)f;
 | |
|   
 | |
|   TToken_string item(16); 
 | |
|   item = msg.get(); 
 | |
|   if (add) item.add(msg.get()); 
 | |
|   item.strip("\"'");
 | |
|   if (add)
 | |
|     l.add_item(item);
 | |
|   else
 | |
|     l.delete_item(item);  
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| HIDDEN const char* copy_value(TToken_string& msg, const TString& val)
 | |
| {
 | |
|   int from = msg.get_int()-1;
 | |
|   int to = -1;
 | |
|   if (from < 0) from = 0;
 | |
|   else to = msg.get_int();
 | |
|   return val.sub(from, to);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 50%
 | |
| bool TMask_field::do_message(int num)
 | |
| {               
 | |
|   const int MAX_CMD = 14;
 | |
|   static const char* commands[MAX_CMD] =
 | |
|   {
 | |
|     "ADD",         // 0
 | |
|     "CLEAR",       // 1
 | |
|     "CO",          // 2
 | |
|     "DEL",         // 3
 | |
|     "DIRTY",       // 4
 | |
|     "DISABLE",     // 5
 | |
|     "ENABLE",      // 6
 | |
|     "ENABLEDEF",   // 7 
 | |
|     "EXIT",        // 8
 | |
|     "HIDE",        // 9
 | |
|     "PUSH",        // 10
 | |
|     "RESET",       // 11
 | |
|     "SHOW",        // 12
 | |
|     "UNDO"         // 13
 | |
|     };
 | |
| 
 | |
|   TToken_string* message = (TToken_string*)_message.objptr(num);
 | |
|   if (message == NULL || message->empty()) return FALSE;
 | |
| 
 | |
|   TToken_string msg(16, ',');
 | |
|   TString value(16);
 | |
| 
 | |
|   for (const char* m = message->get(0); m && *m; m = message->get())
 | |
|   {
 | |
|     KEY key = 0;
 | |
|     msg = m;
 | |
|     value = msg.get();
 | |
|     value.trim();
 | |
|     const char* dlg = msg.get();
 | |
|     
 | |
|     int cmd = -1;
 | |
|     if (isalpha(value[0]))                       // binary search
 | |
|     {         
 | |
|       int f = 0, l = MAX_CMD-1;                    
 | |
|       while (TRUE)
 | |
|       {
 | |
|         cmd = (f+l)>>1;                          
 | |
|         const int cmp = strcmp(value, commands[cmd]);
 | |
|         if (cmp == 0) break;
 | |
|         if (cmp > 0) f = cmd+1;
 | |
|         else         l = cmd-1;
 | |
|         if (f > l) 
 | |
|         {
 | |
|           cmd = -1;
 | |
|           break;
 | |
|         }  
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (cmd == 8)
 | |
|     {
 | |
|       mask().stop_run(atoi(dlg));
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0;
 | |
|     bool broadcast = dlg && strchr(dlg, '@');
 | |
|     if (value[0] == '"') value = value.strip("\"'");
 | |
|     else switch (cmd)
 | |
|     {
 | |
|     case 0:
 | |
|       modify_list(TRUE, mask().field(fld), msg); continue;
 | |
|     case 1:
 | |
|       key = 11000+'c'; break;
 | |
|     case 2:
 | |
|       value = copy_value(msg, get()); break;
 | |
|     case 3:
 | |
|       modify_list(FALSE, mask().field(fld), msg); continue;
 | |
|     case 4:
 | |
|       mask().field(fld).set_dirty(); continue;
 | |
|     case 5:
 | |
|       key = 11000+'d'; break;
 | |
|     case 6:
 | |
|       key = 11000+'e'; break;
 | |
|     case 7:  
 | |
|       key = 11000+'E'; break;
 | |
|     case 9:
 | |
|       key = 11000+'h'; break;
 | |
|     case 10:
 | |
|       key = K_SPACE; break;
 | |
|     case 11:
 | |
|       key = K_F2; break;
 | |
|     case 12:
 | |
|       key = 11000+'s'; break;
 | |
|     case 13:
 | |
|       key = K_F3; break;
 | |
|     default:                        
 | |
|       key = atoi(value);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (key)
 | |
|     {
 | |
|       if (key > 0)
 | |
|       {
 | |
|         if (broadcast) fld = -fld;
 | |
|         mask().send_key(key, fld);
 | |
|       }  
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       // Setta a value il campo fld solo se ha un valore diverso da value
 | |
|       if (broadcast)
 | |
|       {
 | |
|         for (int i = 0; i < mask().fields(); i++)
 | |
|         {
 | |
|           TMask_field& f = mask().fld(i);
 | |
|           if (f.in_group((int)fld))
 | |
|           {
 | |
|             const char* prev = f.get();
 | |
|             if (value != prev)
 | |
|             {
 | |
|               f.set(value);
 | |
|               if (f.showed() || f.ghost())
 | |
|                 f.on_hit();
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         TMask_field& f = mask().field(fld);
 | |
|         const char* prev = f.get();
 | |
|         if (value != prev)
 | |
|         {
 | |
|           f.set(value);
 | |
|           if (f.showed() || f.ghost())
 | |
|             f.on_hit();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 90%
 | |
| bool TMask_field::on_hit()
 | |
| {
 | |
|   if (_handler)
 | |
|   {
 | |
|     bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE);
 | |
|     if (!ok) return FALSE;
 | |
|   }
 | |
|   do_message(0);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TMask_field::to_check(KEY k, bool checkrun) const
 | |
| {   
 | |
|   bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty());
 | |
|   
 | |
|   if (!yes && checkrun)
 | |
|     yes = k == K_TAB && !mask().is_running();
 | |
|   
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TMask_field::on_key(KEY key)
 | |
| {
 | |
|   if (key > 11000)
 | |
|   {
 | |
|     switch(key-11000)
 | |
|     {
 | |
|     case 'E':
 | |
|       enable_default(); break;
 | |
|     case 'c':
 | |
|       reset(); on_hit();
 | |
|     case 'd':
 | |
|       disable(); break;
 | |
|     case 'e':
 | |
|       enable(); break;
 | |
|     case 'h':
 | |
|       hide(); break;
 | |
|     case 's':
 | |
|       show(); break;
 | |
| #ifdef DBG              
 | |
|       default :
 | |
|       return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key);
 | |
| #endif          
 | |
|     }
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   switch(key)
 | |
|   {
 | |
|   case K_SPACE:
 | |
|     set_dirty();
 | |
|     break;
 | |
|   case K_PREV:
 | |
|   case K_NEXT:
 | |
|     dispatch_e_char(parent(), key);
 | |
|     break;
 | |
|   case K_F1:
 | |
|     if (_help.not_empty())
 | |
|       message_box(_help);
 | |
|     else 
 | |
|       beep();
 | |
|     break;
 | |
|   case K_F2:
 | |
|     reset();
 | |
|     set_dirty();
 | |
|     break;
 | |
|   case K_F3:
 | |
|     undo();
 | |
|     set_dirty();
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (_handler)
 | |
|     return _handler(*this, key);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TMask_field::set_focus() const
 | |
| {                                                
 | |
|   const bool force = mask().is_running();
 | |
|   mask().set_focus_win(win(), force);
 | |
| }
 | |
| 
 | |
| HIDDEN char* const _msg = &__tmp_string[512];
 | |
| #define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr)
 | |
| 
 | |
| bool TMask_field::error_box(const char* fmt, ...) const
 | |
| {
 | |
|   build_msg();
 | |
|   if (mask().is_sheetmask() && !mask().is_running())
 | |
|   {                       
 | |
|     xvt_statbar_set(_msg);
 | |
|     beep();
 | |
|   }  
 | |
|   else
 | |
|   {
 | |
|     set_focus();
 | |
|     ::error_box("%s", _msg);
 | |
|     set_focus();
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| bool TMask_field::message_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   set_focus();
 | |
|   build_msg();
 | |
|   ::message_box("%s", _msg);
 | |
|   set_focus();
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| bool TMask_field::warning_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   build_msg();
 | |
|   
 | |
|   if (mask().is_sheetmask() && !mask().is_running())
 | |
|   {
 | |
|     xvt_statbar_set(_msg);
 | |
|     beep();
 | |
|   }  
 | |
|   else
 | |
|   {
 | |
|     set_focus();
 | |
|     ::warning_box("%s", _msg);
 | |
|     set_focus();
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| bool TMask_field::yesno_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   set_focus();
 | |
|   build_msg();
 | |
|   const bool yes = ::yesno_box("%s", _msg);
 | |
|   set_focus();
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| KEY TMask_field::yesnocancel_box(const char* fmt, ...) const
 | |
| {                         
 | |
|   set_focus();
 | |
|   build_msg();
 | |
|   const KEY k = ::yesnocancel_box("%s", _msg);
 | |
|   set_focus();
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TList_sheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
 | |
| : _fld(f), _row(-1)
 | |
| {
 | |
|   _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); 
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TList_sheet::~TList_sheet()
 | |
| {
 | |
|   delete _sheet;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field& TList_sheet::field(short id) const
 | |
| { return field().mask().field(id); }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::read_item(TScanner& scanner)
 | |
| {
 | |
|   TToken_string ts(scanner.string());
 | |
|   _sheet->add(ts);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::parse_input(TScanner& scanner)
 | |
| {
 | |
|   _inp_id.add(scanner.pop());
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TList_sheet::parse_output(TScanner& scanner)
 | |
| {
 | |
|   _out_id.add(scanner.pop());
 | |
| }
 | |
| 
 | |
| // il numero di riga selezionata
 | |
| int TList_sheet::do_input()
 | |
| {
 | |
|   if (_inp_id.empty()) return -2;          // List empty!
 | |
| 
 | |
|   _inp_id.restart();
 | |
|   TToken_string rowsel(80);
 | |
| 
 | |
|   for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
 | |
|   {
 | |
|     if (*fld == '"')
 | |
|     {
 | |
|       rowsel.add(fld+1);
 | |
|       if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const short id  =  _fld->atodlg(fld);
 | |
|       if (id > 0) rowsel.add(field().mask().get(id));
 | |
|       else rowsel.add("");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TString80 fd, it;
 | |
|   for (int i = 0 ; i < _sheet->items(); i++)
 | |
|   {
 | |
|     TToken_string& ts =_sheet->row(i);
 | |
| 
 | |
|     ts.restart();
 | |
|     for ( const char* item = rowsel.get(0); item ; item = rowsel.get())
 | |
|     {
 | |
|       it = item; it.trim();
 | |
|       fd = ts.get(); fd.trim();
 | |
|       if (fd != it) break;
 | |
|     }
 | |
|     if (!item) return i;
 | |
|   }
 | |
| 
 | |
|   return -1;                 // Value not found!
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 50%
 | |
| void TList_sheet::do_output(CheckTime t)
 | |
| {
 | |
|   if (_row < 0 || t == FINAL_CHECK) 
 | |
|     return;
 | |
|   
 | |
|   _out_id.restart();
 | |
|   TToken_string& rowsel = _sheet->row(_row);
 | |
|   rowsel.restart();
 | |
|   for (const char* fld = _out_id.get(); fld; fld = _out_id.get())
 | |
|   {
 | |
|     const short id  = _fld->atodlg(fld);
 | |
|     if (t != STARTING_CHECK || field().field() == NULL)
 | |
|     {
 | |
|       TMask_field& f = field(id);
 | |
|       f.set(rowsel.get());
 | |
|       if (field().dlg() != id)
 | |
|         f.on_hit();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| KEY TList_sheet::run()
 | |
| {
 | |
|   _row = do_input();
 | |
| 
 | |
|   _sheet->select(_row);
 | |
| 
 | |
|   const KEY k = _sheet->run();
 | |
| 
 | |
|   switch (k)
 | |
|   {
 | |
|   case K_ENTER:
 | |
|     _row = (int)_sheet->selected();
 | |
|     do_output();
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TList_sheet::check(CheckTime t)
 | |
| {
 | |
|   const bool passed = (_row = do_input()) != -1;
 | |
|   if (passed) do_output(t);
 | |
|   return passed;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TBrowse
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter)
 | |
| : _relation(r), _cursor(new TCursor (r, filter, key)),
 | |
|   _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::TBrowse(TEdit_field* f, TCursor* c)
 | |
| : _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE)
 | |
| {}
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TBrowse::~TBrowse()
 | |
| {
 | |
|   if (_relation)
 | |
|   {
 | |
|     delete _relation;
 | |
|     delete _cursor;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| void TBrowse::parse_display(TScanner& scanner)
 | |
| {              
 | |
|   const char* s;
 | |
|   s = scanner.string();
 | |
|   _head.add(s);
 | |
|   s = scanner.line();
 | |
|   _items.add(s);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_input(TScanner& scanner)
 | |
| {
 | |
|   const char* s = scanner.pop();
 | |
|   _inp_fn.add(s);
 | |
| 
 | |
|   s = scanner.pop();
 | |
|   if (*s == '"')        // Constant string
 | |
|   {
 | |
|     scanner.push();
 | |
|     _inp_id.add(scanner.line());
 | |
|   }
 | |
|   else            // Field on the mask
 | |
|   {
 | |
|     TString80 str(s);
 | |
|     if (scanner.popkey() == "SE") str << '@';       // Special FILTERing field
 | |
|     else scanner.push();
 | |
|     _inp_id.add(str);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_output(TScanner& scanner)
 | |
| {
 | |
|   const char* s = scanner.pop();
 | |
| #ifdef DBG      
 | |
|   field().atodlg(s);
 | |
| #endif  
 | |
|   _out_id.add(s);
 | |
|   s = scanner.pop();
 | |
|   _out_fn.add(s);  
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TBrowse::parse_copy(const TString& what, const TBrowse* b)
 | |
| {
 | |
|   const bool all = what == "AL";
 | |
|   if (all || what == "US")
 | |
|   {
 | |
|     set_insert(b->get_insert());
 | |
|     _filter = b->get_filter();
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "IN")
 | |
|   {
 | |
|     _inp_id = b->_inp_id;
 | |
|     _inp_fn = b->_inp_fn;
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "DI")
 | |
|   {
 | |
|     _head = b->_head;
 | |
|     _items = b->_items;
 | |
|     if (!all) return TRUE;
 | |
|   }
 | |
|   if (all || what == "OU")
 | |
|   {
 | |
|     _out_id = b->_out_id;
 | |
|     _out_fn = b->_out_fn;
 | |
|     _secondary = TRUE;
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_join(TScanner& scanner)
 | |
| {
 | |
|   TString80 j(scanner.pop());             // File or table
 | |
| 
 | |
|   CHECKS(_relation, "Can't join to NULL relation ", (const char*)j);
 | |
| 
 | |
|   int to;
 | |
|   if (scanner.popkey() == "TO")         // TO keyword
 | |
|   {
 | |
|     const char* t = scanner.pop();
 | |
|     to = name2log(t);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     to = 0;                  // _relation->lfile()->num();
 | |
|     scanner.push();
 | |
|   }
 | |
| 
 | |
|   int key = 1;
 | |
|   if (scanner.popkey() == "KE")
 | |
|     key = scanner.integer();
 | |
|   else scanner.push();
 | |
| 
 | |
|   byte alias = 0;
 | |
|   if (scanner.popkey() == "AL")
 | |
|     alias = scanner.integer();
 | |
|   else scanner.push();
 | |
| 
 | |
|   TToken_string exp(80);
 | |
|   if (scanner.pop() == "INTO")
 | |
|   {
 | |
|     const char* r = scanner.pop();
 | |
|     while (strchr(r, '=') != NULL)
 | |
|     {
 | |
|       exp.add(r);
 | |
|       r = scanner.pop();
 | |
|     }
 | |
|   }
 | |
|   scanner.push();
 | |
| 
 | |
| #ifdef DBG      
 | |
|   if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
 | |
| #endif  
 | |
| 
 | |
|   if (isdigit(j[0]))
 | |
|     _relation->add(atoi(j), exp, key, to, alias);   // join file
 | |
|   else
 | |
|   {
 | |
| #ifdef DBG      
 | |
|     if (j.len() > 4)
 | |
|       yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j);
 | |
|     else  
 | |
| #endif          
 | |
|       _relation->add(j, exp, key, to, alias);      // join table
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::parse_insert(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.popkey() == "RU")
 | |
|   {
 | |
|     _insert = "R";
 | |
|     _insert << scanner.line();
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     _insert = "M";
 | |
|     _insert << scanner.line();
 | |
|   }
 | |
|   _insert.trim();
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TMask_field& TBrowse::field(short n) const
 | |
| { return _fld->mask().field(n); }
 | |
| 
 | |
| // Ritorna il numero di campi non vuoti e non filtrati
 | |
| int TBrowse::do_input(bool filter)
 | |
| {
 | |
|   int ne = 0;
 | |
|   if (_inp_id.empty()) return ne;
 | |
| 
 | |
|   TRectype& cur = _cursor->curr();
 | |
| 
 | |
|   cur.zero();
 | |
|   TRectype filtrec(cur);
 | |
| 
 | |
|   _inp_id.restart();
 | |
|   _inp_fn.restart();
 | |
| 
 | |
|   TString80 val;                  // Value to output
 | |
|   bool tofilter;
 | |
| 
 | |
|   for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
 | |
|   {
 | |
|     if (*fld == '"')
 | |
|     {
 | |
|       val = (fld+1);
 | |
|       if (val.not_empty()) val.rtrim(1);
 | |
|       tofilter = filter;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const short id  = _fld->atodlg(fld);
 | |
|       const bool filter_flag = strchr(fld, '@') != NULL;
 | |
|       tofilter = filter && filter_flag;
 | |
|       val = field(id).get();
 | |
|       if (field(id).is_edit() && val.not_empty() && !filter_flag) 
 | |
|         ne++;          // Increment not empty fields count
 | |
|     }
 | |
| 
 | |
|     TFieldref fldref(_inp_fn.get(), 0); // Output field
 | |
|     fldref.write(val, _cursor->relation());
 | |
|     if (tofilter)
 | |
|     {
 | |
|       if (val.empty()) val.fill('~', fldref.len(cur));
 | |
|       fldref.write(val, filtrec);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!filter) return ne;
 | |
| 
 | |
|   TString work(_filter.size());
 | |
|   for (int i = 0; _filter[i]; i++)
 | |
|   {
 | |
|     if (_filter[i] == '"')
 | |
|     { 
 | |
|       do
 | |
|       {
 | |
|         work << _filter[i++];
 | |
|       } while (_filter[i] && _filter[i] != '"');
 | |
|       work << '"';
 | |
|       if (!_filter[i]) break;
 | |
|     }
 | |
|     else
 | |
|       if (_filter[i] == '#')
 | |
|       {
 | |
|         work << '"' << field(atoi(&_filter[++i])).get() << '"';
 | |
|         while (isspace(_filter[i])) i++;
 | |
|         while (isdigit(_filter[i])) i++;
 | |
|         i--;
 | |
|       }
 | |
|       else work << _filter[i];
 | |
|   }
 | |
| 
 | |
|   _cursor->setfilter(work);
 | |
|   _cursor->setregion(filtrec, filtrec);
 | |
| 
 | |
|   return ne;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::do_output(CheckTime t)
 | |
| {   
 | |
|   if (t == FINAL_CHECK) 
 | |
|     return;
 | |
| 
 | |
|   TString80 sum;
 | |
|   TToken_string flds(24, '+');
 | |
| 
 | |
|   _out_fn.restart();
 | |
|   for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
 | |
|   {
 | |
|     const short id = field().atodlg(fld);
 | |
|     TMask_field& f = field(id);
 | |
| 
 | |
|     flds = _out_fn.get();
 | |
|     if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS)
 | |
|     {
 | |
|       sum.cut(0);
 | |
|       for(const char* fr = flds.get(0); fr; fr = flds.get())
 | |
|       {  
 | |
|         const char* val;         
 | |
|         if (*fr == '"')
 | |
|         { 
 | |
|           const TString80 v(fr);
 | |
|           val = v.mid(1, v.len()-2);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           const TFieldref fld(fr, 0);
 | |
|           val = fld.read(_cursor->relation());
 | |
|         }  
 | |
|         sum << val;
 | |
|       }
 | |
| 
 | |
|       f.set(sum);
 | |
|       if (field().dlg() != id)
 | |
|         f.on_hit();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBrowse::do_clear()
 | |
| {                  
 | |
|   for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get())
 | |
|   {
 | |
|     TMask_field& f = field(atoi(fld));
 | |
|     if (f.field() == NULL && _inp_id.get_pos(fld) < 0) 
 | |
|       f.reset();
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| bool TBrowse::do_insert()
 | |
| {
 | |
|   bool ok = FALSE;
 | |
|   TString80 app;
 | |
| 
 | |
|   if (_insert[0] == 'M')
 | |
|   {
 | |
|     TString80 nm(_insert.mid(1));
 | |
|     if (strncmp(nm, "BATB", 4) == 0)    // Programma gestione tabelle
 | |
|       app = format("ba3 -0 %s", (const char*)nm.mid(4));
 | |
|     // Obbligatorio usare la format globale
 | |
|     else                              // Programma generico di browse/edit
 | |
|       app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num());
 | |
|     // Obbligatorio usare la format globale
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     app = _insert.mid(1);
 | |
|   }
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   if (strnicmp(app, MainApp()->name(), 3) == 0)
 | |
|     app.insert("a", 3);
 | |
| #endif
 | |
| 
 | |
|   TMailbox mail;
 | |
|   TMessage msg(cmd2name(app), MSG_AI, "");
 | |
|   mail.send(msg);
 | |
| 
 | |
|   TExternal_app a(app);
 | |
|   a.run();
 | |
| 
 | |
|   if (mail.check())
 | |
|   {
 | |
|     TMessage* rcv = mail.next_s(MSG_AI);
 | |
|     if (rcv != NULL) _rec = atoi(rcv->body());
 | |
|     if (_rec > 0)
 | |
|     {
 | |
|       _cursor->file().readat(_rec);
 | |
|       ok = _cursor->ok();
 | |
|       if (ok) do_output();
 | |
| #ifdef DBG      
 | |
|       else error_box("Selezione da programma esterno errata");
 | |
| #endif      
 | |
|     }
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| TToken_string& TBrowse::create_siblings(TToken_string& siblings)
 | |
| {
 | |
|   const TMask& mask = field().mask();
 | |
|   siblings = "";                      // Azzera la lista dei campi associati
 | |
|   
 | |
|   if (!mask.is_running())
 | |
|     return siblings;                  // Non saprei come fare
 | |
|   
 | |
|   TBit_array key(4);                  // Elenco delle chiavi gia' utilizzate
 | |
|   key.set(_cursor->key());
 | |
|   
 | |
|   // Scorre la lista dei campi di output
 | |
|   int n = 0;  
 | |
|   for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++)
 | |
|   {
 | |
|     const short id = _fld->atodlg(i);
 | |
|     const TMask_field& f = mask.field(id);
 | |
|     if (!f.showed() || !f.is_edit())  // Scarta i campi non editabili
 | |
|       continue;
 | |
|     const TEdit_field& e = (const TEdit_field&)f;
 | |
|     const TBrowse* b = e.browse();
 | |
|     if (b == NULL) 
 | |
|       continue;                       // Scarta i campi senza ricerca
 | |
|     
 | |
|     const TCursor* c = b->cursor();  
 | |
|     
 | |
|     // Considera ricerche sullo stesso file ma con chiave diversa
 | |
|     if (c && c->file().num() == _cursor->file().num() && 
 | |
|         (key[c->key()] == FALSE || id == _fld->dlg()))      
 | |
|     {
 | |
|       const TString16 fn(_out_fn.get(n));     // Legge nome del campo su file          
 | |
|       const int pos = _items.get_pos(fn);     // Determina header corrispondente
 | |
|       if (pos >= 0)
 | |
|       {
 | |
|         siblings.add(id);
 | |
|         const char* h = _head.get(pos); 
 | |
|         siblings.add(h);
 | |
|         const int et = siblings.find('@');
 | |
|         if (et > 0) siblings.cut(et);
 | |
|         key.set(c->key());                    // Marca la chiave come usata
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   return siblings;
 | |
| }
 | |
| 
 | |
| 
 | |
| KEY TBrowse::run()
 | |
| {
 | |
|   do_input(TRUE);
 | |
|   _cursor->read();
 | |
| 
 | |
|   TString80 caption;
 | |
|   const TLocalisamfile& f = _cursor->file();
 | |
|   if (f.tab())
 | |
|   {
 | |
|     TFilename name("batb"); 
 | |
|     if (f.num() == LF_TABCOM) name << '%';
 | |
|     name << _cursor->file().name() << ".msk";
 | |
|     if (fexist(name))
 | |
|     {
 | |
|       TScanner m(name.lower());
 | |
|       while (m.line().left(2) != "PA");      // Find PAGE
 | |
|       const int apicia = m.token().find('"')+1;
 | |
|       const int apicic = m.token().find('"', apicia);
 | |
|       caption = m.token().sub(apicia, apicic);
 | |
|     }
 | |
|     else
 | |
|       caption = f.description();
 | |
|   }
 | |
|   else
 | |
|     caption = f.description();
 | |
|   if (!isalnum(caption[0])) 
 | |
|     caption = "Selezione";
 | |
|   
 | |
|   KEY k = K_ESC;
 | |
|   long selected = 0;
 | |
| 
 | |
|   TToken_string siblings; create_siblings(siblings);                            
 | |
|   
 | |
| {
 | |
|   TToken_string* sib = siblings.empty() ? NULL : &siblings;
 | |
|   const byte buttons = _insert.empty() ? 0 : 1;
 | |
|   TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib);
 | |
|   k = s.run();
 | |
|   selected = s.selected();
 | |
| }
 | |
| 
 | |
| switch (k)
 | |
| {
 | |
|  case K_INS:
 | |
|   k = do_insert() ? K_ENTER : K_ESC;
 | |
|   break;
 | |
|  case K_ENTER:
 | |
|   *_cursor = selected;
 | |
|   do_output();
 | |
|   break;
 | |
| default:
 | |
|   if (k >= K_CTRL)
 | |
|   {
 | |
|     const short id = siblings.get_int((k - K_CTRL) << 1);
 | |
|     TEdit_field& ef = (TEdit_field&)_fld->mask().field(id);
 | |
|     if (ef.mask().is_running()) ef.set_focus();
 | |
|     else ef.mask().first_focus(-ef.dlg());
 | |
|     ef.mask().send_key(k = K_F9, 0);
 | |
|   }
 | |
|   break;
 | |
| }
 | |
| 
 | |
| return k;
 | |
| }
 | |
| 
 | |
| bool TBrowse::check(CheckTime t)
 | |
| {
 | |
|   bool passed = TRUE;
 | |
| 
 | |
|   if (_secondary == TRUE && t != RUNNING_CHECK)
 | |
|     return TRUE;
 | |
|   //    if (_checked && t == FINAL_CHECK)
 | |
|   //      return TRUE;
 | |
|   //    _checked = TRUE;
 | |
|   if (_fld->check_type() != CHECK_NONE)
 | |
|   {
 | |
|     const TMaskmode mode = (TMaskmode)field().mask().mode();
 | |
| 
 | |
|     CheckType chk = _fld->check_type();
 | |
|     const int ne = do_input(TRUE);
 | |
|     if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL;
 | |
|     if (ne || chk == CHECK_REQUIRED)
 | |
|     {
 | |
|       _cursor->setkey();
 | |
|       _cursor->file().read(_isequal);
 | |
|       passed = _cursor->ok();
 | |
| 
 | |
|       if (t != FINAL_CHECK)
 | |
|       {
 | |
|         if (passed)
 | |
|         {
 | |
|           _cursor->repos();
 | |
|           do_output(t);
 | |
|         }
 | |
|         else 
 | |
|         {
 | |
|           do_clear();
 | |
|           _fld->set_dirty(2);
 | |
|         }  
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|       if (t != FINAL_CHECK) do_clear();
 | |
|   }
 | |
|   //    _checked = passed;
 | |
|   return passed;
 | |
| }
 | |
| 
 | |
| bool TBrowse::empty_check()
 | |
| {
 | |
|   const TMaskmode mode = (TMaskmode)field().mask().mode();
 | |
|   const bool no_check = mode == MODE_SEARCH || field().mask().query_mode();
 | |
| 
 | |
|   if ( no_check || _fld->check_type() == CHECK_NONE ||
 | |
|       _fld->check_type() == CHECK_NORMAL)
 | |
|     return TRUE;
 | |
|   else
 | |
|     return do_input() > 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TEdit_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TEdit_field::TEdit_field(TMask* mask)
 | |
| : TMask_field(mask), _browse(NULL), _sheet(NULL),
 | |
|   _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(TRUE),
 | |
|   _forced(FALSE)
 | |
| {}
 | |
| 
 | |
| TEdit_field::~TEdit_field()
 | |
| {
 | |
|   if (_browse) delete _browse; else
 | |
|     if (_sheet) delete _sheet;
 | |
| }
 | |
| 
 | |
| word TEdit_field::class_id() const
 | |
| { return CLASS_EDIT_FIELD; }
 | |
| 
 | |
| 
 | |
| void TEdit_field::enable(bool on)
 | |
| {
 | |
|   TMask_field::enable(on);
 | |
|   if (_buttonwin != NULL_WIN)
 | |
|     show_window(_buttonwin, on && check_enabled() && showed());
 | |
| }
 | |
| 
 | |
| void TEdit_field::show(bool on)
 | |
| {
 | |
|   TMask_field::show(on);
 | |
|   if (_buttonwin != NULL_WIN)
 | |
|     show_window(_buttonwin, on && check_enabled() && enabled());
 | |
| }
 | |
| 
 | |
| 
 | |
| void TEdit_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _size  = scanner.integer();
 | |
| #ifdef DBG  
 | |
|   if (_size < 1)
 | |
|   {
 | |
|     _size = 8;
 | |
|     yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size);
 | |
|   }
 | |
| #endif
 | |
|   _width = scanner.integer();
 | |
|   if (_width == 0) _width = _size;
 | |
| }
 | |
| 
 | |
| 
 | |
| const TBrowse* TEdit_field::get_browse(TScanner& scanner) const
 | |
| {
 | |
|   const int id = scanner.integer();
 | |
|   const TEdit_field& f = mask().efield(id);
 | |
|   const TBrowse* b = (const TBrowse*)f.browse();
 | |
| #ifdef DBG    
 | |
|   if (b == NULL)
 | |
|     error_box("La USE del campo %d non puo' essere copiata nel campo %d", id, dlg());
 | |
| #endif    
 | |
|   return b;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TEdit_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "PI")            // PICTURE
 | |
|   {
 | |
|     _picture = scanner.string();
 | |
| #ifdef DBG    
 | |
|     if (_picture == "." && _size > 9 && _size != 15) 
 | |
|       ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", 
 | |
|                     dlg(), (const char*)_prompt);
 | |
| #endif    
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "CH")
 | |
|   {
 | |
|     scanner.pop();
 | |
|     if (scanner.key() == "NO") _check = CHECK_NORMAL;
 | |
|     else if (scanner.key() == "RE") _check = CHECK_REQUIRED;
 | |
|     else if (scanner.key() == "FO") {_check = CHECK_REQUIRED; _forced = TRUE;}
 | |
|     else _check = CHECK_NONE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "US")            // USE
 | |
|   {
 | |
| #ifdef DBG  
 | |
|     if (_browse != NULL)
 | |
|       return error_box("USE duplicata nel campo %d", dlg());
 | |
| #endif
 | |
|     
 | |
|     int key = 1;
 | |
|     TRelation* r;
 | |
| 
 | |
|     const int logicnum = scanner.integer();
 | |
|     TString16 tabmaskname;
 | |
| 
 | |
|     if (logicnum > 0)
 | |
|       r = new TRelation(logicnum);
 | |
|     else
 | |
|     {
 | |
|       tabmaskname  = scanner.pop();
 | |
| #ifdef DBG  
 | |
|       if (tabmaskname.len() > 4)
 | |
|         return error_box("'%s' non e' una tabella valida: %d",
 | |
|                          (const char*)tabmaskname, dlg());
 | |
| #endif                    
 | |
|       r = new TRelation(tabmaskname);
 | |
|     }
 | |
| 
 | |
|     if (scanner.popkey() == "KE")
 | |
|     {
 | |
|       key = scanner.integer();
 | |
| #ifdef DBG  
 | |
|       if (key < 1)
 | |
|       {
 | |
|         yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg());
 | |
|         key = 1;
 | |
|       }
 | |
| #endif      
 | |
|     }
 | |
|     else scanner.push();
 | |
| 
 | |
|     const char* filter = "";
 | |
|     if (scanner.popkey() == "SE")
 | |
|       filter = (const char*)scanner.line();
 | |
|     else
 | |
|       scanner.push();
 | |
| 
 | |
|     _browse = new TBrowse(this, r, key, filter);
 | |
| 
 | |
|     if (tabmaskname.not_empty())
 | |
|     {
 | |
|       if (strncmp(MainApp()->name(), "ba3", 3) != 0)
 | |
|       {
 | |
|         tabmaskname.insert("MBATB", 0);
 | |
|         _browse->set_insert(tabmaskname);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "CO")                    // Copyuse
 | |
|   {
 | |
|     const TString16 what(scanner.popkey());
 | |
| 
 | |
|     const TBrowse* b = get_browse(scanner);
 | |
|     if (b == NULL) return FALSE;
 | |
| 
 | |
|     if (what == "US" || what == "AL")
 | |
|       _browse = new TBrowse(this, b->cursor());
 | |
| 
 | |
|     if (_browse)
 | |
|       return _browse->parse_copy(what, b);
 | |
| 
 | |
| #ifdef DBG
 | |
|     return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg());
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "JO")
 | |
|   {
 | |
| #ifdef DBG      
 | |
|     if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg());
 | |
| #endif
 | |
|     _browse->parse_join(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "SH")            // SHEET
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_sheet) return error_box("SHEET duplicato nel campo %d", dlg());
 | |
| #endif
 | |
|     _sheet = new TList_sheet(this, _prompt, scanner.string());
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "IT")            // ITEM
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if (_sheet == NULL) return error_box("ITEM senza SHEET nel campo %d", dlg());
 | |
| #endif    
 | |
|     _sheet->read_item(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "IN")
 | |
|   {
 | |
|     if (_browse) _browse->parse_input(scanner); else
 | |
|       if (_sheet) _sheet->parse_input(scanner);
 | |
| #ifdef DBG    
 | |
|       else error_box("INPUT senza USE o SHEET nel campo %d", dlg());
 | |
| #endif      
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "DI")
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if(!_browse) return error_box("DISPLAY senza USE nel campo %d", dlg());
 | |
| #endif
 | |
|     _browse->parse_display(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "OU")
 | |
|   {
 | |
|     if (_browse) _browse->parse_output(scanner);
 | |
|     else if (_sheet)  _sheet->parse_output(scanner);
 | |
| #ifdef DBG    
 | |
|     else return error_box("OUTPUT senza USE nel campo %d", dlg());
 | |
| #endif    
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "AD")
 | |
|   {
 | |
| #ifdef DBG    
 | |
|     if(!_browse) return error_box("ADD senza USE nel campo %d", dlg());
 | |
| #endif    
 | |
|     _browse->parse_insert(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "VA")
 | |
|   {                    
 | |
|     const char* n = scanner.pop();
 | |
|     _validate_func = isdigit(*n) ? atoi(n) : -1;
 | |
| #ifdef DBG    
 | |
|     if (_validate_func < 0)
 | |
|       return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg());
 | |
| #endif
 | |
| 
 | |
|     const int _nparms = scanner.integer();
 | |
| #ifdef DBG    
 | |
|     if (_nparms < 0)
 | |
|       return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d", dlg());
 | |
| #endif
 | |
| 
 | |
|     for(int i = 0; i < _nparms; i++)
 | |
|       _validate_parms.add(scanner.operand());
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "WA")
 | |
|   {
 | |
|     _warning = scanner.string();
 | |
|     return TRUE;
 | |
|   }
 | |
|   if (scanner.key() == "ME")
 | |
|   {                
 | |
|     TFixed_string l(scanner.line().strip_spaces());
 | |
|     int m = 0;
 | |
|     if (l[0] == '0')
 | |
|     {            
 | |
|       l.ltrim(1);
 | |
|       l.ltrim();    
 | |
|       m = 1;
 | |
|     }                      
 | |
|     if (_message.objptr(m) == 0)
 | |
|       _message.add(new TToken_string(64), m);
 | |
|     TToken_string& ts = (TToken_string&)_message[m];
 | |
|     ts.add(l);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TEdit_field::create(WINDOW parent)
 | |
| {
 | |
|   const int len = create_prompt(parent);
 | |
| 
 | |
|   long align = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST;
 | |
|   _x += len;
 | |
| 
 | |
| #if XVTWS == WMWS
 | |
|   const int delta = 2;
 | |
| #else
 | |
|   const int delta = 1;
 | |
| #endif
 | |
| 
 | |
|   wincreate(WC_EDIT, _width+delta, 1, _str, parent, align);
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW);
 | |
|   SendMessage(hwnd, EM_LIMITTEXT, _size, 0L);    // Limita il testo
 | |
|   long style = GetWindowLong(hwnd, GWL_STYLE);   
 | |
|   if (_flags.uppercase) style != ES_UPPERCASE;   // Edit in maiuscolo
 | |
|   SetWindowLong(hwnd, GWL_STYLE, style);   
 | |
| #endif
 | |
| 
 | |
|   if (_browse || _sheet)
 | |
|   {
 | |
|     long flags = default_flags();
 | |
|     if (flags & CTL_FLAG_DISABLED)
 | |
|     {
 | |
|       flags &= ~CTL_FLAG_DISABLED;
 | |
|       flags |= CTL_FLAG_INVISIBLE;
 | |
|     }
 | |
|     _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y,
 | |
|                                     2, 1,       "*", parent, flags, PTR_LONG(this), DLG_F9);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TEdit_field::destroy()
 | |
| {
 | |
|   if (_buttonwin)
 | |
|   { close_window(_buttonwin); _buttonwin = NULL_WIN; }
 | |
|   TMask_field::destroy();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TEdit_field::set_window_data(const char* data)
 | |
| {
 | |
|   TMask_field::set_window_data(format(data));
 | |
| }
 | |
| 
 | |
| 
 | |
| void TEdit_field::set_field_data(const char* data)
 | |
| { _str = data; }
 | |
| 
 | |
| const char* TEdit_field::get_field_data() const
 | |
| { return _str; }
 | |
| 
 | |
| 
 | |
| const char* TEdit_field::format(const char* d)
 | |
| {
 | |
|   fpark = d;
 | |
|   fpark.trim();
 | |
| 
 | |
|   if (fpark.not_empty())
 | |
|   {              
 | |
|     if (fpark.len() > _size)
 | |
|     {
 | |
| #ifdef DBG      
 | |
|       error_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size);
 | |
| #endif      
 | |
|       fpark.cut(_size);
 | |
|     }
 | |
| 
 | |
|     if (_flags.uppercase)
 | |
|       fpark.upper();
 | |
| 
 | |
|     if (_flags.zerofilled)
 | |
|       fpark.right_just(_size, '0');
 | |
|     else  
 | |
|       if (_flags.rightjust)
 | |
|         fpark.right_just(_size);
 | |
|   }
 | |
| 
 | |
|   return fpark;
 | |
| }
 | |
| 
 | |
| 
 | |
| const char* TEdit_field::picture_data(const char* data, bool video)
 | |
| {
 | |
|   if (video) 
 | |
|   { 
 | |
|     data = format(data);
 | |
|     set_title(win(), (char*)data); 
 | |
|     return get_window_data(); 
 | |
|   }
 | |
|   
 | |
|   set_window_data(data);
 | |
|   TMask_field::get_window_data();
 | |
|   fpark.trim();
 | |
|   return fpark; 
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TEdit_field::validate(KEY k)
 | |
| {
 | |
|   return ::validate(_validate_func, *this, k, _validate_parms);
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TEdit_field::on_hit()
 | |
| {
 | |
|   if (_handler)
 | |
|   {
 | |
|     bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE);
 | |
|     if (!ok) return FALSE;
 | |
|   }
 | |
|   if (_message.objptr(1) && get() == "") do_message(1);
 | |
|   else do_message(0);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TEdit_field::on_key(KEY key)
 | |
| {
 | |
|   switch(key)
 | |
|   {
 | |
|   case K_TAB:
 | |
|     if (_validate_func == AUTOEXIT_FUNC || 
 | |
|         _validate_func == NUMCALC_FUNC ||
 | |
|         _validate_func == STRCALC_FUNC)
 | |
|       set_focusdirty();            // Forza validate
 | |
|     if (to_check(K_TAB, TRUE))
 | |
|     {
 | |
|       set(get());
 | |
|       bool ok = validate(key);     // Check validation expression
 | |
| 
 | |
|       if (!ok)
 | |
|       {
 | |
|         if (_warning.not_empty()) error_box(_warning);
 | |
|         return FALSE;
 | |
|       }
 | |
| 
 | |
|       TMask& m = mask();
 | |
|       const bool query = m.query_mode();
 | |
| 
 | |
|       if (_sheet) ok = query || _sheet->check();  // Check consistency
 | |
|       else
 | |
|         if (check_enabled() && _browse && (!query || forced()))
 | |
|           ok = _browse->check();
 | |
|       
 | |
|       if (!ok)
 | |
|       {
 | |
|         if (_warning.not_empty()) error_box(_warning);
 | |
|         else 
 | |
| #ifdef DBG
 | |
|           error_box("Valore del campo %d non valido: %s", dlg(), (const char*)get());
 | |
| #else
 | |
|         error_box("Valore non valido: %s", (const char*)get());
 | |
| #endif        
 | |
|         return FALSE;
 | |
|       }
 | |
|       
 | |
|       ok = on_hit();
 | |
|       if (!ok)
 | |
|         return FALSE;
 | |
| 
 | |
|       if (query && required() && in_key(0))
 | |
|       {
 | |
|         const byte keys = m.num_keys();
 | |
| 
 | |
|         for (int i = 1; i <= keys; i++)
 | |
|           if (in_key(i) && m.key_valid(i))
 | |
|           {
 | |
|             for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE))
 | |
|               m.field(fld).set_dirty(FALSE);
 | |
|             dispatch_e_char(get_parent(win()), K_AUTO_ENTER);
 | |
|             break;
 | |
|           }
 | |
|       }
 | |
|       return TRUE;
 | |
|     }
 | |
|     break;
 | |
|   case K_ENTER:
 | |
|     if (field() != NULL || mask().mode() == NO_MODE)
 | |
|     {
 | |
|       if (focusdirty()) set(get());
 | |
| 
 | |
|       bool ok = validate(K_ENTER);                           // Check validation expression
 | |
|       if (!ok)
 | |
|       {
 | |
|         if (_warning.not_empty()) error_box(_warning);
 | |
|         return FALSE;
 | |
|       }
 | |
|       
 | |
|       const bool query = mask().query_mode();
 | |
| 
 | |
|       // check consistency
 | |
|       if (_sheet) ok = query || _sheet->check(FINAL_CHECK);
 | |
|       else if (_browse && check_enabled())
 | |
|       {
 | |
|         if (!query || forced())
 | |
|         {
 | |
|           if (dirty()) ok = _browse->check(FINAL_CHECK);     // Check consistency
 | |
|           else ok = _browse->empty_check();
 | |
|         }
 | |
|       }
 | |
|       else 
 | |
|         ok = query || !(check_type() == CHECK_REQUIRED && get().empty());
 | |
| 
 | |
|       if (!ok)
 | |
|       {
 | |
|         if (_warning.not_empty()) error_box(_warning);
 | |
|         else error_box("Valore del campo %d non valido: '%s'", dlg(), (const char*)get());
 | |
|         return FALSE;
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   case K_F9:
 | |
|     if (check_enabled())
 | |
|     {
 | |
|       if (dirty()) set(get());
 | |
|       KEY k = K_ESC;
 | |
|       if (_browse) k = _browse->run();
 | |
|       else if (_sheet) k = _sheet->run();
 | |
|       else beep();
 | |
|       if (mask().is_running() && k != K_F9) set_focus();
 | |
|       if (k == K_ENTER)
 | |
|       {
 | |
|         set_dirty();
 | |
|         if (mask().is_running())   
 | |
|           mask().send_key(K_TAB, 0);
 | |
|         else
 | |
|           on_hit();
 | |
|         return TRUE;
 | |
|       } 
 | |
|       else 
 | |
|         return FALSE;
 | |
|     }
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return TMask_field::on_key(key);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TEdit_field::has_check() const
 | |
| {
 | |
|   if (_browse) return check_type() != CHECK_NONE;
 | |
|   return _sheet != NULL;
 | |
| }
 | |
| 
 | |
| bool TEdit_field::check(CheckTime t)
 | |
| {
 | |
|   if (check_enabled() || (t == STARTING_CHECK && showed()))
 | |
|   {
 | |
|     if (_browse) return _browse->check(t); else
 | |
|       if (_sheet) return _sheet->check(t);
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| void TEdit_field::enable_check(bool on)
 | |
| {
 | |
|   _check_enabled = on;
 | |
|   if (_buttonwin != NULL_WIN)
 | |
|     show_window(_buttonwin, on);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Boolean_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| TBoolean_field::TBoolean_field(TMask* m)
 | |
| : TMask_field(m), _on(FALSE)
 | |
| {}
 | |
| 
 | |
| 
 | |
| word TBoolean_field::class_id() const
 | |
| { return CLASS_BOOLEAN_FIELD; }
 | |
| 
 | |
| 
 | |
| void TBoolean_field::create(WINDOW parent)
 | |
| {
 | |
|   wincreate(WC_CHECKBOX, strlen(_prompt)+4, 1, _prompt, parent, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| const char* TBoolean_field::get_window_data() const
 | |
| {
 | |
|   CHECK(win(), "Control window not initialized");
 | |
|   fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' ';
 | |
|   fpark[1] = '\0';
 | |
|   return fpark;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBoolean_field::set_window_data(const char* data)
 | |
| {
 | |
|   CHECK(win(), "Control window not initialized");
 | |
| 
 | |
|   if (data == NULL) data = "";
 | |
|   const bool b = toupper(*data) == 'X';
 | |
|   xvt_check_box(win(), b);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TBoolean_field::set_field_data(const char* data)
 | |
| {
 | |
|   if (data == NULL) data = "";
 | |
|   _on = toupper(*data) == 'X';
 | |
| }
 | |
| 
 | |
| const char* TBoolean_field::get_field_data() const
 | |
| {
 | |
|   return _on ? "X" : " ";
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TBoolean_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "ME")
 | |
|   {
 | |
|     const bool tf = scanner.integer() ? TRUE : FALSE;   // Message TRUE or FALSE
 | |
| 
 | |
|     if (_message.items() == 0)
 | |
|     {
 | |
|       _message.add(new TToken_string(16));
 | |
|       _message.add(new TToken_string(16));
 | |
|     }
 | |
|     TToken_string& ts = (TToken_string&)_message[tf];
 | |
|     ts.add(scanner.line().strip_spaces());
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| void TBoolean_field::enable(bool on)
 | |
| {
 | |
|   _flags.enabled = on;
 | |
|   xvt_enable_control(_win, on);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TBoolean_field::on_hit()
 | |
| {                          
 | |
|   if (_handler)
 | |
|   {
 | |
|     bool ok = _handler(*this, K_SPACE);
 | |
|     if (!ok) return FALSE;
 | |
|   }
 | |
|   const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on;
 | |
|   do_message(n);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TBoolean_field::on_key(KEY key)
 | |
| {
 | |
|   if (key == K_SPACE) 
 | |
|   {  
 | |
|     on_hit();
 | |
|     set_dirty();
 | |
|     return TRUE;
 | |
|   }  
 | |
|   return TMask_field::on_key(key);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Button_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TButton_field::TButton_field(TMask* m)
 | |
| : TMask_field(m)
 | |
| {
 | |
|   _flags.persistent = TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| word TButton_field::class_id() const
 | |
| { return CLASS_BUTTON_FIELD; }
 | |
| 
 | |
| void TButton_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _width = scanner.integer();
 | |
|   if (_width < 1) _width = 9;
 | |
|   _size  = scanner.integer(); // Height
 | |
|   if (_size < 1) _size = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TButton_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TButton_field::create(WINDOW parent)
 | |
| {
 | |
|   long flags = CTL_FLAG_CENTER_JUST;
 | |
| 
 | |
|   switch (dlg())
 | |
|   {
 | |
|   case DLG_OK:
 | |
|     if (_prompt.empty())
 | |
|       _prompt = "Conferma";   
 | |
|     _virtual_key = _exit_key = K_ENTER;
 | |
|     flags |= CTL_FLAG_DEFAULT;
 | |
|     break;
 | |
|   case DLG_CANCEL:
 | |
|     if (_prompt.empty())
 | |
|       _prompt = "Annulla";
 | |
|     _virtual_key = _exit_key = K_ESC;
 | |
|     break;
 | |
|   case DLG_DELREC:  
 | |
|     _virtual_key = 'E';
 | |
|     _exit_key = K_DEL;
 | |
|     break;
 | |
|   case DLG_PRINT:
 | |
|     if (_prompt.empty())
 | |
|       _prompt = "Stampa"; 
 | |
|     _virtual_key = 'S';
 | |
|     _exit_key = K_ENTER;
 | |
|     break;
 | |
|   case DLG_QUIT:
 | |
|     if (_prompt.empty())
 | |
|       _prompt = "Fine"; 
 | |
|     _virtual_key = K_F4;
 | |
|     _exit_key = K_QUIT;
 | |
|     break;
 | |
|   default:
 | |
|   { 
 | |
|     _exit_key = 0;
 | |
|     TToken_string* message = (TToken_string*)_message.objptr(0);
 | |
|     if (message != NULL)
 | |
|     {
 | |
|       TToken_string msg(message->get(0), ','); 
 | |
|       const TFixed_string m(msg.get(0));
 | |
|       if (m == "EXIT") 
 | |
|         _exit_key = msg.get_int();
 | |
|       else 
 | |
|         if (msg.get_int() == 0) _exit_key = atoi(m);
 | |
|     }
 | |
|     const int n = _prompt.find('~');
 | |
|     _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key;
 | |
|   }  
 | |
|     break;
 | |
|   }
 | |
| 
 | |
| 
 | |
| #if XWTWS == WMWS
 | |
|   _prompt.center_just(_width);
 | |
| #endif          
 | |
|   
 | |
|   wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags);
 | |
| }
 | |
| 
 | |
| void TButton_field::enable(bool on)
 | |
| {
 | |
|   _flags.enabled = on;
 | |
|   xvt_enable_control(_win, on);
 | |
| }
 | |
| 
 | |
| void TButton_field::show(bool on)
 | |
| {
 | |
|   TMask_field::show(on);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TButton_field::on_key(KEY key)
 | |
| 
 | |
| {
 | |
|   if (key == K_SPACE)   
 | |
|   {
 | |
|     on_hit();
 | |
|     return TRUE;
 | |
|   }  
 | |
|   return TMask_field::on_key(key);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Date_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| word TDate_field::class_id() const
 | |
| { return CLASS_DATE_FIELD; }
 | |
| 
 | |
| void TDate_field::create(WINDOW w)
 | |
| {
 | |
|   TEdit_field::create(w);
 | |
|   if (automagic())
 | |
|   {
 | |
|     TDate d(TODAY);
 | |
|     set(d.string());
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TDate_field::parse_head(TScanner&) {}
 | |
| 
 | |
| TDate_field::TDate_field(TMask* m) : TEdit_field(m)
 | |
| {
 | |
|   _size = _width = 10;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TDate_field::on_key(KEY key)
 | |
| {
 | |
|   if (to_check(key))
 | |
|   {
 | |
|     TFixed_string data(get_window_data(), 15);
 | |
|     data.trim();
 | |
|     if (data.not_empty() || required())
 | |
|     {
 | |
|       bool changed = FALSE;
 | |
|       if (isdigit(data[0]))
 | |
|       {
 | |
|         if (data.len() == 6)      // Fix century (for this millenium only)
 | |
|         {
 | |
|           data.insert("19", 4);
 | |
|           changed = TRUE;
 | |
|         }
 | |
|         for (int meno = 2; meno <= 5; meno += 3)
 | |
|           if (data[meno] != '-')
 | |
|           {
 | |
|             data.insert("-", meno);
 | |
|             changed = TRUE;
 | |
|           }
 | |
|         if (data.len() == 8)      // Fix century (for this millenium only)
 | |
|         {
 | |
|           data.insert("19", 6);
 | |
|           changed = TRUE;
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         TDate g(TODAY);
 | |
|         data.upper();
 | |
|         if (data == "IERI")   --g; else
 | |
|           if (data == "DOMANI") ++g;
 | |
|         TString16 gstring(g.string());
 | |
|         if (data == "PRIMO")  { gstring.overwrite("01-01", 0); } else
 | |
|           if (data == "ULTIMO") { gstring.overwrite("31-12", 0); }
 | |
|         data = gstring;
 | |
|         changed = TRUE;
 | |
|       }
 | |
| 
 | |
|       TDate d(data);
 | |
|       if (!d.ok())
 | |
|       {
 | |
|         //                              error_box("La data deve essere nel formato gg-mm-aaaa");
 | |
|         error_box("Data errata o formato non valido");
 | |
|         return FALSE;
 | |
|       }
 | |
|       else
 | |
|         if (changed)
 | |
|           TMask_field::set_window_data(d.string());
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TEdit_field::on_key(key);
 | |
| }
 | |
| 
 | |
| const char * TDate_field::get_window_data() const
 | |
| {
 | |
|   const char * data = TEdit_field::get_window_data();
 | |
|   if (roman())
 | |
|   {
 | |
|     const TDate d(data);
 | |
|     data = d.string(ANSI);
 | |
|   }
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TDate_field::set_window_data(const char * data)
 | |
| {
 | |
|   if (roman())
 | |
|   {
 | |
|     const TDate d(data);
 | |
|     data = d.string();
 | |
|   }
 | |
|   TEdit_field::set_window_data(data);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Real_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TReal_field::TReal_field(TMask* m) : TEdit_field(m)
 | |
| {}
 | |
| 
 | |
| word TReal_field::class_id() const
 | |
| { return CLASS_REAL_FIELD; }
 | |
| 
 | |
| void TReal_field::create(WINDOW w)
 | |
| {
 | |
|   TEdit_field::create(w);
 | |
| 
 | |
|   if (_flags.firm)
 | |
|     set(::format("%ld", MainApp()->get_firm())); else
 | |
|       if (automagic())
 | |
|       {
 | |
|         TDate d(TODAY);
 | |
|         set(::format("%d", d.year()));
 | |
|       }
 | |
| }
 | |
| 
 | |
| bool TReal_field::on_key(KEY key)
 | |
| {
 | |
|   if (to_check(key))
 | |
|   {
 | |
|     if (roman())
 | |
|     {
 | |
|       const int r = atoi(get_window_data());
 | |
|       if (r < 0) return error_box("Numero romano errato");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const char* n = get();
 | |
|       if (*n && !real::is_real(n))
 | |
|         return error_box("Numero non valido");
 | |
| 
 | |
|       const int segno = real(n).sign();
 | |
|       if (required() && segno == 0 && !mask().query_mode())
 | |
|         return error_box("Manca un valore indispensabile");
 | |
| 
 | |
|       if (_flags.uppercase && segno < 0)
 | |
|         return error_box("Il numero deve essere positivo");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TEdit_field::on_key(key);
 | |
| }
 | |
| 
 | |
| void TReal_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _size  = scanner.integer();
 | |
| 
 | |
| #ifdef DBG      
 | |
|   if (_size < 1)
 | |
|   {
 | |
|     _size = 9;
 | |
|     yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size);
 | |
|   }
 | |
| #endif
 | |
|   
 | |
|   _width = _size;
 | |
|   _decimals = scanner.integer();
 | |
| }
 | |
| 
 | |
| void TReal_field::set_window_data(const char* data)
 | |
| {
 | |
|   if (data == NULL) data = "";
 | |
| 
 | |
|   if (roman())
 | |
|   {
 | |
|     data = itor(atoi(data));
 | |
|     TMask_field::set_window_data(data);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     real n(data);
 | |
|     if (!n.is_zero())
 | |
|     {
 | |
|       if (_flags.exchange)
 | |
|       {
 | |
|         const real& e = mask().exchange();
 | |
|         if (e != 1.0) n /= e;
 | |
|       }
 | |
|       if (_picture.empty())
 | |
|         data = n.stringa(_size, _decimals);
 | |
|       else
 | |
|         data = n.string(_picture);
 | |
|     } else data = "";
 | |
|     TEdit_field::set_window_data(data);
 | |
|   }
 | |
| }
 | |
| 
 | |
| const char* TReal_field::get_window_data() const
 | |
| {
 | |
|   TEdit_field::get_window_data();
 | |
|   if (roman())
 | |
|   {
 | |
|     int r = atoi(fpark);
 | |
|     if (r == 0) r = rtoi(fpark);
 | |
|     if (r > 0)
 | |
|     {
 | |
|       int s = decimals();
 | |
|       if (s < 1) s = 4;
 | |
|       if (_flags.zerofilled)
 | |
|         fpark.format("%0*d", s, r);
 | |
|       else
 | |
|         fpark.format("%*d", s, r);
 | |
|     }
 | |
|     else fpark.cut(0);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     fpark = real::ita2eng(fpark);
 | |
|     if (_flags.exchange)
 | |
|     {      
 | |
|       const real& e = mask().exchange();
 | |
|       if (e != 1.0)
 | |
|       {
 | |
|         real n(fpark);
 | |
|         n *= e;
 | |
|         if (n.is_zero()) fpark.cut(0);
 | |
|         else fpark = n.string();
 | |
|       }  
 | |
|     }
 | |
|   }     
 | |
| 
 | |
|   return fpark;
 | |
| }
 | |
| 
 | |
| void TReal_field::set_decimals(int d) 
 | |
| { 
 | |
|   _decimals = d; 
 | |
|   if (_picture[0] == '.')
 | |
|   {
 | |
|     if (d > 0) _picture.format(".%d", d);
 | |
|     else _picture = ".";
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TReal_field::exchange(const real& vec, const real& nuo)
 | |
| {                                
 | |
|   const int dec = (nuo != 1.0) ? 2 : 0;
 | |
|   
 | |
|   if (decimals() != dec) 
 | |
|     set_decimals(dec);
 | |
|   else  
 | |
|     if (dec == 2) 
 | |
|       return;
 | |
|   
 | |
|   if (mask().is_running())
 | |
|   {
 | |
|     const char* n = real::ita2eng(TEdit_field::get_window_data());
 | |
|     if (*n)
 | |
|     {
 | |
|       real r(n); 
 | |
|       r *= vec;
 | |
|       r /= nuo;
 | |
|       r.round(dec);
 | |
|       TEdit_field::set_window_data(r.string(_picture));
 | |
|     }  
 | |
|   }  
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // List_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TList_field::TList_field(TMask* m) : TMask_field(m)
 | |
| {}
 | |
| 
 | |
| word TList_field::class_id() const
 | |
| {
 | |
|   return CLASS_LIST_FIELD;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::read_item(TScanner& scanner)
 | |
| {
 | |
|   TToken_string ts(scanner.string());
 | |
|   _codes.add(ts.get());
 | |
|   _values.add(ts.get());
 | |
| 
 | |
|   ts = "";
 | |
|   while (scanner.popkey() == "ME")
 | |
|     ts.add(scanner.line().strip_spaces());
 | |
|   scanner.push();
 | |
| 
 | |
|   _message.add(ts);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _size = scanner.integer();
 | |
|   _width = scanner.integer();
 | |
|   if (_width < 1) _width = _size+3;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TList_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "IT")            // ITEM
 | |
|   {
 | |
|     read_item(scanner);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (scanner.key() == "LI")            // LISTITEM
 | |
|   {
 | |
|     TScanner sc(scanner.pop());
 | |
|     while (sc.popkey() == "IT")         // ITEM
 | |
|       read_item(sc);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| 
 | |
| int TList_field::items() const
 | |
| {
 | |
|   return _codes.items();
 | |
| }
 | |
| 
 | |
| void TList_field::add_item(const char* s)
 | |
| {
 | |
|   TToken_string t(s);         
 | |
|   const TString16 item(t.get());
 | |
|   const int pos = _codes.get_pos(item);
 | |
|   
 | |
|   if (pos < 0 )
 | |
|   {                                         
 | |
|     _codes.add(item);
 | |
|     win_list_add(win(), -1, (char*)t.get());
 | |
|   }     
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::delete_item(const char* s)
 | |
| {
 | |
|   TString16 t(s);         
 | |
|   const int pos = _codes.get_pos(t);
 | |
|   
 | |
|   if (pos >= 0 )
 | |
|   {                                         
 | |
|     _codes.destroy(pos);
 | |
|     win_list_delete(win(), pos);
 | |
|     if (mask().is_running())
 | |
|     {
 | |
|       win_list_set_sel(win(), 0, TRUE);
 | |
|       if (showed())     on_hit();
 | |
|     }
 | |
|   }     
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::add_list()
 | |
| {
 | |
|   if (roman() && _codes.items() < 12)
 | |
|   {
 | |
|     TString csafe, vsafe;
 | |
|     if (atoi(_codes) > 0)
 | |
|     {
 | |
|       csafe = _codes; _codes = "";
 | |
|       vsafe = _values; _values = "";
 | |
|     }
 | |
|     _codes.add("01|02|03|04|05|06|07|08|09|10|11|12");
 | |
|     _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno");
 | |
|     _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre");
 | |
|     if (atoi(csafe) > 0)
 | |
|     {
 | |
|       _codes.add(csafe);
 | |
|       _values.add(vsafe);
 | |
|       if (_message.objptr(0))
 | |
|       {
 | |
|         _message.add(_message[0], _codes.items()-1);
 | |
|         _message.add(NULL, 0);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   SLIST lst = slist_new();
 | |
|   for (const char* item = _values.get(0); item; item = _values.get())
 | |
|     slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L);
 | |
|   win_list_add(win(), -1, (char*)lst);
 | |
|   slist_dispose(lst);
 | |
| 
 | |
|   const char* init = "";
 | |
|   if (roman() && automagic())
 | |
|     init = format("%02d", TDate(TODAY).month());
 | |
|   set_field_data(init);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::replace_items(const char* codes, const char* values)
 | |
| {
 | |
|   _codes = codes;
 | |
|   _values = values;
 | |
| 
 | |
|   if (win() != NULL_WIN)
 | |
|   {
 | |
|     win_list_clear(win());
 | |
|     add_list();
 | |
|     current(0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::create(WINDOW parent)
 | |
| {
 | |
|   const int len = create_prompt(parent);
 | |
|   _x += len;
 | |
| 
 | |
|   wincreate(WC_LISTBUTTON, _width, 5, "", parent,0);
 | |
|   add_list();
 | |
| }
 | |
| 
 | |
| 
 | |
| int TList_field::str2curr(const char* data)
 | |
| {
 | |
|   TString16 str(data);
 | |
| 
 | |
|   if (roman() && str.len() < 2)
 | |
|     str.insert("0",0);
 | |
|   if (_flags.uppercase)
 | |
|     str.upper();        
 | |
| 
 | |
|   int i = str.not_empty() ? _codes.get_pos(str) : 0;
 | |
| 
 | |
|   if (i < 0)      // Se non trova il codice ritenta dopo trim
 | |
|   {
 | |
|     for (i = 0; str[i] == '0' || str[i] == ' '; i++);
 | |
|     if (i > 0)
 | |
|     {
 | |
|       str.ltrim(i);
 | |
|       i = _codes.get_pos(str);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (i < 0)
 | |
|   {
 | |
|     if (items() && str.not_empty())
 | |
|       yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d",
 | |
|                      data, prompt(), dlg());
 | |
|     i = 0;
 | |
|   }
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::set_window_data(const char* data)
 | |
| {
 | |
|   CHECKD(win(), "Control window not initialized ", dlg());
 | |
|   const int i = str2curr(data);
 | |
|   current(i);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TList_field::current(int n)
 | |
| {
 | |
|   win_list_set_sel(win(), n, TRUE);
 | |
| }
 | |
| 
 | |
| int TList_field::current() const
 | |
| {
 | |
|   const int sel = win_list_get_sel_index(win());
 | |
| #ifdef DBG
 | |
|   if (sel < 0 && items() > 0)
 | |
|     error_box("Lista senza selezione nel campo %d", dlg());
 | |
| #endif
 | |
|   return sel;
 | |
| }
 | |
| 
 | |
| const char* TList_field::get_window_data() const
 | |
| {                                    
 | |
|   const int c = current();
 | |
|   const char* v = ((TList_field*)this)->_codes.get(c);
 | |
|   return v;
 | |
| }
 | |
| 
 | |
| void TList_field::set_field_data(const char* data)
 | |
| {
 | |
|   if (data == NULL || *data == '\0') data = _codes.get(0);
 | |
|   _str = data;
 | |
| }
 | |
| 
 | |
| bool TList_field::on_hit()
 | |
| {
 | |
|   if (_handler)
 | |
|   {
 | |
|     bool ok = _handler(*this, K_SPACE);
 | |
|     if (!ok) return FALSE;
 | |
|   }
 | |
|   const int n = mask().is_running() ? current() : str2curr(_str);
 | |
|   do_message(n);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| const char* TList_field::get_field_data() const
 | |
| {
 | |
|   return _str;
 | |
| }
 | |
| 
 | |
| bool TList_field::on_key(KEY key)
 | |
| {
 | |
|   if (key >= '0' && key <= 'z')
 | |
|   {
 | |
|     const int index = win_list_get_sel_index(win());
 | |
|     CHECK(index >= 0, "List with no selection!");
 | |
|     int newindex = -1;
 | |
| 
 | |
| #if XVTWS == WMWS
 | |
|     if (key >= 'A' && key <= 'z')
 | |
|     {
 | |
|       for (int i = index+1; i != index; i++)
 | |
|       {
 | |
|         char item[16];
 | |
|         bool flag;
 | |
| 
 | |
|         do
 | |
|         {
 | |
|           flag = win_list_get_elt(win(), i, item, 16);
 | |
|           if (!flag)
 | |
|           {
 | |
|             CHECK(i, "La lista e' vuota!");
 | |
|             i = -1;
 | |
|             break;
 | |
|           }
 | |
|         } while (!flag);
 | |
|         if (flag && toupper(*item) == toupper(key))
 | |
|         {
 | |
|           newindex = i;
 | |
|           break;
 | |
|         }
 | |
|       } // for
 | |
|     } // alphabetic
 | |
| #endif
 | |
| 
 | |
|     if (key >= '0' && key <= '9')
 | |
|     {
 | |
|       newindex = (key == '0') ? 10 : key - '1';
 | |
|       if (newindex > items())
 | |
|       {
 | |
|         newindex = -1;
 | |
|         beep();
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (newindex >= 0)
 | |
|     {
 | |
|       win_list_suspend(win());
 | |
|       win_list_set_sel(win(), index, FALSE);
 | |
|       win_list_set_sel(win(), newindex, TRUE);
 | |
|       win_list_resume(win());
 | |
|     }
 | |
|   } // alphanumeric
 | |
| 
 | |
| #if XVTWS == VMWS
 | |
|   if (key == K_TAB && class_id() == CLASS_LIST_FIELD)
 | |
|     dispacth_e_char(win(), K_F9);
 | |
| #endif
 | |
| 
 | |
|   if (key == K_SPACE) on_hit();
 | |
| 
 | |
|   return TMask_field::on_key(key);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRadio_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TRadio_field::TRadio_field(TMask* mask)
 | |
| : TList_field(mask), _nitems(0), _active_item(0)
 | |
| {}
 | |
| 
 | |
| 
 | |
| word TRadio_field::class_id() const
 | |
| {
 | |
|   return CLASS_RADIO_FIELD;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::create(WINDOW parent)
 | |
| {
 | |
|   const short id = dlg();     // Salva il control id
 | |
|   const int items = _codes.items();
 | |
| 
 | |
|   if (_prompt.not_empty())
 | |
|   {
 | |
|     const int dy = _flags.persistent ? 3 : items+2;
 | |
|     create_prompt(parent, _width, dy);
 | |
|   }
 | |
|   _x++; _y++;
 | |
|   _values.restart();
 | |
| 
 | |
|   const char* s;
 | |
|   
 | |
|   const int width = _flags.persistent ? (_width-2)/items-1 : _width-2;
 | |
|   for(_nitems = 0; (s = _values.get()) != NULL; _nitems++)
 | |
|   {
 | |
|     CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id);
 | |
| 
 | |
|     wincreate(WC_RADIOBUTTON, width, 1, s, parent,0);
 | |
|     _radio_ctl_win[_nitems] = _win;
 | |
|     _dlg += 1000;
 | |
|     
 | |
|     if (_flags.persistent)
 | |
|       _x += width+1;
 | |
|     else
 | |
|       _y++;
 | |
|   }
 | |
|   _radio_ctl_win[_nitems] = NULL_WIN;   // Comodo per debug
 | |
| 
 | |
|   _dlg = id;  // Ripristina control id
 | |
| 
 | |
|   set_field_data("");
 | |
| }
 | |
| 
 | |
| void TRadio_field::destroy()
 | |
| {
 | |
|   if (_promptwin)
 | |
|   {     close_window(_promptwin); _promptwin = NULL_WIN; }
 | |
| 
 | |
|   for(int i = 0; i < _nitems; i++)
 | |
|   {
 | |
|     close_window(_radio_ctl_win[i]);
 | |
|     _radio_ctl_win[i] = NULL_WIN;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRadio_field::current() const
 | |
| {
 | |
|   const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems);
 | |
|   return c;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::current(int n)
 | |
| {
 | |
|   _active_item = n;
 | |
|   xvt_check_radio_button(win(), _radio_ctl_win, _nitems);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::check_radiobutton(WINDOW checked)
 | |
| {
 | |
|   for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++);
 | |
|   CHECK(i < _nitems, "Trying to check an invalid radio button");
 | |
|   current(i);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::enable(bool on)
 | |
| {
 | |
|   _flags.enabled = on;
 | |
|   for(int i = 0; i < _nitems; i++)
 | |
|     xvt_enable_control(_radio_ctl_win[i], on);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRadio_field::show(bool on)
 | |
| {
 | |
|   if (_promptwin)
 | |
|     show_window(_promptwin, on);
 | |
| 
 | |
|   for(int i = 0; i < _nitems; i++)
 | |
|     show_window(_radio_ctl_win[i], on);
 | |
|   _flags.showed = on;
 | |
| }
 | |
| 
 | |
| // Return TRUE if focus has left the radio
 | |
| bool TRadio_field::move_focus(int d)
 | |
| {
 | |
|   const int act = _active_item + d;
 | |
|   if (act >= _nitems || act < 0)
 | |
|   {
 | |
|     _active_item = current();
 | |
|     return TRUE;
 | |
|   }
 | |
|   xvt_set_front_control(_radio_ctl_win[_active_item = act]);
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TGroup_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask)
 | |
| {
 | |
|   _flags.persistent = TRUE;
 | |
| }
 | |
| 
 | |
| // _size means _heigth
 | |
| void TGroup_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _width = scanner.integer();
 | |
|   _size  = scanner.integer();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TGroup_field::create(WINDOW parent)
 | |
| {
 | |
|   const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0;
 | |
|   wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f);
 | |
| }
 | |
| 
 |