#include #include #include const short FIRST_FIELD = 101; #if XVT_OS == XVT_OS_WIN #include #include #include /////////////////////////////////////////////////////////// // TSpreadsheet /////////////////////////////////////////////////////////// // @doc EXTERNAL // @class TSpreadsheet | Classe per la creazione di uno spreadsheet all'interno // di una maschera // // @base public | TWindow class TSpreadsheet : public TWindow { // @author:(INTERNAL) Guido // @cfriend TSheet_field friend class TSheet_field; // @access Private Member enum { // @ccost ITF_CID | 0 | Identifica l'interfaccia dello spreadsheet ITF_CID = 0, // @ccost LIST_CID | 1 | Identifica il contenuto dello spreadsheet LIST_CID = 1 }; // @cmember Array di TToken_strings contenenti le righe TString_array _str; // @cmember Array delle colonne disattivate (solo visualizzazione) TBit_array _column_disabled; // @cmember Array dell celle disattivate (solo visualizzazione) TArray _disabled; // @cmember Maschera in cui e' contenuto lo spreadsheet TMask _mask; // @cmember Numero di colonne presenti nello spreadsheet int _columns; // @cmember Trucco per evitare che lo sheet prenda il focus tutte le volte che parte la maschera bool _firstfocus; // @cmember Indica se e' attivo lo spreadsheet bool _active; // @cmember Puntatore al contenuto dello spreadsheet XI_OBJ *_list; // @cmember Puntatore all'interfaccia dello spreadsheet XI_OBJ *_itf; // @cmember Funzione per la gestione di una riga dello sheet (vedi ) SPREADSHEET_NOTIFY _notify; // @cmember Funzione per l'apertura della maschera di edit della riga // (vedi ) SPREADSHEET_GETMASK _getmask; // @cmember Campo che possiede lo spreadsheet TSheet_field* _owner; // @cmember Campo corrente che si sta editando TMask_field* _edit_field; // @cmember Coordinata della riga della cella corrente int _cur_row; // @cmember Numero del record sul file al quale fa riferimento la cella corrente int _cur_rec; // @cmember Coordinata della colonna della cella corrente int _cur_col; // @cmember Indica se la riga corrente e' stat modificata bool _row_dirty; // @cmember Permette di gestire i check OFF_ROW e OFF_CELL bool _check_enabled; // @cmember Numero della riga che necessita aggiornamento (vengono aggiornate // nella ) int _needs_update; // @cmember Inizializza lo spreadsheet void init(); // @cmember Funzione che intercetta gli eventi dello spreadsheet friend void XVT_CALLCONV1 xiev_handler(XI_OBJ *itf, XI_EVENT *xiev); // @access Protected Member protected: //@cmember Gestisce gli eventi delle celle (chiamata dal ) void list_handler(XI_EVENT* xiev); //@cmember Copia una cella nel corrispondente campo della maschera e ne ritorna il contenuto const char* copy_cell2field(XI_OBJ* cell = NULL); //@cmember Gestisce l'uscita delle celle (chiamata dal ) bool off_cell_handler(XI_OBJ* cell = NULL); // @cmember Ritorna il campo della maschera corrispondente alla cella dello // spreadsheet indicata da

TMask_field* col2field(int pos) const; // @cmember Ritorna il campo della maschera corrispondente alla cella dello // spreadsheet indicata da

(chiama ) TMask_field* cell2field(const XI_OBJ* cell) const; // @cmember Ritorna la posizione della colonna con identificatore

int cid2col(short cid) const; // @cmember Ritorna la colonna corrispondente al campo

della maschera int field2col(const TMask_field* f) const; // @cmember Aggiorna il record sullo spreadsheet void update_rec(int rec); TMask_field* field(short id) const; // @cmember Converte il numero del record nel corrispondente numero della riga int rec2row(int rec); // @cmember Converte il numero della riga riga nel corrispondente // numero della riga int row2rec(int& row); // @cmember Setta la posizione (riga e colonna) del focus sullo spreadsheet. // Ritorna il numero del record corrente int set_pos(int row, int col) { _cur_col = col; _cur_row = row; return _cur_rec = row2rec(_cur_row); } // @cmember Chiama la funzione specificata con la bool notify(int row, KEY k); // @cmember Chiama la funzione specificata con la // ogni volta che c'e' una modifica nello spreadsheet void notify_change(); // @cmember Permette di fare tutti gli aggiornamenti necessari (indicati in //

) void on_idle(); // @cmember Cerca la colonna col XI_OBJ* TSpreadsheet::find_column(int col) const; // @access Public Member public: // @cmember Modifica a video la riga void update(int row); // @cmember Ritorna il contenuto della riga

