1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salprn.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include <tools/svwin.h>
42 #include <osl/module.h>
44 #include <wincomp.hxx>
45 #include <saldata.hxx>
49 #include <vcl/salptype.hxx>
51 #include <vcl/print.h>
52 #include <vcl/jobset.h>
54 #include <tools/urlobj.hxx>
55 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
56 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
57 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
58 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
59 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
60 #include <com/sun/star/lang/XInitialization.hpp>
61 #include <comphelper/processfactory.hxx>
66 #define CATCH_DRIVER_EX_BEGIN \
69 if (__builtin_setjmp(jmpbuf) == 0) \
71 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
73 #define CATCH_DRIVER_EX_END(mes, p) \
76 #define CATCH_DRIVER_EX_END_2(mes) \
80 #define CATCH_DRIVER_EX_BEGIN \
83 #define CATCH_DRIVER_EX_END(mes, p) \
85 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
90 #define CATCH_DRIVER_EX_END_2(mes) \
92 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
99 using namespace com::sun::star::uno
;
100 using namespace com::sun::star::lang
;
101 using namespace com::sun::star::ui::dialogs
;
104 // =======================================================================
106 static char aImplWindows
[] = "windows";
107 static char aImplDevices
[] = "devices";
108 static char aImplDevice
[] = "device";
110 static LPDEVMODEA
SAL_DEVMODE_A( const ImplJobSetup
* pSetupData
)
112 LPDEVMODEA pRet
= NULL
;
113 SalDriverData
* pDrv
= (SalDriverData
*)pSetupData
->mpDriverData
;
114 if( pDrv
->mnVersion
== SAL_DRIVERDATA_VERSION_A
&&
115 pSetupData
->mnDriverDataLen
>= sizeof(DEVMODEA
)+sizeof(SalDriverData
)-1
117 pRet
= ((LPDEVMODEA
)((pSetupData
->mpDriverData
) + (pDrv
->mnDriverOffset
)));
121 static LPDEVMODEW
SAL_DEVMODE_W( const ImplJobSetup
* pSetupData
)
123 LPDEVMODEW pRet
= NULL
;
124 SalDriverData
* pDrv
= (SalDriverData
*)pSetupData
->mpDriverData
;
125 if( pDrv
->mnVersion
== SAL_DRIVERDATA_VERSION_W
&&
126 pSetupData
->mnDriverDataLen
>= sizeof(DEVMODEW
)+sizeof(SalDriverData
)-1
128 pRet
= ((LPDEVMODEW
)((pSetupData
->mpDriverData
) + (pDrv
->mnDriverOffset
)));
132 // =======================================================================
134 static ULONG
ImplWinQueueStatusToSal( DWORD nWinStatus
)
137 if ( nWinStatus
& PRINTER_STATUS_PAUSED
)
138 nStatus
|= QUEUE_STATUS_PAUSED
;
139 if ( nWinStatus
& PRINTER_STATUS_ERROR
)
140 nStatus
|= QUEUE_STATUS_ERROR
;
141 if ( nWinStatus
& PRINTER_STATUS_PENDING_DELETION
)
142 nStatus
|= QUEUE_STATUS_PENDING_DELETION
;
143 if ( nWinStatus
& PRINTER_STATUS_PAPER_JAM
)
144 nStatus
|= QUEUE_STATUS_PAPER_JAM
;
145 if ( nWinStatus
& PRINTER_STATUS_PAPER_OUT
)
146 nStatus
|= QUEUE_STATUS_PAPER_OUT
;
147 if ( nWinStatus
& PRINTER_STATUS_MANUAL_FEED
)
148 nStatus
|= QUEUE_STATUS_MANUAL_FEED
;
149 if ( nWinStatus
& PRINTER_STATUS_PAPER_PROBLEM
)
150 nStatus
|= QUEUE_STATUS_PAPER_PROBLEM
;
151 if ( nWinStatus
& PRINTER_STATUS_OFFLINE
)
152 nStatus
|= QUEUE_STATUS_OFFLINE
;
153 if ( nWinStatus
& PRINTER_STATUS_IO_ACTIVE
)
154 nStatus
|= QUEUE_STATUS_IO_ACTIVE
;
155 if ( nWinStatus
& PRINTER_STATUS_BUSY
)
156 nStatus
|= QUEUE_STATUS_BUSY
;
157 if ( nWinStatus
& PRINTER_STATUS_PRINTING
)
158 nStatus
|= QUEUE_STATUS_PRINTING
;
159 if ( nWinStatus
& PRINTER_STATUS_OUTPUT_BIN_FULL
)
160 nStatus
|= QUEUE_STATUS_OUTPUT_BIN_FULL
;
161 if ( nWinStatus
& PRINTER_STATUS_WAITING
)
162 nStatus
|= QUEUE_STATUS_WAITING
;
163 if ( nWinStatus
& PRINTER_STATUS_PROCESSING
)
164 nStatus
|= QUEUE_STATUS_PROCESSING
;
165 if ( nWinStatus
& PRINTER_STATUS_INITIALIZING
)
166 nStatus
|= QUEUE_STATUS_INITIALIZING
;
167 if ( nWinStatus
& PRINTER_STATUS_WARMING_UP
)
168 nStatus
|= QUEUE_STATUS_WARMING_UP
;
169 if ( nWinStatus
& PRINTER_STATUS_TONER_LOW
)
170 nStatus
|= QUEUE_STATUS_TONER_LOW
;
171 if ( nWinStatus
& PRINTER_STATUS_NO_TONER
)
172 nStatus
|= QUEUE_STATUS_NO_TONER
;
173 if ( nWinStatus
& PRINTER_STATUS_PAGE_PUNT
)
174 nStatus
|= QUEUE_STATUS_PAGE_PUNT
;
175 if ( nWinStatus
& PRINTER_STATUS_USER_INTERVENTION
)
176 nStatus
|= QUEUE_STATUS_USER_INTERVENTION
;
177 if ( nWinStatus
& PRINTER_STATUS_OUT_OF_MEMORY
)
178 nStatus
|= QUEUE_STATUS_OUT_OF_MEMORY
;
179 if ( nWinStatus
& PRINTER_STATUS_DOOR_OPEN
)
180 nStatus
|= QUEUE_STATUS_DOOR_OPEN
;
181 if ( nWinStatus
& PRINTER_STATUS_SERVER_UNKNOWN
)
182 nStatus
|= QUEUE_STATUS_SERVER_UNKNOWN
;
183 if ( nWinStatus
& PRINTER_STATUS_POWER_SAVE
)
184 nStatus
|= QUEUE_STATUS_POWER_SAVE
;
185 if ( !nStatus
&& !(nWinStatus
& PRINTER_STATUS_NOT_AVAILABLE
) )
186 nStatus
|= QUEUE_STATUS_READY
;
190 // -----------------------------------------------------------------------
192 static void getPrinterQueueInfoOldStyle( ImplPrnQueueList
* pList
)
199 PRINTER_INFO_2
* pWinInfo2
= NULL
;
200 PRINTER_INFO_2
* pGetInfo2
;
201 EnumPrintersA( PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &nBytes
, &nInfoPrn2
);
204 pWinInfo2
= (PRINTER_INFO_2
*) rtl_allocateMemory( nBytes
);
205 if ( EnumPrintersA( PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pWinInfo2
, nBytes
, &nBytes
, &nInfoPrn2
) )
207 pGetInfo2
= pWinInfo2
;
208 for ( i
= 0; i
< nInfoPrn2
; i
++ )
210 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
211 pInfo
->maPrinterName
= ImplSalGetUniString( pGetInfo2
->pPrinterName
);
212 pInfo
->maDriver
= ImplSalGetUniString( pGetInfo2
->pDriverName
);
214 if ( pGetInfo2
->pPortName
)
215 aPortName
= ImplSalGetUniString( pGetInfo2
->pPortName
);
216 // pLocation can be 0 (the Windows docu doesn't describe this)
217 if ( pGetInfo2
->pLocation
&& strlen( pGetInfo2
->pLocation
) )
218 pInfo
->maLocation
= ImplSalGetUniString( pGetInfo2
->pLocation
);
220 pInfo
->maLocation
= aPortName
;
221 // pComment can be 0 (the Windows docu doesn't describe this)
222 if ( pGetInfo2
->pComment
)
223 pInfo
->maComment
= ImplSalGetUniString( pGetInfo2
->pComment
);
224 pInfo
->mnStatus
= ImplWinQueueStatusToSal( pGetInfo2
->Status
);
225 pInfo
->mnJobs
= pGetInfo2
->cJobs
;
226 pInfo
->mpSysData
= new XubString( aPortName
);
235 // read printers from win.ini
236 // TODO: MSDN: GetProfileString() should not be called from server
237 // code because it is just there for WIN16 compatibility
239 char* pBuf
= new char[nSize
];
240 UINT nRead
= GetProfileStringA( aImplDevices
, NULL
, "", pBuf
, nSize
);
241 while ( nRead
>= nSize
-2 )
245 pBuf
= new char[nSize
];
246 nRead
= GetProfileStringA( aImplDevices
, NULL
, "", pBuf
, nSize
);
249 // extract printer names from buffer and fill list
256 GetProfileStringA( aImplDevices
, pName
, "", aPortBuf
, sizeof( aPortBuf
) );
258 pPortName
= aPortBuf
;
261 xub_StrLen nNameLen
= sal::static_int_cast
<xub_StrLen
>(strlen( pName
));
262 XubString
aName( ImplSalGetUniString( pName
, nNameLen
) );
266 while ( *pTmp
!= ',' )
268 XubString
aDriver( ImplSalGetUniString( pPortName
, (USHORT
)(pTmp
-pPortName
) ) );
276 while ( *pTmp
&& (*pTmp
!= ',') )
279 String
aPortName( ImplSalGetUniString( pPortName
, (USHORT
)(pTmp
-pPortName
) ) );
282 // look up if printer was already found in first loop
286 pGetInfo2
= pWinInfo2
;
287 for ( n
= 0; n
< nInfoPrn2
; n
++ )
289 if ( aName
.EqualsIgnoreCaseAscii( pGetInfo2
->pPrinterName
) )
297 // if it's a new printer, add it
300 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
301 pInfo
->maPrinterName
= aName
;
302 pInfo
->maDriver
= aDriver
;
303 pInfo
->maLocation
= aPortName
;
305 pInfo
->mnJobs
= QUEUE_JOBS_DONTKNOW
;
306 pInfo
->mpSysData
= new XubString( aPortName
);
310 while ( *pTmp
== ',' );
312 pName
+= nNameLen
+ 1;
316 rtl_freeMemory( pWinInfo2
);
319 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
321 if( ! aSalShlData
.mbWPrinter
)
323 getPrinterQueueInfoOldStyle( pList
);
329 PRINTER_INFO_4W
* pWinInfo4
= NULL
;
330 EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, NULL
, 0, &nBytes
, &nInfoPrn4
);
333 pWinInfo4
= (PRINTER_INFO_4W
*) rtl_allocateMemory( nBytes
);
334 if ( EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, (LPBYTE
)pWinInfo4
, nBytes
, &nBytes
, &nInfoPrn4
) )
336 for ( i
= 0; i
< nInfoPrn4
; i
++ )
338 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
339 pInfo
->maPrinterName
= UniString( reinterpret_cast< const sal_Unicode
* >(pWinInfo4
[i
].pPrinterName
) );
342 pInfo
->mpSysData
= NULL
;
346 rtl_freeMemory( pWinInfo4
);
350 // -----------------------------------------------------------------------
352 static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo
* pInfo
)
356 PRINTER_INFO_2
* pWinInfo2
;
357 EnumPrintersA( PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &nBytes
, &nInfoRet
);
360 pWinInfo2
= (PRINTER_INFO_2
*) rtl_allocateMemory( nBytes
);
361 if ( EnumPrintersA( PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pWinInfo2
, nBytes
, &nBytes
, &nInfoRet
) )
363 PRINTER_INFO_2
* pGetInfo2
= pWinInfo2
;
364 for ( DWORD i
= 0; i
< nInfoRet
; i
++ )
366 if ( pInfo
->maPrinterName
.EqualsAscii( pGetInfo2
->pPrinterName
) &&
367 ( pInfo
->maDriver
.Len() == 0 ||
368 pInfo
->maDriver
.EqualsAscii( pGetInfo2
->pDriverName
) )
372 if ( pGetInfo2
->pPortName
)
373 aPortName
= ImplSalGetUniString( pGetInfo2
->pPortName
);
374 // pLocation can be 0 (the Windows docu doesn't describe this)
375 if ( pGetInfo2
->pLocation
&& strlen( pGetInfo2
->pLocation
) )
376 pInfo
->maLocation
= ImplSalGetUniString( pGetInfo2
->pLocation
);
378 pInfo
->maLocation
= aPortName
;
379 // pComment can be 0 (the Windows docu doesn't describe this)
380 if ( pGetInfo2
->pComment
)
381 pInfo
->maComment
= ImplSalGetUniString( pGetInfo2
->pComment
);
382 pInfo
->mnStatus
= ImplWinQueueStatusToSal( pGetInfo2
->Status
);
383 pInfo
->mnJobs
= pGetInfo2
->cJobs
;
384 if( ! pInfo
->mpSysData
)
385 pInfo
->mpSysData
= new XubString( aPortName
);
393 rtl_freeMemory( pWinInfo2
);
397 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* pInfo
)
399 if( ! aSalShlData
.mbWPrinter
)
401 getPrinterQueueStateOldStyle( pInfo
);
406 LPWSTR pPrnName
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pInfo
->maPrinterName
.GetBuffer()));
407 if( OpenPrinterW( pPrnName
, &hPrinter
, NULL
) )
410 GetPrinterW( hPrinter
, 2, NULL
, 0, &nBytes
);
413 PRINTER_INFO_2W
* pWinInfo2
= (PRINTER_INFO_2W
*)rtl_allocateMemory(nBytes
);
414 if( GetPrinterW( hPrinter
, 2, (LPBYTE
)pWinInfo2
, nBytes
, &nBytes
) )
416 if( pWinInfo2
->pDriverName
)
417 pInfo
->maDriver
= String( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pDriverName
) );
419 if ( pWinInfo2
->pPortName
)
420 aPortName
= String( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pPortName
) );
421 // pLocation can be 0 (the Windows docu doesn't describe this)
422 if ( pWinInfo2
->pLocation
&& *pWinInfo2
->pLocation
)
423 pInfo
->maLocation
= String( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pLocation
) );
425 pInfo
->maLocation
= aPortName
;
426 // pComment can be 0 (the Windows docu doesn't describe this)
427 if ( pWinInfo2
->pComment
)
428 pInfo
->maComment
= String( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pComment
) );
429 pInfo
->mnStatus
= ImplWinQueueStatusToSal( pWinInfo2
->Status
);
430 pInfo
->mnJobs
= pWinInfo2
->cJobs
;
431 if( ! pInfo
->mpSysData
)
432 pInfo
->mpSysData
= new XubString( aPortName
);
434 rtl_freeMemory(pWinInfo2
);
436 ClosePrinter( hPrinter
);
440 // -----------------------------------------------------------------------
442 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
444 delete (String
*)(pInfo
->mpSysData
);
448 // -----------------------------------------------------------------------
449 XubString
WinSalInstance::GetDefaultPrinter()
451 static bool bGetDefPrtAPI
= true;
452 static BOOL(WINAPI
*pGetDefaultPrinter
)(LPWSTR
,LPDWORD
) = NULL
;
453 // try to use GetDefaultPrinter API (not available prior to W2000)
456 bGetDefPrtAPI
= false;
457 // check for W2k and XP
458 if( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&& aSalShlData
.maVersionInfo
.dwMajorVersion
>= 5 )
460 OUString
aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "winspool.drv" ) );
461 oslModule pLib
= osl_loadModule( aLibraryName
.pData
, SAL_LOADMODULE_DEFAULT
);
462 oslGenericFunction pFunc
= NULL
;
465 OUString
queryFuncName( RTL_CONSTASCII_USTRINGPARAM( "GetDefaultPrinterW" ) );
466 pFunc
= osl_getFunctionSymbol( pLib
, queryFuncName
.pData
);
469 pGetDefaultPrinter
= (BOOL(WINAPI
*)(LPWSTR
,LPDWORD
)) pFunc
;
472 if( pGetDefaultPrinter
)
475 pGetDefaultPrinter( NULL
, &nChars
);
478 LPWSTR pStr
= (LPWSTR
)rtl_allocateMemory(nChars
*sizeof(WCHAR
));
480 if( pGetDefaultPrinter( pStr
, &nChars
) )
482 aDefPrt
= reinterpret_cast<sal_Unicode
* >(pStr
);
484 rtl_freeMemory( pStr
);
490 // get default printer from win.ini
492 GetProfileStringA( aImplWindows
, aImplDevice
, "", szBuffer
, sizeof( szBuffer
) );
495 // Printername suchen
496 char* pBuf
= szBuffer
;
498 while ( *pTmp
&& (*pTmp
!= ',') )
500 return ImplSalGetUniString( pBuf
, (xub_StrLen
)(pTmp
-pBuf
) );
506 // =======================================================================
508 static DWORD
ImplDeviceCaps( WinSalInfoPrinter
* pPrinter
, WORD nCaps
,
509 BYTE
* pOutput
, const ImplJobSetup
* pSetupData
)
511 if( aSalShlData
.mbWPrinter
)
514 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
517 pDevMode
= SAL_DEVMODE_W( pSetupData
);
519 return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR
>(pPrinter
->maDeviceName
.GetBuffer()),
520 reinterpret_cast<LPCWSTR
>(pPrinter
->maPortName
.GetBuffer()),
521 nCaps
, (LPWSTR
)pOutput
, pDevMode
);
526 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
529 pDevMode
= SAL_DEVMODE_A( pSetupData
);
531 return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
).GetBuffer(),
532 ImplSalGetWinAnsiString( pPrinter
->maPortName
, TRUE
).GetBuffer(),
533 nCaps
, (LPSTR
)pOutput
, pDevMode
);
537 // -----------------------------------------------------------------------
539 static BOOL
ImplTestSalJobSetup( WinSalInfoPrinter
* pPrinter
,
540 ImplJobSetup
* pSetupData
, BOOL bDelete
)
542 if ( pSetupData
&& pSetupData
->mpDriverData
)
544 // signature and size must fit to avoid using
545 // JobSetups from a wrong system
547 // initialize versions from jobsetup
548 // those will be overwritten with driver's version
549 DEVMODEA
* pDevModeA
= NULL
;
550 DEVMODEW
* pDevModeW
= NULL
;
551 LONG dmSpecVersion
= -1;
552 LONG dmDriverVersion
= -1;
553 SalDriverData
* pSalDriverData
= (SalDriverData
*)pSetupData
->mpDriverData
;
554 BYTE
* pDriverData
= ((BYTE
*)pSalDriverData
) + pSalDriverData
->mnDriverOffset
;
555 if( pSalDriverData
->mnVersion
== SAL_DRIVERDATA_VERSION_W
)
557 if( aSalShlData
.mbWPrinter
)
558 pDevModeW
= (DEVMODEW
*)pDriverData
;
560 else if( pSalDriverData
->mnVersion
== SAL_DRIVERDATA_VERSION_A
)
562 if( ! aSalShlData
.mbWPrinter
)
563 pDevModeA
= (DEVMODEA
*)pDriverData
;
566 long nSysJobSize
= -1;
567 if( pPrinter
&& ( pDevModeA
|| pDevModeW
) )
569 // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
570 // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
571 // can avoid potential driver crashes as their jobsetups are often not compatible
572 // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
573 ByteString aPrinterNameA
= ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
);
575 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.GetBuffer()));
576 if ( ! aSalShlData
.mbWPrinter
)
578 if ( !OpenPrinterA( (LPSTR
)aPrinterNameA
.GetBuffer(), &hPrn
, NULL
) )
582 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
585 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
586 if( hPrn
== HGDI_ERROR
)
589 if( aSalShlData
.mbWPrinter
)
591 nSysJobSize
= DocumentPropertiesW( 0, hPrn
,
597 nSysJobSize
= DocumentPropertiesA( 0, hPrn
,
598 (LPSTR
)aPrinterNameA
.GetBuffer(),
602 if( nSysJobSize
< 0 )
604 ClosePrinter( hPrn
);
607 BYTE
*pBuffer
= (BYTE
*)_alloca( nSysJobSize
);
609 if( aSalShlData
.mbWPrinter
)
611 nRet
= DocumentPropertiesW( 0, hPrn
,
613 (LPDEVMODEW
)pBuffer
, NULL
, DM_OUT_BUFFER
);
617 nRet
= DocumentPropertiesA( 0, hPrn
,
618 (LPSTR
)aPrinterNameA
.GetBuffer(),
619 (LPDEVMODEA
)pBuffer
, NULL
, DM_OUT_BUFFER
);
623 ClosePrinter( hPrn
);
627 // the spec version differs between the windows platforms, ie 98,NT,2000/XP
628 // this allows us to throw away printer settings from other platforms that might crash a buggy driver
629 // we check the driver version as well
630 dmSpecVersion
= aSalShlData
.mbWPrinter
? ((DEVMODEW
*)pBuffer
)->dmSpecVersion
: ((DEVMODEA
*)pBuffer
)->dmSpecVersion
;
631 dmDriverVersion
= aSalShlData
.mbWPrinter
? ((DEVMODEW
*)pBuffer
)->dmDriverVersion
: ((DEVMODEA
*)pBuffer
)->dmDriverVersion
;
633 ClosePrinter( hPrn
);
635 SalDriverData
* pSetupDriverData
= (SalDriverData
*)(pSetupData
->mpDriverData
);
636 if ( (pSetupData
->mnSystem
== JOBSETUP_SYSTEM_WINDOWS
) &&
637 (pPrinter
->maDriverName
== pSetupData
->maDriver
) &&
638 (pSetupData
->mnDriverDataLen
> sizeof( SalDriverData
)) &&
639 (long)(pSetupData
->mnDriverDataLen
- pSetupDriverData
->mnDriverOffset
) == nSysJobSize
&&
640 pSetupDriverData
->mnSysSignature
== SAL_DRIVERDATA_SYSSIGN
)
643 (dmSpecVersion
== pDevModeA
->dmSpecVersion
) &&
644 (dmDriverVersion
== pDevModeA
->dmDriverVersion
) )
647 (dmSpecVersion
== pDevModeW
->dmSpecVersion
) &&
648 (dmDriverVersion
== pDevModeW
->dmDriverVersion
) )
653 rtl_freeMemory( pSetupData
->mpDriverData
);
654 pSetupData
->mpDriverData
= NULL
;
655 pSetupData
->mnDriverDataLen
= 0;
662 // -----------------------------------------------------------------------
664 static BOOL
ImplUpdateSalJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
,
665 BOOL bIn
, WinSalFrame
* pVisibleDlgParent
)
667 ByteString aPrinterNameA
= ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
);
669 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.GetBuffer()));
670 if( aSalShlData
.mbWPrinter
)
672 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
677 if ( !OpenPrinterA( (LPSTR
)aPrinterNameA
.GetBuffer(), &hPrn
, NULL
) )
680 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
681 if( hPrn
== HGDI_ERROR
)
685 LONG nSysJobSize
= -1;
687 DWORD nMode
= DM_OUT_BUFFER
;
688 ULONG nDriverDataLen
= 0;
689 SalDriverData
* pOutBuffer
= NULL
;
690 BYTE
* pInBuffer
= NULL
;
692 if( aSalShlData
.mbWPrinter
)
694 nSysJobSize
= DocumentPropertiesW( hWnd
, hPrn
,
699 nSysJobSize
= DocumentPropertiesA( hWnd
, hPrn
,
700 (LPSTR
)ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
).GetBuffer(),
702 if ( nSysJobSize
< 0 )
704 ClosePrinter( hPrn
);
708 // Outputbuffer anlegen
709 nDriverDataLen
= sizeof(SalDriverData
) + nSysJobSize
-1;
710 pOutBuffer
= (SalDriverData
*)rtl_allocateZeroMemory( nDriverDataLen
);
711 pOutBuffer
->mnSysSignature
= SAL_DRIVERDATA_SYSSIGN
;
712 pOutBuffer
->mnVersion
= aSalShlData
.mbWPrinter
? SAL_DRIVERDATA_VERSION_W
: SAL_DRIVERDATA_VERSION_A
;
713 // calculate driver data offset including structure padding
714 pOutBuffer
->mnDriverOffset
= sal::static_int_cast
<USHORT
>(
715 (char*)pOutBuffer
->maDriverData
-
718 // Testen, ob wir einen geeigneten Inputbuffer haben
719 if ( bIn
&& ImplTestSalJobSetup( pPrinter
, pSetupData
, FALSE
) )
721 pInBuffer
= (BYTE
*)pSetupData
->mpDriverData
+ ((SalDriverData
*)pSetupData
->mpDriverData
)->mnDriverOffset
;
722 nMode
|= DM_IN_BUFFER
;
725 // Testen, ob Dialog angezeigt werden soll
726 if ( pVisibleDlgParent
)
728 hWnd
= pVisibleDlgParent
->mhWnd
;
729 nMode
|= DM_IN_PROMPT
;
732 // Release mutex, in the other case we don't get paints and so on
734 if ( pVisibleDlgParent
)
735 nMutexCount
= ImplSalReleaseYieldMutex();
737 BYTE
* pOutDevMode
= (((BYTE
*)pOutBuffer
) + pOutBuffer
->mnDriverOffset
);
738 if( aSalShlData
.mbWPrinter
)
740 nRet
= DocumentPropertiesW( hWnd
, hPrn
,
742 (LPDEVMODEW
)pOutDevMode
, (LPDEVMODEW
)pInBuffer
, nMode
);
746 nRet
= DocumentPropertiesA( hWnd
, hPrn
,
747 (LPSTR
)ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
).GetBuffer(),
748 (LPDEVMODEA
)pOutDevMode
, (LPDEVMODEA
)pInBuffer
, nMode
);
750 if ( pVisibleDlgParent
)
751 ImplSalAcquireYieldMutex( nMutexCount
);
752 ClosePrinter( hPrn
);
754 if( (nRet
< 0) || (pVisibleDlgParent
&& (nRet
== IDCANCEL
)) )
756 rtl_freeMemory( pOutBuffer
);
760 // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
761 if( aSalShlData
.mbWPrinter
)
763 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 64 )
765 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
);
766 if ( nLen
< sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
)/sizeof(sal_Unicode
) )
767 memset( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
)-(nLen
*sizeof(sal_Unicode
)) );
769 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 166 )
771 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmFormName
);
772 if ( nLen
< sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
)/sizeof(sal_Unicode
) )
773 memset( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
)-(nLen
*sizeof(sal_Unicode
)) );
778 if( ((LPDEVMODEA
)pOutDevMode
)->dmSize
>= 32 )
780 sal_Int32 nLen
= strlen( (const char*)((LPDEVMODEA
)pOutDevMode
)->dmDeviceName
);
781 if ( nLen
< sizeof( ((LPDEVMODEA
)pOutDevMode
)->dmDeviceName
) )
782 memset( ((LPDEVMODEA
)pOutDevMode
)->dmDeviceName
+nLen
, 0, sizeof( ((LPDEVMODEA
)pOutDevMode
)->dmDeviceName
)-nLen
);
784 if( ((LPDEVMODEA
)pOutDevMode
)->dmSize
>= 102 )
786 sal_Int32 nLen
= strlen( (const char*)((LPDEVMODEA
)pOutDevMode
)->dmFormName
);
787 if ( nLen
< sizeof( ((LPDEVMODEA
)pOutDevMode
)->dmFormName
) )
788 memset( ((LPDEVMODEA
)pOutDevMode
)->dmFormName
+nLen
, 0, sizeof( ((LPDEVMODEA
)pOutDevMode
)->dmFormName
)-nLen
);
793 if ( pSetupData
->mpDriverData
)
794 rtl_freeMemory( pSetupData
->mpDriverData
);
795 pSetupData
->mnDriverDataLen
= nDriverDataLen
;
796 pSetupData
->mpDriverData
= (BYTE
*)pOutBuffer
;
797 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
802 // -----------------------------------------------------------------------
804 #define DECLARE_DEVMODE( i )\
805 DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\
806 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
807 if( pDevModeA == NULL && pDevModeW == NULL )\
810 #define CHOOSE_DEVMODE(i)\
811 (pDevModeW ? pDevModeW->i : pDevModeA->i)
813 static void ImplDevModeToJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, ULONG nFlags
)
815 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
818 DECLARE_DEVMODE( pSetupData
);
821 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
823 if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_PORTRAIT
)
824 pSetupData
->meOrientation
= ORIENTATION_PORTRAIT
;
825 else if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_LANDSCAPE
)
826 pSetupData
->meOrientation
= ORIENTATION_LANDSCAPE
;
830 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
832 ULONG nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
834 if ( nCount
&& (nCount
!= GDI_ERROR
) )
836 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory( nCount
*sizeof(WORD
) );
837 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
838 pSetupData
->mnPaperBin
= 0;
840 // search the right bin and assign index to mnPaperBin
841 for( ULONG i
= 0; i
< nCount
; i
++ )
843 if( CHOOSE_DEVMODE(dmDefaultSource
) == pBins
[ i
] )
845 pSetupData
->mnPaperBin
= (USHORT
)i
;
850 rtl_freeMemory( pBins
);
855 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
857 if( (CHOOSE_DEVMODE(dmFields
) & (DM_PAPERWIDTH
|DM_PAPERLENGTH
)) == (DM_PAPERWIDTH
|DM_PAPERLENGTH
) )
859 pSetupData
->mnPaperWidth
= CHOOSE_DEVMODE(dmPaperWidth
)*10;
860 pSetupData
->mnPaperHeight
= CHOOSE_DEVMODE(dmPaperLength
)*10;
864 ULONG nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
865 WORD
* pPapers
= NULL
;
866 ULONG nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
867 POINT
* pPaperSizes
= NULL
;
868 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
870 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
871 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
873 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
875 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
876 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
878 if( nPaperSizeCount
== nPaperCount
&& pPaperSizes
&& pPapers
)
880 for( ULONG i
= 0; i
< nPaperCount
; i
++ )
882 if( pPapers
[ i
] == CHOOSE_DEVMODE(dmPaperSize
) )
884 pSetupData
->mnPaperWidth
= pPaperSizes
[ i
].x
*10;
885 pSetupData
->mnPaperHeight
= pPaperSizes
[ i
].y
*10;
891 rtl_freeMemory( pPapers
);
893 rtl_freeMemory( pPaperSizes
);
895 switch( CHOOSE_DEVMODE(dmPaperSize
) )
897 case( DMPAPER_LETTER
):
898 pSetupData
->mePaperFormat
= PAPER_LETTER
;
900 case( DMPAPER_TABLOID
):
901 pSetupData
->mePaperFormat
= PAPER_TABLOID
;
903 case( DMPAPER_LEDGER
):
904 pSetupData
->mePaperFormat
= PAPER_LEDGER
;
906 case( DMPAPER_LEGAL
):
907 pSetupData
->mePaperFormat
= PAPER_LEGAL
;
909 case( DMPAPER_STATEMENT
):
910 pSetupData
->mePaperFormat
= PAPER_STATEMENT
;
912 case( DMPAPER_EXECUTIVE
):
913 pSetupData
->mePaperFormat
= PAPER_EXECUTIVE
;
916 pSetupData
->mePaperFormat
= PAPER_A3
;
919 pSetupData
->mePaperFormat
= PAPER_A4
;
922 pSetupData
->mePaperFormat
= PAPER_A5
;
924 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
926 //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
927 //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
928 //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
929 //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
930 //matches our Excel filter's belief about the matching XlPaperSize
933 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
934 ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
935 //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
938 pSetupData
->mePaperFormat
= PAPER_B4_JIS
;
941 pSetupData
->mePaperFormat
= PAPER_B5_JIS
;
943 case( DMPAPER_QUARTO
):
944 pSetupData
->mePaperFormat
= PAPER_QUARTO
;
946 case( DMPAPER_10X14
):
947 pSetupData
->mePaperFormat
= PAPER_10x14
;
949 case( DMPAPER_NOTE
):
950 pSetupData
->mePaperFormat
= PAPER_LETTER
;
952 case( DMPAPER_ENV_9
):
953 pSetupData
->mePaperFormat
= PAPER_ENV_9
;
955 case( DMPAPER_ENV_10
):
956 pSetupData
->mePaperFormat
= PAPER_ENV_10
;
958 case( DMPAPER_ENV_11
):
959 pSetupData
->mePaperFormat
= PAPER_ENV_11
;
961 case( DMPAPER_ENV_12
):
962 pSetupData
->mePaperFormat
= PAPER_ENV_12
;
964 case( DMPAPER_ENV_14
):
965 pSetupData
->mePaperFormat
= PAPER_ENV_14
;
967 case( DMPAPER_CSHEET
):
968 pSetupData
->mePaperFormat
= PAPER_C
;
970 case( DMPAPER_DSHEET
):
971 pSetupData
->mePaperFormat
= PAPER_D
;
973 case( DMPAPER_ESHEET
):
974 pSetupData
->mePaperFormat
= PAPER_E
;
976 case( DMPAPER_ENV_DL
):
977 pSetupData
->mePaperFormat
= PAPER_ENV_DL
;
979 case( DMPAPER_ENV_C5
):
980 pSetupData
->mePaperFormat
= PAPER_ENV_C5
;
982 case( DMPAPER_ENV_C3
):
983 pSetupData
->mePaperFormat
= PAPER_ENV_C3
;
985 case( DMPAPER_ENV_C4
):
986 pSetupData
->mePaperFormat
= PAPER_ENV_C4
;
988 case( DMPAPER_ENV_C6
):
989 pSetupData
->mePaperFormat
= PAPER_ENV_C6
;
991 case( DMPAPER_ENV_C65
):
992 pSetupData
->mePaperFormat
= PAPER_ENV_C65
;
994 case( DMPAPER_ENV_ITALY
):
995 pSetupData
->mePaperFormat
= PAPER_ENV_ITALY
;
997 case( DMPAPER_ENV_MONARCH
):
998 pSetupData
->mePaperFormat
= PAPER_ENV_MONARCH
;
1000 case( DMPAPER_ENV_PERSONAL
):
1001 pSetupData
->mePaperFormat
= PAPER_ENV_PERSONAL
;
1003 case( DMPAPER_FANFOLD_US
):
1004 pSetupData
->mePaperFormat
= PAPER_FANFOLD_US
;
1006 case( DMPAPER_FANFOLD_STD_GERMAN
):
1007 pSetupData
->mePaperFormat
= PAPER_FANFOLD_DE
;
1009 case( DMPAPER_FANFOLD_LGL_GERMAN
):
1010 pSetupData
->mePaperFormat
= PAPER_FANFOLD_LEGAL_DE
;
1012 case( DMPAPER_ISO_B4
):
1013 pSetupData
->mePaperFormat
= PAPER_B4_ISO
;
1015 case( DMPAPER_JAPANESE_POSTCARD
):
1016 pSetupData
->mePaperFormat
= PAPER_POSTCARD_JP
;
1018 case( DMPAPER_9X11
):
1019 pSetupData
->mePaperFormat
= PAPER_9x11
;
1021 case( DMPAPER_10X11
):
1022 pSetupData
->mePaperFormat
= PAPER_10x11
;
1024 case( DMPAPER_15X11
):
1025 pSetupData
->mePaperFormat
= PAPER_15x11
;
1027 case( DMPAPER_ENV_INVITE
):
1028 pSetupData
->mePaperFormat
= PAPER_ENV_INVITE
;
1030 case( DMPAPER_A_PLUS
):
1031 pSetupData
->mePaperFormat
= PAPER_A_PLUS
;
1033 case( DMPAPER_B_PLUS
):
1034 pSetupData
->mePaperFormat
= PAPER_B_PLUS
;
1036 case( DMPAPER_LETTER_PLUS
):
1037 pSetupData
->mePaperFormat
= PAPER_LETTER_PLUS
;
1039 case( DMPAPER_A4_PLUS
):
1040 pSetupData
->mePaperFormat
= PAPER_A4_PLUS
;
1043 pSetupData
->mePaperFormat
= PAPER_A2
;
1045 case( DMPAPER_DBL_JAPANESE_POSTCARD
):
1046 pSetupData
->mePaperFormat
= PAPER_DOUBLEPOSTCARD_JP
;
1049 pSetupData
->mePaperFormat
= PAPER_A6
;
1051 case( DMPAPER_B6_JIS
):
1052 pSetupData
->mePaperFormat
= PAPER_B6_JIS
;
1054 case( DMPAPER_12X11
):
1055 pSetupData
->mePaperFormat
= PAPER_12x11
;
1058 pSetupData
->mePaperFormat
= PAPER_USER
;
1064 // -----------------------------------------------------------------------
1066 static void ImplJobSetupToDevMode( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, ULONG nFlags
)
1068 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
1071 DECLARE_DEVMODE( pSetupData
);
1074 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
1076 CHOOSE_DEVMODE(dmFields
) |= DM_ORIENTATION
;
1077 if ( pSetupData
->meOrientation
== ORIENTATION_PORTRAIT
)
1078 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_PORTRAIT
;
1080 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_LANDSCAPE
;
1084 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
1086 ULONG nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
1088 if ( nCount
&& (nCount
!= GDI_ERROR
) )
1090 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory(nCount
*sizeof(WORD
));
1091 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
1092 CHOOSE_DEVMODE(dmFields
) |= DM_DEFAULTSOURCE
;
1093 CHOOSE_DEVMODE(dmDefaultSource
) = pBins
[ pSetupData
->mnPaperBin
];
1094 rtl_freeMemory( pBins
);
1099 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
1101 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERSIZE
;
1102 CHOOSE_DEVMODE(dmPaperWidth
) = 0;
1103 CHOOSE_DEVMODE(dmPaperLength
) = 0;
1105 switch( pSetupData
->mePaperFormat
)
1108 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A2
;
1111 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A3
;
1114 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4
;
1117 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A5
;
1119 case( PAPER_B4_ISO
):
1120 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ISO_B4
;
1122 case( PAPER_LETTER
):
1123 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER
;
1125 case( PAPER_LEGAL
):
1126 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEGAL
;
1128 case( PAPER_TABLOID
):
1129 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_TABLOID
;
1132 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
1133 //DMPAPER_ENV_B6 is documented as:
1134 //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
1135 //which is the wrong way around, it is surely 125 x 176, i.e.
1136 //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
1137 //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
1138 //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
1139 case( PAPER_B6_ISO
):
1140 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_B6
;
1143 case( PAPER_ENV_C4
):
1144 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C4
;
1146 case( PAPER_ENV_C5
):
1147 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C5
;
1149 case( PAPER_ENV_C6
):
1150 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C6
;
1152 case( PAPER_ENV_C65
):
1153 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C65
;
1155 case( PAPER_ENV_DL
):
1156 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_DL
;
1159 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_CSHEET
;
1162 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DSHEET
;
1165 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ESHEET
;
1167 case( PAPER_EXECUTIVE
):
1168 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_EXECUTIVE
;
1170 case( PAPER_FANFOLD_LEGAL_DE
):
1171 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_LGL_GERMAN
;
1173 case( PAPER_ENV_MONARCH
):
1174 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_MONARCH
;
1176 case( PAPER_ENV_PERSONAL
):
1177 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_PERSONAL
;
1179 case( PAPER_ENV_9
):
1180 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_9
;
1182 case( PAPER_ENV_10
):
1183 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_10
;
1185 case( PAPER_ENV_11
):
1186 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_11
;
1188 case( PAPER_ENV_12
):
1189 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_12
;
1191 //See the comments on DMPAPER_B4 above
1192 case( PAPER_B4_JIS
):
1193 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B4
;
1195 case( PAPER_B5_JIS
):
1196 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B5
;
1198 case( PAPER_B6_JIS
):
1199 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B6_JIS
;
1201 case( PAPER_LEDGER
):
1202 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEDGER
;
1204 case( PAPER_STATEMENT
):
1205 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_STATEMENT
;
1207 case( PAPER_10x14
):
1208 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X14
;
1210 case( PAPER_ENV_14
):
1211 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_14
;
1213 case( PAPER_ENV_C3
):
1214 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C3
;
1216 case( PAPER_ENV_ITALY
):
1217 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_ITALY
;
1219 case( PAPER_FANFOLD_US
):
1220 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_US
;
1222 case( PAPER_FANFOLD_DE
):
1223 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_STD_GERMAN
;
1225 case( PAPER_POSTCARD_JP
):
1226 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_JAPANESE_POSTCARD
;
1229 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_9X11
;
1231 case( PAPER_10x11
):
1232 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X11
;
1234 case( PAPER_15x11
):
1235 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_15X11
;
1237 case( PAPER_ENV_INVITE
):
1238 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_INVITE
;
1240 case( PAPER_A_PLUS
):
1241 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A_PLUS
;
1243 case( PAPER_B_PLUS
):
1244 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B_PLUS
;
1246 case( PAPER_LETTER_PLUS
):
1247 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER_PLUS
;
1249 case( PAPER_A4_PLUS
):
1250 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4_PLUS
;
1252 case( PAPER_DOUBLEPOSTCARD_JP
):
1253 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DBL_JAPANESE_POSTCARD
;
1256 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A6
;
1258 case( PAPER_12x11
):
1259 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_12X11
;
1264 ULONG nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
1265 WORD
* pPapers
= NULL
;
1266 ULONG nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
1267 POINT
* pPaperSizes
= NULL
;
1268 DWORD nLandscapeAngle
= ImplDeviceCaps( pPrinter
, DC_ORIENTATION
, NULL
, pSetupData
);
1269 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
1271 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
1272 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
1274 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
1276 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
1277 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
1279 if ( (nPaperSizeCount
== nPaperCount
) && pPapers
&& pPaperSizes
)
1281 PaperInfo
aInfo(pSetupData
->mnPaperWidth
, pSetupData
->mnPaperHeight
);
1282 // compare paper formats and select a good match
1283 for ( ULONG i
= 0; i
< nPaperCount
; i
++ )
1285 if ( aInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)))
1287 nPaper
= pPapers
[i
];
1292 // If the printer supports landscape orientation, check paper sizes again
1293 // with landscape orientation. This is necessary as a printer driver provides
1294 // all paper sizes with portrait orientation only!!
1295 if ( !nPaper
&& nLandscapeAngle
!= 0 )
1297 PaperInfo
aRotatedInfo(pSetupData
->mnPaperHeight
, pSetupData
->mnPaperWidth
);
1298 for ( ULONG i
= 0; i
< nPaperCount
; i
++ )
1300 if ( aRotatedInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)) )
1302 nPaper
= pPapers
[i
];
1309 CHOOSE_DEVMODE(dmPaperSize
) = nPaper
;
1314 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERLENGTH
| DM_PAPERWIDTH
;
1315 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_USER
;
1316 CHOOSE_DEVMODE(dmPaperWidth
) = (short)(pSetupData
->mnPaperWidth
/10);
1317 CHOOSE_DEVMODE(dmPaperLength
) = (short)(pSetupData
->mnPaperHeight
/10);
1321 rtl_freeMemory(pPapers
);
1323 rtl_freeMemory(pPaperSizes
);
1331 // -----------------------------------------------------------------------
1333 static HDC
ImplCreateICW_WithCatch( LPWSTR pDriver
,
1335 LPDEVMODEW pDevMode
)
1338 CATCH_DRIVER_EX_BEGIN
;
1339 hDC
= CreateICW( pDriver
, pDevice
, 0, pDevMode
);
1340 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1344 static HDC
ImplCreateICA_WithCatch( char* pDriver
,
1346 LPDEVMODEA pDevMode
)
1349 CATCH_DRIVER_EX_BEGIN
;
1350 hDC
= CreateICA( pDriver
, pDevice
, 0, pDevMode
);
1351 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1356 static HDC
ImplCreateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1359 if( aSalShlData
.mbWPrinter
)
1361 LPDEVMODEW pDevMode
;
1362 if ( pSetupData
&& pSetupData
->mpDriverData
)
1363 pDevMode
= SAL_DEVMODE_W( pSetupData
);
1366 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1367 // pl: does this hold true for Unicode functions ?
1368 if( pPrinter
->maDriverName
.Len() > 2048 || pPrinter
->maDeviceName
.Len() > 2048 )
1370 sal_Unicode pDriverName
[ 4096 ];
1371 sal_Unicode pDeviceName
[ 4096 ];
1372 rtl_copyMemory( pDriverName
, pPrinter
->maDriverName
.GetBuffer(), pPrinter
->maDriverName
.Len()*sizeof(sal_Unicode
));
1373 memset( pDriverName
+pPrinter
->maDriverName
.Len(), 0, 32 );
1374 rtl_copyMemory( pDeviceName
, pPrinter
->maDeviceName
.GetBuffer(), pPrinter
->maDeviceName
.Len()*sizeof(sal_Unicode
));
1375 memset( pDeviceName
+pPrinter
->maDeviceName
.Len(), 0, 32 );
1376 hDC
= ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR
>(pDriverName
),
1377 reinterpret_cast< LPCWSTR
>(pDeviceName
),
1382 LPDEVMODEA pDevMode
;
1383 if ( pSetupData
&& pSetupData
->mpDriverData
)
1384 pDevMode
= SAL_DEVMODE_A( pSetupData
);
1387 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1388 ByteString
aDriver ( ImplSalGetWinAnsiString( pPrinter
->maDriverName
, TRUE
) );
1389 ByteString
aDevice ( ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
) );
1390 int n
= aDriver
.Len() > aDevice
.Len() ? aDriver
.Len() : aDevice
.Len();
1391 // #125813# under some circumstances many printer drivers really
1392 // seem to have a problem with the names and their conversions.
1393 // We need to get on to of this, but haven't been able to reproduce
1394 // the problem yet. Put the names on the stack so we get them
1395 // with an eventual crash report.
1399 char lpszDriverName
[ 4096 ];
1400 char lpszDeviceName
[ 4096 ];
1401 strncpy( lpszDriverName
, aDriver
.GetBuffer(), n
);
1402 strncpy( lpszDeviceName
, aDevice
.GetBuffer(), n
);
1403 // HDU: the crashes usually happen in a MBCS to unicode conversion,
1404 // so I suspect the MBCS string's end is not properly recognized.
1405 // The longest MBCS encoding I'm aware of has six bytes per code
1406 // => add a couple of zeroes...
1407 memset( lpszDriverName
+aDriver
.Len(), 0, 16 );
1408 memset( lpszDeviceName
+aDevice
.Len(), 0, 16 );
1409 hDC
= ImplCreateICA_WithCatch( lpszDriverName
,
1416 // -----------------------------------------------------------------------
1418 static WinSalGraphics
* ImplCreateSalPrnGraphics( HDC hDC
)
1420 WinSalGraphics
* pGraphics
= new WinSalGraphics
;
1421 pGraphics
->SetLayout( 0 );
1422 pGraphics
->mhDC
= hDC
;
1423 pGraphics
->mhWnd
= 0;
1424 pGraphics
->mbPrinter
= TRUE
;
1425 pGraphics
->mbVirDev
= FALSE
;
1426 pGraphics
->mbWindow
= FALSE
;
1427 pGraphics
->mbScreen
= FALSE
;
1428 ImplSalInitGraphics( pGraphics
);
1432 // -----------------------------------------------------------------------
1434 static BOOL
ImplUpdateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1436 HDC hNewDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1440 if ( pPrinter
->mpGraphics
)
1442 ImplSalDeInitGraphics( pPrinter
->mpGraphics
);
1443 DeleteDC( pPrinter
->mpGraphics
->mhDC
);
1444 delete pPrinter
->mpGraphics
;
1447 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hNewDC
);
1448 pPrinter
->mhDC
= hNewDC
;
1453 // =======================================================================
1455 SalInfoPrinter
* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
1456 ImplJobSetup
* pSetupData
)
1458 WinSalInfoPrinter
* pPrinter
= new WinSalInfoPrinter
;
1459 if( ! pQueueInfo
->mpSysData
)
1460 GetPrinterQueueState( pQueueInfo
);
1461 pPrinter
->maDriverName
= pQueueInfo
->maDriver
;
1462 pPrinter
->maDeviceName
= pQueueInfo
->maPrinterName
;
1463 pPrinter
->maPortName
= pQueueInfo
->mpSysData
?
1464 *(String
*)(pQueueInfo
->mpSysData
)
1467 // check if the provided setup data match the actual printer
1468 ImplTestSalJobSetup( pPrinter
, pSetupData
, TRUE
);
1470 HDC hDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1477 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
1478 pPrinter
->mhDC
= hDC
;
1479 if ( !pSetupData
->mpDriverData
)
1480 ImplUpdateSalJobSetup( pPrinter
, pSetupData
, FALSE
, NULL
);
1481 ImplDevModeToJobSetup( pPrinter
, pSetupData
, SAL_JOBSET_ALL
);
1482 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
1487 // -----------------------------------------------------------------------
1489 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
1494 // =======================================================================
1496 WinSalInfoPrinter::WinSalInfoPrinter() :
1501 m_bPapersInit
= FALSE
;
1504 // -----------------------------------------------------------------------
1506 WinSalInfoPrinter::~WinSalInfoPrinter()
1510 ImplSalDeInitGraphics( mpGraphics
);
1511 DeleteDC( mpGraphics
->mhDC
);
1516 // -----------------------------------------------------------------------
1518 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup
* pSetupData
)
1520 m_aPaperFormats
.clear();
1522 DWORD nCount
= ImplDeviceCaps( this, DC_PAPERSIZE
, NULL
, pSetupData
);
1523 if( nCount
== GDI_ERROR
)
1526 POINT
* pPaperSizes
= NULL
;
1529 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nCount
*sizeof(POINT
));
1530 ImplDeviceCaps( this, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
1532 if( aSalShlData
.mbWPrinter
)
1534 sal_Unicode
* pNamesBuffer
= (sal_Unicode
*)rtl_allocateMemory(nCount
*64*sizeof(sal_Unicode
));
1535 ImplDeviceCaps( this, DC_PAPERNAMES
, (BYTE
*)pNamesBuffer
, pSetupData
);
1536 for( DWORD i
= 0; i
< nCount
; ++i
)
1538 PaperInfo
aInfo(pPaperSizes
[i
].x
* 10, pPaperSizes
[i
].y
* 10);
1539 m_aPaperFormats
.push_back( aInfo
);
1541 rtl_freeMemory( pNamesBuffer
);
1545 char* pNamesBuffer
= (char*)rtl_allocateMemory(nCount
*64);
1546 ImplDeviceCaps( this, DC_PAPERNAMES
, (BYTE
*)pNamesBuffer
, pSetupData
);
1547 for( DWORD i
= 0; i
< nCount
; ++i
)
1549 PaperInfo
aInfo(pPaperSizes
[i
].x
* 10, pPaperSizes
[i
].y
* 10);
1550 m_aPaperFormats
.push_back( aInfo
);
1552 rtl_freeMemory( pNamesBuffer
);
1554 rtl_freeMemory( pPaperSizes
);
1557 m_bPapersInit
= true;
1560 // -----------------------------------------------------------------------
1562 DuplexMode
WinSalInfoPrinter::GetDuplexMode( const ImplJobSetup
* pSetupData
)
1564 DuplexMode nRet
= DUPLEX_UNKNOWN
;
1565 if ( pSetupData
&&pSetupData
->mpDriverData
)
1567 if( aSalShlData
.mbWPrinter
)
1569 DEVMODEW
* pDevMode
= SAL_DEVMODE_W( pSetupData
);
1570 if ( pDevMode
&& (pDevMode
->dmFields
& DM_DUPLEX
))
1572 if ( pDevMode
->dmDuplex
== DMDUP_SIMPLEX
)
1580 DEVMODEA
* pDevMode
= SAL_DEVMODE_A( pSetupData
);
1581 if ( pDevMode
&& (pDevMode
->dmFields
& DM_DUPLEX
))
1583 if ( pDevMode
->dmDuplex
== DMDUP_SIMPLEX
)
1593 // -----------------------------------------------------------------------
1595 int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup
* pSetupData
)
1597 int nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1599 if( nRet
!= GDI_ERROR
)
1602 return 900; // guess
1605 // -----------------------------------------------------------------------
1607 SalGraphics
* WinSalInfoPrinter::GetGraphics()
1618 // -----------------------------------------------------------------------
1620 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics
* )
1625 // -----------------------------------------------------------------------
1627 BOOL
WinSalInfoPrinter::Setup( SalFrame
* pFrame
, ImplJobSetup
* pSetupData
)
1629 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, static_cast<WinSalFrame
*>(pFrame
) ) )
1631 ImplDevModeToJobSetup( this, pSetupData
, SAL_JOBSET_ALL
);
1632 return ImplUpdateSalPrnIC( this, pSetupData
);
1638 // -----------------------------------------------------------------------
1640 BOOL
WinSalInfoPrinter::SetPrinterData( ImplJobSetup
* pSetupData
)
1642 if ( !ImplTestSalJobSetup( this, pSetupData
, FALSE
) )
1644 return ImplUpdateSalPrnIC( this, pSetupData
);
1647 // -----------------------------------------------------------------------
1649 BOOL
WinSalInfoPrinter::SetData( ULONG nFlags
, ImplJobSetup
* pSetupData
)
1651 ImplJobSetupToDevMode( this, pSetupData
, nFlags
);
1652 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, NULL
) )
1654 ImplDevModeToJobSetup( this, pSetupData
, nFlags
);
1655 return ImplUpdateSalPrnIC( this, pSetupData
);
1661 // -----------------------------------------------------------------------
1663 ULONG
WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pSetupData
)
1665 DWORD nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1666 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1672 // -----------------------------------------------------------------------
1674 XubString
WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup
* pSetupData
, ULONG nPaperBin
)
1676 XubString aPaperBinName
;
1678 DWORD nBins
= ImplDeviceCaps( this, DC_BINNAMES
, NULL
, pSetupData
);
1679 if ( (nPaperBin
< nBins
) && (nBins
!= GDI_ERROR
) )
1681 if( aSalShlData
.mbWPrinter
)
1683 sal_Unicode
* pBuffer
= new sal_Unicode
[nBins
*24];
1684 DWORD nRet
= ImplDeviceCaps( this, DC_BINNAMES
, (BYTE
*)pBuffer
, pSetupData
);
1685 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1686 aPaperBinName
= pBuffer
+ (nPaperBin
*24);
1691 char* pBuffer
= new char[nBins
*24];
1692 DWORD nRet
= ImplDeviceCaps( this, DC_BINNAMES
, (BYTE
*)pBuffer
, pSetupData
);
1693 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1694 aPaperBinName
= ImplSalGetUniString( (const char*)(pBuffer
+ (nPaperBin
*24)) );
1699 return aPaperBinName
;
1702 // -----------------------------------------------------------------------
1704 ULONG
WinSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pSetupData
, USHORT nType
)
1710 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
1712 case PRINTER_CAPABILITIES_COPIES
:
1713 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1714 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1717 case PRINTER_CAPABILITIES_COLLATECOPIES
:
1718 if ( aSalShlData
.mbW40
)
1720 nRet
= ImplDeviceCaps( this, DC_COLLATE
, NULL
, pSetupData
);
1721 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1723 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1724 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1730 case PRINTER_CAPABILITIES_SETORIENTATION
:
1731 nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1732 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1736 case PRINTER_CAPABILITIES_SETPAPERBIN
:
1737 nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1738 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1742 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
1743 case PRINTER_CAPABILITIES_SETPAPER
:
1744 nRet
= ImplDeviceCaps( this, DC_PAPERS
, NULL
, pSetupData
);
1745 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1753 // -----------------------------------------------------------------------
1755 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup
*,
1756 long& rOutWidth
, long& rOutHeight
,
1757 long& rPageOffX
, long& rPageOffY
,
1758 long& rPageWidth
, long& rPageHeight
)
1762 rOutWidth
= GetDeviceCaps( hDC
, HORZRES
);
1763 rOutHeight
= GetDeviceCaps( hDC
, VERTRES
);
1765 rPageOffX
= GetDeviceCaps( hDC
, PHYSICALOFFSETX
);
1766 rPageOffY
= GetDeviceCaps( hDC
, PHYSICALOFFSETY
);
1767 rPageWidth
= GetDeviceCaps( hDC
, PHYSICALWIDTH
);
1768 rPageHeight
= GetDeviceCaps( hDC
, PHYSICALHEIGHT
);
1771 // =======================================================================
1773 SalPrinter
* WinSalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
1775 WinSalPrinter
* pPrinter
= new WinSalPrinter
;
1776 pPrinter
->mpInfoPrinter
= static_cast<WinSalInfoPrinter
*>(pInfoPrinter
);
1780 // -----------------------------------------------------------------------
1782 void WinSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
1787 // =======================================================================
1789 WIN_BOOL CALLBACK
SalPrintAbortProc( HDC hPrnDC
, int /* nError */ )
1791 SalData
* pSalData
= GetSalData();
1792 WinSalPrinter
* pPrinter
;
1798 // Messages verarbeiten
1800 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1802 TranslateMessage( &aMsg
);
1803 ImplDispatchMessage( &aMsg
);
1811 pPrinter
= pSalData
->mpFirstPrinter
;
1814 if( pPrinter
->mhDC
== hPrnDC
)
1817 pPrinter
= pPrinter
->mpNextPrinter
;
1820 if ( !pPrinter
|| pPrinter
->mbAbort
)
1828 // -----------------------------------------------------------------------
1830 static LPDEVMODEA
ImplSalSetCopies( LPDEVMODEA pDevMode
, ULONG nCopies
, BOOL bCollate
)
1832 LPDEVMODEA pNewDevMode
= pDevMode
;
1833 if ( pDevMode
&& (nCopies
> 1) )
1835 if ( nCopies
> 32765 )
1837 ULONG nDevSize
= pDevMode
->dmSize
+pDevMode
->dmDriverExtra
;
1838 pNewDevMode
= (LPDEVMODEA
)rtl_allocateMemory( nDevSize
);
1839 memcpy( pNewDevMode
, pDevMode
, nDevSize
);
1840 pDevMode
= pNewDevMode
;
1841 pDevMode
->dmFields
|= DM_COPIES
;
1842 pDevMode
->dmCopies
= (short)(USHORT
)nCopies
;
1843 if ( aSalShlData
.mbW40
)
1845 pDevMode
->dmFields
|= DM_COLLATE
;
1847 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1849 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
1856 static LPDEVMODEW
ImplSalSetCopies( LPDEVMODEW pDevMode
, ULONG nCopies
, BOOL bCollate
)
1858 LPDEVMODEW pNewDevMode
= pDevMode
;
1859 if ( pDevMode
&& (nCopies
> 1) )
1861 if ( nCopies
> 32765 )
1863 ULONG nDevSize
= pDevMode
->dmSize
+pDevMode
->dmDriverExtra
;
1864 pNewDevMode
= (LPDEVMODEW
)rtl_allocateMemory( nDevSize
);
1865 memcpy( pNewDevMode
, pDevMode
, nDevSize
);
1866 pDevMode
= pNewDevMode
;
1867 pDevMode
->dmFields
|= DM_COPIES
;
1868 pDevMode
->dmCopies
= (short)(USHORT
)nCopies
;
1869 if ( aSalShlData
.mbW40
)
1871 pDevMode
->dmFields
|= DM_COLLATE
;
1873 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1875 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
1882 // -----------------------------------------------------------------------
1884 WinSalPrinter::WinSalPrinter() :
1886 mpInfoPrinter( NULL
),
1887 mpNextPrinter( NULL
),
1895 SalData
* pSalData
= GetSalData();
1896 // insert printer in printerlist
1897 mpNextPrinter
= pSalData
->mpFirstPrinter
;
1898 pSalData
->mpFirstPrinter
= this;
1901 // -----------------------------------------------------------------------
1903 WinSalPrinter::~WinSalPrinter()
1905 SalData
* pSalData
= GetSalData();
1907 // release DC if there is one still around because of AbortJob
1913 ImplSalDeInitGraphics( mpGraphics
);
1920 // remove printer from printerlist
1921 if ( this == pSalData
->mpFirstPrinter
)
1922 pSalData
->mpFirstPrinter
= mpNextPrinter
;
1925 WinSalPrinter
* pTempPrinter
= pSalData
->mpFirstPrinter
;
1927 while( pTempPrinter
->mpNextPrinter
!= this )
1928 pTempPrinter
= pTempPrinter
->mpNextPrinter
;
1930 pTempPrinter
->mpNextPrinter
= mpNextPrinter
;
1935 // -----------------------------------------------------------------------
1937 void WinSalPrinter::markInvalid()
1942 // -----------------------------------------------------------------------
1944 // need wrappers for StarTocW/A to use structured exception handling
1945 // since SEH does not mix with standard exception handling's cleanup
1946 static int lcl_StartDocW( HDC hDC
, DOCINFOW
* pInfo
, WinSalPrinter
* pPrt
)
1949 CATCH_DRIVER_EX_BEGIN
;
1950 nRet
= ::StartDocW( hDC
, pInfo
);
1951 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1955 static int lcl_StartDocA( HDC hDC
, DOCINFOA
* pInfo
, WinSalPrinter
* pPrt
)
1958 CATCH_DRIVER_EX_BEGIN
;
1959 nRet
= ::StartDocA( hDC
, pInfo
);
1960 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1964 BOOL
WinSalPrinter::StartJob( const XubString
* pFileName
,
1965 const XubString
& rJobName
,
1967 ULONG nCopies
, BOOL bCollate
,
1968 ImplJobSetup
* pSetupData
)
1973 mbCollate
= bCollate
;
1975 LPDEVMODEA pOrgDevModeA
= NULL
;
1976 LPDEVMODEA pDevModeA
= NULL
;
1977 LPDEVMODEW pOrgDevModeW
= NULL
;
1978 LPDEVMODEW pDevModeW
= NULL
;
1980 if( aSalShlData
.mbWPrinter
)
1982 if ( pSetupData
&& pSetupData
->mpDriverData
)
1984 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1985 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, nCopies
, bCollate
);
1990 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1991 sal_Unicode aDrvBuf
[4096];
1992 sal_Unicode aDevBuf
[4096];
1993 rtl_copyMemory( aDrvBuf
, mpInfoPrinter
->maDriverName
.GetBuffer(), (mpInfoPrinter
->maDriverName
.Len()+1)*sizeof(sal_Unicode
));
1994 rtl_copyMemory( aDevBuf
, mpInfoPrinter
->maDeviceName
.GetBuffer(), (mpInfoPrinter
->maDeviceName
.Len()+1)*sizeof(sal_Unicode
));
1995 hDC
= CreateDCW( reinterpret_cast<LPCWSTR
>(aDrvBuf
),
1996 reinterpret_cast<LPCWSTR
>(aDevBuf
),
2000 if ( pDevModeW
!= pOrgDevModeW
)
2001 rtl_freeMemory( pDevModeW
);
2005 if ( pSetupData
&& pSetupData
->mpDriverData
)
2007 pOrgDevModeA
= SAL_DEVMODE_A( pSetupData
);
2008 pDevModeA
= ImplSalSetCopies( pOrgDevModeA
, nCopies
, bCollate
);
2013 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
2014 ByteString
aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter
->maDriverName
, TRUE
) );
2015 ByteString
aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter
->maDeviceName
, TRUE
) );
2016 int n
= aDriver
.Len() > aDevice
.Len() ? aDriver
.Len() : aDevice
.Len();
2018 char *lpszDriverName
= new char[n
];
2019 char *lpszDeviceName
= new char[n
];
2020 strncpy( lpszDriverName
, aDriver
.GetBuffer(), n
);
2021 strncpy( lpszDeviceName
, aDevice
.GetBuffer(), n
);
2022 hDC
= CreateDCA( lpszDriverName
,
2027 delete [] lpszDriverName
;
2028 delete [] lpszDeviceName
;
2030 if ( pDevModeA
!= pOrgDevModeA
)
2031 rtl_freeMemory( pDevModeA
);
2036 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2040 // make sure mhDC is set before the printer driver may call our abortproc
2042 if ( SetAbortProc( hDC
, SalPrintAbortProc
) <= 0 )
2044 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2051 // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages
2052 // ansonsten oefters schickt, versuchen wir vorher alle
2053 // zu verarbeiten und dann eine Dummy-Message reinstellen
2058 // Messages verarbeiten
2060 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
2062 TranslateMessage( &aMsg
);
2063 ImplDispatchMessage( &aMsg
);
2072 ImplPostMessage( GetSalData()->mpFirstInstance
->mhComWnd
, SAL_MSG_DUMMY
, 0, 0 );
2074 // bring up a file choser if printing to file port but no file name given
2075 OUString aOutFileName
;
2076 if( mpInfoPrinter
->maPortName
.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName
&& pFileName
->Len()) )
2079 Reference
< XMultiServiceFactory
> xFactory( ::comphelper::getProcessServiceFactory() );
2082 Reference
< XFilePicker
> xFilePicker( xFactory
->createInstance(
2083 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
2085 DBG_ASSERT( xFilePicker
.is(), "could not get FilePicker service" );
2087 Reference
< XInitialization
> xInit( xFilePicker
, UNO_QUERY
);
2088 Reference
< XFilterManager
> xFilterMgr( xFilePicker
, UNO_QUERY
);
2089 if( xInit
.is() && xFilePicker
.is() && xFilterMgr
.is() )
2091 Sequence
< Any
> aServiceType( 1 );
2092 aServiceType
[0] <<= TemplateDescription::FILESAVE_SIMPLE
;
2093 xInit
->initialize( aServiceType
);
2094 if( xFilePicker
->execute() == ExecutableDialogResults::OK
)
2096 Sequence
< OUString
> aPathSeq( xFilePicker
->getFiles() );
2097 INetURLObject
aObj( aPathSeq
[0] );
2098 // we're using ansi calls (StartDocA) so convert the string
2099 aOutFileName
= aObj
.PathToFileName();
2103 mnError
= SAL_PRINTER_ERROR_ABORT
;
2110 if( aSalShlData
.mbWPrinter
)
2113 memset( &aInfo
, 0, sizeof( DOCINFOW
) );
2114 aInfo
.cbSize
= sizeof( aInfo
);
2115 aInfo
.lpszDocName
= (LPWSTR
)rJobName
.GetBuffer();
2116 if ( pFileName
|| aOutFileName
.getLength() )
2118 if ( (pFileName
&& pFileName
->Len()) || aOutFileName
.getLength() )
2120 aInfo
.lpszOutput
= (LPWSTR
)( (pFileName
&& pFileName
->Len()) ? pFileName
->GetBuffer() : aOutFileName
.getStr());
2123 aInfo
.lpszOutput
= L
"FILE:";
2126 aInfo
.lpszOutput
= NULL
;
2129 int nRet
= lcl_StartDocW( hDC
, &aInfo
, this );
2133 long nError
= GetLastError();
2134 if ( (nRet
== SP_USERABORT
) || (nRet
== SP_APPABORT
) || (nError
== ERROR_PRINT_CANCELLED
) || (nError
== ERROR_CANCELLED
) )
2135 mnError
= SAL_PRINTER_ERROR_ABORT
;
2137 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2143 // Both strings must exist, if StartJob() is called
2144 ByteString
aJobName( ImplSalGetWinAnsiString( rJobName
, TRUE
) );
2145 ByteString aFileName
;
2148 memset( &aInfo
, 0, sizeof( DOCINFOA
) );
2149 aInfo
.cbSize
= sizeof( aInfo
);
2150 aInfo
.lpszDocName
= (LPCSTR
)aJobName
.GetBuffer();
2151 if ( pFileName
|| aOutFileName
.getLength() )
2153 if ( pFileName
->Len() || aOutFileName
.getLength() )
2155 aFileName
= ImplSalGetWinAnsiString( pFileName
? *pFileName
: static_cast<const XubString
>(aOutFileName
), TRUE
);
2156 aInfo
.lpszOutput
= (LPCSTR
)aFileName
.GetBuffer();
2159 aInfo
.lpszOutput
= "FILE:";
2162 aInfo
.lpszOutput
= NULL
;
2165 int nRet
= lcl_StartDocA( hDC
, &aInfo
, this );
2168 long nError
= GetLastError();
2169 if ( (nRet
== SP_USERABORT
) || (nRet
== SP_APPABORT
) || (nError
== ERROR_PRINT_CANCELLED
) || (nError
== ERROR_CANCELLED
) )
2170 mnError
= SAL_PRINTER_ERROR_ABORT
;
2172 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2180 // -----------------------------------------------------------------------
2182 BOOL
WinSalPrinter::EndJob()
2186 if ( isValid() && hDC
)
2190 ImplSalDeInitGraphics( mpGraphics
);
2195 // #i54419# Windows fax printer brings up a dialog in EndDoc
2196 // which text previously copied in soffice process can be
2197 // pasted to -> deadlock due to mutex not released.
2198 // it should be safe to release the yield mutex over the EndDoc
2199 // call, however the real solution is supposed to be the threading
2200 // framework yet to come.
2201 SalData
* pSalData
= GetSalData();
2202 ULONG nAcquire
= pSalData
->mpFirstInstance
->ReleaseYieldMutex();
2203 CATCH_DRIVER_EX_BEGIN
;
2204 if( ::EndDoc( hDC
) <= 0 )
2205 err
= GetLastError();
2206 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
2208 pSalData
->mpFirstInstance
->AcquireYieldMutex( nAcquire
);
2216 // -----------------------------------------------------------------------
2218 BOOL
WinSalPrinter::AbortJob()
2222 // Abort asyncron ausloesen
2226 SalData
* pSalData
= GetSalData();
2227 ImplPostMessage( pSalData
->mpFirstInstance
->mhComWnd
,
2228 SAL_MSG_PRINTABORTJOB
, (WPARAM
)hDC
, 0 );
2234 // -----------------------------------------------------------------------
2236 void ImplSalPrinterAbortJobAsync( HDC hPrnDC
)
2238 SalData
* pSalData
= GetSalData();
2239 WinSalPrinter
* pPrinter
= pSalData
->mpFirstPrinter
;
2241 // Feststellen, ob Printer noch existiert
2244 if ( pPrinter
->mhDC
== hPrnDC
)
2247 pPrinter
= pPrinter
->mpNextPrinter
;
2250 // Wenn Printer noch existiert, dann den Job abbrechen
2253 HDC hDC
= pPrinter
->mhDC
;
2256 if ( pPrinter
->mpGraphics
)
2258 ImplSalDeInitGraphics( pPrinter
->mpGraphics
);
2259 delete pPrinter
->mpGraphics
;
2260 pPrinter
->mpGraphics
= NULL
;
2263 CATCH_DRIVER_EX_BEGIN
;
2265 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter
);
2273 // -----------------------------------------------------------------------
2275 SalGraphics
* WinSalPrinter::StartPage( ImplJobSetup
* pSetupData
, BOOL bNewJobData
)
2277 if( ! isValid() || mhDC
== 0 )
2281 if ( pSetupData
&& pSetupData
->mpDriverData
&& bNewJobData
)
2283 if( aSalShlData
.mbWPrinter
)
2285 LPDEVMODEW pOrgDevModeW
;
2286 LPDEVMODEW pDevModeW
;
2287 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
2288 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, mnCopies
, mbCollate
);
2289 ResetDCW( hDC
, pDevModeW
);
2290 if ( pDevModeW
!= pOrgDevModeW
)
2291 rtl_freeMemory( pDevModeW
);
2295 LPDEVMODEA pOrgDevModeA
;
2296 LPDEVMODEA pDevModeA
;
2297 pOrgDevModeA
= SAL_DEVMODE_A( pSetupData
);
2298 pDevModeA
= ImplSalSetCopies( pOrgDevModeA
, mnCopies
, mbCollate
);
2299 ResetDCA( hDC
, pDevModeA
);
2300 if ( pDevModeA
!= pOrgDevModeA
)
2301 rtl_freeMemory( pDevModeA
);
2305 CATCH_DRIVER_EX_BEGIN
;
2306 nRet
= ::StartPage( hDC
);
2307 CATCH_DRIVER_EX_END( "exception in StartPage", this );
2312 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2316 // Hack to work around old PostScript printer drivers optimizing away empty pages
2317 // TODO: move into ImplCreateSalPrnGraphics()?
2318 HPEN hTempPen
= SelectPen( hDC
, GetStockPen( NULL_PEN
) );
2319 HBRUSH hTempBrush
= SelectBrush( hDC
, GetStockBrush( NULL_BRUSH
) );
2320 WIN_Rectangle( hDC
, -8000, -8000, -7999, -7999 );
2321 SelectPen( hDC
, hTempPen
);
2322 SelectBrush( hDC
, hTempBrush
);
2324 mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
2328 // -----------------------------------------------------------------------
2330 BOOL
WinSalPrinter::EndPage()
2333 if ( hDC
&& mpGraphics
)
2335 ImplSalDeInitGraphics( mpGraphics
);
2344 CATCH_DRIVER_EX_BEGIN
;
2345 nRet
= ::EndPage( hDC
);
2346 CATCH_DRIVER_EX_END( "exception in EndPage", this );
2353 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2358 // -----------------------------------------------------------------------
2360 ULONG
WinSalPrinter::GetErrorCode()