#include #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, "Too 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) // Compute 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; // Compute 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; if (!(buttons & 0x10)) add_button(DLG_SELECT, "Selezione", K_ENTER); if (_checkable) add_button(DLG_USER, "Tutti"); if (buttons & 0x1) add_button(DLG_LINK, "Gestione", K_INS); if (buttons & 0x2) add_button(DLG_NEWREC, "~Nuovo", K_CTRL+'N'); if (buttons & 0x4) add_button(DLG_DELREC, "Elimina", K_DEL); if (buttons & 0x8) add_button(DLG_QUIT, "Fine", K_ESC); else add_button(DLG_CANCEL, "Annulla", K_ESC); } } // @doc INTERNAL // @mfunc Aggiunge un bottone nella finestra void TSheet::add_button( short id, // @parm Identificatore del bottone da aggiungere const char* caption, // @parm Testo del bottone da aggiungere KEY key) // @parm Combinazione di tasti corrispondente { #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()); if (_checkable) xvt_enable_control(_button[1], items() > 0 && _check_enabled); 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); } // @doc INTERNAL // @mfunc Crea la pagina void TSheet::build_page( long from) // @parm Numero della prima riga da visualizzare // @comm Carica le righe visibili { 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) { const long vec = selected(); const long nuo = first()+y-f; select(nuo); if (ep->type == E_MOUSE_DBL) dispatch_e_char(win, K_ENTER); else if (vec == nuo) { // dispatch_e_char(win, K_SPACE); // Cosi' lo interpreta come spazio nel campo di edit!!! TSheet::on_key(K_SPACE); // Mette l'eventuale segno di check } } 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_CTRL+'N'); break; case DLG_LINK: 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]); on_key(_key[i]); return; 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); } // @doc INTERNAL // @mfunc Converte le coordinate da logiche (caratteri) in coordinate fisiche (pixel) // (vedi ) // // @rdesc Ritorna le coordinate fisiche cercate PNT TSheet::log2dev( long x, // @parm Coordinata X da convertire long y) const // @parm Coordinata Y da convertire { 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 & 0x1) stop_run(key); break; case K_CTRL+'N': if (_buttonmask & 0x2) stop_run(key); 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) { if (key != K_ENTER || !_disabled[selected()]) 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); } // @doc INTERNAL // @mfunc Abilita/disabilita una riga void TSheet::enable( long n, // @parm Numero della riga da abilitare/diabilitare (default -1) bool on) // @parm Operazione da svolgere sulla riga // // @flag TRUE | Abilita la riga

-esima (default) // @flag FALSE | Disabilita la riga

-esima // @comm Se

e' minore di 0 allora vengono abilitate/disabilitate tutte le righe { if (n >= 0) _disabled.set(n, !on); else { if (on) _disabled.reset(); else { _disabled.set(items()); _disabled.set(); } } } // @doc INTERNAL // @mfunc Seleziona una riga facendola diventare corrente void TSheet::select( long n) // @parm Riga da selezionare (default -1) // @comm Se

assume un valore minore di 1 viene selezionata la prima riga. // Nela caso si cerci di selezionare una riga maggiore di quelle presenti viene selezionata // l'ultima. { 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(); } } // @doc INTERNAL // @mfunc Permette di attivare/disattivare una riga void TSheet::check( long n, // @parm Numero della riga da attivare/disattivare bool on) // @parm Operazione da effettuare sulla riga: // // @flag TRUE | Attiva la riga

.esima (default) // @flag FALSE | Disttiva la riga

.esima { 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; #ifdef DBG if (i < 0 || i > visible_rows()) { yesnofatal_box("Line out of screen: %ld", n); i = 1; } #endif 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); } } // @doc INTERNAL // @mfunc Forza il ridisegno di una riga. // // @rdesc Ritorna se e' riuscito a fare il ridisegno (cioe' se la riga era visibile) bool TSheet::update_row( long n) // @parm Numero della riga da ridisegnare { 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(FOCUS_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_NONE, 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; } // @doc INTERNAL // @mfunc Ritorna il contenuto di una riga // // @rdesc Ritorna la con tutti gli elemnti della riga TToken_string& TSheet::row( long n) // @parm Riga di cui ritorna il contenuto (default -1) // @comm Se viene passato un numero di riga minore di 1 viene ritornato il contenuto della riga // selezionata. { if (n < 0) n = selected(); int idx = 1; // if (!is_visible(n) || _last_update < 0) if (_last_update < 0 || n < _last_update || n >= _last_update + _page.items() -1) { // if (_last_update < 0) // set_scroll_max(width(), items()); build_page(n); // set_first(n); } else idx = int(n - _last_update) + 1; // const int 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_FS_NONE, 0); _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 = 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); } // Certified 100% // @doc EXTERNAL // @mfunc Copia le righe nella pagina da visualizzare void TArray_sheet::page_build( long first, // @parm Prima riga da visualizzare byte num) // @parm Numero di righe da vsiualizzare { for (byte i = 0; i < num; i++) set_row(data(first+i), i); } // @doc EXTERNAL // @mfunc Aggiunge un elemento allo sheet // // @rdesc Ritorna il numero di elemnti presenti nello sheet long TArray_sheet::add( const TToken_string& s) // @parm Oggetto da aggiungere // @parm const TToken_string | *s | Oggetto da aggiungere passato per indirizzo // @syntax add(const TToken_string& s) // @syntax 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() > 0) { 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(); _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 && what != _sel) 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_ENTER) { field().set(old); // Restore field status field().set_dirty(spork); } return key; }