1418 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1418 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <msksheet.h>
 | |
| #include <real.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h>
 | |
| 
 | |
| const short FIRST_FIELD = 101;
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
| 
 | |
| #include <xil.h>
 | |
| #include <colors.h>
 | |
| 
 | |
| extern "C"
 | |
| {
 | |
| #include <cpb.h>
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSpreadsheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TSpreadsheet : public TWindow
 | |
| {
 | |
|   friend class TSheet_field;
 | |
| 
 | |
|   enum { ITF_CID = 0, LIST_CID = 1 };
 | |
| 
 | |
|   TString_array _str;         // Array di TToken_strings
 | |
|   TBit_array _column_disabled;
 | |
|   TArray _disabled;           // Array di TBit_array
 | |
| 
 | |
|   TMask _mask;
 | |
|   int _columns;
 | |
|   bool _firstfocus, _active;
 | |
| 
 | |
|   XI_OBJ *_list, *_itf;
 | |
| 
 | |
|   SPREADSHEET_NOTIFY _notify;
 | |
|   
 | |
|   TSheet_field* _owner;          // Owner
 | |
|   
 | |
|   TMask_field* _edit_field;      // Current edit field
 | |
|   int _cur_row, _cur_rec, _cur_col;      // Current cell
 | |
|   bool _row_dirty;               // Current row changed
 | |
|   bool _check_enabled;           // Perform OFF_ROW and OFF_CELL checks
 | |
|   bool _update;                  // It's safe to update the display
 | |
|   
 | |
|   TString16 _button;
 | |
| 
 | |
|   static void xiev_handler(XI_OBJ *itf, XI_EVENT *xiev);
 | |
|   void init();
 | |
| 
 | |
| protected:
 | |
|   void list_handler(XI_EVENT *xiev);
 | |
| 
 | |
|   TMask_field* col2field(int pos) const;
 | |
|   TMask_field* cell2field(const XI_OBJ* cell) const;
 | |
|   void update_rec(int rec);
 | |
|   TMask_field* field(short id) const;
 | |
| 
 | |
|   int rec2row(int rec);
 | |
|   int row2rec(int& row);
 | |
|   int set_pos(int row, int col) { _cur_col = col; _cur_row = row; return _cur_rec = row2rec(_cur_row); }
 | |
| 
 | |
|   bool notify(int row, KEY k);
 | |
|   void notify_change();
 | |
| 
 | |
| public:
 | |
|   void update(int row);
 | |
| 
 | |
|   TToken_string& row(int n) { return _str.row(n); }
 | |
|   int add(const TToken_string& s) { return _str.add(s); }
 | |
|   int add(TToken_string* s) { return _str.add(s); }
 | |
|   int insert(int rec);
 | |
|   bool destroy(int rec = -1);
 | |
|   TString_array& rows_array() { return _str; }
 | |
| 
 | |
|   void set_focus_cell(int riga, int colonna);
 | |
|   void activate(bool on);
 | |
|   void enable_column(int col, bool on = TRUE);
 | |
|   void enable_cell(int row, int column, bool on = TRUE);
 | |
|   bool cell_disabled(int row, int column) const;
 | |
| 
 | |
|   TMask& sheet_mask() { return _mask; }
 | |
|   TMask& mask() const;
 | |
|   
 | |
|   void mask2str(int n);
 | |
|   void str2mask(int n);
 | |
|   KEY edit(int n);
 | |
|   
 | |
|   int items() const { return _str.items(); }
 | |
|   int selected() const { return _cur_rec; }
 | |
|   int columns() const { return _columns; }
 | |
| 
 | |
|   bool dirty() const { return _owner->dirty(); }
 | |
|   void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork); }
 | |
|   
 | |
|   bool active() const { return _active; }
 | |
|   bool test_focus_change();
 | |
| 
 | |
|   void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; }
 | |
| 
 | |
|   TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno,
 | |
|                const char* head, WINDOW parent, TSheet_field* owner);
 | |
|   virtual ~TSpreadsheet();
 | |
| };
 | |
| 
 | |
| // Certified 100%
 | |
| void TSpreadsheet::init()
 | |
| {
 | |
|   static bool first = TRUE;
 | |
|   if (!first) return;
 | |
| 
 | |
|   DRAW_CTOOLS ct;
 | |
|   win_get_draw_ctools(TASK_WIN, &ct);
 | |
|   xi_set_font(&ct.font);
 | |
| 
 | |
|   xi_init();
 | |
|   xi_set_pref(XI_PREF_3D_LOOK, TRUE);
 | |
|   first = FALSE;
 | |
| }                             
 | |
| 
 | |
| 
 | |
| TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy,
 | |
|                            const char* maskname, int maskno,
 | |
|                            const char* head, WINDOW parent, 
 | |
|                            TSheet_field* o)
 | |
| : _mask(maskname, maskno), _notify(NULL), _edit_field(NULL), 
 | |
|   _owner(o), _cur_row(0), _cur_col(0), _active(TRUE),
 | |
|   _row_dirty(FALSE), _check_enabled(TRUE), _firstfocus(TRUE), _update(TRUE)
 | |
| {
 | |
|   const int NUMBER_WIDTH = 3;
 | |
|   const int MAX_COL = 32;
 | |
|   int m_width[MAX_COL], v_width[MAX_COL];
 | |
|   int fixed_columns = 1;                               // Number of fixed columns
 | |
| 
 | |
|   init();
 | |
| 
 | |
|   // Calcolo larghezza massima tabella
 | |
| 
 | |
|   TToken_string header(head);
 | |
|   TToken_string new_header(256);
 | |
|   int i = 0, tot_width = NUMBER_WIDTH+1;
 | |
|   int f_width = tot_width<<1;                          // Stima larghezza colonne fisse
 | |
|   int max_width = f_width;                             // Stima larghezza della colonna piu' grande
 | |
|   
 | |
|   for (const char* h = header.get(); h; h = header.get(), i++)
 | |
|   {
 | |
|     CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i);
 | |
| 
 | |
|     const int cid = FIRST_FIELD+i;                    // Column & Field ID
 | |
|     const TMask_field* f = field(cid);                // Field on mask
 | |
|     CHECKD(f, "The spreadsheet mask needs ALSO field ", cid);
 | |
| 
 | |
|     TString80 testa(h);
 | |
|     const int at = testa.find('@');
 | |
|     int m, v;
 | |
|     if (at >= 0)
 | |
|     {
 | |
|       const TString& wi = testa.mid(at+1);
 | |
|       m = atoi(wi);
 | |
|       if (wi.find('F') >= 0) 
 | |
|       {
 | |
|         fixed_columns++;
 | |
|         f_width += m+1;
 | |
|       }  
 | |
|       testa.cut(at);
 | |
|       v = max(at, m+(f->has_query() ? 1 : 0));
 | |
|     } 
 | |
|     else 
 | |
|     {
 | |
|       m = testa.len();
 | |
|       v = m+(f->has_query() ? 1 : 0);
 | |
|     }
 | |
|     
 | |
|     m_width[i] = m+1;                                 // m = number of allowed chars
 | |
|     v_width[i] = v+1;                                 // v = width of column
 | |
|     if (v >= max_width) max_width = v+1;
 | |
|     
 | |
|     tot_width += v_width[i];
 | |
|     
 | |
|     new_header.add(testa);
 | |
|   }
 | |