-esima TToken_string& row(int n) { return _str.row(n); } // @cmember Aggiunge una riga allo spreadsheet passata come puntatore // (vedi ) int add(const TToken_string& s) { return _str.add(s); } // @cmember Aggiunge una riga allo spreadsheet (vedi ) int add(TToken_string* s) { return _str.add(s); } // @cmember Inserisce un record in una posizione stabilita int insert(int rec); // @cmember Elimina il record

bool destroy(int rec = -1); // @cmember Ritorna l'array di tutte le stringhe delle righe TString_array& rows_array() { return _str; } // @cmember Trova una colonna abilitata a partire da colonna int find_enabled_column(int rec, int colonna, int direction) const; // @cmember Permette di mettere il focus su una cella void set_focus_cell(int riga, int colonna); // @cmember Abilita/disabilita tutto lo spreadsheet (vedi ) void activate(bool on); // @cmember Permette di abilitare/disabiltare una colonna void enable_column(int col, bool on = TRUE); // @cmember Permette di eliminare una colonna dallo spreadsheet void delete_column(const int col) const; // @cmember Sposta la colonna dalla posizione

alla posizione //

void move_column(const int fromindex, const int toindex) const; // @cmember Permette di invertire la posiozne di due colonne void swap_columns(const int fromid, const int toid) const; // @cmember Permette di invertire la posiozne di due righe void swap_rows(const int fromindex, const int toindex); // @cmember Setta la larghezza della colonna void set_column_width(const int col, const int width) const; // @cmember Setta il titolo della colonna void set_column_header(const int col, const TString& header) const; // @cmember Setta l'allinemento di una colonna void set_column_justify(int col, bool right); // @cmember Permette di abilitare/disabilitare una singola cella void enable_cell(int row, int column, bool on = TRUE); // @cmember Controlla se una cella e' disabilitata bool cell_disabled(int row, int column) const; // @cmember Ritorna la maschera che appartiene allo spreadsheet TMask& sheet_mask() const; // @cmember Ritorna la maschera cui appartiene lo spreadsheet TMask& mask() const; // @cmember Ricopia i campi della maschera nel record

-esimo ed // aggiorna il display void mask2str(int n); // @cmember Ricopia i campi del record

-esimo nella maschera ed // aggiorna il display void str2mask(int n); // @cmember Apre la maschera della riga

-esima editando la riga KEY edit(int n); // @cmember Ritorna il numero di righe dello sheet int items() const { return _str.items(); } // @cmember Ritorna il record corrente int selected() const { return _cur_rec; } // @cmember Seleziona una riga dandogli il focus void select(int r); // @cmember Ritorna il numero di colonne presenti enllo spreadsheet int columns() const { return _columns; } // @cmember Controlla se e' stato modificato una cella dello spreadsheet bool dirty() const { return _owner->dirty(); } // @cmember Permette di indicare se e' stata modificata una cella dello spreadsheet void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork); } // @cmember Ritorna il valore della variabile active bool active() const { return _active; } // @cmember Ritorna se e' possibile lasciare il focus dallo spreadsheet (TRUE se e' possibile) bool test_focus_change(); // @cmember Setta il membro

on il valore

void set_getmask(SPREADSHEET_GETMASK n) { _getmask = n; } // @cmember Setta il membro

on il valore

