diff --git a/include/applicat.cpp b/include/applicat.cpp index 2244f415d..1af26d4c7 100755 --- a/include/applicat.cpp +++ b/include/applicat.cpp @@ -1,3 +1,678 @@ +<<<<<<< applicat.cpp +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BITTEST(w,p) (((w) & (0x0001 << (p))) != 0) + +/////////////////////////////////////////////////////////// +// Metodi di accesso globali all'applicazione corrente +/////////////////////////////////////////////////////////// + +HIDDEN TApplication* _application = NULL; + +TString16 TApplication::_user; + +TApplication* MainApp() +{ + CHECK(_application, "NULL application!"); +#ifdef DBG + error_box("Ti lascio usare MainApp ancora per pochi giorni!"); +#endif + return _application; +} + +TApplication& main_app() +{ + CHECK(_application, "NULL application!"); + return *_application; +} + +bool xvt_running() { return _application != NULL; } + +/////////////////////////////////////////////////////////// +// Gestione dello sfondo della finestra principale +/////////////////////////////////////////////////////////// + +HIDDEN long backdrop_eh( WINDOW win, EVENT* ep) +{ +#if XVT_OS == XVT_OS_WIN + clear_window( win, COLOR_GRAY ); +#else + clear_window( win, COLOR_BLUE ); +#endif + + return 0L; +} + +HIDDEN void create_backdrop( void ) +{ +#if XVT_OS == XVT_OS_WIN + xvt_create_statbar(); + xvt_statbar_set(""); +#else + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_MENU, COLOR_BLACK, COLOR_WHITE); + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_DIALOG, COLOR_BLUE, COLOR_WHITE); + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_WINDOW, COLOR_RED, COLOR_WHITE); + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_CONTROL, COLOR_BLACK, COLOR_WHITE); + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_DISABLED, COLOR_GRAY, COLOR_WHITE); + xvt_escape(XVT_ESC_CH_COLOR, XVT_CH_CLR_MNEMONIC, COLOR_RED, COLOR_WHITE); + + RCT rct; + get_client_rect( SCREEN_WIN, &rct ); + create_window(W_PLAIN, &rct, (char*) "BACKDROP", 0, TASK_WIN, + WSF_NO_MENUBAR | WSF_CH_BACKDROP , EM_UPDATE, + backdrop_eh, 0L ); +#endif +} + +/////////////////////////////////////////////////////////// +// Gestione del banner iniziale +/////////////////////////////////////////////////////////// + +class TBanner : public TWindow +{ +protected: + virtual void handler(WINDOW win, EVENT* ep); + +public: + TBanner(); + ~TBanner(); +}; + +TBanner::TBanner() +{ + create(-1, 6, 72, 6, "BANNER", WSF_NONE, W_PLAIN); + hide_brush(); + open_modal(); + do_events(); +} + +TBanner::~TBanner() +{ + close_modal(); +} + +void TBanner::handler(WINDOW win, EVENT* ep) +{ + if (ep->type == E_UPDATE) + { + const int BIGY = CHARY<<1; + + clear(COLOR_LTGRAY); + RCT r; get_client_rect(win, &r); + + set_color(COLOR_WHITE, COLOR_LTGRAY); + set_font(FF_TIMES, FS_BOLD | FS_ITALIC, BIGY); + char* t = (char*)(const char*)main_app().title(); + int w = win_get_text_width(win, t, -1); + int a; win_get_font_metrics(win, NULL, &a, NULL); + int x = (r.right-w)>>1, y = (r.bottom+a)>>1 ; + win_draw_text(win, x+1, y+1, t, -1); + set_color(COLOR_BLACK, COLOR_LTGRAY); + win_draw_text(win, x, y, t, -1); + + set_font(FF_TIMES); + t = "PRASSI S.p.A."; + w = win_get_text_width(win, t, -1); + x = (r.right-r.left-w)>>1, y = BIGY; + win_draw_text(win, x, y, t, -1); + + t = "Caricamento in corso"; + w = win_get_text_width(win, t, -1); + x = (r.right-r.left-w)>>1, y = r.bottom - CHARY; + win_draw_text(win, x, y, t, -1); + + r.left += 4; r.right -= 4; + r.top += 4; r.bottom -= 4; + set_pen(COLOR_BLACK); win_draw_rect(win, &r); + offset_rect(&r, 1, 1); + set_pen(COLOR_WHITE); win_draw_rect(win, &r); + + win_draw_icon(win, CHARX<<1, CHARX<<1, ICON_RSRC); + } + else + TWindow::handler(win, ep); +} + +#if XVT_OS == XVT_OS_WIN + +/////////////////////////////////////////////////////////// +// Gestione dei processi per Windows(R) +/////////////////////////////////////////////////////////// + +#include + +const word WM_WAKEUP = RegisterWindowMessage("WAKEUP"); +DWORD waiting_for = 0; + +HIDDEN BOOLEAN waiting_event_hook(HWND, WORD msg, WORD, + DWORD lparam, long far* ret) +{ + if (msg == WM_WAKEUP) + { + if( lparam == waiting_for || lparam == 0) + { + waiting_for = 0L; + TTemp_window tw(TASK_WIN); + tw.maximize(); + } + *ret = 0; + return TRUE; + } + + return FALSE; +} + + +HIDDEN DWORD name2id(const char* name) +{ + waiting_for = 0L; + for (int i = 0; i < 5 && name[i] > ' '; i++) + { + waiting_for <<= 6; + waiting_for |= toupper(name[i]) - '0'; + } + return waiting_for; +} + + +void TApplication::wait_for(const char* command) +{ + TTemp_window tw(TASK_WIN); + tw.iconize(); + name2id(cmd2name(command)); + + const long old_hook = get_value(TASK_WIN, ATTR_EVENT_HOOK); + set_value(TASK_WIN, ATTR_EVENT_HOOK, (long)waiting_event_hook); + while (waiting_for) do_events(); + + // We need to restore these things + set_value(TASK_WIN, ATTR_EVENT_HOOK, old_hook); + xvt_statbar_refresh(); +} + +void TApplication::wake_up_caller() const +{ + name2id(name()); + SendMessage(-1, WM_WAKEUP, 0, waiting_for); +} + +#endif + + +long TApplication::task_eh(WINDOW win, EVENT *ep) +{ + switch (ep->type) + { + case E_CREATE: + create_backdrop(); +#if defined(DBG) && XVT_OS == XVT_OS_SCOUNIX + message_box("Attach to process %d ...", getpid()); +#endif + do_events(); + break; +#if XVT_OS == XVT_OS_WIN + case E_UPDATE: + backdrop_eh(win, ep); + break; +#endif + default: + break; + } + + return _application->handler(win, ep); +} + +long TApplication::handler(WINDOW win, EVENT* ep) +{ + switch (ep->type) + { + case E_CREATE: + { + TBanner banner; + _create_ok = create(); + if (!_create_ok) + stop_run(); + } + break; + case E_COMMAND: + switch(ep->v.cmd.tag) + { + case M_FILE_QUIT: + if (can_close()) + stop_run(); + break; + case M_FILE_PG_SETUP: + printer().set(); + break; + case M_FILE_PRINT: + print(); + break; + case M_FILE_NEW: + set_firm(); + break; + case M_FILE_REVERT: + config(); + break; + case (M_FILE+11): + about(); + break; + default: + if (ep->v.cmd.tag >= BAR_ITEM(1)) + { + if(!menu(ep->v.cmd.tag)) + stop_run(); + } + break; + } + break; + case E_CLOSE: + if (can_close()) + stop_run(); + break; + case E_QUIT: + if (ep->v.query) + { + if (can_close()) + quit_OK(); + } + else + stop_run(); + break; +default: + break; +} + + return 0L; +} + + +void TApplication::stop_run() +{ + if (_savefirm) prefhndl->set_codditta(_savefirm); + terminate(); + xvt_terminate(); +} + + +TApplication::TApplication() : _printer(NULL), _savefirm(0), _create_ok(FALSE) +{ + init_global_vars(); + _bar = TASK_MENUBAR; +} + + +TApplication::~TApplication() +{} + + +TPrinter* TApplication::set_printer(TPrinter* p) +{ + TPrinter* printer = _printer; + _printer = p; + return printer; +} + + +TPrinter& TApplication::printer() +{ + if (_printer == NULL) + _printer = new TPrinter; + return *_printer; +} + + +bool TApplication::create() +{ + return TRUE; +} + + +bool TApplication::destroy() +{ + return TRUE; +} + + +void TApplication::terminate() +{ +#if XVT_OS == XVT_OS_WIN + wake_up_caller(); // Manda il segnale di risveglio al chiamante +#endif + + close_all_dialogs(); + + if (_create_ok) + { + destroy(); // Distruzione files e maschere + do_events(); + + if (_printer != NULL) // Distruzione dell'eventuale stampante + { + if (printer().isopen()) + printer().close(); + delete _printer; + _printer = NULL; + } + } + + free_global_vars(); // Distruzione variabili globali + + customize_controls(FALSE); // Rilascio eventuali DLL +} + + +const char* TApplication::get_module_name() const +{ + TScanner scanner("prassi.aut"); + + bool ok = FALSE; + for (int aut = 0; scanner.line() != ""; aut++) + if (strncmp(scanner.token(), _name, 2) == 0) { ok = TRUE; break; } + + const char* module = scanner.token().mid(3); + if (ok) ok = has_module(aut); + + if (!ok) + fatal_box("Il modulo '%s' non e' autorizzato", module); + + return module; +} + + +void TApplication::set_perms() +{ + CGetAut(1); + _dongle_aut.set(0, TRUE); + for (int i = 1 ; i < ENDAUT; i++) + { + const int af = i - 1; + const bool val = BITTEST(_int_tab0[af / 16], af % 16); + _dongle_aut.set(i, val); + } + _user_aut.set(0, TRUE); + if (_user.not_empty()) + { + if (_user == "PRASSI") + { + for (int i = 1 ; i < ENDAUT; i++) + _user_aut.set(i); + } + else + { + TLocalisamfile users(LF_USER); + + users.zero(); + users.put("USERNAME", _user); + if (users.read() == NOERR) + { + const TString80 aut(users.get("AUTSTR")); + const int max = aut.len(); + + for (int i = 1 ; i < max; i++) + _user_aut.set(i, aut[i] == 'X'); + } + } + } +} + + +void TApplication::check_parameters(int & argc, char* argv[]) + +{ + if (strncmp(argv[argc - 1], "-u", 2) == 0) + { + _user = &argv[argc - 1][2]; + argc--; + } +#ifdef DBG + else _user = "PRASSI"; +#endif +} + + +void TApplication::run(int argc, char* argv[], const char* title) +{ + TFilename base(argv[0]); + + base.ext(""); base.lower(); + _title = title; + if (_user.empty()) + check_parameters(argc, argv); + + __argc = argc; + __argv = (const char**)argv; + + int addbar; + if (argc > 1) + { + addbar = atoi(argv[1]+1); + _name = cmd2name(argv[0], argv[1]); + } + else + { + addbar = 0; + _name = cmd2name(argv[0]); + } + set_perms(); + + TString80 caption; + caption << "PRASSI S.p.A. - " << get_module_name(); + + static XVT_CONFIG cfg; + cfg.base_appl_name = (char*)base.name(); + cfg.appl_name = (char*)(const char*)_title; + cfg.taskwin_title = (char*)(const char*)caption; + cfg.menu_bar_ID = TASK_MENUBAR+addbar; + cfg.about_box_ID = 0; + + customize_controls(TRUE); + + _application = this; + xvt_system(argc, argv, 0L, task_eh, &cfg); +} + + +// About box: risposta alla opzione Informazioni del menu File +void TApplication::about() const +{ +#include + const TFilename n(__argv[0]); + message_box("PRASSI Versione Beta %4.2f\nProgramma %s\nLibreria del %s", + VERSION, (const char*)n.name(), __DATE__); +} + +// Risposta alla selezione Stampa del menu File +void TApplication::print() +{ +#ifdef DBG + error_box("Non saprei bene cosa stampare!"); +#endif +} + +void TApplication::check_menu_item(MENU_TAG item) +{ + win_menu_check(TASK_WIN, item, TRUE); + win_update_menu_bar(TASK_WIN); +} + +void TApplication::uncheck_menu_item(MENU_TAG item) +{ + win_menu_check(TASK_WIN, item, FALSE); + win_update_menu_bar(TASK_WIN); +} + + +void TApplication::enable_menu_item(MENU_TAG item, bool on) +{ + win_menu_enable(TASK_WIN, item, on); + win_update_menu_bar(TASK_WIN); +} + + +void TApplication::dispatch_e_menu(MENU_TAG item) +{ +#if XVT_OS == XVT_OS_WIN + HWND w = (HWND)get_value(TASK_WIN, ATTR_NATIVE_WINDOW); + PostMessage(w, WM_COMMAND, item, 0L); +#else + EVENT e; + e.type = E_COMMAND; + e.v.cmd.tag = item; + e.v.cmd.shift = e.v.cmd.control = 0; + dispatch_event(TASK_WIN, &e); +#endif +} + + +bool TApplication::has_module(int module, int checktype) const +{ + bool ok = TRUE; + if (checktype == CHK_ALL || checktype == CHK_DONGLE) + ok = _dongle_aut[module]; + if (ok && checktype == CHK_ALL || checktype == CHK_USER) + ok = _user_aut[module]; + return ok; +} + + +long TApplication::get_firm() const +{ + return prefhndl->get_codditta(); +} + +const char* TApplication::get_firm_dir() const +{ + return format("%s%s", __ptprf, prefhndl->name()); +} + + +bool TApplication::set_firm(long newfirm) +{ + disable_menu_item(M_FILE_NEW); + const long oldfirm = get_firm(); + + if (newfirm < 1) + { + TMask mask("bagn002"); + + mask.send_key(K_CTRL+K_SHIFT+(extended_firm() ? 's' : 'h'), -2); + const KEY k = mask.run(); + + enable_menu_item(M_FILE_NEW); + if (k == K_ENTER) + { + newfirm = mask.get_long(F_CODDITTA); + const int tipodir = mask.get_int(F_TIPO); + + if (tipodir > 0) + { + if (_savefirm == 0) _savefirm = oldfirm; + prefhndl->set(tipodir == 1 ? "com" : ""); + return TRUE; + } + } + } + + if (newfirm == oldfirm || newfirm < 1) + return newfirm > 0; + + if (prefhndl->test(newfirm)) + { + prefhndl->set_codditta(newfirm); + _savefirm = 0; + } + + return TRUE; +} + +bool TApplication::config() + // gestisce le voci di configurazione + // le si passa il file in cui cercare il proprio + // paragrafo (comunque relativo alla ditta) + // se non c'e', viene creato copiando il default + // la variabile EdMask di quel paragrafo specifica + // la maschera da usare +{ + TConfig cnf(CONFIG_DITTA); + bool ok = FALSE; + + TFilename maskname(cnf.get("EdMask")); + if (!maskname.empty()) + { + TMask m(maskname); + + // carica campi + for (int i = 0; i < m.fields(); i++) + { + TMask_field& f = m.fld(i); + const TFieldref* fref = f.field(); + if (fref != NULL) + { + const char* fname = fref->name(); + if (fname != NULL) + { + TString& oldvl = cnf.get(fname); + if (!oldvl.empty()) + f.set(oldvl); + } + } + } + + + // run mask + disable_menu_item(M_FILE_NEW); + disable_menu_item(M_FILE_REVERT); + + if (m.run() == K_ENTER) + { + // aggiusta campi + for (i = 0; i < m.fields(); i++) + { + TMask_field& f = m.fld(i); + if (f.dirty()) + { + const TFieldref* fref = f.field(); + if (fref != NULL) + { + const char* fname = fref->name(); + const char* value = f.get(); + const char* oldvl = cnf.get(fname); + if (change_config(fname,oldvl,value)) + cnf.set(fname, value, NULL, TRUE); + } + } + } + ok = TRUE; + } + else ok = FALSE; + enable_menu_item(M_FILE_NEW); + enable_menu_item(M_FILE_REVERT); + return ok; + } + return warning_box("Nessun parametro da configurare"); +} + +bool TApplication::change_config(const char* var, const char* oldv, + const char* newv) + +{ return TRUE; } +======= #include #include @@ -666,3 +1341,4 @@ bool TApplication::change_config(const char* var, const char* oldv, const char* newv) { return TRUE; } +>>>>>>> 1.24 diff --git a/include/applicat.h b/include/applicat.h index 65ed4c774..3ac8b0a5b 100755 --- a/include/applicat.h +++ b/include/applicat.h @@ -1,104 +1,106 @@ -#ifndef __APPLICATION_H -#define __APPLICATION_H - -#ifndef INCL_XVTH -#include -#endif - -#ifndef __PRINTER_H -#include -#endif - -// @C -// Classe TApplication -// @END - -#define MSG_AI "AI" // message auto_insert (relapp) -#define MSG_FS "FS" // message filtered start (relapp) -#define MSG_LN "LN" // message (printapp -> relapp) -#define CHK_ALL -1 // all authorization checks -#define CHK_DONGLE 0 // dongle authorization checks -#define CHK_USER 1 // user authorization checks - -class TApplication -{ - // @DPRIV - int _bar; - int __argc; - const char** __argv; - TBit_array _dongle_aut; - TBit_array _user_aut; - - TString80 _name, _title; - TPrinter* _printer; - - static TString16 _user; - -protected: - const char* get_module_name() const; - static long task_eh(WINDOW win, EVENT* ep); - - virtual long handler(WINDOW win, EVENT* ep); - virtual bool extended_firm() const { return FALSE; } // Extended set_firm dialog box - - virtual bool create(); // Crea la finestra principale - virtual bool menu(MENU_TAG) { return TRUE; } // Controlla il menu - virtual bool destroy(); // Rimuove l'applicazione - virtual void print(); - - virtual bool change_config(const char* var, const char* oldv, const char* newv); - void set_user(const char * user) { _user = user; } - - void terminate(); - bool config(); - void about() const; - -public: - // @FPUB - - void setbar(int menubar) { _bar = menubar;} // Modifica la menu-bar - void run(int argc, char* argv[], const char* name); - - // @DES Queste funzioni possono essere ridefinite da ogni applicazione - // @FPUB - virtual word class_id() const { return CLASS_APPLICATION; } - void stop_run(); // Forza chiusura applicazione - - void check_menu_item(MENU_TAG item); // Check menu - void uncheck_menu_item(MENU_TAG item); // Uncheck - void enable_menu_item(MENU_TAG item, bool on = TRUE); - void disable_menu_item(MENU_TAG item) { enable_menu_item(item, FALSE); } - void dispatch_e_menu(MENU_TAG item); - - const TString& name() const { return _name; } - const char** argv() const { return __argv; } - const char* argv(int i) const { return __argv[i]; } - int argc() const { return __argc; } - - void set_title(const char* t) { _title = t; } - const TString& title() const { return _title; } - - void wait_for(const char* name); - void wake_up_caller() const; - - TPrinter* set_printer(TPrinter* p); - TPrinter& printer(); - - static void check_parameters(int & argc, char *argv[]); - - void set_perms(); - const TString& user() const { return _user; } - bool has_module(int module, int checktype = CHK_ALL) const; - bool set_firm(long cod = -1); - long get_firm() const; - const char* get_firm_dir() const; - - TApplication(); - virtual ~TApplication(); -}; - -bool xvt_running(); // xvt is running? -TApplication* MainApp(); // main application (old fashioned: will be removed soon -TApplication& main_app(); - -#endif // __APPLICATION_H +#ifndef __APPLICATION_H +#define __APPLICATION_H + +#ifndef INCL_XVTH +#include +#endif + +#ifndef __PRINTER_H +#include +#endif + +// @C +// Classe TApplication +// @END + +#define MSG_AI "AI" // message auto_insert (relapp) +#define MSG_FS "FS" // message filtered start (relapp) +#define MSG_LN "LN" // message (printapp -> relapp) +#define CHK_ALL -1 // all authorization checks +#define CHK_DONGLE 0 // dongle authorization checks +#define CHK_USER 1 // user authorization checks + +class TApplication +{ + // @DPRIV + int _bar; + int __argc; + const char** __argv; + TBit_array _dongle_aut; + TBit_array _user_aut; + + TString80 _name, _title; + TPrinter* _printer; + + long _savefirm; + bool _create_ok; + static TString16 _user; + +protected: + const char* get_module_name() const; + static long task_eh(WINDOW win, EVENT* ep); + + virtual long handler(WINDOW win, EVENT* ep); + virtual bool extended_firm() const { return FALSE; } // Extended set_firm dialog box + + virtual bool create(); // Crea la finestra principale + virtual bool menu(MENU_TAG) { return TRUE; } // Controlla il menu + virtual bool destroy(); // Rimuove l'applicazione + virtual void print(); + + virtual bool change_config(const char* var, const char* oldv, const char* newv); + void set_user(const char * user) { _user = user; } + + void terminate(); + bool config(); + void about() const; + +public: + // @FPUB + + void setbar(int menubar) { _bar = menubar;} // Modifica la menu-bar + void run(int argc, char* argv[], const char* name); + + // @DES Queste funzioni possono essere ridefinite da ogni applicazione + // @FPUB + virtual word class_id() const { return CLASS_APPLICATION; } + void stop_run(); // Forza chiusura applicazione + + void check_menu_item(MENU_TAG item); // Check menu + void uncheck_menu_item(MENU_TAG item); // Uncheck + void enable_menu_item(MENU_TAG item, bool on = TRUE); + void disable_menu_item(MENU_TAG item) { enable_menu_item(item, FALSE); } + void dispatch_e_menu(MENU_TAG item); + + const TString& name() const { return _name; } + const char** argv() const { return __argv; } + const char* argv(int i) const { return __argv[i]; } + int argc() const { return __argc; } + + void set_title(const char* t) { _title = t; } + const TString& title() const { return _title; } + + void wait_for(const char* name); + void wake_up_caller() const; + + TPrinter* set_printer(TPrinter* p); + TPrinter& printer(); + + static void check_parameters(int & argc, char *argv[]); + + void set_perms(); + const TString& user() const { return _user; } + bool has_module(int module, int checktype = CHK_ALL) const; + bool set_firm(long cod = -1); + long get_firm() const; + const char* get_firm_dir() const; + + TApplication(); + virtual ~TApplication(); +}; + +bool xvt_running(); // xvt is running? +TApplication* MainApp(); // main application (old fashioned: will be removed soon +TApplication& main_app(); + +#endif // __APPLICATION_H diff --git a/include/checks.cpp b/include/checks.cpp index 8fe6204f3..4079fd882 100755 --- a/include/checks.cpp +++ b/include/checks.cpp @@ -1,209 +1,208 @@ -#include -#include -#include - -#ifdef XVT_OS -#include -#if XVT_OS == XVT_OS_WIN -#include -#include -#else -#include -#endif -#include -#endif // XVT_OS - - -#ifdef FOXPRO -#undef XVT_OS -#include -#endif - -#ifdef XVT_R3_API -#include -#endif - -#include - -#define buildmsg() char msg[256];va_list argptr;va_start(argptr,fmt);vsprintf(msg,fmt,argptr);va_end(argptr) - -#ifdef XVT_OS - -int fatal_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - MessageBeep(MB_ICONHAND); - MessageBox(GetFocus(), msg, "ERRORE FATALE", MB_OK | MB_ICONHAND | MB_SYSTEMMODAL); - const TApplication* a = MainApp(); - if (a != NULL) - a->wake_up_caller(); - xvt_terminate(); -#else - beep(); - if (xvt_running()) xvt_fatal("%s", msg); - else - { - fprintf(stderr, "%s\n", msg); - getchar(); - exit(1); - } -#endif - - return 0; -} - - -int error_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - MessageBeep(MB_ICONEXCLAMATION); - MessageBox(GetFocus(), msg, "ERRORE", MB_OK | MB_ICONEXCLAMATION); -#else - beep(); - if (xvt_running()) xvt_error("%s", msg); - else - { - fprintf(stderr, "%s\n", msg); - getchar(); - } -#endif - - return 0; -} - - -int warning_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - MessageBeep(MB_ICONQUESTION); - MessageBox(GetFocus(), msg, "ATTENZIONE", MB_OK | MB_ICONQUESTION); -#else - beep(); - xvt_note("%s", msg); -#endif - - return 0; -} - - -int message_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - MessageBox(GetFocus(), msg, "INFORMAZIONE", MB_OK | MB_ICONINFORMATION); -#else - xvt_note("%s", msg); -#endif - - return 0; -} - -int sorry_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - MessageBeep(MB_OK); - MessageBox(GetFocus(), msg, "SPIACENTE", MB_OK | MB_ICONINFORMATION); -#else - xvt_note("%s", msg); -#endif - - return 0; -} - -int yesno_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - int r = MessageBox(GetFocus(), msg, "RICHIESTA", MB_YESNO | MB_ICONQUESTION); - return r == IDYES; -#else - ASK_RESPONSE r = xvt_ask((char*) "Si", (char*) "No", NULL, "%s", msg); - return r == RESP_DEFAULT; -#endif -} - - -int yesnofatal_box(const char* fmt, ...) -{ - buildmsg(); - -#ifdef DBG - char s[256]; sprintf(s, "%s\nContinuare ugualmente?", msg); - const int ret = yesno_box("%s", s); - if (!ret) fatal_box(""); -#else - fatal_box("%s", msg); -#endif - - return FALSE; -} - - - -int yesnocancel_box(const char* fmt, ...) -{ - buildmsg(); - -#if XVT_OS == XVT_OS_WIN - int r = MessageBox(GetFocus(), msg, "RICHIESTA", MB_YESNOCANCEL | MB_ICONQUESTION); - if (r == IDYES) r = K_YES; - else - if (r == IDNO) r = K_NO; - else - r = K_ESC; - return r; -#else - ASK_RESPONSE r = xvt_ask((char*) "Si", (char*) "No", (char*) "Annulla", "%s", msg); - if (r == RESP_DEFAULT) r = K_YES; - else - if (r == RESP_2) r = K_NO; - else - r = K_ESC; - return r; -#endif -} - -#endif // XVT_OS - - -#ifdef FOXPRO - -int error_box(const char* fmt, ...) -{ - buildmsg(); - _UserError(msg); - return 0; -} - -int fatal_box(const char* fmt, ...) -{ - buildmsg(); - _UserError(msg); - return 0; -} - -int message_box(const char* fmt, ...) -{ - buildmsg(); - _UserError(msg); - return 0; -} - -int yesnofatal_box(const char* fmt, ...) -{ - buildmsg(); - _UserError(msg); - return 0; -} -#endif // FOXPRO - +#include +#include +#include + +#ifdef XVT_OS +#include +#if XVT_OS == XVT_OS_WIN +#include +#include +#else +#include +#endif +#include +#endif // XVT_OS + + +#ifdef FOXPRO +#undef XVT_OS +#include +#endif + +#ifdef XVT_R3_API +#include +#endif + +#include + +#define buildmsg() char msg[256];va_list argptr;va_start(argptr,fmt);vsprintf(msg,fmt,argptr);va_end(argptr) + +#ifdef XVT_OS + +int fatal_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + MessageBeep(MB_ICONHAND); + MessageBox(GetFocus(), msg, "ERRORE FATALE", MB_OK | MB_ICONHAND | MB_SYSTEMMODAL); + + if (xvt_running()) + main_app().stop_run(); +#else + beep(); + if (xvt_running()) xvt_fatal("%s", msg); + else + { + fprintf(stderr, "%s\n", msg); + getchar(); + exit(1); + } +#endif + + return 0; +} + + +int error_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + MessageBeep(MB_ICONEXCLAMATION); + MessageBox(GetFocus(), msg, "ERRORE", MB_OK | MB_ICONEXCLAMATION); +#else + beep(); + if (xvt_running()) xvt_error("%s", msg); + else + { + fprintf(stderr, "%s\n", msg); + getchar(); + } +#endif + + return 0; +} + + +int warning_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + MessageBeep(MB_ICONQUESTION); + MessageBox(GetFocus(), msg, "ATTENZIONE", MB_OK | MB_ICONQUESTION); +#else + beep(); + xvt_note("%s", msg); +#endif + + return 0; +} + + +int message_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + MessageBox(GetFocus(), msg, "INFORMAZIONE", MB_OK | MB_ICONINFORMATION); +#else + xvt_note("%s", msg); +#endif + + return 0; +} + +int sorry_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + MessageBeep(MB_OK); + MessageBox(GetFocus(), msg, "SPIACENTE", MB_OK | MB_ICONINFORMATION); +#else + xvt_note("%s", msg); +#endif + + return 0; +} + +int yesno_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + int r = MessageBox(GetFocus(), msg, "RICHIESTA", MB_YESNO | MB_ICONQUESTION); + return r == IDYES; +#else + ASK_RESPONSE r = xvt_ask((char*) "Si", (char*) "No", NULL, "%s", msg); + return r == RESP_DEFAULT; +#endif +} + + +int yesnofatal_box(const char* fmt, ...) +{ + buildmsg(); + +#ifdef DBG + char s[256]; sprintf(s, "%s\nContinuare ugualmente?", msg); + const int ret = yesno_box("%s", s); + if (!ret) fatal_box(""); +#else + fatal_box("%s", msg); +#endif + + return FALSE; +} + + + +int yesnocancel_box(const char* fmt, ...) +{ + buildmsg(); + +#if XVT_OS == XVT_OS_WIN + int r = MessageBox(GetFocus(), msg, "RICHIESTA", MB_YESNOCANCEL | MB_ICONQUESTION); + if (r == IDYES) r = K_YES; + else + if (r == IDNO) r = K_NO; + else + r = K_ESC; + return r; +#else + ASK_RESPONSE r = xvt_ask((char*) "Si", (char*) "No", (char*) "Annulla", "%s", msg); + if (r == RESP_DEFAULT) r = K_YES; + else + if (r == RESP_2) r = K_NO; + else + r = K_ESC; + return r; +#endif +} + +#endif // XVT_OS + + +#ifdef FOXPRO + +int error_box(const char* fmt, ...) +{ + buildmsg(); + _UserError(msg); + return 0; +} + +int fatal_box(const char* fmt, ...) +{ + buildmsg(); + _UserError(msg); + return 0; +} + +int message_box(const char* fmt, ...) +{ + buildmsg(); + _UserError(msg); + return 0; +} + +int yesnofatal_box(const char* fmt, ...) +{ + buildmsg(); + _UserError(msg); + return 0; +} +#endif // FOXPRO + diff --git a/include/controls.cpp b/include/controls.cpp index 9319f5204..2f1a26064 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -1,1025 +1,1026 @@ -extern "C" -{ -#include -#include -#include -} - -#if XVT_OS != XVT_OS_WIN -#error "This file should be compiled for Windows only" -#endif - -#include -#include -#include -#include -#include - -#include - -/////////////////////////////////////////////////////////// -// TPicture_array -/////////////////////////////////////////////////////////// - -class TPicture_array -{ - enum { MAXPIC = 128 }; - PICTURE _picture[MAXPIC]; - -public: - PICTURE getbmp(short id); - PICTURE operator[](short id) { return _picture[id-BMP_OK]; } - void reset(); - - TPicture_array(); - ~TPicture_array() { reset(); } -}; - - -PICTURE TPicture_array::getbmp(short id) -{ - const int i = id-BMP_OK; - CHECKD(i >= 0 && i < MAXPIC, "Control ID out of range", id); - - if (_picture[i] != NULL) - { - if (i < 100) return _picture[i]; - picture_free(_picture[i]); - } - _picture[i] = cpb_picture_load(id); - - if (_picture[i] == NULL) - error_box("Can't load picture %d", id); - - return _picture[i]; -} - - -TPicture_array::TPicture_array() -{ - memset(_picture, 0, sizeof(_picture)); -} - -void TPicture_array::reset() -{ - for (int i = 0; i < MAXPIC; i++) - if (_picture[i] != NULL) - { - picture_free(_picture[i]); - _picture[i] = NULL; - } -} - - -/////////////////////////////////////////////////////////// -// Static data and functions -/////////////////////////////////////////////////////////// - -HIDDEN TControl* creating = NULL; -HIDDEN long ctl_flags; -HIDDEN WINDOW _hdc; -HIDDEN RCT _client; -HIDDEN TPicture_array cpb; - -HIDDEN void get_geometry(WINDOW win) -{ - get_client_rect(win, &_client); - _client.right--; _client.bottom--; - _hdc = win; -} - -HIDDEN void set_creation_args(WIN_CREATION_ARGS *a) -{ - long& flags = a->win_flags; - if (ctl_flags & CTL_FLAG_DISABLED) flags |= WSF_DISABLED; - if (ctl_flags & CTL_FLAG_INVISIBLE) flags |= WSF_INVISIBLE; - - switch(creating->id()) - { - case -2: - flags |= WSF_DISABLED; - break; - default:break; - } -} - -void xvt_draw_rect(WINDOW win, const RCT& rect, COLOR lt, COLOR rb, short depth) -{ - RCT r = rect; - - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = lt; - - for (short d = 0; d < depth;) - { - win_set_cpen(win, &pen); - - PNT p; // Current vertex of the rectangle - - bool drawed = FALSE; - if (lt != COLOR_LTGRAY) - { - p.h = r.left; p.v = r.bottom; - win_move_to(win, p); - - p.v = r.top; - win_draw_line(win, p); - p.h = r.right; - win_draw_line(win, p); - drawed = TRUE; - } - - if (rb != COLOR_LTGRAY) - { - if (pen.color != rb) - { - pen.color = rb; - win_set_cpen(win, &pen); - } - if (!drawed) - { - p.h = r.right; p.v = r.top; - win_move_to(win, p); - } - p.v = r.bottom; - win_draw_line(win, p); - p.h = r.left; - win_draw_line(win, p); - } - - if (++d < depth) - { - r.left++; r.top++; - r.right--; r.bottom--; - } - } -} - - -void TControl::create( - short left, short top, short right, short bottom, const char* title, - WINDOW parent, long flags, long app_data, short id) -{ - bool bold = *title == '@'; - if (bold) title += 2; - - const int prop_count = 1; - const char* prop_list[prop_count+1] = - { - title, - NULL - }; - - _id = id; - _caption = title; _caption.strip("~"); - _disabled = (flags & CTL_FLAG_DISABLED) != 0; - _checked = (flags & CTL_FLAG_CHECKED) != 0; - _multiple = (flags & CTL_FLAG_MULTIPLE) != 0; - _focused = FALSE; - - creating = this; - ctl_flags = flags; - _win = xvtcm_create(id, left, top, right, bottom, - prop_count, (char**)prop_list, parent, - 0, 0, NULL, handler, set_creation_args); - CHECKS(_win, "Can't create control ", title); - - creating = NULL; - set_app_data(_win, app_data); - xvt_set_font(_win, FF_FIXED, bold ? FS_BOLD : 0); -} - - -// Virtual destructor needed to make derived descrutors live! -TControl::~TControl() -{} - - -long TControl::handler(WINDOW win, EVENT* ep) -{ - static bool tracking = FALSE; - static bool pressed = FALSE; - - if (ep->type == E_CREATE) - xvtcm_eh_start(win, ep); - - TControl** model = (TControl**)xvtcm_get_model(win, sizeof(TControl*)); - CHECK(model, "Can't get the model"); - - TControl*& cc = *model; - if (ep->type == E_CREATE) - { - CHECK(creating, "Can't create a NULL control"); - cc = creating; - } - CHECK(cc, "Can't handle a NULL control"); - - if (creating == NULL) switch(ep->type) - { - case E_FOCUS: - cc->focus((bool)ep->v.active); - case E_UPDATE: - cc->update(); - break; - case E_MOUSE_DOWN: - trap_mouse(win); - tracking = pressed = TRUE; - cc->mouse_down(ep->v.mouse.where); - break; - case E_CHAR: - { - const KEY key = e_char_to_key(ep); - switch(key) - { - case K_SPACE: - cc->mouse_up(); - break; - default: - dispatch_e_char(get_parent(win), key); - break; - } - } - break; - case E_MOUSE_MOVE: - if (tracking) - { - RCT r; - get_client_rect(win, &r); - if (pt_in_rect(&r, ep->v.mouse.where)) - { - if (!pressed) - { - cc->mouse_down(ep->v.mouse.where); - pressed = TRUE; - } - } - else - { - if (pressed) - { - cc->update(); - pressed = FALSE; - } - } - } - break; - case E_MOUSE_UP: - if (tracking) - { - release_mouse(); - tracking = FALSE; - if (pressed) - { - cc->mouse_up(); - pressed = FALSE; - } - } - break; - case E_DESTROY: - delete *model; - *model = NULL; - xvtcm_eh_end(win, ep); - break; - default: - break; - } - - return 0L; -} - -void TControl::enable(bool on) -{ - if (on == disabled()) - { - _disabled = !on; - update(); - enable_window(win(), on); - } -} - -void TControl::check(bool on) -{ - _checked = on; -} - -void TControl::update() const -{ - if (_win != _hdc) - get_geometry(_win); - clear_window(_hdc, MASK_BACK_COLOR); - win_set_fore_color(_hdc, disabled() ? COLOR_GRAY : COLOR_BLACK); -} - -/////////////////////////////////////////////////////////// -// TText -/////////////////////////////////////////////////////////// - -class TText : public TControl -{ -protected: - virtual WIN_TYPE type() const { return WC_TEXT; } - virtual void update() const; - -public: - TText(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); -}; - -TText::TText(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -{ - create(left, top, right, bottom, caption, parent, flags, app_data, id); -} - -void TText::update() const -{ - TControl::update(); - win_draw_text(_hdc, _client.left, _client.top+BASEY, (char*)caption(), -1); -} - -/////////////////////////////////////////////////////////// -// TGroup -/////////////////////////////////////////////////////////// - -class TGroup : public TText -{ -protected: - virtual WIN_TYPE type() const { return WC_GROUPBOX; } - virtual void update() const; - void draw_round_rect(const RCT& r, COLOR c) const; - -public: - TGroup(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); -}; - -TGroup::TGroup(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -: TText(left, top, right, bottom, caption, parent, flags, app_data, - (id < 0) ? -2 : id) -{} - -void TGroup::draw_round_rect(const RCT& r, COLOR c) const -{ - CPEN pen; - pen.width = 2; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = c; - win_set_cpen(_hdc, &pen); - - CBRUSH brush = { PAT_HOLLOW, MASK_BACK_COLOR }; - win_set_cbrush(_hdc, &brush); - win_draw_roundrect(_hdc, (RCT*)&r, ROWY, ROWY); -} - -void TGroup::update() const -{ - TText::update(); - - RCT r = _client; - r.top += CHARY; - r.right-=4; r.bottom-=ROWY/2; - if (multiple()) - { - r.left++; r.top++; r.right--; r.bottom--; - draw_round_rect(r, COLOR_BLUE); - } - else - { - xvt_draw_rect(_hdc, r, COLOR_GRAY, COLOR_CYAN); - } -} - -/////////////////////////////////////////////////////////// -// Button -/////////////////////////////////////////////////////////// - -class TButton : public TControl -{ -protected: - enum { DEPTH = 2 }; - - virtual WIN_TYPE type() const { return WC_PUSHBUTTON; } - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - virtual void check(bool on); - virtual void draw_pressed(bool pressed) const; - -public: - TButton(short left, short top, short right, short bottom, - const char* caption,WINDOW parent, - long flags, long app_data, short id); -}; - - -TButton::TButton(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -{ - create(left, top, right, bottom, caption, parent, flags, app_data, id); -} - - -void TButton::draw_pressed(bool pressed) const -{ - get_geometry(win()); - - clear_window(_hdc, COLOR_LTGRAY); - RCT r = _client; - xvt_draw_rect(_hdc, r, COLOR_BLACK, COLOR_BLACK); - - COLOR lt = pressed ? COLOR_GRAY : COLOR_WHITE; - COLOR rb = pressed ? COLOR_LTGRAY : COLOR_GRAY; - - for (int i = DEPTH; i--;) - { - r.left++; r.top++; r.right--; r.bottom--; - xvt_draw_rect(_hdc, r, lt, rb); - if (i == 1) lt = COLOR_LTGRAY; - } -} - - -void TButton::update() const -{ - TControl::update(); - draw_pressed(checked()); -} - -void TButton::mouse_down(PNT) -{ - draw_pressed(!checked()); -} - -void TButton::mouse_up() -{ - draw_pressed(checked()); - - EVENT e; // Notification message - e.type = E_CONTROL; - e.v.ctl.id = id(); - e.v.ctl.ci.type = type(); - e.v.ctl.ci.win = win(); - dispatch_event(get_parent(win()), &e); -} - -void TButton::check(bool on) -{ - TControl::check(on); - draw_pressed(on); -} - -/////////////////////////////////////////////////////////// -// TPush button -/////////////////////////////////////////////////////////// - -class TPush_button : public TButton -{ - PICTURE _picup, _picdn; - byte _dx, _dy; - int _accel; - -protected: - void draw_pressed(bool pressed) const; - void update() const; - -public: - TPush_button(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); - virtual ~TPush_button(); -}; - -TPush_button::TPush_button(short left, short top, short right, short bottom, - const char* capt, WINDOW parent, - long flags, long app_data, short id) -: TButton(left-(id == DLG_F9), top, right, bottom, - capt, parent, flags, app_data, id), - _picup(0L), _picdn(0L) -{ - switch(id) - { - case DLG_OK: - if (strcmp("Conferma", caption()) == 0) - capt = format("#%d", BMP_OK); - break; - case DLG_CANCEL: - if (strcmp("Annulla", caption()) == 0) - capt = format("#%d", BMP_CANCEL); - break; - case DLG_QUIT: - capt = format("#%d#%d", BMP_QUIT, BMP_QUITDN); - break; - case DLG_SELECT: - capt = format("#%d", BMP_SELECT); - break; - case DLG_DELREC: - capt = format("#%d#%d", BMP_DELREC, BMP_DELRECDN); - break; - case DLG_NEWREC: - if (strcmp("Nuovo", caption()) == 0) // Puo' essere Gestione - capt = format("#%d#%d", BMP_NEWREC, BMP_NEWRECDN); - break; - case DLG_FIRSTREC: - capt = format("#%d", BMP_FIRSTREC); - break; - case DLG_PREVREC: - capt = format("#%d", BMP_PREVREC); - break; - case DLG_STOPREC: - capt = format("#%d", BMP_STOPREC); - break; - case DLG_NEXTREC: - capt = format("#%d", BMP_NEXTREC); - break; - case DLG_LASTREC: - capt = format("#%d", BMP_LASTREC); - break; - case DLG_SAVEREC: - capt = format("#%d#%d", BMP_SAVEREC, BMP_SAVERECDN); - break; - case DLG_FINDREC: - capt = format("#%d", BMP_FINDREC); - break; - case DLG_F9: - capt = format("#%d", BMP_SEARCH); - break; - case DLG_LINK: - capt = format("#%d", BMP_LINK); - break; - case DLG_EDIT: - capt = format("#%d", BMP_EDIT); - break; - case DLG_PRINT: - capt = format("#%d", BMP_PRINT); - break; - case DLG_SETPRINT: - capt = format("#%d", BMP_SETPRINT); - break; - default: - break; - } - - const int height = bottom-top; - const int width = right-left; - - if (*capt == '#') - { - int pid = atoi(capt+1); - _picup = cpb.getbmp(pid); - const char* d = strrchr(capt, '#'); - if (d > capt) - { - pid = atoi(d+1); - _picdn = cpb.getbmp(pid); - } - - RCT r; - cpb_get_picture_size(_picup, &r); - _dx = byte((width-r.right+1) >> 1); - _dy = byte((height-r.bottom) >> 1); - _accel = -1; - } - else - { - TFixed_string c(capt); - _accel = c.find('~'); - if (_accel > 0) - _accel *= CHARX; - - _dx = (width - win_get_text_width(win(), (char*)caption(), -1)) >> 1; - _dy = (byte)(height-4+BASEY)>>1; - } -} - -TPush_button::~TPush_button() -{ -} - -void TPush_button::draw_pressed(bool pressed) const -{ - TButton::draw_pressed(pressed); - - const int p = pressed ? DEPTH : 0; - if (_picup) - { - const PICTURE pic = (pressed && _picdn) ? _picdn : _picup; - cpb_win_picture_draw_at(_hdc, pic, _dx+p, _dy+p); - } - else - { - const char* t = caption(); - - win_set_fore_color(_hdc, COLOR_WHITE); - win_draw_text(_hdc, _dx+p+1, _dy+p+1, (char*)t, -1); - if (_accel >= 0) - win_draw_text(_hdc, _dx+_accel+p+1, _dy+p+3, "_", 1); - - const COLOR c = disabled() ? DISABLED_COLOR : NORMAL_COLOR; - win_set_fore_color(_hdc, c); - win_draw_text(_hdc, _dx+p, _dy+p, (char*)t, -1); - if (_accel >= 0) - win_draw_text(_hdc, _dx+_accel+p, _dy+p+2, "_", 1); - } -} - -void TPush_button::update() const -{ - draw_pressed(FALSE); - if (focused() && id() != DLG_F9) - { - /* - HWND hwnd = (HWND)get_value(_hdc, ATTR_NATIVE_WINDOW); - HDC hdc = GetDC(hwnd); - RECT r; - r.left = _client.left+DEPTH+1; - r.top = _client.top+DEPTH; - r.right = _client.right-DEPTH-1; - r.bottom = _client.bottom-DEPTH; - DrawFocusRect(hdc, &r); - ReleaseDC(hwnd, hdc); - */ - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = COLOR_RED; - win_set_cpen(_hdc, &pen); - CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE }; - win_set_cbrush(_hdc, &brush); - win_draw_rect(_hdc, &_client); - } else - if (disabled() && _picup) - { - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; - pen.color = COLOR_LTGRAY; - win_set_cpen(_hdc, &pen); - - const int sx = _client.left+DEPTH+1; - const int sy = _client.top+DEPTH+1; - const int ex = _client.right-DEPTH-1; - const int ey = _client.bottom-DEPTH-1; - - for (int i = sx; i < ex; i += 2) - { - PNT p = { sy, i }; - win_move_to(_hdc, p); - p.v = ey; - win_draw_line(_hdc, p); - } - for (i = sy; i < ey; i += 2) - { - PNT p = { i, sx }; - win_move_to(_hdc, p); - p.h = ex; - win_draw_line(_hdc, p); - } - } -} - -/////////////////////////////////////////////////////////// -// TPage_button -/////////////////////////////////////////////////////////// - -class TPage_button : public TControl -{ - enum { height = 19, width = 32 }; - byte _flag; - -protected: - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - -public: - TPage_button(WINDOW parent, byte flag); -}; - -TPage_button::TPage_button(WINDOW parent, byte flag) : _flag(flag) -{ - RCT r; get_client_rect(parent, &r); - create(r.right-width, r.bottom-height, r.right, r.bottom, - "", parent, 0L, 0L, DLG_PAGE); - cpb.getbmp(BMP_BOOK1 + flag -1); -} - -void TPage_button::mouse_down(PNT where) -{ - check(where.h < (width>>1)); -} - -void TPage_button::mouse_up() -{ - dispatch_e_char(get_parent(win()), checked() ? K_PREV : K_NEXT); -} - -void TPage_button::update() const -{ - TControl::update(); - cpb_win_picture_draw_at(_hdc, cpb[BMP_BOOK1 + _flag -1], 0, 0); -} - -/////////////////////////////////////////////////////////// -// TTag_button -/////////////////////////////////////////////////////////// - -class TTag_button : public TControl -{ - enum { height = 12, width = 32 }; - byte _curr; - byte _page; - byte _pages; - - WINDOW _parent; - -protected: - virtual void update() const; - virtual void mouse_down(PNT where); - virtual void mouse_up(); - -public: - TTag_button(WINDOW parent, byte p, byte tot); -}; - -TTag_button::TTag_button(WINDOW parent, byte p, byte tot) -: _parent(parent), _page(p), _pages(tot), _curr(p) -{ - RCT r; get_client_rect(parent, &r); - create(0, 0, r.right, CHARY, "", parent,0L,0L, DLG_PAGETAGS); -} - -void TTag_button::update() const -{ - get_geometry(win()); - clear_window(_hdc, COLOR_GRAY); - - for (int i = 0; i < _pages; i++) - { - RCT r; set_rect(&r, width*i, 0, width*(i+1), _client.bottom+4); - CBRUSH b = { PAT_SOLID, (i == _page) ? MASK_BACK_COLOR : COLOR_GRAY }; - win_set_cbrush(_hdc, &b); - win_set_std_cpen(_hdc, TL_PEN_BLACK); - win_draw_rect(_hdc, &r); - - if (i == _page) -#ifdef __CTL3D__ - xvt_draw_rect(_hdc, r, COLOR_WHITE, COLOR_GRAY); -#else - xvt_draw_rect(_hdc, r, COLOR_CYAN, COLOR_GRAY); -#endif - - char n[4]; sprintf(n, "%d", i+1); - win_draw_text(_hdc, (width-CHARX)/2 + i*width, BASEY, n, -1); - } - - CPEN pen; - pen.width = 1; - pen.pat = PAT_SOLID; - pen.style = P_SOLID; -#ifdef __CTL3D__ - pen.color = COLOR_WHITE; -#else - pen.color = COLOR_CYAN; -#endif - win_set_cpen(_hdc, &pen); - - PNT p = { _client.bottom, 0 }; - win_move_to(_hdc, p); - p.h = width*_page; - win_draw_line(_hdc, p); - p.h += width+1; - win_move_to(_hdc, p); - p.h = _client.right; - win_draw_line(_hdc, p); -} - -void TTag_button::mouse_down(PNT where) -{ - _curr = where.h / width; - if (_curr >= _pages) _curr = _pages-1; -} - -void TTag_button::mouse_up() -{ - if (_curr != _page) - dispatch_e_char(_parent, K_CTRL + K_F1 + _curr); -} - -/////////////////////////////////////////////////////////// -// Checkbox -/////////////////////////////////////////////////////////// - -class TCheckbox : public TButton -{ - static bool _bmploaded; - -protected: - virtual WIN_TYPE type() const; - virtual void draw_pressed(bool pressed) const; - virtual void update() const; - - int radio() const { return multiple() ? 1 : 0; } - -public: - TCheckbox(short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id); - virtual ~TCheckbox(); -}; - -bool TCheckbox::_bmploaded = FALSE; - -TCheckbox::TCheckbox( - short left, short top, short right, short bottom, - const char* caption, WINDOW parent, - long flags, long app_data, short id) -: TButton(left, top, right, bottom, - caption, parent, flags, app_data, id) -{ - if (!_bmploaded) - { - cpb.getbmp(BMP_CHECK_ON); - cpb.getbmp(BMP_CHECK_OFF); - cpb.getbmp(BMP_RADIO_ON); - cpb.getbmp(BMP_RADIO_OFF); - _bmploaded = TRUE; - } -} - - -TCheckbox::~TCheckbox() -{ -} - - -WIN_TYPE TCheckbox::type() const -{ - return multiple() ? WC_RADIOBUTTON : WC_CHECKBOX; -} - - -void TCheckbox::draw_pressed(bool pressed) const -{ - get_geometry(win()); - PICTURE pic; - if (radio()) - pic = pressed ? cpb[BMP_RADIO_ON] : cpb[BMP_RADIO_OFF]; - else - pic = pressed ? cpb[BMP_CHECK_ON] : cpb[BMP_CHECK_OFF]; - cpb_win_picture_draw_at(_hdc, pic, _client.left, _client.top); -} - - -void TCheckbox::update() const -{ - TButton::update(); - - const int x = _client.left+20; - const int y = _client.top + BASEY; - - if (focused()) - { -#if XVT_OS == XVT_OS_WIN - RECT r; - r.left = x-2; r.top = _client.top; - r.right = _client.right; r.bottom = y+3; - - HWND hwnd = (HWND)get_value(_hdc, ATTR_NATIVE_WINDOW); - HDC hdc = GetDC(hwnd); - DrawFocusRect(hdc, &r); - ReleaseDC(hwnd, hdc); -#endif - } - - win_draw_text(_hdc, x, y, (char*)caption(), -1); -} - -/////////////////////////////////////////////////////////// -// User functions -/////////////////////////////////////////////////////////// - -WINDOW xvt_create_checkbox( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - TCheckbox* cb = new TCheckbox(left, top, right, bottom, - caption, parent, - flags, app_data, id); - - // It'll destroy itself automagically :-) - - return cb->win(); -} - -WINDOW xvt_create_radiobutton( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - flags |= CTL_FLAG_MULTIPLE; - TCheckbox* cb = new TCheckbox(left, top, right, bottom, - caption, parent, - flags, app_data, id); - - // It'll destroy itself automagically :-) - return cb->win(); -} - - -WINDOW xvt_create_pushbutton( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - TControl* pb; - - switch (id) - { - case DLG_PAGE: - pb = new TPage_button(parent, (byte)flags); - break; - case DLG_PAGETAGS: - pb = new TTag_button(parent, (byte)flags, (byte)app_data); - break; - default: - if (bottom-top > (CHARY<<1)) - { - top += BASEY>>1; - bottom -= BASEY>>1; - } - pb = new TPush_button(left, top, right, bottom, - caption, parent, - flags, app_data, id); - } - - // It'll destroy itself automagically :-) - return pb->win(); -} - - -WINDOW xvt_create_text( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - TText* cb = new TText(left, top, right, bottom, - caption, parent, - flags, app_data, id); - // It'll destroy itself automagically :-) - return cb->win(); -} - - -WINDOW xvt_create_groupbox( - short left, short top, short right, short bottom, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - TGroup* cb = new TGroup(left, top, right, bottom, - caption, parent, - flags, app_data, id); - // It'll destroy itself automagically :-) - return cb->win(); -} - - -void free_controls_bmp() -{ - cpb.reset(); -} - - -TControl* TControl::WINDOW2TControl(WINDOW win) -{ - TControl** model = (TControl**)xvtcm_get_model(win, 0); - CHECK(model && *model, "Can't get the model from a window"); - return *model; -} +extern "C" +{ +#include +#include +#include +} + +#if XVT_OS != XVT_OS_WIN +#error "This file should be compiled for Windows only" +#endif + +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////// +// TPicture_array +/////////////////////////////////////////////////////////// + +class TPicture_array +{ + enum { MAXPIC = 128 }; + PICTURE _picture[MAXPIC]; + +public: + PICTURE getbmp(short id); + PICTURE operator[](short id) { return _picture[id-BMP_OK]; } + void reset(); + + TPicture_array(); + ~TPicture_array() { reset(); } +}; + + +PICTURE TPicture_array::getbmp(short id) +{ + const int i = id-BMP_OK; + CHECKD(i >= 0 && i < MAXPIC, "Control ID out of range", id); + + if (_picture[i] != NULL) + { + if (i < 100) return _picture[i]; + picture_free(_picture[i]); + } + _picture[i] = cpb_picture_load(id); + + if (_picture[i] == NULL) + error_box("Can't load picture %d", id); + + return _picture[i]; +} + + +TPicture_array::TPicture_array() +{ + memset(_picture, 0, sizeof(_picture)); +} + +void TPicture_array::reset() +{ + for (int i = 0; i < MAXPIC; i++) + if (_picture[i] != NULL) + { + picture_free(_picture[i]); + _picture[i] = NULL; + } +} + + +/////////////////////////////////////////////////////////// +// Static data and functions +/////////////////////////////////////////////////////////// + +HIDDEN TControl* creating = NULL; +HIDDEN long ctl_flags; +HIDDEN WINDOW _hdc; +HIDDEN RCT _client; +HIDDEN TPicture_array cpb; + +HIDDEN void get_geometry(WINDOW win) +{ + get_client_rect(win, &_client); + _client.right--; _client.bottom--; + _hdc = win; +} + +HIDDEN void set_creation_args(WIN_CREATION_ARGS *a) +{ + long& flags = a->win_flags; + if (ctl_flags & CTL_FLAG_DISABLED) flags |= WSF_DISABLED; + if (ctl_flags & CTL_FLAG_INVISIBLE) flags |= WSF_INVISIBLE; + + switch(creating->id()) + { + case -2: + flags |= WSF_DISABLED; + break; + default:break; + } +} + +void xvt_draw_rect(WINDOW win, const RCT& rect, COLOR lt, COLOR rb, short depth) +{ + RCT r = rect; + + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = lt; + + for (short d = 0; d < depth;) + { + win_set_cpen(win, &pen); + + PNT p; // Current vertex of the rectangle + + bool drawed = FALSE; + if (lt != COLOR_LTGRAY) + { + p.h = r.left; p.v = r.bottom; + win_move_to(win, p); + + p.v = r.top; + win_draw_line(win, p); + p.h = r.right; + win_draw_line(win, p); + drawed = TRUE; + } + + if (rb != COLOR_LTGRAY) + { + if (pen.color != rb) + { + pen.color = rb; + win_set_cpen(win, &pen); + } + if (!drawed) + { + p.h = r.right; p.v = r.top; + win_move_to(win, p); + } + p.v = r.bottom; + win_draw_line(win, p); + p.h = r.left; + win_draw_line(win, p); + } + + if (++d < depth) + { + r.left++; r.top++; + r.right--; r.bottom--; + } + } +} + + +void TControl::create( + short left, short top, short right, short bottom, const char* title, + WINDOW parent, long flags, long app_data, short id) +{ + bool bold = *title == '@'; + if (bold) title += 2; + + const int prop_count = 1; + const char* prop_list[prop_count+1] = + { + title, + NULL + }; + + _id = id; + _caption = title; _caption.strip("~"); + _disabled = (flags & CTL_FLAG_DISABLED) != 0; + _checked = (flags & CTL_FLAG_CHECKED) != 0; + _multiple = (flags & CTL_FLAG_MULTIPLE) != 0; + _focused = FALSE; + + creating = this; + ctl_flags = flags; + _win = xvtcm_create(id, left, top, right, bottom, + prop_count, (char**)prop_list, parent, + 0, 0, NULL, handler, set_creation_args); + CHECKS(_win, "Can't create control ", title); + + creating = NULL; + set_app_data(_win, app_data); + xvt_set_font(_win, FF_FIXED, bold ? FS_BOLD : 0); +} + + +// Virtual destructor needed to make derived descrutors live! +TControl::~TControl() +{} + + +long TControl::handler(WINDOW win, EVENT* ep) +{ + static bool tracking = FALSE; + static bool pressed = FALSE; + + if (ep->type == E_CREATE) + xvtcm_eh_start(win, ep); + + TControl** model = (TControl**)xvtcm_get_model(win, sizeof(TControl*)); + CHECK(model, "Can't get the model"); + + TControl*& cc = *model; + if (ep->type == E_CREATE) + { + CHECK(creating, "Can't create a NULL control"); + cc = creating; + } + CHECK(cc, "Can't handle a NULL control"); + + if (creating == NULL) switch(ep->type) + { + case E_FOCUS: + cc->focus((bool)ep->v.active); + case E_UPDATE: + cc->update(); + break; + case E_MOUSE_DOWN: + trap_mouse(win); + tracking = pressed = TRUE; + cc->mouse_down(ep->v.mouse.where); + break; + case E_CHAR: + { + const KEY key = e_char_to_key(ep); + switch(key) + { + case K_SPACE: + cc->mouse_up(); + break; + default: + dispatch_e_char(get_parent(win), key); + break; + } + } + break; + case E_MOUSE_MOVE: + if (tracking) + { + RCT r; + get_client_rect(win, &r); + if (pt_in_rect(&r, ep->v.mouse.where)) + { + if (!pressed) + { + cc->mouse_down(ep->v.mouse.where); + pressed = TRUE; + } + } + else + { + if (pressed) + { + cc->update(); + pressed = FALSE; + } + } + } + break; + case E_MOUSE_UP: + if (tracking) + { + release_mouse(); + tracking = FALSE; + if (pressed) + { + cc->mouse_up(); + pressed = FALSE; + } + } + break; + case E_DESTROY: + delete *model; + *model = NULL; + xvtcm_eh_end(win, ep); + break; + default: + break; + } + + return 0L; +} + +void TControl::enable(bool on) +{ + if (on == disabled()) + { + _disabled = !on; + update(); + enable_window(win(), on); + } +} + +void TControl::check(bool on) +{ + _checked = on; +} + +void TControl::update() const +{ + if (_win != _hdc) + get_geometry(_win); + clear_window(_hdc, MASK_BACK_COLOR); + win_set_fore_color(_hdc, disabled() ? COLOR_GRAY : COLOR_BLACK); +} + +/////////////////////////////////////////////////////////// +// TText +/////////////////////////////////////////////////////////// + +class TText : public TControl +{ +protected: + virtual WIN_TYPE type() const { return WC_TEXT; } + virtual void update() const; + +public: + TText(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id); +}; + +TText::TText(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id) +{ + create(left, top, right, bottom, caption, parent, flags, app_data, id); +} + +void TText::update() const +{ + TControl::update(); + win_draw_text(_hdc, _client.left, _client.top+BASEY, (char*)caption(), -1); +} + +/////////////////////////////////////////////////////////// +// TGroup +/////////////////////////////////////////////////////////// + +class TGroup : public TText +{ +protected: + virtual WIN_TYPE type() const { return WC_GROUPBOX; } + virtual void update() const; + void draw_round_rect(const RCT& r, COLOR c) const; + +public: + TGroup(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id); +}; + +TGroup::TGroup(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id) +: TText(left, top, right, bottom, caption, parent, flags, app_data, + (id < 0) ? -2 : id) +{} + +void TGroup::draw_round_rect(const RCT& r, COLOR c) const +{ + CPEN pen; + pen.width = 2; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = c; + win_set_cpen(_hdc, &pen); + + CBRUSH brush = { PAT_HOLLOW, MASK_BACK_COLOR }; + win_set_cbrush(_hdc, &brush); + win_draw_roundrect(_hdc, (RCT*)&r, ROWY, ROWY); +} + +void TGroup::update() const +{ + TText::update(); + + RCT r = _client; + r.top += CHARY; + r.right-=4; r.bottom-=ROWY/2; + if (multiple()) + { + r.left++; r.top++; r.right--; r.bottom--; + draw_round_rect(r, COLOR_BLUE); + } + else + { + xvt_draw_rect(_hdc, r, COLOR_GRAY, COLOR_CYAN); + } +} + +/////////////////////////////////////////////////////////// +// Button +/////////////////////////////////////////////////////////// + +class TButton : public TControl +{ +protected: + enum { DEPTH = 2 }; + + virtual WIN_TYPE type() const { return WC_PUSHBUTTON; } + virtual void update() const; + virtual void mouse_down(PNT where); + virtual void mouse_up(); + virtual void check(bool on); + virtual void draw_pressed(bool pressed) const; + +public: + TButton(short left, short top, short right, short bottom, + const char* caption,WINDOW parent, + long flags, long app_data, short id); +}; + + +TButton::TButton(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id) +{ + create(left, top, right, bottom, caption, parent, flags, app_data, id); +} + + +void TButton::draw_pressed(bool pressed) const +{ + get_geometry(win()); + + clear_window(_hdc, COLOR_LTGRAY); + RCT r = _client; + xvt_draw_rect(_hdc, r, COLOR_BLACK, COLOR_BLACK); + + COLOR lt = pressed ? COLOR_GRAY : COLOR_WHITE; + COLOR rb = pressed ? COLOR_LTGRAY : COLOR_GRAY; + + for (int i = DEPTH; i--;) + { + r.left++; r.top++; r.right--; r.bottom--; + xvt_draw_rect(_hdc, r, lt, rb); + if (i == 1) lt = COLOR_LTGRAY; + } +} + + +void TButton::update() const +{ + TControl::update(); + draw_pressed(checked()); +} + +void TButton::mouse_down(PNT) +{ + draw_pressed(!checked()); +} + +void TButton::mouse_up() +{ + draw_pressed(checked()); + + EVENT e; // Notification message + e.type = E_CONTROL; + e.v.ctl.id = id(); + e.v.ctl.ci.type = type(); + e.v.ctl.ci.win = win(); + dispatch_event(get_parent(win()), &e); +} + +void TButton::check(bool on) +{ + TControl::check(on); + draw_pressed(on); +} + +/////////////////////////////////////////////////////////// +// TPush button +/////////////////////////////////////////////////////////// + +class TPush_button : public TButton +{ + PICTURE _picup, _picdn; + byte _dx, _dy; + int _accel; + +protected: + void draw_pressed(bool pressed) const; + void update() const; + +public: + TPush_button(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id); + virtual ~TPush_button(); +}; + +TPush_button::TPush_button(short left, short top, short right, short bottom, + const char* capt, WINDOW parent, + long flags, long app_data, short id) +: TButton(left-(id == DLG_F9), top, right, bottom, + capt, parent, flags, app_data, id), + _picup(0L), _picdn(0L) +{ + switch(id) + { + case DLG_OK: + if (strcmp("Conferma", caption()) == 0) + capt = format("#%d", BMP_OK); + break; + case DLG_CANCEL: + if (strcmp("Annulla", caption()) == 0) + capt = format("#%d", BMP_CANCEL); + break; + case DLG_QUIT: + capt = format("#%d#%d", BMP_QUIT, BMP_QUITDN); + break; + case DLG_SELECT: + capt = format("#%d", BMP_SELECT); + break; + case DLG_DELREC: + capt = format("#%d#%d", BMP_DELREC, BMP_DELRECDN); + break; + case DLG_NEWREC: + if (strcmp("Nuovo", caption()) == 0) // Puo' essere Gestione + capt = format("#%d#%d", BMP_NEWREC, BMP_NEWRECDN); + break; + case DLG_FIRSTREC: + capt = format("#%d", BMP_FIRSTREC); + break; + case DLG_PREVREC: + capt = format("#%d", BMP_PREVREC); + break; + case DLG_STOPREC: + capt = format("#%d", BMP_STOPREC); + break; + case DLG_NEXTREC: + capt = format("#%d", BMP_NEXTREC); + break; + case DLG_LASTREC: + capt = format("#%d", BMP_LASTREC); + break; + case DLG_SAVEREC: + capt = format("#%d#%d", BMP_SAVEREC, BMP_SAVERECDN); + break; + case DLG_FINDREC: + capt = format("#%d", BMP_FINDREC); + break; + case DLG_F9: + capt = format("#%d", BMP_SEARCH); + break; + case DLG_LINK: + capt = format("#%d", BMP_LINK); + break; + case DLG_EDIT: + capt = format("#%d", BMP_EDIT); + break; + case DLG_PRINT: + capt = format("#%d", BMP_PRINT); + break; + case DLG_SETPRINT: + capt = format("#%d", BMP_SETPRINT); + break; + default: + break; + } + + const int height = bottom-top; + const int width = right-left; + + const char* diesis = strchr(capt, '#'); + if (diesis != NULL) + { + int pid = atoi(++diesis); + _picup = cpb.getbmp(pid); + diesis = strchr(diesis, '#'); + if (diesis != NULL) + { + pid = atoi(++diesis); + _picdn = cpb.getbmp(pid); + } + + RCT r; + cpb_get_picture_size(_picup, &r); + _dx = byte((width-r.right+1) >> 1); + _dy = byte((height-r.bottom) >> 1); + _accel = -1; + } + else + { + TFixed_string c(capt); + _accel = c.find('~'); + if (_accel > 0) + _accel *= CHARX; + + _dx = (width - win_get_text_width(win(), (char*)caption(), -1)) >> 1; + _dy = (byte)(height-4+BASEY)>>1; + } +} + +TPush_button::~TPush_button() +{ +} + +void TPush_button::draw_pressed(bool pressed) const +{ + TButton::draw_pressed(pressed); + + const int p = pressed ? DEPTH : 0; + if (_picup) + { + const PICTURE pic = (pressed && _picdn) ? _picdn : _picup; + cpb_win_picture_draw_at(_hdc, pic, _dx+p, _dy+p); + } + else + { + const char* t = caption(); + + win_set_fore_color(_hdc, COLOR_WHITE); + win_draw_text(_hdc, _dx+p+1, _dy+p+1, (char*)t, -1); + if (_accel >= 0) + win_draw_text(_hdc, _dx+_accel+p+1, _dy+p+3, "_", 1); + + const COLOR c = disabled() ? DISABLED_COLOR : NORMAL_COLOR; + win_set_fore_color(_hdc, c); + win_draw_text(_hdc, _dx+p, _dy+p, (char*)t, -1); + if (_accel >= 0) + win_draw_text(_hdc, _dx+_accel+p, _dy+p+2, "_", 1); + } +} + +void TPush_button::update() const +{ + draw_pressed(FALSE); + if (focused() && id() != DLG_F9) + { + /* + HWND hwnd = (HWND)get_value(_hdc, ATTR_NATIVE_WINDOW); + HDC hdc = GetDC(hwnd); + RECT r; + r.left = _client.left+DEPTH+1; + r.top = _client.top+DEPTH; + r.right = _client.right-DEPTH-1; + r.bottom = _client.bottom-DEPTH; + DrawFocusRect(hdc, &r); + ReleaseDC(hwnd, hdc); + */ + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = COLOR_RED; + win_set_cpen(_hdc, &pen); + CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE }; + win_set_cbrush(_hdc, &brush); + win_draw_rect(_hdc, &_client); + } else + if (disabled() && _picup) + { + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; + pen.color = COLOR_LTGRAY; + win_set_cpen(_hdc, &pen); + + const int sx = _client.left+DEPTH+1; + const int sy = _client.top+DEPTH+1; + const int ex = _client.right-DEPTH-1; + const int ey = _client.bottom-DEPTH-1; + + for (int i = sx; i < ex; i += 2) + { + PNT p = { sy, i }; + win_move_to(_hdc, p); + p.v = ey; + win_draw_line(_hdc, p); + } + for (i = sy; i < ey; i += 2) + { + PNT p = { i, sx }; + win_move_to(_hdc, p); + p.h = ex; + win_draw_line(_hdc, p); + } + } +} + +/////////////////////////////////////////////////////////// +// TPage_button +/////////////////////////////////////////////////////////// + +class TPage_button : public TControl +{ + enum { height = 19, width = 32 }; + byte _flag; + +protected: + virtual void update() const; + virtual void mouse_down(PNT where); + virtual void mouse_up(); + +public: + TPage_button(WINDOW parent, byte flag); +}; + +TPage_button::TPage_button(WINDOW parent, byte flag) : _flag(flag) +{ + RCT r; get_client_rect(parent, &r); + create(r.right-width, r.bottom-height, r.right, r.bottom, + "", parent, 0L, 0L, DLG_PAGE); + cpb.getbmp(BMP_BOOK1 + flag -1); +} + +void TPage_button::mouse_down(PNT where) +{ + check(where.h < (width>>1)); +} + +void TPage_button::mouse_up() +{ + dispatch_e_char(get_parent(win()), checked() ? K_PREV : K_NEXT); +} + +void TPage_button::update() const +{ + TControl::update(); + cpb_win_picture_draw_at(_hdc, cpb[BMP_BOOK1 + _flag -1], 0, 0); +} + +/////////////////////////////////////////////////////////// +// TTag_button +/////////////////////////////////////////////////////////// + +class TTag_button : public TControl +{ + enum { height = 12, width = 32 }; + byte _curr; + byte _page; + byte _pages; + + WINDOW _parent; + +protected: + virtual void update() const; + virtual void mouse_down(PNT where); + virtual void mouse_up(); + +public: + TTag_button(WINDOW parent, byte p, byte tot); +}; + +TTag_button::TTag_button(WINDOW parent, byte p, byte tot) +: _parent(parent), _page(p), _pages(tot), _curr(p) +{ + RCT r; get_client_rect(parent, &r); + create(0, 0, r.right, CHARY, "", parent,0L,0L, DLG_PAGETAGS); +} + +void TTag_button::update() const +{ + get_geometry(win()); + clear_window(_hdc, COLOR_GRAY); + + for (int i = 0; i < _pages; i++) + { + RCT r; set_rect(&r, width*i, 0, width*(i+1), _client.bottom+4); + CBRUSH b = { PAT_SOLID, (i == _page) ? MASK_BACK_COLOR : COLOR_GRAY }; + win_set_cbrush(_hdc, &b); + win_set_std_cpen(_hdc, TL_PEN_BLACK); + win_draw_rect(_hdc, &r); + + if (i == _page) +#ifdef __CTL3D__ + xvt_draw_rect(_hdc, r, COLOR_WHITE, COLOR_GRAY); +#else + xvt_draw_rect(_hdc, r, COLOR_CYAN, COLOR_GRAY); +#endif + + char n[4]; sprintf(n, "%d", i+1); + win_draw_text(_hdc, (width-CHARX)/2 + i*width, BASEY, n, -1); + } + + CPEN pen; + pen.width = 1; + pen.pat = PAT_SOLID; + pen.style = P_SOLID; +#ifdef __CTL3D__ + pen.color = COLOR_WHITE; +#else + pen.color = COLOR_CYAN; +#endif + win_set_cpen(_hdc, &pen); + + PNT p = { _client.bottom, 0 }; + win_move_to(_hdc, p); + p.h = width*_page; + win_draw_line(_hdc, p); + p.h += width+1; + win_move_to(_hdc, p); + p.h = _client.right; + win_draw_line(_hdc, p); +} + +void TTag_button::mouse_down(PNT where) +{ + _curr = where.h / width; + if (_curr >= _pages) _curr = _pages-1; +} + +void TTag_button::mouse_up() +{ + if (_curr != _page) + dispatch_e_char(_parent, K_CTRL + K_F1 + _curr); +} + +/////////////////////////////////////////////////////////// +// Checkbox +/////////////////////////////////////////////////////////// + +class TCheckbox : public TButton +{ + static bool _bmploaded; + +protected: + virtual WIN_TYPE type() const; + virtual void draw_pressed(bool pressed) const; + virtual void update() const; + + int radio() const { return multiple() ? 1 : 0; } + +public: + TCheckbox(short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id); + virtual ~TCheckbox(); +}; + +bool TCheckbox::_bmploaded = FALSE; + +TCheckbox::TCheckbox( + short left, short top, short right, short bottom, + const char* caption, WINDOW parent, + long flags, long app_data, short id) +: TButton(left, top, right, bottom, + caption, parent, flags, app_data, id) +{ + if (!_bmploaded) + { + cpb.getbmp(BMP_CHECK_ON); + cpb.getbmp(BMP_CHECK_OFF); + cpb.getbmp(BMP_RADIO_ON); + cpb.getbmp(BMP_RADIO_OFF); + _bmploaded = TRUE; + } +} + + +TCheckbox::~TCheckbox() +{ +} + + +WIN_TYPE TCheckbox::type() const +{ + return multiple() ? WC_RADIOBUTTON : WC_CHECKBOX; +} + + +void TCheckbox::draw_pressed(bool pressed) const +{ + get_geometry(win()); + PICTURE pic; + if (radio()) + pic = pressed ? cpb[BMP_RADIO_ON] : cpb[BMP_RADIO_OFF]; + else + pic = pressed ? cpb[BMP_CHECK_ON] : cpb[BMP_CHECK_OFF]; + cpb_win_picture_draw_at(_hdc, pic, _client.left, _client.top); +} + + +void TCheckbox::update() const +{ + TButton::update(); + + const int x = _client.left+20; + const int y = _client.top + BASEY; + + if (focused()) + { +#if XVT_OS == XVT_OS_WIN + RECT r; + r.left = x-2; r.top = _client.top; + r.right = _client.right; r.bottom = y+3; + + HWND hwnd = (HWND)get_value(_hdc, ATTR_NATIVE_WINDOW); + HDC hdc = GetDC(hwnd); + DrawFocusRect(hdc, &r); + ReleaseDC(hwnd, hdc); +#endif + } + + win_draw_text(_hdc, x, y, (char*)caption(), -1); +} + +/////////////////////////////////////////////////////////// +// User functions +/////////////////////////////////////////////////////////// + +WINDOW xvt_create_checkbox( + short left, short top, short right, short bottom, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + TCheckbox* cb = new TCheckbox(left, top, right, bottom, + caption, parent, + flags, app_data, id); + + // It'll destroy itself automagically :-) + + return cb->win(); +} + +WINDOW xvt_create_radiobutton( + short left, short top, short right, short bottom, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + flags |= CTL_FLAG_MULTIPLE; + TCheckbox* cb = new TCheckbox(left, top, right, bottom, + caption, parent, + flags, app_data, id); + + // It'll destroy itself automagically :-) + return cb->win(); +} + + +WINDOW xvt_create_pushbutton( + short left, short top, short right, short bottom, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + TControl* pb; + + switch (id) + { + case DLG_PAGE: + pb = new TPage_button(parent, (byte)flags); + break; + case DLG_PAGETAGS: + pb = new TTag_button(parent, (byte)flags, (byte)app_data); + break; + default: + if (bottom-top > (CHARY<<1)) + { + top += BASEY>>1; + bottom -= BASEY>>1; + } + pb = new TPush_button(left, top, right, bottom, + caption, parent, + flags, app_data, id); + } + + // It'll destroy itself automagically :-) + return pb->win(); +} + + +WINDOW xvt_create_text( + short left, short top, short right, short bottom, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + TText* cb = new TText(left, top, right, bottom, + caption, parent, + flags, app_data, id); + // It'll destroy itself automagically :-) + return cb->win(); +} + + +WINDOW xvt_create_groupbox( + short left, short top, short right, short bottom, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + TGroup* cb = new TGroup(left, top, right, bottom, + caption, parent, + flags, app_data, id); + // It'll destroy itself automagically :-) + return cb->win(); +} + + +void free_controls_bmp() +{ + cpb.reset(); +} + + +TControl* TControl::WINDOW2TControl(WINDOW win) +{ + TControl** model = (TControl**)xvtcm_get_model(win, 0); + CHECK(model && *model, "Can't get the model from a window"); + return *model; +} diff --git a/include/form.cpp b/include/form.cpp index 52adeb962..19462e848 100755 --- a/include/form.cpp +++ b/include/form.cpp @@ -1,1073 +1,1073 @@ -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -/////////////////////////////////////////////////////////// -// TForm_flags -/////////////////////////////////////////////////////////// - -struct TForm_flags : public TObject -{ - bool automagic : 1; - bool disabled : 1; - bool hidden : 1; - -protected: - void print_on(ostream& out) const; - -public: - TForm_flags(); - - void to_mask(TMask& m) const; - void from_mask(const TMask& m); - - bool update(const char* s); -}; - -TForm_flags::TForm_flags() -{ - hidden = automagic = disabled = FALSE; -} - -bool TForm_flags::update(const char* s) -{ - for (; *s; s++) switch(toupper(*s)) - { - case 'A': automagic = TRUE; break; - case 'D': disabled = TRUE; break; - case 'H': hidden = TRUE; break; - default : error_box("Unknown form item flag '%c'", *s); break; - } - return TRUE; -} - -void TForm_flags::print_on(ostream& out) const -{ - TString s(4); - - if (automagic) s << "A"; - if (disabled) s << "D"; - if (hidden) s << "H"; - - if (s.not_empty()) out << " FLAGS \"" << s << '"' << endl; -} - -void TForm_flags::to_mask(TMask& m) const -{ - m.set(F_DISABLED, disabled ? "X" : " "); - m.set(F_HIDDEN, hidden ? "X" : " "); - m.set(F_AUTOMAGIC, automagic ? "X" : " "); -} - -void TForm_flags::from_mask(const TMask& m) -{ - hidden = m.get_bool(F_HIDDEN); - disabled = m.get_bool(F_DISABLED); - automagic = m.get_bool(F_AUTOMAGIC); -} - - -/////////////////////////////////////////////////////////// -// TForm_item -/////////////////////////////////////////////////////////// - -class TForm_item : public TObject -{ - TPrint_section* _section; - TString _desc; - TForm_flags _flag; - TBit_array _group; - TArray _message; - -protected: - int _x, _y, _width, _heigth; - TString _prompt; - - virtual void print_on(ostream& out) const; - virtual void print_body(ostream& out) const; - - virtual void to_mask(TMask& m) const; - virtual void from_mask(const TMask& m); - - int width() const { return _width; } - int heigth() const { return _heigth; } - - bool hidden() const { return _flag.hidden; } - bool disabled() const { return _flag.disabled; } - bool automagic() const { return !_flag.automagic; } - - virtual bool parse_head(TScanner&); - virtual bool parse_item(TScanner&); - - virtual const char* get() const { return _prompt; } - virtual bool set(const char* s) { _prompt = s; return TRUE; } - - TToken_string& message(int m = 0); - void send_message(const TString& cmd, TForm_item* dest) const; - bool do_message(int m = 0); - - void string_at(int x, int y, const char* s); - -public: - virtual bool parse(TScanner&); - virtual bool update(); - - bool edit(TMaskmode mode); - - TPrint_section* section() const { return _section; } - - bool in_group(byte g) const { return g == 0 || _group[g]; } - const TString& key() const { return _desc; } - void to_row(TToken_string& row) const; - - void show(bool on = TRUE) { _flag.hidden = !on; } - void hide() { show(FALSE); } - void enable(bool on = TRUE); - void disable() { enable(FALSE); } - - TForm_item(TPrint_section* section); -}; - - -TForm_item::TForm_item(TPrint_section* section) -: _section(section), _x(-1), _y(-1), _width(0), _heigth(0) -{} - -bool TForm_item::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - if (_width) _heigth = scanner.integer(); - return TRUE; -} - -void TForm_item::print_on(ostream& out) const -{ - out << class_name(); - if (_width > 0) - { - out << ' ' << _width; - if (_heigth > 0) - out << ' ' << _heigth; - } - out << "\nBEGIN\n"; - - print_body(out); - - out << "END\n" << endl; -} - -void TForm_item::print_body(ostream& out) const -{ - if (_y >= 0) - out << " PROMPT " << _x << ' ' << _y << " \"" << _prompt << "\"\n"; - - if (_desc.not_empty()) - out << " KEY \"" << _desc << "\"\n"; - - if (_group.ones()) - out << " GROUP " << _group << "\n"; - - out << _flag; - - if (_message.items() == 1) - { - const char* m = (TToken_string&)_message[0]; - out << " MESSAGE " << m << endl; - } -} - -bool TForm_item::parse_item(TScanner& scanner) -{ - if (scanner.key() == "PR") - { - _x = scanner.integer(); - _y = scanner.integer(); - _prompt = scanner.string(); - return TRUE; - } - - if (scanner.key() == "FL") - return _flag.update(scanner.string()); - - if (scanner.key() == "ME") - { - TString m(scanner.line()); - m.strip_spaces(); - message(0).add(m); - return TRUE; - } - - if (scanner.key() == "KE") - { - _desc = scanner.string(); - return TRUE; - } - - if (scanner.key() == "GR") - { - _group.set(scanner.line()); - return TRUE; - } - - error_box("Unknown symbol in item '%s': '%s'", - (const char*)key(), (const char*)scanner.token()); - - return FALSE; -} - -bool TForm_item::parse(TScanner& scanner) -{ - bool ok = parse_head(scanner); - - if (ok && scanner.popkey() != "BE") - ok = error_box("Missing BEGIN in form item %s", (const char*)key()); - - while (ok && scanner.popkey() != "EN") - ok = parse_item(scanner); - - return ok; -} - -void TForm_item::enable(bool on) -{ - _flag.disabled = !on; - if (on) show(); - else hide(); -} - - -void TForm_item::string_at(int x, int y, const char* s) -{ - if (hidden()) return; - - TPrintrow& row = _section->row(y-1); // Seleziona riga di stampa - - if (_width > 0 && strlen(s) > (word)_width) // Tronca testo se necessario - { - strncpy(__tmp_string, s, width()); - __tmp_string[width()] = '\0'; - s = __tmp_string; - } - row.put(s, x-1); // Stampa testo -} - - -TToken_string& TForm_item::message(int m) -{ - TToken_string* t = (TToken_string*)_message.objptr(m); - if (t == NULL) - { - t = new TToken_string(16); - _message.add(t, m); - } - return *t; -} - - -void TForm_item::send_message(const TString& cmd, TForm_item* des) const -{ - if (cmd == "ADD" || cmd == "SUM" || cmd == "INC") - { - const real n((cmd[0] != 'I') ? get() : "1.0"); - real r(des->get()); - r += n; - des->set(r.string()); - } else - if (cmd == "COPY") - { - des->set(get()); - } else - if (cmd == "APPEND") - { - TString val(80); - val = des->get(); - if (val.not_empty()) val << ' '; - val << get(); - des->set(val); - } else - - if (cmd == "DISABLE") - { - des->disable(); - } else - if (cmd == "ENABLE") - { - des->enable(); - } else - if (cmd == "HIDE") - { - des->hide(); - } else - if (cmd == "SHOW") - { - des->show(); - } else - if (cmd == "RESET") - { - des->set(""); - } else - if (cmd[0] == '"') - { - TString val(cmd); - val.strip("\""); - des->set(val); - } else - error_box("Unknown message in item '%s': '%s'", - (const char*)key(), (const char*)cmd); -} - - -bool TForm_item::do_message(int num) -{ - if (message(num).empty()) return FALSE; - - TToken_string msg(16, ','); - TString cmd(8); - const char* m; - - message(num).restart(); - while ((m = message(num).get()) != NULL) - { - msg = m; - cmd = msg.get(); // Get command - - TFixed_string str(msg.get()); - const word id = atoi(str); // Get destination id - - // Send the message to all fields with the given group - for (int i = 0; i < section()->items(); i++) - { - TForm_item* des = section()->item(i); - if (des->in_group(id)) - send_message(cmd, des); - } - } - - return TRUE; -} - - -bool TForm_item::update() -{ - string_at(_x, _y, _prompt); - do_message(); - return TRUE; -} - -void TForm_item::to_row(TToken_string& row) const -{ - row = class_name(); - row.add(key()); -} - -void TForm_item::to_mask(TMask& m) const -{ - m.set(F_CLASS, class_name()); - m.set(F_KEY, key()); - m.set(F_X, _x); - m.set(F_Y, _y); - m.set(F_PROMPT, _prompt); - m.set(F_WIDTH, _width); - _flag.to_mask(m); - - TString g; - g << _group; - m.set(F_GROUP, g); -} - -void TForm_item::from_mask(const TMask& m) -{ - _desc = m.get(F_KEY); - _x = atoi(m.get(F_X)); - _y = atoi(m.get(F_Y)); - _prompt = m.get(F_PROMPT); - _width = atoi(m.get(F_WIDTH)); - - TString flag; - if (m.get(F_AUTOMAGIC) == "X") flag << "A"; - if (m.get(F_HIDDEN) == "X") flag << "H"; - _flag.update(flag); -} - - -bool TForm_item::edit(TMaskmode mode) -{ - TMask m("bagn003", mode); - if (mode == MODE_INS) - { - m.enable(0); - m.show(); - } - - to_mask(m); - const bool dirty = (m.run() == K_ENTER) && m.dirty(); - if (dirty) from_mask(m); - - return dirty; -} - - -/////////////////////////////////////////////////////////// -// TForm_string -/////////////////////////////////////////////////////////// - -class TForm_string : public TForm_item -{ - TString _str, _picture; - TArray _field; - -protected: - virtual const char* class_name() const { return "STRING"; } - virtual void print_body(ostream& out) const; - - virtual void to_mask(TMask& m) const; - virtual void from_mask(const TMask& m); - - virtual bool parse_item(TScanner&); - virtual bool update(); - - const char* get() const; - bool set(const char*); - - const TString& picture() const { return _picture; } - - TFieldref* field(int i) const { return (TFieldref*)_field.objptr(i); } - void put_paragraph(const char* s); - - bool read(); - -public: - TForm_string(TPrint_section* section) : TForm_item(section) {} -}; - -bool TForm_string::parse_item(TScanner& scanner) -{ - if (scanner.key() == "FI") - { - TFieldref* fr = new TFieldref(scanner.line(), 0); - _field.add(fr); - return TRUE; - } - - if (scanner.key() == "PI") - { - _picture = scanner.string(); - return TRUE; - } - - return TForm_item::parse_item(scanner); -} - -void TForm_string::print_body(ostream& out) const -{ - TForm_item::print_body(out); - if (_picture.not_empty()) - out << " PICTURE \"" << _picture << "\"" << endl; - for (int i = 0; i < _field.items(); i++) - out << " FIELD " << *field(i) << endl; -} - -void TForm_string::to_mask(TMask& m) const -{ - TForm_item::to_mask(m); - TString f(24); f << *field(0); - m.set(F_FIELD, f); - m.set(F_PICTURE, _picture); -} - -void TForm_string::from_mask(const TMask& m) -{ - TForm_item::from_mask(m); - _picture = m.get(F_PICTURE); - *field(0) = m.get(F_FIELD); -} - -bool TForm_string::set(const char* s) -{ - _str = s; - if (width()) _str.cut(width()); - return TRUE; -} - -const char* TForm_string::get() const -{ return _str; } - -bool TForm_string::read() -{ - if (_field.items() && !disabled()) - { - const char* s = ""; - for (int i = 0; i < _field.items(); i++) - { - s = field(i)->read(section()->form()->relation()); - if (*s) break; - } - set(s); - return TRUE; - } - - return FALSE; -} - -void TForm_string::put_paragraph(const char* s) -{ - if (hidden()) return; - - if (heigth() > 1) - { - TParagraph_string p(s, width()); - int i = _prompt.not_empty() ? 1 : 0; - for (; (s = p.get()) != NULL && i < heigth(); i++) - string_at(_x, _y+i, s); - } - else string_at(-1, _y, s); -} - - -bool TForm_string::update() -{ - TForm_item::update(); - if (read()) - { - if (_picture.not_empty()) - { - TString p; - p.picture(_picture, get()); - put_paragraph(p); - } else put_paragraph(get()); - } - return TRUE; -} - -/////////////////////////////////////////////////////////// -// TForm_number -/////////////////////////////////////////////////////////// - -class TForm_number : public TForm_string -{ -protected: - virtual const char* class_name() const { return "NUMBER"; } - virtual bool parse_head(TScanner& scanner); - virtual bool update(); - -public: - TForm_number(TPrint_section* section) : TForm_string(section) {} -}; - - -bool TForm_number::parse_head(TScanner& scanner) -{ - _width = 0; - _heigth = scanner.integer(); - return TRUE; -} - - -bool TForm_number::update() -{ - TForm_item::update(); - if (read()) - { - real n(get()); - n.round(heigth()); - const char* s = n.string(picture()); - put_paragraph(s); - } - return TRUE; -} - -/////////////////////////////////////////////////////////// -// TForm_date -/////////////////////////////////////////////////////////// - -class TForm_date : public TForm_string -{ -protected: - virtual const char* class_name() const { return "DATE"; } - virtual bool set(const char*); - -public: - TForm_date(TPrint_section* section); -}; - - -TForm_date::TForm_date(TPrint_section* section) -: TForm_string(section) -{ - if (automagic()) - { - TDate oggi(TODAY); - set(oggi.string()); - } -} - - -bool TForm_date::set(const char* s) -{ - TDate d(s); - bool ok = d.ok(); - if (ok) - ok = TForm_string::set(d.string((width() == 8) ? 2 : 4)); - return ok; -} - -/////////////////////////////////////////////////////////// -// TForm_list -/////////////////////////////////////////////////////////// - -class TForm_list : public TForm_string -{ - TToken_string _codes; - TToken_string _values; - -protected: - virtual const char* class_name() const { return "LIST"; } - virtual bool parse_item(TScanner& scanner); - virtual void print_body(ostream& out) const; - virtual bool update(); - -public: - TForm_list(TPrint_section* section); -}; - -TForm_list::TForm_list(TPrint_section* section) -: TForm_string(section) -{} - -bool TForm_list::parse_item(TScanner& scanner) -{ - if (scanner.key() == "IT") - { - TToken_string s(scanner.string()); - _codes.add(s.get()); - _values.add(s.get()); - while (scanner.popkey() == "ME") - { - TString m(scanner.line()); - m.strip_spaces(); - message(_values.items()-1).add(m); - } - scanner.push(); - return TRUE; - } - - return TForm_string::parse_item(scanner); -} - - -void TForm_list::print_body(ostream& out) const -{ - TForm_string::print_body(out); - - TToken_string& cod = (TToken_string&)_codes; // Trick to skip const - TToken_string& val = (TToken_string&)_values; - - int i = 0; - TString c(cod.get(0)); - TString v(val.get(0)); - - for (; c[0]; c = cod.get(), v = val.get(), i++) - { - out << " ITEM \"" << c; - if (v.not_empty()) out << '|' << v; - out << '"'; - - const char* m = ((TForm_list*)this)->message(i); - if (*m) out << " MESSAGE " << m; - - out << endl; - } -} - - -bool TForm_list::update() -{ - bool ok = TRUE; - - if (!read()) return ok; - - int pos = _codes.get_pos(get()); - if (pos < 0) - { - TString k(_codes.get(0)); - ok = error_box("Il campo '%s' non puo' valere '%s': assumo '%s'", - (const char*)key(), get(), (const char*)k); - set(k); - pos = 0; - } - - do_message(pos); - - if (!hidden()) - { - if (_prompt.not_empty()) - { - int found = -1; - for (int i = 0; found < pos && _prompt[i]; i++) - if (_prompt[i] != ' ') found++; - if (found == pos) - { - char c[2] = { _prompt[i], '\0' }; - string_at(_x+i, _y, c); - } - else error_box("Non trovo l'elemento %d in '%s'", (const char*)_prompt); - } - else - { - const char* c = _values.get(pos); - if (c == NULL) c = get(); - if (c) string_at(_x, _y, c); - } - } - - return ok; -} - - -/////////////////////////////////////////////////////////// -// TPrint_section -/////////////////////////////////////////////////////////// - -void TPrint_section::init(const char* name, TForm* f) -{ - _name = name; - _form = f; -} - -TPrint_section::TPrint_section(const char* name, TForm* f) -: _heigth(0) -{ - init(name, f); -} - -TPrintrow& TPrint_section::row(int num) -{ - TPrintrow* pr = (TPrintrow*)objptr(num); - if (!pr) - { - pr = new TPrintrow; - add(pr, num); - } - return *pr; -} - -TForm_item* TPrint_section::parse_item(TScanner& scanner) -{ - if (scanner.key() == "ST") - return new TForm_string(this); - if (scanner.key() == "NU") - return new TForm_number(this); - if (scanner.key() == "DA") - return new TForm_date(this); - if (scanner.key() == "LI") - return new TForm_list(this); - - error_box("Elemento sconosciuto nella sezione %s: %s", - (const char*)_name, (const char*)scanner.token()); - return NULL; -} - -bool TPrint_section::parse(TScanner& scanner) -{ - _heigth = scanner.integer(); - - set_cursor(TASK_WIN, CURSOR_WAIT); - - while (scanner.popkey() != "EN") - { - TForm_item *fi = parse_item(scanner); - if (!fi) return FALSE; - - if (fi->parse(scanner)) - _item.add(fi); - else - return FALSE; - } - - set_cursor(TASK_WIN, CURSOR_ARROW); - - return TRUE; -} - -bool TPrint_section::update() -{ - destroy(); - const int last = _item.items(); - bool ok = TRUE; - for (int i = 0; i < last; i++) - { - bool esito = ((TForm_item&)_item[i]).update(); - if (!esito) ok = FALSE; - } - i = items(); - if (i < _heigth) row(_heigth-1); - else if (i > _heigth) - ok = warning_box("Sezione %s troppo lunga: %d > %d", - (const char*)_name, i, _heigth); - return ok; -} - -bool TPrint_section::edit(int mode) -{ - TString title(40); - title = "Campi della sezione "; title << _name; - - TArray_sheet a(-1, -1, 0, 0, title, "Tipo@6|Descrizione@40", 0x8); - - for (int i = 0; i < items(); i++) - { - TToken_string s(64); - item(i)->to_row(s); - a.add(s); - } - - bool dirty = FALSE; - while (a.run() == K_ENTER) - { - i = (int)a.selected(); - const bool spork = item(i)->edit((TMaskmode)mode); - if (spork) - { - dirty = TRUE; - item(i)->to_row(a.row(i)); - } - } - return dirty; -} - -void TPrint_section::print_on(ostream& out) const -{ - out << "\nPAGE " << _name << ' ' << _heigth << '\n' << endl; - for(int i = 0; i < items(); i++) - out << *item(i); -} - -/////////////////////////////////////////////////////////// -// TForm -/////////////////////////////////////////////////////////// - -bool TForm::parse_use(TScanner& scanner) -{ - const int logicnum = scanner.integer(); - const char* tab = NULL; - - if (logicnum > 0) - _relation = new TRelation(logicnum); - else - { - tab = scanner.pop(); - if (strlen(tab) > 4) - return error_box("'%s' non e' una tabella valida: %d", tab); - _relation = new TRelation(tab); - } - - int key = 1; - if (scanner.popkey() == "KE") - { - key = scanner.integer(); - if (key < 1) - { - error_box("Chiave non valida '%s': uso 1", - (const char*)scanner.token()); - key = 1; - } - } - else scanner.push(); - - _cursor = new TCursor(_relation, "", key); - return TRUE; -} - - -bool TForm::parse_join(TScanner& scanner) -{ - TString j(scanner.pop()); // File or table - - int to = 0; - if (scanner.popkey() == "TO") // TO keyword - { - const char* n = scanner.pop(); - to = name2log(n); - } - else scanner.push(); - - int key = 1; - if (scanner.popkey() == "KE") - key = scanner.integer(); - else scanner.push(); - - int 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(); - } - if (exp.empty()) - error_box("JOIN senza espressioni INTO"); - } - scanner.push(); - - if (isdigit(j[0])) - _relation->add(atoi(j), exp, key, to, alias); // join file - else - _relation->add(j, exp, key, to, alias); // join table - - return TRUE; -} - - -bool TForm::set_header() -{ - TPrinter& printer = MainApp()->printer(); - printer.resetheader(); - - const bool ok = _head.update(); - - int last = _head.last(); - for (int j = 0; j <= last; j++) - printer.setheaderline(j, _head.row(j)); - - return ok; -} - - -bool TForm::set_footer() -{ - TPrinter& printer = MainApp()->printer(); - printer.resetfooter(); - - const bool ok = _foot.update(); - - int last = _foot.last(); - for (int j = 0; j <= last; j++) - printer.setfooterline(j, _foot.row(j)); - - return ok; -} - -// Stampa gli items dal from a to -// se to < 0 stampa fino alla fine del file - -bool TForm::print(long from, long to) -{ - TPrinter& printer = MainApp()->printer(); - const bool was_open = printer.isopen(); - - if (!was_open && !printer.open()) - return FALSE; - - if (to < 0) to = _cursor->items()-1; - - bool ok = set_header() && set_footer(); - - for (long i = from; i <= to && ok; i++) - { - if (from < 0) to = from; - else *_cursor = i; - - ok &= _body.update(); - if (!ok) ok = yesno_box("Stampo ugualmente"); - if (!ok) break; - - const word last = _body.last()+1; - if (last < printer.rows() && last > printer.rows_left()) - ok = printer.formfeed(); - for (word j = 0; j < last && ok; j++) - ok = printer.print(_body.row(j)); - } - - if (!was_open) - printer.close(); - - return ok; -} - - -void TForm::print_on(ostream& out) const -{ - out << *_cursor->relation() << endl; - if (_head.items()) out << _head; - if (_body.items()) out << _body; - if (_foot.items()) out << _foot; - out << "ENDPAGE" << endl; -} - - -bool TForm::edit(int mode, int section) -{ - bool dirty = FALSE; - - switch (section) - { - case 0: dirty = _head.edit(mode); break; - case 2: dirty = _foot.edit(mode); break; - default: dirty = _body.edit(mode); break; - } - - if (dirty && yesno_box("Salvare le modifiche?")) - { - set_cursor(TASK_WIN, CURSOR_WAIT); - TFilename bak(_name); bak.ext("bak"); - rename(_name, bak); - ofstream out(_name); - print_on(out); - set_cursor(TASK_WIN, CURSOR_ARROW); - } - - return dirty; -} - - - -TForm::TForm(const char* name) : _name(name) -{ - _name.ext("frm"); - TScanner scanner(_name); - - bool ok = FALSE; - if (scanner.popkey() == "US") - ok = parse_use(scanner); - - CHECKS(ok, "Missing USE in form: ", name); - - while (ok && scanner.popkey() == "JO") - ok = parse_join(scanner); - scanner.push(); - - _head.init("HEADER", this); - _body.init("BODY", this); - _foot.init("FOOTER", this); - - while (scanner.popkey() == "PA") - { - scanner.pop(); - if (scanner.token() == "HEADER") _head.parse(scanner); else - if (scanner.token() == "BODY") _body.parse(scanner); else - if (scanner.token() == "FOOTER") _foot.parse(scanner); - } -} - -TForm::~TForm() -{ - if (_cursor) - { - delete _cursor; - delete _relation; - } -} +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////// +// TForm_flags +/////////////////////////////////////////////////////////// + +struct TForm_flags : public TObject +{ + bool automagic : 1; + bool disabled : 1; + bool hidden : 1; + +protected: + void print_on(ostream& out) const; + +public: + TForm_flags(); + + void to_mask(TMask& m) const; + void from_mask(const TMask& m); + + bool update(const char* s); +}; + +TForm_flags::TForm_flags() +{ + hidden = automagic = disabled = FALSE; +} + +bool TForm_flags::update(const char* s) +{ + for (; *s; s++) switch(toupper(*s)) + { + case 'A': automagic = TRUE; break; + case 'D': disabled = TRUE; break; + case 'H': hidden = TRUE; break; + default : error_box("Unknown form item flag '%c'", *s); break; + } + return TRUE; +} + +void TForm_flags::print_on(ostream& out) const +{ + TString s(4); + + if (automagic) s << "A"; + if (disabled) s << "D"; + if (hidden) s << "H"; + + if (s.not_empty()) out << " FLAGS \"" << s << '"' << endl; +} + +void TForm_flags::to_mask(TMask& m) const +{ + m.set(F_DISABLED, disabled ? "X" : " "); + m.set(F_HIDDEN, hidden ? "X" : " "); + m.set(F_AUTOMAGIC, automagic ? "X" : " "); +} + +void TForm_flags::from_mask(const TMask& m) +{ + hidden = m.get_bool(F_HIDDEN); + disabled = m.get_bool(F_DISABLED); + automagic = m.get_bool(F_AUTOMAGIC); +} + + +/////////////////////////////////////////////////////////// +// TForm_item +/////////////////////////////////////////////////////////// + +class TForm_item : public TObject +{ + TPrint_section* _section; + TString _desc; + TForm_flags _flag; + TBit_array _group; + TArray _message; + +protected: + int _x, _y, _width, _heigth; + TString _prompt; + + virtual void print_on(ostream& out) const; + virtual void print_body(ostream& out) const; + + virtual void to_mask(TMask& m) const; + virtual void from_mask(const TMask& m); + + int width() const { return _width; } + int heigth() const { return _heigth; } + + bool hidden() const { return _flag.hidden; } + bool disabled() const { return _flag.disabled; } + bool automagic() const { return !_flag.automagic; } + + virtual bool parse_head(TScanner&); + virtual bool parse_item(TScanner&); + + virtual const char* get() const { return _prompt; } + virtual bool set(const char* s) { _prompt = s; return TRUE; } + + TToken_string& message(int m = 0); + void send_message(const TString& cmd, TForm_item* dest) const; + bool do_message(int m = 0); + + void string_at(int x, int y, const char* s); + +public: + virtual bool parse(TScanner&); + virtual bool update(); + + bool edit(TMaskmode mode); + + TPrint_section* section() const { return _section; } + + bool in_group(byte g) const { return g == 0 || _group[g]; } + const TString& key() const { return _desc; } + void to_row(TToken_string& row) const; + + void show(bool on = TRUE) { _flag.hidden = !on; } + void hide() { show(FALSE); } + void enable(bool on = TRUE); + void disable() { enable(FALSE); } + + TForm_item(TPrint_section* section); +}; + + +TForm_item::TForm_item(TPrint_section* section) +: _section(section), _x(-1), _y(-1), _width(0), _heigth(0) +{} + +bool TForm_item::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + if (_width) _heigth = scanner.integer(); + return TRUE; +} + +void TForm_item::print_on(ostream& out) const +{ + out << class_name(); + if (_width > 0) + { + out << ' ' << _width; + if (_heigth > 0) + out << ' ' << _heigth; + } + out << "\nBEGIN\n"; + + print_body(out); + + out << "END\n" << endl; +} + +void TForm_item::print_body(ostream& out) const +{ + if (_y >= 0) + out << " PROMPT " << _x << ' ' << _y << " \"" << _prompt << "\"\n"; + + if (_desc.not_empty()) + out << " KEY \"" << _desc << "\"\n"; + + if (_group.ones()) + out << " GROUP " << _group << "\n"; + + out << _flag; + + if (_message.items() == 1) + { + const char* m = (TToken_string&)_message[0]; + out << " MESSAGE " << m << endl; + } +} + +bool TForm_item::parse_item(TScanner& scanner) +{ + if (scanner.key() == "PR") + { + _x = scanner.integer(); + _y = scanner.integer(); + _prompt = scanner.string(); + return TRUE; + } + + if (scanner.key() == "FL") + return _flag.update(scanner.string()); + + if (scanner.key() == "ME") + { + TString m(scanner.line()); + m.strip_spaces(); + message(0).add(m); + return TRUE; + } + + if (scanner.key() == "KE") + { + _desc = scanner.string(); + return TRUE; + } + + if (scanner.key() == "GR") + { + _group.set(scanner.line()); + return TRUE; + } + + error_box("Unknown symbol in item '%s': '%s'", + (const char*)key(), (const char*)scanner.token()); + + return FALSE; +} + +bool TForm_item::parse(TScanner& scanner) +{ + bool ok = parse_head(scanner); + + if (ok && scanner.popkey() != "BE") + ok = error_box("Missing BEGIN in form item %s", (const char*)key()); + + while (ok && scanner.popkey() != "EN") + ok = parse_item(scanner); + + return ok; +} + +void TForm_item::enable(bool on) +{ + _flag.disabled = !on; + if (on) show(); + else hide(); +} + + +void TForm_item::string_at(int x, int y, const char* s) +{ + if (hidden()) return; + + TPrintrow& row = _section->row(y-1); // Seleziona riga di stampa + + if (_width > 0 && strlen(s) > (word)_width) // Tronca testo se necessario + { + strncpy(__tmp_string, s, width()); + __tmp_string[width()] = '\0'; + s = __tmp_string; + } + row.put(s, x-1); // Stampa testo +} + + +TToken_string& TForm_item::message(int m) +{ + TToken_string* t = (TToken_string*)_message.objptr(m); + if (t == NULL) + { + t = new TToken_string(16); + _message.add(t, m); + } + return *t; +} + + +void TForm_item::send_message(const TString& cmd, TForm_item* des) const +{ + if (cmd == "ADD" || cmd == "SUM" || cmd == "INC") + { + const real n((cmd[0] != 'I') ? get() : "1.0"); + real r(des->get()); + r += n; + des->set(r.string()); + } else + if (cmd == "COPY") + { + des->set(get()); + } else + if (cmd == "APPEND") + { + TString val(80); + val = des->get(); + if (val.not_empty()) val << ' '; + val << get(); + des->set(val); + } else + + if (cmd == "DISABLE") + { + des->disable(); + } else + if (cmd == "ENABLE") + { + des->enable(); + } else + if (cmd == "HIDE") + { + des->hide(); + } else + if (cmd == "SHOW") + { + des->show(); + } else + if (cmd == "RESET") + { + des->set(""); + } else + if (cmd[0] == '"') + { + TString val(cmd); + val.strip("\""); + des->set(val); + } else + error_box("Unknown message in item '%s': '%s'", + (const char*)key(), (const char*)cmd); +} + + +bool TForm_item::do_message(int num) +{ + if (message(num).empty()) return FALSE; + + TToken_string msg(16, ','); + TString cmd(8); + const char* m; + + message(num).restart(); + while ((m = message(num).get()) != NULL) + { + msg = m; + cmd = msg.get(); // Get command + + TFixed_string str(msg.get()); + const word id = atoi(str); // Get destination id + + // Send the message to all fields with the given group + for (int i = 0; i < section()->items(); i++) + { + TForm_item* des = section()->item(i); + if (des->in_group(id)) + send_message(cmd, des); + } + } + + return TRUE; +} + + +bool TForm_item::update() +{ + string_at(_x, _y, _prompt); + do_message(); + return TRUE; +} + +void TForm_item::to_row(TToken_string& row) const +{ + row = class_name(); + row.add(key()); +} + +void TForm_item::to_mask(TMask& m) const +{ + m.set(F_CLASS, class_name()); + m.set(F_KEY, key()); + m.set(F_X, _x); + m.set(F_Y, _y); + m.set(F_PROMPT, _prompt); + m.set(F_WIDTH, _width); + _flag.to_mask(m); + + TString g; + g << _group; + m.set(F_GROUP, g); +} + +void TForm_item::from_mask(const TMask& m) +{ + _desc = m.get(F_KEY); + _x = atoi(m.get(F_X)); + _y = atoi(m.get(F_Y)); + _prompt = m.get(F_PROMPT); + _width = atoi(m.get(F_WIDTH)); + + TString flag; + if (m.get(F_AUTOMAGIC) == "X") flag << "A"; + if (m.get(F_HIDDEN) == "X") flag << "H"; + _flag.update(flag); +} + + +bool TForm_item::edit(TMaskmode mode) +{ + TMask m("bagn003", mode); + if (mode == MODE_INS) + { + m.enable(0); + m.show(); + } + + to_mask(m); + const bool dirty = (m.run() == K_ENTER) && m.dirty(); + if (dirty) from_mask(m); + + return dirty; +} + + +/////////////////////////////////////////////////////////// +// TForm_string +/////////////////////////////////////////////////////////// + +class TForm_string : public TForm_item +{ + TString _str, _picture; + TArray _field; + +protected: + virtual const char* class_name() const { return "STRING"; } + virtual void print_body(ostream& out) const; + + virtual void to_mask(TMask& m) const; + virtual void from_mask(const TMask& m); + + virtual bool parse_item(TScanner&); + virtual bool update(); + + const char* get() const; + bool set(const char*); + + const TString& picture() const { return _picture; } + + TFieldref* field(int i) const { return (TFieldref*)_field.objptr(i); } + void put_paragraph(const char* s); + + bool read(); + +public: + TForm_string(TPrint_section* section) : TForm_item(section) {} +}; + +bool TForm_string::parse_item(TScanner& scanner) +{ + if (scanner.key() == "FI") + { + TFieldref* fr = new TFieldref(scanner.line(), 0); + _field.add(fr); + return TRUE; + } + + if (scanner.key() == "PI") + { + _picture = scanner.string(); + return TRUE; + } + + return TForm_item::parse_item(scanner); +} + +void TForm_string::print_body(ostream& out) const +{ + TForm_item::print_body(out); + if (_picture.not_empty()) + out << " PICTURE \"" << _picture << "\"" << endl; + for (int i = 0; i < _field.items(); i++) + out << " FIELD " << *field(i) << endl; +} + +void TForm_string::to_mask(TMask& m) const +{ + TForm_item::to_mask(m); + TString f(24); f << *field(0); + m.set(F_FIELD, f); + m.set(F_PICTURE, _picture); +} + +void TForm_string::from_mask(const TMask& m) +{ + TForm_item::from_mask(m); + _picture = m.get(F_PICTURE); + *field(0) = m.get(F_FIELD); +} + +bool TForm_string::set(const char* s) +{ + _str = s; + if (width()) _str.cut(width()); + return TRUE; +} + +const char* TForm_string::get() const +{ return _str; } + +bool TForm_string::read() +{ + if (_field.items() && !disabled()) + { + const char* s = ""; + for (int i = 0; i < _field.items(); i++) + { + s = field(i)->read(section()->form()->relation()); + if (*s) break; + } + set(s); + return TRUE; + } + + return FALSE; +} + +void TForm_string::put_paragraph(const char* s) +{ + if (hidden()) return; + + if (heigth() > 1) + { + TParagraph_string p(s, width()); + int i = _prompt.not_empty() ? 1 : 0; + for (; (s = p.get()) != NULL && i < heigth(); i++) + string_at(_x, _y+i, s); + } + else string_at(-1, _y, s); +} + + +bool TForm_string::update() +{ + TForm_item::update(); + if (read()) + { + if (_picture.not_empty()) + { + TString p; + p.picture(_picture, get()); + put_paragraph(p); + } else put_paragraph(get()); + } + return TRUE; +} + +/////////////////////////////////////////////////////////// +// TForm_number +/////////////////////////////////////////////////////////// + +class TForm_number : public TForm_string +{ +protected: + virtual const char* class_name() const { return "NUMBER"; } + virtual bool parse_head(TScanner& scanner); + virtual bool update(); + +public: + TForm_number(TPrint_section* section) : TForm_string(section) {} +}; + + +bool TForm_number::parse_head(TScanner& scanner) +{ + _width = 0; + _heigth = scanner.integer(); + return TRUE; +} + + +bool TForm_number::update() +{ + TForm_item::update(); + if (read()) + { + real n(get()); + n.round(heigth()); + const char* s = n.string(picture()); + put_paragraph(s); + } + return TRUE; +} + +/////////////////////////////////////////////////////////// +// TForm_date +/////////////////////////////////////////////////////////// + +class TForm_date : public TForm_string +{ +protected: + virtual const char* class_name() const { return "DATE"; } + virtual bool set(const char*); + +public: + TForm_date(TPrint_section* section); +}; + + +TForm_date::TForm_date(TPrint_section* section) +: TForm_string(section) +{ + if (automagic()) + { + TDate oggi(TODAY); + set(oggi.string()); + } +} + + +bool TForm_date::set(const char* s) +{ + TDate d(s); + bool ok = d.ok(); + if (ok) + ok = TForm_string::set(d.string((width() == 8) ? 2 : 4)); + return ok; +} + +/////////////////////////////////////////////////////////// +// TForm_list +/////////////////////////////////////////////////////////// + +class TForm_list : public TForm_string +{ + TToken_string _codes; + TToken_string _values; + +protected: + virtual const char* class_name() const { return "LIST"; } + virtual bool parse_item(TScanner& scanner); + virtual void print_body(ostream& out) const; + virtual bool update(); + +public: + TForm_list(TPrint_section* section); +}; + +TForm_list::TForm_list(TPrint_section* section) +: TForm_string(section) +{} + +bool TForm_list::parse_item(TScanner& scanner) +{ + if (scanner.key() == "IT") + { + TToken_string s(scanner.string()); + _codes.add(s.get()); + _values.add(s.get()); + while (scanner.popkey() == "ME") + { + TString m(scanner.line()); + m.strip_spaces(); + message(_values.items()-1).add(m); + } + scanner.push(); + return TRUE; + } + + return TForm_string::parse_item(scanner); +} + + +void TForm_list::print_body(ostream& out) const +{ + TForm_string::print_body(out); + + TToken_string& cod = (TToken_string&)_codes; // Trick to skip const + TToken_string& val = (TToken_string&)_values; + + int i = 0; + TString c(cod.get(0)); + TString v(val.get(0)); + + for (; c[0]; c = cod.get(), v = val.get(), i++) + { + out << " ITEM \"" << c; + if (v.not_empty()) out << '|' << v; + out << '"'; + + const char* m = ((TForm_list*)this)->message(i); + if (*m) out << " MESSAGE " << m; + + out << endl; + } +} + + +bool TForm_list::update() +{ + bool ok = TRUE; + + if (!read()) return ok; + + int pos = _codes.get_pos(get()); + if (pos < 0) + { + TString k(_codes.get(0)); + ok = error_box("Il campo '%s' non puo' valere '%s': assumo '%s'", + (const char*)key(), get(), (const char*)k); + set(k); + pos = 0; + } + + do_message(pos); + + if (!hidden()) + { + if (_prompt.not_empty()) + { + int found = -1; + for (int i = 0; found < pos && _prompt[i]; i++) + if (_prompt[i] != ' ') found++; + if (found == pos) + { + char c[2] = { _prompt[i], '\0' }; + string_at(_x+i, _y, c); + } + else error_box("Non trovo l'elemento %d in '%s'", (const char*)_prompt); + } + else + { + const char* c = _values.get(pos); + if (c == NULL) c = get(); + if (c) string_at(_x, _y, c); + } + } + + return ok; +} + + +/////////////////////////////////////////////////////////// +// TPrint_section +/////////////////////////////////////////////////////////// + +void TPrint_section::init(const char* name, TForm* f) +{ + _name = name; + _form = f; +} + +TPrint_section::TPrint_section(const char* name, TForm* f) +: _heigth(0) +{ + init(name, f); +} + +TPrintrow& TPrint_section::row(int num) +{ + TPrintrow* pr = (TPrintrow*)objptr(num); + if (!pr) + { + pr = new TPrintrow; + add(pr, num); + } + return *pr; +} + +TForm_item* TPrint_section::parse_item(TScanner& scanner) +{ + if (scanner.key() == "ST") + return new TForm_string(this); + if (scanner.key() == "NU") + return new TForm_number(this); + if (scanner.key() == "DA") + return new TForm_date(this); + if (scanner.key() == "LI") + return new TForm_list(this); + + error_box("Elemento sconosciuto nella sezione %s: %s", + (const char*)_name, (const char*)scanner.token()); + return NULL; +} + +bool TPrint_section::parse(TScanner& scanner) +{ + _heigth = scanner.integer(); + + set_cursor(TASK_WIN, CURSOR_WAIT); + + while (scanner.popkey() != "EN") + { + TForm_item *fi = parse_item(scanner); + if (!fi) return FALSE; + + if (fi->parse(scanner)) + _item.add(fi); + else + return FALSE; + } + + set_cursor(TASK_WIN, CURSOR_ARROW); + + return TRUE; +} + +bool TPrint_section::update() +{ + destroy(); + const int last = _item.items(); + bool ok = TRUE; + for (int i = 0; i < last; i++) + { + bool esito = ((TForm_item&)_item[i]).update(); + if (!esito) ok = FALSE; + } + i = items(); + if (i < _heigth) row(_heigth-1); + else if (i > _heigth) + ok = warning_box("Sezione %s troppo lunga: %d > %d", + (const char*)_name, i, _heigth); + return ok; +} + +bool TPrint_section::edit(int mode) +{ + TString title(40); + title = "Campi della sezione "; title << _name; + + TArray_sheet a(-1, -1, 0, 0, title, "Tipo@6|Descrizione@40", 0x8); + + for (int i = 0; i < items(); i++) + { + TToken_string s(64); + item(i)->to_row(s); + a.add(s); + } + + bool dirty = FALSE; + while (a.run() == K_ENTER) + { + i = (int)a.selected(); + const bool spork = item(i)->edit((TMaskmode)mode); + if (spork) + { + dirty = TRUE; + item(i)->to_row(a.row(i)); + } + } + return dirty; +} + +void TPrint_section::print_on(ostream& out) const +{ + out << "\nPAGE " << _name << ' ' << _heigth << '\n' << endl; + for(int i = 0; i < items(); i++) + out << *item(i); +} + +/////////////////////////////////////////////////////////// +// TForm +/////////////////////////////////////////////////////////// + +bool TForm::parse_use(TScanner& scanner) +{ + const int logicnum = scanner.integer(); + const char* tab = NULL; + + if (logicnum > 0) + _relation = new TRelation(logicnum); + else + { + tab = scanner.pop(); + if (strlen(tab) > 4) + return error_box("'%s' non e' una tabella valida: %d", tab); + _relation = new TRelation(tab); + } + + int key = 1; + if (scanner.popkey() == "KE") + { + key = scanner.integer(); + if (key < 1) + { + error_box("Chiave non valida '%s': uso 1", + (const char*)scanner.token()); + key = 1; + } + } + else scanner.push(); + + _cursor = new TCursor(_relation, "", key); + return TRUE; +} + + +bool TForm::parse_join(TScanner& scanner) +{ + TString j(scanner.pop()); // File or table + + int to = 0; + if (scanner.popkey() == "TO") // TO keyword + { + const char* n = scanner.pop(); + to = name2log(n); + } + else scanner.push(); + + int key = 1; + if (scanner.popkey() == "KE") + key = scanner.integer(); + else scanner.push(); + + int 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(); + } + if (exp.empty()) + error_box("JOIN senza espressioni INTO"); + } + scanner.push(); + + if (isdigit(j[0])) + _relation->add(atoi(j), exp, key, to, alias); // join file + else + _relation->add(j, exp, key, to, alias); // join table + + return TRUE; +} + + +bool TForm::set_header() +{ + TPrinter& printer = main_app().printer(); + printer.resetheader(); + + const bool ok = _head.update(); + + int last = _head.last(); + for (int j = 0; j <= last; j++) + printer.setheaderline(j, _head.row(j)); + + return ok; +} + + +bool TForm::set_footer() +{ + TPrinter& printer = main_app().printer(); + printer.resetfooter(); + + const bool ok = _foot.update(); + + int last = _foot.last(); + for (int j = 0; j <= last; j++) + printer.setfooterline(j, _foot.row(j)); + + return ok; +} + +// Stampa gli items dal from a to +// se to < 0 stampa fino alla fine del file + +bool TForm::print(long from, long to) +{ + TPrinter& printer = main_app().printer(); + const bool was_open = printer.isopen(); + + if (!was_open && !printer.open()) + return FALSE; + + if (to < 0) to = _cursor->items()-1; + + bool ok = set_header() && set_footer(); + + for (long i = from; i <= to && ok; i++) + { + if (from < 0) to = from; + else *_cursor = i; + + ok &= _body.update(); + if (!ok) ok = yesno_box("Stampo ugualmente"); + if (!ok) break; + + const word last = _body.last()+1; + if (last < printer.rows() && last > printer.rows_left()) + ok = printer.formfeed(); + for (word j = 0; j < last && ok; j++) + ok = printer.print(_body.row(j)); + } + + if (!was_open) + printer.close(); + + return ok; +} + + +void TForm::print_on(ostream& out) const +{ + out << *_cursor->relation() << endl; + if (_head.items()) out << _head; + if (_body.items()) out << _body; + if (_foot.items()) out << _foot; + out << "ENDPAGE" << endl; +} + + +bool TForm::edit(int mode, int section) +{ + bool dirty = FALSE; + + switch (section) + { + case 0: dirty = _head.edit(mode); break; + case 2: dirty = _foot.edit(mode); break; + default: dirty = _body.edit(mode); break; + } + + if (dirty && yesno_box("Salvare le modifiche?")) + { + set_cursor(TASK_WIN, CURSOR_WAIT); + TFilename bak(_name); bak.ext("bak"); + rename(_name, bak); + ofstream out(_name); + print_on(out); + set_cursor(TASK_WIN, CURSOR_ARROW); + } + + return dirty; +} + + + +TForm::TForm(const char* name) : _name(name) +{ + _name.ext("frm"); + TScanner scanner(_name); + + bool ok = FALSE; + if (scanner.popkey() == "US") + ok = parse_use(scanner); + + CHECKS(ok, "Missing USE in form: ", name); + + while (ok && scanner.popkey() == "JO") + ok = parse_join(scanner); + scanner.push(); + + _head.init("HEADER", this); + _body.init("BODY", this); + _foot.init("FOOTER", this); + + while (scanner.popkey() == "PA") + { + scanner.pop(); + if (scanner.token() == "HEADER") _head.parse(scanner); else + if (scanner.token() == "BODY") _body.parse(scanner); else + if (scanner.token() == "FOOTER") _foot.parse(scanner); + } +} + +TForm::~TForm() +{ + if (_cursor) + { + delete _cursor; + delete _relation; + } +} diff --git a/include/mailbox.cpp b/include/mailbox.cpp index 06238b654..aa535a96a 100755 --- a/include/mailbox.cpp +++ b/include/mailbox.cpp @@ -1,202 +1,202 @@ -// $Id: mailbox.cpp,v 1.5 1994-10-25 10:00:59 alex Exp $ - -#include -#include - -#include -#include -#include - -#if XVT_OS == XVT_OS_DOS || XVT_OS == XVT_OS_WIN -#include -#else -#include -#endif - -#define DEF_MSGS_CAPACITY 50 -#define MAX_TXT_LEN 200 - -TMessage::TMessage(const char* to, const char* sub, const char* text, - const char* from) -{ - _to = to; _subject = sub; - _text = text; - _from = (from == NULL || *from == '\0' ? main_app().name() : from); - _flags = 0x00; _number = -1; -} - -void TMessage::send() -{ - TMailbox mail; - mail.send(*this); -} - - -void TMailbox::reread() - // reads new messages from mailbox; - // create messages, put messages in _msgs array in cronological order -{ - char buf[MAX_TXT_LEN]; - - ifstream mbox(_path); - - // skip read messages - mbox.seekg(_lastpos); - while (mbox.getline(buf, MAX_TXT_LEN -1) != NULL) - { - // process new message - TMessage* tmnew = new TMessage (NULL, NULL, NULL, buf); - // lines are - mbox.getline(buf, MAX_TXT_LEN -1); - tmnew->subject(buf); - mbox.getline(buf, MAX_TXT_LEN -1); - tmnew->body(buf); - _msgs.add(tmnew); - tmnew->number(_msgs.items()); - n_new++; - } - _lastpos = mbox.tellg(); -} - -TMessage* TMailbox::next_unread() -{ - // returns next unread message; - if (_cnt == _msgs.items()) - return NULL; - while(this->get(_cnt)->isread()) - { - _cnt++; - if (_cnt == _msgs.items()) - return NULL; - } - n_new --; - return this->get(_lastread = _cnt); -} - -TMessage* TMailbox::next_read() -{ - // next read/unread message - if (_cnt == _msgs.items()) - return NULL; - if (!(this->get(_cnt)->isread())) - n_new--; - return this->get(_cnt++); -} - -TMessage* TMailbox::next(bool read) -{ - // next message, default unread - TMessage* m = read ? next_read() : next_unread(); - if (m) - m->setread(); - return m; -} - - -TMessage* TMailbox::next_s(char* s, bool read) -{ - // next message with matching subject - for (;;) - { - if (_cnt == _msgs.items()) - return NULL; - if (strcmp(this->get(_cnt)->subject(), s) == 0) - { - if (read) break; - else - { - if (!(this->get(_cnt)->isread())) break; - } - } - _cnt++; - } - this->get(_cnt)->setread(); - if (!read) n_new--; - return this->get(_cnt); -} - -TMessage* TMailbox::next_f(char* f, bool read) -{ - // next message with matching sender - for (;;) - { - if (_cnt == _msgs.items()) - return NULL; - if (strcmp(this->get(_cnt)->from(), f) == 0) - { - if (read) break; - else { if (!(this->get(_cnt)->isread())) break; } - } - _cnt++; - } - this->get(_cnt)->setread(); - if (!read) n_new--; - return this->get(_cnt); -} - -void TMailbox::send(TMessage& m) -{ - CHECK(m.from().not_empty() && m.to().not_empty() && - (m.subject().not_empty || m.body().not_empty()), - "Can't send partially empty message"); - - // strcpy(to_path, getenv("TMPDIR") == NULL ? MAILDIR : getenv("TMPDIR")); - TFilename to_path; to_path.tempdir(); - to_path << "/" << m.to() << ".mbx"; - - ofstream fto(to_path, ios::app); - CHECK(fto.good(),"send: trouble opening mailbox file"); - fto << m.from() << '\n' - << m.subject() << '\n' - << m.body() << '\n'; - fto.close(); -} - -void TMailbox::sendcmd(int argc, char* argv[], char* to) -{ - CHECK(0,"MAILBOX::COMMANDLINE INTERFACE NOT IMPLEMENTED"); - for (int i = 0; i < argc; i++) - { - // parse argv[i] - // create new message - // send it out - } -} - -char* TMailbox::readcmd(char*) -{ - // filters all messages to recipient and adds to to_path - CHECK(0,"MAILBOX::COMMANDLINE INTERFACE NOT IMPLEMENTED"); - // TMessage* m; - return "NOT YET IMPLEMENTED"; -} - -TMailbox::TMailbox(const char* appname) : _msgs(DEF_MSGS_CAPACITY) -{ - if (appname == NULL) - appname = main_app().name(); // myself; must be global - - _path.tempdir(); - // strcpy(_path, getenv("TMPDIR") == NULL ? MAILDIR : getenv("TMPDIR")); - _path << "/" << appname << ".mbx"; - - _lastread =0; _lastpos = 0l; - n_new = 0; - this->reread(); - restart(); -} - -TMailbox::~TMailbox() -{ - TMessage* m; - // scan all remaining messages and erase mailbox - reread(); - if (access(_path,0) == 0) - remove(_path); - // send unread messages to myself - while((m = next()) != NULL) - { - m->to(MainApp()->name()); - send(*m); - } -} +// $Id: mailbox.cpp,v 1.6 1994-11-10 13:44:25 guy Exp $ + +#include +#include + +#include +#include +#include + +#if XVT_OS == XVT_OS_DOS || XVT_OS == XVT_OS_WIN +#include +#else +#include +#endif + +#define DEF_MSGS_CAPACITY 50 +#define MAX_TXT_LEN 200 + +TMessage::TMessage(const char* to, const char* sub, const char* text, + const char* from) +{ + _to = to; _subject = sub; + _text = text; + _from = (from == NULL || *from == '\0' ? main_app().name() : from); + _flags = 0x00; _number = -1; +} + +void TMessage::send() +{ + TMailbox mail; + mail.send(*this); +} + + +void TMailbox::reread() + // reads new messages from mailbox; + // create messages, put messages in _msgs array in cronological order +{ + char buf[MAX_TXT_LEN]; + + ifstream mbox(_path); + + // skip read messages + mbox.seekg(_lastpos); + while (mbox.getline(buf, MAX_TXT_LEN -1) != NULL) + { + // process new message + TMessage* tmnew = new TMessage (NULL, NULL, NULL, buf); + // lines are + mbox.getline(buf, MAX_TXT_LEN -1); + tmnew->subject(buf); + mbox.getline(buf, MAX_TXT_LEN -1); + tmnew->body(buf); + _msgs.add(tmnew); + tmnew->number(_msgs.items()); + n_new++; + } + _lastpos = mbox.tellg(); +} + +TMessage* TMailbox::next_unread() +{ + // returns next unread message; + if (_cnt == _msgs.items()) + return NULL; + while(this->get(_cnt)->isread()) + { + _cnt++; + if (_cnt == _msgs.items()) + return NULL; + } + n_new --; + return this->get(_lastread = _cnt); +} + +TMessage* TMailbox::next_read() +{ + // next read/unread message + if (_cnt == _msgs.items()) + return NULL; + if (!(this->get(_cnt)->isread())) + n_new--; + return this->get(_cnt++); +} + +TMessage* TMailbox::next(bool read) +{ + // next message, default unread + TMessage* m = read ? next_read() : next_unread(); + if (m) + m->setread(); + return m; +} + + +TMessage* TMailbox::next_s(char* s, bool read) +{ + // next message with matching subject + for (;;) + { + if (_cnt == _msgs.items()) + return NULL; + if (strcmp(this->get(_cnt)->subject(), s) == 0) + { + if (read) break; + else + { + if (!(this->get(_cnt)->isread())) break; + } + } + _cnt++; + } + this->get(_cnt)->setread(); + if (!read) n_new--; + return this->get(_cnt); +} + +TMessage* TMailbox::next_f(char* f, bool read) +{ + // next message with matching sender + for (;;) + { + if (_cnt == _msgs.items()) + return NULL; + if (strcmp(this->get(_cnt)->from(), f) == 0) + { + if (read) break; + else { if (!(this->get(_cnt)->isread())) break; } + } + _cnt++; + } + this->get(_cnt)->setread(); + if (!read) n_new--; + return this->get(_cnt); +} + +void TMailbox::send(TMessage& m) +{ + CHECK(m.from().not_empty() && m.to().not_empty() && + (m.subject().not_empty || m.body().not_empty()), + "Can't send partially empty message"); + + // strcpy(to_path, getenv("TMPDIR") == NULL ? MAILDIR : getenv("TMPDIR")); + TFilename to_path; to_path.tempdir(); + to_path << "/" << m.to() << ".mbx"; + + ofstream fto(to_path, ios::app); + CHECK(fto.good(),"send: trouble opening mailbox file"); + fto << m.from() << '\n' + << m.subject() << '\n' + << m.body() << '\n'; + fto.close(); +} + +void TMailbox::sendcmd(int argc, char* argv[], char* to) +{ + CHECK(0,"MAILBOX::COMMANDLINE INTERFACE NOT IMPLEMENTED"); + for (int i = 0; i < argc; i++) + { + // parse argv[i] + // create new message + // send it out + } +} + +char* TMailbox::readcmd(char*) +{ + // filters all messages to recipient and adds to to_path + CHECK(0,"MAILBOX::COMMANDLINE INTERFACE NOT IMPLEMENTED"); + // TMessage* m; + return "NOT YET IMPLEMENTED"; +} + +TMailbox::TMailbox(const char* appname) : _msgs(DEF_MSGS_CAPACITY) +{ + if (appname == NULL) + appname = main_app().name(); // myself; must be global + + _path.tempdir(); + // strcpy(_path, getenv("TMPDIR") == NULL ? MAILDIR : getenv("TMPDIR")); + _path << "/" << appname << ".mbx"; + + _lastread =0; _lastpos = 0l; + n_new = 0; + this->reread(); + restart(); +} + +TMailbox::~TMailbox() +{ + TMessage* m; + // scan all remaining messages and erase mailbox + reread(); + if (access(_path,0) == 0) + remove(_path); + // send unread messages to myself + while((m = next()) != NULL) + { + m->to(main_app().name()); + send(*m); + } +} diff --git a/include/mask.cpp b/include/mask.cpp index bb48c05a7..cb3af6f40 100755 --- a/include/mask.cpp +++ b/include/mask.cpp @@ -769,7 +769,8 @@ bool TMask::on_key(KEY key) } } } - else return fld(_focus).on_key(key); + else + return fld(_focus).on_key(key); } return TRUE; @@ -1125,7 +1126,9 @@ void TMask::send_key(KEY key, short to) const { if (to == 0) { - dispatch_e_char(win(), key); + WINDOW w = win(); + if (w == NULL_WIN) w = _pagewin[0]; + dispatch_e_char(w, key); return; } diff --git a/include/maskfld.cpp b/include/maskfld.cpp index 1c514365f..ae5d6f20b 100755 --- a/include/maskfld.cpp +++ b/include/maskfld.cpp @@ -1,4 +1,4 @@ -// $Id: maskfld.cpp,v 1.42 1994-11-07 13:50:56 guy Exp $ +// $Id: maskfld.cpp,v 1.43 1994-11-10 13:44:30 guy Exp $ #include #include @@ -1349,8 +1349,7 @@ 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; // Non saprei come fare + // if (!mask.is_running()) return siblings; TBit_array key(4); // Elenco delle chiavi gia' utilizzate key.set(_cursor->key()); @@ -1451,8 +1450,7 @@ default: { const short id = siblings.get_int((k - K_CTRL) << 1); TEdit_field& ef = (TEdit_field&)_fld->mask().field(id); - if (ef.mask().is_running()) ef.set_focus(); - else ef.mask().first_focus(-ef.dlg()); + ef.set_focus(); ef.mask().send_key(k = K_F9, 0); } break; @@ -1652,7 +1650,7 @@ bool TEdit_field::parse_item(TScanner& scanner) if (tabmaskname.not_empty()) { - if (strncmp(MainApp()->name(), "ba3", 3) != 0) + if (strncmp(main_app().name(), "ba3", 3) != 0) { tabmaskname.insert("MBATB", 0); _browse->set_insert(tabmaskname); @@ -2412,7 +2410,7 @@ void TReal_field::create(WINDOW w) TEdit_field::create(w); if (_flags.firm) - set(::format("%ld", MainApp()->get_firm())); else + set(::format("%ld", main_app().get_firm())); else if (automagic()) { TDate d(TODAY); diff --git a/include/msksheet.cpp b/include/msksheet.cpp index 8f6597965..6c32b1bbe 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -1,1223 +1,1228 @@ -#include -#include -#include -#include - -const short FIRST_FIELD = 101; - -#if XVT_OS == XVT_OS_WIN - -#include -#include - -/////////////////////////////////////////////////////////// -// TSpreadsheet -/////////////////////////////////////////////////////////// - -#define K_PLUS '+' - -class TSpreadsheet : public TWindow -{ - enum { ITF_CID = 0, LIST_CID = 1 }; - - TArray _str; // Array di TToken_strings - TBit_array _column_disabled; - TArray _disabled; // Array di TBit_array - - TMask _mask; - int _columns; - bool _dirty; - bool _firstfocus; - - XI_OBJ *_list, *_itf; - - SPREADSHEET_NOTIFY _notify; - - TMask_field* _edit_field; // Current edit field - int _cur_row, _cur_col; // Current cell - bool _row_dirty; // Current row changed - bool _check_enabled; // Perform OFF_ROW checks - - static void xiev_handler(XI_OBJ *itf, XI_EVENT *xiev); - void init(); - -protected: - void list_handler(XI_EVENT *xiev); - - TMask_field* cell2field(const XI_OBJ* cell) const; - void update_rec(int rec); - void set_focus_cell(int riga, int colonna); - - void mask2str(int n); - void str2mask(int n); - KEY edit(int n); - - TMask_field* field(short id) const; - - int rec2row(int rec); - int row2rec(int row); - - bool notify(int r, KEY k); - -public: - void update(int row); - - TToken_string& row(int n); - TArray& rows_array() const { return (TArray&)_str; } - int add(TToken_string&); - int insert(int rec); - bool destroy(int rec = -1); - - void enable_column(int col, bool on = TRUE); - void enable_cell(int row, int column, bool on = TRUE); - bool cell_disabled(int row, int column) const; - - TMask& sheet_mask() { return _mask; } - TMask& mask(); - - int items() const { return _str.items(); } - int selected() const { return _cur_row; } - int columns() const { return _columns; } - bool dirty() const { return _dirty; } - void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } - - void set_dirty(bool spork = TRUE) { _dirty = spork; } - - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, - const char* head, WINDOW parent); - virtual ~TSpreadsheet(); -}; - -// Certified 100% -void TSpreadsheet::init() -{ - static bool first = TRUE; - if (!first) return; - - DRAW_CTOOLS ct; - win_get_draw_ctools(TASK_WIN, &ct); - xi_set_font(&ct.font); - - xi_init(); - xi_set_pref(XI_PREF_3D_LOOK, TRUE); - // xi_set_pref(XI_PREF_COLOR_LIGHT, COLOR_CYAN); - // xi_set_pref(XI_PREF_COLOR_CTRL, MASK_BACK_COLOR); - // xi_set_pref(XI_PREF_COLOR_DARK, COLOR_GRAY); - - first = FALSE; -} - - -TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, - const char* maskname, int maskno, - const char* head, WINDOW parent) -: _mask(maskname, NO_MODE, maskno), _notify(NULL), _edit_field(NULL), _cur_row(0), _cur_col(0), - _row_dirty(FALSE), _check_enabled(TRUE), _firstfocus(TRUE) -{ - const int NUMBER_WIDTH = 3; - const int MAX_COL = 32; - int m_width[MAX_COL], v_width[MAX_COL]; - int fixed_columns = 1; // Number of fixed columns - - init(); - - // Calcolo larghezza massima tabella - - TToken_string header(head); - TToken_string new_header(256); - int i = 0, tot_width = NUMBER_WIDTH+1; - int f_width = tot_width<<1; // Stima larghezza colonne fisse - int max_width = f_width; // Stima larghezza della colonna piu' grande - - for (const char* h = header.get(); h; h = header.get(), i++) - { - CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); - - const int cid = FIRST_FIELD+i; // Column & Field ID - const TMask_field* f = field(cid); // Field on mask - CHECKD(f, "The spreadsheet mask needs ALSO field ", cid); - - TString80 testa(h); - const int at = testa.find('@'); - int m, v; - if (at >= 0) - { - const TString& wi = testa.mid(at+1); - m = atoi(wi); - if (wi[wi.len()-1] == 'F') - { - fixed_columns++; - f_width += m+1; - } - testa.cut(at); - v = max(at, m+(f->has_query() ? 1 : 0)); - } - else - { - m = testa.len(); - v = m+(f->has_query() ? 1 : 0); - } - - m_width[i] = m+1; // m = number of allowed chars - v_width[i] = v+1; // v = width of column - if (v >= max_width) max_width = v+1; - - tot_width += v_width[i]; - - new_header.add(testa); - } - _columns = i; - - if (x < 0) x = 0; - if (y < 0) y = 0; - if (dx == 0) - { - dx = tot_width; - if (dx > 76) dx = -x; - } - - RCT rct = resize_rect(x, y, dx, dy, WO_TE, parent); - rct.bottom -= 12; - rct.right -= 28; - - if ((f_width+max_width)*CHARX > rct.right) - fixed_columns = 1; - - XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID, - (XI_EVENT_HANDLER)xiev_handler, &rct, (char*)maskname, - PTR_LONG(this)); - itfdef->v.itf->automatic_back_color = FALSE; - itfdef->v.itf->back_color = MASK_BACK_COLOR; - - XI_OBJ_DEF* listdef = xi_add_list_def(itfdef, LIST_CID, - 0, 0, rct.bottom-rct.top, - XI_ATR_ENABLED | XI_ATR_VISIBLE, - NORMAL_COLOR, NORMAL_BACK_COLOR, // normal - NORMAL_COLOR, DISABLED_BACK_COLOR, // disabled - COLOR_RED, // active - LIST_CID); - listdef->v.list->sizable_columns = TRUE; - listdef->v.list->movable_columns = TRUE; - listdef->v.list->scroll_bar = TRUE; - listdef->v.list->scroll_bar_button = TRUE; - listdef->v.list->fixed_columns = fixed_columns; - listdef->v.list->width = rct.right-rct.left; - listdef->v.list->min_cell_height = CHARY; - listdef->v.list->min_heading_height = CHARY; - listdef->v.list->white_space_color = COLOR_GRAY; - - XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, - XI_ATR_RJUST, 0, NUMBER_WIDTH, NUMBER_WIDTH, ""); - coldef->v.column->heading_platform = TRUE; - coldef->v.column->column_platform = TRUE; - coldef->v.column->center_heading = TRUE; - - for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) - { - const int cid = FIRST_FIELD+i; // Column & Field ID - const TMask_field* f = field(cid); // Field on mask - - long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL; - if (f->class_id() == CLASS_REAL_FIELD) flags |= XI_ATR_RJUST; - if (f->active()) flags |= XI_ATR_ENABLED | XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT; - else _column_disabled.set(i); - - coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i], m_width[i], (char*)h); - coldef->v.column->heading_platform = TRUE; - coldef->v.column->center_heading = TRUE; - } - - RCT itfrct; - xi_get_def_rect(itfdef, &itfrct); - offset_rect(&itfrct, rct.left, rct.top); - itfrct.bottom++; - - WINDOW win = create_window(W_NO_BORDER, &itfrct, "", 0, parent, - 0, EM_ALL, (EVENT_HANDLER)xi_event, 0L); - CHECK(win, "Can't create a window for the spreadsheet"); - - set_win(win); // Set TWindow::_win - itfdef->v.itf->win = win; // Link interface to win - - xi_create(NULL, itfdef); // Create the whole thing! - xi_tree_free(itfdef); // Free definitions - - _itf = xi_get_itf(win); // Store useful references for later use - _list = xi_get_obj(_itf, LIST_CID); -} - -TSpreadsheet::~TSpreadsheet() -{ - set_win(NULL_WIN); -} - - - -// Converts a row number in the correspondig record number -int TSpreadsheet::row2rec(int row) -{ - int rows; - const long* rec = xi_get_list_info(_list, &rows); - -#ifdef DBG - if (row < 0 || row >= rows) - { - error_box("Line %d is not visible", row); - return 0L; - } -#endif - - return (int)rec[row]; -} - - -// Converts a row number in the correspondig record number -int TSpreadsheet::rec2row(int record) -{ - int rows; - const long* rec = xi_get_list_info(_list, &rows); - int r = int(record - rec[0]); - if (r < 0 || r >= rows) - r = -1; - - return r; -} - -// Retrieves the corresponding field of the mask from a spredsheet cell -TMask_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const -{ - const int pos = cell->v.cell.column; - - int num; - XI_OBJ** column = xi_get_member_list(_list, &num); - - TMask_field* good = NULL; - for (short id = column[pos]->cid; ; id += 100) - { - TMask_field* f = field(id); - if (f == NULL) break; - good = f; // We've found a field with the proper ID ... - if (f->active()) break; // ... and it's active: end of search - } - - return good; -} - -void TSpreadsheet::update_rec(int rec) -{ - const int riga = rec2row(rec); - if (riga >= 0) - { - XI_OBJ row; - XI_MAKE_ROW(&row, _list, riga); - xi_cell_request(&row); // Update internal values - xi_set_row_height(&row, CHARY+1); // Force row updating - } -} - -void TSpreadsheet::set_focus_cell(int riga, int colonna) -{ - set_front_window(win()); // It seems necessary to make xi_set_focus work properly - XI_OBJ cell; - XI_MAKE_CELL(&cell, _list, rec2row(riga), colonna); - xi_set_focus(&cell); -} - - -int TSpreadsheet::insert(int rec) -{ - const bool ok = notify(rec, K_INS); - if (!ok) return -1; - - TToken_string s; // Empty row - const int r = _str.insert(s, rec); - _disabled.insert(NULL, rec); - - xi_insert_row(_list, INT_MAX); - xi_cell_request(_list); - - return r; -} - - -bool TSpreadsheet::destroy(int rec) -{ - bool ok = TRUE; - - if (rec < 0) - { - _disabled.destroy(); - _str.destroy(); - } - else - { - _disabled.destroy(rec, TRUE); // Destroy enable info - ok = _str.destroy(rec, TRUE); // Destroy line - enable_cell(_str.items(), -1); // Enable last line - } - - if (ok && mask().is_running()) - update(-1); - - return ok; -} - - -void TSpreadsheet::update(int row) -{ - if (row < 0) - { - xi_cell_request(_list); // Force updatde - xi_scroll(_list, XI_SCROLL_FIRST); - } - else - update_rec(row); -} - - -void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev) -{ - TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf); - CHECK(es, "NULL Edit sheet in xi event"); - es->list_handler(xiev); -} - - -// Certified 75% -void TSpreadsheet::list_handler(XI_EVENT *xiev) -{ - switch (xiev->type) - { - case XIE_GET_FIRST: - { - const long max = items(); - if (max > 0L) - { - long n = max * (long)xiev->v.rec_request.percent / 100L; - if (n < 0L) n = 0L; - xiev->v.rec_request.data_rec = n; - } - else - xiev->refused = TRUE; - } - break; - case XIE_GET_LAST: - xiev->v.rec_request.data_rec = items()-1; - break; - case XIE_GET_PREV: - case XIE_GET_NEXT: -{ - const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ; - if (n < 0 || n >= items()) - xiev->refused = TRUE; - else - xiev->v.rec_request.data_rec = n; -} -break; - case XIE_CELL_REQUEST: -{ - const int rec = (int)xiev->v.cell_request.rec; - const char* src = NULL; - int nm; - XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm); - const int num = xiev->v.cell_request.col_nbr; - const int cid = obj[num]->cid; - - if (cid >= FIRST_FIELD) - { - if (rec < items()) - { - const int col = cid - FIRST_FIELD; - TMask_field* f = field(cid); - src = row(rec).get(col); // Set value for cell - if (src && *src && (f->class_id() == CLASS_REAL_FIELD - || f->class_id() == CLASS_DATE_FIELD)) - { - src = f->picture_data(src, FALSE); // Get formatted string - } - if (field(cid)->has_query()) - { - xiev->v.cell_request.button = - xiev->v.cell_request.button_on_focus = TRUE; - } - if (cell_disabled(rec, col)) - xiev->v.cell_request.back_color = MASK_BACK_COLOR; - } - } else src = format("%d", rec+1); - - const int len = xiev->v.cell_request.len; - char* dst = xiev->v.cell_request.s; - if (src) - { - strncpy(dst, src, len); - if (isspace(*dst)) - { - TFixed_string d(dst); - d.ltrim(); - } - } - else - *dst = '\0'; -} -break; - case XIE_CHG_CELL: - if (!_row_dirty) -{ - notify(_cur_row, K_SPACE); - _row_dirty = TRUE; -} -break; - case XIE_BUTTON: - if (xiev->v.xi_obj->type == XIT_CELL) -{ - if (_edit_field) - { - const char* val = xi_get_text(xiev->v.xi_obj, NULL, -1); - _edit_field->set(val); // Update current cell - _check_enabled = FALSE; // Disable checks - if (!_row_dirty) notify(_cur_row, K_SPACE); - if (_edit_field->on_key(K_F9)) // Show search sheet - { - mask2str(_cur_row); // Update row - _row_dirty = TRUE; - } - set_front_window(win()); // It seems necessary to make xi_set_focus work properly - xi_set_focus(xiev->v.xi_obj); // Restore focus to cell - _check_enabled = TRUE; // Enable checks - } -} else -if (xiev->v.xi_obj->type == XIT_LIST) - insert(-1); - break; - case XIE_DBL_CELL: -{ - _check_enabled = FALSE; - - const int oldrow = _cur_row; - _cur_row = row2rec(xiev->v.xi_obj->v.cell.row); - _cur_col = xiev->v.xi_obj->v.cell.column; - - if (oldrow != _cur_row || !_row_dirty) - notify(_cur_row, K_SPACE); - - const KEY k = edit(_cur_row); - if (k == K_ENTER) - { - update_rec(_cur_row); - _row_dirty = TRUE; - } - - if (!cell_disabled(_cur_row, _cur_col)) - set_focus_cell(_cur_row, _cur_col); - _check_enabled = TRUE; -} -break; - case XIE_ON_LIST: - if (_firstfocus) // Trick to avoid the sheet to keep the focus forever ... -{ // .. it costed me two day worth of hard work! - xiev->refused = TRUE; - _firstfocus = FALSE; -} -else -mask().set_focus_win(win(), FALSE); -break; - case XIE_OFF_LIST: - break; - case XIE_ON_ROW: - if (_check_enabled) -{ - const int rec = row2rec(xiev->v.xi_obj->v.row); - if (rec < items()) - { - _cur_row = rec; - str2mask(rec); - _row_dirty = FALSE; - } - else - xiev->refused = TRUE; -} -break; - case XIE_OFF_ROW: - if (_row_dirty && _check_enabled) -{ - _check_enabled = FALSE; // Avoid recursion! - str2mask(_cur_row); // It shouldn't have to be necessary - bool ok = _mask.check_fields(); - if (ok) - { - mask2str(_cur_row); - ok = notify(_cur_row, K_ENTER); // Notify edit - } - if (!ok) - { - xiev->refused = TRUE; - } - else - { - xvt_statbar_refresh(); - } - _check_enabled = TRUE; -} -break; - case XIE_ON_CELL: - if (_check_enabled) -{ - TMask_field* f = cell2field(xiev->v.xi_obj); - const int col = (f->dlg() - FIRST_FIELD) % 100; - if (!cell_disabled(_cur_row, col)) - { - _edit_field = f; - _cur_col = xiev->v.xi_obj->v.cell.column; - } - else - { - xiev->refused = TRUE; // Refuse focus on disabled cells - } -} -break; - case XIE_OFF_CELL: - if (_edit_field && _check_enabled) -{ - _check_enabled = FALSE; - if (_row_dirty) - { - TMask_field* c = _edit_field; // Save field, it could turn out to be NULL on error - const char* nuo = c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE); - c->set(nuo); // Set new mask value - c->set_dirty(); // Get it dirty! - if (c->on_key(c->is_edit() ? K_TAB : K_SPACE) == FALSE) // Test it - { - xiev->refused = *nuo != '\0'; - } - else - { - mask2str(_cur_row); // Update sheet row - _edit_field = NULL; // Reset current field - } - } - _check_enabled = TRUE; -} -break; - case XIE_GET_PERCENT: -{ - const long rec = xiev->v.get_percent.record; - long n = items(); if (n < 1) n = 1; - xiev->v.get_percent.percent = int(rec * 100L / n); -} -break; - case XIE_CLEANUP: - break; - case XIE_XVT_EVENT: -{ - EVENT* ep = &xiev->v.xvte; - switch (ep->type) - { - case E_FOCUS: - if (ep->v.active == FALSE) - { - const bool ok = (bool)xi_move_focus(_itf); - if (!ok) - { - set_dirty(2); - xiev->refused = TRUE; - } - } - break; - case E_CHAR: - if (_edit_field) - { - const KEY k = e_char_to_key(ep); - switch(k) - { - case K_F1: - _check_enabled = FALSE; // Disable checks - _edit_field->on_key(K_F1); - set_focus_cell(_cur_row, _cur_col); - _check_enabled = TRUE; // Enable checks - break; - case K_F2: - case K_F3: - case K_F8: - case K_F9: - case K_F11: - { - _check_enabled = FALSE; // Disable checks - if (!_row_dirty) notify(_cur_row, K_SPACE); - if (_edit_field->on_key(k)) - { - mask2str(_cur_row); - _row_dirty = TRUE; - } - set_focus_cell(_cur_row, _cur_col); - _check_enabled = TRUE; // Enable checks - } - break; - case K_PREV: - case K_NEXT: - { - const bool ok = (bool)xi_move_focus(_itf); - if (ok) dispatch_e_char(parent(), k); - } - break; - case K_ESC: - { - xi_set_focus(_itf); - dispatch_e_char(parent(), K_ESC); - } - break; - - case K_CTRL+K_PREV: - xi_scroll(_list, XI_SCROLL_PGUP); - break; - case K_CTRL+K_NEXT: - xi_scroll(_list, XI_SCROLL_PGDOWN); - break; - case K_CTRL+K_HOME: - xi_scroll(_list, XI_SCROLL_FIRST); - break; - case K_CTRL+K_END: - xi_scroll(_list, XI_SCROLL_LAST); - break; - default: - break; - } - } - break; - default: - break; - } -} -break; -default: -break; -} -} - -int TSpreadsheet::add(TToken_string& t) -{ - return _str.add(t); -} - -TToken_string& TSpreadsheet::row(int n) -{ - return (TToken_string&)_str[n]; -} - -#else - -#include - -/////////////////////////////////////////////////////////// -// TSpreadsheet -/////////////////////////////////////////////////////////// - -class TSpreadsheet : public TArray_sheet -{ - TMask _mask; - SPREADSHEET_NOTIFY _notify; - bool _dirty; - - TBit_array _column_disabled; - TArray _disabled; // Array di TBit_array - -protected: - virtual bool on_key(KEY key); - KEY edit(int n, KEY tasto); - bool notify(int r, KEY k); - - TMask_field* field(short id) const; - - void mask2str(int riga); - void str2mask(int riga); - -public: - TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, - const char* head, WINDOW parent); - - TArray& rows_array() const { return data(); } - - TMask& sheet_mask() { return _mask; } - TMask& mask(); - - void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } - void set_dirty(bool spork = TRUE) { _dirty = spork;} - bool dirty() const { return _dirty;} - - void enable_column(int col, bool on); - void enable_cell(int row, int column, bool on = TRUE); - bool cell_disabled(int row, int column) const; -}; - -TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, - const char* maskname, int maskno, - const char* head, WINDOW parent) -: TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), - _mask(maskname, NO_MODE, maskno), _notify(NULL) -{} - -bool TSpreadsheet::on_key(KEY k) -{ - switch(k) - { - case K_CTRL_ENTER: - case K_ESC: - mask().send_key(k, 0); - return TRUE; - case K_ENTER: // Selezione riga per editing - if (items() < 1) k = K_INS; // Se vuoto crea riga da editare - case K_INS: - case 'A': // Aggiunge dopo - case 'I': // Aggiunge prima - { - int n = (int)selected(); - if (k != K_ENTER) - { - if (k == K_INS) n = items(); else // Aggiunge alla fine - if (k == 'A') n++; - - if (n < 0) n = 0; else - if (n > items()) n = items(); // Controlla range n - - if (notify(n, K_INS) == FALSE) // Chiede l'ok alla applicazione - return FALSE; - - insert(TToken_string(80), n); // Aggiunge una riga vuota - k = K_INS; // Inserimento in corso - } - - notify(n, K_SPACE); // Notifica inizio cambiamento - k = edit(n, k); // Edita riga selezionata o creata - if (k == K_ENTER) - notify(n, K_ENTER); // Notifica avvenuto cambiamento - - set_front_window(win()); // Aggiorna sheet a video - open(); - } - break; - case K_TAB: - case K_BTAB: - case K_SHIFT_TAB: - dispatch_e_char(get_parent(win()), k); - return TRUE; - default: - break; - } - - return TArray_sheet::on_key(k); -} - -#endif - -/////////////////////////////////////////////////////////// -// Metodi di TSpreadsheet comuni a tutte le piattaforme -/////////////////////////////////////////////////////////// - -TMask& TSpreadsheet::mask() -{ - TMask* m = (TMask*)get_app_data(parent()); - return *m; -} - - -TMask_field* TSpreadsheet::field(short id) const -{ - const int pos = _mask.id2pos(id); - if (pos < 0) return NULL; - return &_mask.fld(pos); -} - - -void TSpreadsheet::mask2str(int riga) -{ - TToken_string& r = row(riga); - r.cut(0); - for (short id = FIRST_FIELD; ; id++) - { - int pos = _mask.id2pos(id); - if (pos < 0) break; - - for(int dlg = id; pos >= 0; pos = _mask.id2pos(dlg += 100)) - { - const TMask_field& f = _mask.fld(pos); - if (f.showed()) - { - r.add(f.get()); - break; - } - } -#ifdef DBG - if (pos < 0) - { - warning_box("Non e' visibile il campo %d per lo sheet", dlg); - r.add(" "); - } -#endif - } -#if XVT_OS == XVT_OS_WIN - update_rec(riga); -#endif -} - - -// Certified 50% -void TSpreadsheet::enable_cell(int row, int column, bool on) -{ - TBit_array* ba = (TBit_array*)_disabled.objptr(row); - if (ba == NULL) - { - if (on) return; // Don't waste time and memory - ba = new TBit_array(_column_disabled); - _disabled.add(ba, row); - } - - if (column >= 0) - ba->set(column, !on); - else - { - if (on) - _disabled.destroy(row, FALSE); // Let's save some memory! - else - { -#if XVT_OS == XVT_OS_WIN - ba->set(_columns); // Force right array size -#else - ba->set(32); // Force array size -#endif - ba->set(); // Set all bits - } - } -} - - -void TSpreadsheet::enable_column(int col, bool on) -{ - const bool change = _column_disabled[col] == on; - _column_disabled.set(col, !on); -#if XVT_OS == XVT_OS_WIN - if (change) - { - int num; - XI_OBJ** columns = xi_get_member_list(_list, &num); - CHECKD(col+1 < num, "Can't enable column ", col); - XI_OBJ* column = columns[col+1]; - - long attr = xi_get_attrib(column); - if (on) attr |= XI_ATR_ENABLED; - else attr &= ~XI_ATR_ENABLED; - - xi_move_focus(_itf); // Set focus to interface - xi_set_attrib(column, attr); // Set new attributes - RCT r; xi_get_rect(column, &r); - xi_set_column_width(column, (r.right-r.left+1) / CHARX); // Force redraw - } -#endif -} - - -// Certified 99% -bool TSpreadsheet::cell_disabled(int row, int column) const -{ - TBit_array* ba = (TBit_array*)_disabled.objptr(row); - if (ba == NULL) return _column_disabled[column]; // Use default - return (*ba)[column]; -} - - -// Certified 75% -void TSpreadsheet::str2mask(int riga) -{ - if (riga == items()) - { - _mask.reset(); - mask2str(riga); - return; - } - TToken_string& r = row(riga); - r.restart(); - - TString80 val; - for (short id = FIRST_FIELD; ; id++) - { - int pos = _mask.id2pos(id); - if (pos < 0) break; - - val = r.get(); // Value to set - - int rid = id; - while (pos >= 0) - { - TMask_field& f = _mask.fld(pos); - f.set(val); - f.enable(!cell_disabled(riga, id-FIRST_FIELD)); - - if (f.active() || f.ghost()) - { - if (f.has_check()) f.check(STARTING_CHECK); - f.set_dirty(FALSE); - f.on_hit(); - } - f.set_dirty(FALSE); - - rid += 100; - pos = _mask.id2pos(rid); - } - } - - _mask.set_caption(format("Riga %d", riga+1)); -} - - -// Certified 100% -bool TSpreadsheet::notify(int n, KEY k) -{ - const bool ok = _notify ? _notify(n, k) : TRUE; - if (k == K_ENTER) - set_dirty(ok ? TRUE : 3); - return ok; -} - - -// Certified 99% -#if XVT_OS != XVT_OS_WIN -KEY TSpreadsheet::edit(int n, KEY tasto) -#else - KEY TSpreadsheet::edit(int n) -#endif -{ - const int olditems = items(); - str2mask(n); - - const KEY k = _mask.run(); - - if (k == K_ENTER) - { - mask2str(n); - } else - if (k == K_DEL) - { - const bool ok = notify(n, K_DEL); // Notifica intenzione di cancellare - if (ok) - { - destroy(n); - if (n < items()) - str2mask(n); - } - } -#if XVT_OS != XVT_OS_WIN -else - if (k == K_ESC) - { - if (tasto == K_INS) - destroy(n); - } -#endif - - return k; -} - -/////////////////////////////////////////////////////////// -// TSheet_field -/////////////////////////////////////////////////////////// - -// Certified 100% -TSheet_field::TSheet_field(TMask* m) -: TMask_field(m), _sheet(NULL) -{} - -// Certified 100% -word TSheet_field::class_id() const -{ - return CLASS_SHEET_FIELD; -} - -// Certified 100% -TSheet_field::~TSheet_field() -{ - CHECK(_sheet, "Can't delete NULL sheet"); - delete _sheet; -} - -// Certified 100% -void TSheet_field::reset() -{ - _sheet->destroy(); -} - -// Certified 100% -void TSheet_field::destroy(int r) -{ - _sheet->destroy(r); -} - - -void TSheet_field::parse_head(TScanner& scanner) -{ - _width = scanner.integer(); - _size = scanner.integer(); - if (_size == 0) _size = -1; -} - - -// Certified 100% -bool TSheet_field::parse_item(TScanner& scanner) -{ - if (scanner.key() == "IT") - { - _head.add(scanner.string()); - return TRUE; - } - return TMask_field::parse_item(scanner); -} - -// Certified 100% -void TSheet_field::create(WINDOW parent) -{ - const TMask& m = mask(); - _sheet = new TSpreadsheet(_x, _y, _width, _size, m.source_file(), m.sheets(), - _head, parent); - - _win = _sheet->win(); - enable_window(_win, enabled()); - show_window(_win, showed()); -} - - -// Certified 100% -TArray& TSheet_field::rows_array() const -{ - return _sheet->rows_array(); -} - - -// Certified 100% -// Ritorna l'indice della prima riga vuota dello sheet -int TSheet_field::first_empty() const -{ - const int max = _sheet->items(); - for (int n = 0; n < max; n++) - if (_sheet->row(n).empty_items()) - break; - return n; -} - - -TToken_string& TSheet_field::row(int n) -{ - const int max = _sheet->items(); - if (n < 0 || n >= max) - { - if (n < 0) n = first_empty(); - if (n >= max) n = _sheet->add(TToken_string(80)); - } - return _sheet->row(n); -} - - -void TSheet_field::force_update(int r) -{ -#if XVT_OS == XVT_OS_WIN - _sheet->update(r); -#else - _sheet->open(); -#endif -} - - -int TSheet_field::items() const -{ - return (int)_sheet->items(); -} - - -int TSheet_field::selected() const -{ - return _sheet->selected(); -} - -void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) -{ - _sheet->set_notify(n); -} - - -void TSheet_field::enable_column(int column, bool on) -{ - _sheet->enable_column(column, on); -} - - -void TSheet_field::enable_cell(int row, int column, bool on) -{ - _sheet->enable_cell(row, column, on); -} - - -TMask& TSheet_field::sheet_mask() const -{ - return _sheet->sheet_mask(); -} - -bool TSheet_field::on_hit() -{ - if (!mask().is_running()) - { - force_update(); - _sheet->set_dirty(FALSE); - } - return TRUE; -} - -bool TSheet_field::on_key(KEY k) -{ - if (k == K_TAB) - { - const bool spork = _sheet->dirty(); - if (spork != FALSE && spork != TRUE) - return FALSE; - set_dirty(spork); - } - - return TMask_field::on_key(k); -} - -void TSheet_field::exchange(bool show_value, const real& nuo) -{ - TMask& m = sheet_mask(); - - const real& vec = mask().exchange(); - - if (vec != nuo) - { - TBit_array valuta(32); - int i = 0; - for (int f = FIRST_FIELD; ;f++, i++) - { - const int pos = m.id2pos(f); - if (pos < 0) break; - if (m.fld(pos).class_id() == CLASS_REAL_FIELD) - { - if (m.fld(pos).exchangeable()) - valuta.set(i); - } - } - - for (int riga = 0; riga < items(); riga++) - { - TToken_string& r = row(riga); - for (const char* s = r.get(i = 0); s; s = r.get(++i)) - if (*s > ' ' && valuta[i]) - { - real v(s); - v *= nuo; - v /= vec; - v.round(); - r.add(v.string(), i); - } - } - } - - m.set_exchange(show_value, nuo); - - if (mask().is_running()) - force_update(); -} +#include +#include +#include +#include + +const short FIRST_FIELD = 101; + +#if XVT_OS == XVT_OS_WIN + +#include +#include + +/////////////////////////////////////////////////////////// +// TSpreadsheet +/////////////////////////////////////////////////////////// + +#define K_PLUS '+' + +class TSpreadsheet : public TWindow +{ + enum { ITF_CID = 0, LIST_CID = 1 }; + + TArray _str; // Array di TToken_strings + TBit_array _column_disabled; + TArray _disabled; // Array di TBit_array + + TMask _mask; + int _columns; + bool _dirty; + bool _firstfocus; + + XI_OBJ *_list, *_itf; + + SPREADSHEET_NOTIFY _notify; + + TMask_field* _edit_field; // Current edit field + int _cur_row, _cur_col; // Current cell + bool _row_dirty; // Current row changed + bool _check_enabled; // Perform OFF_ROW checks + + static void xiev_handler(XI_OBJ *itf, XI_EVENT *xiev); + void init(); + +protected: + void list_handler(XI_EVENT *xiev); + + TMask_field* cell2field(const XI_OBJ* cell) const; + void update_rec(int rec); + void set_focus_cell(int riga, int colonna); + + void mask2str(int n); + void str2mask(int n); + KEY edit(int n); + + TMask_field* field(short id) const; + + int rec2row(int rec); + int row2rec(int row); + + bool notify(int r, KEY k); + +public: + void update(int row); + + TToken_string& row(int n); + TArray& rows_array() const { return (TArray&)_str; } + int add(TToken_string&); + int insert(int rec); + bool destroy(int rec = -1); + + void enable_column(int col, bool on = TRUE); + void enable_cell(int row, int column, bool on = TRUE); + bool cell_disabled(int row, int column) const; + + TMask& sheet_mask() { return _mask; } + TMask& mask(); + + int items() const { return _str.items(); } + int selected() const { return _cur_row; } + int columns() const { return _columns; } + bool dirty() const { return _dirty; } + void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } + + void set_dirty(bool spork = TRUE) { _dirty = spork; } + + TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, + const char* head, WINDOW parent); + virtual ~TSpreadsheet(); +}; + +// Certified 100% +void TSpreadsheet::init() +{ + static bool first = TRUE; + if (!first) return; + + DRAW_CTOOLS ct; + win_get_draw_ctools(TASK_WIN, &ct); + xi_set_font(&ct.font); + + xi_init(); + xi_set_pref(XI_PREF_3D_LOOK, TRUE); + // xi_set_pref(XI_PREF_COLOR_LIGHT, COLOR_CYAN); + // xi_set_pref(XI_PREF_COLOR_CTRL, MASK_BACK_COLOR); + // xi_set_pref(XI_PREF_COLOR_DARK, COLOR_GRAY); + + first = FALSE; +} + + +TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, + const char* maskname, int maskno, + const char* head, WINDOW parent) +: _mask(maskname, NO_MODE, maskno), _notify(NULL), _edit_field(NULL), _cur_row(0), _cur_col(0), + _row_dirty(FALSE), _check_enabled(TRUE), _firstfocus(TRUE) +{ + const int NUMBER_WIDTH = 3; + const int MAX_COL = 32; + int m_width[MAX_COL], v_width[MAX_COL]; + int fixed_columns = 1; // Number of fixed columns + + init(); + + // Calcolo larghezza massima tabella + + TToken_string header(head); + TToken_string new_header(256); + int i = 0, tot_width = NUMBER_WIDTH+1; + int f_width = tot_width<<1; // Stima larghezza colonne fisse + int max_width = f_width; // Stima larghezza della colonna piu' grande + + for (const char* h = header.get(); h; h = header.get(), i++) + { + CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i); + + const int cid = FIRST_FIELD+i; // Column & Field ID + const TMask_field* f = field(cid); // Field on mask + CHECKD(f, "The spreadsheet mask needs ALSO field ", cid); + + TString80 testa(h); + const int at = testa.find('@'); + int m, v; + if (at >= 0) + { + const TString& wi = testa.mid(at+1); + m = atoi(wi); + if (wi[wi.len()-1] == 'F') + { + fixed_columns++; + f_width += m+1; + } + testa.cut(at); + v = max(at, m+(f->has_query() ? 1 : 0)); + } + else + { + m = testa.len(); + v = m+(f->has_query() ? 1 : 0); + } + + m_width[i] = m+1; // m = number of allowed chars + v_width[i] = v+1; // v = width of column + if (v >= max_width) max_width = v+1; + + tot_width += v_width[i]; + + new_header.add(testa); + } + _columns = i; + + if (x < 0) x = 0; + if (y < 0) y = 0; + if (dx == 0) + { + dx = tot_width; + if (dx > 76) dx = -x; + } + + RCT rct = resize_rect(x, y, dx, dy, WO_TE, parent); + rct.bottom -= 12; + rct.right -= 28; + + if ((f_width+max_width)*CHARX > rct.right) + fixed_columns = 1; + + XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID, + (XI_EVENT_HANDLER)xiev_handler, &rct, (char*)maskname, + PTR_LONG(this)); + itfdef->v.itf->automatic_back_color = FALSE; + itfdef->v.itf->back_color = MASK_BACK_COLOR; + + XI_OBJ_DEF* listdef = xi_add_list_def(itfdef, LIST_CID, + 0, 0, rct.bottom-rct.top, + XI_ATR_ENABLED | XI_ATR_VISIBLE, + NORMAL_COLOR, NORMAL_BACK_COLOR, // normal + NORMAL_COLOR, DISABLED_BACK_COLOR, // disabled + COLOR_RED, // active + LIST_CID); + listdef->v.list->sizable_columns = TRUE; + listdef->v.list->movable_columns = TRUE; + listdef->v.list->scroll_bar = TRUE; + listdef->v.list->scroll_bar_button = TRUE; + listdef->v.list->fixed_columns = fixed_columns; + listdef->v.list->width = rct.right-rct.left; + listdef->v.list->min_cell_height = CHARY; + listdef->v.list->min_heading_height = CHARY; + listdef->v.list->white_space_color = COLOR_GRAY; + + XI_OBJ_DEF* coldef = xi_add_column_def(listdef, 0, + XI_ATR_RJUST, 0, NUMBER_WIDTH, NUMBER_WIDTH, ""); + coldef->v.column->heading_platform = TRUE; + coldef->v.column->column_platform = TRUE; + coldef->v.column->center_heading = TRUE; + + for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++) + { + const int cid = FIRST_FIELD+i; // Column & Field ID + const TMask_field* f = field(cid); // Field on mask + + long flags = XI_ATR_EDITMENU | XI_ATR_AUTOSCROLL; + if (f->class_id() == CLASS_REAL_FIELD) flags |= XI_ATR_RJUST; + if (f->active()) flags |= XI_ATR_ENABLED | XI_ATR_FOCUSBORDER | XI_ATR_AUTOSELECT; + else _column_disabled.set(i); + + coldef = xi_add_column_def(listdef, cid, flags, cid, v_width[i], m_width[i], (char*)h); + coldef->v.column->heading_platform = TRUE; + coldef->v.column->center_heading = TRUE; + } + + RCT itfrct; + xi_get_def_rect(itfdef, &itfrct); + offset_rect(&itfrct, rct.left, rct.top); + itfrct.bottom++; + + WINDOW win = create_window(W_NO_BORDER, &itfrct, "", 0, parent, + 0, EM_ALL, (EVENT_HANDLER)xi_event, 0L); + CHECK(win, "Can't create a window for the spreadsheet"); + + set_win(win); // Set TWindow::_win + itfdef->v.itf->win = win; // Link interface to win + + xi_create(NULL, itfdef); // Create the whole thing! + xi_tree_free(itfdef); // Free definitions + + _itf = xi_get_itf(win); // Store useful references for later use + _list = xi_get_obj(_itf, LIST_CID); +} + +TSpreadsheet::~TSpreadsheet() +{ + set_win(NULL_WIN); +} + + + +// Converts a row number in the correspondig record number +int TSpreadsheet::row2rec(int row) +{ + int rows; + const long* rec = xi_get_list_info(_list, &rows); + +#ifdef DBG + if (row < 0 || row >= rows) + { + error_box("Line %d is not visible", row); + return 0L; + } +#endif + + return (int)rec[row]; +} + + +// Converts a row number in the correspondig record number +int TSpreadsheet::rec2row(int record) +{ + int rows; + const long* rec = xi_get_list_info(_list, &rows); + int r = int(record - rec[0]); + if (r < 0 || r >= rows) + r = -1; + + return r; +} + +// Retrieves the corresponding field of the mask from a spredsheet cell +TMask_field* TSpreadsheet::cell2field(const XI_OBJ* cell) const +{ + const int pos = cell->v.cell.column; + + int num; + XI_OBJ** column = xi_get_member_list(_list, &num); + + TMask_field* good = NULL; + for (short id = column[pos]->cid; ; id += 100) + { + TMask_field* f = field(id); + if (f == NULL) break; + good = f; // We've found a field with the proper ID ... + if (f->active()) break; // ... and it's active: end of search + } + + return good; +} + +void TSpreadsheet::update_rec(int rec) +{ + const int riga = rec2row(rec); + if (riga >= 0) + { + XI_OBJ row; + XI_MAKE_ROW(&row, _list, riga); + xi_cell_request(&row); // Update internal values + xi_set_row_height(&row, CHARY+1); // Force row updating + } +} + +void TSpreadsheet::set_focus_cell(int riga, int colonna) +{ + set_front_window(win()); // It seems necessary to make xi_set_focus work properly + XI_OBJ cell; + XI_MAKE_CELL(&cell, _list, rec2row(riga), colonna); + xi_set_focus(&cell); +} + + +int TSpreadsheet::insert(int rec) +{ + const bool ok = notify(rec, K_INS); + if (!ok) return -1; + + TToken_string s; // Empty row + const int r = _str.insert(s, rec); + _disabled.insert(NULL, rec); + + xi_insert_row(_list, INT_MAX); + xi_cell_request(_list); + + return r; +} + + +bool TSpreadsheet::destroy(int rec) +{ + bool ok = TRUE; + + if (rec < 0) + { + _disabled.destroy(); + _str.destroy(); + } + else + { + _disabled.destroy(rec, TRUE); // Destroy enable info + ok = _str.destroy(rec, TRUE); // Destroy line + enable_cell(_str.items(), -1); // Enable last line + } + + if (ok && mask().is_running()) + update(-1); + + return ok; +} + + +void TSpreadsheet::update(int row) +{ + if (row < 0) + { + xi_cell_request(_list); // Force updatde + xi_scroll(_list, XI_SCROLL_FIRST); + } + else + update_rec(row); +} + + +void TSpreadsheet::xiev_handler(XI_OBJ *itf, XI_EVENT *xiev) +{ + TSpreadsheet* es = (TSpreadsheet*)xi_get_app_data(itf); + CHECK(es, "NULL Edit sheet in xi event"); + es->list_handler(xiev); +} + + +// Certified 75% +void TSpreadsheet::list_handler(XI_EVENT *xiev) +{ + switch (xiev->type) + { + case XIE_GET_FIRST: + { + const long max = items(); + if (max > 0L) + { + long n = max * (long)xiev->v.rec_request.percent / 100L; + if (n < 0L) n = 0L; + xiev->v.rec_request.data_rec = n; + } + else + xiev->refused = TRUE; + } + break; + case XIE_GET_LAST: + xiev->v.rec_request.data_rec = items()-1; + break; + case XIE_GET_PREV: + case XIE_GET_NEXT: +{ + const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ; + if (n < 0 || n >= items()) + xiev->refused = TRUE; + else + xiev->v.rec_request.data_rec = n; +} +break; + case XIE_CELL_REQUEST: +{ + const int rec = (int)xiev->v.cell_request.rec; + const char* src = NULL; + int nm; + XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm); + const int num = xiev->v.cell_request.col_nbr; + const int cid = obj[num]->cid; + + if (cid >= FIRST_FIELD) + { + if (rec < items()) + { + const int col = cid - FIRST_FIELD; + TMask_field* f = field(cid); + src = row(rec).get(col); // Set value for cell + if (src && *src && (f->class_id() == CLASS_REAL_FIELD + || f->class_id() == CLASS_DATE_FIELD)) + { + src = f->picture_data(src, FALSE); // Get formatted string + } + if (field(cid)->has_query()) + { + xiev->v.cell_request.button = + xiev->v.cell_request.button_on_focus = TRUE; + } + if (cell_disabled(rec, col)) + xiev->v.cell_request.back_color = MASK_BACK_COLOR; + } + } else src = format("%d", rec+1); + + const int len = xiev->v.cell_request.len; + char* dst = xiev->v.cell_request.s; + if (src) + { + strncpy(dst, src, len); + if (isspace(*dst)) + { + TFixed_string d(dst); + d.ltrim(); + } + } + else + *dst = '\0'; +} +break; + case XIE_CHG_CELL: + if (!_row_dirty) +{ + notify(_cur_row, K_SPACE); + _row_dirty = TRUE; +} +break; + case XIE_BUTTON: + if (xiev->v.xi_obj->type == XIT_CELL) +{ + if (_edit_field) + { + const char* val = xi_get_text(xiev->v.xi_obj, NULL, -1); + _edit_field->set(val); // Update current cell + _check_enabled = FALSE; // Disable checks + if (!_row_dirty) notify(_cur_row, K_SPACE); + if (_edit_field->on_key(K_F9)) // Show search sheet + { + mask2str(_cur_row); // Update row + _row_dirty = TRUE; + } + set_front_window(win()); // It seems necessary to make xi_set_focus work properly + xi_set_focus(xiev->v.xi_obj); // Restore focus to cell + _check_enabled = TRUE; // Enable checks + } +} else +if (xiev->v.xi_obj->type == XIT_LIST) + insert(-1); + break; + case XIE_DBL_CELL: +{ + _check_enabled = FALSE; + + const int oldrow = _cur_row; + _cur_row = row2rec(xiev->v.xi_obj->v.cell.row); + _cur_col = xiev->v.xi_obj->v.cell.column; + + if (oldrow != _cur_row || !_row_dirty) + notify(_cur_row, K_SPACE); + + const KEY k = edit(_cur_row); + if (k == K_ENTER) + { + update_rec(_cur_row); + _row_dirty = TRUE; + } + + if (!cell_disabled(_cur_row, _cur_col)) + set_focus_cell(_cur_row, _cur_col); + _check_enabled = TRUE; +} +break; + case XIE_ON_LIST: + if (_firstfocus) // Trick to avoid the sheet to keep the focus forever ... +{ // .. it costed me two day worth of hard work! + xiev->refused = TRUE; + _firstfocus = FALSE; +} +else +mask().set_focus_win(win(), FALSE); +break; + case XIE_OFF_LIST: + break; + case XIE_ON_ROW: + if (_check_enabled) +{ + const int rec = row2rec(xiev->v.xi_obj->v.row); + if (rec < items()) + { + _cur_row = rec; + str2mask(rec); + _row_dirty = FALSE; + } + else + xiev->refused = TRUE; +} +break; + case XIE_OFF_ROW: + if (_row_dirty && _check_enabled) +{ + _check_enabled = FALSE; // Avoid recursion! + str2mask(_cur_row); // It shouldn't have to be necessary + bool ok = _mask.check_fields(); + if (ok) + { + mask2str(_cur_row); + ok = notify(_cur_row, K_ENTER); // Notify edit + } + if (!ok) + { + xiev->refused = TRUE; + } + else + { + xvt_statbar_refresh(); + } + _check_enabled = TRUE; +} +break; + case XIE_ON_CELL: + if (_check_enabled) +{ + TMask_field* f = cell2field(xiev->v.xi_obj); + const int col = (f->dlg() - FIRST_FIELD) % 100; + if (!cell_disabled(_cur_row, col)) + { + _edit_field = f; + _cur_col = xiev->v.xi_obj->v.cell.column; + } + else + { + xiev->refused = TRUE; // Refuse focus on disabled cells + } +} +break; + case XIE_OFF_CELL: + if (_edit_field && _check_enabled) +{ + _check_enabled = FALSE; + if (_row_dirty) + { + TMask_field* c = _edit_field; // Save field, it could turn out to be NULL on error + const char* nuo = c->picture_data(xi_get_text(xiev->v.xi_obj, NULL, -1), TRUE); + c->set(nuo); // Set new mask value + c->set_dirty(); // Get it dirty! + if (c->on_key(c->is_edit() ? K_TAB : K_SPACE) == FALSE) // Test it + { + xiev->refused = *nuo != '\0'; + } + else + { + mask2str(_cur_row); // Update sheet row + _edit_field = NULL; // Reset current field + } + } + _check_enabled = TRUE; +} +break; + case XIE_GET_PERCENT: +{ + const long rec = xiev->v.get_percent.record; + long n = items(); if (n < 1) n = 1; + xiev->v.get_percent.percent = int(rec * 100L / n); +} +break; + case XIE_CLEANUP: + break; + case XIE_XVT_EVENT: +{ + EVENT* ep = &xiev->v.xvte; + switch (ep->type) + { + case E_FOCUS: + if (ep->v.active == FALSE) + { + const bool ok = (bool)xi_move_focus(_itf); + if (!ok) + { + set_dirty(2); + xiev->refused = TRUE; + } + } + break; + case E_CHAR: + if (_edit_field) + { + const KEY k = e_char_to_key(ep); + switch(k) + { + case K_F1: + _check_enabled = FALSE; // Disable checks + _edit_field->on_key(K_F1); + set_focus_cell(_cur_row, _cur_col); + _check_enabled = TRUE; // Enable checks + break; + case K_F2: + case K_F3: + case K_F8: + case K_F9: + case K_F11: + { + _check_enabled = FALSE; // Disable checks + if (!_row_dirty) notify(_cur_row, K_SPACE); + if (_edit_field->on_key(k)) + { + mask2str(_cur_row); + _row_dirty = TRUE; + } + set_focus_cell(_cur_row, _cur_col); + _check_enabled = TRUE; // Enable checks + } + break; + case K_PREV: + case K_NEXT: + { + const bool ok = (bool)xi_move_focus(_itf); + if (ok) dispatch_e_char(parent(), k); + } + break; + case K_ESC: + { + xi_set_focus(_itf); + dispatch_e_char(parent(), K_ESC); + } + break; + + case K_CTRL+K_PREV: + xi_scroll(_list, XI_SCROLL_PGUP); + break; + case K_CTRL+K_NEXT: + xi_scroll(_list, XI_SCROLL_PGDOWN); + break; + case K_CTRL+K_HOME: + xi_scroll(_list, XI_SCROLL_FIRST); + break; + case K_CTRL+K_END: + xi_scroll(_list, XI_SCROLL_LAST); + break; + default: + break; + } + } + break; + default: + break; + } +} +break; +default: +break; +} +} + +int TSpreadsheet::add(TToken_string& t) +{ + return _str.add(t); +} + +TToken_string& TSpreadsheet::row(int n) +{ + return (TToken_string&)_str[n]; +} + +#else + +#include + +/////////////////////////////////////////////////////////// +// TSpreadsheet +/////////////////////////////////////////////////////////// + +class TSpreadsheet : public TArray_sheet +{ + TMask _mask; + SPREADSHEET_NOTIFY _notify; + bool _dirty; + + TBit_array _column_disabled; + TArray _disabled; // Array di TBit_array + +protected: + virtual bool on_key(KEY key); + KEY edit(int n, KEY tasto); + bool notify(int r, KEY k); + + TMask_field* field(short id) const; + + void mask2str(int riga); + void str2mask(int riga); + +public: + TSpreadsheet(short x, short y, short dx, short dy, const char* maskname, int maskno, + const char* head, WINDOW parent); + + TArray& rows_array() const { return data(); } + + TMask& sheet_mask() { return _mask; } + TMask& mask(); + + void set_notify(SPREADSHEET_NOTIFY n) { _notify = n; } + void set_dirty(bool spork = TRUE) { _dirty = spork;} + bool dirty() const { return _dirty;} + + void enable_column(int col, bool on); + void enable_cell(int row, int column, bool on = TRUE); + bool cell_disabled(int row, int column) const; +}; + +TSpreadsheet::TSpreadsheet(short x, short y, short dx, short dy, + const char* maskname, int maskno, + const char* head, WINDOW parent) +: TArray_sheet(x, y, dx, dy, maskname, head, 0, parent), + _mask(maskname, NO_MODE, maskno), _notify(NULL) +{} + +bool TSpreadsheet::on_key(KEY k) +{ + switch(k) + { + case K_CTRL_ENTER: + case K_ESC: + mask().send_key(k, 0); + return TRUE; + case K_ENTER: // Selezione riga per editing + if (items() < 1) k = K_INS; // Se vuoto crea riga da editare + case K_INS: + case 'A': // Aggiunge dopo + case 'I': // Aggiunge prima + { + int n = (int)selected(); + if (k != K_ENTER) + { + if (k == K_INS) n = items(); else // Aggiunge alla fine + if (k == 'A') n++; + + if (n < 0) n = 0; else + if (n > items()) n = items(); // Controlla range n + + if (notify(n, K_INS) == FALSE) // Chiede l'ok alla applicazione + return FALSE; + + insert(TToken_string(80), n); // Aggiunge una riga vuota + k = K_INS; // Inserimento in corso + } + + notify(n, K_SPACE); // Notifica inizio cambiamento + k = edit(n, k); // Edita riga selezionata o creata + if (k == K_ENTER) + notify(n, K_ENTER); // Notifica avvenuto cambiamento + + set_front_window(win()); // Aggiorna sheet a video + open(); + } + break; + case K_TAB: + case K_BTAB: + case K_SHIFT_TAB: + dispatch_e_char(get_parent(win()), k); + return TRUE; + default: + break; + } + + return TArray_sheet::on_key(k); +} + +#endif + +/////////////////////////////////////////////////////////// +// Metodi di TSpreadsheet comuni a tutte le piattaforme +/////////////////////////////////////////////////////////// + +TMask& TSpreadsheet::mask() +{ + TMask* m = (TMask*)get_app_data(parent()); + return *m; +} + + +TMask_field* TSpreadsheet::field(short id) const +{ + const int pos = _mask.id2pos(id); + if (pos < 0) return NULL; + return &_mask.fld(pos); +} + + +void TSpreadsheet::mask2str(int riga) +{ + TToken_string& r = row(riga); + r.cut(0); + for (short id = FIRST_FIELD; ; id++) + { + int pos = _mask.id2pos(id); + if (pos < 0) break; + + for(int dlg = id; pos >= 0; pos = _mask.id2pos(dlg += 100)) + { + const TMask_field& f = _mask.fld(pos); + if (f.showed()) + { + r.add(f.get()); + break; + } + } +#ifdef DBG + if (pos < 0) + { + warning_box("Non e' visibile il campo %d per lo sheet", dlg); + r.add(" "); + } +#endif + } +#if XVT_OS == XVT_OS_WIN + update_rec(riga); +#endif +} + + +// Certified 50% +void TSpreadsheet::enable_cell(int row, int column, bool on) +{ + TBit_array* ba = (TBit_array*)_disabled.objptr(row); + if (ba == NULL) + { + if (on) return; // Don't waste time and memory + ba = new TBit_array(_column_disabled); + _disabled.add(ba, row); + } + + if (column >= 0) + ba->set(column, !on); + else + { + if (on) + _disabled.destroy(row, FALSE); // Let's save some memory! + else + { +#if XVT_OS == XVT_OS_WIN + ba->set(_columns); // Force right array size +#else + ba->set(32); // Force array size +#endif + ba->set(); // Set all bits + } + } +} + + +void TSpreadsheet::enable_column(int col, bool on) +{ + const bool change = _column_disabled[col] == on; + _column_disabled.set(col, !on); +#if XVT_OS == XVT_OS_WIN + if (change) + { + int num; + XI_OBJ** columns = xi_get_member_list(_list, &num); + CHECKD(col+1 < num, "Can't enable column ", col); + XI_OBJ* column = columns[col+1]; + + long attr = xi_get_attrib(column); + if (on) attr |= XI_ATR_ENABLED; + else attr &= ~XI_ATR_ENABLED; + + xi_move_focus(_itf); // Set focus to interface + xi_set_attrib(column, attr); // Set new attributes + RCT r; xi_get_rect(column, &r); + xi_set_column_width(column, (r.right-r.left+1) / CHARX); // Force redraw + } +#endif +} + + +// Certified 99% +bool TSpreadsheet::cell_disabled(int row, int column) const +{ + TBit_array* ba = (TBit_array*)_disabled.objptr(row); + if (ba == NULL) return _column_disabled[column]; // Use default + return (*ba)[column]; +} + + +// Certified 75% +void TSpreadsheet::str2mask(int riga) +{ + if (riga == items()) + { + _mask.reset(); + mask2str(riga); + return; + } + TToken_string& r = row(riga); + r.restart(); + + TString80 val; + for (short id = FIRST_FIELD; ; id++) + { + int pos = _mask.id2pos(id); + if (pos < 0) break; + + val = r.get(); // Value to set + + int rid = id; + while (pos >= 0) + { + TMask_field& f = _mask.fld(pos); + f.set(val); + f.enable(!cell_disabled(riga, id-FIRST_FIELD)); + + if (f.active() || f.ghost()) + { + if (f.has_check()) f.check(STARTING_CHECK); + f.set_dirty(FALSE); + f.on_hit(); + } + f.set_dirty(FALSE); + + rid += 100; + pos = _mask.id2pos(rid); + } + } + + _mask.set_caption(format("Riga %d", riga+1)); +} + + +// Certified 100% +bool TSpreadsheet::notify(int n, KEY k) +{ + const bool ok = _notify ? _notify(n, k) : TRUE; + if (k == K_ENTER) + set_dirty(ok ? TRUE : 3); + return ok; +} + + +// Certified 99% +#if XVT_OS != XVT_OS_WIN +KEY TSpreadsheet::edit(int n, KEY tasto) +#else + KEY TSpreadsheet::edit(int n) +#endif +{ + const int olditems = items(); + str2mask(n); + + const KEY k = _mask.run(); + + if (k == K_ENTER) + { + mask2str(n); + } else + if (k == K_DEL) + { + const bool ok = notify(n, K_DEL); // Notifica intenzione di cancellare + if (ok) + { + destroy(n); + if (n < items()) + str2mask(n); + } + } +#if XVT_OS != XVT_OS_WIN +else + if (k == K_ESC) + { + if (tasto == K_INS) + destroy(n); + } +#endif + + return k; +} + +/////////////////////////////////////////////////////////// +// TSheet_field +/////////////////////////////////////////////////////////// + +// Certified 100% +TSheet_field::TSheet_field(TMask* m) +: TMask_field(m), _sheet(NULL) +{} + +// Certified 100% +word TSheet_field::class_id() const +{ + return CLASS_SHEET_FIELD; +} + +// Certified 100% +TSheet_field::~TSheet_field() +{ + CHECK(_sheet, "Can't delete NULL sheet"); + delete _sheet; +} + +// Certified 100% +void TSheet_field::reset() +{ + _sheet->destroy(); +} + +// Certified 100% +void TSheet_field::destroy(int r) +{ + _sheet->destroy(r); +} + + +void TSheet_field::parse_head(TScanner& scanner) +{ + _width = scanner.integer(); + _size = scanner.integer(); + if (_size == 0) _size = -1; +} + + +// Certified 100% +bool TSheet_field::parse_item(TScanner& scanner) +{ + if (scanner.key() == "IT") + { + _head.add(scanner.string()); + return TRUE; + } + return TMask_field::parse_item(scanner); +} + +// Certified 100% +void TSheet_field::create(WINDOW parent) +{ + const TMask& m = mask(); + _sheet = new TSpreadsheet(_x, _y, _width, _size, m.source_file(), m.sheets(), + _head, parent); + + _win = _sheet->win(); + enable_window(_win, enabled()); + show_window(_win, showed()); +} + + +// Certified 100% +TArray& TSheet_field::rows_array() const +{ + return _sheet->rows_array(); +} + + +// Certified 100% +// Ritorna l'indice della prima riga vuota dello sheet +int TSheet_field::first_empty() const +{ + const int max = _sheet->items(); + for (int n = 0; n < max; n++) + if (_sheet->row(n).empty_items()) + break; + return n; +} + + +TToken_string& TSheet_field::row(int n) +{ + const int max = _sheet->items(); + if (n < 0 || n >= max) + { + if (n < 0) n = first_empty(); + if (n >= max) n = _sheet->add(TToken_string(80)); + } + return _sheet->row(n); +} + + +void TSheet_field::force_update(int r) +{ +#if XVT_OS == XVT_OS_WIN + _sheet->update(r); +#else + _sheet->open(); +#endif +} + + +int TSheet_field::items() const +{ + return (int)_sheet->items(); +} + + +int TSheet_field::selected() const +{ + return _sheet->selected(); +} + +void TSheet_field::set_notify(SPREADSHEET_NOTIFY n) +{ + _sheet->set_notify(n); +} + + +void TSheet_field::enable_column(int column, bool on) +{ + _sheet->enable_column(column, on); +} + + +void TSheet_field::enable_cell(int row, int column, bool on) +{ + _sheet->enable_cell(row, column, on); +} + +bool TSheet_field::cell_disabled(int row, int column) const +{ + return _sheet->cell_disabled(row, column); +} + + +TMask& TSheet_field::sheet_mask() const +{ + return _sheet->sheet_mask(); +} + +bool TSheet_field::on_hit() +{ + if (!mask().is_running()) + { + force_update(); + _sheet->set_dirty(FALSE); + } + return TRUE; +} + +bool TSheet_field::on_key(KEY k) +{ + if (k == K_TAB) + { + const bool spork = _sheet->dirty(); + if (spork != FALSE && spork != TRUE) + return FALSE; + set_dirty(spork); + } + + return TMask_field::on_key(k); +} + +void TSheet_field::exchange(bool show_value, const real& nuo) +{ + TMask& m = sheet_mask(); + + const real& vec = mask().exchange(); + + if (vec != nuo) + { + TBit_array valuta(32); + int i = 0; + for (int f = FIRST_FIELD; ;f++, i++) + { + const int pos = m.id2pos(f); + if (pos < 0) break; + if (m.fld(pos).class_id() == CLASS_REAL_FIELD) + { + if (m.fld(pos).exchangeable()) + valuta.set(i); + } + } + + for (int riga = 0; riga < items(); riga++) + { + TToken_string& r = row(riga); + for (const char* s = r.get(i = 0); s; s = r.get(++i)) + if (*s > ' ' && valuta[i]) + { + real v(s); + v *= nuo; + v /= vec; + v.round(); + r.add(v.string(), i); + } + } + } + + m.set_exchange(show_value, nuo); + + if (mask().is_running()) + force_update(); +} diff --git a/include/msksheet.h b/include/msksheet.h index 46de41b3f..4a9e4c023 100755 --- a/include/msksheet.h +++ b/include/msksheet.h @@ -1,50 +1,51 @@ -#ifndef __MSKSHEET_H -#define __MSKSHEET_H - -#ifndef __MASK_H -#include -#endif - - -class TSpreadsheet; -typedef bool (*SPREADSHEET_NOTIFY)(int r, KEY k); - - -class TSheet_field : public TMask_field -{ - TSpreadsheet* _sheet; - TToken_string _head; - -protected: - virtual word class_id() const; - virtual bool on_hit(); - virtual bool on_key(KEY k); - - virtual void parse_head(TScanner& scanner); - virtual bool parse_item(TScanner& scanner); - virtual void create(WINDOW parent); - - virtual void exchange(bool show_value, const real& n); - -public: - TToken_string& row(int n); // Get/Create a new row - TArray& rows_array() const; // Get all rows - int first_empty() const; // First empty row - int items() const; // Number of rows - int selected() const; // Number of current row - - virtual void reset(); - void destroy(int r = -1); // Destroy row - void force_update(int r = -1);// Update data/screen - - TMask& sheet_mask() const; - void set_notify(SPREADSHEET_NOTIFY n); - void enable_column(int col, bool on = TRUE); - void enable_cell(int row, int column, bool on = TRUE); - void disable_cell(int row, int column) { enable_cell(row, column, FALSE); } - - TSheet_field(TMask* m); - virtual ~TSheet_field(); -}; - -#endif +#ifndef __MSKSHEET_H +#define __MSKSHEET_H + +#ifndef __MASK_H +#include +#endif + + +class TSpreadsheet; +typedef bool (*SPREADSHEET_NOTIFY)(int r, KEY k); + + +class TSheet_field : public TMask_field +{ + TSpreadsheet* _sheet; + TToken_string _head; + +protected: + virtual word class_id() const; + virtual bool on_hit(); + virtual bool on_key(KEY k); + + virtual void parse_head(TScanner& scanner); + virtual bool parse_item(TScanner& scanner); + virtual void create(WINDOW parent); + + virtual void exchange(bool show_value, const real& n); + +public: + TToken_string& row(int n); // Get/Create a new row + TArray& rows_array() const; // Get all rows + int first_empty() const; // First empty row + int items() const; // Number of rows + int selected() const; // Number of current row + + virtual void reset(); + void destroy(int r = -1); // Destroy row + void force_update(int r = -1);// Update data/screen + + TMask& sheet_mask() const; + void set_notify(SPREADSHEET_NOTIFY n); + void enable_column(int col, bool on = TRUE); + void enable_cell(int row, int column, bool on = TRUE); + void disable_cell(int row, int column) { enable_cell(row, column, FALSE); } + bool cell_disabled(int row, int column) const; + + TSheet_field(TMask* m); + virtual ~TSheet_field(); +}; + +#endif diff --git a/include/printer.cpp b/include/printer.cpp index dbe73f019..0042c1b42 100755 --- a/include/printer.cpp +++ b/include/printer.cpp @@ -1,1528 +1,1528 @@ -#include -#include -#include - -#if XVT_OS==XVT_OS_SCOUNIX -#include -#include -#include -#else -#include -#endif - -#define STYLE_NUM 4 - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -struct PrDesc -{ - TTextfile *_txt; - PRINT_RCD *_prcd; - bool _graphics; - int _formlen; - int _charsize; - int _lines_per_inch; -} -PrintWhat; - -#define LINES_PER_INCH (6.0) - -#if XVT_OS == XVT_OS_WIN - -#include - -void TPrinter::_get_windows_printer_names (TToken_string & t) -{ - char *buf = new char[4096]; // ammazzao' - - GetProfileString ("devices", NULL, "", buf, 4096); - - for (int i = 0; i < 4095; i++) - { - if (buf[i] == '\0' && buf[i + 1] == '\0') - break; - if (buf[i] == '\0' && buf[i + 1] != '\0') - buf[i] = '|'; - } - t = buf; - delete buf; -} - -BOOLEAN TPrinter::start_winprint (long data) -{ - PrDesc *pd = (PrDesc *) data; - TTextfile& txt = *(pd->_txt); - TPrintwin pw(pd->_prcd, txt, pd->_charsize); - pw.print_background (pd->_graphics); - pw.do_print(); - return pw.aborted(); -} -#endif - -// utils del caz -HIDDEN void read_int (const char *s, int &n, int &cnt) -{ - static char nbuf[10]; - int j = 0; - while (!isdigit (s[cnt])) - cnt++; - while (isdigit (s[cnt])) - nbuf[j++] = s[cnt++]; - nbuf[j] = '\0'; - n = atoi (nbuf); -} - -#if XVT_OS == XVT_OS_WIN -void TPrinter::set_win_formlen () -{ - long pw, ph, phr, pvr; - xvt_escape (XVT_ESC_GET_PRINTER_INFO, _print_rcd, &ph, &pw, &pvr, &phr); - if (pvr != 0) - { - _formlen = (int) ((ph / pvr) * _lines_per_inch); - _dots_per_line = (int) (pvr / _lines_per_inch); - _vert_offset = (int) (ph % (long) (_formlen * _dots_per_line)); - _horz_offset = 0; // not implemented (font dependent) - - } - else - warning_box ("Il driver di stampante non e' valido.\n" - "Non stampare prima di averlo reinstallato"); -} -#endif - -void TPrinter::_parse_background () -{ - char op; - int x1, x2, y1, y2; - TToken_string tt (20); - TString txt (80); - TArray pix; - char ch; - int cnt = 0; - - while ((ch = _bg_desc[cnt++]) != '\0') - { - op = ch; - tt = ""; - char bf[2]; - bf[1] = '\0'; - switch (op) - { - case ' ': // ignore whitespace - - case '\t': - case '\n': - continue; - break; - case 'l': // line - - case 'b': // box - - case 'r': // round box - - cnt++; - read_int (_bg_desc, x1, cnt); - read_int (_bg_desc, y1, cnt); - read_int (_bg_desc, x2, cnt); - read_int (_bg_desc, y2, cnt); - cnt++; - tt << op; - tt.add (x1 - 1); - tt.add (y1 - 1); - tt.add (x2 - 1); - tt.add (y2 - 1); - break; - case 't': // text - - cnt++; - read_int (_bg_desc, x1, cnt); - read_int (_bg_desc, y1, cnt); - cnt++; - txt = ""; - while ((ch = _bg_desc[cnt++]) != '}') - txt << ch; - tt << op; - tt.add (x1 - 1); - tt.add (y1 - 1); - tt.add (txt); - break; - case 'P': // set pen style - - case 'B': // set brush - - case 'W': // set line width - - case 'C': // set pen color - - tt << op; - bf[0] = _bg_desc[cnt++]; - tt.add (bf); - break; - default: - yesnofatal_box ("Unknown background opcode: %c", op); - break; - } - pix.add (tt); - } - - // now build row descriptions - - // colors are listed in printapp: - - char curcol = 'n'; - char curpen = 'n'; - char curpat = 'n'; - char curwid = '1'; - - for (int l = 0; l < _formlen; l++) - { - - TString *rwd = (TString *) _background.objptr (l); - if (rwd == NULL) - { - _background.add (rwd = new TString, l); - if (curcol != 'n') - (*rwd) << 'C' << curcol; - if (curpat != 'n') - (*rwd) << 'B' << curpat; - if (curwid != '1') - (*rwd) << 'W' << curwid; - if (curpen != 'n') - (*rwd) << 'P' << curcol; - } - for (int j = 0; j < pix.items (); j++) - { - TToken_string & tt = (TToken_string &) pix[j]; - tt.restart (); - - // la stringa contiene l'opcode piu' i parametri in binario, - // incrementati di 1 per evitare lo 0 - - switch (*(tt.get (0))) - { - case 'b': - x1 = tt.get_int (1) + 1; - y1 = tt.get_int (2) + 1; - x2 = tt.get_int (3) + 1; - y2 = tt.get_int (4) + 1; - if (y1 == l + 1) // at ze biginnin - - { - (*rwd) << 'u' << char (x1); - (*rwd) << 'r' << char (x1) << char (x2); - (*rwd) << 'u' << char (x2); - } - else if (y2 == l + 1) // at ze end - - { - (*rwd) << 'o' << char (x1); - (*rwd) << 'r' << char (x1) << char (x2); - (*rwd) << 'o' << char (x2); - } - else if (y1 < l + 1 && y2 > l + 1) // in ze middol - - { - (*rwd) << 'v' << char (x1); - (*rwd) << 'v' << char (x2); - } - break; - case 'l': - x1 = tt.get_int (1) + 1; - y1 = tt.get_int (2) + 1; - x2 = tt.get_int (3) + 1; - y2 = tt.get_int (4) + 1; - if (y1 == y2 && y1 == l + 1) // orizzontale - - { - (*rwd) << 'h' << char (x1) << char (x2); - } - else if (y1 <= l + 1 && y2 >= l + 1) // verticale - - { - (*rwd) << 'v' << char (x1); - } - break; - case 't': - x1 = tt.get_int (1) + 1; - y1 = tt.get_int (2) + 1; // al gh'e' - - if (y1 == l + 1) - { - } - break; - case 'W': - curwid = *(tt.get (1)); - (*rwd) << 'W' << curwid; - break; - case 'P': - curpen = *(tt.get (1)); - (*rwd) << 'P' << curpen; - break; - case 'B': - curpat = *(tt.get (1)); - (*rwd) << 'B' << curpat; - break; - case 'C': - curcol = *(tt.get (1)); - (*rwd) << 'C' << curcol; - break; - } - } - } -} - -void TPrinter::setbackground (const char *b) -{ - _background.destroy (); - _bg_desc = b; - if (b != NULL) - _parse_background (); -} - -bool printers_on_key (TMask_field & f, KEY key); - -// fv support structs for config - -bool PrinterDef::read (const char *name, FILE * fd) -{ - _printername = name; - _printername.trim (); - - TToken_string tmp (64, '='); - TString l (48); - TString r (16); - - while (TRUE) - { - const long p = ftell (fd); // Memorizza inizio paragrafo - - if (fgets (__tmp_string, 256, fd) == NULL) - return FALSE; - tmp = __tmp_string; - tmp.trim (); - - if (tmp == "[End of File]") - return FALSE; - - if (tmp[0] == '[') - { - fseek (fd, p, SEEK_SET); // Ritorna ad inizio paragrafo - - break; - } - - l = tmp.get (); - l.trim (); - r = tmp.get (); - r.trim (); - - if (l == "Device name") - { - _devicename = r; - } - else if (l == "Filter name") - { - _filtername = r; - } - else if (l == "Printer type") - { - _printertype = r; - } - else if (l == "Normal") - { - strcpy (_atstr[normalstyle], r); - } - else if (l == "Bold") - { - strcpy (_atstr[boldstyle], r); - } - else if (l == "Italic") - { - strcpy (_atstr[italicstyle], r); - } - else if (l == "Underlined") - { - strcpy (_atstr[underlinedstyle], r); - } - else if (l == "Code") - { - TToken_string code (r); - _names.add (TString (code.get ())); - _codes.add (TString (code.get ())); - } - else if (l == "Form feed") - { - _ffcode = r; - } - else if (l == "Newline") - { - _nlcode = r; - } - else - return error_box ("Riga di configurazione stampante errata:\n%s", (const char *) l); - } - return TRUE; -} - -bool PrinterDef::isdefault () -{ - return strcmp(_printername, "Default") == 0; -} - -////////// TPRINTROW ////////// - -TPrintrow ::TPrintrow () -{ - reset (); -} - -TPrintrow ::TPrintrow (const TPrintrow & pr) -{ - _row = pr.row (); - memcpy (_attr, pr._attr, MAXSTR); - memcpy (_cols, pr._cols, MAXSTR); - _currentcolor = 'w'; - _currentcolor <<= 8; - _currentcolor += 'n'; - _currentstyle = pr._currentstyle; - for (int i = 0; i < MAXSTR; i++) - _cols[i] = _currentcolor; - _lastpos = pr._lastpos; -} - -TObject *TPrintrow::dup () const -{ - return new TPrintrow (*this); -} - -const char *TPrintrow ::class_name () const -{ - return "Printrow"; -} - -word TPrintrow ::class_id () - const -{ - return CLASS_PRINTROW; -} - -TPrintrow & TPrintrow :: -reset () -{ - _row.spaces (sizeof (_attr)); - _currentcolor = 'w'; - _currentcolor <<= 8; - _currentcolor += 'n'; - memset (_attr, normalstyle, sizeof (_attr)); - for (int i = 0; i < MAXSTR; i++) - _cols[i] = _currentcolor; - _lastpos = 0; - _currentstyle = normalstyle; - return *this; -} - -const char *TPrintrow::row_codified () -{ - // returns the row with @-codes for font style and color - char last_attr = -1; - int last_color = -1; - int k = 0; - _row.rtrim (); - for (int i = 0; i < _row.len (); i++) - { - if (_attr[i] != last_attr) - { - __tmp_string[k++] = '@'; - switch (_attr[i]) - { - case normalstyle: - __tmp_string[k++] = 'r'; - break; - case boldstyle: - __tmp_string[k++] = 'b'; - break; - case italicstyle: - __tmp_string[k++] = 'i'; - break; - case underlinedstyle: - __tmp_string[k++] = 'u'; - break; - } - last_attr = _attr[i]; - } - if (_cols[i] != last_color) - { - __tmp_string[k++] = '$'; - __tmp_string[k++] = '['; - __tmp_string[k++] = (char) (_cols[i] & 0x00ff); - __tmp_string[k++] = ','; - __tmp_string[k++] = (char) (_cols[i] >> 8); - __tmp_string[k++] = ']'; - last_color = _cols[i]; - } - __tmp_string[k++] = _row[i]; - } - // k = k > 255 ? 255 : k; - __tmp_string[k] = '\0'; - return __tmp_string; -} - -TPrintrow & TPrintrow::put(const char *str, int position, int len) -{ - if (len < 1) - len = strlen (str); - - if (position < 0) - position = _lastpos; - - char bg = 'w', fg = 'n'; - for (int i = 0; i < len; i++) - { - char c = str[i]; - if (c == '$' && str[i + 1] == '[') - { - ++i; - fg = str[++i]; - c = str[++i]; - if (c == ']') - bg = _currentcolor >> 8; - else if (c == ',') - { - bg = str[++i]; - i++; - } - else - { - CHECK (0, "Error in color specification"); - } - _currentcolor = (bg << 8) + fg; - } - else if (c == '@') - { - c = str[++i]; - switch (toupper (c)) - { - case '#': - case '<': - case '>': - // printer MUST handle them - { - const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8); - _row[position] = '@'; - _attr[position++] = _currentstyle; - for (int j = 1; j < n; j++) - { - _row[position] = c; - _attr[position++] = _currentstyle; - } - } - break; - case 'B': - _currentstyle = boldstyle; - break; - case 'I': - _currentstyle = italicstyle; - break; - case 'U': - _currentstyle = underlinedstyle; - break; - case 'R': - _currentstyle = normalstyle; - break; - default: - // should be number followed by skip or jump - if (isdigit (c)) - { - // read number - char digbuf[8]; - int cnt = 0; - digbuf[cnt++] = c; - while (isdigit (c = str[++i])) - digbuf[cnt++] = c; - digbuf[cnt] = '\0'; - int pp = atoi (digbuf); - if (toupper (c) == 'G') - { - if (pp >= MAXSTR) - fatal_box ("printrow reaches position %d", pp); - if (pp > position) - for (int k = position; k < pp; k++) - { - _attr[k] = _currentstyle; - _cols[k] = _currentcolor; - } - position = pp; - } - else if (toupper (c) == 'J') - { - if (pp + position >= MAXSTR) - fatal_box ("printrow reaches position %d", pp + position); - for (int k = 0; k < pp; k++) - { - _attr[k + position] = _currentstyle; - _cols[k + position] = _currentcolor; - } - position += pp; - } - } - else - { - _row[position] = c; - _attr[position++] = _currentstyle; - _cols[position++] = _currentcolor; - } - } // switch - - } - else - { - _row[position] = c; - _attr[position] = _currentstyle; - _cols[position++] = _currentcolor; - } - } // for - - _lastpos = position; - return *this; -} - -////////// TPRINTER ////////// - -bool printers_on_key (TMask_field & f, KEY key) -{ - if (key == K_SPACE) - { - TToken_string pn1 (10), pn2 (20); - - const PrinterDef & def = MainApp()->printer().get_description(atoi(f.get ())); - const char *s; - int j = 0; - while ((s = def.get_codenames (j)) != NULL) - { - pn1.add (format ("%02d", j)); - pn2.add (s); - j++; - } - ((TList_field &) f.mask ().field (MSK_1_CODES)).replace_items (pn1, pn2); - } - return TRUE; -} - -#if XVT_OS == XVT_OS_WIN - -bool set_windows_print_device (TMask_field& f, KEY key) -{ - static char szDevice[80]; - if (key == K_SPACE && f.mask().is_running()) - { - if (MainApp()->printer().get_printrcd() != NULL) - free_print_rcd (MainApp ()->printer().get_printrcd ()); - TToken_string & pn = MainApp()->printer().getprinternames (); - TString pdev (pn.get (atoi (f.get()))); - GetProfileString ("devices", pdev, "", szDevice, sizeof (szDevice)); - pdev << "," << szDevice; - // scrivi (e semmai lo si risistema poi) - WriteProfileString("windows", "device", pdev); - MainApp()->printer().set_printrcd(get_print_rcd (&(MainApp ()->printer ().get_printrcdsize ()))); - MainApp()->printer().set_win_formlen(); - } - return TRUE; -} - -#endif - -TPrinter::TPrinter() -: _date (TODAY), _multiple_link (FALSE), _frozen (FALSE), _isgraphics (TRUE), - _lines_per_inch (6), _ch_size (12), _ncopies(1) - -{ - _footerhandler = _headerhandler = NULL; - _linkhandler = NULL; - _config = "printer.ini"; - _curprn = 0; // first in list if no default is specified - - _curcode = 0; // first in list if no default is specified - - _formlen = 66; - _frompage = 0; - _topage = 0xffff; - _hwformfeed = FALSE; - _currentpage = 1; - _currentrow = 1; - _fp = NULL; - _headersize = 0; - _footersize = 0; - _isopen = FALSE; - _multiple_copies = main_app().class_id() == CLASS_PRINT_APPLICATION; - - // read configuration file - read_configuration (_config); -#if XVT_OS == XVT_OS_WIN - print_begin (); - _print_rcd = get_print_rcd (&_print_rcd_size); - set_win_formlen (); - - static char defPrinter[80]; - static char szDevice[50]; - - // get default printer driver - GetProfileString ("windows", "device", ",,,", defPrinter, sizeof(defPrinter)); - TString pdev (defPrinter); - GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice)); - pdev << "," << szDevice; - TToken_string dio (pdev, ','); - TToken_string pn2(1024); - - // get printer names - _get_windows_printer_names (pn2); - - // determine index of current default printer - for (int i = 0; i < pn2.items (); i++) - { - if (TString(dio.get(0)) == TString(pn2.get(i))) - { - _curprn = i; - break; - } - } - -#else - _isgraphics = FALSE; -#endif -} - -TToken_string& TPrinter::getprinternames () -{ - // per ora va solo in windows -#if XVT_OS == XVT_OS_WIN - _get_windows_printer_names (_printer_names); -#endif - return _printer_names; -} - -void TPrinter::read_configuration (const char *conf) -{ - - FILE *cnfp = fopen (conf, "r"); - if (cnfp == NULL) - fatal_box ("Impossibile aprire il file %s", (const char *) _config); - - for (int i = 0; !feof (cnfp); i++) - { - if (fgets (__tmp_string, 256, cnfp) == NULL) - return; - // else - if (strncmp (__tmp_string, "[Default]", 9) != 0) - // fgets(__tmp_string,256,cnfp); - // else - { - if (*__tmp_string == '[') - { - // fatal_box("[ expected in file of printer configuration"); - - char *u = strchr (__tmp_string, ']'); - if (u) - *u = '\0'; - u = __tmp_string + 1; - - PrinterDef *pp = new PrinterDef; - _printers.add (pp); - if (pp->read (u, cnfp) == FALSE) - break; - } - } - } - fclose (cnfp); - - TFilename s ("printer.def"); -#if XVT_OS == XVT_OS_SCOUNIX - s << format (".%d", getuid ()); -#endif - if (fexist (s)) - { - TScanner sc (s); - TToken_string t (sc.line ()); - int where_print = t.get_int (1); - t = sc.line (); - _curprn = t.get_int(1); - t = sc.line (); - _printerfile = t.get (1); - t = sc.line (); - _curcode = t.get_int (1); -#if XVT_OS != XVT_OS_WIN - PrinterDef & def = (PrinterDef &) get_description (_curprn); -#endif - switch (where_print) - { - case 0: // stampante -#if XVT_OS == XVT_OS_WIN - _printertype = winprinter; -#else - switch (atoi (def._printertype)) - { - case 0: - _printertype = normprinter; - break; - case 1: - _printertype = localprinter; - break; - case 2: - _printertype = spoolprinter; - break; - } -#endif - break; - case 1: // file - - _printertype = fileprinter; - break; - case 2: // video - - _printertype = screenvis; - _curcode = 0; - break; - } - } -} - -TPrinter::~TPrinter () -{ -#if XVT_OS == XVT_OS_WIN - print_end (); -#endif -} - -const char* TPrinter::class_name () const -{ - return "Printer"; -} - -word TPrinter::class_id () const -{ - return CLASS_PRINTER; -} - -TPrintrow *TPrinter::getheaderline (int linetoget) -{ - return ((TPrintrow *) _header.objptr (linetoget)); -} - -TPrintrow *TPrinter::getfooterline (int linetoget) -{ - return ((TPrintrow *) _footer.objptr (linetoget)); -} - -void TPrinter::setheaderline (int linetoset, TPrintrow * line) -{ - _header.add (line, linetoset); - if (linetoset >= _headersize) - _headersize = linetoset + 1; -} - -void TPrinter::setheaderline (int linetoset, const TPrintrow & line) -{ - TPrintrow *p = new TPrintrow (line); - setheaderline (linetoset, p); -} - -void TPrinter::setfooterline (int linetoset, TPrintrow* line) -{ - _footer.add (line, linetoset); - // if (linetoset >= _footersize) _footersize = linetoset+1; -} - -void TPrinter::setfooterline (int linetoset, const TPrintrow& line) -{ - TPrintrow *p = new TPrintrow (line); - setfooterline (linetoset, p); -} - -void TPrinter::resetheader () -{ - _header.destroy (); - _headersize = 0; -} - -void TPrinter::resetfooter () -{ - _footer.destroy (); - // _footersize = 0; -} - -bool TPrinter::printrow (TPrintrow * rowtoprint) -{ - if (!isopen ()) - return FALSE; - - if (_currentpage < _frompage || _currentpage > _topage) - return TRUE; - - TString rw (rowtoprint == NULL ? "" : (_printertype == screenvis || _printertype == winprinter ? - rowtoprint->row_codified () : - rowtoprint->row ())); - rw.rtrim (); - - int lun = rw.len (); - int idx; - - for (idx = 0; idx < lun; idx++) - { - if (rw[idx] == '@') // gestione data e n. di pagina - - { - switch (rw[idx + 1]) - { - case '#': - rw.overwrite (format ("%-5u", _currentpage), idx++); - break; - case '>': - rw.overwrite (_date.string (4), idx++); - break; - case '<': - rw.overwrite (_date.string (2), idx++); - break; - default: - break; - } - } - } - - if (_printertype == screenvis) - { - if (!_vf->frozen ()) - _vf->add_line (rw); - else - _frozen = TRUE; - return TRUE; - } - - if (_printertype == winprinter) - { - // add line to txt - // CHECK balla colori - if (!_frozen) - _txt.append (rw); - return TRUE; - } - - const PrinterDef & pd = get_description (_curprn); - int prvstl = -1; - for (idx = 0; idx < lun; idx++) - { - int cst = rowtoprint->get_style (idx); - if (cst != prvstl) - { - fprintf (_fp, "%s", pd._atstr[normalstyle]); - if (cst != normalstyle) - fprintf (_fp, "%s", pd._atstr[cst]); - } - prvstl = cst; - putc (rw[idx], _fp); - } - if (newline ()) - putc (newline (), _fp); - - return TRUE; -} - -word TPrinter::rows_left() const -{ - word left = _formlen - _currentrow - _footersize + 1; - if (_currentrow < 2) - left -= _headersize; - return left; -} - -bool TPrinter::print(TPrintrow & rowtoprint) -{ - bool ok = TRUE; - - if (_currentrow > _formlen - _footersize) - ok = printfooter (); - - // if (ok && _currentrow <= _headersize) - if (ok && _currentrow == 1) - ok = printheader(); - - if (ok) - { - ok = printrow(&rowtoprint); - _currentrow++; - } - - return ok; -} - -bool TPrinter::printheader() -{ - if (_headerhandler) - _headerhandler (*this); - - bool ok = TRUE; - for (int i = 0; i < _headersize && ok; i++) - ok = printrow(getheaderline(i)); - - _currentrow = _headersize + 1; - return ok; -} - -bool TPrinter::printfooter() -{ - if (_footerhandler) - _footerhandler (*this); - - bool ok = TRUE; - for (int i = 0; i < _footersize && ok; i++) - ok = printrow(getfooterline(i)); - -#if XVT_OS != XVT_OS_WIN - if (ok) - printformfeed(); -#endif - - _currentrow = 1; - _currentpage++; - - return ok; -} - -bool TPrinter::skip(int linestoskip) -{ - int jumpline; - - CHECK (linestoskip >= 0, "Linestoskip can't be negative"); - jumpline = _currentrow + linestoskip; - return jump(jumpline); -} - -bool TPrinter::jump(int jumpline) -{ - int i = 0; - bool ok = TRUE; - - CHECK (jumpline >= 0, "Jumpline can't be negative"); - if (jumpline > _formlen - _footersize) - ok = formfeed(); - else - for (i = _currentrow; i < jumpline; i++) - if (!printrow()) - ok = FALSE; - if (jumpline > _formlen - _footersize) - ok = FALSE; - return ok; -} - -bool TPrinter::formfeed() -{ - const int lastrow = _formlen - _footersize; - for (; _currentrow <= lastrow; _currentrow++) - printrow(); - return printfooter(); -} - -void TPrinter::reset() -{ - resetheader(); - resetfooter(); - _currentpage = 1; - _currentrow = 1; -} - -bool TPrinter::printformfeed() -{ -#if XVT_OS != XVT_OS_WIN - const PrinterDef & pd = get_description(_curprn); - - if (_printertype != screenvis && _hwformfeed) - fprintf(_fp, "%s",(const char *)pd._ffcode); -#endif - return TRUE; -} - -bool TPrinter::open() -{ - // qui -#if XVT_OS==XVT_OS_SCOUNIX - if (_printertype == spoolprinter) - { - const PrinterDef & def = get_description(_curprn); - int pfd[2]; - - if (pipe(pfd) == -1) - return error_box ("Impossibile creare processo di stampa " "(pipe)"); - - int ret = fork(); - if (ret == -1) - return error_box("Impossibile creare processo di stampa " "(fork)"); - - if (ret == 0) - { - if ((::close(0) != -1) && (::dup(pfd[0]) == 0) && - (::close(pfd[0]) == 0) && (::close(pfd[1]) != -1)) - { - char s0[80]; - - sprintf (s0, "-d%s", (const char *) def._devicename); - if ((def._filtername).not_empty ()) - { - char s1[80]; - sprintf (s1, "-o %s", (const char *) def._filtername); - char *ws[5] = - {"lpr", "-s", s0, s1, NULL}; - execvp (ws[0], ws); - } - else - { - char *ws[4] = - {"lpr", "-s", s0, NULL}; - execvp(ws[0], ws); - } - exit(-1); - } - } - if ((::close (pfd[0]) == -1) || ((_fp = fdopen(pfd[1], "w")) == NULL)) - return error_box ("Impossibile creare processo di stampa" "(close)"); - } - else -#endif - if (_printertype == screenvis) - { - _vf = new TViswin (NULL, "Anteprima di stampa", TRUE, TRUE, - _linksdescr.items () > 0); - _vf->open_modal (); - } - else if (_printertype == winprinter) - { - // prepare text object for new text - _txt.destroy (); - } - else - { - const PrinterDef & def = get_description (_curprn); - TFilename fname (_printerfile); - - if (_printertype == normprinter) - fname = def._devicename; - _fp = fopen (fname, "w"); - - if (_fp == NULL) - return error_box ("Errore di apertura file stampa: '%s'", - (const char *) fname); - - TString code (def.get_codes (_curcode)); - if (code.not_empty ()) - { - const char *s = code; - fputs (esc ((char *) s), _fp); - } - } - - _currentrow = 1; - _currentpage = 1; - - return _isopen = TRUE; -} - -void TPrinter::set() -{ - main_app().disable_menu_item (M_FILE_PG_SETUP); - - TMask mask ("bagn001a"); - TToken_string pn1 (50), pn2 (100); - int i; - - TFilename defile("printer.def"); -#if XVT_OS == XVT_OS_SCOUNIX - defile << format (".%d", getuid ()); -#endif - mask.set_workfile(defile); - - -#if XVT_OS != XVT_OS_WIN - - for (i = 0; i < _printers.items (); i++) - { - pn1.add (i); - pn2.add (((PrinterDef &) _printers[i])._printername); - } - - ((TList_field &) (mask.field (MSK_1_PRINTERS))).replace_items (pn1, pn2); - mask.hide(MSK_1_SIZE); - mask.hide(MSK_1_LINES); - mask.disable(DLG_SETPRINT); - if (!_multiple_copies) mask.hide(MSK_1_NPAGES); - - pn1 = ""; - pn2 = ""; - - for (i = 0; i < ((PrinterDef &)_printers[_curprn])._names.items(); i++) - { - pn1.add(format ("%d", i)); - pn2.add((TString &)((PrinterDef &) _printers[_curprn])._names[i]); - } - - ((TList_field &)(mask.field (MSK_1_CODES))).replace_items(pn1, pn2); - mask.set_handler (MSK_1_PRINTERS, printers_on_key); - if (_printertype == fileprinter) - mask.set (MSK_1_TYPE, "1"); - else if (_printertype == screenvis) - mask.set (MSK_1_TYPE, "2"); - else - mask.set (MSK_1_TYPE, "0"); - - mask.set(MSK_1_PRINTERS, format("%d", _curprn)); - mask.set(MSK_1_CODES, format("%d", _curcode)); - mask.set(MSK_1_FILENAME, _printerfile); - mask.set(MSK_1_NPAGES, _ncopies); - - KEY k; - - if ((k = mask.run()) == K_ESC) - return; - - if (k == K_INS) // premuto REGISTRA - mask.save(); - - // get user choices - - _curprn = atoi(mask.get(MSK_1_PRINTERS)); - _ncopies = atoi(mask.get(MSK_1_NPAGES)); - - PrinterDef& def = (PrinterDef &) get_description (_curprn); - switch (atoi(mask.get (MSK_1_TYPE))) - { - case 0: // stampante - - _printertype = normprinter; - _curcode = atoi (mask.get (MSK_1_CODES)); - switch (atoi (def._printertype)) - { - case 0: - _printertype = normprinter; - break; - case 1: - _printertype = localprinter; - break; - case 2: - _printertype = spoolprinter; - break; - } - break; - case 1: // file - - _printertype = fileprinter; - _printerfile = mask.get (MSK_1_FILENAME); - _curcode = atoi (mask.get (MSK_1_CODES)); - break; - case 2: // video - - _printertype = screenvis; - _curcode = 0; - break; - } - -#else - - _get_windows_printer_names(pn2); - char old_default[80]; - GetProfileString ("windows", "device", ",,,", old_default, sizeof(old_default)); - - for (i = 0; i < pn2.items (); i++) - pn1.add(i); - - ((TList_field &) (mask.field (MSK_1_PRINTERS))).replace_items(pn1, pn2); - mask.set(MSK_1_PRINTERS, pn1.get(_curprn)); - - mask.hide(MSK_1_CODES); - if (!_multiple_copies) mask.hide(MSK_1_NPAGES); - - mask.set(MSK_1_ISGRAPHICS, _isgraphics ? "X" : ""); - mask.set(MSK_1_SIZE, _ch_size); - mask.set(MSK_1_LINES, _lines_per_inch); - - mask.set(MSK_1_NPAGES, _ncopies); - - if (_printertype == fileprinter) - mask.set (MSK_1_TYPE, "1"); - else if (_printertype == screenvis) - mask.set (MSK_1_TYPE, "2"); - else - mask.set (MSK_1_TYPE, "0"); - - mask.set_handler (MSK_1_PRINTERS, set_windows_print_device); - - KEY k; - int oldprn = _curprn; - - while ((k = mask.run ()) != K_ESC && k != K_ENTER && k != K_INS) - { - if (k == DLG_SETPRINT) - { - // l'handler setta default di windows a quella nel listbox e ribecca l'rcd - if (_print_rcd != NULL) - { - if (page_setup_dlg(_print_rcd)) - { - // see if user has changed printer - // determine index of currently selected printer - // ACTHUNG! Deep hacking of XVT internals! NON PORTABLE! - if (_print_rcd != NULL) - free_print_rcd (_print_rcd); - _print_rcd = get_print_rcd(&_print_rcd_size); - for (i = 0; i < pn2.items(); i++) - if (strcmp((const char *)(_print_rcd + 4), pn2.get(i)) == 0) - { - _curprn = i; - break; - } - - mask.set(MSK_1_PRINTERS, pn1.get(_curprn)); - - set_win_formlen(); - } - mask.set_focus(); - } - else - beep (); - } - } - - _curprn = atoi(mask.get(MSK_1_PRINTERS)); - - if (k == K_INS) - { - // tutto resta com'e' - mask.save (); - } - if (k == K_ESC || k == K_ENTER) - { - // riaggiusta stampante default windows come prima - // curprn e rcd sono quelle di prima - MainApp()->enable_menu_item(M_FILE_PG_SETUP); - WriteProfileString("windows","device", old_default); - } - if (k == K_ESC) - { - if (_print_rcd != NULL) - free_print_rcd (_print_rcd); - _curprn = oldprn; - _print_rcd = get_print_rcd(&_print_rcd_size); - set_win_formlen(); - return; - } - - _ncopies = atoi (mask.get (MSK_1_NPAGES)); - - switch (atoi (mask.get (MSK_1_TYPE))) - { - case 0: // stampante - - _printertype = winprinter; - break; - case 1: // file - - _printertype = fileprinter; - _printerfile = mask.get (MSK_1_FILENAME); - _curcode = atoi (mask.get (MSK_1_CODES)); - break; - case 2: // video - - _printertype = screenvis; - _curcode = 0; - break; - } - - _isgraphics = mask.get_bool (MSK_1_ISGRAPHICS); - _ch_size = atoi (mask.get (MSK_1_SIZE)); - _lines_per_inch = atoi (mask.get (MSK_1_LINES)); - set_win_formlen (); - -#endif - - main_app().enable_menu_item (M_FILE_PG_SETUP); -} - -void TPrinter::close () -{ - if (isopen () && _currentrow > 1 && - (_footersize || (_printertype != screenvis && _printertype != winprinter))) - formfeed (); - - if (_fp) - { - fclose (_fp); - _fp = NULL; - } - - if (_printertype == screenvis) - { - CHECK (_vf, "VF!"); - _vf->close_print (); - _vf->run (); - if (_vf->is_open ()) - _vf->close_modal (); - delete _vf; - freeze (FALSE); - _vf = NULL; - } -#if XVT_OS == XVT_OS_WIN -else if (_printertype == winprinter) -{ - PrintWhat._prcd = _print_rcd; - PrintWhat._txt = &_txt; - PrintWhat._graphics = _isgraphics; - PrintWhat._charsize = _ch_size; - start_print_thread (start_winprint, (long) (&PrintWhat)); -} -#endif -else if (_printertype == localprinter) -{ -#if XVT_OS == XVT_OS_SCOUNIX - TFilename s1 = tmpnam (NULL); - switch (fork ()) - { - case -1: - break; - case 0: - execlp ("localprint", "localprint", (const char *) s1, NULL); - default: - wait ((int *) NULL); - } - remove (s1); -#endif -} -_isopen = FALSE; -} - -// -// TFile_printer -// - -#include - -#if XVT_OS == XVT_OS_DOS -#define FORMAT_COMMAND "FORMAT" -#else -#define FORMAT_COMMAND "dosformat -fq" -#endif - -const long disk_sizes[] = -{360000, 1200000, 720000, 1400000, 2880000}; - -TFile_printer ::TFile_printer (const char *ffile, const char *label, int len_rec, int num_rec_inizio, int num_rec_fine, int tipo_disco) -{ - set_printtype (fileprinter); - - _num_rec_testa_coda = num_rec_inizio + num_rec_fine; - _file = ffile; - _label = label; - _len_rec = len_rec; - _volume = 1; - _size = disk_sizes[tipo_disco]; - _num_rec_volume = int ((_size / len_rec) - _num_rec_testa_coda); - _nome_file_fissato = TRUE; - _formatta = FALSE; - _label_fissata = TRUE; - -} - -void TFile_printer::open() -{ -} - -void TFile_printer :: -close () -{ -} - -bool TFile_printer :: -genera_dischetti () -{ - int r; - - warning_box ("Questa procedura richiede %2d dischetti", - _volume); - - for (int i = 0; i < _tmp_files.items (); i++) - { - // Avvisa l'utente di inserire un dischetto - r = yesno_box ("Inserire il dischetto n. %2d di %2d nel drive %2s", - i + 1, _volume, _drive); - if (!r) - return error_box ("Procedura interrotta!"); - - // e eventualmente lo formatta - if (_formatta) - { - TString dep (30); - if (_label != NULL) - dep << FORMAT_COMMAND << " " << "/v:" << _label << " " << _drive; - else - dep << FORMAT_COMMAND << " " << _drive; - - TExternal_app sys (dep); - sys.run (); - } - - // copia il file sul dischetto - fcopy ((const char *) &_tmp_files[i], (const char *) _drive); - - } - return TRUE; -} - -TFile_printer::~TFile_printer () -{ -} - -void TFile_printer::set () -{ - TMask m ("bagn004"); - KEY tasto; - int f; - - // - // - // -------------------------------------------------------------------- - // Qui bisogna inserire la lista dei drive disponibili nella maschera - // Per ora tale lista e' fissa e contiene solo A: e B: - // -------------------------------------------------------------------- - // - // - - m.set (F_FILE_DESTINAZIONE, _file); - m.set (F_LABEL, _label); - - if (_nome_file_fissato) - m.disable (F_FILE_DESTINAZIONE); - - if (_label_fissata) - m.disable (F_LABEL); - - tasto = m.run (); - - if (tasto == K_ENTER) - { - f = atoi (m.get (F_FORMATO_DISCO)); - _drive = m.get (F_DRIVE); - _file = m.get (F_FILE_DESTINAZIONE); - _label = m.get (F_LABEL); - _formatta = (bool) (m.get (F_FORMATTA) == "X"); - _size = disk_sizes[f]; - _num_rec_volume = int ((_size / _len_rec) - _num_rec_testa_coda); - } -} - -// -// TFile printer fine -// +#include +#include +#include + +#if XVT_OS==XVT_OS_SCOUNIX +#include +#include +#include +#else +#include +#endif + +#define STYLE_NUM 4 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct PrDesc +{ + TTextfile *_txt; + PRINT_RCD *_prcd; + bool _graphics; + int _formlen; + int _charsize; + int _lines_per_inch; +} +PrintWhat; + +#define LINES_PER_INCH (6.0) + +#if XVT_OS == XVT_OS_WIN + +#include + +void TPrinter::_get_windows_printer_names (TToken_string & t) +{ + char *buf = new char[4096]; // ammazzao' + + GetProfileString ("devices", NULL, "", buf, 4096); + + for (int i = 0; i < 4095; i++) + { + if (buf[i] == '\0' && buf[i + 1] == '\0') + break; + if (buf[i] == '\0' && buf[i + 1] != '\0') + buf[i] = '|'; + } + t = buf; + delete buf; +} + +BOOLEAN TPrinter::start_winprint (long data) +{ + PrDesc *pd = (PrDesc *) data; + TTextfile& txt = *(pd->_txt); + TPrintwin pw(pd->_prcd, txt, pd->_charsize); + pw.print_background (pd->_graphics); + pw.do_print(); + return pw.aborted(); +} +#endif + +// utils del caz +HIDDEN void read_int (const char *s, int &n, int &cnt) +{ + static char nbuf[10]; + int j = 0; + while (!isdigit (s[cnt])) + cnt++; + while (isdigit (s[cnt])) + nbuf[j++] = s[cnt++]; + nbuf[j] = '\0'; + n = atoi (nbuf); +} + +#if XVT_OS == XVT_OS_WIN +void TPrinter::set_win_formlen () +{ + long pw, ph, phr, pvr; + xvt_escape (XVT_ESC_GET_PRINTER_INFO, _print_rcd, &ph, &pw, &pvr, &phr); + if (pvr != 0) + { + _formlen = (int) ((ph / pvr) * _lines_per_inch); + _dots_per_line = (int) (pvr / _lines_per_inch); + _vert_offset = (int) (ph % (long) (_formlen * _dots_per_line)); + _horz_offset = 0; // not implemented (font dependent) + + } + else + warning_box ("Il driver di stampante non e' valido.\n" + "Non stampare prima di averlo reinstallato"); +} +#endif + +void TPrinter::_parse_background () +{ + char op; + int x1, x2, y1, y2; + TToken_string tt (20); + TString txt (80); + TArray pix; + char ch; + int cnt = 0; + + while ((ch = _bg_desc[cnt++]) != '\0') + { + op = ch; + tt = ""; + char bf[2]; + bf[1] = '\0'; + switch (op) + { + case ' ': // ignore whitespace + + case '\t': + case '\n': + continue; + break; + case 'l': // line + + case 'b': // box + + case 'r': // round box + + cnt++; + read_int (_bg_desc, x1, cnt); + read_int (_bg_desc, y1, cnt); + read_int (_bg_desc, x2, cnt); + read_int (_bg_desc, y2, cnt); + cnt++; + tt << op; + tt.add (x1 - 1); + tt.add (y1 - 1); + tt.add (x2 - 1); + tt.add (y2 - 1); + break; + case 't': // text + + cnt++; + read_int (_bg_desc, x1, cnt); + read_int (_bg_desc, y1, cnt); + cnt++; + txt = ""; + while ((ch = _bg_desc[cnt++]) != '}') + txt << ch; + tt << op; + tt.add (x1 - 1); + tt.add (y1 - 1); + tt.add (txt); + break; + case 'P': // set pen style + + case 'B': // set brush + + case 'W': // set line width + + case 'C': // set pen color + + tt << op; + bf[0] = _bg_desc[cnt++]; + tt.add (bf); + break; + default: + yesnofatal_box ("Unknown background opcode: %c", op); + break; + } + pix.add (tt); + } + + // now build row descriptions + + // colors are listed in printapp: + + char curcol = 'n'; + char curpen = 'n'; + char curpat = 'n'; + char curwid = '1'; + + for (int l = 0; l < _formlen; l++) + { + + TString *rwd = (TString *) _background.objptr (l); + if (rwd == NULL) + { + _background.add (rwd = new TString, l); + if (curcol != 'n') + (*rwd) << 'C' << curcol; + if (curpat != 'n') + (*rwd) << 'B' << curpat; + if (curwid != '1') + (*rwd) << 'W' << curwid; + if (curpen != 'n') + (*rwd) << 'P' << curcol; + } + for (int j = 0; j < pix.items (); j++) + { + TToken_string & tt = (TToken_string &) pix[j]; + tt.restart (); + + // la stringa contiene l'opcode piu' i parametri in binario, + // incrementati di 1 per evitare lo 0 + + switch (*(tt.get (0))) + { + case 'b': + x1 = tt.get_int (1) + 1; + y1 = tt.get_int (2) + 1; + x2 = tt.get_int (3) + 1; + y2 = tt.get_int (4) + 1; + if (y1 == l + 1) // at ze biginnin + + { + (*rwd) << 'u' << char (x1); + (*rwd) << 'r' << char (x1) << char (x2); + (*rwd) << 'u' << char (x2); + } + else if (y2 == l + 1) // at ze end + + { + (*rwd) << 'o' << char (x1); + (*rwd) << 'r' << char (x1) << char (x2); + (*rwd) << 'o' << char (x2); + } + else if (y1 < l + 1 && y2 > l + 1) // in ze middol + + { + (*rwd) << 'v' << char (x1); + (*rwd) << 'v' << char (x2); + } + break; + case 'l': + x1 = tt.get_int (1) + 1; + y1 = tt.get_int (2) + 1; + x2 = tt.get_int (3) + 1; + y2 = tt.get_int (4) + 1; + if (y1 == y2 && y1 == l + 1) // orizzontale + + { + (*rwd) << 'h' << char (x1) << char (x2); + } + else if (y1 <= l + 1 && y2 >= l + 1) // verticale + + { + (*rwd) << 'v' << char (x1); + } + break; + case 't': + x1 = tt.get_int (1) + 1; + y1 = tt.get_int (2) + 1; // al gh'e' + + if (y1 == l + 1) + { + } + break; + case 'W': + curwid = *(tt.get (1)); + (*rwd) << 'W' << curwid; + break; + case 'P': + curpen = *(tt.get (1)); + (*rwd) << 'P' << curpen; + break; + case 'B': + curpat = *(tt.get (1)); + (*rwd) << 'B' << curpat; + break; + case 'C': + curcol = *(tt.get (1)); + (*rwd) << 'C' << curcol; + break; + } + } + } +} + +void TPrinter::setbackground (const char *b) +{ + _background.destroy (); + _bg_desc = b; + if (b != NULL) + _parse_background (); +} + +bool printers_on_key (TMask_field & f, KEY key); + +// fv support structs for config + +bool PrinterDef::read (const char *name, FILE * fd) +{ + _printername = name; + _printername.trim (); + + TToken_string tmp (64, '='); + TString l (48); + TString r (16); + + while (TRUE) + { + const long p = ftell (fd); // Memorizza inizio paragrafo + + if (fgets (__tmp_string, 256, fd) == NULL) + return FALSE; + tmp = __tmp_string; + tmp.trim (); + + if (tmp == "[End of File]") + return FALSE; + + if (tmp[0] == '[') + { + fseek (fd, p, SEEK_SET); // Ritorna ad inizio paragrafo + + break; + } + + l = tmp.get (); + l.trim (); + r = tmp.get (); + r.trim (); + + if (l == "Device name") + { + _devicename = r; + } + else if (l == "Filter name") + { + _filtername = r; + } + else if (l == "Printer type") + { + _printertype = r; + } + else if (l == "Normal") + { + strcpy (_atstr[normalstyle], r); + } + else if (l == "Bold") + { + strcpy (_atstr[boldstyle], r); + } + else if (l == "Italic") + { + strcpy (_atstr[italicstyle], r); + } + else if (l == "Underlined") + { + strcpy (_atstr[underlinedstyle], r); + } + else if (l == "Code") + { + TToken_string code (r); + _names.add (TString (code.get ())); + _codes.add (TString (code.get ())); + } + else if (l == "Form feed") + { + _ffcode = r; + } + else if (l == "Newline") + { + _nlcode = r; + } + else + return error_box ("Riga di configurazione stampante errata:\n%s", (const char *) l); + } + return TRUE; +} + +bool PrinterDef::isdefault () +{ + return strcmp(_printername, "Default") == 0; +} + +////////// TPRINTROW ////////// + +TPrintrow ::TPrintrow () +{ + reset (); +} + +TPrintrow ::TPrintrow (const TPrintrow & pr) +{ + _row = pr.row (); + memcpy (_attr, pr._attr, MAXSTR); + memcpy (_cols, pr._cols, MAXSTR); + _currentcolor = 'w'; + _currentcolor <<= 8; + _currentcolor += 'n'; + _currentstyle = pr._currentstyle; + for (int i = 0; i < MAXSTR; i++) + _cols[i] = _currentcolor; + _lastpos = pr._lastpos; +} + +TObject *TPrintrow::dup () const +{ + return new TPrintrow (*this); +} + +const char *TPrintrow ::class_name () const +{ + return "Printrow"; +} + +word TPrintrow ::class_id () + const +{ + return CLASS_PRINTROW; +} + +TPrintrow & TPrintrow :: +reset () +{ + _row.spaces (sizeof (_attr)); + _currentcolor = 'w'; + _currentcolor <<= 8; + _currentcolor += 'n'; + memset (_attr, normalstyle, sizeof (_attr)); + for (int i = 0; i < MAXSTR; i++) + _cols[i] = _currentcolor; + _lastpos = 0; + _currentstyle = normalstyle; + return *this; +} + +const char *TPrintrow::row_codified () +{ + // returns the row with @-codes for font style and color + char last_attr = -1; + int last_color = -1; + int k = 0; + _row.rtrim (); + for (int i = 0; i < _row.len (); i++) + { + if (_attr[i] != last_attr) + { + __tmp_string[k++] = '@'; + switch (_attr[i]) + { + case normalstyle: + __tmp_string[k++] = 'r'; + break; + case boldstyle: + __tmp_string[k++] = 'b'; + break; + case italicstyle: + __tmp_string[k++] = 'i'; + break; + case underlinedstyle: + __tmp_string[k++] = 'u'; + break; + } + last_attr = _attr[i]; + } + if (_cols[i] != last_color) + { + __tmp_string[k++] = '$'; + __tmp_string[k++] = '['; + __tmp_string[k++] = (char) (_cols[i] & 0x00ff); + __tmp_string[k++] = ','; + __tmp_string[k++] = (char) (_cols[i] >> 8); + __tmp_string[k++] = ']'; + last_color = _cols[i]; + } + __tmp_string[k++] = _row[i]; + } + // k = k > 255 ? 255 : k; + __tmp_string[k] = '\0'; + return __tmp_string; +} + +TPrintrow & TPrintrow::put(const char *str, int position, int len) +{ + if (len < 1) + len = strlen (str); + + if (position < 0) + position = _lastpos; + + char bg = 'w', fg = 'n'; + for (int i = 0; i < len; i++) + { + char c = str[i]; + if (c == '$' && str[i + 1] == '[') + { + ++i; + fg = str[++i]; + c = str[++i]; + if (c == ']') + bg = _currentcolor >> 8; + else if (c == ',') + { + bg = str[++i]; + i++; + } + else + { + CHECK (0, "Error in color specification"); + } + _currentcolor = (bg << 8) + fg; + } + else if (c == '@') + { + c = str[++i]; + switch (toupper (c)) + { + case '#': + case '<': + case '>': + // printer MUST handle them + { + const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8); + _row[position] = '@'; + _attr[position++] = _currentstyle; + for (int j = 1; j < n; j++) + { + _row[position] = c; + _attr[position++] = _currentstyle; + } + } + break; + case 'B': + _currentstyle = boldstyle; + break; + case 'I': + _currentstyle = italicstyle; + break; + case 'U': + _currentstyle = underlinedstyle; + break; + case 'R': + _currentstyle = normalstyle; + break; + default: + // should be number followed by skip or jump + if (isdigit (c)) + { + // read number + char digbuf[8]; + int cnt = 0; + digbuf[cnt++] = c; + while (isdigit (c = str[++i])) + digbuf[cnt++] = c; + digbuf[cnt] = '\0'; + int pp = atoi (digbuf); + if (toupper (c) == 'G') + { + if (pp >= MAXSTR) + fatal_box ("printrow reaches position %d", pp); + if (pp > position) + for (int k = position; k < pp; k++) + { + _attr[k] = _currentstyle; + _cols[k] = _currentcolor; + } + position = pp; + } + else if (toupper (c) == 'J') + { + if (pp + position >= MAXSTR) + fatal_box ("printrow reaches position %d", pp + position); + for (int k = 0; k < pp; k++) + { + _attr[k + position] = _currentstyle; + _cols[k + position] = _currentcolor; + } + position += pp; + } + } + else + { + _row[position] = c; + _attr[position++] = _currentstyle; + _cols[position++] = _currentcolor; + } + } // switch + + } + else + { + _row[position] = c; + _attr[position] = _currentstyle; + _cols[position++] = _currentcolor; + } + } // for + + _lastpos = position; + return *this; +} + +////////// TPRINTER ////////// + +bool printers_on_key (TMask_field & f, KEY key) +{ + if (key == K_SPACE) + { + TToken_string pn1 (10), pn2 (20); + + const PrinterDef & def = main_app().printer().get_description(atoi(f.get ())); + const char *s; + int j = 0; + while ((s = def.get_codenames (j)) != NULL) + { + pn1.add (format ("%02d", j)); + pn2.add (s); + j++; + } + ((TList_field &) f.mask ().field (MSK_1_CODES)).replace_items (pn1, pn2); + } + return TRUE; +} + +#if XVT_OS == XVT_OS_WIN + +bool set_windows_print_device (TMask_field& f, KEY key) +{ + static char szDevice[80]; + if (key == K_SPACE && f.mask().is_running()) + { + if (main_app().printer().get_printrcd() != NULL) + free_print_rcd (main_app().printer().get_printrcd ()); + TToken_string & pn = main_app().printer().getprinternames (); + TString pdev (pn.get (atoi (f.get()))); + GetProfileString ("devices", pdev, "", szDevice, sizeof (szDevice)); + pdev << "," << szDevice; + // scrivi (e semmai lo si risistema poi) + WriteProfileString("windows", "device", pdev); + main_app().printer().set_printrcd(get_print_rcd (&(MainApp ()->printer ().get_printrcdsize ()))); + main_app().printer().set_win_formlen(); + } + return TRUE; +} + +#endif + +TPrinter::TPrinter() +: _date (TODAY), _multiple_link (FALSE), _frozen (FALSE), _isgraphics (TRUE), + _lines_per_inch (6), _ch_size (12), _ncopies(1) + +{ + _footerhandler = _headerhandler = NULL; + _linkhandler = NULL; + _config = "printer.ini"; + _curprn = 0; // first in list if no default is specified + + _curcode = 0; // first in list if no default is specified + + _formlen = 66; + _frompage = 0; + _topage = 0xffff; + _hwformfeed = FALSE; + _currentpage = 1; + _currentrow = 1; + _fp = NULL; + _headersize = 0; + _footersize = 0; + _isopen = FALSE; + _multiple_copies = main_app().class_id() == CLASS_PRINT_APPLICATION; + + // read configuration file + read_configuration (_config); +#if XVT_OS == XVT_OS_WIN + print_begin (); + _print_rcd = get_print_rcd (&_print_rcd_size); + set_win_formlen (); + + static char defPrinter[80]; + static char szDevice[50]; + + // get default printer driver + GetProfileString ("windows", "device", ",,,", defPrinter, sizeof(defPrinter)); + TString pdev (defPrinter); + GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice)); + pdev << "," << szDevice; + TToken_string dio (pdev, ','); + TToken_string pn2(1024); + + // get printer names + _get_windows_printer_names (pn2); + + // determine index of current default printer + for (int i = 0; i < pn2.items (); i++) + { + if (TString(dio.get(0)) == TString(pn2.get(i))) + { + _curprn = i; + break; + } + } + +#else + _isgraphics = FALSE; +#endif +} + +TToken_string& TPrinter::getprinternames () +{ + // per ora va solo in windows +#if XVT_OS == XVT_OS_WIN + _get_windows_printer_names (_printer_names); +#endif + return _printer_names; +} + +void TPrinter::read_configuration (const char *conf) +{ + + FILE *cnfp = fopen (conf, "r"); + if (cnfp == NULL) + fatal_box ("Impossibile aprire il file %s", (const char *) _config); + + for (int i = 0; !feof (cnfp); i++) + { + if (fgets (__tmp_string, 256, cnfp) == NULL) + return; + // else + if (strncmp (__tmp_string, "[Default]", 9) != 0) + // fgets(__tmp_string,256,cnfp); + // else + { + if (*__tmp_string == '[') + { + // fatal_box("[ expected in file of printer configuration"); + + char *u = strchr (__tmp_string, ']'); + if (u) + *u = '\0'; + u = __tmp_string + 1; + + PrinterDef *pp = new PrinterDef; + _printers.add (pp); + if (pp->read (u, cnfp) == FALSE) + break; + } + } + } + fclose (cnfp); + + TFilename s ("printer.def"); +#if XVT_OS == XVT_OS_SCOUNIX + s << format (".%d", getuid ()); +#endif + if (fexist (s)) + { + TScanner sc (s); + TToken_string t (sc.line ()); + int where_print = t.get_int (1); + t = sc.line (); + _curprn = t.get_int(1); + t = sc.line (); + _printerfile = t.get (1); + t = sc.line (); + _curcode = t.get_int (1); +#if XVT_OS != XVT_OS_WIN + PrinterDef & def = (PrinterDef &) get_description (_curprn); +#endif + switch (where_print) + { + case 0: // stampante +#if XVT_OS == XVT_OS_WIN + _printertype = winprinter; +#else + switch (atoi (def._printertype)) + { + case 0: + _printertype = normprinter; + break; + case 1: + _printertype = localprinter; + break; + case 2: + _printertype = spoolprinter; + break; + } +#endif + break; + case 1: // file + + _printertype = fileprinter; + break; + case 2: // video + + _printertype = screenvis; + _curcode = 0; + break; + } + } +} + +TPrinter::~TPrinter () +{ +#if XVT_OS == XVT_OS_WIN + print_end (); +#endif +} + +const char* TPrinter::class_name () const +{ + return "Printer"; +} + +word TPrinter::class_id () const +{ + return CLASS_PRINTER; +} + +TPrintrow *TPrinter::getheaderline (int linetoget) +{ + return ((TPrintrow *) _header.objptr (linetoget)); +} + +TPrintrow *TPrinter::getfooterline (int linetoget) +{ + return ((TPrintrow *) _footer.objptr (linetoget)); +} + +void TPrinter::setheaderline (int linetoset, TPrintrow * line) +{ + _header.add (line, linetoset); + if (linetoset >= _headersize) + _headersize = linetoset + 1; +} + +void TPrinter::setheaderline (int linetoset, const TPrintrow & line) +{ + TPrintrow *p = new TPrintrow (line); + setheaderline (linetoset, p); +} + +void TPrinter::setfooterline (int linetoset, TPrintrow* line) +{ + _footer.add (line, linetoset); + // if (linetoset >= _footersize) _footersize = linetoset+1; +} + +void TPrinter::setfooterline (int linetoset, const TPrintrow& line) +{ + TPrintrow *p = new TPrintrow (line); + setfooterline (linetoset, p); +} + +void TPrinter::resetheader () +{ + _header.destroy (); + _headersize = 0; +} + +void TPrinter::resetfooter () +{ + _footer.destroy (); + // _footersize = 0; +} + +bool TPrinter::printrow (TPrintrow * rowtoprint) +{ + if (!isopen ()) + return FALSE; + + if (_currentpage < _frompage || _currentpage > _topage) + return TRUE; + + TString rw (rowtoprint == NULL ? "" : (_printertype == screenvis || _printertype == winprinter ? + rowtoprint->row_codified () : + rowtoprint->row ())); + rw.rtrim (); + + int lun = rw.len (); + int idx; + + for (idx = 0; idx < lun; idx++) + { + if (rw[idx] == '@') // gestione data e n. di pagina + + { + switch (rw[idx + 1]) + { + case '#': + rw.overwrite (format ("%-5u", _currentpage), idx++); + break; + case '>': + rw.overwrite (_date.string (4), idx++); + break; + case '<': + rw.overwrite (_date.string (2), idx++); + break; + default: + break; + } + } + } + + if (_printertype == screenvis) + { + if (!_vf->frozen ()) + _vf->add_line (rw); + else + _frozen = TRUE; + return TRUE; + } + + if (_printertype == winprinter) + { + // add line to txt + // CHECK balla colori + if (!_frozen) + _txt.append (rw); + return TRUE; + } + + const PrinterDef & pd = get_description (_curprn); + int prvstl = -1; + for (idx = 0; idx < lun; idx++) + { + int cst = rowtoprint->get_style (idx); + if (cst != prvstl) + { + fprintf (_fp, "%s", pd._atstr[normalstyle]); + if (cst != normalstyle) + fprintf (_fp, "%s", pd._atstr[cst]); + } + prvstl = cst; + putc (rw[idx], _fp); + } + if (newline ()) + putc (newline (), _fp); + + return TRUE; +} + +word TPrinter::rows_left() const +{ + word left = _formlen - _currentrow - _footersize + 1; + if (_currentrow < 2) + left -= _headersize; + return left; +} + +bool TPrinter::print(TPrintrow & rowtoprint) +{ + bool ok = TRUE; + + if (_currentrow > _formlen - _footersize) + ok = printfooter (); + + // if (ok && _currentrow <= _headersize) + if (ok && _currentrow == 1) + ok = printheader(); + + if (ok) + { + ok = printrow(&rowtoprint); + _currentrow++; + } + + return ok; +} + +bool TPrinter::printheader() +{ + if (_headerhandler) + _headerhandler (*this); + + bool ok = TRUE; + for (int i = 0; i < _headersize && ok; i++) + ok = printrow(getheaderline(i)); + + _currentrow = _headersize + 1; + return ok; +} + +bool TPrinter::printfooter() +{ + if (_footerhandler) + _footerhandler (*this); + + bool ok = TRUE; + for (int i = 0; i < _footersize && ok; i++) + ok = printrow(getfooterline(i)); + +#if XVT_OS != XVT_OS_WIN + if (ok) + printformfeed(); +#endif + + _currentrow = 1; + _currentpage++; + + return ok; +} + +bool TPrinter::skip(int linestoskip) +{ + int jumpline; + + CHECK (linestoskip >= 0, "Linestoskip can't be negative"); + jumpline = _currentrow + linestoskip; + return jump(jumpline); +} + +bool TPrinter::jump(int jumpline) +{ + int i = 0; + bool ok = TRUE; + + CHECK (jumpline >= 0, "Jumpline can't be negative"); + if (jumpline > _formlen - _footersize) + ok = formfeed(); + else + for (i = _currentrow; i < jumpline; i++) + if (!printrow()) + ok = FALSE; + if (jumpline > _formlen - _footersize) + ok = FALSE; + return ok; +} + +bool TPrinter::formfeed() +{ + const int lastrow = _formlen - _footersize; + for (; _currentrow <= lastrow; _currentrow++) + printrow(); + return printfooter(); +} + +void TPrinter::reset() +{ + resetheader(); + resetfooter(); + _currentpage = 1; + _currentrow = 1; +} + +bool TPrinter::printformfeed() +{ +#if XVT_OS != XVT_OS_WIN + const PrinterDef & pd = get_description(_curprn); + + if (_printertype != screenvis && _hwformfeed) + fprintf(_fp, "%s",(const char *)pd._ffcode); +#endif + return TRUE; +} + +bool TPrinter::open() +{ + // qui +#if XVT_OS==XVT_OS_SCOUNIX + if (_printertype == spoolprinter) + { + const PrinterDef & def = get_description(_curprn); + int pfd[2]; + + if (pipe(pfd) == -1) + return error_box ("Impossibile creare processo di stampa " "(pipe)"); + + int ret = fork(); + if (ret == -1) + return error_box("Impossibile creare processo di stampa " "(fork)"); + + if (ret == 0) + { + if ((::close(0) != -1) && (::dup(pfd[0]) == 0) && + (::close(pfd[0]) == 0) && (::close(pfd[1]) != -1)) + { + char s0[80]; + + sprintf (s0, "-d%s", (const char *) def._devicename); + if ((def._filtername).not_empty ()) + { + char s1[80]; + sprintf (s1, "-o %s", (const char *) def._filtername); + char *ws[5] = + {"lpr", "-s", s0, s1, NULL}; + execvp (ws[0], ws); + } + else + { + char *ws[4] = + {"lpr", "-s", s0, NULL}; + execvp(ws[0], ws); + } + exit(-1); + } + } + if ((::close (pfd[0]) == -1) || ((_fp = fdopen(pfd[1], "w")) == NULL)) + return error_box ("Impossibile creare processo di stampa" "(close)"); + } + else +#endif + if (_printertype == screenvis) + { + _vf = new TViswin (NULL, "Anteprima di stampa", TRUE, TRUE, + _linksdescr.items () > 0); + _vf->open_modal (); + } + else if (_printertype == winprinter) + { + // prepare text object for new text + _txt.destroy (); + } + else + { + const PrinterDef & def = get_description (_curprn); + TFilename fname (_printerfile); + + if (_printertype == normprinter) + fname = def._devicename; + _fp = fopen (fname, "w"); + + if (_fp == NULL) + return error_box ("Errore di apertura file stampa: '%s'", + (const char *) fname); + + TString code (def.get_codes (_curcode)); + if (code.not_empty ()) + { + const char *s = code; + fputs (esc ((char *) s), _fp); + } + } + + _currentrow = 1; + _currentpage = 1; + + return _isopen = TRUE; +} + +void TPrinter::set() +{ + main_app().disable_menu_item (M_FILE_PG_SETUP); + + TMask mask ("bagn001a"); + TToken_string pn1 (50), pn2 (100); + int i; + + TFilename defile("printer.def"); +#if XVT_OS == XVT_OS_SCOUNIX + defile << format (".%d", getuid ()); +#endif + mask.set_workfile(defile); + + +#if XVT_OS != XVT_OS_WIN + + for (i = 0; i < _printers.items (); i++) + { + pn1.add (i); + pn2.add (((PrinterDef &) _printers[i])._printername); + } + + ((TList_field &) (mask.field (MSK_1_PRINTERS))).replace_items (pn1, pn2); + mask.hide(MSK_1_SIZE); + mask.hide(MSK_1_LINES); + mask.disable(DLG_SETPRINT); + if (!_multiple_copies) mask.hide(MSK_1_NPAGES); + + pn1 = ""; + pn2 = ""; + + for (i = 0; i < ((PrinterDef &)_printers[_curprn])._names.items(); i++) + { + pn1.add(format ("%d", i)); + pn2.add((TString &)((PrinterDef &) _printers[_curprn])._names[i]); + } + + ((TList_field &)(mask.field (MSK_1_CODES))).replace_items(pn1, pn2); + mask.set_handler (MSK_1_PRINTERS, printers_on_key); + if (_printertype == fileprinter) + mask.set (MSK_1_TYPE, "1"); + else if (_printertype == screenvis) + mask.set (MSK_1_TYPE, "2"); + else + mask.set (MSK_1_TYPE, "0"); + + mask.set(MSK_1_PRINTERS, format("%d", _curprn)); + mask.set(MSK_1_CODES, format("%d", _curcode)); + mask.set(MSK_1_FILENAME, _printerfile); + mask.set(MSK_1_NPAGES, _ncopies); + + KEY k; + + if ((k = mask.run()) == K_ESC) + return; + + if (k == K_INS) // premuto REGISTRA + mask.save(); + + // get user choices + + _curprn = atoi(mask.get(MSK_1_PRINTERS)); + _ncopies = atoi(mask.get(MSK_1_NPAGES)); + + PrinterDef& def = (PrinterDef &) get_description (_curprn); + switch (atoi(mask.get (MSK_1_TYPE))) + { + case 0: // stampante + + _printertype = normprinter; + _curcode = atoi (mask.get (MSK_1_CODES)); + switch (atoi (def._printertype)) + { + case 0: + _printertype = normprinter; + break; + case 1: + _printertype = localprinter; + break; + case 2: + _printertype = spoolprinter; + break; + } + break; + case 1: // file + + _printertype = fileprinter; + _printerfile = mask.get (MSK_1_FILENAME); + _curcode = atoi (mask.get (MSK_1_CODES)); + break; + case 2: // video + + _printertype = screenvis; + _curcode = 0; + break; + } + +#else + + _get_windows_printer_names(pn2); + char old_default[80]; + GetProfileString ("windows", "device", ",,,", old_default, sizeof(old_default)); + + for (i = 0; i < pn2.items (); i++) + pn1.add(i); + + ((TList_field &) (mask.field (MSK_1_PRINTERS))).replace_items(pn1, pn2); + mask.set(MSK_1_PRINTERS, pn1.get(_curprn)); + + mask.hide(MSK_1_CODES); + if (!_multiple_copies) mask.hide(MSK_1_NPAGES); + + mask.set(MSK_1_ISGRAPHICS, _isgraphics ? "X" : ""); + mask.set(MSK_1_SIZE, _ch_size); + mask.set(MSK_1_LINES, _lines_per_inch); + + mask.set(MSK_1_NPAGES, _ncopies); + + if (_printertype == fileprinter) + mask.set (MSK_1_TYPE, "1"); + else if (_printertype == screenvis) + mask.set (MSK_1_TYPE, "2"); + else + mask.set (MSK_1_TYPE, "0"); + + mask.set_handler (MSK_1_PRINTERS, set_windows_print_device); + + KEY k; + int oldprn = _curprn; + + while ((k = mask.run ()) != K_ESC && k != K_ENTER && k != K_INS) + { + if (k == DLG_SETPRINT) + { + // l'handler setta default di windows a quella nel listbox e ribecca l'rcd + if (_print_rcd != NULL) + { + if (page_setup_dlg(_print_rcd)) + { + // see if user has changed printer + // determine index of currently selected printer + // ACTHUNG! Deep hacking of XVT internals! NON PORTABLE! + if (_print_rcd != NULL) + free_print_rcd (_print_rcd); + _print_rcd = get_print_rcd(&_print_rcd_size); + for (i = 0; i < pn2.items(); i++) + if (strcmp((const char *)(_print_rcd + 4), pn2.get(i)) == 0) + { + _curprn = i; + break; + } + + mask.set(MSK_1_PRINTERS, pn1.get(_curprn)); + + set_win_formlen(); + } + mask.set_focus(); + } + else + beep (); + } + } + + _curprn = atoi(mask.get(MSK_1_PRINTERS)); + + if (k == K_INS) + { + // tutto resta com'e' + mask.save (); + } + if (k == K_ESC || k == K_ENTER) + { + // riaggiusta stampante default windows come prima + // curprn e rcd sono quelle di prima + main_app().enable_menu_item(M_FILE_PG_SETUP); + WriteProfileString("windows","device", old_default); + } + if (k == K_ESC) + { + if (_print_rcd != NULL) + free_print_rcd (_print_rcd); + _curprn = oldprn; + _print_rcd = get_print_rcd(&_print_rcd_size); + set_win_formlen(); + return; + } + + _ncopies = atoi (mask.get (MSK_1_NPAGES)); + + switch (atoi (mask.get (MSK_1_TYPE))) + { + case 0: // stampante + + _printertype = winprinter; + break; + case 1: // file + + _printertype = fileprinter; + _printerfile = mask.get (MSK_1_FILENAME); + _curcode = atoi (mask.get (MSK_1_CODES)); + break; + case 2: // video + + _printertype = screenvis; + _curcode = 0; + break; + } + + _isgraphics = mask.get_bool (MSK_1_ISGRAPHICS); + _ch_size = atoi (mask.get (MSK_1_SIZE)); + _lines_per_inch = atoi (mask.get (MSK_1_LINES)); + set_win_formlen (); + +#endif + + main_app().enable_menu_item (M_FILE_PG_SETUP); +} + +void TPrinter::close () +{ + if (isopen () && _currentrow > 1 && + (_footersize || (_printertype != screenvis && _printertype != winprinter))) + formfeed (); + + if (_fp) + { + fclose (_fp); + _fp = NULL; + } + + if (_printertype == screenvis) + { + CHECK (_vf, "VF!"); + _vf->close_print (); + _vf->run (); + if (_vf->is_open ()) + _vf->close_modal (); + delete _vf; + freeze (FALSE); + _vf = NULL; + } +#if XVT_OS == XVT_OS_WIN +else if (_printertype == winprinter) +{ + PrintWhat._prcd = _print_rcd; + PrintWhat._txt = &_txt; + PrintWhat._graphics = _isgraphics; + PrintWhat._charsize = _ch_size; + start_print_thread (start_winprint, (long) (&PrintWhat)); +} +#endif +else if (_printertype == localprinter) +{ +#if XVT_OS == XVT_OS_SCOUNIX + TFilename s1 = tmpnam (NULL); + switch (fork ()) + { + case -1: + break; + case 0: + execlp ("localprint", "localprint", (const char *) s1, NULL); + default: + wait ((int *) NULL); + } + remove (s1); +#endif +} +_isopen = FALSE; +} + +// +// TFile_printer +// + +#include + +#if XVT_OS == XVT_OS_DOS +#define FORMAT_COMMAND "FORMAT" +#else +#define FORMAT_COMMAND "dosformat -fq" +#endif + +const long disk_sizes[] = +{360000, 1200000, 720000, 1400000, 2880000}; + +TFile_printer ::TFile_printer (const char *ffile, const char *label, int len_rec, int num_rec_inizio, int num_rec_fine, int tipo_disco) +{ + set_printtype (fileprinter); + + _num_rec_testa_coda = num_rec_inizio + num_rec_fine; + _file = ffile; + _label = label; + _len_rec = len_rec; + _volume = 1; + _size = disk_sizes[tipo_disco]; + _num_rec_volume = int ((_size / len_rec) - _num_rec_testa_coda); + _nome_file_fissato = TRUE; + _formatta = FALSE; + _label_fissata = TRUE; + +} + +void TFile_printer::open() +{ +} + +void TFile_printer :: +close () +{ +} + +bool TFile_printer :: +genera_dischetti () +{ + int r; + + warning_box ("Questa procedura richiede %2d dischetti", + _volume); + + for (int i = 0; i < _tmp_files.items (); i++) + { + // Avvisa l'utente di inserire un dischetto + r = yesno_box ("Inserire il dischetto n. %2d di %2d nel drive %2s", + i + 1, _volume, _drive); + if (!r) + return error_box ("Procedura interrotta!"); + + // e eventualmente lo formatta + if (_formatta) + { + TString dep (30); + if (_label != NULL) + dep << FORMAT_COMMAND << " " << "/v:" << _label << " " << _drive; + else + dep << FORMAT_COMMAND << " " << _drive; + + TExternal_app sys (dep); + sys.run (); + } + + // copia il file sul dischetto + fcopy ((const char *) &_tmp_files[i], (const char *) _drive); + + } + return TRUE; +} + +TFile_printer::~TFile_printer () +{ +} + +void TFile_printer::set () +{ + TMask m ("bagn004"); + KEY tasto; + int f; + + // + // + // -------------------------------------------------------------------- + // Qui bisogna inserire la lista dei drive disponibili nella maschera + // Per ora tale lista e' fissa e contiene solo A: e B: + // -------------------------------------------------------------------- + // + // + + m.set (F_FILE_DESTINAZIONE, _file); + m.set (F_LABEL, _label); + + if (_nome_file_fissato) + m.disable (F_FILE_DESTINAZIONE); + + if (_label_fissata) + m.disable (F_LABEL); + + tasto = m.run (); + + if (tasto == K_ENTER) + { + f = atoi (m.get (F_FORMATO_DISCO)); + _drive = m.get (F_DRIVE); + _file = m.get (F_FILE_DESTINAZIONE); + _label = m.get (F_LABEL); + _formatta = (bool) (m.get (F_FORMATTA) == "X"); + _size = disk_sizes[f]; + _num_rec_volume = int ((_size / _len_rec) - _num_rec_testa_coda); + } +} + +// +// TFile printer fine +// diff --git a/include/sheet.cpp b/include/sheet.cpp index 400a9ca4a..9359f4c8a 100755 --- a/include/sheet.cpp +++ b/include/sheet.cpp @@ -1,793 +1,793 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -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(); - - 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; 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 (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; get_client_rect(win(), &wr); - RCT br; 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; set_rect(&r, x, y, x+br.right, y+br.bottom); - move_window(_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); - repos_buttons(); - } - TScroll_window::open(); - force_update(); -} - - -void TSheet::set_first(long n) -{ - update_thumb(-1, n); -} - - -void TSheet::set_row(const TToken_string& row, byte i) -{ - if (i > 64) i = 0; else i++; - if (_page.objptr(i) == NULL) - _page.add(row, i); - else - ((TToken_string&)_page[i]) = row; -} - - -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 && 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; - 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() < 1) key = K_ESC; - 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) - { - bool ok = TRUE; - switch(key) - { - case K_SPACE: _checked.not(selected()); break; - case K_F2 : uncheck(-1); break; - case K_F3 : check(-1); break; - default : ok = FALSE; break; - } - if (ok) force_update(); - } - return TScroll_window::on_key(key); -} - - -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) -{ - if (n < 0) - { - if (on) - { - _checked.set(items()-1); // Force the size of Bit_array - _checked.set(); - } - else - _checked.reset(); - } - else - _checked.set(n, on); -} - - -// 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 = (TToken_string&)(_page[i]); - t.restart(); - - const short y = row_to_win(n); - const char* s; - - int x = 0; - for (int j = 0; (s = t.get()) != NULL; x += _size[j++]+1) - { - int x1 = x; - if (n >= 0) - { - if (_checkable && j == 0) - s = _checked[n] ? "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); - } - - 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(COLOR_BLACK, COLOR_WHITE); - set_brush(COLOR_WHITE); - set_pen(COLOR_BLACK); - set_font(FF_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 (get_front_window() == win()) - invert_row(selected()); -} - -void TSheet::print() -{ - TPrinter& pr = MainApp()->printer(); - TPrintrow row; - bool ok = pr.open(); - - set_cursor(TASK_WIN, CURSOR_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); - } - } - set_cursor(TASK_WIN, CURSOR_ARROW); - - 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) -{} - -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, -1); - 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 campi = 0; - for (const char* t = fldlst.get(0); t; t = fldlst.get(), campi++) - if (*t > ' ' && *t != '"') - { - TFieldref fr(t, 0); - TRecfield* rf = new TRecfield(_cursor->curr(fr.file()), - fr.name(), fr.from(), fr.to() - 1); - _fields.add(rf, campi); - } -} - - -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 (byte r = 0; r < rows; r++, ++(*_cursor)) - { - l.cut(0); - const int last = _fields.last(); - for (int i = 0; i <= last; i++) - { - TRecfield* rf = (TRecfield*)_fields.objptr(i); - TFixed_string 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) - { -#if XVT_OS == XVT_OS_WIN - xvt_create_control(WC_EDIT, 1, -3, f->size()+1, 1, f->get(), win(), - CTL_FLAG_DISABLED, 0L, 100); -#else - xvt_create_control(WC_EDIT, 1, -3, f->size()+2, 1, f->get(), win(), - CTL_FLAG_DISABLED, 0L, 100); -#endif - } - - if (s && s->items() > 2) - { - int maxlen = 0; - SLIST lst = slist_new(); - for (const char* item = s->get(0); item; item = s->get()) - { - item = s->get(); - const int len = strlen(item); - if (len > maxlen) maxlen = len; - slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L); - } - - WINDOW listbox = xvt_create_control(WC_LISTBUTTON, f->size()+3, -3, maxlen+3, 3, - "", win(), 0, 0L, 99); - win_list_add(listbox, -1, (char*)lst); - slist_dispose(lst); - - TString16 id; id << f->dlg(); - const int sel = s->get_pos(id) >> 1; - win_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; get_client_rect(win(), &wr); // Get window size - - int left = CHARX; // left coord of next control to draw - - for (int id = 99; id <= 100; id++) - { - const WINDOW w = get_ctl_window(win(), id); - if (w != NULL_WIN) - { - RCT r; get_client_rect(w, &r); - r.left = left; - r.top = wr.bottom - 4*CHARY + 4; - r.right += r.left; - r.bottom += r.top; - move_window(w, &r); - left = r.right+CHARX; // Increase left coord - } - } -} - - -bool TBrowse_sheet::on_key(KEY k) -{ - const WINDOW ctl = get_ctl_window(win(), 100); - const bool alnum = k >= ' ' && k < 256; - - 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) 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) 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(); - set_title(ctl, (char*)(const char*)val); - } - return TRUE; - } - else - { - field().set(""); - if (ctl != NULL_WIN) 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 == 99) - { - const int what = win_list_get_sel_index(ep->v.ctl.ci.win); - if (what >= 0) - stop_run(K_CTRL + what); - else - set_front_window(win); - 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_F9 || key == K_INS) - { - field().set(old); // Restore field status - field().set_dirty(spork); - } - - return key; -} +#include +#include +#include +#include +#include +#include +#include +#include + +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(); + + 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; 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 (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; get_client_rect(win(), &wr); + RCT br; 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; set_rect(&r, x, y, x+br.right, y+br.bottom); + move_window(_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); + repos_buttons(); + } + TScroll_window::open(); + force_update(); +} + + +void TSheet::set_first(long n) +{ + update_thumb(-1, n); +} + + +void TSheet::set_row(const TToken_string& row, byte i) +{ + if (i > 64) i = 0; else i++; + if (_page.objptr(i) == NULL) + _page.add(row, i); + else + ((TToken_string&)_page[i]) = row; +} + + +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 && 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; + 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() < 1) key = K_ESC; + 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) + { + bool ok = TRUE; + switch(key) + { + case K_SPACE: _checked.not(selected()); break; + case K_F2 : uncheck(-1); break; + case K_F3 : check(-1); break; + default : ok = FALSE; break; + } + if (ok) force_update(); + } + return TScroll_window::on_key(key); +} + + +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) +{ + if (n < 0) + { + if (on) + { + _checked.set(items()-1); // Force the size of Bit_array + _checked.set(); + } + else + _checked.reset(); + } + else + _checked.set(n, on); +} + + +// 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 = (TToken_string&)(_page[i]); + t.restart(); + + const short y = row_to_win(n); + const char* s; + + int x = 0; + for (int j = 0; (s = t.get()) != NULL; x += _size[j++]+1) + { + int x1 = x; + if (n >= 0) + { + if (_checkable && j == 0) + s = _checked[n] ? "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); + } + + 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(COLOR_BLACK, COLOR_WHITE); + set_brush(COLOR_WHITE); + set_pen(COLOR_BLACK); + set_font(FF_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 (get_front_window() == win()) + invert_row(selected()); +} + +void TSheet::print() +{ + TPrinter& pr = main_app().printer(); + TPrintrow row; + bool ok = pr.open(); + + set_cursor(TASK_WIN, CURSOR_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); + } + } + set_cursor(TASK_WIN, CURSOR_ARROW); + + 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) +{} + +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, -1); + 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 campi = 0; + for (const char* t = fldlst.get(0); t; t = fldlst.get(), campi++) + if (*t > ' ' && *t != '"') + { + TFieldref fr(t, 0); + TRecfield* rf = new TRecfield(_cursor->curr(fr.file()), + fr.name(), fr.from(), fr.to() - 1); + _fields.add(rf, campi); + } +} + + +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 (byte r = 0; r < rows; r++, ++(*_cursor)) + { + l.cut(0); + const int last = _fields.last(); + for (int i = 0; i <= last; i++) + { + TRecfield* rf = (TRecfield*)_fields.objptr(i); + TFixed_string 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) + { +#if XVT_OS == XVT_OS_WIN + xvt_create_control(WC_EDIT, 1, -3, f->size()+1, 1, f->get(), win(), + CTL_FLAG_DISABLED, 0L, 100); +#else + xvt_create_control(WC_EDIT, 1, -3, f->size()+2, 1, f->get(), win(), + CTL_FLAG_DISABLED, 0L, 100); +#endif + } + + if (s && s->items() > 2) + { + int maxlen = 0; + SLIST lst = slist_new(); + for (const char* item = s->get(0); item; item = s->get()) + { + item = s->get(); + const int len = strlen(item); + if (len > maxlen) maxlen = len; + slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L); + } + + WINDOW listbox = xvt_create_control(WC_LISTBUTTON, f->size()+3, -3, maxlen+3, 3, + "", win(), 0, 0L, 99); + win_list_add(listbox, -1, (char*)lst); + slist_dispose(lst); + + TString16 id; id << f->dlg(); + const int sel = s->get_pos(id) >> 1; + win_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; get_client_rect(win(), &wr); // Get window size + + int left = CHARX; // left coord of next control to draw + + for (int id = 99; id <= 100; id++) + { + const WINDOW w = get_ctl_window(win(), id); + if (w != NULL_WIN) + { + RCT r; get_client_rect(w, &r); + r.left = left; + r.top = wr.bottom - 4*CHARY + 4; + r.right += r.left; + r.bottom += r.top; + move_window(w, &r); + left = r.right+CHARX; // Increase left coord + } + } +} + + +bool TBrowse_sheet::on_key(KEY k) +{ + const WINDOW ctl = get_ctl_window(win(), 100); + const bool alnum = k >= ' ' && k < 256; + + 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) 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) 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(); + set_title(ctl, (char*)(const char*)val); + } + return TRUE; + } + else + { + field().set(""); + if (ctl != NULL_WIN) 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 == 99) + { + const int what = win_list_get_sel_index(ep->v.ctl.ci.win); + if (what >= 0) + stop_run(K_CTRL + what); + else + set_front_window(win); + 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_F9 || key == K_INS) + { + field().set(old); // Restore field status + field().set_dirty(spork); + } + + return key; +} diff --git a/include/strings.cpp b/include/strings.cpp index 9892195cd..274a2e018 100755 --- a/include/strings.cpp +++ b/include/strings.cpp @@ -1,948 +1,950 @@ -#include -#include -#include -#include -#include -#include - -#include -#if XVT_OS==XVT_OS_SCOUNIX -#include -#include -#include -#else -#include -#include -#endif - -#include - -HIDDEN const int MAXSTR = 301; -HIDDEN char __spark[MAXSTR]; // Utility buffer -TFixed_string spark(__spark, MAXSTR); - -// Dinamically resizes a string -// Certified 99% -// It doesn't work for static strings and negative values of size -void TString::resize(int size, bool cpy) -{ - char* s = new char[size+1]; - if (cpy && _str) strcpy(s, _str); - else *s = '\0'; - - if (_str) - delete _str; - - _str = s; - _size = size; -} - -// Set the value for the string -// Certified 99% (uses resize) -TString& TString::set(const char* s) -{ - if (s == NULL) s = ""; - const int sz = *s ? strlen(s) : 7; - if (sz > size()) resize(sz, FALSE); - strcpy(_str, s); - - return *this; -} - -// Eventually expands the string for s more chars -int TString::make_room(int s) -{ - const int lun = len(); - const int spare = size() - lun; - if (spare < s) - resize(size() + 2*s, TRUE); // Melius abundare ... - return lun; -} - -TString::TString(const char* s) : _str(NULL), _size(0) -{ set(s); } - -TString::TString(const TString& s) : _str(NULL), _size(0) -{ set(s); } - -TString::TString(int size) : _str(NULL), _size(0) -{ resize(size, FALSE); } - -TString::TString() : _str(NULL), _size(0) -{ resize(7, FALSE); } - -TString::~TString() -{ - if (_str) - delete _str; -} - -TString& TString::operator <<(const char* s) -{ - if (s && *s) - { - const int pos = make_room(strlen(s)); - strcpy(&_str[pos], s); - } - return *this; -} - -TString& TString::operator <<(char c) -{ - int pos = make_room(1); - _str[pos++] = c; - _str[pos] = '\0'; - return *this; -} - - -TString& TString::operator <<(int n) -{ - char s[16]; - sprintf(s, "%d", n); - return operator <<(s); -} - - -TString& TString::operator <<(long n) -{ - char s[16]; - sprintf(s, "%ld", n); - return operator <<(s); -} - -TString& TString::operator <<(double n) -{ - char s[32]; - sprintf(s, "%lf", n); - return operator <<(s); -} - -// Appends an object to the string -// Certified 50% -// The object should be completely storable in __spark -TString& TString::operator <<(const TObject& obj) -{ - ostrstream out(__spark, MAXSTR); - obj.print_on(out); - out << ends; - return operator <<(__spark); -} - - -TString& TString::operator <<(const TString& str) -{ return operator <<(str._str); } - - -TString& TString::strip(const char* k) -{ - int j = 0; - for (int i = 0; _str[i]; i++) - { - char c = _str[i]; - if (strchr(k, c) == NULL) _str[j++] = c; - } - return cut(j); -} - - -TString& TString::strip_spaces() -{ - char instring = '\0'; - int j = 0; - for (int i = 0; _str[i]; i++) - { - char c = _str[i]; - if (isspace(c) && !instring) continue; - if (c == '"' || c == '\'') - { - if (instring == c) instring = '\0'; - else - if (instring == '\0') instring = c; - } - _str[j++] = c; - } - _str[j] = '\0'; - return *this; -} - -// Certified 100% -const char* TString::class_name() const -{ return "String"; } - -// Certified 100% -word TString::class_id() const -{ return CLASS_STRING; } - -TObject* TString::dup() const -{ - TString* s = new TString(size()); - s->set(_str); - return s; -} - - -void TString::read_from(istream& in) -{ - in >> __tmp_string; - set(__tmp_string); -} - - -// Certified 100% -void TString::print_on(ostream& out) const -{ out << _str; } - - -// Certified 100% -int TString::find(char c, int from) const -{ - CHECKD(from <= len(), "Trying to find past end of string", from); - const char* p = strchr(_str + from, c); - return p ? int(p - _str) : -1; -} - -// Certified 50% -bool TString::match(const char* s) const - -{ - if (strchr(s, '?') == NULL) return operator ==(s); - - for (const char* me = _str; *s && *me; s++, me++) - if (*s != '?' && *s != *me) break; - return *s == '\0' && *me == '\0'; -} - -#if XVT_OS == XVT_OS_SCOUNIX -HIDDEN char* strstr(const char* string1, const char* string2) -{ - const int len = strlen(string2); - while (*string1) - { - if (strncmp(string1, string2, len) == 0) return (char*) string1; - string1++; - } - return NULL; -} -#endif - - -// Certified 100% -int TString::find(const char* s, int from) const -{ - CHECKD(from <= len(), "Trying to find past end of string", from); - const char* p = strstr(_str + from, s); - return p ? int(p - _str) : -1; -} - - -// Certified 99% -const TString& TString::left(int count) const -{ - spark.strncpy(_str, count); - return spark; -} - -// Certified 99% -const TString& TString::right(int count) const -{ - int from = len()-count; - if (from < 0) from = 0; - spark = _str + from; - return spark; -} - - -// Certified 100% -const TString& TString::mid(int from, int count) const -{ - const int l = len(); - -#ifdef DBG - if (from < 0) - { - yesnofatal_box("Ivalid MID parameter: from = %d", from); - from = 0; - } -#endif - - if (from > l) from = l; - if (count < 0) count = l-from; - - spark.strncpy(&_str[from],count); - return spark; -} - - -// Certified 100% -const TString& TString::sub(int from, int to) const -{ - const int count = to-from; - return mid(from, count); -} - -// Certified 100% -TString& TString::cut(int n) -{ - _str[n] = '\0'; - return *this; -} - - -TString& TString::ltrim(int count) -{ - const char* s; - - if (count > 0) - { - if (count >= len()) return cut(0); - s = &_str[count]; - } - else for (s = _str; *s && isspace(*s); s++); - - if (s != _str) strcpy(_str, s); - return *this; -} - -TString& TString::rtrim(int count) -{ - if (count > 0) - { - int i = len() - count; - if (i < 0) i = 0; - cut(i); - } - else - { - char* good = _str-1; - for (char* s = _str; *s; s++) if (!isspace(*s)) good = s; - *(good+1) = '\0'; - } - return *this; -} - -TString& TString::trim() -{ - char* last = _str; - - // Salta spazi iniziali - for (const char* s = _str; *s && isspace(*s); s++); - - // Copia stringa - if (s > _str) - { - for(char* c = _str; *s; s++) - { - *c++ = *s; - if (!isspace(*s)) last = c; - } - // Elimina spazi finali - *last = '\0'; - } - else rtrim(); - - return *this; -} - -// Certified 100% -TString& TString::fill(char c, int n) -{ - if (n < 0) n = size(); else - if (n > size()) resize(n, FALSE); - memset(_str, c, n); - _str[n] = '\0'; - return *this; -} - -// Certified 100% -TString& TString::right_just(int n, char c) -{ - if (n < 0) n = size(); - trim(); - spark = _str; - fill(c, n); - overwrite(spark, n-spark.len()); - - return *this; -} - -// Certified 100% -TString& TString::center_just(int n, char c) -{ - if (n < 0) n = size(); - trim(); - spark = _str; - fill(c, n); - const int p = (n-spark.len()) >> 1; - overwrite(spark, p); - - return *this; -} - -// Certified 100% -TString& TString::left_just(int n, char c) -{ - if (n < 0) n = size(); - trim(); - spark = _str; - fill(c, n); - overwrite(spark, 0); - - return *this; -} - -TString& TString::picture(const char* pic, const char* s) -{ - if (pic == NULL || *pic == '\0') - return set(s); - - set(pic); - - int l = strlen(s)-1; // Prossimo carattere da sostituire a # - - for (int i = len()-1; i >= 0; i--) - { - const char k = pic[i]; - if (k == '#') _str[i] = (l >= 0) ? s[l--] : ' '; - else if (k == '~') { _str[i] = ' '; l--; } - } - - return *this; -} - -// Certified 90% (__spark size limited) -TString& TString::format(const char* fmt, ...) -{ - va_list pars; - va_start(pars, fmt); - const int tot = vsprintf(__spark, fmt, pars); - va_end(pars); - - CHECK(tot >= 0 && tot < spark.size(), "Ue'! Quanto scrivi?"); - if (tot > size()) resize(tot, FALSE); - strcpy(_str, __spark); - - return *this; -} - -// Certified 100% -TString& TString::upper() -{ - for (char* s = _str; *s; s++) *s = toupper(*s); - return *this; -} - -// Certified 100% -TString& TString::lower() -{ - for (char* s = _str; *s; s++) *s = tolower(*s); - return *this; -} - - -// Certified 90% -TString& TString::overwrite(const char* s, int pos) -{ - const int l = len(); - if (pos < 0) pos = l; - const int max = pos+strlen(s); - if (max > size()) resize(max, TRUE); // resize needed? - - const bool over = max > l; // beyond end of string? - for (int i = l; i < pos; i++) _str[i] = ' '; // space padding - for (; *s; s++) _str[pos++] = *s; // write - if (over) _str[pos] = '\0'; // end of string - - return *this; -} - - -// Certified 90% -TString& TString::insert(const char* s, int pos) -{ - if (s && *s) - { - const int l = strlen(s); - make_room(l); - mid(pos); // Scrivi in spark la stringa da pos in poi - overwrite(s, pos); // Aggiungi s - strcpy(&_str[pos+l], spark); // Aggiungi spark - } - return *this; -} - -// Villa's megasmart hash function -// Certified 90% -word TString::hash() const -{ - word h = 0x0000; - for (int i = 0; _str[i]; i++) - h ^= (i & 0x1) ? (_str[i] << 8) : _str[i]; - return h; -} - -/////////////////////////////////////////////////////////// -// TFixed_string -/////////////////////////////////////////////////////////// - -// Certified 100% -TFixed_string::TFixed_string(const char* str, int size) -: TString((char*)str, (size < 1) ? strlen(str) : size-1) -{ - if (size > 0 && memchr(str, '\0', size) == NULL) - cut(0); -} - - -// Certified 100% -TFixed_string::~TFixed_string() -{ _str = NULL; } // Impedisce la deallocazione - - -// Certified 100% -void TFixed_string::resize(int size, bool) -{ -#ifdef DBG - fatal_box("Impossibile ridimensionare una stringa fissa da %d a %d caratteri:\n'%s'", - _size, size, _str); -#endif -} - - -// Certified 99% (s != NULL) -void TFixed_string::strncpy(const char* s, int n) -{ - CHECKD(n <= _size, "Fixed string can't be strncpyed: lenght ", n); - for (int i = 0; *s && i < n; i++) _str[i] = *s++; - _str[i] = '\0'; -} - -// Certified 99% -// More efficient than TString::format, it does not use spark -TString& TFixed_string::format(const char* fmt, ...) -{ - va_list pars; - va_start(pars, fmt); - const int tot = vsprintf(_str, fmt, pars); - va_end(pars); - CHECK(tot >= 0 && tot < size(), "Ue'! Quanto scrivi con 'sta format?"); - return *this; -} - - - -/////////////////////////////////////////////////////////// -// Filename -/////////////////////////////////////////////////////////// - -inline bool is_not_slash(char s) -{ return s != '\\' && s != '/'; } - -// Certified 90% -const char* TFilename::ext() const -{ - const char* d = strrchr(name(), '.'); - if (d && is_not_slash(*(++d))) return d; - return ""; -} - -// Certified 90% -void TFilename::ext(const char* e) -{ - char* d = strrchr(name(), '.'); - if (d && is_not_slash(*(d+1))) *d = '\0'; - - if (*e && *e != '.') *this << "."; - *this << e; -} - - -// Certified 90% -const char* TFilename::name() const -{ - const char* d = strrchr(_str, '\\'); - if (d == NULL) d = strrchr(_str, '/'); - if (d == NULL) d = strchr(_str, ':'); - if (d == NULL) d = _str-1; - return d+1; -} - -// Certified 90% -const char* TFilename::path() const -{ - const char* d = strrchr(_str, '\\'); - if (d == NULL) d = strrchr(_str, '/'); - if (d == NULL) - { - d = strchr(_str, ':'); - if (d != NULL) d++; - } - if (d == NULL) spark.cut(0); - else spark.strncpy(_str, d - _str); - return spark; -} - -// Certified 70% -const TFilename& TFilename::tempdir() -{ - const char* dirpref = getenv("TEMP"); - if (dirpref == NULL) dirpref = getenv("TMP"); - if (dirpref == NULL) dirpref = "/tmp"; - set(dirpref); - const int last = len()-1; - - if (!is_not_slash(_str[last])) cut(last); - if (!fexist(_str)) - { - int res = -#if XVT_OS==XVT_OS_SCOUNIX - mkdir(_str, 0777); -#else - mkdir(_str); -#endif - if (res != 0) - fatal_box("Impossibile creare la directory '%s' per i file temporanei", _str); - } - if (not_empty()) *this << "/" ; - TString16 u(main_app().user()); - - u.lower(); - *this << u; - if (!fexist(_str)) - { - int res = -#if XVT_OS==XVT_OS_SCOUNIX - mkdir(_str, 0777); -#else - mkdir(_str); -#endif - // if (res == 0) - // message_box("E' stata creata la directory per i file temporanei '%s'", _str); - // else - if (res != 0) - fatal_box("Impossibile creare la directory '%s' per i file temporanei", _str); - } - return *this; -} - - -// Certified 50% -const TFilename& TFilename::temp(const char* prefix) -{ - const TFilename dirpref(tempdir()); - char* t = NULL; - - if (prefix) - { - set(prefix); // Copia prefisso e ... - strip("$#"); // ... toglie caratteri jolly - - const TFixed_string f(prefix); -#if XVT_OS==XVT_OS_SCOUNIX - if (f.find("$$") != -1) *this << getpid(); - if (f.find("##") != -1) *this << getuid(); -#else - if (f.find("$$") != -1) - { - char pid[8]; - sprintf(pid, "%d", getpid()); - pid[3] = '\0'; - *this << pid; - } -#endif - - t = tempnam((char*)(const char*)dirpref, (char*)_str); - } - else - t = tempnam((char*)(const char*)dirpref, NULL); - - set(t); - -#ifdef DBG - if (fexist(_str)) - fatal_box("Il file '%s' esiste gia'", _str); -#endif - if (t) free(t); - - return *this; -} - - -/////////////////////////////////////////////////////////// -// Token string -/////////////////////////////////////////////////////////// - -// Certified 100% -TToken_string::TToken_string(const char* s, char separator) -: TString(s), _separator(separator) -{ - restart(); -} - -// Certified 100% -TToken_string::TToken_string(int n, char separator) -: TString(n), _separator(separator), _last(0) -{} - -// Certified 100% -TToken_string::TToken_string(const TToken_string& s) -: TString(s), _separator(s._separator), _last(s._last) -{} - - -// Certified 100% -TObject* TToken_string::dup() const -{ - return new TToken_string(_str, _separator); -} - -// Certified 90% -const char* TToken_string::get() -{ - if (_last < 0) return NULL; - - const int start = _last; - - if (_str[start] == '\0') - { - _last = -1; - return NULL; - } - else - if (_str[start] == _separator) - { - _last = start+1; - } - else - { - const int k = find(_separator, start); - _last = (k >= 0) ? k+1 : -1; - return sub(start, k); - } - return ""; -} - -// Certified 50% -const char* TToken_string::get(int n) -{ - if (n < 0) - { - if (n == -2) - { - const char* sep = strrchr(_str, _separator); - _last = -1; - return sep ? sep+1 : _str; - } - else return get(); - } - int sep = 0; - for (const char* s = _str; sep < n && *s; s++) - if (*s == _separator) sep++; - - if (sep >= n) - { - char* p = strchr(s, _separator); - if (p == NULL) - { - spark = s; - _last = -1; - } - else - { - *p = '\0'; - spark = s; - *p = _separator; - _last = (int)((const char*)p - _str) + 1; - } - } - else - { - _last = -1; - return NULL; - } - - return spark; -} - - -// Certified 99% -char TToken_string::get_char(int n) -{ - const char* const car = get(n); - return car ? *car : '\0'; -} - -// Certified 99% -int TToken_string::get_int(int n) -{ - const char* const num = get(n); - return num ? atoi(num) : 0; -} - - -// Certified 99% -long TToken_string::get_long(int n) -{ - const char* const num = get(n); - return num ? atol(num) : 0L; -} - - -// Certified 70% -bool TToken_string::set_item(const char* v, int n) -{ - int sep = 0; - for (int i = 0; sep < n && _str[i]; i++) - if (_str[i] == _separator) sep++; - - if (sep < n) // Aggiunge items mancanti prima della posizione n - { - for (;sep < n; sep++) *this << _separator; - *this << v; - return FALSE; - } - - int e = find(_separator, i); - if (e < 0) e = len(); - - spark = &_str[e]; // Salva items seguenti - cut(i); // Considera solo items precedenti - *this << v << spark; // Aggiunge item desiderato e seguenti - return TRUE; -} - - -// Certified 80% -int TToken_string::get_pos(const char* s) -{ - const char* item; - - restart(); - for (int i = 0; (item = get()) != NULL; i++) - if (strcmp(item, s) == 0) return i; - - return -1; -} - - -// Certified 90% -bool TToken_string::empty_items() const -{ - for (const char* c = _str; *c; c++) - if (!isspace(*c) && *c != _separator) return FALSE; - return TRUE; -} - - -// Certified 80% -int TToken_string::items() const -{ - int t = 0; - if (not_empty()) - { - t++; - for (const char* s = _str; *s; s++) - if (*s == _separator) t++; - } - return t; -} - -// Adds an item to the token string -// Certified 99% -void TToken_string::add(const char* s, int pos) -{ - if (s == NULL || *s == '\0') s = " "; - if (pos < 0) - { - if (not_empty()) *this << _separator; - *this << s; - } - else - set_item(s, pos); - if (_last < 0) _last = 0; -} - -// Certified 0% -void TToken_string::add(char c, int pos) -{ - const char s[2] = { c, '\0' }; - add(s, pos); -} - -// Adds an integer value to the token string -// Certified 100% -void TToken_string::add(long n, int pos) -{ - char s[16]; - sprintf(s, "%ld", n); - add(s, pos); -} - -void TToken_string::add(int n, int pos) -{ - char s[16]; - sprintf(s, "%d", n); - add(s, pos); -} - -// Certified 50% -void TToken_string::destroy(int n) -{ - if (_last == -2) return ; - - if (n < 0) - { - char* s = strrchr(_str, _separator); - if (s != NULL) *s = '\0'; - } - else - { - int sep = 0; - for (char* s = _str; sep < n && *s; s++) - if (*s == _separator) sep++; - - if (sep >= n) - { - const char* p = strchr(s, _separator); - *s = '\0'; - if (p != NULL) strcat(s, p+1); - } - } - restart(); -} - -/////////////////////////////////////////////////////////// -// Paragraph string -/////////////////////////////////////////////////////////// - -TParagraph_string::TParagraph_string(const char* s, int width) -: TToken_string(s, '|'), _width(width) -{ tokenize(); } - -const TString& TParagraph_string::operator =(const char* s) -{ - TToken_string::operator=(s); - tokenize(); - return *this; -} - -void TParagraph_string::tokenize() -{ - int start = 0; - for (int end = start+_width; end < len(); end = start+_width) - { - for (int i = end; i >= start; i--) - if (isspace(_str[i])) break; - - if (i < start) - { - insert("|", end); - start = end+1; - } - else - { - _str[i] = '|'; - start = i+1; - } - } -} +#include +#include +#include +#include +#include +#include + +#include +#if XVT_OS==XVT_OS_SCOUNIX +#include +#include +#include +#else +#include +#include +#endif + +#include + +HIDDEN const int MAXSTR = 301; +HIDDEN char __spark[MAXSTR]; // Utility buffer +TFixed_string spark(__spark, MAXSTR); + +// Dinamically resizes a string +// Certified 99% +// It doesn't work for static strings and negative values of size +void TString::resize(int size, bool cpy) +{ + char* s = new char[size+1]; + if (cpy && _str) strcpy(s, _str); + else *s = '\0'; + + if (_str) + delete _str; + + _str = s; + _size = size; +} + +// Set the value for the string +// Certified 99% (uses resize) +TString& TString::set(const char* s) +{ + if (s == NULL) s = ""; + const int sz = *s ? strlen(s) : 7; + if (sz > size()) resize(sz, FALSE); + strcpy(_str, s); + + return *this; +} + +// Eventually expands the string for s more chars +int TString::make_room(int s) +{ + const int lun = len(); + const int spare = size() - lun; + if (spare < s) + resize(size() + 2*s, TRUE); // Melius abundare ... + return lun; +} + +TString::TString(const char* s) : _str(NULL), _size(0) +{ set(s); } + +TString::TString(const TString& s) : _str(NULL), _size(0) +{ set(s); } + +TString::TString(int size) : _str(NULL), _size(0) +{ resize(size, FALSE); } + +TString::TString() : _str(NULL), _size(0) +{ resize(7, FALSE); } + +TString::~TString() +{ + if (_str) + delete _str; +} + +TString& TString::operator <<(const char* s) +{ + if (s && *s) + { + const int pos = make_room(strlen(s)); + strcpy(&_str[pos], s); + } + return *this; +} + +TString& TString::operator <<(char c) +{ + int pos = make_room(1); + _str[pos++] = c; + _str[pos] = '\0'; + return *this; +} + + +TString& TString::operator <<(int n) +{ + char s[16]; + sprintf(s, "%d", n); + return operator <<(s); +} + + +TString& TString::operator <<(long n) +{ + char s[16]; + sprintf(s, "%ld", n); + return operator <<(s); +} + +TString& TString::operator <<(double n) +{ + char s[32]; + sprintf(s, "%lf", n); + return operator <<(s); +} + +// Appends an object to the string +// Certified 50% +// The object should be completely storable in __spark +TString& TString::operator <<(const TObject& obj) +{ + ostrstream out(__spark, MAXSTR); + obj.print_on(out); + out << ends; + return operator <<(__spark); +} + + +TString& TString::operator <<(const TString& str) +{ return operator <<(str._str); } + + +TString& TString::strip(const char* k) +{ + int j = 0; + for (int i = 0; _str[i]; i++) + { + char c = _str[i]; + if (strchr(k, c) == NULL) _str[j++] = c; + } + return cut(j); +} + + +TString& TString::strip_spaces() +{ + char instring = '\0'; + int j = 0; + for (int i = 0; _str[i]; i++) + { + char c = _str[i]; + if (isspace(c) && !instring) continue; + if (c == '"' || c == '\'') + { + if (instring == c) instring = '\0'; + else + if (instring == '\0') instring = c; + } + _str[j++] = c; + } + _str[j] = '\0'; + return *this; +} + +// Certified 100% +const char* TString::class_name() const +{ return "String"; } + +// Certified 100% +word TString::class_id() const +{ return CLASS_STRING; } + +TObject* TString::dup() const +{ + TString* s = new TString(size()); + s->set(_str); + return s; +} + + +void TString::read_from(istream& in) +{ + in >> __tmp_string; + set(__tmp_string); +} + + +// Certified 100% +void TString::print_on(ostream& out) const +{ out << _str; } + + +// Certified 100% +int TString::find(char c, int from) const +{ + CHECKD(from <= len(), "Trying to find past end of string", from); + const char* p = strchr(_str + from, c); + return p ? int(p - _str) : -1; +} + +// Certified 50% +bool TString::match(const char* s) const + +{ + if (strchr(s, '?') == NULL) return operator ==(s); + + for (const char* me = _str; *s && *me; s++, me++) + if (*s != '?' && *s != *me) break; + return *s == '\0' && *me == '\0'; +} + +#if XVT_OS == XVT_OS_SCOUNIX +HIDDEN char* strstr(const char* string1, const char* string2) +{ + const int len = strlen(string2); + while (*string1) + { + if (strncmp(string1, string2, len) == 0) return (char*) string1; + string1++; + } + return NULL; +} +#endif + + +// Certified 100% +int TString::find(const char* s, int from) const +{ + CHECKD(from <= len(), "Trying to find past end of string", from); + const char* p = strstr(_str + from, s); + return p ? int(p - _str) : -1; +} + + +// Certified 99% +const TString& TString::left(int count) const +{ + spark.strncpy(_str, count); + return spark; +} + +// Certified 99% +const TString& TString::right(int count) const +{ + int from = len()-count; + if (from < 0) from = 0; + spark = _str + from; + return spark; +} + + +// Certified 100% +const TString& TString::mid(int from, int count) const +{ + const int l = len(); + +#ifdef DBG + if (from < 0) + { + yesnofatal_box("Ivalid MID parameter: from = %d", from); + from = 0; + } +#endif + + if (from > l) from = l; + if (count < 0) count = l-from; + + spark.strncpy(&_str[from],count); + return spark; +} + + +// Certified 100% +const TString& TString::sub(int from, int to) const +{ + const int count = to-from; + return mid(from, count); +} + +// Certified 100% +TString& TString::cut(int n) +{ + _str[n] = '\0'; + return *this; +} + + +TString& TString::ltrim(int count) +{ + const char* s; + + if (count > 0) + { + if (count >= len()) return cut(0); + s = &_str[count]; + } + else for (s = _str; *s && isspace(*s); s++); + + if (s != _str) strcpy(_str, s); + return *this; +} + +TString& TString::rtrim(int count) +{ + if (count > 0) + { + int i = len() - count; + if (i < 0) i = 0; + cut(i); + } + else + { + char* good = _str-1; + for (char* s = _str; *s; s++) if (!isspace(*s)) good = s; + *(good+1) = '\0'; + } + return *this; +} + +TString& TString::trim() +{ + char* last = _str; + + // Salta spazi iniziali + for (const char* s = _str; *s && isspace(*s); s++); + + // Copia stringa + if (s > _str) + { + for(char* c = _str; *s; s++) + { + *c++ = *s; + if (!isspace(*s)) last = c; + } + // Elimina spazi finali + *last = '\0'; + } + else rtrim(); + + return *this; +} + +// Certified 100% +TString& TString::fill(char c, int n) +{ + if (n < 0) n = size(); else + if (n > size()) resize(n, FALSE); + memset(_str, c, n); + _str[n] = '\0'; + return *this; +} + +// Certified 100% +TString& TString::right_just(int n, char c) +{ + if (n < 0) n = size(); + trim(); + spark = _str; + fill(c, n); + overwrite(spark, n-spark.len()); + + return *this; +} + +// Certified 100% +TString& TString::center_just(int n, char c) +{ + if (n < 0) n = size(); + trim(); + spark = _str; + fill(c, n); + const int p = (n-spark.len()) >> 1; + overwrite(spark, p); + + return *this; +} + +// Certified 100% +TString& TString::left_just(int n, char c) +{ + if (n < 0) n = size(); + trim(); + spark = _str; + fill(c, n); + overwrite(spark, 0); + + return *this; +} + +TString& TString::picture(const char* pic, const char* s) +{ + if (pic == NULL || *pic == '\0') + return set(s); + + set(pic); + + int l = strlen(s)-1; // Prossimo carattere da sostituire a # + + for (int i = len()-1; i >= 0; i--) + { + const char k = pic[i]; + if (k == '#') _str[i] = (l >= 0) ? s[l--] : ' '; + else if (k == '~') { _str[i] = ' '; l--; } + } + + return *this; +} + +// Certified 90% (__spark size limited) +TString& TString::format(const char* fmt, ...) +{ + va_list pars; + va_start(pars, fmt); + const int tot = vsprintf(__spark, fmt, pars); + va_end(pars); + + CHECK(tot >= 0 && tot < spark.size(), "Ue'! Quanto scrivi?"); + if (tot > size()) resize(tot, FALSE); + strcpy(_str, __spark); + + return *this; +} + +// Certified 100% +TString& TString::upper() +{ + for (char* s = _str; *s; s++) *s = toupper(*s); + return *this; +} + +// Certified 100% +TString& TString::lower() +{ + for (char* s = _str; *s; s++) *s = tolower(*s); + return *this; +} + + +// Certified 90% +TString& TString::overwrite(const char* s, int pos) +{ + const int l = len(); + if (pos < 0) pos = l; + const int max = pos+strlen(s); + if (max > size()) resize(max, TRUE); // resize needed? + + const bool over = max > l; // beyond end of string? + for (int i = l; i < pos; i++) _str[i] = ' '; // space padding + for (; *s; s++) _str[pos++] = *s; // write + if (over) _str[pos] = '\0'; // end of string + + return *this; +} + + +// Certified 90% +TString& TString::insert(const char* s, int pos) +{ + if (s && *s) + { + const int l = strlen(s); + make_room(l); + mid(pos); // Scrivi in spark la stringa da pos in poi + overwrite(s, pos); // Aggiungi s + strcpy(&_str[pos+l], spark); // Aggiungi spark + } + return *this; +} + +// Villa's megasmart hash function +// Certified 90% +word TString::hash() const +{ + word h = 0x0000; + for (int i = 0; _str[i]; i++) + h ^= (i & 0x1) ? (_str[i] << 8) : _str[i]; + return h; +} + +/////////////////////////////////////////////////////////// +// TFixed_string +/////////////////////////////////////////////////////////// + +// Certified 100% +TFixed_string::TFixed_string(const char* str, int size) +: TString((char*)str, (size < 1) ? strlen(str) : size-1) +{ + if (size > 0 && memchr(str, '\0', size) == NULL) + cut(0); +} + + +// Certified 100% +TFixed_string::~TFixed_string() +{ _str = NULL; } // Impedisce la deallocazione + + +// Certified 100% +void TFixed_string::resize(int size, bool) +{ +#ifdef DBG + fatal_box("Impossibile ridimensionare una stringa fissa da %d a %d caratteri:\n'%s'", + _size, size, _str); +#endif +} + + +// Certified 99% (s != NULL) +void TFixed_string::strncpy(const char* s, int n) +{ + CHECKD(n <= _size, "Fixed string can't be strncpyed: lenght ", n); + for (int i = 0; *s && i < n; i++) _str[i] = *s++; + _str[i] = '\0'; +} + +// Certified 99% +// More efficient than TString::format, it does not use spark +TString& TFixed_string::format(const char* fmt, ...) +{ + va_list pars; + va_start(pars, fmt); + const int tot = vsprintf(_str, fmt, pars); + va_end(pars); + CHECK(tot >= 0 && tot < size(), "Ue'! Quanto scrivi con 'sta format?"); + return *this; +} + + + +/////////////////////////////////////////////////////////// +// Filename +/////////////////////////////////////////////////////////// + +inline bool is_not_slash(char s) +{ return s != '\\' && s != '/'; } + +// Certified 90% +const char* TFilename::ext() const +{ + const char* d = strrchr(name(), '.'); + if (d && is_not_slash(*(++d))) return d; + return ""; +} + +// Certified 90% +void TFilename::ext(const char* e) +{ + char* d = strrchr(name(), '.'); + if (d && is_not_slash(*(d+1))) *d = '\0'; + + if (*e && *e != '.') *this << "."; + *this << e; +} + + +// Certified 90% +const char* TFilename::name() const +{ + const char* d = strrchr(_str, '\\'); + if (d == NULL) d = strrchr(_str, '/'); + if (d == NULL) d = strchr(_str, ':'); + if (d == NULL) d = _str-1; + return d+1; +} + +// Certified 90% +const char* TFilename::path() const +{ + const char* d = strrchr(_str, '\\'); + if (d == NULL) d = strrchr(_str, '/'); + if (d == NULL) + { + d = strchr(_str, ':'); + if (d != NULL) d++; + } + if (d == NULL) spark.cut(0); + else spark.strncpy(_str, d - _str); + return spark; +} + +// Certified 70% +const TFilename& TFilename::tempdir() +{ + const char* dirpref = getenv("TEMP"); + if (dirpref == NULL) dirpref = getenv("TMP"); + if (dirpref == NULL) dirpref = "/tmp"; + set(dirpref); + const int last = len()-1; + + if (!is_not_slash(_str[last])) cut(last); + + int res = 0; + + if (!fexist(_str)) + { + res = +#if XVT_OS==XVT_OS_SCOUNIX + mkdir(_str, 0777); +#else + mkdir(_str); +#endif + } + + if (res == 0) + { + if (not_empty()) *this << "/" ; + *this << main_app().user(); + lower(); + if (!fexist(_str)) + { + res = +#if XVT_OS==XVT_OS_SCOUNIX + mkdir(_str, 0777); +#else + mkdir(_str); +#endif + } + } + + if (res != 0) + fatal_box("Impossibile creare la directory '%s' per i file temporanei", _str); + + return *this; +} + + +// Certified 50% +const TFilename& TFilename::temp(const char* prefix) +{ + const TFilename dirpref(tempdir()); + char* t = NULL; + + if (prefix) + { + set(prefix); // Copia prefisso e ... + strip("$#"); // ... toglie caratteri jolly + + const TFixed_string f(prefix); +#if XVT_OS==XVT_OS_SCOUNIX + if (f.find("$$") != -1) *this << getpid(); + if (f.find("##") != -1) *this << getuid(); +#else + if (f.find("$$") != -1) + { + char pid[8]; + sprintf(pid, "%d", getpid()); + pid[3] = '\0'; + *this << pid; + } +#endif + + t = tempnam((char*)(const char*)dirpref, (char*)_str); + } + else + t = tempnam((char*)(const char*)dirpref, NULL); + + set(t); + +#ifdef DBG + if (fexist(_str)) + fatal_box("Il file '%s' esiste gia'", _str); +#endif + if (t) free(t); + + return *this; +} + + +/////////////////////////////////////////////////////////// +// Token string +/////////////////////////////////////////////////////////// + +// Certified 100% +TToken_string::TToken_string(const char* s, char separator) +: TString(s), _separator(separator) +{ + restart(); +} + +// Certified 100% +TToken_string::TToken_string(int n, char separator) +: TString(n), _separator(separator), _last(0) +{} + +// Certified 100% +TToken_string::TToken_string(const TToken_string& s) +: TString(s), _separator(s._separator), _last(s._last) +{} + + +// Certified 100% +TObject* TToken_string::dup() const +{ + return new TToken_string(_str, _separator); +} + +// Certified 90% +const char* TToken_string::get() +{ + if (_last < 0) return NULL; + + const int start = _last; + + if (_str[start] == '\0') + { + _last = -1; + return NULL; + } + else + if (_str[start] == _separator) + { + _last = start+1; + } + else + { + const int k = find(_separator, start); + _last = (k >= 0) ? k+1 : -1; + return sub(start, k); + } + return ""; +} + +// Certified 50% +const char* TToken_string::get(int n) +{ + if (n < 0) + { + if (n == -2) + { + const char* sep = strrchr(_str, _separator); + _last = -1; + return sep ? sep+1 : _str; + } + else return get(); + } + int sep = 0; + for (const char* s = _str; sep < n && *s; s++) + if (*s == _separator) sep++; + + if (sep >= n) + { + char* p = strchr(s, _separator); + if (p == NULL) + { + spark = s; + _last = -1; + } + else + { + *p = '\0'; + spark = s; + *p = _separator; + _last = (int)((const char*)p - _str) + 1; + } + } + else + { + _last = -1; + return NULL; + } + + return spark; +} + + +// Certified 99% +char TToken_string::get_char(int n) +{ + const char* const car = get(n); + return car ? *car : '\0'; +} + +// Certified 99% +int TToken_string::get_int(int n) +{ + const char* const num = get(n); + return num ? atoi(num) : 0; +} + + +// Certified 99% +long TToken_string::get_long(int n) +{ + const char* const num = get(n); + return num ? atol(num) : 0L; +} + + +// Certified 70% +bool TToken_string::set_item(const char* v, int n) +{ + int sep = 0; + for (int i = 0; sep < n && _str[i]; i++) + if (_str[i] == _separator) sep++; + + if (sep < n) // Aggiunge items mancanti prima della posizione n + { + for (;sep < n; sep++) *this << _separator; + *this << v; + return FALSE; + } + + int e = find(_separator, i); + if (e < 0) e = len(); + + spark = &_str[e]; // Salva items seguenti + cut(i); // Considera solo items precedenti + *this << v << spark; // Aggiunge item desiderato e seguenti + return TRUE; +} + + +// Certified 80% +int TToken_string::get_pos(const char* s) +{ + const char* item; + + restart(); + for (int i = 0; (item = get()) != NULL; i++) + if (strcmp(item, s) == 0) return i; + + return -1; +} + + +// Certified 90% +bool TToken_string::empty_items() const +{ + for (const char* c = _str; *c; c++) + if (!isspace(*c) && *c != _separator) return FALSE; + return TRUE; +} + + +// Certified 80% +int TToken_string::items() const +{ + int t = 0; + if (not_empty()) + { + t++; + for (const char* s = _str; *s; s++) + if (*s == _separator) t++; + } + return t; +} + +// Adds an item to the token string +// Certified 99% +void TToken_string::add(const char* s, int pos) +{ + if (s == NULL || *s == '\0') s = " "; + if (pos < 0) + { + if (not_empty()) *this << _separator; + *this << s; + } + else + set_item(s, pos); + if (_last < 0) _last = 0; +} + +// Certified 0% +void TToken_string::add(char c, int pos) +{ + const char s[2] = { c, '\0' }; + add(s, pos); +} + +// Adds an integer value to the token string +// Certified 100% +void TToken_string::add(long n, int pos) +{ + char s[16]; + sprintf(s, "%ld", n); + add(s, pos); +} + +void TToken_string::add(int n, int pos) +{ + char s[16]; + sprintf(s, "%d", n); + add(s, pos); +} + +// Certified 50% +void TToken_string::destroy(int n) +{ + if (_last == -2) return ; + + if (n < 0) + { + char* s = strrchr(_str, _separator); + if (s != NULL) *s = '\0'; + } + else + { + int sep = 0; + for (char* s = _str; sep < n && *s; s++) + if (*s == _separator) sep++; + + if (sep >= n) + { + const char* p = strchr(s, _separator); + *s = '\0'; + if (p != NULL) strcat(s, p+1); + } + } + restart(); +} + +/////////////////////////////////////////////////////////// +// Paragraph string +/////////////////////////////////////////////////////////// + +TParagraph_string::TParagraph_string(const char* s, int width) +: TToken_string(s, '|'), _width(width) +{ tokenize(); } + +const TString& TParagraph_string::operator =(const char* s) +{ + TToken_string::operator=(s); + tokenize(); + return *this; +} + +void TParagraph_string::tokenize() +{ + int start = 0; + for (int end = start+_width; end < len(); end = start+_width) + { + for (int i = end; i >= start; i--) + if (isspace(_str[i])) break; + + if (i < start) + { + insert("|", end); + start = end+1; + } + else + { + _str[i] = '|'; + start = i+1; + } + } +} diff --git a/include/validate.cpp b/include/validate.cpp index 0896e68e2..540f22691 100755 --- a/include/validate.cpp +++ b/include/validate.cpp @@ -1,591 +1,591 @@ -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -typedef bool (*VAL_FUNC)(TEdit_field&, KEY k); -HIDDEN const TArray* _parms; - -HIDDEN int get_val_param_num() { return _parms->items(); } - -HIDDEN const char* get_val_param(int i) -{ return i < _parms->items() ? (const char*)((const TString&) (*_parms)[i]):"" ; } - -HIDDEN bool _expr_val(TEdit_field& f, KEY) -{ - TTypeexp type = atoi(get_val_param(0)) == 0 ? _numexpr :_strexpr; - TExpression e(get_val_param(1), type); - - for (int i = 0 ; i < e.numvar(); i++) - { - const char* s = e.varname(i); - if (s[0] != '#') - { - TString80 err; err << "Non trovo la variabile " << s << " in " << e; - return f.error_box((const char*)err); - } - s++; - const int fldid = atoi(s); - if (type == _numexpr) - { - const real r(fldid == 0 ? f.get() : f.mask().get(fldid)); - e.setvar(i, r); - } - else - { - const char* v = fldid == 0 ? f.get() : f.mask().get(fldid); - e.setvar(i, v); - } - } - return bool(e); -} - - -HIDDEN bool _emptycopy_val(TEdit_field& f, KEY) -{ - if (f.get().empty()) - { - const short id = atoi(get_val_param(0)); - const TFixed_string val(f.mask().get(id)); - if (val.not_empty()) - { - f.set(val); - f.on_hit(); - } - } - return TRUE; -} - - -bool pi_check(const char * st, const char * paiva) -{ - int tot = 0, y; - TString16 stato (st); - TString16 pi (paiva); - - if ((stato.not_empty()) && (stato != "IT")) return TRUE; - if (pi.empty()) return TRUE; - if (pi.len() != 11) - return FALSE; - - for (int i = 0; i <= 9; i++) - { - if ((i + 1) & 0x0001) tot += (pi[i] - '0'); - else - { - y = (pi[i] - '0') * 2; - if (y >= 10) - { - tot += (y / 10); - y = y % 10; - } - tot += y; - } - } - y = 10 - (tot % 10); - if (y == 10) y = 0; - bool ok = (pi[10] == (y + '0')); - - return ok; -} - - -// Controlla la partita iva se e' non vuota ed italiana -HIDDEN bool _pi_val(TEdit_field& f, KEY) -{ - if (f.mask().query_mode()) return TRUE; - - TString16 stato(f.mask().get(atoi(get_val_param(0)))), pi(f.get()); - - if (stato.not_empty() && stato != "IT") return TRUE; - if (pi.empty()) return TRUE; - if (pi.len() != 11) - { - f.error_box("Lunghezza partita IVA diversa da 11"); - return FALSE; - } - - bool ok = pi_check (stato, pi); - if (!ok) - { - if(f.dirty()) - { - ok = f.yesno_box("Partita IVA errata, la accetto ugualmente?"); - if (ok) f.set_dirty(FALSE); - } - else ok = TRUE; // Era gia' errata e la ho accettata - } - return ok; -} - - -HIDDEN bool __cf_check (const char * codcf) -{ - const TString16 cf (codcf); - if (cf.len() != 16) return FALSE; - - const TFixed_string tab("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); - - int tot = 0, y; - - byte val[36][2]; - - val[0][0] = 0; val[0][1] = 1; - val[1][0] = 1; val[1][1] = 0; - val[2][0] = 2; val[2][1] = 5; - val[3][0] = 3; val[3][1] = 7; - val[4][0] = 4; val[4][1] = 9; - val[5][0] = 5; val[5][1] = 13; - val[6][0] = 6; val[6][1] = 15; - val[7][0] = 7; val[7][1] = 17; - val[8][0] = 8; val[8][1] = 19; - val[9][0] = 9; val[9][1] = 21; - val[10][0] = 10; val[10][1] = 2; - val[11][0] = 11; val[11][1] = 4; - val[12][0] = 12; val[12][1] = 18; - val[13][0] = 13; val[13][1] = 20; - val[14][0] = 14; val[14][1] = 11; - val[15][0] = 15; val[15][1] = 3; - val[16][0] = 16; val[16][1] = 6; - val[17][0] = 17; val[17][1] = 8; - val[18][0] = 18; val[18][1] = 12; - val[19][0] = 19; val[19][1] = 14; - val[20][0] = 20; val[20][1] = 16; - val[21][0] = 21; val[21][1] = 10; - val[22][0] = 22; val[22][1] = 22; - val[23][0] = 23; val[23][1] = 25; - val[24][0] = 24; val[24][1] = 24; - val[25][0] = 25; val[25][1] = 23; - val[26][0] = 0; val[26][1] = 1; - val[27][0] = 1; val[27][1] = 0; - val[28][0] = 2; val[28][1] = 5; - val[29][0] = 3; val[29][1] = 7; - val[30][0] = 4; val[30][1] = 9; - val[31][0] = 5; val[31][1] = 13; - val[32][0] = 6; val[32][1] = 15; - val[33][0] = 7; val[33][1] = 17; - val[34][0] = 8; val[34][1] = 19; - val[35][0] = 9; val[35][1] = 21; - - for (int i = 0; i <= 14; i++) - { - y = tab.find(cf[i]); - if (y >= 0) tot += val[y][(i + 1) & 0x1]; - } - const bool ok = (cf[15] == (tot % 26) + 'A'); - - return ok; -} - - -bool cf_check (const char * stato, const char * codcf) -{ - TString16 cf (codcf); - if (cf.empty()) - return TRUE; - const bool ok = (cf.len() == 11 && isdigit(cf[0])) ? pi_check(stato, cf) : __cf_check(cf); - return ok; -} - - -HIDDEN bool _cf_val(TEdit_field& f, KEY key) -{ - if (f.mask().query_mode()) return TRUE; - - const TString16 cf(f.get()); - bool ok = TRUE; - - if (cf.empty()) return TRUE; - if (cf.len() == 11 && isdigit(cf[0])) - { - TString16 stato(f.mask().get(atoi(get_val_param(0)))); - if (stato.not_empty() && stato != "IT") return TRUE; - - ok = pi_check (stato, cf); - } - else - ok = __cf_check(cf); - if (!ok) - { - if(f.dirty()) - { - ok = f.yesno_box("Codice fiscale errato: lo accetto ugualmente?"); - if (ok) f.set_dirty(FALSE); - } - else ok = TRUE; // Era gia' errato al caricamento quindi lo accetto - } - return ok; -} - - -HIDDEN bool _xt_pi_val(TEdit_field& f, KEY key) - -{ - TMask& m = f.mask(); - if (m.query_mode()) return TRUE; - - TString16 value(f.get()); - if (value.empty()) return f.error_box("Partita IVA obbligatoria"); - - const TString16 stato(m.get(atoi(get_val_param(0)))); - if (stato.not_empty() && stato != "IT") return TRUE; - - if (!_pi_val(f, key)) return FALSE; - - TLocalisamfile c(LF_COMUNI); - - const int pi = atoi(value.mid(7,3)); - - for (int i = 1 ; i < 3; i++) - { - const int comune = atoi(get_val_param(i)); - if (comune) - { - const TString16 com(m.get(comune)); // Comune residenza fiscale e residenza - if (com.not_empty()) - { - c.zero(); - c.put("COM", com); - if (c.read() == NOERR) - { - const int s1 = c.get_int("UFFIVA1"); - const int s2 = c.get_int("UFFIVA2"); - const int s3 = c.get_int("UFFIVA3"); - if (pi != s1 && pi != s2 && pi != s3) - { - const char* ui = format("%03d", s1); - if (f.yesno_box("Ufficio IVA della partita IVA non congruente: correggere in %s?", ui)) - { - value.overwrite(ui, 7); - f.set(value); - } - } - break; - } - } - } - } - return TRUE; -} - - -HIDDEN bool _xtz_pi_val(TEdit_field& f, KEY key) -{ - if (f.mask().query_mode()) return TRUE; - TString16 pi(f.get()); - if (pi.empty()) return TRUE; - return _xt_pi_val(f, key); -} - - -HIDDEN bool _xt_cf_val(TEdit_field& f, KEY key) -{ - if (f.mask().query_mode()) return TRUE; - - TString16 cf(f.get()); - if (cf.empty()) return f.error_box("Codice fiscale obbligatorio"); - - if (!_cf_val(f, key)) return FALSE; - - if (cf.len() == 11 && isdigit(cf[0])) - { - // if (!_xt_pi_val(f, key)) return FALSE; - // TString16 stato(f.mask().get(atoi(get_val_param(0)))); - // if ((stato.not_empty()) && (stato != "IT")) return TRUE; - return TRUE; - } - - bool passed = __cf_check(cf); - if (!passed) return TRUE; - - TMask& m = f.mask(); - - TMask_field& fld_sex = m.field(atoi(get_val_param(1))); - TMask_field& fld_dat = m.field(atoi(get_val_param(2))); - TMask_field& fld_com = m.field(atoi(get_val_param(3))); - - const char sesso = fld_sex.get()[0]; - TString16 data(fld_dat.get()); - TString16 com(fld_com.get()); - - TString16 wm("LMNPQRSTUV"); - int p; - if ((p = wm.find(cf[6])) != -1) cf[6] = '0' + p; - if ((p = wm.find(cf[7])) != -1) cf[7] = '0' + p; - if ((p = wm.find(cf[9])) != -1) cf[9] = '0' + p; - if ((p = wm.find(cf[10])) != -1) cf[10] = '0' + p; - if ((p = wm.find(cf[12])) != -1) cf[12] = '0' + p; - if ((p = wm.find(cf[13])) != -1) cf[13] = '0' + p; - if ((p = wm.find(cf[14])) != -1) cf[14] = '0' + p; - int gn = atoi(cf.mid(9,2)); - - if ((sesso == 'F' && gn < 40) || (sesso == 'M' && gn > 40)) - { - passed = fld_sex.yesno_box("Sesso non congruente al codice fiscale:\n" - "correzione automatica?"); - if (passed) fld_sex.set(sesso == 'M' ? "F" : "M"); - else return TRUE; - } - - if (gn > 40) gn -= 40; // Aggiusta giorno di nascita delle donne - - // Controllo data di nascita - wm = "ABCDEHLMPRST"; - if (data.not_empty()) - { - const TDate d(data); - int err = 0; - if ((d.year() % 100) != atoi(cf.mid(6, 2))) - err = 1; - if (wm[d.month() - 1] != cf[8]) - err = 2; - if (d.day() != gn) - err = 3; - if (err != 0) - { - const char* const what = err==1 ? "Anno" : (err==2 ? "Mese" : "Giorno"); - passed = fld_dat.yesno_box("%s di nascita non congruente al codice fiscale: correzione automatica?", what); - if (passed) data = ""; - else return TRUE; - } - } - - if (data.empty()) - { - const int mn = wm.find(cf[8]) + 1; - if (mn > 0) - { - const TDate d(gn, mn, 1900 + atoi(cf.mid(6, 2))); - fld_dat.set(d.string()); - } - } - - // Controllo del comune di nascita - const char* const codcom = cf.mid(11, 4); - if (com.not_empty() && com != codcom) - { - passed = fld_com.yesno_box("Comune non congruente al codice fiscale: correzione automatica?"); - if (passed) com = ""; - else return TRUE; - } - if (com.empty()) - { - fld_com.set(codcom); - fld_com.on_key(K_TAB); - } - - return TRUE; -} - - -HIDDEN bool _xtz_cf_val(TEdit_field& f, KEY key) - -{ - if (f.mask().query_mode()) return TRUE; - const char* cf = f.get(); - return (*cf == '\0') ? TRUE : _xt_cf_val(f, key); -} - - -HIDDEN bool _notempty_val(TEdit_field& f, KEY) -{ - return f.mask().query_mode() || f.get().not_empty(); -} - - -HIDDEN bool _date_cmp(TEdit_field& f, KEY) -{ - TFixed_string s(f.get()); - if (s.empty()) return TRUE; - - TDate d0(s), d1(f.mask().get(atoi(get_val_param(1)))); - TFixed_string op(get_val_param(0)); - - if (op == "==") return d0 == d1; - if (op == "!=") return d0 != d1; - if (op == ">") return d0 > d1; - if (op == "<") return d0 < d1; - if (op == ">=") return d0 >= d1; - if (op == "<=") return d0 <= d1; - -#ifdef DBG - f.error_box("Bad date operator '%s' in field %d", (const char*) op, f.dlg()); -#endif - - return FALSE; -} - - -HIDDEN bool _fixlen_val(TEdit_field& f, KEY) -{ - const TFixed_string s(f.get()); - - if (s.empty()) return TRUE; - - const int length = atoi(get_val_param(0)); - const bool ok = s.len() == length; - if (!ok) f.error_box("Lunghezza errata: deve essere %d", length); - return ok; -} - - -HIDDEN bool _mtcheck_val(TEdit_field& f, KEY) -{ - const int month = atoi(f.get()); - if (month < 1 || month > 13) return FALSE; - - TLocalisamfile d(LF_NDITTE); - d.zero(); - d.put(NDT_CODDITTA, MainApp()->get_firm()); - d.read(); - if (d.bad()) return TRUE; - if (d.get_char(NDT_FREQVIVA) == 'M') return TRUE; - return month == 13 || (month % 3) == 0; -} - - -HIDDEN bool _reqif_val(TEdit_field& f, KEY k) -{ - if (k == K_ENTER) - { - if (f.get().not_empty()) return TRUE; - const int nparms = get_val_param_num(); - for (int i = 0 ; i < nparms; i++) - { - const short id = atoi(get_val_param(i)); - if (id > 0 && f.mask().get(id).not_empty()) - return FALSE; - } - } - return TRUE; -} - - -HIDDEN bool _autoexit_val(TEdit_field& f, KEY key) -{ - if (f.mask().mode() != MODE_QUERY) return TRUE; - const int nparms = get_val_param_num(); - bool one_not_empty = FALSE; - for (int i = nparms; i-- > 0;) - { - const short id = f.atodlg(get_val_param(i)); - const TMask_field& c = f.mask().field(id); - const bool empty = c.get().empty(); - if (empty) - { - if (c.check_type() != CHECK_NONE || one_not_empty) - return TRUE; - } - else - one_not_empty = TRUE; - } - - if (key == K_TAB) - { - if (one_not_empty) - f.mask().stop_run(K_AUTO_ENTER); - } - - return TRUE; -} - - -HIDDEN bool _numcalc_val(TEdit_field& f, KEY k) -{ - if (k != K_TAB) return TRUE; - TExpression e(get_val_param(0), _numexpr); - - for (int i = 0 ; i < e.numvar(); i++) - { - const char* s = e.varname(i); - if (s[0] != '#') - { - TString80 err; err << "Cannot load variable " << s << " in " << e; - return f.error_box((const char*)err); - } - s++; - const int fldid = atoi(s); - e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); - } - const TFixed_string s((const char*)e); - f.set(s); - return TRUE; -} - - -HIDDEN bool _strcalc_val(TEdit_field& f, KEY k) -{ - if (k != K_TAB) return TRUE; - TExpression e(get_val_param(0), _strexpr); - - for (int i = 0 ; i < e.numvar(); i++) - { - const char* s = e.varname(i); - if (s[0] != '#') - { - TString80 err; err << "Cannot load variable " << s << " in " << e; - return f.error_box((const char*)err); - } - s++; - const int fldid = atoi(s); - e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); - } - TFixed_string s((const char*) e); - f.set(s); - return TRUE; -} - - -HIDDEN bool _onereq_val(TEdit_field& f, KEY k) -{ - if (k != K_ENTER) return TRUE; - const TMask& m = f.mask(); - if (m.mode() == MODE_QUERY) return TRUE; - const int nparms = get_val_param_num(); - TString s; - - for (int i = 0; i < nparms ; i++) - { - s = m.get(atoi(get_val_param(i))); - if (s.not_empty()) return TRUE; - } - return FALSE; -} - - -#define MAX_FUNC 17 - -HIDDEN VAL_FUNC _global_val_func[MAX_FUNC] = -{ - _expr_val, - _emptycopy_val, - _pi_val, - _cf_val, - _notempty_val, - _date_cmp, - _xt_pi_val, - _xt_cf_val, - _xtz_pi_val, - _xtz_cf_val, - _fixlen_val, - _mtcheck_val, - _reqif_val, - _autoexit_val, - _numcalc_val, - _strcalc_val, - _onereq_val - }; - -bool validate(int fn, TEdit_field& f, KEY k, const TArray& parms) -{ - _parms = &parms; - return (fn >= 0 && fn < MAX_FUNC) ? _global_val_func[fn](f, k) : TRUE; -} - +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +typedef bool (*VAL_FUNC)(TEdit_field&, KEY k); +HIDDEN const TArray* _parms; + +HIDDEN int get_val_param_num() { return _parms->items(); } + +HIDDEN const char* get_val_param(int i) +{ return i < _parms->items() ? (const char*)((const TString&) (*_parms)[i]):"" ; } + +HIDDEN bool _expr_val(TEdit_field& f, KEY) +{ + TTypeexp type = atoi(get_val_param(0)) == 0 ? _numexpr :_strexpr; + TExpression e(get_val_param(1), type); + + for (int i = 0 ; i < e.numvar(); i++) + { + const char* s = e.varname(i); + if (s[0] != '#') + { + TString80 err; err << "Non trovo la variabile " << s << " in " << e; + return f.error_box((const char*)err); + } + s++; + const int fldid = atoi(s); + if (type == _numexpr) + { + const real r(fldid == 0 ? f.get() : f.mask().get(fldid)); + e.setvar(i, r); + } + else + { + const char* v = fldid == 0 ? f.get() : f.mask().get(fldid); + e.setvar(i, v); + } + } + return bool(e); +} + + +HIDDEN bool _emptycopy_val(TEdit_field& f, KEY) +{ + if (f.get().empty()) + { + const short id = atoi(get_val_param(0)); + const TFixed_string val(f.mask().get(id)); + if (val.not_empty()) + { + f.set(val); + f.on_hit(); + } + } + return TRUE; +} + + +bool pi_check(const char * st, const char * paiva) +{ + int tot = 0, y; + TString16 stato (st); + TString16 pi (paiva); + + if ((stato.not_empty()) && (stato != "IT")) return TRUE; + if (pi.empty()) return TRUE; + if (pi.len() != 11) + return FALSE; + + for (int i = 0; i <= 9; i++) + { + if ((i + 1) & 0x0001) tot += (pi[i] - '0'); + else + { + y = (pi[i] - '0') * 2; + if (y >= 10) + { + tot += (y / 10); + y = y % 10; + } + tot += y; + } + } + y = 10 - (tot % 10); + if (y == 10) y = 0; + bool ok = (pi[10] == (y + '0')); + + return ok; +} + + +// Controlla la partita iva se e' non vuota ed italiana +HIDDEN bool _pi_val(TEdit_field& f, KEY) +{ + if (f.mask().query_mode()) return TRUE; + + TString16 stato(f.mask().get(atoi(get_val_param(0)))), pi(f.get()); + + if (stato.not_empty() && stato != "IT") return TRUE; + if (pi.empty()) return TRUE; + if (pi.len() != 11) + { + f.error_box("Lunghezza partita IVA diversa da 11"); + return FALSE; + } + + bool ok = pi_check (stato, pi); + if (!ok) + { + if(f.dirty()) + { + ok = f.yesno_box("Partita IVA errata, la accetto ugualmente?"); + if (ok) f.set_dirty(FALSE); + } + else ok = TRUE; // Era gia' errata e la ho accettata + } + return ok; +} + + +HIDDEN bool __cf_check (const char * codcf) +{ + const TString16 cf (codcf); + if (cf.len() != 16) return FALSE; + + const TFixed_string tab("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + + int tot = 0, y; + + byte val[36][2]; + + val[0][0] = 0; val[0][1] = 1; + val[1][0] = 1; val[1][1] = 0; + val[2][0] = 2; val[2][1] = 5; + val[3][0] = 3; val[3][1] = 7; + val[4][0] = 4; val[4][1] = 9; + val[5][0] = 5; val[5][1] = 13; + val[6][0] = 6; val[6][1] = 15; + val[7][0] = 7; val[7][1] = 17; + val[8][0] = 8; val[8][1] = 19; + val[9][0] = 9; val[9][1] = 21; + val[10][0] = 10; val[10][1] = 2; + val[11][0] = 11; val[11][1] = 4; + val[12][0] = 12; val[12][1] = 18; + val[13][0] = 13; val[13][1] = 20; + val[14][0] = 14; val[14][1] = 11; + val[15][0] = 15; val[15][1] = 3; + val[16][0] = 16; val[16][1] = 6; + val[17][0] = 17; val[17][1] = 8; + val[18][0] = 18; val[18][1] = 12; + val[19][0] = 19; val[19][1] = 14; + val[20][0] = 20; val[20][1] = 16; + val[21][0] = 21; val[21][1] = 10; + val[22][0] = 22; val[22][1] = 22; + val[23][0] = 23; val[23][1] = 25; + val[24][0] = 24; val[24][1] = 24; + val[25][0] = 25; val[25][1] = 23; + val[26][0] = 0; val[26][1] = 1; + val[27][0] = 1; val[27][1] = 0; + val[28][0] = 2; val[28][1] = 5; + val[29][0] = 3; val[29][1] = 7; + val[30][0] = 4; val[30][1] = 9; + val[31][0] = 5; val[31][1] = 13; + val[32][0] = 6; val[32][1] = 15; + val[33][0] = 7; val[33][1] = 17; + val[34][0] = 8; val[34][1] = 19; + val[35][0] = 9; val[35][1] = 21; + + for (int i = 0; i <= 14; i++) + { + y = tab.find(cf[i]); + if (y >= 0) tot += val[y][(i + 1) & 0x1]; + } + const bool ok = (cf[15] == (tot % 26) + 'A'); + + return ok; +} + + +bool cf_check (const char * stato, const char * codcf) +{ + TString16 cf (codcf); + if (cf.empty()) + return TRUE; + const bool ok = (cf.len() == 11 && isdigit(cf[0])) ? pi_check(stato, cf) : __cf_check(cf); + return ok; +} + + +HIDDEN bool _cf_val(TEdit_field& f, KEY key) +{ + if (f.mask().query_mode()) return TRUE; + + const TString16 cf(f.get()); + bool ok = TRUE; + + if (cf.empty()) return TRUE; + if (cf.len() == 11 && isdigit(cf[0])) + { + TString16 stato(f.mask().get(atoi(get_val_param(0)))); + if (stato.not_empty() && stato != "IT") return TRUE; + + ok = pi_check (stato, cf); + } + else + ok = __cf_check(cf); + if (!ok) + { + if(f.dirty()) + { + ok = f.yesno_box("Codice fiscale errato: lo accetto ugualmente?"); + if (ok) f.set_dirty(FALSE); + } + else ok = TRUE; // Era gia' errato al caricamento quindi lo accetto + } + return ok; +} + + +HIDDEN bool _xt_pi_val(TEdit_field& f, KEY key) + +{ + TMask& m = f.mask(); + if (m.query_mode()) return TRUE; + + TString16 value(f.get()); + if (value.empty()) return f.error_box("Partita IVA obbligatoria"); + + const TString16 stato(m.get(atoi(get_val_param(0)))); + if (stato.not_empty() && stato != "IT") return TRUE; + + if (!_pi_val(f, key)) return FALSE; + + TLocalisamfile c(LF_COMUNI); + + const int pi = atoi(value.mid(7,3)); + + for (int i = 1 ; i < 3; i++) + { + const int comune = atoi(get_val_param(i)); + if (comune) + { + const TString16 com(m.get(comune)); // Comune residenza fiscale e residenza + if (com.not_empty()) + { + c.zero(); + c.put("COM", com); + if (c.read() == NOERR) + { + const int s1 = c.get_int("UFFIVA1"); + const int s2 = c.get_int("UFFIVA2"); + const int s3 = c.get_int("UFFIVA3"); + if (pi != s1 && pi != s2 && pi != s3) + { + const char* ui = format("%03d", s1); + if (f.yesno_box("Ufficio IVA della partita IVA non congruente: correggere in %s?", ui)) + { + value.overwrite(ui, 7); + f.set(value); + } + } + break; + } + } + } + } + return TRUE; +} + + +HIDDEN bool _xtz_pi_val(TEdit_field& f, KEY key) +{ + if (f.mask().query_mode()) return TRUE; + TString16 pi(f.get()); + if (pi.empty()) return TRUE; + return _xt_pi_val(f, key); +} + + +HIDDEN bool _xt_cf_val(TEdit_field& f, KEY key) +{ + if (f.mask().query_mode()) return TRUE; + + TString16 cf(f.get()); + if (cf.empty()) return f.error_box("Codice fiscale obbligatorio"); + + if (!_cf_val(f, key)) return FALSE; + + if (cf.len() == 11 && isdigit(cf[0])) + { + // if (!_xt_pi_val(f, key)) return FALSE; + // TString16 stato(f.mask().get(atoi(get_val_param(0)))); + // if ((stato.not_empty()) && (stato != "IT")) return TRUE; + return TRUE; + } + + bool passed = __cf_check(cf); + if (!passed) return TRUE; + + TMask& m = f.mask(); + + TMask_field& fld_sex = m.field(atoi(get_val_param(1))); + TMask_field& fld_dat = m.field(atoi(get_val_param(2))); + TMask_field& fld_com = m.field(atoi(get_val_param(3))); + + const char sesso = fld_sex.get()[0]; + TString16 data(fld_dat.get()); + TString16 com(fld_com.get()); + + TString16 wm("LMNPQRSTUV"); + int p; + if ((p = wm.find(cf[6])) != -1) cf[6] = '0' + p; + if ((p = wm.find(cf[7])) != -1) cf[7] = '0' + p; + if ((p = wm.find(cf[9])) != -1) cf[9] = '0' + p; + if ((p = wm.find(cf[10])) != -1) cf[10] = '0' + p; + if ((p = wm.find(cf[12])) != -1) cf[12] = '0' + p; + if ((p = wm.find(cf[13])) != -1) cf[13] = '0' + p; + if ((p = wm.find(cf[14])) != -1) cf[14] = '0' + p; + int gn = atoi(cf.mid(9,2)); + + if ((sesso == 'F' && gn < 40) || (sesso == 'M' && gn > 40)) + { + passed = fld_sex.yesno_box("Sesso non congruente al codice fiscale:\n" + "correzione automatica?"); + if (passed) fld_sex.set(sesso == 'M' ? "F" : "M"); + else return TRUE; + } + + if (gn > 40) gn -= 40; // Aggiusta giorno di nascita delle donne + + // Controllo data di nascita + wm = "ABCDEHLMPRST"; + if (data.not_empty()) + { + const TDate d(data); + int err = 0; + if ((d.year() % 100) != atoi(cf.mid(6, 2))) + err = 1; + if (wm[d.month() - 1] != cf[8]) + err = 2; + if (d.day() != gn) + err = 3; + if (err != 0) + { + const char* const what = err==1 ? "Anno" : (err==2 ? "Mese" : "Giorno"); + passed = fld_dat.yesno_box("%s di nascita non congruente al codice fiscale: correzione automatica?", what); + if (passed) data = ""; + else return TRUE; + } + } + + if (data.empty()) + { + const int mn = wm.find(cf[8]) + 1; + if (mn > 0) + { + const TDate d(gn, mn, 1900 + atoi(cf.mid(6, 2))); + fld_dat.set(d.string()); + } + } + + // Controllo del comune di nascita + const char* const codcom = cf.mid(11, 4); + if (com.not_empty() && com != codcom) + { + passed = fld_com.yesno_box("Comune non congruente al codice fiscale: correzione automatica?"); + if (passed) com = ""; + else return TRUE; + } + if (com.empty()) + { + fld_com.set(codcom); + fld_com.on_key(K_TAB); + } + + return TRUE; +} + + +HIDDEN bool _xtz_cf_val(TEdit_field& f, KEY key) + +{ + if (f.mask().query_mode()) return TRUE; + const char* cf = f.get(); + return (*cf == '\0') ? TRUE : _xt_cf_val(f, key); +} + + +HIDDEN bool _notempty_val(TEdit_field& f, KEY) +{ + return f.mask().query_mode() || f.get().not_empty(); +} + + +HIDDEN bool _date_cmp(TEdit_field& f, KEY) +{ + TFixed_string s(f.get()); + if (s.empty()) return TRUE; + + TDate d0(s), d1(f.mask().get(atoi(get_val_param(1)))); + TFixed_string op(get_val_param(0)); + + if (op == "==") return d0 == d1; + if (op == "!=") return d0 != d1; + if (op == ">") return d0 > d1; + if (op == "<") return d0 < d1; + if (op == ">=") return d0 >= d1; + if (op == "<=") return d0 <= d1; + +#ifdef DBG + f.error_box("Bad date operator '%s' in field %d", (const char*) op, f.dlg()); +#endif + + return FALSE; +} + + +HIDDEN bool _fixlen_val(TEdit_field& f, KEY) +{ + const TFixed_string s(f.get()); + + if (s.empty()) return TRUE; + + const int length = atoi(get_val_param(0)); + const bool ok = s.len() == length; + if (!ok) f.error_box("Lunghezza errata: deve essere %d", length); + return ok; +} + + +HIDDEN bool _mtcheck_val(TEdit_field& f, KEY) +{ + const int month = atoi(f.get()); + if (month < 1 || month > 13) return FALSE; + + TLocalisamfile d(LF_NDITTE); + d.zero(); + d.put(NDT_CODDITTA, main_app().get_firm()); + d.read(); + if (d.bad()) return TRUE; + if (d.get_char(NDT_FREQVIVA) == 'M') return TRUE; + return month == 13 || (month % 3) == 0; +} + + +HIDDEN bool _reqif_val(TEdit_field& f, KEY k) +{ + if (k == K_ENTER) + { + if (f.get().not_empty()) return TRUE; + const int nparms = get_val_param_num(); + for (int i = 0 ; i < nparms; i++) + { + const short id = atoi(get_val_param(i)); + if (id > 0 && f.mask().get(id).not_empty()) + return FALSE; + } + } + return TRUE; +} + + +HIDDEN bool _autoexit_val(TEdit_field& f, KEY key) +{ + if (f.mask().mode() != MODE_QUERY) return TRUE; + const int nparms = get_val_param_num(); + bool one_not_empty = FALSE; + for (int i = nparms; i-- > 0;) + { + const short id = f.atodlg(get_val_param(i)); + const TMask_field& c = f.mask().field(id); + const bool empty = c.get().empty(); + if (empty) + { + if (c.check_type() != CHECK_NONE || one_not_empty) + return TRUE; + } + else + one_not_empty = TRUE; + } + + if (key == K_TAB) + { + if (one_not_empty) + f.mask().stop_run(K_AUTO_ENTER); + } + + return TRUE; +} + + +HIDDEN bool _numcalc_val(TEdit_field& f, KEY k) +{ + if (k != K_TAB) return TRUE; + TExpression e(get_val_param(0), _numexpr); + + for (int i = 0 ; i < e.numvar(); i++) + { + const char* s = e.varname(i); + if (s[0] != '#') + { + TString80 err; err << "Cannot load variable " << s << " in " << e; + return f.error_box((const char*)err); + } + s++; + const int fldid = atoi(s); + e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); + } + const TFixed_string s((const char*)e); + f.set(s); + return TRUE; +} + + +HIDDEN bool _strcalc_val(TEdit_field& f, KEY k) +{ + if (k != K_TAB) return TRUE; + TExpression e(get_val_param(0), _strexpr); + + for (int i = 0 ; i < e.numvar(); i++) + { + const char* s = e.varname(i); + if (s[0] != '#') + { + TString80 err; err << "Cannot load variable " << s << " in " << e; + return f.error_box((const char*)err); + } + s++; + const int fldid = atoi(s); + e.setvar(i, fldid == 0 ? f.get() : f.mask().get(fldid)); + } + TFixed_string s((const char*) e); + f.set(s); + return TRUE; +} + + +HIDDEN bool _onereq_val(TEdit_field& f, KEY k) +{ + if (k != K_ENTER) return TRUE; + const TMask& m = f.mask(); + if (m.mode() == MODE_QUERY) return TRUE; + const int nparms = get_val_param_num(); + TString s; + + for (int i = 0; i < nparms ; i++) + { + s = m.get(atoi(get_val_param(i))); + if (s.not_empty()) return TRUE; + } + return FALSE; +} + + +#define MAX_FUNC 17 + +HIDDEN VAL_FUNC _global_val_func[MAX_FUNC] = +{ + _expr_val, + _emptycopy_val, + _pi_val, + _cf_val, + _notempty_val, + _date_cmp, + _xt_pi_val, + _xt_cf_val, + _xtz_pi_val, + _xtz_cf_val, + _fixlen_val, + _mtcheck_val, + _reqif_val, + _autoexit_val, + _numcalc_val, + _strcalc_val, + _onereq_val + }; + +bool validate(int fn, TEdit_field& f, KEY k, const TArray& parms) +{ + _parms = &parms; + return (fn >= 0 && fn < MAX_FUNC) ? _global_val_func[fn](f, k) : TRUE; +} + diff --git a/include/viswin.cpp b/include/viswin.cpp index 2b305601c..63d56de87 100755 --- a/include/viswin.cpp +++ b/include/viswin.cpp @@ -1,1913 +1,1912 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef __PRINTER_H -typedef void (*LINKHANDLER) (int, const char *); -#endif - -#if XVT_OS == XVT_OS_WIN -extern "C" -{ -#include -} -#endif - -#define BUTTONROW_SIZE 3 -#define W_X1 (origin().x+5) -#define W_Y1 (origin().y+1) -#define W_X2 (origin().x+columns()) -#define W_Y2 (origin().y+rows()+1-BUTTONROW_SIZE) -#define TEXTROWS (rows() - 1 - BUTTONROW_SIZE) -#define TEXTCOLUMNS (columns() - 6) - -#define DLG_QUIT_TITLE "Fine" -#define DLG_EDIT_TITLE "~Edit" -#define DLG_LINK_TITLE "~Collega" -#define DLG_PRINT_TITLE "~Stampa" - -#if XVT_OS == XVT_OS_WIN -#define BACKGROUND MASK_BACK_COLOR -#define FOREGROUND COLOR_BLACK -#else -#define BACKGROUND COLOR_BLACK -#define FOREGROUND COLOR_WHITE -#endif - -#define K_CTRL_DOWN (K_CTRL + K_DOWN) -#define K_CTRL_UP (K_CTRL + K_UP) -#define K_SHIFT_UP (K_SHIFT + K_UP) -#define K_SHIFT_DOWN (K_SHIFT + K_DOWN) -#define K_SHIFT_LEFT (K_SHIFT + K_LEFT) -#define K_SHIFT_RIGHT (K_SHIFT + K_RIGHT) -#define K_ALT_RIGHT (K_CTRL + 'K') -#define K_ALT_LEFT (K_CTRL + 'L') -#define CTRL_C ('C') -#define CTRL_E ('E') -#define CTRL_S ('S') -#define CTRL_R ('R') - -// vista la mania degli 883, eccoti un po' di concerti di Mozart -const long E_ADDLINE = 488l; -const long E_ADDLINE_ONSCREEN = 467l; - - -void TViswin::exec_link() -{ - if (_linkID != -1) - { - LINKHANDLER pl = main_app().printer().getlinkhandler(); - if (pl) - pl(_linkID, _multiple ? (const char*)_multiple_link : (const char*)_linktxt); - - // dai opzione per rifare la stampa se e' arrivato un messaggio - // dall'applicazione chiamata - // schiaffa indi il tutto in una funzione - TMailbox m; - if (m.next_s(MSG_LN) != NULL) - { - if (yesno_box("Si desidera riaggiornare la stampa?")) - { - ((TPrint_application*)MainApp())->repeat_print(); -#if XVT_OS == XVT_OS_WIN - xvt_statbar_set (""); - xvt_statbar_refresh (); -#endif - stop_run(K_ENTER); - } - } - - set_focus(); - check_link(); - _need_update = TRUE; - force_update(); - do_events(); - check_link (&_point); - } - else - beep(); -} - - - -void TViswin::display_link (long y, long x1, long x2, const char *d) -{ - if (!_link_displayed) - { - paint_link (y, x1, x2); - _link_displayed = TRUE; -#if XVT_OS == XVT_OS_WIN - xvt_statbar_set (d); - xvt_statbar_refresh (); -#endif - xvt_enable_control (_link_button, TRUE); - } -} - - -void TViswin::erase_link (long y, long x1, long x2) -{ - if (_link_displayed) - { - paint_link (y, x1, x2); - _link_displayed = FALSE; -#if XVT_OS == XVT_OS_WIN - xvt_statbar_set (""); - xvt_statbar_refresh (); -#endif - xvt_enable_control (_link_button, FALSE); - } -} - -void TViswin::paint_link (long y, long x1, long x2) -{ - if (adjust_box (x1, x2, y)) - invert_bar ((int) (x1 + 6l), (int) (y + 1l), (int) (x2 + 6l), (int) (y + 2l)); -} - -bool TViswin::adjust_box (long &x1, long &x2, long y) -{ - if (y < origin ().y || y > origin ().y + _textrows) - return FALSE; - if (origin ().x > x1) - x1 = origin ().x; - if (origin ().x + _textcolumns < x2) - x2 = origin ().x + _textcolumns; - return TRUE; -} - -bool TViswin::check_link (TPoint * p) -{ - static char descr[128], pdescr[128]; - static int old_id = -1, plinkID = -1; - static long y, x1, x2; - static long py, px1, px2; - - if (p == NULL) // erase and go - { - if (old_id != -1) - { - erase_link (y, x1, x2); - old_id = _linkID = plinkID = -1; - py = px1 = px2 = x1 = y = x2 = 0l; - } - return FALSE; - } - - // poi se e' il caso lo si risistema - if (p == &_point) - plinkID = -1; - - for (int i = 0; i < _hotspots->items (); i++) - { - TToken_string & t = (TToken_string &) (*_hotspots)[i]; - t.restart (); - long ty = t.get_long (); - long tx1 = t.get_long (); - long tx2 = t.get_long (); - if (p->y == ty && p->x < tx2 && p->x >= tx1) - { - // ci siamo - int id = (int) t.get_long (4); - - if (ty != y || tx1 != x1 || tx2 != x2) - { - if (old_id != -1) - erase_link (y, x1, x2); - TToken_string & ttt = (TToken_string &) (*_links)[id]; - ttt.restart (); - strcpy (descr, ttt.get ()); - strcat (descr, t.get (3)); - _linktxt = t.get(3); - if (_multiple) - { - // get all parts of the same color - const char *cp; - _txt.read_line (ty); - _multiple_link = ""; - - while (cp = _txt.piece ()) - { - if (_txt.get_foreground () == *(ttt.get (1)) && - _txt.get_background () == *(ttt.get (2))) - _multiple_link.add (cp); - } - } - old_id = _linkID = id; - y = ty; - x1 = tx1; - x2 = tx2; - display_link (y, x1, x2, descr); - } - if (p == &_point) - { - strcpy (pdescr, descr); - plinkID = id; - px1 = x1; - px2 = x2; - py = y; - } - return TRUE; - } - } - // non sono su un bottone: puo' esserci il point - if (old_id != -1 && plinkID == -1) - { - old_id = _linkID = -1; - erase_link (y, x1, x2); - x1 = x2 = y = 0l; - } - // se point e' su un bottone, evidenzia quello - else if (plinkID != -1 && (x1 != px1 || x2 != px2 || y != py)) - { - // erase old one - erase_link (y, x1, x2); - old_id = _linkID = plinkID; - x1 = px1; - x2 = px2; - y = py; - strcpy (descr, pdescr); - display_link (y, x1, x2, descr); - return TRUE; - } - return FALSE; -} - -bool TViswin::in_text (const TPoint & p) const -{ - if (p.x > 5 && p.x < columns () && p.y > 0 && p.y < (rows () - 3)) - return TRUE; - return FALSE; -} - - -bool TViswin::need_paint_sel (bool smart) -{ - TPoint p1, p2; - adjust_selection (p1, p2); - long end = origin ().y + _textrows; - bool r = _isselection; - if (smart) - r = r && ( - (origin ().y >= p1.y - 1 && origin ().y <= p2.y + 1) || - (end >= p1.y - 1 && end <= p2.y + 1)); - return r; -} - -void TViswin::erase_selection () -{ - if (_sel_displayed) - paint_selection (); - _sel_displayed = FALSE; -} - -void TViswin::display_selection () -{ - if (!_sel_displayed) - paint_selection (); - _sel_displayed = TRUE; -} - -void TViswin::adjust_selection (TPoint & p1, TPoint & p2) -{ - if (_sel_start.y < _sel_end.y) - { - p1 = _sel_start; - p2 = _sel_end; - } - else - { - p1 = _sel_end; - p2 = _sel_start; - } -} - -void TViswin::shift_screen (scroll dir) -{ - RCT r; - - if (_scrolling) - return; - _scrolling = TRUE; - // origin() e' gia' stata modificata - switch (dir) - { - case up: - case down: - set_rect (&r, 0, CHARY + 2, (int) (CHARX * (_textcolumns + 6)), (int) (CHARY * (_textrows + 1))); - win_scroll_rect (win (), &r, 0, dir == down ? CHARY : -CHARY); - paint_row (dir == up ? origin ().y + _textrows - 1 : origin ().y); - break; - case left: - case right: - set_rect (&r, CHARX * 6, 0, (int) (CHARX * (_textcolumns + 6) + 2), (int) (CHARY * (_textrows + 1) - 2)); - win_scroll_rect (win (), &r, dir == right ? CHARX : -CHARX, 0); - paint_column (dir == left ? origin ().x + _textcolumns - 1 : origin ().x, - dir == left); - break; - default: - break; - } - _scrolling = FALSE; -} - -WINDOW TViswin::add_button (short id, const char *caption) -{ - const int BUT_HEIGHT = -#if XVT_OS == XVT_OS_WIN - 2 -#else - 1 -#endif - ; - WINDOW b = xvt_create_control (WC_PUSHBUTTON, 0, 0, 11, - BUT_HEIGHT, caption, win (), 0, 0, id); - - for (int i = 0; i < MAXBUT; i++) - if (_button[i] == NULL_WIN) - { - _button[i] = b; - break; - } - return b; -} - -void TViswin::repos_buttons () -{ - for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++) - if (buttons == MAXBUT - 1) - { - buttons++; - break; - } - - if (buttons == 0) - return; - - autoscroll (FALSE); - set_mode (M_COPY); - set_brush (MASK_BACK_COLOR); - bar (5, rows () - 3, columns () + 1, rows () + 1); - autoscroll (TRUE); - - RCT wr; - get_client_rect (win (), &wr); - RCT br; - 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; - set_rect (&r, x, y, x + br.right, y + br.bottom); - move_window (_button[b], &r); - } -} - -void TViswin::open () -{ - set_scroll_max (MAXLEN, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); - repos_buttons (); - TScroll_window ::open (); - _need_update = TRUE; - force_update (); -} - -// prints the window contents -void TViswin::paint_screen () -{ - bool first = TRUE; - for (long j = 0; j < _textrows; j++) - { - long rw = origin ().y + j; - if (rw < _txt.lines ()) - paint_row (rw); - else if (!_isopen) - { -#if XVT_OS == XVT_OS_WIN - autoscroll (FALSE); - set_mode (M_COPY); - set_pen (COLOR_BLACK); - - PNT b, e; - b.h = CHARX * 5; - b.v = (CHARY * (int) (j + 1l - origin ().y)) - 2; - e.h = CHARX * columns (); - e.v = b.v; - win_move_to (win (), b); - win_draw_line (win (), e); - set_pen (COLOR_LTGRAY); - e.v++; - b.v++; - win_move_to (win (), b); - win_draw_line (win (), e); - set_brush (COLOR_DKGRAY); - bar (5, (int) (j + 1l - origin ().y), (int) columns (), (int) (rows () - 3l)); - autoscroll (TRUE); - break; -#endif - } - } -} - -void TViswin::paint_background (long j, int row) -{ - if (!_isbackground) - return; - int rw = (int) (j % (long) _formlen); - TString & rwd = (TString &) (*_bg)[rw]; - int cnt = 0; - char ch; - - char curcol = 'n'; - char curpen = 'n'; - char curpat = 'n'; - char curwid = '1'; - - unsigned int x1, x2; - PNT b, e; - while (ch = rwd[cnt++]) - { - switch (ch) - { - case 'v': // verticale intera - - x1 = (unsigned char) rwd[cnt++] + 5; - b.h = e.h = x1 * CHARX + CHARX / 2; - b.v = row * CHARY; - e.v = (row + 1) * CHARY; - win_move_to (win (), b); - win_draw_line (win (), e); - break; - case 'o': // verticale pezzo sopra - - x1 = (unsigned char) rwd[cnt++] + 5; - b.h = e.h = x1 * CHARX + CHARX / 2; - b.v = row * CHARY; - e.v = (row + 1) * CHARY - CHARY / 2; - win_move_to (win (), b); - win_draw_line (win (), e); - break; - case 'u': // verticale pezzo sotto - - x1 = (unsigned char) rwd[cnt++] + 5; - b.h = e.h = x1 * CHARX + CHARX / 2; - b.v = row * CHARY + CHARY / 2; - e.v = (row + 1) * CHARY; - win_move_to (win (), b); - win_draw_line (win (), e); - break; - case 'h': // orizzontale intera - - x1 = (unsigned char) rwd[cnt++] + 5; - x2 = (unsigned char) rwd[cnt++] + 5; - b.v = e.v = row * CHARY + CHARY / 2; - b.h = x1 * CHARX; - e.h = (x2 + 1) * CHARX; - win_move_to (win (), b); - win_draw_line (win (), e); - break; - case 'r': // orizzontale scorciata agli estremi - - x1 = (unsigned char) rwd[cnt++] + 5; - x2 = (unsigned char) rwd[cnt++] + 5; - b.v = e.v = row * CHARY + CHARY / 2; - b.h = x1 * CHARX + CHARX / 2; - e.h = x2 * CHARX + CHARX / 2; - win_move_to (win (), b); - win_draw_line (win (), e); - break; - case 'W': - curwid = rwd[cnt++]; - set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), - trans_pen (curpen)); - break; - case 'P': - curpen = rwd[cnt++]; - set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), - trans_pen (curpen)); - break; - case 'B': - curpat = rwd[cnt++]; - set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), - trans_pen (curpen)); - break; - case 'C': - curcol = rwd[cnt++]; - set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), - trans_pen (curpen)); - break; - default: - break; - } - } - // restore default pen - set_pen (COLOR_BLACK); -} - -void TViswin::paint_row (long j) -{ - // int or = (int)origin().x; - long y = origin ().y; - TPoint p1, p2; - if (need_paint_sel (FALSE)) - adjust_selection (p1, p2); - int row = (int) (j + 1l - y); - static char fill[] = " " - " "; - autoscroll (FALSE); - set_font (FF_FIXED, 0); - set_mode (M_COPY); - set_opaque_text (TRUE); - set_color (FOREGROUND, BACKGROUND); - printat (0, row, "%05ld", j + 1); - if (_scrolling) - { - hide_pen (); - set_brush (COLOR_WHITE); - RCT r; - r.top = row * CHARY; - r.left = CHARX * 5, - r.bottom = r.top + CHARY + 2; - r.right = CHARX * 255; - win_draw_rect (win (), &r); - } - const char *cp; - int pos = 0; - _txt.read_line (j, origin ().x); - while (cp = _txt.piece ()) - { -#if XVT_OS != XVT_OS_SCOUNIX - int st = _txt.get_style (); - long bg = trans_color (_txt.get_background ()); - long fg = trans_color (_txt.get_foreground ()); - set_font (FF_FIXED, st & 0x000f); - set_color (fg, bg); -#else - set_color (COLOR_BLACK, COLOR_WHITE); -#endif - printat (6 + pos, row, "%s", cp); -#if XVT_OS == XVT_OS_WIN - if (st & underlined) - { - PNT b, e; - - set_pen (COLOR_BLACK); - b.h = CHARX * (6 + pos); - b.v = (row + 1) * CHARY; - e.h = CHARX * (6 + pos + strlen (cp)); - e.v = (row + 1) * CHARY; - win_move_to (win (), b); - win_draw_line (win (), e); - } -#endif - pos += strlen (cp); - } - if (_scrolling && (pos < _textcolumns)) - { - set_color (COLOR_BLACK, COLOR_WHITE); - printat (6 + pos, row, "%s", fill); - } -#if XVT_OS == XVT_OS_WIN // paint page limits - if ((j % _formlen) == (_formlen - 1)) // last row - - { - PNT b, e; - - b.h = CHARX * 5; - b.v = (row + 1) * CHARY - 1; - e.h = CHARX * 132; - e.v = (row + 1) * CHARY - 1; - set_pen (COLOR_LTGRAY, 2, PAT_SOLID, P_DASH); - win_move_to (win (), b); - win_draw_line (win (), e); - } -#endif - paint_background (j, row); - autoscroll (TRUE); -} - -void TViswin::paint_column (long j, bool end) -{ - paint_header (); - set_opaque_text (TRUE); - set_mode (M_COPY); - TPoint p1, p2; - if (need_paint_sel (FALSE)) - adjust_selection (p1, p2); - set_color (COLOR_BLACK, COLOR_WHITE); - - autoscroll (FALSE); - for (long l = 0l; l < _textrows && l < (_txt.lines () - origin ().y); l++) - { - const char *c = (const char *) _txt.line (origin ().y + l); -#if XVT_OS != XVT_OS_SCOUNIX - int st = _txt.get_style ((int) j); - set_font (FF_FIXED, st & 0x000f); - long bg = trans_color (_txt.get_background ((int) j)); - long fg = trans_color (_txt.get_foreground ((int) j)); - set_color (fg, bg); -#endif - int col = end ? (int) (_textcolumns + 5) : 6; - printat (col, (int) l + 1, "%c", - (unsigned int) j < strlen (c) ? c[(int) j] : ' '); -#if XVT_OS == XVT_OS_WIN - if ((st & underlined) && strlen (c) > (word) j) - { - PNT b, e; - - set_pen (COLOR_BLACK); - b.h = CHARX * col; - b.v = (int) (l + 2l) * CHARY; - e.h = CHARX * (col + 1); - e.v = (int) (l + 2l) * CHARY; - win_move_to (win (), b); - win_draw_line (win (), e); - } -#endif - paint_background ((int) l, (int) l + 1); - } - autoscroll (TRUE); -} - -void TViswin::draw_crossbars () - // prints reference crossbars -{ -#if XVT_OS == XVT_OS_WIN - - if (_cross.v > CHARY && _cross.v < (rows () - 3) * CHARY && - _cross.h > CHARX * 5 && _cross.h < columns () * CHARX) - { - set_pen (COLOR_BLACK); - set_mode (M_XOR); - - PNT b1, e1, b2, e2; - - autoscroll (FALSE); - b1.h = _cross.h; - b1.v = CHARY; - e1.h = _cross.h; - e1.v = ((rows () - 3) * CHARY); - b2.h = CHARX * 5; - b2.v = _cross.v; - e2.h = CHARX * columns (); - e2.v = _cross.v; - win_move_to (win (), b1); - win_draw_line (win (), e1); - win_move_to (win (), b2); - win_draw_line (win (), e2); - autoscroll (TRUE); - } -#endif -} - -void TViswin::display_crossbar () -{ - if (!_cross_displayed) - draw_crossbars (); - _cross_displayed = TRUE; -} - -void TViswin::erase_crossbar () -{ - if (_cross_displayed) - draw_crossbars (); - _cross_displayed = FALSE; -} - -void TViswin::display_point () -{ - - if (!_point_displayed) - paint_point (); - _point_displayed = TRUE; -} - -void TViswin::erase_point () -{ - if (_point_displayed) - paint_point (); - _point_displayed = FALSE; -} - -void TViswin::paint_point (bool erase) -{ - autoscroll (FALSE); - static bool wasbar; - - if (_isbar) - { - invert_bar (6, (int) (_point.y - origin ().y + 1l), - (int) columns (), (int) (_point.y - origin ().y + 2l)); - invert_bar ((int) (_point.x - origin ().x + 6l), 1, - (int) (_point.x - origin ().x + 7l), (int) (rows () - 3l)); - } - else - { - invert_bar ((int) (_point.x - origin ().x + 6l), (int) (_point.y - origin ().y + 1l), - (int) (_point.x - origin ().x + 7l), (int) (_point.y - origin ().y + 2l)); - invert_bar (0, (int) (_point.y - origin ().y + 1l), 5, - (int) (_point.y - origin ().y + 2l)); - invert_bar ((int) (_point.x - origin ().x + 6l), 0, - (int) (_point.x - origin ().x + 7l), 1); - } - autoscroll (TRUE); - wasbar = _isbar; -} - -// draw screen header -void TViswin::paint_header () -{ - set_mode (M_COPY); - set_opaque_text (TRUE); - set_color (FOREGROUND, BACKGROUND); - set_font (FF_FIXED, 0); - TString htmpst (10); - for (int i = 1; i < 26; i++) - { - htmpst.format ("%d", i); - htmpst.right_just (10, '.'); - printat (i * 10 - 4, (int) origin ().y, "%s", (const char *) htmpst); - } - autoscroll (FALSE); - set_color (COLOR_WHITE, BACKGROUND); - printat (0, 0, "P.%3ld ", ((origin ().y) / _formlen) + 1l); - autoscroll (TRUE); -} - -void TViswin::paint_selection () -{ - TPoint p1, p2; - adjust_selection (p1, p2); - - // paint rows - for (long l = p1.y; l <= p2.y; l++) - { - int top, left, right; - top = (int) (l - origin ().y + 1); - if (top > 0 && top <= _textrows) - { - left = p1.y == l ? (int) (p1.x - origin ().x + 6l) : 6; - right = p2.y == l ? (int) (p2.x - origin ().x + 6l) : - (int) (_textcolumns + 6l); - autoscroll (FALSE); - invert_bar (left, top, right, top + 1); - autoscroll (TRUE); - } - } -} - -void TViswin::paint_waitbar (bool xor) -{ -#if XVT_OS == XVT_OS_WIN - static int pic; -#endif - autoscroll (FALSE); - if (xor) - { -#if XVT_OS == XVT_OS_WIN - cpb_win_picture_draw_at (win (), _picture[pic], 4, 4 + (int) (rows () - 3l) * CHARY); - if (pic == 3) - pic = 0; - else - pic++; -#else - invert_bar (3, rows () - 2, 4, rows () - 1); -#endif - } - else - { -#if XVT_OS == XVT_OS_WIN - cpb_win_picture_draw_at (win (), _picture[pic], 4, - 4 + (int) (rows () - 3l) * CHARY); - if (pic == 3) - pic = 0; - else - pic++; -#else - printat (3, rows () - 2, "%c", '*'); -#endif - } - autoscroll (TRUE); -} - -void TViswin::update () -{ - if (_scrolling) - return; - - erase_point (); - autoscroll (FALSE); - set_mode (M_COPY); - set_brush (MASK_BACK_COLOR); - bar (5, rows () - 3, columns () + 1, rows () + 1); - - if (_need_update) - { - if (_isselection) - erase_selection (); - clear (COLOR_WHITE); - set_mode (M_COPY); - set_brush (MASK_BACK_COLOR); - autoscroll (FALSE); - bar (0, 0, columns () + 1, 1); - bar (0, 0, 5, rows () + 1); - bar (5, rows () - 3, columns () + 1, rows () + 1); - if (_isopen) - paint_waitbar (FALSE); -#if XVT_OS == XVT_OS_WIN -else - cpb_win_picture_draw_at (win(), _modpic, 4, - 4 + (int) (rows () - 3l) * CHARY); -#endif - autoscroll (TRUE); - paint_header (); - paint_screen (); - if (_isselection) - display_selection (); - } - display_point (); - autoscroll (TRUE); - _need_update = TRUE; - _need_scroll = none; -} - -void TViswin::abort_print () -{ - if (yesno_box ("Interruzione della stampa su video?")) - { - _txt.freeze (); - freeze (); - set_focus (); - close_print (); - } -} - -void TViswin::handler (WINDOW win, EVENT * ep) -{ - int kdiff_x, kdiff_y; - PNT newcross; - TPoint p; - static bool ignore = FALSE; - bool tlnk = FALSE; - int kdiff; - long new_origin; - switch (ep->type) - { - case E_USER: - if (ep->v.user.id == E_ADDLINE) - { - set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? - _txt.lines () : _txt.lines () - _textrows); - } - else if (ep->v.user.id == E_ADDLINE_ONSCREEN) - { - set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); - erase_point (); - if (need_paint_sel (FALSE)) - erase_selection (); - paint_row (_txt.lines () - 1l); - if (need_paint_sel (FALSE)) - display_selection (); - display_point (); - if (_txt.lines () > 1l) - _need_update = FALSE; - else - force_update (); - } - autoscroll (FALSE); - _textrows = TEXTROWS; - _textcolumns = TEXTCOLUMNS; - autoscroll (TRUE); - break; - case E_CONTROL: - if (ep->v.ctl.ci.type == WC_PUSHBUTTON) - switch (ep->v.ctl.id) - { - case DLG_QUIT: - if (_isopen) - abort_print (); - else - { -#if XVT_OS == XVT_OS_WIN - xvt_statbar_set (""); - xvt_statbar_refresh (); -#endif - stop_run (K_ENTER); - } - break; - case DLG_PRINT: - _txt.print (); - break; - case DLG_EDIT: - check_link (); - call_editor (); - _need_update = TRUE; - update (); - check_link (&_point); - break; - case DLG_LINK: - exec_link(); - break; - } - break; - case E_TIMER: - if (ep->v.timer.id == _timer) - { - kill_timer (_timer); - _istimer = FALSE; - } - else if (ep->v.timer.id == _wtimer) - { - paint_waitbar (); - kill_timer (_wtimer); - if (_isopen) - _wtimer = set_timer (win, 150l); - } - break; - case E_MOUSE_DBL: - break; - case E_MOUSE_DOWN: - p = ep->v.mouse.where; - trap_mouse (win); - - if (ep->v.mouse.button == 0) // left button: text selection - - { - if (need_paint_sel (FALSE)) - { - erase_selection (); - _isselection = FALSE; - } - if (!in_text (p) || (p.y + origin ().y) >= _txt.lines ()) - { - ignore = TRUE; - break; - } - - erase_point (); - _sel_start = ep->v.mouse.where; - _sel_start.x += (origin ().x - 6); - _sel_start.y += (origin ().y - 1); - _sel_end = _sel_start; - _selecting = TRUE; - } - else - { - // show crossbars - _cross = ep->v.mouse.where; - display_crossbar (); - _iscross = TRUE; - } - break; - case E_MOUSE_UP: - release_mouse (); - - if (ep->v.mouse.button == 0) // left button: text selection/move - // point - - { - p = ep->v.mouse.where; - - if (_isopen && (p.x >= 4 && p.x) <= 6 && - (p.y >= (int) rows () - 3 && p.y <= (int) rows () - 1)) - { - abort_print (); - ignore = TRUE; - } - if (ignore) - { - ignore = FALSE; - _selecting = FALSE; - break; - } - // confirm selection & store - p.x += (origin ().x - 6); - p.y += (origin ().y - 1); - - if (_sel_start == p) - { - if (_isselection) - { - _isselection = FALSE; - erase_selection (); - } - if (_sel_start == _point && !_selecting) - { - dispatch_e_char (win, K_F5); - } - else - { - TPoint xx; - _point.x = p.x; - _point.y = p.y; - if (_point.y > _txt.lines ()) - _point.y = _txt.lines () - 1l; - if (_point.y < 0) - _point.y = 0; - if (_point.x < 0) - _point.x = 0; - if (_point.x > 255) - _point.x = 255; - - check_link (&_point); - display_point (); - } - } - else - { - _sel_end.x = p.x; - _sel_end.y = p.y; - if (_sel_end.y >= _txt.lines ()) - _sel_end.y = _txt.lines () - 1l; - if (_sel_end.y < 0) - _sel_end.y = 0; - if (_sel_end.x < 0) - _sel_end.x = 0; - if (_sel_end.x > 255) - _sel_end.x = 255; - _point = _sel_end; - _isselection = TRUE; - check_link (&_point); - display_point (); - } - _selecting = FALSE; - } - else - { - erase_crossbar (); - _iscross = FALSE; - } - break; - case E_MOUSE_MOVE: - { - /* - if (!_selecting && !_iscross) // no buttons pressed - { - p = ep->v.mouse.where; - if (in_text (p)) - { - p.x += (origin ().x - 6); - p.y += (origin ().y - 1); - check_link (&p); - } - } - */ - if (_selecting || _iscross) - { - p = ep->v.mouse.where; - if (_selecting) - _isselection = TRUE;; - { - _isselection = TRUE; - } - // scroll if necessary - if (p.y >= _textrows + 1l) - { - if (_isselection) - erase_selection (); - if (_iscross) - erase_crossbar (); - dispatch_e_scroll (win, K_DOWN); - if (_isselection) - display_selection (); - if (_iscross) - display_crossbar (); - } - else if (p.y <= 0l) - { - if (_isselection) - erase_selection (); - if (_iscross) - erase_crossbar (); - dispatch_e_scroll (win, K_UP); - if (_isselection) - display_selection (); - if (_iscross) - display_crossbar (); - } - else if (p.x <= 5l) - { - if (_isselection) - erase_selection (); - if (_iscross) - erase_crossbar (); - dispatch_e_scroll (win, K_LEFT); - if (_isselection) - display_selection (); - if (_iscross) - display_crossbar (); - } - else if (p.x >= _textcolumns + 6) - { - if (_isselection) - erase_selection (); - if (_iscross) - erase_crossbar (); - dispatch_e_scroll (win, K_RIGHT); - if (_isselection) - display_selection (); - if (_iscross) - display_crossbar (); - } - if (_selecting) - { - if (in_text (p)) - { - p.x += (origin ().x - 6); - p.y += (origin ().y - 1); - _point = p; - if (_point.y >= _txt.lines ()) - _point.y = _txt.lines () - 1l; - } - if (_point != _sel_end) - { - erase_selection (); - _sel_end = _point; - display_selection (); - } - } - } - if (_iscross) - { - newcross = ep->v.mouse.where; - if (_cross.h != newcross.h || _cross.v != newcross.v) - { - erase_crossbar (); - _cross = newcross; - display_crossbar (); - } - } - } - break; - case E_SIZE: - if (is_open ()) - { - check_link (); - erase_point (); - if (_isselection) - erase_selection (); - autoscroll (FALSE); - _textrows = TEXTROWS; - _textcolumns = TEXTCOLUMNS; - autoscroll (TRUE); - repos_buttons (); - display_point (); - _need_update = TRUE; - force_update (); - do_events (); - check_link (&_point); - } - break; - case E_HSCROLL: - case E_VSCROLL: - { - erase_point (); - tlnk = TRUE; - switch (ep->v.scroll.what) - { - case SC_PAGE_UP: - if (ep->type == E_VSCROLL) - { - if (origin().y > 0) - { - kdiff = (int) (_point.y - origin ().y); - new_origin = origin ().y > _textrows ? - origin ().y - _textrows + 1l : 0; - _point.y = new_origin + kdiff; - check_link (); - update_thumb (origin ().x, new_origin); - _need_update = TRUE; - update (); // ORRIIIBILE! - - check_link (&_point); - _need_update = FALSE; - } - else - { - beep (); - update_thumb(-1, 0); - } - } - else - { - if (origin ().x > 0) - { - kdiff = (int) (_point.x - origin ().x); - new_origin = origin ().x > _textcolumns ? - origin ().x - _textcolumns + 1 : 0; - _point.x = new_origin + kdiff; - check_link (); - update_thumb(new_origin, _point.y); - _need_update = TRUE; - update (); // AAAARGH! - - check_link (&_point); - _need_update = FALSE; - } - else - { - beep (); - update_thumb(0, -1); - } - } - break; - case SC_LINE_UP: - if (ep->type == E_VSCROLL) - { - _need_update = FALSE; - if (origin ().y > 0l) - { - _point.y--; - if (need_paint_sel ()) - erase_selection (); - check_link (); - update_thumb (origin ().x, origin ().y - 1l); - _need_scroll = down; - } - else - { - beep (); - update_thumb(-1, 0); - } - } - else - { - _need_update = FALSE; - if (origin ().x > 0l) - { - if (need_paint_sel (FALSE)) - erase_selection (); - check_link (); - update_thumb (origin ().x - 1l, origin ().y); - _point.x--; - _need_scroll = right; - } - else - { - beep (); - update_thumb(0, -1); - } - } - break; - case SC_PAGE_DOWN: - if (ep->type == E_VSCROLL) - { - if ((origin ().y + _textrows) < _txt.lines ()) - { - kdiff = (int) (_point.y - origin ().y); - new_origin = (_txt.lines () - origin ().y) > - (_textrows * 2l) ? - origin ().y + _textrows - 1 : _txt.lines () - _textrows; - _point.y = new_origin + kdiff; - check_link (); - update_thumb (origin ().x, new_origin); - _need_update = TRUE; - update (); // AAAARGH! - - check_link (&_point); - _need_update = FALSE; - } - else - { - beep (); - update_thumb(-1, _txt.lines()-_textrows-1); - } - } - else - { - if ((origin ().x + _textcolumns) < 256) - { - kdiff = (int) (_point.x - origin ().x); - new_origin = (256 - origin ().x) > _textcolumns ? - origin ().x + _textcolumns - 1 : 256 - _textcolumns; - _point.x = new_origin + kdiff; - check_link (); - update_thumb (new_origin, origin ().y); - _need_update = TRUE; - update (); // AAAARGH! - - check_link (&_point); - _need_update = FALSE; - } - else - { - beep (); - update_thumb(255-_textcolumns, -1); - } - } - break; - case SC_LINE_DOWN: - if (ep->type == E_VSCROLL) - { - _need_update = FALSE; - if ((origin ().y + _textrows) < _txt.lines ()) - { - if (need_paint_sel ()) - erase_selection (); - check_link (); - update_thumb (origin ().x, origin ().y + 1l); - _point.y++; - _need_scroll = up; - } - else - { - beep (); - update_thumb(-1, _txt.lines()-_textrows-1); - } - } - else - { - _need_update = FALSE; - if ((origin ().x + _textcolumns) < 256) - { - if (need_paint_sel (FALSE)) - erase_selection (); - check_link (); - update_thumb (origin ().x + 1l, origin ().y); - _need_scroll = left; - _point.x++; - } - else - { - beep (); - update_thumb(255-_textcolumns, -1); - } - } - break; - case SC_THUMB: - - check_link (); - kdiff_x = (int) (_point.x - origin ().x); - kdiff_y = (int) (_point.y - origin ().y); - - p.x = ep->type == E_VSCROLL ? origin ().x : ep->v.scroll.pos; - p.y = ep->type == E_HSCROLL ? origin ().y : ep->v.scroll.pos; - - if ((p.y + _textrows) >= _txt.lines ()) - p.y = _txt.lines () - _textrows -1; - if ((p.x + _textcolumns) >= 255) - p.x = 255 - _textcolumns; - - update_thumb (p.x, p.y); - - _point.x = ep->type == E_VSCROLL ? origin ().x : - origin ().x + kdiff_x; - _point.y = ep->type == E_HSCROLL ? origin ().y : - origin ().y + kdiff_y; - _need_update = TRUE; - update (); - check_link (&_point); - break; - - default: - break; - } - // for failed scrollings - if (!_selecting && _need_scroll == none) - { - check_link (&_point); - display_point (); - } - } - break; - default: - break; - } - if (_need_scroll != none) - { - _need_update = FALSE; - scroll tmp = _need_scroll; - _need_scroll = none; - shift_screen (tmp); - if (!_selecting) - { - check_link (&_point); - display_point (); - } - if (_isselection) - display_selection (); - } - if (ep->type != E_UPDATE || _need_update) - TWindow ::handler (win, ep); - else if (ep->type == E_UPDATE) - update (); -} - -bool TViswin::on_key (KEY key) -{ - EVENT_TYPE type = E_USER; - - if (_istimer) - return TRUE; - _timer = set_timer (win (), 50l); - _istimer = TRUE; - - if (key == K_UP || key == K_DOWN || key == K_LEFT || key == K_RIGHT) - if (_selflag) - key += K_SHIFT; - - if (_selecting && key != K_SHIFT_UP && key != K_SHIFT_DOWN - && key != K_SHIFT_LEFT && key != K_SHIFT_RIGHT) - _selecting = FALSE; - - switch (key) - { - case CTRL_E: - if (_isedit) - { - check_link (); - call_editor (); - set_focus (); - _need_update = TRUE; - update (); - check_link (&_point); - } - break; - case CTRL_C: - exec_link(); - break; - case CTRL_S: - if (_isprint) - _txt.print (); - break; - case CTRL_R: - _need_update = TRUE; - check_link (); - force_update (); - do_events (); - check_link (&_point); - break; - case K_ESC: - if (_isopen) - abort_print (); - else - { - -#if XVT_OS == XVT_OS_WIN - xvt_statbar_set (""); - xvt_statbar_refresh (); -#endif - stop_run (K_ESC); - } - break; - case K_ENTER: - if (_isselection) - { - erase_selection (); - _isselection = FALSE; - } - break; - case K_TAB: - if (_curbut == (_buttons - 1)) - _curbut = 0; - else - _curbut++; - break; - case K_BTAB: - if (_curbut == 0) - _curbut = _buttons - 1; - else - _curbut--; - break; - case K_SPACE: - case K_CTRL_ENTER: - if (_linkID != -1) - { - exec_link(); - } - else - dispatch_e_char (_button[_curbut], K_SPACE); - break; - case K_LHOME: - _need_update = TRUE; - update_thumb (0, 0); - _point.set (0, 0); - check_link (&_point); - force_update (); - break; - case K_LEND: - _need_update = TRUE; - update_thumb (0, _txt.lines () - _textrows); - _point.set (0, _txt.lines () - 1); - check_link (&_point); - force_update (); - break; - case K_RIGHT: - case K_LEFT: - case K_WRIGHT: - case K_WLEFT: - case K_ALT_RIGHT: - case K_ALT_LEFT: - case K_SHIFT_RIGHT: - case K_SHIFT_LEFT: - type = E_HSCROLL; - break; - case K_UP: - case K_DOWN: - case K_NEXT: - case K_PREV: - case K_CTRL_UP: - case K_CTRL_DOWN: - case K_SHIFT_UP: - case K_SHIFT_DOWN: - type = E_VSCROLL; - break; - case K_F5: - check_link (); - erase_point (); - _isbar = !_isbar; - _need_update = TRUE; - force_update (); - do_events (); - check_link (&_point); - break; - case K_F6: - _selflag = !_selflag; - break; - default: - break; - } - - switch (type) - { - case E_HSCROLL: - case E_VSCROLL: - { - erase_point (); - check_link (); - switch (key) - { - case K_PREV: - dispatch_e_scroll (win(), K_PREV); - break; - case K_NEXT: - dispatch_e_scroll (win(), K_NEXT); - break; - case K_WLEFT: - dispatch_e_scroll (win(), K_BTAB); - break; - case K_WRIGHT: - dispatch_e_scroll (win(), K_TAB); - break; - case K_CTRL_UP: - dispatch_e_scroll (win(), K_UP); - break; - case K_CTRL_DOWN: - dispatch_e_scroll (win(), K_DOWN); - break; - case K_ALT_LEFT: - dispatch_e_scroll (win(), K_LEFT); - break; - case K_ALT_RIGHT: - dispatch_e_scroll (win(), K_RIGHT); - break; - case K_UP: - case K_SHIFT_UP: - _need_update = FALSE; - if (key == K_SHIFT_UP) - { - if (need_paint_sel (FALSE)) - erase_selection (); - if (!_selecting) - { - _sel_start = _point; - _selecting = TRUE; - } - } - if (_point.y > 0l) - { - if (_point.y == origin ().y) - { - if (need_paint_sel ()) - erase_selection (); - update_thumb (origin ().x, --_point.y); - _need_scroll = down; - } - else - _point.y--; - if (key == K_SHIFT_UP) - { - _sel_end = _point; - _isselection = TRUE; - } - } - else - beep (); - break; - case K_LEFT: - case K_SHIFT_LEFT: - _need_update = FALSE; - if (_point.x > 0l) - { - if (key == K_SHIFT_LEFT) - { - if (need_paint_sel (FALSE)) - erase_selection (); - if (!_selecting) - { - _sel_start = _point; - _selecting = TRUE; - } - } - if (_point.x == origin ().x) - { - _need_update = FALSE; - if (need_paint_sel (FALSE)) - erase_selection (); - update_thumb (--_point.x, origin ().y); - _need_scroll = right; - } - else - _point.x--; - if (key == K_SHIFT_LEFT) - { - _sel_end = _point; - _isselection = TRUE; - } - } - else - beep (); - break; - case K_DOWN: - case K_SHIFT_DOWN: - _need_update = FALSE; - if (_point.y < (_txt.lines () - 1)) - { - if (key == K_SHIFT_DOWN) - { - if (need_paint_sel (FALSE)) - erase_selection (); - if (!_selecting) - { - _sel_start = _point; - _selecting = TRUE; - } - } - if (_point.y == origin ().y + _textrows - 1) - { - if (need_paint_sel ()) - erase_selection (); - // check_link(); - update_thumb (origin ().x, (++_point.y) - _textrows + 1); - _need_scroll = up; - } - else - _point.y++; - if (key == K_SHIFT_DOWN) - { - _sel_end = _point; - _isselection = TRUE; - } - } - else - beep (); - break; - case K_RIGHT: - case K_SHIFT_RIGHT: - _need_update = FALSE; - if (_point.x < 256) - { - if (key == K_SHIFT_RIGHT) - { - if (need_paint_sel (FALSE)) - erase_selection (); - if (!_selecting) - { - _sel_start = _point; - _selecting = TRUE; - } - } - if (_point.x == (origin ().x + _textcolumns - 1)) - { - if (need_paint_sel (FALSE)) - erase_selection (); - // check_link(); - update_thumb ((++_point.x) - _textcolumns + 1l, origin ().y); - _need_scroll = left; - } - else - _point.x++; - if (key == K_SHIFT_RIGHT) - { - _sel_end = _point; - _isselection = TRUE; - } - } - else - beep (); - break; - default: - break; - } - if (_need_scroll != none) - { - _need_update = FALSE; - scroll tmp = _need_scroll; - _need_scroll = none; - shift_screen (tmp); - } - if (_isselection) - display_selection (); - check_link (&_point); - force_update (); - } - break; -default: - break; -} - return TWindow::on_key (key); -} - -bool TViswin::call_editor () -{ - TConfig cnf (CONFIG_GENERAL, "Link"); - TString editor (cnf.get ("txt")); - - bool ok = FALSE; - - if (!editor.empty ()) - { - TString newfilename; - - static FILE_SPEC fs; - get_default_dir (&fs.dir); - strcpy (fs.type, "txt"); - save_dir (); - if (save_file_dlg (&fs, "Salva il file con il nome:") == FL_OK) - { - restore_dir (); - char path[256]; - dir_to_str (&fs.dir, path, sizeof (path)); - newfilename << path << '/' << fs.name; - - TPoint p1, p2; - if (_isselection) - adjust_selection (p1, p2); - - if (_txt.write (newfilename, _isselection ? &p1 : NULL, - _isselection ? &p2 : NULL)) - { - newfilename.insert (" ", 0); - newfilename.insert (editor, 0); - TExternal_app edit (newfilename); - if (edit.run (TRUE)) - beep (); - else - ok = TRUE; - } - } - else - restore_dir (); - } - else - warning_box ("Nessun editor specificato nei parametri studio"); - return ok; -} - -void TViswin::add_line (const char *l) -{ - if (_isopen && !_frozen) - { - if (_txt.frozen ()) // error writing files - - { - close_print (); - return; - } - _txt.append (l); - EVENT ev; - ev.type = E_USER; - ev.v.user.id = (_txt.lines () - origin ().y) <= _textrows ? - E_ADDLINE_ONSCREEN : E_ADDLINE; - dispatch_event (win (), &ev); - do_events (); - } -} - -void TViswin::close_print () -{ - _isopen = FALSE; - kill_timer (_wtimer); - _need_update = TRUE; - force_update (); -} - -TViswin ::TViswin (const char *fname, - const char *title, - bool editbutton, - bool printbutton, - bool linkbutton): - _filename (fname), _txt (fname, BUFFERSIZE), _islink (linkbutton), _isedit (editbutton), - _isprint (printbutton), _isbar (FALSE), _istimer (FALSE), _iscross (FALSE), - _isselection (FALSE), _sel_displayed (FALSE), _cross_displayed (FALSE), - _link_displayed (FALSE), _point_displayed (FALSE), _selecting (FALSE), - _scrolling (FALSE), _selflag (FALSE), _need_update (TRUE), _need_scroll (none), - _multiple (FALSE), - _frozen (FALSE) -{ - if (title == NULL) - title = (fname ? fname : "Anteprima di stampa"); - - _isopen = fname == NULL; - if (_isopen) - _filename = _txt.name (); - - for (int i = 0; i < MAXBUT; i++) - _button[i] = NULL_WIN; - - const int larg = 76; - const int alt = 20; - RCT r; - get_client_rect (TASK_WIN, &r); - int maxlarg = r.right / CHARX - 6; // Calculates max window width - - int maxalt = r.bottom / CHARY - 6; - if (larg > maxlarg) - maxlarg = larg; - if (alt > maxalt) - maxalt = alt; - -#if XVT_OS == XVT_OS_WIN - for (i = 0; i < 4; i++) - _picture[i] = cpb_picture_load (BMP_MODULE1 + i); - _modpic = cpb_picture_load (BMP_MODULE); -#endif - - create (-1, -1, maxlarg, maxalt, title, - WSF_CLOSE | WSF_HSCROLL | WSF_VSCROLL | WSF_SIZE); - - set_opaque_text (TRUE); - set_font (FF_FIXED); - - add_button (DLG_QUIT, DLG_QUIT_TITLE); - _buttons = 1; - - if (_isedit) - { - add_button (DLG_EDIT, DLG_EDIT_TITLE); - _buttons++; - } - if (_islink) - { - _link_button = add_button (DLG_LINK, DLG_LINK_TITLE); - _buttons++; - xvt_enable_control (_link_button, FALSE); - } - if (_isprint) - { - add_button (DLG_PRINT, DLG_PRINT_TITLE); - _buttons++; - } - - //#if XVT_OS == XVT_OS_SCOUNIX - // maximize(); - // #endif - - _curbut = 0; - - if (_isopen) - _wtimer = set_timer (win (), 150l); - - _point.set (0, 0); - autoscroll (FALSE); - _textrows = TEXTROWS; - _textcolumns = TEXTCOLUMNS; - autoscroll (TRUE); - - _links = &(main_app().printer ().links ()); - _multiple = main_app().printer ().ismultiplelink (); - _bg = main_app().printer ().getbgdesc (); - _isbackground = _bg->items () > 0; - _formlen = main_app().printer ().formlen (); - - for (i = 0; i < _links->items (); i++) - { - TToken_string & t = (TToken_string &) (*_links)[i]; - char f = *(t.get (1)); - char b = *(t.get (2)); - t.restart (); - _txt.set_hotspots (f, b); - } - _hotspots = &(_txt.hotspots ()); -} - -TViswin ::~TViswin () -{ -#if XVT_OS == XVT_OS_WIN - for (int i = 0; i < 4; i++) - picture_free (_picture[i]); -#endif -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __PRINTER_H +typedef void (*LINKHANDLER) (int, const char *); +#endif + +#if XVT_OS == XVT_OS_WIN +extern "C" +{ +#include +} +#endif + +#define BUTTONROW_SIZE 3 +#define W_X1 (origin().x+5) +#define W_Y1 (origin().y+1) +#define W_X2 (origin().x+columns()) +#define W_Y2 (origin().y+rows()+1-BUTTONROW_SIZE) +#define TEXTROWS (rows() - 1 - BUTTONROW_SIZE) +#define TEXTCOLUMNS (columns() - 6) + +#define DLG_QUIT_TITLE "Fine" +#define DLG_EDIT_TITLE "~Edit" +#define DLG_LINK_TITLE "~Collega" +#define DLG_PRINT_TITLE "~Stampa" + +#if XVT_OS == XVT_OS_WIN +#define BACKGROUND MASK_BACK_COLOR +#define FOREGROUND COLOR_BLACK +#else +#define BACKGROUND COLOR_BLACK +#define FOREGROUND COLOR_WHITE +#endif + +#define K_CTRL_DOWN (K_CTRL + K_DOWN) +#define K_CTRL_UP (K_CTRL + K_UP) +#define K_SHIFT_UP (K_SHIFT + K_UP) +#define K_SHIFT_DOWN (K_SHIFT + K_DOWN) +#define K_SHIFT_LEFT (K_SHIFT + K_LEFT) +#define K_SHIFT_RIGHT (K_SHIFT + K_RIGHT) +#define K_ALT_RIGHT (K_CTRL + 'K') +#define K_ALT_LEFT (K_CTRL + 'L') +#define CTRL_C ('C') +#define CTRL_E ('E') +#define CTRL_S ('S') +#define CTRL_R ('R') + +// vista la mania degli 883, eccoti un po' di concerti di Mozart +const long E_ADDLINE = 488L; +const long E_ADDLINE_ONSCREEN = 467L; + + +void TViswin::exec_link() +{ + if (_linkID != -1) + { + LINKHANDLER pl = main_app().printer().getlinkhandler(); + if (pl) + pl(_linkID, _multiple ? (const char*)_multiple_link : (const char*)_linktxt); + + // dai opzione per rifare la stampa se e' arrivato un messaggio + // dall'applicazione chiamata + // schiaffa indi il tutto in una funzione + TMailbox m; + if (m.next_s(MSG_LN) != NULL) + { + if (yesno_box("Si desidera riaggiornare la stampa?")) + { + ((TPrint_application&)main_app()).repeat_print(); +#if XVT_OS == XVT_OS_WIN + xvt_statbar_refresh (); +#endif + stop_run(K_ENTER); + } + } + + set_focus(); + check_link(); + _need_update = TRUE; + force_update(); + do_events(); + check_link (&_point); + } + else + beep(); +} + + + +void TViswin::display_link (long y, long x1, long x2, const char *d) +{ + if (!_link_displayed) + { + paint_link (y, x1, x2); + _link_displayed = TRUE; +#if XVT_OS == XVT_OS_WIN + xvt_statbar_set (d); + xvt_statbar_refresh (); +#endif + xvt_enable_control (_link_button, TRUE); + } +} + + +void TViswin::erase_link (long y, long x1, long x2) +{ + if (_link_displayed) + { + paint_link (y, x1, x2); + _link_displayed = FALSE; +#if XVT_OS == XVT_OS_WIN + xvt_statbar_set (""); + xvt_statbar_refresh (); +#endif + xvt_enable_control (_link_button, FALSE); + } +} + +void TViswin::paint_link (long y, long x1, long x2) +{ + if (adjust_box (x1, x2, y)) + invert_bar ((int) (x1 + 6l), (int) (y + 1l), (int) (x2 + 6l), (int) (y + 2l)); +} + +bool TViswin::adjust_box (long &x1, long &x2, long y) +{ + if (y < origin ().y || y > origin ().y + _textrows) + return FALSE; + if (origin ().x > x1) + x1 = origin ().x; + if (origin ().x + _textcolumns < x2) + x2 = origin ().x + _textcolumns; + return TRUE; +} + +bool TViswin::check_link (TPoint * p) +{ + static char descr[128], pdescr[128]; + static int old_id = -1, plinkID = -1; + static long y, x1, x2; + static long py, px1, px2; + + if (p == NULL) // erase and go + { + if (old_id != -1) + { + erase_link (y, x1, x2); + old_id = _linkID = plinkID = -1; + py = px1 = px2 = x1 = y = x2 = 0l; + } + return FALSE; + } + + // poi se e' il caso lo si risistema + if (p == &_point) + plinkID = -1; + + for (int i = 0; i < _hotspots->items (); i++) + { + TToken_string & t = (TToken_string &) (*_hotspots)[i]; + t.restart (); + long ty = t.get_long (); + long tx1 = t.get_long (); + long tx2 = t.get_long (); + if (p->y == ty && p->x < tx2 && p->x >= tx1) + { + // ci siamo + int id = (int) t.get_long (4); + + if (ty != y || tx1 != x1 || tx2 != x2) + { + if (old_id != -1) + erase_link (y, x1, x2); + TToken_string & ttt = (TToken_string &) (*_links)[id]; + ttt.restart (); + strcpy (descr, ttt.get ()); + strcat (descr, t.get (3)); + _linktxt = t.get(3); + if (_multiple) + { + // get all parts of the same color + const char *cp; + _txt.read_line (ty); + _multiple_link = ""; + + while (cp = _txt.piece ()) + { + if (_txt.get_foreground () == *(ttt.get (1)) && + _txt.get_background () == *(ttt.get (2))) + _multiple_link.add (cp); + } + } + old_id = _linkID = id; + y = ty; + x1 = tx1; + x2 = tx2; + display_link (y, x1, x2, descr); + } + if (p == &_point) + { + strcpy (pdescr, descr); + plinkID = id; + px1 = x1; + px2 = x2; + py = y; + } + return TRUE; + } + } + // non sono su un bottone: puo' esserci il point + if (old_id != -1 && plinkID == -1) + { + old_id = _linkID = -1; + erase_link (y, x1, x2); + x1 = x2 = y = 0l; + } + // se point e' su un bottone, evidenzia quello + else if (plinkID != -1 && (x1 != px1 || x2 != px2 || y != py)) + { + // erase old one + erase_link (y, x1, x2); + old_id = _linkID = plinkID; + x1 = px1; + x2 = px2; + y = py; + strcpy (descr, pdescr); + display_link (y, x1, x2, descr); + return TRUE; + } + return FALSE; +} + +bool TViswin::in_text (const TPoint & p) const +{ + if (p.x > 5 && p.x < columns () && p.y > 0 && p.y < (rows () - 3)) + return TRUE; + return FALSE; +} + + +bool TViswin::need_paint_sel (bool smart) +{ + TPoint p1, p2; + adjust_selection (p1, p2); + long end = origin ().y + _textrows; + bool r = _isselection; + if (smart) + r = r && ( + (origin ().y >= p1.y - 1 && origin ().y <= p2.y + 1) || + (end >= p1.y - 1 && end <= p2.y + 1)); + return r; +} + +void TViswin::erase_selection () +{ + if (_sel_displayed) + paint_selection (); + _sel_displayed = FALSE; +} + +void TViswin::display_selection () +{ + if (!_sel_displayed) + paint_selection (); + _sel_displayed = TRUE; +} + +void TViswin::adjust_selection (TPoint & p1, TPoint & p2) +{ + if (_sel_start.y < _sel_end.y) + { + p1 = _sel_start; + p2 = _sel_end; + } + else + { + p1 = _sel_end; + p2 = _sel_start; + } +} + +void TViswin::shift_screen (scroll dir) +{ + RCT r; + + if (_scrolling) + return; + _scrolling = TRUE; + // origin() e' gia' stata modificata + switch (dir) + { + case up: + case down: + set_rect (&r, 0, CHARY + 2, (int) (CHARX * (_textcolumns + 6)), (int) (CHARY * (_textrows + 1))); + win_scroll_rect (win (), &r, 0, dir == down ? CHARY : -CHARY); + paint_row (dir == up ? origin ().y + _textrows - 1 : origin ().y); + break; + case left: + case right: + set_rect (&r, CHARX * 6, 0, (int) (CHARX * (_textcolumns + 6) + 2), (int) (CHARY * (_textrows + 1) - 2)); + win_scroll_rect (win (), &r, dir == right ? CHARX : -CHARX, 0); + paint_column (dir == left ? origin ().x + _textcolumns - 1 : origin ().x, + dir == left); + break; + default: + break; + } + _scrolling = FALSE; +} + +WINDOW TViswin::add_button (short id, const char *caption) +{ + const int BUT_HEIGHT = +#if XVT_OS == XVT_OS_WIN + 2 +#else + 1 +#endif + ; + WINDOW b = xvt_create_control (WC_PUSHBUTTON, 0, 0, 11, + BUT_HEIGHT, caption, win (), 0, 0, id); + + for (int i = 0; i < MAXBUT; i++) + if (_button[i] == NULL_WIN) + { + _button[i] = b; + break; + } + return b; +} + +void TViswin::repos_buttons () +{ + for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++) + if (buttons == MAXBUT - 1) + { + buttons++; + break; + } + + if (buttons == 0) + return; + + autoscroll (FALSE); + set_mode (M_COPY); + set_brush (MASK_BACK_COLOR); + bar (5, rows () - 3, columns () + 1, rows () + 1); + autoscroll (TRUE); + + RCT wr; + get_client_rect (win (), &wr); + RCT br; + 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; + set_rect (&r, x, y, x + br.right, y + br.bottom); + move_window (_button[b], &r); + } +} + +void TViswin::open () +{ + set_scroll_max (MAXLEN, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); + repos_buttons (); + TScroll_window ::open (); + _need_update = TRUE; + force_update (); +} + +// prints the window contents +void TViswin::paint_screen () +{ + bool first = TRUE; + for (long j = 0; j < _textrows; j++) + { + long rw = origin ().y + j; + if (rw < _txt.lines ()) + paint_row (rw); + else if (!_isopen) + { +#if XVT_OS == XVT_OS_WIN + autoscroll (FALSE); + set_mode (M_COPY); + set_pen (COLOR_BLACK); + + PNT b, e; + b.h = CHARX * 5; + b.v = (CHARY * (int) (j + 1l - origin ().y)) - 2; + e.h = CHARX * columns (); + e.v = b.v; + win_move_to (win (), b); + win_draw_line (win (), e); + set_pen (COLOR_LTGRAY); + e.v++; + b.v++; + win_move_to (win (), b); + win_draw_line (win (), e); + set_brush (COLOR_DKGRAY); + bar (5, (int) (j + 1l - origin ().y), (int) columns (), (int) (rows () - 3l)); + autoscroll (TRUE); + break; +#endif + } + } +} + +void TViswin::paint_background (long j, int row) +{ + if (!_isbackground) + return; + int rw = (int) (j % (long) _formlen); + TString & rwd = (TString &) (*_bg)[rw]; + int cnt = 0; + char ch; + + char curcol = 'n'; + char curpen = 'n'; + char curpat = 'n'; + char curwid = '1'; + + unsigned int x1, x2; + PNT b, e; + while (ch = rwd[cnt++]) + { + switch (ch) + { + case 'v': // verticale intera + + x1 = (unsigned char) rwd[cnt++] + 5; + b.h = e.h = x1 * CHARX + CHARX / 2; + b.v = row * CHARY; + e.v = (row + 1) * CHARY; + win_move_to (win (), b); + win_draw_line (win (), e); + break; + case 'o': // verticale pezzo sopra + + x1 = (unsigned char) rwd[cnt++] + 5; + b.h = e.h = x1 * CHARX + CHARX / 2; + b.v = row * CHARY; + e.v = (row + 1) * CHARY - CHARY / 2; + win_move_to (win (), b); + win_draw_line (win (), e); + break; + case 'u': // verticale pezzo sotto + + x1 = (unsigned char) rwd[cnt++] + 5; + b.h = e.h = x1 * CHARX + CHARX / 2; + b.v = row * CHARY + CHARY / 2; + e.v = (row + 1) * CHARY; + win_move_to (win (), b); + win_draw_line (win (), e); + break; + case 'h': // orizzontale intera + + x1 = (unsigned char) rwd[cnt++] + 5; + x2 = (unsigned char) rwd[cnt++] + 5; + b.v = e.v = row * CHARY + CHARY / 2; + b.h = x1 * CHARX; + e.h = (x2 + 1) * CHARX; + win_move_to (win (), b); + win_draw_line (win (), e); + break; + case 'r': // orizzontale scorciata agli estremi + + x1 = (unsigned char) rwd[cnt++] + 5; + x2 = (unsigned char) rwd[cnt++] + 5; + b.v = e.v = row * CHARY + CHARY / 2; + b.h = x1 * CHARX + CHARX / 2; + e.h = x2 * CHARX + CHARX / 2; + win_move_to (win (), b); + win_draw_line (win (), e); + break; + case 'W': + curwid = rwd[cnt++]; + set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), + trans_pen (curpen)); + break; + case 'P': + curpen = rwd[cnt++]; + set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), + trans_pen (curpen)); + break; + case 'B': + curpat = rwd[cnt++]; + set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), + trans_pen (curpen)); + break; + case 'C': + curcol = rwd[cnt++]; + set_pen (trans_color (curcol), curwid - '0', trans_brush (curpat), + trans_pen (curpen)); + break; + default: + break; + } + } + // restore default pen + set_pen (COLOR_BLACK); +} + +void TViswin::paint_row (long j) +{ + // int or = (int)origin().x; + long y = origin ().y; + TPoint p1, p2; + if (need_paint_sel (FALSE)) + adjust_selection (p1, p2); + int row = (int) (j + 1l - y); + static char fill[] = " " + " "; + autoscroll (FALSE); + set_font (FF_FIXED, 0); + set_mode (M_COPY); + set_opaque_text (TRUE); + set_color (FOREGROUND, BACKGROUND); + printat (0, row, "%05ld", j + 1); + if (_scrolling) + { + hide_pen (); + set_brush (COLOR_WHITE); + RCT r; + r.top = row * CHARY; + r.left = CHARX * 5, + r.bottom = r.top + CHARY + 2; + r.right = CHARX * 255; + win_draw_rect (win (), &r); + } + const char *cp; + int pos = 0; + _txt.read_line (j, origin ().x); + while (cp = _txt.piece ()) + { +#if XVT_OS != XVT_OS_SCOUNIX + int st = _txt.get_style (); + long bg = trans_color (_txt.get_background ()); + long fg = trans_color (_txt.get_foreground ()); + set_font (FF_FIXED, st & 0x000f); + set_color (fg, bg); +#else + set_color (COLOR_BLACK, COLOR_WHITE); +#endif + printat (6 + pos, row, "%s", cp); +#if XVT_OS == XVT_OS_WIN + if (st & underlined) + { + PNT b, e; + + set_pen (COLOR_BLACK); + b.h = CHARX * (6 + pos); + b.v = (row + 1) * CHARY; + e.h = CHARX * (6 + pos + strlen (cp)); + e.v = (row + 1) * CHARY; + win_move_to (win (), b); + win_draw_line (win (), e); + } +#endif + pos += strlen (cp); + } + if (_scrolling && (pos < _textcolumns)) + { + set_color (COLOR_BLACK, COLOR_WHITE); + printat (6 + pos, row, "%s", fill); + } +#if XVT_OS == XVT_OS_WIN // paint page limits + if ((j % _formlen) == (_formlen - 1)) // last row + + { + PNT b, e; + + b.h = CHARX * 5; + b.v = (row + 1) * CHARY - 1; + e.h = CHARX * 132; + e.v = (row + 1) * CHARY - 1; + set_pen (COLOR_LTGRAY, 2, PAT_SOLID, P_DASH); + win_move_to (win (), b); + win_draw_line (win (), e); + } +#endif + paint_background (j, row); + autoscroll (TRUE); +} + +void TViswin::paint_column (long j, bool end) +{ + paint_header (); + set_opaque_text (TRUE); + set_mode (M_COPY); + TPoint p1, p2; + if (need_paint_sel (FALSE)) + adjust_selection (p1, p2); + set_color (COLOR_BLACK, COLOR_WHITE); + + autoscroll (FALSE); + for (long l = 0l; l < _textrows && l < (_txt.lines () - origin ().y); l++) + { + const char *c = (const char *) _txt.line (origin ().y + l); +#if XVT_OS != XVT_OS_SCOUNIX + int st = _txt.get_style ((int) j); + set_font (FF_FIXED, st & 0x000f); + long bg = trans_color (_txt.get_background ((int) j)); + long fg = trans_color (_txt.get_foreground ((int) j)); + set_color (fg, bg); +#endif + int col = end ? (int) (_textcolumns + 5) : 6; + printat (col, (int) l + 1, "%c", + (unsigned int) j < strlen (c) ? c[(int) j] : ' '); +#if XVT_OS == XVT_OS_WIN + if ((st & underlined) && strlen (c) > (word) j) + { + PNT b, e; + + set_pen (COLOR_BLACK); + b.h = CHARX * col; + b.v = (int) (l + 2l) * CHARY; + e.h = CHARX * (col + 1); + e.v = (int) (l + 2l) * CHARY; + win_move_to (win (), b); + win_draw_line (win (), e); + } +#endif + paint_background ((int) l, (int) l + 1); + } + autoscroll (TRUE); +} + +void TViswin::draw_crossbars () + // prints reference crossbars +{ +#if XVT_OS == XVT_OS_WIN + + if (_cross.v > CHARY && _cross.v < (rows () - 3) * CHARY && + _cross.h > CHARX * 5 && _cross.h < columns () * CHARX) + { + set_pen (COLOR_BLACK); + set_mode (M_XOR); + + PNT b1, e1, b2, e2; + + autoscroll (FALSE); + b1.h = _cross.h; + b1.v = CHARY; + e1.h = _cross.h; + e1.v = ((rows () - 3) * CHARY); + b2.h = CHARX * 5; + b2.v = _cross.v; + e2.h = CHARX * columns (); + e2.v = _cross.v; + win_move_to (win (), b1); + win_draw_line (win (), e1); + win_move_to (win (), b2); + win_draw_line (win (), e2); + autoscroll (TRUE); + } +#endif +} + +void TViswin::display_crossbar () +{ + if (!_cross_displayed) + draw_crossbars (); + _cross_displayed = TRUE; +} + +void TViswin::erase_crossbar () +{ + if (_cross_displayed) + draw_crossbars (); + _cross_displayed = FALSE; +} + +void TViswin::display_point () +{ + + if (!_point_displayed) + paint_point (); + _point_displayed = TRUE; +} + +void TViswin::erase_point () +{ + if (_point_displayed) + paint_point (); + _point_displayed = FALSE; +} + +void TViswin::paint_point (bool erase) +{ + autoscroll (FALSE); + static bool wasbar; + + if (_isbar) + { + invert_bar (6, (int) (_point.y - origin ().y + 1l), + (int) columns (), (int) (_point.y - origin ().y + 2l)); + invert_bar ((int) (_point.x - origin ().x + 6l), 1, + (int) (_point.x - origin ().x + 7l), (int) (rows () - 3l)); + } + else + { + invert_bar ((int) (_point.x - origin ().x + 6l), (int) (_point.y - origin ().y + 1l), + (int) (_point.x - origin ().x + 7l), (int) (_point.y - origin ().y + 2l)); + invert_bar (0, (int) (_point.y - origin ().y + 1l), 5, + (int) (_point.y - origin ().y + 2l)); + invert_bar ((int) (_point.x - origin ().x + 6l), 0, + (int) (_point.x - origin ().x + 7l), 1); + } + autoscroll (TRUE); + wasbar = _isbar; +} + +// draw screen header +void TViswin::paint_header () +{ + set_mode (M_COPY); + set_opaque_text (TRUE); + set_color (FOREGROUND, BACKGROUND); + set_font (FF_FIXED, 0); + TString htmpst (10); + for (int i = 1; i < 26; i++) + { + htmpst.format ("%d", i); + htmpst.right_just (10, '.'); + printat (i * 10 - 4, (int) origin ().y, "%s", (const char *) htmpst); + } + autoscroll (FALSE); + set_color (COLOR_WHITE, BACKGROUND); + printat (0, 0, "P.%3ld ", ((origin ().y) / _formlen) + 1l); + autoscroll (TRUE); +} + +void TViswin::paint_selection () +{ + TPoint p1, p2; + adjust_selection (p1, p2); + + // paint rows + for (long l = p1.y; l <= p2.y; l++) + { + int top, left, right; + top = (int) (l - origin ().y + 1); + if (top > 0 && top <= _textrows) + { + left = p1.y == l ? (int) (p1.x - origin ().x + 6l) : 6; + right = p2.y == l ? (int) (p2.x - origin ().x + 6l) : + (int) (_textcolumns + 6l); + autoscroll (FALSE); + invert_bar (left, top, right, top + 1); + autoscroll (TRUE); + } + } +} + +void TViswin::paint_waitbar (bool xor) +{ +#if XVT_OS == XVT_OS_WIN + static int pic; +#endif + autoscroll (FALSE); + if (xor) + { +#if XVT_OS == XVT_OS_WIN + cpb_win_picture_draw_at (win (), _picture[pic], 4, 4 + (int) (rows () - 3l) * CHARY); + if (pic == 3) + pic = 0; + else + pic++; +#else + invert_bar (3, rows () - 2, 4, rows () - 1); +#endif + } + else + { +#if XVT_OS == XVT_OS_WIN + cpb_win_picture_draw_at (win (), _picture[pic], 4, + 4 + (int) (rows () - 3l) * CHARY); + if (pic == 3) + pic = 0; + else + pic++; +#else + printat (3, rows () - 2, "%c", '*'); +#endif + } + autoscroll (TRUE); +} + +void TViswin::update () +{ + if (_scrolling) + return; + + erase_point (); + autoscroll (FALSE); + set_mode (M_COPY); + set_brush (MASK_BACK_COLOR); + bar (5, rows () - 3, columns () + 1, rows () + 1); + + if (_need_update) + { + if (_isselection) + erase_selection (); + clear (COLOR_WHITE); + set_mode (M_COPY); + set_brush (MASK_BACK_COLOR); + autoscroll (FALSE); + bar (0, 0, columns () + 1, 1); + bar (0, 0, 5, rows () + 1); + bar (5, rows () - 3, columns () + 1, rows () + 1); + if (_isopen) + paint_waitbar (FALSE); +#if XVT_OS == XVT_OS_WIN +else + cpb_win_picture_draw_at (win(), _modpic, 4, + 4 + (int) (rows () - 3l) * CHARY); +#endif + autoscroll (TRUE); + paint_header (); + paint_screen (); + if (_isselection) + display_selection (); + } + display_point (); + autoscroll (TRUE); + _need_update = TRUE; + _need_scroll = none; +} + +void TViswin::abort_print () +{ + if (yesno_box ("Interruzione della stampa su video?")) + { + _txt.freeze (); + freeze (); + set_focus (); + close_print (); + } +} + +void TViswin::handler (WINDOW win, EVENT * ep) +{ + int kdiff_x, kdiff_y; + PNT newcross; + TPoint p; + static bool ignore = FALSE; + bool tlnk = FALSE; + int kdiff; + long new_origin; + switch (ep->type) + { + case E_USER: + if (ep->v.user.id == E_ADDLINE) + { + set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? + _txt.lines () : _txt.lines () - _textrows); + } + else if (ep->v.user.id == E_ADDLINE_ONSCREEN) + { + set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); + erase_point (); + if (need_paint_sel (FALSE)) + erase_selection (); + paint_row (_txt.lines () - 1l); + if (need_paint_sel (FALSE)) + display_selection (); + display_point (); + if (_txt.lines () > 1l) + _need_update = FALSE; + else + force_update (); + } + autoscroll (FALSE); + _textrows = TEXTROWS; + _textcolumns = TEXTCOLUMNS; + autoscroll (TRUE); + break; + case E_CONTROL: + if (ep->v.ctl.ci.type == WC_PUSHBUTTON) + switch (ep->v.ctl.id) + { + case DLG_QUIT: + if (_isopen) + abort_print (); + else + { +#if XVT_OS == XVT_OS_WIN + xvt_statbar_set (""); + xvt_statbar_refresh (); +#endif + stop_run (K_ENTER); + } + break; + case DLG_PRINT: + _txt.print (); + break; + case DLG_EDIT: + check_link (); + call_editor (); + _need_update = TRUE; + update (); + check_link (&_point); + break; + case DLG_LINK: + exec_link(); + break; + } + break; + case E_TIMER: + if (ep->v.timer.id == _timer) + { + kill_timer (_timer); + _istimer = FALSE; + } + else if (ep->v.timer.id == _wtimer) + { + paint_waitbar (); + kill_timer (_wtimer); + if (_isopen) + _wtimer = set_timer (win, 150l); + } + break; + case E_MOUSE_DBL: + break; + case E_MOUSE_DOWN: + p = ep->v.mouse.where; + trap_mouse (win); + + if (ep->v.mouse.button == 0) // left button: text selection + + { + if (need_paint_sel (FALSE)) + { + erase_selection (); + _isselection = FALSE; + } + if (!in_text (p) || (p.y + origin ().y) >= _txt.lines ()) + { + ignore = TRUE; + break; + } + + erase_point (); + _sel_start = ep->v.mouse.where; + _sel_start.x += (origin ().x - 6); + _sel_start.y += (origin ().y - 1); + _sel_end = _sel_start; + _selecting = TRUE; + } + else + { + // show crossbars + _cross = ep->v.mouse.where; + display_crossbar (); + _iscross = TRUE; + } + break; + case E_MOUSE_UP: + release_mouse (); + + if (ep->v.mouse.button == 0) // left button: text selection/move + // point + + { + p = ep->v.mouse.where; + + if (_isopen && (p.x >= 4 && p.x) <= 6 && + (p.y >= (int) rows () - 3 && p.y <= (int) rows () - 1)) + { + abort_print (); + ignore = TRUE; + } + if (ignore) + { + ignore = FALSE; + _selecting = FALSE; + break; + } + // confirm selection & store + p.x += (origin ().x - 6); + p.y += (origin ().y - 1); + + if (_sel_start == p) + { + if (_isselection) + { + _isselection = FALSE; + erase_selection (); + } + if (_sel_start == _point && !_selecting) + { + dispatch_e_char (win, K_F5); + } + else + { + TPoint xx; + _point.x = p.x; + _point.y = p.y; + if (_point.y > _txt.lines ()) + _point.y = _txt.lines () - 1l; + if (_point.y < 0) + _point.y = 0; + if (_point.x < 0) + _point.x = 0; + if (_point.x > 255) + _point.x = 255; + + check_link (&_point); + display_point (); + } + } + else + { + _sel_end.x = p.x; + _sel_end.y = p.y; + if (_sel_end.y >= _txt.lines ()) + _sel_end.y = _txt.lines () - 1l; + if (_sel_end.y < 0) + _sel_end.y = 0; + if (_sel_end.x < 0) + _sel_end.x = 0; + if (_sel_end.x > 255) + _sel_end.x = 255; + _point = _sel_end; + _isselection = TRUE; + check_link (&_point); + display_point (); + } + _selecting = FALSE; + } + else + { + erase_crossbar (); + _iscross = FALSE; + } + break; + case E_MOUSE_MOVE: + { + /* + if (!_selecting && !_iscross) // no buttons pressed + { + p = ep->v.mouse.where; + if (in_text (p)) + { + p.x += (origin ().x - 6); + p.y += (origin ().y - 1); + check_link (&p); + } + } + */ + if (_selecting || _iscross) + { + p = ep->v.mouse.where; + if (_selecting) + _isselection = TRUE;; + { + _isselection = TRUE; + } + // scroll if necessary + if (p.y >= _textrows + 1l) + { + if (_isselection) + erase_selection (); + if (_iscross) + erase_crossbar (); + dispatch_e_scroll (win, K_DOWN); + if (_isselection) + display_selection (); + if (_iscross) + display_crossbar (); + } + else if (p.y <= 0l) + { + if (_isselection) + erase_selection (); + if (_iscross) + erase_crossbar (); + dispatch_e_scroll (win, K_UP); + if (_isselection) + display_selection (); + if (_iscross) + display_crossbar (); + } + else if (p.x <= 5l) + { + if (_isselection) + erase_selection (); + if (_iscross) + erase_crossbar (); + dispatch_e_scroll (win, K_LEFT); + if (_isselection) + display_selection (); + if (_iscross) + display_crossbar (); + } + else if (p.x >= _textcolumns + 6) + { + if (_isselection) + erase_selection (); + if (_iscross) + erase_crossbar (); + dispatch_e_scroll (win, K_RIGHT); + if (_isselection) + display_selection (); + if (_iscross) + display_crossbar (); + } + if (_selecting) + { + if (in_text (p)) + { + p.x += (origin ().x - 6); + p.y += (origin ().y - 1); + _point = p; + if (_point.y >= _txt.lines ()) + _point.y = _txt.lines () - 1l; + } + if (_point != _sel_end) + { + erase_selection (); + _sel_end = _point; + display_selection (); + } + } + } + if (_iscross) + { + newcross = ep->v.mouse.where; + if (_cross.h != newcross.h || _cross.v != newcross.v) + { + erase_crossbar (); + _cross = newcross; + display_crossbar (); + } + } + } + break; + case E_SIZE: + if (is_open ()) + { + check_link (); + erase_point (); + if (_isselection) + erase_selection (); + autoscroll (FALSE); + _textrows = TEXTROWS; + _textcolumns = TEXTCOLUMNS; + autoscroll (TRUE); + repos_buttons (); + display_point (); + _need_update = TRUE; + force_update (); + do_events (); + check_link (&_point); + } + break; + case E_HSCROLL: + case E_VSCROLL: + { + erase_point (); + tlnk = TRUE; + switch (ep->v.scroll.what) + { + case SC_PAGE_UP: + if (ep->type == E_VSCROLL) + { + if (origin().y > 0) + { + kdiff = (int) (_point.y - origin ().y); + new_origin = origin ().y > _textrows ? + origin ().y - _textrows + 1l : 0; + _point.y = new_origin + kdiff; + check_link (); + update_thumb (origin ().x, new_origin); + _need_update = TRUE; + update (); // ORRIIIBILE! + + check_link (&_point); + _need_update = FALSE; + } + else + { + beep (); + update_thumb(-1, 0); + } + } + else + { + if (origin ().x > 0) + { + kdiff = (int) (_point.x - origin ().x); + new_origin = origin ().x > _textcolumns ? + origin ().x - _textcolumns + 1 : 0; + _point.x = new_origin + kdiff; + check_link (); + update_thumb(new_origin, _point.y); + _need_update = TRUE; + update (); // AAAARGH! + + check_link (&_point); + _need_update = FALSE; + } + else + { + beep (); + update_thumb(0, -1); + } + } + break; + case SC_LINE_UP: + if (ep->type == E_VSCROLL) + { + _need_update = FALSE; + if (origin ().y > 0l) + { + _point.y--; + if (need_paint_sel ()) + erase_selection (); + check_link (); + update_thumb (origin ().x, origin ().y - 1l); + _need_scroll = down; + } + else + { + beep (); + update_thumb(-1, 0); + } + } + else + { + _need_update = FALSE; + if (origin ().x > 0l) + { + if (need_paint_sel (FALSE)) + erase_selection (); + check_link (); + update_thumb (origin ().x - 1l, origin ().y); + _point.x--; + _need_scroll = right; + } + else + { + beep (); + update_thumb(0, -1); + } + } + break; + case SC_PAGE_DOWN: + if (ep->type == E_VSCROLL) + { + if ((origin ().y + _textrows) < _txt.lines ()) + { + kdiff = (int) (_point.y - origin ().y); + new_origin = (_txt.lines () - origin ().y) > + (_textrows * 2l) ? + origin ().y + _textrows - 1 : _txt.lines () - _textrows; + _point.y = new_origin + kdiff; + check_link (); + update_thumb (origin ().x, new_origin); + _need_update = TRUE; + update (); // AAAARGH! + + check_link (&_point); + _need_update = FALSE; + } + else + { + beep (); + update_thumb(-1, _txt.lines()-_textrows-1); + } + } + else + { + if ((origin ().x + _textcolumns) < 256) + { + kdiff = (int) (_point.x - origin ().x); + new_origin = (256 - origin ().x) > _textcolumns ? + origin ().x + _textcolumns - 1 : 256 - _textcolumns; + _point.x = new_origin + kdiff; + check_link (); + update_thumb (new_origin, origin ().y); + _need_update = TRUE; + update (); // AAAARGH! + + check_link (&_point); + _need_update = FALSE; + } + else + { + beep (); + update_thumb(255-_textcolumns, -1); + } + } + break; + case SC_LINE_DOWN: + if (ep->type == E_VSCROLL) + { + _need_update = FALSE; + if ((origin ().y + _textrows) < _txt.lines ()) + { + if (need_paint_sel ()) + erase_selection (); + check_link (); + update_thumb (origin ().x, origin ().y + 1l); + _point.y++; + _need_scroll = up; + } + else + { + beep (); + update_thumb(-1, _txt.lines()-_textrows-1); + } + } + else + { + _need_update = FALSE; + if ((origin ().x + _textcolumns) < 256) + { + if (need_paint_sel (FALSE)) + erase_selection (); + check_link (); + update_thumb (origin ().x + 1l, origin ().y); + _need_scroll = left; + _point.x++; + } + else + { + beep (); + update_thumb(255-_textcolumns, -1); + } + } + break; + case SC_THUMB: + + check_link (); + kdiff_x = (int) (_point.x - origin ().x); + kdiff_y = (int) (_point.y - origin ().y); + + p.x = ep->type == E_VSCROLL ? origin ().x : ep->v.scroll.pos; + p.y = ep->type == E_HSCROLL ? origin ().y : ep->v.scroll.pos; + + if ((p.y + _textrows) >= _txt.lines ()) + p.y = _txt.lines () - _textrows -1; + if ((p.x + _textcolumns) >= 255) + p.x = 255 - _textcolumns; + + update_thumb (p.x, p.y); + + _point.x = ep->type == E_VSCROLL ? origin ().x : + origin ().x + kdiff_x; + _point.y = ep->type == E_HSCROLL ? origin ().y : + origin ().y + kdiff_y; + _need_update = TRUE; + update (); + check_link (&_point); + break; + + default: + break; + } + // for failed scrollings + if (!_selecting && _need_scroll == none) + { + check_link (&_point); + display_point (); + } + } + break; + default: + break; + } + if (_need_scroll != none) + { + _need_update = FALSE; + scroll tmp = _need_scroll; + _need_scroll = none; + shift_screen (tmp); + if (!_selecting) + { + check_link (&_point); + display_point (); + } + if (_isselection) + display_selection (); + } + if (ep->type != E_UPDATE || _need_update) + TWindow ::handler (win, ep); + else if (ep->type == E_UPDATE) + update (); +} + +bool TViswin::on_key (KEY key) +{ + EVENT_TYPE type = E_USER; + + if (_istimer) + return TRUE; + _timer = set_timer (win (), 50l); + _istimer = TRUE; + + if (key == K_UP || key == K_DOWN || key == K_LEFT || key == K_RIGHT) + if (_selflag) + key += K_SHIFT; + + if (_selecting && key != K_SHIFT_UP && key != K_SHIFT_DOWN + && key != K_SHIFT_LEFT && key != K_SHIFT_RIGHT) + _selecting = FALSE; + + switch (key) + { + case CTRL_E: + if (_isedit) + { + check_link (); + call_editor (); + set_focus (); + _need_update = TRUE; + update (); + check_link (&_point); + } + break; + case CTRL_C: + exec_link(); + break; + case CTRL_S: + if (_isprint) + _txt.print (); + break; + case CTRL_R: + _need_update = TRUE; + check_link (); + force_update (); + do_events (); + check_link (&_point); + break; + case K_ESC: + if (_isopen) + abort_print (); + else + { + +#if XVT_OS == XVT_OS_WIN + xvt_statbar_set (""); + xvt_statbar_refresh (); +#endif + stop_run (K_ESC); + } + break; + case K_ENTER: + if (_isselection) + { + erase_selection (); + _isselection = FALSE; + } + break; + case K_TAB: + if (_curbut == (_buttons - 1)) + _curbut = 0; + else + _curbut++; + break; + case K_BTAB: + if (_curbut == 0) + _curbut = _buttons - 1; + else + _curbut--; + break; + case K_SPACE: + case K_CTRL_ENTER: + if (_linkID != -1) + { + exec_link(); + } + else + dispatch_e_char (_button[_curbut], K_SPACE); + break; + case K_LHOME: + _need_update = TRUE; + update_thumb (0, 0); + _point.set (0, 0); + check_link (&_point); + force_update (); + break; + case K_LEND: + _need_update = TRUE; + update_thumb (0, _txt.lines () - _textrows); + _point.set (0, _txt.lines () - 1); + check_link (&_point); + force_update (); + break; + case K_RIGHT: + case K_LEFT: + case K_WRIGHT: + case K_WLEFT: + case K_ALT_RIGHT: + case K_ALT_LEFT: + case K_SHIFT_RIGHT: + case K_SHIFT_LEFT: + type = E_HSCROLL; + break; + case K_UP: + case K_DOWN: + case K_NEXT: + case K_PREV: + case K_CTRL_UP: + case K_CTRL_DOWN: + case K_SHIFT_UP: + case K_SHIFT_DOWN: + type = E_VSCROLL; + break; + case K_F5: + check_link (); + erase_point (); + _isbar = !_isbar; + _need_update = TRUE; + force_update (); + do_events (); + check_link (&_point); + break; + case K_F6: + _selflag = !_selflag; + break; + default: + break; + } + + switch (type) + { + case E_HSCROLL: + case E_VSCROLL: + { + erase_point (); + check_link (); + switch (key) + { + case K_PREV: + dispatch_e_scroll (win(), K_PREV); + break; + case K_NEXT: + dispatch_e_scroll (win(), K_NEXT); + break; + case K_WLEFT: + dispatch_e_scroll (win(), K_BTAB); + break; + case K_WRIGHT: + dispatch_e_scroll (win(), K_TAB); + break; + case K_CTRL_UP: + dispatch_e_scroll (win(), K_UP); + break; + case K_CTRL_DOWN: + dispatch_e_scroll (win(), K_DOWN); + break; + case K_ALT_LEFT: + dispatch_e_scroll (win(), K_LEFT); + break; + case K_ALT_RIGHT: + dispatch_e_scroll (win(), K_RIGHT); + break; + case K_UP: + case K_SHIFT_UP: + _need_update = FALSE; + if (key == K_SHIFT_UP) + { + if (need_paint_sel (FALSE)) + erase_selection (); + if (!_selecting) + { + _sel_start = _point; + _selecting = TRUE; + } + } + if (_point.y > 0l) + { + if (_point.y == origin ().y) + { + if (need_paint_sel ()) + erase_selection (); + update_thumb (origin ().x, --_point.y); + _need_scroll = down; + } + else + _point.y--; + if (key == K_SHIFT_UP) + { + _sel_end = _point; + _isselection = TRUE; + } + } + else + beep (); + break; + case K_LEFT: + case K_SHIFT_LEFT: + _need_update = FALSE; + if (_point.x > 0l) + { + if (key == K_SHIFT_LEFT) + { + if (need_paint_sel (FALSE)) + erase_selection (); + if (!_selecting) + { + _sel_start = _point; + _selecting = TRUE; + } + } + if (_point.x == origin ().x) + { + _need_update = FALSE; + if (need_paint_sel (FALSE)) + erase_selection (); + update_thumb (--_point.x, origin ().y); + _need_scroll = right; + } + else + _point.x--; + if (key == K_SHIFT_LEFT) + { + _sel_end = _point; + _isselection = TRUE; + } + } + else + beep (); + break; + case K_DOWN: + case K_SHIFT_DOWN: + _need_update = FALSE; + if (_point.y < (_txt.lines () - 1)) + { + if (key == K_SHIFT_DOWN) + { + if (need_paint_sel (FALSE)) + erase_selection (); + if (!_selecting) + { + _sel_start = _point; + _selecting = TRUE; + } + } + if (_point.y == origin ().y + _textrows - 1) + { + if (need_paint_sel ()) + erase_selection (); + // check_link(); + update_thumb (origin ().x, (++_point.y) - _textrows + 1); + _need_scroll = up; + } + else + _point.y++; + if (key == K_SHIFT_DOWN) + { + _sel_end = _point; + _isselection = TRUE; + } + } + else + beep (); + break; + case K_RIGHT: + case K_SHIFT_RIGHT: + _need_update = FALSE; + if (_point.x < 256) + { + if (key == K_SHIFT_RIGHT) + { + if (need_paint_sel (FALSE)) + erase_selection (); + if (!_selecting) + { + _sel_start = _point; + _selecting = TRUE; + } + } + if (_point.x == (origin ().x + _textcolumns - 1)) + { + if (need_paint_sel (FALSE)) + erase_selection (); + // check_link(); + update_thumb ((++_point.x) - _textcolumns + 1l, origin ().y); + _need_scroll = left; + } + else + _point.x++; + if (key == K_SHIFT_RIGHT) + { + _sel_end = _point; + _isselection = TRUE; + } + } + else + beep (); + break; + default: + break; + } + if (_need_scroll != none) + { + _need_update = FALSE; + scroll tmp = _need_scroll; + _need_scroll = none; + shift_screen (tmp); + } + if (_isselection) + display_selection (); + check_link (&_point); + force_update (); + } + break; +default: + break; +} + return TWindow::on_key (key); +} + +bool TViswin::call_editor () +{ + TConfig cnf (CONFIG_GENERAL, "Link"); + TString editor (cnf.get ("txt")); + + bool ok = FALSE; + + if (!editor.empty ()) + { + TString newfilename; + + static FILE_SPEC fs; + get_default_dir (&fs.dir); + strcpy (fs.type, "txt"); + save_dir (); + if (save_file_dlg (&fs, "Salva il file con il nome:") == FL_OK) + { + restore_dir (); + char path[256]; + dir_to_str (&fs.dir, path, sizeof (path)); + newfilename << path << '/' << fs.name; + + TPoint p1, p2; + if (_isselection) + adjust_selection (p1, p2); + + if (_txt.write (newfilename, _isselection ? &p1 : NULL, + _isselection ? &p2 : NULL)) + { + newfilename.insert (" ", 0); + newfilename.insert (editor, 0); + TExternal_app edit (newfilename); + if (edit.run (TRUE)) + beep (); + else + ok = TRUE; + } + } + else + restore_dir (); + } + else + warning_box ("Nessun editor specificato nei parametri studio"); + return ok; +} + +void TViswin::add_line (const char *l) +{ + if (_isopen && !_frozen) + { + if (_txt.frozen ()) // error writing files + + { + close_print (); + return; + } + _txt.append (l); + EVENT ev; + ev.type = E_USER; + ev.v.user.id = (_txt.lines () - origin ().y) <= _textrows ? + E_ADDLINE_ONSCREEN : E_ADDLINE; + dispatch_event (win (), &ev); + do_events (); + } +} + +void TViswin::close_print () +{ + _isopen = FALSE; + kill_timer (_wtimer); + _need_update = TRUE; + force_update (); +} + +TViswin ::TViswin (const char *fname, + const char *title, + bool editbutton, + bool printbutton, + bool linkbutton): + _filename (fname), _txt (fname, BUFFERSIZE), _islink (linkbutton), _isedit (editbutton), + _isprint (printbutton), _isbar (FALSE), _istimer (FALSE), _iscross (FALSE), + _isselection (FALSE), _sel_displayed (FALSE), _cross_displayed (FALSE), + _link_displayed (FALSE), _point_displayed (FALSE), _selecting (FALSE), + _scrolling (FALSE), _selflag (FALSE), _need_update (TRUE), _need_scroll (none), + _multiple (FALSE), + _frozen (FALSE) +{ + if (title == NULL) + title = (fname ? fname : "Anteprima di stampa"); + + _isopen = fname == NULL; + if (_isopen) + _filename = _txt.name (); + + for (int i = 0; i < MAXBUT; i++) + _button[i] = NULL_WIN; + + const int larg = 76; + const int alt = 20; + RCT r; + get_client_rect (TASK_WIN, &r); + int maxlarg = r.right / CHARX - 6; // Calculates max window width + + int maxalt = r.bottom / CHARY - 6; + if (larg > maxlarg) + maxlarg = larg; + if (alt > maxalt) + maxalt = alt; + +#if XVT_OS == XVT_OS_WIN + for (i = 0; i < 4; i++) + _picture[i] = cpb_picture_load (BMP_MODULE1 + i); + _modpic = cpb_picture_load (BMP_MODULE); +#endif + + create (-1, -1, maxlarg, maxalt, title, + WSF_CLOSE | WSF_HSCROLL | WSF_VSCROLL | WSF_SIZE); + + set_opaque_text (TRUE); + set_font (FF_FIXED); + + add_button (DLG_QUIT, DLG_QUIT_TITLE); + _buttons = 1; + + if (_isedit) + { + add_button (DLG_EDIT, DLG_EDIT_TITLE); + _buttons++; + } + if (_islink) + { + _link_button = add_button (DLG_LINK, DLG_LINK_TITLE); + _buttons++; + xvt_enable_control (_link_button, FALSE); + } + if (_isprint) + { + add_button (DLG_PRINT, DLG_PRINT_TITLE); + _buttons++; + } + + //#if XVT_OS == XVT_OS_SCOUNIX + // maximize(); + // #endif + + _curbut = 0; + + if (_isopen) + _wtimer = set_timer (win (), 150l); + + _point.set (0, 0); + autoscroll (FALSE); + _textrows = TEXTROWS; + _textcolumns = TEXTCOLUMNS; + autoscroll (TRUE); + + _links = &(main_app().printer ().links ()); + _multiple = main_app().printer ().ismultiplelink (); + _bg = main_app().printer ().getbgdesc (); + _isbackground = _bg->items () > 0; + _formlen = main_app().printer ().formlen (); + + for (i = 0; i < _links->items (); i++) + { + TToken_string & t = (TToken_string &) (*_links)[i]; + char f = *(t.get (1)); + char b = *(t.get (2)); + t.restart (); + _txt.set_hotspots (f, b); + } + _hotspots = &(_txt.hotspots ()); +} + +TViswin ::~TViswin () +{ +#if XVT_OS == XVT_OS_WIN + for (int i = 0; i < 4; i++) + picture_free (_picture[i]); +#endif +} diff --git a/include/xvtility.cpp b/include/xvtility.cpp index 8edd3e475..89c9279c1 100755 --- a/include/xvtility.cpp +++ b/include/xvtility.cpp @@ -1,928 +1,927 @@ -#include -#include - -#include -#include - -#if XVT_OS == XVT_OS_SCOUNIX -extern "C" { long nap(long period); } -#endif - -#ifdef DBG -// FATAL_HOOK che intercetta errori fatali XVT -// put breakpoint here -void fatal_hook() -{ - int dummy = 0; - dummy++; -} -#endif - -#if XVTWS == WMWS - -short CHARX = 8; -short CHARY = 8; -short BASEY = 8; -short ROWY = 8; - -COLOR MASK_BACK_COLOR = COLOR_WHITE; -COLOR NORMAL_COLOR = COLOR_BLACK; -COLOR NORMAL_BACK_COLOR = COLOR_WHITE; -COLOR DISABLED_COLOR = COLOR_GRAY; -COLOR DISABLED_BACK_COLOR = COLOR_WHITE; -COLOR FOCUS_COLOR = COLOR_BLACK; -COLOR FOCUS_BACK_COLOR = COLOR_WHITE; - -#else - -#include -#include - -#ifdef __CTL3D__ -#include -#endif - -HIDDEN COLORREF COLOR2RGB(COLOR c) -{ - const byte red = byte((c >> 16) & 0xFF); - const byte gre = byte((c >> 8) & 0xFF); - const byte blu = byte(c & 0xFF); - return RGB(red, gre, blu); -} - -HIDDEN COLOR RGB2COLOR(COLORREF c) -{ - const byte red = byte(c & 0xFF); - const byte gre = byte((c >> 8) & 0xFF); - const byte blu = byte((c >> 16) & 0xFF); - return MAKE_COLOR(red, gre, blu); -} - - -extern "C" { - WINDOW xvtwi_hwnd_to_window(HWND); -#include -} -#include - -short CHARX = 8; -short ROWY = GetSystemMetrics(SM_CYSCREEN) / 25; -short CHARY = 14; -short BASEY = 12; - -HIDDEN HFONT NormalFont = NULL; -HIDDEN LOGFONT LogFont; -HIDDEN int FontWeight; - -#ifdef __CTL3D__ -COLOR MASK_BACK_COLOR = COLOR_LTGRAY; -#else -COLOR MASK_BACK_COLOR = MAKE_COLOR(0,128,128); -#endif - -COLOR NORMAL_COLOR = COLOR_BLACK; -COLOR NORMAL_BACK_COLOR = COLOR_LTGRAY; -COLOR DISABLED_COLOR = COLOR_GRAY; -COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR; - -HIDDEN COLORREF MaskColor = COLOR2RGB(MASK_BACK_COLOR); -HIDDEN HBRUSH MaskBrush = CreateSolidBrush(MaskColor); - -HIDDEN COLORREF FocusForeColor = COLOR2RGB(COLOR_BLACK); -HIDDEN COLORREF FocusBackColor = COLOR2RGB(COLOR_CYAN); -HIDDEN HBRUSH FocusBrush = CreateSolidBrush(FocusBackColor); - -COLOR FOCUS_COLOR = RGB2COLOR(FocusForeColor); -COLOR FOCUS_BACK_COLOR = RGB2COLOR(FocusBackColor); - -HIDDEN COLORREF NormalForeColor = COLOR2RGB(NORMAL_COLOR); -HIDDEN COLORREF NormalBackColor = COLOR2RGB(NORMAL_BACK_COLOR); -HIDDEN HBRUSH NormalBrush = CreateSolidBrush(NormalBackColor); - -static BOOLEAN event_hook(HWND hwnd, - UINT msg, - UINT wparam, - ULONG lparam, - long* ret) -{ - switch(msg) - { -#ifdef __CTL3D__ - case WM_SYSCOLORCHANGE: - Ctl3dColorChange(); - break; -#endif - case WM_CTLCOLOR: - { -#ifdef __CTL3D__ - *ret = Ctl3dCtlColorEx(msg, wparam, lparam); - return TRUE; -#else - const word type = HIWORD(lparam); - if (type == CTLCOLOR_LISTBOX || type == CTLCOLOR_EDIT || - type == CTLCOLOR_MSGBOX) - { - HWND hwnd = LOWORD(lparam); - HDC hdc = wparam; - - if (!IsWindowEnabled(hwnd)) // Campo disabilitato - { - if (type != CTLCOLOR_MSGBOX) - { - SetTextColor(hdc, NormalForeColor); - SetBkColor(hdc, MaskColor); - } - *ret = MaskBrush; - return TRUE; - } - - bool focus = GetFocus() == hwnd; - if (type != CTLCOLOR_MSGBOX) - { - SetTextColor(hdc, focus ? FocusForeColor : NormalForeColor); - SetBkColor(hdc, focus ? FocusBackColor : NormalBackColor); - } - *ret = focus ? FocusBrush : NormalBrush; - return TRUE; - } -#endif - } - break; - case WM_COMMAND: - { - const word notify = HIWORD(lparam); - if (notify == EN_KILLFOCUS || notify == EN_SETFOCUS) - { - HWND hwnd = LOWORD(lparam); // Ridisegna BENE il campo - InvalidateRect(hwnd, NULL, TRUE); - } - } - break; - case WM_KEYDOWN: - if (wparam == VK_PRIOR || wparam == VK_NEXT || - wparam == VK_UP || wparam == VK_DOWN ) - { - char name[16]; - GetClassName(hwnd, name, 5); - if (stricmp(name, "Edit") == 0) - { - KEY key; - switch(wparam) - { - case VK_PRIOR: - key = K_PREV; break; - case VK_NEXT: - key = K_NEXT; break; - case VK_UP: - key = K_UP; break; - case VK_DOWN: - key = K_DOWN; break; - default: - key = 0; break; - } - if (key > 0) - { - WINDOW w = cur_win(); - if (w != NULL_WIN) - dispatch_e_char(w, key); - } - } - } - break; - case WM_MENUCHAR: - { - WINDOW w = cur_win(); - if (w != NULL_WIN) - { - const KEY key = toupper(wparam)+K_CTRL; - dispatch_e_char(w, key); - } - } - break; - default: - break; - } - - return FALSE; -} - - -HIDDEN WIN_TYPE _wc_type = W_NONE; - -static void createwindow_hook(DWORD* exstyle, LPCSTR* classname, LPCSTR* windowname, DWORD* styl, - int* x, int* y, int* width, int* height, HWND* parent, HMENU* menu, - HINSTANCE inst, void **) -{ - if (_wc_type == WC_EDIT) - { - *y++; - } else - if (_wc_type == WC_GROUPBOX) - { - *classname = "Static"; - } - _wc_type = W_NONE; -} - -#endif - - -RCT& resize_rect(short x, short y, short dx, short dy, WIN_TYPE wt, WINDOW parent) -{ - static RCT r; - - if (parent != TASK_WIN) - { - if (get_window_type(parent) == W_PLAIN) // Mask with Toolbar - { - if (y >= 0) y++; - if (x > 0 || (wt != WO_TE && x == 0)) - { - RCT pc; get_client_rect(parent, &pc); // Get parent window size - const int width = pc.right; - const int tot = 80*CHARX; - if (width > tot) x += (width-tot) / (CHARX<<1); - } - } - wt = WC_EDIT; - } - -#if XVT_OS == XVT_OS_WIN - switch (wt) - { - case WC_EDIT : - r.left = (x+1)*CHARX; - r.top = y*ROWY; - r.right = dx*CHARX; - r.bottom = (CHARY << 1) - BASEY; - if (dy > 1) - r.bottom += ROWY*(dy-1); - break; - case W_DOC: - r.left = x * CHARX; - r.top = y * ROWY; - r.right = dx * CHARX; - r.bottom = dy * CHARY; - break; - default: - r.left = x * CHARX; - r.top = y * ROWY; - r.right = (dx+2)*CHARX; - r.bottom = dy*ROWY-1; - break; - } -#else - r.left = x * CHARX; - r.top = y * CHARY; - r.right = dx * CHARX; - r.bottom = dy * CHARY; -#endif - - if (x < 0 || y < 0 || dx <= 0 || dy <= 0) - { - RCT pc; - if (parent == NULL_WIN) parent = TASK_WIN; - get_client_rect(parent, &pc); // Get parent window size - const short MAXX = pc.right; - const short MAXY = pc.bottom; - - if (x < 0) - { - x = -x; - if (wt != WC_EDIT && x == 1) x = 11; - if (x > 10) - { - const int num = x/10 -1; - const int tot = x%10; - const int spc = (MAXX - tot*r.right) / (tot+1); - r.left = spc + num*(spc+r.right); - } - else - r.left = MAXX - r.right - x*CHARX; - } - - if (y < 0) - { - y = -y; - if (wt != WC_EDIT && y == 1) y = 11; - if (y > 10) - { - const int num = y/10 -1; - const int tot = y%10; - const int spc = (MAXY - tot*r.bottom) / (tot+1); - r.top = spc + num*(spc+r.bottom); - } - else - r.top = MAXY - r.bottom - (y-1)*ROWY; - } - - if (dx <= 0) r.right = MAXX + dx*CHARX; - else r.right += r.left; - if (dy <= 0) r.bottom = MAXY + dy*ROWY; - else r.bottom += r.top; - } - else - { - r.right += r.left; - r.bottom += r.top; - } - return r; -} - - -void beep() -{ xvt_beep(); } - - -/////////////////////////////////////////////////////////// -// Event Handling -/////////////////////////////////////////////////////////// - -class TEvent_manager -{ - enum { MAX = 16 }; - WINDOW _w[MAX]; - EVENT _e[MAX]; - int _begin, _end; - -public: - TEvent_manager() : _begin(0), _end(0) {} - void push(WINDOW win, const EVENT& event); - void pop(); -}; - -HIDDEN TEvent_manager EM; - -void TEvent_manager::push(WINDOW w, const EVENT& e) -{ - CHECK(w, "You shouldn't send events to NULL_WIN!"); - _w[_end] = w; - _e[_end] = e; - _end = (++_end) % MAX; - CHECKD(_end != _begin, "Too many events queued: max. ", MAX); -} - -void TEvent_manager::pop() -{ - if (_begin != _end) - { - const int i = _begin; - _begin = (++_begin) % MAX; // Other events may occur! - dispatch_event(_w[i], &_e[i]); - } -} - -void do_events() -{ - process_events(); - EM.pop(); -#if XVT_OS == XVT_OS_SCOUNIX - nap(20); -#endif -} - -KEY e_char_to_key(const EVENT* ep) -{ - CHECK(ep->type == E_CHAR, "I can't convert a Non-E_CHAR event to a key"); - - KEY key = ep->v.chr.ch; - if (key < K_INS || key > K_HELP) - { - // if (ep->v.chr.shift && !isprint(key)) key += K_SHIFT; - if (ep->v.chr.shift && (key < ' ' || key > 'z')) key += K_SHIFT; - if (key >= ' ' && ep->v.chr.control) key += K_CTRL; - } - return key; -} - - -void dispatch_e_char(WINDOW win, KEY key) -{ - EVENT e; - - e.type = E_CHAR; - - if (key > 10000) { e.v.chr.control = TRUE; key -= K_CTRL; } - else e.v.chr.control = FALSE; - - if (key > 1000) { e.v.chr.shift = TRUE; key -= K_SHIFT; } - else e.v.chr.shift = FALSE; - - e.v.chr.ch = short(key); - - EM.push(win, e); -} - - -void dispatch_e_scroll(WINDOW win, KEY key) -{ - EVENT e; - EVENT_TYPE& t = e.type; - SCROLL_CONTROL& w = e.v.scroll.what; - short& p = e.v.scroll.pos; - - w = SC_NONE; - - switch(key) - { - case K_HOME: - t = E_HSCROLL; - w = SC_THUMB; - p = 0; - break; - case K_LHOME: - t = E_VSCROLL; - w = SC_THUMB; - p = 0; - break; - case K_UP: - t = E_VSCROLL; - w = SC_LINE_UP; - break; - case K_DOWN: - t = E_VSCROLL; - w = SC_LINE_DOWN; - break; - case K_BTAB: - t = E_HSCROLL; - w = SC_PAGE_UP; - break; - case K_TAB: - t = E_HSCROLL; - w = SC_PAGE_DOWN; - break; - case K_PREV: - t = E_VSCROLL; - w = SC_PAGE_UP; - break; - case K_NEXT: - t = E_VSCROLL; - w = SC_PAGE_DOWN; - break; - case K_LEFT: - t = E_HSCROLL; - w = SC_LINE_UP; - break; - case K_RIGHT: - t = E_HSCROLL; - w = SC_LINE_DOWN; - break; - default: - break; - }; - - if (w != SC_NONE) dispatch_event(win, &e); -} - -void customize_controls(bool on) -{ -#if XVTWS == WMWS - if (on) - { - // set_value(NULL_WIN,ATTR_CH_SHADOW,XVT_CH_SHADOW_WINDOW|XVT_CH_SHADOW_DIALOG); - set_value(NULL_WIN, ATTR_CH_TOGGLE_COMBO, (long)K_F9); - } -#endif - -#if XVT_OS == XVT_OS_WIN - if (on) - { - const long TWIN_STYLE = WSF_ICONIZABLE | WSF_SIZE | WSF_CLOSE | WSF_MAXIMIZED; - set_value(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, TWIN_STYLE); - - set_value(NULL_WIN,ATTR_WIN_PM_DRAWABLE_TWIN, TRUE); - set_value(NULL_WIN,ATTR_EVENT_HOOK, (long)event_hook); -#ifdef __CTL3D__ - // set_value(NULL_WIN,ATTR_WIN_CREATEWINDOW_HOOK, (long)createwindow_hook); - HINSTANCE _hInstance = (HINSTANCE)get_value(NULL_WIN, ATTR_WIN_INSTANCE); - Ctl3dRegister(_hInstance); - Ctl3dAutoSubclass(_hInstance); -#endif - } - else - { -#ifdef __CTL3D__ - HINSTANCE _hInstance = (HINSTANCE)get_value(NULL_WIN, ATTR_WIN_INSTANCE); - Ctl3dUnregister(_hInstance); -#endif - DeleteObject(NormalFont); - DeleteObject(MaskBrush); - DeleteObject(NormalBrush); - DeleteObject(FocusBrush); - free_controls_bmp(); - } -#endif - -#ifdef DBG - if (on) set_value(NULL_WIN,ATTR_FATAL_ERR_HANDLER, (long)fatal_hook); -#endif -} - -#if XVT_OS == XVT_OS_WIN -void xvt_init_font() -{ - NormalFont = GetStockObject(ANSI_FIXED_FONT); - GetObject(NormalFont, sizeof(LOGFONT), &LogFont); - - TConfig font(CONFIG_GENERAL, "Font"); - CHARY = (int)font.get_long("Height"); - if (CHARY > 0) - { - LogFont.lfHeight = CHARY; - LogFont.lfWidth = (int)font.get_long("Width"); - LogFont.lfWeight = FontWeight = (int)font.get_long("Weight"); - LogFont.lfCharSet = (int)font.get_long("CharSet"); - LogFont.lfClipPrecision = (int)font.get_long("Clip"); - LogFont.lfOutPrecision = (int)font.get_long("Precision"); - LogFont.lfQuality = (int)font.get_long("Quality");; - LogFont.lfPitchAndFamily = (int)font.get_long("Pitch"); - strcpy(LogFont.lfFaceName, font.get("Name")); - } - else - { - LogFont.lfHeight = CHARY = 10; - FontWeight = 400; - } - NormalFont = CreateFontIndirect(&LogFont); - xvt_set_font(TASK_WIN, FF_FIXED, 0); - - // Get true text size - TEXTMETRIC tm; - HWND hwnd = (HWND)get_value(TASK_WIN, ATTR_NATIVE_WINDOW); - HDC hdc = GetDC(hwnd); - GetTextMetrics(hdc, &tm); - ReleaseDC(hwnd, hdc); - - const int COLX = GetSystemMetrics(SM_CXSCREEN) / 80; - CHARX = tm.tmAveCharWidth+1; - if (CHARX > COLX) CHARX = COLX; - - CHARY = tm.tmHeight; - BASEY = tm.tmAscent; - if (CHARY > ROWY-2) CHARY = ROWY-2; -} -#endif - -void xvt_set_font(WINDOW win, int family, int style, int dim) -{ - CHECK(win != NULL_WIN, "Can't set the font in a NULL window"); - -#if XVT_OS == XVT_OS_WIN - if (dim < 1) - { - // LogFont.lfWidth = (style & FS_BOLD) ? width : width; - // LogFont.lfHeight = CHARY + ((style & FS_BOLD) ? 2 : 0); - LogFont.lfWeight = FontWeight + ((style & FS_BOLD) ? 300 : 0); - LogFont.lfItalic = (style & FS_ITALIC) ? TRUE : FALSE; - set_value(NULL_WIN, ATTR_WIN_PM_LOGFONT, (long)&LogFont); - set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, TRUE); - win_set_font(win, NULL, FALSE); - set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, FALSE); - return; - } -#endif - - FONT font; - select_font(family, style, dim < 1 ? CHARY : dim, &font); - win_set_font(win, &font, FALSE); -} - - -WINDOW xvt_create_window(WIN_TYPE wt, - short x, short y, short dx, short dy, - const char* caption, WINDOW parent, - long flags, EVENT_HANDLER eh, long app_data - ) -{ - RCT& rect = resize_rect(x, y, dx, dy, wt, parent); - - if (wt == WD_MODAL) wt = W_DOC; - WINDOW win = create_window(wt, - &rect, - (char*)caption, - 0, parent, - flags, - EM_ALL, eh, - app_data); - - CHECKD(win, "Can't create a window: XVT error ", get_xvterrno()); - -#if XVT_OS == XVT_OS_WIN - static bool to_set = TRUE; - HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); - if (to_set) - { - word style = GetClassWord(hwnd, GCW_STYLE); - style |= CS_BYTEALIGNCLIENT; - SetClassWord(hwnd, GCW_STYLE, style); - to_set = FALSE; - } - /* - long style = GetWindowLong(hwnd, GWL_STYLE); - style &= ~WS_CLIPCHILDREN; - SetWindowLong(hwnd, GWL_STYLE, style); - */ -#endif - - return win; -} - -WINDOW xvt_create_control(WIN_TYPE wt, - short x, short y, short dx, short dy, - const char* caption, - WINDOW parent, - long flags, - long app_data, - int id) -{ - RCT r = resize_rect(x, y, dx, dy, wt, parent); - WINDOW win = NULL_WIN; - -#if XVT_OS == XVT_OS_WIN - _wc_type = wt; - - if (wt == WC_PUSHBUTTON) - win = xvt_create_pushbutton(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - -#ifndef __CTL3D__ - if (wt == WC_CHECKBOX) - win = xvt_create_checkbox(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - - if (wt == WC_RADIOBUTTON) - win = xvt_create_radiobutton(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - - if (wt == WC_GROUPBOX) - { - win = xvt_create_groupbox(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - } - - if (wt == WC_TEXT) - { - win = xvt_create_text(r.left, r.top, r.right, r.bottom, - caption, parent, flags, app_data, id); - } -#else - if (wt == WC_GROUPBOX) - { - win = xvt_create_text(r.left, r.top, r.right, r.top+CHARY, - caption, parent, flags, app_data, id); - } -#endif - -#endif - - if (win == NULL_WIN) - { - if (wt == WC_PUSHBUTTON) - { - if (dy == 2) r.bottom -= ROWY; - if (id == DLG_F9) - { wt = WC_TEXT; r.right = r.left+CHARX; caption = "*"; } - else if (*caption == '#') caption = ""; - } - while (*caption == '@') caption += 2; - win = create_control(wt, &r, (char*)caption, parent, - flags, app_data, id); - } - -#ifdef DBG - if (win == NULL_WIN) - fatal_box("Can't create control %d: XVT error %d", id, get_xvterrno()); -#endif - -#if XVT_OS == XVT_OS_WIN -#ifdef __CTL3D__ - if (wt != WC_PUSHBUTTON) -#else - if (wt == WC_EDIT || wt == WC_LISTBUTTON) -#endif - { - HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); - SendMessage(hwnd, WM_SETFONT, NormalFont, TRUE); -#ifdef __CTL3D__ - Ctl3dSubclassCtl(hwnd); -#endif - } -#endif - - return win; -} - - -const char* xvt_get_title(WINDOW win) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - const TControl* c = TControl::WINDOW2TControl(win); - return c->caption(); -#else - get_title(win, __tmp_string, 80); - return __tmp_string; -#endif -} - -void xvt_set_front_control(WINDOW win) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->focus(TRUE); -#endif - set_front_window(win); -} - - -void xvt_enable_control(WINDOW win, bool on) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - c->enable(on); -#else - enable_window(win, on); -#endif -} - - -void xvt_check_box(WINDOW win, bool on) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = (TControl*)TControl::WINDOW2TControl(win); - c->check(on); -#else - win_check_box(win, on); -#endif -} - - -bool xvt_get_checked_state(WINDOW win) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - TControl* c = TControl::WINDOW2TControl(win); - return c->checked(); -#else - return get_checked_state(win) ? TRUE : FALSE; -#endif -} - - -void xvt_check_radio_button(WINDOW win, const WINDOW* ctls, int count) -{ -#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) - for (int i = 0; i < count; i++) - xvt_check_box(ctls[i], ctls[i] == win); -#else - win_check_radio_button(win, (WINDOW*)ctls, count); -#endif -} - - -int xvt_get_checked_radio(const WINDOW* ctls, int count) -{ - for (int i = 0; i < count; i++) - if (xvt_get_checked_state(ctls[i])) return i; - -#ifdef DBG - error_box("Accendi la tua radio per favore!"); -#endif - - return 0; -} - - -/////////////////////////////////////////////////////////// -// Gestione Status bar -/////////////////////////////////////////////////////////// - -HIDDEN WINDOW statbar = NULL_WIN; - -WINDOW xvt_create_statbar() -{ - CHECK(statbar == NULL_WIN, "Onli uan stabar, plis"); - -#if XVT_OS == XVT_OS_WIN - const int prop_count = 4; - char* prop_list[prop_count+1] = - { - "Status bar", - "HEIGHT=24", - "TASK_WIN", - "FIELD_OFFSET=24", - NULL - }; - - statbar = statbar_create(0, 0, 600, 1024, 800, prop_count, prop_list, - TASK_WIN, 0, 0, ""); - - xvt_init_font(); - DRAW_CTOOLS ct; win_get_draw_ctools(TASK_WIN, &ct); - statbar_set_font(statbar, &ct.font); -#endif - - return statbar; -} - -void xvt_statbar_set(const char* text, bool def) -{ -#if XVT_OS == XVT_OS_WIN - TString256 t(text); - const TDate oggi(TODAY); - t << '\t' << oggi.string() << " - " << main_app().title(); - if (def) - statbar_set_default_title(statbar, (char*)(const char*)t); - else - statbar_set_title(statbar, (char*)(const char*)t); -#endif -} - -void xvt_statbar_refresh() -{ -#if XVT_OS == XVT_OS_WIN - statbar_set_title(statbar, NULL); -#endif -} - -/////////////////////////////////////////////////////////// -// Test menu -/////////////////////////////////////////////////////////// - -HIDDEN bool test_menu_tag(MENU_ITEM* mi, MENU_TAG tag) -{ - while (mi->tag) - { - if (mi->tag == tag) return TRUE; - if (mi->child != NULL) - { - const bool ok = test_menu_tag(mi->child, tag); - if (ok) return TRUE; - } - mi++; - } - return FALSE; -} - - -bool xvt_test_menu_tag(MENU_TAG tag) -{ - MENU_ITEM *mi = win_menu_fetch(TASK_WIN); - const bool ok = test_menu_tag(mi, tag); - menu_free(mi); - return ok; -} - - -// translation of graphics attributes from codes chars -// used by print functions - -COLOR trans_color(char c) -{ - switch (c) - { - case 'n': return COLOR_BLACK; break; - case 'r': return COLOR_RED; break; - case 'g': return COLOR_GREEN; break; - case 'b': return COLOR_BLUE; break; - case 'c': return COLOR_CYAN; break; - case 'y': return COLOR_YELLOW; break; - case 'v': return COLOR_MAGENTA; break; - case 'w': return COLOR_WHITE; break; - case 'm': return MASK_BACK_COLOR; break; - case 'd': return COLOR_DKGRAY; break; - case 'l': return COLOR_LTGRAY; break; - case 'k': return COLOR_GRAY; break; - default: CHECK(0,"trans_color: Undefined color"); break; - } - return -1; -} - -PAT_STYLE trans_brush(char p) -{ - switch (p) - { - case 'n' : return PAT_NONE; break; - case 'h' : return PAT_HOLLOW; break; - case 's' : return PAT_SOLID; break; - case '-' : return PAT_HORZ; break; - case '|' : return PAT_VERT; break; - case '/' : return PAT_FDIAG; break; - case '\\': return PAT_BDIAG; break; - case 'X' : return PAT_DIAGCROSS; break; - case '+' : return PAT_CROSS; break; - default : CHECK(0,"trans_brush: Undefined pattern"); break; - } - return PAT_NONE; -} - -PEN_STYLE trans_pen(char p) -{ - switch (p) - { - case 'n' : return P_SOLID; break; - case '.' : return P_DOT; break; - case '-' : return P_DASH; break; - default: CHECK(0,"trans_pen: Undefined pattern"); break; - } - return P_SOLID; -} - +#include +#include + +#include +#include + +#if XVT_OS == XVT_OS_SCOUNIX +extern "C" { long nap(long period); } +#endif + +#ifdef DBG +// FATAL_HOOK che intercetta errori fatali XVT +// put breakpoint here +void fatal_hook() +{ + int dummy = 0; + dummy++; +} +#endif + +#if XVTWS == WMWS + +short CHARX = 8; +short CHARY = 8; +short BASEY = 8; +short ROWY = 8; + +COLOR MASK_BACK_COLOR = COLOR_WHITE; +COLOR NORMAL_COLOR = COLOR_BLACK; +COLOR NORMAL_BACK_COLOR = COLOR_WHITE; +COLOR DISABLED_COLOR = COLOR_GRAY; +COLOR DISABLED_BACK_COLOR = COLOR_WHITE; +COLOR FOCUS_COLOR = COLOR_BLACK; +COLOR FOCUS_BACK_COLOR = COLOR_WHITE; + +#else + +#include +#include + +#ifdef __CTL3D__ +#include +#endif + +HIDDEN COLORREF COLOR2RGB(COLOR c) +{ + const byte red = byte((c >> 16) & 0xFF); + const byte gre = byte((c >> 8) & 0xFF); + const byte blu = byte(c & 0xFF); + return RGB(red, gre, blu); +} + +HIDDEN COLOR RGB2COLOR(COLORREF c) +{ + const byte red = byte(c & 0xFF); + const byte gre = byte((c >> 8) & 0xFF); + const byte blu = byte((c >> 16) & 0xFF); + return MAKE_COLOR(red, gre, blu); +} + + +extern "C" { + WINDOW xvtwi_hwnd_to_window(HWND); +#include +} +#include + +short CHARX = 8; +short ROWY = GetSystemMetrics(SM_CYSCREEN) / 25; +short CHARY = 14; +short BASEY = 12; + +HIDDEN HFONT NormalFont = NULL; +HIDDEN LOGFONT LogFont; +HIDDEN int FontWeight; + +#ifdef __CTL3D__ +COLOR MASK_BACK_COLOR = COLOR_LTGRAY; +#else +COLOR MASK_BACK_COLOR = MAKE_COLOR(0,128,128); +#endif + +COLOR NORMAL_COLOR = COLOR_BLACK; +COLOR NORMAL_BACK_COLOR = COLOR_LTGRAY; +COLOR DISABLED_COLOR = COLOR_GRAY; +COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR; + +HIDDEN COLORREF MaskColor = COLOR2RGB(MASK_BACK_COLOR); +HIDDEN HBRUSH MaskBrush = CreateSolidBrush(MaskColor); + +HIDDEN COLORREF FocusForeColor = COLOR2RGB(COLOR_BLACK); +HIDDEN COLORREF FocusBackColor = COLOR2RGB(COLOR_CYAN); +HIDDEN HBRUSH FocusBrush = CreateSolidBrush(FocusBackColor); + +COLOR FOCUS_COLOR = RGB2COLOR(FocusForeColor); +COLOR FOCUS_BACK_COLOR = RGB2COLOR(FocusBackColor); + +HIDDEN COLORREF NormalForeColor = COLOR2RGB(NORMAL_COLOR); +HIDDEN COLORREF NormalBackColor = COLOR2RGB(NORMAL_BACK_COLOR); +HIDDEN HBRUSH NormalBrush = CreateSolidBrush(NormalBackColor); + +static BOOLEAN event_hook(HWND hwnd, + UINT msg, + UINT wparam, + ULONG lparam, + long* ret) +{ + switch(msg) + { +#ifdef __CTL3D__ + case WM_SYSCOLORCHANGE: + Ctl3dColorChange(); + break; +#endif + case WM_CTLCOLOR: + { +#ifdef __CTL3D__ + *ret = Ctl3dCtlColorEx(msg, wparam, lparam); + return TRUE; +#else + const word type = HIWORD(lparam); + if (type == CTLCOLOR_LISTBOX || type == CTLCOLOR_EDIT || + type == CTLCOLOR_MSGBOX) + { + HWND hwnd = LOWORD(lparam); + HDC hdc = wparam; + + if (!IsWindowEnabled(hwnd)) // Campo disabilitato + { + if (type != CTLCOLOR_MSGBOX) + { + SetTextColor(hdc, NormalForeColor); + SetBkColor(hdc, MaskColor); + } + *ret = MaskBrush; + return TRUE; + } + + bool focus = GetFocus() == hwnd; + if (type != CTLCOLOR_MSGBOX) + { + SetTextColor(hdc, focus ? FocusForeColor : NormalForeColor); + SetBkColor(hdc, focus ? FocusBackColor : NormalBackColor); + } + *ret = focus ? FocusBrush : NormalBrush; + return TRUE; + } +#endif + } + break; + case WM_COMMAND: + { + const word notify = HIWORD(lparam); + if (notify == EN_KILLFOCUS || notify == EN_SETFOCUS) + { + HWND hwnd = LOWORD(lparam); // Ridisegna BENE il campo + InvalidateRect(hwnd, NULL, TRUE); + } + } + break; + case WM_KEYDOWN: + if (wparam == VK_PRIOR || wparam == VK_NEXT || + wparam == VK_UP || wparam == VK_DOWN ) + { + char name[16]; + GetClassName(hwnd, name, 5); + if (stricmp(name, "Edit") == 0) + { + KEY key; + switch(wparam) + { + case VK_PRIOR: + key = K_PREV; break; + case VK_NEXT: + key = K_NEXT; break; + case VK_UP: + key = K_UP; break; + case VK_DOWN: + key = K_DOWN; break; + default: + key = 0; break; + } + if (key > 0) + { + WINDOW w = cur_win(); + if (w != NULL_WIN) + dispatch_e_char(w, key); + } + } + } + break; + case WM_MENUCHAR: + { + WINDOW w = cur_win(); + if (w != NULL_WIN) + { + const KEY key = toupper(wparam)+K_CTRL; + dispatch_e_char(w, key); + } + } + break; + default: + break; + } + + return FALSE; +} + + +HIDDEN WIN_TYPE _wc_type = W_NONE; + +static void createwindow_hook(DWORD* exstyle, LPCSTR* classname, LPCSTR* windowname, DWORD* styl, + int* x, int* y, int* width, int* height, HWND* parent, HMENU* menu, + HINSTANCE inst, void **) +{ + if (_wc_type == WC_EDIT) + { + *y++; + } else + if (_wc_type == WC_GROUPBOX) + { + *classname = "Static"; + } + _wc_type = W_NONE; +} + +#endif + + +RCT& resize_rect(short x, short y, short dx, short dy, WIN_TYPE wt, WINDOW parent) +{ + static RCT r; + + if (parent != TASK_WIN) + { + if (get_window_type(parent) == W_PLAIN) // Mask with Toolbar + { + if (y >= 0) y++; + if (x > 0 || (wt != WO_TE && x == 0)) + { + RCT pc; get_client_rect(parent, &pc); // Get parent window size + const int width = pc.right; + const int tot = 80*CHARX; + if (width > tot) x += (width-tot) / (CHARX<<1); + } + } + wt = WC_EDIT; + } + +#if XVT_OS == XVT_OS_WIN + switch (wt) + { + case WC_EDIT : + r.left = (x+1)*CHARX; + r.top = y*ROWY; + r.right = dx*CHARX; + r.bottom = (CHARY << 1) - BASEY; + if (dy > 1) + r.bottom += ROWY*(dy-1); + break; + case W_DOC: + r.left = x * CHARX; + r.top = y * ROWY; + r.right = dx * CHARX; + r.bottom = dy * CHARY; + break; + default: + r.left = x * CHARX; + r.top = y * ROWY; + r.right = (dx+2)*CHARX; + r.bottom = dy*ROWY-1; + break; + } +#else + r.left = x * CHARX; + r.top = y * CHARY; + r.right = dx * CHARX; + r.bottom = dy * CHARY; +#endif + + if (x < 0 || y < 0 || dx <= 0 || dy <= 0) + { + RCT pc; + if (parent == NULL_WIN) parent = TASK_WIN; + get_client_rect(parent, &pc); // Get parent window size + const short MAXX = pc.right; + const short MAXY = pc.bottom; + + if (x < 0) + { + x = -x; + if (wt != WC_EDIT && x == 1) x = 11; + if (x > 10) + { + const int num = x/10 -1; + const int tot = x%10; + const int spc = (MAXX - tot*r.right) / (tot+1); + r.left = spc + num*(spc+r.right); + } + else + r.left = MAXX - r.right - x*CHARX; + } + + if (y < 0) + { + y = -y; + if (wt != WC_EDIT && y == 1) y = 11; + if (y > 10) + { + const int num = y/10 -1; + const int tot = y%10; + const int spc = (MAXY - tot*r.bottom) / (tot+1); + r.top = spc + num*(spc+r.bottom); + } + else + r.top = MAXY - r.bottom - (y-1)*ROWY; + } + + if (dx <= 0) r.right = MAXX + dx*CHARX; + else r.right += r.left; + if (dy <= 0) r.bottom = MAXY + dy*ROWY; + else r.bottom += r.top; + } + else + { + r.right += r.left; + r.bottom += r.top; + } + return r; +} + + +void beep() +{ xvt_beep(); } + + +/////////////////////////////////////////////////////////// +// Event Handling +/////////////////////////////////////////////////////////// + +class TEvent_manager +{ + enum { MAX = 16 }; + WINDOW _w[MAX]; + EVENT _e[MAX]; + int _begin, _end; + +public: + TEvent_manager() : _begin(0), _end(0) {} + void push(WINDOW win, const EVENT& event); + void pop(); +}; + +HIDDEN TEvent_manager EM; + +void TEvent_manager::push(WINDOW w, const EVENT& e) +{ + CHECK(w, "You shouldn't send events to NULL_WIN!"); + _w[_end] = w; + _e[_end] = e; + _end = (++_end) % MAX; + CHECKD(_end != _begin, "Too many events queued: max. ", MAX); +} + +void TEvent_manager::pop() +{ + if (_begin != _end) + { + const int i = _begin; + _begin = (++_begin) % MAX; // Other events may occur! + dispatch_event(_w[i], &_e[i]); + } +} + +void do_events() +{ + process_events(); + EM.pop(); +#if XVT_OS == XVT_OS_SCOUNIX + nap(20); +#endif +} + +KEY e_char_to_key(const EVENT* ep) +{ + CHECK(ep->type == E_CHAR, "I can't convert a Non-E_CHAR event to a key"); + + KEY key = ep->v.chr.ch; + if (key < K_INS || key > K_HELP) + { + // if (ep->v.chr.shift && !isprint(key)) key += K_SHIFT; + if (ep->v.chr.shift && (key < ' ' || key > 'z')) key += K_SHIFT; + if (key >= ' ' && ep->v.chr.control) key += K_CTRL; + } + return key; +} + + +void dispatch_e_char(WINDOW win, KEY key) +{ + EVENT e; + + e.type = E_CHAR; + + if (key > 10000) { e.v.chr.control = TRUE; key -= K_CTRL; } + else e.v.chr.control = FALSE; + + if (key > 1000) { e.v.chr.shift = TRUE; key -= K_SHIFT; } + else e.v.chr.shift = FALSE; + + e.v.chr.ch = short(key); + + EM.push(win, e); +} + + +void dispatch_e_scroll(WINDOW win, KEY key) +{ + EVENT e; + EVENT_TYPE& t = e.type; + SCROLL_CONTROL& w = e.v.scroll.what; + short& p = e.v.scroll.pos; + + w = SC_NONE; + + switch(key) + { + case K_HOME: + t = E_HSCROLL; + w = SC_THUMB; + p = 0; + break; + case K_LHOME: + t = E_VSCROLL; + w = SC_THUMB; + p = 0; + break; + case K_UP: + t = E_VSCROLL; + w = SC_LINE_UP; + break; + case K_DOWN: + t = E_VSCROLL; + w = SC_LINE_DOWN; + break; + case K_BTAB: + t = E_HSCROLL; + w = SC_PAGE_UP; + break; + case K_TAB: + t = E_HSCROLL; + w = SC_PAGE_DOWN; + break; + case K_PREV: + t = E_VSCROLL; + w = SC_PAGE_UP; + break; + case K_NEXT: + t = E_VSCROLL; + w = SC_PAGE_DOWN; + break; + case K_LEFT: + t = E_HSCROLL; + w = SC_LINE_UP; + break; + case K_RIGHT: + t = E_HSCROLL; + w = SC_LINE_DOWN; + break; + default: + break; + }; + + if (w != SC_NONE) dispatch_event(win, &e); +} + +void customize_controls(bool on) +{ +#if XVTWS == WMWS + if (on) + { + // set_value(NULL_WIN,ATTR_CH_SHADOW,XVT_CH_SHADOW_WINDOW|XVT_CH_SHADOW_DIALOG); + set_value(NULL_WIN, ATTR_CH_TOGGLE_COMBO, (long)K_F9); + } +#endif + +#if XVT_OS == XVT_OS_WIN + if (on) + { + const long TWIN_STYLE = WSF_ICONIZABLE | WSF_SIZE | WSF_CLOSE | WSF_MAXIMIZED; + set_value(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, TWIN_STYLE); + + set_value(NULL_WIN,ATTR_WIN_PM_DRAWABLE_TWIN, TRUE); + set_value(NULL_WIN,ATTR_EVENT_HOOK, (long)event_hook); +#ifdef __CTL3D__ + // set_value(NULL_WIN,ATTR_WIN_CREATEWINDOW_HOOK, (long)createwindow_hook); + HINSTANCE _hInstance = (HINSTANCE)get_value(NULL_WIN, ATTR_WIN_INSTANCE); + Ctl3dRegister(_hInstance); + Ctl3dAutoSubclass(_hInstance); +#endif + } + else + { +#ifdef __CTL3D__ + HINSTANCE _hInstance = (HINSTANCE)get_value(NULL_WIN, ATTR_WIN_INSTANCE); + Ctl3dUnregister(_hInstance); +#endif + DeleteObject(NormalFont); + DeleteObject(MaskBrush); + DeleteObject(NormalBrush); + DeleteObject(FocusBrush); + free_controls_bmp(); + } +#endif + +#ifdef DBG + if (on) set_value(NULL_WIN,ATTR_FATAL_ERR_HANDLER, (long)fatal_hook); +#endif +} + +#if XVT_OS == XVT_OS_WIN +void xvt_init_font() +{ + NormalFont = GetStockObject(ANSI_FIXED_FONT); + GetObject(NormalFont, sizeof(LOGFONT), &LogFont); + + TConfig font(CONFIG_GENERAL, "Font"); + CHARY = (int)font.get_long("Height"); + if (CHARY > 0) + { + LogFont.lfHeight = CHARY; + LogFont.lfWidth = (int)font.get_long("Width"); + LogFont.lfWeight = FontWeight = (int)font.get_long("Weight"); + LogFont.lfCharSet = (int)font.get_long("CharSet"); + LogFont.lfClipPrecision = (int)font.get_long("Clip"); + LogFont.lfOutPrecision = (int)font.get_long("Precision"); + LogFont.lfQuality = (int)font.get_long("Quality");; + LogFont.lfPitchAndFamily = (int)font.get_long("Pitch"); + strcpy(LogFont.lfFaceName, font.get("Name")); + } + else + { + LogFont.lfHeight = CHARY = 10; + FontWeight = 400; + } + NormalFont = CreateFontIndirect(&LogFont); + xvt_set_font(TASK_WIN, FF_FIXED, 0); + + // Get true text size + TEXTMETRIC tm; + HWND hwnd = (HWND)get_value(TASK_WIN, ATTR_NATIVE_WINDOW); + HDC hdc = GetDC(hwnd); + GetTextMetrics(hdc, &tm); + ReleaseDC(hwnd, hdc); + + const int COLX = GetSystemMetrics(SM_CXSCREEN) / 80; + CHARX = tm.tmAveCharWidth+1; + if (CHARX > COLX) CHARX = COLX; + + CHARY = tm.tmHeight; + BASEY = tm.tmAscent; + if (CHARY > ROWY-2) CHARY = ROWY-2; +} +#endif + +void xvt_set_font(WINDOW win, int family, int style, int dim) +{ + CHECK(win != NULL_WIN, "Can't set the font in a NULL window"); + +#if XVT_OS == XVT_OS_WIN + if (dim < 1) + { + // LogFont.lfWidth = (style & FS_BOLD) ? width : width; + // LogFont.lfHeight = CHARY + ((style & FS_BOLD) ? 2 : 0); + LogFont.lfWeight = FontWeight + ((style & FS_BOLD) ? 300 : 0); + LogFont.lfItalic = (style & FS_ITALIC) ? TRUE : FALSE; + set_value(NULL_WIN, ATTR_WIN_PM_LOGFONT, (long)&LogFont); + set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, TRUE); + win_set_font(win, NULL, FALSE); + set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, FALSE); + return; + } +#endif + + FONT font; + select_font(family, style, dim < 1 ? CHARY : dim, &font); + win_set_font(win, &font, FALSE); +} + + +WINDOW xvt_create_window(WIN_TYPE wt, + short x, short y, short dx, short dy, + const char* caption, WINDOW parent, + long flags, EVENT_HANDLER eh, long app_data + ) +{ + RCT& rect = resize_rect(x, y, dx, dy, wt, parent); + + if (wt == WD_MODAL) wt = W_DOC; + WINDOW win = create_window(wt, + &rect, + (char*)caption, + 0, parent, + flags, + EM_ALL, eh, + app_data); + + CHECKD(win, "Can't create a window: XVT error ", get_xvterrno()); + +#if XVT_OS == XVT_OS_WIN + static bool to_set = TRUE; + HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); + if (to_set) + { + word style = GetClassWord(hwnd, GCW_STYLE); + style |= CS_BYTEALIGNCLIENT; + SetClassWord(hwnd, GCW_STYLE, style); + to_set = FALSE; + } + /* + long style = GetWindowLong(hwnd, GWL_STYLE); + style &= ~WS_CLIPCHILDREN; + SetWindowLong(hwnd, GWL_STYLE, style); + */ +#endif + + return win; +} + +WINDOW xvt_create_control(WIN_TYPE wt, + short x, short y, short dx, short dy, + const char* caption, + WINDOW parent, + long flags, + long app_data, + int id) +{ + RCT r = resize_rect(x, y, dx, dy, wt, parent); + WINDOW win = NULL_WIN; + +#if XVT_OS == XVT_OS_WIN + _wc_type = wt; + + if (wt == WC_PUSHBUTTON) + win = xvt_create_pushbutton(r.left, r.top, r.right, r.bottom, + caption, parent, flags, app_data, id); + +#ifndef __CTL3D__ + if (wt == WC_CHECKBOX) + win = xvt_create_checkbox(r.left, r.top, r.right, r.bottom, + caption, parent, flags, app_data, id); + + if (wt == WC_RADIOBUTTON) + win = xvt_create_radiobutton(r.left, r.top, r.right, r.bottom, + caption, parent, flags, app_data, id); + + if (wt == WC_GROUPBOX) + { + win = xvt_create_groupbox(r.left, r.top, r.right, r.bottom, + caption, parent, flags, app_data, id); + } + + if (wt == WC_TEXT) + { + win = xvt_create_text(r.left, r.top, r.right, r.bottom, + caption, parent, flags, app_data, id); + } +#else + if (wt == WC_GROUPBOX) + { + win = xvt_create_text(r.left, r.top, r.right, r.top+CHARY, + caption, parent, flags, app_data, id); + } +#endif + +#endif + + if (win == NULL_WIN) + { + if (wt == WC_PUSHBUTTON) + { + if (dy == 2) r.bottom -= ROWY; + if (id == DLG_F9) + { wt = WC_TEXT; r.right = r.left+CHARX; caption = "*"; } + else if (*caption == '#') caption = ""; + } + while (*caption == '@') caption += 2; + win = create_control(wt, &r, (char*)caption, parent, + flags, app_data, id); + } + +#ifdef DBG + if (win == NULL_WIN) + fatal_box("Can't create control %d: XVT error %d", id, get_xvterrno()); +#endif + +#if XVT_OS == XVT_OS_WIN +#ifdef __CTL3D__ + if (wt != WC_PUSHBUTTON) +#else + if (wt == WC_EDIT || wt == WC_LISTBUTTON) +#endif + { + HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); + SendMessage(hwnd, WM_SETFONT, NormalFont, TRUE); +#ifdef __CTL3D__ + Ctl3dSubclassCtl(hwnd); +#endif + } +#endif + + return win; +} + + +const char* xvt_get_title(WINDOW win) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + const TControl* c = TControl::WINDOW2TControl(win); + return c->caption(); +#else + get_title(win, __tmp_string, 80); + return __tmp_string; +#endif +} + +void xvt_set_front_control(WINDOW win) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + TControl* c = TControl::WINDOW2TControl(win); + c->focus(TRUE); +#endif + set_front_window(win); +} + + +void xvt_enable_control(WINDOW win, bool on) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + TControl* c = TControl::WINDOW2TControl(win); + c->enable(on); +#else + enable_window(win, on); +#endif +} + + +void xvt_check_box(WINDOW win, bool on) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + TControl* c = (TControl*)TControl::WINDOW2TControl(win); + c->check(on); +#else + win_check_box(win, on); +#endif +} + + +bool xvt_get_checked_state(WINDOW win) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + TControl* c = TControl::WINDOW2TControl(win); + return c->checked(); +#else + return get_checked_state(win) ? TRUE : FALSE; +#endif +} + + +void xvt_check_radio_button(WINDOW win, const WINDOW* ctls, int count) +{ +#if XVT_OS == XVT_OS_WIN && !defined(__CTL3D__) + for (int i = 0; i < count; i++) + xvt_check_box(ctls[i], ctls[i] == win); +#else + win_check_radio_button(win, (WINDOW*)ctls, count); +#endif +} + + +int xvt_get_checked_radio(const WINDOW* ctls, int count) +{ + for (int i = 0; i < count; i++) + if (xvt_get_checked_state(ctls[i])) return i; + +#ifdef DBG + error_box("Accendi la tua radio per favore!"); +#endif + + return 0; +} + + +/////////////////////////////////////////////////////////// +// Gestione Status bar +/////////////////////////////////////////////////////////// + +HIDDEN WINDOW statbar = NULL_WIN; + +WINDOW xvt_create_statbar() +{ + CHECK(statbar == NULL_WIN, "Onli uan stabar, plis"); + +#if XVT_OS == XVT_OS_WIN + const int prop_count = 4; + char* prop_list[prop_count+1] = + { + "Status bar", + "HEIGHT=24", + "TASK_WIN", + "FIELD_OFFSET=24", + NULL + }; + + statbar = statbar_create(0, 0, 600, 1024, 800, prop_count, prop_list, + TASK_WIN, 0, 0, ""); + + xvt_init_font(); + DRAW_CTOOLS ct; win_get_draw_ctools(TASK_WIN, &ct); + statbar_set_font(statbar, &ct.font); +#endif + + return statbar; +} + +void xvt_statbar_set(const char* text, bool def) +{ +#if XVT_OS == XVT_OS_WIN + const TDate oggi(TODAY); + TString t(80); + t << text << '\t' << oggi.string() << " - " << main_app().title(); + if (def) + statbar_set_default_title(statbar, (char*)(const char*)t); + statbar_set_title(statbar, (char*)(const char*)t); +#endif +} + +void xvt_statbar_refresh() +{ +#if XVT_OS == XVT_OS_WIN + statbar_set_title(statbar, NULL); +#endif +} + +/////////////////////////////////////////////////////////// +// Test menu +/////////////////////////////////////////////////////////// + +HIDDEN bool test_menu_tag(MENU_ITEM* mi, MENU_TAG tag) +{ + while (mi->tag) + { + if (mi->tag == tag) return TRUE; + if (mi->child != NULL) + { + const bool ok = test_menu_tag(mi->child, tag); + if (ok) return TRUE; + } + mi++; + } + return FALSE; +} + + +bool xvt_test_menu_tag(MENU_TAG tag) +{ + MENU_ITEM *mi = win_menu_fetch(TASK_WIN); + const bool ok = test_menu_tag(mi, tag); + menu_free(mi); + return ok; +} + + +// translation of graphics attributes from codes chars +// used by print functions + +COLOR trans_color(char c) +{ + switch (c) + { + case 'n': return COLOR_BLACK; break; + case 'r': return COLOR_RED; break; + case 'g': return COLOR_GREEN; break; + case 'b': return COLOR_BLUE; break; + case 'c': return COLOR_CYAN; break; + case 'y': return COLOR_YELLOW; break; + case 'v': return COLOR_MAGENTA; break; + case 'w': return COLOR_WHITE; break; + case 'm': return MASK_BACK_COLOR; break; + case 'd': return COLOR_DKGRAY; break; + case 'l': return COLOR_LTGRAY; break; + case 'k': return COLOR_GRAY; break; + default: CHECK(0,"trans_color: Undefined color"); break; + } + return -1; +} + +PAT_STYLE trans_brush(char p) +{ + switch (p) + { + case 'n' : return PAT_NONE; break; + case 'h' : return PAT_HOLLOW; break; + case 's' : return PAT_SOLID; break; + case '-' : return PAT_HORZ; break; + case '|' : return PAT_VERT; break; + case '/' : return PAT_FDIAG; break; + case '\\': return PAT_BDIAG; break; + case 'X' : return PAT_DIAGCROSS; break; + case '+' : return PAT_CROSS; break; + default : CHECK(0,"trans_brush: Undefined pattern"); break; + } + return PAT_NONE; +} + +PEN_STYLE trans_pen(char p) +{ + switch (p) + { + case 'n' : return P_SOLID; break; + case '.' : return P_DOT; break; + case '-' : return P_DASH; break; + default: CHECK(0,"trans_pen: Undefined pattern"); break; + } + return P_SOLID; +} +