#include #include #include #include #include #include #include /////////////////////////////////////////////////////////// // TSheet /////////////////////////////////////////////////////////// TSheet::TSheet(short x, short y, short dx, short dy, const char* title, const char* head, byte buttons, long first, WINDOW parent) : _curr(first), _last_update(-1), _checkable(FALSE), _check_enabled(TRUE), _buttonmask(buttons) { const char* g; TToken_string new_head(512); TToken_string h(head); TString item(80); for(_columns = 0; (g = h.get()) != NULL; _columns++) { CHECK(_columns < MAX_COL, "To many columns in sheet "); item = g; const int et = item.find('@'); if (et >= 0) { const char t = item.right(1)[0]; _type[_columns] = isalpha(t) ? toupper(t) : '\0'; const int l = atoi(item.mid(et+1)); item.cut(et); if (_columns == 0 && et == 0 && l <= 1) _checkable = _size[0] = 1; else _size[_columns] = l > 0 ? l : item.len(); } else { _size[_columns] = item.len(); _type[_columns] = '\0'; } item.trim(); new_head.add(item); } set_row(new_head, -1); for (int i = 0; i < MAX_BUT; i++) _button[i] = NULL_WIN; if (parent == NULL_WIN) parent = TASK_WIN; long flags = WSF_CLOSE | WSF_SIZE | WSF_VSCROLL | WSF_HSCROLL ; WIN_TYPE wt = W_DOC; if (parent != TASK_WIN) { wt = W_PLAIN; flags = WSF_VSCROLL; } if (dx == 0) // Calculates window width { RCT r; xvt_vobj_get_client_rect(parent, &r); dx = r.right/CHARX -6; const int larg = width(); if (dx > larg) dx = larg; } if (dy == 0) dy = 20; // Calculates window height create(x, y, dx, dy, title, flags, wt, parent); if (wt != W_PLAIN) // If normal sheet add buttons { _visible_rows = rows()- head_on() - 3; add_button(DLG_SELECT, "Selezione" ); if (_checkable) add_button(DLG_USER, "Tutti"); if (buttons & 0x1) add_button(DLG_NEWREC, "Gestione"); if (buttons & 0x2) add_button(DLG_NEWREC, "Nuovo"); if (buttons & 0x4) add_button(DLG_DELREC, "Elimina"); if (buttons & 0x8) add_button(DLG_QUIT, "Fine"); else add_button(DLG_CANCEL, "Annulla"); } } void TSheet::add_button(short id, const char* caption, KEY key) { #if XVT_OS == XVT_OS_WIN const int BUT_HEIGHT = 2; #else const int BUT_HEIGHT = 1; #endif WINDOW b = xvt_create_control(WC_PUSHBUTTON, 0, 0, 11, BUT_HEIGHT, caption, win(), 0, 0, id); for (int i = 0; i < MAX_BUT; i++) if (_button[i] == NULL_WIN) { _button[i] = b; _key[i] = key; break; } } void TSheet::repos_buttons() const { for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++) if (buttons == MAX_BUT-1) { buttons++; break; } if (buttons == 0) return; RCT wr; xvt_vobj_get_client_rect(win(), &wr); RCT br; xvt_vobj_get_client_rect(_button[0], &br); int space = (wr.right - buttons * br.right) / (buttons+1); if (space < 0) space = 0; int x = space; const int y = wr.bottom - br.bottom-4; for (int b = 0; b < buttons; b++, x += br.right+space) { RCT r; xvt_rect_set(&r, x, y, x+br.right, y+br.bottom); xvt_vobj_move(_button[b], &r); } } void TSheet::open() { set_scroll_max(width(), items()); _last_update = -1; if (!is_visible(_curr)) set_first(_curr); if (buttons_on()) { // Abilita selezione se c'e' almeno un elemento xvt_enable_control(_button[0], items() > 0 && _disabled.ones() < items()); repos_buttons(); } TScroll_window::open(); force_update(); } void TSheet::set_first(long n) { update_thumb(-1, n); } void TSheet::set_row(const TToken_string& r, byte i) { if (i > 64) i = 0; else i++; _page.add(r, i); } void TSheet::build_page(long from) { const long f = (from < 0) ? first() : from; if (_last_update != f) { int r = visible_rows(); if (f+r > items()) r = int(items()-f); if (r > 0) page_build(f, r); _last_update = f; } } short TSheet::reserved_rows() const { return buttons_on() ? 3 : 0; } void TSheet::handler(WINDOW win, EVENT* ep) { switch(ep->type) { case E_FOCUS: invert_row(selected()); break; case E_MOUSE_DOWN: if (ep->v.mouse.button) { dispatch_e_char(win, K_ESC); return; } case E_MOUSE_DBL: { const short y = ep->v.mouse.where.v / CHARY; const short f = head_on() ? 1 : 0; if (y >= f) { long vec = selected(); long nuo = first()+y-f; select(nuo); if (ep->type == E_MOUSE_DBL) dispatch_e_char(win, K_ENTER); else if (_checkable && _check_enabled && !_disabled[nuo] && vec == nuo) { _checked.not(nuo); force_update(); } } else dispatch_e_char(win, y ? K_UP : K_PREV); } break; case E_CONTROL: switch(ep->v.ctl.id) { case DLG_OK : case DLG_SELECT: dispatch_e_char(win, K_ENTER); break; case DLG_CANCEL: case DLG_QUIT : dispatch_e_char(win, K_ESC); break; case DLG_NEWREC: dispatch_e_char(win, K_INS); break; case DLG_DELREC: dispatch_e_char(win, K_DEL); break; case DLG_USER: dispatch_e_char(win, one_checked() ? K_F2 : K_F3); break; default: { const WINDOW b = ep->v.ctl.ci.win; for (int i = 0; i < MAX_BUT; i++) if (_button[i] == b) { stop_run(_key[i]); break; } } break; } break; case E_SIZE: { _last_update = -1; _visible_rows = ep->v.size.height/CHARY - (head_on() ? 1 : 0); if (buttons_on()) { _visible_rows -= reserved_rows(); repos_buttons(); } force_update(); } break; default: break; } TScroll_window::handler(win, ep); } PNT TSheet::log2dev(long x, long y) const { if (autoscrolling()) x -= origin().x; return TWindow::log2dev(x, y); } bool TSheet::on_key(KEY key) { switch(key) { case K_ENTER: if (items() == 0) key = K_ESC; if (selected() < 0 || _disabled[selected()]) break; case K_ESC: stop_run(key); case K_DEL: if ((_buttonmask & 0x4) && items()) stop_run(key); break; case K_INS: if (_buttonmask & 0x3) stop_run(K_INS); break; case K_LHOME: select(0); return TRUE; case K_LEND: select(items()-1); return TRUE; case K_PREV: select(selected()-visible_rows()); return TRUE; case K_UP: select(selected()-1); return TRUE; case K_NEXT: select(selected()+visible_rows()); return TRUE; case K_DOWN: select(selected()+1); return TRUE; case K_CTRL+'P': print(); break; default: for (int i = 0; i < MAX_BUT; i++) if (_key[i] == key) { stop_run(key); break; } break; } if (_checkable && _check_enabled && items() > 0) { switch(key) { case K_SPACE: check(selected(), !checked(selected())); break; case K_F2: uncheck(-1); break; case K_F3: check(-1); break; default: break; } } return TScroll_window::on_key(key); } void TSheet::enable(long n, bool on) { if (n >= 0) _disabled.set(n, !on); else { if (on) _disabled.reset(); else { _disabled.set(items()); _disabled.set(); } } } void TSheet::select(long n) { if (n < 0) n = 0; else if (n >= items()) n = items()-1; invert_row(_curr); _curr = n; if (is_visible(_curr)) invert_row(_curr); else { const long s = (_curr < first()) ? _curr : _curr-visible_rows()+1; set_first(s); force_update(); } } void TSheet::check(long n, bool on) { long s = selected(); if (n < 0) { if (on) { _checked.set(items()-1); // Force the size of Bit_array _checked.set(); if (on && _disabled.first_one() >= 0) { for (long i = 0; i < items(); i++) if (_disabled[i]) _checked.reset(i); else s = i; } } else _checked.reset(); } else { if (!_disabled[n]) _checked.set(n, on); } force_update(); select(s); } // Converte il numero di riga assoluto nell'indice dell'array _page int TSheet::row_to_page(long n) const { long i = (n < 0) ? 0L : n-first()+1; if (i < 0 || i > visible_rows()) { error_box("Line out of screen"); i = 0L; } return (int)i; } // Converte il numero di riga assoluto nella coordinata y sulla finestra int TSheet::row_to_win(long n) const { int y = row_to_page(n); if (y < 1) y = 0; else if (!head_on()) y--; return y; } // Calcola la larghezza totale dello sheet virtuale int TSheet::width() const { int width = 0; for (int c = 0; c < _columns; c++) width += _size[c]+(c > 0); return width; } void TSheet::invert_row(long n) { if (win() != NULL_WIN && is_visible(n)) { const short y = row_to_win(n); autoscroll(FALSE); invert_bar(0,y,columns(),y+1); autoscroll(TRUE); } } bool TSheet::update_row(long n) { const int i = row_to_page(n); if (i >= _page.items()) return FALSE; TToken_string& t = _page.row(i); t.restart(); const bool chk = n >= 0 && _checked[n] && !_disabled[n]; bool changed = FALSE; if (chk) { set_color(MASK_BACK_COLOR, NORMAL_BACK_COLOR); changed = TRUE; } else if (_disabled[n]) { set_color(DISABLED_COLOR, NORMAL_BACK_COLOR); changed = TRUE; } if (n < 0) set_font("", XVT_FS_BOLD, 0); int minx = (int)origin().x; int maxx = minx + columns(); minx -= 80; int x = 0; const int y = row_to_win(n); const char* s; for (int j = 0; x < maxx && (s = t.get()) != NULL; x += _size[j++]+1) if (x > minx) { int x1 = x; if (n >= 0) { if (_checkable && j == 0) { s = chk ? "X" : " "; } switch (_type[j]) { case 'R': x1 += _size[j]-strlen(s); // Allinea a destra break; case 'M': s = itor(atoi(s)); // Numeri romani break; default: break; } } else { x1 += (_size[j]-strlen(s)) >> 1; // Centra le testate } stringat(x1, y, s); } if (changed) set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); if (n < 0) set_font("", XVT_FS_NONE, 0); return TRUE; } TToken_string& TSheet::row(long n) { if (n < 0) n = selected(); if (!is_visible(n)) { build_page(n); set_first(n); } short idx = row_to_page(n); return (TToken_string&)_page[idx]; } void TSheet::update() { if (_last_update < 0) { set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); set_pen(NORMAL_COLOR); set_brush(NORMAL_BACK_COLOR); set_font(XVT_FFN_FIXED); _visible_rows = rows() - reserved_rows() - head_on(); } if (head_on()) { const int height = visible_rows()+1; const int width = columns()+1; short x = -1; for (int c = 0; c < _columns; c++) { x += _size[c] + 1; line(x,0,x,height); } autoscroll(FALSE); set_brush(MASK_BACK_COLOR); bar(0,0,width,1); if (buttons_on()) bar(0, height, width, height+reserved_rows()+1); autoscroll(TRUE); } build_page(); if (head_on()) update_row(-1); long last = first() + visible_rows(); if (last > items()) last = items(); for (long n = first(); n < last; n++) update_row(n); if (xvt_scr_get_focus_vobj() == win()) invert_row(selected()); } void TSheet::print() { TPrinter& pr = main_app().printer(); TPrintrow row; bool ok = pr.open(); main_app().begin_wait(); int step = visible_rows(); for (long n = 0L; ok && n < items(); n += step) { set_first(n); build_page(); if ((n+step) > items()) step = int(items()-n); for (int i = 1; ok && i <= step; i++) { const char* s; TToken_string& t = (TToken_string&)_page[i]; t.restart(); row.reset(); for (int j = 0, x = 0; (s = t.get()) != NULL; x += _size[j++]+1) row.put(s, x); ok = pr.print(row); } } main_app().end_wait(); if (ok) { pr.formfeed(); pr.close(); } set_focus(); } /////////////////////////////////////////////////////////// // TArray_sheet /////////////////////////////////////////////////////////// TArray_sheet::TArray_sheet(short x, short y, short dx, short dy, const char* caption, const char* head, byte buttons, WINDOW parent) : TSheet(x, y, dx, dy, caption, head, buttons, 0L, parent) { select(0); } // Certified 90% bool TArray_sheet::destroy(int i) { uncheck(-1); enable(-1); return _data.destroy(i, TRUE); } // Copia le righe nella pagina da visualizzare // Certified 100% void TArray_sheet::page_build(long first, byte num) { for (byte i = 0; i < num; i++) set_row(data(first+i), i); } long TArray_sheet::add(const TToken_string& s) { const long n = _data.add(s, -1); set_scroll_max(-1, n); return n; } long TArray_sheet::add(TToken_string* s) { const long n = _data.add(s); set_scroll_max(-1, n); return n; } long TArray_sheet::insert(const TToken_string& s, long n) { _data.insert(s, (int)n); set_scroll_max(-1, items()); return n; } /////////////////////////////////////////////////////////// // TCursor_sheet /////////////////////////////////////////////////////////// TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons) : TSheet(-1,-1, 0, 0, title,head,buttons,cursor->pos()), _cursor(cursor), _records(cursor->items()) { TToken_string fldlst(fields); int campo = 0; for (const char* t = fldlst.get(0); t; t = fldlst.get(), campo++) if (*t > ' ' && *t != '"') { const TFieldref fr(t, 0); TRecfield* rf = new TRecfield(_cursor->curr(fr.file()), fr.name(), fr.from(), fr.to() - 1); _fields.add(rf, campo); const TFieldtypes tipo = rf->type(); if (tipo == _intfld || tipo == _longfld || tipo == _realfld) { byte& c = column_flag(campo); if (c == '\0') c = 'R'; // Allinea a destra tutti i campi numerici } } } KEY TCursor_sheet::run() { _records = _cursor->items(); _cursor->freeze(TRUE); const KEY k = TSheet::run(); _cursor->freeze(FALSE); return k; } void TCursor_sheet::page_build(long first, byte rows) { TToken_string l(256); *_cursor = (TRecnotype)first; for (int r = 0; r < rows; r++, ++(*_cursor)) { l.cut(0); const int last = _fields.last(); for (int i = 0; i <= last; i++) { const TRecfield* rf = (TRecfield*)_fields.objptr(i); const char* s = rf ? (const char*)*rf : ""; l.add(s); } set_row(l, r); } } /////////////////////////////////////////////////////////// // TBrowse_sheet /////////////////////////////////////////////////////////// TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons, TEdit_field* f, TToken_string* s) : TCursor_sheet(cursor, fields, title, head, buttons), _field(f) { if (field().browse()->inputs() == 1 && cursor->items() > 0) { #if XVT_OS == XVT_OS_SCOUNIX const int s = f->size()+2; #else const int s = f->size()+1; #endif xvt_create_control(WC_EDIT, 1, -3, s, 1, f->get(), win(), CTL_FLAG_DISABLED, 0L, DLG_EDIT); } if (s && s->items() > 2) { int maxlen = 0; SLIST lst = xvt_slist_create(); for (const char* item = s->get(0); item; item = s->get()) { item = s->get(); const int len = strlen(item); if (len > maxlen) maxlen = len; xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); } WINDOW listbox = xvt_create_control(WC_LISTBUTTON, f->size()+3, -3, maxlen+3, 3, "", win(), 0, 0L, DLG_FINDREC); xvt_list_add(listbox, -1, (char*)lst); xvt_slist_destroy(lst); TString16 id; id << f->dlg(); const int sel = s->get_pos(id) >> 1; xvt_list_set_sel(listbox, sel, TRUE); } } short TBrowse_sheet::reserved_rows() const { return TSheet::reserved_rows() + 1; } void TBrowse_sheet::repos_buttons() const { TSheet::repos_buttons(); // Repos toolbar RCT wr; xvt_vobj_get_client_rect(win(), &wr); // Get window size int left = CHARX; // left coord of next control to draw for (int i = 0; i < 2; i++) { const short id = i ? DLG_EDIT : DLG_FINDREC; const WINDOW w = xvt_win_get_ctl(win(), id); if (w != NULL_WIN) { RCT r; xvt_vobj_get_client_rect(w, &r); r.left = left; r.top = wr.bottom - 4*CHARY + 4; r.right += r.left; r.bottom += r.top; xvt_vobj_move(w, &r); left = r.right+CHARX; // Increase left coord } } } bool TBrowse_sheet::on_key(KEY k) { const WINDOW ctl = xvt_win_get_ctl(win(), DLG_EDIT); const bool alnum = k >= ' ' && k < K_UP; if (ctl != NULL_WIN && (alnum || k == K_BACKSPACE || k == K_DEL)) { const long oldsel = selected(); const bool corre = field().mask().is_running(); const WINDOW fldwin = field().win(); TString80 old(corre ? field().get_window_data() : field().get_field_data()); TString80 val(old.ltrim()); if (alnum) { if (val.len() >= field().size()) val.cut(0); if (field()._flags.uppercase && isalpha(k)) k = toupper(k); val << char(k); } else val.rtrim(1); if (corre) xvt_vobj_set_title(fldwin, (char*)(const char*)val); else field().set_field_data(val); ((TBrowse*)field().browse())->do_input(FALSE); _cursor->read(); if (_cursor->file().bad()) { beep(); val = old; if (corre) xvt_vobj_set_title(fldwin, (char*)(const char*)val); else field().set_field_data(val); *_cursor = oldsel; } else select(_cursor->pos()); if (ctl != NULL_WIN) { val = corre ? field().get_window_data() : field().get_field_data(); xvt_vobj_set_title(ctl, (char*)(const char*)val); } return TRUE; } else { field().set(""); if (ctl != NULL_WIN) xvt_vobj_set_title(ctl, ""); } return TSheet::on_key(k); } void TBrowse_sheet::handler(WINDOW win, EVENT* ep) { if (ep->type == E_CONTROL && ep->v.ctl.id == DLG_FINDREC) { const int what = xvt_list_get_sel_index(ep->v.ctl.ci.win); if (what >= 0) stop_run(K_CTRL + what); else set_focus(); return; } TCursor_sheet::handler(win, ep); } KEY TBrowse_sheet::run() { const bool spork = field().dirty(); // Store field status const TString80 old(field().get()); const KEY key = TCursor_sheet::run(); if (key == K_ESC || key == K_INS || key >= K_CTRL) { field().set(old); // Restore field status field().set_dirty(spork); } return key; }