From 2f9b35286a13e2bb4be83f228f708d47a783c2ff Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 15 Sep 1995 13:55:52 +0000 Subject: [PATCH] Aggiunto metodo trail nei reali per autoregolare la precisione dopo moltiplicazioni e e divisioni git-svn-id: svn://10.65.10.50/trunk@1833 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/msksheet.cpp | 3770 +++++++++++++++++++++--------------------- 1 file changed, 1896 insertions(+), 1874 deletions(-) diff --git a/include/msksheet.cpp b/include/msksheet.cpp index a37cd8922..1e60b8115 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -1,1874 +1,1896 @@ -#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 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 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(); - - // @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 putatore - // (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 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 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() - { return _mask; } - // @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), _edit_field(NULL), _getmask( NULL ), - _owner(o), _cur_row(0), _cur_col(0), _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(); - - _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()) - 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 (_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, - 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() -{ - 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); - 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); -} - -void TSpreadsheet::update_rec(int rec) -{ - const int riga = rec2row(rec); - if (riga >= 0) - { - if (rec == selected()) - xi_set_focus(_itf); - XI_OBJ row; - XI_MAKE_ROW(&row, _list, riga); - xi_cell_request(&row); // Update internal values - if (rec == selected()/* && _cur_col > 0*/) - set_focus_cell(riga, _cur_col); - } -} - - -void TSpreadsheet::set_focus_cell(int riga, int colonna) -{ - xvt_scr_set_focus_vobj(win()); - const int r = row2rec(riga); - - if (colonna <= 0) colonna = 1; - - 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; - } - } -} - - -// @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. -{ - if (items() >= 999 || !_active) - return -1; - if (rec < 0 && items() > 0 && !_owner->append() ) - rec = _cur_rec + 1; - - const int r = _str.insert(new TToken_string(80), rec); - - const bool ok = notify(r, K_INS); - - if (!ok) - { - _str.destroy(r); - return -1; - } - - _disabled.insert(NULL, r); - xi_insert_row(_list, INT_MAX); - xi_cell_request(_list); - - 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 -{ - 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; -} - - -// @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) - { - 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); -} - -// 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(); - - 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 && !_cell_dirty) - { - notify_change(); - _cell_dirty = TRUE; - _edit_field->set_focusdirty(); - } - 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) - _row_dirty = FALSE; - - str2mask(_cur_rec); - update(_cur_rec); // Forces update delayed by str2mask - - if (_mask.id2pos(FIRST_FIELD-1) != -1) - { - TMask_field* button = &_mask.field(FIRST_FIELD-1); - button->on_hit(); - if (_mask.dirty()) - { - notify_change(); - mask2str(_cur_rec); - } - } - _check_enabled = TRUE; - } - 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()) - _cur_rec = items() - 1; - } - - if (_cur_rec >= 0 && !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() && 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 (_row_dirty && _check_enabled) - { - _check_enabled = FALSE; // Avoid recursion! - 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(); - _edit_field = NULL; // Reset current field - } - else - xiev->refused = TRUE; - - _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. - _edit_field = NULL; - } - 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'; - - if (!xiev->refused) - mask2str(_cur_rec); // Update sheet row - } - _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_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_TAB : K_BTAB; - break; - case K_F1: - case K_SHIFT+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(); - const bool ok = _edit_field->on_key(k); - if (!ok && k == K_F9) // Ricerca non completata? - { - _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) // Ricerca alternativa - { - _cur_col = col; - dispatch_e_char(win(), K_F9); - } - } - if (ok) - { - mask2str(_cur_rec); - update(_cur_rec); _needs_update = -1; // Update immediately! - set_focus_cell(_cur_row, _cur_col); - } - _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 r) -{ - xi_scroll_rec(_list, r, NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); - set_focus_cell(0, 1); -} - -#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() { return _mask; } - TMask& mask() const; - - // Matteo - 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 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), /* Matteo */ _getmask( NULL ) -{ - _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 = 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_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 = _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() || f.ghost()) - { - 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 - 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 -} - -void TSpreadsheet::on_idle() -{ - if (_needs_update >= 0) - { - update_rec(_needs_update); - _needs_update = -1; - } -} - -// 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 - - break; - } - - } -#endif -} - -// Matteo - -void TSpreadsheet::delete_column( const int col ) const -{ -#if XVT_OS == XVT_OS_WIN - int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); - CHECKD( col+1 < num, "Can't delete column ", col ); - XI_OBJ* column = columns[ col+1]; - - 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) -{ - _str.swap(fromindex, toindex); - _disabled.swap(fromindex, toindex); -} - -void TSpreadsheet::set_column_width(const int col, const int width) const -{ -#if XVT_OS == XVT_OS_WIN - int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); - CHECKD(col+1 < num, "Can't set column width ", col); - XI_OBJ* column = columns[col+1]; - - 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 - int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); - CHECKD(col+1 < num, "Can't set column width ", col); - XI_OBJ* column = columns[col+1]; - - 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 -} - - - -// Certified 99% -// @mfunc Controlla se una cella e' disabilitata -// -// @rdesc Ritorna lo stato della cella indicate: -// -// @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); - 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); - 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 = 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); - } - } -#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), _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(); -} - -// 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 (!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; -} - - -// @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 = _sheet->items(); - if (n < 0 || n >= max) - { - if (n < 0) n = first_empty(); - if (n >= max) - { - n = _sheet->add(new TToken_string(80)); - // force_update(n); - } - } - 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 _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 - int rows; xi_get_list_info(_sheet->_list, &rows); - if (rows > 0) - { - _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); -} - -// 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); -} - -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_ROWEDIT ) - { - if ( items( ) ) - { - _sheet->select( _sheet->items( ) - 1 ); - XI_EVENT xie; - xie.type = XIE_DBL_CELL; - xie.v.xi_obj = NULL; - _sheet->list_handler( &xie ); - return TRUE; - } - }; - 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(); -} +#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 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 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(); + + // @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 putatore + // (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 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 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() + { return _mask; } + // @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), _edit_field(NULL), _getmask( NULL ), + _owner(o), _cur_row(0), _cur_col(0), _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(); + + _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()) + 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 (_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, + 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() +{ + 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); + 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); +} + +void TSpreadsheet::update_rec(int rec) +{ + const int riga = rec2row(rec); + if (riga >= 0) + { + if (rec == selected()) + xi_set_focus(_itf); + XI_OBJ row; + XI_MAKE_ROW(&row, _list, riga); + xi_cell_request(&row); // Update internal values + if (rec == selected()/* && _cur_col > 0*/) + set_focus_cell(riga, _cur_col); + } +} + + +void TSpreadsheet::set_focus_cell(int riga, int colonna) +{ + xvt_scr_set_focus_vobj(win()); + const int r = row2rec(riga); + + if (colonna <= 0) colonna = 1; + + 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; + } + } +} + + +// @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 ) + return -1; + + if (items() >= 999 || !_active) + return -1; + if (rec < 0 && items() > 0 && !_owner->append() ) + rec = _cur_rec + 1; + + ininsert = TRUE; + const int r = _str.insert(new TToken_string(80), rec); + + const bool ok = notify(r, K_INS); + + if (!ok) + { + _str.destroy(r); + return -1; + } + + _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 ); + 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 -1; + + 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 + enable_cell(_str.items(), -1); // Enable last line + } + + if (ok && mask().is_running()) + update(-1); + + // Notifica l'avvenuta cancellazione + notify( rec, K_CTRL + K_DEL ); + 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) + { + 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); +} + +// 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(); + + 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 && !_cell_dirty) + { + notify_change(); + _cell_dirty = TRUE; + _edit_field->set_focusdirty(); + } + 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) + _row_dirty = FALSE; + + str2mask(_cur_rec); + update(_cur_rec); // Forces update delayed by str2mask + + if (_mask.id2pos(FIRST_FIELD-1) != -1) + { + TMask_field* button = &_mask.field(FIRST_FIELD-1); + button->on_hit(); + if (_mask.dirty()) + { + notify_change(); + mask2str(_cur_rec); + } + } + _check_enabled = TRUE; + } + 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()) + _cur_rec = items() - 1; + } + + if (_cur_rec >= 0 && !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() && 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 (_row_dirty && _check_enabled) + { + _check_enabled = FALSE; // Avoid recursion! + 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(); + _edit_field = NULL; // Reset current field + } + else + xiev->refused = TRUE; + + _check_enabled = TRUE; + } + // Notifica l'abbandono della riga + notify( _cur_rec, K_CTRL + K_TAB ); + 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. + _edit_field = NULL; + } + 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'; + + if (!xiev->refused) + mask2str(_cur_rec); // Update sheet row + } + _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_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_TAB : K_BTAB; + break; + case K_F1: + case K_SHIFT+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(); + const bool ok = _edit_field->on_key(k); + if (!ok && k == K_F9) // Ricerca non completata? + { + _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) // Ricerca alternativa + { + _cur_col = col; + dispatch_e_char(win(), K_F9); + } + } + if (ok) + { + mask2str(_cur_rec); + update(_cur_rec); _needs_update = -1; // Update immediately! + set_focus_cell(_cur_row, _cur_col); + } + _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 r) +{ + xi_scroll_rec(_list, r, NORMAL_COLOR, XI_ATR_ENABLED | XI_ATR_AUTOSELECT, 0); + set_focus_cell(0, 1); +} + +#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() { return _mask; } + TMask& mask() const; + + // Matteo + 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 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), /* Matteo */ _getmask( NULL ) +{ + _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 = 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_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 = _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() || f.ghost()) + { + 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 + 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 +} + +void TSpreadsheet::on_idle() +{ + if (_needs_update >= 0) + { + update_rec(_needs_update); + _needs_update = -1; + } +} + +// 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 + + break; + } + + } +#endif +} + +// Matteo + +void TSpreadsheet::delete_column( const int col ) const +{ +#if XVT_OS == XVT_OS_WIN + int num; + XI_OBJ** columns = xi_get_member_list(_list, &num); + CHECKD( col+1 < num, "Can't delete column ", col ); + XI_OBJ* column = columns[ col+1]; + + 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) +{ + _str.swap(fromindex, toindex); + _disabled.swap(fromindex, toindex); +} + +void TSpreadsheet::set_column_width(const int col, const int width) const +{ +#if XVT_OS == XVT_OS_WIN + int num; + XI_OBJ** columns = xi_get_member_list(_list, &num); + CHECKD(col+1 < num, "Can't set column width ", col); + XI_OBJ* column = columns[col+1]; + + 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 + int num; + XI_OBJ** columns = xi_get_member_list(_list, &num); + CHECKD(col+1 < num, "Can't set column width ", col); + XI_OBJ* column = columns[col+1]; + + 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 +} + + + +// Certified 99% +// @mfunc Controlla se una cella e' disabilitata +// +// @rdesc Ritorna lo stato della cella indicate: +// +// @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); + 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); + 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 = 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); + } + } +#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), _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(); +} + +// 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 (!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; +} + + +// @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 = _sheet->items(); + if (n < 0 || n >= max) + { + if (n < 0) n = first_empty(); + if (n >= max) + { + n = _sheet->add(new TToken_string(80)); + // force_update(n); + } + } + 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 _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 + int rows; xi_get_list_info(_sheet->_list, &rows); + if (rows > 0) + { + _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); +} + +// 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); +} + +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_ROWEDIT ) + { + if ( items( ) ) + { + _sheet->select( _sheet->items( ) - 1 ); + XI_EVENT xie; + xie.type = XIE_DBL_CELL; + xie.v.xi_obj = NULL; + _sheet->list_handler( &xie ); + return TRUE; + } + }; + 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(); +}