1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
27 #include <osl/module.h>
29 #include <tools/urlobj.hxx>
31 #include <win/wincomp.hxx>
32 #include <win/saldata.hxx>
33 #include <win/salinst.h>
34 #include <win/salgdi.h>
35 #include <win/salframe.h>
36 #include <win/salprn.h>
38 #include <salptype.hxx>
42 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
43 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
44 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
45 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/lang/XInitialization.hpp>
48 #include <comphelper/processfactory.hxx>
53 #include <sehandler.hxx>
57 #define CATCH_DRIVER_EX_BEGIN \
60 if (__builtin_setjmp(jmpbuf) == 0) \
62 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
64 #define CATCH_DRIVER_EX_END(mes, p) \
67 #define CATCH_DRIVER_EX_END_2(mes) \
71 #define CATCH_DRIVER_EX_BEGIN \
74 #define CATCH_DRIVER_EX_END(mes, p) \
76 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
81 #define CATCH_DRIVER_EX_END_2(mes) \
83 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
90 using namespace com::sun::star
;
91 using namespace com::sun::star::uno
;
92 using namespace com::sun::star::lang
;
93 using namespace com::sun::star::ui::dialogs
;
95 // =======================================================================
97 static char aImplWindows
[] = "windows";
98 static char aImplDevice
[] = "device";
100 static LPDEVMODEW
SAL_DEVMODE_W( const ImplJobSetup
* pSetupData
)
102 LPDEVMODEW pRet
= NULL
;
103 SalDriverData
* pDrv
= (SalDriverData
*)pSetupData
->mpDriverData
;
104 if( pSetupData
->mnDriverDataLen
>= sizeof(DEVMODEW
)+sizeof(SalDriverData
)-1 )
105 pRet
= ((LPDEVMODEW
)((pSetupData
->mpDriverData
) + (pDrv
->mnDriverOffset
)));
109 // =======================================================================
111 static sal_uLong
ImplWinQueueStatusToSal( DWORD nWinStatus
)
113 sal_uLong nStatus
= 0;
114 if ( nWinStatus
& PRINTER_STATUS_PAUSED
)
115 nStatus
|= QUEUE_STATUS_PAUSED
;
116 if ( nWinStatus
& PRINTER_STATUS_ERROR
)
117 nStatus
|= QUEUE_STATUS_ERROR
;
118 if ( nWinStatus
& PRINTER_STATUS_PENDING_DELETION
)
119 nStatus
|= QUEUE_STATUS_PENDING_DELETION
;
120 if ( nWinStatus
& PRINTER_STATUS_PAPER_JAM
)
121 nStatus
|= QUEUE_STATUS_PAPER_JAM
;
122 if ( nWinStatus
& PRINTER_STATUS_PAPER_OUT
)
123 nStatus
|= QUEUE_STATUS_PAPER_OUT
;
124 if ( nWinStatus
& PRINTER_STATUS_MANUAL_FEED
)
125 nStatus
|= QUEUE_STATUS_MANUAL_FEED
;
126 if ( nWinStatus
& PRINTER_STATUS_PAPER_PROBLEM
)
127 nStatus
|= QUEUE_STATUS_PAPER_PROBLEM
;
128 if ( nWinStatus
& PRINTER_STATUS_OFFLINE
)
129 nStatus
|= QUEUE_STATUS_OFFLINE
;
130 if ( nWinStatus
& PRINTER_STATUS_IO_ACTIVE
)
131 nStatus
|= QUEUE_STATUS_IO_ACTIVE
;
132 if ( nWinStatus
& PRINTER_STATUS_BUSY
)
133 nStatus
|= QUEUE_STATUS_BUSY
;
134 if ( nWinStatus
& PRINTER_STATUS_PRINTING
)
135 nStatus
|= QUEUE_STATUS_PRINTING
;
136 if ( nWinStatus
& PRINTER_STATUS_OUTPUT_BIN_FULL
)
137 nStatus
|= QUEUE_STATUS_OUTPUT_BIN_FULL
;
138 if ( nWinStatus
& PRINTER_STATUS_WAITING
)
139 nStatus
|= QUEUE_STATUS_WAITING
;
140 if ( nWinStatus
& PRINTER_STATUS_PROCESSING
)
141 nStatus
|= QUEUE_STATUS_PROCESSING
;
142 if ( nWinStatus
& PRINTER_STATUS_INITIALIZING
)
143 nStatus
|= QUEUE_STATUS_INITIALIZING
;
144 if ( nWinStatus
& PRINTER_STATUS_WARMING_UP
)
145 nStatus
|= QUEUE_STATUS_WARMING_UP
;
146 if ( nWinStatus
& PRINTER_STATUS_TONER_LOW
)
147 nStatus
|= QUEUE_STATUS_TONER_LOW
;
148 if ( nWinStatus
& PRINTER_STATUS_NO_TONER
)
149 nStatus
|= QUEUE_STATUS_NO_TONER
;
150 if ( nWinStatus
& PRINTER_STATUS_PAGE_PUNT
)
151 nStatus
|= QUEUE_STATUS_PAGE_PUNT
;
152 if ( nWinStatus
& PRINTER_STATUS_USER_INTERVENTION
)
153 nStatus
|= QUEUE_STATUS_USER_INTERVENTION
;
154 if ( nWinStatus
& PRINTER_STATUS_OUT_OF_MEMORY
)
155 nStatus
|= QUEUE_STATUS_OUT_OF_MEMORY
;
156 if ( nWinStatus
& PRINTER_STATUS_DOOR_OPEN
)
157 nStatus
|= QUEUE_STATUS_DOOR_OPEN
;
158 if ( nWinStatus
& PRINTER_STATUS_SERVER_UNKNOWN
)
159 nStatus
|= QUEUE_STATUS_SERVER_UNKNOWN
;
160 if ( nWinStatus
& PRINTER_STATUS_POWER_SAVE
)
161 nStatus
|= QUEUE_STATUS_POWER_SAVE
;
162 if ( !nStatus
&& !(nWinStatus
& PRINTER_STATUS_NOT_AVAILABLE
) )
163 nStatus
|= QUEUE_STATUS_READY
;
167 // -----------------------------------------------------------------------
169 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
174 EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, NULL
, 0, &nBytes
, &nInfoPrn4
);
177 PRINTER_INFO_4W
* pWinInfo4
= (PRINTER_INFO_4W
*) rtl_allocateMemory( nBytes
);
178 if ( EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, (LPBYTE
)pWinInfo4
, nBytes
, &nBytes
, &nInfoPrn4
) )
180 for ( i
= 0; i
< nInfoPrn4
; i
++ )
182 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
183 pInfo
->maPrinterName
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo4
[i
].pPrinterName
) );
186 pInfo
->mpSysData
= NULL
;
190 rtl_freeMemory( pWinInfo4
);
194 // -----------------------------------------------------------------------
196 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* pInfo
)
199 LPWSTR pPrnName
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pInfo
->maPrinterName
.getStr()));
200 if( OpenPrinterW( pPrnName
, &hPrinter
, NULL
) )
203 GetPrinterW( hPrinter
, 2, NULL
, 0, &nBytes
);
206 PRINTER_INFO_2W
* pWinInfo2
= (PRINTER_INFO_2W
*)rtl_allocateMemory(nBytes
);
207 if( GetPrinterW( hPrinter
, 2, (LPBYTE
)pWinInfo2
, nBytes
, &nBytes
) )
209 if( pWinInfo2
->pDriverName
)
210 pInfo
->maDriver
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pDriverName
) );
212 if ( pWinInfo2
->pPortName
)
213 aPortName
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pPortName
) );
214 // pLocation can be 0 (the Windows docu doesn't describe this)
215 if ( pWinInfo2
->pLocation
&& *pWinInfo2
->pLocation
)
216 pInfo
->maLocation
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pLocation
) );
218 pInfo
->maLocation
= aPortName
;
219 // pComment can be 0 (the Windows docu doesn't describe this)
220 if ( pWinInfo2
->pComment
)
221 pInfo
->maComment
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pComment
) );
222 pInfo
->mnStatus
= ImplWinQueueStatusToSal( pWinInfo2
->Status
);
223 pInfo
->mnJobs
= pWinInfo2
->cJobs
;
224 if( ! pInfo
->mpSysData
)
225 pInfo
->mpSysData
= new OUString(aPortName
);
227 rtl_freeMemory(pWinInfo2
);
229 ClosePrinter( hPrinter
);
233 // -----------------------------------------------------------------------
235 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
237 delete pInfo
->mpSysData
;
241 // -----------------------------------------------------------------------
242 OUString
WinSalInstance::GetDefaultPrinter()
245 GetDefaultPrinterW( NULL
, &nChars
);
248 LPWSTR pStr
= (LPWSTR
)rtl_allocateMemory(nChars
*sizeof(WCHAR
));
250 if( GetDefaultPrinterW( pStr
, &nChars
) )
252 aDefPrt
= reinterpret_cast<sal_Unicode
* >(pStr
);
254 rtl_freeMemory( pStr
);
259 // get default printer from win.ini
261 GetProfileStringA( aImplWindows
, aImplDevice
, "", szBuffer
, sizeof( szBuffer
) );
264 // Printername suchen
265 char* pBuf
= szBuffer
;
267 while ( *pTmp
&& (*pTmp
!= ',') )
269 return ImplSalGetUniString( pBuf
, static_cast<sal_Int32
>(pTmp
-pBuf
) );
275 // =======================================================================
277 static DWORD
ImplDeviceCaps( WinSalInfoPrinter
* pPrinter
, WORD nCaps
,
278 BYTE
* pOutput
, const ImplJobSetup
* pSetupData
)
281 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
284 pDevMode
= SAL_DEVMODE_W( pSetupData
);
286 return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR
>(pPrinter
->maDeviceName
.getStr()),
287 reinterpret_cast<LPCWSTR
>(pPrinter
->maPortName
.getStr()),
288 nCaps
, (LPWSTR
)pOutput
, pDevMode
);
291 // -----------------------------------------------------------------------
293 static sal_Bool
ImplTestSalJobSetup( WinSalInfoPrinter
* pPrinter
,
294 ImplJobSetup
* pSetupData
, sal_Bool bDelete
)
296 if ( pSetupData
&& pSetupData
->mpDriverData
)
298 // signature and size must fit to avoid using
299 // JobSetups from a wrong system
301 // initialize versions from jobsetup
302 // those will be overwritten with driver's version
303 DEVMODEW
* pDevModeW
= NULL
;
304 LONG dmSpecVersion
= -1;
305 LONG dmDriverVersion
= -1;
306 SalDriverData
* pSalDriverData
= (SalDriverData
*)pSetupData
->mpDriverData
;
307 BYTE
* pDriverData
= ((BYTE
*)pSalDriverData
) + pSalDriverData
->mnDriverOffset
;
308 pDevModeW
= (DEVMODEW
*)pDriverData
;
310 long nSysJobSize
= -1;
311 if( pPrinter
&& pDevModeW
)
313 // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
314 // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
315 // can avoid potential driver crashes as their jobsetups are often not compatible
316 // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
318 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.getStr()));
319 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
322 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
323 if( hPrn
== HGDI_ERROR
)
326 nSysJobSize
= DocumentPropertiesW( 0, hPrn
,
330 if( nSysJobSize
< 0 )
332 ClosePrinter( hPrn
);
335 BYTE
*pBuffer
= (BYTE
*)_alloca( nSysJobSize
);
336 LONG nRet
= DocumentPropertiesW( 0, hPrn
,
338 (LPDEVMODEW
)pBuffer
, NULL
, DM_OUT_BUFFER
);
341 ClosePrinter( hPrn
);
345 // the spec version differs between the windows platforms, ie 98,NT,2000/XP
346 // this allows us to throw away printer settings from other platforms that might crash a buggy driver
347 // we check the driver version as well
348 dmSpecVersion
= ((DEVMODEW
*)pBuffer
)->dmSpecVersion
;
349 dmDriverVersion
= ((DEVMODEW
*)pBuffer
)->dmDriverVersion
;
351 ClosePrinter( hPrn
);
353 SalDriverData
* pSetupDriverData
= (SalDriverData
*)(pSetupData
->mpDriverData
);
354 if ( (pSetupData
->mnSystem
== JOBSETUP_SYSTEM_WINDOWS
) &&
355 (pPrinter
->maDriverName
== pSetupData
->maDriver
) &&
356 (pSetupData
->mnDriverDataLen
> sizeof( SalDriverData
)) &&
357 (long)(pSetupData
->mnDriverDataLen
- pSetupDriverData
->mnDriverOffset
) == nSysJobSize
&&
358 pSetupDriverData
->mnSysSignature
== SAL_DRIVERDATA_SYSSIGN
)
361 (dmSpecVersion
== pDevModeW
->dmSpecVersion
) &&
362 (dmDriverVersion
== pDevModeW
->dmDriverVersion
) )
367 rtl_freeMemory( pSetupData
->mpDriverData
);
368 pSetupData
->mpDriverData
= NULL
;
369 pSetupData
->mnDriverDataLen
= 0;
376 // -----------------------------------------------------------------------
378 static sal_Bool
ImplUpdateSalJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
,
379 sal_Bool bIn
, WinSalFrame
* pVisibleDlgParent
)
382 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.getStr()));
383 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
385 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
386 if( hPrn
== HGDI_ERROR
)
391 DWORD nMode
= DM_OUT_BUFFER
;
392 sal_uLong nDriverDataLen
= 0;
393 SalDriverData
* pOutBuffer
= NULL
;
394 BYTE
* pInBuffer
= NULL
;
396 LONG nSysJobSize
= DocumentPropertiesW( hWnd
, hPrn
,
399 if ( nSysJobSize
< 0 )
401 ClosePrinter( hPrn
);
406 nDriverDataLen
= sizeof(SalDriverData
) + nSysJobSize
-1;
407 pOutBuffer
= (SalDriverData
*)rtl_allocateZeroMemory( nDriverDataLen
);
408 pOutBuffer
->mnSysSignature
= SAL_DRIVERDATA_SYSSIGN
;
409 // calculate driver data offset including structure padding
410 pOutBuffer
->mnDriverOffset
= sal::static_int_cast
<sal_uInt16
>(
411 (char*)pOutBuffer
->maDriverData
-
414 // check if we have a suitable input buffer
415 if ( bIn
&& ImplTestSalJobSetup( pPrinter
, pSetupData
, FALSE
) )
417 pInBuffer
= (BYTE
*)pSetupData
->mpDriverData
+ ((SalDriverData
*)pSetupData
->mpDriverData
)->mnDriverOffset
;
418 nMode
|= DM_IN_BUFFER
;
421 // check if the dialog should be shown
422 if ( pVisibleDlgParent
)
424 hWnd
= pVisibleDlgParent
->mhWnd
;
425 nMode
|= DM_IN_PROMPT
;
428 // Release mutex, in the other case we don't get paints and so on
429 sal_uLong nMutexCount
=0;
430 if ( pVisibleDlgParent
)
431 nMutexCount
= ImplSalReleaseYieldMutex();
433 BYTE
* pOutDevMode
= (((BYTE
*)pOutBuffer
) + pOutBuffer
->mnDriverOffset
);
434 nRet
= DocumentPropertiesW( hWnd
, hPrn
,
436 (LPDEVMODEW
)pOutDevMode
, (LPDEVMODEW
)pInBuffer
, nMode
);
437 if ( pVisibleDlgParent
)
438 ImplSalAcquireYieldMutex( nMutexCount
);
439 ClosePrinter( hPrn
);
441 if( (nRet
< 0) || (pVisibleDlgParent
&& (nRet
== IDCANCEL
)) )
443 rtl_freeMemory( pOutBuffer
);
447 // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
448 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 64 )
450 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
);
451 if ( sal::static_int_cast
<size_t>(nLen
) < SAL_N_ELEMENTS( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
) )
452 memset( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
)-(nLen
*sizeof(sal_Unicode
)) );
454 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 166 )
456 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmFormName
);
457 if ( sal::static_int_cast
<size_t>(nLen
) < SAL_N_ELEMENTS( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
) )
458 memset( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
)-(nLen
*sizeof(sal_Unicode
)) );
462 if ( pSetupData
->mpDriverData
)
463 rtl_freeMemory( pSetupData
->mpDriverData
);
464 pSetupData
->mnDriverDataLen
= nDriverDataLen
;
465 pSetupData
->mpDriverData
= (BYTE
*)pOutBuffer
;
466 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
471 // -----------------------------------------------------------------------
473 #define DECLARE_DEVMODE( i )\
474 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
475 if( pDevModeW == NULL )\
478 #define CHOOSE_DEVMODE(i)\
481 static void ImplDevModeToJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, sal_uLong nFlags
)
483 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
486 DECLARE_DEVMODE( pSetupData
);
489 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
491 if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_PORTRAIT
)
492 pSetupData
->meOrientation
= ORIENTATION_PORTRAIT
;
493 else if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_LANDSCAPE
)
494 pSetupData
->meOrientation
= ORIENTATION_LANDSCAPE
;
498 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
500 sal_uLong nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
502 if ( nCount
&& (nCount
!= GDI_ERROR
) )
504 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory( nCount
*sizeof(WORD
) );
505 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
506 pSetupData
->mnPaperBin
= 0;
508 // search the right bin and assign index to mnPaperBin
509 for( sal_uLong i
= 0; i
< nCount
; i
++ )
511 if( CHOOSE_DEVMODE(dmDefaultSource
) == pBins
[ i
] )
513 pSetupData
->mnPaperBin
= (sal_uInt16
)i
;
518 rtl_freeMemory( pBins
);
523 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
525 if( (CHOOSE_DEVMODE(dmFields
) & (DM_PAPERWIDTH
|DM_PAPERLENGTH
)) == (DM_PAPERWIDTH
|DM_PAPERLENGTH
) )
527 pSetupData
->mnPaperWidth
= CHOOSE_DEVMODE(dmPaperWidth
)*10;
528 pSetupData
->mnPaperHeight
= CHOOSE_DEVMODE(dmPaperLength
)*10;
532 sal_uLong nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
533 WORD
* pPapers
= NULL
;
534 sal_uLong nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
535 POINT
* pPaperSizes
= NULL
;
536 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
538 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
539 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
541 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
543 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
544 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
546 if( nPaperSizeCount
== nPaperCount
&& pPaperSizes
&& pPapers
)
548 for( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
550 if( pPapers
[ i
] == CHOOSE_DEVMODE(dmPaperSize
) )
552 pSetupData
->mnPaperWidth
= pPaperSizes
[ i
].x
*10;
553 pSetupData
->mnPaperHeight
= pPaperSizes
[ i
].y
*10;
559 rtl_freeMemory( pPapers
);
561 rtl_freeMemory( pPaperSizes
);
563 switch( CHOOSE_DEVMODE(dmPaperSize
) )
565 case( DMPAPER_LETTER
):
566 pSetupData
->mePaperFormat
= PAPER_LETTER
;
568 case( DMPAPER_TABLOID
):
569 pSetupData
->mePaperFormat
= PAPER_TABLOID
;
571 case( DMPAPER_LEDGER
):
572 pSetupData
->mePaperFormat
= PAPER_LEDGER
;
574 case( DMPAPER_LEGAL
):
575 pSetupData
->mePaperFormat
= PAPER_LEGAL
;
577 case( DMPAPER_STATEMENT
):
578 pSetupData
->mePaperFormat
= PAPER_STATEMENT
;
580 case( DMPAPER_EXECUTIVE
):
581 pSetupData
->mePaperFormat
= PAPER_EXECUTIVE
;
584 pSetupData
->mePaperFormat
= PAPER_A3
;
587 pSetupData
->mePaperFormat
= PAPER_A4
;
590 pSetupData
->mePaperFormat
= PAPER_A5
;
592 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
594 //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
595 //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
596 //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
597 //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
598 //matches our Excel filter's belief about the matching XlPaperSize
601 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
602 ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
603 //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
606 pSetupData
->mePaperFormat
= PAPER_B4_JIS
;
609 pSetupData
->mePaperFormat
= PAPER_B5_JIS
;
611 case( DMPAPER_QUARTO
):
612 pSetupData
->mePaperFormat
= PAPER_QUARTO
;
614 case( DMPAPER_10X14
):
615 pSetupData
->mePaperFormat
= PAPER_10x14
;
617 case( DMPAPER_NOTE
):
618 pSetupData
->mePaperFormat
= PAPER_LETTER
;
620 case( DMPAPER_ENV_9
):
621 pSetupData
->mePaperFormat
= PAPER_ENV_9
;
623 case( DMPAPER_ENV_10
):
624 pSetupData
->mePaperFormat
= PAPER_ENV_10
;
626 case( DMPAPER_ENV_11
):
627 pSetupData
->mePaperFormat
= PAPER_ENV_11
;
629 case( DMPAPER_ENV_12
):
630 pSetupData
->mePaperFormat
= PAPER_ENV_12
;
632 case( DMPAPER_ENV_14
):
633 pSetupData
->mePaperFormat
= PAPER_ENV_14
;
635 case( DMPAPER_CSHEET
):
636 pSetupData
->mePaperFormat
= PAPER_C
;
638 case( DMPAPER_DSHEET
):
639 pSetupData
->mePaperFormat
= PAPER_D
;
641 case( DMPAPER_ESHEET
):
642 pSetupData
->mePaperFormat
= PAPER_E
;
644 case( DMPAPER_ENV_DL
):
645 pSetupData
->mePaperFormat
= PAPER_ENV_DL
;
647 case( DMPAPER_ENV_C5
):
648 pSetupData
->mePaperFormat
= PAPER_ENV_C5
;
650 case( DMPAPER_ENV_C3
):
651 pSetupData
->mePaperFormat
= PAPER_ENV_C3
;
653 case( DMPAPER_ENV_C4
):
654 pSetupData
->mePaperFormat
= PAPER_ENV_C4
;
656 case( DMPAPER_ENV_C6
):
657 pSetupData
->mePaperFormat
= PAPER_ENV_C6
;
659 case( DMPAPER_ENV_C65
):
660 pSetupData
->mePaperFormat
= PAPER_ENV_C65
;
662 case( DMPAPER_ENV_ITALY
):
663 pSetupData
->mePaperFormat
= PAPER_ENV_ITALY
;
665 case( DMPAPER_ENV_MONARCH
):
666 pSetupData
->mePaperFormat
= PAPER_ENV_MONARCH
;
668 case( DMPAPER_ENV_PERSONAL
):
669 pSetupData
->mePaperFormat
= PAPER_ENV_PERSONAL
;
671 case( DMPAPER_FANFOLD_US
):
672 pSetupData
->mePaperFormat
= PAPER_FANFOLD_US
;
674 case( DMPAPER_FANFOLD_STD_GERMAN
):
675 pSetupData
->mePaperFormat
= PAPER_FANFOLD_DE
;
677 case( DMPAPER_FANFOLD_LGL_GERMAN
):
678 pSetupData
->mePaperFormat
= PAPER_FANFOLD_LEGAL_DE
;
680 case( DMPAPER_ISO_B4
):
681 pSetupData
->mePaperFormat
= PAPER_B4_ISO
;
683 case( DMPAPER_JAPANESE_POSTCARD
):
684 pSetupData
->mePaperFormat
= PAPER_POSTCARD_JP
;
686 case( DMPAPER_9X11
):
687 pSetupData
->mePaperFormat
= PAPER_9x11
;
689 case( DMPAPER_10X11
):
690 pSetupData
->mePaperFormat
= PAPER_10x11
;
692 case( DMPAPER_15X11
):
693 pSetupData
->mePaperFormat
= PAPER_15x11
;
695 case( DMPAPER_ENV_INVITE
):
696 pSetupData
->mePaperFormat
= PAPER_ENV_INVITE
;
698 case( DMPAPER_A_PLUS
):
699 pSetupData
->mePaperFormat
= PAPER_A_PLUS
;
701 case( DMPAPER_B_PLUS
):
702 pSetupData
->mePaperFormat
= PAPER_B_PLUS
;
704 case( DMPAPER_LETTER_PLUS
):
705 pSetupData
->mePaperFormat
= PAPER_LETTER_PLUS
;
707 case( DMPAPER_A4_PLUS
):
708 pSetupData
->mePaperFormat
= PAPER_A4_PLUS
;
711 pSetupData
->mePaperFormat
= PAPER_A2
;
713 case( DMPAPER_DBL_JAPANESE_POSTCARD
):
714 pSetupData
->mePaperFormat
= PAPER_DOUBLEPOSTCARD_JP
;
717 pSetupData
->mePaperFormat
= PAPER_A6
;
719 case( DMPAPER_B6_JIS
):
720 pSetupData
->mePaperFormat
= PAPER_B6_JIS
;
722 case( DMPAPER_12X11
):
723 pSetupData
->mePaperFormat
= PAPER_12x11
;
726 pSetupData
->mePaperFormat
= PAPER_USER
;
731 if( nFlags
& SAL_JOBSET_DUPLEXMODE
)
733 DuplexMode eDuplex
= DUPLEX_UNKNOWN
;
734 if( (CHOOSE_DEVMODE(dmFields
) & DM_DUPLEX
) )
736 if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_SIMPLEX
)
737 eDuplex
= DUPLEX_OFF
;
738 else if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_VERTICAL
)
739 eDuplex
= DUPLEX_LONGEDGE
;
740 else if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_HORIZONTAL
)
741 eDuplex
= DUPLEX_SHORTEDGE
;
743 pSetupData
->meDuplexMode
= eDuplex
;
747 // -----------------------------------------------------------------------
749 static void ImplJobSetupToDevMode( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, sal_uLong nFlags
)
751 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
754 DECLARE_DEVMODE( pSetupData
);
757 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
759 CHOOSE_DEVMODE(dmFields
) |= DM_ORIENTATION
;
760 if ( pSetupData
->meOrientation
== ORIENTATION_PORTRAIT
)
761 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_PORTRAIT
;
763 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_LANDSCAPE
;
767 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
769 sal_uLong nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
771 if ( nCount
&& (nCount
!= GDI_ERROR
) )
773 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory(nCount
*sizeof(WORD
));
774 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
775 CHOOSE_DEVMODE(dmFields
) |= DM_DEFAULTSOURCE
;
776 CHOOSE_DEVMODE(dmDefaultSource
) = pBins
[ pSetupData
->mnPaperBin
];
777 rtl_freeMemory( pBins
);
782 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
784 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERSIZE
;
785 CHOOSE_DEVMODE(dmPaperWidth
) = 0;
786 CHOOSE_DEVMODE(dmPaperLength
) = 0;
788 switch( pSetupData
->mePaperFormat
)
791 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A2
;
794 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A3
;
797 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4
;
800 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A5
;
803 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ISO_B4
;
805 case( PAPER_LETTER
):
806 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER
;
809 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEGAL
;
811 case( PAPER_TABLOID
):
812 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_TABLOID
;
815 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
816 //DMPAPER_ENV_B6 is documented as:
817 //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
818 //which is the wrong way around, it is surely 125 x 176, i.e.
819 //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
820 //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
821 //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
822 case( PAPER_B6_ISO
):
823 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_B6
;
826 case( PAPER_ENV_C4
):
827 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C4
;
829 case( PAPER_ENV_C5
):
830 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C5
;
832 case( PAPER_ENV_C6
):
833 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C6
;
835 case( PAPER_ENV_C65
):
836 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C65
;
838 case( PAPER_ENV_DL
):
839 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_DL
;
842 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_CSHEET
;
845 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DSHEET
;
848 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ESHEET
;
850 case( PAPER_EXECUTIVE
):
851 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_EXECUTIVE
;
853 case( PAPER_FANFOLD_LEGAL_DE
):
854 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_LGL_GERMAN
;
856 case( PAPER_ENV_MONARCH
):
857 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_MONARCH
;
859 case( PAPER_ENV_PERSONAL
):
860 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_PERSONAL
;
863 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_9
;
865 case( PAPER_ENV_10
):
866 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_10
;
868 case( PAPER_ENV_11
):
869 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_11
;
871 case( PAPER_ENV_12
):
872 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_12
;
874 //See the comments on DMPAPER_B4 above
875 case( PAPER_B4_JIS
):
876 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B4
;
878 case( PAPER_B5_JIS
):
879 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B5
;
881 case( PAPER_B6_JIS
):
882 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B6_JIS
;
884 case( PAPER_LEDGER
):
885 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEDGER
;
887 case( PAPER_STATEMENT
):
888 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_STATEMENT
;
891 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X14
;
893 case( PAPER_ENV_14
):
894 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_14
;
896 case( PAPER_ENV_C3
):
897 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C3
;
899 case( PAPER_ENV_ITALY
):
900 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_ITALY
;
902 case( PAPER_FANFOLD_US
):
903 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_US
;
905 case( PAPER_FANFOLD_DE
):
906 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_STD_GERMAN
;
908 case( PAPER_POSTCARD_JP
):
909 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_JAPANESE_POSTCARD
;
912 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_9X11
;
915 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X11
;
918 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_15X11
;
920 case( PAPER_ENV_INVITE
):
921 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_INVITE
;
923 case( PAPER_A_PLUS
):
924 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A_PLUS
;
926 case( PAPER_B_PLUS
):
927 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B_PLUS
;
929 case( PAPER_LETTER_PLUS
):
930 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER_PLUS
;
932 case( PAPER_A4_PLUS
):
933 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4_PLUS
;
935 case( PAPER_DOUBLEPOSTCARD_JP
):
936 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DBL_JAPANESE_POSTCARD
;
939 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A6
;
942 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_12X11
;
947 sal_uLong nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
948 WORD
* pPapers
= NULL
;
949 sal_uLong nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
950 POINT
* pPaperSizes
= NULL
;
951 DWORD nLandscapeAngle
= ImplDeviceCaps( pPrinter
, DC_ORIENTATION
, NULL
, pSetupData
);
952 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
954 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
955 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
957 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
959 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
960 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
962 if ( (nPaperSizeCount
== nPaperCount
) && pPapers
&& pPaperSizes
)
964 PaperInfo
aInfo(pSetupData
->mnPaperWidth
, pSetupData
->mnPaperHeight
);
965 // compare paper formats and select a good match
966 for ( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
968 if ( aInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)))
975 // If the printer supports landscape orientation, check paper sizes again
976 // with landscape orientation. This is necessary as a printer driver provides
977 // all paper sizes with portrait orientation only!!
978 if ( !nPaper
&& nLandscapeAngle
!= 0 )
980 PaperInfo
aRotatedInfo(pSetupData
->mnPaperHeight
, pSetupData
->mnPaperWidth
);
981 for ( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
983 if ( aRotatedInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)) )
992 CHOOSE_DEVMODE(dmPaperSize
) = nPaper
;
997 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERLENGTH
| DM_PAPERWIDTH
;
998 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_USER
;
999 CHOOSE_DEVMODE(dmPaperWidth
) = (short)(pSetupData
->mnPaperWidth
/10);
1000 CHOOSE_DEVMODE(dmPaperLength
) = (short)(pSetupData
->mnPaperHeight
/10);
1004 rtl_freeMemory(pPapers
);
1006 rtl_freeMemory(pPaperSizes
);
1012 if( (nFlags
& SAL_JOBSET_DUPLEXMODE
) )
1014 switch( pSetupData
->meDuplexMode
)
1017 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1018 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_SIMPLEX
;
1020 case DUPLEX_SHORTEDGE
:
1021 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1022 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_HORIZONTAL
;
1024 case DUPLEX_LONGEDGE
:
1025 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1026 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_VERTICAL
;
1028 case DUPLEX_UNKNOWN
:
1034 // -----------------------------------------------------------------------
1036 static HDC
ImplCreateICW_WithCatch( LPWSTR pDriver
,
1038 LPDEVMODEW pDevMode
)
1041 CATCH_DRIVER_EX_BEGIN
;
1042 hDC
= CreateICW( pDriver
, pDevice
, 0, pDevMode
);
1043 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1047 static HDC
ImplCreateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1050 LPDEVMODEW pDevMode
;
1051 if ( pSetupData
&& pSetupData
->mpDriverData
)
1052 pDevMode
= SAL_DEVMODE_W( pSetupData
);
1055 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1056 // pl: does this hold true for Unicode functions ?
1057 if( pPrinter
->maDriverName
.getLength() > 2048 || pPrinter
->maDeviceName
.getLength() > 2048 )
1059 sal_Unicode pDriverName
[ 4096 ];
1060 sal_Unicode pDeviceName
[ 4096 ];
1061 memcpy( pDriverName
, pPrinter
->maDriverName
.getStr(), pPrinter
->maDriverName
.getLength()*sizeof(sal_Unicode
));
1062 memset( pDriverName
+pPrinter
->maDriverName
.getLength(), 0, 32 );
1063 memcpy( pDeviceName
, pPrinter
->maDeviceName
.getStr(), pPrinter
->maDeviceName
.getLength()*sizeof(sal_Unicode
));
1064 memset( pDeviceName
+pPrinter
->maDeviceName
.getLength(), 0, 32 );
1065 hDC
= ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR
>(pDriverName
),
1066 reinterpret_cast< LPCWSTR
>(pDeviceName
),
1071 // -----------------------------------------------------------------------
1073 static WinSalGraphics
* ImplCreateSalPrnGraphics( HDC hDC
)
1075 WinSalGraphics
* pGraphics
= new WinSalGraphics
;
1076 pGraphics
->SetLayout( 0 );
1077 pGraphics
->mhDC
= hDC
;
1078 pGraphics
->mhWnd
= 0;
1079 pGraphics
->mbPrinter
= TRUE
;
1080 pGraphics
->mbVirDev
= FALSE
;
1081 pGraphics
->mbWindow
= FALSE
;
1082 pGraphics
->mbScreen
= FALSE
;
1083 ImplSalInitGraphics( pGraphics
);
1087 // -----------------------------------------------------------------------
1089 static sal_Bool
ImplUpdateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1091 HDC hNewDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1095 if ( pPrinter
->mpGraphics
)
1097 ImplSalDeInitGraphics( pPrinter
->mpGraphics
);
1098 DeleteDC( pPrinter
->mpGraphics
->mhDC
);
1099 delete pPrinter
->mpGraphics
;
1102 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hNewDC
);
1103 pPrinter
->mhDC
= hNewDC
;
1108 // =======================================================================
1110 SalInfoPrinter
* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
1111 ImplJobSetup
* pSetupData
)
1113 WinSalInfoPrinter
* pPrinter
= new WinSalInfoPrinter
;
1114 if( ! pQueueInfo
->mpSysData
)
1115 GetPrinterQueueState( pQueueInfo
);
1116 pPrinter
->maDriverName
= pQueueInfo
->maDriver
;
1117 pPrinter
->maDeviceName
= pQueueInfo
->maPrinterName
;
1118 pPrinter
->maPortName
= pQueueInfo
->mpSysData
?
1119 *pQueueInfo
->mpSysData
1122 // check if the provided setup data match the actual printer
1123 ImplTestSalJobSetup( pPrinter
, pSetupData
, TRUE
);
1125 HDC hDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1132 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
1133 pPrinter
->mhDC
= hDC
;
1134 if ( !pSetupData
->mpDriverData
)
1135 ImplUpdateSalJobSetup( pPrinter
, pSetupData
, FALSE
, NULL
);
1136 ImplDevModeToJobSetup( pPrinter
, pSetupData
, SAL_JOBSET_ALL
);
1137 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
1142 // -----------------------------------------------------------------------
1144 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
1149 // =======================================================================
1151 WinSalInfoPrinter::WinSalInfoPrinter() :
1156 m_bPapersInit
= FALSE
;
1159 // -----------------------------------------------------------------------
1161 WinSalInfoPrinter::~WinSalInfoPrinter()
1165 ImplSalDeInitGraphics( mpGraphics
);
1166 DeleteDC( mpGraphics
->mhDC
);
1171 // -----------------------------------------------------------------------
1173 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup
* pSetupData
)
1175 m_aPaperFormats
.clear();
1177 DWORD nCount
= ImplDeviceCaps( this, DC_PAPERSIZE
, NULL
, pSetupData
);
1178 if( nCount
== GDI_ERROR
)
1183 POINT
* pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nCount
*sizeof(POINT
));
1184 ImplDeviceCaps( this, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
1186 sal_Unicode
* pNamesBuffer
= (sal_Unicode
*)rtl_allocateMemory(nCount
*64*sizeof(sal_Unicode
));
1187 ImplDeviceCaps( this, DC_PAPERNAMES
, (BYTE
*)pNamesBuffer
, pSetupData
);
1188 for( DWORD i
= 0; i
< nCount
; ++i
)
1190 PaperInfo
aInfo(pPaperSizes
[i
].x
* 10, pPaperSizes
[i
].y
* 10);
1191 m_aPaperFormats
.push_back( aInfo
);
1193 rtl_freeMemory( pNamesBuffer
);
1194 rtl_freeMemory( pPaperSizes
);
1197 m_bPapersInit
= true;
1200 // -----------------------------------------------------------------------
1202 int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup
* pSetupData
)
1204 int nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1206 if( nRet
!= sal::static_int_cast
<int>( GDI_ERROR
) )
1209 return 900; // guess
1212 // -----------------------------------------------------------------------
1214 SalGraphics
* WinSalInfoPrinter::GetGraphics()
1225 // -----------------------------------------------------------------------
1227 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics
* )
1232 // -----------------------------------------------------------------------
1234 sal_Bool
WinSalInfoPrinter::Setup( SalFrame
* pFrame
, ImplJobSetup
* pSetupData
)
1236 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, static_cast<WinSalFrame
*>(pFrame
) ) )
1238 ImplDevModeToJobSetup( this, pSetupData
, SAL_JOBSET_ALL
);
1239 return ImplUpdateSalPrnIC( this, pSetupData
);
1245 // -----------------------------------------------------------------------
1247 sal_Bool
WinSalInfoPrinter::SetPrinterData( ImplJobSetup
* pSetupData
)
1249 if ( !ImplTestSalJobSetup( this, pSetupData
, FALSE
) )
1251 return ImplUpdateSalPrnIC( this, pSetupData
);
1254 // -----------------------------------------------------------------------
1256 sal_Bool
WinSalInfoPrinter::SetData( sal_uLong nFlags
, ImplJobSetup
* pSetupData
)
1258 ImplJobSetupToDevMode( this, pSetupData
, nFlags
);
1259 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, NULL
) )
1261 ImplDevModeToJobSetup( this, pSetupData
, nFlags
);
1262 return ImplUpdateSalPrnIC( this, pSetupData
);
1268 // -----------------------------------------------------------------------
1270 sal_uLong
WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pSetupData
)
1272 DWORD nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1273 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1279 // -----------------------------------------------------------------------
1281 OUString
WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup
* pSetupData
, sal_uLong nPaperBin
)
1283 XubString aPaperBinName
;
1285 DWORD nBins
= ImplDeviceCaps( this, DC_BINNAMES
, NULL
, pSetupData
);
1286 if ( (nPaperBin
< nBins
) && (nBins
!= GDI_ERROR
) )
1288 sal_Unicode
* pBuffer
= new sal_Unicode
[nBins
*24];
1289 DWORD nRet
= ImplDeviceCaps( this, DC_BINNAMES
, (BYTE
*)pBuffer
, pSetupData
);
1290 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1291 aPaperBinName
= pBuffer
+ (nPaperBin
*24);
1295 return aPaperBinName
;
1298 // -----------------------------------------------------------------------
1300 sal_uLong
WinSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pSetupData
, sal_uInt16 nType
)
1306 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
1308 case PRINTER_CAPABILITIES_COPIES
:
1309 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1310 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1313 case PRINTER_CAPABILITIES_COLLATECOPIES
:
1314 nRet
= ImplDeviceCaps( this, DC_COLLATE
, NULL
, pSetupData
);
1315 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1317 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1318 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1323 case PRINTER_CAPABILITIES_SETORIENTATION
:
1324 nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1325 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1329 case PRINTER_CAPABILITIES_SETPAPERBIN
:
1330 nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1331 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1335 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
1336 case PRINTER_CAPABILITIES_SETPAPER
:
1337 nRet
= ImplDeviceCaps( this, DC_PAPERS
, NULL
, pSetupData
);
1338 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1346 // -----------------------------------------------------------------------
1348 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup
*,
1349 long& rOutWidth
, long& rOutHeight
,
1350 long& rPageOffX
, long& rPageOffY
,
1351 long& rPageWidth
, long& rPageHeight
)
1355 rOutWidth
= GetDeviceCaps( hDC
, HORZRES
);
1356 rOutHeight
= GetDeviceCaps( hDC
, VERTRES
);
1358 rPageOffX
= GetDeviceCaps( hDC
, PHYSICALOFFSETX
);
1359 rPageOffY
= GetDeviceCaps( hDC
, PHYSICALOFFSETY
);
1360 rPageWidth
= GetDeviceCaps( hDC
, PHYSICALWIDTH
);
1361 rPageHeight
= GetDeviceCaps( hDC
, PHYSICALHEIGHT
);
1364 // =======================================================================
1366 SalPrinter
* WinSalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
1368 WinSalPrinter
* pPrinter
= new WinSalPrinter
;
1369 pPrinter
->mpInfoPrinter
= static_cast<WinSalInfoPrinter
*>(pInfoPrinter
);
1373 // -----------------------------------------------------------------------
1375 void WinSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
1380 // =======================================================================
1382 BOOL CALLBACK
SalPrintAbortProc( HDC hPrnDC
, int /* nError */ )
1384 SalData
* pSalData
= GetSalData();
1385 WinSalPrinter
* pPrinter
;
1386 sal_Bool bWhile
= TRUE
;
1391 // Messages verarbeiten
1393 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1395 TranslateMessage( &aMsg
);
1396 ImplDispatchMessage( &aMsg
);
1405 pPrinter
= pSalData
->mpFirstPrinter
;
1408 if( pPrinter
->mhDC
== hPrnDC
)
1411 pPrinter
= pPrinter
->mpNextPrinter
;
1414 if ( !pPrinter
|| pPrinter
->mbAbort
)
1422 // -----------------------------------------------------------------------
1424 static LPDEVMODEW
ImplSalSetCopies( LPDEVMODEW pDevMode
, sal_uLong nCopies
, sal_Bool bCollate
)
1426 LPDEVMODEW pNewDevMode
= pDevMode
;
1427 if ( pDevMode
&& (nCopies
> 1) )
1429 if ( nCopies
> 32765 )
1431 sal_uLong nDevSize
= pDevMode
->dmSize
+pDevMode
->dmDriverExtra
;
1432 pNewDevMode
= (LPDEVMODEW
)rtl_allocateMemory( nDevSize
);
1433 memcpy( pNewDevMode
, pDevMode
, nDevSize
);
1434 pDevMode
= pNewDevMode
;
1435 pDevMode
->dmFields
|= DM_COPIES
;
1436 pDevMode
->dmCopies
= (short)(sal_uInt16
)nCopies
;
1437 pDevMode
->dmFields
|= DM_COLLATE
;
1439 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1441 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
1447 // -----------------------------------------------------------------------
1449 WinSalPrinter::WinSalPrinter() :
1451 mpInfoPrinter( NULL
),
1452 mpNextPrinter( NULL
),
1460 SalData
* pSalData
= GetSalData();
1461 // insert printer in printerlist
1462 mpNextPrinter
= pSalData
->mpFirstPrinter
;
1463 pSalData
->mpFirstPrinter
= this;
1466 // -----------------------------------------------------------------------
1468 WinSalPrinter::~WinSalPrinter()
1470 SalData
* pSalData
= GetSalData();
1472 // release DC if there is one still around because of AbortJob
1478 ImplSalDeInitGraphics( mpGraphics
);
1485 // remove printer from printerlist
1486 if ( this == pSalData
->mpFirstPrinter
)
1487 pSalData
->mpFirstPrinter
= mpNextPrinter
;
1490 WinSalPrinter
* pTempPrinter
= pSalData
->mpFirstPrinter
;
1492 while( pTempPrinter
->mpNextPrinter
!= this )
1493 pTempPrinter
= pTempPrinter
->mpNextPrinter
;
1495 pTempPrinter
->mpNextPrinter
= mpNextPrinter
;
1500 // -----------------------------------------------------------------------
1502 void WinSalPrinter::markInvalid()
1507 // -----------------------------------------------------------------------
1509 // need wrappers for StarTocW/A to use structured exception handling
1510 // since SEH does not mix with standard exception handling's cleanup
1511 static int lcl_StartDocW( HDC hDC
, DOCINFOW
* pInfo
, WinSalPrinter
* pPrt
)
1515 CATCH_DRIVER_EX_BEGIN
;
1516 nRet
= ::StartDocW( hDC
, pInfo
);
1517 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1521 sal_Bool
WinSalPrinter::StartJob( const OUString
* pFileName
,
1522 const OUString
& rJobName
,
1527 ImplJobSetup
* pSetupData
)
1532 mbCollate
= bCollate
;
1534 LPDEVMODEW pOrgDevModeW
= NULL
;
1535 LPDEVMODEW pDevModeW
= NULL
;
1537 if ( pSetupData
&& pSetupData
->mpDriverData
)
1539 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1540 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, nCopies
, bCollate
);
1543 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1544 sal_Unicode aDrvBuf
[4096];
1545 sal_Unicode aDevBuf
[4096];
1546 memcpy( aDrvBuf
, mpInfoPrinter
->maDriverName
.getStr(), (mpInfoPrinter
->maDriverName
.getLength()+1)*sizeof(sal_Unicode
));
1547 memcpy( aDevBuf
, mpInfoPrinter
->maDeviceName
.getStr(), (mpInfoPrinter
->maDeviceName
.getLength()+1)*sizeof(sal_Unicode
));
1548 hDC
= CreateDCW( reinterpret_cast<LPCWSTR
>(aDrvBuf
),
1549 reinterpret_cast<LPCWSTR
>(aDevBuf
),
1553 if ( pDevModeW
!= pOrgDevModeW
)
1554 rtl_freeMemory( pDevModeW
);
1558 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1562 // make sure mhDC is set before the printer driver may call our abortproc
1564 if ( SetAbortProc( hDC
, SalPrintAbortProc
) <= 0 )
1566 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1573 // As the Telocom Balloon Fax driver tends to send messages repeatedly
1574 // we try to process first all, and then insert a dummy message
1575 sal_Bool bWhile
= TRUE
;
1581 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1583 TranslateMessage( &aMsg
);
1584 ImplDispatchMessage( &aMsg
);
1594 ImplPostMessage( GetSalData()->mpFirstInstance
->mhComWnd
, SAL_MSG_DUMMY
, 0, 0 );
1596 // bring up a file choser if printing to file port but no file name given
1597 OUString aOutFileName
;
1598 if( mpInfoPrinter
->maPortName
.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "FILE:" ) ) && !(pFileName
&& !pFileName
->isEmpty()) )
1601 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1602 uno::Reference
< XFilePicker3
> xFilePicker
= FilePicker::createWithMode(xContext
, TemplateDescription::FILESAVE_SIMPLE
);
1604 if( xFilePicker
->execute() == ExecutableDialogResults::OK
)
1606 Sequence
< OUString
> aPathSeq( xFilePicker
->getFiles() );
1607 INetURLObject
aObj( aPathSeq
[0] );
1608 // we're using ansi calls (StartDocA) so convert the string
1609 aOutFileName
= aObj
.PathToFileName();
1613 mnError
= SAL_PRINTER_ERROR_ABORT
;
1619 memset( &aInfo
, 0, sizeof( DOCINFOW
) );
1620 aInfo
.cbSize
= sizeof( aInfo
);
1621 aInfo
.lpszDocName
= (LPWSTR
)rJobName
.getStr();
1622 if ( pFileName
|| aOutFileName
.getLength() )
1624 if ( (pFileName
&& !pFileName
->isEmpty()) || aOutFileName
.getLength() )
1626 aInfo
.lpszOutput
= (LPWSTR
)( (pFileName
&& !pFileName
->isEmpty()) ? pFileName
->getStr() : aOutFileName
.getStr());
1629 aInfo
.lpszOutput
= L
"FILE:";
1632 aInfo
.lpszOutput
= NULL
;
1635 int nRet
= lcl_StartDocW( hDC
, &aInfo
, this );
1639 long nError
= GetLastError();
1640 if ( (nRet
== SP_USERABORT
) || (nRet
== SP_APPABORT
) || (nError
== ERROR_PRINT_CANCELLED
) || (nError
== ERROR_CANCELLED
) )
1641 mnError
= SAL_PRINTER_ERROR_ABORT
;
1643 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1650 // -----------------------------------------------------------------------
1652 sal_Bool
WinSalPrinter::EndJob()
1655 if ( isValid() && hDC
)
1659 ImplSalDeInitGraphics( mpGraphics
);
1664 // #i54419# Windows fax printer brings up a dialog in EndDoc
1665 // which text previously copied in soffice process can be
1666 // pasted to -> deadlock due to mutex not released.
1667 // it should be safe to release the yield mutex over the EndDoc
1668 // call, however the real solution is supposed to be the threading
1669 // framework yet to come.
1670 volatile sal_uLong nAcquire
= GetSalData()->mpFirstInstance
->ReleaseYieldMutex();
1671 CATCH_DRIVER_EX_BEGIN
;
1672 if( ::EndDoc( hDC
) <= 0 )
1674 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
1676 GetSalData()->mpFirstInstance
->AcquireYieldMutex( nAcquire
);
1684 // -----------------------------------------------------------------------
1686 sal_Bool
WinSalPrinter::AbortJob()
1690 // trigger Abort asynchronously
1694 SalData
* pSalData
= GetSalData();
1695 ImplPostMessage( pSalData
->mpFirstInstance
->mhComWnd
,
1696 SAL_MSG_PRINTABORTJOB
, (WPARAM
)hDC
, 0 );
1702 // -----------------------------------------------------------------------
1704 void ImplSalPrinterAbortJobAsync( HDC hPrnDC
)
1706 SalData
* pSalData
= GetSalData();
1707 WinSalPrinter
* pPrinter
= pSalData
->mpFirstPrinter
;
1709 // check if printer still exists
1712 if ( pPrinter
->mhDC
== hPrnDC
)
1715 pPrinter
= pPrinter
->mpNextPrinter
;
1718 // if printer still exists, cancel the job
1721 HDC hDC
= pPrinter
->mhDC
;
1724 if ( pPrinter
->mpGraphics
)
1726 ImplSalDeInitGraphics( pPrinter
->mpGraphics
);
1727 delete pPrinter
->mpGraphics
;
1728 pPrinter
->mpGraphics
= NULL
;
1731 CATCH_DRIVER_EX_BEGIN
;
1733 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter
);
1741 // -----------------------------------------------------------------------
1743 SalGraphics
* WinSalPrinter::StartPage( ImplJobSetup
* pSetupData
, sal_Bool bNewJobData
)
1745 if( ! isValid() || mhDC
== 0 )
1749 if ( pSetupData
&& pSetupData
->mpDriverData
&& bNewJobData
)
1751 LPDEVMODEW pOrgDevModeW
;
1752 LPDEVMODEW pDevModeW
;
1753 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1754 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, mnCopies
, mbCollate
);
1755 ResetDCW( hDC
, pDevModeW
);
1756 if ( pDevModeW
!= pOrgDevModeW
)
1757 rtl_freeMemory( pDevModeW
);
1759 volatile int nRet
= 0;
1760 CATCH_DRIVER_EX_BEGIN
;
1761 nRet
= ::StartPage( hDC
);
1762 CATCH_DRIVER_EX_END( "exception in StartPage", this );
1767 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1771 // Hack to work around old PostScript printer drivers optimizing away empty pages
1772 // TODO: move into ImplCreateSalPrnGraphics()?
1773 HPEN hTempPen
= SelectPen( hDC
, GetStockPen( NULL_PEN
) );
1774 HBRUSH hTempBrush
= SelectBrush( hDC
, GetStockBrush( NULL_BRUSH
) );
1775 WIN_Rectangle( hDC
, -8000, -8000, -7999, -7999 );
1776 SelectPen( hDC
, hTempPen
);
1777 SelectBrush( hDC
, hTempBrush
);
1779 mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
1783 // -----------------------------------------------------------------------
1785 sal_Bool
WinSalPrinter::EndPage()
1788 if ( hDC
&& mpGraphics
)
1790 ImplSalDeInitGraphics( mpGraphics
);
1798 volatile int nRet
= 0;
1799 CATCH_DRIVER_EX_BEGIN
;
1800 nRet
= ::EndPage( hDC
);
1801 CATCH_DRIVER_EX_END( "exception in EndPage", this );
1808 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1813 // -----------------------------------------------------------------------
1815 sal_uLong
WinSalPrinter::GetErrorCode()
1820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */