aef90e02ab
str2mask e sua sorella mask2str. git-svn-id: svn://10.65.10.50/trunk@1266 c028cbd2-c16b-5b4b-a496-9718f37d4682
1447 lines
35 KiB
C++
Executable File
1447 lines
35 KiB
C++
Executable File
#include <msksheet.h>
|
|
#include <real.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
const short FIRST_FIELD = 101;
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
|
|
#include <xil.h>
|
|
#include <colors.h>
|
|
|
|
extern "C"
|
|
{
|
|
#include <cpb.h>
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TSpreadsheet
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TSpreadsheet : public TWindow
|
|
{
|
|
friend class TSheet_field;
|
|
|
|
enum { ITF_CID = 0, LIST_CID = 1 };
|
|
|
|
TString_array _str; // Array di TToken_strings
|
|
TBit_array _column_disabled;
|
|
TArray _disabled; // Array di TBit_array
|
|
|
|
TMask _mask;
|
|
int _columns;
|
|
bool _firstfocus, _active;
|
|
|
|
XI_OBJ *_list, *_itf;
|
|
|
|
SPREADSHEET_NOTIFY _notify;
|
|
|
|
TSheet_field* _owner; // Owner
|
|
|
|
TMask_field* _edit_field; // Current edit field
|
|
int _cur_row, _cur_rec, _cur_col; // Current cell
|
|
bool _row_dirty; // Current row changed
|
|
bool _check_enabled; // Perform OFF_ROW and OFF_CELL checks
|
|
bool _update; // It's safe to update the display
|
|
|
|
void init();
|
|
friend void XVT_CALLCONV1 xiev_handler(XI_OBJ *itf, XI_EVENT *xiev);
|
|
protected:
|
|
void list_handler(XI_EVENT *xiev);
|
|
|
|
TMask_field* col2field(int pos) const;
|
|
TMask_field* cell2field(const XI_OBJ* cell) const;
|
|
void update_rec(int rec);
|
|
TMask_field* field(short id) const;
|
|
|
|
int rec2row(int rec);
|
|
int row2rec(int& row);
|
|
int set_pos(int row, int col) { _cur_col = col; _cur_row = row; return _cur_rec = row2rec(_cur_row); }
|
|
|
|
bool notify(int row, KEY k);
|
|
void notify_change();
|
|
|
|
public:
|
|
void update(int row);
|
|
|
|
TToken_string& row(int n) { return _str.row(n); }
|
|
int add(const TToken_string& s) { return _str.add(s); }
|
|
int add(TToken_string* s) { return _str.add(s); }
|
|
int insert(int rec);
|
|
bool destroy(int rec = -1);
|
|
TString_array& rows_array() { return _str; }
|
|
|
|
void set_focus_cell(int riga, int colonna);
|
|
void activate(bool on);
|
|
void enable_column(int col, bool on = TRUE);
|
|
void enable_cell(int row, int column, bool on = TRUE);
|
|
bool cell_disabled(int row, int column) const;
|
|
|
|
TMask& sheet_mask() { return _mask; }
|
|
TMask& mask() const;
|
|
|
|
void mask2str(int n);
|
|
void str2mask(int n);
|
|
KEY edit(int n);
|
|
|
|
int items() const { return _str.items(); }
|
|
int selected() const { return _cur_rec; }
|
|
int columns() const { return _columns; }
|
|
|
|
bool dirty() const { return _owner->dirty(); }
|
|
void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork); }
|
|
|
|
bool active() const { return _active; }
|
|
bool test_focus_change();
|
|
|
|
void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; }
|
|
|
|
TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno,
|
|
const char* head, WINDOW parent, TSheet_field* owner);
|
|
virtual ~TSpreadsheet();
|
|
};
|
|
|
|
// Certified 100%
|
|
void TSpreadsheet::init()
|
|
{
|
|
static bool first = TRUE;
|
|
if (!first) return;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy,
|
|
const char* maskname, int maskno,
|
|
const char* head, WINDOW parent,
|
|
TSheet_field* o)
|
|
: _mask(maskname, maskno), _notify(NULL), _edit_field(NULL),
|
|
_owner(o), _cur_row(0), _cur_col(0), _active(TRUE),
|
|
_row_dirty(FALSE), _check_enabled(TRUE), _firstfocus(TRUE), _update(TRUE)
|
|
{
|
|
const int NUMBER_WIDTH = 3;
|
|
const int MAX_COL = 32;
|
|
int m_width[MAX_COL], v_width[MAX_COL];
|
|
int fixed_columns = 1; // Number of fixed columns
|
|
|
|
init();
|
|
|
|
// Calcolo larghezza massima tabella
|
|
|
|
TToken_string header(head);
|
|
TToken_string new_header(256);
|
|
int i = 0, tot_width = NUMBER_WIDTH+1;
|
|
int f_width = tot_width<<1; // Stima larghezza colonne fisse
|
|
int max_width = f_width; // Stima larghezza della colonna piu' grande
|
|
|
|
for (const char* h = header.get(); h; h = header.get(), i++)
|
|
{
|
|
CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i);
|
|
|
|
const int cid = FIRST_FIELD+i; // Column & Field ID
|
|
const TMask_field* f = field(cid); // Field on mask
|
|
CHECKD(f, "The spreadsheet mask needs ALSO field ", cid);
|
|
|
|
TString80 testa(h);
|
|
const int at = testa.find('@');
|
|
int m, v;
|
|
if (at >= 0)
|
|
{
|
|
const TString& wi = testa.mid(at+1);
|
|
m = atoi(wi);
|
|
if (wi.find('F') >= 0)
|
|
{
|
|
fixed_columns++;
|
|
f_width += m+1;
|
|
}
|
|
testa.cut(at);
|
|
v = max(at, m+(f->has_query() ? 1 : 0));
|
|
}
|
|
else
|
|
{
|
|
m = testa.len();
|
|
v = m+(f->has_query() ? 1 : 0);
|
|
}
|
|
|
|
#ifdef DBG
|
|
if (f->is_edit() && m < f->size())
|
|
{
|
|
yesnofatal_box("Il campo %d della maschera e' piu' largo della colonna %s",
|
|
cid, (const char*)testa);
|
|
m = f->size();
|
|
}
|
|
#endif
|
|
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, MASK_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; // (v_width[i]*CHARX-16) >> 1;
|
|
// coldef->v.column->icon_y = (CHARY-16) >> 1;
|
|
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_REAL_FIELD:
|
|
flags |= XI_ATR_RJUST; break;
|
|
case CLASS_BUTTON_FIELD:
|
|
flags |= XI_ATR_SELECTABLE; break;
|
|
default:
|
|
break;
|
|
}
|
|
if (f->active()) flags |= XI_ATR_ENABLED | XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT;
|
|
else _column_disabled.set(i);
|
|
|
|
coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i], m_width[i],
|
|
(char*)(const char*)testo);
|
|
coldef->v.column->heading_platform = TRUE;
|
|
coldef->v.column->center_heading = TRUE;
|
|
// if (acqua == CLASS_BUTTON_FIELD)
|
|
// {
|
|
// const TFixed_string testa(header.get(i));
|
|
// const int diesis = testa.find('#');
|
|
// if (diesis > 0)
|
|
// {
|
|
// _button = testa.mid(diesis+1);
|
|
// coldef->v.column->icon_x = (v_width[i]*CHARX-16) >> 1;
|
|
// coldef->v.column->icon_y = (CHARY-16) >> 1;
|
|
// coldef->v.column->column_platform = TRUE;
|
|
// }
|
|
// else _button = testo;
|
|
// }
|
|
}
|
|
|
|
RCT itfrct;
|
|
xi_get_def_rect(itfdef, &itfrct);
|
|
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(NULL, itfdef); // Create the whole thing!
|
|
xi_tree_free(itfdef); // Free definitions
|
|
|
|
_itf = xi_get_itf(win); // Store useful references for later use
|
|
_list = xi_get_obj(_itf, LIST_CID);
|
|
}
|
|
|
|
TSpreadsheet::~TSpreadsheet()
|
|
{
|
|
set_win(NULL_WIN);
|
|
}
|
|
|
|
|
|
// Converts a row number in the correspondig record number
|
|
int TSpreadsheet::row2rec(int& row)
|
|
{
|
|
int rows;
|
|
const long* rec = xi_get_list_info(_list, &rows);
|
|
|
|
int r = -1;
|
|
if (row < 0)
|
|
{
|
|
row = 0;
|
|
r = (int)rec[row]-1;
|
|
}
|
|
else
|
|
if (row >= rows)
|
|
{
|
|
row = rows-1;
|
|
r = (int)rec[row]+1;
|
|
}
|
|
else
|
|
r = (int)rec[row];
|
|
|
|
CHECKD(r >= 0 && r <= items(), "Sheet line out of range: ", row);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
// Converts a row number in the correspondig record number
|
|
int TSpreadsheet::rec2row(int record)
|
|
{
|
|
int rows;
|
|
const long* rec = xi_get_list_info(_list, &rows);
|
|
int r = int(record - rec[0]);
|
|
if (r < 0 || r >= rows)
|
|
r = -1;
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
// Retrieves the corresponding field of the mask from a spredsheet cell
|
|
TMask_field* TSpreadsheet::col2field(int pos) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_list, &num);
|
|
|
|
TMask_field* good = NULL;
|
|
for (short id = column[pos]->cid; ; id += 100)
|
|
{
|
|
TMask_field* f = field(id);
|
|
if (f == NULL) break; // End of search
|
|
good = f; // We've found a field with the proper ID ...
|
|
if (f->active()) break; // ... and it's active: end of search
|
|
}
|
|
|
|
CHECKD(good, "Can't find field corresponding to column ", pos);
|
|
return good;
|
|
}
|
|
|
|
|
|
// Retrieves the corresponding field of the mask from a spredsheet cell
|
|
TMask_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const
|
|
{
|
|
return col2field(cell->v.cell.column);
|
|
}
|
|
|
|
void TSpreadsheet::update_rec(int rec)
|
|
{
|
|
const int riga = rec2row(rec);
|
|
if (riga >= 0)
|
|
{
|
|
XI_OBJ row;
|
|
XI_MAKE_ROW(&row, _list, riga);
|
|
xi_cell_request(&row); // Update internal values
|
|
if (_update)
|
|
xi_set_row_height(&row, CHARY+1); // Force row updating
|
|
}
|
|
}
|
|
|
|
|
|
void TSpreadsheet::set_focus_cell(int riga, int colonna)
|
|
{
|
|
xvt_scr_set_focus_vobj(win());
|
|
const int r = row2rec(riga);
|
|
|
|
for (; colonna < _columns; colonna++)
|
|
if (!cell_disabled(r, colonna-1))
|
|
break;
|
|
|
|
if (colonna < _columns)
|
|
{
|
|
XI_OBJ cell;
|
|
XI_MAKE_CELL(&cell, _list, riga, colonna);
|
|
xi_set_focus(&cell);
|
|
|
|
if (_edit_field == NULL)
|
|
{
|
|
_cur_row = riga;
|
|
_cur_col = colonna;
|
|
_cur_rec = r;
|
|
_edit_field = col2field(colonna);
|
|
str2mask(_cur_rec);
|
|
_row_dirty = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int TSpreadsheet::insert(int rec)
|
|
{
|
|
const bool ok = notify(rec, K_INS);
|
|
if (!ok) return -1;
|
|
|
|
TToken_string s(80); // Empty row
|
|
const int r = _str.insert(s, rec);
|
|
_disabled.insert(NULL, rec);
|
|
|
|
xi_insert_row(_list, INT_MAX);
|
|
xi_cell_request(_list);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
bool TSpreadsheet::destroy(int rec)
|
|
{
|
|
bool ok = TRUE;
|
|
|
|
if (rec < 0)
|
|
{
|
|
_disabled.destroy();
|
|
_str.destroy();
|
|
set_dirty(_row_dirty = FALSE);
|
|
}
|
|
else
|
|
{
|
|
_disabled.destroy(rec, TRUE); // Destroy enable info
|
|
ok = _str.destroy(rec, TRUE); // Destroy line
|
|
enable_cell(_str.items(), -1); // Enable last line
|
|
}
|
|
|
|
if (ok && mask().is_running())
|
|
update(-1);
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
void TSpreadsheet::update(int row)
|
|
{
|
|
if (row < 0)
|
|
{
|
|
xi_cell_request(_list); // Force updatde
|
|
if (_update)
|
|
xi_scroll(_list, XI_SCROLL_FIRST);
|
|
}
|
|
else
|
|
update_rec(row);
|
|
}
|
|
|
|
|
|
void TSpreadsheet::notify_change()
|
|
{
|
|
if (!_row_dirty)
|
|
{
|
|
notify(_cur_rec, K_SPACE);
|
|
_row_dirty = TRUE;
|
|
set_dirty();
|
|
}
|
|
}
|
|
|
|
|
|
bool TSpreadsheet::test_focus_change()
|
|
{
|
|
bool ok = dirty() != 3;
|
|
if (ok && _row_dirty)
|
|
{
|
|
str2mask(selected());
|
|
ok = sheet_mask().check_fields();
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
//void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev)
|
|
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)
|
|
{
|
|
notify_change();
|
|
_edit_field->set_focusdirty(_cell_dirty = TRUE);
|
|
}
|
|
break;
|
|
case XIE_BUTTON:
|
|
if (xiev->v.xi_obj->type == XIT_CELL)
|
|
dispatch_e_char(win(), K_F9);
|
|
else
|
|
if (xiev->v.xi_obj->type == XIT_LIST)
|
|
insert(-1);
|
|
break;
|
|
case XIE_SELECT:
|
|
if (xiev->v.xi_obj->type == XIT_ROW)
|
|
{
|
|
_check_enabled = FALSE;
|
|
|
|
const int oldrec = _cur_rec;
|
|
set_pos(xiev->v.select.xi_obj->v.row, xiev->v.select.column);
|
|
if (oldrec != _cur_rec)
|
|
{
|
|
str2mask(_cur_rec);
|
|
_row_dirty = FALSE;
|
|
}
|
|
|
|
update(_cur_rec);
|
|
|
|
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;
|
|
set_pos(xiev->v.xi_obj->v.cell.row, xiev->v.xi_obj->v.cell.column);
|
|
|
|
if (oldrec != _cur_rec || !_row_dirty)
|
|
{
|
|
_row_dirty = FALSE;
|
|
notify_change();
|
|
}
|
|
const KEY k = edit(_cur_rec);
|
|
if (k == K_ENTER)
|
|
{
|
|
update_rec(_cur_rec);
|
|
_row_dirty = TRUE;
|
|
} else
|
|
if (k == K_DEL)
|
|
_row_dirty = _cell_dirty = FALSE;
|
|
|
|
if (!cell_disabled(_cur_rec, _cur_col-1))
|
|
set_focus_cell(_cur_row, _cur_col);
|
|
_check_enabled = TRUE;
|
|
}
|
|
break;
|
|
case XIE_ON_LIST:
|
|
if (_firstfocus) // Trick to avoid the sheet to keep the focus forever ...
|
|
{ // .. it costed me two day worth of hard work!
|
|
xiev->refused = TRUE;
|
|
_firstfocus = FALSE;
|
|
}
|
|
else
|
|
mask().set_focus_win(win(), FALSE);
|
|
break;
|
|
case XIE_OFF_LIST:
|
|
break;
|
|
case XIE_ON_ROW:
|
|
if (_check_enabled)
|
|
{
|
|
set_pos(xiev->v.xi_obj->v.row, _cur_col);
|
|
if (_cur_rec < items())
|
|
{
|
|
str2mask(_cur_rec);
|
|
_row_dirty = FALSE;
|
|
}
|
|
else
|
|
{
|
|
_cur_row = _cur_rec = 0;
|
|
xiev->refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case XIE_OFF_ROW:
|
|
if (_row_dirty && _check_enabled)
|
|
{
|
|
_check_enabled = FALSE; // Avoid recursion!
|
|
// str2mask(_cur_rec); // It shouldn't have to be necessary
|
|
bool ok = sheet_mask().check_fields();
|
|
if (ok)
|
|
{
|
|
const int next = _cur_rec + (_lastab == K_TAB ? +1 : -1);
|
|
_update = rec2row(next) >= 0; // Disable update if next record is not visible
|
|
mask2str(_cur_rec); // Update sheet with mask contents
|
|
ok = notify(_cur_rec, K_ENTER); // Notify edit
|
|
_update = TRUE; // Reenable update
|
|
}
|
|
if (!ok)
|
|
xiev->refused = TRUE;
|
|
else
|
|
xvt_statbar_refresh();
|
|
|
|
_check_enabled = TRUE;
|
|
}
|
|
break;
|
|
case XIE_ON_CELL:
|
|
if (_check_enabled)
|
|
{
|
|
TMask_field* f = cell2field(xiev->v.xi_obj);
|
|
const int col = (f->dlg()-FIRST_FIELD) % 100;
|
|
if (cell_disabled(_cur_rec, col)) // If the cell is disabled ...
|
|
{
|
|
dispatch_e_char(win(), _lastab); // ... skip to the next one.
|
|
}
|
|
else
|
|
{
|
|
_edit_field = f;
|
|
_cur_col = xiev->v.xi_obj->v.cell.column;
|
|
_edit_field->set_focusdirty(_cell_dirty = FALSE);
|
|
}
|
|
}
|
|
break;
|
|
case XIE_OFF_CELL:
|
|
if (_edit_field && _check_enabled)
|
|
{
|
|
_check_enabled = FALSE;
|
|
if (_cell_dirty)
|
|
{
|
|
TMask_field* c = _edit_field; // Save field, it could turn out to be NULL on error
|
|
const char* nuo = c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE);
|
|
c->set(nuo); // Set new mask value
|
|
c->set_dirty(); // Get it dirty!
|
|
if (c->on_key(c->is_edit() ? K_TAB : K_SPACE) == FALSE) // Test it
|
|
xiev->refused = *nuo != '\0';
|
|
else
|
|
mask2str(_cur_rec); // Update sheet row
|
|
}
|
|
if (!xiev->refused)
|
|
_edit_field = NULL; // Reset current field
|
|
_check_enabled = TRUE;
|
|
}
|
|
break;
|
|
case XIE_GET_PERCENT:
|
|
{
|
|
const long rec = xiev->v.get_percent.record;
|
|
long n = items(); if (n < 1) n = 1;
|
|
xiev->v.get_percent.percent = int(rec * 100L / n);
|
|
}
|
|
break;
|
|
case XIE_CLEANUP:
|
|
break;
|
|
case XIE_XVT_EVENT:
|
|
{
|
|
EVENT* ep = &xiev->v.xvte;
|
|
switch (ep->type)
|
|
{
|
|
case E_FOCUS:
|
|
if (_check_enabled && ep->v.active == FALSE)
|
|
{
|
|
const bool ok = (bool)xi_move_focus(_itf);
|
|
if (!ok)
|
|
{
|
|
set_dirty(3);
|
|
xiev->refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case E_CHAR:
|
|
if (_edit_field)
|
|
{
|
|
const KEY k = e_char_to_key(ep);
|
|
switch(k)
|
|
{
|
|
case K_TAB:
|
|
case K_BTAB:
|
|
_lastab = k;
|
|
break;
|
|
case K_UP:
|
|
_lastab = K_BTAB;
|
|
break;
|
|
case K_DOWN:
|
|
_lastab = K_TAB;
|
|
break;
|
|
case K_F1:
|
|
_check_enabled = FALSE; // Disable checks
|
|
_edit_field->on_key(K_F1);
|
|
set_focus_cell(_cur_row, _cur_col);
|
|
_check_enabled = TRUE; // Enable checks
|
|
break;
|
|
case K_F2:
|
|
case K_F3:
|
|
case K_F8:
|
|
case K_F9:
|
|
case K_F11:
|
|
if (_check_enabled && active())
|
|
{
|
|
_check_enabled = FALSE; // Disable checks
|
|
notify_change();
|
|
if (_edit_field->on_key(k) == FALSE && k == K_F9)
|
|
{
|
|
_edit_field = &_mask.fld(_mask.focus_field());
|
|
const short foca = _edit_field->dlg();
|
|
const int col = (foca - FIRST_FIELD) % 100 +1;
|
|
if (col > 0 && col != _cur_col)
|
|
{
|
|
_cur_col = col;
|
|
dispatch_e_char(win(), K_F9);
|
|
}
|
|
}
|
|
mask2str(_cur_rec);
|
|
set_focus_cell(_cur_row, _cur_col);
|
|
_check_enabled = TRUE; // Enable checks
|
|
}
|
|
break;
|
|
case K_PREV:
|
|
case K_NEXT:
|
|
case K_ESC:
|
|
if (xi_move_focus(_itf))
|
|
dispatch_e_char(parent(), k);
|
|
break;
|
|
case K_ENTER:
|
|
case K_SHIFT+K_ENTER:
|
|
if (xi_move_focus(_itf))
|
|
dispatch_e_char(parent(), k == K_ENTER ? K_TAB : K_BTAB);
|
|
break;
|
|
case K_CTRL+K_PREV:
|
|
xi_scroll(_list, XI_SCROLL_PGUP);
|
|
break;
|
|
case K_CTRL+K_NEXT:
|
|
xi_scroll(_list, XI_SCROLL_PGDOWN);
|
|
break;
|
|
case K_CTRL+K_HOME:
|
|
xi_scroll(_list, XI_SCROLL_FIRST);
|
|
break;
|
|
case K_CTRL+K_END:
|
|
xi_scroll(_list, XI_SCROLL_LAST);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TSpreadsheet::activate(bool on)
|
|
{
|
|
_active = on;
|
|
|
|
const dword old = xi_get_attrib(_list);
|
|
dword att = on ? (old & ~XI_ATR_NAVIGATE) : (old | XI_ATR_NAVIGATE);
|
|
if (old != att)
|
|
{
|
|
int num;
|
|
XI_OBJ** columns = xi_get_member_list(_list, &num);
|
|
|
|
xi_move_focus(_itf); // Set focus to interface
|
|
if (on)
|
|
att |= XI_ATR_TABWRAP;
|
|
else
|
|
att &= ~XI_ATR_TABWRAP;
|
|
|
|
xi_set_attrib(_list, att);
|
|
|
|
for (int col = 1; col < num; col++)
|
|
{
|
|
XI_OBJ* column = columns[col];
|
|
att = xi_get_attrib(column);
|
|
if (on)
|
|
{
|
|
att &= ~XI_ATR_READONLY;
|
|
att |= XI_ATR_AUTOSELECT;
|
|
}
|
|
else
|
|
{
|
|
att |= XI_ATR_READONLY;
|
|
att &= ~XI_ATR_AUTOSELECT;
|
|
}
|
|
xi_set_attrib(column, att); // Set new attributes
|
|
}
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#include <sheet.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TSpreadsheet
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TSpreadsheet : public TArray_sheet
|
|
{
|
|
TMask _mask;
|
|
SPREADSHEET_NOTIFY _notify;
|
|
TSheet_field * _owner;
|
|
|
|
TBit_array _column_disabled;
|
|
TArray _disabled; // Array di TBit_array
|
|
|
|
protected:
|
|
virtual bool on_key(KEY key);
|
|
KEY edit(int n, KEY tasto);
|
|
bool notify(int r, KEY k);
|
|
|
|
TMask_field* field(short id) const;
|
|
|
|
public:
|
|
TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno,
|
|
const char* head, WINDOW parent, TSheet_field * o);
|
|
|
|
TMask& sheet_mask() { return _mask; }
|
|
TMask& mask() const;
|
|
|
|
void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; }
|
|
void set_dirty(bool spork = TRUE) { _owner->set_dirty(spork);}
|
|
bool dirty() const { return _owner->dirty(); }
|
|
bool test_focus_change() { return TRUE; }
|
|
|
|
void mask2str(int riga);
|
|
void str2mask(int riga);
|
|
|
|
void enable_column(int col, bool on);
|
|
void enable_cell(int row, int column, bool on = TRUE);
|
|
bool cell_disabled(int row, int column) const;
|
|
virtual ~TSpreadsheet() {}
|
|
};
|
|
|
|
TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy,
|
|
const char* maskname, int maskno,
|
|
const char* head, WINDOW parent,
|
|
TSheet_field* o)
|
|
: TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), _owner(o),
|
|
_mask(maskname, maskno), _notify(NULL)
|
|
{}
|
|
|
|
bool TSpreadsheet::on_key(KEY k)
|
|
{
|
|
switch(k)
|
|
{
|
|
case K_CTRL_ENTER:
|
|
case K_ESC:
|
|
mask().send_key(k, 0);
|
|
return TRUE;
|
|
case K_ENTER: // Selezione riga per editing
|
|
if (items() < 1) k = K_INS; // Se vuoto crea riga da editare
|
|
case K_INS:
|
|
case 'A': // Aggiunge dopo
|
|
case 'I': // Aggiunge prima
|
|
{
|
|
int n = (int)selected();
|
|
if (k != K_ENTER)
|
|
{
|
|
if (k == K_INS) n = items(); else // Aggiunge alla fine
|
|
if (k == 'A') n++;
|
|
|
|
if (n < 0) n = 0; else
|
|
if (n > items()) n = items(); // Controlla range n
|
|
|
|
if (notify(n, K_INS) == FALSE) // Chiede l'ok alla applicazione
|
|
return FALSE;
|
|
|
|
insert(TToken_string(80), n); // Aggiunge una riga vuota
|
|
k = K_INS; // Inserimento in corso
|
|
}
|
|
|
|
notify(n, K_SPACE); // Notifica inizio cambiamento
|
|
k = edit(n, k); // Edita riga selezionata o creata
|
|
if (k == K_ENTER)
|
|
notify(n, K_ENTER); // Notifica avvenuto cambiamento
|
|
|
|
xvt_R3_set_front_window(win());
|
|
/* xvt_scr_set_focus_vobj(win()); -- set_focus does not raise window */
|
|
/* xvt_vobj_raise(win()); -- note: raise is illegal on controls */ // 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())
|
|
{
|
|
r.add(f.get());
|
|
break;
|
|
}
|
|
}
|
|
#ifdef DBG
|
|
if (pos < 0)
|
|
{
|
|
yesnofatal_box("Non e' visibile il campo %d per lo sheet", dlg);
|
|
r.add(" ");
|
|
}
|
|
#endif
|
|
}
|
|
#if XVT_OS == XVT_OS_WIN
|
|
update(rec);
|
|
#endif
|
|
}
|
|
|
|
|
|
// Certified 50%
|
|
void TSpreadsheet::enable_cell(int row, int column, bool on)
|
|
{
|
|
TBit_array* ba = (TBit_array*)_disabled.objptr(row);
|
|
if (ba == NULL)
|
|
{
|
|
if (on) return; // Don't waste time and memory
|
|
ba = new TBit_array(_column_disabled);
|
|
_disabled.add(ba, row);
|
|
}
|
|
|
|
if (column >= 0)
|
|
ba->set(column, !on);
|
|
else
|
|
{
|
|
if (on)
|
|
_disabled.destroy(row, FALSE); // Let's save some memory!
|
|
else
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN
|
|
ba->set(_columns); // Force right array size
|
|
#else
|
|
ba->set(32); // Force array size
|
|
#endif
|
|
ba->set(); // Set all bits
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void TSpreadsheet::enable_column(int col, bool on)
|
|
{
|
|
const bool change = _column_disabled[col] == on;
|
|
_column_disabled.set(col, !on);
|
|
#if XVT_OS == XVT_OS_WIN
|
|
if (change)
|
|
{
|
|
int num;
|
|
XI_OBJ** columns = xi_get_member_list(_list, &num);
|
|
CHECKD(col+1 < num, "Can't enable column ", col);
|
|
XI_OBJ* column = columns[col+1];
|
|
|
|
dword attr = xi_get_attrib(column);
|
|
if (on) attr |= XI_ATR_ENABLED;
|
|
else attr &= ~XI_ATR_ENABLED;
|
|
|
|
xi_move_focus(_itf); // Set focus to interface
|
|
xi_set_attrib(column, attr); // Set new attributes
|
|
RCT r; xi_get_rect(column, &r);
|
|
xi_set_column_width(column, (r.right-r.left+1) / CHARX); // Force redraw
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
// Certified 99%
|
|
bool TSpreadsheet::cell_disabled(int row, int column) const
|
|
{
|
|
TBit_array* ba = (TBit_array*)_disabled.objptr(row);
|
|
if (ba == NULL) return _column_disabled[column]; // Use default
|
|
return (*ba)[column];
|
|
}
|
|
|
|
|
|
// Certified 75%
|
|
void TSpreadsheet::str2mask(int riga)
|
|
{
|
|
if (riga == items())
|
|
{
|
|
sheet_mask().reset();
|
|
mask2str(riga);
|
|
return;
|
|
}
|
|
|
|
TToken_string& r = row(riga);
|
|
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)
|
|
{
|
|
const char* v = r.get((id % 100)-1);
|
|
if (v)
|
|
{
|
|
val = v; // Save the value, f.set(v) could use TString methods
|
|
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.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(rec, k) : TRUE;
|
|
if (k == K_ENTER)
|
|
set_dirty(ok ? TRUE : 3);
|
|
return ok;
|
|
}
|
|
|
|
// Certified 99%
|
|
#if XVT_OS != XVT_OS_WIN
|
|
KEY TSpreadsheet::edit(int n, KEY tasto)
|
|
#else
|
|
KEY TSpreadsheet::edit(int n)
|
|
#endif
|
|
{
|
|
const int olditems = items();
|
|
str2mask(n);
|
|
|
|
const KEY k = sheet_mask().run();
|
|
|
|
if (k == K_ENTER)
|
|
{
|
|
#if XVT_OS != XVT_OS_WIN
|
|
mask2str(n);
|
|
#endif
|
|
} else
|
|
if (k == K_DEL)
|
|
{
|
|
const bool ok = notify(n, K_DEL); // Notifica intenzione di cancellare
|
|
if (ok)
|
|
{
|
|
destroy(n);
|
|
if (n < items())
|
|
str2mask(n);
|
|
}
|
|
}
|
|
#if XVT_OS != XVT_OS_WIN
|
|
else
|
|
if (k == K_ESC)
|
|
{
|
|
if (tasto == K_INS)
|
|
destroy(n);
|
|
}
|
|
#endif
|
|
|
|
return k;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TSheet_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Certified 100%
|
|
TSheet_field::TSheet_field(TMask* m)
|
|
: TMask_field(m), _sheet(NULL)
|
|
{}
|
|
|
|
// Certified 100%
|
|
word TSheet_field::class_id() const
|
|
{
|
|
return CLASS_SHEET_FIELD;
|
|
}
|
|
|
|
// Certified 100%
|
|
TSheet_field::~TSheet_field()
|
|
{
|
|
CHECK(_sheet, "Can't delete NULL sheet");
|
|
delete _sheet;
|
|
}
|
|
|
|
// Certified 100%
|
|
void TSheet_field::reset()
|
|
{
|
|
_sheet->destroy();
|
|
_sheet->sheet_mask().reset();
|
|
}
|
|
|
|
// Certified 100%
|
|
void TSheet_field::destroy(int r)
|
|
{
|
|
_sheet->destroy(r);
|
|
}
|
|
|
|
|
|
void TSheet_field::parse_head(TScanner& scanner)
|
|
{
|
|
_width = scanner.integer();
|
|
_size = scanner.integer();
|
|
if (_size == 0) _size = -1;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
bool TSheet_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "IT")
|
|
{
|
|
_head.add(scanner.string());
|
|
return TRUE;
|
|
}
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
// Certified 100%
|
|
void TSheet_field::create(WINDOW parent)
|
|
{
|
|
const TMask& m = mask();
|
|
_sheet = new TSpreadsheet(_x, _y, _width, _size, m.source_file(),
|
|
m.sheets(), _head, parent, this);
|
|
|
|
_win = _sheet->win();
|
|
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;
|
|
}
|
|
|
|
|
|
TToken_string& TSheet_field::row(int n)
|
|
{
|
|
const int max = _sheet->items();
|
|
if (n < 0 || n >= max)
|
|
{
|
|
if (n < 0) n = first_empty();
|
|
if (n >= max) n = _sheet->add(new TToken_string(80));
|
|
}
|
|
return _sheet->row(n);
|
|
}
|
|
|
|
|
|
void TSheet_field::force_update(int r)
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN
|
|
_sheet->update(r);
|
|
#else
|
|
_sheet->open();
|
|
#endif
|
|
}
|
|
|
|
int TSheet_field::items() const
|
|
{
|
|
return (int)_sheet->items();
|
|
}
|
|
|
|
int TSheet_field::selected() const
|
|
{
|
|
return _sheet->selected();
|
|
}
|
|
|
|
void TSheet_field::set_notify(SPREADSHEET_NOTIFY n)
|
|
{
|
|
_sheet->set_notify(n);
|
|
}
|
|
|
|
void TSheet_field::highlight() const
|
|
{
|
|
TMask_field::highlight();
|
|
#if XVT_OS == XVT_OS_WIN
|
|
if (items())
|
|
{
|
|
_sheet->_firstfocus = FALSE;
|
|
if (_sheet->_edit_field == NULL)
|
|
_sheet->set_focus_cell(0, 1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void TSheet_field::enable(bool on)
|
|
{
|
|
_sheet->activate(on);
|
|
}
|
|
|
|
void TSheet_field::enable_column(int column, bool on)
|
|
{
|
|
_sheet->enable_column(column, on);
|
|
}
|
|
|
|
|
|
void TSheet_field::enable_cell(int row, int column, bool on)
|
|
{
|
|
_sheet->enable_cell(row, column, on);
|
|
}
|
|
|
|
bool TSheet_field::cell_disabled(int row, int column) const
|
|
{
|
|
return _sheet->cell_disabled(row, column);
|
|
}
|
|
|
|
|
|
TMask& TSheet_field::sheet_mask() const
|
|
{
|
|
return _sheet->sheet_mask();
|
|
}
|
|
|
|
bool TSheet_field::on_hit()
|
|
{
|
|
if (!mask().is_running())
|
|
{
|
|
force_update();
|
|
set_dirty(FALSE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TSheet_field::test_focus_change()
|
|
{
|
|
return _sheet->test_focus_change();
|
|
}
|
|
|
|
bool TSheet_field::on_key(KEY k)
|
|
{
|
|
if (k == K_ENTER)
|
|
{
|
|
if (!test_focus_change())
|
|
return FALSE;
|
|
}
|
|
return TMask_field::on_key(k);
|
|
}
|
|
|
|
void TSheet_field::exchange(bool show_value, const real& nuo)
|
|
{
|
|
TMask& m = sheet_mask();
|
|
|
|
const real& vec = mask().exchange();
|
|
|
|
if (vec != nuo)
|
|
{
|
|
TBit_array valuta(32);
|
|
int i = 0;
|
|
for (int f = FIRST_FIELD; ;f++, i++)
|
|
{
|
|
const int pos = m.id2pos(f);
|
|
if (pos < 0) break;
|
|
if (m.fld(pos).class_id() == CLASS_REAL_FIELD)
|
|
{
|
|
if (m.fld(pos).exchangeable())
|
|
valuta.set(i);
|
|
}
|
|
}
|
|
|
|
for (int riga = 0; riga < items(); riga++)
|
|
{
|
|
TToken_string& r = row(riga);
|
|
for (const char* s = r.get(i = 0); s; s = r.get(++i))
|
|
if (*s > ' ' && valuta[i])
|
|
{
|
|
real v(s);
|
|
v *= nuo;
|
|
v /= vec;
|
|
v.round();
|
|
r.add(v.string(), i);
|
|
}
|
|
}
|
|
}
|
|
|
|
m.set_exchange(show_value, nuo);
|
|
|
|
if (mask().is_running())
|
|
force_update();
|
|
}
|