void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } // @cmember Costruttore TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, const char* head, WINDOW parent, TSheet_field* owner); // @cmember Distruttore virtual ~TSpreadsheet(); }; // Certified 100% void TSpreadsheet::init() { static bool first = TRUE; if (!first) return; XVT_FNTID font = xvt_dwin_get_font(TASK_WIN); xi_set_font_id(font); xi_init(); xi_set_pref(XI_PREF_3D_LOOK, TRUE); first = FALSE; } // @mfunc Costruttore TSpreadsheet::TSpreadsheet( short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet short dx, // @parm Larghezza (in caratteri) dello spreasheet short dy, // @parm Lunghezza (in caratteri) dello spreasheet const char* maskname, // @parm Nome del file della maschera int maskno, // @parm Numero identificativo della maschera nel file const char* head, // @parm Titolo della maschera WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet TSheet_field* o) // @parm Indica il campo della maschera che contiene lo spreadsheet : _mask(maskname, maskno), _notify(NULL), _getmask( NULL ), _owner(o), _cur_row(0), _cur_col(0), _cur_rec(0), _edit_field(NULL), _active(TRUE), _row_dirty(FALSE), _check_enabled(TRUE), _firstfocus(TRUE), _needs_update(-1) { 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(); sheet_mask().set_sheet(o); // 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; // Memory and video width 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); } if (f->is_edit()) m = f->size(); if (v > 69) v = 69; 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; word attr = XI_ATR_RJUST; if (sheet_mask().id2pos(FIRST_FIELD -1) != -1) attr |= XI_ATR_SELECTABLE; XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, attr, 0, NUMBER_WIDTH, NUMBER_WIDTH+1, attr & XI_ATR_SELECTABLE ? "X" : ""); coldef->v.column->heading_platform = TRUE; coldef->v.column->column_platform = TRUE; if (attr & XI_ATR_SELECTABLE) { coldef->v.column->icon_rid = ICO_SEARCH; coldef->v.column->icon_x = 2; listdef->v.list->min_heading_height = 16; } else 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_EDIT_FIELD: if (f->right_justified()) flags |= XI_ATR_RJUST; break; 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; } RCT itfrct; xi_get_def_rect(itfdef, &itfrct); xvt_rect_offset(&itfrct, rct.left, rct.top); itfrct.bottom++; WINDOW win = xvt_win_create(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(XI_NULL_OBJ, 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() { if (_getmask != NULL) _getmask(0, _mask, TRUE); // Distrugge la maschera customizzata set_win(NULL_WIN); } TMask& TSpreadsheet::sheet_mask() const { TMask& m = ((TSpreadsheet*)this)->_mask; if (_getmask != NULL && _cur_rec >= 0 && _cur_rec < items()) return *_getmask((int)_cur_rec, m, FALSE); return m; } // 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); CHECKD(pos >= 0 && pos < num, "Bad column number", pos); TMask_field* good = NULL; for (short id = column[pos]->cid; ; id += 100) { TMask_field* f = field(id); if (f == NULL) break; // Search failed 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); } int TSpreadsheet::cid2col(short cid) const { CHECKD(cid >= FIRST_FIELD, "Bad column id ", cid); int num; XI_OBJ** column = xi_get_member_list(_list, &num); for (int c = num-1; c > 1; c--) { if (column[c]->cid == cid) break; } return c; } int TSpreadsheet::field2col(const TMask_field* f) const { const short cid = FIRST_FIELD + (f->dlg() % 100) - 1; return cid2col(cid); } void TSpreadsheet::update_rec(int rec) { const int riga = rec2row(rec); if (riga >= 0) { const bool has_focus = rec == selected() && mask().focus_field().dlg() == _owner->dlg(); if (has_focus) xi_set_focus(_itf); XI_OBJ row; XI_MAKE_ROW(&row, _list, riga); xi_cell_request(&row); // Update internal values if (has_focus) { str2mask(_cur_rec); set_focus_cell(riga, _cur_col); } } } // Cerca una colonna abilitata a partire da colonna // La prima cella utilizzabile ha indice 1 // rec e' un numero di record assoluto // colonna e' un numero di colonna a video: puo' succedere che la 3 corrisponda al campo 107 int TSpreadsheet::find_enabled_column(int rec, int colonna, int direction) const { CHECKD(direction == +1 || direction == -1, "Bad column search direction", direction); const int last = _columns - 1; if (colonna <= 0 || colonna > last) colonna = 1; int num; XI_OBJ** column = xi_get_member_list(_list, &num); bool first = TRUE; for (int c = colonna; first || c != colonna; c += direction) { if (c > last) { c = 1; first = FALSE; } else if (c < 1) { c = last; first = FALSE; } const short n = column[c]->cid - FIRST_FIELD; if (!cell_disabled(rec, n)) return c; } return 0; } // riga (da 0), colonna (0 = numero, 1 = prima cella, ...) void TSpreadsheet::set_focus_cell(int riga, int colonna) { xvt_scr_set_focus_vobj(win()); mask().set_focus_win(win(), FALSE); const int rec = row2rec(riga); colonna = find_enabled_column(rec, colonna, +1); if (colonna > 0) { XI_OBJ cell; XI_MAKE_CELL(&cell, _list, riga, colonna); xi_set_focus(&cell); _edit_field = col2field(_cur_col = colonna); if (rec != _cur_rec) { _cur_rec = rec; _cur_row = riga; str2mask(_cur_rec); _row_dirty = FALSE; } } } // @mfunc Inserisce un record in una posizione stabilita // // @rdesc Ritorna la posizione nella quale e' stato inserito il record. Se non riesce ad inserirlo // ritorna -1. int TSpreadsheet::insert( int rec) // @parm Numero del record da inserire nello spreadsheet // @comm Non e' possibile inserire un nuovo record nel caso nello spreadsheet vi siano // almeno 999 righe oppure se lo spreadsheet non e' attivo. { static bool ininsert = FALSE; if (ininsert || items() >= 999) return -1; if (rec < 0 && items() > 0 && !_owner->append() ) rec = _cur_rec + 1; ininsert = TRUE; int r = _str.insert(new TToken_string(80), rec); const bool ok = notify(r, K_INS); if (ok) { _disabled.insert(NULL, r); xi_insert_row(_list, INT_MAX); xi_cell_request(_list); // Notifica che l'inserimento è terminato notify(r, K_CTRL + K_INS); } else { _str.destroy(r); r = -1; } ininsert = FALSE; return r; } // @mfunc Elimina una riga // // @rdesc Ritorna il risultato dell'operazione: // // @flag TRUE | Se la riga esisteve e quindi e' stata eliminata // @flag FALSE | Se la riga non esisteve bool TSpreadsheet::destroy( int rec) // @parm Numero della riga da eliminare // @comm Se il parametro

