Bump version to 4.1-6
[LibreOffice.git] / vcl / win / source / gdi / salprn.cxx
blob94af77c514dc407231f5a30e3fae7c8a29ec0750
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #define WINVER 0x0500
23 #include <string.h>
25 #include <svsys.h>
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>
39 #include <print.h>
40 #include <jobset.h>
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>
50 #include <malloc.h>
52 #ifdef __MINGW32__
53 #include <sehandler.hxx>
54 #endif
56 #ifdef __MINGW32__
57 #define CATCH_DRIVER_EX_BEGIN \
58 jmp_buf jmpbuf; \
59 __SEHandler han; \
60 if (__builtin_setjmp(jmpbuf) == 0) \
61 { \
62 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
64 #define CATCH_DRIVER_EX_END(mes, p) \
65 } \
66 han.Reset()
67 #define CATCH_DRIVER_EX_END_2(mes) \
68 } \
69 han.Reset()
70 #else
71 #define CATCH_DRIVER_EX_BEGIN \
72 __try \
74 #define CATCH_DRIVER_EX_END(mes, p) \
75 } \
76 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
77 { \
78 OSL_FAIL( mes ); \
79 p->markInvalid(); \
81 #define CATCH_DRIVER_EX_END_2(mes) \
82 } \
83 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
84 { \
85 OSL_FAIL( mes ); \
87 #endif
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)));
106 return pRet;
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;
164 return nStatus;
167 // -----------------------------------------------------------------------
169 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
171 DWORD i;
172 DWORD nBytes = 0;
173 DWORD nInfoPrn4 = 0;
174 EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 );
175 if ( nBytes )
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) );
184 pInfo->mnStatus = 0;
185 pInfo->mnJobs = 0;
186 pInfo->mpSysData = NULL;
187 pList->Add( pInfo );
190 rtl_freeMemory( pWinInfo4 );
194 // -----------------------------------------------------------------------
196 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
198 HANDLE hPrinter = 0;
199 LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.getStr()));
200 if( OpenPrinterW( pPrnName, &hPrinter, NULL ) )
202 DWORD nBytes = 0;
203 GetPrinterW( hPrinter, 2, NULL, 0, &nBytes );
204 if( 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) );
211 XubString aPortName;
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) );
217 else
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;
238 delete pInfo;
241 // -----------------------------------------------------------------------
242 OUString WinSalInstance::GetDefaultPrinter()
244 DWORD nChars = 0;
245 GetDefaultPrinterW( NULL, &nChars );
246 if( nChars )
248 LPWSTR pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR));
249 XubString aDefPrt;
250 if( GetDefaultPrinterW( pStr, &nChars ) )
252 aDefPrt = reinterpret_cast<sal_Unicode* >(pStr);
254 rtl_freeMemory( pStr );
255 if( aDefPrt.Len() )
256 return aDefPrt;
259 // get default printer from win.ini
260 char szBuffer[256];
261 GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) );
262 if ( szBuffer[0] )
264 // Printername suchen
265 char* pBuf = szBuffer;
266 char* pTmp = pBuf;
267 while ( *pTmp && (*pTmp != ',') )
268 pTmp++;
269 return ImplSalGetUniString( pBuf, static_cast<sal_Int32>(pTmp-pBuf) );
271 else
272 return OUString();
275 // =======================================================================
277 static DWORD ImplDeviceCaps( WinSalInfoPrinter* pPrinter, WORD nCaps,
278 BYTE* pOutput, const ImplJobSetup* pSetupData )
280 DEVMODEW* pDevMode;
281 if ( !pSetupData || !pSetupData->mpDriverData )
282 pDevMode = NULL;
283 else
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#
317 HANDLE hPrn;
318 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.getStr()));
319 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
320 return FALSE;
322 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
323 if( hPrn == HGDI_ERROR )
324 return FALSE;
326 nSysJobSize = DocumentPropertiesW( 0, hPrn,
327 pPrinterNameW,
328 NULL, NULL, 0 );
330 if( nSysJobSize < 0 )
332 ClosePrinter( hPrn );
333 return FALSE;
335 BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize );
336 LONG nRet = DocumentPropertiesW( 0, hPrn,
337 pPrinterNameW,
338 (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER );
339 if( nRet < 0 )
341 ClosePrinter( hPrn );
342 return FALSE;
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 )
360 if( pDevModeW &&
361 (dmSpecVersion == pDevModeW->dmSpecVersion) &&
362 (dmDriverVersion == pDevModeW->dmDriverVersion) )
363 return TRUE;
365 if ( bDelete )
367 rtl_freeMemory( pSetupData->mpDriverData );
368 pSetupData->mpDriverData = NULL;
369 pSetupData->mnDriverDataLen = 0;
373 return FALSE;
376 // -----------------------------------------------------------------------
378 static sal_Bool ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData,
379 sal_Bool bIn, WinSalFrame* pVisibleDlgParent )
381 HANDLE hPrn;
382 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.getStr()));
383 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
384 return FALSE;
385 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
386 if( hPrn == HGDI_ERROR )
387 return FALSE;
389 LONG nRet;
390 HWND hWnd = 0;
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,
397 pPrinterNameW,
398 NULL, NULL, 0 );
399 if ( nSysJobSize < 0 )
401 ClosePrinter( hPrn );
402 return FALSE;
405 // make Outputbuffer
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 -
412 (char*)pOutBuffer );
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,
435 pPrinterNameW,
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 );
444 return FALSE;
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)) );
461 // update data
462 if ( pSetupData->mpDriverData )
463 rtl_freeMemory( pSetupData->mpDriverData );
464 pSetupData->mnDriverDataLen = nDriverDataLen;
465 pSetupData->mpDriverData = (BYTE*)pOutBuffer;
466 pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
468 return TRUE;
471 // -----------------------------------------------------------------------
473 #define DECLARE_DEVMODE( i )\
474 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
475 if( pDevModeW == NULL )\
476 return
478 #define CHOOSE_DEVMODE(i)\
479 (pDevModeW->i)
481 static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags )
483 if ( !pSetupData || !pSetupData->mpDriverData )
484 return;
486 DECLARE_DEVMODE( pSetupData );
488 // Orientation
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;
497 // PaperBin
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;
514 break;
518 rtl_freeMemory( pBins );
522 // PaperSize
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;
530 else
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;
554 break;
558 if( pPapers )
559 rtl_freeMemory( pPapers );
560 if( pPaperSizes )
561 rtl_freeMemory( pPaperSizes );
563 switch( CHOOSE_DEVMODE(dmPaperSize) )
565 case( DMPAPER_LETTER ):
566 pSetupData->mePaperFormat = PAPER_LETTER;
567 break;
568 case( DMPAPER_TABLOID ):
569 pSetupData->mePaperFormat = PAPER_TABLOID;
570 break;
571 case( DMPAPER_LEDGER ):
572 pSetupData->mePaperFormat = PAPER_LEDGER;
573 break;
574 case( DMPAPER_LEGAL ):
575 pSetupData->mePaperFormat = PAPER_LEGAL;
576 break;
577 case( DMPAPER_STATEMENT ):
578 pSetupData->mePaperFormat = PAPER_STATEMENT;
579 break;
580 case( DMPAPER_EXECUTIVE ):
581 pSetupData->mePaperFormat = PAPER_EXECUTIVE;
582 break;
583 case( DMPAPER_A3 ):
584 pSetupData->mePaperFormat = PAPER_A3;
585 break;
586 case( DMPAPER_A4 ):
587 pSetupData->mePaperFormat = PAPER_A4;
588 break;
589 case( DMPAPER_A5 ):
590 pSetupData->mePaperFormat = PAPER_A5;
591 break;
592 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
593 //i.e.
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
599 //enumeration.
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
604 //(cmc)
605 case( DMPAPER_B4 ):
606 pSetupData->mePaperFormat = PAPER_B4_JIS;
607 break;
608 case( DMPAPER_B5 ):
609 pSetupData->mePaperFormat = PAPER_B5_JIS;
610 break;
611 case( DMPAPER_QUARTO ):
612 pSetupData->mePaperFormat = PAPER_QUARTO;
613 break;
614 case( DMPAPER_10X14 ):
615 pSetupData->mePaperFormat = PAPER_10x14;
616 break;
617 case( DMPAPER_NOTE ):
618 pSetupData->mePaperFormat = PAPER_LETTER;
619 break;
620 case( DMPAPER_ENV_9 ):
621 pSetupData->mePaperFormat = PAPER_ENV_9;
622 break;
623 case( DMPAPER_ENV_10 ):
624 pSetupData->mePaperFormat = PAPER_ENV_10;
625 break;
626 case( DMPAPER_ENV_11 ):
627 pSetupData->mePaperFormat = PAPER_ENV_11;
628 break;
629 case( DMPAPER_ENV_12 ):
630 pSetupData->mePaperFormat = PAPER_ENV_12;
631 break;
632 case( DMPAPER_ENV_14 ):
633 pSetupData->mePaperFormat = PAPER_ENV_14;
634 break;
635 case( DMPAPER_CSHEET ):
636 pSetupData->mePaperFormat = PAPER_C;
637 break;
638 case( DMPAPER_DSHEET ):
639 pSetupData->mePaperFormat = PAPER_D;
640 break;
641 case( DMPAPER_ESHEET ):
642 pSetupData->mePaperFormat = PAPER_E;
643 break;
644 case( DMPAPER_ENV_DL):
645 pSetupData->mePaperFormat = PAPER_ENV_DL;
646 break;
647 case( DMPAPER_ENV_C5):
648 pSetupData->mePaperFormat = PAPER_ENV_C5;
649 break;
650 case( DMPAPER_ENV_C3):
651 pSetupData->mePaperFormat = PAPER_ENV_C3;
652 break;
653 case( DMPAPER_ENV_C4):
654 pSetupData->mePaperFormat = PAPER_ENV_C4;
655 break;
656 case( DMPAPER_ENV_C6):
657 pSetupData->mePaperFormat = PAPER_ENV_C6;
658 break;
659 case( DMPAPER_ENV_C65):
660 pSetupData->mePaperFormat = PAPER_ENV_C65;
661 break;
662 case( DMPAPER_ENV_ITALY ):
663 pSetupData->mePaperFormat = PAPER_ENV_ITALY;
664 break;
665 case( DMPAPER_ENV_MONARCH ):
666 pSetupData->mePaperFormat = PAPER_ENV_MONARCH;
667 break;
668 case( DMPAPER_ENV_PERSONAL ):
669 pSetupData->mePaperFormat = PAPER_ENV_PERSONAL;
670 break;
671 case( DMPAPER_FANFOLD_US ):
672 pSetupData->mePaperFormat = PAPER_FANFOLD_US;
673 break;
674 case( DMPAPER_FANFOLD_STD_GERMAN ):
675 pSetupData->mePaperFormat = PAPER_FANFOLD_DE;
676 break;
677 case( DMPAPER_FANFOLD_LGL_GERMAN ):
678 pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE;
679 break;
680 case( DMPAPER_ISO_B4 ):
681 pSetupData->mePaperFormat = PAPER_B4_ISO;
682 break;
683 case( DMPAPER_JAPANESE_POSTCARD ):
684 pSetupData->mePaperFormat = PAPER_POSTCARD_JP;
685 break;
686 case( DMPAPER_9X11 ):
687 pSetupData->mePaperFormat = PAPER_9x11;
688 break;
689 case( DMPAPER_10X11 ):
690 pSetupData->mePaperFormat = PAPER_10x11;
691 break;
692 case( DMPAPER_15X11 ):
693 pSetupData->mePaperFormat = PAPER_15x11;
694 break;
695 case( DMPAPER_ENV_INVITE ):
696 pSetupData->mePaperFormat = PAPER_ENV_INVITE;
697 break;
698 case( DMPAPER_A_PLUS ):
699 pSetupData->mePaperFormat = PAPER_A_PLUS;
700 break;
701 case( DMPAPER_B_PLUS ):
702 pSetupData->mePaperFormat = PAPER_B_PLUS;
703 break;
704 case( DMPAPER_LETTER_PLUS ):
705 pSetupData->mePaperFormat = PAPER_LETTER_PLUS;
706 break;
707 case( DMPAPER_A4_PLUS ):
708 pSetupData->mePaperFormat = PAPER_A4_PLUS;
709 break;
710 case( DMPAPER_A2 ):
711 pSetupData->mePaperFormat = PAPER_A2;
712 break;
713 case( DMPAPER_DBL_JAPANESE_POSTCARD ):
714 pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP;
715 break;
716 case( DMPAPER_A6 ):
717 pSetupData->mePaperFormat = PAPER_A6;
718 break;
719 case( DMPAPER_B6_JIS ):
720 pSetupData->mePaperFormat = PAPER_B6_JIS;
721 break;
722 case( DMPAPER_12X11 ):
723 pSetupData->mePaperFormat = PAPER_12x11;
724 break;
725 default:
726 pSetupData->mePaperFormat = PAPER_USER;
727 break;
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 )
752 return;
754 DECLARE_DEVMODE( pSetupData );
756 // Orientation
757 if ( nFlags & SAL_JOBSET_ORIENTATION )
759 CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION;
760 if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT )
761 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT;
762 else
763 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE;
766 // PaperBin
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 );
781 // PaperSize
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 )
790 case( PAPER_A2 ):
791 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2;
792 break;
793 case( PAPER_A3 ):
794 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3;
795 break;
796 case( PAPER_A4 ):
797 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4;
798 break;
799 case( PAPER_A5 ):
800 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5;
801 break;
802 case( PAPER_B4_ISO):
803 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4;
804 break;
805 case( PAPER_LETTER ):
806 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER;
807 break;
808 case( PAPER_LEGAL ):
809 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL;
810 break;
811 case( PAPER_TABLOID ):
812 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID;
813 break;
814 #if 0
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;
824 break;
825 #endif
826 case( PAPER_ENV_C4 ):
827 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4;
828 break;
829 case( PAPER_ENV_C5 ):
830 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5;
831 break;
832 case( PAPER_ENV_C6 ):
833 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6;
834 break;
835 case( PAPER_ENV_C65 ):
836 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65;
837 break;
838 case( PAPER_ENV_DL ):
839 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL;
840 break;
841 case( PAPER_C ):
842 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET;
843 break;
844 case( PAPER_D ):
845 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET;
846 break;
847 case( PAPER_E ):
848 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET;
849 break;
850 case( PAPER_EXECUTIVE ):
851 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE;
852 break;
853 case( PAPER_FANFOLD_LEGAL_DE ):
854 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN;
855 break;
856 case( PAPER_ENV_MONARCH ):
857 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH;
858 break;
859 case( PAPER_ENV_PERSONAL ):
860 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL;
861 break;
862 case( PAPER_ENV_9 ):
863 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9;
864 break;
865 case( PAPER_ENV_10 ):
866 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10;
867 break;
868 case( PAPER_ENV_11 ):
869 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11;
870 break;
871 case( PAPER_ENV_12 ):
872 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12;
873 break;
874 //See the comments on DMPAPER_B4 above
875 case( PAPER_B4_JIS ):
876 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4;
877 break;
878 case( PAPER_B5_JIS ):
879 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5;
880 break;
881 case( PAPER_B6_JIS ):
882 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS;
883 break;
884 case( PAPER_LEDGER ):
885 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER;
886 break;
887 case( PAPER_STATEMENT ):
888 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT;
889 break;
890 case( PAPER_10x14 ):
891 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14;
892 break;
893 case( PAPER_ENV_14 ):
894 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14;
895 break;
896 case( PAPER_ENV_C3 ):
897 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3;
898 break;
899 case( PAPER_ENV_ITALY ):
900 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY;
901 break;
902 case( PAPER_FANFOLD_US ):
903 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US;
904 break;
905 case( PAPER_FANFOLD_DE ):
906 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN;
907 break;
908 case( PAPER_POSTCARD_JP ):
909 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD;
910 break;
911 case( PAPER_9x11 ):
912 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11;
913 break;
914 case( PAPER_10x11 ):
915 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11;
916 break;
917 case( PAPER_15x11 ):
918 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11;
919 break;
920 case( PAPER_ENV_INVITE ):
921 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE;
922 break;
923 case( PAPER_A_PLUS ):
924 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS;
925 break;
926 case( PAPER_B_PLUS ):
927 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS;
928 break;
929 case( PAPER_LETTER_PLUS ):
930 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS;
931 break;
932 case( PAPER_A4_PLUS ):
933 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS;
934 break;
935 case( PAPER_DOUBLEPOSTCARD_JP ):
936 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD;
937 break;
938 case( PAPER_A6 ):
939 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6;
940 break;
941 case( PAPER_12x11 ):
942 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11;
943 break;
944 default:
946 short nPaper = 0;
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)))
970 nPaper = pPapers[i];
971 break;
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)) )
985 nPaper = pPapers[i];
986 break;
991 if ( nPaper )
992 CHOOSE_DEVMODE(dmPaperSize) = nPaper;
995 if ( !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);
1003 if ( pPapers )
1004 rtl_freeMemory(pPapers);
1005 if ( pPaperSizes )
1006 rtl_freeMemory(pPaperSizes);
1008 break;
1012 if( (nFlags & SAL_JOBSET_DUPLEXMODE) )
1014 switch( pSetupData->meDuplexMode )
1016 case DUPLEX_OFF:
1017 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1018 CHOOSE_DEVMODE(dmDuplex) = DMDUP_SIMPLEX;
1019 break;
1020 case DUPLEX_SHORTEDGE:
1021 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1022 CHOOSE_DEVMODE(dmDuplex) = DMDUP_HORIZONTAL;
1023 break;
1024 case DUPLEX_LONGEDGE:
1025 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1026 CHOOSE_DEVMODE(dmDuplex) = DMDUP_VERTICAL;
1027 break;
1028 case DUPLEX_UNKNOWN:
1029 break;
1034 // -----------------------------------------------------------------------
1036 static HDC ImplCreateICW_WithCatch( LPWSTR pDriver,
1037 LPCWSTR pDevice,
1038 LPDEVMODEW pDevMode )
1040 HDC hDC = 0;
1041 CATCH_DRIVER_EX_BEGIN;
1042 hDC = CreateICW( pDriver, pDevice, 0, pDevMode );
1043 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1044 return hDC;
1047 static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1049 HDC hDC = 0;
1050 LPDEVMODEW pDevMode;
1051 if ( pSetupData && pSetupData->mpDriverData )
1052 pDevMode = SAL_DEVMODE_W( pSetupData );
1053 else
1054 pDevMode = NULL;
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 )
1058 return 0;
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),
1067 pDevMode );
1068 return hDC;
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 );
1084 return pGraphics;
1087 // -----------------------------------------------------------------------
1089 static sal_Bool ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1091 HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1092 if ( !hNewDC )
1093 return FALSE;
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;
1105 return TRUE;
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
1120 : OUString();
1122 // check if the provided setup data match the actual printer
1123 ImplTestSalJobSetup( pPrinter, pSetupData, TRUE );
1125 HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1126 if ( !hDC )
1128 delete pPrinter;
1129 return NULL;
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;
1139 return pPrinter;
1142 // -----------------------------------------------------------------------
1144 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
1146 delete pPrinter;
1149 // =======================================================================
1151 WinSalInfoPrinter::WinSalInfoPrinter() :
1152 mpGraphics( NULL ),
1153 mhDC( 0 ),
1154 mbGraphics( FALSE )
1156 m_bPapersInit = FALSE;
1159 // -----------------------------------------------------------------------
1161 WinSalInfoPrinter::~WinSalInfoPrinter()
1163 if ( mpGraphics )
1165 ImplSalDeInitGraphics( mpGraphics );
1166 DeleteDC( mpGraphics->mhDC );
1167 delete mpGraphics;
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 )
1179 nCount = 0;
1181 if( nCount )
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 ) )
1207 return nRet * 10;
1208 else
1209 return 900; // guess
1212 // -----------------------------------------------------------------------
1214 SalGraphics* WinSalInfoPrinter::GetGraphics()
1216 if ( mbGraphics )
1217 return NULL;
1219 if ( mpGraphics )
1220 mbGraphics = TRUE;
1222 return mpGraphics;
1225 // -----------------------------------------------------------------------
1227 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics* )
1229 mbGraphics = FALSE;
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 );
1242 return FALSE;
1245 // -----------------------------------------------------------------------
1247 sal_Bool WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
1249 if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) )
1250 return 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 );
1265 return FALSE;
1268 // -----------------------------------------------------------------------
1270 sal_uLong WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData )
1272 DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1273 if ( nRet && (nRet != GDI_ERROR) )
1274 return nRet;
1275 else
1276 return 0;
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);
1292 delete [] pBuffer;
1295 return aPaperBinName;
1298 // -----------------------------------------------------------------------
1300 sal_uLong WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, sal_uInt16 nType )
1302 DWORD nRet;
1304 switch ( nType )
1306 case PRINTER_CAPABILITIES_SUPPORTDIALOG:
1307 return TRUE;
1308 case PRINTER_CAPABILITIES_COPIES:
1309 nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
1310 if ( nRet && (nRet != GDI_ERROR) )
1311 return nRet;
1312 return 0;
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) )
1319 return nRet;
1321 return 0;
1323 case PRINTER_CAPABILITIES_SETORIENTATION:
1324 nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
1325 if ( nRet && (nRet != GDI_ERROR) )
1326 return TRUE;
1327 return FALSE;
1329 case PRINTER_CAPABILITIES_SETPAPERBIN:
1330 nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1331 if ( nRet && (nRet != GDI_ERROR) )
1332 return TRUE;
1333 return FALSE;
1335 case PRINTER_CAPABILITIES_SETPAPERSIZE:
1336 case PRINTER_CAPABILITIES_SETPAPER:
1337 nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData );
1338 if ( nRet && (nRet != GDI_ERROR) )
1339 return TRUE;
1340 return FALSE;
1343 return 0;
1346 // -----------------------------------------------------------------------
1348 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
1349 long& rOutWidth, long& rOutHeight,
1350 long& rPageOffX, long& rPageOffY,
1351 long& rPageWidth, long& rPageHeight )
1353 HDC hDC = mhDC;
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);
1370 return pPrinter;
1373 // -----------------------------------------------------------------------
1375 void WinSalInstance::DestroyPrinter( SalPrinter* pPrinter )
1377 delete pPrinter;
1380 // =======================================================================
1382 BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
1384 SalData* pSalData = GetSalData();
1385 WinSalPrinter* pPrinter;
1386 sal_Bool bWhile = TRUE;
1387 int i = 0;
1391 // Messages verarbeiten
1392 MSG aMsg;
1393 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
1395 TranslateMessage( &aMsg );
1396 ImplDispatchMessage( &aMsg );
1398 i++;
1399 if ( i > 15 )
1400 bWhile = FALSE;
1402 else
1403 bWhile = FALSE;
1405 pPrinter = pSalData->mpFirstPrinter;
1406 while ( pPrinter )
1408 if( pPrinter->mhDC == hPrnDC )
1409 break;
1411 pPrinter = pPrinter->mpNextPrinter;
1414 if ( !pPrinter || pPrinter->mbAbort )
1415 return FALSE;
1417 while ( bWhile );
1419 return TRUE;
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 )
1430 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;
1438 if ( bCollate )
1439 pDevMode->dmCollate = DMCOLLATE_TRUE;
1440 else
1441 pDevMode->dmCollate = DMCOLLATE_FALSE;
1444 return pNewDevMode;
1447 // -----------------------------------------------------------------------
1449 WinSalPrinter::WinSalPrinter() :
1450 mpGraphics( NULL ),
1451 mpInfoPrinter( NULL ),
1452 mpNextPrinter( NULL ),
1453 mhDC( 0 ),
1454 mnError( 0 ),
1455 mnCopies( 0 ),
1456 mbCollate( FALSE ),
1457 mbAbort( FALSE ),
1458 mbValid( true )
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
1473 HDC hDC = mhDC;
1474 if ( hDC )
1476 if ( mpGraphics )
1478 ImplSalDeInitGraphics( mpGraphics );
1479 delete mpGraphics;
1482 DeleteDC( hDC );
1485 // remove printer from printerlist
1486 if ( this == pSalData->mpFirstPrinter )
1487 pSalData->mpFirstPrinter = mpNextPrinter;
1488 else
1490 WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
1492 while( pTempPrinter->mpNextPrinter != this )
1493 pTempPrinter = pTempPrinter->mpNextPrinter;
1495 pTempPrinter->mpNextPrinter = mpNextPrinter;
1497 mbValid = false;
1500 // -----------------------------------------------------------------------
1502 void WinSalPrinter::markInvalid()
1504 mbValid = false;
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 )
1513 (void) pPrt;
1514 int nRet = 0;
1515 CATCH_DRIVER_EX_BEGIN;
1516 nRet = ::StartDocW( hDC, pInfo );
1517 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1518 return nRet;
1521 sal_Bool WinSalPrinter::StartJob( const OUString* pFileName,
1522 const OUString& rJobName,
1523 const OUString&,
1524 sal_uLong nCopies,
1525 bool bCollate,
1526 bool /*bDirect*/,
1527 ImplJobSetup* pSetupData )
1529 mnError = 0;
1530 mbAbort = FALSE;
1531 mnCopies = nCopies;
1532 mbCollate = bCollate;
1534 LPDEVMODEW pOrgDevModeW = NULL;
1535 LPDEVMODEW pDevModeW = NULL;
1536 HDC hDC = 0;
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),
1550 NULL,
1551 pDevModeW );
1553 if ( pDevModeW != pOrgDevModeW )
1554 rtl_freeMemory( pDevModeW );
1556 if ( !hDC )
1558 mnError = SAL_PRINTER_ERROR_GENERALERROR;
1559 return FALSE;
1562 // make sure mhDC is set before the printer driver may call our abortproc
1563 mhDC = hDC;
1564 if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
1566 mnError = SAL_PRINTER_ERROR_GENERALERROR;
1567 return FALSE;
1570 mnError = 0;
1571 mbAbort = FALSE;
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;
1576 int i = 0;
1579 // process messages
1580 MSG aMsg;
1581 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
1583 TranslateMessage( &aMsg );
1584 ImplDispatchMessage( &aMsg );
1586 i++;
1587 if ( i > 15 )
1588 bWhile = FALSE;
1590 else
1591 bWhile = FALSE;
1593 while ( bWhile );
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();
1611 else
1613 mnError = SAL_PRINTER_ERROR_ABORT;
1614 return FALSE;
1618 DOCINFOW aInfo;
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());
1628 else
1629 aInfo.lpszOutput = L"FILE:";
1631 else
1632 aInfo.lpszOutput = NULL;
1634 // start Job
1635 int nRet = lcl_StartDocW( hDC, &aInfo, this );
1637 if ( nRet <= 0 )
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;
1642 else
1643 mnError = SAL_PRINTER_ERROR_GENERALERROR;
1644 return FALSE;
1647 return TRUE;
1650 // -----------------------------------------------------------------------
1652 sal_Bool WinSalPrinter::EndJob()
1654 HDC hDC = mhDC;
1655 if ( isValid() && hDC )
1657 if ( mpGraphics )
1659 ImplSalDeInitGraphics( mpGraphics );
1660 delete mpGraphics;
1661 mpGraphics = NULL;
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 )
1673 GetLastError();
1674 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
1676 GetSalData()->mpFirstInstance->AcquireYieldMutex( nAcquire );
1677 DeleteDC( hDC );
1678 mhDC = 0;
1681 return TRUE;
1684 // -----------------------------------------------------------------------
1686 sal_Bool WinSalPrinter::AbortJob()
1688 mbAbort = TRUE;
1690 // trigger Abort asynchronously
1691 HDC hDC = mhDC;
1692 if ( hDC )
1694 SalData* pSalData = GetSalData();
1695 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd,
1696 SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 );
1699 return TRUE;
1702 // -----------------------------------------------------------------------
1704 void ImplSalPrinterAbortJobAsync( HDC hPrnDC )
1706 SalData* pSalData = GetSalData();
1707 WinSalPrinter* pPrinter = pSalData->mpFirstPrinter;
1709 // check if printer still exists
1710 while ( pPrinter )
1712 if ( pPrinter->mhDC == hPrnDC )
1713 break;
1715 pPrinter = pPrinter->mpNextPrinter;
1718 // if printer still exists, cancel the job
1719 if ( pPrinter )
1721 HDC hDC = pPrinter->mhDC;
1722 if ( hDC )
1724 if ( pPrinter->mpGraphics )
1726 ImplSalDeInitGraphics( pPrinter->mpGraphics );
1727 delete pPrinter->mpGraphics;
1728 pPrinter->mpGraphics = NULL;
1731 CATCH_DRIVER_EX_BEGIN;
1732 ::AbortDoc( hDC );
1733 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter );
1735 DeleteDC( hDC );
1736 pPrinter->mhDC = 0;
1741 // -----------------------------------------------------------------------
1743 SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, sal_Bool bNewJobData )
1745 if( ! isValid() || mhDC == 0 )
1746 return NULL;
1748 HDC hDC = mhDC;
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 );
1764 if ( nRet <= 0 )
1766 GetLastError();
1767 mnError = SAL_PRINTER_ERROR_GENERALERROR;
1768 return NULL;
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 );
1780 return mpGraphics;
1783 // -----------------------------------------------------------------------
1785 sal_Bool WinSalPrinter::EndPage()
1787 HDC hDC = mhDC;
1788 if ( hDC && mpGraphics )
1790 ImplSalDeInitGraphics( mpGraphics );
1791 delete mpGraphics;
1792 mpGraphics = NULL;
1795 if( ! isValid() )
1796 return FALSE;
1798 volatile int nRet = 0;
1799 CATCH_DRIVER_EX_BEGIN;
1800 nRet = ::EndPage( hDC );
1801 CATCH_DRIVER_EX_END( "exception in EndPage", this );
1803 if ( nRet > 0 )
1804 return TRUE;
1805 else
1807 GetLastError();
1808 mnError = SAL_PRINTER_ERROR_GENERALERROR;
1809 return FALSE;
1813 // -----------------------------------------------------------------------
1815 sal_uLong WinSalPrinter::GetErrorCode()
1817 return mnError;
1820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */