1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <unistd.h>
32*cdf0e10cSrcweir #include <sys/wait.h>
33*cdf0e10cSrcweir #include <signal.h>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include "cupsmgr.hxx"
36*cdf0e10cSrcweir #include "vcl/fontmanager.hxx"
37*cdf0e10cSrcweir #include "vcl/strhelper.hxx"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include "unx/saldata.hxx"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "tools/urlobj.hxx"
42*cdf0e10cSrcweir #include "tools/stream.hxx"
43*cdf0e10cSrcweir #include "tools/debug.hxx"
44*cdf0e10cSrcweir #include "tools/config.hxx"
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #include "i18npool/paper.hxx"
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #include "rtl/strbuf.hxx"
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir #include "osl/thread.hxx"
51*cdf0e10cSrcweir #include "osl/mutex.hxx"
52*cdf0e10cSrcweir #include "osl/process.h"
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir // filename of configuration files
55*cdf0e10cSrcweir #define PRINT_FILENAME  "psprint.conf"
56*cdf0e10cSrcweir // the group of the global defaults
57*cdf0e10cSrcweir #define GLOBAL_DEFAULTS_GROUP "__Global_Printer_Defaults__"
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir #include <hash_set>
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir using namespace psp;
62*cdf0e10cSrcweir using namespace rtl;
63*cdf0e10cSrcweir using namespace osl;
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir namespace psp
66*cdf0e10cSrcweir {
67*cdf0e10cSrcweir     class SystemQueueInfo : public Thread
68*cdf0e10cSrcweir     {
69*cdf0e10cSrcweir         mutable Mutex               m_aMutex;
70*cdf0e10cSrcweir         bool                        m_bChanged;
71*cdf0e10cSrcweir         std::list< PrinterInfoManager::SystemPrintQueue >
72*cdf0e10cSrcweir                                     m_aQueues;
73*cdf0e10cSrcweir         OUString                    m_aCommand;
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir         virtual void run();
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir         public:
78*cdf0e10cSrcweir         SystemQueueInfo();
79*cdf0e10cSrcweir         ~SystemQueueInfo();
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir         bool hasChanged() const;
82*cdf0e10cSrcweir         OUString getCommand() const;
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir         // sets changed status to false; therefore not const
85*cdf0e10cSrcweir         void getSystemQueues( std::list< PrinterInfoManager::SystemPrintQueue >& rQueues );
86*cdf0e10cSrcweir     };
87*cdf0e10cSrcweir } // namespace
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir /*
90*cdf0e10cSrcweir *  class PrinterInfoManager
91*cdf0e10cSrcweir */
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir // -----------------------------------------------------------------
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir PrinterInfoManager& PrinterInfoManager::get()
96*cdf0e10cSrcweir {
97*cdf0e10cSrcweir     SalData* pSalData = GetSalData();
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir     if( ! pSalData->m_pPIManager )
100*cdf0e10cSrcweir     {
101*cdf0e10cSrcweir         pSalData->m_pPIManager = CUPSManager::tryLoadCUPS();
102*cdf0e10cSrcweir         if( ! pSalData->m_pPIManager )
103*cdf0e10cSrcweir             pSalData->m_pPIManager = new PrinterInfoManager();
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir         pSalData->m_pPIManager->initialize();
106*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
107*cdf0e10cSrcweir         fprintf( stderr, "PrinterInfoManager::get create Manager of type %d\n", pSalData->m_pPIManager->getType() );
108*cdf0e10cSrcweir         #endif
109*cdf0e10cSrcweir     }
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir     return *pSalData->m_pPIManager;
112*cdf0e10cSrcweir }
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir void PrinterInfoManager::release()
115*cdf0e10cSrcweir {
116*cdf0e10cSrcweir     SalData* pSalData = GetSalData();
117*cdf0e10cSrcweir     delete pSalData->m_pPIManager;
118*cdf0e10cSrcweir     pSalData->m_pPIManager = NULL;
119*cdf0e10cSrcweir }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir // -----------------------------------------------------------------
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir PrinterInfoManager::PrinterInfoManager( Type eType ) :
124*cdf0e10cSrcweir     m_pQueueInfo( NULL ),
125*cdf0e10cSrcweir     m_eType( eType ),
126*cdf0e10cSrcweir     m_bUseIncludeFeature( false ),
127*cdf0e10cSrcweir     m_bUseJobPatch( true ),
128*cdf0e10cSrcweir     m_aSystemDefaultPaper( RTL_CONSTASCII_USTRINGPARAM( "A4" ) ),
129*cdf0e10cSrcweir     m_bDisableCUPS( false )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir     if( eType == Default )
132*cdf0e10cSrcweir         m_pQueueInfo = new SystemQueueInfo();
133*cdf0e10cSrcweir     initSystemDefaultPaper();
134*cdf0e10cSrcweir }
135*cdf0e10cSrcweir 
136*cdf0e10cSrcweir // -----------------------------------------------------------------
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir PrinterInfoManager::~PrinterInfoManager()
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir     delete m_pQueueInfo;
141*cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 1
142*cdf0e10cSrcweir     fprintf( stderr, "PrinterInfoManager: destroyed Manager of type %d\n", getType() );
143*cdf0e10cSrcweir     #endif
144*cdf0e10cSrcweir }
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir // -----------------------------------------------------------------
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir bool PrinterInfoManager::isCUPSDisabled() const
149*cdf0e10cSrcweir {
150*cdf0e10cSrcweir     return m_bDisableCUPS;
151*cdf0e10cSrcweir }
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir // -----------------------------------------------------------------
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir void PrinterInfoManager::setCUPSDisabled( bool bDisable )
156*cdf0e10cSrcweir {
157*cdf0e10cSrcweir     m_bDisableCUPS = bDisable;
158*cdf0e10cSrcweir     writePrinterConfig();
159*cdf0e10cSrcweir     // actually we know the printers changed
160*cdf0e10cSrcweir     // however this triggers reinitialization the right way
161*cdf0e10cSrcweir     checkPrintersChanged( true );
162*cdf0e10cSrcweir }
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir // -----------------------------------------------------------------
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir void PrinterInfoManager::initSystemDefaultPaper()
167*cdf0e10cSrcweir {
168*cdf0e10cSrcweir     m_aSystemDefaultPaper = rtl::OStringToOUString(
169*cdf0e10cSrcweir         PaperInfo::toPSName(PaperInfo::getSystemDefaultPaper().getPaper()),
170*cdf0e10cSrcweir         RTL_TEXTENCODING_UTF8);
171*cdf0e10cSrcweir }
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir // -----------------------------------------------------------------
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir bool PrinterInfoManager::checkPrintersChanged( bool bWait )
176*cdf0e10cSrcweir {
177*cdf0e10cSrcweir     // check if files were created, deleted or modified since initialize()
178*cdf0e10cSrcweir     ::std::list< WatchFile >::const_iterator it;
179*cdf0e10cSrcweir     bool bChanged = false;
180*cdf0e10cSrcweir     for( it = m_aWatchFiles.begin(); it != m_aWatchFiles.end() && ! bChanged; ++it )
181*cdf0e10cSrcweir     {
182*cdf0e10cSrcweir         DirectoryItem aItem;
183*cdf0e10cSrcweir         if( DirectoryItem::get( it->m_aFilePath, aItem ) )
184*cdf0e10cSrcweir         {
185*cdf0e10cSrcweir             if( it->m_aModified.Seconds != 0 )
186*cdf0e10cSrcweir                 bChanged = true; // file probably has vanished
187*cdf0e10cSrcweir         }
188*cdf0e10cSrcweir         else
189*cdf0e10cSrcweir         {
190*cdf0e10cSrcweir             FileStatus aStatus( FileStatusMask_ModifyTime );
191*cdf0e10cSrcweir             if( aItem.getFileStatus( aStatus ) )
192*cdf0e10cSrcweir                 bChanged = true; // unlikely but not impossible
193*cdf0e10cSrcweir             else
194*cdf0e10cSrcweir             {
195*cdf0e10cSrcweir                 TimeValue aModified = aStatus.getModifyTime();
196*cdf0e10cSrcweir                 if( aModified.Seconds != it->m_aModified.Seconds )
197*cdf0e10cSrcweir                     bChanged = true;
198*cdf0e10cSrcweir             }
199*cdf0e10cSrcweir         }
200*cdf0e10cSrcweir     }
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir     if( bWait && m_pQueueInfo )
203*cdf0e10cSrcweir     {
204*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
205*cdf0e10cSrcweir         fprintf( stderr, "syncing printer discovery thread\n" );
206*cdf0e10cSrcweir         #endif
207*cdf0e10cSrcweir         m_pQueueInfo->join();
208*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
209*cdf0e10cSrcweir         fprintf( stderr, "done: syncing printer discovery thread\n" );
210*cdf0e10cSrcweir         #endif
211*cdf0e10cSrcweir     }
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir     if( ! bChanged && m_pQueueInfo )
214*cdf0e10cSrcweir         bChanged = m_pQueueInfo->hasChanged();
215*cdf0e10cSrcweir     if( bChanged )
216*cdf0e10cSrcweir     {
217*cdf0e10cSrcweir         initialize();
218*cdf0e10cSrcweir     }
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir     return bChanged;
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir // -----------------------------------------------------------------
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir void PrinterInfoManager::initialize()
226*cdf0e10cSrcweir {
227*cdf0e10cSrcweir     m_bUseIncludeFeature = false;
228*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = gsl_getSystemTextEncoding();
229*cdf0e10cSrcweir     m_aPrinters.clear();
230*cdf0e10cSrcweir     m_aWatchFiles.clear();
231*cdf0e10cSrcweir     OUString aDefaultPrinter;
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir     // first initialize the global defaults
234*cdf0e10cSrcweir     // have to iterate over all possible files
235*cdf0e10cSrcweir     // there should be only one global setup section in all
236*cdf0e10cSrcweir     // available config files
237*cdf0e10cSrcweir     m_aGlobalDefaults = PrinterInfo();
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir     // need a parser for the PPDContext. generic printer should do.
240*cdf0e10cSrcweir     m_aGlobalDefaults.m_pParser = PPDParser::getParser( String( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) );
241*cdf0e10cSrcweir     m_aGlobalDefaults.m_aContext.setParser( m_aGlobalDefaults.m_pParser );
242*cdf0e10cSrcweir     m_aGlobalDefaults.m_bPerformFontSubstitution = true;
243*cdf0e10cSrcweir     m_bDisableCUPS = false;
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir     if( ! m_aGlobalDefaults.m_pParser )
246*cdf0e10cSrcweir     {
247*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
248*cdf0e10cSrcweir         fprintf( stderr, "Error: no default PPD file SGENPRT available, shutting down psprint...\n" );
249*cdf0e10cSrcweir         #endif
250*cdf0e10cSrcweir         return;
251*cdf0e10cSrcweir     }
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir     std::list< OUString > aDirList;
254*cdf0e10cSrcweir     psp::getPrinterPathList( aDirList, NULL );
255*cdf0e10cSrcweir     std::list< OUString >::const_iterator print_dir_it;
256*cdf0e10cSrcweir     for( print_dir_it = aDirList.begin(); print_dir_it != aDirList.end(); ++print_dir_it )
257*cdf0e10cSrcweir     {
258*cdf0e10cSrcweir         INetURLObject aFile( *print_dir_it, INET_PROT_FILE, INetURLObject::ENCODE_ALL );
259*cdf0e10cSrcweir         aFile.Append( String( RTL_CONSTASCII_USTRINGPARAM( PRINT_FILENAME ) ) );
260*cdf0e10cSrcweir         Config aConfig( aFile.PathToFileName() );
261*cdf0e10cSrcweir         if( aConfig.HasGroup( GLOBAL_DEFAULTS_GROUP ) )
262*cdf0e10cSrcweir         {
263*cdf0e10cSrcweir             #if OSL_DEBUG_LEVEL > 1
264*cdf0e10cSrcweir             fprintf( stderr, "found global defaults in %s\n", OUStringToOString( aFile.PathToFileName(), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
265*cdf0e10cSrcweir             #endif
266*cdf0e10cSrcweir             aConfig.SetGroup( GLOBAL_DEFAULTS_GROUP );
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir             ByteString aValue( aConfig.ReadKey( "Copies" ) );
269*cdf0e10cSrcweir             if( aValue.Len() )
270*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nCopies = aValue.ToInt32();
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "Orientation" );
273*cdf0e10cSrcweir             if( aValue.Len() )
274*cdf0e10cSrcweir                 m_aGlobalDefaults.m_eOrientation = aValue.EqualsIgnoreCaseAscii( "Landscape" ) ? orientation::Landscape : orientation::Portrait;
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "MarginAdjust" );
277*cdf0e10cSrcweir             if( aValue.Len() )
278*cdf0e10cSrcweir             {
279*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nLeftMarginAdjust   = aValue.GetToken( 0, ',' ).ToInt32();
280*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nRightMarginAdjust  = aValue.GetToken( 1, ',' ).ToInt32();
281*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nTopMarginAdjust    = aValue.GetToken( 2, ',' ).ToInt32();
282*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nBottomMarginAdjust = aValue.GetToken( 3, ',' ).ToInt32();
283*cdf0e10cSrcweir             }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "ColorDepth", "24" );
286*cdf0e10cSrcweir             if( aValue.Len() )
287*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nColorDepth = aValue.ToInt32();
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "ColorDevice" );
290*cdf0e10cSrcweir             if( aValue.Len() )
291*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nColorDevice = aValue.ToInt32();
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "PSLevel" );
294*cdf0e10cSrcweir             if( aValue.Len() )
295*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nPSLevel = aValue.ToInt32();
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "PDFDevice" );
298*cdf0e10cSrcweir             if( aValue.Len() )
299*cdf0e10cSrcweir                 m_aGlobalDefaults.m_nPDFDevice = aValue.ToInt32();
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "PerformFontSubstitution" );
302*cdf0e10cSrcweir             if( aValue.Len() )
303*cdf0e10cSrcweir             {
304*cdf0e10cSrcweir                 if( ! aValue.Equals( "0" ) && ! aValue.EqualsIgnoreCaseAscii( "false" ) )
305*cdf0e10cSrcweir                     m_aGlobalDefaults.m_bPerformFontSubstitution = true;
306*cdf0e10cSrcweir                 else
307*cdf0e10cSrcweir                     m_aGlobalDefaults.m_bPerformFontSubstitution = false;
308*cdf0e10cSrcweir             }
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir             aValue = aConfig.ReadKey( "DisableCUPS" );
311*cdf0e10cSrcweir             if( aValue.Len() )
312*cdf0e10cSrcweir             {
313*cdf0e10cSrcweir                 if( aValue.Equals( "1" ) || aValue.EqualsIgnoreCaseAscii( "true" ) )
314*cdf0e10cSrcweir                     m_bDisableCUPS = true;
315*cdf0e10cSrcweir                 else
316*cdf0e10cSrcweir                     m_bDisableCUPS = false;
317*cdf0e10cSrcweir             }
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir             // get the PPDContext of global JobData
320*cdf0e10cSrcweir             for( int nKey = 0; nKey < aConfig.GetKeyCount(); nKey++ )
321*cdf0e10cSrcweir             {
322*cdf0e10cSrcweir                 ByteString aKey( aConfig.GetKeyName( nKey ) );
323*cdf0e10cSrcweir                 if( aKey.CompareTo( "PPD_", 4 ) == COMPARE_EQUAL )
324*cdf0e10cSrcweir                 {
325*cdf0e10cSrcweir                     aValue = aConfig.ReadKey( aKey );
326*cdf0e10cSrcweir                     const PPDKey* pKey = m_aGlobalDefaults.m_pParser->getKey( String( aKey.Copy( 4 ), RTL_TEXTENCODING_ISO_8859_1 ) );
327*cdf0e10cSrcweir                     if( pKey )
328*cdf0e10cSrcweir                     {
329*cdf0e10cSrcweir                         m_aGlobalDefaults.m_aContext.
330*cdf0e10cSrcweir                         setValue( pKey,
331*cdf0e10cSrcweir                         aValue.Equals( "*nil" ) ? NULL : pKey->getValue( String( aValue, RTL_TEXTENCODING_ISO_8859_1 ) ),
332*cdf0e10cSrcweir                         sal_True );
333*cdf0e10cSrcweir                     }
334*cdf0e10cSrcweir                 }
335*cdf0e10cSrcweir                 else if( aKey.Len() > 10 && aKey.CompareTo("SubstFont_", 10 ) == COMPARE_EQUAL )
336*cdf0e10cSrcweir                 {
337*cdf0e10cSrcweir                     aValue = aConfig.ReadKey( aKey );
338*cdf0e10cSrcweir                     m_aGlobalDefaults.m_aFontSubstitutes[ OStringToOUString( aKey.Copy( 10 ), RTL_TEXTENCODING_ISO_8859_1 ) ] = OStringToOUString( aValue, RTL_TEXTENCODING_ISO_8859_1 );
339*cdf0e10cSrcweir                 }
340*cdf0e10cSrcweir             }
341*cdf0e10cSrcweir             #if OSL_DEBUG_LEVEL > 1
342*cdf0e10cSrcweir             fprintf( stderr, "global settings: fontsubst = %s, %d substitutes\n", m_aGlobalDefaults.m_bPerformFontSubstitution ? "true" : "false", (int)m_aGlobalDefaults.m_aFontSubstitutes.size() );
343*cdf0e10cSrcweir             #endif
344*cdf0e10cSrcweir         }
345*cdf0e10cSrcweir     }
346*cdf0e10cSrcweir     setDefaultPaper( m_aGlobalDefaults.m_aContext );
347*cdf0e10cSrcweir     fillFontSubstitutions( m_aGlobalDefaults );
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir     // now collect all available printers
350*cdf0e10cSrcweir     for( print_dir_it = aDirList.begin(); print_dir_it != aDirList.end(); ++print_dir_it )
351*cdf0e10cSrcweir     {
352*cdf0e10cSrcweir         INetURLObject aDir( *print_dir_it, INET_PROT_FILE, INetURLObject::ENCODE_ALL );
353*cdf0e10cSrcweir         INetURLObject aFile( aDir );
354*cdf0e10cSrcweir         aFile.Append( String( RTL_CONSTASCII_USTRINGPARAM( PRINT_FILENAME ) ) );
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir         // check directory validity
357*cdf0e10cSrcweir         OUString aUniPath;
358*cdf0e10cSrcweir         FileBase::getFileURLFromSystemPath( aDir.PathToFileName(), aUniPath );
359*cdf0e10cSrcweir         Directory aDirectory( aUniPath );
360*cdf0e10cSrcweir         if( aDirectory.open() )
361*cdf0e10cSrcweir             continue;
362*cdf0e10cSrcweir         aDirectory.close();
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir         FileBase::getFileURLFromSystemPath( aFile.PathToFileName(), aUniPath );
366*cdf0e10cSrcweir         FileStatus aStatus( FileStatusMask_ModifyTime );
367*cdf0e10cSrcweir         DirectoryItem aItem;
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir         // setup WatchFile list
370*cdf0e10cSrcweir         WatchFile aWatchFile;
371*cdf0e10cSrcweir         aWatchFile.m_aFilePath = aUniPath;
372*cdf0e10cSrcweir         if( ! DirectoryItem::get( aUniPath, aItem ) &&
373*cdf0e10cSrcweir             ! aItem.getFileStatus( aStatus ) )
374*cdf0e10cSrcweir         {
375*cdf0e10cSrcweir             aWatchFile.m_aModified = aStatus.getModifyTime();
376*cdf0e10cSrcweir         }
377*cdf0e10cSrcweir         else
378*cdf0e10cSrcweir         {
379*cdf0e10cSrcweir             aWatchFile.m_aModified.Seconds = 0;
380*cdf0e10cSrcweir             aWatchFile.m_aModified.Nanosec = 0;
381*cdf0e10cSrcweir         }
382*cdf0e10cSrcweir         m_aWatchFiles.push_back( aWatchFile );
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir         Config aConfig( aFile.PathToFileName() );
385*cdf0e10cSrcweir         for( int nGroup = 0; nGroup < aConfig.GetGroupCount(); nGroup++ )
386*cdf0e10cSrcweir         {
387*cdf0e10cSrcweir             aConfig.SetGroup( aConfig.GetGroupName( nGroup ) );
388*cdf0e10cSrcweir             ByteString aValue = aConfig.ReadKey( "Printer" );
389*cdf0e10cSrcweir             if( aValue.Len() )
390*cdf0e10cSrcweir             {
391*cdf0e10cSrcweir                 OUString aPrinterName;
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir                 int nNamePos = aValue.Search( '/' );
394*cdf0e10cSrcweir                 // check for valid value of "Printer"
395*cdf0e10cSrcweir                 if( nNamePos == STRING_NOTFOUND )
396*cdf0e10cSrcweir                     continue;
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir                 Printer aPrinter;
399*cdf0e10cSrcweir                 // initialize to global defaults
400*cdf0e10cSrcweir                 aPrinter.m_aInfo = m_aGlobalDefaults;
401*cdf0e10cSrcweir                 // global settings do not default the printer substitution
402*cdf0e10cSrcweir                 // list ! the substitution list in there is only used for
403*cdf0e10cSrcweir                 // newly created printers
404*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aFontSubstitutes.clear();
405*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aFontSubstitutions.clear();
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir                 aPrinterName = String( aValue.Copy( nNamePos+1 ), RTL_TEXTENCODING_UTF8 );
408*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aPrinterName     = aPrinterName;
409*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aDriverName      = String( aValue.Copy( 0, nNamePos ), RTL_TEXTENCODING_UTF8 );
410*cdf0e10cSrcweir 
411*cdf0e10cSrcweir                 // set parser, merge settings
412*cdf0e10cSrcweir                 // don't do this for CUPS printers as this is done
413*cdf0e10cSrcweir                 // by the CUPS system itself
414*cdf0e10cSrcweir                 if( aPrinter.m_aInfo.m_aDriverName.compareToAscii( "CUPS:", 5 ) != 0 )
415*cdf0e10cSrcweir                 {
416*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_pParser          = PPDParser::getParser( aPrinter.m_aInfo.m_aDriverName );
417*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_aContext.setParser( aPrinter.m_aInfo.m_pParser );
418*cdf0e10cSrcweir                     // note: setParser also purges the context
419*cdf0e10cSrcweir 
420*cdf0e10cSrcweir                     // ignore this printer if its driver is not found
421*cdf0e10cSrcweir                     if( ! aPrinter.m_aInfo.m_pParser )
422*cdf0e10cSrcweir                         continue;
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir                     // merge the ppd context keys if the printer has the same keys and values
425*cdf0e10cSrcweir                     // this is a bit tricky, since it involves mixing two PPDs
426*cdf0e10cSrcweir                     // without constraints which might end up badly
427*cdf0e10cSrcweir                     // this feature should be use with caution
428*cdf0e10cSrcweir                     // it is mainly to select default paper sizes for new printers
429*cdf0e10cSrcweir                     for( int nPPDValueModified = 0; nPPDValueModified < m_aGlobalDefaults.m_aContext.countValuesModified(); nPPDValueModified++ )
430*cdf0e10cSrcweir                     {
431*cdf0e10cSrcweir                         const PPDKey* pDefKey = m_aGlobalDefaults.m_aContext.getModifiedKey( nPPDValueModified );
432*cdf0e10cSrcweir                         const PPDValue* pDefValue = m_aGlobalDefaults.m_aContext.getValue( pDefKey );
433*cdf0e10cSrcweir                         const PPDKey* pPrinterKey = pDefKey ? aPrinter.m_aInfo.m_pParser->getKey( pDefKey->getKey() ) : NULL;
434*cdf0e10cSrcweir                         if( pDefKey && pPrinterKey )
435*cdf0e10cSrcweir                             // at least the options exist in both PPDs
436*cdf0e10cSrcweir                         {
437*cdf0e10cSrcweir                             if( pDefValue )
438*cdf0e10cSrcweir                             {
439*cdf0e10cSrcweir                                 const PPDValue* pPrinterValue = pPrinterKey->getValue( pDefValue->m_aOption );
440*cdf0e10cSrcweir                                 if( pPrinterValue )
441*cdf0e10cSrcweir                                     // the printer has a corresponding option for the key
442*cdf0e10cSrcweir                                 aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, pPrinterValue );
443*cdf0e10cSrcweir                             }
444*cdf0e10cSrcweir                             else
445*cdf0e10cSrcweir                                 aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, NULL );
446*cdf0e10cSrcweir                         }
447*cdf0e10cSrcweir                     }
448*cdf0e10cSrcweir 
449*cdf0e10cSrcweir                     aValue = aConfig.ReadKey( "Command" );
450*cdf0e10cSrcweir                     // no printer without a command
451*cdf0e10cSrcweir                     if( ! aValue.Len() )
452*cdf0e10cSrcweir                     {
453*cdf0e10cSrcweir                         /*  TODO:
454*cdf0e10cSrcweir                         *  porters: please append your platform to the Solaris
455*cdf0e10cSrcweir                         *  case if your platform has SystemV printing per default.
456*cdf0e10cSrcweir                         */
457*cdf0e10cSrcweir                         #if defined SOLARIS
458*cdf0e10cSrcweir                         aValue = "lp";
459*cdf0e10cSrcweir                         #else
460*cdf0e10cSrcweir                         aValue = "lpr";
461*cdf0e10cSrcweir                         #endif
462*cdf0e10cSrcweir                     }
463*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_aCommand = String( aValue, RTL_TEXTENCODING_UTF8 );
464*cdf0e10cSrcweir                 }
465*cdf0e10cSrcweir 
466*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "QuickCommand" );
467*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aQuickCommand = String( aValue, RTL_TEXTENCODING_UTF8 );
468*cdf0e10cSrcweir 
469*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "Features" );
470*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aFeatures = String( aValue, RTL_TEXTENCODING_UTF8 );
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir                 // override the settings in m_aGlobalDefaults if keys exist
473*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "DefaultPrinter" );
474*cdf0e10cSrcweir                 if( ! aValue.Equals( "0" ) && ! aValue.EqualsIgnoreCaseAscii( "false" ) )
475*cdf0e10cSrcweir                     aDefaultPrinter = aPrinterName;
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "Location" );
478*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aLocation = String( aValue, RTL_TEXTENCODING_UTF8 );
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "Comment" );
481*cdf0e10cSrcweir                 aPrinter.m_aInfo.m_aComment = String( aValue, RTL_TEXTENCODING_UTF8 );
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "Copies" );
484*cdf0e10cSrcweir                 if( aValue.Len() )
485*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nCopies = aValue.ToInt32();
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "Orientation" );
488*cdf0e10cSrcweir                 if( aValue.Len() )
489*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_eOrientation = aValue.EqualsIgnoreCaseAscii( "Landscape" ) ? orientation::Landscape : orientation::Portrait;
490*cdf0e10cSrcweir 
491*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "MarginAdjust" );
492*cdf0e10cSrcweir                 if( aValue.Len() )
493*cdf0e10cSrcweir                 {
494*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nLeftMarginAdjust    = aValue.GetToken( 0, ',' ).ToInt32();
495*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nRightMarginAdjust   = aValue.GetToken( 1, ',' ).ToInt32();
496*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nTopMarginAdjust     = aValue.GetToken( 2, ',' ).ToInt32();
497*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nBottomMarginAdjust  = aValue.GetToken( 3, ',' ).ToInt32();
498*cdf0e10cSrcweir                 }
499*cdf0e10cSrcweir 
500*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "ColorDepth" );
501*cdf0e10cSrcweir                 if( aValue.Len() )
502*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nColorDepth = aValue.ToInt32();
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "ColorDevice" );
505*cdf0e10cSrcweir                 if( aValue.Len() )
506*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nColorDevice = aValue.ToInt32();
507*cdf0e10cSrcweir 
508*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "PSLevel" );
509*cdf0e10cSrcweir                 if( aValue.Len() )
510*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nPSLevel = aValue.ToInt32();
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "PDFDevice" );
513*cdf0e10cSrcweir                 if( aValue.Len() )
514*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_nPDFDevice = aValue.ToInt32();
515*cdf0e10cSrcweir 
516*cdf0e10cSrcweir                 aValue = aConfig.ReadKey( "PerformFontSubstitution" );
517*cdf0e10cSrcweir                 if( ! aValue.Equals( "0" ) && ! aValue.EqualsIgnoreCaseAscii( "false" ) )
518*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_bPerformFontSubstitution = true;
519*cdf0e10cSrcweir                 else
520*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_bPerformFontSubstitution = false;
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir                 // now iterate over all keys to extract multi key information:
523*cdf0e10cSrcweir                 // 1. PPDContext information
524*cdf0e10cSrcweir                 // 2. Font substitution table
525*cdf0e10cSrcweir                 for( int nKey = 0; nKey < aConfig.GetKeyCount(); nKey++ )
526*cdf0e10cSrcweir                 {
527*cdf0e10cSrcweir                     ByteString aKey( aConfig.GetKeyName( nKey ) );
528*cdf0e10cSrcweir                     if( aKey.CompareTo( "PPD_", 4 ) == COMPARE_EQUAL && aPrinter.m_aInfo.m_pParser )
529*cdf0e10cSrcweir                     {
530*cdf0e10cSrcweir                         aValue = aConfig.ReadKey( aKey );
531*cdf0e10cSrcweir                         const PPDKey* pKey = aPrinter.m_aInfo.m_pParser->getKey( String( aKey.Copy( 4 ), RTL_TEXTENCODING_ISO_8859_1 ) );
532*cdf0e10cSrcweir                         if( pKey )
533*cdf0e10cSrcweir                         {
534*cdf0e10cSrcweir                             aPrinter.m_aInfo.m_aContext.
535*cdf0e10cSrcweir                             setValue( pKey,
536*cdf0e10cSrcweir                             aValue.Equals( "*nil" ) ? NULL : pKey->getValue( String( aValue, RTL_TEXTENCODING_ISO_8859_1 ) ),
537*cdf0e10cSrcweir                             sal_True );
538*cdf0e10cSrcweir                         }
539*cdf0e10cSrcweir                     }
540*cdf0e10cSrcweir                     else if( aKey.Len() > 10 && aKey.CompareTo("SubstFont_", 10 ) == COMPARE_EQUAL )
541*cdf0e10cSrcweir                     {
542*cdf0e10cSrcweir                         aValue = aConfig.ReadKey( aKey );
543*cdf0e10cSrcweir                         aPrinter.m_aInfo.m_aFontSubstitutes[ OStringToOUString( aKey.Copy( 10 ), RTL_TEXTENCODING_ISO_8859_1 ) ] = OStringToOUString( aValue, RTL_TEXTENCODING_ISO_8859_1 );
544*cdf0e10cSrcweir                     }
545*cdf0e10cSrcweir                 }
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir                 setDefaultPaper( aPrinter.m_aInfo.m_aContext );
548*cdf0e10cSrcweir                 fillFontSubstitutions( aPrinter.m_aInfo );
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir                 // finally insert printer
551*cdf0e10cSrcweir                 FileBase::getFileURLFromSystemPath( aFile.PathToFileName(), aPrinter.m_aFile );
552*cdf0e10cSrcweir                 aPrinter.m_bModified    = false;
553*cdf0e10cSrcweir                 aPrinter.m_aGroup       = aConfig.GetGroupName( nGroup );
554*cdf0e10cSrcweir                 std::hash_map< OUString, Printer, OUStringHash >::const_iterator find_it =
555*cdf0e10cSrcweir                 m_aPrinters.find( aPrinterName );
556*cdf0e10cSrcweir                 if( find_it != m_aPrinters.end() )
557*cdf0e10cSrcweir                 {
558*cdf0e10cSrcweir                     aPrinter.m_aAlternateFiles = find_it->second.m_aAlternateFiles;
559*cdf0e10cSrcweir                     aPrinter.m_aAlternateFiles.push_front( find_it->second.m_aFile );
560*cdf0e10cSrcweir                 }
561*cdf0e10cSrcweir                 m_aPrinters[ aPrinterName ] = aPrinter;
562*cdf0e10cSrcweir             }
563*cdf0e10cSrcweir         }
564*cdf0e10cSrcweir     }
565*cdf0e10cSrcweir 
566*cdf0e10cSrcweir     // set default printer
567*cdf0e10cSrcweir     if( m_aPrinters.size() )
568*cdf0e10cSrcweir     {
569*cdf0e10cSrcweir         if( m_aPrinters.find( aDefaultPrinter ) == m_aPrinters.end() )
570*cdf0e10cSrcweir             aDefaultPrinter = m_aPrinters.begin()->first;
571*cdf0e10cSrcweir     }
572*cdf0e10cSrcweir     else
573*cdf0e10cSrcweir         aDefaultPrinter = OUString();
574*cdf0e10cSrcweir     m_aDefaultPrinter = aDefaultPrinter;
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir     if( m_eType != Default )
577*cdf0e10cSrcweir         return;
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir     // add a default printer for every available print queue
580*cdf0e10cSrcweir     // merge paper and font substitution from default printer,
581*cdf0e10cSrcweir     // all else from global defaults
582*cdf0e10cSrcweir     PrinterInfo aMergeInfo( m_aGlobalDefaults );
583*cdf0e10cSrcweir     aMergeInfo.m_aDriverName    = String( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) );
584*cdf0e10cSrcweir     aMergeInfo.m_aFeatures      = String( RTL_CONSTASCII_USTRINGPARAM( "autoqueue" ) );
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir     if( m_aDefaultPrinter.getLength() )
587*cdf0e10cSrcweir     {
588*cdf0e10cSrcweir         PrinterInfo aDefaultInfo( getPrinterInfo( m_aDefaultPrinter ) );
589*cdf0e10cSrcweir         aMergeInfo.m_bPerformFontSubstitution = aDefaultInfo.m_bPerformFontSubstitution;
590*cdf0e10cSrcweir         fillFontSubstitutions( aMergeInfo );
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir         const PPDKey* pDefKey           = aDefaultInfo.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
593*cdf0e10cSrcweir         const PPDKey* pMergeKey         = aMergeInfo.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
594*cdf0e10cSrcweir         const PPDValue* pDefValue       = aDefaultInfo.m_aContext.getValue( pDefKey );
595*cdf0e10cSrcweir         const PPDValue* pMergeValue     = pMergeKey ? pMergeKey->getValue( pDefValue->m_aOption ) : NULL;
596*cdf0e10cSrcweir         if( pMergeKey && pMergeValue )
597*cdf0e10cSrcweir             aMergeInfo.m_aContext.setValue( pMergeKey, pMergeValue );
598*cdf0e10cSrcweir     }
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir     getSystemPrintQueues();
601*cdf0e10cSrcweir     for( ::std::list< SystemPrintQueue >::iterator it = m_aSystemPrintQueues.begin(); it != m_aSystemPrintQueues.end(); ++it )
602*cdf0e10cSrcweir     {
603*cdf0e10cSrcweir         String aPrinterName( RTL_CONSTASCII_USTRINGPARAM( "<" ) );
604*cdf0e10cSrcweir         aPrinterName += String( it->m_aQueue );
605*cdf0e10cSrcweir         aPrinterName.Append( '>' );
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir         if( m_aPrinters.find( aPrinterName ) != m_aPrinters.end() )
608*cdf0e10cSrcweir             // probably user made this one permanent in padmin
609*cdf0e10cSrcweir         continue;
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir         String aCmd( m_aSystemPrintCommand );
612*cdf0e10cSrcweir         aCmd.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(PRINTER)" ) ), it->m_aQueue );
613*cdf0e10cSrcweir 
614*cdf0e10cSrcweir         Printer aPrinter;
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir         // initialize to merged defaults
617*cdf0e10cSrcweir         aPrinter.m_aInfo = aMergeInfo;
618*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aPrinterName     = aPrinterName;
619*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aCommand         = aCmd;
620*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aComment         = it->m_aComment;
621*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aLocation        = it->m_aLocation;
622*cdf0e10cSrcweir         aPrinter.m_bModified                = false;
623*cdf0e10cSrcweir         aPrinter.m_aGroup                   = ByteString( aPrinterName, aEncoding ); //provide group name in case user makes this one permanent in padmin
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir         m_aPrinters[ aPrinterName ] = aPrinter;
626*cdf0e10cSrcweir     }
627*cdf0e10cSrcweir }
628*cdf0e10cSrcweir 
629*cdf0e10cSrcweir // -----------------------------------------------------------------
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir void PrinterInfoManager::listPrinters( ::std::list< OUString >& rList ) const
632*cdf0e10cSrcweir {
633*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::const_iterator it;
634*cdf0e10cSrcweir     rList.clear();
635*cdf0e10cSrcweir     for( it = m_aPrinters.begin(); it != m_aPrinters.end(); ++it )
636*cdf0e10cSrcweir         rList.push_back( it->first );
637*cdf0e10cSrcweir }
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir // -----------------------------------------------------------------
640*cdf0e10cSrcweir 
641*cdf0e10cSrcweir const PrinterInfo& PrinterInfoManager::getPrinterInfo( const OUString& rPrinter ) const
642*cdf0e10cSrcweir {
643*cdf0e10cSrcweir     static PrinterInfo aEmptyInfo;
644*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::const_iterator it = m_aPrinters.find( rPrinter );
645*cdf0e10cSrcweir 
646*cdf0e10cSrcweir     DBG_ASSERT( it != m_aPrinters.end(), "Do not ask for info about nonexistent printers" );
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir     return it != m_aPrinters.end() ? it->second.m_aInfo : aEmptyInfo;
649*cdf0e10cSrcweir }
650*cdf0e10cSrcweir 
651*cdf0e10cSrcweir // -----------------------------------------------------------------
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir void PrinterInfoManager::changePrinterInfo( const OUString& rPrinter, const PrinterInfo& rNewInfo )
654*cdf0e10cSrcweir {
655*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::iterator it = m_aPrinters.find( rPrinter );
656*cdf0e10cSrcweir 
657*cdf0e10cSrcweir     DBG_ASSERT( it != m_aPrinters.end(), "Do not change nonexistant printers" );
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir     if( it != m_aPrinters.end() )
660*cdf0e10cSrcweir     {
661*cdf0e10cSrcweir         it->second.m_aInfo      = rNewInfo;
662*cdf0e10cSrcweir         // recalculate font substitutions
663*cdf0e10cSrcweir         fillFontSubstitutions( it->second.m_aInfo );
664*cdf0e10cSrcweir         it->second.m_bModified  = true;
665*cdf0e10cSrcweir         writePrinterConfig();
666*cdf0e10cSrcweir     }
667*cdf0e10cSrcweir }
668*cdf0e10cSrcweir 
669*cdf0e10cSrcweir // -----------------------------------------------------------------
670*cdf0e10cSrcweir 
671*cdf0e10cSrcweir // need to check writeability / creatability of config files
672*cdf0e10cSrcweir static bool checkWriteability( const OUString& rUniPath )
673*cdf0e10cSrcweir {
674*cdf0e10cSrcweir     bool bRet = false;
675*cdf0e10cSrcweir     OUString aSysPath;
676*cdf0e10cSrcweir     FileBase::getSystemPathFromFileURL( rUniPath, aSysPath );
677*cdf0e10cSrcweir     SvFileStream aStream( aSysPath, STREAM_READ | STREAM_WRITE );
678*cdf0e10cSrcweir     if( aStream.IsOpen() && aStream.IsWritable() )
679*cdf0e10cSrcweir         bRet = true;
680*cdf0e10cSrcweir     return bRet;
681*cdf0e10cSrcweir }
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir bool PrinterInfoManager::writePrinterConfig()
684*cdf0e10cSrcweir {
685*cdf0e10cSrcweir     // find at least one writeable config
686*cdf0e10cSrcweir     ::std::hash_map< OUString, Config*, OUStringHash > files;
687*cdf0e10cSrcweir     ::std::hash_map< OUString, int, OUStringHash > rofiles;
688*cdf0e10cSrcweir     ::std::hash_map< OUString, Config*, OUStringHash >::iterator file_it;
689*cdf0e10cSrcweir 
690*cdf0e10cSrcweir     for( ::std::list< WatchFile >::const_iterator wit = m_aWatchFiles.begin(); wit != m_aWatchFiles.end(); ++wit )
691*cdf0e10cSrcweir     {
692*cdf0e10cSrcweir         if( checkWriteability( wit->m_aFilePath ) )
693*cdf0e10cSrcweir         {
694*cdf0e10cSrcweir             files[ wit->m_aFilePath ] = new Config( wit->m_aFilePath );
695*cdf0e10cSrcweir             break;
696*cdf0e10cSrcweir         }
697*cdf0e10cSrcweir     }
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir     if( files.empty() )
700*cdf0e10cSrcweir         return false;
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir     Config* pGlobal = files.begin()->second;
703*cdf0e10cSrcweir     pGlobal->SetGroup( GLOBAL_DEFAULTS_GROUP );
704*cdf0e10cSrcweir     pGlobal->WriteKey( "DisableCUPS", m_bDisableCUPS ? "true" : "false" );
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::iterator it;
707*cdf0e10cSrcweir     for( it = m_aPrinters.begin(); it != m_aPrinters.end(); ++it )
708*cdf0e10cSrcweir     {
709*cdf0e10cSrcweir         if( ! it->second.m_bModified )
710*cdf0e10cSrcweir             // printer was not changed, do nothing
711*cdf0e10cSrcweir         continue;
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir         // don't save autoqueue printers
714*cdf0e10cSrcweir         sal_Int32 nIndex = 0;
715*cdf0e10cSrcweir         bool bAutoQueue = false;
716*cdf0e10cSrcweir         while( nIndex != -1 && ! bAutoQueue )
717*cdf0e10cSrcweir         {
718*cdf0e10cSrcweir             OUString aToken( it->second.m_aInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
719*cdf0e10cSrcweir             if( aToken.getLength() && aToken.compareToAscii( "autoqueue" ) == 0 )
720*cdf0e10cSrcweir                 bAutoQueue = true;
721*cdf0e10cSrcweir         }
722*cdf0e10cSrcweir         if( bAutoQueue )
723*cdf0e10cSrcweir             continue;
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir         if( it->second.m_aFile.getLength() )
726*cdf0e10cSrcweir         {
727*cdf0e10cSrcweir             // check if file is writable
728*cdf0e10cSrcweir             if( files.find( it->second.m_aFile ) == files.end() )
729*cdf0e10cSrcweir             {
730*cdf0e10cSrcweir                 bool bInsertToNewFile = false;
731*cdf0e10cSrcweir                 // maybe it is simply not inserted yet
732*cdf0e10cSrcweir                 if( rofiles.find( it->second.m_aFile ) == rofiles.end() )
733*cdf0e10cSrcweir                 {
734*cdf0e10cSrcweir                     if( checkWriteability( it->second.m_aFile ) )
735*cdf0e10cSrcweir                         files[ it->second.m_aFile ] = new Config( it->second.m_aFile );
736*cdf0e10cSrcweir                     else
737*cdf0e10cSrcweir                         bInsertToNewFile = true;
738*cdf0e10cSrcweir                 }
739*cdf0e10cSrcweir                 else
740*cdf0e10cSrcweir                     bInsertToNewFile = true;
741*cdf0e10cSrcweir                 // original file is read only, insert printer in a new writeable file
742*cdf0e10cSrcweir                 if( bInsertToNewFile )
743*cdf0e10cSrcweir                 {
744*cdf0e10cSrcweir                     rofiles[ it->second.m_aFile ] = 1;
745*cdf0e10cSrcweir                     // update alternate file list
746*cdf0e10cSrcweir                     // the remove operation ensures uniqueness of each alternate
747*cdf0e10cSrcweir                     it->second.m_aAlternateFiles.remove( it->second.m_aFile );
748*cdf0e10cSrcweir                     it->second.m_aAlternateFiles.remove( files.begin()->first );
749*cdf0e10cSrcweir                     it->second.m_aAlternateFiles.push_front( it->second.m_aFile );
750*cdf0e10cSrcweir                     // update file
751*cdf0e10cSrcweir                     it->second.m_aFile = files.begin()->first;
752*cdf0e10cSrcweir                 }
753*cdf0e10cSrcweir             }
754*cdf0e10cSrcweir         }
755*cdf0e10cSrcweir         else // a new printer, write it to the first file available
756*cdf0e10cSrcweir             it->second.m_aFile = files.begin()->first;
757*cdf0e10cSrcweir 
758*cdf0e10cSrcweir         if( ! it->second.m_aGroup.getLength() ) // probably a new printer
759*cdf0e10cSrcweir             it->second.m_aGroup = OString( it->first.getStr(), it->first.getLength(), RTL_TEXTENCODING_UTF8 );
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir         if( files.find( it->second.m_aFile ) != files.end() )
762*cdf0e10cSrcweir         {
763*cdf0e10cSrcweir             Config* pConfig = files[ it->second.m_aFile ];
764*cdf0e10cSrcweir             pConfig->DeleteGroup( it->second.m_aGroup ); // else some old keys may remain
765*cdf0e10cSrcweir             pConfig->SetGroup( it->second.m_aGroup );
766*cdf0e10cSrcweir 
767*cdf0e10cSrcweir             ByteString aValue( String( it->second.m_aInfo.m_aDriverName ), RTL_TEXTENCODING_UTF8 );
768*cdf0e10cSrcweir             aValue += '/';
769*cdf0e10cSrcweir             aValue += ByteString( String( it->first ), RTL_TEXTENCODING_UTF8 );
770*cdf0e10cSrcweir             pConfig->WriteKey( "Printer", aValue );
771*cdf0e10cSrcweir             pConfig->WriteKey( "DefaultPrinter", it->first == m_aDefaultPrinter ? "1" : "0" );
772*cdf0e10cSrcweir             pConfig->WriteKey( "Location", ByteString( String( it->second.m_aInfo.m_aLocation ), RTL_TEXTENCODING_UTF8 ) );
773*cdf0e10cSrcweir             pConfig->WriteKey( "Comment", ByteString( String( it->second.m_aInfo.m_aComment ), RTL_TEXTENCODING_UTF8 ) );
774*cdf0e10cSrcweir             pConfig->WriteKey( "Command", ByteString( String( it->second.m_aInfo.m_aCommand ), RTL_TEXTENCODING_UTF8 ) );
775*cdf0e10cSrcweir             pConfig->WriteKey( "QuickCommand", ByteString( String( it->second.m_aInfo.m_aQuickCommand ), RTL_TEXTENCODING_UTF8 ) );
776*cdf0e10cSrcweir             pConfig->WriteKey( "Features", ByteString( String( it->second.m_aInfo.m_aFeatures ), RTL_TEXTENCODING_UTF8 ) );
777*cdf0e10cSrcweir             pConfig->WriteKey( "Copies", ByteString::CreateFromInt32( it->second.m_aInfo.m_nCopies ) );
778*cdf0e10cSrcweir             pConfig->WriteKey( "Orientation", it->second.m_aInfo.m_eOrientation == orientation::Landscape ? "Landscape" : "Portrait" );
779*cdf0e10cSrcweir             pConfig->WriteKey( "PSLevel", ByteString::CreateFromInt32( it->second.m_aInfo.m_nPSLevel ) );
780*cdf0e10cSrcweir             pConfig->WriteKey( "PDFDevice", ByteString::CreateFromInt32( it->second.m_aInfo.m_nPDFDevice ) );
781*cdf0e10cSrcweir             pConfig->WriteKey( "ColorDevice", ByteString::CreateFromInt32( it->second.m_aInfo.m_nColorDevice ) );
782*cdf0e10cSrcweir             pConfig->WriteKey( "ColorDepth", ByteString::CreateFromInt32( it->second.m_aInfo.m_nColorDepth ) );
783*cdf0e10cSrcweir             aValue = ByteString::CreateFromInt32( it->second.m_aInfo.m_nLeftMarginAdjust );
784*cdf0e10cSrcweir             aValue += ',';
785*cdf0e10cSrcweir             aValue += ByteString::CreateFromInt32( it->second.m_aInfo.m_nRightMarginAdjust );
786*cdf0e10cSrcweir             aValue += ',';
787*cdf0e10cSrcweir             aValue += ByteString::CreateFromInt32( it->second.m_aInfo.m_nTopMarginAdjust );
788*cdf0e10cSrcweir             aValue += ',';
789*cdf0e10cSrcweir             aValue += ByteString::CreateFromInt32( it->second.m_aInfo.m_nBottomMarginAdjust );
790*cdf0e10cSrcweir             pConfig->WriteKey( "MarginAdjust", aValue );
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir             if( it->second.m_aInfo.m_aDriverName.compareToAscii( "CUPS:", 5 ) != 0 )
793*cdf0e10cSrcweir             {
794*cdf0e10cSrcweir                 // write PPDContext (not for CUPS)
795*cdf0e10cSrcweir                 for( int i = 0; i < it->second.m_aInfo.m_aContext.countValuesModified(); i++ )
796*cdf0e10cSrcweir                 {
797*cdf0e10cSrcweir                     const PPDKey* pKey = it->second.m_aInfo.m_aContext.getModifiedKey( i );
798*cdf0e10cSrcweir                     ByteString aKey( "PPD_" );
799*cdf0e10cSrcweir                     aKey += ByteString( pKey->getKey(), RTL_TEXTENCODING_ISO_8859_1 );
800*cdf0e10cSrcweir 
801*cdf0e10cSrcweir                     const PPDValue* pValue = it->second.m_aInfo.m_aContext.getValue( pKey );
802*cdf0e10cSrcweir                     aValue = pValue ? ByteString( pValue->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ) : ByteString( "*nil" );
803*cdf0e10cSrcweir                     pConfig->WriteKey( aKey, aValue );
804*cdf0e10cSrcweir                 }
805*cdf0e10cSrcweir             }
806*cdf0e10cSrcweir 
807*cdf0e10cSrcweir             // write font substitution table
808*cdf0e10cSrcweir             pConfig->WriteKey( "PerformFontSubstitution", it->second.m_aInfo.m_bPerformFontSubstitution ? "true" : "false" );
809*cdf0e10cSrcweir             for( ::std::hash_map< OUString, OUString, OUStringHash >::const_iterator subst = it->second.m_aInfo.m_aFontSubstitutes.begin();
810*cdf0e10cSrcweir             subst != it->second.m_aInfo.m_aFontSubstitutes.end(); ++subst )
811*cdf0e10cSrcweir             {
812*cdf0e10cSrcweir                 ByteString aKey( "SubstFont_" );
813*cdf0e10cSrcweir                 aKey.Append( OUStringToOString( subst->first, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
814*cdf0e10cSrcweir                 pConfig->WriteKey( aKey, OUStringToOString( subst->second, RTL_TEXTENCODING_ISO_8859_1 ) );
815*cdf0e10cSrcweir             }
816*cdf0e10cSrcweir         }
817*cdf0e10cSrcweir     }
818*cdf0e10cSrcweir 
819*cdf0e10cSrcweir     // get rid of Config objects. this also writes any changes
820*cdf0e10cSrcweir     for( file_it = files.begin(); file_it != files.end(); ++file_it )
821*cdf0e10cSrcweir         delete file_it->second;
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir     return true;
824*cdf0e10cSrcweir }
825*cdf0e10cSrcweir 
826*cdf0e10cSrcweir // -----------------------------------------------------------------
827*cdf0e10cSrcweir 
828*cdf0e10cSrcweir bool PrinterInfoManager::addPrinter( const OUString& rPrinterName, const OUString& rDriverName )
829*cdf0e10cSrcweir {
830*cdf0e10cSrcweir     bool bSuccess = false;
831*cdf0e10cSrcweir 
832*cdf0e10cSrcweir     const PPDParser* pParser = NULL;
833*cdf0e10cSrcweir     if( m_aPrinters.find( rPrinterName ) == m_aPrinters.end() && ( pParser = PPDParser::getParser( rDriverName ) ) )
834*cdf0e10cSrcweir     {
835*cdf0e10cSrcweir         Printer aPrinter;
836*cdf0e10cSrcweir         aPrinter.m_bModified                        = true;
837*cdf0e10cSrcweir         aPrinter.m_aInfo                            = m_aGlobalDefaults;
838*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aDriverName              = rDriverName;
839*cdf0e10cSrcweir         aPrinter.m_aInfo.m_pParser                  = pParser;
840*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aContext.setParser( pParser );
841*cdf0e10cSrcweir         aPrinter.m_aInfo.m_aPrinterName             = rPrinterName;
842*cdf0e10cSrcweir 
843*cdf0e10cSrcweir         fillFontSubstitutions( aPrinter.m_aInfo );
844*cdf0e10cSrcweir         // merge PPD values with global defaults
845*cdf0e10cSrcweir         for( int nPPDValueModified = 0; nPPDValueModified < m_aGlobalDefaults.m_aContext.countValuesModified(); nPPDValueModified++ )
846*cdf0e10cSrcweir         {
847*cdf0e10cSrcweir             const PPDKey* pDefKey = m_aGlobalDefaults.m_aContext.getModifiedKey( nPPDValueModified );
848*cdf0e10cSrcweir             const PPDValue* pDefValue = m_aGlobalDefaults.m_aContext.getValue( pDefKey );
849*cdf0e10cSrcweir             const PPDKey* pPrinterKey = pDefKey ? aPrinter.m_aInfo.m_pParser->getKey( pDefKey->getKey() ) : NULL;
850*cdf0e10cSrcweir             if( pDefKey && pPrinterKey )
851*cdf0e10cSrcweir                 // at least the options exist in both PPDs
852*cdf0e10cSrcweir             {
853*cdf0e10cSrcweir                 if( pDefValue )
854*cdf0e10cSrcweir                 {
855*cdf0e10cSrcweir                     const PPDValue* pPrinterValue = pPrinterKey->getValue( pDefValue->m_aOption );
856*cdf0e10cSrcweir                     if( pPrinterValue )
857*cdf0e10cSrcweir                         // the printer has a corresponding option for the key
858*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, pPrinterValue );
859*cdf0e10cSrcweir                 }
860*cdf0e10cSrcweir                 else
861*cdf0e10cSrcweir                     aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, NULL );
862*cdf0e10cSrcweir             }
863*cdf0e10cSrcweir         }
864*cdf0e10cSrcweir 
865*cdf0e10cSrcweir         m_aPrinters[ rPrinterName ] = aPrinter;
866*cdf0e10cSrcweir         bSuccess = true;
867*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
868*cdf0e10cSrcweir         fprintf( stderr, "new printer %s, level = %d, pdfdevice = %d, colordevice = %d, depth = %d\n",
869*cdf0e10cSrcweir         OUStringToOString( rPrinterName, osl_getThreadTextEncoding() ).getStr(),
870*cdf0e10cSrcweir         m_aPrinters[rPrinterName].m_aInfo.m_nPSLevel,
871*cdf0e10cSrcweir         m_aPrinters[rPrinterName].m_aInfo.m_nPDFDevice,
872*cdf0e10cSrcweir         m_aPrinters[rPrinterName].m_aInfo.m_nColorDevice,
873*cdf0e10cSrcweir         m_aPrinters[rPrinterName].m_aInfo.m_nColorDepth );
874*cdf0e10cSrcweir         #endif
875*cdf0e10cSrcweir         // comment: logically one should writePrinterConfig() here
876*cdf0e10cSrcweir         // but immediately after addPrinter() a changePrinterInfo()
877*cdf0e10cSrcweir         // will follow (see padmin code), which writes it again,
878*cdf0e10cSrcweir         // so we can currently save some performance here
879*cdf0e10cSrcweir     }
880*cdf0e10cSrcweir     return bSuccess;
881*cdf0e10cSrcweir }
882*cdf0e10cSrcweir 
883*cdf0e10cSrcweir // -----------------------------------------------------------------
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir bool PrinterInfoManager::removePrinter( const OUString& rPrinterName, bool bCheckOnly )
886*cdf0e10cSrcweir {
887*cdf0e10cSrcweir     bool bSuccess = true;
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::iterator it = m_aPrinters.find( rPrinterName );
890*cdf0e10cSrcweir     if( it != m_aPrinters.end() )
891*cdf0e10cSrcweir     {
892*cdf0e10cSrcweir         if( it->second.m_aFile.getLength() )
893*cdf0e10cSrcweir         {
894*cdf0e10cSrcweir             // this printer already exists in a config file
895*cdf0e10cSrcweir 
896*cdf0e10cSrcweir 
897*cdf0e10cSrcweir             // check writeability of config file(s)
898*cdf0e10cSrcweir             if( ! checkWriteability( it->second.m_aFile ) )
899*cdf0e10cSrcweir                 bSuccess = false;
900*cdf0e10cSrcweir             else
901*cdf0e10cSrcweir             {
902*cdf0e10cSrcweir                 for( std::list< OUString >::const_iterator file_it = it->second.m_aAlternateFiles.begin();
903*cdf0e10cSrcweir                 file_it != it->second.m_aAlternateFiles.end() && bSuccess; ++file_it )
904*cdf0e10cSrcweir                 {
905*cdf0e10cSrcweir                     if( ! checkWriteability( *file_it ) )
906*cdf0e10cSrcweir                         bSuccess = false;
907*cdf0e10cSrcweir                 }
908*cdf0e10cSrcweir             }
909*cdf0e10cSrcweir             if( bSuccess && ! bCheckOnly )
910*cdf0e10cSrcweir             {
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir                 Config aConfig( it->second.m_aFile );
913*cdf0e10cSrcweir                 aConfig.DeleteGroup( it->second.m_aGroup );
914*cdf0e10cSrcweir                 aConfig.Flush();
915*cdf0e10cSrcweir                 for( std::list< OUString >::const_iterator file_it = it->second.m_aAlternateFiles.begin();
916*cdf0e10cSrcweir                 file_it != it->second.m_aAlternateFiles.end() && bSuccess; ++file_it )
917*cdf0e10cSrcweir                 {
918*cdf0e10cSrcweir                     Config aAltConfig( *file_it );
919*cdf0e10cSrcweir                     aAltConfig.DeleteGroup( it->second.m_aGroup );
920*cdf0e10cSrcweir                     aAltConfig.Flush();
921*cdf0e10cSrcweir                 }
922*cdf0e10cSrcweir             }
923*cdf0e10cSrcweir         }
924*cdf0e10cSrcweir         if( bSuccess && ! bCheckOnly )
925*cdf0e10cSrcweir         {
926*cdf0e10cSrcweir             m_aPrinters.erase( it );
927*cdf0e10cSrcweir             // need this here because someone may call
928*cdf0e10cSrcweir             // checkPrintersChanged after the removal
929*cdf0e10cSrcweir             // but then other added printers were not flushed
930*cdf0e10cSrcweir             // to disk, so they are discarded
931*cdf0e10cSrcweir             writePrinterConfig();
932*cdf0e10cSrcweir         }
933*cdf0e10cSrcweir     }
934*cdf0e10cSrcweir     return bSuccess;
935*cdf0e10cSrcweir }
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir // -----------------------------------------------------------------
938*cdf0e10cSrcweir 
939*cdf0e10cSrcweir bool PrinterInfoManager::setDefaultPrinter( const OUString& rPrinterName )
940*cdf0e10cSrcweir {
941*cdf0e10cSrcweir     bool bSuccess = false;
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir     ::std::hash_map< OUString, Printer, OUStringHash >::iterator it = m_aPrinters.find( rPrinterName );
944*cdf0e10cSrcweir     if( it != m_aPrinters.end() )
945*cdf0e10cSrcweir     {
946*cdf0e10cSrcweir         bSuccess = true;
947*cdf0e10cSrcweir         it->second.m_bModified = true;
948*cdf0e10cSrcweir         if( ( it = m_aPrinters.find( m_aDefaultPrinter ) ) != m_aPrinters.end() )
949*cdf0e10cSrcweir             it->second.m_bModified = true;
950*cdf0e10cSrcweir         m_aDefaultPrinter = rPrinterName;
951*cdf0e10cSrcweir         writePrinterConfig();
952*cdf0e10cSrcweir     }
953*cdf0e10cSrcweir     return bSuccess;
954*cdf0e10cSrcweir }
955*cdf0e10cSrcweir 
956*cdf0e10cSrcweir // -----------------------------------------------------------------
957*cdf0e10cSrcweir bool PrinterInfoManager::addOrRemovePossible() const
958*cdf0e10cSrcweir {
959*cdf0e10cSrcweir     return true;
960*cdf0e10cSrcweir }
961*cdf0e10cSrcweir 
962*cdf0e10cSrcweir // -----------------------------------------------------------------
963*cdf0e10cSrcweir 
964*cdf0e10cSrcweir void PrinterInfoManager::fillFontSubstitutions( PrinterInfo& rInfo ) const
965*cdf0e10cSrcweir {
966*cdf0e10cSrcweir     PrintFontManager& rFontManager( PrintFontManager::get() );
967*cdf0e10cSrcweir     rInfo.m_aFontSubstitutions.clear();
968*cdf0e10cSrcweir 
969*cdf0e10cSrcweir     if( ! rInfo.m_bPerformFontSubstitution ||
970*cdf0e10cSrcweir         ! rInfo.m_aFontSubstitutes.size() )
971*cdf0e10cSrcweir     return;
972*cdf0e10cSrcweir 
973*cdf0e10cSrcweir     ::std::list< FastPrintFontInfo > aFonts;
974*cdf0e10cSrcweir     ::std::hash_map< OUString, ::std::list< FastPrintFontInfo >, OUStringHash > aPrinterFonts;
975*cdf0e10cSrcweir     rFontManager.getFontListWithFastInfo( aFonts, rInfo.m_pParser );
976*cdf0e10cSrcweir 
977*cdf0e10cSrcweir     // get builtin fonts
978*cdf0e10cSrcweir     ::std::list< FastPrintFontInfo >::const_iterator it;
979*cdf0e10cSrcweir     for( it = aFonts.begin(); it != aFonts.end(); ++it )
980*cdf0e10cSrcweir         if( it->m_eType == fonttype::Builtin )
981*cdf0e10cSrcweir             aPrinterFonts[ it->m_aFamilyName.toAsciiLowerCase() ].push_back( *it );
982*cdf0e10cSrcweir 
983*cdf0e10cSrcweir     // map lower case, so build a local copy of the font substitutions
984*cdf0e10cSrcweir     ::std::hash_map< OUString, OUString, OUStringHash > aSubstitutions;
985*cdf0e10cSrcweir     ::std::hash_map< OUString, OUString, OUStringHash >::const_iterator subst;
986*cdf0e10cSrcweir     for( subst = rInfo.m_aFontSubstitutes.begin(); subst != rInfo.m_aFontSubstitutes.end(); ++subst )
987*cdf0e10cSrcweir     {
988*cdf0e10cSrcweir         OUString aFamily( subst->first.toAsciiLowerCase() );
989*cdf0e10cSrcweir         // first look if there is a builtin of this family
990*cdf0e10cSrcweir         // in this case override the substitution table
991*cdf0e10cSrcweir         if( aPrinterFonts.find( aFamily ) != aPrinterFonts.end() )
992*cdf0e10cSrcweir             aSubstitutions[ aFamily ] = aFamily;
993*cdf0e10cSrcweir         else
994*cdf0e10cSrcweir             aSubstitutions[ aFamily ] = subst->second.toAsciiLowerCase();
995*cdf0e10cSrcweir     }
996*cdf0e10cSrcweir 
997*cdf0e10cSrcweir 
998*cdf0e10cSrcweir     // now find substitutions
999*cdf0e10cSrcweir     for( it = aFonts.begin(); it != aFonts.end(); ++it )
1000*cdf0e10cSrcweir     {
1001*cdf0e10cSrcweir         if( it->m_eType != fonttype::Builtin )
1002*cdf0e10cSrcweir         {
1003*cdf0e10cSrcweir             OUString aFamily( it->m_aFamilyName.toAsciiLowerCase() );
1004*cdf0e10cSrcweir             subst = aSubstitutions.find( aFamily );
1005*cdf0e10cSrcweir             if( subst != aSubstitutions.end() )
1006*cdf0e10cSrcweir             {
1007*cdf0e10cSrcweir                 // search a substitution
1008*cdf0e10cSrcweir                 const ::std::list< FastPrintFontInfo >& rBuiltins( aPrinterFonts[ aSubstitutions[ aFamily ] ] );
1009*cdf0e10cSrcweir                 ::std::list< FastPrintFontInfo >::const_iterator builtin;
1010*cdf0e10cSrcweir                 int nLastMatch = -10000;
1011*cdf0e10cSrcweir                 fontID nSubstitute = -1;
1012*cdf0e10cSrcweir                 for( builtin = rBuiltins.begin(); builtin != rBuiltins.end(); ++builtin )
1013*cdf0e10cSrcweir                 {
1014*cdf0e10cSrcweir                     int nMatch = 0;
1015*cdf0e10cSrcweir                     int nDiff;
1016*cdf0e10cSrcweir                     if( builtin->m_eItalic == it->m_eItalic )
1017*cdf0e10cSrcweir                         nMatch += 8000;
1018*cdf0e10cSrcweir 
1019*cdf0e10cSrcweir                     nDiff = builtin->m_eWeight - it->m_eWeight;
1020*cdf0e10cSrcweir                     nDiff = nDiff < 0 ? -nDiff : nDiff;
1021*cdf0e10cSrcweir                     nMatch += 4000 - 1000*nDiff;
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir                     nDiff = builtin->m_eWidth - it->m_eWidth;
1024*cdf0e10cSrcweir                     nDiff = nDiff < 0 ? -nDiff : nDiff;
1025*cdf0e10cSrcweir                     nMatch += 2000 - 500*nDiff;
1026*cdf0e10cSrcweir 
1027*cdf0e10cSrcweir                     if( nMatch > nLastMatch )
1028*cdf0e10cSrcweir                     {
1029*cdf0e10cSrcweir                         nLastMatch = nMatch;
1030*cdf0e10cSrcweir                         nSubstitute = builtin->m_nID;
1031*cdf0e10cSrcweir                     }
1032*cdf0e10cSrcweir                 }
1033*cdf0e10cSrcweir                 if( nSubstitute != -1 )
1034*cdf0e10cSrcweir                 {
1035*cdf0e10cSrcweir                     rInfo.m_aFontSubstitutions[ it->m_nID ] = nSubstitute;
1036*cdf0e10cSrcweir                     #if OSL_DEBUG_LEVEL > 2
1037*cdf0e10cSrcweir                     FastPrintFontInfo aInfo;
1038*cdf0e10cSrcweir                     rFontManager.getFontFastInfo( nSubstitute, aInfo );
1039*cdf0e10cSrcweir                     fprintf( stderr,
1040*cdf0e10cSrcweir                     "substitute %s %s %d %d\n"
1041*cdf0e10cSrcweir                     " ->        %s %s %d %d\n",
1042*cdf0e10cSrcweir                     OUStringToOString( it->m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1043*cdf0e10cSrcweir                     it->m_eItalic == italic::Upright ? "r" : it->m_eItalic == italic::Oblique ? "o" : it->m_eItalic == italic::Italic ? "i" : "u",
1044*cdf0e10cSrcweir                     it->m_eWeight,
1045*cdf0e10cSrcweir                     it->m_eWidth,
1046*cdf0e10cSrcweir 
1047*cdf0e10cSrcweir                     OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1048*cdf0e10cSrcweir                     aInfo.m_eItalic == italic::Upright ? "r" : aInfo.m_eItalic == italic::Oblique ? "o" : aInfo.m_eItalic == italic::Italic ? "i" : "u",
1049*cdf0e10cSrcweir                     aInfo.m_eWeight,
1050*cdf0e10cSrcweir                     aInfo.m_eWidth
1051*cdf0e10cSrcweir                     );
1052*cdf0e10cSrcweir                     #endif
1053*cdf0e10cSrcweir                 }
1054*cdf0e10cSrcweir             }
1055*cdf0e10cSrcweir         }
1056*cdf0e10cSrcweir     }
1057*cdf0e10cSrcweir }
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir // -----------------------------------------------------------------
1060*cdf0e10cSrcweir 
1061*cdf0e10cSrcweir void PrinterInfoManager::getSystemPrintCommands( std::list< OUString >& rCommands )
1062*cdf0e10cSrcweir {
1063*cdf0e10cSrcweir     if( m_pQueueInfo && m_pQueueInfo->hasChanged() )
1064*cdf0e10cSrcweir     {
1065*cdf0e10cSrcweir         m_aSystemPrintCommand = m_pQueueInfo->getCommand();
1066*cdf0e10cSrcweir         m_pQueueInfo->getSystemQueues( m_aSystemPrintQueues );
1067*cdf0e10cSrcweir         delete m_pQueueInfo, m_pQueueInfo = NULL;
1068*cdf0e10cSrcweir     }
1069*cdf0e10cSrcweir 
1070*cdf0e10cSrcweir     std::list< SystemPrintQueue >::const_iterator it;
1071*cdf0e10cSrcweir     rCommands.clear();
1072*cdf0e10cSrcweir     String aPrinterConst( RTL_CONSTASCII_USTRINGPARAM( "(PRINTER)" ) );
1073*cdf0e10cSrcweir     for( it = m_aSystemPrintQueues.begin(); it != m_aSystemPrintQueues.end(); ++it )
1074*cdf0e10cSrcweir     {
1075*cdf0e10cSrcweir         String aCmd( m_aSystemPrintCommand );
1076*cdf0e10cSrcweir         aCmd.SearchAndReplace( aPrinterConst, it->m_aQueue );
1077*cdf0e10cSrcweir         rCommands.push_back( aCmd );
1078*cdf0e10cSrcweir     }
1079*cdf0e10cSrcweir }
1080*cdf0e10cSrcweir 
1081*cdf0e10cSrcweir const std::list< PrinterInfoManager::SystemPrintQueue >& PrinterInfoManager::getSystemPrintQueues()
1082*cdf0e10cSrcweir {
1083*cdf0e10cSrcweir     if( m_pQueueInfo && m_pQueueInfo->hasChanged() )
1084*cdf0e10cSrcweir     {
1085*cdf0e10cSrcweir         m_aSystemPrintCommand = m_pQueueInfo->getCommand();
1086*cdf0e10cSrcweir         m_pQueueInfo->getSystemQueues( m_aSystemPrintQueues );
1087*cdf0e10cSrcweir         delete m_pQueueInfo, m_pQueueInfo = NULL;
1088*cdf0e10cSrcweir     }
1089*cdf0e10cSrcweir 
1090*cdf0e10cSrcweir     return m_aSystemPrintQueues;
1091*cdf0e10cSrcweir }
1092*cdf0e10cSrcweir 
1093*cdf0e10cSrcweir bool PrinterInfoManager::checkFeatureToken( const rtl::OUString& rPrinterName, const char* pToken ) const
1094*cdf0e10cSrcweir {
1095*cdf0e10cSrcweir     const PrinterInfo& rPrinterInfo( getPrinterInfo( rPrinterName ) );
1096*cdf0e10cSrcweir     sal_Int32 nIndex = 0;
1097*cdf0e10cSrcweir     while( nIndex != -1 )
1098*cdf0e10cSrcweir     {
1099*cdf0e10cSrcweir         OUString aOuterToken = rPrinterInfo.m_aFeatures.getToken( 0, ',', nIndex );
1100*cdf0e10cSrcweir         sal_Int32 nInnerIndex = 0;
1101*cdf0e10cSrcweir         OUString aInnerToken = aOuterToken.getToken( 0, '=', nInnerIndex );
1102*cdf0e10cSrcweir         if( aInnerToken.equalsIgnoreAsciiCaseAscii( pToken ) )
1103*cdf0e10cSrcweir             return true;
1104*cdf0e10cSrcweir     }
1105*cdf0e10cSrcweir     return false;
1106*cdf0e10cSrcweir }
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir FILE* PrinterInfoManager::startSpool( const OUString& rPrintername, bool bQuickCommand )
1109*cdf0e10cSrcweir {
1110*cdf0e10cSrcweir     const PrinterInfo&   rPrinterInfo   = getPrinterInfo (rPrintername);
1111*cdf0e10cSrcweir     const rtl::OUString& rCommand       = (bQuickCommand && rPrinterInfo.m_aQuickCommand.getLength() ) ?
1112*cdf0e10cSrcweir                                           rPrinterInfo.m_aQuickCommand : rPrinterInfo.m_aCommand;
1113*cdf0e10cSrcweir     rtl::OString aShellCommand  = OUStringToOString (rCommand, RTL_TEXTENCODING_ISO_8859_1);
1114*cdf0e10cSrcweir     aShellCommand += rtl::OString( " 2>/dev/null" );
1115*cdf0e10cSrcweir 
1116*cdf0e10cSrcweir     return popen (aShellCommand.getStr(), "w");
1117*cdf0e10cSrcweir }
1118*cdf0e10cSrcweir 
1119*cdf0e10cSrcweir int PrinterInfoManager::endSpool( const OUString& /*rPrintername*/, const OUString& /*rJobTitle*/, FILE* pFile, const JobData& /*rDocumentJobData*/, bool /*bBanner*/ )
1120*cdf0e10cSrcweir {
1121*cdf0e10cSrcweir     return (0 == pclose( pFile ));
1122*cdf0e10cSrcweir }
1123*cdf0e10cSrcweir 
1124*cdf0e10cSrcweir void PrinterInfoManager::setupJobContextData( JobData& rData )
1125*cdf0e10cSrcweir {
1126*cdf0e10cSrcweir     std::hash_map< OUString, Printer, OUStringHash >::iterator it =
1127*cdf0e10cSrcweir     m_aPrinters.find( rData.m_aPrinterName );
1128*cdf0e10cSrcweir     if( it != m_aPrinters.end() )
1129*cdf0e10cSrcweir     {
1130*cdf0e10cSrcweir         rData.m_pParser     = it->second.m_aInfo.m_pParser;
1131*cdf0e10cSrcweir         rData.m_aContext    = it->second.m_aInfo.m_aContext;
1132*cdf0e10cSrcweir     }
1133*cdf0e10cSrcweir }
1134*cdf0e10cSrcweir 
1135*cdf0e10cSrcweir void PrinterInfoManager::setDefaultPaper( PPDContext& rContext ) const
1136*cdf0e10cSrcweir {
1137*cdf0e10cSrcweir     if(  ! rContext.getParser() )
1138*cdf0e10cSrcweir         return;
1139*cdf0e10cSrcweir 
1140*cdf0e10cSrcweir     const PPDKey* pPageSizeKey = rContext.getParser()->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
1141*cdf0e10cSrcweir     if( ! pPageSizeKey )
1142*cdf0e10cSrcweir         return;
1143*cdf0e10cSrcweir 
1144*cdf0e10cSrcweir     int nModified = rContext.countValuesModified();
1145*cdf0e10cSrcweir     while( nModified-- &&
1146*cdf0e10cSrcweir         rContext.getModifiedKey( nModified ) != pPageSizeKey )
1147*cdf0e10cSrcweir     ;
1148*cdf0e10cSrcweir 
1149*cdf0e10cSrcweir     if( nModified >= 0 ) // paper was set already, do not modify
1150*cdf0e10cSrcweir     {
1151*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1152*cdf0e10cSrcweir         fprintf( stderr, "not setting default paper, already set %s\n",
1153*cdf0e10cSrcweir         OUStringToOString( rContext.getValue( pPageSizeKey )->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1154*cdf0e10cSrcweir         #endif
1155*cdf0e10cSrcweir         return;
1156*cdf0e10cSrcweir     }
1157*cdf0e10cSrcweir 
1158*cdf0e10cSrcweir     // paper not set, fill in default value
1159*cdf0e10cSrcweir     const PPDValue* pPaperVal = NULL;
1160*cdf0e10cSrcweir     int nValues = pPageSizeKey->countValues();
1161*cdf0e10cSrcweir     for( int i = 0; i < nValues && ! pPaperVal; i++ )
1162*cdf0e10cSrcweir     {
1163*cdf0e10cSrcweir         const PPDValue* pVal = pPageSizeKey->getValue( i );
1164*cdf0e10cSrcweir         if( pVal->m_aOption.EqualsIgnoreCaseAscii( m_aSystemDefaultPaper.getStr() ) )
1165*cdf0e10cSrcweir             pPaperVal = pVal;
1166*cdf0e10cSrcweir     }
1167*cdf0e10cSrcweir     if( pPaperVal )
1168*cdf0e10cSrcweir     {
1169*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1170*cdf0e10cSrcweir         fprintf( stderr, "setting default paper %s\n", OUStringToOString( pPaperVal->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1171*cdf0e10cSrcweir         #endif
1172*cdf0e10cSrcweir         rContext.setValue( pPageSizeKey, pPaperVal );
1173*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1174*cdf0e10cSrcweir         pPaperVal = rContext.getValue( pPageSizeKey );
1175*cdf0e10cSrcweir         fprintf( stderr, "-> got paper %s\n", OUStringToOString( pPaperVal->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1176*cdf0e10cSrcweir         #endif
1177*cdf0e10cSrcweir     }
1178*cdf0e10cSrcweir }
1179*cdf0e10cSrcweir 
1180*cdf0e10cSrcweir // -----------------------------------------------------------------
1181*cdf0e10cSrcweir 
1182*cdf0e10cSrcweir SystemQueueInfo::SystemQueueInfo() :
1183*cdf0e10cSrcweir     m_bChanged( false )
1184*cdf0e10cSrcweir {
1185*cdf0e10cSrcweir     create();
1186*cdf0e10cSrcweir }
1187*cdf0e10cSrcweir 
1188*cdf0e10cSrcweir SystemQueueInfo::~SystemQueueInfo()
1189*cdf0e10cSrcweir {
1190*cdf0e10cSrcweir     static const char* pNoSyncDetection = getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
1191*cdf0e10cSrcweir     if( ! pNoSyncDetection || !*pNoSyncDetection )
1192*cdf0e10cSrcweir         join();
1193*cdf0e10cSrcweir     else
1194*cdf0e10cSrcweir         terminate();
1195*cdf0e10cSrcweir }
1196*cdf0e10cSrcweir 
1197*cdf0e10cSrcweir bool SystemQueueInfo::hasChanged() const
1198*cdf0e10cSrcweir {
1199*cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
1200*cdf0e10cSrcweir     bool bChanged = m_bChanged;
1201*cdf0e10cSrcweir     return bChanged;
1202*cdf0e10cSrcweir }
1203*cdf0e10cSrcweir 
1204*cdf0e10cSrcweir void SystemQueueInfo::getSystemQueues( std::list< PrinterInfoManager::SystemPrintQueue >& rQueues )
1205*cdf0e10cSrcweir {
1206*cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
1207*cdf0e10cSrcweir     rQueues = m_aQueues;
1208*cdf0e10cSrcweir     m_bChanged = false;
1209*cdf0e10cSrcweir }
1210*cdf0e10cSrcweir 
1211*cdf0e10cSrcweir OUString SystemQueueInfo::getCommand() const
1212*cdf0e10cSrcweir {
1213*cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
1214*cdf0e10cSrcweir     OUString aRet = m_aCommand;
1215*cdf0e10cSrcweir     return aRet;
1216*cdf0e10cSrcweir }
1217*cdf0e10cSrcweir 
1218*cdf0e10cSrcweir struct SystemCommandParameters;
1219*cdf0e10cSrcweir typedef void(* tokenHandler)(const std::list< rtl::OString >&,
1220*cdf0e10cSrcweir                 std::list< PrinterInfoManager::SystemPrintQueue >&,
1221*cdf0e10cSrcweir                 const SystemCommandParameters*);
1222*cdf0e10cSrcweir 
1223*cdf0e10cSrcweir struct SystemCommandParameters
1224*cdf0e10cSrcweir {
1225*cdf0e10cSrcweir     const char*     pQueueCommand;
1226*cdf0e10cSrcweir     const char*     pPrintCommand;
1227*cdf0e10cSrcweir     const char*     pForeToken;
1228*cdf0e10cSrcweir     const char*     pAftToken;
1229*cdf0e10cSrcweir     unsigned int    nForeTokenCount;
1230*cdf0e10cSrcweir     tokenHandler    pHandler;
1231*cdf0e10cSrcweir };
1232*cdf0e10cSrcweir 
1233*cdf0e10cSrcweir #if ! (defined(LINUX) || defined(NETBSD) || defined(FREEBSD))
1234*cdf0e10cSrcweir static void lpgetSysQueueTokenHandler(
1235*cdf0e10cSrcweir     const std::list< rtl::OString >& i_rLines,
1236*cdf0e10cSrcweir     std::list< PrinterInfoManager::SystemPrintQueue >& o_rQueues,
1237*cdf0e10cSrcweir     const SystemCommandParameters* )
1238*cdf0e10cSrcweir {
1239*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1240*cdf0e10cSrcweir     std::hash_set< OUString, OUStringHash > aUniqueSet;
1241*cdf0e10cSrcweir     std::hash_set< OUString, OUStringHash > aOnlySet;
1242*cdf0e10cSrcweir     aUniqueSet.insert( OUString( RTL_CONSTASCII_USTRINGPARAM( "_all" ) ) );
1243*cdf0e10cSrcweir     aUniqueSet.insert( OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
1244*cdf0e10cSrcweir 
1245*cdf0e10cSrcweir     // the eventual "all" attribute of the "_all" queue tells us, which
1246*cdf0e10cSrcweir     // printers are to be used for this user at all
1247*cdf0e10cSrcweir 
1248*cdf0e10cSrcweir     // find _all: line
1249*cdf0e10cSrcweir     rtl::OString aAllLine( "_all:" );
1250*cdf0e10cSrcweir     rtl::OString aAllAttr( "all=" );
1251*cdf0e10cSrcweir     for( std::list< rtl::OString >::const_iterator it = i_rLines.begin();
1252*cdf0e10cSrcweir          it != i_rLines.end(); ++it )
1253*cdf0e10cSrcweir     {
1254*cdf0e10cSrcweir         if( it->indexOf( aAllLine, 0 ) == 0 )
1255*cdf0e10cSrcweir         {
1256*cdf0e10cSrcweir             // now find the "all" attribute
1257*cdf0e10cSrcweir             ++it;
1258*cdf0e10cSrcweir             while( it != i_rLines.end() )
1259*cdf0e10cSrcweir             {
1260*cdf0e10cSrcweir                 rtl::OString aClean( WhitespaceToSpace( *it ) );
1261*cdf0e10cSrcweir                 if( aClean.indexOf( aAllAttr, 0 ) == 0 )
1262*cdf0e10cSrcweir                 {
1263*cdf0e10cSrcweir                     // insert the comma separated entries into the set of printers to use
1264*cdf0e10cSrcweir                     sal_Int32 nPos = aAllAttr.getLength();
1265*cdf0e10cSrcweir                     while( nPos != -1 )
1266*cdf0e10cSrcweir                     {
1267*cdf0e10cSrcweir                         OString aTok( aClean.getToken( 0, ',', nPos ) );
1268*cdf0e10cSrcweir                         if( aTok.getLength() > 0 )
1269*cdf0e10cSrcweir                             aOnlySet.insert( rtl::OStringToOUString( aTok, aEncoding ) );
1270*cdf0e10cSrcweir                     }
1271*cdf0e10cSrcweir                     break;
1272*cdf0e10cSrcweir                 }
1273*cdf0e10cSrcweir             }
1274*cdf0e10cSrcweir             break;
1275*cdf0e10cSrcweir         }
1276*cdf0e10cSrcweir     }
1277*cdf0e10cSrcweir 
1278*cdf0e10cSrcweir     bool bInsertAttribute = false;
1279*cdf0e10cSrcweir     rtl::OString aDescrStr( "description=" );
1280*cdf0e10cSrcweir     rtl::OString aLocStr( "location=" );
1281*cdf0e10cSrcweir     for( std::list< rtl::OString >::const_iterator it = i_rLines.begin();
1282*cdf0e10cSrcweir          it != i_rLines.end(); ++it )
1283*cdf0e10cSrcweir     {
1284*cdf0e10cSrcweir         sal_Int32 nPos = 0;
1285*cdf0e10cSrcweir         // find the begin of a new printer section
1286*cdf0e10cSrcweir         nPos = it->indexOf( ':', 0 );
1287*cdf0e10cSrcweir         if( nPos != -1 )
1288*cdf0e10cSrcweir         {
1289*cdf0e10cSrcweir             OUString aSysQueue( rtl::OStringToOUString( it->copy( 0, nPos ), aEncoding ) );
1290*cdf0e10cSrcweir             // do not insert duplicates (e.g. lpstat tends to produce such lines)
1291*cdf0e10cSrcweir             // in case there was a "_all" section, insert only those printer explicitly
1292*cdf0e10cSrcweir             // set in the "all" attribute
1293*cdf0e10cSrcweir             if( aUniqueSet.find( aSysQueue ) == aUniqueSet.end() &&
1294*cdf0e10cSrcweir                 ( aOnlySet.empty() || aOnlySet.find( aSysQueue ) != aOnlySet.end() )
1295*cdf0e10cSrcweir                 )
1296*cdf0e10cSrcweir             {
1297*cdf0e10cSrcweir                 o_rQueues.push_back( PrinterInfoManager::SystemPrintQueue() );
1298*cdf0e10cSrcweir                 o_rQueues.back().m_aQueue = aSysQueue;
1299*cdf0e10cSrcweir                 o_rQueues.back().m_aLocation = aSysQueue;
1300*cdf0e10cSrcweir                 aUniqueSet.insert( aSysQueue );
1301*cdf0e10cSrcweir                 bInsertAttribute = true;
1302*cdf0e10cSrcweir             }
1303*cdf0e10cSrcweir             else
1304*cdf0e10cSrcweir                 bInsertAttribute = false;
1305*cdf0e10cSrcweir             continue;
1306*cdf0e10cSrcweir         }
1307*cdf0e10cSrcweir         if( bInsertAttribute && ! o_rQueues.empty() )
1308*cdf0e10cSrcweir         {
1309*cdf0e10cSrcweir             // look for "description" attribute, insert as comment
1310*cdf0e10cSrcweir             nPos = it->indexOf( aDescrStr, 0 );
1311*cdf0e10cSrcweir             if( nPos != -1 )
1312*cdf0e10cSrcweir             {
1313*cdf0e10cSrcweir                 ByteString aComment( WhitespaceToSpace( it->copy(nPos+12) ) );
1314*cdf0e10cSrcweir                 if( aComment.Len() > 0 )
1315*cdf0e10cSrcweir                     o_rQueues.back().m_aComment = String( aComment, aEncoding );
1316*cdf0e10cSrcweir                 continue;
1317*cdf0e10cSrcweir             }
1318*cdf0e10cSrcweir             // look for "location" attribute, inser as location
1319*cdf0e10cSrcweir             nPos = it->indexOf( aLocStr, 0 );
1320*cdf0e10cSrcweir             if( nPos != -1 )
1321*cdf0e10cSrcweir             {
1322*cdf0e10cSrcweir                 ByteString aLoc( WhitespaceToSpace( it->copy(nPos+9) ) );
1323*cdf0e10cSrcweir                 if( aLoc.Len() > 0 )
1324*cdf0e10cSrcweir                     o_rQueues.back().m_aLocation = String( aLoc, aEncoding );
1325*cdf0e10cSrcweir                 continue;
1326*cdf0e10cSrcweir             }
1327*cdf0e10cSrcweir         }
1328*cdf0e10cSrcweir     }
1329*cdf0e10cSrcweir }
1330*cdf0e10cSrcweir #endif
1331*cdf0e10cSrcweir static void standardSysQueueTokenHandler(
1332*cdf0e10cSrcweir     const std::list< rtl::OString >& i_rLines,
1333*cdf0e10cSrcweir     std::list< PrinterInfoManager::SystemPrintQueue >& o_rQueues,
1334*cdf0e10cSrcweir     const SystemCommandParameters* i_pParms)
1335*cdf0e10cSrcweir {
1336*cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1337*cdf0e10cSrcweir     std::hash_set< OUString, OUStringHash > aUniqueSet;
1338*cdf0e10cSrcweir     rtl::OString aForeToken( i_pParms->pForeToken );
1339*cdf0e10cSrcweir     rtl::OString aAftToken( i_pParms->pAftToken );
1340*cdf0e10cSrcweir     /* Normal Unix print queue discovery, also used for Darwin 5 LPR printing
1341*cdf0e10cSrcweir     */
1342*cdf0e10cSrcweir     for( std::list< rtl::OString >::const_iterator it = i_rLines.begin();
1343*cdf0e10cSrcweir          it != i_rLines.end(); ++it )
1344*cdf0e10cSrcweir     {
1345*cdf0e10cSrcweir         sal_Int32 nPos = 0;
1346*cdf0e10cSrcweir 
1347*cdf0e10cSrcweir         // search for a line describing a printer:
1348*cdf0e10cSrcweir         // find if there are enough tokens before the name
1349*cdf0e10cSrcweir         for( unsigned int i = 0; i < i_pParms->nForeTokenCount && nPos != -1; i++ )
1350*cdf0e10cSrcweir         {
1351*cdf0e10cSrcweir             nPos = it->indexOf( aForeToken, nPos );
1352*cdf0e10cSrcweir             if( nPos != -1 && it->getLength() >= nPos+aForeToken.getLength() )
1353*cdf0e10cSrcweir                 nPos += aForeToken.getLength();
1354*cdf0e10cSrcweir         }
1355*cdf0e10cSrcweir         if( nPos != -1 )
1356*cdf0e10cSrcweir         {
1357*cdf0e10cSrcweir             // find if there is the token after the queue
1358*cdf0e10cSrcweir             sal_Int32 nAftPos = it->indexOf( aAftToken, nPos );
1359*cdf0e10cSrcweir             if( nAftPos != -1 )
1360*cdf0e10cSrcweir             {
1361*cdf0e10cSrcweir                 // get the queue name between fore and aft tokens
1362*cdf0e10cSrcweir                 OUString aSysQueue( rtl::OStringToOUString( it->copy( nPos, nAftPos - nPos ), aEncoding ) );
1363*cdf0e10cSrcweir                 // do not insert duplicates (e.g. lpstat tends to produce such lines)
1364*cdf0e10cSrcweir                 if( aUniqueSet.find( aSysQueue ) == aUniqueSet.end() )
1365*cdf0e10cSrcweir                 {
1366*cdf0e10cSrcweir                     o_rQueues.push_back( PrinterInfoManager::SystemPrintQueue() );
1367*cdf0e10cSrcweir                     o_rQueues.back().m_aQueue = aSysQueue;
1368*cdf0e10cSrcweir                     o_rQueues.back().m_aLocation = aSysQueue;
1369*cdf0e10cSrcweir                     aUniqueSet.insert( aSysQueue );
1370*cdf0e10cSrcweir                 }
1371*cdf0e10cSrcweir             }
1372*cdf0e10cSrcweir         }
1373*cdf0e10cSrcweir     }
1374*cdf0e10cSrcweir }
1375*cdf0e10cSrcweir 
1376*cdf0e10cSrcweir static const struct SystemCommandParameters aParms[] =
1377*cdf0e10cSrcweir {
1378*cdf0e10cSrcweir     #if defined(LINUX) || defined(NETBSD) || defined(FREEBSD)
1379*cdf0e10cSrcweir     { "/usr/sbin/lpc status", "lpr -P \"(PRINTER)\"", "", ":", 0, standardSysQueueTokenHandler },
1380*cdf0e10cSrcweir     { "lpc status", "lpr -P \"(PRINTER)\"", "", ":", 0, standardSysQueueTokenHandler },
1381*cdf0e10cSrcweir     { "LANG=C;LC_ALL=C;export LANG LC_ALL;lpstat -s", "lp -d \"(PRINTER)\"", "system for ", ": ", 1, standardSysQueueTokenHandler }
1382*cdf0e10cSrcweir     #else
1383*cdf0e10cSrcweir     { "LANG=C;LC_ALL=C;export LANG LC_ALL;lpget list", "lp -d \"(PRINTER)\"", "", ":", 0, lpgetSysQueueTokenHandler },
1384*cdf0e10cSrcweir     { "LANG=C;LC_ALL=C;export LANG LC_ALL;lpstat -s", "lp -d \"(PRINTER)\"", "system for ", ": ", 1, standardSysQueueTokenHandler },
1385*cdf0e10cSrcweir     { "/usr/sbin/lpc status", "lpr -P \"(PRINTER)\"", "", ":", 0, standardSysQueueTokenHandler },
1386*cdf0e10cSrcweir     { "lpc status", "lpr -P \"(PRINTER)\"", "", ":", 0, standardSysQueueTokenHandler }
1387*cdf0e10cSrcweir     #endif
1388*cdf0e10cSrcweir };
1389*cdf0e10cSrcweir 
1390*cdf0e10cSrcweir void SystemQueueInfo::run()
1391*cdf0e10cSrcweir {
1392*cdf0e10cSrcweir     char pBuffer[1024];
1393*cdf0e10cSrcweir     FILE *pPipe;
1394*cdf0e10cSrcweir     std::list< rtl::OString > aLines;
1395*cdf0e10cSrcweir 
1396*cdf0e10cSrcweir     /* Discover which command we can use to get a list of all printer queues */
1397*cdf0e10cSrcweir     for( unsigned int i = 0; i < sizeof(aParms)/sizeof(aParms[0]); i++ )
1398*cdf0e10cSrcweir     {
1399*cdf0e10cSrcweir         aLines.clear();
1400*cdf0e10cSrcweir         rtl::OStringBuffer aCmdLine( 128 );
1401*cdf0e10cSrcweir         aCmdLine.append( aParms[i].pQueueCommand );
1402*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1403*cdf0e10cSrcweir         fprintf( stderr, "trying print queue command \"%s\" ... ", aParms[i].pQueueCommand );
1404*cdf0e10cSrcweir         #endif
1405*cdf0e10cSrcweir         aCmdLine.append( " 2>/dev/null" );
1406*cdf0e10cSrcweir         if( (pPipe = popen( aCmdLine.getStr(), "r" )) )
1407*cdf0e10cSrcweir         {
1408*cdf0e10cSrcweir             while( fgets( pBuffer, 1024, pPipe ) )
1409*cdf0e10cSrcweir                 aLines.push_back( rtl::OString( pBuffer ) );
1410*cdf0e10cSrcweir             if( ! pclose( pPipe ) )
1411*cdf0e10cSrcweir             {
1412*cdf0e10cSrcweir                 std::list< PrinterInfoManager::SystemPrintQueue > aSysPrintQueues;
1413*cdf0e10cSrcweir                 aParms[i].pHandler( aLines, aSysPrintQueues, &(aParms[i]) );
1414*cdf0e10cSrcweir                 MutexGuard aGuard( m_aMutex );
1415*cdf0e10cSrcweir                 m_bChanged  = true;
1416*cdf0e10cSrcweir                 m_aQueues   = aSysPrintQueues;
1417*cdf0e10cSrcweir                 m_aCommand  = rtl::OUString::createFromAscii( aParms[i].pPrintCommand );
1418*cdf0e10cSrcweir                 #if OSL_DEBUG_LEVEL > 1
1419*cdf0e10cSrcweir                 fprintf( stderr, "success\n" );
1420*cdf0e10cSrcweir                 #endif
1421*cdf0e10cSrcweir                 break;
1422*cdf0e10cSrcweir             }
1423*cdf0e10cSrcweir         }
1424*cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1425*cdf0e10cSrcweir         fprintf( stderr, "failed\n" );
1426*cdf0e10cSrcweir         #endif
1427*cdf0e10cSrcweir     }
1428*cdf0e10cSrcweir }
1429*cdf0e10cSrcweir 
1430