campo-sirio/xvaga/xvtextra.cpp

1498 lines
37 KiB
C++
Executable File

#include "wxinc.h"
#include <wx/filename.h>
#include <wx/print.h>
#include <wx/snglinst.h>
#include <wx/tokenzr.h>
#include "xvt.h"
#include "xvtart.h"
#ifdef __WXMSW__
#include "wx/dcps.h"
#include "wx/msw/printdlg.h"
#include "oswin32.h"
#else
#include "wx/setup.h"
#include "wx/dcps.h"
#include "oslinux.h"
#include "incstr.h"
#endif
#include "xvtpdf.h"
#include "xvtwin.h"
#pragma pack(4)
struct TPRINT_RCD : public PRINT_RCD
{
#ifdef __WXMSW__
unsigned char m_data[16*1024];
unsigned int m_size; // Dimensione della struct DEVMODE
void SetData(void * data, unsigned int nSize);
#else
wxPrintNativeDataBase* m_data;
unsigned int m_size; // Dimensione di wxPostScriptPrintNativeData
void GetData(wxPrintNativeDataBase* data) const;
void SetData(void * data);
#endif
unsigned int GetSize() const { return m_size; }
TPRINT_RCD();
~TPRINT_RCD();
};
#pragma pack()
#ifdef __WXMSW__
void TPRINT_RCD::SetData(void* data, unsigned int nSize)
{
if (nSize <= sizeof(m_data))
{
memset(m_data, 0, sizeof(m_data)); // Azzero per bene anche tutto quanto segue nSize
memcpy(m_data, data, nSize);
m_size = nSize;
}
else
xvt_dm_post_error("Printer info exceeds 16K");
}
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;
}
#else
void TPRINT_RCD::GetData(wxPrintNativeDataBase * data) const
{
memcpy(data, m_data, GetSize());
}
void TPRINT_RCD::SetData(void* data)
{
memcpy(m_data, data, GetSize());
}
wxNativePrintFactory __factory;
TPRINT_RCD::TPRINT_RCD()
{
m_data = __factory.CreatePrintNativeData();
m_size = sizeof(*m_data);
}
TPRINT_RCD::~TPRINT_RCD()
{
delete m_data;
}
#endif
///////////////////////////////////////////////////////////
// TwxPrintOut
///////////////////////////////////////////////////////////
class TwxPrintOut : public wxPrintout
{
protected:
const TPRINT_RCD* m_prcd;
bool m_bBadDriver;
virtual bool HasPage(int pageNum);
virtual bool OnPrintPage(int pageNum);
void ResetDC();
wxDC* CreateDC(const TPRINT_RCD* prcd, const char* title);
public:
void SetBadDriver(bool bd) { m_bBadDriver = bd; }
bool HasBadDriver() const { return m_bBadDriver; }
wxString PrinterName() const;
bool IsPDF() const { return !HasBadDriver() && xvt_print_is_pdf(m_prcd) != 0; }
bool InitDC(const TPRINT_RCD* prcd, const char* title);
TwxPrintOut(const TPRINT_RCD* prcd = NULL);
virtual ~TwxPrintOut() {}
};
wxString TwxPrintOut::PrinterName() const
{
char strName[MAX_PATH] = "";
xvt_print_get_name(m_prcd, strName, sizeof(strName));
return wxString(strName);
}
bool TwxPrintOut::HasPage(int WXUNUSED(pageNum))
{ return true; }
bool TwxPrintOut::OnPrintPage(int WXUNUSED(pageNum))
{ return false; }
void TwxPrintOut::ResetDC()
{
wxDC* dc = GetDC();
if (dc != NULL)
{
delete dc;
SetDC(NULL);
}
}
static void RCD2data(const TPRINT_RCD* prcd, wxPrintData& data)
{
#ifdef WIN32
wxWindowsPrintNativeData ndb;
ndb.SetDevMode(OsWin32_ConvertToNativePrinterInfo((void*)prcd->m_data, prcd->m_size));
ndb.TransferTo(data);
// in assenza di PDEVNAMES aggiorno il nome in questo modo
char strName[MAX_PATH] = "";
xvt_print_get_name(prcd, strName, sizeof(strName));
data.SetPrinterName(strName);
#else
prcd->GetData(data.GetNativeData());
data.ConvertFromNative();
#endif
}
static void data2RCD(const wxPrintData& data, TPRINT_RCD* prcd)
{
#ifdef WIN32
wxWindowsPrintNativeData* pNative = (wxWindowsPrintNativeData*)data.GetNativeData();
unsigned int nSize = 0;
void* ptr = OsWin32_ConvertFromNativePrinterInfo(pNative->GetDevMode(), nSize);
prcd->SetData(ptr, nSize);
delete ptr;
#else
((wxPrintData&)data).ConvertToNative();
prcd->SetData(data.GetNativeData());
#endif
}
wxDC* TwxPrintOut::CreateDC(const TPRINT_RCD* prcd, const char* title)
{
m_prcd = prcd;
wxDC* dc = NULL;
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;
RCD2data(prcd, data);
const bool ispdf = IsPDF();
if (ispdf)
dc = new TwxPDFDC(data, title);
else
#ifdef WIN32
dc = new wxPrinterDC(data);
#else
dc = new wxPostScriptDC(data);
#endif
}
if (dc->IsOk())
{
wxSize s = dc->GetPPI();
SetPPIPrinter(s.x, s.y);
s = dc->GetSize();
SetPageSizePixels(s.x, s.y);
SetDC(dc);
wxWindow* pAbort = wxPrinterBase::sm_abortWindow;
if (pAbort != NULL)
{
wxWindow* pStatic = pAbort->FindWindow(wxID_STATIC);
if (pStatic != NULL)
{
wxString strPrompt;
if (IsPDF())
{
const wxFileName fn(title);
strPrompt << wxT("Generazione di ") << fn.GetFullName();
}
else
strPrompt << wxT("Stampa su ") << PrinterName();
pStatic->SetLabel(strPrompt);
}
}
}
else
{
// delete dc;
dc = NULL;
}
return dc;
}
bool TwxPrintOut::InitDC(const TPRINT_RCD* prcd, const char* title)
{
ResetDC();
wxDC* dc = CreateDC(prcd, title);
if (dc != NULL)
{
wxSize s = dc->GetPPI();
if (s.x > 0)
SetPPIPrinter(s.x, s.y);
s = dc->GetSize();
if (s.x > 0)
SetPageSizePixels(s.x, s.y);
SetDC(dc);
}
m_bBadDriver = dc == NULL;
return !m_bBadDriver;
}
TwxPrintOut::TwxPrintOut(const TPRINT_RCD* prcd)
: wxPrintout(_GetAppTitle()), m_bBadDriver(false)
{
InitDC(prcd, _GetAppTitle());
}
///////////////////////////////////////////////////////////
// TwxPrintOutCache
///////////////////////////////////////////////////////////
class TwxPrintOutCache
{
unsigned long m_signature;
TwxPrintOut* m_po;
bool m_bLocked;
protected:
unsigned long Signature(const TPRINT_RCD* prcd) const;
public:
TwxPrintOut& Get(const TPRINT_RCD* prcd);
void Reset();
void Lock() { m_bLocked = true; }
void Unlock() { m_bLocked = false; }
bool Ok() const { return m_po != NULL; }
bool Locked() const { return m_bLocked; }
bool Printing() const { return Ok() && Locked(); }
TwxPrintOutCache();
~TwxPrintOutCache();
} m_PrintoutCache;
unsigned long TwxPrintOutCache::Signature(const TPRINT_RCD* prcd) const
{
unsigned long h = 0;
if (prcd != NULL)
{
const unsigned char* data = (const unsigned char*)prcd;
const size_t sz = prcd->GetSize();
for (size_t c = 0; c < sz; c++)
{
h = (h << 2) + data[c];
const unsigned long i = h & 0xC0000000;
if (i) h = (h ^ (i >> 12)) & 0x3FFFFFFF;
}
}
return h;
}
void TwxPrintOutCache::Reset()
{
wxASSERT(!Locked());
if (m_po != NULL)
{
delete m_po;
m_po = NULL;
// Marca come non valido anche il puntatore al DC contenuto nel defunto m_po
TDCMapper& m = GetTDCMapper();
if (m.HasValidDC(PRINTER_WIN))
m.GetTDC(PRINTER_WIN).KillDC();
}
}
TwxPrintOut& TwxPrintOutCache::Get(const TPRINT_RCD* prcd)
{
if (!Locked())
{
if (prcd == NULL)
{
if (m_po == NULL)
m_po = new TwxPrintOut;
}
else
{
unsigned long signature = Signature(prcd);
if (m_po != NULL && m_signature == signature)
return *m_po;
Reset();
m_po = new TwxPrintOut(prcd);
m_signature = signature;
}
}
wxASSERT(m_po != NULL);
return *m_po;
}
TwxPrintOutCache::TwxPrintOutCache() : m_signature(0), m_po(NULL)
{ }
TwxPrintOutCache::~TwxPrintOutCache()
{
// Reset(); // Essendo un oggetto statico la delete m_po non funziona!
}
///////////////////////////////////////////////////////////
// TPrintDC
///////////////////////////////////////////////////////////
// Flag di reset ad inizio pagina
bool TPrintDC::_page_start = false;
void TPrintDC::SetPageStart()
{ _page_start = true; }
wxDC& TPrintDC::GetDC(bool)
{
_dc = m_PrintoutCache.Get(NULL).GetDC(); // Forza display context corrente
if (_page_start)
{
_dirty = -1;
_page_start = false;
}
return TDC::GetDC(false);
}
void TPrintDC::KillDC()
{
_dc = NULL; // _dc is owned by wxPrintout
}
TPrintDC::TPrintDC(wxWindow* owner) : TDC(owner)
{
_page_start = false;
}
TPrintDC::~TPrintDC()
{
KillDC();
}
///////////////////////////////////////////////////////////
// Printing management :-(((((
///////////////////////////////////////////////////////////
BOOLEAN xvt_app_escape(int esc_code, PRINT_RCD* rcd, long* ph, long* pw, long* pvr, long* phr)
{
switch (esc_code)
{
case XVT_ESC_GET_PRINTER_INFO:
if (ph) *ph = *pw = 0;
if (pvr) *pvr = *phr = 0;
if (rcd == NULL || xvt_print_is_valid(rcd))
{
const TwxPrintOut& po = m_PrintoutCache.Get((TPRINT_RCD*)rcd);
int w, h;
if (ph)
{
po.GetPageSizePixels(&w, &h);
*pw = w; *ph = h;
}
if (pvr)
{
po.GetPPIPrinter(&w, &h);
*phr = w; *pvr = h;
}
return TRUE;
}
break;
case XVT_ESC_SET_PRINTER_INFO:
if (xvt_print_is_valid(rcd) && ph != NULL && pw != NULL)
{
TPRINT_RCD* prcd = (TPRINT_RCD*)rcd;
wxPrintData data;
RCD2data(prcd, data);
data.SetOrientation(*ph >= *pw ? wxPORTRAIT : wxLANDSCAPE);
data.ConvertToNative();
data2RCD(data, prcd);
TwxPrintOut& po = m_PrintoutCache.Get((TPRINT_RCD*)rcd);
po.InitDC(prcd, _GetAppTitle());
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();
wxPrintData& data = pdd.GetPrintData();
RCD2data(rcd, data);
pdd.EnableMargins(false);
const BOOLEAN ok = dlg.ShowModal() == wxID_OK;
if (ok)
{
data2RCD(data, rcd);
m_PrintoutCache.Reset();
}
return ok;
}
static wxBitmap& GetCachedBitmap(const wxString& strName, const wxRect& dst)
{
static wxString _strName;
static wxRect _dst;
static wxBitmap _bmp;
if (strName != _strName || dst.GetSize() != _dst.GetSize())
{
wxImage img;
if (img.LoadFile(strName))
{
if (img.HasAlpha() || img.HasMask())
img.Rescale(dst.width, dst.height, wxIMAGE_QUALITY_NORMAL);
else
img.Rescale(dst.width, dst.height, wxIMAGE_QUALITY_HIGH);
_bmp = wxBitmap(img);
_strName = strName;
_dst = dst;
}
else
{
_bmp = wxNullBitmap;
_strName = "";
_dst.width = _dst.height = 0;
}
}
return _bmp;
}
void xvt_dwin_draw_image_on_pdf(WINDOW win, const char* name, const RCT* dest)
{
const wxRect dst = RCT2Rect(dest);
wxDC& dc = GetTDCMapper().GetDC(win);
if (win == PRINTER_WIN)
{
TwxPDFDC* pPDF = wxDynamicCast(&dc, TwxPDFDC);
if (pPDF != NULL)
{
pPDF->DrawImage(name, dst);
return;
}
}
wxString strName(name); strName.MakeLower();
wxBitmap& bmp = GetCachedBitmap(strName, dst);
if (bmp.IsOk())
{
//wxIcon ico; ico.CopyFromBitmap(bmp);
//dc.DrawIcon(ico, dst.x, dst.y);
wxMemoryDC mem(bmp);
dc.Blit(dst.x, dst.y, dst.width, dst.height, &mem, 0, 0, wxCOPY, true);
}
}
long xvt_fmap_get_family_sizes(PRINT_RCD *precp, char *family, long *size_array, BOOLEAN *scalable, long max_sizes)
{
long size = 0;
*scalable = FALSE;
#ifdef __WXMSW__
if (xvt_print_is_valid(precp))
{
const TwxPrintOut& po = m_PrintoutCache.Get((TPRINT_RCD*)precp);
if (!po.HasBadDriver())
size = OsWin32_EnumerateSizes(po.GetDC()->GetHDC(), family, size_array, scalable, max_sizes);
}
else
{
size = OsWin32_EnumerateSizes(NULL, 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;
#ifdef __WXMSW__
if (xvt_print_is_valid(precp))
{
TwxPrintOut& po = m_PrintoutCache.Get((TPRINT_RCD*)precp);
if (!po.HasBadDriver())
{
size = OsWin32_EnumerateFamilies(po.GetDC()->GetHDC(), family_array, max_families);
if (size == 0)
po.SetBadDriver(true);
}
}
else
{
wxFrame* tw = (wxFrame*)TASK_WIN;
wxClientDC dc(tw);
size = OsWin32_EnumerateFamilies(dc.GetHDC(), family_array, max_families);
}
#else
size = OsLinux_EnumerateFamilies(family_array, max_families);
#endif
return size;
}
void xvt_print_close(void)
{
// Nothing to do ?
m_PrintoutCache.Reset();
}
BOOLEAN xvt_print_close_page(PRINT_RCD* WXUNUSED(precp))
{
BOOLEAN ok = m_PrintoutCache.Printing();
if (ok)
{
const TwxPrintOut& po = m_PrintoutCache.Get(NULL);
wxDC* dc = po.GetDC();
dc->EndPage();
//GetTDCMapper().DestroyTDC(PRINTER_WIN); // Elimina dalla lista dei display context
}
return ok;
}
PRINT_RCD* xvt_print_create(int *sizep)
{
return xvt_print_create_by_name(sizep, NULL);
}
// Impone il nome ad un PRINT_RCD.
// Utilizzato per la definiz. della stamp. virtuale PDF predefinita
int xvt_print_set_name(PRINT_RCD* precp, const char* name)
{
if (precp == NULL)
return 0;
if (name == NULL || !*name)
return 0;
wxString n = name;
#ifdef __WXMSW__
wxStrncpy(((char*)precp) + 4, name, 32);
#else
TPRINT_RCD* rcd = (TPRINT_RCD*)precp;
wxPrintData data;
rcd->GetData(data);
data.SetPrinterName(n);
rcd->SetData(data);
#endif
return n.Length();
}
// Nuova funzione inventata da Aga
PRINT_RCD* xvt_print_create_by_name(int* sizep, const char* name)
{
TPRINT_RCD* pr = NULL;
*sizep = 0;
const bool ispdf = name != NULL && xvt_str_same(name, XVT_PDF_PRINTER_NAME);
if (ispdf)
name = NULL;
#ifdef __WXMSW__
void* data = OsWin32_GetPrinterInfo(*sizep, name);
if (data == NULL)
{
SLIST plist = xvt_print_list_devices();
SLIST_ELT pitem = xvt_slist_get_first(plist);
name = xvt_slist_get(plist, pitem, NULL);
data = OsWin32_GetPrinterInfo(*sizep, name);
xvt_slist_destroy(plist);
}
if (data != NULL)
{
pr = new TPRINT_RCD;
pr->SetData(data, *sizep);
*sizep += 4; // Spazio per puntatore iniziale
delete data;
}
#else
wxPrintData data;
data.SetPrinterName(name == NULL ? "" : name);
pr = new TPRINT_RCD;
data2RCD(data, pr);
*sizep = pr->GetSize();
#endif
if (ispdf)
xvt_print_set_name(pr, XVT_PDF_PRINTER_NAME);
return pr;
}
WINDOW xvt_print_create_win(PRINT_RCD* precp, const char* title)
{
bool ok = xvt_print_is_valid(precp) != FALSE;
if (ok)
{
TPRINT_RCD* rcd = (TPRINT_RCD*)precp;
if (m_PrintoutCache.Printing())
{
TwxPrintOut& po = m_PrintoutCache.Get(NULL);
ok = po.InitDC(rcd, title);
if (ok)
{
po.OnBeginPrinting();
po.OnBeginDocument(1, 32000);
}
}
else
{
TwxPrintOut& po = m_PrintoutCache.Get(rcd);
ok = po.InitDC(rcd, title);
}
}
return ok ? PRINTER_WIN : NULL_WIN;
}
void xvt_print_destroy(PRINT_RCD* precp)
{
if (precp != NULL)
delete precp;
}
RCT* xvt_print_get_next_band(void)
{
static bool yes = false;
static RCT rct;
yes = !yes;
if (!yes)
return NULL;
const TwxPrintOut& po = m_PrintoutCache.Get(NULL);
int w = 0, h = 0;
po.GetPageSizePixels(&w, &h);
rct.left = rct.top = 0;
rct.right = w;
rct.bottom = h;
return &rct;
}
BOOLEAN xvt_print_is_pdf(const PRINT_RCD* precp)
{
bool yes = precp != NULL;
if (yes)
{
char strName[MAX_PATH];
xvt_print_get_name(precp, strName, sizeof(strName));
yes = xvt_str_same(strName, XVT_PDF_PRINTER_NAME) != 0;
}
return yes;
}
BOOLEAN xvt_print_pdf_version(char* version, int size)
{
const BOOLEAN ok = version && size > 12;
if (ok)
{
wxString str = "PDFlib ";
str += PDFLIB_VERSIONSTRING;
wxStrncpy(version, str, size);
}
return ok;
}
BOOLEAN xvt_print_is_valid(const PRINT_RCD* precp)
{
BOOLEAN ok = precp != NULL && precp->pr == NULL;
if (ok)
{
const TPRINT_RCD* rcd = (const TPRINT_RCD*)precp;
#ifdef __WXMSW__
ok = OsWin32_CheckPrinterInfo(rcd->m_data, rcd->m_size);
#else
wxPrintData data;
RCD2data(rcd, data);
ok = data.Ok();
#endif
}
return ok;
}
int xvt_print_get_name(const PRINT_RCD* precp, char* name, int sz_s)
{
if (!xvt_print_is_valid(precp))
return 0;
#ifdef __WXMSW__
wxString n = ((const char*)precp) + 4;
if (n.Length() >= 30)
{
double dBest = 0.0;
wxString strBest = n;
SLIST plist = xvt_print_list_devices();
for (SLIST_ELT pitem = xvt_slist_get_first(plist);
pitem != NULL; pitem = xvt_slist_get_next(plist, pitem))
{
const char* pname = xvt_slist_get(plist, pitem, NULL);
const double dScore = xvt_str_fuzzy_compare_ignoring_case(n, pname);
if (dScore > dBest)
{
dBest = dScore;
strBest = pname;
if (dScore >= 1.0)
break;
}
}
xvt_slist_destroy(plist);
n = strBest;
}
#else
TPRINT_RCD* rcd = (TPRINT_RCD*)precp;
wxPrintData data;
RCD2data(rcd, data);
wxString n = data.GetPrinterName();
#endif
if (name != NULL && sz_s > 0)
{
wxStrncpy(name, n, sz_s);
name[sz_s-1] = '\0';
}
return n.Length();
}
BOOLEAN xvt_print_open(void)
{
return m_PrintoutCache.Ok();
}
///////////////////////////////////////////////////////////
class TwxPrintAbortDialog : public wxPrintAbortDialog
{
public:
void Pulse();
TwxPrintAbortDialog();
};
void TwxPrintAbortDialog::Pulse()
{
wxGauge* pGauge = wxStaticCast(FindWindow(wxID_FORWARD), wxGauge);
pGauge->Pulse();
}
TwxPrintAbortDialog::TwxPrintAbortDialog()
: wxPrintAbortDialog(NULL, _("Stampa"),
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
{
wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL );
button_sizer->Add(new wxStaticText(this, wxID_STATIC, _("Stampa in corso..."),
wxDefaultPosition, wxSize(480,-1)), 0, wxALL, 10 );
button_sizer->Add(new wxGauge(this, wxID_FORWARD, 1, wxDefaultPosition, wxSize(480,-1)), 0, wxALL, 10 );
//button_sizer->Add(new wxButton(this, wxID_CANCEL, wxT("Annulla") ), 0, wxALL | wxALIGN_CENTER, 10 );
button_sizer->Add(new wxBitmapButton(this, wxID_CANCEL, xvtart_GetToolResource(102,32) ), 0, wxALL | wxALIGN_CENTER, 10 );
SetAutoLayout(true);
SetSizer(button_sizer);
button_sizer->Fit(this);
button_sizer->SetSizeHints(this);
Show();
Update();
}
void CreateAbortWindow()
{
wxPrinterBase::sm_abortWindow = new TwxPrintAbortDialog;
}
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)
{
const wxString strDir = ::wxGetCwd(); // Memorizzo la directory corrente (Acrobat la cambia)
wxBeginBusyCursor();
m_PrintoutCache.Reset(); // Forza nuovo contesto di stampa
TwxPrintOut& po = m_PrintoutCache.Get(NULL);
m_PrintoutCache.Lock();
wxEndBusyCursor();
CreateAbortWindow();
const BOOLEAN success = print_fcn(data);
DestroyAbortWindow();
if (!po.HasBadDriver())
{
po.OnEndDocument();
po.OnEndPrinting();
}
m_PrintoutCache.Unlock();
m_PrintoutCache.Reset();
::wxSetWorkingDirectory(strDir); // Ripristino la directory corrente (Acrobat l'ha cambiata)
return success;
}
BOOLEAN xvt_print_suspend_thread()
{
BOOLEAN ok = m_PrintoutCache.Printing();
if (ok)
{
TwxPrintOut& po = m_PrintoutCache.Get(NULL);
po.OnEndDocument(); // Sembra generare una pagina vuota indesiderata
po.OnEndPrinting();
}
return ok;
}
BOOLEAN xvt_print_restart_thread()
{
TwxPrintOut& po = m_PrintoutCache.Get(NULL);
po.OnBeginPrinting();
return po.OnBeginDocument(1, 32000);
}
BOOLEAN xvt_print_open_page(PRINT_RCD* WXUNUSED(precp))
{
BOOLEAN ok = m_PrintoutCache.Printing();
if (ok)
{
if (wxPrinterBase::sm_abortIt)
ok = FALSE;
else
{
TwxPrintOut& po = m_PrintoutCache.Get(NULL);
po.GetDC()->StartPage();
TPrintDC::SetPageStart(); // Flag per azzeramento dati DC
// Aggiorna barra di attesa
TwxPrintAbortDialog* pad = wxDynamicCast(wxPrinterBase::sm_abortWindow, TwxPrintAbortDialog);
if (pad != NULL)
{
pad->Pulse();
wxWakeUpIdle();
}
}
}
return ok;
}
///////////////////////////////////////////////////////////
// Added by XVAGA
///////////////////////////////////////////////////////////
SLIST xvt_print_list_devices()
{
SLIST list = xvt_slist_create();
const DWORD dwFlags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
const int level = xvt_sys_get_os_version() >= XVT_WS_WIN_NT ? 4 : 5;
DWORD dwSize = 0, dwPrinters = 0;
::EnumPrinters (dwFlags, NULL, level, NULL, 0, &dwSize, &dwPrinters);
if (dwSize > 0)
{
BYTE* pBuffer = new BYTE[dwSize];
::EnumPrinters (dwFlags, NULL, level, pBuffer, dwSize, &dwSize, &dwPrinters);
if (level == 4)
{
const PRINTER_INFO_4* pPrnInfo = (const PRINTER_INFO_4*)pBuffer;
for (UINT i=0; i < dwPrinters; i++)
{
xvt_slist_add_at_elt(list, NULL, pPrnInfo->pPrinterName, NULL);
pPrnInfo++;
}
}
else
{
const PRINTER_INFO_5* pPrnInfo = (const PRINTER_INFO_5*)pBuffer;
for (UINT i=0; i < dwPrinters; i++)
{
xvt_slist_add_at_elt(list, NULL, pPrnInfo->pPrinterName, NULL);
pPrnInfo++;
}
}
delete[] pBuffer;
}
return list;
}
BOOLEAN xvt_print_set_default_device(const char* name)
{
BOOLEAN ok = name != NULL && *name > ' ';
if (ok)
{
wxString pdev(name);
if (pdev.Find(',') < 0)
{
char szDevice[_MAX_PATH];
::GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice));
pdev << ',' << szDevice;
}
ok = ::WriteProfileString("windows", "device", pdev) != 0;
}
return ok;
}
BOOLEAN xvt_print_get_default_device(char* name, int namesize)
{
return ::GetProfileString ("windows", "device", ",,,", name, namesize) != 0;
}
///////////////////////////////////////////////////////////
// Gestione files di configurazione
///////////////////////////////////////////////////////////
int xvt_fsys_get_campo_stp_value(const char* name, char* value, int valsize)
{
BOOLEAN bFound = FALSE;
const char* const stpfile = "c:/campo.stp";
int p;
DIRECTORY dir;
char exedir[_MAX_PATH], path[_MAX_PATH];
xvt_fsys_get_default_dir(&dir);
xvt_fsys_convert_dir_to_str(&dir, exedir, sizeof(exedir));
for (p = 1; ; p++)
{
char para[4]; sprintf(para, "%d", p);
int len = xvt_sys_get_profile_string(stpfile, para, "Program", "", path, sizeof(path));
if (len <= 0)
break;
if (wxEndsWithPathSeparator(path))
{
len--;
path[len] = '\0';
}
if (xvt_str_same(path, exedir))
{
xvt_sys_get_profile_string(stpfile, para, name, "", value, valsize);
bFound = *value > ' ';
break;
}
}
return bFound;
}
/*
@($) CGetCampoIni FILES
@(ID)
Restituisce il nome del file che contiene il prefisso corrente.
@(FD)
@(ISV)
s,s1 = stringhe di lavoro.
Versione WIN32 e LINUX.
@(FSV)
*/
const char* xvt_fsys_get_campo_ini()
{
static wxString prawin;
if (prawin.IsEmpty())
{
BOOLEAN bFound = FALSE;
char exedir[_MAX_PATH], path[_MAX_PATH];
// Nelle installazioni sfigate con programmi in rete cerca di stabilire il percorso locale di Campo.ini
DIRECTORY dir;
xvt_fsys_get_default_dir(&dir);
xvt_fsys_convert_dir_to_str(&dir, exedir, sizeof(exedir));
if (xvt_fsys_is_network_drive(exedir))
bFound = xvt_fsys_get_campo_stp_value("CampoIni", path, sizeof(path));
if (!bFound)
{
if (OsWin32_IsWindowsServer())
{
xvt_fsys_build_pathname(path, NULL, wxGetHomeDir(), "campo", "ini", NULL);
bFound = xvt_fsys_file_exists(path);
if (!bFound)
{
char pathstd[_MAX_PATH];
xvt_fsys_build_pathname(pathstd, NULL, exedir, "campo", "ini", NULL);
if (xvt_fsys_file_exists(pathstd))
wxCopyFile(pathstd, path);
}
}
}
if (!bFound)
xvt_fsys_build_pathname(path, NULL, exedir, "campo", "ini", NULL);
if (!xvt_fsys_file_exists(path))
{
char msg[_MAX_PATH];
sprintf(msg, _("Impossibile aprire '%s'"), path);
xvt_dm_post_fatal_exit(msg);
}
prawin = path;
}
return prawin;
}
///////////////////////////////////////////////////////////
// Gestione MD5
///////////////////////////////////////////////////////////
#include "MD5Checksum.h"
BOOLEAN xvt_str_md5(const char* instr, char* outstr)
{
wxASSERT(outstr != NULL);
BOOLEAN ok = instr && *instr && outstr;
if (ok)
{
wxStrcpy(outstr, wxMD5Checksum::GetMD5((unsigned char*)instr, strlen(instr)));
ok = *outstr != '\0';
}
return ok;
}
BOOLEAN xvt_fsys_file_md5(const char* path, char* outstr)
{
wxASSERT(outstr != NULL);
BOOLEAN ok = path && *path && outstr;
if (ok)
{
wxStrcpy(outstr, wxMD5Checksum::GetMD5(wxString(path)));
ok = *outstr != '\0';
}
return ok;
}
///////////////////////////////////////////////////////////
// Gestione firma digitale
///////////////////////////////////////////////////////////
class TwxSignatureDlg : public wxDialog
{
private:
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
protected:
wxTextCtrl* AddString(wxSizer* ctlSizer, int id, const char* label,
wxString* str, int nFlags = 0);
public:
wxString m_strUser, m_strPIN;
bool m_bMark;
TwxSignatureDlg();
};
bool TwxSignatureDlg::TransferDataToWindow()
{
FindWindowById(1001, this)->SetLabel(m_strUser);
// FindWindowById(1002, this)->SetLabel(m_strPin); // Non riproporre
wxCheckBox* cb = wxStaticCast(FindWindowById(1003, this), wxCheckBox);
cb->SetValue(m_bMark);
return true;
}
bool TwxSignatureDlg::TransferDataFromWindow()
{
m_strUser = FindWindowById(1001, this)->GetLabel();
m_strPIN = FindWindowById(1002, this)->GetLabel();
wxCheckBox* cb = wxStaticCast(FindWindowById(1003, this), wxCheckBox);
m_bMark = cb->IsEnabled() && cb->GetValue();
return !m_strUser.IsEmpty() && !m_strPIN.IsEmpty();
}
wxTextCtrl* TwxSignatureDlg::AddString(wxSizer* ctlSizer, int id, const char* label, wxString* str, int nFlags)
{
wxStaticText* lbl = new wxStaticText(this, wxID_ANY, label);
wxTextCtrl* txt = new wxTextCtrl(this, id, wxEmptyString, wxDefaultPosition, wxSize(120, -1),
nFlags, wxTextValidator(wxFILTER_ASCII, str));
ctlSizer->Add(lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4);
ctlSizer->Add(txt, 1, wxALIGN_LEFT | wxALL, 4);
return txt;
}
TwxSignatureDlg::TwxSignatureDlg() : wxDialog(NULL, wxID_ANY, "ESigner", wxDefaultPosition)
{
wxSizer* ctlSizer = new wxFlexGridSizer(4, 2, 4, 4);
AddString(ctlSizer, 1001, "Utente", &m_strUser);
AddString(ctlSizer, 1002, "PIN", &m_strPIN, wxTE_PASSWORD);
wxCheckBox* ctlMark = new wxCheckBox(this, 1003, "Marcatura temporale");
if (xvt_net_get_status() <= 0)
ctlMark->Disable();
ctlSizer->AddSpacer(4);
ctlSizer->Add(ctlMark, 0, wxALIGN_LEFT | wxALL, 4);
wxSizer* ctlButtonSizer = CreateButtonSizer(wxOK | wxCANCEL);
wxBoxSizer* ctlTopSizer = new wxBoxSizer(wxVERTICAL);
ctlTopSizer->Add(ctlSizer, 0, wxALIGN_CENTER);
ctlTopSizer->Add(ctlButtonSizer, 0, wxALIGN_CENTER);
SetSizer(ctlTopSizer);
ctlTopSizer->SetSizeHints(this);
}
typedef
int (*dllSignMethod) (
char *operation, //operazione : S (firma file),
// S+D (firma directory),
// S+T (firma + marca file),
// S+T+D (firma + marca directory)
char *method, //metodo : F (file cert), P (file PFX), T (token/smartcard)
char *inputFile, //percorso file di input
char *outputFile, //percorso file di output (senza estensione)
char *timestampOutputFile, //percorso file di output TSR (marca temporale separata)
char *extension, //estensione in caso di input PDF
char *certificateFile, //nome file .cer o .crt contenente il certificato
char *kprivFile, //nome file .pem contenente la chiave privata
char *pfxFile, //nome file pfx contenente certificato e chiave privata
char *pkcs11Dll, //nome dll PKCS11
char *pin_passphrase, //passphrase o PIN (per chiave privata, pfx o token)
char *directoryTokenCache, //directory cache certificati estratti da token
char *indexCertificateOnToken, //numero certificato del token
char *tsaURI, //URI della TSA (http:\\....)
char *tsaUsername, //Username TSA
char *tsaPassword, //Password TSA
char *tsaPolicy, //Policy TSA
char *tsaCoding, //Codifica TSA: binary o base64
char *rootCADir) //percorso directory contenente i certificati della rootca
;
typedef int (*dllVerifyMethod) (
char *operation, //operazione : V (verifica file),
// V+D (verifica directory),
char *inputFileName, //percorso file di input
char *responseFileName, //percorso file di esito
char *rootCADir, //percorso directory contenente i certificati della rootca
char *rootTSADir, //percorso directory contenente i certificati delle rootTSA
char *resultDescription //parametro di output contenente l'esito della verifica
);
class TEsigner
{
#ifdef WIN32
HMODULE m_hESigner;
dllSignMethod _SignPDF;
dllVerifyMethod _VerifyPDF;
#endif
wxString m_strUser, m_strPin, m_strDllFile, m_strCertificate;
wxString m_strTSAuri, m_strTSAuser, m_strTSApwd, m_strPolicy, m_strTSAcoding;
bool m_bMark;
public:
bool Init(bool on);
bool Sign(const wxString& strInput, wxString& strOutput);
bool Verify(const wxString& strInput);
TEsigner();
~TEsigner();
} __TheSigner;
TEsigner::TEsigner() : m_bMark(false)
#ifdef WIN32
, m_hESigner(NULL), _SignPDF(NULL), _VerifyPDF(NULL)
#endif
{}
TEsigner::~TEsigner()
{ Init(false); }
bool TEsigner::Init(bool bLoad)
{
bool ok = false;
#ifdef WIN32
if (bLoad)
{
char str[_MAX_PATH] = "";
xvt_sys_get_profile_string(NULL, NULL, "Study", "", str, sizeof(str));
wxString strConfig; strConfig = str;
if (!wxEndsWithPathSeparator(strConfig))
strConfig << wxFILE_SEP_PATH;
strConfig << "config" << wxFILE_SEP_PATH << wxGetHostName() << ".ini";
if (m_hESigner == NULL)
{
m_hESigner = ::LoadLibrary("esigner.dll");
if (m_hESigner != NULL)
{
_SignPDF = (dllSignMethod)::GetProcAddress(m_hESigner, "Sign");
_VerifyPDF = (dllVerifyMethod)::GetProcAddress(m_hESigner, "Verify");
m_strPin.Empty();
TwxSignatureDlg dlg;
if (m_strUser.IsEmpty())
m_strUser = wxGetUserId();
dlg.m_strUser = m_strUser;
dlg.m_bMark = m_bMark;
if (dlg.ShowModal() == wxID_OK)
{
m_strUser = dlg.m_strUser;
m_strPin= dlg.m_strPIN;
m_bMark = dlg.m_bMark;
}
else
return ok = false;
xvt_sys_get_profile_string(strConfig, "fd", "Cert_"+m_strUser, "", str, sizeof(str));
if (*str == '\0') // Se non trova l'utente corrente di riprova con Guest
xvt_sys_get_profile_string(strConfig, "fd", "Cert_Guest", "", str, sizeof(str));
wxStringTokenizer strDllCert(str, ",");
m_strDllFile = strDllCert.GetNextToken(); m_strDllFile.MakeLower();
m_strCertificate = strDllCert.GetNextToken();
if (m_strCertificate.IsEmpty() && m_strDllFile.EndsWith(".dll"))
m_strCertificate = "0";
if (m_bMark)
{
m_strTSAuri = strDllCert.GetNextToken();
m_strTSAuser = strDllCert.GetNextToken();
m_strTSApwd = strDllCert.GetNextToken();
m_strPolicy = strDllCert.GetNextToken();
m_strTSAcoding = strDllCert.GetNextToken();
if (m_strTSAcoding.IsEmpty())
m_strTSAcoding = wxT("binary");
if (m_strTSAuri.IsEmpty())
{
wxString msg;
msg << "Mancano i parametri per la marcatura temporale"
<< "\nControllare Cert_" << m_strUser
<< " nel paragrafo [fd]\ndel file " << strConfig;
xvt_dm_post_warning(msg);
m_bMark = false;
}
}
}
}
ok = m_hESigner != NULL && _SignPDF != NULL && _VerifyPDF != NULL;
if (ok)
{
ok = wxFileExists(m_strDllFile);
if (!ok)
{
wxString msg;
msg << "Impossibile caricare il certificato/driver " << m_strDllFile
<< "\nControllare Cert_" << m_strUser
<< " nel paragrafo [fd]\ndel file " << strConfig;
xvt_dm_post_error(msg);
}
}
else
xvt_dm_post_error("Impossibile caricare 'ESigner.dll'");
}
else
{
if (m_hESigner != NULL)
{
::FreeLibrary(m_hESigner);
m_hESigner = NULL;
_SignPDF = NULL;
_VerifyPDF = NULL;
m_strPin.Empty();
}
}
#endif
return ok;
}
bool TEsigner::Sign(const wxString& strInput, wxString& strOutput)
{
if ((m_strPin.IsEmpty() || m_strDllFile.IsEmpty()) && !Init(true))
return false;
const char* ext = strInput.Lower().EndsWith(".pdf") ? ".pdf.p7m" : "";
if (strOutput.IsEmpty())
strOutput = strInput + ".p7m";
::wxRemoveFile(strOutput); // Altrimenti la fantastica dll s'incazza come una biscia
const wxString strFile = strOutput.BeforeFirst('.');
int res = 0;
if (m_strDllFile.Lower().EndsWith(".dll"))
{
if (m_bMark && !m_strTSAuri.IsEmpty()) // Firma con marcatura temporale
{
res = _SignPDF("S", "T", // "S"ignature with "T"oken or smartcard
(char*)(const char*)strInput, (char*)(const char*)strFile,
NULL, (char*)ext, NULL, NULL, NULL, (char*)(const char*)m_strDllFile,
(char*)(const char*)m_strPin, NULL, (char*)(const char*)m_strCertificate,
(char*)(const char*)m_strTSAuri, (char*)(const char*)m_strTSAuser,
(char*)(const char*)m_strTSApwd, (char*)(const char*)m_strPolicy,
(char*)(const char*)m_strTSAcoding, NULL);
}
else // Firma normale
{
res = _SignPDF("S", "T", // "S"ignature with "T"oken or smartcard
(char*)(const char*)strInput, (char*)(const char*)strFile,
NULL, (char*)ext, NULL, NULL, NULL, (char*)(const char*)m_strDllFile,
(char*)(const char*)m_strPin, NULL, (char*)(const char*)m_strCertificate,
NULL, NULL, NULL, NULL, NULL, NULL);
}
}
else
{
if (m_bMark && !m_strTSAuri.IsEmpty()) // Firma con marcatura temporale
{
res = _SignPDF("S", "P", // "S"ignature with "P"fx file
(char*)(const char*)strInput, (char*)(const char*)strFile,
NULL, (char*)ext, NULL, NULL, (char*)(const char*)m_strDllFile, NULL,
(char*)(const char*)m_strPin, NULL, NULL,
(char*)(const char*)m_strTSAuri, (char*)(const char*)m_strTSAuser,
(char*)(const char*)m_strTSApwd, (char*)(const char*)m_strPolicy,
(char*)(const char*)m_strTSAcoding, NULL);
}
else
{
res = _SignPDF("S", "P", // "S"ignature with "P"fx file
(char*)(const char*)strInput, (char*)(const char*)strFile,
NULL, (char*)ext, NULL, NULL, (char*)(const char*)m_strDllFile, NULL,
(char*)(const char*)m_strPin, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
}
}
if (res == 0)
{
if (!xvt_fsys_file_exists(strOutput))
{
wxString str = "ESigner.dll can't create " + strOutput;
xvt_dm_post_error(str);
res = -1;
}
}
else
{
wxString str;
str.Printf("ESigner.dll error %d", res);
xvt_dm_post_error(str);
}
return res == 0;
}
bool TEsigner::Verify(const wxString& strInput)
{
int res = -1;
if (Init(!strInput.IsEmpty()))
{
char file[_MAX_PATH], result[_MAX_PATH];
wxStrncpy(file, strInput, _MAX_PATH);
res = _VerifyPDF("V", file, NULL, NULL, NULL, result);
}
return res == 0;
}
BOOLEAN xvt_sign_start()
{
return __TheSigner.Init(true);
}
BOOLEAN xvt_sign_stop()
{
__TheSigner.Init(false);
return TRUE;
}
BOOLEAN xvt_sign_file(const char* input_name, char* output_name)
{
wxString strInput = input_name, strOutput = output_name;
if (strInput.IsEmpty())
{
FILE_SPEC fs;
xvt_fsys_convert_str_to_fspec(strInput, &fs);
if (xvt_dm_post_file_open(&fs, "File") != FL_OK)
return false;
}
strInput.MakeLower();
BOOLEAN ok = __TheSigner.Sign(strInput, strOutput);
if (ok && output_name != NULL)
wxStrncpy(output_name, strOutput, _MAX_PATH);
return ok;
}
BOOLEAN xvt_sign_test(const char* input_name)
{
wxString strInput = input_name;
if (strInput.IsEmpty())
{
FILE_SPEC fs;
xvt_fsys_convert_str_to_fspec(strInput, &fs);
if (xvt_dm_post_file_open(&fs, "File") != FL_OK)
return FALSE;
}
return __TheSigner.Verify(strInput);
}