xref: /trunk/main/vcl/source/gdi/print.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #define ENABLE_BYTESTRING_STREAM_OPERATORS
32 #include <list>
33 
34 #include <tools/debug.hxx>
35 #include <tools/resary.hxx>
36 #include <tools/stream.hxx>
37 #include <tools/vcompat.hxx>
38 
39 #include <vcl/unohelp.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/wrkwin.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/window.hxx>
44 #include <vcl/gdimtf.hxx>
45 #include <vcl/metaact.hxx>
46 #include <vcl/print.hxx>
47 
48 #include <salinst.hxx>
49 #include <salgdi.hxx>
50 #include <salptype.hxx>
51 #include <salprn.hxx>
52 #include <svdata.hxx>
53 #include <svids.hrc>
54 #include <jobset.h>
55 #include <outdev.h>
56 #include <print.h>
57 
58 #include <comphelper/processfactory.hxx>
59 
60 #include "com/sun/star/beans/XPropertySet.hpp"
61 #include "com/sun/star/container/XNameAccess.hpp"
62 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
63 
64 using namespace com::sun::star::uno;
65 using namespace com::sun::star::lang;
66 using namespace com::sun::star::beans;
67 using namespace com::sun::star::container;
68 
69 int nImplSysDialog = 0;
70 
71 // =======================================================================
72 
73 namespace
74 {
75     static Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
76     {
77         PaperInfo aInfo(nWidth100thMM, nHeight100thMM);
78         aInfo.doSloppyFit();
79         return aInfo.getPaper();
80     }
81 
82 // -----------------------------------------------------------------------
83 
84     static const PaperInfo& ImplGetEmptyPaper()
85     {
86         static PaperInfo aInfo(PAPER_USER);
87         return aInfo;
88     }
89 }
90 
91 // =======================================================================
92 
93 void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
94 {
95 	const ImplJobSetup* pConstData = rJobSetup.ImplGetConstData();
96 
97 	if ( !pConstData->mnPaperWidth || !pConstData->mnPaperHeight )
98 	{
99 		if ( pConstData->mePaperFormat != PAPER_USER )
100 		{
101 			ImplJobSetup* pData  = rJobSetup.ImplGetData();
102             PaperInfo aInfo(pConstData->mePaperFormat);
103 			pData->mnPaperWidth  = aInfo.getWidth();
104 			pData->mnPaperHeight = aInfo.getHeight();
105 		}
106 	}
107 	else if ( pConstData->mePaperFormat == PAPER_USER )
108 	{
109 		Paper ePaper = ImplGetPaperFormat( pConstData->mnPaperWidth, pConstData->mnPaperHeight );
110 		if ( ePaper != PAPER_USER )
111 			rJobSetup.ImplGetData()->mePaperFormat = ePaper;
112 	}
113 }
114 
115 // ------------------
116 // - PrinterOptions -
117 // ------------------
118 
119 PrinterOptions::PrinterOptions() :
120     mbReduceTransparency( sal_False ),
121     meReducedTransparencyMode( PRINTER_TRANSPARENCY_AUTO ),
122     mbReduceGradients( sal_False ),
123     meReducedGradientsMode( PRINTER_GRADIENT_STRIPES ),
124     mnReducedGradientStepCount( 64 ),
125     mbReduceBitmaps( sal_False ),
126     meReducedBitmapMode( PRINTER_BITMAP_NORMAL ),
127     mnReducedBitmapResolution( 200 ),
128     mbReducedBitmapsIncludeTransparency( sal_True ),
129     mbConvertToGreyscales( sal_False )
130 {
131 }
132 
133 // -----------------------------------------------------------------------
134 
135 PrinterOptions::~PrinterOptions()
136 {
137 }
138 
139 #define	PROPERTYNAME_REDUCETRANSPARENCY	                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReduceTransparency"))
140 #define	PROPERTYNAME_REDUCEDTRANSPARENCYMODE	        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedTransparencyMode"))
141 #define	PROPERTYNAME_REDUCEGRADIENTS		            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReduceGradients"))
142 #define	PROPERTYNAME_REDUCEDGRADIENTMODE		        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedGradientMode"))
143 #define PROPERTYNAME_REDUCEDGRADIENTSTEPCOUNT           rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedGradientStepCount"))
144 #define PROPERTYNAME_REDUCEBITMAPS                      rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReduceBitmaps"))
145 #define PROPERTYNAME_REDUCEDBITMAPMODE                  rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedBitmapMode"))
146 #define PROPERTYNAME_REDUCEDBITMAPRESOLUTION            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedBitmapResolution"))
147 #define PROPERTYNAME_REDUCEDBITMAPINCLUDESTRANSPARENCY  rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedBitmapIncludesTransparency"))
148 #define PROPERTYNAME_CONVERTTOGREYSCALES                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ConvertToGreyscales"))
149 
150 bool PrinterOptions::ReadFromConfig( bool i_bFile )
151 {
152     bool bSuccess = false;
153     // save old state in case something goes wrong
154     PrinterOptions aOldValues( *this );
155 
156     // get the configuration service
157     Reference< XMultiServiceFactory > xConfigProvider;
158     Reference< XNameAccess > xConfigAccess;
159     try
160     {
161         // get service provider
162         Reference< XMultiServiceFactory > xSMgr( comphelper::getProcessServiceFactory() );
163         // create configuration hierachical access name
164         if( xSMgr.is() )
165         {
166             try
167             {
168                 xConfigProvider = Reference< XMultiServiceFactory >(
169                         xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
170                                         "com.sun.star.configuration.ConfigurationProvider" ))),
171                         UNO_QUERY );
172                 if( xConfigProvider.is() )
173                 {
174                     Sequence< Any > aArgs(1);
175                     PropertyValue aVal;
176                     aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
177                     if( i_bFile )
178                         aVal.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Print/Option/File" ) );
179                     else
180                         aVal.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Print/Option/Printer" ) );
181                     aArgs.getArray()[0] <<= aVal;
182                     xConfigAccess = Reference< XNameAccess >(
183                             xConfigProvider->createInstanceWithArguments(
184                                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" )), aArgs ),
185                                 UNO_QUERY );
186                     if( xConfigAccess.is() )
187                     {
188                         Reference< XPropertySet > xSet( xConfigAccess, UNO_QUERY );
189                         if( xSet.is() )
190                         {
191                             sal_Int32 nValue = 0;
192                             sal_Bool  bValue = 0;
193                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCETRANSPARENCY) >>= bValue )
194                                 SetReduceTransparency( bValue );
195                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDTRANSPARENCYMODE) >>= nValue )
196                                 SetReducedTransparencyMode( (PrinterTransparencyMode)nValue );
197                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEGRADIENTS) >>= bValue )
198                                 SetReduceGradients( bValue );
199                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDGRADIENTMODE) >>= nValue )
200                                 SetReducedGradientMode( (PrinterGradientMode)nValue );
201                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDGRADIENTSTEPCOUNT) >>= nValue )
202                                 SetReducedGradientStepCount( (sal_uInt16)nValue );
203                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEBITMAPS) >>= bValue )
204                                 SetReduceBitmaps( bValue );
205                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDBITMAPMODE) >>= nValue )
206                                 SetReducedBitmapMode( (PrinterBitmapMode)nValue );
207                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDBITMAPRESOLUTION) >>= nValue )
208                                 SetReducedBitmapResolution( (sal_uInt16)nValue );
209                             if( xSet->getPropertyValue(PROPERTYNAME_REDUCEDBITMAPINCLUDESTRANSPARENCY) >>= bValue )
210                                 SetReducedBitmapIncludesTransparency( bValue );
211                             if( xSet->getPropertyValue(PROPERTYNAME_CONVERTTOGREYSCALES) >>= bValue )
212                                 SetConvertToGreyscales( bValue );
213 
214                             bSuccess = true;
215                         }
216                     }
217                 }
218             }
219             catch( Exception& )
220             {
221             }
222         }
223     }
224     catch( WrappedTargetException& )
225     {
226     }
227 
228     if( ! bSuccess )
229         *this = aOldValues;
230     return bSuccess;
231 }
232 
233 void Printer::SetPrinterOptions( const PrinterOptions& i_rOptions )
234 {
235     *mpPrinterOptions = i_rOptions;
236 }
237 
238 // -------------
239 // - QueueInfo -
240 // -------------
241 
242 QueueInfo::QueueInfo()
243 {
244 	mnStatus	= 0;
245 	mnJobs		= 0;
246 }
247 
248 // -----------------------------------------------------------------------
249 
250 QueueInfo::QueueInfo( const QueueInfo& rInfo ) :
251 	maPrinterName( rInfo.maPrinterName ),
252 	maDriver( rInfo.maDriver ),
253 	maLocation( rInfo.maLocation ),
254 	maComment( rInfo.maComment ),
255 	mnStatus( rInfo.mnStatus ),
256 	mnJobs( rInfo.mnJobs )
257 {
258 }
259 
260 // -----------------------------------------------------------------------
261 
262 QueueInfo::~QueueInfo()
263 {
264 }
265 
266 // -----------------------------------------------------------------------
267 
268 bool QueueInfo::operator==( const QueueInfo& rInfo ) const
269 {
270 	return
271 		maPrinterName	== rInfo.maPrinterName	&&
272 		maDriver		== rInfo.maDriver		&&
273 		maLocation		== rInfo.maLocation		&&
274 		maComment		== rInfo.maComment		&&
275 		mnStatus		== rInfo.mnStatus		&&
276 		mnJobs			== rInfo.mnJobs;
277 }
278 
279 // -----------------------------------------------------------------------
280 
281 SvStream& operator<<( SvStream& rOStream, const QueueInfo& rInfo )
282 {
283 	VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
284 
285 	rOStream.WriteByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
286 	rOStream.WriteByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
287 	rOStream.WriteByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
288 	rOStream.WriteByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
289 	rOStream << rInfo.mnStatus;
290 	rOStream << rInfo.mnJobs;
291 
292 	return rOStream;
293 }
294 
295 // -----------------------------------------------------------------------
296 
297 SvStream& operator>>( SvStream& rIStream, QueueInfo& rInfo )
298 {
299 	VersionCompat aCompat( rIStream, STREAM_READ );
300 
301 	rIStream.ReadByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
302 	rIStream.ReadByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
303 	rIStream.ReadByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
304 	rIStream.ReadByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
305 	rIStream >> rInfo.mnStatus;
306 	rIStream >> rInfo.mnJobs;
307 
308 	return rIStream;
309 }
310 
311 // =======================================================================
312 
313 SalPrinterQueueInfo::SalPrinterQueueInfo()
314 {
315 	mnStatus	= 0;
316 	mnJobs		= QUEUE_JOBS_DONTKNOW;
317 	mpSysData	= NULL;
318 }
319 
320 // -----------------------------------------------------------------------
321 
322 SalPrinterQueueInfo::~SalPrinterQueueInfo()
323 {
324 }
325 
326 // -----------------------------------------------------------------------
327 
328 ImplPrnQueueList::~ImplPrnQueueList()
329 {
330 	ImplSVData* 		pSVData = ImplGetSVData();
331     for( unsigned int i = 0; i < m_aQueueInfos.size(); i++ )
332     {
333         delete m_aQueueInfos[i].mpQueueInfo;
334         pSVData->mpDefInst->DeletePrinterQueueInfo( m_aQueueInfos[i].mpSalQueueInfo );
335     }
336 }
337 
338 // -----------------------------------------------------------------------
339 
340 void ImplPrnQueueList::Add( SalPrinterQueueInfo* pData )
341 {
342     std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash >::iterator it =
343         m_aNameToIndex.find( pData->maPrinterName );
344     if( it == m_aNameToIndex.end() )
345     {
346         m_aNameToIndex[ pData->maPrinterName ] = m_aQueueInfos.size();
347         m_aQueueInfos.push_back( ImplPrnQueueData() );
348         m_aQueueInfos.back().mpQueueInfo = NULL;
349         m_aQueueInfos.back().mpSalQueueInfo = pData;
350         m_aPrinterList.push_back( pData->maPrinterName );
351     }
352     else // this should not happen, but ...
353     {
354         ImplPrnQueueData& rData = m_aQueueInfos[ it->second ];
355         delete rData.mpQueueInfo;
356         rData.mpQueueInfo = NULL;
357         ImplGetSVData()->mpDefInst->DeletePrinterQueueInfo( rData.mpSalQueueInfo );
358         rData.mpSalQueueInfo = pData;
359     }
360 }
361 
362 // -----------------------------------------------------------------------
363 
364 ImplPrnQueueData* ImplPrnQueueList::Get( const rtl::OUString& rPrinter )
365 {
366     ImplPrnQueueData* pData = NULL;
367     std::hash_map<rtl::OUString,sal_Int32,rtl::OUStringHash>::iterator it =
368         m_aNameToIndex.find( rPrinter );
369     if( it != m_aNameToIndex.end() )
370         pData = &m_aQueueInfos[it->second];
371     return pData;
372 }
373 
374 // =======================================================================
375 
376 static void ImplInitPrnQueueList()
377 {
378 	ImplSVData* pSVData = ImplGetSVData();
379 
380 	pSVData->maGDIData.mpPrinterQueueList = new ImplPrnQueueList;
381 
382     static const char* pEnv = getenv( "SAL_DISABLE_PRINTERLIST" );
383     if( !pEnv || !*pEnv )
384         pSVData->mpDefInst->GetPrinterQueueInfo( pSVData->maGDIData.mpPrinterQueueList );
385 }
386 
387 // -----------------------------------------------------------------------
388 
389 void ImplDeletePrnQueueList()
390 {
391 	ImplSVData* 		pSVData = ImplGetSVData();
392 	ImplPrnQueueList*	pPrnList = pSVData->maGDIData.mpPrinterQueueList;
393 
394 	if ( pPrnList )
395 	{
396 		delete pPrnList;
397 		pSVData->maGDIData.mpPrinterQueueList = NULL;
398 	}
399 }
400 
401 // -----------------------------------------------------------------------
402 
403 const std::vector<rtl::OUString>& Printer::GetPrinterQueues()
404 {
405 	ImplSVData* 		pSVData = ImplGetSVData();
406 	if ( !pSVData->maGDIData.mpPrinterQueueList )
407 		ImplInitPrnQueueList();
408     return pSVData->maGDIData.mpPrinterQueueList->m_aPrinterList;
409 }
410 
411 // -----------------------------------------------------------------------
412 const QueueInfo* Printer::GetQueueInfo( const String& rPrinterName, bool bStatusUpdate )
413 {
414 	ImplSVData* pSVData = ImplGetSVData();
415 
416 	if ( !pSVData->maGDIData.mpPrinterQueueList )
417 		ImplInitPrnQueueList();
418 
419     ImplPrnQueueData* pInfo = pSVData->maGDIData.mpPrinterQueueList->Get( rPrinterName );
420     if( pInfo )
421     {
422         if( !pInfo->mpQueueInfo || bStatusUpdate )
423             pSVData->mpDefInst->GetPrinterQueueState( pInfo->mpSalQueueInfo );
424 
425         if ( !pInfo->mpQueueInfo )
426             pInfo->mpQueueInfo = new QueueInfo;
427 
428         pInfo->mpQueueInfo->maPrinterName	= pInfo->mpSalQueueInfo->maPrinterName;
429         pInfo->mpQueueInfo->maDriver		= pInfo->mpSalQueueInfo->maDriver;
430         pInfo->mpQueueInfo->maLocation		= pInfo->mpSalQueueInfo->maLocation;
431         pInfo->mpQueueInfo->maComment		= pInfo->mpSalQueueInfo->maComment;
432         pInfo->mpQueueInfo->mnStatus		= pInfo->mpSalQueueInfo->mnStatus;
433         pInfo->mpQueueInfo->mnJobs			= pInfo->mpSalQueueInfo->mnJobs;
434         return pInfo->mpQueueInfo;
435     }
436     return NULL;
437 }
438 
439 // -----------------------------------------------------------------------
440 
441 XubString Printer::GetDefaultPrinterName()
442 {
443     static const char* pEnv = getenv( "SAL_DISABLE_DEFAULTPRINTER" );
444     if( !pEnv || !*pEnv )
445     {
446         ImplSVData* pSVData = ImplGetSVData();
447 
448         return pSVData->mpDefInst->GetDefaultPrinter();
449     }
450     return XubString();
451 }
452 
453 // =======================================================================
454 
455 void Printer::ImplInitData()
456 {
457 	mbDevOutput 		= sal_False;
458 	meOutDevType		= OUTDEV_PRINTER;
459 	mbDefPrinter		= sal_False;
460 	mnError 			= 0;
461 	mnCurPage			= 0;
462 	mnCurPrintPage		= 0;
463 	mnPageQueueSize 	= 0;
464 	mnCopyCount 		= 1;
465 	mbCollateCopy		= sal_False;
466 	mbPrinting			= sal_False;
467 	mbJobActive 		= sal_False;
468 	mbPrintFile 		= sal_False;
469 	mbInPrintPage		= sal_False;
470 	mbNewJobSetup		= sal_False;
471 	mpInfoPrinter		= NULL;
472 	mpPrinter			= NULL;
473 	mpDisplayDev		= NULL;
474 	mbIsQueuePrinter	= sal_False;
475     mpPrinterOptions    = new PrinterOptions;
476 
477 	// Printer in die Liste eintragen
478 	ImplSVData* pSVData = ImplGetSVData();
479 	mpNext = pSVData->maGDIData.mpFirstPrinter;
480 	mpPrev = NULL;
481 	if ( mpNext )
482 		mpNext->mpPrev = this;
483 	else
484 		pSVData->maGDIData.mpLastPrinter = this;
485 	pSVData->maGDIData.mpFirstPrinter = this;
486 }
487 
488 // -----------------------------------------------------------------------
489 
490 void Printer::ImplInit( SalPrinterQueueInfo* pInfo )
491 {
492 	ImplSVData* pSVData = ImplGetSVData();
493     // #i74084# update info for this specific SalPrinterQueueInfo
494     pSVData->mpDefInst->GetPrinterQueueState( pInfo );
495 
496 	// Testen, ob Treiber ueberhaupt mit dem JobSetup uebereinstimmt
497 	ImplJobSetup* pJobSetup = maJobSetup.ImplGetData();
498 
499 	if ( pJobSetup->mpDriverData )
500 	{
501 		if ( (pJobSetup->maPrinterName != pInfo->maPrinterName) ||
502 			 (pJobSetup->maDriver != pInfo->maDriver) )
503 		{
504 			rtl_freeMemory( pJobSetup->mpDriverData );
505 			pJobSetup->mpDriverData = NULL;
506 			pJobSetup->mnDriverDataLen = 0;
507 		}
508 	}
509 
510 	// Printernamen merken
511 	maPrinterName = pInfo->maPrinterName;
512 	maDriver = pInfo->maDriver;
513 
514 	// In JobSetup den Printernamen eintragen
515 	pJobSetup->maPrinterName = maPrinterName;
516 	pJobSetup->maDriver = maDriver;
517 
518 	mpInfoPrinter	= pSVData->mpDefInst->CreateInfoPrinter( pInfo, pJobSetup );
519 	mpPrinter		= NULL;
520 	mpJobGraphics	= NULL;
521 	ImplUpdateJobSetupPaper( maJobSetup );
522 
523 	if ( !mpInfoPrinter )
524 	{
525 		ImplInitDisplay( NULL );
526 		return;
527 	}
528 
529 	// we need a graphics
530 	if ( !ImplGetGraphics() )
531 	{
532 		ImplInitDisplay( NULL );
533 		return;
534 	}
535 
536 	// Daten initialisieren
537 	ImplUpdatePageData();
538 	mpFontList = new ImplDevFontList();
539 	mpFontCache = new ImplFontCache( sal_True );
540 	mpGraphics->GetDevFontList( mpFontList );
541 }
542 
543 // -----------------------------------------------------------------------
544 
545 void Printer::ImplInitDisplay( const Window* pWindow )
546 {
547 	ImplSVData* pSVData = ImplGetSVData();
548 
549 	mpInfoPrinter		= NULL;
550 	mpPrinter			= NULL;
551 	mpJobGraphics		= NULL;
552 
553 	if ( pWindow )
554 		mpDisplayDev = new VirtualDevice( *pWindow );
555 	else
556 		mpDisplayDev = new VirtualDevice();
557 	mpFontList			= pSVData->maGDIData.mpScreenFontList;
558 	mpFontCache 		= pSVData->maGDIData.mpScreenFontCache;
559 	mnDPIX				= mpDisplayDev->mnDPIX;
560 	mnDPIY				= mpDisplayDev->mnDPIY;
561 }
562 
563 // -----------------------------------------------------------------------
564 
565 SalPrinterQueueInfo* Printer::ImplGetQueueInfo( const XubString& rPrinterName,
566 												const XubString* pDriver )
567 {
568 	ImplSVData* pSVData = ImplGetSVData();
569 	if ( !pSVData->maGDIData.mpPrinterQueueList )
570 		ImplInitPrnQueueList();
571 
572 	ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList;
573 	if ( pPrnList && pPrnList->m_aQueueInfos.size() )
574 	{
575 		// first search for the printer name driectly
576 		ImplPrnQueueData* pInfo = pPrnList->Get( rPrinterName );
577 		if( pInfo )
578 			return pInfo->mpSalQueueInfo;
579 
580 		// then search case insensitive
581         for( unsigned int i = 0; i < pPrnList->m_aQueueInfos.size(); i++ )
582         {
583             if( pPrnList->m_aQueueInfos[i].mpSalQueueInfo->maPrinterName.EqualsIgnoreCaseAscii( rPrinterName ) )
584                 return pPrnList->m_aQueueInfos[i].mpSalQueueInfo;
585 		}
586 
587 		// then search for driver name
588 		if ( pDriver )
589 		{
590             for( unsigned int i = 0; i < pPrnList->m_aQueueInfos.size(); i++ )
591             {
592                 if( pPrnList->m_aQueueInfos[i].mpSalQueueInfo->maDriver == *pDriver )
593                     return pPrnList->m_aQueueInfos[i].mpSalQueueInfo;
594             }
595 		}
596 
597 		// then the default printer
598 		pInfo = pPrnList->Get( GetDefaultPrinterName() );
599         if( pInfo )
600             return pInfo->mpSalQueueInfo;
601 
602         // last chance: the first available printer
603         return pPrnList->m_aQueueInfos[0].mpSalQueueInfo;
604 	}
605 
606 	return NULL;
607 }
608 
609 // -----------------------------------------------------------------------
610 
611 void Printer::ImplUpdatePageData()
612 {
613 	// we need a graphics
614 	if ( !ImplGetGraphics() )
615 		return;
616 
617 	mpGraphics->GetResolution( mnDPIX, mnDPIY );
618 	mpInfoPrinter->GetPageInfo( maJobSetup.ImplGetConstData(),
619 								mnOutWidth, mnOutHeight,
620 								maPageOffset.X(), maPageOffset.Y(),
621 								maPaperSize.Width(), maPaperSize.Height() );
622     static const char* pDebugOffset = getenv( "SAL_DBG_PAGEOFFSET" );
623     if( pDebugOffset )
624     {
625         rtl::OString aLine( pDebugOffset );
626         sal_Int32 nIndex = 0;
627         rtl::OString aToken( aLine.getToken( 0, ',', nIndex ) );
628         sal_Int32 nLeft = aToken.toInt32();
629         sal_Int32 nTop = nLeft;
630         if( nIndex > 0 )
631         {
632             aToken = aLine.getToken( 0, ',', nIndex );
633             nTop = aToken.toInt32();
634         }
635         maPageOffset = LogicToPixel( Point( static_cast<long>(nLeft),
636                                             static_cast<long>(nTop) ),
637                                      MapMode( MAP_100TH_MM )
638                                      );
639         mnOutWidth = maPaperSize.Width() - 2*maPageOffset.X();
640         mnOutWidth = maPaperSize.Width() - 2*maPageOffset.Y();
641     }
642 }
643 
644 // -----------------------------------------------------------------------
645 
646 void Printer::ImplUpdateFontList()
647 {
648 	ImplUpdateFontData( sal_True );
649 }
650 
651 // -----------------------------------------------------------------------
652 
653 Printer::Printer()
654 {
655 	ImplInitData();
656 	SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( GetDefaultPrinterName(), NULL );
657 	if ( pInfo )
658 	{
659 		ImplInit( pInfo );
660 		if ( !IsDisplayPrinter() )
661 			mbDefPrinter = sal_True;
662 	}
663 	else
664 		ImplInitDisplay( NULL );
665 }
666 
667 // -----------------------------------------------------------------------
668 
669 Printer::Printer( const Window* pWindow )
670 {
671 	ImplInitData();
672 	ImplInitDisplay( pWindow );
673 }
674 
675 // -----------------------------------------------------------------------
676 
677 Printer::Printer( const JobSetup& rJobSetup ) :
678 	maJobSetup( rJobSetup )
679 {
680 	ImplInitData();
681 	SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rJobSetup.mpData->maPrinterName,
682 												   &rJobSetup.mpData->maDriver );
683 	if ( pInfo )
684 	{
685 		ImplInit( pInfo );
686 		SetJobSetup( rJobSetup );
687 	}
688 	else
689 	{
690 		ImplInitDisplay( NULL );
691 		maJobSetup = JobSetup();
692 	}
693 }
694 
695 // -----------------------------------------------------------------------
696 
697 Printer::Printer( const QueueInfo& rQueueInfo )
698 {
699 	ImplInitData();
700 	SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rQueueInfo.GetPrinterName(),
701 												   &rQueueInfo.GetDriver() );
702 	if ( pInfo )
703 		ImplInit( pInfo );
704 	else
705 		ImplInitDisplay( NULL );
706 }
707 
708 // -----------------------------------------------------------------------
709 
710 Printer::Printer( const XubString& rPrinterName )
711 {
712 	ImplInitData();
713 	SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rPrinterName, NULL );
714 	if ( pInfo )
715 		ImplInit( pInfo );
716 	else
717 		ImplInitDisplay( NULL );
718 }
719 
720 // -----------------------------------------------------------------------
721 
722 Printer::~Printer()
723 {
724 	DBG_ASSERT( !IsPrinting(), "Printer::~Printer() - Job is printing" );
725 	DBG_ASSERT( !IsJobActive(), "Printer::~Printer() - Job is active" );
726 
727     delete mpPrinterOptions;
728 
729 	ImplReleaseGraphics();
730 	if ( mpInfoPrinter )
731 		ImplGetSVData()->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
732 	if ( mpDisplayDev )
733 		delete mpDisplayDev;
734 	else
735 	{
736 		// OutputDevice-Dtor versucht das gleiche, deshalb muss hier
737 		// der FontEntry auch auf NULL gesetzt werden
738         // TODO: consolidate duplicate cleanup by Printer and OutputDevice
739 		if ( mpFontEntry )
740 		{
741 			mpFontCache->Release( mpFontEntry );
742 			mpFontEntry = NULL;
743 		}
744 		if ( mpGetDevFontList )
745 		{
746 			delete mpGetDevFontList;
747 			mpGetDevFontList = NULL;
748 		}
749 		if ( mpGetDevSizeList )
750 		{
751 			delete mpGetDevSizeList;
752 			mpGetDevSizeList = NULL;
753 		}
754 		delete mpFontCache;
755         mpFontCache = NULL;
756         // font list deleted by OutputDevice dtor
757 	}
758 
759 	// Printer aus der Liste eintragen
760 	ImplSVData* pSVData = ImplGetSVData();
761 	if ( mpPrev )
762 		mpPrev->mpNext = mpNext;
763 	else
764 		pSVData->maGDIData.mpFirstPrinter = mpNext;
765 	if ( mpNext )
766 		mpNext->mpPrev = mpPrev;
767 	else
768 		pSVData->maGDIData.mpLastPrinter = mpPrev;
769 }
770 
771 // -----------------------------------------------------------------------
772 void Printer::Compat_OldPrinterMetrics( bool bSet )
773 {
774     // propagate flag
775     if( mpInfoPrinter )
776         mpInfoPrinter->m_bCompatMetrics = bSet;
777 
778     // get new font data
779     ImplUpdateFontData( sal_True );
780 }
781 
782 // -----------------------------------------------------------------------
783 
784 sal_uLong Printer::GetCapabilities( sal_uInt16 nType ) const
785 {
786 	if ( IsDisplayPrinter() )
787 		return sal_False;
788 
789     if( mpInfoPrinter )
790 	    return mpInfoPrinter->GetCapabilities( maJobSetup.ImplGetConstData(), nType );
791     else
792         return sal_False;
793 }
794 
795 // -----------------------------------------------------------------------
796 
797 sal_Bool Printer::HasSupport( PrinterSupport eFeature ) const
798 {
799 	switch ( eFeature )
800 	{
801 		case SUPPORT_SET_ORIENTATION:
802 			return (sal_Bool)GetCapabilities( PRINTER_CAPABILITIES_SETORIENTATION );
803 		case SUPPORT_SET_PAPERBIN:
804 			return (sal_Bool)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERBIN );
805 		case SUPPORT_SET_PAPERSIZE:
806 			return (sal_Bool)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERSIZE );
807 		case SUPPORT_SET_PAPER:
808 			return (sal_Bool)GetCapabilities( PRINTER_CAPABILITIES_SETPAPER );
809 		case SUPPORT_COPY:
810 			return (GetCapabilities( PRINTER_CAPABILITIES_COPIES ) != 0);
811 		case SUPPORT_COLLATECOPY:
812 			return (GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES ) != 0);
813 		case SUPPORT_SETUPDIALOG:
814 			return (sal_Bool)GetCapabilities( PRINTER_CAPABILITIES_SUPPORTDIALOG );
815 		case SUPPORT_FAX:
816 			return (sal_Bool) GetCapabilities( PRINTER_CAPABILITIES_FAX );
817 		case SUPPORT_PDF:
818 			return (sal_Bool) GetCapabilities( PRINTER_CAPABILITIES_PDF );
819 	}
820 
821 	return sal_True;
822 }
823 
824 // -----------------------------------------------------------------------
825 
826 sal_Bool Printer::SetJobSetup( const JobSetup& rSetup )
827 {
828 	if ( IsDisplayPrinter() || mbInPrintPage )
829 		return sal_False;
830 
831 	JobSetup aJobSetup = rSetup;
832 
833 	ImplReleaseGraphics();
834 	if ( mpInfoPrinter->SetPrinterData( aJobSetup.ImplGetData() ) )
835 	{
836 		ImplUpdateJobSetupPaper( aJobSetup );
837 		mbNewJobSetup = sal_True;
838 		maJobSetup = aJobSetup;
839 		ImplUpdatePageData();
840 		ImplUpdateFontList();
841 		return sal_True;
842 	}
843 
844 	return sal_False;
845 }
846 
847 // -----------------------------------------------------------------------
848 
849 
850 sal_Bool Printer::Setup( Window* pWindow )
851 {
852 	if ( IsDisplayPrinter() )
853 		return sal_False;
854 
855 	if ( IsJobActive() || IsPrinting() )
856 		return sal_False;
857 
858 	JobSetup aJobSetup = maJobSetup;
859 	SalFrame* pFrame;
860 	if ( !pWindow )
861         pWindow = ImplGetDefaultWindow();
862     if( !pWindow )
863         return sal_False;
864 
865     pFrame = pWindow->ImplGetFrame();
866 	ImplReleaseGraphics();
867 	ImplSVData* pSVData = ImplGetSVData();
868 	pSVData->maAppData.mnModalMode++;
869 	nImplSysDialog++;
870 	sal_Bool bSetup = mpInfoPrinter->Setup( pFrame, aJobSetup.ImplGetData() );
871 	pSVData->maAppData.mnModalMode--;
872 	nImplSysDialog--;
873 	if ( bSetup )
874 	{
875 		ImplUpdateJobSetupPaper( aJobSetup );
876 		mbNewJobSetup = sal_True;
877 		maJobSetup = aJobSetup;
878 		ImplUpdatePageData();
879 		ImplUpdateFontList();
880 		return sal_True;
881 	}
882 	return sal_False;
883 }
884 
885 // -----------------------------------------------------------------------
886 
887 sal_Bool Printer::SetPrinterProps( const Printer* pPrinter )
888 {
889 	if ( IsJobActive() || IsPrinting() )
890 		return sal_False;
891 
892 	ImplSVData* pSVData = ImplGetSVData();
893 
894 	mbDefPrinter	    = pPrinter->mbDefPrinter;
895 	maPrintFile 	    = pPrinter->maPrintFile;
896 	mbPrintFile 	    = pPrinter->mbPrintFile;
897 	mnCopyCount 	    = pPrinter->mnCopyCount;
898 	mbCollateCopy	    = pPrinter->mbCollateCopy;
899 	mnPageQueueSize     = pPrinter->mnPageQueueSize;
900     *mpPrinterOptions   = *pPrinter->mpPrinterOptions;
901 
902 	if ( pPrinter->IsDisplayPrinter() )
903 	{
904 		// Alten Printer zerstoeren
905 		if ( !IsDisplayPrinter() )
906 		{
907 			ImplReleaseGraphics();
908 			pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
909 			if ( mpFontEntry )
910 			{
911 				mpFontCache->Release( mpFontEntry );
912 				mpFontEntry = NULL;
913 			}
914 			if ( mpGetDevFontList )
915 			{
916 				delete mpGetDevFontList;
917 				mpGetDevFontList = NULL;
918 			}
919 			if ( mpGetDevSizeList )
920 			{
921 				delete mpGetDevSizeList;
922 				mpGetDevSizeList = NULL;
923 			}
924             // clean up font list
925 			delete mpFontCache;
926 			delete mpFontList;
927 			mpFontCache = NULL;
928 			mpFontList = NULL;
929 
930 			mbInitFont = sal_True;
931 			mbNewFont = sal_True;
932 			mpInfoPrinter = NULL;
933 		}
934 
935 		// Neuen Printer bauen
936 		ImplInitDisplay( NULL );
937 		return sal_True;
938 	}
939 
940 	// Alten Printer zerstoeren?
941 	if ( GetName() != pPrinter->GetName() )
942 	{
943 		ImplReleaseGraphics();
944 		if ( mpDisplayDev )
945 		{
946 			delete mpDisplayDev;
947 			mpDisplayDev = NULL;
948 		}
949 		else
950 		{
951 			pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
952 
953 			if ( mpFontEntry )
954 			{
955 				mpFontCache->Release( mpFontEntry );
956 				mpFontEntry = NULL;
957 			}
958 			if ( mpGetDevFontList )
959 			{
960 				delete mpGetDevFontList;
961 				mpGetDevFontList = NULL;
962 			}
963 			if ( mpGetDevSizeList )
964 			{
965 				delete mpGetDevSizeList;
966 				mpGetDevSizeList = NULL;
967 			}
968 			delete mpFontCache;
969 			delete mpFontList;
970 			mpFontCache = NULL;
971 			mpFontList = NULL;
972 			mbInitFont = sal_True;
973 			mbNewFont = sal_True;
974 			mpInfoPrinter = NULL;
975 		}
976 
977 		// Neuen Printer bauen
978 		XubString aDriver = pPrinter->GetDriverName();
979 		SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( pPrinter->GetName(), &aDriver );
980 		if ( pInfo )
981 		{
982 			ImplInit( pInfo );
983 			SetJobSetup( pPrinter->GetJobSetup() );
984 		}
985 		else
986 			ImplInitDisplay( NULL );
987 	}
988 	else
989 		SetJobSetup( pPrinter->GetJobSetup() );
990 
991 	return sal_False;
992 }
993 
994 // -----------------------------------------------------------------------
995 
996 sal_Bool Printer::SetOrientation( Orientation eOrientation )
997 {
998 	if ( mbInPrintPage )
999 		return sal_False;
1000 
1001 	if ( maJobSetup.ImplGetConstData()->meOrientation != eOrientation )
1002 	{
1003 		JobSetup		aJobSetup = maJobSetup;
1004 		ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1005 		pSetupData->meOrientation = eOrientation;
1006 
1007 		if ( IsDisplayPrinter() )
1008 		{
1009 			mbNewJobSetup = sal_True;
1010 			maJobSetup = aJobSetup;
1011 			return sal_True;
1012 		}
1013 
1014 		ImplReleaseGraphics();
1015 		if ( mpInfoPrinter->SetData( SAL_JOBSET_ORIENTATION, pSetupData ) )
1016 		{
1017 			ImplUpdateJobSetupPaper( aJobSetup );
1018 			mbNewJobSetup = sal_True;
1019 			maJobSetup = aJobSetup;
1020 			ImplUpdatePageData();
1021 			ImplUpdateFontList();
1022 			return sal_True;
1023 		}
1024 		else
1025 			return sal_False;
1026 	}
1027 
1028 	return sal_True;
1029 }
1030 
1031 // -----------------------------------------------------------------------
1032 
1033 Orientation Printer::GetOrientation() const
1034 {
1035 	return maJobSetup.ImplGetConstData()->meOrientation;
1036 }
1037 
1038 // -----------------------------------------------------------------------
1039 
1040 sal_Bool Printer::SetPaperBin( sal_uInt16 nPaperBin )
1041 {
1042 	if ( mbInPrintPage )
1043 		return sal_False;
1044 
1045 	if ( (maJobSetup.ImplGetConstData()->mnPaperBin != nPaperBin) &&
1046 		 (nPaperBin < GetPaperBinCount()) )
1047 	{
1048 		JobSetup		aJobSetup = maJobSetup;
1049 		ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1050 		pSetupData->mnPaperBin = nPaperBin;
1051 
1052 		if ( IsDisplayPrinter() )
1053 		{
1054 			mbNewJobSetup = sal_True;
1055 			maJobSetup = aJobSetup;
1056 			return sal_True;
1057 		}
1058 
1059 		ImplReleaseGraphics();
1060 		if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERBIN, pSetupData ) )
1061 		{
1062 			ImplUpdateJobSetupPaper( aJobSetup );
1063 			mbNewJobSetup = sal_True;
1064 			maJobSetup = aJobSetup;
1065 			ImplUpdatePageData();
1066 			ImplUpdateFontList();
1067 			return sal_True;
1068 		}
1069 		else
1070 			return sal_False;
1071 	}
1072 
1073 	return sal_True;
1074 }
1075 
1076 // -----------------------------------------------------------------------
1077 
1078 sal_uInt16 Printer::GetPaperBin() const
1079 {
1080 	return maJobSetup.ImplGetConstData()->mnPaperBin;
1081 }
1082 
1083 // -----------------------------------------------------------------------
1084 
1085 // Map user paper format to a available printer paper formats
1086 void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup, bool bMatchNearest )
1087 {
1088 	ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1089 
1090 	int		nLandscapeAngle	= GetLandscapeAngle();
1091 	int		nPaperCount		= GetPaperInfoCount();
1092     bool    bFound = false;
1093 
1094     PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
1095 
1096 	// Alle Papierformate vergleichen und ein passendes raussuchen
1097 	for ( int i = 0; i < nPaperCount; i++ )
1098 	{
1099 		const PaperInfo& rPaperInfo = GetPaperInfo( i );
1100 
1101 		if ( aInfo.sloppyEqual(rPaperInfo) )
1102 		{
1103 			pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.getWidth(),
1104 															rPaperInfo.getHeight() );
1105             pSetupData->meOrientation = ORIENTATION_PORTRAIT;
1106             bFound = true;
1107 			break;
1108 		}
1109 	}
1110 
1111 	// If the printer supports landscape orientation, check paper sizes again
1112 	// with landscape orientation. This is necessary as a printer driver provides
1113 	// all paper sizes with portrait orientation only!!
1114 	if ( pSetupData->mePaperFormat == PAPER_USER &&
1115 		 nLandscapeAngle != 0 &&
1116 		 HasSupport( SUPPORT_SET_ORIENTATION ))
1117 	{
1118 
1119         PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
1120 
1121 		for ( int i = 0; i < nPaperCount; i++ )
1122 		{
1123 			const PaperInfo& rPaperInfo = GetPaperInfo( i );
1124 
1125 			if ( aRotatedInfo.sloppyEqual( rPaperInfo ) )
1126 			{
1127 				pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.getWidth(),
1128 																rPaperInfo.getHeight() );
1129                 pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
1130                 bFound = true;
1131 				break;
1132 			}
1133 		}
1134 	}
1135 
1136     if( ! bFound && bMatchNearest )
1137     {
1138          sal_Int64 nBestMatch = SAL_MAX_INT64;
1139          int nBestIndex = 0;
1140          Orientation eBestOrientation = ORIENTATION_PORTRAIT;
1141          for( int i = 0; i < nPaperCount; i++ )
1142          {
1143              const PaperInfo& rPaperInfo = GetPaperInfo( i );
1144 
1145              // check protrait match
1146              sal_Int64 nDX = pSetupData->mnPaperWidth - rPaperInfo.getWidth();
1147              sal_Int64 nDY = pSetupData->mnPaperHeight - rPaperInfo.getHeight();
1148              sal_Int64 nMatch = nDX*nDX + nDY*nDY;
1149              if( nMatch < nBestMatch )
1150              {
1151                  nBestMatch = nMatch;
1152                  nBestIndex = i;
1153                  eBestOrientation = ORIENTATION_PORTRAIT;
1154              }
1155 
1156              // check landscape match
1157              nDX = pSetupData->mnPaperWidth - rPaperInfo.getHeight();
1158              nDY = pSetupData->mnPaperHeight - rPaperInfo.getWidth();
1159              nMatch = nDX*nDX + nDY*nDY;
1160              if( nMatch < nBestMatch )
1161              {
1162                  nBestMatch = nMatch;
1163                  nBestIndex = i;
1164                  eBestOrientation = ORIENTATION_LANDSCAPE;
1165              }
1166          }
1167          const PaperInfo& rBestInfo = GetPaperInfo( nBestIndex );
1168          pSetupData->mePaperFormat = ImplGetPaperFormat( rBestInfo.getWidth(),
1169                                                          rBestInfo.getHeight() );
1170          pSetupData->meOrientation = eBestOrientation;
1171     }
1172 }
1173 
1174 // -----------------------------------------------------------------------
1175 
1176 sal_Bool Printer::SetPaper( Paper ePaper )
1177 {
1178 	if ( mbInPrintPage )
1179 		return sal_False;
1180 
1181 	if ( maJobSetup.ImplGetConstData()->mePaperFormat != ePaper )
1182 	{
1183 		JobSetup		aJobSetup = maJobSetup;
1184 		ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1185 		pSetupData->mePaperFormat = ePaper;
1186 		if ( ePaper != PAPER_USER )
1187 		{
1188             PaperInfo aInfo(ePaper);
1189 			pSetupData->mnPaperWidth  = aInfo.getWidth();
1190 			pSetupData->mnPaperHeight = aInfo.getHeight();
1191 		}
1192 
1193 		if ( IsDisplayPrinter() )
1194 		{
1195 			mbNewJobSetup = sal_True;
1196 			maJobSetup = aJobSetup;
1197 			return sal_True;
1198 		}
1199 
1200 		ImplReleaseGraphics();
1201 		if ( ePaper == PAPER_USER )
1202 			ImplFindPaperFormatForUserSize( aJobSetup, false );
1203 		if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE|SAL_JOBSET_ORIENTATION, pSetupData ) )
1204 		{
1205 			ImplUpdateJobSetupPaper( aJobSetup );
1206 			mbNewJobSetup = sal_True;
1207 			maJobSetup = aJobSetup;
1208 			ImplUpdatePageData();
1209 			ImplUpdateFontList();
1210 			return sal_True;
1211 		}
1212 		else
1213 			return sal_False;
1214 	}
1215 
1216 	return sal_True;
1217 }
1218 
1219 // -----------------------------------------------------------------------
1220 
1221 sal_Bool Printer::SetPaperSizeUser( const Size& rSize )
1222 {
1223     return SetPaperSizeUser( rSize, false );
1224 }
1225 
1226 sal_Bool Printer::SetPaperSizeUser( const Size& rSize, bool bMatchNearest )
1227 {
1228 	if ( mbInPrintPage )
1229 		return sal_False;
1230 
1231 	Size	aPixSize = LogicToPixel( rSize );
1232 	Size	aPageSize = PixelToLogic( aPixSize, MAP_100TH_MM );
1233 	if ( (maJobSetup.ImplGetConstData()->mePaperFormat != PAPER_USER)		||
1234 		 (maJobSetup.ImplGetConstData()->mnPaperWidth  != aPageSize.Width()) ||
1235 		 (maJobSetup.ImplGetConstData()->mnPaperHeight != aPageSize.Height()) )
1236 	{
1237 		JobSetup		aJobSetup = maJobSetup;
1238 		ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1239 		pSetupData->mePaperFormat	= PAPER_USER;
1240 		pSetupData->mnPaperWidth	= aPageSize.Width();
1241 		pSetupData->mnPaperHeight	= aPageSize.Height();
1242 
1243 		if ( IsDisplayPrinter() )
1244 		{
1245 			mbNewJobSetup = sal_True;
1246 			maJobSetup = aJobSetup;
1247 			return sal_True;
1248 		}
1249 
1250 		ImplReleaseGraphics();
1251 		ImplFindPaperFormatForUserSize( aJobSetup, bMatchNearest );
1252 
1253 		// Changing the paper size can also change the orientation!
1254 		if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE|SAL_JOBSET_ORIENTATION, pSetupData ) )
1255 		{
1256 			ImplUpdateJobSetupPaper( aJobSetup );
1257 			mbNewJobSetup = sal_True;
1258 			maJobSetup = aJobSetup;
1259 			ImplUpdatePageData();
1260 			ImplUpdateFontList();
1261 			return sal_True;
1262 		}
1263 		else
1264 			return sal_False;
1265 	}
1266 
1267 	return sal_True;
1268 }
1269 
1270 // -----------------------------------------------------------------------
1271 
1272 int Printer::GetPaperInfoCount() const
1273 {
1274     if( ! mpInfoPrinter )
1275         return 0;
1276     if( ! mpInfoPrinter->m_bPapersInit )
1277         mpInfoPrinter->InitPaperFormats( maJobSetup.ImplGetConstData() );
1278     return mpInfoPrinter->m_aPaperFormats.size();
1279 }
1280 
1281 // -----------------------------------------------------------------------
1282 
1283 rtl::OUString Printer::GetPaperName( Paper ePaper )
1284 {
1285     ImplSVData* pSVData = ImplGetSVData();
1286     if( ! pSVData->mpPaperNames )
1287     {
1288         pSVData->mpPaperNames = new std::hash_map< int, rtl::OUString >();
1289         if( ImplGetResMgr() )
1290         {
1291             ResStringArray aPaperStrings( VclResId( RID_STR_PAPERNAMES ) );
1292             static const int PaperIndex[] =
1293             {
1294                 PAPER_A0, PAPER_A1, PAPER_A2, PAPER_A3, PAPER_A4, PAPER_A5,
1295                 PAPER_B4_ISO, PAPER_B5_ISO, PAPER_LETTER, PAPER_LEGAL, PAPER_TABLOID,
1296                 PAPER_USER, PAPER_B6_ISO, PAPER_ENV_C4, PAPER_ENV_C5, PAPER_ENV_C6, PAPER_ENV_C65,
1297                 PAPER_ENV_DL, PAPER_SLIDE_DIA, PAPER_SCREEN, PAPER_C, PAPER_D, PAPER_E,
1298                 PAPER_EXECUTIVE, PAPER_FANFOLD_LEGAL_DE, PAPER_ENV_MONARCH, PAPER_ENV_PERSONAL,
1299                 PAPER_ENV_9, PAPER_ENV_10, PAPER_ENV_11, PAPER_ENV_12, PAPER_KAI16,
1300                 PAPER_KAI32, PAPER_KAI32BIG, PAPER_B4_JIS, PAPER_B5_JIS, PAPER_B6_JIS
1301             };
1302             OSL_ENSURE( sal_uInt32(sizeof(PaperIndex)/sizeof(PaperIndex[0])) == aPaperStrings.Count(), "localized paper name count wrong" );
1303             for( int i = 0; i < int(sizeof(PaperIndex)/sizeof(PaperIndex[0])); i++ )
1304                 (*pSVData->mpPaperNames)[PaperIndex[i]] = aPaperStrings.GetString(i);
1305         }
1306     }
1307 
1308     std::hash_map<int,rtl::OUString>::const_iterator it = pSVData->mpPaperNames->find( (int)ePaper );
1309     return (it != pSVData->mpPaperNames->end()) ? it->second : rtl::OUString();
1310 }
1311 
1312 // -----------------------------------------------------------------------
1313 
1314 rtl::OUString Printer::GetPaperName( bool i_bPaperUser ) const
1315 {
1316 	Size  aPageSize = PixelToLogic( GetPaperSizePixel(), MAP_100TH_MM );
1317 	Paper ePaper    = ImplGetPaperFormat( aPageSize.Width(), aPageSize.Height() );
1318 	if( ePaper == PAPER_USER )
1319 	    ePaper = ImplGetPaperFormat( aPageSize.Height(), aPageSize.Width() );
1320 	return (ePaper != PAPER_USER || i_bPaperUser ) ? GetPaperName( ePaper ) : rtl::OUString();
1321 }
1322 
1323 // -----------------------------------------------------------------------
1324 
1325 const PaperInfo& Printer::GetPaperInfo( int nPaper ) const
1326 {
1327     if( ! mpInfoPrinter )
1328         return ImplGetEmptyPaper();
1329     if( ! mpInfoPrinter->m_bPapersInit )
1330         mpInfoPrinter->InitPaperFormats( maJobSetup.ImplGetConstData() );
1331     if( mpInfoPrinter->m_aPaperFormats.empty() || nPaper < 0 || nPaper >= int(mpInfoPrinter->m_aPaperFormats.size()) )
1332         return ImplGetEmptyPaper();
1333     return mpInfoPrinter->m_aPaperFormats[nPaper];
1334 }
1335 
1336 // -----------------------------------------------------------------------
1337 
1338 DuplexMode Printer::GetDuplexMode() const
1339 {
1340 	return maJobSetup.ImplGetConstData()->meDuplexMode;
1341 }
1342 
1343 // -----------------------------------------------------------------------
1344 
1345 sal_Bool Printer::SetDuplexMode( DuplexMode eDuplex )
1346 {
1347 	if ( mbInPrintPage )
1348 		return sal_False;
1349 
1350 	if ( maJobSetup.ImplGetConstData()->meDuplexMode != eDuplex )
1351 	{
1352 		JobSetup		aJobSetup = maJobSetup;
1353 		ImplJobSetup*	pSetupData = aJobSetup.ImplGetData();
1354 		pSetupData->meDuplexMode = eDuplex;
1355 
1356 		if ( IsDisplayPrinter() )
1357 		{
1358 			mbNewJobSetup = sal_True;
1359 			maJobSetup = aJobSetup;
1360 			return sal_True;
1361 		}
1362 
1363 		ImplReleaseGraphics();
1364 		if ( mpInfoPrinter->SetData( SAL_JOBSET_DUPLEXMODE, pSetupData ) )
1365 		{
1366 			ImplUpdateJobSetupPaper( aJobSetup );
1367 			mbNewJobSetup = sal_True;
1368 			maJobSetup = aJobSetup;
1369 			ImplUpdatePageData();
1370 			ImplUpdateFontList();
1371 			return sal_True;
1372 		}
1373 		else
1374 			return sal_False;
1375 	}
1376 
1377 	return sal_True;
1378 }
1379 
1380 // -----------------------------------------------------------------------
1381 
1382 int Printer::GetLandscapeAngle() const
1383 {
1384     return mpInfoPrinter ? mpInfoPrinter->GetLandscapeAngle( maJobSetup.ImplGetConstData() ) : 900;
1385 }
1386 
1387 // -----------------------------------------------------------------------
1388 
1389 Paper Printer::GetPaper() const
1390 {
1391 	return maJobSetup.ImplGetConstData()->mePaperFormat;
1392 }
1393 
1394 // -----------------------------------------------------------------------
1395 
1396 sal_uInt16 Printer::GetPaperBinCount() const
1397 {
1398 	if ( IsDisplayPrinter() )
1399 		return 0;
1400 
1401 	return (sal_uInt16)mpInfoPrinter->GetPaperBinCount( maJobSetup.ImplGetConstData() );
1402 }
1403 
1404 // -----------------------------------------------------------------------
1405 
1406 XubString Printer::GetPaperBinName( sal_uInt16 nPaperBin ) const
1407 {
1408 	if ( IsDisplayPrinter() )
1409 		return ImplGetSVEmptyStr();
1410 
1411 	if ( nPaperBin < GetPaperBinCount() )
1412 		return mpInfoPrinter->GetPaperBinName( maJobSetup.ImplGetConstData(), nPaperBin );
1413 	else
1414 		return ImplGetSVEmptyStr();
1415 }
1416 
1417 // -----------------------------------------------------------------------
1418 
1419 sal_Bool Printer::SetCopyCount( sal_uInt16 nCopy, sal_Bool bCollate )
1420 {
1421 	mnCopyCount = nCopy;
1422     mbCollateCopy = bCollate;
1423 	return sal_True;
1424 }
1425 
1426 // -----------------------------------------------------------------------
1427 
1428 void Printer::Error()
1429 {
1430 	maErrorHdl.Call( this );
1431 }
1432 
1433 // -----------------------------------------------------------------------
1434 
1435 
1436 sal_uLong Printer::ImplSalPrinterErrorCodeToVCL( sal_uLong nError )
1437 {
1438 	sal_uLong nVCLError;
1439 	switch ( nError )
1440 	{
1441 		case 0:
1442 			nVCLError = PRINTER_OK;
1443 			break;
1444 		case SAL_PRINTER_ERROR_ABORT:
1445 			nVCLError = PRINTER_ABORT;
1446 			break;
1447 		default:
1448 			nVCLError = PRINTER_GENERALERROR;
1449 			break;
1450 	}
1451 
1452 	return nVCLError;
1453 }
1454 
1455 // -----------------------------------------------------------------------
1456 
1457 void Printer::ImplEndPrint()
1458 {
1459 	mbPrinting		= sal_False;
1460 	mnCurPrintPage	= 0;
1461 	maJobName.Erase();
1462 }
1463 
1464 // -----------------------------------------------------------------------
1465 
1466 IMPL_LINK( Printer, ImplDestroyPrinterAsync, void*, pSalPrinter )
1467 {
1468 	SalPrinter* pPrinter = (SalPrinter*)pSalPrinter;
1469 	ImplSVData* pSVData = ImplGetSVData();
1470 	pSVData->mpDefInst->DestroyPrinter( pPrinter );
1471 	return 0;
1472 }
1473 
1474 // -----------------------------------------------------------------------
1475 
1476 sal_Bool Printer::EndJob()
1477 {
1478 	sal_Bool bRet = sal_False;
1479 	if ( !IsJobActive() )
1480 		return bRet;
1481 
1482 	DBG_ASSERT( !mbInPrintPage, "Printer::EndJob() - StartPage() without EndPage() called" );
1483 
1484 	mbJobActive = sal_False;
1485 
1486 	if ( mpPrinter )
1487 	{
1488 		ImplReleaseGraphics();
1489 
1490 		mnCurPage = 0;
1491 
1492 		bRet = sal_True;
1493 
1494         mbPrinting		= sal_False;
1495         mnCurPrintPage	= 0;
1496         maJobName.Erase();
1497 
1498         mbDevOutput = sal_False;
1499         bRet = mpPrinter->EndJob();
1500         // Hier den Drucker nicht asyncron zerstoeren, da es
1501         // W95 nicht verkraftet, wenn gleichzeitig gedruckt wird
1502         // und ein Druckerobjekt zerstoert wird
1503         ImplGetSVData()->mpDefInst->DestroyPrinter( mpPrinter );
1504         mpPrinter = NULL;
1505 	}
1506 
1507 	return bRet;
1508 }
1509 
1510 // -----------------------------------------------------------------------
1511 
1512 sal_Bool Printer::AbortJob()
1513 {
1514 	// Wenn wir einen Queue-Printer haben, kann man diesen noch mit
1515 	// AbortJob() abbrechen, solange dieser noch am Drucken ist
1516 	if ( !IsJobActive() && !IsPrinting() )
1517 		return sal_False;
1518 
1519 	mbJobActive 	= sal_False;
1520 	mbInPrintPage	= sal_False;
1521 	mpJobGraphics	= NULL;
1522 
1523 	if ( mpPrinter )
1524 	{
1525 		mbPrinting		= sal_False;
1526 		mnCurPage		= 0;
1527 		mnCurPrintPage	= 0;
1528 		maJobName.Erase();
1529 
1530         ImplReleaseGraphics();
1531         mbDevOutput = sal_False;
1532         mpPrinter->AbortJob();
1533         Application::PostUserEvent( LINK( this, Printer, ImplDestroyPrinterAsync ), mpPrinter );
1534         mpPrinter = NULL;
1535 
1536 		return sal_True;
1537 	}
1538 
1539 	return sal_False;
1540 }
1541 
1542 // -----------------------------------------------------------------------
1543 
1544 void Printer::ImplStartPage()
1545 {
1546 	if ( !IsJobActive() )
1547 		return;
1548 
1549 	if ( mpPrinter )
1550 	{
1551         SalGraphics* pGraphics = mpPrinter->StartPage( maJobSetup.ImplGetConstData(), mbNewJobSetup );
1552         if ( pGraphics )
1553         {
1554             ImplReleaseGraphics();
1555             mpJobGraphics = pGraphics;
1556         }
1557         mbDevOutput = sal_True;
1558 
1559 		// PrintJob not aborted ???
1560 		if ( IsJobActive() )
1561 		{
1562 			mbInPrintPage = sal_True;
1563 			mnCurPage++;
1564             mnCurPrintPage++;
1565 		}
1566 	}
1567 }
1568 
1569 // -----------------------------------------------------------------------
1570 
1571 void Printer::ImplEndPage()
1572 {
1573 	if ( !IsJobActive() )
1574 		return;
1575 
1576 	mbInPrintPage = sal_False;
1577 
1578 	if ( mpPrinter )
1579 	{
1580         mpPrinter->EndPage();
1581         ImplReleaseGraphics();
1582         mbDevOutput = sal_False;
1583 
1584 		mpJobGraphics = NULL;
1585 		mbNewJobSetup = sal_False;
1586 	}
1587 }
1588 
1589 // -----------------------------------------------------------------------
1590 
1591 void Printer::updatePrinters()
1592 {
1593 	ImplSVData* 		pSVData = ImplGetSVData();
1594 	ImplPrnQueueList*	pPrnList = pSVData->maGDIData.mpPrinterQueueList;
1595 
1596 	if ( pPrnList )
1597 	{
1598         ImplPrnQueueList* pNewList = new ImplPrnQueueList;
1599         pSVData->mpDefInst->GetPrinterQueueInfo( pNewList );
1600 
1601         bool bChanged = pPrnList->m_aQueueInfos.size() != pNewList->m_aQueueInfos.size();
1602         for( unsigned int i = 0; ! bChanged && i < pPrnList->m_aQueueInfos.size(); i++ )
1603         {
1604             ImplPrnQueueData& rInfo     = pPrnList->m_aQueueInfos[i];
1605             ImplPrnQueueData& rNewInfo  = pNewList->m_aQueueInfos[i];
1606             if( ! rInfo.mpSalQueueInfo || ! rNewInfo.mpSalQueueInfo || // sanity check
1607                 rInfo.mpSalQueueInfo->maPrinterName != rNewInfo.mpSalQueueInfo->maPrinterName )
1608             {
1609                 bChanged = true;
1610             }
1611 		}
1612         if( bChanged )
1613         {
1614             ImplDeletePrnQueueList();
1615             pSVData->maGDIData.mpPrinterQueueList = pNewList;
1616 
1617             Application* pApp = GetpApp();
1618             if( pApp )
1619             {
1620                 DataChangedEvent aDCEvt( DATACHANGED_PRINTER );
1621                 pApp->DataChanged( aDCEvt );
1622                 pApp->NotifyAllWindows( aDCEvt );
1623             }
1624         }
1625         else
1626             delete pNewList;
1627 	}
1628 }
1629