#include "wxinc.h" #include "wx/print.h" #include "wx/printdlg.h" #include "xvt.h" #ifdef WIN32 #include "oswin32.h" #else #include "oslinux.h" #include #endif #include "xvintern.h" #pragma pack(4) struct TPRINT_RCD : public PRINT_RCD { unsigned char m_data[16*1024]; unsigned int m_size; // Dimensione della struct DEVMODE void SetData(void* data, unsigned int nSize); TPRINT_RCD(); ~TPRINT_RCD(); }; #pragma pack() void TPRINT_RCD::SetData(void* data, unsigned int nSize) { if (nSize <= sizeof(m_data)) { memcpy(m_data, data, nSize); m_size = nSize; } } TPRINT_RCD::TPRINT_RCD() : m_size(0) { pr = NULL; memset(m_data, 0, sizeof(m_data)); } TPRINT_RCD::~TPRINT_RCD() { memset(m_data, 0, sizeof(m_data)); m_size = 0; } /////////////////////////////////////////////////////////// // TwxPrintOut /////////////////////////////////////////////////////////// class TwxPrintOut : public wxPrintout { protected: TPRINT_RCD* m_prcd; bool m_bBadDriver; virtual bool HasPage(int pageNum); virtual bool OnPrintPage(int pageNum); void ResetDC(); public: void SetBadDriver(bool bd) { m_bBadDriver = bd; } bool HasBadDriver() const { return m_bBadDriver; } void InitDC(TPRINT_RCD* prcd); TwxPrintOut(TPRINT_RCD* prcd = NULL); virtual ~TwxPrintOut(); }; static TwxPrintOut* m_po = NULL; bool TwxPrintOut::HasPage(int pageNum) { return true; } bool TwxPrintOut::OnPrintPage(int pageNum) { return false; } void TwxPrintOut::ResetDC() { wxDC* dc = GetDC(); if (dc != NULL) delete dc; } void TwxPrintOut::InitDC(TPRINT_RCD* prcd) { ResetDC(); wxDC* dc = NULL; m_prcd = prcd; if (m_prcd == NULL) { wxPrinter printer; #ifdef WIN32 dc = new wxPrinterDC(printer.GetPrintDialogData().GetPrintData()); #else dc = new wxPostScriptDC(printer.GetPrintDialogData().GetPrintData()); #endif } else { wxPrintData data; #ifdef WIN32 data.SetNativeData(OsWin32_ConvertToNativePrinterInfo(prcd->m_data, prcd->m_size)); data.ConvertFromNative(); dc = new wxPrinterDC(data); #else dc = new wxPostScriptDC(prcd->m_data); #endif } wxSize s = dc->GetPPI(); SetPPIPrinter(s.x, s.y); s = dc->GetSize(); SetPageSizePixels(s.x, s.y); SetDC(dc); } TwxPrintOut::TwxPrintOut(TPRINT_RCD* prcd) : wxPrintout(_GetAppTitle()), m_bBadDriver(false) { InitDC(prcd); } TwxPrintOut::~TwxPrintOut() { ResetDC(); } /////////////////////////////////////////////////////////// // TwxPrintOutCache /////////////////////////////////////////////////////////// class TwxPrintOutCache { unsigned long m_signature; TwxPrintOut* m_po; protected: unsigned long Signature(TPRINT_RCD* prcd) const; public: TwxPrintOut* Get(TPRINT_RCD* prcd); void Reset(); TwxPrintOutCache() : m_signature(0), m_po(NULL) { } ~TwxPrintOutCache() { Reset(); } } m_PrintoutCache; unsigned long TwxPrintOutCache::Signature(TPRINT_RCD* prcd) const { const unsigned char* data = (const unsigned char*)prcd; unsigned long h = 0; for (size_t c = 0; c < prcd->m_size; c++) { h = (h << 2) + data[c]; const unsigned long i = h & 0xC0000000; if (i) h = (h ^ (i >> 12)) & 0x3FFFFFFF; } return h; } void TwxPrintOutCache::Reset() { if (m_po != NULL) { delete m_po; m_po = NULL; } } TwxPrintOut* TwxPrintOutCache::Get(TPRINT_RCD* prcd) { unsigned long signature = Signature(prcd); if (m_po != NULL && m_signature == signature) return m_po; Reset(); m_po = new TwxPrintOut(prcd); m_signature = signature; return m_po; } /////////////////////////////////////////////////////////// // TPrintDC /////////////////////////////////////////////////////////// wxDC& TPrintDC::GetDC(bool) { _dc = m_po->GetDC(); // Forza display context corrente if (_dirty) _dirty = -1; return TDC::GetDC(false); } TPrintDC::TPrintDC(wxWindow* owner) : TDC(owner) { } TPrintDC::~TPrintDC() { _dc = NULL; // Evita distruzione! } /////////////////////////////////////////////////////////// // Printing management :-((((( /////////////////////////////////////////////////////////// BOOLEAN xvt_app_escape(int esc_code, PRINT_RCD* rcd, long* ph, long* pw, long* pvr, long* phr) { *ph = *pw = *pvr = *phr = 0; switch (esc_code) { case XVT_ESC_GET_PRINTER_INFO: if (rcd == NULL || xvt_print_is_valid(rcd)) { int w, h; if (m_po == NULL) { TwxPrintOut* po = m_PrintoutCache.Get((TPRINT_RCD*)rcd); po->GetPPIPrinter(&w, &h); *phr = w; *pvr = h; po->GetPageSizePixels(&w, &h); *pw = w; *ph = h; } else { m_po->GetPPIPrinter(&w, &h); *phr = w; *pvr = h; m_po->GetPageSizePixels(&w, &h); *pw = w; *ph = h; } return TRUE; } break; default: break; } return FALSE; } BOOLEAN xvt_dm_post_page_setup(PRINT_RCD* precp) { wxPageSetupDialog dlg((wxWindow*)TASK_WIN); TPRINT_RCD* rcd = (TPRINT_RCD*)precp; wxPageSetupData& pdd = dlg.GetPageSetupData(); // pdd.EnablePrinter(false); // Vieta di cambiare stampante wxPrintData& data = pdd.GetPrintData(); #ifdef WIN32 data.SetNativeData(OsWin32_ConvertToNativePrinterInfo(rcd->m_data, rcd->m_size)); data.ConvertFromNative(); #endif if (dlg.ShowModal() == wxID_OK) { #ifdef WIN32 data.ConvertToNative(); void* pHandle = data.GetNativeData(); unsigned int nSize = 0; void* ptr = OsWin32_ConvertFromNativePrinterInfo(pHandle, nSize); rcd->SetData(ptr, nSize); delete ptr; #else rcd->SetData((void *) &data, (unsigned int) sizeof(data)); #endif m_PrintoutCache.Reset(); return TRUE; } return FALSE; } long xvt_fmap_get_family_sizes(PRINT_RCD *precp, char *family, long *size_array, BOOLEAN *scalable, long max_sizes) { long size = 0; *scalable = FALSE; if (precp != NULL) { #ifdef WIN32 TwxPrintOut* po = m_PrintoutCache.Get((TPRINT_RCD*)precp); if (po->HasBadDriver()) { HDC hdc = ::GetDC(NULL); // Screen DC size = OsWin32_EnumerateSizes((unsigned int)hdc, family, size_array, scalable, max_sizes); } else size = OsWin32_EnumerateSizes(po->GetDC()->GetHDC(), family, size_array, scalable, max_sizes); #else size = OsLinux_EnumerateSizes(family, size_array, scalable, max_sizes); #endif } return size; } long xvt_fmap_get_families(PRINT_RCD *precp, char **family_array, long max_families) { long size = 0; family_array[0] = NULL; if (precp != NULL) { #ifdef WIN32 TwxPrintOut* po = m_PrintoutCache.Get((TPRINT_RCD*)precp); size = OsWin32_EnumerateFamilies(po->GetDC()->GetHDC(), family_array, max_families); if (size == 0) { po->SetBadDriver(true); HDC hdc = ::GetDC(NULL); // Screen DC size = OsWin32_EnumerateFamilies((unsigned int)hdc, family_array, max_families); } #else size = OsLinux_EnumerateFamilies(family_array, max_families); #endif } return size; } void xvt_print_close(void) { // Nothing to do ? } BOOLEAN xvt_print_close_page(PRINT_RCD* /*precp*/) { BOOLEAN ok = m_po != NULL; if (ok) m_po->GetDC()->EndPage(); return ok; } PRINT_RCD* xvt_print_create(int *sizep) { TPRINT_RCD* pr = NULL; *sizep = 0; #ifdef WIN32 void* data = OsWin32_GetPrinterInfo(*sizep, NULL); if (data != NULL) { pr = new TPRINT_RCD; pr->SetData(data, *sizep); *sizep += 4; // Spazio per puntatore iniziale delete data; } #else wxPrinter printer; wxPrintData &data = printer.GetPrintDialogData().GetPrintData(); data.SetPrinterName(""); //verificare pr = new TPRINT_RCD; pr->SetData((void *) &data, (unsigned int) sizeof(data)); #endif return pr; } // Nuova funzione inventata da Aga PRINT_RCD* xvt_print_create_by_name(int* sizep, const char* name) { TPRINT_RCD* pr = NULL; *sizep = 0; #ifdef WIN32 void* data = OsWin32_GetPrinterInfo(*sizep, name); if (data != NULL) { pr = new TPRINT_RCD; pr->SetData(data, *sizep); *sizep += 4; // Spazio per puntatore iniziale delete data; } #else wxPrinter printer; wxPrintData &data = printer.GetPrintDialogData().GetPrintData(); wxString PrinterName(name); data.SetPrinterName(PrinterName); //verificare pr = new TPRINT_RCD; pr->SetData((void *) &data, (unsigned int) sizeof(data)); #endif return pr; } WINDOW xvt_print_create_win(PRINT_RCD* precp, char* /* title */) { WINDOW win = NULL_WIN; if (m_po != NULL) { m_po->InitDC((TPRINT_RCD*)precp); m_po->OnBeginPrinting(); m_po->OnBeginDocument(1, 32000); win = _print_win; } return win; } void xvt_print_destroy(PRINT_RCD* precp) { delete precp; } RCT* xvt_print_get_next_band(void) { static bool yes = false; static RCT rct; yes = !yes; if (m_po == NULL || !yes) return NULL; int w, h; m_po->GetPageSizePixels(&w, &h); rct.left = rct.top = 0; rct.right = w; rct.bottom = h; return &rct; } BOOLEAN xvt_print_is_valid(PRINT_RCD* precp) { BOOLEAN ok = precp != NULL && precp->pr == NULL; if (ok) { #ifdef WIN32 TPRINT_RCD* rcd = (TPRINT_RCD*)precp; ok = OsWin32_CheckPrinterInfo(rcd->m_data, rcd->m_size); #else // verificare (c'e' da fare qualcosa ?) #endif } return ok; } BOOLEAN xvt_print_open(void) { return m_po == NULL; } /////////////////////////////////////////////////////////// void CreateAbortWindow() { wxFrame* parent = (wxFrame*)TASK_WIN; wxPrintAbortDialog* win = new wxPrintAbortDialog(parent, "Stampa" , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE); wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL ); button_sizer->Add( new wxStaticText( win, -1, "Stampa in corso..."), 0, wxALL, 10 ); button_sizer->Add( new wxButton( win, wxID_CANCEL, wxT("Annulla") ), 0, wxALL | wxALIGN_CENTER, 10 ); win->SetAutoLayout( TRUE ); win->SetSizer( button_sizer ); button_sizer->Fit(win); button_sizer->SetSizeHints (win) ; win->Show(); win->Update(); wxPrinterBase::sm_abortWindow = win; } void DestroyAbortWindow() { if (wxPrinterBase::sm_abortWindow != NULL) { wxPrinterBase::sm_abortWindow->Hide(); delete wxPrinterBase::sm_abortWindow; wxPrinterBase::sm_abortWindow = NULL; } } /////////////////////////////////////////////////////////// BOOLEAN xvt_print_start_thread(BOOLEAN(*print_fcn)(long), long data) { wxBeginBusyCursor(); m_po = new TwxPrintOut; wxEndBusyCursor(); CreateAbortWindow(); print_fcn(data); DestroyAbortWindow(); #ifdef WIN32 int w, h; m_po->GetPPIPrinter(&w, &h); if (h == 6) { wxDC* dc = m_po->GetDC(); dc->StartPage(); OsWin32_SpoolRow("\n\n", 1, dc->GetHDC()); dc->EndPage(); } #endif m_po->OnEndDocument(); m_po->OnEndPrinting(); delete m_po; m_po = NULL; return TRUE; } BOOLEAN xvt_print_open_page(PRINT_RCD* precp) { BOOLEAN ok = m_po != NULL; if (ok) { if (wxPrinterBase::sm_abortIt) ok = FALSE; else m_po->GetDC()->StartPage(); } return ok; } /////////////////////////////////////////////////////////// // Added by XVAGA /////////////////////////////////////////////////////////// #ifdef LINUX static bool is_cups() { static int printer_system = -1; if (printer_system < 0) printer_system = xvt_fsys_file_exists("/etc/cups/printer.conf") ? 1 : 2; return (printer_system == 1); } #endif SLIST xvt_print_list_devices() { SLIST list = xvt_slist_create(); #ifdef WIN32 char buf[4096]; memset(buf, 0, sizeof(buf)); GetProfileString("devices", NULL, "", buf, sizeof(buf)); int start = 0; for (int i = 0; i < sizeof(buf); i++) if (buf[i] == '\0') { const char* pname = buf+start; if (*pname == '\0') break; xvt_slist_add_at_elt(list, NULL, pname, NULL); start = i+1; } #else if (is_cups()) { ifstream p("/etc/cups/printer.conf"); // vedere char line[4096]; while (p.getline(line, sizeof(line))) { if (line[0] == '<') { char * s = strstr(line, "Printer") ; if (s != NULL) { s += 7; while (isspace(*s)) s++; if (*s) { char * l = s + strlen(s) - 1; while (isspace(*l)) l--; *(l + 1) = '\0'; xvt_slist_add_at_elt(list, NULL, s, 0L); } } } } } else { ifstream p("/etc/printcap"); // vedere char line[4096]; while (p.getline(line, sizeof(line))) { if (line[0] != '#') { const int len = strlen(line); int i; for (i = 0; i < len; i++) { const char c = line[i]; if (!(isalpha(c) || isdigit(c) || isblank(c))) break; } line[i] = '\0'; xvt_slist_add_at_elt(list, NULL, line, 0L); } } } #endif return list; } BOOLEAN xvt_print_set_default_device(const char* name) { BOOLEAN ok = name && *name > ' '; #ifdef WIN32 if (ok) { wxString pdev(name); if (pdev.Find(',') < 0) { char szDevice[256]; ::GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice)); pdev << ',' << szDevice; } ok = ::WriteProfileString("windows", "device", pdev) != 0; } #else SORRY_BOX(); //verificare #endif return ok; } BOOLEAN xvt_print_get_default_device(char* name, int namesize) { bool ok = FALSE; #ifdef WIN32 ok = ::GetProfileString ("windows", "device", ",,,", name, namesize) != 0; #else *name = '\0'; if (is_cups()) { ifstream p("/etc/cups/printer.conf"); // vedere char line[4096]; while (p.getline(line, sizeof(line))) { if (line[0] == '<') { char * s = strstr(line, "ltPrinter") ; if (s != NULL) { s += 9; while (isspace(*s)) s++; if (*s) { char * l = s + strlen(s) - 1; while (isspace(*l)) l--; *(l + 1) = '\0'; strcpy(name, s); } ok = TRUE; } } } } #endif return ok; }