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 .
24 #include <osl/module.h>
26 #include <tools/urlobj.hxx>
28 #include <win/wincomp.hxx>
29 #include <win/saldata.hxx>
30 #include <win/salinst.h>
31 #include <win/salgdi.h>
32 #include <win/salframe.h>
33 #include <win/salprn.h>
35 #include <salptype.hxx>
39 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
41 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
42 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <comphelper/processfactory.hxx>
49 #if defined ( __MINGW32__ )
50 #include <sehandler.hxx>
53 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
54 #define CATCH_DRIVER_EX_BEGIN \
57 if (__builtin_setjmp(jmpbuf) == 0) \
59 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
61 #define CATCH_DRIVER_EX_END(mes, p) \
64 #define CATCH_DRIVER_EX_END_2(mes) \
68 #define CATCH_DRIVER_EX_BEGIN \
71 #define CATCH_DRIVER_EX_END(mes, p) \
73 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
78 #define CATCH_DRIVER_EX_END_2(mes) \
80 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
86 using namespace com::sun::star
;
87 using namespace com::sun::star::uno
;
88 using namespace com::sun::star::lang
;
89 using namespace com::sun::star::ui::dialogs
;
91 static char aImplWindows
[] = "windows";
92 static char aImplDevice
[] = "device";
94 static LPDEVMODEW
SAL_DEVMODE_W( const ImplJobSetup
* pSetupData
)
96 LPDEVMODEW pRet
= NULL
;
97 SalDriverData
* pDrv
= (SalDriverData
*)pSetupData
->mpDriverData
;
98 if( pSetupData
->mnDriverDataLen
>= sizeof(DEVMODEW
)+sizeof(SalDriverData
)-1 )
99 pRet
= ((LPDEVMODEW
)((pSetupData
->mpDriverData
) + (pDrv
->mnDriverOffset
)));
103 static PrintQueueFlags
ImplWinQueueStatusToSal( DWORD nWinStatus
)
105 PrintQueueFlags nStatus
= PrintQueueFlags::NONE
;
106 if ( nWinStatus
& PRINTER_STATUS_PAUSED
)
107 nStatus
|= PrintQueueFlags::Paused
;
108 if ( nWinStatus
& PRINTER_STATUS_ERROR
)
109 nStatus
|= PrintQueueFlags::Error
;
110 if ( nWinStatus
& PRINTER_STATUS_PENDING_DELETION
)
111 nStatus
|= PrintQueueFlags::PendingDeletion
;
112 if ( nWinStatus
& PRINTER_STATUS_PAPER_JAM
)
113 nStatus
|= PrintQueueFlags::PaperJam
;
114 if ( nWinStatus
& PRINTER_STATUS_PAPER_OUT
)
115 nStatus
|= PrintQueueFlags::PaperOut
;
116 if ( nWinStatus
& PRINTER_STATUS_MANUAL_FEED
)
117 nStatus
|= PrintQueueFlags::ManualFeed
;
118 if ( nWinStatus
& PRINTER_STATUS_PAPER_PROBLEM
)
119 nStatus
|= PrintQueueFlags::PaperProblem
;
120 if ( nWinStatus
& PRINTER_STATUS_OFFLINE
)
121 nStatus
|= PrintQueueFlags::Offline
;
122 if ( nWinStatus
& PRINTER_STATUS_IO_ACTIVE
)
123 nStatus
|= PrintQueueFlags::IOActive
;
124 if ( nWinStatus
& PRINTER_STATUS_BUSY
)
125 nStatus
|= PrintQueueFlags::Busy
;
126 if ( nWinStatus
& PRINTER_STATUS_PRINTING
)
127 nStatus
|= PrintQueueFlags::Printing
;
128 if ( nWinStatus
& PRINTER_STATUS_OUTPUT_BIN_FULL
)
129 nStatus
|= PrintQueueFlags::OutputBinFull
;
130 if ( nWinStatus
& PRINTER_STATUS_WAITING
)
131 nStatus
|= PrintQueueFlags::Waiting
;
132 if ( nWinStatus
& PRINTER_STATUS_PROCESSING
)
133 nStatus
|= PrintQueueFlags::Processing
;
134 if ( nWinStatus
& PRINTER_STATUS_INITIALIZING
)
135 nStatus
|= PrintQueueFlags::Initializing
;
136 if ( nWinStatus
& PRINTER_STATUS_WARMING_UP
)
137 nStatus
|= PrintQueueFlags::WarmingUp
;
138 if ( nWinStatus
& PRINTER_STATUS_TONER_LOW
)
139 nStatus
|= PrintQueueFlags::TonerLow
;
140 if ( nWinStatus
& PRINTER_STATUS_NO_TONER
)
141 nStatus
|= PrintQueueFlags::NoToner
;
142 if ( nWinStatus
& PRINTER_STATUS_PAGE_PUNT
)
143 nStatus
|= PrintQueueFlags::PagePunt
;
144 if ( nWinStatus
& PRINTER_STATUS_USER_INTERVENTION
)
145 nStatus
|= PrintQueueFlags::UserIntervention
;
146 if ( nWinStatus
& PRINTER_STATUS_OUT_OF_MEMORY
)
147 nStatus
|= PrintQueueFlags::OutOfMemory
;
148 if ( nWinStatus
& PRINTER_STATUS_DOOR_OPEN
)
149 nStatus
|= PrintQueueFlags::DoorOpen
;
150 if ( nWinStatus
& PRINTER_STATUS_SERVER_UNKNOWN
)
151 nStatus
|= PrintQueueFlags::StatusUnknown
;
152 if ( nWinStatus
& PRINTER_STATUS_POWER_SAVE
)
153 nStatus
|= PrintQueueFlags::PowerSave
;
154 if ( nStatus
== PrintQueueFlags::NONE
&& !(nWinStatus
& PRINTER_STATUS_NOT_AVAILABLE
) )
155 nStatus
|= PrintQueueFlags::Ready
;
159 // - WinSalInstance -
161 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
166 EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, NULL
, 0, &nBytes
, &nInfoPrn4
);
169 PRINTER_INFO_4W
* pWinInfo4
= (PRINTER_INFO_4W
*) rtl_allocateMemory( nBytes
);
170 if ( EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, (LPBYTE
)pWinInfo4
, nBytes
, &nBytes
, &nInfoPrn4
) )
172 for ( i
= 0; i
< nInfoPrn4
; i
++ )
174 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
175 pInfo
->maPrinterName
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo4
[i
].pPrinterName
) );
176 pInfo
->mnStatus
= PrintQueueFlags::NONE
;
178 pInfo
->mpSysData
= NULL
;
182 rtl_freeMemory( pWinInfo4
);
186 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* pInfo
)
189 LPWSTR pPrnName
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pInfo
->maPrinterName
.getStr()));
190 if( OpenPrinterW( pPrnName
, &hPrinter
, NULL
) )
193 GetPrinterW( hPrinter
, 2, NULL
, 0, &nBytes
);
196 PRINTER_INFO_2W
* pWinInfo2
= (PRINTER_INFO_2W
*)rtl_allocateMemory(nBytes
);
197 if( GetPrinterW( hPrinter
, 2, (LPBYTE
)pWinInfo2
, nBytes
, &nBytes
) )
199 if( pWinInfo2
->pDriverName
)
200 pInfo
->maDriver
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pDriverName
) );
202 if ( pWinInfo2
->pPortName
)
203 aPortName
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pPortName
) );
204 // pLocation can be 0 (the Windows docu doesn't describe this)
205 if ( pWinInfo2
->pLocation
&& *pWinInfo2
->pLocation
)
206 pInfo
->maLocation
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pLocation
) );
208 pInfo
->maLocation
= aPortName
;
209 // pComment can be 0 (the Windows docu doesn't describe this)
210 if ( pWinInfo2
->pComment
)
211 pInfo
->maComment
= OUString( reinterpret_cast< const sal_Unicode
* >(pWinInfo2
->pComment
) );
212 pInfo
->mnStatus
= ImplWinQueueStatusToSal( pWinInfo2
->Status
);
213 pInfo
->mnJobs
= pWinInfo2
->cJobs
;
214 if( ! pInfo
->mpSysData
)
215 pInfo
->mpSysData
= new OUString(aPortName
);
217 rtl_freeMemory(pWinInfo2
);
219 ClosePrinter( hPrinter
);
223 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
225 delete pInfo
->mpSysData
;
229 OUString
WinSalInstance::GetDefaultPrinter()
232 GetDefaultPrinterW( NULL
, &nChars
);
235 LPWSTR pStr
= (LPWSTR
)rtl_allocateMemory(nChars
*sizeof(WCHAR
));
237 if( GetDefaultPrinterW( pStr
, &nChars
) )
239 aDefPrt
= OUString(reinterpret_cast<sal_Unicode
* >(pStr
));
241 rtl_freeMemory( pStr
);
242 if( !aDefPrt
.isEmpty() )
246 // get default printer from win.ini
248 GetProfileStringA( aImplWindows
, aImplDevice
, "", szBuffer
, sizeof( szBuffer
) );
251 // search for printer name
252 char* pBuf
= szBuffer
;
254 while ( *pTmp
&& (*pTmp
!= ',') )
256 return ImplSalGetUniString( pBuf
, static_cast<sal_Int32
>(pTmp
-pBuf
) );
262 static DWORD
ImplDeviceCaps( WinSalInfoPrinter
* pPrinter
, WORD nCaps
,
263 BYTE
* pOutput
, const ImplJobSetup
* pSetupData
)
266 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
269 pDevMode
= SAL_DEVMODE_W( pSetupData
);
271 return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR
>(pPrinter
->maDeviceName
.getStr()),
272 reinterpret_cast<LPCWSTR
>(pPrinter
->maPortName
.getStr()),
273 nCaps
, (LPWSTR
)pOutput
, pDevMode
);
276 static bool ImplTestSalJobSetup( WinSalInfoPrinter
* pPrinter
,
277 ImplJobSetup
* pSetupData
, bool bDelete
)
279 if ( pSetupData
&& pSetupData
->mpDriverData
)
281 // signature and size must fit to avoid using
282 // JobSetups from a wrong system
284 // initialize versions from jobsetup
285 // those will be overwritten with driver's version
286 DEVMODEW
* pDevModeW
= NULL
;
287 LONG dmSpecVersion
= -1;
288 LONG dmDriverVersion
= -1;
289 SalDriverData
* pSalDriverData
= (SalDriverData
*)pSetupData
->mpDriverData
;
290 BYTE
* pDriverData
= ((BYTE
*)pSalDriverData
) + pSalDriverData
->mnDriverOffset
;
291 pDevModeW
= (DEVMODEW
*)pDriverData
;
293 long nSysJobSize
= -1;
294 if( pPrinter
&& pDevModeW
)
296 // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
297 // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
298 // can avoid potential driver crashes as their jobsetups are often not compatible
299 // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
301 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.getStr()));
302 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
305 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
306 if( hPrn
== HGDI_ERROR
)
309 nSysJobSize
= DocumentPropertiesW( 0, hPrn
,
313 if( nSysJobSize
< 0 )
315 ClosePrinter( hPrn
);
318 BYTE
*pBuffer
= (BYTE
*)_alloca( nSysJobSize
);
319 LONG nRet
= DocumentPropertiesW( 0, hPrn
,
321 (LPDEVMODEW
)pBuffer
, NULL
, DM_OUT_BUFFER
);
324 ClosePrinter( hPrn
);
328 // the spec version differs between the windows platforms, ie 98,NT,2000/XP
329 // this allows us to throw away printer settings from other platforms that might crash a buggy driver
330 // we check the driver version as well
331 dmSpecVersion
= ((DEVMODEW
*)pBuffer
)->dmSpecVersion
;
332 dmDriverVersion
= ((DEVMODEW
*)pBuffer
)->dmDriverVersion
;
334 ClosePrinter( hPrn
);
336 SalDriverData
* pSetupDriverData
= (SalDriverData
*)(pSetupData
->mpDriverData
);
337 if ( (pSetupData
->mnSystem
== JOBSETUP_SYSTEM_WINDOWS
) &&
338 (pPrinter
->maDriverName
== pSetupData
->maDriver
) &&
339 (pSetupData
->mnDriverDataLen
> sizeof( SalDriverData
)) &&
340 (long)(pSetupData
->mnDriverDataLen
- pSetupDriverData
->mnDriverOffset
) == nSysJobSize
&&
341 pSetupDriverData
->mnSysSignature
== SAL_DRIVERDATA_SYSSIGN
)
344 (dmSpecVersion
== pDevModeW
->dmSpecVersion
) &&
345 (dmDriverVersion
== pDevModeW
->dmDriverVersion
) )
350 rtl_freeMemory( pSetupData
->mpDriverData
);
351 pSetupData
->mpDriverData
= NULL
;
352 pSetupData
->mnDriverDataLen
= 0;
359 static bool ImplUpdateSalJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
,
360 bool bIn
, WinSalFrame
* pVisibleDlgParent
)
363 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.getStr()));
364 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
366 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
367 if( hPrn
== HGDI_ERROR
)
372 DWORD nMode
= DM_OUT_BUFFER
;
373 sal_uLong nDriverDataLen
= 0;
374 SalDriverData
* pOutBuffer
= NULL
;
375 BYTE
* pInBuffer
= NULL
;
377 LONG nSysJobSize
= DocumentPropertiesW( hWnd
, hPrn
,
380 if ( nSysJobSize
< 0 )
382 ClosePrinter( hPrn
);
387 nDriverDataLen
= sizeof(SalDriverData
) + nSysJobSize
-1;
388 pOutBuffer
= (SalDriverData
*)rtl_allocateZeroMemory( nDriverDataLen
);
389 pOutBuffer
->mnSysSignature
= SAL_DRIVERDATA_SYSSIGN
;
390 // calculate driver data offset including structure padding
391 pOutBuffer
->mnDriverOffset
= sal::static_int_cast
<sal_uInt16
>(
392 (char*)pOutBuffer
->maDriverData
-
395 // check if we have a suitable input buffer
396 if ( bIn
&& ImplTestSalJobSetup( pPrinter
, pSetupData
, FALSE
) )
398 pInBuffer
= (BYTE
*)pSetupData
->mpDriverData
+ ((SalDriverData
*)pSetupData
->mpDriverData
)->mnDriverOffset
;
399 nMode
|= DM_IN_BUFFER
;
402 // check if the dialog should be shown
403 if ( pVisibleDlgParent
)
405 hWnd
= pVisibleDlgParent
->mhWnd
;
406 nMode
|= DM_IN_PROMPT
;
409 // Release mutex, in the other case we don't get paints and so on
410 sal_uLong nMutexCount
=0;
411 if ( pVisibleDlgParent
)
412 nMutexCount
= ImplSalReleaseYieldMutex();
414 BYTE
* pOutDevMode
= (((BYTE
*)pOutBuffer
) + pOutBuffer
->mnDriverOffset
);
415 nRet
= DocumentPropertiesW( hWnd
, hPrn
,
417 (LPDEVMODEW
)pOutDevMode
, (LPDEVMODEW
)pInBuffer
, nMode
);
418 if ( pVisibleDlgParent
)
419 ImplSalAcquireYieldMutex( nMutexCount
);
420 ClosePrinter( hPrn
);
422 if( (nRet
< 0) || (pVisibleDlgParent
&& (nRet
== IDCANCEL
)) )
424 rtl_freeMemory( pOutBuffer
);
428 // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
429 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 64 )
431 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
);
432 if ( sal::static_int_cast
<size_t>(nLen
) < SAL_N_ELEMENTS( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
) )
433 memset( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmDeviceName
)-(nLen
*sizeof(sal_Unicode
)) );
435 if( ((LPDEVMODEW
)pOutDevMode
)->dmSize
>= 166 )
437 sal_Int32 nLen
= rtl_ustr_getLength( (const sal_Unicode
*)((LPDEVMODEW
)pOutDevMode
)->dmFormName
);
438 if ( sal::static_int_cast
<size_t>(nLen
) < SAL_N_ELEMENTS( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
) )
439 memset( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
+nLen
, 0, sizeof( ((LPDEVMODEW
)pOutDevMode
)->dmFormName
)-(nLen
*sizeof(sal_Unicode
)) );
443 if ( pSetupData
->mpDriverData
)
444 rtl_freeMemory( pSetupData
->mpDriverData
);
445 pSetupData
->mnDriverDataLen
= nDriverDataLen
;
446 pSetupData
->mpDriverData
= (BYTE
*)pOutBuffer
;
447 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
452 #define DECLARE_DEVMODE( i )\
453 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
454 if( pDevModeW == NULL )\
457 #define CHOOSE_DEVMODE(i)\
460 static void ImplDevModeToJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, sal_uLong nFlags
)
462 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
465 DECLARE_DEVMODE( pSetupData
);
468 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
470 if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_PORTRAIT
)
471 pSetupData
->meOrientation
= ORIENTATION_PORTRAIT
;
472 else if ( CHOOSE_DEVMODE(dmOrientation
) == DMORIENT_LANDSCAPE
)
473 pSetupData
->meOrientation
= ORIENTATION_LANDSCAPE
;
477 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
479 sal_uLong nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
481 if ( nCount
&& (nCount
!= GDI_ERROR
) )
483 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory( nCount
*sizeof(WORD
) );
484 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
485 pSetupData
->mnPaperBin
= 0;
487 // search the right bin and assign index to mnPaperBin
488 for( sal_uLong i
= 0; i
< nCount
; i
++ )
490 if( CHOOSE_DEVMODE(dmDefaultSource
) == pBins
[ i
] )
492 pSetupData
->mnPaperBin
= (sal_uInt16
)i
;
497 rtl_freeMemory( pBins
);
502 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
504 if( (CHOOSE_DEVMODE(dmFields
) & (DM_PAPERWIDTH
|DM_PAPERLENGTH
)) == (DM_PAPERWIDTH
|DM_PAPERLENGTH
) )
506 pSetupData
->mnPaperWidth
= CHOOSE_DEVMODE(dmPaperWidth
)*10;
507 pSetupData
->mnPaperHeight
= CHOOSE_DEVMODE(dmPaperLength
)*10;
511 sal_uLong nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
512 WORD
* pPapers
= NULL
;
513 sal_uLong nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
514 POINT
* pPaperSizes
= NULL
;
515 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
517 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
518 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
520 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
522 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
523 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
525 if( nPaperSizeCount
== nPaperCount
&& pPaperSizes
&& pPapers
)
527 for( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
529 if( pPapers
[ i
] == CHOOSE_DEVMODE(dmPaperSize
) )
531 pSetupData
->mnPaperWidth
= pPaperSizes
[ i
].x
*10;
532 pSetupData
->mnPaperHeight
= pPaperSizes
[ i
].y
*10;
538 rtl_freeMemory( pPapers
);
540 rtl_freeMemory( pPaperSizes
);
542 switch( CHOOSE_DEVMODE(dmPaperSize
) )
544 case( DMPAPER_LETTER
):
545 pSetupData
->mePaperFormat
= PAPER_LETTER
;
547 case( DMPAPER_TABLOID
):
548 pSetupData
->mePaperFormat
= PAPER_TABLOID
;
550 case( DMPAPER_LEDGER
):
551 pSetupData
->mePaperFormat
= PAPER_LEDGER
;
553 case( DMPAPER_LEGAL
):
554 pSetupData
->mePaperFormat
= PAPER_LEGAL
;
556 case( DMPAPER_STATEMENT
):
557 pSetupData
->mePaperFormat
= PAPER_STATEMENT
;
559 case( DMPAPER_EXECUTIVE
):
560 pSetupData
->mePaperFormat
= PAPER_EXECUTIVE
;
563 pSetupData
->mePaperFormat
= PAPER_A3
;
566 pSetupData
->mePaperFormat
= PAPER_A4
;
569 pSetupData
->mePaperFormat
= PAPER_A5
;
571 //See http://wiki.openoffice.org/wiki/DefaultPaperSize
573 //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
574 //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
575 //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
576 //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
577 //matches our Excel filter's belief about the matching XlPaperSize
580 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
581 ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
582 //which is bogus as it's either JIS 257 x 364 or ISO 250 x 353
585 pSetupData
->mePaperFormat
= PAPER_B4_JIS
;
588 pSetupData
->mePaperFormat
= PAPER_B5_JIS
;
590 case( DMPAPER_QUARTO
):
591 pSetupData
->mePaperFormat
= PAPER_QUARTO
;
593 case( DMPAPER_10X14
):
594 pSetupData
->mePaperFormat
= PAPER_10x14
;
596 case( DMPAPER_NOTE
):
597 pSetupData
->mePaperFormat
= PAPER_LETTER
;
599 case( DMPAPER_ENV_9
):
600 pSetupData
->mePaperFormat
= PAPER_ENV_9
;
602 case( DMPAPER_ENV_10
):
603 pSetupData
->mePaperFormat
= PAPER_ENV_10
;
605 case( DMPAPER_ENV_11
):
606 pSetupData
->mePaperFormat
= PAPER_ENV_11
;
608 case( DMPAPER_ENV_12
):
609 pSetupData
->mePaperFormat
= PAPER_ENV_12
;
611 case( DMPAPER_ENV_14
):
612 pSetupData
->mePaperFormat
= PAPER_ENV_14
;
614 case( DMPAPER_CSHEET
):
615 pSetupData
->mePaperFormat
= PAPER_C
;
617 case( DMPAPER_DSHEET
):
618 pSetupData
->mePaperFormat
= PAPER_D
;
620 case( DMPAPER_ESHEET
):
621 pSetupData
->mePaperFormat
= PAPER_E
;
623 case( DMPAPER_ENV_DL
):
624 pSetupData
->mePaperFormat
= PAPER_ENV_DL
;
626 case( DMPAPER_ENV_C5
):
627 pSetupData
->mePaperFormat
= PAPER_ENV_C5
;
629 case( DMPAPER_ENV_C3
):
630 pSetupData
->mePaperFormat
= PAPER_ENV_C3
;
632 case( DMPAPER_ENV_C4
):
633 pSetupData
->mePaperFormat
= PAPER_ENV_C4
;
635 case( DMPAPER_ENV_C6
):
636 pSetupData
->mePaperFormat
= PAPER_ENV_C6
;
638 case( DMPAPER_ENV_C65
):
639 pSetupData
->mePaperFormat
= PAPER_ENV_C65
;
641 case( DMPAPER_ENV_ITALY
):
642 pSetupData
->mePaperFormat
= PAPER_ENV_ITALY
;
644 case( DMPAPER_ENV_MONARCH
):
645 pSetupData
->mePaperFormat
= PAPER_ENV_MONARCH
;
647 case( DMPAPER_ENV_PERSONAL
):
648 pSetupData
->mePaperFormat
= PAPER_ENV_PERSONAL
;
650 case( DMPAPER_FANFOLD_US
):
651 pSetupData
->mePaperFormat
= PAPER_FANFOLD_US
;
653 case( DMPAPER_FANFOLD_STD_GERMAN
):
654 pSetupData
->mePaperFormat
= PAPER_FANFOLD_DE
;
656 case( DMPAPER_FANFOLD_LGL_GERMAN
):
657 pSetupData
->mePaperFormat
= PAPER_FANFOLD_LEGAL_DE
;
659 case( DMPAPER_ISO_B4
):
660 pSetupData
->mePaperFormat
= PAPER_B4_ISO
;
662 case( DMPAPER_JAPANESE_POSTCARD
):
663 pSetupData
->mePaperFormat
= PAPER_POSTCARD_JP
;
665 case( DMPAPER_9X11
):
666 pSetupData
->mePaperFormat
= PAPER_9x11
;
668 case( DMPAPER_10X11
):
669 pSetupData
->mePaperFormat
= PAPER_10x11
;
671 case( DMPAPER_15X11
):
672 pSetupData
->mePaperFormat
= PAPER_15x11
;
674 case( DMPAPER_ENV_INVITE
):
675 pSetupData
->mePaperFormat
= PAPER_ENV_INVITE
;
677 case( DMPAPER_A_PLUS
):
678 pSetupData
->mePaperFormat
= PAPER_A_PLUS
;
680 case( DMPAPER_B_PLUS
):
681 pSetupData
->mePaperFormat
= PAPER_B_PLUS
;
683 case( DMPAPER_LETTER_PLUS
):
684 pSetupData
->mePaperFormat
= PAPER_LETTER_PLUS
;
686 case( DMPAPER_A4_PLUS
):
687 pSetupData
->mePaperFormat
= PAPER_A4_PLUS
;
690 pSetupData
->mePaperFormat
= PAPER_A2
;
692 case( DMPAPER_DBL_JAPANESE_POSTCARD
):
693 pSetupData
->mePaperFormat
= PAPER_DOUBLEPOSTCARD_JP
;
696 pSetupData
->mePaperFormat
= PAPER_A6
;
698 case( DMPAPER_B6_JIS
):
699 pSetupData
->mePaperFormat
= PAPER_B6_JIS
;
701 case( DMPAPER_12X11
):
702 pSetupData
->mePaperFormat
= PAPER_12x11
;
705 pSetupData
->mePaperFormat
= PAPER_USER
;
710 if( nFlags
& SAL_JOBSET_DUPLEXMODE
)
712 DuplexMode eDuplex
= DUPLEX_UNKNOWN
;
713 if( (CHOOSE_DEVMODE(dmFields
) & DM_DUPLEX
) )
715 if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_SIMPLEX
)
716 eDuplex
= DUPLEX_OFF
;
717 else if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_VERTICAL
)
718 eDuplex
= DUPLEX_LONGEDGE
;
719 else if( CHOOSE_DEVMODE(dmDuplex
) == DMDUP_HORIZONTAL
)
720 eDuplex
= DUPLEX_SHORTEDGE
;
722 pSetupData
->meDuplexMode
= eDuplex
;
726 static void ImplJobSetupToDevMode( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
, sal_uLong nFlags
)
728 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
731 DECLARE_DEVMODE( pSetupData
);
734 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
736 CHOOSE_DEVMODE(dmFields
) |= DM_ORIENTATION
;
737 if ( pSetupData
->meOrientation
== ORIENTATION_PORTRAIT
)
738 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_PORTRAIT
;
740 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_LANDSCAPE
;
744 if ( nFlags
& SAL_JOBSET_PAPERBIN
)
746 sal_uLong nCount
= ImplDeviceCaps( pPrinter
, DC_BINS
, NULL
, pSetupData
);
748 if ( nCount
&& (nCount
!= GDI_ERROR
) )
750 WORD
* pBins
= (WORD
*)rtl_allocateZeroMemory(nCount
*sizeof(WORD
));
751 ImplDeviceCaps( pPrinter
, DC_BINS
, (BYTE
*)pBins
, pSetupData
);
752 CHOOSE_DEVMODE(dmFields
) |= DM_DEFAULTSOURCE
;
753 CHOOSE_DEVMODE(dmDefaultSource
) = pBins
[ pSetupData
->mnPaperBin
];
754 rtl_freeMemory( pBins
);
759 if ( nFlags
& SAL_JOBSET_PAPERSIZE
)
761 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERSIZE
;
762 CHOOSE_DEVMODE(dmPaperWidth
) = 0;
763 CHOOSE_DEVMODE(dmPaperLength
) = 0;
765 switch( pSetupData
->mePaperFormat
)
768 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A2
;
771 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A3
;
774 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4
;
777 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A5
;
780 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ISO_B4
;
782 case( PAPER_LETTER
):
783 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER
;
786 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEGAL
;
788 case( PAPER_TABLOID
):
789 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_TABLOID
;
792 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
793 //DMPAPER_ENV_B6 is documented as:
794 //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
795 //which is the wrong way around, it is surely 125 x 176, i.e.
796 //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
797 //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
798 //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
799 case( PAPER_B6_ISO
):
800 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_B6
;
803 case( PAPER_ENV_C4
):
804 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C4
;
806 case( PAPER_ENV_C5
):
807 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C5
;
809 case( PAPER_ENV_C6
):
810 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C6
;
812 case( PAPER_ENV_C65
):
813 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C65
;
815 case( PAPER_ENV_DL
):
816 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_DL
;
819 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_CSHEET
;
822 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DSHEET
;
825 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ESHEET
;
827 case( PAPER_EXECUTIVE
):
828 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_EXECUTIVE
;
830 case( PAPER_FANFOLD_LEGAL_DE
):
831 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_LGL_GERMAN
;
833 case( PAPER_ENV_MONARCH
):
834 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_MONARCH
;
836 case( PAPER_ENV_PERSONAL
):
837 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_PERSONAL
;
840 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_9
;
842 case( PAPER_ENV_10
):
843 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_10
;
845 case( PAPER_ENV_11
):
846 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_11
;
848 case( PAPER_ENV_12
):
849 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_12
;
851 //See the comments on DMPAPER_B4 above
852 case( PAPER_B4_JIS
):
853 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B4
;
855 case( PAPER_B5_JIS
):
856 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B5
;
858 case( PAPER_B6_JIS
):
859 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B6_JIS
;
861 case( PAPER_LEDGER
):
862 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEDGER
;
864 case( PAPER_STATEMENT
):
865 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_STATEMENT
;
868 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X14
;
870 case( PAPER_ENV_14
):
871 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_14
;
873 case( PAPER_ENV_C3
):
874 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C3
;
876 case( PAPER_ENV_ITALY
):
877 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_ITALY
;
879 case( PAPER_FANFOLD_US
):
880 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_US
;
882 case( PAPER_FANFOLD_DE
):
883 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_STD_GERMAN
;
885 case( PAPER_POSTCARD_JP
):
886 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_JAPANESE_POSTCARD
;
889 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_9X11
;
892 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X11
;
895 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_15X11
;
897 case( PAPER_ENV_INVITE
):
898 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_INVITE
;
900 case( PAPER_A_PLUS
):
901 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A_PLUS
;
903 case( PAPER_B_PLUS
):
904 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B_PLUS
;
906 case( PAPER_LETTER_PLUS
):
907 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER_PLUS
;
909 case( PAPER_A4_PLUS
):
910 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4_PLUS
;
912 case( PAPER_DOUBLEPOSTCARD_JP
):
913 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DBL_JAPANESE_POSTCARD
;
916 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A6
;
919 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_12X11
;
924 sal_uLong nPaperCount
= ImplDeviceCaps( pPrinter
, DC_PAPERS
, NULL
, pSetupData
);
925 WORD
* pPapers
= NULL
;
926 sal_uLong nPaperSizeCount
= ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, NULL
, pSetupData
);
927 POINT
* pPaperSizes
= NULL
;
928 DWORD nLandscapeAngle
= ImplDeviceCaps( pPrinter
, DC_ORIENTATION
, NULL
, pSetupData
);
929 if ( nPaperCount
&& (nPaperCount
!= GDI_ERROR
) )
931 pPapers
= (WORD
*)rtl_allocateZeroMemory(nPaperCount
*sizeof(WORD
));
932 ImplDeviceCaps( pPrinter
, DC_PAPERS
, (BYTE
*)pPapers
, pSetupData
);
934 if ( nPaperSizeCount
&& (nPaperSizeCount
!= GDI_ERROR
) )
936 pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nPaperSizeCount
*sizeof(POINT
));
937 ImplDeviceCaps( pPrinter
, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
939 if ( (nPaperSizeCount
== nPaperCount
) && pPapers
&& pPaperSizes
)
941 PaperInfo
aInfo(pSetupData
->mnPaperWidth
, pSetupData
->mnPaperHeight
);
942 // compare paper formats and select a good match
943 for ( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
945 if ( aInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)))
952 // If the printer supports landscape orientation, check paper sizes again
953 // with landscape orientation. This is necessary as a printer driver provides
954 // all paper sizes with portrait orientation only!!
955 if ( !nPaper
&& nLandscapeAngle
!= 0 )
957 PaperInfo
aRotatedInfo(pSetupData
->mnPaperHeight
, pSetupData
->mnPaperWidth
);
958 for ( sal_uLong i
= 0; i
< nPaperCount
; i
++ )
960 if ( aRotatedInfo
.sloppyEqual(PaperInfo(pPaperSizes
[i
].x
*10, pPaperSizes
[i
].y
*10)) )
969 CHOOSE_DEVMODE(dmPaperSize
) = nPaper
;
974 CHOOSE_DEVMODE(dmFields
) |= DM_PAPERLENGTH
| DM_PAPERWIDTH
;
975 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_USER
;
976 CHOOSE_DEVMODE(dmPaperWidth
) = (short)(pSetupData
->mnPaperWidth
/10);
977 CHOOSE_DEVMODE(dmPaperLength
) = (short)(pSetupData
->mnPaperHeight
/10);
981 rtl_freeMemory(pPapers
);
983 rtl_freeMemory(pPaperSizes
);
989 if( (nFlags
& SAL_JOBSET_DUPLEXMODE
) )
991 switch( pSetupData
->meDuplexMode
)
994 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
995 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_SIMPLEX
;
997 case DUPLEX_SHORTEDGE
:
998 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
999 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_HORIZONTAL
;
1001 case DUPLEX_LONGEDGE
:
1002 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1003 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_VERTICAL
;
1005 case DUPLEX_UNKNOWN
:
1011 static HDC
ImplCreateICW_WithCatch( LPWSTR pDriver
,
1013 LPDEVMODEW pDevMode
)
1016 CATCH_DRIVER_EX_BEGIN
;
1017 hDC
= CreateICW( pDriver
, pDevice
, 0, pDevMode
);
1018 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1022 static HDC
ImplCreateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1025 LPDEVMODEW pDevMode
;
1026 if ( pSetupData
&& pSetupData
->mpDriverData
)
1027 pDevMode
= SAL_DEVMODE_W( pSetupData
);
1030 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1031 // pl: does this hold true for Unicode functions ?
1032 if( pPrinter
->maDriverName
.getLength() > 2048 || pPrinter
->maDeviceName
.getLength() > 2048 )
1034 sal_Unicode pDriverName
[ 4096 ];
1035 sal_Unicode pDeviceName
[ 4096 ];
1036 memcpy( pDriverName
, pPrinter
->maDriverName
.getStr(), pPrinter
->maDriverName
.getLength()*sizeof(sal_Unicode
));
1037 memset( pDriverName
+pPrinter
->maDriverName
.getLength(), 0, 32 );
1038 memcpy( pDeviceName
, pPrinter
->maDeviceName
.getStr(), pPrinter
->maDeviceName
.getLength()*sizeof(sal_Unicode
));
1039 memset( pDeviceName
+pPrinter
->maDeviceName
.getLength(), 0, 32 );
1040 hDC
= ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR
>(pDriverName
),
1041 reinterpret_cast< LPCWSTR
>(pDeviceName
),
1046 static WinSalGraphics
* ImplCreateSalPrnGraphics( HDC hDC
)
1048 WinSalGraphics
* pGraphics
= new WinSalGraphics(WinSalGraphics::PRINTER
, false, 0, /* CHECKME */ NULL
);
1049 pGraphics
->SetLayout( SalLayoutFlags::NONE
);
1050 pGraphics
->setHDC(hDC
);
1051 pGraphics
->InitGraphics();
1055 static bool ImplUpdateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1057 HDC hNewDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1061 if ( pPrinter
->mpGraphics
)
1063 pPrinter
->mpGraphics
->DeInitGraphics();
1064 DeleteDC( pPrinter
->mpGraphics
->getHDC() );
1065 delete pPrinter
->mpGraphics
;
1068 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hNewDC
);
1069 pPrinter
->mhDC
= hNewDC
;
1074 // - WinSalInstance -
1076 SalInfoPrinter
* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
1077 ImplJobSetup
* pSetupData
)
1079 WinSalInfoPrinter
* pPrinter
= new WinSalInfoPrinter
;
1080 if( ! pQueueInfo
->mpSysData
)
1081 GetPrinterQueueState( pQueueInfo
);
1082 pPrinter
->maDriverName
= pQueueInfo
->maDriver
;
1083 pPrinter
->maDeviceName
= pQueueInfo
->maPrinterName
;
1084 pPrinter
->maPortName
= pQueueInfo
->mpSysData
?
1085 *pQueueInfo
->mpSysData
1088 // check if the provided setup data match the actual printer
1089 ImplTestSalJobSetup( pPrinter
, pSetupData
, TRUE
);
1091 HDC hDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
1098 pPrinter
->mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
1099 pPrinter
->mhDC
= hDC
;
1100 if ( !pSetupData
->mpDriverData
)
1101 ImplUpdateSalJobSetup( pPrinter
, pSetupData
, FALSE
, NULL
);
1102 ImplDevModeToJobSetup( pPrinter
, pSetupData
, SAL_JOBSET_ALL
);
1103 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
1108 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
1113 // - WinSalInfoPrinter -
1115 WinSalInfoPrinter::WinSalInfoPrinter() :
1120 m_bPapersInit
= FALSE
;
1123 WinSalInfoPrinter::~WinSalInfoPrinter()
1127 mpGraphics
->DeInitGraphics();
1128 DeleteDC( mpGraphics
->getHDC() );
1133 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup
* pSetupData
)
1135 m_aPaperFormats
.clear();
1137 DWORD nCount
= ImplDeviceCaps( this, DC_PAPERSIZE
, NULL
, pSetupData
);
1138 if( nCount
== GDI_ERROR
)
1143 POINT
* pPaperSizes
= (POINT
*)rtl_allocateZeroMemory(nCount
*sizeof(POINT
));
1144 ImplDeviceCaps( this, DC_PAPERSIZE
, (BYTE
*)pPaperSizes
, pSetupData
);
1146 sal_Unicode
* pNamesBuffer
= (sal_Unicode
*)rtl_allocateMemory(nCount
*64*sizeof(sal_Unicode
));
1147 ImplDeviceCaps( this, DC_PAPERNAMES
, (BYTE
*)pNamesBuffer
, pSetupData
);
1148 for( DWORD i
= 0; i
< nCount
; ++i
)
1150 PaperInfo
aInfo(pPaperSizes
[i
].x
* 10, pPaperSizes
[i
].y
* 10);
1151 m_aPaperFormats
.push_back( aInfo
);
1153 rtl_freeMemory( pNamesBuffer
);
1154 rtl_freeMemory( pPaperSizes
);
1157 m_bPapersInit
= true;
1160 int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup
* pSetupData
)
1162 int nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1164 if( nRet
!= sal::static_int_cast
<int>( GDI_ERROR
) )
1167 return 900; // guess
1170 SalGraphics
* WinSalInfoPrinter::AcquireGraphics()
1181 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics
* )
1186 bool WinSalInfoPrinter::Setup( SalFrame
* pFrame
, ImplJobSetup
* pSetupData
)
1188 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, static_cast<WinSalFrame
*>(pFrame
) ) )
1190 ImplDevModeToJobSetup( this, pSetupData
, SAL_JOBSET_ALL
);
1191 return ImplUpdateSalPrnIC( this, pSetupData
);
1197 bool WinSalInfoPrinter::SetPrinterData( ImplJobSetup
* pSetupData
)
1199 if ( !ImplTestSalJobSetup( this, pSetupData
, FALSE
) )
1201 return ImplUpdateSalPrnIC( this, pSetupData
);
1204 bool WinSalInfoPrinter::SetData( sal_uLong nFlags
, ImplJobSetup
* pSetupData
)
1206 ImplJobSetupToDevMode( this, pSetupData
, nFlags
);
1207 if ( ImplUpdateSalJobSetup( this, pSetupData
, TRUE
, NULL
) )
1209 ImplDevModeToJobSetup( this, pSetupData
, nFlags
);
1210 return ImplUpdateSalPrnIC( this, pSetupData
);
1216 sal_uLong
WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pSetupData
)
1218 DWORD nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1219 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1225 OUString
WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup
* pSetupData
, sal_uLong nPaperBin
)
1227 OUString aPaperBinName
;
1229 DWORD nBins
= ImplDeviceCaps( this, DC_BINNAMES
, NULL
, pSetupData
);
1230 if ( (nPaperBin
< nBins
) && (nBins
!= GDI_ERROR
) )
1232 sal_Unicode
* pBuffer
= new sal_Unicode
[nBins
*24];
1233 DWORD nRet
= ImplDeviceCaps( this, DC_BINNAMES
, (BYTE
*)pBuffer
, pSetupData
);
1234 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1235 aPaperBinName
= OUString( pBuffer
+ (nPaperBin
*24) );
1239 return aPaperBinName
;
1242 sal_uLong
WinSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pSetupData
, sal_uInt16 nType
)
1248 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
1250 case PRINTER_CAPABILITIES_COPIES
:
1251 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1252 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1255 case PRINTER_CAPABILITIES_COLLATECOPIES
:
1256 nRet
= ImplDeviceCaps( this, DC_COLLATE
, NULL
, pSetupData
);
1257 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1259 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1260 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1265 case PRINTER_CAPABILITIES_SETORIENTATION
:
1266 nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1267 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1271 case PRINTER_CAPABILITIES_SETPAPERBIN
:
1272 nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1273 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1277 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
1278 case PRINTER_CAPABILITIES_SETPAPER
:
1279 nRet
= ImplDeviceCaps( this, DC_PAPERS
, NULL
, pSetupData
);
1280 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1288 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup
*,
1289 long& rOutWidth
, long& rOutHeight
,
1290 long& rPageOffX
, long& rPageOffY
,
1291 long& rPageWidth
, long& rPageHeight
)
1295 rOutWidth
= GetDeviceCaps( hDC
, HORZRES
);
1296 rOutHeight
= GetDeviceCaps( hDC
, VERTRES
);
1298 rPageOffX
= GetDeviceCaps( hDC
, PHYSICALOFFSETX
);
1299 rPageOffY
= GetDeviceCaps( hDC
, PHYSICALOFFSETY
);
1300 rPageWidth
= GetDeviceCaps( hDC
, PHYSICALWIDTH
);
1301 rPageHeight
= GetDeviceCaps( hDC
, PHYSICALHEIGHT
);
1304 // - WinSalInstance -
1306 SalPrinter
* WinSalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
1308 WinSalPrinter
* pPrinter
= new WinSalPrinter
;
1309 pPrinter
->mpInfoPrinter
= static_cast<WinSalInfoPrinter
*>(pInfoPrinter
);
1313 void WinSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
1318 BOOL CALLBACK
SalPrintAbortProc( HDC hPrnDC
, int /* nError */ )
1320 SalData
* pSalData
= GetSalData();
1321 WinSalPrinter
* pPrinter
;
1329 if ( PeekMessageW( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1331 TranslateMessage( &aMsg
);
1332 DispatchMessageW( &aMsg
);
1341 pPrinter
= pSalData
->mpFirstPrinter
;
1344 if( pPrinter
->mhDC
== hPrnDC
)
1347 pPrinter
= pPrinter
->mpNextPrinter
;
1350 if ( !pPrinter
|| pPrinter
->mbAbort
)
1358 static LPDEVMODEW
ImplSalSetCopies( LPDEVMODEW pDevMode
, sal_uLong nCopies
, bool bCollate
)
1360 LPDEVMODEW pNewDevMode
= pDevMode
;
1361 if ( pDevMode
&& (nCopies
> 1) )
1363 if ( nCopies
> 32765 )
1365 sal_uLong nDevSize
= pDevMode
->dmSize
+pDevMode
->dmDriverExtra
;
1366 pNewDevMode
= (LPDEVMODEW
)rtl_allocateMemory( nDevSize
);
1367 memcpy( pNewDevMode
, pDevMode
, nDevSize
);
1368 pDevMode
= pNewDevMode
;
1369 pDevMode
->dmFields
|= DM_COPIES
;
1370 pDevMode
->dmCopies
= (short)(sal_uInt16
)nCopies
;
1371 pDevMode
->dmFields
|= DM_COLLATE
;
1373 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1375 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
1381 // - WinSalPrinter -
1383 WinSalPrinter::WinSalPrinter() :
1385 mpInfoPrinter( NULL
),
1386 mpNextPrinter( NULL
),
1394 SalData
* pSalData
= GetSalData();
1395 // insert printer in printerlist
1396 mpNextPrinter
= pSalData
->mpFirstPrinter
;
1397 pSalData
->mpFirstPrinter
= this;
1400 WinSalPrinter::~WinSalPrinter()
1402 SalData
* pSalData
= GetSalData();
1404 // release DC if there is one still around because of AbortJob
1410 mpGraphics
->DeInitGraphics();
1417 // remove printer from printerlist
1418 if ( this == pSalData
->mpFirstPrinter
)
1419 pSalData
->mpFirstPrinter
= mpNextPrinter
;
1422 WinSalPrinter
* pTempPrinter
= pSalData
->mpFirstPrinter
;
1424 while( pTempPrinter
->mpNextPrinter
!= this )
1425 pTempPrinter
= pTempPrinter
->mpNextPrinter
;
1427 pTempPrinter
->mpNextPrinter
= mpNextPrinter
;
1432 void WinSalPrinter::markInvalid()
1437 // need wrappers for StarTocW/A to use structured exception handling
1438 // since SEH does not mix with standard exception handling's cleanup
1439 static int lcl_StartDocW( HDC hDC
, DOCINFOW
* pInfo
, WinSalPrinter
* pPrt
)
1443 CATCH_DRIVER_EX_BEGIN
;
1444 nRet
= ::StartDocW( hDC
, pInfo
);
1445 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1449 bool WinSalPrinter::StartJob( const OUString
* pFileName
,
1450 const OUString
& rJobName
,
1455 ImplJobSetup
* pSetupData
)
1460 mbCollate
= bCollate
;
1462 LPDEVMODEW pOrgDevModeW
= NULL
;
1463 LPDEVMODEW pDevModeW
= NULL
;
1465 if ( pSetupData
&& pSetupData
->mpDriverData
)
1467 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1468 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, nCopies
, bCollate
);
1471 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1472 sal_Unicode aDrvBuf
[4096];
1473 sal_Unicode aDevBuf
[4096];
1474 memcpy( aDrvBuf
, mpInfoPrinter
->maDriverName
.getStr(), (mpInfoPrinter
->maDriverName
.getLength()+1)*sizeof(sal_Unicode
));
1475 memcpy( aDevBuf
, mpInfoPrinter
->maDeviceName
.getStr(), (mpInfoPrinter
->maDeviceName
.getLength()+1)*sizeof(sal_Unicode
));
1476 hDC
= CreateDCW( reinterpret_cast<LPCWSTR
>(aDrvBuf
),
1477 reinterpret_cast<LPCWSTR
>(aDevBuf
),
1481 if ( pDevModeW
!= pOrgDevModeW
)
1482 rtl_freeMemory( pDevModeW
);
1486 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1490 // make sure mhDC is set before the printer driver may call our abortproc
1492 if ( SetAbortProc( hDC
, SalPrintAbortProc
) <= 0 )
1494 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1501 // As the Telocom Balloon Fax driver tends to send messages repeatedly
1502 // we try to process first all, and then insert a dummy message
1509 if ( PeekMessageW( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1511 TranslateMessage( &aMsg
);
1512 DispatchMessageW( &aMsg
);
1522 PostMessageW( GetSalData()->mpFirstInstance
->mhComWnd
, SAL_MSG_DUMMY
, 0, 0 );
1524 // bring up a file choser if printing to file port but no file name given
1525 OUString aOutFileName
;
1526 if( mpInfoPrinter
->maPortName
.equalsIgnoreAsciiCase( "FILE:" ) && !(pFileName
&& !pFileName
->isEmpty()) )
1529 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1530 uno::Reference
< XFilePicker3
> xFilePicker
= FilePicker::createWithMode(xContext
, TemplateDescription::FILESAVE_SIMPLE
);
1532 if( xFilePicker
->execute() == ExecutableDialogResults::OK
)
1534 Sequence
< OUString
> aPathSeq( xFilePicker
->getFiles() );
1535 INetURLObject
aObj( aPathSeq
[0] );
1536 // we're using ansi calls (StartDocA) so convert the string
1537 aOutFileName
= aObj
.PathToFileName();
1541 mnError
= SAL_PRINTER_ERROR_ABORT
;
1547 memset( &aInfo
, 0, sizeof( DOCINFOW
) );
1548 aInfo
.cbSize
= sizeof( aInfo
);
1549 aInfo
.lpszDocName
= (LPWSTR
)rJobName
.getStr();
1550 if ( pFileName
|| aOutFileName
.getLength() )
1552 if ( (pFileName
&& !pFileName
->isEmpty()) || aOutFileName
.getLength() )
1554 aInfo
.lpszOutput
= (LPWSTR
)( (pFileName
&& !pFileName
->isEmpty()) ? pFileName
->getStr() : aOutFileName
.getStr());
1557 aInfo
.lpszOutput
= L
"FILE:";
1560 aInfo
.lpszOutput
= NULL
;
1563 int nRet
= lcl_StartDocW( hDC
, &aInfo
, this );
1567 long nError
= GetLastError();
1568 if ( (nRet
== SP_USERABORT
) || (nRet
== SP_APPABORT
) || (nError
== ERROR_PRINT_CANCELLED
) || (nError
== ERROR_CANCELLED
) )
1569 mnError
= SAL_PRINTER_ERROR_ABORT
;
1571 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1578 bool WinSalPrinter::EndJob()
1581 if ( isValid() && hDC
)
1585 mpGraphics
->DeInitGraphics();
1590 // #i54419# Windows fax printer brings up a dialog in EndDoc
1591 // which text previously copied in soffice process can be
1592 // pasted to -> deadlock due to mutex not released.
1593 // it should be safe to release the yield mutex over the EndDoc
1594 // call, however the real solution is supposed to be the threading
1595 // framework yet to come.
1596 volatile sal_uLong nAcquire
= GetSalData()->mpFirstInstance
->ReleaseYieldMutex();
1597 CATCH_DRIVER_EX_BEGIN
;
1598 if( ::EndDoc( hDC
) <= 0 )
1600 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
1602 GetSalData()->mpFirstInstance
->AcquireYieldMutex( nAcquire
);
1610 bool WinSalPrinter::AbortJob()
1614 // trigger Abort asynchronously
1618 SalData
* pSalData
= GetSalData();
1619 PostMessageW( pSalData
->mpFirstInstance
->mhComWnd
,
1620 SAL_MSG_PRINTABORTJOB
, (WPARAM
)hDC
, 0 );
1626 void ImplSalPrinterAbortJobAsync( HDC hPrnDC
)
1628 SalData
* pSalData
= GetSalData();
1629 WinSalPrinter
* pPrinter
= pSalData
->mpFirstPrinter
;
1631 // check if printer still exists
1634 if ( pPrinter
->mhDC
== hPrnDC
)
1637 pPrinter
= pPrinter
->mpNextPrinter
;
1640 // if printer still exists, cancel the job
1643 HDC hDC
= pPrinter
->mhDC
;
1646 if ( pPrinter
->mpGraphics
)
1648 pPrinter
->mpGraphics
->DeInitGraphics();
1649 delete pPrinter
->mpGraphics
;
1650 pPrinter
->mpGraphics
= NULL
;
1653 CATCH_DRIVER_EX_BEGIN
;
1655 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter
);
1663 SalGraphics
* WinSalPrinter::StartPage( ImplJobSetup
* pSetupData
, bool bNewJobData
)
1665 if( ! isValid() || mhDC
== 0 )
1669 if ( pSetupData
&& pSetupData
->mpDriverData
&& bNewJobData
)
1671 LPDEVMODEW pOrgDevModeW
;
1672 LPDEVMODEW pDevModeW
;
1673 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1674 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, mnCopies
, mbCollate
);
1675 ResetDCW( hDC
, pDevModeW
);
1676 if ( pDevModeW
!= pOrgDevModeW
)
1677 rtl_freeMemory( pDevModeW
);
1679 volatile int nRet
= 0;
1680 CATCH_DRIVER_EX_BEGIN
;
1681 nRet
= ::StartPage( hDC
);
1682 CATCH_DRIVER_EX_END( "exception in StartPage", this );
1687 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1691 // Hack to work around old PostScript printer drivers optimizing away empty pages
1692 // TODO: move into ImplCreateSalPrnGraphics()?
1693 HPEN hTempPen
= SelectPen( hDC
, GetStockPen( NULL_PEN
) );
1694 HBRUSH hTempBrush
= SelectBrush( hDC
, GetStockBrush( NULL_BRUSH
) );
1695 WIN_Rectangle( hDC
, -8000, -8000, -7999, -7999 );
1696 SelectPen( hDC
, hTempPen
);
1697 SelectBrush( hDC
, hTempBrush
);
1699 mpGraphics
= ImplCreateSalPrnGraphics( hDC
);
1703 bool WinSalPrinter::EndPage()
1706 if ( hDC
&& mpGraphics
)
1708 mpGraphics
->DeInitGraphics();
1716 volatile int nRet
= 0;
1717 CATCH_DRIVER_EX_BEGIN
;
1718 nRet
= ::EndPage( hDC
);
1719 CATCH_DRIVER_EX_END( "exception in EndPage", this );
1726 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
1731 sal_uLong
WinSalPrinter::GetErrorCode()
1736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */