#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if XVT_OS == XVT_OS_WIN #include #endif HIDDEN TString256 fpark; // @doc EXTERNAL /////////////////////////////////////////////////////////// // Field Flags /////////////////////////////////////////////////////////// // Certified 100% TMask_field::TField_Flags::TField_Flags() { automagic = persistent = FALSE; enabled = enable_default = TRUE; shown = show_default = TRUE; uppercase = rightjust = FALSE; zerofilled = FALSE; dirty = focusdirty = FALSE; roman = exchange = FALSE; firm = ghost = FALSE; password = FALSE; trim = TRUE; pipeallowed = FALSE; } // Certified 100% char TMask_field::TField_Flags::update(const char* f) { for (const char* s = f; *s; s++) switch(toupper(*s)) { case ' ': case '_': trim = FALSE; break; case '*': password = TRUE; break; case 'A': automagic = persistent = TRUE; break; case 'D': enable_default = enabled = FALSE; break; case 'F': firm = persistent = TRUE; break; case 'G': ghost = TRUE; break; case 'H': show_default = shown = FALSE; break; case 'M': roman = TRUE; break; case 'P': persistent = TRUE; break; case 'R': rightjust = TRUE; break; case 'U': uppercase = TRUE; break; case 'V': exchange = TRUE; break; case 'Z': zerofilled = TRUE; break; default : CHECKS(0, "FLAG sconosciuto in ", f); break; } return *s; } /////////////////////////////////////////////////////////// // TMask_field /////////////////////////////////////////////////////////// int TMask_field::_x; // Position of the field int TMask_field::_y; int TMask_field::_width; TString80 TMask_field::_prompt; TMask_field::TMask_field(TMask* m) : _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0), _keys(0), _groups(0), _help(0), _handler(NULL), _validate_func(-1), _validate_parms(1), _field(NULL) { _x = -1; _y = -1; } // Certified 100% TMask_field::~TMask_field() { if (_field) delete _field; } // Certified 100% const char* TMask_field::class_name() const { return "Field"; } // Certified 100% word TMask_field::class_id() const { return CLASS_FIELD; } // Certified 100% bool TMask_field::ok() const { return win() != NULL_WIN && dlg() >= -1; } // Certified 100% void TMask_field::parse_head(TScanner&) {} // Certified 100% short TMask_field::atodlg(const char* s) const { short d = s ? atoi(s) : 0; #ifdef DBG if (d == 0 || d < -1 || d > 1000) { yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s); d = -1; } #endif return d; } // @mfunc Costruisce il campo void TMask_field::construct( short id, // @parm Identificatore del campo const char* prompt, // @parm Prompt del campo int x, // @parm Posizione in x (in caratteri) del campo nella maschera int y, // @parm Posizione in y (in caratteri) del campo nella maschera int len, // @parm Lunghezza vidibile del campo WINDOW parent, // @parm Finestra padre alla quale assegnare il campo const char* flags, // @parm Flags del campo (default "") int width) // @parm Lunghezza del campo // @parm TScanner& | scanner | File dal quale leggere leggere le informazioni // @syntax void construct(TScanner& scanner, WINDOW parent); // @syntax void construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags, int width); // // @comm E' possibile costruire il campo leggendo direttamente dal file, oppure passare alla funzione // tutti i parametri necessari alla definizione del campo stesso { _x = x; _y = y; _prompt = prompt; _size = len; if (class_id() == CLASS_REAL_FIELD) { ((TReal_field*)this)->set_decimals(width); _width = _size; } else _width = width < 1 ? _size : width; _dlg = id; _flags.update(flags); create(parent); } void TMask_field::construct(TScanner& scanner, WINDOW parent) { _dlg = atodlg(scanner.pop()); parse_head(scanner); _prompt.cut(0); scanner.popkey(); // BEGIN #ifdef DBG if (scanner.key() != "BE") { yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg); scanner.push(); } #endif while(scanner.popkey() != "EN") // END of control parse_item(scanner); create(parent); } void TMask_field::set_back_color(COLOR c) const { xvt_set_ctrl_back_color(win(), c); } bool TMask_field::parse_item(TScanner& scanner) { if (scanner.key() == "PR") // PROMPT { _x = scanner.integer(); _y = scanner.integer(); _prompt = scanner.string(); return TRUE; } if (scanner.key() == "FL") // FLAG { const char* f = scanner.string(); return _flags.update(f) == '\0'; } if (scanner.key() == "FI") // FIELD { CHECKD(_field == NULL, "Only one FIELD, please: ", dlg()); _field = new TFieldref(scanner.line(), 0); return TRUE; } if (scanner.key() == "HE") // HELP { _help = scanner.string(); return TRUE; } if (scanner.key() == "KE") // KEY { _keys.set(scanner.line()); _keys.set(0L); return TRUE; } if ( scanner.key() == "CU") // CUSTOM DATA { _userdata.add(scanner.string()); return TRUE; } if (scanner.key() == "ME") { if (_message.objptr(0) == 0) _message.add(new TToken_string(64), 0); TToken_string& ts = (TToken_string&)_message[0]; ts.add(scanner.line().strip_spaces()); return TRUE; } if (scanner.key() == "GR") { _groups.set(scanner.line()); return TRUE; } if (scanner.key() == "VA") { const char* n = scanner.pop(); _validate_func = isdigit(*n) ? atoi(n) : -1; #ifdef DBG if (_validate_func < 0) return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg()); #endif const int _nparms = scanner.integer(); #ifdef DBG if (_nparms < 0 || _nparms > 100) return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d", dlg(), _nparms); #endif for(int i = 0; i < _nparms; i++) _validate_parms.add(scanner.operand()); return TRUE; } if (scanner.key() == "WA") { _warning = scanner.string(); return TRUE; } return FALSE; } long TMask_field::default_flags() const { long f = CTL_FLAG_NATIVE_JUST; if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE; if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED; return f; } // Certified 100% // @mfunc Crea la finestra del controllo // // @rdesc Ritorna la finestra creata WINDOW TMask_field::wincreate( WIN_TYPE ct, // @parm Tipo di finestra da creare short dx, // @parm Larghezza iniziale della finestra short dy, // @parm Altezza iniziale della finestra const char* title, // @parm Titolo della finestra WINDOW parent, // @parm Finestra padre di quella da creare long flags) // @parm fleg della finestra { _win = xvt_create_control(ct, _x, _y, dx, dy, (char*)title, parent, flags | default_flags(), PTR_LONG(this), _dlg); return _win; } // Certified 100% WINDOW TMask_field::parent() const { return xvt_vobj_get_parent(win()); } // Certified 90% // @mfunc Crea il prompt del controllo // // @rdesc Ritorna la lunghezza del prompt creato int TMask_field::create_prompt( WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo int width, // @parm Larghezza del controllo int heigth) // @parm Altezza del controllo { const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX; if (width < 1) width = _prompt.len() - (_prompt[0] == '@' ? 2 : 0); _prompt.rtrim(); // Could save some bytes if (width) { const long flags = default_flags() & (~CTL_FLAG_DISABLED); // Static controls shouldn't be grayed #if XVT_OS == XVT_OS_WIN const int k = _prompt.find('~'); if (k >= 0) _prompt[k] = '&'; #endif _promptwin = xvt_create_control ( wt, _x, _y, width, heigth, _prompt, parent, flags, 0L, -1 ); } if (_x == -1 && _y == -1) { _x = 1; _y = 30; } return width; } // Certified 100% void TMask_field::destroy() { if (_win) { xvt_vobj_destroy(_win); _win = NULL_WIN; } if (_promptwin) { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } } // Certified 100% void TMask_field::create(WINDOW parent) { _width = _prompt.len(); if (_width) wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST); } // Certified 100% // @mfunc Abilita/disabilita il campo (lo rende scrivibile) void TMask_field::enable( bool on) // @parm Operazione da svolgere: // // @flag TRUE | Abilita il campo (default) // @flag FALSE | Disabilita il campo { const word c = class_id(); if (c != CLASS_FIELD) { xvt_vobj_set_enabled(_win, on); _flags.enabled = on; } } // Certified 100% void TMask_field::enable_default() { const bool ed = _flags.enable_default; enable(ed); } // Certified 100% // @mfunc Permette di rendere visibile/invisibile un campo void TMask_field::show( bool on) // @parm Operazione da svolgere: // // @flag TRUE | Rendere visibile il campo (default) // @flag FALSE | Rendere invisibile il campo { xvt_vobj_set_visible(_win, on); if (_promptwin != NULL_WIN) xvt_vobj_set_visible(_promptwin, on); _flags.shown = on; } // Certified 100% void TMask_field::show_default() { const bool sd = _flags.show_default; show(sd); } // Certified 100% bool TMask_field::active() const { return enabled() && shown() && class_id() != CLASS_FIELD; }; // Certified 90% word TMask_field::last_key() const { long u = _keys.last_one(); if (u < 0) u = 0; return (word)u; } // Certified 90% void TMask_field::reset_key(byte key) { CHECK(key>0, "Can't reset key 0"); _keys.reset(long(key)); if (last_key()==0) _keys.reset(0L); } void TMask_field::set_dirty(bool d) { if (_flags.dirty == 3 && d == FALSE) return; _flags.dirty = d; set_focusdirty(d); } // Certified 99% const char* TMask_field::get_window_data() const { return xvt_vobj_get_title(win(), (char*)(const char*)fpark, fpark.size()); } // Certified 99% void TMask_field::set_window_data(const char* data) { if (data != NULL) xvt_vobj_set_title(win(), (char*)data); } // Certified 100% void TMask_field::set_field_data(const char*) {} // Certified 100% const char* TMask_field::get_field_data() const { return NULL; } // @mfunc Permette di dare la stessa formattazione del campo della maschera // // @rdesc Ritorna la stringa formattata const char* TMask_field::picture_data( const char* data, // @parm Stringa da dare il formato bool video) const // @parm Se TRUE permette di visualizzare la stringa a video // @comm Utilizzata soprattutto dagli sheet che in questo modo possono formattare // il contenuto delle celle con lo stesso formato deglia altri campi della maschera // dell stesso tipo. { if (video) { fpark = data; fpark.trim(); if (_flags.uppercase) fpark.upper(); return fpark; } return data; } // Certified 90% const char* TMask_field::prompt() const { if (_promptwin != NULL_WIN) _prompt = xvt_get_title(_promptwin); else _prompt = ""; return _prompt; } // Certified 90% void TMask_field::set_field(const TString& fr) { if (_field != NULL) *_field = fr; else _field = new TFieldref(fr, 0); } // Certified 100% void TMask_field::reset() { if (!_flags.persistent && class_id() != CLASS_FIELD) set(""); } // Certified 00% void TMask_field::set_prompt(const char* p) { if (_promptwin != NULL_WIN) { word style = 0; for (const char* s = p; *s == '@'; s++) { s++; switch(toupper(*s)) { case 'B': style |= XVT_FS_BOLD; break; case 'U': style |= XVT_FS_UNDERLINE; break; default : CHECKS(0, "Invalid prompt style ", s); break; } } if (style) xvt_set_font(_win, "", style, CHARY-12); xvt_vobj_set_title(_promptwin, (char*)p); } } void TMask_field::set(const char* s) { if (mask().is_running()) { set_window_data(s); set_dirty(); } else set_field_data(s); } TString& TMask_field::get() const { static TString gpark; if (mask().is_running()) gpark = get_window_data(); else gpark = get_field_data(); if (_flags.trim) gpark.trim(); return gpark; } void TMask_field::undo() { set_window_data(get_field_data()); } bool TMask_field::autoload(const TRelation* r) { if (_field) { set(_field->read(r)); return TRUE; } return FALSE; } bool TMask_field::autosave(TRelation* r) const { if (_field) { _field->write(get(), r); return TRUE; } return FALSE; } // Certified 50% HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg) { #ifdef DBG if (f.class_id() != CLASS_LIST_FIELD) { yesnofatal_box("Can't add/delete items of non list-box field %d", f.dlg()); return; } #endif TList_field& l = (TList_field&)f; TToken_string item(16); item = msg.get(); if (add) item.add(msg.get()); item.strip("\"'"); if (add) l.add_item(item); else l.delete_item(item); } // Certified 99% HIDDEN const char* copy_value(TToken_string& msg, const TString& val) { int from = msg.get_int()-1; int to = -1; if (from < 0) from = 0; else to = msg.get_int(); return val.sub(from, to); } HIDDEN void run_app(TMask& mask, TToken_string& msg) { TFilename a; for (const char* m = msg.get(1); m; m = msg.get()) { if (a.not_empty()) a << ' '; for (const char* f = m; *f; f++) { if (*f == '#') { const int id = atoi(++f); a << mask.get(id); break; } else a << *f; } } TExternal_app app(a); app.run(); mask.set_focus(); } void TMask_field::send_key(KEY k, short to) { mask().send_key(k, to, this); } // Certified 90% bool TMask_field::do_message(int num) { const int MAX_CMD = 17; static const char* commands[MAX_CMD] = { "ADD", // 0 "CLEAR", // 1 "CO", // 2 "DEL", // 3 "DIRTY", // 4 "DISABLE", // 5 "ENABLE", // 6 "ENABLEDEF", // 7 "EXIT", // 8 "HIDE", // 9 "NORMAL", // 10 "PUSH", // 11 "REQUIRED", // 12 "RESET", // 13 "RU", // 14 "SHOW", // 15 "UNDO" // 16 }; TToken_string* message = (TToken_string*)_message.objptr(num); if (message == NULL || message->empty()) return FALSE; TToken_string msg(16, ','); TString256 value; for (const char* m = message->get(0); m && *m; m = message->get()) { KEY key = 0; msg = m; value = msg.get(); const char* dlg = msg.get(); int cmd = -1; if (isalpha(value[0])) // binary search { int f = 0, l = MAX_CMD-1; while (TRUE) { cmd = (f+l)>>1; const int cmp = strcmp(value, commands[cmd]); if (cmp == 0) break; if (cmp > 0) f = cmd+1; else l = cmd-1; if (f > l) { cmd = -1; break; } } } if (cmd == 8) { mask().stop_run(atoi(dlg)); continue; } else if (cmd == 14) { run_app(mask(), msg); continue; } short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0; bool broadcast = dlg && strchr(dlg, '@'); if (value[0] == '"') value = value.strip("\"'"); else switch (cmd) { case 0: modify_list(TRUE, mask().field(fld), msg); continue; case 1: key = 11000+'c'; break; case 2: value = copy_value(msg, get()); break; case 3: modify_list(FALSE, mask().field(fld), msg); continue; case 4: mask().field(fld).set_dirty(); continue; case 5: key = 11000+'d'; break; case 6: key = 11000+'e'; break; case 7: key = 11000+'E'; break; case 9: key = 11000+'h'; break; case 10: mask().efield(fld).check_type(CHECK_NORMAL); continue; case 11: key = K_SPACE; break; case 12: mask().efield(fld).check_type(CHECK_REQUIRED); continue; case 13: key = K_F2; break; case 15: key = 11000+'s'; break; case 16: key = K_F3; break; default: key = atoi(value); break; } if (key) { if (key > 0) { if (broadcast) fld = -fld; send_key(key, fld); } } else { // Setta a value il campo fld solo se ha un valore diverso da value if (broadcast) { for (int i = 0; i < mask().fields(); i++) { TMask_field& f = mask().fld(i); if (f.in_group((int)fld)) { const char* prev = f.get(); if (value != prev) { f.set(value); if (f.shown() || f.ghost()) f.on_hit(); } } } } else { TMask_field& f = mask().field(fld); const char* prev = f.get(); if (value != prev) { f.set(value); if (f.shown() || f.ghost()) f.on_hit(); } } } } return TRUE; } bool TMask_field::test_focus_change() { bool ok = TRUE; if (focusdirty()) ok = on_key(K_TAB); // Comportamento normale else if (is_edit() && in_key(1)) ok = on_hit(); // Serve per eseguire gli handler autoprementi return ok; } // Certified 90% bool TMask_field::on_hit() { if (_handler) { bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); if (!ok) return FALSE; } do_message(0); return TRUE; } // @mfunc Permette di spedire il check // // @rdesc Ritorna il risultato del check: // // @flag TRUE | Se il check ha dato esito positivo // @flag FALSE | Se il check ha dato esito negativo bool TMask_field::to_check( KEY k, // @parm Tasto da passare al campo come simulazione di inizio controllo bool checkrun) const // @parm Permette di testare sanche e la maschera e' in esecuzione { bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty()); if (!yes && checkrun) yes = k == K_TAB && !mask().is_running(); return yes; } // Certified 90% bool TMask_field::on_key(KEY key) { if (key > 11000) { switch(key-11000) { case 'E': enable_default(); break; case 'c': reset(); on_hit(); case 'd': disable(); break; case 'e': enable(); break; case 'h': hide(); break; case 's': show(); break; #ifdef DBG default : return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key); #endif } return TRUE; } switch(key) { case K_SPACE: set_dirty(); break; case K_PREV: case K_NEXT: send_key(key, 0); break; case K_F1: #if XVT_OS == XVT_OS_WIN if (fexist("prassi.hlp")) { struct MULTIGUY { UINT mkSize; BYTE mkKeylist; char mkKeyphrase[16]; } mk; TFilename topic(mask().source_file()); topic.ext(""); mk.mkSize = sizeof(MULTIGUY); mk.mkKeylist = 'M'; strcpy(mk.mkKeyphrase, topic); TFilename hlp("prassi.hlp"); const TString16 mod(topic.left(2)); if (mod != "ba") hlp.insert(mod, 0); HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); set_focus(); break; } #endif case K_SHIFT+K_F1: if (_help.not_empty()) message_box(_help); else beep(); set_focus(); break; case K_F11: { const char* c = ""; if (field()) c = field()->name(); message_box("State utilizzando il campo %d della maschera '%s'\n" "corrispondente al campo su file '%s'", dlg(), (const char*)mask().source_file(), c); set_focus(); } break; case K_F2: if (is_edit()) set(""); else reset(); set_dirty(); break; case K_F3: undo(); set_dirty(); break; default: break; } if (_handler) return _handler(*this, key); return TRUE; } void TMask_field::highlight() const { xvt_scr_set_focus_vobj(win()); } void TMask_field::set_focus() const { const bool force = mask().is_running(); mask().set_focus_win(win(), force); } HIDDEN char* const _msg = &__tmp_string[512]; #define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr) // @mfunc Crea una error-box relativo al campo (chiama ) // // @rdesc Ritorna sempre FALSE bool TMask_field::error_box( const char* fmt, // @parm Formato della stringa da scrivere ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti // viene creata una finestra di errore normale. { build_msg(); if (mask().is_sheetmask() && !mask().is_running()) { xvt_statbar_set(_msg); beep(); } else { set_focus(); ::error_box("%s", _msg); set_focus(); } return FALSE; } bool TMask_field::message_box(const char* fmt, ...) const { set_focus(); build_msg(); ::message_box("%s", _msg); set_focus(); return FALSE; } // @mfunc Crea una warning-box relativo al campo (chiama ) // // @rdesc Ritorna sempre FALSE bool TMask_field::warning_box( const char* fmt, // @parm Formato della stringa da scrivere ...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in

// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti // viene creata una finestra di warning normale. { build_msg(); if (mask().is_sheetmask() && !mask().is_running()) { xvt_statbar_set(_msg); beep(); } else { set_focus(); ::warning_box("%s", _msg); set_focus(); } return FALSE; } bool TMask_field::yesno_box(const char* fmt, ...) const { set_focus(); build_msg(); const bool yes = ::yesno_box("%s", _msg); set_focus(); return yes; } KEY TMask_field::yesnocancel_box(const char* fmt, ...) const { set_focus(); build_msg(); const KEY k = ::yesnocancel_box("%s", _msg); set_focus(); return k; } /////////////////////////////////////////////////////////// // TList_sheet /////////////////////////////////////////////////////////// // Certified 100% TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head) : _fld(f), _row(-1) { _sheet = new TArray_sheet(-1, -1, 0, 0, caption, head); } // Certified 100% TList_sheet::~TList_sheet() { delete _sheet; } // Certified 100% TMask_field& TList_sheet::field(short id) const { return field().mask().field(id); } // Certified 100% void TList_sheet::read_item(TScanner& scanner) { TToken_string ts(scanner.string()); _sheet->add(ts); } // Certified 100% void TList_sheet::parse_input(TScanner& scanner) { _inp_id.add(scanner.pop()); } // Certified 100% void TList_sheet::parse_output(TScanner& scanner) { _out_id.add(scanner.pop()); } // il numero di riga selezionata int TList_sheet::do_input() { if (_inp_id.empty()) return -2; // List empty! _inp_id.restart(); TToken_string rowsel(80); for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { rowsel.add(fld+1); if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1); } else { const short id = _fld->atodlg(fld); if (id > 0) { TMask_field& tempf = field().mask().field(id); if ( tempf.class_id() == CLASS_ZOOM_FIELD ) { TZoom_field& tempz = ( TZoom_field & ) tempf; rowsel.add( tempz.get_first_line( ) ); } else rowsel.add(field().mask().get(id)); } else rowsel.add(""); } } TString80 fd, it; for (int i = 0 ; i < _sheet->items(); i++) { TToken_string& ts =_sheet->row(i); ts.restart(); for ( const char* item = rowsel.get(0); item ; item = rowsel.get()) { it = item; it.trim(); fd = ts.get(); fd.trim(); if (fd != it) break; } if (!item) return i; } return -1; // Value not found! } // Certified 50% void TList_sheet::do_output(CheckTime t) { if (_row < 0 || t == FINAL_CHECK) return; _out_id.restart(); TToken_string& rowsel = _sheet->row(_row); rowsel.restart(); for (const char* fld = _out_id.get(); fld; fld = _out_id.get()) { const short id = _fld->atodlg(fld); TMask_field& f = field(id); const char* val = rowsel.get(); if (t != STARTING_CHECK || f.field() == NULL) { f.set(val); if (field().dlg() != id) f.on_hit(); } } } // Certified 100% KEY TList_sheet::run() { _row = do_input(); _sheet->select(_row); const KEY k = _sheet->run(); switch (k) { case K_ENTER: _row = (int)_sheet->selected(); do_output(); break; default: break; } return k; } // Certified 100% bool TList_sheet::check(CheckTime t) { const bool passed = (_row = do_input()) != -1; if (passed) do_output(t); return passed; } /////////////////////////////////////////////////////////// // TBrowse /////////////////////////////////////////////////////////// // Certified 100% TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter) : _relation(r), _cursor(new TCursor (r, filter, key)), _fld(f), _filter(filter), _secondary(FALSE), _checked(FALSE) {} // Certified 100% TBrowse::TBrowse(TEdit_field* f, TCursor* c) : _relation(NULL), _cursor(c), _fld(f), _secondary(FALSE), _checked(FALSE) {} // Certified 100% TBrowse::~TBrowse() { if (_relation) { delete _relation; delete _cursor; } } // Certified 100% void TBrowse::parse_display(TScanner& scanner) { const char* s; s = scanner.string(); _head.add(s); s = scanner.line(); _items.add(s); } void TBrowse::parse_input(TScanner& scanner) { const char* s = scanner.pop(); _inp_fn.add(s); s = scanner.pop(); if (*s == '"') // Constant string { scanner.push(); TString& str = scanner.line(); _inp_id.add(str); if (_cursor->file().num() == LF_GOLEM) // GOLEM 2 detected! { str.strip("\""); _insert = "G"; _insert << str; } } else // Field on the mask { TString80 str(s); if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field else scanner.push(); _inp_id.add(str); } } void TBrowse::parse_output(TScanner& scanner) { const char* s = scanner.pop(); #ifdef DBG field().atodlg(s); #endif _out_id.add(s); s = scanner.pop(); _out_fn.add(s); } bool TBrowse::parse_copy(const TString& what, const TBrowse& b) { const bool all = what == "AL"; if (all || what == "US") { set_insert(b.get_insert()); _filter = b.get_filter(); if (field()._warning.empty()) field()._warning = b.field()._warning; if (!all) return TRUE; } if (all || what == "IN") { _inp_id = b._inp_id; _inp_fn = b._inp_fn; if (!all) return TRUE; } if (all || what == "DI") { _head = b._head; _items = b._items; if (!all) return TRUE; } if (all || what == "OU") { _out_id = b._out_id; _out_fn = b._out_fn; _secondary = b.field().has_check(); } return TRUE; } void TBrowse::parse_join(TScanner& scanner) { TString80 j(scanner.pop()); // File or table CHECKS(_relation, "Can't join to NULL relation ", (const char*)j); int to; if (scanner.popkey() == "TO") // TO keyword { const char* t = scanner.pop(); to = name2log(t); } else { to = 0; // _relation->lfile()->num(); scanner.push(); } int key = 1; if (scanner.popkey() == "KE") key = scanner.integer(); else scanner.push(); byte alias = 0; if (scanner.popkey() == "AL") alias = scanner.integer(); else scanner.push(); TToken_string exp(80); if (scanner.pop() == "INTO") { const char* r = scanner.pop(); while (strchr(r, '=') != NULL) { exp.add(r); r = scanner.pop(); } } scanner.push(); #ifdef DBG if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); #endif if (isdigit(j[0])) _relation->add(atoi(j), exp, key, to, alias); // join file else { #ifdef DBG if (j.len() > 4) yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); else #endif _relation->add(j, exp, key, to, alias); // join table } } void TBrowse::parse_insert(TScanner& scanner) { const TString& key = scanner.popkey(); _insert.cut(0); if (key != "NO") { _insert << key[0] << scanner.line(); _insert.trim(); } } // Certified 100% TMask_field& TBrowse::field(short n) const { return _fld->mask().field(n); } // Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro int TBrowse::inputs() { int inp = 0; for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get()) { if (*fld != '"' && strchr(fld, '@') == NULL && field(atoi(fld)).is_edit()) inp++; } return inp; } // @mfunc Ritorna il numero di campi non vuoti e non filtrati // // @rdesc Numero di campi non vuoti e non filtrati int TBrowse::do_input( bool filter) // @parm ?? // @comm Questa funzione serve ai TCursor_sheet { int ne = 0; if (_inp_id.empty()) return ne; TRectype& cur = _cursor->curr(); cur.zero(); TRectype filtrec(cur); _inp_id.restart(); _inp_fn.restart(); TString256 val; // Value to output bool tofilter; for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get()) { if (*fld == '"') { val = (fld+1); if (val.not_empty()) val.rtrim(1); tofilter = filter; } else { const short id = _fld->atodlg(fld); const bool filter_flag = strchr(fld, '@') != NULL; tofilter = filter && filter_flag; val = field(id).get(); const TMask_field& f = field(id); if (f.class_id() == CLASS_DATE_FIELD && f.right_justified()) { const TDate d(val); val = d.string(ANSI); } if (f.is_edit() && val.not_empty() && !filter_flag) ne++; // Increment not empty fields count } TFieldref fldref(_inp_fn.get(), 0); // Output field fldref.write(val, _cursor->relation()); if (tofilter) { if (val.empty()) val.fill('~', fldref.len(cur)); fldref.write(val, filtrec); } } if (!filter) return ne; TString work(_filter.size()); for (int i = 0; _filter[i]; i++) { if (_filter[i] == '"') { do { work << _filter[i++]; } while (_filter[i] && _filter[i] != '"'); work << '"'; if (!_filter[i]) break; } else if (_filter[i] == '#') { work << '"' << field(atoi(&_filter[++i])).get() << '"'; while (isspace(_filter[i])) i++; while (isdigit(_filter[i])) i++; i--; } else work << _filter[i]; } _cursor->setfilter(work); _cursor->setregion(filtrec, filtrec); return ne; } void TBrowse::do_output(CheckTime t) { if (t == FINAL_CHECK) return; TString sum; TToken_string flds(24, '+'); _out_fn.restart(); for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get()) { const short id = field().atodlg(fld); TMask_field& f = field(id); flds = _out_fn.get(); if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS) { sum.cut(0); for(const char* fr = flds.get(0); fr; fr = flds.get()) { if (*fr == '"') { sum << (fr+1); sum.rtrim(1); } else { const TFieldref fld(fr, 0); sum << fld.read(_cursor->relation()); } } f.set(sum); if (field().dlg() != id) f.on_hit(); } } } void TBrowse::do_clear() { for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get()) { TMask_field& f = field(atoi(fld)); if (f.field() == NULL && _inp_id.get_pos(fld) < 0) f.reset(); } } bool TBrowse::do_insert() { bool ok = FALSE; TString80 app; if (_insert[0] == 'M') { TString80 nm(_insert.mid(1)); if (nm.compare("batb", 4, TRUE) == 0) // Programma gestione tabelle app = format("ba3 -0 %s", (const char*)nm.mid(4)); // Obbligatorio usare la format globale else // Programma generico di browse/edit app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num()); // Obbligatorio usare la format globale } else if (_insert[0] == 'G') { TGolem golem(&_insert[1], atol(field().get())); const bool ok = golem.edit(); return ok ? TRUE : error_box("Impossibile modificare l'oggetto"); } else { app = &_insert[1]; } if (app.find('#') != -1) { TString80 w(app); app = ""; for (const char* f = w; *f; f++) { if (*f == '#') { const int id = atoi(++f); app << _fld->mask().get(id); while (isspace(*f)) ++f; while (isdigit(*f)) ++f; if (*f) app << ' ' << *f; else break; } else app << *f; } } TMailbox mail; TMessage msg(app, MSG_AI, ""); mail.send(msg); TExternal_app a(app); a.run(); _fld->mask().set_focus(); if (mail.check()) { TMessage* rcv = mail.next_s(MSG_AI); if (rcv != NULL) _rec = atoi(rcv->body()); if (_rec > 0) { _cursor->file().readat(_rec); ok = _cursor->ok(); if (ok) do_output(); #ifdef DBG else yesnofatal_box("Selezione da programma esterno errata"); #endif } } return ok; } TToken_string& TBrowse::create_siblings(TToken_string& siblings) { const TMask& mask = field().mask(); siblings = ""; // Azzera la lista dei campi associati // if (!mask.is_running()) return siblings; TBit_array key(4); // Elenco delle chiavi gia' utilizzate key.set(_cursor->key()); // Scorre la lista dei campi di output int n = 0; for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++) { const short id = _fld->atodlg(i); const TMask_field& f = mask.field(id); if (!f.shown() || !f.is_edit()) // Scarta i campi non editabili continue; const TEdit_field& e = (const TEdit_field&)f; const TBrowse* b = e.browse(); if (b == NULL) continue; // Scarta i campi senza ricerca const TCursor* c = b->cursor(); // Considera ricerche sullo stesso file ma con chiave diversa if (c->file().num() == _cursor->file().num() && (key[c->key()] == FALSE || id == _fld->dlg())) { TString16 fn(_out_fn.get(n)); // Legge nome del campo su file int pos = _items.get_pos(fn); // Determina header corrispondente if (pos < 0) // Se non lo trova identico ... { const int q = fn.find('['); if (q > 0) { fn.cut(q); pos = _items.get_pos(fn); // ... ritenta senza parentesi } } if (pos >= 0) { siblings.add(id); const char* h = _head.get(pos); siblings.add(h); const int et = siblings.find('@'); if (et > 0) siblings.cut(et); key.set(c->key()); // Marca la chiave come usata } } } return siblings; } KEY TBrowse::run() { do_input(TRUE); _cursor->read(_isgteq); const TLocalisamfile& f = _cursor->file(); TString80 caption(prefix().description(f.name())); if (!isalnum(caption[0])) caption = "Selezione"; KEY k = K_ESC; long selected = 0; TToken_string siblings; create_siblings(siblings); { TToken_string* sib = siblings.empty() ? NULL : &siblings; byte buttons = 0; if (_insert.not_empty()) { buttons = 1; // Mette il bottone di gestione, a meno che ... if (_insert[0] == 'G') { buttons |= 2; } else { const TString& maskname = _fld->mask().source_file(); if (maskname.compare("batb", 4, TRUE) == 0 && _fld->in_key(0)) { const char* tabname = _cursor->file().name(); if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0) buttons = 0; } } } TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib); k = s.run(); selected = s.selected(); } switch (k) { case K_INS: if (_insert[0] == 'G') field().set(format("%ld", selected+1)); k = do_insert() ? K_ENTER : K_ESC; break; case K_CTRL+'N': { TGolem gol(&_insert[1], 0); if (gol.import()) field().set(format("%ld", gol.id())); } k = K_ENTER; break; case K_ENTER: *_cursor = selected; do_output(); break; default: if (k >= K_CTRL) { const TMask& m = _fld->mask(); const short id = siblings.get_int((k - K_CTRL) << 1); TEdit_field& ef = m.efield(id); ef.set_focus(); k = K_F9; if (m.is_running()) ef.send_key(k, 0); } break; } return k; } bool TBrowse::check(CheckTime t) { bool passed = TRUE; if (_secondary == TRUE && t != RUNNING_CHECK) return TRUE; if (_fld->check_type() != CHECK_NONE) { const TMaskmode mode = (TMaskmode)field().mask().mode(); CheckType chk = _fld->check_type(); if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY)) chk = CHECK_NORMAL; const int ne = do_input(TRUE); if (ne || chk == CHECK_REQUIRED) { _cursor->setkey(); _cursor->file().read(_isequal); passed = _cursor->ok(); if (t != FINAL_CHECK) { if (passed) { _cursor->repos(); do_output(t); } else { if (chk == CHECK_SEARCH) { passed = TRUE; } else { do_clear(); if (!_fld->mask().query_mode() && _fld->check_enabled()) _fld->set_dirty(3); } } } else { if (chk == CHECK_SEARCH) passed = TRUE; } } else { if (chk == CHECK_SEARCH) passed = TRUE; else { if (t != FINAL_CHECK) do_clear(); } } } return passed; } bool TBrowse::empty_check() { if (field().mask().query_mode() || _fld->check_type() != CHECK_REQUIRED) return TRUE; else return do_input() > 0; } /////////////////////////////////////////////////////////// // TEdit_field /////////////////////////////////////////////////////////// TEdit_field::TEdit_field(TMask* mask) : TMask_field(mask), _browse(NULL), _sheet(NULL), _buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(FALSE), _forced(FALSE) {} TEdit_field::~TEdit_field() { if (_browse) delete _browse; else if (_sheet) delete _sheet; } word TEdit_field::class_id() const { return CLASS_EDIT_FIELD; } void TEdit_field::enable(bool on) { TMask_field::enable(on); if (_buttonwin != NULL_WIN) xvt_vobj_set_visible(_buttonwin, on && check_enabled() && shown()); } void TEdit_field::show(bool on) { TMask_field::show(on); if (_buttonwin != NULL_WIN) xvt_vobj_set_visible(_buttonwin, on && check_enabled() && enabled()); } void TEdit_field::parse_head(TScanner& scanner) { _size = scanner.integer(); #ifdef DBG if (_size < 1) { _size = 8; yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); } #endif _width = scanner.integer(); if (_width == 0) _width = _size; } const TBrowse* TEdit_field::get_browse(TScanner& scanner) const { const int id = scanner.integer(); const TEdit_field& f = mask().efield(id); const TBrowse* b = (const TBrowse*)f.browse(); #ifdef DBG if (b == NULL) yesnofatal_box("La USE del campo %d e' nulla e non puo' essere copiata nel campo %d", id, dlg()); #endif return b; } bool TEdit_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") // PICTURE { _picture = scanner.string(); #ifdef DBG if (_picture == "." && _size > 9 && _size != 15) ::warning_box("Guy propone una dimensione di 15 per il campo %d: %s\nMa probabilmente ha toppato ...", dlg(), (const char*)_prompt); #endif return TRUE; } if (scanner.key() == "CH") { scanner.pop(); if (scanner.key() == "NO") _check = CHECK_NORMAL; else if (scanner.key() == "RE") _check = CHECK_REQUIRED; else if (scanner.key() == "FO") { _check = CHECK_REQUIRED; _forced = TRUE; } else if (scanner.key() == "SE") _check = CHECK_SEARCH; else _check = CHECK_NONE; return TRUE; } if (scanner.key() == "US") // USE { #ifdef DBG if (_browse != NULL) return yesnofatal_box("USE duplicata nel campo %d", dlg()); #endif int key = 1; TRelation* r; const int logicnum = scanner.integer(); TString16 tabmaskname; if (logicnum > 0) r = new TRelation(logicnum); else { tabmaskname = scanner.pop(); #ifdef DBG if (tabmaskname.len() > 4) return yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)tabmaskname, dlg()); #endif r = new TRelation(tabmaskname); } if (scanner.popkey() == "KE") { key = scanner.integer(); #ifdef DBG if (key < 1 || key > 15) { yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg()); key = 1; } #endif } else scanner.push(); const char* filter = ""; if (scanner.popkey() == "SE") filter = (const char*)scanner.line(); else scanner.push(); _browse = new TBrowse(this, r, key, filter); if (tabmaskname.not_empty()) { tabmaskname.insert("MBATB", 0); _browse->set_insert(tabmaskname); } _check_enabled = TRUE; return TRUE; } if (scanner.key() == "CO") // Copyuse { const TString16 what(scanner.popkey()); const TBrowse* b = get_browse(scanner); if (b == NULL) return FALSE; if (what == "US" || what == "AL") _browse = new TBrowse(this, b->cursor()); if (_browse) { _check_enabled = TRUE; return _browse->parse_copy(what, *b); } #ifdef DBG return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg()); #endif } if (scanner.key() == "JO") { #ifdef DBG if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg()); #endif _browse->parse_join(scanner); return TRUE; } if (scanner.key() == "SH") // SHEET { #ifdef DBG if (_sheet) return yesnofatal_box("SHEET duplicato nel campo %d", dlg()); #endif _sheet = new TList_sheet(this, _prompt, scanner.string()); _check_enabled = TRUE; return TRUE; } if (scanner.key() == "IT") // ITEM { #ifdef DBG if (_sheet == NULL) return yesnofatal_box("ITEM senza SHEET nel campo %d", dlg()); #endif _sheet->read_item(scanner); return TRUE; } if (scanner.key() == "IN") { if (_browse) _browse->parse_input(scanner); else if (_sheet) _sheet->parse_input(scanner); #ifdef DBG else yesnofatal_box("INPUT senza USE o SHEET nel campo %d", dlg()); #endif return TRUE; } if (scanner.key() == "DI") { #ifdef DBG if(!_browse) return yesnofatal_box("DISPLAY senza USE nel campo %d", dlg()); #endif _browse->parse_display(scanner); return TRUE; } if (scanner.key() == "OU") { if (_browse) _browse->parse_output(scanner); else if (_sheet) _sheet->parse_output(scanner); #ifdef DBG else return yesnofatal_box("OUTPUT senza USE nel campo %d", dlg()); #endif return TRUE; } if (scanner.key() == "AD") { #ifdef DBG if(!_browse) return yesnofatal_box("ADD senza USE nel campo %d", dlg()); #endif _browse->parse_insert(scanner); return TRUE; } if (scanner.key() == "ME") { TFixed_string l(scanner.line().strip_spaces()); int m = 0; if (l[0] == '0') { l.ltrim(1); l.ltrim(); m = 1; } if (_message.objptr(m) == 0) _message.add(new TToken_string(64), m); TToken_string& ts = (TToken_string&)_message[m]; ts.add(l); return TRUE; } return TMask_field::parse_item(scanner); } void TEdit_field::create(WINDOW parent) { const int len = create_prompt(parent); long bandiere = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST; if (_flags.uppercase) bandiere |= CTL_FLAG_MAC_GENEVA9; if (_flags.password) bandiere |= CTL_FLAG_MAC_MONACO9; _x += len; #if XVTWS == WMWS const int delta = 2; #else const int delta = 1; #endif wincreate(WC_EDIT, _width+delta, 1, _str, parent, bandiere); #if XVT_OS == XVT_OS_WIN HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW); SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo #endif if (_browse || _sheet) { long flags = default_flags(); if (flags & CTL_FLAG_DISABLED) { flags &= ~CTL_FLAG_DISABLED; flags |= CTL_FLAG_INVISIBLE; } TString16 ico("*"); if (_browse && _browse->get_insert()[0] == 'G') { const char* g = _browse->get_insert(); TGolem golem(g+1, 0); ico.format("#%d", golem.icon()); } _buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, 2, 1, ico, parent, flags, PTR_LONG(this), DLG_F9); } } void TEdit_field::set_back_color(COLOR c) const { if (_promptwin != NULL_WIN) xvt_set_ctrl_back_color(_promptwin, c); } void TEdit_field::destroy() { if (_buttonwin) { xvt_vobj_destroy(_buttonwin); _buttonwin = NULL_WIN; } TMask_field::destroy(); } void TEdit_field::set_window_data(const char* data) { TMask_field::set_window_data(format(data)); } void TEdit_field::set_field_data(const char* data) { _str = data; } const char* TEdit_field::get_field_data() const { return _str; } const char* TEdit_field::format(const char* d) const { fpark = d; if (_flags.trim) fpark.trim(); if (fpark.not_empty()) { int len = fpark.len(); if (len > _size) { #ifdef DBG yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), (const char*)fpark, _size); #endif fpark.cut(len = _size); } if (len < _size) { if (_flags.zerofilled) { if (isdigit(fpark[0]) && real::is_real(fpark)) fpark.right_just(_size, '0'); } else if (_flags.rightjust) fpark.right_just(_size); } if (_flags.uppercase) fpark.upper(); if (!_flags.pipeallowed) { for (int p = 0; fpark[p]; p++) if (fpark[p] == '|') fpark[p] = '/'; } } return fpark; } const char* TEdit_field::picture_data(const char* data, bool video) const { fpark = video ? data : format(data); if (_flags.trim) fpark.trim(); return fpark; } // @mfunc Chiama l' eventuale funzione di validazione // // @rdesc Ritorna il risultato dell funzione di validazione: // // @flag TRUE | Se la validata ha avuto successo // @flag FALSE | Se la validata no ha avuto successo bool TEdit_field::validate( KEY k) // @parm Tasto da passare alla funzione di validazione { return _validate_func < 0 ? TRUE : ::validate(_validate_func, *this, k, _validate_parms); } // Certified 90% bool TEdit_field::on_hit() { if (_validate_func >= 0 && (_validate_func == AUTOEXIT_FUNC || _validate_func == NUMCALC_FUNC || _validate_func == STRCALC_FUNC)) { set(get()); bool ok = validate(is_edit() ? K_TAB : K_SPACE); // Check validation expression if (!ok) return FALSE; } if (_handler) { bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE); if (!ok) return FALSE; } if (_message.objptr(1) && get() == "") do_message(1); else do_message(0); return TRUE; } // @mfunc Mostra un messaggio di errore di default per il campo // // @rdesc Ritorna sempre FALSE bool TEdit_field::default_error_box() const // @comm Se il campo non possiede un warning particolare chiama la // indicando genericamente che il valore immesso non e' valido, altrimenti // riporta il warning associato al campo { if (_warning.empty()) { const char* p = prompt(); if (isalnum(p[0])) error_box("Valore non valido per %s: '%s'", p, (const char*)get()); else error_box("Valore non valido: '%s'", (const char*)get()); } else error_box(_warning); return FALSE; } bool TEdit_field::on_key(KEY key) { switch(key) { case K_TAB: if (_validate_func >= 0 && (_validate_func == AUTOEXIT_FUNC || _validate_func == NUMCALC_FUNC || _validate_func == STRCALC_FUNC)) set_focusdirty(); // Forza validate if (to_check(K_TAB, TRUE)) { set(get()); bool ok = validate(key); // Check validation expression if (!ok) { if (_warning.not_empty()) default_error_box(); return FALSE; } TMask& m = mask(); const bool query = m.query_mode(); if (_sheet) ok = query || _sheet->check(); // Check consistency else if (_browse && check_enabled() && (!query || forced()) && _validate_func != 21) ok = _browse->check(); if (!ok) return default_error_box(); ok = on_hit(); if (!ok) return FALSE; if (query && required() && in_key(0)) { const byte keys = m.num_keys(); for (int i = 1; i <= keys; i++) if (in_key(i) && m.key_valid(i)) { for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE)) m.field(fld).set_dirty(FALSE); mask().stop_run(K_AUTO_ENTER); break; } } return TRUE; } break; case K_ENTER: if (field() != NULL || mask().mode() == NO_MODE) { if (focusdirty()) set(get()); bool ok = validate(K_ENTER); // Check validation expression if (!ok) { if (_warning.not_empty()) default_error_box(); return FALSE; } const bool query = mask().query_mode(); // check consistency if (_sheet) ok = query || _sheet->check(FINAL_CHECK); else { ok = query || !(check_type() == CHECK_REQUIRED && get().empty()); if (_browse && ok && check_enabled() && _validate_func != 21 && // 21 = NOT_EMPTY_CHECK_FIELD (!query || forced())) { if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency else ok = _browse->empty_check(); } } if (!ok) return default_error_box(); } break; case K_F9: if (check_enabled()) { enable_check(FALSE); if (dirty()) set(get()); KEY k = K_ESC; if (_browse) k = _browse->run(); else if (_sheet) k = _sheet->run(); else beep(); if (k != K_F9) set_focus(); enable_check(TRUE); if (k == K_ENTER) { set_dirty(); if (mask().is_running()) send_key(K_TAB, 0); else on_hit(); return TRUE; } else return FALSE; } break; default: break; } return TMask_field::on_key(key); } bool TEdit_field::has_check() const { if (_browse) return check_type() != CHECK_NONE; return _sheet != NULL; } bool TEdit_field::check(CheckTime t) { bool ok = TRUE; if (check_enabled() || (t == STARTING_CHECK && shown())) { if (_browse) ok = (_validate_func == 21) || _browse->check(t); else if (_sheet) ok = _sheet->check(t); } return ok; } // @mfunc Permette di abilitare/disabilitare un check di un campo void TEdit_field::enable_check( bool on) // @parm Operazione da svolgere // // @flag TRUE | Abilita il check del campo (default) // @flag FALSE | Disabilita il check del campo { _check_enabled = on; if (_buttonwin != NULL_WIN) xvt_vobj_set_visible(_buttonwin, on); } /////////////////////////////////////////////////////////// // Boolean_field /////////////////////////////////////////////////////////// TBoolean_field::TBoolean_field(TMask* m) : TMask_field(m), _on(FALSE) {} word TBoolean_field::class_id() const { return CLASS_BOOLEAN_FIELD; } void TBoolean_field::create(WINDOW parent) { wincreate(WC_CHECKBOX, _prompt.len()+3, 1, _prompt, parent, 0); } void TBoolean_field::set_back_color(COLOR c) const { xvt_set_ctrl_back_color(win(), c); } const char* TBoolean_field::get_window_data() const { CHECK(win(), "Control window not initialized"); fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' '; fpark[1] = '\0'; return fpark; } void TBoolean_field::set_window_data(const char* data) { CHECK(win(), "Control window not initialized"); if (data == NULL) data = ""; const bool b = toupper(*data) == 'X'; xvt_check_box(win(), b); } void TBoolean_field::set_field_data(const char* data) { if (data == NULL) data = ""; _on = toupper(*data) == 'X'; } const char* TBoolean_field::get_field_data() const { return _on ? "X" : " "; } bool TBoolean_field::parse_item(TScanner& scanner) { if (scanner.key() == "ME") { const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE if (_message.items() == 0) { _message.add(new TToken_string(16)); _message.add(new TToken_string(16)); } TToken_string& ts = (TToken_string&)_message[tf]; ts.add(scanner.line().strip_spaces()); return TRUE; } return TMask_field::parse_item(scanner); } void TBoolean_field::enable(bool on) { _flags.enabled = on; xvt_enable_control(_win, on); } bool TBoolean_field::on_hit() { if (_handler) { bool ok = _handler(*this, K_SPACE); if (!ok) return FALSE; } const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on; do_message(n); return TRUE; } bool TBoolean_field::on_key(KEY key) { if (key == K_SPACE) { on_hit(); set_dirty(); return TRUE; } return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // Button_field /////////////////////////////////////////////////////////// TButton_field::TButton_field(TMask* m) : TMask_field(m) { _flags.persistent = TRUE; } word TButton_field::class_id() const { return CLASS_BUTTON_FIELD; } void TButton_field::parse_head(TScanner& scanner) { _width = scanner.integer(); if (_width < 1) _width = 9; _size = scanner.integer(); // Height if (_size < 1) _size = 1; } bool TButton_field::parse_item(TScanner& scanner) { if (scanner.key() == "PI") { const int bmp = scanner.integer(); _prompt << '#' << bmp; return bmp > 0; } return TMask_field::parse_item(scanner); } void TButton_field::create(WINDOW parent) { long flags = CTL_FLAG_CENTER_JUST; switch (dlg()) { case DLG_OK: if (_prompt.empty()) _prompt = "Conferma"; _virtual_key = _exit_key = K_ENTER; flags |= CTL_FLAG_DEFAULT; break; case DLG_CANCEL: if (_prompt.empty()) _prompt = "Annulla"; _virtual_key = _exit_key = K_ESC; break; case DLG_DELREC: if (_prompt.empty()) _prompt = "Elimina"; _virtual_key = 'E'; _exit_key = K_DEL; break; case DLG_PRINT: if (_prompt.empty()) _prompt = "Stampa"; _virtual_key = 'S'; _exit_key = K_ENTER; break; case DLG_QUIT: if (_prompt.empty()) _prompt = "Fine"; _virtual_key = K_F4; _exit_key = K_QUIT; break; default: { _exit_key = 0; TToken_string* message = (TToken_string*)_message.objptr(0); if (message != NULL) { TToken_string msg(message->get(0), ','); const TFixed_string m(msg.get(0)); if (m == "EXIT") _exit_key = msg.get_int(); else if (msg.get_int() == 0) _exit_key = atoi(m); } const int n = _prompt.find('~'); _virtual_key = (n >= 0) ? toupper(_prompt[n+1]) : _exit_key; } break; } #if XWTWS == WMWS const int diesis = _prompt.find('#'); if (diesis > 0) _prompt.cut(diesis); _prompt.center_just(_width); #endif wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags); } void TButton_field::set_back_color(COLOR c) const {} void TButton_field::enable(bool on) { _flags.enabled = on; xvt_enable_control(_win, on); } void TButton_field::show(bool on) { TMask_field::show(on); } bool TButton_field::on_key(KEY key) { if (key == K_SPACE) { on_hit(); return TRUE; } return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // Date_field /////////////////////////////////////////////////////////// word TDate_field::class_id() const { return CLASS_DATE_FIELD; } void TDate_field::create(WINDOW w) { TEdit_field::create(w); if (automagic()) { TDate d(TODAY); set(d.string()); } } void TDate_field::parse_head(TScanner&) {} TDate_field::TDate_field(TMask* m) : TEdit_field(m) { _size = _width = 10; } const char* TDate_field::get_window_data() const { bool dummy; TString16 str = TEdit_field::get_window_data(); return format_data(str, &dummy); } void TDate_field::set_window_data(const char* data) { const TDate d(data); TEdit_field::set_window_data(d.string()); } // @mfunc Permette di formattare la data secondo i flag correnti // // @rdesc Ritorna la data formattata const char* TDate_field::format_data( const char* datum, // @parm Stringa contenenete la data da formattare bool* ch) const // @parm Indica se e' stata cambiato il formato rispetto alla stringa passsata // @comm Permette di gestire anche alcuni date particolari come: // // @flag IERI | Inserisce la data del giorno precedente a quella del sistema // @flag OGGI | Inserisce la data del sistema // @flag DOMANI | Inserisce la data del giorno successivo a quella del sistema // @flag PRIMO | Primo giorno dell'anno (01-01-aa) // @flag ULTIMO | Ultimo giorno dell'anno (31-12-aa) // @flag NATALE | Giorno di natale (25-12-aa) { bool changed = FALSE; fpark = datum; fpark.trim(); if (fpark.not_empty()) { if (isdigit(fpark[0])) { if (fpark.len() == 6) // Fix century (for this millenium only) { fpark.insert("19", 4); changed = TRUE; } for (int meno = 2; meno <= 5; meno += 3) if (fpark[meno] != '-') { fpark.insert("-", meno); changed = TRUE; } if (fpark.len() == 8) // Fix century (for this millenium only) { fpark.insert("19", 6); changed = TRUE; } } else { TDate g(TODAY); fpark.upper(); if (fpark == "IERI") { --g; changed = TRUE; } else if (fpark == "DOMANI") { ++g; changed = TRUE; } TString16 gstring(g.string()); if (fpark == "PRIMO") { gstring.overwrite("01-01", 0); changed = TRUE; } else if (fpark == "NATALE") { gstring.overwrite("25-12", 0); changed = TRUE; } else if (fpark == "ULTIMO") { gstring.overwrite("31-12", 0); changed = TRUE; } else if (fpark == "OGGI") changed = TRUE; if (changed) fpark = gstring; } } if (ch) *ch = changed; return fpark; } bool TDate_field::on_key(KEY key) { if (to_check(key)) { bool changed = FALSE; TFixed_string data(format_data(get_window_data(),&changed), 15); if (data.not_empty()) { // TDate d(data); if (!TDate::isdate(data)) { error_box("Data errata o formato non valido"); return FALSE; } else if (changed) TMask_field::set_window_data(data); } } return TEdit_field::on_key(key); } bool TDate_field::autosave(TRelation* r) const { const char* td = get(); if (right_justified()) { TDate d(td); td = d.string(ANSI); } if (field()) { field()->write(td, r); return TRUE; } return FALSE; } const char* TDate_field::picture_data(const char* data, bool video) const { return video ? format_data(data) : data; } /////////////////////////////////////////////////////////// // Real_field /////////////////////////////////////////////////////////// TReal_field::TReal_field(TMask* m) : TEdit_field(m) {} word TReal_field::class_id() const { return CLASS_REAL_FIELD; } void TReal_field::create(WINDOW w) { TEdit_field::create(w); _flags.rightjust = TRUE; if (_flags.firm) set(::format("%ld", main_app().get_firm())); else if (automagic()) { TDate d(TODAY); set(::format("%d", d.year())); } } bool TReal_field::autoload(const TRelation* r) { const bool ok = TMask_field::autoload(r); if (ok && _flags.zerofilled && _str.not_empty()) { int s = size(); if (roman()) { s = decimals(); if (s < 1) s = 4; } _str.right_just(s, '0'); } return ok; } bool TReal_field::on_key(KEY key) { if (to_check(key)) { if (roman()) { const int r = atoi(get_window_data()); if (r < 0) return error_box("Numero romano errato"); } else { const char* n = get(); if (*n && !real::is_real(n)) return error_box("Valore numerico non valido"); if (_flags.uppercase && *n == '-') return error_box("Il numero deve essere positivo"); if (_flags.firm) { const long f = atol(n); if (f > 0 && prefix().exist(f)) main_app().set_firm(f); } } } return TEdit_field::on_key(key); } void TReal_field::parse_head(TScanner& scanner) { _size = scanner.integer(); #ifdef DBG if (_size < 1) { _size = 9; yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size); } #endif _width = _size; _decimals = scanner.integer(); } void TReal_field::set_window_data(const char* data) { if (data == NULL) data = ""; if (roman()) { data = itor(atoi(data)); } else { real n(data); if (!n.is_zero()) { if (exchangeable() && decimals()) { const real& e = mask().exchange(); n /= e; } if (_picture.empty()) { const char pad = _flags.zerofilled ? '0' : ' '; data = n.stringa(_size, _decimals, pad); } else { fpark = n.string(_picture); fpark.right_just(_size); data = fpark; } } else data = ""; } TMask_field::set_window_data(data); } const char* TReal_field::get_window_data() const { TEdit_field::get_window_data(); if (roman()) { int r = atoi(fpark); if (r == 0) r = rtoi(fpark); if (r > 0) { int s = decimals(); if (s < 1) s = 4; if (_flags.zerofilled) fpark.format("%0*d", s, r); else fpark.format("%*d", s, r); } else fpark.cut(0); } else { fpark = real::ita2eng(fpark); if (exchangeable() && decimals()) { real n(fpark); const real& e = mask().exchange(); n *= e; if (n.is_zero()) fpark.cut(0); else fpark = n.string(); } } return fpark; } const char* TReal_field::picture_data(const char* data, bool video) const { if (video) { fpark = real::ita2eng(data); if (_flags.zerofilled && fpark.not_empty()) fpark.right_just(_size, '0'); } else { const real n(data); if (!n.is_zero()) { if (_picture.empty()) { const char pad = _flags.zerofilled ? '0' : ' '; fpark = n.stringa(_size, _decimals, pad); } else fpark = n.string(_picture); } else fpark.cut(0); } return fpark.trim(); } void TReal_field::set_decimals(int d) { _decimals = d; if (_picture[0] == '.') { if (d > 0) _picture.format(".%d", d); else _picture = "."; } } void TReal_field::exchange(bool show_value, const real& nuo) { const int dec = show_value ? 2 : 0; // Quanti decimali voglio const bool value = decimals() != 0; // Sono attualmente in valuta ? if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito! if (mask().is_running()) { const char* n = get_window_data(); if (*n) { const real& vec = mask().exchange(); real r(n); if (!show_value) r *= nuo; r /= vec; r.round(dec); set_decimals(dec); TEdit_field::set_window_data(r.string(_picture)); } } if (decimals() != dec) set_decimals(dec); } /////////////////////////////////////////////////////////// // List_field /////////////////////////////////////////////////////////// TList_field::TList_field(TMask* m) : TMask_field(m) {} word TList_field::class_id() const { return CLASS_LIST_FIELD; } void TList_field::read_item(TScanner& scanner) { TToken_string ts(scanner.string()); _codes.add(ts.get()); _values.add(ts.get()); ts = ""; while (scanner.popkey() == "ME") ts.add(scanner.line().strip_spaces()); scanner.push(); _message.add(ts); } void TList_field::parse_head(TScanner& scanner) { _size = scanner.integer(); _width = scanner.integer(); if (_width < 1) _width = _size+3; } bool TList_field::parse_item(TScanner& scanner) { if (scanner.key() == "IT") // ITEM { read_item(scanner); return TRUE; } if (scanner.key() == "LI") // LISTITEM { TScanner sc(scanner.pop()); while (sc.popkey() == "IT") // ITEM read_item(sc); return TRUE; } return TMask_field::parse_item(scanner); } int TList_field::items() const { return _codes.items(); } // @mfunc Aggiunge delle voci al list sheet void TList_field::add_item( const char* s) // @parm Voci da aggiungere // @comm Se il parametro

e' passato con il formato di una vengono // aggiunte tante voci quanti sono gli elementi. { TToken_string t(s); const TString16 item(t.get()); const int pos = _codes.get_pos(item); if (pos < 0 ) { _codes.add(item); xvt_list_add(win(), -1, (char*)t.get()); } } void TList_field::delete_item(const char* s) { TString16 t(s); const int pos = _codes.get_pos(t); if (pos >= 0 ) { _codes.destroy(pos); xvt_list_rem(win(), pos); if (mask().is_running()) { xvt_list_set_sel(win(), 0, TRUE); if (shown()) on_hit(); } } } void TList_field::add_list() { if (roman() && _codes.items() < 12) { TString csafe, vsafe; if (atoi(_codes) > 0) { csafe = _codes; _codes = ""; vsafe = _values; _values = ""; } _codes.add("01|02|03|04|05|06|07|08|09|10|11|12"); _values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno"); _values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre"); if (atoi(csafe) > 0) { _codes.add(csafe); _values.add(vsafe); if (_message.objptr(0)) { _message.add(_message[0], _codes.items()-1); _message.add(NULL, 0); } } } SLIST lst = xvt_slist_create(); for (const char* item = _values.get(0); item; item = _values.get()) xvt_slist_add_at_elt(lst, (SLIST_ELT)NULL, (char*)item, 0L); xvt_list_add(win(), -1, (char*)lst); xvt_slist_destroy(lst); const char* init = ""; if (roman() && automagic()) init = format("%02d", TDate(TODAY).month()); set_field_data(init); } // @mfunc Sostituisce alle voci correnti quelle passate come parametri void TList_field::replace_items( const char* codes, // @parm Codici da sostituire ai correnti const char* values) // @parm Voci da sostituire a quelle correnti // @comm I parametri

