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