diff --git a/include/msksheet.cpp b/include/msksheet.cpp index cd41d6257..9bf9c5af0 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -1,1034 +1,1039 @@ -#include -#include -#include -#include - -const short FIRST_FIELD = 101; - -#if XVT_OS == XVT_OS_WIN - -#include -#include - -/////////////////////////////////////////////////////////// -// TSpreadsheet -/////////////////////////////////////////////////////////// - -#define K_PLUS '+' - -class TSpreadsheet : public TWindow -{ - enum { ITF_CID = 0, LIST_CID = 1 }; - - TArray _str; // Array di TToken_strings - TBit_array _column_disabled; - TArray _disabled; // Array di TBit_array - - TMask _mask; - int _columns; - bool _dirty; - - XI_OBJ *_list; - - SPREADSHEET_NOTIFY _notify; - - static void xiev_handler(XI_OBJ *itf, XI_EVENT *xiev); - void init(); - -protected: - void list_handler(XI_EVENT *xiev); - - TMask_field* cell2field(const XI_OBJ* cell) const; - void update_rec(int rec); - void set_focus_cell(int riga, int colonna); - - void mask2str(int n); - void str2mask(int n); - KEY edit(int n); - - TMask_field* field(short id) const; - - int rec2row(int rec); - int row2rec(int row); - - bool notify(int r, KEY k); - -public: - void update(int row); - - TToken_string& row(int n); - TArray& rows_array() const { return (TArray&)_str; } - int add(TToken_string&); - int insert(int rec); - bool destroy(int rec = -1); - - void enable_column(int col, bool on = TRUE); - void enable_cell(int row, int column, bool on = TRUE); - bool cell_disabled(int row, int column) const; - - TMask& mask() { return _mask; } - int items() const { return _str.items(); } - int columns() const { return _columns; } - bool dirty() const { return _dirty; } - void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } - - void set_dirty(bool spork = TRUE) { _dirty = spork; } - - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, - const char* head, WINDOW parent); -}; - -// Certified 99% -void TSpreadsheet::init() -{ - static bool first = TRUE; - - if (!first) return; - - xvt_set_font(TASK_WIN, FF_FIXED, 0); - DRAW_CTOOLS ct; - win_get_draw_ctools(TASK_WIN, &ct); - xi_set_font(&ct.font); - - xi_init(); - xi_set_pref(XI_PREF_3D_LOOK, TRUE); -// xi_set_pref(XI_PREF_COLOR_LIGHT, COLOR_CYAN); -// xi_set_pref(XI_PREF_COLOR_CTRL, MASK_BACK_COLOR); -// xi_set_pref(XI_PREF_COLOR_DARK, COLOR_GRAY); - - first = FALSE; -} - -TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, - const char* maskname, int maskno, - const char* head, WINDOW parent) - : _mask(maskname, NO_MODE, maskno), _notify(NULL) - -{ - const int NUMBER_WIDTH = 3; - const int MAX_COL = 32; - int width[MAX_COL]; - - init(); - - // Calcolo larghezza massima tabella - - TToken_string header(head); - TToken_string new_header(256); - int i = 0, tot_width = NUMBER_WIDTH+1; - for (const char* h = header.get(); h; h = header.get(), i++) - { - CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); - int w; - char* at = strchr(h, '@'); - if (at) - { - w = atoi(at+1); - *at = '\0'; - } else w = strlen(h); - - width[i] = w+1; - - 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); - if (f->has_query()) w += 2; - - tot_width += w; - new_header.add(h); - } - _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.right -= 20; - rct.bottom -= 8; - - 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_COLOR, DISABLED_BACK_COLOR, NORMAL_COLOR, - LIST_CID); - listdef->v.list->scroll_bar = TRUE; - listdef->v.list->sizable_columns = TRUE; - listdef->v.list->movable_columns = TRUE; - listdef->v.list->scroll_bar_button = TRUE; - listdef->v.list->fixed_columns = 1; - 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 = COLOR_GRAY; - - XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, - XI_ATR_RJUST, 0, NUMBER_WIDTH, NUMBER_WIDTH, ""); - coldef->v.column->heading_platform = TRUE; - coldef->v.column->column_platform = TRUE; - coldef->v.column->center_heading = TRUE; - - for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) - { - const int cid = FIRST_FIELD+i; // Column & Field ID - const TMask_field* f = field(cid); // Field on mask - const int w = width[i] + (f->has_query() ? 2 : 0); // Column width - - long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL; - if (f->class_id() == CLASS_REAL_FIELD) flags |= XI_ATR_RJUST; - if (f->active()) flags |= XI_ATR_ENABLED; - else _column_disabled.set(i); - - coldef = xi_add_column_def(listdef, cid, - flags, cid, w, width[i], (char*)h); - coldef->v.column->heading_platform = TRUE; - coldef->v.column->center_heading = TRUE; - } - - RCT itfrct; - xi_get_def_rect(itfdef, &itfrct); - offset_rect(&itfrct, rct.left, rct.top); - itfrct.bottom++; - - WINDOW win = create_window(W_NO_BORDER, &itfrct, "", 0, parent, - 0, EM_ALL, (EVENT_HANDLER)xi_event, 0L); - CHECK(win, "Can't create a window for the spreadsheet"); - - set_win(win); // Set TWindow::_win - itfdef->v.itf->win = win; - - xi_create(NULL, itfdef); - xi_tree_free(itfdef); - - XI_OBJ* itf = xi_get_itf(win); - _list = xi_get_obj(itf, LIST_CID); -} - - -// 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); - -#ifdef DBG - if (row < 0 || row >= rows) - { - error_box("Line %d is not visible", row); - return 0L; - } -#endif - - return (int)rec[row]; -} - - -// 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::cell2field(const XI_OBJ* cell) const -{ - const int pos = cell->v.cell.column; - - int num; - XI_OBJ** column = xi_get_member_list(_list, &num); - - TMask_field* good = NULL; - for (short id = column[pos]->cid; ; id += 100) - { - TMask_field* f = field(id); - if (f == NULL) break; - good = f; - if (f->active()) break; - } - - return good; -} - -void TSpreadsheet::update_rec(int rec) -{ - const int riga = rec2row(rec); - if (riga >= 0) - { - XI_OBJ row; - XI_MAKE_ROW(&row, _list, riga); - xi_cell_request(&row); // Update internal values - xi_set_row_height(&row, CHARY+1); // Force row updating - } -} - -void TSpreadsheet::set_focus_cell(int riga, int colonna) -{ - set_front_window(win()); - XI_OBJ cell; - XI_MAKE_CELL(&cell, _list, rec2row(riga), colonna); - xi_set_focus(&cell); -} - - -int TSpreadsheet::insert(int rec) -{ - const bool ok = notify(rec, K_INS); - if (!ok) return -1; - - TToken_string s; // Empty row - const int r = _str.insert(s, rec); - _disabled.insert(NULL, rec); - - xi_insert_row(_list, INT_MAX); - xi_cell_request(_list); - - return r; -} - - -bool TSpreadsheet::destroy(int rec) -{ - bool ok = TRUE; - - if (rec < 0) - { - _disabled.destroy(); - _str.destroy(); - } - 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) xi_cell_request(_list); - - return ok; -} - - -void TSpreadsheet::update(int row) -{ - if (row < 0) - { - xi_cell_request(_list); - xi_scroll(_list, XI_SCROLL_FIRST); - set_front_window(win()); - } - else - update_rec(row); -} - - -void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev) -{ - TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf); - CHECK(es, "NULL Edit sheet in xi event"); - es->list_handler(xiev); -} - - -// Certified 75% -void TSpreadsheet::list_handler(XI_EVENT *xiev) -{ - static TMask_field* edit_field = NULL; // Current edit field - static int cur_row = 0, cur_col = 0; // Current cell - static bool row_dirty = FALSE; // Current row changed - static bool check_enabled = TRUE; // Perform OFF_ROW checks - - switch (xiev->type) - { - case XIE_GET_FIRST: - { - const long max = items(); - if (max <= 0L) - { - xiev->refused = TRUE; - break; - } - long n = max * (long)xiev->v.rec_request.percent / 100L; - if (n < 0L) n = 0L; - xiev->v.rec_request.data_rec = n; - } - 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 (src && *src && f->class_id() == CLASS_REAL_FIELD) - { - src = f->picture_data(src, FALSE); // Get formatted string - } - if (field(cid)->has_query()) - { - xiev->v.cell_request.button = - xiev->v.cell_request.button_on_focus = TRUE; - } - if (cell_disabled(rec, col)) - xiev->v.cell_request.back_color = MASK_BACK_COLOR; - } - } else src = format("%d", rec+1); - - const int len = xiev->v.cell_request.len; - char* dst = xiev->v.cell_request.s; - if (src) - { - strncpy(dst, src, len); - if (isspace(*dst)) - { - TFixed_string d(dst); - d.ltrim(); - } - } - else - *dst = '\0'; - } - break; - case XIE_BUTTON: - if (xiev->v.xi_obj->type == XIT_CELL) - { - if (edit_field) - { - const char* val = xi_get_text(xiev->v.xi_obj, NULL, -1); - edit_field->set(val); // Update current cell - check_enabled = FALSE; // Disable checks - if (!row_dirty) notify(cur_row, K_SPACE); - if (edit_field->on_key(K_F9)) // Show search sheet - { - mask2str(cur_row); // Update row - row_dirty = TRUE; - } - check_enabled = TRUE; // Enable checks - xi_set_focus(xiev->v.xi_obj); // Restore focus to cell - } - } else - if (xiev->v.xi_obj->type == XIT_LIST) - insert(-1); - break; - case XIE_DBL_CELL: - { - check_enabled = FALSE; - cur_row = row2rec(xiev->v.xi_obj->v.cell.row); - cur_col = xiev->v.xi_obj->v.cell.column; - const KEY k = edit(cur_row); - if (k == K_ENTER) - { - update_rec(cur_row); - row_dirty = TRUE; - } - xi_set_focus(xiev->v.xi_obj); - check_enabled = TRUE; - } - break; - case XIE_ON_ROW: - { - const int rec = row2rec(xiev->v.xi_obj->v.row); - if (rec < items()) - { - cur_row = rec; - str2mask(rec); - row_dirty = FALSE; - } - else - xiev->refused = TRUE; - } - break; - case XIE_OFF_ROW: - if (row_dirty && check_enabled) - { - check_enabled = FALSE; // Avoid recursion! - set_dirty(); - str2mask(cur_row); // It shouldn't have to be necessary - bool ok = _mask.check_fields(); - if (ok) - { - mask2str(cur_row); - ok = notify(cur_row, K_ENTER); // Notify edit - } - if (!ok) - { - set_focus_cell(cur_row, cur_col); - } - check_enabled = TRUE; - } - break; - case XIE_ON_CELL: - { - TMask_field* f = cell2field(xiev->v.xi_obj); - const int col = (f->dlg() - FIRST_FIELD) % 100; - if (!cell_disabled(cur_row, col)) - { - edit_field = f; - cur_col = xiev->v.xi_obj->v.cell.column; - xi_set_color(xiev->v.xi_obj, XIC_BACK, FOCUS_BACK_COLOR); - } - else - { - xiev->refused = TRUE; - } - } - break; - case XIE_OFF_CELL: - if (edit_field && check_enabled) - { - TMask_field* c = edit_field; // Save field, it could turn out to be NULL on error - const TString80 old(c->get()); // Save old value on mask - const TString80 nuo(c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE)); - if (old != nuo) - { - check_enabled = FALSE; - if (!row_dirty) - { - notify(cur_row, K_SPACE); - row_dirty = TRUE; - } - c->set(nuo); // Set new mask value - c->set_dirty(); // Get it dirty! - if (c->on_key(K_TAB) == FALSE) // Test it - { - c->set(old); - xi_set_focus(xiev->v.xi_obj); - } - else - { - mask2str(cur_row); // Update sheet row - edit_field = NULL; // Reset current field - } - check_enabled = TRUE; - } - xi_set_color(xiev->v.xi_obj, XIC_BACK, NORMAL_BACK_COLOR); - } - 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: - set_win(NULL_WIN); - break; - case XIE_XVT_EVENT: - { - EVENT* ep = &xiev->v.xvte; - switch (ep->type) - { - case E_FOCUS: - if (ep->v.active == FALSE) - { - XI_OBJ* itf = xi_get_itf(win()); - const bool ok = (bool)xi_move_focus(itf); - if (!ok) - xiev->refused = TRUE; - } - break; - case E_CHAR: - if (edit_field) - { - const KEY k = e_char_to_key(ep); - switch(k) - { - case K_F1: - check_enabled = FALSE; // Disable checks - edit_field->on_key(K_F1); - set_focus_cell(cur_row, cur_col); - check_enabled = TRUE; // Enable checks -// xiev->refused = TRUE; - break; - case K_F2: - case K_F3: - case K_F8: - case K_F9: - { - check_enabled = FALSE; // Disable checks - if (!row_dirty) notify(cur_row, K_SPACE); - if (edit_field->on_key(k)) - { - mask2str(cur_row); - row_dirty = TRUE; - } - set_focus_cell(cur_row, cur_col); - check_enabled = TRUE; // Enable checks - } - break; - case K_PLUS: - insert(cur_row); - xiev->refused = TRUE; - break; - case K_PREV: - xi_scroll(_list, XI_SCROLL_PGUP); -// xiev->refused = TRUE; - break; - case K_NEXT: - xi_scroll(_list, XI_SCROLL_PGDOWN); -// xiev->refused = TRUE; - break; - case K_HOME: - xi_scroll(_list, XI_SCROLL_FIRST); -// xiev->refused = TRUE; - break; - case K_END: - xi_scroll(_list, XI_SCROLL_LAST); -// xiev->refused = TRUE; - break; - default: - break; - } - } - break; - default: - break; - } - } - break; - default: - break; - } -} - -int TSpreadsheet::add(TToken_string& t) -{ - return _str.add(t); -} - -TToken_string& TSpreadsheet::row(int n) -{ - return (TToken_string&)_str[n]; -} - -#else - -#include - -/////////////////////////////////////////////////////////// -// TSpreadsheet -/////////////////////////////////////////////////////////// - -class TSpreadsheet : public TArray_sheet -{ - TMask _mask; - SPREADSHEET_NOTIFY _notify; - bool _dirty; - - TBit_array _column_disabled; - TArray _disabled; // Array di TBit_array - -protected: - virtual bool on_key(KEY key); - KEY edit(int n); - bool notify(int r, KEY k); - - TMask_field* field(short id) const; - - void mask2str(int riga); - void str2mask(int riga); - -public: - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, - const char* head, WINDOW parent); - - TArray& rows_array() const { return data(); } - - TMask& mask() { return _mask; } - void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } - void set_dirty(bool spork = TRUE) { _dirty = spork;} - bool dirty() const { return _dirty;} - - void enable_column(int col, bool on); - void enable_cell(int row, int column, bool on = TRUE); - bool cell_disabled(int row, int column) const; -}; - -TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, - const char* maskname, int maskno, - const char* head, WINDOW parent) - : TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), - _mask(maskname, NO_MODE, maskno), _notify(NULL) -{} - -bool TSpreadsheet::on_key(KEY k) -{ - switch(k) - { - case K_SHIFT_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 - } - - edit(n); // Edita riga selezionata o creata - - set_front_window(win()); // Aggiorna sheet a video - open(); - } - break; - case K_TAB: - case K_BTAB: - case K_SHIFT_TAB: - dispatch_e_char(get_parent(win()), k); - return TRUE; - default: - break; - } - - return TArray_sheet::on_key(k); -} - -#endif - -TMask_field* TSpreadsheet::field(short id) const -{ - const int pos = _mask.id2pos(id); - if (pos < 0) return NULL; - return &_mask.fld(pos); -} - - -void TSpreadsheet::mask2str(int riga) -{ - TToken_string& r = row(riga); - r.cut(0); - for (short id = FIRST_FIELD; ; id++) - { - const int pos = _mask.id2pos(id); - if (pos < 0) break; - r.add(_mask.fld(pos).get()); - } -#if XVT_OS == XVT_OS_WIN - update_rec(riga); -#endif -} - - -// Certified 50% -void TSpreadsheet::enable_cell(int row, int column, bool on) -{ - TBit_array* ba = (TBit_array*)_disabled.objptr(row); - if (ba == NULL) - { - if (on) return; // Don't waste time and memory - ba = new TBit_array(_column_disabled); - _disabled.add(ba, row); - } - - if (column >= 0) - ba->set(column, !on); - else - { - if (on) - _disabled.destroy(row, FALSE); // Let's save some memory! - else - { -#if XVT_OS == XVT_OS_WIN - ba->set(_columns); // Force right array size -#else - ba->set(32); // Force array size -#endif - ba->set(); // Set all bits - } - } -} - - -void TSpreadsheet::enable_column(int col, bool on) -{ - _column_disabled.set(col, !on); -} - - -// Certified 99% -bool TSpreadsheet::cell_disabled(int row, int column) const -{ - TBit_array* ba = (TBit_array*)_disabled.objptr(row); - if (ba == NULL) return _column_disabled[column]; // Use default - return (*ba)[column]; -} - - -// Certified 75% -void TSpreadsheet::str2mask(int riga) -{ - if (riga == items()) - { - _mask.reset(); - mask2str(riga); - return; - } - TToken_string& r = row(riga); - r.restart(); - - TString80 val; - for (short id = FIRST_FIELD; ; id++) - { - int pos = _mask.id2pos(id); - if (pos < 0) break; - - val = r.get(); // Value to set - - int rid = id; - while (pos >= 0) - { - TMask_field& f = _mask.fld(pos); - f.set(val); - f.enable(!cell_disabled(riga, id-FIRST_FIELD)); - if (f.active() || f.ghost()) - { - if (f.has_check()) f.check(STARTING_CHECK); - f.on_hit(); - } - f.set_dirty(FALSE); - - rid += 100; - pos = _mask.id2pos(rid); - } - } - - _mask.set_caption(format("Riga %d", riga+1)); -} - - -// Certified 100% -bool TSpreadsheet::notify(int n, KEY k) -{ - return _notify ? _notify(n, k) : TRUE; -} - - -// Certified 99% -KEY TSpreadsheet::edit(int n) -{ - str2mask(n); - notify(n, K_SPACE); // Notifica intenzione di modificare - const KEY k = _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); - str2mask(n); - } - } - return k; -} - -/////////////////////////////////////////////////////////// -// TSheet_field -/////////////////////////////////////////////////////////// - -// Certified 100% -TSheet_field::TSheet_field(TMask* m) - : TMask_field(m), _sheet(NULL) -{} - -// Certified 100% -word TSheet_field::class_id() const -{ - return CLASS_SHEET_FIELD; -} - -// Certified 100% -TSheet_field::~TSheet_field() -{ - CHECK(_sheet, "Can't delete NULL sheet"); - delete _sheet; -} - -// Certified 100% -void TSheet_field::reset() -{ - _sheet->destroy(); -} - -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); - - _win = _sheet->win(); - enable_window(_win, enabled()); - show_window(_win, showed()); -} - - -// Certified 100% -TArray& TSheet_field::rows_array() const -{ - return _sheet->rows_array(); -} - - -// Certified 100% -// Ritorna l'indice della prima riga vuota dello sheet -int TSheet_field::first_empty() const -{ - const int max = _sheet->items(); - for (int n = 0; n < max; n++) - if (_sheet->row(n).empty_items()) - break; - return n; -} - - -TToken_string& TSheet_field::row(int n) -{ - const int max = _sheet->items(); - if (n < 0 || n >= max) - { - if (n < 0) n = first_empty(); - if (n >= max) n = _sheet->add(TToken_string(80)); - } - return _sheet->row(n); -} - - -void TSheet_field::force_update(int r) -{ -#if XVTWS == WMWS - _sheet->open(); -#else - _sheet->update(r); -#endif -} - - -void TSheet_field::set_window_data(const char*) -{ - _sheet->set_dirty(FALSE); - set_dirty(FALSE); -} - -void TSheet_field::set_field_data(const char*) -{ - set_dirty(_sheet->dirty()); -} - - -int TSheet_field::items() const -{ - return (int)_sheet->items(); -} - - -void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) -{ - _sheet->set_notify(n); -} - - -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); -} - - -TMask& TSheet_field::sheet_mask() const -{ - return _sheet->mask(); -} - - -bool TSheet_field::on_key(KEY k) -{ - if (k == K_TAB) - { - set_dirty(_sheet->dirty()); - } - return TMask_field::on_key(k); -} +#include +#include +#include +#include + +const short FIRST_FIELD = 101; + +#if XVT_OS == XVT_OS_WIN + +#include +#include + +/////////////////////////////////////////////////////////// +// TSpreadsheet +/////////////////////////////////////////////////////////// + +#define K_PLUS '+' + +class TSpreadsheet : public TWindow +{ + enum { ITF_CID = 0, LIST_CID = 1 }; + + TArray _str; // Array di TToken_strings + TBit_array _column_disabled; + TArray _disabled; // Array di TBit_array + + TMask _mask; + int _columns; + bool _dirty; + + XI_OBJ *_list; + + SPREADSHEET_NOTIFY _notify; + + static void xiev_handler(XI_OBJ *itf, XI_EVENT *xiev); + void init(); + +protected: + void list_handler(XI_EVENT *xiev); + + TMask_field* cell2field(const XI_OBJ* cell) const; + void update_rec(int rec); + void set_focus_cell(int riga, int colonna); + + void mask2str(int n); + void str2mask(int n); + KEY edit(int n); + + TMask_field* field(short id) const; + + int rec2row(int rec); + int row2rec(int row); + + bool notify(int r, KEY k); + +public: + void update(int row); + + TToken_string& row(int n); + TArray& rows_array() const { return (TArray&)_str; } + int add(TToken_string&); + int insert(int rec); + bool destroy(int rec = -1); + + void enable_column(int col, bool on = TRUE); + void enable_cell(int row, int column, bool on = TRUE); + bool cell_disabled(int row, int column) const; + + TMask& mask() { return _mask; } + int items() const { return _str.items(); } + int columns() const { return _columns; } + bool dirty() const { return _dirty; } + void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } + + void set_dirty(bool spork = TRUE) { _dirty = spork; } + + TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, + const char* head, WINDOW parent); +}; + +// Certified 99% +void TSpreadsheet::init() +{ + static bool first = TRUE; + + if (!first) return; + + xvt_set_font(TASK_WIN, FF_FIXED, 0); + DRAW_CTOOLS ct; + win_get_draw_ctools(TASK_WIN, &ct); + xi_set_font(&ct.font); + + xi_init(); + xi_set_pref(XI_PREF_3D_LOOK, TRUE); +// xi_set_pref(XI_PREF_COLOR_LIGHT, COLOR_CYAN); +// xi_set_pref(XI_PREF_COLOR_CTRL, MASK_BACK_COLOR); +// xi_set_pref(XI_PREF_COLOR_DARK, COLOR_GRAY); + + first = FALSE; +} + +TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, + const char* maskname, int maskno, + const char* head, WINDOW parent) + : _mask(maskname, NO_MODE, maskno), _notify(NULL) + +{ + const int NUMBER_WIDTH = 3; + const int MAX_COL = 32; + int width[MAX_COL]; + + init(); + + // Calcolo larghezza massima tabella + + TToken_string header(head); + TToken_string new_header(256); + int i = 0, tot_width = NUMBER_WIDTH+1; + for (const char* h = header.get(); h; h = header.get(), i++) + { + CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); + int w; + char* at = strchr(h, '@'); + if (at) + { + w = atoi(at+1); + *at = '\0'; + } else w = strlen(h); + + width[i] = w+1; + + 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); + if (f->has_query()) w += 2; + + tot_width += w; + new_header.add(h); + } + _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.right -= 20; + rct.bottom -= 8; + + 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_COLOR, DISABLED_BACK_COLOR, NORMAL_COLOR, + LIST_CID); + listdef->v.list->scroll_bar = TRUE; + listdef->v.list->sizable_columns = TRUE; + listdef->v.list->movable_columns = TRUE; + listdef->v.list->scroll_bar_button = TRUE; + listdef->v.list->fixed_columns = 1; + 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 = COLOR_GRAY; + + XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, + XI_ATR_RJUST, 0, NUMBER_WIDTH, NUMBER_WIDTH, ""); + coldef->v.column->heading_platform = TRUE; + coldef->v.column->column_platform = TRUE; + coldef->v.column->center_heading = TRUE; + + for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) + { + const int cid = FIRST_FIELD+i; // Column & Field ID + const TMask_field* f = field(cid); // Field on mask + const int w = width[i] + (f->has_query() ? 2 : 0); // Column width + + long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL; + if (f->class_id() == CLASS_REAL_FIELD) flags |= XI_ATR_RJUST; + if (f->active()) flags |= XI_ATR_ENABLED; + else _column_disabled.set(i); + + coldef = xi_add_column_def(listdef, cid, + flags, cid, w, width[i], (char*)h); + coldef->v.column->heading_platform = TRUE; + coldef->v.column->center_heading = TRUE; + } + + RCT itfrct; + xi_get_def_rect(itfdef, &itfrct); + offset_rect(&itfrct, rct.left, rct.top); + itfrct.bottom++; + + WINDOW win = create_window(W_NO_BORDER, &itfrct, "", 0, parent, + 0, EM_ALL, (EVENT_HANDLER)xi_event, 0L); + CHECK(win, "Can't create a window for the spreadsheet"); + + set_win(win); // Set TWindow::_win + itfdef->v.itf->win = win; + + xi_create(NULL, itfdef); + xi_tree_free(itfdef); + + XI_OBJ* itf = xi_get_itf(win); + _list = xi_get_obj(itf, LIST_CID); +} + + +// 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); + +#ifdef DBG + if (row < 0 || row >= rows) + { + error_box("Line %d is not visible", row); + return 0L; + } +#endif + + return (int)rec[row]; +} + + +// 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::cell2field(const XI_OBJ* cell) const +{ + const int pos = cell->v.cell.column; + + int num; + XI_OBJ** column = xi_get_member_list(_list, &num); + + TMask_field* good = NULL; + for (short id = column[pos]->cid; ; id += 100) + { + TMask_field* f = field(id); + if (f == NULL) break; + good = f; + if (f->active()) break; + } + + return good; +} + +void TSpreadsheet::update_rec(int rec) +{ + const int riga = rec2row(rec); + if (riga >= 0) + { + XI_OBJ row; + XI_MAKE_ROW(&row, _list, riga); + xi_cell_request(&row); // Update internal values + xi_set_row_height(&row, CHARY+1); // Force row updating + } +} + +void TSpreadsheet::set_focus_cell(int riga, int colonna) +{ + set_front_window(win()); + XI_OBJ cell; + XI_MAKE_CELL(&cell, _list, rec2row(riga), colonna); + xi_set_focus(&cell); +} + + +int TSpreadsheet::insert(int rec) +{ + const bool ok = notify(rec, K_INS); + if (!ok) return -1; + + TToken_string s; // Empty row + const int r = _str.insert(s, rec); + _disabled.insert(NULL, rec); + + xi_insert_row(_list, INT_MAX); + xi_cell_request(_list); + + return r; +} + + +bool TSpreadsheet::destroy(int rec) +{ + bool ok = TRUE; + + if (rec < 0) + { + _disabled.destroy(); + _str.destroy(); + } + 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) xi_cell_request(_list); + + return ok; +} + + +void TSpreadsheet::update(int row) +{ + if (row < 0) + { + xi_cell_request(_list); + xi_scroll(_list, XI_SCROLL_FIRST); + set_front_window(win()); + } + else + update_rec(row); +} + + +void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev) +{ + TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf); + CHECK(es, "NULL Edit sheet in xi event"); + es->list_handler(xiev); +} + + +// Certified 75% +void TSpreadsheet::list_handler(XI_EVENT *xiev) +{ + static TMask_field* edit_field = NULL; // Current edit field + static int cur_row = 0, cur_col = 0; // Current cell + static bool row_dirty = FALSE; // Current row changed + static bool check_enabled = TRUE; // Perform OFF_ROW checks + + switch (xiev->type) + { + case XIE_GET_FIRST: + { + const long max = items(); + if (max <= 0L) + { + xiev->refused = TRUE; + break; + } + long n = max * (long)xiev->v.rec_request.percent / 100L; + if (n < 0L) n = 0L; + xiev->v.rec_request.data_rec = n; + } + 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 (src && *src && f->class_id() == CLASS_REAL_FIELD) + { + src = f->picture_data(src, FALSE); // Get formatted string + } + if (field(cid)->has_query()) + { + xiev->v.cell_request.button = + xiev->v.cell_request.button_on_focus = TRUE; + } + if (cell_disabled(rec, col)) + xiev->v.cell_request.back_color = MASK_BACK_COLOR; + } + } else src = format("%d", rec+1); + + const int len = xiev->v.cell_request.len; + char* dst = xiev->v.cell_request.s; + if (src) + { + strncpy(dst, src, len); + if (isspace(*dst)) + { + TFixed_string d(dst); + d.ltrim(); + } + } + else + *dst = '\0'; + } + break; + case XIE_BUTTON: + if (xiev->v.xi_obj->type == XIT_CELL) + { + if (edit_field) + { + const char* val = xi_get_text(xiev->v.xi_obj, NULL, -1); + edit_field->set(val); // Update current cell + check_enabled = FALSE; // Disable checks + if (!row_dirty) notify(cur_row, K_SPACE); + if (edit_field->on_key(K_F9)) // Show search sheet + { + mask2str(cur_row); // Update row + row_dirty = TRUE; + } + check_enabled = TRUE; // Enable checks + xi_set_focus(xiev->v.xi_obj); // Restore focus to cell + } + } else + if (xiev->v.xi_obj->type == XIT_LIST) + insert(-1); + break; + case XIE_DBL_CELL: + { + check_enabled = FALSE; + cur_row = row2rec(xiev->v.xi_obj->v.cell.row); + cur_col = xiev->v.xi_obj->v.cell.column; + const KEY k = edit(cur_row); + if (k == K_ENTER) + { + update_rec(cur_row); + row_dirty = TRUE; + } + xi_set_focus(xiev->v.xi_obj); + check_enabled = TRUE; + } + break; + case XIE_ON_ROW: + { + const int rec = row2rec(xiev->v.xi_obj->v.row); + if (rec < items()) + { + cur_row = rec; + str2mask(rec); + row_dirty = FALSE; + } + else + xiev->refused = TRUE; + } + break; + case XIE_OFF_ROW: + if (row_dirty && check_enabled) + { + check_enabled = FALSE; // Avoid recursion! + set_dirty(); + str2mask(cur_row); // It shouldn't have to be necessary + bool ok = _mask.check_fields(); + if (ok) + { + mask2str(cur_row); + ok = notify(cur_row, K_ENTER); // Notify edit + } + else + { + xiev->refused = TRUE; + set_dirty(2); // Set error status + set_focus_cell(cur_row, cur_col); + } + check_enabled = TRUE; + } + break; + case XIE_ON_CELL: + { + TMask_field* f = cell2field(xiev->v.xi_obj); + const int col = (f->dlg() - FIRST_FIELD) % 100; + if (!cell_disabled(cur_row, col)) + { + edit_field = f; + cur_col = xiev->v.xi_obj->v.cell.column; + xi_set_color(xiev->v.xi_obj, XIC_BACK, FOCUS_BACK_COLOR); + } + else + { + xiev->refused = TRUE; // Refuse focus on disabled cells + } + } + break; + case XIE_OFF_CELL: + if (edit_field && check_enabled) + { + TMask_field* c = edit_field; // Save field, it could turn out to be NULL on error + const TString80 old(c->get()); // Save old value on mask + const TString80 nuo(c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE)); + if (old != nuo) + { + check_enabled = FALSE; + if (!row_dirty) + { + notify(cur_row, K_SPACE); + row_dirty = TRUE; + } + c->set(nuo); // Set new mask value + c->set_dirty(); // Get it dirty! + if (c->on_key(K_TAB) == FALSE) // Test it + { + c->set(old); + xi_set_focus(xiev->v.xi_obj); + } + else + { + mask2str(cur_row); // Update sheet row + edit_field = NULL; // Reset current field + } + check_enabled = TRUE; + } + xi_set_color(xiev->v.xi_obj, XIC_BACK, NORMAL_BACK_COLOR); + } + 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: + set_win(NULL_WIN); + break; + case XIE_XVT_EVENT: + { + EVENT* ep = &xiev->v.xvte; + switch (ep->type) + { + case E_FOCUS: + if (ep->v.active == FALSE) + { + XI_OBJ* itf = xi_get_itf(win()); + const bool ok = (bool)xi_move_focus(itf); + if (!ok) + xiev->refused = TRUE; + } + break; + case E_CHAR: + if (edit_field) + { + const KEY k = e_char_to_key(ep); + switch(k) + { + case K_F1: + check_enabled = FALSE; // Disable checks + edit_field->on_key(K_F1); + set_focus_cell(cur_row, cur_col); + check_enabled = TRUE; // Enable checks +// xiev->refused = TRUE; + break; + case K_F2: + case K_F3: + case K_F8: + case K_F9: + { + check_enabled = FALSE; // Disable checks + if (!row_dirty) notify(cur_row, K_SPACE); + if (edit_field->on_key(k)) + { + mask2str(cur_row); + row_dirty = TRUE; + } + set_focus_cell(cur_row, cur_col); + check_enabled = TRUE; // Enable checks + } + break; + case K_PLUS: + insert(cur_row); + xiev->refused = TRUE; + break; + case K_PREV: + xi_scroll(_list, XI_SCROLL_PGUP); +// xiev->refused = TRUE; + break; + case K_NEXT: + xi_scroll(_list, XI_SCROLL_PGDOWN); +// xiev->refused = TRUE; + break; + case K_HOME: + xi_scroll(_list, XI_SCROLL_FIRST); +// xiev->refused = TRUE; + break; + case K_END: + xi_scroll(_list, XI_SCROLL_LAST); +// xiev->refused = TRUE; + break; + default: + break; + } + } + break; + default: + break; + } + } + break; + default: + break; + } +} + +int TSpreadsheet::add(TToken_string& t) +{ + return _str.add(t); +} + +TToken_string& TSpreadsheet::row(int n) +{ + return (TToken_string&)_str[n]; +} + +#else + +#include + +/////////////////////////////////////////////////////////// +// TSpreadsheet +/////////////////////////////////////////////////////////// + +class TSpreadsheet : public TArray_sheet +{ + TMask _mask; + SPREADSHEET_NOTIFY _notify; + bool _dirty; + + TBit_array _column_disabled; + TArray _disabled; // Array di TBit_array + +protected: + virtual bool on_key(KEY key); + KEY edit(int n); + bool notify(int r, KEY k); + + TMask_field* field(short id) const; + + void mask2str(int riga); + void str2mask(int riga); + +public: + TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, + const char* head, WINDOW parent); + + TArray& rows_array() const { return data(); } + + TMask& mask() { return _mask; } + void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } + void set_dirty(bool spork = TRUE) { _dirty = spork;} + bool dirty() const { return _dirty;} + + void enable_column(int col, bool on); + void enable_cell(int row, int column, bool on = TRUE); + bool cell_disabled(int row, int column) const; +}; + +TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, + const char* maskname, int maskno, + const char* head, WINDOW parent) + : TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), + _mask(maskname, NO_MODE, maskno), _notify(NULL) +{} + +bool TSpreadsheet::on_key(KEY k) +{ + switch(k) + { + case K_SHIFT_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 + } + + edit(n); // Edita riga selezionata o creata + + set_front_window(win()); // Aggiorna sheet a video + open(); + } + break; + case K_TAB: + case K_BTAB: + case K_SHIFT_TAB: + dispatch_e_char(get_parent(win()), k); + return TRUE; + default: + break; + } + + return TArray_sheet::on_key(k); +} + +#endif + +TMask_field* TSpreadsheet::field(short id) const +{ + const int pos = _mask.id2pos(id); + if (pos < 0) return NULL; + return &_mask.fld(pos); +} + + +void TSpreadsheet::mask2str(int riga) +{ + TToken_string& r = row(riga); + r.cut(0); + for (short id = FIRST_FIELD; ; id++) + { + const int pos = _mask.id2pos(id); + if (pos < 0) break; + r.add(_mask.fld(pos).get()); + } +#if XVT_OS == XVT_OS_WIN + update_rec(riga); +#endif +} + + +// Certified 50% +void TSpreadsheet::enable_cell(int row, int column, bool on) +{ + TBit_array* ba = (TBit_array*)_disabled.objptr(row); + if (ba == NULL) + { + if (on) return; // Don't waste time and memory + ba = new TBit_array(_column_disabled); + _disabled.add(ba, row); + } + + if (column >= 0) + ba->set(column, !on); + else + { + if (on) + _disabled.destroy(row, FALSE); // Let's save some memory! + else + { +#if XVT_OS == XVT_OS_WIN + ba->set(_columns); // Force right array size +#else + ba->set(32); // Force array size +#endif + ba->set(); // Set all bits + } + } +} + + +void TSpreadsheet::enable_column(int col, bool on) +{ + _column_disabled.set(col, !on); +} + + +// Certified 99% +bool TSpreadsheet::cell_disabled(int row, int column) const +{ + TBit_array* ba = (TBit_array*)_disabled.objptr(row); + if (ba == NULL) return _column_disabled[column]; // Use default + return (*ba)[column]; +} + + +// Certified 75% +void TSpreadsheet::str2mask(int riga) +{ + if (riga == items()) + { + _mask.reset(); + mask2str(riga); + return; + } + TToken_string& r = row(riga); + r.restart(); + + TString80 val; + for (short id = FIRST_FIELD; ; id++) + { + int pos = _mask.id2pos(id); + if (pos < 0) break; + + val = r.get(); // Value to set + + int rid = id; + while (pos >= 0) + { + TMask_field& f = _mask.fld(pos); + f.set(val); + f.enable(!cell_disabled(riga, id-FIRST_FIELD)); + if (f.active() || f.ghost()) + { + if (f.has_check()) f.check(STARTING_CHECK); + f.on_hit(); + } + f.set_dirty(FALSE); + + rid += 100; + pos = _mask.id2pos(rid); + } + } + + _mask.set_caption(format("Riga %d", riga+1)); +} + + +// Certified 100% +bool TSpreadsheet::notify(int n, KEY k) +{ + return _notify ? _notify(n, k) : TRUE; +} + + +// Certified 99% +KEY TSpreadsheet::edit(int n) +{ + str2mask(n); + notify(n, K_SPACE); // Notifica intenzione di modificare + const KEY k = _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); + str2mask(n); + } + } + return k; +} + +/////////////////////////////////////////////////////////// +// TSheet_field +/////////////////////////////////////////////////////////// + +// Certified 100% +TSheet_field::TSheet_field(TMask* m) + : TMask_field(m), _sheet(NULL) +{} + +// Certified 100% +word TSheet_field::class_id() const +{ + return CLASS_SHEET_FIELD; +} + +// Certified 100% +TSheet_field::~TSheet_field() +{ + CHECK(_sheet, "Can't delete NULL sheet"); + delete _sheet; +} + +// Certified 100% +void TSheet_field::reset() +{ + _sheet->destroy(); +} + +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); + + _win = _sheet->win(); + enable_window(_win, enabled()); + show_window(_win, showed()); +} + + +// Certified 100% +TArray& TSheet_field::rows_array() const +{ + return _sheet->rows_array(); +} + + +// Certified 100% +// Ritorna l'indice della prima riga vuota dello sheet +int TSheet_field::first_empty() const +{ + const int max = _sheet->items(); + for (int n = 0; n < max; n++) + if (_sheet->row(n).empty_items()) + break; + return n; +} + + +TToken_string& TSheet_field::row(int n) +{ + const int max = _sheet->items(); + if (n < 0 || n >= max) + { + if (n < 0) n = first_empty(); + if (n >= max) n = _sheet->add(TToken_string(80)); + } + return _sheet->row(n); +} + + +void TSheet_field::force_update(int r) +{ +#if XVTWS == WMWS + _sheet->open(); +#else + _sheet->update(r); +#endif +} + + +void TSheet_field::set_window_data(const char*) +{ + _sheet->set_dirty(FALSE); + set_dirty(FALSE); +} + +void TSheet_field::set_field_data(const char*) +{ + set_dirty(_sheet->dirty()); +} + + +int TSheet_field::items() const +{ + return (int)_sheet->items(); +} + + +void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) +{ + _sheet->set_notify(n); +} + + +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); +} + + +TMask& TSheet_field::sheet_mask() const +{ + return _sheet->mask(); +} + + +bool TSheet_field::on_key(KEY k) +{ + if (k == K_TAB) + { + const bool spork = _sheet->dirty(); + if (spork < FALSE || spork > TRUE) + return error_box("Tabella inconsistente: correggere i valori errati prima di uscirne"); + set_dirty(spork); + } + return TMask_field::on_key(k); +}