summaryrefslogtreecommitdiff
path: root/vcl/win/source/gdi/salprn.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/win/source/gdi/salprn.cxx')
-rw-r--r--vcl/win/source/gdi/salprn.cxx2367
1 files changed, 2367 insertions, 0 deletions
diff --git a/vcl/win/source/gdi/salprn.cxx b/vcl/win/source/gdi/salprn.cxx
new file mode 100644
index 000000000000..f4f55dd0adbf
--- /dev/null
+++ b/vcl/win/source/gdi/salprn.cxx
@@ -0,0 +1,2367 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: salprn.cxx,v $
+ * $Revision: 1.36 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <string.h>
+#include <tools/svwin.h>
+
+#ifdef __MINGW32__
+#include <excpt.h>
+#endif
+
+#ifndef _OSL_MODULE_H
+#include <osl/module.h>
+#endif
+#include <wincomp.hxx>
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salgdi.h>
+#include <salframe.h>
+#include <vcl/salptype.hxx>
+#include <salprn.h>
+#include <vcl/print.h>
+#include <vcl/jobset.h>
+
+#include <tools/urlobj.hxx>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker.hpp>
+#include <com/sun/star/ui/dialogs/XFilterManager.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <malloc.h>
+
+#ifdef __MINGW32__
+#define CATCH_DRIVER_EX_BEGIN \
+ jmp_buf jmpbuf; \
+ __SEHandler han; \
+ if (__builtin_setjmp(jmpbuf) == 0) \
+ { \
+ han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
+
+#define CATCH_DRIVER_EX_END(mes, p) \
+ } \
+ han.Reset()
+#define CATCH_DRIVER_EX_END_2(mes) \
+ } \
+ han.Reset()
+#else
+#define CATCH_DRIVER_EX_BEGIN \
+ __try \
+ {
+#define CATCH_DRIVER_EX_END(mes, p) \
+ } \
+ __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
+ { \
+ DBG_ERROR( mes ); \
+ p->markInvalid(); \
+ }
+#define CATCH_DRIVER_EX_END_2(mes) \
+ } \
+ __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
+ { \
+ DBG_ERROR( mes ); \
+ }
+#endif
+
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::ui::dialogs;
+using namespace rtl;
+
+// =======================================================================
+
+static char aImplWindows[] = "windows";
+static char aImplDevices[] = "devices";
+static char aImplDevice[] = "device";
+
+static LPDEVMODEA SAL_DEVMODE_A( const ImplJobSetup* pSetupData )
+{
+ LPDEVMODEA pRet = NULL;
+ SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
+ if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_A &&
+ pSetupData->mnDriverDataLen >= sizeof(DEVMODEA)+sizeof(SalDriverData)-1
+ )
+ pRet = ((LPDEVMODEA)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
+ return pRet;
+}
+
+static LPDEVMODEW SAL_DEVMODE_W( const ImplJobSetup* pSetupData )
+{
+ LPDEVMODEW pRet = NULL;
+ SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
+ if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_W &&
+ pSetupData->mnDriverDataLen >= sizeof(DEVMODEW)+sizeof(SalDriverData)-1
+ )
+ pRet = ((LPDEVMODEW)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
+ return pRet;
+}
+
+// =======================================================================
+
+static ULONG ImplWinQueueStatusToSal( DWORD nWinStatus )
+{
+ ULONG nStatus = 0;
+ if ( nWinStatus & PRINTER_STATUS_PAUSED )
+ nStatus |= QUEUE_STATUS_PAUSED;
+ if ( nWinStatus & PRINTER_STATUS_ERROR )
+ nStatus |= QUEUE_STATUS_ERROR;
+ if ( nWinStatus & PRINTER_STATUS_PENDING_DELETION )
+ nStatus |= QUEUE_STATUS_PENDING_DELETION;
+ if ( nWinStatus & PRINTER_STATUS_PAPER_JAM )
+ nStatus |= QUEUE_STATUS_PAPER_JAM;
+ if ( nWinStatus & PRINTER_STATUS_PAPER_OUT )
+ nStatus |= QUEUE_STATUS_PAPER_OUT;
+ if ( nWinStatus & PRINTER_STATUS_MANUAL_FEED )
+ nStatus |= QUEUE_STATUS_MANUAL_FEED;
+ if ( nWinStatus & PRINTER_STATUS_PAPER_PROBLEM )
+ nStatus |= QUEUE_STATUS_PAPER_PROBLEM;
+ if ( nWinStatus & PRINTER_STATUS_OFFLINE )
+ nStatus |= QUEUE_STATUS_OFFLINE;
+ if ( nWinStatus & PRINTER_STATUS_IO_ACTIVE )
+ nStatus |= QUEUE_STATUS_IO_ACTIVE;
+ if ( nWinStatus & PRINTER_STATUS_BUSY )
+ nStatus |= QUEUE_STATUS_BUSY;
+ if ( nWinStatus & PRINTER_STATUS_PRINTING )
+ nStatus |= QUEUE_STATUS_PRINTING;
+ if ( nWinStatus & PRINTER_STATUS_OUTPUT_BIN_FULL )
+ nStatus |= QUEUE_STATUS_OUTPUT_BIN_FULL;
+ if ( nWinStatus & PRINTER_STATUS_WAITING )
+ nStatus |= QUEUE_STATUS_WAITING;
+ if ( nWinStatus & PRINTER_STATUS_PROCESSING )
+ nStatus |= QUEUE_STATUS_PROCESSING;
+ if ( nWinStatus & PRINTER_STATUS_INITIALIZING )
+ nStatus |= QUEUE_STATUS_INITIALIZING;
+ if ( nWinStatus & PRINTER_STATUS_WARMING_UP )
+ nStatus |= QUEUE_STATUS_WARMING_UP;
+ if ( nWinStatus & PRINTER_STATUS_TONER_LOW )
+ nStatus |= QUEUE_STATUS_TONER_LOW;
+ if ( nWinStatus & PRINTER_STATUS_NO_TONER )
+ nStatus |= QUEUE_STATUS_NO_TONER;
+ if ( nWinStatus & PRINTER_STATUS_PAGE_PUNT )
+ nStatus |= QUEUE_STATUS_PAGE_PUNT;
+ if ( nWinStatus & PRINTER_STATUS_USER_INTERVENTION )
+ nStatus |= QUEUE_STATUS_USER_INTERVENTION;
+ if ( nWinStatus & PRINTER_STATUS_OUT_OF_MEMORY )
+ nStatus |= QUEUE_STATUS_OUT_OF_MEMORY;
+ if ( nWinStatus & PRINTER_STATUS_DOOR_OPEN )
+ nStatus |= QUEUE_STATUS_DOOR_OPEN;
+ if ( nWinStatus & PRINTER_STATUS_SERVER_UNKNOWN )
+ nStatus |= QUEUE_STATUS_SERVER_UNKNOWN;
+ if ( nWinStatus & PRINTER_STATUS_POWER_SAVE )
+ nStatus |= QUEUE_STATUS_POWER_SAVE;
+ if ( !nStatus && !(nWinStatus & PRINTER_STATUS_NOT_AVAILABLE) )
+ nStatus |= QUEUE_STATUS_READY;
+ return nStatus;
+}
+
+// -----------------------------------------------------------------------
+
+static void getPrinterQueueInfoOldStyle( ImplPrnQueueList* pList )
+{
+ DWORD i;
+ DWORD n;
+ DWORD nBytes = 0;
+ DWORD nInfoPrn2;
+ BOOL bFound = FALSE;
+ PRINTER_INFO_2* pWinInfo2 = NULL;
+ PRINTER_INFO_2* pGetInfo2;
+ EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoPrn2 );
+ if ( nBytes )
+ {
+ pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
+ if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoPrn2 ) )
+ {
+ pGetInfo2 = pWinInfo2;
+ for ( i = 0; i < nInfoPrn2; i++ )
+ {
+ SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+ pInfo->maPrinterName = ImplSalGetUniString( pGetInfo2->pPrinterName );
+ pInfo->maDriver = ImplSalGetUniString( pGetInfo2->pDriverName );
+ XubString aPortName;
+ if ( pGetInfo2->pPortName )
+ aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
+ // pLocation can be 0 (the Windows docu doesn't describe this)
+ if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
+ pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
+ else
+ pInfo->maLocation = aPortName;
+ // pComment can be 0 (the Windows docu doesn't describe this)
+ if ( pGetInfo2->pComment )
+ pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
+ pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
+ pInfo->mnJobs = pGetInfo2->cJobs;
+ pInfo->mpSysData = new XubString( aPortName );
+ pList->Add( pInfo );
+ pGetInfo2++;
+ }
+
+ bFound = TRUE;
+ }
+ }
+
+ // read printers from win.ini
+ // TODO: MSDN: GetProfileString() should not be called from server
+ // code because it is just there for WIN16 compatibility
+ UINT nSize = 4096;
+ char* pBuf = new char[nSize];
+ UINT nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
+ while ( nRead >= nSize-2 )
+ {
+ nSize += 2048;
+ delete []pBuf;
+ pBuf = new char[nSize];
+ nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
+ }
+
+ // extract printer names from buffer and fill list
+ char* pName = pBuf;
+ while ( *pName )
+ {
+ char* pPortName;
+ char* pTmp;
+ char aPortBuf[256];
+ GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) );
+
+ pPortName = aPortBuf;
+
+ // create name
+ xub_StrLen nNameLen = sal::static_int_cast<xub_StrLen>(strlen( pName ));
+ XubString aName( ImplSalGetUniString( pName, nNameLen ) );
+
+ // get driver name
+ pTmp = pPortName;
+ while ( *pTmp != ',' )
+ pTmp++;
+ XubString aDriver( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) );
+ pPortName = pTmp;
+
+ // get port names
+ do
+ {
+ pPortName++;
+ pTmp = pPortName;
+ while ( *pTmp && (*pTmp != ',') )
+ pTmp++;
+
+ String aPortName( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) );
+
+ // create new entry
+ // look up if printer was already found in first loop
+ BOOL bAdd = TRUE;
+ if ( pWinInfo2 )
+ {
+ pGetInfo2 = pWinInfo2;
+ for ( n = 0; n < nInfoPrn2; n++ )
+ {
+ if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) )
+ {
+ bAdd = FALSE;
+ break;
+ }
+ pGetInfo2++;
+ }
+ }
+ // if it's a new printer, add it
+ if ( bAdd )
+ {
+ SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+ pInfo->maPrinterName = aName;
+ pInfo->maDriver = aDriver;
+ pInfo->maLocation = aPortName;
+ pInfo->mnStatus = 0;
+ pInfo->mnJobs = QUEUE_JOBS_DONTKNOW;
+ pInfo->mpSysData = new XubString( aPortName );
+ pList->Add( pInfo );
+ }
+ }
+ while ( *pTmp == ',' );
+
+ pName += nNameLen + 1;
+ }
+
+ delete []pBuf;
+ rtl_freeMemory( pWinInfo2 );
+}
+
+void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
+{
+ if( ! aSalShlData.mbWPrinter )
+ {
+ getPrinterQueueInfoOldStyle( pList );
+ return;
+ }
+ DWORD i;
+ DWORD nBytes = 0;
+ DWORD nInfoPrn4 = 0;
+ PRINTER_INFO_4W* pWinInfo4 = NULL;
+ EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 );
+ if ( nBytes )
+ {
+ pWinInfo4 = (PRINTER_INFO_4W*) rtl_allocateMemory( nBytes );
+ if ( EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)pWinInfo4, nBytes, &nBytes, &nInfoPrn4 ) )
+ {
+ for ( i = 0; i < nInfoPrn4; i++ )
+ {
+ SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+ pInfo->maPrinterName = UniString( reinterpret_cast< const sal_Unicode* >(pWinInfo4[i].pPrinterName) );
+ pInfo->mnStatus = 0;
+ pInfo->mnJobs = 0;
+ pInfo->mpSysData = NULL;
+ pList->Add( pInfo );
+ }
+ }
+ rtl_freeMemory( pWinInfo4 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo* pInfo )
+{
+ DWORD nBytes = 0;
+ DWORD nInfoRet;
+ PRINTER_INFO_2* pWinInfo2;
+ EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoRet );
+ if ( nBytes )
+ {
+ pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
+ if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoRet ) )
+ {
+ PRINTER_INFO_2* pGetInfo2 = pWinInfo2;
+ for ( DWORD i = 0; i < nInfoRet; i++ )
+ {
+ if ( pInfo->maPrinterName.EqualsAscii( pGetInfo2->pPrinterName ) &&
+ ( pInfo->maDriver.Len() == 0 ||
+ pInfo->maDriver.EqualsAscii( pGetInfo2->pDriverName ) )
+ )
+ {
+ XubString aPortName;
+ if ( pGetInfo2->pPortName )
+ aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
+ // pLocation can be 0 (the Windows docu doesn't describe this)
+ if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
+ pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
+ else
+ pInfo->maLocation = aPortName;
+ // pComment can be 0 (the Windows docu doesn't describe this)
+ if ( pGetInfo2->pComment )
+ pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
+ pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
+ pInfo->mnJobs = pGetInfo2->cJobs;
+ if( ! pInfo->mpSysData )
+ pInfo->mpSysData = new XubString( aPortName );
+ break;
+ }
+
+ pGetInfo2++;
+ }
+ }
+
+ rtl_freeMemory( pWinInfo2 );
+ }
+}
+
+void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
+{
+ if( ! aSalShlData.mbWPrinter )
+ {
+ getPrinterQueueStateOldStyle( pInfo );
+ return;
+ }
+
+ HANDLE hPrinter = 0;
+ LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.GetBuffer()));
+ if( OpenPrinterW( pPrnName, &hPrinter, NULL ) )
+ {
+ DWORD nBytes = 0;
+ GetPrinterW( hPrinter, 2, NULL, 0, &nBytes );
+ if( nBytes )
+ {
+ PRINTER_INFO_2W* pWinInfo2 = (PRINTER_INFO_2W*)rtl_allocateMemory(nBytes);
+ if( GetPrinterW( hPrinter, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes ) )
+ {
+ if( pWinInfo2->pDriverName )
+ pInfo->maDriver = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pDriverName) );
+ XubString aPortName;
+ if ( pWinInfo2->pPortName )
+ aPortName = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pPortName) );
+ // pLocation can be 0 (the Windows docu doesn't describe this)
+ if ( pWinInfo2->pLocation && *pWinInfo2->pLocation )
+ pInfo->maLocation = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pLocation) );
+ else
+ pInfo->maLocation = aPortName;
+ // pComment can be 0 (the Windows docu doesn't describe this)
+ if ( pWinInfo2->pComment )
+ pInfo->maComment = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pComment) );
+ pInfo->mnStatus = ImplWinQueueStatusToSal( pWinInfo2->Status );
+ pInfo->mnJobs = pWinInfo2->cJobs;
+ if( ! pInfo->mpSysData )
+ pInfo->mpSysData = new XubString( aPortName );
+ }
+ rtl_freeMemory(pWinInfo2);
+ }
+ ClosePrinter( hPrinter );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
+{
+ delete (String*)(pInfo->mpSysData);
+ delete pInfo;
+}
+
+// -----------------------------------------------------------------------
+XubString WinSalInstance::GetDefaultPrinter()
+{
+ static bool bGetDefPrtAPI = true;
+ static BOOL(WINAPI*pGetDefaultPrinter)(LPWSTR,LPDWORD) = NULL;
+ // try to use GetDefaultPrinter API (not available prior to W2000)
+ if( bGetDefPrtAPI )
+ {
+ bGetDefPrtAPI = false;
+ // check for W2k and XP
+ if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
+ {
+ OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "winspool.drv" ) );
+ oslModule pLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
+ oslGenericFunction pFunc = NULL;
+ if( pLib )
+ {
+ OUString queryFuncName( RTL_CONSTASCII_USTRINGPARAM( "GetDefaultPrinterW" ) );
+ pFunc = osl_getFunctionSymbol( pLib, queryFuncName.pData );
+ }
+
+ pGetDefaultPrinter = (BOOL(WINAPI*)(LPWSTR,LPDWORD)) pFunc;
+ }
+ }
+ if( pGetDefaultPrinter )
+ {
+ DWORD nChars = 0;
+ pGetDefaultPrinter( NULL, &nChars );
+ if( nChars )
+ {
+ LPWSTR pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR));
+ XubString aDefPrt;
+ if( pGetDefaultPrinter( pStr, &nChars ) )
+ {
+ aDefPrt = reinterpret_cast<sal_Unicode* >(pStr);
+ }
+ rtl_freeMemory( pStr );
+ if( aDefPrt.Len() )
+ return aDefPrt;
+ }
+ }
+
+ // get default printer from win.ini
+ char szBuffer[256];
+ GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) );
+ if ( szBuffer[0] )
+ {
+ // Printername suchen
+ char* pBuf = szBuffer;
+ char* pTmp = pBuf;
+ while ( *pTmp && (*pTmp != ',') )
+ pTmp++;
+ return ImplSalGetUniString( pBuf, (xub_StrLen)(pTmp-pBuf) );
+ }
+ else
+ return XubString();
+}
+
+// =======================================================================
+
+static DWORD ImplDeviceCaps( WinSalInfoPrinter* pPrinter, WORD nCaps,
+ BYTE* pOutput, const ImplJobSetup* pSetupData )
+{
+ if( aSalShlData.mbWPrinter )
+ {
+ DEVMODEW* pDevMode;
+ if ( !pSetupData || !pSetupData->mpDriverData )
+ pDevMode = NULL;
+ else
+ pDevMode = SAL_DEVMODE_W( pSetupData );
+
+ return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR>(pPrinter->maDeviceName.GetBuffer()),
+ reinterpret_cast<LPCWSTR>(pPrinter->maPortName.GetBuffer()),
+ nCaps, (LPWSTR)pOutput, pDevMode );
+ }
+ else
+ {
+ DEVMODEA* pDevMode;
+ if ( !pSetupData || !pSetupData->mpDriverData )
+ pDevMode = NULL;
+ else
+ pDevMode = SAL_DEVMODE_A( pSetupData );
+
+ return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
+ ImplSalGetWinAnsiString( pPrinter->maPortName, TRUE ).GetBuffer(),
+ nCaps, (LPSTR)pOutput, pDevMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplTestSalJobSetup( WinSalInfoPrinter* pPrinter,
+ ImplJobSetup* pSetupData, BOOL bDelete )
+{
+ if ( pSetupData && pSetupData->mpDriverData )
+ {
+ // signature and size must fit to avoid using
+ // JobSetups from a wrong system
+
+ // initialize versions from jobsetup
+ // those will be overwritten with driver's version
+ DEVMODEA* pDevModeA = NULL;
+ DEVMODEW* pDevModeW = NULL;
+ LONG dmSpecVersion = -1;
+ LONG dmDriverVersion = -1;
+ SalDriverData* pSalDriverData = (SalDriverData*)pSetupData->mpDriverData;
+ BYTE* pDriverData = ((BYTE*)pSalDriverData) + pSalDriverData->mnDriverOffset;
+ if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_W )
+ {
+ if( aSalShlData.mbWPrinter )
+ pDevModeW = (DEVMODEW*)pDriverData;
+ }
+ else if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_A )
+ {
+ if( ! aSalShlData.mbWPrinter )
+ pDevModeA = (DEVMODEA*)pDriverData;
+ }
+
+ long nSysJobSize = -1;
+ if( pPrinter && ( pDevModeA || pDevModeW ) )
+ {
+ // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
+ // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
+ // can avoid potential driver crashes as their jobsetups are often not compatible
+ // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
+ ByteString aPrinterNameA= ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
+ HANDLE hPrn;
+ LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
+ if ( ! aSalShlData.mbWPrinter )
+ {
+ if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
+ return FALSE;
+ }
+ else
+ if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
+ return FALSE;
+
+ // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
+ if( hPrn == HGDI_ERROR )
+ return FALSE;
+
+ if( aSalShlData.mbWPrinter )
+ {
+ nSysJobSize = DocumentPropertiesW( 0, hPrn,
+ pPrinterNameW,
+ NULL, NULL, 0 );
+ }
+ else
+ {
+ nSysJobSize = DocumentPropertiesA( 0, hPrn,
+ (LPSTR)aPrinterNameA.GetBuffer(),
+ NULL, NULL, 0 );
+ }
+
+ if( nSysJobSize < 0 )
+ {
+ ClosePrinter( hPrn );
+ return FALSE;
+ }
+ BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize );
+ LONG nRet = -1;
+ if( aSalShlData.mbWPrinter )
+ {
+ nRet = DocumentPropertiesW( 0, hPrn,
+ pPrinterNameW,
+ (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER );
+ }
+ else
+ {
+ nRet = DocumentPropertiesA( 0, hPrn,
+ (LPSTR)aPrinterNameA.GetBuffer(),
+ (LPDEVMODEA)pBuffer, NULL, DM_OUT_BUFFER );
+ }
+ if( nRet < 0 )
+ {
+ ClosePrinter( hPrn );
+ return FALSE;
+ }
+
+ // the spec version differs between the windows platforms, ie 98,NT,2000/XP
+ // this allows us to throw away printer settings from other platforms that might crash a buggy driver
+ // we check the driver version as well
+ dmSpecVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmSpecVersion : ((DEVMODEA*)pBuffer)->dmSpecVersion;
+ dmDriverVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmDriverVersion : ((DEVMODEA*)pBuffer)->dmDriverVersion;
+
+ ClosePrinter( hPrn );
+ }
+ SalDriverData* pSetupDriverData = (SalDriverData*)(pSetupData->mpDriverData);
+ if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) &&
+ (pPrinter->maDriverName == pSetupData->maDriver) &&
+ (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) &&
+ (long)(pSetupData->mnDriverDataLen - pSetupDriverData->mnDriverOffset) == nSysJobSize &&
+ pSetupDriverData->mnSysSignature == SAL_DRIVERDATA_SYSSIGN )
+ {
+ if( pDevModeA &&
+ (dmSpecVersion == pDevModeA->dmSpecVersion) &&
+ (dmDriverVersion == pDevModeA->dmDriverVersion) )
+ return TRUE;
+ if( pDevModeW &&
+ (dmSpecVersion == pDevModeW->dmSpecVersion) &&
+ (dmDriverVersion == pDevModeW->dmDriverVersion) )
+ return TRUE;
+ }
+ if ( bDelete )
+ {
+ rtl_freeMemory( pSetupData->mpDriverData );
+ pSetupData->mpDriverData = NULL;
+ pSetupData->mnDriverDataLen = 0;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData,
+ BOOL bIn, WinSalFrame* pVisibleDlgParent )
+{
+ ByteString aPrinterNameA = ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
+ HANDLE hPrn;
+ LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
+ if( aSalShlData.mbWPrinter )
+ {
+ if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
+ return FALSE;
+ }
+ else
+ {
+ if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
+ return FALSE;
+ }
+ // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
+ if( hPrn == HGDI_ERROR )
+ return FALSE;
+
+ LONG nRet;
+ LONG nSysJobSize = -1;
+ HWND hWnd = 0;
+ DWORD nMode = DM_OUT_BUFFER;
+ ULONG nDriverDataLen = 0;
+ SalDriverData* pOutBuffer = NULL;
+ BYTE* pInBuffer = NULL;
+
+ if( aSalShlData.mbWPrinter )
+ {
+ nSysJobSize = DocumentPropertiesW( hWnd, hPrn,
+ pPrinterNameW,
+ NULL, NULL, 0 );
+ }
+ else
+ nSysJobSize = DocumentPropertiesA( hWnd, hPrn,
+ (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
+ NULL, NULL, 0 );
+ if ( nSysJobSize < 0 )
+ {
+ ClosePrinter( hPrn );
+ return FALSE;
+ }
+
+ // Outputbuffer anlegen
+ nDriverDataLen = sizeof(SalDriverData) + nSysJobSize-1;
+ pOutBuffer = (SalDriverData*)rtl_allocateZeroMemory( nDriverDataLen );
+ pOutBuffer->mnSysSignature = SAL_DRIVERDATA_SYSSIGN;
+ pOutBuffer->mnVersion = aSalShlData.mbWPrinter ? SAL_DRIVERDATA_VERSION_W : SAL_DRIVERDATA_VERSION_A;
+ // calculate driver data offset including structure padding
+ pOutBuffer->mnDriverOffset = sal::static_int_cast<USHORT>(
+ (char*)pOutBuffer->maDriverData -
+ (char*)pOutBuffer );
+
+ // Testen, ob wir einen geeigneten Inputbuffer haben
+ if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) )
+ {
+ pInBuffer = (BYTE*)pSetupData->mpDriverData + ((SalDriverData*)pSetupData->mpDriverData)->mnDriverOffset;
+ nMode |= DM_IN_BUFFER;
+ }
+
+ // Testen, ob Dialog angezeigt werden soll
+ if ( pVisibleDlgParent )
+ {
+ hWnd = pVisibleDlgParent->mhWnd;
+ nMode |= DM_IN_PROMPT;
+ }
+
+ // Release mutex, in the other case we don't get paints and so on
+ ULONG nMutexCount=0;
+ if ( pVisibleDlgParent )
+ nMutexCount = ImplSalReleaseYieldMutex();
+
+ BYTE* pOutDevMode = (((BYTE*)pOutBuffer) + pOutBuffer->mnDriverOffset);
+ if( aSalShlData.mbWPrinter )
+ {
+ nRet = DocumentPropertiesW( hWnd, hPrn,
+ pPrinterNameW,
+ (LPDEVMODEW)pOutDevMode, (LPDEVMODEW)pInBuffer, nMode );
+ }
+ else
+ {
+ nRet = DocumentPropertiesA( hWnd, hPrn,
+ (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
+ (LPDEVMODEA)pOutDevMode, (LPDEVMODEA)pInBuffer, nMode );
+ }
+ if ( pVisibleDlgParent )
+ ImplSalAcquireYieldMutex( nMutexCount );
+ ClosePrinter( hPrn );
+
+ if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) )
+ {
+ rtl_freeMemory( pOutBuffer );
+ return FALSE;
+ }
+
+ // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
+ if( aSalShlData.mbWPrinter )
+ {
+ if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 64 )
+ {
+ sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmDeviceName );
+ if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )/sizeof(sal_Unicode) )
+ memset( ((LPDEVMODEW)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )-(nLen*sizeof(sal_Unicode)) );
+ }
+ if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 166 )
+ {
+ sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmFormName );
+ if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )/sizeof(sal_Unicode) )
+ memset( ((LPDEVMODEW)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )-(nLen*sizeof(sal_Unicode)) );
+ }
+ }
+ else
+ {
+ if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 32 )
+ {
+ sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmDeviceName );
+ if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName ) )
+ memset( ((LPDEVMODEA)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName )-nLen );
+ }
+ if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 102 )
+ {
+ sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmFormName );
+ if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName ) )
+ memset( ((LPDEVMODEA)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName )-nLen );
+ }
+ }
+
+ // update data
+ if ( pSetupData->mpDriverData )
+ rtl_freeMemory( pSetupData->mpDriverData );
+ pSetupData->mnDriverDataLen = nDriverDataLen;
+ pSetupData->mpDriverData = (BYTE*)pOutBuffer;
+ pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+#define DECLARE_DEVMODE( i )\
+ DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\
+ DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
+ if( pDevModeA == NULL && pDevModeW == NULL )\
+ return
+
+#define CHOOSE_DEVMODE(i)\
+ (pDevModeW ? pDevModeW->i : pDevModeA->i)
+
+static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags )
+{
+ if ( !pSetupData || !pSetupData->mpDriverData )
+ return;
+
+ DECLARE_DEVMODE( pSetupData );
+
+ // Orientation
+ if ( nFlags & SAL_JOBSET_ORIENTATION )
+ {
+ if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_PORTRAIT )
+ pSetupData->meOrientation = ORIENTATION_PORTRAIT;
+ else if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_LANDSCAPE )
+ pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
+ }
+
+ // PaperBin
+ if ( nFlags & SAL_JOBSET_PAPERBIN )
+ {
+ ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
+
+ if ( nCount && (nCount != GDI_ERROR) )
+ {
+ WORD* pBins = (WORD*)rtl_allocateZeroMemory( nCount*sizeof(WORD) );
+ ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
+ pSetupData->mnPaperBin = 0;
+
+ // search the right bin and assign index to mnPaperBin
+ for( ULONG i = 0; i < nCount; i++ )
+ {
+ if( CHOOSE_DEVMODE(dmDefaultSource) == pBins[ i ] )
+ {
+ pSetupData->mnPaperBin = (USHORT)i;
+ break;
+ }
+ }
+
+ rtl_freeMemory( pBins );
+ }
+ }
+
+ // PaperSize
+ if ( nFlags & SAL_JOBSET_PAPERSIZE )
+ {
+ if( (CHOOSE_DEVMODE(dmFields) & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) )
+ {
+ pSetupData->mnPaperWidth = CHOOSE_DEVMODE(dmPaperWidth)*10;
+ pSetupData->mnPaperHeight = CHOOSE_DEVMODE(dmPaperLength)*10;
+ }
+ else
+ {
+ ULONG nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
+ WORD* pPapers = NULL;
+ ULONG nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
+ POINT* pPaperSizes = NULL;
+ if ( nPaperCount && (nPaperCount != GDI_ERROR) )
+ {
+ pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
+ ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
+ }
+ if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
+ {
+ pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
+ ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
+ }
+ if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers )
+ {
+ for( ULONG i = 0; i < nPaperCount; i++ )
+ {
+ if( pPapers[ i ] == CHOOSE_DEVMODE(dmPaperSize) )
+ {
+ pSetupData->mnPaperWidth = pPaperSizes[ i ].x*10;
+ pSetupData->mnPaperHeight = pPaperSizes[ i ].y*10;
+ break;
+ }
+ }
+ }
+ if( pPapers )
+ rtl_freeMemory( pPapers );
+ if( pPaperSizes )
+ rtl_freeMemory( pPaperSizes );
+ }
+ switch( CHOOSE_DEVMODE(dmPaperSize) )
+ {
+ case( DMPAPER_LETTER ):
+ pSetupData->mePaperFormat = PAPER_LETTER;
+ break;
+ case( DMPAPER_TABLOID ):
+ pSetupData->mePaperFormat = PAPER_TABLOID;
+ break;
+ case( DMPAPER_LEDGER ):
+ pSetupData->mePaperFormat = PAPER_LEDGER;
+ break;
+ case( DMPAPER_LEGAL ):
+ pSetupData->mePaperFormat = PAPER_LEGAL;
+ break;
+ case( DMPAPER_STATEMENT ):
+ pSetupData->mePaperFormat = PAPER_STATEMENT;
+ break;
+ case( DMPAPER_EXECUTIVE ):
+ pSetupData->mePaperFormat = PAPER_EXECUTIVE;
+ break;
+ case( DMPAPER_A3 ):
+ pSetupData->mePaperFormat = PAPER_A3;
+ break;
+ case( DMPAPER_A4 ):
+ pSetupData->mePaperFormat = PAPER_A4;
+ break;
+ case( DMPAPER_A5 ):
+ pSetupData->mePaperFormat = PAPER_A5;
+ break;
+ //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
+ //i.e.
+ //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
+ //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
+ //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
+ //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
+ //matches our Excel filter's belief about the matching XlPaperSize
+ //enumeration.
+ //
+ //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
+ ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
+ //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
+ //(cmc)
+ case( DMPAPER_B4 ):
+ pSetupData->mePaperFormat = PAPER_B4_JIS;
+ break;
+ case( DMPAPER_B5 ):
+ pSetupData->mePaperFormat = PAPER_B5_JIS;
+ break;
+ case( DMPAPER_QUARTO ):
+ pSetupData->mePaperFormat = PAPER_QUARTO;
+ break;
+ case( DMPAPER_10X14 ):
+ pSetupData->mePaperFormat = PAPER_10x14;
+ break;
+ case( DMPAPER_NOTE ):
+ pSetupData->mePaperFormat = PAPER_LETTER;
+ break;
+ case( DMPAPER_ENV_9 ):
+ pSetupData->mePaperFormat = PAPER_ENV_9;
+ break;
+ case( DMPAPER_ENV_10 ):
+ pSetupData->mePaperFormat = PAPER_ENV_10;
+ break;
+ case( DMPAPER_ENV_11 ):
+ pSetupData->mePaperFormat = PAPER_ENV_11;
+ break;
+ case( DMPAPER_ENV_12 ):
+ pSetupData->mePaperFormat = PAPER_ENV_12;
+ break;
+ case( DMPAPER_ENV_14 ):
+ pSetupData->mePaperFormat = PAPER_ENV_14;
+ break;
+ case( DMPAPER_CSHEET ):
+ pSetupData->mePaperFormat = PAPER_C;
+ break;
+ case( DMPAPER_DSHEET ):
+ pSetupData->mePaperFormat = PAPER_D;
+ break;
+ case( DMPAPER_ESHEET ):
+ pSetupData->mePaperFormat = PAPER_E;
+ break;
+ case( DMPAPER_ENV_DL):
+ pSetupData->mePaperFormat = PAPER_ENV_DL;
+ break;
+ case( DMPAPER_ENV_C5):
+ pSetupData->mePaperFormat = PAPER_ENV_C5;
+ break;
+ case( DMPAPER_ENV_C3):
+ pSetupData->mePaperFormat = PAPER_ENV_C3;
+ break;
+ case( DMPAPER_ENV_C4):
+ pSetupData->mePaperFormat = PAPER_ENV_C4;
+ break;
+ case( DMPAPER_ENV_C6):
+ pSetupData->mePaperFormat = PAPER_ENV_C6;
+ break;
+ case( DMPAPER_ENV_C65):
+ pSetupData->mePaperFormat = PAPER_ENV_C65;
+ break;
+ case( DMPAPER_ENV_ITALY ):
+ pSetupData->mePaperFormat = PAPER_ENV_ITALY;
+ break;
+ case( DMPAPER_ENV_MONARCH ):
+ pSetupData->mePaperFormat = PAPER_ENV_MONARCH;
+ break;
+ case( DMPAPER_ENV_PERSONAL ):
+ pSetupData->mePaperFormat = PAPER_ENV_PERSONAL;
+ break;
+ case( DMPAPER_FANFOLD_US ):
+ pSetupData->mePaperFormat = PAPER_FANFOLD_US;
+ break;
+ case( DMPAPER_FANFOLD_STD_GERMAN ):
+ pSetupData->mePaperFormat = PAPER_FANFOLD_DE;
+ break;
+ case( DMPAPER_FANFOLD_LGL_GERMAN ):
+ pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE;
+ break;
+ case( DMPAPER_ISO_B4 ):
+ pSetupData->mePaperFormat = PAPER_B4_ISO;
+ break;
+ case( DMPAPER_JAPANESE_POSTCARD ):
+ pSetupData->mePaperFormat = PAPER_POSTCARD_JP;
+ break;
+ case( DMPAPER_9X11 ):
+ pSetupData->mePaperFormat = PAPER_9x11;
+ break;
+ case( DMPAPER_10X11 ):
+ pSetupData->mePaperFormat = PAPER_10x11;
+ break;
+ case( DMPAPER_15X11 ):
+ pSetupData->mePaperFormat = PAPER_15x11;
+ break;
+ case( DMPAPER_ENV_INVITE ):
+ pSetupData->mePaperFormat = PAPER_ENV_INVITE;
+ break;
+ case( DMPAPER_A_PLUS ):
+ pSetupData->mePaperFormat = PAPER_A_PLUS;
+ break;
+ case( DMPAPER_B_PLUS ):
+ pSetupData->mePaperFormat = PAPER_B_PLUS;
+ break;
+ case( DMPAPER_LETTER_PLUS ):
+ pSetupData->mePaperFormat = PAPER_LETTER_PLUS;
+ break;
+ case( DMPAPER_A4_PLUS ):
+ pSetupData->mePaperFormat = PAPER_A4_PLUS;
+ break;
+ case( DMPAPER_A2 ):
+ pSetupData->mePaperFormat = PAPER_A2;
+ break;
+ case( DMPAPER_DBL_JAPANESE_POSTCARD ):
+ pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP;
+ break;
+ case( DMPAPER_A6 ):
+ pSetupData->mePaperFormat = PAPER_A6;
+ break;
+ case( DMPAPER_B6_JIS ):
+ pSetupData->mePaperFormat = PAPER_B6_JIS;
+ break;
+ case( DMPAPER_12X11 ):
+ pSetupData->mePaperFormat = PAPER_12x11;
+ break;
+ default:
+ pSetupData->mePaperFormat = PAPER_USER;
+ break;
+ }
+ }
+
+ if( nFlags & SAL_JOBSET_DUPLEXMODE )
+ {
+ DuplexMode eDuplex = DUPLEX_UNKNOWN;
+ if( (CHOOSE_DEVMODE(dmFields) & DM_DUPLEX) )
+ {
+ if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_SIMPLEX )
+ eDuplex = DUPLEX_OFF;
+ else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_VERTICAL )
+ eDuplex = DUPLEX_LONGEDGE;
+ else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_HORIZONTAL )
+ eDuplex = DUPLEX_SHORTEDGE;
+ }
+ pSetupData->meDuplexMode = eDuplex;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplJobSetupToDevMode( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags )
+{
+ if ( !pSetupData || !pSetupData->mpDriverData )
+ return;
+
+ DECLARE_DEVMODE( pSetupData );
+
+ // Orientation
+ if ( nFlags & SAL_JOBSET_ORIENTATION )
+ {
+ CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION;
+ if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT )
+ CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT;
+ else
+ CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE;
+ }
+
+ // PaperBin
+ if ( nFlags & SAL_JOBSET_PAPERBIN )
+ {
+ ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
+
+ if ( nCount && (nCount != GDI_ERROR) )
+ {
+ WORD* pBins = (WORD*)rtl_allocateZeroMemory(nCount*sizeof(WORD));
+ ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
+ CHOOSE_DEVMODE(dmFields) |= DM_DEFAULTSOURCE;
+ CHOOSE_DEVMODE(dmDefaultSource) = pBins[ pSetupData->mnPaperBin ];
+ rtl_freeMemory( pBins );
+ }
+ }
+
+ // PaperSize
+ if ( nFlags & SAL_JOBSET_PAPERSIZE )
+ {
+ CHOOSE_DEVMODE(dmFields) |= DM_PAPERSIZE;
+ CHOOSE_DEVMODE(dmPaperWidth) = 0;
+ CHOOSE_DEVMODE(dmPaperLength) = 0;
+
+ switch( pSetupData->mePaperFormat )
+ {
+ case( PAPER_A2 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2;
+ break;
+ case( PAPER_A3 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3;
+ break;
+ case( PAPER_A4 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4;
+ break;
+ case( PAPER_A5 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5;
+ break;
+ case( PAPER_B4_ISO):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4;
+ break;
+ case( PAPER_LETTER ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER;
+ break;
+ case( PAPER_LEGAL ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL;
+ break;
+ case( PAPER_TABLOID ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID;
+ break;
+#if 0
+ //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
+ //DMPAPER_ENV_B6 is documented as:
+ //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
+ //which is the wrong way around, it is surely 125 x 176, i.e.
+ //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
+ //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
+ //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
+ case( PAPER_B6_ISO ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_B6;
+ break;
+#endif
+ case( PAPER_ENV_C4 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4;
+ break;
+ case( PAPER_ENV_C5 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5;
+ break;
+ case( PAPER_ENV_C6 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6;
+ break;
+ case( PAPER_ENV_C65 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65;
+ break;
+ case( PAPER_ENV_DL ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL;
+ break;
+ case( PAPER_C ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET;
+ break;
+ case( PAPER_D ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET;
+ break;
+ case( PAPER_E ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET;
+ break;
+ case( PAPER_EXECUTIVE ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE;
+ break;
+ case( PAPER_FANFOLD_LEGAL_DE ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN;
+ break;
+ case( PAPER_ENV_MONARCH ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH;
+ break;
+ case( PAPER_ENV_PERSONAL ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL;
+ break;
+ case( PAPER_ENV_9 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9;
+ break;
+ case( PAPER_ENV_10 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10;
+ break;
+ case( PAPER_ENV_11 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11;
+ break;
+ case( PAPER_ENV_12 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12;
+ break;
+ //See the comments on DMPAPER_B4 above
+ case( PAPER_B4_JIS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4;
+ break;
+ case( PAPER_B5_JIS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5;
+ break;
+ case( PAPER_B6_JIS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS;
+ break;
+ case( PAPER_LEDGER ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER;
+ break;
+ case( PAPER_STATEMENT ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT;
+ break;
+ case( PAPER_10x14 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14;
+ break;
+ case( PAPER_ENV_14 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14;
+ break;
+ case( PAPER_ENV_C3 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3;
+ break;
+ case( PAPER_ENV_ITALY ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY;
+ break;
+ case( PAPER_FANFOLD_US ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US;
+ break;
+ case( PAPER_FANFOLD_DE ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN;
+ break;
+ case( PAPER_POSTCARD_JP ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD;
+ break;
+ case( PAPER_9x11 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11;
+ break;
+ case( PAPER_10x11 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11;
+ break;
+ case( PAPER_15x11 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11;
+ break;
+ case( PAPER_ENV_INVITE ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE;
+ break;
+ case( PAPER_A_PLUS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS;
+ break;
+ case( PAPER_B_PLUS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS;
+ break;
+ case( PAPER_LETTER_PLUS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS;
+ break;
+ case( PAPER_A4_PLUS ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS;
+ break;
+ case( PAPER_DOUBLEPOSTCARD_JP ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD;
+ break;
+ case( PAPER_A6 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6;
+ break;
+ case( PAPER_12x11 ):
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11;
+ break;
+ default:
+ {
+ short nPaper = 0;
+ ULONG nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
+ WORD* pPapers = NULL;
+ ULONG nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
+ POINT* pPaperSizes = NULL;
+ DWORD nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, NULL, pSetupData );
+ if ( nPaperCount && (nPaperCount != GDI_ERROR) )
+ {
+ pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
+ ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
+ }
+ if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
+ {
+ pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
+ ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
+ }
+ if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes )
+ {
+ PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
+ // compare paper formats and select a good match
+ for ( ULONG i = 0; i < nPaperCount; i++ )
+ {
+ if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)))
+ {
+ nPaper = pPapers[i];
+ break;
+ }
+ }
+
+ // If the printer supports landscape orientation, check paper sizes again
+ // with landscape orientation. This is necessary as a printer driver provides
+ // all paper sizes with portrait orientation only!!
+ if ( !nPaper && nLandscapeAngle != 0 )
+ {
+ PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
+ for ( ULONG i = 0; i < nPaperCount; i++ )
+ {
+ if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) )
+ {
+ nPaper = pPapers[i];
+ break;
+ }
+ }
+ }
+
+ if ( nPaper )
+ CHOOSE_DEVMODE(dmPaperSize) = nPaper;
+ }
+
+ if ( !nPaper )
+ {
+ CHOOSE_DEVMODE(dmFields) |= DM_PAPERLENGTH | DM_PAPERWIDTH;
+ CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_USER;
+ CHOOSE_DEVMODE(dmPaperWidth) = (short)(pSetupData->mnPaperWidth/10);
+ CHOOSE_DEVMODE(dmPaperLength) = (short)(pSetupData->mnPaperHeight/10);
+ }
+
+ if ( pPapers )
+ rtl_freeMemory(pPapers);
+ if ( pPaperSizes )
+ rtl_freeMemory(pPaperSizes);
+
+ break;
+ }
+ }
+ }
+ if( (nFlags & SAL_JOBSET_DUPLEXMODE) )
+ {
+ switch( pSetupData->meDuplexMode )
+ {
+ case DUPLEX_OFF:
+ CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
+ CHOOSE_DEVMODE(dmDuplex) = DMDUP_SIMPLEX;
+ break;
+ case DUPLEX_SHORTEDGE:
+ CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
+ CHOOSE_DEVMODE(dmDuplex) = DMDUP_HORIZONTAL;
+ break;
+ case DUPLEX_LONGEDGE:
+ CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
+ CHOOSE_DEVMODE(dmDuplex) = DMDUP_VERTICAL;
+ break;
+ case DUPLEX_UNKNOWN:
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static HDC ImplCreateICW_WithCatch( LPWSTR pDriver,
+ LPCWSTR pDevice,
+ LPDEVMODEW pDevMode )
+{
+ HDC hDC = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ hDC = CreateICW( pDriver, pDevice, 0, pDevMode );
+ CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
+ return hDC;
+}
+
+static HDC ImplCreateICA_WithCatch( char* pDriver,
+ char* pDevice,
+ LPDEVMODEA pDevMode )
+{
+ HDC hDC = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ hDC = CreateICA( pDriver, pDevice, 0, pDevMode );
+ CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
+ return hDC;
+}
+
+
+static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
+{
+ HDC hDC = 0;
+ if( aSalShlData.mbWPrinter )
+ {
+ LPDEVMODEW pDevMode;
+ if ( pSetupData && pSetupData->mpDriverData )
+ pDevMode = SAL_DEVMODE_W( pSetupData );
+ else
+ pDevMode = NULL;
+ // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
+ // pl: does this hold true for Unicode functions ?
+ if( pPrinter->maDriverName.Len() > 2048 || pPrinter->maDeviceName.Len() > 2048 )
+ return 0;
+ sal_Unicode pDriverName[ 4096 ];
+ sal_Unicode pDeviceName[ 4096 ];
+ rtl_copyMemory( pDriverName, pPrinter->maDriverName.GetBuffer(), pPrinter->maDriverName.Len()*sizeof(sal_Unicode));
+ memset( pDriverName+pPrinter->maDriverName.Len(), 0, 32 );
+ rtl_copyMemory( pDeviceName, pPrinter->maDeviceName.GetBuffer(), pPrinter->maDeviceName.Len()*sizeof(sal_Unicode));
+ memset( pDeviceName+pPrinter->maDeviceName.Len(), 0, 32 );
+ hDC = ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR >(pDriverName),
+ reinterpret_cast< LPCWSTR >(pDeviceName),
+ pDevMode );
+ }
+ else
+ {
+ LPDEVMODEA pDevMode;
+ if ( pSetupData && pSetupData->mpDriverData )
+ pDevMode = SAL_DEVMODE_A( pSetupData );
+ else
+ pDevMode = NULL;
+ // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
+ ByteString aDriver ( ImplSalGetWinAnsiString( pPrinter->maDriverName, TRUE ) );
+ ByteString aDevice ( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ) );
+ int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
+ // #125813# under some circumstances many printer drivers really
+ // seem to have a problem with the names and their conversions.
+ // We need to get on to of this, but haven't been able to reproduce
+ // the problem yet. Put the names on the stack so we get them
+ // with an eventual crash report.
+ if( n >= 2048 )
+ return 0;
+ n += 2048;
+ char lpszDriverName[ 4096 ];
+ char lpszDeviceName[ 4096 ];
+ strncpy( lpszDriverName, aDriver.GetBuffer(), n );
+ strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
+ // HDU: the crashes usually happen in a MBCS to unicode conversion,
+ // so I suspect the MBCS string's end is not properly recognized.
+ // The longest MBCS encoding I'm aware of has six bytes per code
+ // => add a couple of zeroes...
+ memset( lpszDriverName+aDriver.Len(), 0, 16 );
+ memset( lpszDeviceName+aDevice.Len(), 0, 16 );
+ hDC = ImplCreateICA_WithCatch( lpszDriverName,
+ lpszDeviceName,
+ pDevMode );
+ }
+ return hDC;
+}
+
+// -----------------------------------------------------------------------
+
+static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC )
+{
+ WinSalGraphics* pGraphics = new WinSalGraphics;
+ pGraphics->SetLayout( 0 );
+ pGraphics->mhDC = hDC;
+ pGraphics->mhWnd = 0;
+ pGraphics->mbPrinter = TRUE;
+ pGraphics->mbVirDev = FALSE;
+ pGraphics->mbWindow = FALSE;
+ pGraphics->mbScreen = FALSE;
+ ImplSalInitGraphics( pGraphics );
+ return pGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
+{
+ HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
+ if ( !hNewDC )
+ return FALSE;
+
+ if ( pPrinter->mpGraphics )
+ {
+ ImplSalDeInitGraphics( pPrinter->mpGraphics );
+ DeleteDC( pPrinter->mpGraphics->mhDC );
+ delete pPrinter->mpGraphics;
+ }
+
+ pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hNewDC );
+ pPrinter->mhDC = hNewDC;
+
+ return TRUE;
+}
+
+// =======================================================================
+
+SalInfoPrinter* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
+ ImplJobSetup* pSetupData )
+{
+ WinSalInfoPrinter* pPrinter = new WinSalInfoPrinter;
+ if( ! pQueueInfo->mpSysData )
+ GetPrinterQueueState( pQueueInfo );
+ pPrinter->maDriverName = pQueueInfo->maDriver;
+ pPrinter->maDeviceName = pQueueInfo->maPrinterName;
+ pPrinter->maPortName = pQueueInfo->mpSysData ?
+ *(String*)(pQueueInfo->mpSysData)
+ : String();
+
+ // check if the provided setup data match the actual printer
+ ImplTestSalJobSetup( pPrinter, pSetupData, TRUE );
+
+ HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
+ if ( !hDC )
+ {
+ delete pPrinter;
+ return NULL;
+ }
+
+ pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hDC );
+ pPrinter->mhDC = hDC;
+ if ( !pSetupData->mpDriverData )
+ ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL );
+ ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL );
+ pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
+
+ return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
+{
+ delete pPrinter;
+}
+
+// =======================================================================
+
+WinSalInfoPrinter::WinSalInfoPrinter() :
+ mpGraphics( NULL ),
+ mhDC( 0 ),
+ mbGraphics( FALSE )
+{
+ m_bPapersInit = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+WinSalInfoPrinter::~WinSalInfoPrinter()
+{
+ if ( mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ DeleteDC( mpGraphics->mhDC );
+ delete mpGraphics;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
+{
+ m_aPaperFormats.clear();
+
+ DWORD nCount = ImplDeviceCaps( this, DC_PAPERSIZE, NULL, pSetupData );
+ if( nCount == GDI_ERROR )
+ nCount = 0;
+
+ POINT* pPaperSizes = NULL;
+ if( nCount )
+ {
+ pPaperSizes = (POINT*)rtl_allocateZeroMemory(nCount*sizeof(POINT));
+ ImplDeviceCaps( this, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
+
+ if( aSalShlData.mbWPrinter )
+ {
+ sal_Unicode* pNamesBuffer = (sal_Unicode*)rtl_allocateMemory(nCount*64*sizeof(sal_Unicode));
+ ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
+ for( DWORD i = 0; i < nCount; ++i )
+ {
+ PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
+ m_aPaperFormats.push_back( aInfo );
+ }
+ rtl_freeMemory( pNamesBuffer );
+ }
+ else
+ {
+ char* pNamesBuffer = (char*)rtl_allocateMemory(nCount*64);
+ ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
+ for( DWORD i = 0; i < nCount; ++i )
+ {
+ PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
+ m_aPaperFormats.push_back( aInfo );
+ }
+ rtl_freeMemory( pNamesBuffer );
+ }
+ rtl_freeMemory( pPaperSizes );
+ }
+
+ m_bPapersInit = true;
+}
+
+// -----------------------------------------------------------------------
+
+int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
+{
+ int nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
+
+ if( nRet != GDI_ERROR )
+ return nRet * 10;
+ else
+ return 900; // guess
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* WinSalInfoPrinter::GetGraphics()
+{
+ if ( mbGraphics )
+ return NULL;
+
+ if ( mpGraphics )
+ mbGraphics = TRUE;
+
+ return mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInfoPrinter::ReleaseGraphics( SalGraphics* )
+{
+ mbGraphics = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData )
+{
+ if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, static_cast<WinSalFrame*>(pFrame) ) )
+ {
+ ImplDevModeToJobSetup( this, pSetupData, SAL_JOBSET_ALL );
+ return ImplUpdateSalPrnIC( this, pSetupData );
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
+{
+ if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) )
+ return FALSE;
+ return ImplUpdateSalPrnIC( this, pSetupData );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalInfoPrinter::SetData( ULONG nFlags, ImplJobSetup* pSetupData )
+{
+ ImplJobSetupToDevMode( this, pSetupData, nFlags );
+ if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, NULL ) )
+ {
+ ImplDevModeToJobSetup( this, pSetupData, nFlags );
+ return ImplUpdateSalPrnIC( this, pSetupData );
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData )
+{
+ DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return nRet;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+XubString WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pSetupData, ULONG nPaperBin )
+{
+ XubString aPaperBinName;
+
+ DWORD nBins = ImplDeviceCaps( this, DC_BINNAMES, NULL, pSetupData );
+ if ( (nPaperBin < nBins) && (nBins != GDI_ERROR) )
+ {
+ if( aSalShlData.mbWPrinter )
+ {
+ sal_Unicode* pBuffer = new sal_Unicode[nBins*24];
+ DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ aPaperBinName = pBuffer + (nPaperBin*24);
+ delete [] pBuffer;
+ }
+ else
+ {
+ char* pBuffer = new char[nBins*24];
+ DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ aPaperBinName = ImplSalGetUniString( (const char*)(pBuffer + (nPaperBin*24)) );
+ delete [] pBuffer;
+ }
+ }
+
+ return aPaperBinName;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, USHORT nType )
+{
+ DWORD nRet;
+
+ switch ( nType )
+ {
+ case PRINTER_CAPABILITIES_SUPPORTDIALOG:
+ return TRUE;
+ case PRINTER_CAPABILITIES_COPIES:
+ nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return nRet;
+ return 0;
+ case PRINTER_CAPABILITIES_COLLATECOPIES:
+ if ( aSalShlData.mbW40 )
+ {
+ nRet = ImplDeviceCaps( this, DC_COLLATE, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ {
+ nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return nRet;
+ }
+ }
+ return 0;
+
+ case PRINTER_CAPABILITIES_SETORIENTATION:
+ nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return TRUE;
+ return FALSE;
+
+ case PRINTER_CAPABILITIES_SETPAPERBIN:
+ nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return TRUE;
+ return FALSE;
+
+ case PRINTER_CAPABILITIES_SETPAPERSIZE:
+ case PRINTER_CAPABILITIES_SETPAPER:
+ nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData );
+ if ( nRet && (nRet != GDI_ERROR) )
+ return TRUE;
+ return FALSE;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
+ long& rOutWidth, long& rOutHeight,
+ long& rPageOffX, long& rPageOffY,
+ long& rPageWidth, long& rPageHeight )
+{
+ HDC hDC = mhDC;
+
+ rOutWidth = GetDeviceCaps( hDC, HORZRES );
+ rOutHeight = GetDeviceCaps( hDC, VERTRES );
+
+ rPageOffX = GetDeviceCaps( hDC, PHYSICALOFFSETX );
+ rPageOffY = GetDeviceCaps( hDC, PHYSICALOFFSETY );
+ rPageWidth = GetDeviceCaps( hDC, PHYSICALWIDTH );
+ rPageHeight = GetDeviceCaps( hDC, PHYSICALHEIGHT );
+}
+
+// =======================================================================
+
+SalPrinter* WinSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
+{
+ WinSalPrinter* pPrinter = new WinSalPrinter;
+ pPrinter->mpInfoPrinter = static_cast<WinSalInfoPrinter*>(pInfoPrinter);
+ return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::DestroyPrinter( SalPrinter* pPrinter )
+{
+ delete pPrinter;
+}
+
+// =======================================================================
+
+WIN_BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
+{
+ SalData* pSalData = GetSalData();
+ WinSalPrinter* pPrinter;
+ BOOL bWhile = TRUE;
+ int i = 0;
+
+ do
+ {
+ // Messages verarbeiten
+ MSG aMsg;
+ if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplDispatchMessage( &aMsg );
+ i++;
+ if ( i > 15 )
+ bWhile = FALSE;
+ }
+ else
+ bWhile = FALSE;
+
+ pPrinter = pSalData->mpFirstPrinter;
+ while ( pPrinter )
+ {
+ if( pPrinter->mhDC == hPrnDC )
+ break;
+
+ pPrinter = pPrinter->mpNextPrinter;
+ }
+
+ if ( !pPrinter || pPrinter->mbAbort )
+ return FALSE;
+ }
+ while ( bWhile );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+static LPDEVMODEA ImplSalSetCopies( LPDEVMODEA pDevMode, ULONG nCopies, BOOL bCollate )
+{
+ LPDEVMODEA pNewDevMode = pDevMode;
+ if ( pDevMode && (nCopies > 1) )
+ {
+ if ( nCopies > 32765 )
+ nCopies = 32765;
+ ULONG nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
+ pNewDevMode = (LPDEVMODEA)rtl_allocateMemory( nDevSize );
+ memcpy( pNewDevMode, pDevMode, nDevSize );
+ pDevMode = pNewDevMode;
+ pDevMode->dmFields |= DM_COPIES;
+ pDevMode->dmCopies = (short)(USHORT)nCopies;
+ if ( aSalShlData.mbW40 )
+ {
+ pDevMode->dmFields |= DM_COLLATE;
+ if ( bCollate )
+ pDevMode->dmCollate = DMCOLLATE_TRUE;
+ else
+ pDevMode->dmCollate = DMCOLLATE_FALSE;
+ }
+ }
+
+ return pNewDevMode;
+}
+
+static LPDEVMODEW ImplSalSetCopies( LPDEVMODEW pDevMode, ULONG nCopies, BOOL bCollate )
+{
+ LPDEVMODEW pNewDevMode = pDevMode;
+ if ( pDevMode && (nCopies > 1) )
+ {
+ if ( nCopies > 32765 )
+ nCopies = 32765;
+ ULONG nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
+ pNewDevMode = (LPDEVMODEW)rtl_allocateMemory( nDevSize );
+ memcpy( pNewDevMode, pDevMode, nDevSize );
+ pDevMode = pNewDevMode;
+ pDevMode->dmFields |= DM_COPIES;
+ pDevMode->dmCopies = (short)(USHORT)nCopies;
+ if ( aSalShlData.mbW40 )
+ {
+ pDevMode->dmFields |= DM_COLLATE;
+ if ( bCollate )
+ pDevMode->dmCollate = DMCOLLATE_TRUE;
+ else
+ pDevMode->dmCollate = DMCOLLATE_FALSE;
+ }
+ }
+
+ return pNewDevMode;
+}
+
+// -----------------------------------------------------------------------
+
+WinSalPrinter::WinSalPrinter() :
+ mpGraphics( NULL ),
+ mpInfoPrinter( NULL ),
+ mpNextPrinter( NULL ),
+ mhDC( 0 ),
+ mnError( 0 ),
+ mnCopies( 0 ),
+ mbCollate( FALSE ),
+ mbAbort( FALSE ),
+ mbValid( true )
+{
+ SalData* pSalData = GetSalData();
+ // insert printer in printerlist
+ mpNextPrinter = pSalData->mpFirstPrinter;
+ pSalData->mpFirstPrinter = this;
+}
+
+// -----------------------------------------------------------------------
+
+WinSalPrinter::~WinSalPrinter()
+{
+ SalData* pSalData = GetSalData();
+
+ // release DC if there is one still around because of AbortJob
+ HDC hDC = mhDC;
+ if ( hDC )
+ {
+ if ( mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ delete mpGraphics;
+ }
+
+ DeleteDC( hDC );
+ }
+
+ // remove printer from printerlist
+ if ( this == pSalData->mpFirstPrinter )
+ pSalData->mpFirstPrinter = mpNextPrinter;
+ else
+ {
+ WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
+
+ while( pTempPrinter->mpNextPrinter != this )
+ pTempPrinter = pTempPrinter->mpNextPrinter;
+
+ pTempPrinter->mpNextPrinter = mpNextPrinter;
+ }
+ mbValid = false;
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalPrinter::markInvalid()
+{
+ mbValid = false;
+}
+
+// -----------------------------------------------------------------------
+
+// need wrappers for StarTocW/A to use structured exception handling
+// since SEH does not mix with standard exception handling's cleanup
+static int lcl_StartDocW( HDC hDC, DOCINFOW* pInfo, WinSalPrinter* pPrt )
+{
+ int nRet = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ nRet = ::StartDocW( hDC, pInfo );
+ CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
+ return nRet;
+}
+
+static int lcl_StartDocA( HDC hDC, DOCINFOA* pInfo, WinSalPrinter* pPrt )
+{
+ int nRet = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ nRet = ::StartDocA( hDC, pInfo );
+ CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
+ return nRet;
+}
+
+BOOL WinSalPrinter::StartJob( const XubString* pFileName,
+ const XubString& rJobName,
+ const XubString&,
+ ULONG nCopies,
+ bool bCollate,
+ bool /*bDirect*/,
+ ImplJobSetup* pSetupData )
+{
+ mnError = 0;
+ mbAbort = FALSE;
+ mnCopies = nCopies;
+ mbCollate = bCollate;
+
+ LPDEVMODEA pOrgDevModeA = NULL;
+ LPDEVMODEA pDevModeA = NULL;
+ LPDEVMODEW pOrgDevModeW = NULL;
+ LPDEVMODEW pDevModeW = NULL;
+ HDC hDC = 0;
+ if( aSalShlData.mbWPrinter )
+ {
+ if ( pSetupData && pSetupData->mpDriverData )
+ {
+ pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
+ pDevModeW = ImplSalSetCopies( pOrgDevModeW, nCopies, bCollate );
+ }
+ else
+ pDevModeW = NULL;
+
+ // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
+ sal_Unicode aDrvBuf[4096];
+ sal_Unicode aDevBuf[4096];
+ rtl_copyMemory( aDrvBuf, mpInfoPrinter->maDriverName.GetBuffer(), (mpInfoPrinter->maDriverName.Len()+1)*sizeof(sal_Unicode));
+ rtl_copyMemory( aDevBuf, mpInfoPrinter->maDeviceName.GetBuffer(), (mpInfoPrinter->maDeviceName.Len()+1)*sizeof(sal_Unicode));
+ hDC = CreateDCW( reinterpret_cast<LPCWSTR>(aDrvBuf),
+ reinterpret_cast<LPCWSTR>(aDevBuf),
+ NULL,
+ pDevModeW );
+
+ if ( pDevModeW != pOrgDevModeW )
+ rtl_freeMemory( pDevModeW );
+ }
+ else
+ {
+ if ( pSetupData && pSetupData->mpDriverData )
+ {
+ pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
+ pDevModeA = ImplSalSetCopies( pOrgDevModeA, nCopies, bCollate );
+ }
+ else
+ pDevModeA = NULL;
+
+ // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
+ ByteString aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter->maDriverName, TRUE ) );
+ ByteString aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter->maDeviceName, TRUE ) );
+ int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
+ n += 2048;
+ char *lpszDriverName = new char[n];
+ char *lpszDeviceName = new char[n];
+ strncpy( lpszDriverName, aDriver.GetBuffer(), n );
+ strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
+ hDC = CreateDCA( lpszDriverName,
+ lpszDeviceName,
+ NULL,
+ pDevModeA );
+
+ delete [] lpszDriverName;
+ delete [] lpszDeviceName;
+
+ if ( pDevModeA != pOrgDevModeA )
+ rtl_freeMemory( pDevModeA );
+ }
+
+ if ( !hDC )
+ {
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+
+ // make sure mhDC is set before the printer driver may call our abortproc
+ mhDC = hDC;
+ if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
+ {
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+
+ mnError = 0;
+ mbAbort = FALSE;
+
+ // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages
+ // ansonsten oefters schickt, versuchen wir vorher alle
+ // zu verarbeiten und dann eine Dummy-Message reinstellen
+ BOOL bWhile = TRUE;
+ int i = 0;
+ do
+ {
+ // Messages verarbeiten
+ MSG aMsg;
+ if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplDispatchMessage( &aMsg );
+ i++;
+ if ( i > 15 )
+ bWhile = FALSE;
+ }
+ else
+ bWhile = FALSE;
+ }
+ while ( bWhile );
+ ImplPostMessage( GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0 );
+
+ // bring up a file choser if printing to file port but no file name given
+ OUString aOutFileName;
+ if( mpInfoPrinter->maPortName.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName && pFileName->Len()) )
+ {
+
+ Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
+ if( xFactory.is() )
+ {
+ Reference< XFilePicker > xFilePicker( xFactory->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
+ UNO_QUERY );
+ DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" );
+
+ Reference< XInitialization > xInit( xFilePicker, UNO_QUERY );
+ Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY );
+ if( xInit.is() && xFilePicker.is() && xFilterMgr.is() )
+ {
+ Sequence< Any > aServiceType( 1 );
+ aServiceType[0] <<= TemplateDescription::FILESAVE_SIMPLE;
+ xInit->initialize( aServiceType );
+ if( xFilePicker->execute() == ExecutableDialogResults::OK )
+ {
+ Sequence< OUString > aPathSeq( xFilePicker->getFiles() );
+ INetURLObject aObj( aPathSeq[0] );
+ // we're using ansi calls (StartDocA) so convert the string
+ aOutFileName = aObj.PathToFileName();
+ }
+ else
+ {
+ mnError = SAL_PRINTER_ERROR_ABORT;
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ if( aSalShlData.mbWPrinter )
+ {
+ DOCINFOW aInfo;
+ memset( &aInfo, 0, sizeof( DOCINFOW ) );
+ aInfo.cbSize = sizeof( aInfo );
+ aInfo.lpszDocName = (LPWSTR)rJobName.GetBuffer();
+ if ( pFileName || aOutFileName.getLength() )
+ {
+ if ( (pFileName && pFileName->Len()) || aOutFileName.getLength() )
+ {
+ aInfo.lpszOutput = (LPWSTR)( (pFileName && pFileName->Len()) ? pFileName->GetBuffer() : aOutFileName.getStr());
+ }
+ else
+ aInfo.lpszOutput = L"FILE:";
+ }
+ else
+ aInfo.lpszOutput = NULL;
+
+ // start Job
+ int nRet = lcl_StartDocW( hDC, &aInfo, this );
+
+ if ( nRet <= 0 )
+ {
+ long nError = GetLastError();
+ if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
+ mnError = SAL_PRINTER_ERROR_ABORT;
+ else
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+ }
+ else
+ {
+ // Both strings must exist, if StartJob() is called
+ ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) );
+ ByteString aFileName;
+
+ DOCINFOA aInfo;
+ memset( &aInfo, 0, sizeof( DOCINFOA ) );
+ aInfo.cbSize = sizeof( aInfo );
+ aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer();
+ if ( pFileName || aOutFileName.getLength() )
+ {
+ if ( pFileName->Len() || aOutFileName.getLength() )
+ {
+ aFileName = ImplSalGetWinAnsiString( pFileName ? *pFileName : static_cast<const XubString>(aOutFileName), TRUE );
+ aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer();
+ }
+ else
+ aInfo.lpszOutput = "FILE:";
+ }
+ else
+ aInfo.lpszOutput = NULL;
+
+ // start Job
+ int nRet = lcl_StartDocA( hDC, &aInfo, this );
+ if ( nRet <= 0 )
+ {
+ long nError = GetLastError();
+ if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
+ mnError = SAL_PRINTER_ERROR_ABORT;
+ else
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalPrinter::EndJob()
+{
+ DWORD err = 0;
+ HDC hDC = mhDC;
+ if ( isValid() && hDC )
+ {
+ if ( mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ delete mpGraphics;
+ mpGraphics = NULL;
+ }
+
+ // #i54419# Windows fax printer brings up a dialog in EndDoc
+ // which text previously copied in soffice process can be
+ // pasted to -> deadlock due to mutex not released.
+ // it should be safe to release the yield mutex over the EndDoc
+ // call, however the real solution is supposed to be the threading
+ // framework yet to come.
+ SalData* pSalData = GetSalData();
+ ULONG nAcquire = pSalData->mpFirstInstance->ReleaseYieldMutex();
+ CATCH_DRIVER_EX_BEGIN;
+ if( ::EndDoc( hDC ) <= 0 )
+ err = GetLastError();
+ CATCH_DRIVER_EX_END( "exception in EndDoc", this );
+
+ pSalData->mpFirstInstance->AcquireYieldMutex( nAcquire );
+ DeleteDC( hDC );
+ mhDC = 0;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalPrinter::AbortJob()
+{
+ mbAbort = TRUE;
+
+ // Abort asyncron ausloesen
+ HDC hDC = mhDC;
+ if ( hDC )
+ {
+ SalData* pSalData = GetSalData();
+ ImplPostMessage( pSalData->mpFirstInstance->mhComWnd,
+ SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalPrinterAbortJobAsync( HDC hPrnDC )
+{
+ SalData* pSalData = GetSalData();
+ WinSalPrinter* pPrinter = pSalData->mpFirstPrinter;
+
+ // Feststellen, ob Printer noch existiert
+ while ( pPrinter )
+ {
+ if ( pPrinter->mhDC == hPrnDC )
+ break;
+
+ pPrinter = pPrinter->mpNextPrinter;
+ }
+
+ // Wenn Printer noch existiert, dann den Job abbrechen
+ if ( pPrinter )
+ {
+ HDC hDC = pPrinter->mhDC;
+ if ( hDC )
+ {
+ if ( pPrinter->mpGraphics )
+ {
+ ImplSalDeInitGraphics( pPrinter->mpGraphics );
+ delete pPrinter->mpGraphics;
+ pPrinter->mpGraphics = NULL;
+ }
+
+ CATCH_DRIVER_EX_BEGIN;
+ ::AbortDoc( hDC );
+ CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter );
+
+ DeleteDC( hDC );
+ pPrinter->mhDC = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobData )
+{
+ if( ! isValid() || mhDC == 0 )
+ return NULL;
+
+ HDC hDC = mhDC;
+ if ( pSetupData && pSetupData->mpDriverData && bNewJobData )
+ {
+ if( aSalShlData.mbWPrinter )
+ {
+ LPDEVMODEW pOrgDevModeW;
+ LPDEVMODEW pDevModeW;
+ pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
+ pDevModeW = ImplSalSetCopies( pOrgDevModeW, mnCopies, mbCollate );
+ ResetDCW( hDC, pDevModeW );
+ if ( pDevModeW != pOrgDevModeW )
+ rtl_freeMemory( pDevModeW );
+ }
+ else
+ {
+ LPDEVMODEA pOrgDevModeA;
+ LPDEVMODEA pDevModeA;
+ pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
+ pDevModeA = ImplSalSetCopies( pOrgDevModeA, mnCopies, mbCollate );
+ ResetDCA( hDC, pDevModeA );
+ if ( pDevModeA != pOrgDevModeA )
+ rtl_freeMemory( pDevModeA );
+ }
+ }
+ int nRet = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ nRet = ::StartPage( hDC );
+ CATCH_DRIVER_EX_END( "exception in StartPage", this );
+
+ if ( nRet <= 0 )
+ {
+ GetLastError();
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return NULL;
+ }
+
+ // Hack to work around old PostScript printer drivers optimizing away empty pages
+ // TODO: move into ImplCreateSalPrnGraphics()?
+ HPEN hTempPen = SelectPen( hDC, GetStockPen( NULL_PEN ) );
+ HBRUSH hTempBrush = SelectBrush( hDC, GetStockBrush( NULL_BRUSH ) );
+ WIN_Rectangle( hDC, -8000, -8000, -7999, -7999 );
+ SelectPen( hDC, hTempPen );
+ SelectBrush( hDC, hTempBrush );
+
+ mpGraphics = ImplCreateSalPrnGraphics( hDC );
+ return mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WinSalPrinter::EndPage()
+{
+ HDC hDC = mhDC;
+ if ( hDC && mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ delete mpGraphics;
+ mpGraphics = NULL;
+ }
+
+ if( ! isValid() )
+ return FALSE;
+
+ int nRet = 0;
+ CATCH_DRIVER_EX_BEGIN;
+ nRet = ::EndPage( hDC );
+ CATCH_DRIVER_EX_END( "exception in EndPage", this );
+
+ if ( nRet > 0 )
+ return TRUE;
+ else
+ {
+ GetLastError();
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ULONG WinSalPrinter::GetErrorCode()
+{
+ return mnError;
+}