assume valore -1 vengono eliminate tutte le righe presenti // nello spreadsheet { static bool indestroy = FALSE; if ( indestroy ) return FALSE; indestroy = TRUE; 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 } if (ok && mask().is_running()) update(-1); indestroy = FALSE; return ok; } // @mfunc Modifica a video la riga void TSpreadsheet::update( int row) // @parm Numero della riga da modificare // @comm Se il valore di

e' minore di 0 viene aggiornato l'intero spreadsheet { if (row < 0) { _needs_update = -1; // Clear pending row update 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) ok = xi_move_focus(_itf) ? TRUE : FALSE; return ok; } HIDDEN void XVT_CALLCONV1 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); } const char* TSpreadsheet::copy_cell2field(XI_OBJ* cell) { const char* val; if (cell == NULL) { XI_OBJ cella; XI_MAKE_CELL(&cella, _list, _cur_row, _cur_col); val = _edit_field->picture_data(xi_get_text(&cella, NULL, -1), TRUE); } else val = _edit_field->picture_data(xi_get_text(cell, NULL, -1), TRUE); _edit_field->set(val); _edit_field->set_dirty(); // Get it dirty! return val; } bool TSpreadsheet::off_cell_handler(XI_OBJ *cell) { bool ok = TRUE; if (_edit_field != NULL) { const char* nuo = copy_cell2field(cell); if (_edit_field->on_key(_edit_field->is_edit() ? K_TAB : K_SPACE) == FALSE) // Test it ok = *nuo != '\0'; mask2str(_cur_rec); // Update sheet row } return ok; } // 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); src = row(rec).get(col); // Set value for cell if (f->is_edit()) { if (src && *src) src = f->picture_data(src, FALSE); // Get formatted string if (f->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 && !_cell_dirty) { notify_change(); _cell_dirty = TRUE; _edit_field->set_dirty(); } 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; if (_cell_dirty) off_cell_handler(); const int oldrec = _cur_rec; set_pos(xiev->v.select.xi_obj->v.row, 1 /* xiev->v.select.column */); if (oldrec != _cur_rec) { _row_dirty = FALSE; on_idle(); // Forces update delayed by str2mask } const int button_pos = sheet_mask().id2pos(FIRST_FIELD-1); if (button_pos >= 0) { TMask_field& button = sheet_mask().fld(button_pos); if (button.active()) { str2mask(_cur_rec); button.on_hit(); if (sheet_mask().dirty()) { notify_change(); mask2str(_cur_rec); } } } _check_enabled = TRUE; _owner->highlight(); } xiev->refused = TRUE; break; case XIE_DBL_CELL: { _check_enabled = FALSE; const int oldrec = _cur_rec; if ( xiev->v.xi_obj != NULL ) { 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 (_cur_rec >= items()) { _row_dirty = _cell_dirty = FALSE; set_pos(0, 1); } if (_cur_rec >= 0) 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: on_idle(); break; case XIE_ON_ROW: if (_check_enabled) { set_pos(xiev->v.xi_obj->v.row, _cur_col); if (_cur_rec < items() && notify(_cur_rec, K_TAB)) { str2mask(_cur_rec); _row_dirty = FALSE; } else { _cur_row = _cur_rec = 0; xiev->refused = TRUE; } } break; case XIE_OFF_ROW: if (_check_enabled) { _check_enabled = FALSE; // Avoid recursion! if (_row_dirty) { bool ok = sheet_mask().check_fields(); if (ok) { mask2str(_cur_rec); // Update sheet with mask contents ok = notify(_cur_rec, K_ENTER); // Notify edit } if (ok) { xvt_statbar_refresh(); } else { xiev->refused = TRUE; } } if (!xiev->refused) { // Notifica l'abbandono della riga notify(_cur_rec, K_CTRL+K_TAB); } _check_enabled = TRUE; } break; case XIE_ON_CELL: if (_check_enabled) { TMask_field* f = cell2field(xiev->v.xi_obj); const int logical_column = (f->dlg()-FIRST_FIELD) % 100; const int physical_column = xiev->v.xi_obj->v.cell.column; if (cell_disabled(_cur_rec, logical_column)) // If the cell is disabled ... { const int dir = _lastab == K_TAB ? +1 : -1; const int nex = find_enabled_column(_cur_rec, physical_column, dir); if (nex > 0) // If at least one enabled cell exists { // _edit_field = NULL; set_focus_cell(_cur_row, nex); } else xiev->refused = TRUE; } else { _edit_field = f; _cur_col = physical_column; _edit_field->set_focusdirty(_cell_dirty = FALSE); } } break; case XIE_OFF_CELL: if (_edit_field && _check_enabled && _cell_dirty) { _check_enabled = FALSE; XI_OBJ* cell = xiev->v.xi_obj; xiev->refused = !off_cell_handler(cell); _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) { if (!mask().is_running()) _row_dirty = _cell_dirty = 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_ROWEDIT: xiev->type = XIE_DBL_CELL; xiev->v.xi_obj = NULL; list_handler( xiev ); break; case K_TAB: case K_BTAB: _lastab = k; break; case K_UP: case K_DOWN: _lastab = (_cur_col == 2) ? K_BTAB : K_TAB; break; case K_F1: case K_SHIFT+K_F1: _check_enabled = FALSE; // Disable checks _edit_field->on_key(k); set_focus_cell(_cur_row, _cur_col); _check_enabled = TRUE; // Enable checks break; case K_F8: case K_F9: if (_edit_field != NULL) copy_cell2field(); case K_F2: case K_F3: case K_F11: if (_check_enabled && active()) { _check_enabled = FALSE; // Disable checks notify_change(); const bool ok = _edit_field->on_key(k); if (!ok && k == K_F9) // Ricerca non completata? { _edit_field = &sheet_mask().focus_field(); const int col = field2col(_edit_field); if (col != _cur_col) // Ricerca alternativa { _cur_col = col; dispatch_e_char(win(), K_F9); } } if (ok) { mask2str(_cur_rec); on_idle(); // Update immediately! } _check_enabled = TRUE; // Re-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 } } } void TSpreadsheet::select(int rec) { int row = rec2row(rec); if (row < 0) { xi_scroll_rec(_list, rec, NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); row = 0; } _cur_rec = -1; set_focus_cell(row, 1); } void TSpreadsheet::on_idle() { if (_needs_update >= 0) { if (_needs_update < items()) update_rec(_needs_update); _needs_update = -1; } } // @mfunc Cerca la colonna col XI_OBJ* TSpreadsheet::find_column( int col) const // @param Indice o identificatore colonna { CHECKD(col >= 0, "Bad column ", col); if (col < columns()) // Se e' un indice trasformalo in identificatore col += FIRST_FIELD; int num; XI_OBJ** columns = xi_get_member_list(_list, &num); for (int c = 1; c < num; c++) { if (columns[c]->cid == col) break; } if (c == num) { yesnofatal_box("Can't find column with id=%d", col); c = 0; } return columns[c]; } #else #include /////////////////////////////////////////////////////////// // TSpreadsheet /////////////////////////////////////////////////////////// class TSpreadsheet : public TArray_sheet { TMask _mask; SPREADSHEET_NOTIFY _notify; // Matteo SPREADSHEET_GETMASK _getmask; 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() const { return ((TSpreadsheet*)this)->_mask; } TMask& mask() const; void swap_columns(const int fromid, const int toid) const; void swap_rows( const int fromindex, const int toindex); void set_getmask(SPREADSHEET_GETMASK n) { _getmask = n; } 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); // Matteo void delete_column( const int col ) const; void move_column( const int fromindex, const int toindex ) const; void set_column_width( const int col, const int width ) const; void set_column_header( const int col, const TString& header ) const; void set_column_justify(int col, bool right); 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), _getmask( NULL ) { sheet_mask().set_sheet(o); } 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 = (int)items(); else // Aggiunge alla fine if (k == 'A') n++; if (n < 0) n = 0; else if (n > (int)items()) n = (int)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_TAB); // Notifica selezione 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 xvt_vobj_raise(win()); // Aggiorna sheet a video open(); } break; case K_TAB: case K_BTAB: case K_SHIFT_TAB: dispatch_e_char(xvt_vobj_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*)xvt_vobj_get_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 = sheet_mask().id2pos(id); return pos < 0 ? NULL : &sheet_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() || f.ghost()) { r.add(f.get()); break; } } if (pos < 0) { #ifdef DBG yesnofatal_box("Mask2str: Non e' visibile il campo %d", dlg); #endif r.add(" "); } } #if XVT_OS == XVT_OS_WIN if (_needs_update != rec) { if (_needs_update >= 0) { #ifdef DBG warning_box("Double update: %d and %d", _needs_update, rec); #endif update_rec(_needs_update); } _needs_update = rec; } #endif } // Certified 50% // @mfunc Permette di abilitare/disabilitare una singola cella void TSpreadsheet::enable_cell( int row, // @parm Riga della cella da abilitare/disabilitare int column, // @parm Colonna della cella da abilitare/disabilitare bool on) // @parm Indica l'operazione da effettuare sulla cella: // // @flag TRUE | La cella viene abilitata (default) // @flag FALSE| La cella viene disabilitata { 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 } } } // @mfunc Permette di abilitare/disabiltare una colonna void TSpreadsheet::enable_column( int col, // @parm Numero della colonna da abilitare/disabilitare bool on) // @parm Indica l'operazione da effettuare sulla colonna: // // @flag TRUE | Abilita la colonna (default) // @flag FALSE| Disabilita la colonna { 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); for (int c = 1; c < num; c++) if (columns[c]->cid == FIRST_FIELD+col) { XI_OBJ* column = columns[c]; 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 */ update(-1); break; } } #endif } void TSpreadsheet::delete_column( const int col ) const { #if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_delete( column ); #endif } void TSpreadsheet::move_column( const int fromindex, const int toindex) const { #if XVT_OS == XVT_OS_WIN int num; XI_OBJ** columns = xi_get_member_list(_list, &num); CHECKD(fromindex+1 < num, "Can't move column ", fromindex); XI_OBJ* column = columns[fromindex+1]; xi_move_column( column, toindex ); #endif } void TSpreadsheet::swap_columns(const int fromid, const int toid) const { #if XVT_OS == XVT_OS_WIN int num; XI_OBJ** columns = xi_get_member_list(_list, &num); XI_OBJ* from_column = XI_NULL_OBJ; XI_OBJ* to_column = XI_NULL_OBJ; int from_pos = 0; int to_pos = 0; for (int c = 1; c < num; c++) { XI_OBJ* column = columns[c]; if (column->cid == fromid) { from_column = column; from_pos = c; } if (column->cid == toid) { to_column = column; to_pos = c; }; } xi_move_column(from_column, to_pos); if (to_pos < from_pos) from_pos++; xi_move_column(to_column, from_pos); #endif } void TSpreadsheet::swap_rows( const int fromindex, const int toindex) { #if XVT_OS == XVT_OS_WIN _str.swap(fromindex, toindex); _disabled.swap(fromindex, toindex); #endif } void TSpreadsheet::set_column_width(const int col, const int width) const { #if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_set_column_width(column, width); // Force redraw #endif } void TSpreadsheet::set_column_header(const int col, const TString& header) const { #if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); xi_set_text(column, (char *)(const char *)header ); RCT r; xi_get_rect(column, &r); xi_set_column_width(column, (r.right-r.left+1) / CHARX); // Force redraw #endif } void TSpreadsheet::set_column_justify(int col, bool right) { #if XVT_OS == XVT_OS_WIN XI_OBJ* column = find_column(col); dword attr = xi_get_attrib(column); if (right) attr |= XI_ATR_RJUST; else attr &= ~XI_ATR_RJUST; xi_set_attrib(column, attr); // Set new attribute update(-1); #endif } // Certified 99% // @mfunc Controlla se una cella o un'intera riga e' disabilitata // // @rdesc Se column e' minore di zero si considera l'intera riga // @rdesc Ritorna lo stato della cella indicata: // // @flag TRUE | Se la cella e' disabilitata // @flag FALSE| Se la cella e' abilitata bool TSpreadsheet::cell_disabled(int row, int column) const { TBit_array* ba = (TBit_array*)_disabled.objptr(row); bool d; if (column < 0) d = ba == NULL ? FALSE : (ba->ones() >= columns()-1); else d = ba == NULL ? _column_disabled[column] : (*ba)[column]; return d; } // Certified 75% void TSpreadsheet::str2mask(int riga) { if (riga == items()) { sheet_mask().reset(); mask2str(riga); return; } TToken_string& r = row(riga); TString val(80); for (int i = 0; i < sheet_mask().fields(); i++) { TMask_field& f = sheet_mask().fld(i); const short id = f.dlg(); if (id >= FIRST_FIELD) { val = r.get((id % 100)-1); f.set(val); const bool on = active() ? !cell_disabled(riga, id-FIRST_FIELD) : FALSE; f.enable(on); } } for (i = 0; i < sheet_mask().fields(); i++) { TMask_field& f = sheet_mask().fld(i); const short id = f.dlg(); if (id >= FIRST_FIELD && f.class_id() != CLASS_BUTTON_FIELD && (f.active() || f.ghost())) { if (f.has_check()) f.check(STARTING_CHECK); f.set_dirty(FALSE); f.on_hit(); } } for (i = 0; i < sheet_mask().fields(); i++) { TMask_field& f = sheet_mask().fld(i); const short id = f.dlg(); if (id > FIRST_FIELD) { if (f.dirty() == TRUE) f.set_dirty(FALSE); } } sheet_mask().set_caption(format("Riga %d", riga+1)); } // Certified 100% bool TSpreadsheet::notify(int rec, KEY k) { const bool ok = _notify ? _notify(*_owner, 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 { KEY k; const int olditems = (int)items(); str2mask(n); if( _getmask ) { TMask& totalmask = sheet_mask(); TMask& usermask = *_getmask( n, totalmask, FALSE ); // Carico la maschera dell'utente con la maschera totale for( int i = 0; i < usermask.fields(); i ++ ) { TMask_field& dest_field = usermask.fld( i ); if ( dest_field.dlg( ) > 100 ) { const TMask_field& source_field = totalmask.field( dest_field.dlg( ) ); dest_field.set( source_field.get( ) ); } } k = usermask.run(); if (k == K_ENTER) // Carico la maschera totale con la maschera dell'utente for( i = 0; i < usermask.fields(); i ++ ) { const TMask_field& source_field = usermask.fld( i ); if ( source_field.dlg( ) > 100 ) { TMask_field& dest_field = totalmask.field( source_field.dlg() ); dest_field.set( source_field.get( ) ); } } _getmask( n, totalmask, TRUE ); } else 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); notify(n, K_CTRL+K_DEL); // Notifica l'avvenuta cancellazione } } else if (k == K_ESC) { #if XVT_OS == XVT_OS_WIN str2mask(n); #else if (tasto == K_INS) destroy(n); #endif } } return k; } /////////////////////////////////////////////////////////// // TSheet_field /////////////////////////////////////////////////////////// // Certified 100% TSheet_field::TSheet_field(TMask* m) : TMask_field(m), _sheet(NULL), _append(TRUE) {} // 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(); force_update(); } // 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(); xvt_vobj_set_visible(_win, shown()); if (!_flags.enable_default) { _flags.enabled = TRUE; // Lo sheet e' sempre operabile anche se non editabile 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 = (int)_sheet->items(); for (int n = 0; n < max; n++) if (_sheet->row(n).empty_items()) break; return n; } // @mfunc Ritorna nuova riga dello spreadshhet // // @rdesc Ritorna la stringa letta TToken_string& TSheet_field::row( int n) // @parm Numero della riga da leggere/creare // @comm Se il parametro

e maggiore del numero massimo di righe presenti // o minore di 0 viene aggiunta una riga vuota in fondo allo spreadsheet // (viene chiamata la ) { const int max = (int)_sheet->items(); if (n < 0 || n >= max) { if (n < 0) n = first_empty(); if (n >= max) { n = (int)_sheet->add(new TToken_string(80)); } } return _sheet->row(n); } // @mfunc Forza l'aggiornamento dei dati della riga sullo schermo void TSheet_field::force_update( int r) // @parm Numero della riga da aggiornare // @comm Se il parametro

assume valore -1 vengono aggiornate tutte le righe presenti // nello spreadsheet { #if XVT_OS == XVT_OS_WIN _sheet->update(r); #else _sheet->open(); #endif } int TSheet_field::items() const { return (int)_sheet->items(); } int TSheet_field::selected() const { return (int)_sheet->selected(); } void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) { _sheet->set_notify(n); } void TSheet_field::set_getmask(SPREADSHEET_GETMASK n) { _sheet->set_getmask( n ); } // Certified 50% void TSheet_field::highlight() const { TMask_field::highlight(); #if XVT_OS == XVT_OS_WIN if (_sheet->_check_enabled) { int rows; xi_get_list_info(_sheet->_list, &rows); if (rows > 0) { if (_sheet->notify(_sheet->_cur_rec, K_TAB)) { _sheet->set_focus_cell(_sheet->_cur_row, _sheet->_cur_col); _sheet->str2mask(selected()); } } } #endif } void TSheet_field::enable(bool on) { _sheet->activate(on); } bool TSheet_field::enabled() const { return items() > 0; } 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); } // Matteo void TSheet_field::delete_column( const int col ) const { _sheet->delete_column( col ); } void TSheet_field::move_column( const int fromindex, const int toindex ) const { _sheet->move_column(fromindex, toindex); } void TSheet_field::swap_columns(const int fromid, const int toid) const { _sheet->swap_columns(fromid, toid); } void TSheet_field::swap_rows( const int fromindex, const int toindex) { _sheet->swap_rows(fromindex, toindex); } void TSheet_field::set_column_width( const int col, const int width ) const { _sheet->set_column_width(col, width); } void TSheet_field::set_column_header( const int col, const TString& header ) const { _sheet->set_column_header(col, header); } void TSheet_field::set_column_justify(int col, bool right) { if (col < FIRST_FIELD) col += FIRST_FIELD; sheet_mask().field(col).set_justify(right); _sheet->set_column_justify(col, right); } 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; } void TSheet_field::select(int r) { _sheet->select(r); } 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; } if (k == K_TAB && !focusdirty() && items() > 0) { select(0); } #if XVT_OS == XVT_OS_WIN if (k == K_ROWEDIT && items() > 0) { select(items()-1); XI_EVENT xie; xie.type = XIE_DBL_CELL; xie.v.xi_obj = NULL; _sheet->list_handler( &xie ); return TRUE; } #endif return TMask_field::on_key(k); } void TSheet_field::on_idle() { #if XVT_OS == XVT_OS_WIN _sheet->on_idle(); #endif } 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(); }