e

devono essere TToken_string se lo voci da sostiutire // sono piu' di una { _codes = codes; _values = values; if (win() != NULL_WIN) { xvt_list_clear(win()); add_list(); current(0); } } void TList_field::create(WINDOW parent) { const int len = create_prompt(parent); _x += len; wincreate(WC_LISTBUTTON, _width, 5, "", parent,0); add_list(); } void TList_field::set_back_color(COLOR c) const { if (_promptwin != NULL_WIN) xvt_set_ctrl_back_color(_promptwin, c); } int TList_field::str2curr(const char* data) { TString16 str(data); if (roman() && str.len() < 2) str.insert("0",0); if (_flags.uppercase) str.upper(); int i = str.not_empty() ? _codes.get_pos(str) : 0; if (i < 0) // Se non trova il codice ritenta dopo trim { for (i = 0; str[i] == '0' || str[i] == ' '; i++); if (i > 0) { str.ltrim(i); i = _codes.get_pos(str); } } if (i < 0) { if (items() && str.not_empty()) yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d", data, prompt(), dlg()); i = 0; } return i; } void TList_field::set_window_data(const char* data) { CHECKD(win(), "Control window not initialized ", dlg()); const int i = str2curr(data); current(i); } void TList_field::current(int n) { xvt_list_set_sel(win(), n, TRUE); } int TList_field::current() const { const int sel = xvt_list_get_sel_index(win()); #ifdef DBG if (sel < 0 && items() > 0) error_box("Lista senza selezione nel campo %d", dlg()); #endif return sel; } const char* TList_field::get_window_data() const { const int c = current(); const char* v = ((TList_field*)this)->_codes.get(c); return v; } void TList_field::set_field_data(const char* data) { const int i = str2curr(data); _str = _codes.get(i); } bool TList_field::on_hit() { if (_handler) { bool ok = _handler(*this, K_SPACE); if (!ok) return FALSE; } const int n = mask().is_running() ? current() : str2curr(_str); do_message(n); return TRUE; } const char* TList_field::get_field_data() const { return _str; } bool TList_field::on_key(KEY key) { if (key >= '0' && key <= 'z') { const int index = current(); CHECK(index >= 0, "List with no selection!"); int newindex = -1; #if XVTWS == WMWS if (key >= 'A' && key <= 'z') { for (int i = index+1; i != index; i++) { char item[16]; bool flag; do { flag = xvt_list_get_elt(win(), i, item, 16); if (!flag) { CHECK(i, "La lista e' vuota!"); i = -1; break; } } while (!flag); if (flag && toupper(*item) == toupper(key)) { newindex = i; break; } } // for } // alphabetic #endif if (key >= '0' && key <= '9') { newindex = (key == '0') ? 10 : key - '1'; if (newindex > items()) { newindex = -1; beep(); } } if (newindex >= 0) current(newindex); /* { xvt_list_suspend(win()); xvt_list_set_sel(win(), index, FALSE); xvt_list_set_sel(win(), newindex, TRUE); xvt_list_resume(win()); } */ } #if XVTWS == VMWS if (key == K_TAB && class_id() == CLASS_LIST_FIELD) dispacth_e_char(win(), K_F9); #endif if (_validate_func >= 0 && (key == K_TAB || key == K_ENTER)) { const bool ok = ::validate(_validate_func, *this, key, _validate_parms); if (!ok) { if (_warning.not_empty()) return error_box(_warning); } } if (key == K_SPACE) on_hit(); return TMask_field::on_key(key); } /////////////////////////////////////////////////////////// // TRadio_field /////////////////////////////////////////////////////////// TRadio_field::TRadio_field(TMask* mask) : TList_field(mask), _nitems(0), _active_item(0) {} word TRadio_field::class_id() const { return CLASS_RADIO_FIELD; } void TRadio_field::create(WINDOW parent) { const short id = dlg(); // Salva il control id const int items = _codes.items(); if (_prompt.not_empty()) { const int dy = _flags.zerofilled ? 3 : items+2; create_prompt(parent, _width, dy); } _x++; _y++; _values.restart(); const char* s; const int width = _flags.zerofilled ? (_width-2)/items-1 : _width-2; for(_nitems = 0; (s = _values.get()) != NULL; _nitems++) { CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id); wincreate(WC_RADIOBUTTON, width, 1, s, parent,0); _radio_ctl_win[_nitems] = _win; _dlg += 1000; if (_flags.zerofilled) _x += width+1; else _y++; } _radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug _dlg = id; // Ripristina control id set_field_data(""); } void TRadio_field::set_back_color(COLOR c) const { TList_field::set_back_color(c); xvt_set_ctrl_back_color(win(), c); } void TRadio_field::destroy() { if (_promptwin) { xvt_vobj_destroy(_promptwin); _promptwin = NULL_WIN; } for(int i = 0; i < _nitems; i++) { xvt_vobj_destroy(_radio_ctl_win[i]); _radio_ctl_win[i] = NULL_WIN; } } int TRadio_field::current() const { const int c = xvt_get_checked_radio(_radio_ctl_win, _nitems); return c; } void TRadio_field::current(int n) { _active_item = n; xvt_check_radio_button(win(), _radio_ctl_win, _nitems); } void TRadio_field::check_radiobutton(WINDOW checked) { for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++); CHECK(i < _nitems, "Trying to check an invalid radio button"); current(i); } void TRadio_field::enable(bool on) { _flags.enabled = on; for(int i = 0; i < _nitems; i++) xvt_enable_control(_radio_ctl_win[i], on); } void TRadio_field::show(bool on) { if (_promptwin) xvt_vobj_set_visible(_promptwin, on); for(int i = 0; i < _nitems; i++) xvt_vobj_set_visible(_radio_ctl_win[i], on); _flags.shown = on; } // @mfunc Sposta il focus dal radio button // // @rdesc Ritorna TRUE se il focus ha lasciato il radio button bool TRadio_field::move_focus( int d) // @parm Numero di posizioni di spostamento del focus // @comm Poiche' la gestione dei radio button e' gestita direttamente da Windows // in caso si prema TAB o SHIF+TAB all'interno si passa da una voce // all'altra e non al campo successivo o precedente. { const int act = _active_item + d; if (act >= _nitems || act < 0) { _active_item = current(); return TRUE; } xvt_set_front_control(_radio_ctl_win[_active_item = act]); return FALSE; } /////////////////////////////////////////////////////////// // TGroup_field /////////////////////////////////////////////////////////// TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask) { _flags.persistent = TRUE; } // _size means _heigth void TGroup_field::parse_head(TScanner& scanner) { _width = scanner.integer(); _size = scanner.integer(); } void TGroup_field::create(WINDOW parent) { const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0; wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f); } void TGroup_field::set_back_color(COLOR c) const { xvt_set_ctrl_back_color(win(), c); } void TGroup_field::set_window_data(const char* data) { xvt_set_title(win(), data); } void TGroup_field::set_field_data(const char* data) { xvt_set_title(win(), data); } /////////////////////////////////////////////////////////// // TMemo_field /////////////////////////////////////////////////////////// TMemo_field::TMemo_field(TMask* mask) : TMask_field(mask), _te(BAD_TXEDIT), _data( "", '\n' ) { } TMemo_field::~TMemo_field() { _te = BAD_TXEDIT; } void TMemo_field::parse_head(TScanner& scanner) { _width = scanner.integer(); _size = scanner.integer(); } void TMemo_field::create(WINDOW parent) { const short dx = _width; const short dy = _size-1; TMask_field::create(parent); WIN_DEF wd; wd.wtype = WO_TE; wd.rct = resize_rect(_x, _y+1, dx, dy, WC_EDIT, parent); wd.text = NULL; wd.units = U_PIXELS; wd.v.tx.attrib = TX_NOMENU | TX_BORDER | TX_AUTOVSCROLL | TX_WRAP; wd.v.tx.font_id = xvt_dwin_get_font(TASK_WIN); wd.v.tx.margin = wd.rct.right - wd.rct.left; wd.v.tx.limit = 256; wd.v.tx.tx_id = dlg(); _te = xvt_tx_create_def(&wd, parent, NULL); CHECK(_te != BAD_TXEDIT, "Can't create a memo field"); enable_default(); // Setta colori default } void TMemo_field::highlight() const { xvt_tx_set_active(_te); } bool TMemo_field::on_key(KEY k) { return TMask_field::on_key(k); } void TMemo_field::enable(bool on) { TMask_field::enable( TRUE ); unsigned attr = xvt_tx_get_attr(_te); if (on) { xvt_tx_set_colors(_te, NORMAL_COLOR, COLOR_BLACK, NORMAL_BACK_COLOR); attr &= ~TX_READONLY; } else { xvt_tx_set_colors(_te, DISABLED_COLOR, COLOR_BLACK, DISABLED_BACK_COLOR); attr |= TX_READONLY; } xvt_tx_set_attr(_te, attr); } void TMemo_field::show(bool on) { TMask_field::show(on); } /* bool TMemo_field::autoload(const TRelation* r) { const TFieldref* f = field(); xvt_tx_clear(_te); if (f != NULL) { TToken_string data( r->lfile( f->file( ) ).get( f->name( ) ), '\n' ); xvt_tx_suspend(_te); for (T_LNUM i = 0; i < (T_LNUM)data.items( ); i++) xvt_tx_add_par(_te, i, ( char * )data.get( i ) ); xvt_tx_resume(_te); return i > 0; } return FALSE; } bool TMemo_field::autosave(TRelation* r) const { const TFieldref* f = field(); if (dirty() && f != NULL) { const T_PNUM num_par = xvt_tx_get_num_pars(_te); TToken_string data( "", '\n' ); TString par(256); TString256 line; for (T_PNUM p = 0; p < num_par; p++) { par.cut(0); const T_LNUM lines = xvt_tx_get_num_par_lines(_te, p); for (T_LNUM l = 0; l < lines; l++) { unsigned len; xvt_tx_get_line(_te, p, A_LOCK, l, &len); const char* s = xvt_tx_get_line(_te, p, A_GET, l, &len); CHECK(s, "Null memo line"); line.strncpy(s, len); xvt_tx_get_line(_te, p, A_UNLOCK, l, &len); if (par.not_empty()) par << ' '; par << line; } data.add(par); } r->lfile(f->file()).put( f->name(), data ); return num_par > 0; } return FALSE; } */ void TMemo_field::set_window_data(const char* data) { TToken_string realdata( data, '\n' ); xvt_tx_clear(_te); xvt_tx_suspend(_te); for (T_LNUM i = 0; i < (T_LNUM)realdata.items( ); i++) xvt_tx_add_par(_te, i, ( char * )realdata.get( i ) ); xvt_tx_resume(_te); } const char* TMemo_field::get_window_data() const { const T_PNUM num_par = xvt_tx_get_num_pars(_te); TToken_string data( "", '\n' ); TString par(256); TString256 line; for (T_PNUM p = 0; p < num_par; p++) { par.cut(0); const T_LNUM lines = xvt_tx_get_num_par_lines(_te, p); for (T_LNUM l = 0; l < lines; l++) { unsigned len; xvt_tx_get_line(_te, p, A_LOCK, l, &len); const char* s = xvt_tx_get_line(_te, p, A_GET, l, &len); CHECK(s, "Null memo line"); line.strncpy(s, len); xvt_tx_get_line(_te, p, A_UNLOCK, l, &len); if (par.not_empty()) par << ' '; par << line; } data.add(par); } return data; } void TMemo_field::set_field_data(const char* data ) { _data = data; } const char* TMemo_field::get_field_data() const { return _data; } void TZoom_field::set_window_data( const char* data ) { TToken_string getfl( data, '\n' ); TString spark( getfl.get( 0 ) ); TEdit_field::set_window_data( spark ); // set_first_line( spark ); } const char* TZoom_field::get_window_data( ) const { TToken_string& m = (TToken_string&)_memo; const int pos = m.find('\n'); TString park; if (pos >= 0) park=&(m[pos+1]); m = TEdit_field::get_window_data(); if (pos >= 0 ) m << '\n' << park; return _memo; } void TZoom_field::set_field_data( const char* data ) { _memo = data; } const char* TZoom_field::get_field_data( ) const { return _memo; } bool TZoom_field::on_key( KEY key ) { if ( key == K_F8 ) { set_first_line( get_window_data( ) ); TMask m( "Zoom", 1, 72, 15 ); m.add_memo( 101, 0, prompt(), 2, 2, 68, 10 ); m.add_button( DLG_OK, 0, "", -12, 13, 9, 2 ); m.add_button( DLG_CANCEL, 0, "", -22, 13, 9, 2 ); m.set( 101, _memo ); if ( m.run( ) != K_ESC ) { _memo = m.get(101); TString line(get_first_line()); if (line.len() > size()) line.cut(size()); set_window_data( line ); } } return TEdit_field::on_key( key ); } void TZoom_field::enable(bool on) { TEdit_field::enable(on); if (_buttonzoom != NULL_WIN) xvt_vobj_set_visible(_buttonzoom, on && shown()); } void TZoom_field::show(bool on) { TEdit_field::show(on); if (_buttonzoom != NULL_WIN) xvt_vobj_set_visible(_buttonzoom, on && enabled()); } TZoom_field::TZoom_field( TMask* mask ) : TEdit_field( mask ), _memo( "", '\n' ) { } TZoom_field::~TZoom_field( ) { } const char *TZoom_field::get_first_line( ) { return _memo.get( 0 ); } void TZoom_field::set_first_line( const char * c ) { TToken_string gfl( c, '\n' ); TString spark( gfl.get( 0 ) ); TString park; const int pos = _memo.find('\n'); if (pos >= 0) park=&(_memo[pos+1]); _memo = spark; if (pos >= 0 ) _memo << '\n' << park; // _memo.destroy( 1 ); } void TZoom_field::create(WINDOW parent) { TEdit_field::create( parent ); #if XVTWS == WMWS int delta = 2; #else int delta = 1; #endif if (_browse || _sheet) delta += 2; _buttonzoom = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y, 2, 1, "Z", parent, default_flags(), PTR_LONG(this), DLG_F8); } void TZoom_field::destroy() { if (_buttonzoom) { xvt_vobj_destroy(_buttonzoom); _buttonwin = NULL_WIN; } TEdit_field::destroy(); }