xref: /trunk/main/vcl/source/gdi/print.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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