|   _columns = i;
 | |
|   
 | |
|   if (x < 0) x = 0; 
 | |
|   if (y < 0) y = 0;
 | |
|   if (dx == 0) 
 | |
|   {
 | |
|     dx = tot_width;                  
 | |
|     if (dx > 76) dx = -x;
 | |
|   }  
 | |
|   
 | |
|   RCT rct = resize_rect(x, y, dx, dy, WO_TE, parent);
 | |
|   rct.bottom -= 12;
 | |
|   rct.right  -= 28;
 | |
|   
 | |
|   if ((f_width+max_width)*CHARX > rct.right)
 | |
|     fixed_columns = 1;
 | |
| 
 | |
|   XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID,
 | |
|                                          (XI_EVENT_HANDLER)xiev_handler, &rct, (char*)maskname,
 | |
|                                          PTR_LONG(this));
 | |
|   itfdef->v.itf->automatic_back_color = FALSE;
 | |
|   itfdef->v.itf->back_color = MASK_BACK_COLOR;
 | |
| 
 | |
|   XI_OBJ_DEF* listdef = xi_add_list_def(itfdef, LIST_CID,
 | |
|                                         0, 0, rct.bottom-rct.top,
 | |
|                                         XI_ATR_ENABLED | XI_ATR_VISIBLE,
 | |
|                                         NORMAL_COLOR, NORMAL_BACK_COLOR,    // normal
 | |
|                                         NORMAL_COLOR, DISABLED_BACK_COLOR,  // disabled
 | |
|                                         COLOR_RED,                          // active
 | |
|                                         LIST_CID);
 | |
|   listdef->v.list->sizable_columns = TRUE;
 | |
|   listdef->v.list->movable_columns = TRUE;
 | |
|   listdef->v.list->scroll_bar = TRUE;
 | |
|   listdef->v.list->scroll_bar_button = TRUE;
 | |
|   listdef->v.list->fixed_columns = fixed_columns;
 | |
|   listdef->v.list->width = rct.right-rct.left;
 | |
|   listdef->v.list->min_cell_height = CHARY;
 | |
|   listdef->v.list->min_heading_height = CHARY;
 | |
|   listdef->v.list->white_space_color = MASK_DARK_COLOR;
 | |
| 
 | |
|   XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0,
 | |
|                                          XI_ATR_RJUST, 0, NUMBER_WIDTH, NUMBER_WIDTH, "");
 | |
|   coldef->v.column->heading_platform = TRUE;
 | |
|   coldef->v.column->column_platform = TRUE;
 | |
|   coldef->v.column->center_heading = TRUE;
 | |
| 
 | |
|   for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++)
 | |
|   {                  
 | |
|     const TString80 testo(h);
 | |
|     const int cid = FIRST_FIELD+i;                     // Column & Field ID
 | |
|     const TMask_field* f = field(cid);                 // Field on mask
 | |
|     const int acqua = f->class_id();
 | |
| 
 | |
|     long flags =  XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL;
 | |
|     switch (acqua)
 | |
|     {
 | |
|     case CLASS_REAL_FIELD:
 | |
|       flags |= XI_ATR_RJUST; break;
 | |
|     case CLASS_BUTTON_FIELD:
 | |
|       flags |= XI_ATR_SELECTABLE; break;
 | |
|     default:
 | |
|       break;
 | |
|     }      
 | |
|     if (f->active()) flags |= XI_ATR_ENABLED | XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT;
 | |
|     else _column_disabled.set(i);
 | |
| 
 | |
|     coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i], m_width[i], 
 | |
|                                (char*)(const char*)testo);
 | |
|     coldef->v.column->heading_platform = TRUE;
 | |
|     coldef->v.column->center_heading = TRUE;
 | |
|     if (acqua == CLASS_BUTTON_FIELD)
 | |
|     {
 | |
|       const TFixed_string testa(header.get(i));
 | |
|       const int diesis = testa.find('#');
 | |
|       if (diesis > 0) 
 | |
|       {
 | |
|         _button = testa.mid(diesis+1);
 | |
|         coldef->v.column->icon_x = (v_width[i]*CHARX-16) >> 1;
 | |
|         coldef->v.column->icon_y = (CHARY-16) >> 1;  
 | |
|         coldef->v.column->column_platform = TRUE;
 | |
|       }  
 | |
|       else _button = testo;
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   RCT itfrct;
 | |
|   xi_get_def_rect(itfdef, &itfrct);
 | |
|   offset_rect(&itfrct, rct.left, rct.top);
 | |
|   itfrct.bottom++;
 | |
| 
 | |
|   WINDOW win = create_window(W_NO_BORDER, &itfrct, "", 0, parent,
 | |
|                              0, EM_ALL, (EVENT_HANDLER)xi_event, 0L);
 | |
|   CHECK(win, "Can't create a window for the spreadsheet");
 | |
| 
 | |
|   set_win(win);                                                                 // Set TWindow::_win
 | |
|   itfdef->v.itf->win = win;           // Link interface to win
 | |
| 
 | |
|   xi_create(NULL, itfdef);            // Create the whole thing!
 | |
|   xi_tree_free(itfdef);               // Free definitions
 | |
| 
 | |
|   _itf  = xi_get_itf(win);            // Store useful references for later use
 | |
|   _list = xi_get_obj(_itf, LIST_CID);
 | |
| }
 | |
| 
 | |
| TSpreadsheet::~TSpreadsheet() 
 | |
| {                    
 | |
|   set_win(NULL_WIN); 
 | |
| }             
 | |
| 
 | |
| 
 | |
| // Converts a row number in the correspondig record number
 | |
| int TSpreadsheet::row2rec(int& row)
 | |
| {
 | |
|   int rows;
 | |
|   const long* rec = xi_get_list_info(_list, &rows);
 | |
|   
 | |
|   int r = -1;
 | |
|   if (row < 0) 
 | |
|   {
 | |
|     row = 0;
 | |
|     r = (int)rec[row]-1; 
 | |
|   }  
 | |
|   else 
 | |
|     if (row >= rows) 
 | |
|     { 
 | |
|       row = rows-1;
 | |
|       r = (int)rec[row]+1; 
 | |
|     }  
 | |
|     else 
 | |
|       r = (int)rec[row];
 | |
|   
 | |
|   CHECKD(r >= 0 && r <= items(), "Sheet line out of range: ", row);
 | |
| 
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Converts a row number in the correspondig record number
 | |
| int TSpreadsheet::rec2row(int record)
 | |
| {
 | |
|   int rows;
 | |
|   const long* rec = xi_get_list_info(_list, &rows);
 | |
|   int r = int(record - rec[0]);
 | |
|   if (r < 0 || r >= rows) 
 | |
|     r = -1;
 | |
|   
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Retrieves the corresponding field of the mask from a spredsheet cell
 | |
| TMask_field* TSpreadsheet::col2field(int pos) const
 | |
| {
 | |
|   int num;
 | |
|   XI_OBJ** column = xi_get_member_list(_list, &num);
 | |
| 
 | |
|   TMask_field* good = NULL;
 | |
|   for (short id = column[pos]->cid; ; id += 100)
 | |
|   {
 | |
|     TMask_field* f = field(id);
 | |
|     if (f == NULL) break;             // End of search
 | |
|     good = f;                         // We've found a field with the proper ID ...
 | |
|     if (f->active()) break;           // ... and it's active: end of search
 | |
|   }
 | |
| 
 | |
|   CHECKD(good, "Can't find field corresponding to column ", pos);
 | |
|   return good;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Retrieves the corresponding field of the mask from a spredsheet cell
 | |
| TMask_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const
 | |
| {
 | |
|   return col2field(cell->v.cell.column);
 | |
| }
 | |
| 
 | |
| void TSpreadsheet::update_rec(int rec)
 | |
| {                 
 | |
|   const int riga = rec2row(rec);
 | |
|   if (riga >= 0)
 | |
|   {
 | |
|     XI_OBJ row;
 | |
|     XI_MAKE_ROW(&row, _list, riga);
 | |
|     xi_cell_request(&row);            // Update internal values
 | |
|     xi_set_row_height(&row, CHARY+1); // Force row updating
 | |
|   }  
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSpreadsheet::set_focus_cell(int riga, int colonna)
 | |
| {                 
 | |
|   set_front_window(win());    // It seems necessary
 | |
| 
 | |
|   const int r = row2rec(riga);   
 | |
|   
 | |
|   for (; colonna < _columns; colonna++)
 | |
|     if (!cell_disabled(r, colonna-1))
 | |
|       break;
 | |
|   
 | |
|   if (colonna < _columns)
 | |
|   {          
 | |
|     XI_OBJ cell;     
 | |
|     XI_MAKE_CELL(&cell, _list, riga, colonna);
 | |
|     xi_set_focus(&cell);          
 | |
|     
 | |
|     if (_edit_field == NULL)
 | |
|     {
 | |
|       _cur_row = riga;
 | |
|       _cur_col = colonna;
 | |
|       _cur_rec = r;
 | |
|       _edit_field = col2field(colonna);
 | |
|       str2mask(_cur_rec);
 | |
|       _row_dirty = FALSE;
 | |
|     }  
 | |
|   } 
 | |
| }
 | |
| 
 | |
| 
 | |
| int TSpreadsheet::insert(int rec)
 | |
| {
 | |
|   const bool ok = notify(rec, K_INS);
 | |
|   if (!ok) return -1;
 | |
| 
 | |
|   TToken_string s(80);                    // Empty row
 | |
|   const int r = _str.insert(s, rec);
 | |
|   _disabled.insert(NULL, rec);
 | |
| 
 | |
|   xi_insert_row(_list, INT_MAX);
 | |
|   xi_cell_request(_list);
 | |
| 
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TSpreadsheet::destroy(int rec)
 | |
| {   
 | |
|   bool ok = TRUE;
 | |
|   
 | |
|   if (rec < 0)
 | |
|   {
 | |
|     _disabled.destroy();
 | |
|     _str.destroy();
 | |
|     set_dirty(_row_dirty = FALSE);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     _disabled.destroy(rec, TRUE);       // Destroy enable info
 | |
|     ok = _str.destroy(rec, TRUE);       // Destroy line
 | |
|     enable_cell(_str.items(), -1);      // Enable last line
 | |
|   }  
 | |
| 
 | |
|   if (ok && mask().is_running()) 
 | |
|     update(-1);
 | |
|   
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSpreadsheet::update(int row)
 | |
| {                        
 | |
|   if (_update)
 | |
|   {
 | |
|     if (row < 0)
 | |
|     {                 
 | |
|       xi_cell_request(_list);                 // Force updatde
 | |
|       xi_scroll(_list, XI_SCROLL_FIRST);
 | |
|     }
 | |
|     else
 | |
|       update_rec(row);  
 | |
|   }    
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSpreadsheet::notify_change()
 | |
| {
 | |
|   if (!_row_dirty)
 | |
|   {
 | |
|     notify(_cur_rec, K_SPACE);
 | |
|     _row_dirty = TRUE;
 | |
|     set_dirty();
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TSpreadsheet::test_focus_change()
 | |
| {
 | |
|   bool ok = dirty() != 3;
 | |
|   if (ok && _row_dirty)   
 | |
|   {               
 | |
|     str2mask(selected());
 | |
|     ok = sheet_mask().check_fields();                           
 | |
|   }  
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev)
 | |
| {
 | |
|   TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf);
 | |
|   CHECK(es, "NULL Edit sheet in xi event");
 | |
|   es->list_handler(xiev);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 75%
 | |
| void TSpreadsheet::list_handler(XI_EVENT *xiev)
 | |
| {
 | |
|   static KEY _lastab = K_TAB;
 | |
|   static bool _cell_dirty;
 | |
| 
 | |
|   switch (xiev->type)
 | |
|   {
 | |
|   case XIE_GET_FIRST:
 | |
|     if (items() > 0L)
 | |
|     {
 | |
|       long n = items() * (long)xiev->v.rec_request.percent / 100L;
 | |
|       if (n < 0L) n = 0L;
 | |
|       xiev->v.rec_request.data_rec = n;
 | |
|     }
 | |
|     else
 | |
|       xiev->refused = TRUE;
 | |
|     break;
 | |
|   case XIE_GET_LAST:
 | |
|     xiev->v.rec_request.data_rec = items()-1;
 | |
|     break;
 | |
|   case XIE_GET_PREV:
 | |
|   case XIE_GET_NEXT:
 | |
|   {
 | |
|     const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ;
 | |
|     if (n < 0 || n >= items())
 | |
|       xiev->refused = TRUE;
 | |
|     else
 | |
|       xiev->v.rec_request.data_rec = n;
 | |
|   }
 | |
|     break;
 | |
|   case XIE_CELL_REQUEST:
 | |
|   {
 | |
|     const int rec = (int)xiev->v.cell_request.rec;
 | |
|     const char* src = NULL;
 | |
|     int nm;
 | |
|     XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm);
 | |
|     const int num = xiev->v.cell_request.col_nbr;
 | |
|     const int cid = obj[num]->cid;
 | |
| 
 | |
|     if (cid >= FIRST_FIELD)
 | |
|     {
 | |
|       if (rec < items())
 | |
|       {   
 | |
|         const int col = cid - FIRST_FIELD;
 | |
|         TMask_field* f = field(cid);
 | |
|         const int acqua = f->class_id();
 | |
|         
 | |
|         if (acqua == CLASS_BUTTON_FIELD)
 | |
|         {                                 
 | |
|           if (isdigit(_button[0]))
 | |
|             xiev->v.cell_request.icon_rid = atoi(_button);
 | |
|           else  
 | |
|             src = _button;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           src = row(rec).get(col);                  // Set value for cell
 | |
|           if (src && *src && f->is_edit())
 | |
|           {
 | |
|             src = f->picture_data(src, FALSE);      // Get formatted string
 | |
|           }
 | |
|           if (field(cid)->has_query())
 | |
|           {
 | |
|             xiev->v.cell_request.button = TRUE;
 | |
|             xiev->v.cell_request.button_on_focus = TRUE;
 | |
|           }
 | |
|           if (cell_disabled(rec, col))
 | |
|             xiev->v.cell_request.back_color = DISABLED_BACK_COLOR;
 | |
|         }
 | |
|       }  
 | |
|     } else src = format("%d", rec+1);
 | |
| 
 | |
|     char* dst = xiev->v.cell_request.s;
 | |
|     if (src && *src)
 | |
|     {
 | |
|       const int len = xiev->v.cell_request.len;
 | |
|       strncpy(dst, src, len);
 | |
|     }  
 | |
|     else
 | |
|       *dst = '\0';
 | |
|   }
 | |
|     break;
 | |
|   case XIE_CHG_CELL:
 | |
|     if (_edit_field)
 | |
|     {
 | |
|       notify_change();
 | |
|       _edit_field->set_focusdirty(_cell_dirty = TRUE);
 | |
|     }  
 | |
|     break;
 | |
|   case XIE_BUTTON:
 | |
|     if (xiev->v.xi_obj->type == XIT_CELL)
 | |
|       dispatch_e_char(win(), K_F9);
 | |
|     else
 | |
|       if (xiev->v.xi_obj->type == XIT_LIST)
 | |
|         insert(-1);
 | |
|     break;
 | |
|   case XIE_SELECT:
 | |
|     if (xiev->v.xi_obj->type == XIT_ROW)
 | |
|     {    
 | |
|       _check_enabled = FALSE;    
 | |
|       
 | |
|       const int oldrec = _cur_rec;
 | |
|       set_pos(xiev->v.select.xi_obj->v.row, xiev->v.select.column);
 | |
|       if (oldrec != _cur_rec)
 | |
|       {                        
 | |
|         str2mask(_cur_rec);
 | |
|         _row_dirty = FALSE;
 | |
|       }   
 | |
|       
 | |
|       update(_cur_rec);
 | |
|       
 | |
|       TMask_field* button = col2field(_cur_col);
 | |
|       notify_change();
 | |
|       button->on_hit();
 | |
|       mask2str(_cur_rec);
 | |
|       
 | |
|       _check_enabled = TRUE;    
 | |
|     }    
 | |
|     xiev->refused = TRUE;
 | |
|     break;
 | |
|   case XIE_DBL_CELL:
 | |
|   {
 | |
|     _check_enabled = FALSE;
 | |
|     
 | |
|     const int oldrec = _cur_rec;
 | |
|     set_pos(xiev->v.xi_obj->v.cell.row, xiev->v.xi_obj->v.cell.column);
 | |
|     
 | |
|     if (oldrec != _cur_rec || !_row_dirty)
 | |
|     {
 | |
|       _row_dirty = FALSE;
 | |
|       notify_change();
 | |
|     }
 | |
|     const KEY k = edit(_cur_rec);
 | |
|     if (k == K_ENTER)
 | |
|     {
 | |
|       update_rec(_cur_rec);
 | |
|       _row_dirty = TRUE;
 | |
|     } else
 | |
|       if (k == K_DEL)
 | |
|         _row_dirty = _cell_dirty = FALSE;
 | |
| 
 | |
|     if (!cell_disabled(_cur_rec, _cur_col-1))
 | |
|       set_focus_cell(_cur_row, _cur_col);
 | |
|     _check_enabled = TRUE;
 | |
|   }
 | |
|     break;
 | |
|   case XIE_ON_LIST:
 | |
|     if (_firstfocus)         // Trick to avoid the sheet to keep the focus forever ...
 | |
|     {                         // .. it costed me two day worth of hard work!
 | |
|       xiev->refused = TRUE;
 | |
|       _firstfocus = FALSE;
 | |
|     } 
 | |
|     else 
 | |
|       mask().set_focus_win(win(), FALSE);
 | |
|     break;
 | |
|   case XIE_OFF_LIST:
 | |
|     break;
 | |
|   case XIE_ON_ROW:
 | |
|     if (_check_enabled)
 | |
|     {
 | |
|       set_pos(xiev->v.xi_obj->v.row, _cur_col);
 | |
|       if (_cur_rec < items())
 | |
|       {
 | |
|         str2mask(_cur_rec);
 | |
|         _row_dirty = FALSE;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         _cur_row = _cur_rec = 0;
 | |
|         xiev->refused = TRUE;
 | |
|       }  
 | |
|     }
 | |
|     break;
 | |
|   case XIE_OFF_ROW:
 | |
|     if (_row_dirty && _check_enabled)
 | |
|     {
 | |
|       _check_enabled = FALSE;                 // Avoid recursion!
 | |
|       str2mask(_cur_rec);                     // It shouldn't have to be necessary
 | |
|       bool ok = sheet_mask().check_fields();
 | |
|       if (ok) 
 | |
|       { 
 | |
|         _update = FALSE;
 | |
|         mask2str(_cur_rec);               
 | |
|         ok = notify(_cur_rec, K_ENTER);       // Notify edit
 | |
|         _update = TRUE;
 | |
|       } 
 | |
|       if (!ok)
 | |
|         xiev->refused = TRUE;
 | |
|       else
 | |
|         xvt_statbar_refresh();
 | |
| 
 | |
|       _check_enabled = TRUE; 
 | |
|     }
 | |
|     break;
 | |
|   case XIE_ON_CELL:
 | |
|     if (_check_enabled)
 | |
|     {                 
 | |
|       TMask_field* f = cell2field(xiev->v.xi_obj);
 | |
|       const int col = (f->dlg()-FIRST_FIELD) % 100;
 | |
|       if (cell_disabled(_cur_rec, col))     // If the cell is disabled ...
 | |
|       {                                  
 | |
|         dispatch_e_char(win(), _lastab);    // ... skip to the next one.
 | |
|       }
 | |
|       else
 | |
|       {  
 | |
|         _edit_field = f;
 | |
|         _cur_col = xiev->v.xi_obj->v.cell.column;
 | |
|         _edit_field->set_focusdirty(_cell_dirty = FALSE);
 | |
|       }  
 | |
|     }
 | |
|     break;
 | |
|   case XIE_OFF_CELL:
 | |
|     if (_edit_field && _check_enabled)
 | |
|     {
 | |
|       _check_enabled = FALSE;
 | |
|       if (_cell_dirty)
 | |
|       {
 | |
|         TMask_field* c = _edit_field;       // Save field, it could turn out to be NULL on error
 | |
|         const char* nuo = c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE);
 | |
|         c->set(nuo);                                              // Set new mask value
 | |
|         c->set_dirty();                                           // Get it dirty!
 | |
|         if (c->on_key(c->is_edit() ? K_TAB : K_SPACE) == FALSE)   // Test it
 | |
|           xiev->refused = *nuo != '\0';
 | |
|         else
 | |
|           mask2str(_cur_rec);             // Update sheet row
 | |
|       }  
 | |
|       if (!xiev->refused)
 | |
|         _edit_field = NULL;               // Reset current field
 | |
|       _check_enabled = TRUE;
 | |
|     }
 | |
|     break;
 | |
|   case XIE_GET_PERCENT:
 | |
|   {
 | |
|     const long rec = xiev->v.get_percent.record;
 | |
|     long n = items(); if (n < 1) n = 1;
 | |
|     xiev->v.get_percent.percent = int(rec * 100L / n);
 | |
|   }
 | |
|     break;
 | |
|   case XIE_CLEANUP:
 | |
|     break;
 | |
|   case XIE_XVT_EVENT:
 | |
|   {
 | |
|     EVENT* ep = &xiev->v.xvte;
 | |
|     switch (ep->type)
 | |
|     {
 | |
|     case E_FOCUS:
 | |
|       if (_check_enabled && ep->v.active == FALSE)
 | |
|       {
 | |
|         const bool ok = (bool)xi_move_focus(_itf);
 | |
|         if (!ok)
 | |
|         {
 | |
|           set_dirty(3);
 | |
|           xiev->refused = TRUE;
 | |
|         }  
 | |
|       }
 | |
|       break;
 | |
|     case E_CHAR:
 | |
|       if (_edit_field)
 | |
|       {
 | |
|         const KEY k = e_char_to_key(ep);
 | |
|         switch(k)
 | |
|         {
 | |
|         case K_TAB:
 | |
|         case K_BTAB:
 | |
|           _lastab = k;
 | |
|           break;
 | |
|         case K_F1:
 | |
|           _check_enabled = FALSE;                               // Disable checks
 | |
|           _edit_field->on_key(K_F1);
 | |
|           set_focus_cell(_cur_row, _cur_col);
 | |
|           _check_enabled = TRUE;                                // Enable checks
 | |
|           break;
 | |
|         case K_F2:
 | |
|         case K_F3:
 | |
|         case K_F8:
 | |
|         case K_F9:
 | |
|         case K_F11:
 | |
|           if (_check_enabled && active())
 | |
|           {
 | |
|             _check_enabled = FALSE;                               // Disable checks
 | |
|             notify_change();
 | |
|             if (_edit_field->on_key(k))
 | |
|             {
 | |
|               mask2str(_cur_rec);
 | |
|             }                               
 | |
|             else
 | |
|             {
 | |
|               if (k == K_F9)
 | |
|               {
 | |
|                 _edit_field = &_mask.fld(_mask.focus_field());
 | |
|                 const short foca = _edit_field->dlg();
 | |
|                 const int col = (foca - FIRST_FIELD) % 100 +1;
 | |
|                 if (col > 0 && col != _cur_col)
 | |
|                 {
 | |
|                   _cur_col = col;
 | |
|                   dispatch_e_char(win(), K_F9);
 | |
|                 }
 | |
|               }  
 | |
|             }  
 | |
|             set_focus_cell(_cur_row, _cur_col);
 | |
|             _check_enabled = TRUE;                                // Enable checks
 | |
|           }  
 | |
|           break;
 | |
|         case K_PREV:
 | |
|         case K_NEXT:
 | |
|         case K_ESC:  
 | |
|           if (xi_move_focus(_itf))
 | |
|             dispatch_e_char(parent(), k);
 | |
|           break;
 | |
|         case K_ENTER:
 | |
|         case K_SHIFT+K_ENTER:
 | |
|           if (xi_move_focus(_itf))
 | |
|             dispatch_e_char(parent(), k == K_ENTER ? K_TAB : K_BTAB);
 | |
|           break;  
 | |
|         case K_CTRL+K_PREV:
 | |
|           xi_scroll(_list, XI_SCROLL_PGUP);
 | |
|           break;
 | |
|         case K_CTRL+K_NEXT:
 | |
|           xi_scroll(_list, XI_SCROLL_PGDOWN);
 | |
|           break;
 | |
|         case K_CTRL+K_HOME:
 | |
|           xi_scroll(_list, XI_SCROLL_FIRST);
 | |
|           break;
 | |
|         case K_CTRL+K_END:
 | |
|           xi_scroll(_list, XI_SCROLL_LAST);
 | |
|           break;
 | |
|         default:
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TSpreadsheet::activate(bool on)
 | |
| {
 | |
|   _active = on;
 | |
|   
 | |
|   const dword old = xi_get_attrib(_list);
 | |
|   dword att = on ? (old & ~XI_ATR_NAVIGATE) : (old | XI_ATR_NAVIGATE);
 | |
|   if (old != att) 
 | |
|   {
 | |
|     int num;
 | |
|     XI_OBJ** columns = xi_get_member_list(_list, &num);
 | |
|     
 | |
|     xi_move_focus(_itf);                  // Set focus to interface
 | |
|     if (on)
 | |
|       att |= XI_ATR_TABWRAP;
 | |
|     else 
 | |
|       att &= ~XI_ATR_TABWRAP;
 | |
|     
 | |
|     xi_set_attrib(_list, att);        
 | |
|     
 | |
|     for (int col = 1; col < num; col++)
 | |
|     {
 | |
|       XI_OBJ* column = columns[col];
 | |
|       att = xi_get_attrib(column);
 | |
|       if (on) 
 | |
|       {
 | |
|         att &= ~XI_ATR_READONLY;
 | |
|         att |= XI_ATR_AUTOSELECT;
 | |
|       }  
 | |
|       else    
 | |
|       {
 | |
|         att |= XI_ATR_READONLY;
 | |
|         att &= ~XI_ATR_AUTOSELECT;
 | |
|       }  
 | |
|       xi_set_attrib(column, att);          // Set new attributes
 | |
|     }  
 | |
|   }  
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| #include <sheet.h>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSpreadsheet
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TSpreadsheet : public TArray_sheet
 | |
| {
 | |
|   TMask _mask;
 | |
|   SPREADSHEET_NOTIFY _notify;
 | |
|   TSheet_field * _owner;
 | |
| 
 | |
|   TBit_array _column_disabled;
 | |
|   TArray _disabled;           // Array di TBit_array
 | |
| 
 | |
| protected:
 | |
|   virtual bool on_key(KEY key);
 | |
|   KEY edit(int n, KEY tasto);
 | |
|   bool notify(int r, KEY k);
 | |
| 
 | |
|   TMask_field* field(short id) const;
 | |
| 
 | |
| public:
 | |
|   TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno,
 | |
|                const char* head, WINDOW parent, TSheet_field * o);
 | |
| 
 | |
|   TMask& sheet_mask() { return _mask; }
 | |
|   TMask& mask() const;
 | |
| 
 | |
|   void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; }
 | |
|   void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork);}
 | |
|   bool dirty() const { return _owner->dirty(); }
 | |
|   bool test_focus_change() { return TRUE; }
 | |
| 
 | |
|   void mask2str(int riga);
 | |
|   void str2mask(int riga);
 | |
| 
 | |
|   void enable_column(int col, bool on);
 | |
|   void enable_cell(int row, int column, bool on = TRUE);
 | |
|   bool cell_disabled(int row, int column) const;
 | |
|   virtual ~TSpreadsheet() {}
 | |
| };
 | |
| 
 | |
| TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, 
 | |
|                            const char* maskname, int maskno,
 | |
|                            const char* head, WINDOW parent,
 | |
|                            TSheet_field* o)
 | |
| : TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), _owner(o),
 | |
|   _mask(maskname, maskno), _notify(NULL)
 | |
| {}
 | |
| 
 | |
| bool TSpreadsheet::on_key(KEY k)
 | |
| {
 | |
|   switch(k)
 | |
|   {
 | |
|   case K_CTRL_ENTER:
 | |
|   case K_ESC: 
 | |
|     mask().send_key(k, 0);
 | |
|     return TRUE;
 | |
|   case K_ENTER:                             // Selezione riga per editing
 | |
|     if (items() < 1) k = K_INS;             // Se vuoto crea riga da editare 
 | |
|   case K_INS:
 | |
|   case 'A':                                 // Aggiunge dopo
 | |
|   case 'I':                                 // Aggiunge prima
 | |
|   {
 | |
|     int n = (int)selected();
 | |
|     if (k != K_ENTER)
 | |
|     {
 | |
|       if (k == K_INS) n = items(); else   // Aggiunge alla fine
 | |
|         if (k == 'A') n++;                  
 | |
|       
 | |
|       if (n < 0) n = 0; else
 | |
|         if (n > items()) n = items();     // Controlla range n 
 | |
|       
 | |
|       if (notify(n, K_INS) == FALSE)      // Chiede l'ok alla applicazione
 | |
|         return FALSE;
 | |
|       
 | |
|       insert(TToken_string(80), n);       // Aggiunge una riga vuota
 | |
|       k = K_INS;                          // Inserimento in corso
 | |
|     }  
 | |
|     
 | |
|     notify(n, K_SPACE);                   // Notifica inizio cambiamento
 | |
|     k = edit(n, k);                       // Edita riga selezionata o creata
 | |
|     if (k == K_ENTER)
 | |
|       notify(n, K_ENTER);                 // Notifica avvenuto cambiamento
 | |
| 
 | |
|     set_front_window(win());              // Aggiorna sheet a video
 | |
|     open();
 | |
|   }
 | |
|     break;
 | |
|   case K_TAB:
 | |
|   case K_BTAB:
 | |
|   case K_SHIFT_TAB:
 | |
|     dispatch_e_char(get_parent(win()), k);
 | |
|     return TRUE;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return TArray_sheet::on_key(k);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Metodi di TSpreadsheet comuni a tutte le piattaforme
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TMask& TSpreadsheet::mask() const
 | |
| {
 | |
|   TMask* m = (TMask*)get_app_data(parent());
 | |
|   return *m;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Ritorna il campo con l'identificatore dato della maschera dello sheet
 | |
| TMask_field* TSpreadsheet::field(short id) const
 | |
| {
 | |
|   const int pos = _mask.id2pos(id);
 | |
|   return pos < 0 ? NULL : &_mask.fld(pos);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Ricopia i campi della maschera nel record dato ed aggiorna il display
 | |
| void TSpreadsheet::mask2str(int rec)
 | |
| {
 | |
|   TToken_string& r = row(rec);
 | |
|   r.cut(0);
 | |
|   for (short id = FIRST_FIELD; ; id++)
 | |
|   {                                 
 | |
|     int pos = sheet_mask().id2pos(id);
 | |
|     if (pos < 0) break;
 | |
|     
 | |
|     for(int dlg = id; pos >= 0; pos = sheet_mask().id2pos(dlg += 100))
 | |
|     {
 | |
|       const TMask_field& f = sheet_mask().fld(pos);
 | |
|       if (f.shown())
 | |
|       {
 | |
|         r.add(f.get());
 | |
|         break;
 | |
|       }  
 | |
|     }  
 | |
| #ifdef DBG
 | |
|     if (pos < 0) 
 | |
|     {
 | |
|       yesnofatal_box("Non e' visibile il campo %d per lo sheet", dlg);
 | |
|       r.add(" ");
 | |
|     }
 | |
| #endif    
 | |
|   }
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   update(rec);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 50%
 | |
| void TSpreadsheet::enable_cell(int row, int column, bool on)
 | |
| {
 | |
|   TBit_array* ba = (TBit_array*)_disabled.objptr(row);
 | |
|   if (ba == NULL)
 | |
|   {
 | |
|     if (on) return;   // Don't waste time and memory
 | |
|     ba = new TBit_array(_column_disabled);
 | |
|     _disabled.add(ba, row);
 | |
|   }
 | |
| 
 | |
|   if (column >= 0)
 | |
|     ba->set(column, !on);
 | |
|   else
 | |
|   {
 | |
|     if (on)
 | |
|       _disabled.destroy(row, FALSE);  // Let's save some memory!
 | |
|     else
 | |
|     {
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|       ba->set(_columns); // Force right array size
 | |
| #else
 | |
|       ba->set(32);       // Force array size
 | |
| #endif
 | |
|       ba->set();         // Set all bits
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSpreadsheet::enable_column(int col, bool on)
 | |
| {
 | |
|   const bool change = _column_disabled[col] == on;
 | |
|   _column_disabled.set(col, !on);
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   if (change)
 | |
|   {
 | |
|     int num;
 | |
|     XI_OBJ** columns = xi_get_member_list(_list, &num);
 | |
|     CHECKD(col+1 < num, "Can't enable column ", col);
 | |
|     XI_OBJ* column = columns[col+1];
 | |
| 
 | |
|     dword attr = xi_get_attrib(column);
 | |
|     if (on) attr |= XI_ATR_ENABLED;
 | |
|     else    attr &= ~XI_ATR_ENABLED;
 | |
| 
 | |
|     xi_move_focus(_itf);                  // Set focus to interface
 | |
|     xi_set_attrib(column, attr);          // Set new attributes
 | |
|     RCT r; xi_get_rect(column, &r); 
 | |
|     xi_set_column_width(column, (r.right-r.left+1) / CHARX);   // Force redraw
 | |
|   }
 | |
| #endif 
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 99%
 | |
| bool TSpreadsheet::cell_disabled(int row, int column) const
 | |
| {
 | |
|   TBit_array* ba = (TBit_array*)_disabled.objptr(row);
 | |
|   if (ba == NULL) return _column_disabled[column];  // Use default
 | |
|   return (*ba)[column];
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 75%
 | |
| void TSpreadsheet::str2mask(int riga)
 | |
| {
 | |
|   if (riga == items())
 | |
|   {
 | |
|     sheet_mask().reset();
 | |
|     mask2str(riga);
 | |
|     return;
 | |
|   }
 | |
|   TToken_string& r = row(riga);
 | |
|   r.restart();
 | |
|   
 | |
|   TString80 val;  
 | |
|   for (short id = FIRST_FIELD; ; id++)
 | |
|   {
 | |
|     int pos = sheet_mask().id2pos(id);
 | |
|     if (pos < 0) break;
 | |
| 
 | |
|     val = r.get(); // Value to set
 | |
| 
 | |
|     int rid = id;
 | |
|     while (pos >= 0)
 | |
|     {
 | |
|       TMask_field& f = sheet_mask().fld(pos);
 | |
|       f.set(val);
 | |
|       const bool on = active() ? !cell_disabled(riga, id-FIRST_FIELD) : FALSE;
 | |
|       f.enable(on);
 | |
| 
 | |
|       if (f.dirty() <= TRUE)
 | |
|       {
 | |
|         if (f.active() || f.ghost())
 | |
|         {
 | |
|           if (f.has_check()) f.check(STARTING_CHECK);
 | |
|           f.set_dirty(FALSE);
 | |
|           f.on_hit();
 | |
|         }
 | |
|         f.set_dirty(FALSE);
 | |
|       }
 | |
|       else
 | |
|         sheet_mask().first_focus(-rid);
 | |
|       
 | |
|       rid += 100;
 | |
|       pos = sheet_mask().id2pos(rid);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   sheet_mask().set_caption(format("Riga %d", riga+1));
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TSpreadsheet::notify(int rec, KEY k)
 | |
| {
 | |
|   const bool ok = _notify ? _notify(rec, k) : TRUE;
 | |
|   if (k == K_ENTER)
 | |
|     set_dirty(ok ? TRUE : 3);
 | |
|   return ok;  
 | |
| }
 | |
| 
 | |
| // Certified 99%
 | |
| #if XVT_OS != XVT_OS_WIN
 | |
| KEY TSpreadsheet::edit(int n, KEY tasto)
 | |
| #else
 | |
|   KEY TSpreadsheet::edit(int n)
 | |
| #endif
 | |
| {
 | |
|   const int olditems = items();
 | |
|   str2mask(n);
 | |
| 
 | |
|   const KEY k = sheet_mask().run();
 | |
| 
 | |
|   if (k == K_ENTER)
 | |
|   {
 | |
|     mask2str(n);
 | |
|   } else
 | |
|     if (k == K_DEL)
 | |
|     {
 | |
|       const bool ok = notify(n, K_DEL); // Notifica intenzione di cancellare
 | |
|       if (ok) 
 | |
|       {
 | |
|         destroy(n);
 | |
|         if (n < items())
 | |
|           str2mask(n);
 | |
|       }  
 | |
|     } 
 | |
| #if XVT_OS != XVT_OS_WIN
 | |
| else
 | |
|   if (k == K_ESC)
 | |
|   {            
 | |
|     if (tasto == K_INS)
 | |
|       destroy(n);
 | |
|   }
 | |
| #endif
 | |
|   
 | |
|   return k;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSheet_field
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 100%
 | |
| TSheet_field::TSheet_field(TMask* m)
 | |
| : TMask_field(m), _sheet(NULL)
 | |
| {}
 | |
| 
 | |
| // Certified 100%
 | |
| word TSheet_field::class_id() const
 | |
| {
 | |
|   return CLASS_SHEET_FIELD;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TSheet_field::~TSheet_field()
 | |
| {
 | |
|   CHECK(_sheet, "Can't delete NULL sheet");
 | |
|   delete _sheet;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TSheet_field::reset()
 | |
| {
 | |
|   _sheet->destroy();
 | |
|   _sheet->sheet_mask().reset();
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TSheet_field::destroy(int r)
 | |
| {
 | |
|   _sheet->destroy(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSheet_field::parse_head(TScanner& scanner)
 | |
| {
 | |
|   _width = scanner.integer();
 | |
|   _size  = scanner.integer();
 | |
|   if (_size == 0) _size = -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| bool TSheet_field::parse_item(TScanner& scanner)
 | |
| {
 | |
|   if (scanner.key() == "IT")
 | |
|   {
 | |
|     _head.add(scanner.string());
 | |
|     return TRUE;
 | |
|   }
 | |
|   return TMask_field::parse_item(scanner);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TSheet_field::create(WINDOW parent)
 | |
| {
 | |
|   const TMask& m = mask();
 | |
|   _sheet = new TSpreadsheet(_x, _y, _width, _size, m.source_file(), 
 | |
|                             m.sheets(), _head, parent, this);
 | |
| 
 | |
|   _win = _sheet->win();
 | |
|   show_window(_win, shown());
 | |
|   if (!enabled()) disable();
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TString_array& TSheet_field::rows_array() const
 | |
| {
 | |
|   return _sheet->rows_array();
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| // Ritorna l'indice della prima riga vuota dello sheet
 | |
| int TSheet_field::first_empty() const
 | |
| {
 | |
|   const int max = _sheet->items();
 | |
|   for (int n = 0; n < max; n++)
 | |
|     if (_sheet->row(n).empty_items())
 | |
|       break;
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| 
 | |
| TToken_string& TSheet_field::row(int n)
 | |
| {
 | |
|   const int max = _sheet->items();
 | |
|   if (n < 0 || n >= max)
 | |
|   {
 | |
|     if (n < 0) n = first_empty();
 | |
|     if (n >= max) n = _sheet->add(new TToken_string(80));
 | |
|   }
 | |
|   return _sheet->row(n);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSheet_field::force_update(int r)
 | |
| {
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   if (_sheet->_check_enabled)
 | |
|     _sheet->update(r);
 | |
| #else
 | |
|   _sheet->open();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| int TSheet_field::items() const
 | |
| {
 | |
|   return (int)_sheet->items();
 | |
| }
 | |
| 
 | |
| int TSheet_field::selected() const
 | |
| {
 | |
|   return _sheet->selected();
 | |
| }
 | |
| 
 | |
| void TSheet_field::set_notify(SPREADSHEET_NOTIFY n)
 | |
| {
 | |
|   _sheet->set_notify(n);
 | |
| }
 | |
| 
 | |
| void TSheet_field::highlight() const
 | |
| {
 | |
|   TMask_field::highlight();
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   if (items())
 | |
|   {                    
 | |
|     _sheet->_firstfocus = FALSE;
 | |
|     if (_sheet->_edit_field == NULL)
 | |
|       _sheet->set_focus_cell(0, 1);
 | |
|   }  
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TSheet_field::enable(bool on)
 | |
| {
 | |
|   _sheet->activate(on);
 | |
| }
 | |
| 
 | |
| void TSheet_field::enable_column(int column, bool on)
 | |
| {
 | |
|   _sheet->enable_column(column, on);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TSheet_field::enable_cell(int row, int column, bool on)
 | |
| {                          
 | |
|   _sheet->enable_cell(row, column, on);
 | |
| }
 | |
| 
 | |
| bool TSheet_field::cell_disabled(int row, int column) const
 | |
| {
 | |
|   return _sheet->cell_disabled(row, column);
 | |
| }
 | |
| 
 | |
| 
 | |
| TMask& TSheet_field::sheet_mask() const
 | |
| {
 | |
|   return _sheet->sheet_mask();
 | |
| }
 | |
| 
 | |
| bool TSheet_field::on_hit()
 | |
| {
 | |
|   if (!mask().is_running())
 | |
|   {
 | |
|     force_update();
 | |
|     set_dirty(FALSE);
 | |
|   }
 | |
|   return TRUE;  
 | |
| }  
 | |
| 
 | |
| bool TSheet_field::test_focus_change()
 | |
| {
 | |
|   return _sheet->test_focus_change();
 | |
| }                       
 | |
| 
 | |
| bool TSheet_field::on_key(KEY k)
 | |
| {                
 | |
|   if (k == K_ENTER)
 | |
|   {          
 | |
|     if (!test_focus_change()) 
 | |
|       return FALSE;
 | |
|   }
 | |
|   return TMask_field::on_key(k);
 | |
| }
 | |
| 
 | |
| void TSheet_field::exchange(bool show_value, const real& nuo)
 | |
| {        
 | |
|   TMask& m = sheet_mask();
 | |
| 
 | |
|   const real& vec = mask().exchange();
 | |
|   
 | |
|   if (vec != nuo)
 | |
|   {
 | |
|     TBit_array valuta(32);
 | |
|     int i = 0;
 | |
|     for (int f = FIRST_FIELD; ;f++, i++)
 | |
|     {
 | |
|       const int pos = m.id2pos(f);
 | |
|       if (pos < 0) break;
 | |
|       if (m.fld(pos).class_id() == CLASS_REAL_FIELD)
 | |
|       {
 | |
|         if (m.fld(pos).exchangeable())
 | |
|           valuta.set(i);
 | |
|       }
 | |
|     }  
 | |
|     
 | |
|     for (int riga = 0; riga < items(); riga++)
 | |
|     {
 | |
|       TToken_string& r = row(riga);
 | |
|       for (const char* s = r.get(i = 0); s; s = r.get(++i))
 | |
|         if (*s > ' ' && valuta[i])
 | |
|         {
 | |
|           real v(s); 
 | |
|           v *= nuo;
 | |
|           v /= vec;
 | |
|           v.round();
 | |
|           r.add(v.string(), i);
 | |
|         }
 | |
|     }    
 | |
|   }  
 | |
|   
 | |
|   m.set_exchange(show_value, nuo);
 | |
|   
 | |
|   if (mask().is_running()) 
 | |
|     force_update();
 | |
| }
 |