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 <stdlib.h>
31 : : #include <stdio.h>
32 : :
33 : : #include <boost/unordered_map.hpp>
34 : :
35 : : #include <comphelper/string.hxx>
36 : : #include "vcl/ppdparser.hxx"
37 : : #include "vcl/strhelper.hxx"
38 : : #include "vcl/helper.hxx"
39 : : #include "vcl/svapp.hxx"
40 : : #include "cupsmgr.hxx"
41 : : #include "tools/urlobj.hxx"
42 : : #include "tools/stream.hxx"
43 : : #include "tools/zcodec.hxx"
44 : : #include "osl/mutex.hxx"
45 : : #include "osl/file.hxx"
46 : : #include "osl/process.h"
47 : : #include "osl/thread.h"
48 : : #include "rtl/strbuf.hxx"
49 : : #include "rtl/ustrbuf.hxx"
50 : : #include "rtl/instance.hxx"
51 : : #include <sal/macros.h>
52 : : #include <salhelper/linkhelper.hxx>
53 : :
54 : : #include "com/sun/star/lang/Locale.hpp"
55 : :
56 : : namespace psp
57 : : {
58 : : class PPDTranslator
59 : : {
60 : : struct LocaleEqual
61 : : {
62 : 0 : bool operator()(const com::sun::star::lang::Locale& i_rLeft,
63 : : const com::sun::star::lang::Locale& i_rRight) const
64 : : {
65 : 0 : return i_rLeft.Language.equals( i_rRight.Language ) &&
66 : 0 : i_rLeft.Country.equals( i_rRight.Country ) &&
67 [ # # ]: 0 : i_rLeft.Variant.equals( i_rRight.Variant );
[ # # # # ]
68 : : }
69 : : };
70 : :
71 : : struct LocaleHash
72 : : {
73 : 8040 : size_t operator()(const com::sun::star::lang::Locale& rLocale) const
74 : : { return
75 : 8040 : (size_t)rLocale.Language.hashCode()
76 : 8040 : ^ (size_t)rLocale.Country.hashCode()
77 : 8040 : ^ (size_t)rLocale.Variant.hashCode()
78 : : ;
79 : : }
80 : : };
81 : :
82 : : typedef boost::unordered_map< com::sun::star::lang::Locale, rtl::OUString, LocaleHash, LocaleEqual > translation_map;
83 : : typedef boost::unordered_map< rtl::OUString, translation_map, rtl::OUStringHash > key_translation_map;
84 : :
85 : : key_translation_map m_aTranslations;
86 : : public:
87 [ + - ]: 60 : PPDTranslator() {}
88 : 60 : ~PPDTranslator() {}
89 : :
90 : :
91 : : void insertValue(
92 : : const rtl::OUString& i_rKey,
93 : : const rtl::OUString& i_rOption,
94 : : const rtl::OUString& i_rValue,
95 : : const rtl::OUString& i_rTranslation,
96 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale()
97 : : );
98 : :
99 : 7860 : void insertOption( const rtl::OUString& i_rKey,
100 : : const rtl::OUString& i_rOption,
101 : : const rtl::OUString& i_rTranslation,
102 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() )
103 : : {
104 [ + - ]: 7860 : insertValue( i_rKey, i_rOption, rtl::OUString(), i_rTranslation, i_rLocale );
105 : 7860 : }
106 : :
107 : 240 : void insertKey( const rtl::OUString& i_rKey,
108 : : const rtl::OUString& i_rTranslation,
109 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() )
110 : : {
111 [ + - ]: 240 : insertValue( i_rKey, rtl::OUString(), rtl::OUString(), i_rTranslation, i_rLocale );
112 : 240 : }
113 : :
114 : : rtl::OUString translateValue(
115 : : const rtl::OUString& i_rKey,
116 : : const rtl::OUString& i_rOption,
117 : : const rtl::OUString& i_rValue,
118 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale()
119 : : ) const;
120 : :
121 : 0 : rtl::OUString translateOption( const rtl::OUString& i_rKey,
122 : : const rtl::OUString& i_rOption,
123 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() ) const
124 : : {
125 [ # # ]: 0 : return translateValue( i_rKey, i_rOption, rtl::OUString(), i_rLocale );
126 : : }
127 : :
128 : 0 : rtl::OUString translateKey( const rtl::OUString& i_rKey,
129 : : const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() ) const
130 : : {
131 [ # # ]: 0 : return translateValue( i_rKey, rtl::OUString(), rtl::OUString(), i_rLocale );
132 : : }
133 : : };
134 : :
135 : 0 : static com::sun::star::lang::Locale normalizeInputLocale(
136 : : const com::sun::star::lang::Locale& i_rLocale,
137 : : bool bInsertDefault = false
138 : : )
139 : : {
140 : 0 : com::sun::star::lang::Locale aLoc( i_rLocale );
141 [ # # ][ # # ]: 0 : if( bInsertDefault && aLoc.Language.isEmpty() )
[ # # ]
142 : : {
143 : : // empty locale requested, fill in application UI locale
144 [ # # ][ # # ]: 0 : aLoc = Application::GetSettings().GetUILocale();
145 : :
146 : : #if OSL_DEBUG_LEVEL > 1
147 : : static const char* pEnvLocale = getenv( "SAL_PPDPARSER_LOCALE" );
148 : : if( pEnvLocale && *pEnvLocale )
149 : : {
150 : : rtl::OString aStr( pEnvLocale );
151 : : sal_Int32 nLen = aStr.getLength();
152 : : aLoc.Language = rtl::OStringToOUString( aStr.copy( 0, nLen > 2 ? 2 : nLen ), RTL_TEXTENCODING_MS_1252 );
153 : : if( nLen >=5 && aStr.getStr()[2] == '_' )
154 : : aLoc.Country = rtl::OStringToOUString( aStr.copy( 3, 2 ), RTL_TEXTENCODING_MS_1252 );
155 : : else
156 : : aLoc.Country = rtl::OUString();
157 : : aLoc.Variant = rtl::OUString();
158 : : }
159 : : #endif
160 : : }
161 : 0 : aLoc.Language = aLoc.Language.toAsciiLowerCase();
162 : 0 : aLoc.Country = aLoc.Country.toAsciiUpperCase();
163 : 0 : aLoc.Variant = aLoc.Variant.toAsciiUpperCase();
164 : :
165 : 0 : return aLoc;
166 : : }
167 : :
168 : 8160 : void PPDTranslator::insertValue(
169 : : const rtl::OUString& i_rKey,
170 : : const rtl::OUString& i_rOption,
171 : : const rtl::OUString& i_rValue,
172 : : const rtl::OUString& i_rTranslation,
173 : : const com::sun::star::lang::Locale& i_rLocale
174 : : )
175 : : {
176 : 8160 : rtl::OUStringBuffer aKey( i_rKey.getLength() + i_rOption.getLength() + i_rValue.getLength() + 2 );
177 [ + - ]: 8160 : aKey.append( i_rKey );
178 [ + + ][ + + ]: 8160 : if( !i_rOption.isEmpty() || !i_rValue.isEmpty() )
[ + + ]
179 : : {
180 [ + - ]: 7920 : aKey.append( sal_Unicode( ':' ) );
181 [ + - ]: 7920 : aKey.append( i_rOption );
182 : : }
183 [ + + ]: 8160 : if( !i_rValue.isEmpty() )
184 : : {
185 [ + - ]: 60 : aKey.append( sal_Unicode( ':' ) );
186 [ + - ]: 60 : aKey.append( i_rValue );
187 : : }
188 [ + - ][ + + ]: 8160 : if( aKey.getLength() && !i_rTranslation.isEmpty() )
[ + + ]
189 : : {
190 [ + - ]: 8040 : rtl::OUString aK( aKey.makeStringAndClear() );
191 : 8040 : com::sun::star::lang::Locale aLoc;
192 : 8040 : aLoc.Language = i_rLocale.Language.toAsciiLowerCase();
193 : 8040 : aLoc.Country = i_rLocale.Country.toAsciiUpperCase();
194 : 8040 : aLoc.Variant = i_rLocale.Variant.toAsciiUpperCase();
195 [ + - ][ + - ]: 8040 : m_aTranslations[ aK ][ aLoc ] = i_rTranslation;
196 : 8160 : }
197 : 8160 : }
198 : :
199 : 0 : rtl::OUString PPDTranslator::translateValue(
200 : : const rtl::OUString& i_rKey,
201 : : const rtl::OUString& i_rOption,
202 : : const rtl::OUString& i_rValue,
203 : : const com::sun::star::lang::Locale& i_rLocale
204 : : ) const
205 : : {
206 : 0 : rtl::OUString aResult;
207 : :
208 : 0 : rtl::OUStringBuffer aKey( i_rKey.getLength() + i_rOption.getLength() + i_rValue.getLength() + 2 );
209 [ # # ]: 0 : aKey.append( i_rKey );
210 [ # # ][ # # ]: 0 : if( !i_rOption.isEmpty() || !i_rValue.isEmpty() )
[ # # ]
211 : : {
212 [ # # ]: 0 : aKey.append( sal_Unicode( ':' ) );
213 [ # # ]: 0 : aKey.append( i_rOption );
214 : : }
215 [ # # ]: 0 : if( !i_rValue.isEmpty() )
216 : : {
217 [ # # ]: 0 : aKey.append( sal_Unicode( ':' ) );
218 [ # # ]: 0 : aKey.append( i_rValue );
219 : : }
220 [ # # ]: 0 : if( aKey.getLength() )
221 : : {
222 [ # # ]: 0 : rtl::OUString aK( aKey.makeStringAndClear() );
223 [ # # ]: 0 : key_translation_map::const_iterator it = m_aTranslations.find( aK );
224 [ # # ][ # # ]: 0 : if( it != m_aTranslations.end() )
225 : : {
226 [ # # ]: 0 : const translation_map& rMap( it->second );
227 : :
228 [ # # ]: 0 : com::sun::star::lang::Locale aLoc( normalizeInputLocale( i_rLocale, true ) );
229 [ # # ]: 0 : for( int nTry = 0; nTry < 4; nTry++ )
230 : : {
231 [ # # ]: 0 : translation_map::const_iterator tr = rMap.find( aLoc );
232 [ # # ][ # # ]: 0 : if( tr != rMap.end() )
233 : : {
234 [ # # ]: 0 : aResult = tr->second;
235 : : break;
236 : : }
237 [ # # # # ]: 0 : switch( nTry )
238 : : {
239 : 0 : case 0: aLoc.Variant = rtl::OUString();break;
240 : 0 : case 1: aLoc.Country = rtl::OUString();break;
241 : 0 : case 2: aLoc.Language = rtl::OUString();break;
242 : : }
243 : 0 : }
244 : 0 : }
245 : : }
246 : 0 : return aResult;
247 : : }
248 : :
249 : : class PPDCache
250 : : {
251 : : public:
252 : : std::list< PPDParser* > aAllParsers;
253 : : boost::unordered_map< rtl::OUString, rtl::OUString, rtl::OUStringHash >* pAllPPDFiles;
254 : 80 : PPDCache()
255 : 80 : : pAllPPDFiles(NULL)
256 : 80 : {}
257 : 80 : ~PPDCache()
258 : 80 : {
259 [ + - ][ + + ]: 140 : while( aAllParsers.begin() != aAllParsers.end() )
260 : : {
261 [ + - ][ + - ]: 60 : delete aAllParsers.front();
[ + - ]
262 [ + - ]: 60 : aAllParsers.pop_front();
263 : : }
264 [ + - ][ + - ]: 80 : delete pAllPPDFiles;
265 : 80 : pAllPPDFiles = NULL;
266 : 80 : }
267 : : };
268 : : }
269 : :
270 : : using namespace psp;
271 : :
272 : : using ::rtl::OUString;
273 : : using ::rtl::OStringBuffer;
274 : : using ::rtl::OUStringHash;
275 : :
276 : : #define BSTRING(x) rtl::OUStringToOString( x, osl_getThreadTextEncoding() )
277 : :
278 : : namespace
279 : : {
280 : : struct thePPDCache : public rtl::Static<PPDCache, thePPDCache> {};
281 : : }
282 : :
283 : : class PPDDecompressStream
284 : : {
285 : : SvFileStream* mpFileStream;
286 : : SvMemoryStream* mpMemStream;
287 : : rtl::OUString maFileName;
288 : :
289 : : // forbid copying
290 : : PPDDecompressStream( const PPDDecompressStream& );
291 : : PPDDecompressStream& operator=(const PPDDecompressStream& );
292 : :
293 : : public:
294 : : PPDDecompressStream( const rtl::OUString& rFile );
295 : : ~PPDDecompressStream();
296 : :
297 : : bool IsOpen() const;
298 : : bool IsEof() const;
299 : : rtl::OString ReadLine();
300 : : void Open( const rtl::OUString& i_rFile );
301 : : void Close();
302 : 259 : const rtl::OUString& GetFileName() const { return maFileName; }
303 : : };
304 : :
305 : 359 : PPDDecompressStream::PPDDecompressStream( const rtl::OUString& i_rFile ) :
306 : : mpFileStream( NULL ),
307 : 359 : mpMemStream( NULL )
308 : : {
309 [ + - ]: 359 : Open( i_rFile );
310 : 359 : }
311 : :
312 : 359 : PPDDecompressStream::~PPDDecompressStream()
313 : : {
314 [ + - ]: 359 : Close();
315 : 359 : }
316 : :
317 : 618 : void PPDDecompressStream::Open( const rtl::OUString& i_rFile )
318 : : {
319 [ + - ]: 618 : Close();
320 : :
321 [ + - ][ + - ]: 618 : mpFileStream = new SvFileStream( i_rFile, STREAM_READ );
[ + - ][ + - ]
322 [ + - ]: 618 : maFileName = mpFileStream->GetFileName();
323 : :
324 [ + + ]: 618 : if( ! mpFileStream->IsOpen() )
325 : : {
326 [ + - ]: 299 : Close();
327 : 618 : return;
328 : : }
329 : :
330 : 319 : rtl::OString aLine;
331 [ + - ]: 319 : mpFileStream->ReadLine( aLine );
332 [ + - ]: 319 : mpFileStream->Seek( 0 );
333 : :
334 : : // check for compress'ed or gzip'ed file
335 : 319 : sal_uLong nCompressMethod = 0;
336 [ + - ][ - + ]: 319 : if( aLine.getLength() > 1 && static_cast<unsigned char>(aLine[0]) == 0x1f )
[ - + ]
337 : : {
338 [ # # ]: 0 : if( static_cast<unsigned char>(aLine[1]) == 0x8b ) // check for gzip
339 : 0 : nCompressMethod = ZCODEC_DEFAULT | ZCODEC_GZ_LIB;
340 : : }
341 : :
342 [ - + ]: 319 : if( nCompressMethod != 0 )
343 : : {
344 : : // so let's try to decompress the stream
345 [ # # ][ # # ]: 0 : mpMemStream = new SvMemoryStream( 4096, 4096 );
346 [ # # ]: 0 : ZCodec aCodec;
347 [ # # ]: 0 : aCodec.BeginCompression( nCompressMethod );
348 [ # # ]: 0 : long nComp = aCodec.Decompress( *mpFileStream, *mpMemStream );
349 [ # # ]: 0 : aCodec.EndCompression();
350 [ # # ]: 0 : if( nComp < 0 )
351 : : {
352 : : // decompression failed, must be an uncompressed stream after all
353 [ # # ][ # # ]: 0 : delete mpMemStream, mpMemStream = NULL;
354 [ # # ]: 0 : mpFileStream->Seek( 0 );
355 : : }
356 : : else
357 : : {
358 : : // compression successfull, can get rid of file stream
359 [ # # ][ # # ]: 0 : delete mpFileStream, mpFileStream = NULL;
360 [ # # ]: 0 : mpMemStream->Seek( 0 );
361 [ # # ]: 0 : }
362 : 618 : }
363 : : }
364 : :
365 : 1336 : void PPDDecompressStream::Close()
366 : : {
367 [ - + ]: 1336 : delete mpMemStream, mpMemStream = NULL;
368 [ + + ]: 1336 : delete mpFileStream, mpFileStream = NULL;
369 : 1336 : }
370 : :
371 : 658 : bool PPDDecompressStream::IsOpen() const
372 : : {
373 [ + - ][ + + ]: 658 : return (mpMemStream || (mpFileStream && mpFileStream->IsOpen()));
[ + - ]
374 : : }
375 : :
376 : 34980 : bool PPDDecompressStream::IsEof() const
377 : : {
378 [ - + ][ + - ]: 34980 : return ( mpMemStream ? mpMemStream->IsEof() : ( mpFileStream ? mpFileStream->IsEof() : true ) );
[ + + ]
379 : : }
380 : :
381 : 35179 : rtl::OString PPDDecompressStream::ReadLine()
382 : : {
383 : 35179 : rtl::OString o_rLine;
384 [ - + ]: 35179 : if( mpMemStream )
385 [ # # ]: 0 : mpMemStream->ReadLine( o_rLine );
386 [ + - ]: 35179 : else if( mpFileStream )
387 [ + - ]: 35179 : mpFileStream->ReadLine( o_rLine );
388 : 35179 : return o_rLine;
389 : : }
390 : :
391 : 240 : static osl::FileBase::RC resolveLink( const rtl::OUString& i_rURL, rtl::OUString& o_rResolvedURL, rtl::OUString& o_rBaseName, osl::FileStatus::Type& o_rType, int nLinkLevel = 10 )
392 : : {
393 : : salhelper::LinkResolver aResolver(osl_FileStatus_Mask_FileName |
394 : : osl_FileStatus_Mask_Type |
395 : 240 : osl_FileStatus_Mask_FileURL);
396 : :
397 [ + - ]: 240 : osl::FileBase::RC aRet = aResolver.fetchFileStatus(i_rURL, nLinkLevel);
398 : :
399 [ + - ]: 240 : if (aRet == osl::FileBase::E_None)
400 : : {
401 [ + - ]: 240 : o_rResolvedURL = aResolver.m_aStatus.getFileURL();
402 [ + - ]: 240 : o_rBaseName = aResolver.m_aStatus.getFileName();
403 [ + - ]: 240 : o_rType = aResolver.m_aStatus.getFileType();
404 : : }
405 : :
406 : 240 : return aRet;
407 : : }
408 : :
409 : 240 : void PPDParser::scanPPDDir( const String& rDir )
410 : : {
411 : : static struct suffix_t
412 : : {
413 : : const sal_Char* pSuffix;
414 : : const sal_Int32 nSuffixLen;
415 : : } const pSuffixes[] =
416 : : { { ".PS", 3 }, { ".PPD", 4 }, { ".PS.GZ", 6 }, { ".PPD.GZ", 7 } };
417 : :
418 : 240 : const int nSuffixes = SAL_N_ELEMENTS(pSuffixes);
419 : :
420 [ + - ]: 240 : PPDCache &rPPDCache = thePPDCache::get();
421 : :
422 [ + - ]: 240 : osl::Directory aDir( rDir );
423 [ + - ][ + - ]: 240 : if ( aDir.open() == osl::FileBase::E_None )
424 : : {
425 : 240 : osl::DirectoryItem aItem;
426 : :
427 [ + - ][ + - ]: 240 : INetURLObject aPPDDir(rDir);
428 [ + - ][ + + ]: 480 : while( aDir.getNextItem( aItem ) == osl::FileBase::E_None )
429 : : {
430 : 240 : osl::FileStatus aStatus( osl_FileStatus_Mask_FileName );
431 [ + - ][ + - ]: 240 : if( aItem.getFileStatus( aStatus ) == osl::FileBase::E_None )
432 : : {
433 : 240 : rtl::OUStringBuffer aURLBuf( rDir.Len() + 64 );
434 [ + - ][ + - ]: 240 : aURLBuf.append( rDir );
435 [ + - ]: 240 : aURLBuf.append( sal_Unicode( '/' ) );
436 [ + - ][ + - ]: 240 : aURLBuf.append( aStatus.getFileName() );
437 : :
438 : 240 : rtl::OUString aFileURL, aFileName;
439 : 240 : osl::FileStatus::Type eType = osl::FileStatus::Unknown;
440 : :
441 [ + - ][ + - ]: 240 : if( resolveLink( aURLBuf.makeStringAndClear(), aFileURL, aFileName, eType ) == osl::FileBase::E_None )
[ + - ]
442 : : {
443 [ + - ]: 240 : if( eType == osl::FileStatus::Regular )
444 : : {
445 [ + - ]: 240 : INetURLObject aPPDFile = aPPDDir;
446 [ + - ]: 240 : aPPDFile.Append( aFileName );
447 : :
448 : : // match extension
449 [ + + ]: 720 : for( int nSuffix = 0; nSuffix < nSuffixes; nSuffix++ )
450 : : {
451 [ + - ]: 600 : if( aFileName.getLength() > pSuffixes[nSuffix].nSuffixLen )
452 : : {
453 [ + + ]: 600 : if( aFileName.endsWithIgnoreAsciiCaseAsciiL( pSuffixes[nSuffix].pSuffix, pSuffixes[nSuffix].nSuffixLen ) )
454 : : {
455 [ + - ][ + - ]: 120 : (*rPPDCache.pAllPPDFiles)[ aFileName.copy( 0, aFileName.getLength() - pSuffixes[nSuffix].nSuffixLen ) ] = aPPDFile.PathToFileName();
456 : 120 : break;
457 : : }
458 : : }
459 [ + - ]: 240 : }
460 : : }
461 [ # # ]: 0 : else if( eType == osl::FileStatus::Directory )
462 : : {
463 [ # # ][ # # ]: 0 : scanPPDDir( aFileURL );
[ # # ]
464 : : }
465 : 240 : }
466 : : }
467 : 240 : }
468 [ + - ][ + - ]: 240 : aDir.close();
[ + - ]
469 [ + - ]: 240 : }
470 : 240 : }
471 : :
472 : 339 : void PPDParser::initPPDFiles()
473 : : {
474 [ + - ]: 339 : PPDCache &rPPDCache = thePPDCache::get();
475 [ + + ]: 339 : if( rPPDCache.pAllPPDFiles )
476 : 339 : return;
477 : :
478 [ + - ][ + - ]: 120 : rPPDCache.pAllPPDFiles = new boost::unordered_map< OUString, OUString, OUStringHash >();
479 : :
480 : : // check installation directories
481 [ + - ]: 120 : std::list< OUString > aPathList;
482 [ + - ]: 120 : psp::getPrinterPathList( aPathList, PRINTER_PPDDIR );
483 [ + + ]: 300 : for( std::list< OUString >::const_iterator ppd_it = aPathList.begin(); ppd_it != aPathList.end(); ++ppd_it )
484 : : {
485 [ + - ]: 180 : INetURLObject aPPDDir( *ppd_it, INET_PROT_FILE, INetURLObject::ENCODE_ALL );
486 [ + - ][ + - ]: 180 : scanPPDDir( aPPDDir.GetMainURL( INetURLObject::NO_DECODE ) );
[ + - ][ + - ]
487 [ + - ]: 180 : }
488 [ + - ][ + - ]: 120 : if( rPPDCache.pAllPPDFiles->find( OUString( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) ) == rPPDCache.pAllPPDFiles->end() )
[ + - ][ + + ]
489 : : {
490 : : // last try: search in directory of executable (mainly for setup)
491 : 60 : OUString aExe;
492 [ + - ][ + - ]: 60 : if( osl_getExecutableFile( &aExe.pData ) == osl_Process_E_None )
493 : : {
494 [ + - ]: 60 : INetURLObject aDir( aExe );
495 [ + - ]: 60 : aDir.removeSegment();
496 : : #ifdef DEBUG
497 : : fprintf( stderr, "scanning last chance dir: %s\n", rtl::OUStringToOString( aDir.GetMainURL( INetURLObject::NO_DECODE ), osl_getThreadTextEncoding() ).getStr() );
498 : : #endif
499 [ + - ][ + - ]: 60 : scanPPDDir( aDir.GetMainURL( INetURLObject::NO_DECODE ) );
[ + - ][ + - ]
[ + - ]
500 : : #ifdef DEBUG
501 : : fprintf( stderr, "SGENPRT %s\n", rPPDCache.pAllPPDFiles->find( OUString( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) ) == rPPDCache.pAllPPDFiles->end() ? "not found" : "found" );
502 : : #endif
503 : 60 : }
504 : 339 : }
505 : : }
506 : :
507 : 0 : void PPDParser::getKnownPPDDrivers( std::list< rtl::OUString >& o_rDrivers, bool bRefresh )
508 : : {
509 [ # # ]: 0 : PPDCache &rPPDCache = thePPDCache::get();
510 : :
511 [ # # ]: 0 : if( bRefresh )
512 : : {
513 [ # # ][ # # ]: 0 : delete rPPDCache.pAllPPDFiles;
514 : 0 : rPPDCache.pAllPPDFiles = NULL;
515 : : }
516 : :
517 [ # # ]: 0 : initPPDFiles();
518 : 0 : o_rDrivers.clear();
519 : :
520 : 0 : boost::unordered_map< OUString, OUString, OUStringHash >::const_iterator it;
521 [ # # ][ # # ]: 0 : for( it = rPPDCache.pAllPPDFiles->begin(); it != rPPDCache.pAllPPDFiles->end(); ++it )
[ # # ]
522 [ # # ][ # # ]: 0 : o_rDrivers.push_back( it->first );
523 : 0 : }
524 : :
525 : 299 : String PPDParser::getPPDFile( const String& rFile )
526 : : {
527 [ + - ][ + - ]: 299 : INetURLObject aPPD( rFile, INET_PROT_FILE, INetURLObject::ENCODE_ALL );
528 : : // someone might enter a full qualified name here
529 [ + - ][ + - ]: 299 : PPDDecompressStream aStream( aPPD.PathToFileName() );
530 [ + - ]: 299 : if( ! aStream.IsOpen() )
531 : : {
532 : 299 : boost::unordered_map< OUString, OUString, OUStringHash >::const_iterator it;
533 [ + - ]: 299 : PPDCache &rPPDCache = thePPDCache::get();
534 : :
535 : 299 : bool bRetry = true;
536 [ + + ]: 339 : do
537 : : {
538 [ + - ]: 339 : initPPDFiles();
539 : : // some PPD files contain dots beside the extension, so try name first
540 : : // and cut of points after that
541 [ + - ]: 339 : rtl::OUString aBase( rFile );
542 : 339 : sal_Int32 nLastIndex = aBase.lastIndexOf( sal_Unicode( '/' ) );
543 [ - + ]: 339 : if( nLastIndex >= 0 )
544 : 0 : aBase = aBase.copy( nLastIndex+1 );
545 [ - + ][ - + ]: 678 : do
[ + + ]
546 : : {
547 [ + - ]: 339 : it = rPPDCache.pAllPPDFiles->find( aBase );
548 : 339 : nLastIndex = aBase.lastIndexOf( sal_Unicode( '.' ) );
549 [ - + ]: 339 : if( nLastIndex > 0 )
550 : 0 : aBase = aBase.copy( 0, nLastIndex );
551 [ + - ][ + - ]: 678 : } while( it == rPPDCache.pAllPPDFiles->end() && nLastIndex > 0 );
[ + - ]
[ # # # # ]
552 : :
553 [ + - ][ + + ]: 339 : if( it == rPPDCache.pAllPPDFiles->end() && bRetry )
[ + + ][ + - ]
[ + - ][ + +
# # # # ]
554 : : {
555 : : // a new file ? rehash
556 [ + - ][ + - ]: 40 : delete rPPDCache.pAllPPDFiles; rPPDCache.pAllPPDFiles = NULL;
557 : 40 : bRetry = false;
558 : : // note this is optimized for office start where
559 : : // no new files occur and initPPDFiles is called only once
560 : 339 : }
561 : 339 : } while( ! rPPDCache.pAllPPDFiles );
562 : :
563 [ + - ][ + + ]: 299 : if( it != rPPDCache.pAllPPDFiles->end() )
564 [ + - ][ + - ]: 299 : aStream.Open( it->second );
565 : : }
566 : :
567 [ + - ]: 299 : String aRet;
568 [ + + ]: 299 : if( aStream.IsOpen() )
569 : : {
570 [ + - ]: 259 : rtl::OString aLine = aStream.ReadLine();
571 [ + - ]: 259 : if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("*PPD-Adobe")) == 0)
572 [ + - ]: 259 : aRet = aStream.GetFileName();
573 : : else
574 : : {
575 : : // our *Include hack does usually not begin
576 : : // with *PPD-Adobe, so try some lines for *Include
577 : 0 : int nLines = 10;
578 [ # # ][ # # ]: 0 : while (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("*Include")) != 0 && --nLines)
[ # # ]
579 [ # # ]: 0 : aLine = aStream.ReadLine();
580 [ # # ]: 0 : if( nLines )
581 [ # # ]: 0 : aRet = aStream.GetFileName();
582 : 259 : }
583 : : }
584 : :
585 [ + - ][ + - ]: 299 : return aRet;
586 : : }
587 : :
588 : 0 : String PPDParser::getPPDPrinterName( const String& rFile )
589 : : {
590 [ # # ]: 0 : String aPath = getPPDFile( rFile );
591 [ # # ]: 0 : String aName;
592 : :
593 : : // read in the file
594 [ # # ][ # # ]: 0 : PPDDecompressStream aStream( aPath );
595 [ # # ]: 0 : if( aStream.IsOpen() )
596 : : {
597 [ # # ]: 0 : String aCurLine;
598 [ # # ][ # # ]: 0 : while( ! aStream.IsEof() && aStream.IsOpen() )
[ # # ]
599 : : {
600 [ # # ]: 0 : rtl::OString aByteLine = aStream.ReadLine();
601 [ # # ][ # # ]: 0 : aCurLine = rtl::OStringToOUString(aByteLine, RTL_TEXTENCODING_MS_1252);
602 [ # # ][ # # ]: 0 : if( aCurLine.CompareIgnoreCaseToAscii( "*include:", 9 ) == COMPARE_EQUAL )
603 : : {
604 [ # # ]: 0 : aCurLine.Erase( 0, 9 );
605 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, ' ');
[ # # ]
606 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, ' ');
[ # # ]
607 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, '\t');
[ # # ]
608 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\t');
[ # # ]
609 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\r');
[ # # ]
610 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\n');
[ # # ]
611 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, '"');
[ # # ]
612 [ # # ][ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '"');
[ # # ]
613 [ # # ]: 0 : aStream.Close();
614 [ # # ][ # # ]: 0 : aStream.Open( getPPDFile( aCurLine ) );
[ # # ][ # # ]
615 : 0 : continue;
616 : : }
617 [ # # ][ # # ]: 0 : if( aCurLine.CompareToAscii( "*ModelName:", 11 ) == COMPARE_EQUAL )
618 : : {
619 [ # # ][ # # ]: 0 : aName = aCurLine.GetToken( 1, '"' );
[ # # ]
620 : : break;
621 : : }
622 [ # # ][ # # ]: 0 : else if( aCurLine.CompareToAscii( "*NickName:", 10 ) == COMPARE_EQUAL )
623 [ # # ][ # # ]: 0 : aName = aCurLine.GetToken( 1, '"' );
[ # # ]
624 [ # # # ]: 0 : }
[ # # ]
625 : : }
626 [ # # ][ # # ]: 0 : return aName;
627 : : }
628 : :
629 : 299 : const PPDParser* PPDParser::getParser( const String& rFile )
630 : : {
631 [ + + ][ + - ]: 299 : static ::osl::Mutex aMutex;
[ + - ][ # # ]
632 [ + - ]: 299 : ::osl::Guard< ::osl::Mutex > aGuard( aMutex );
633 : :
634 [ + - ]: 299 : String aFile = rFile;
635 [ + - ][ + - ]: 299 : if( rFile.CompareToAscii( "CUPS:", 5 ) != COMPARE_EQUAL )
636 [ + - ][ + - ]: 299 : aFile = getPPDFile( rFile );
[ + - ]
637 [ + + ]: 299 : if( ! aFile.Len() )
638 : : {
639 : : #if OSL_DEBUG_LEVEL > 1
640 : : fprintf( stderr, "Could not get printer PPD file \"%s\" !\n", ::rtl::OUStringToOString( rFile, osl_getThreadTextEncoding() ).getStr() );
641 : : #endif
642 : 40 : return NULL;
643 : : }
644 : :
645 [ + - ]: 259 : PPDCache &rPPDCache = thePPDCache::get();
646 [ + - ][ # # ]: 259 : for( ::std::list< PPDParser* >::const_iterator it = rPPDCache.aAllParsers.begin(); it != rPPDCache.aAllParsers.end(); ++it )
[ + - ][ + - ]
[ + + ]
647 [ + - ][ + - ]: 199 : if( (*it)->m_aFile == aFile )
[ + - ]
648 [ + - ]: 199 : return *it;
649 : :
650 : 60 : PPDParser* pNewParser = NULL;
651 [ + - ][ + - ]: 60 : if( aFile.CompareToAscii( "CUPS:", 5 ) != COMPARE_EQUAL )
652 [ + - ][ + - ]: 60 : pNewParser = new PPDParser( aFile );
653 : : else
654 : : {
655 [ # # ]: 0 : PrinterInfoManager& rMgr = PrinterInfoManager::get();
656 [ # # ]: 0 : if( rMgr.getType() == PrinterInfoManager::CUPS )
657 : : {
658 : : #ifdef ENABLE_CUPS
659 [ # # ][ # # ]: 0 : pNewParser = const_cast<PPDParser*>(static_cast<CUPSManager&>(rMgr).createCUPSParser( aFile ));
660 : : #endif
661 : : }
662 : : }
663 [ + - ]: 60 : if( pNewParser )
664 : : {
665 : : // this may actually be the SGENPRT parser,
666 : : // so ensure uniquness here
667 [ + - ]: 60 : rPPDCache.aAllParsers.remove( pNewParser );
668 : : // insert new parser to list
669 [ + - ]: 60 : rPPDCache.aAllParsers.push_front( pNewParser );
670 : : }
671 [ + - ][ + - ]: 299 : return pNewParser;
672 : : }
673 : :
674 : 60 : PPDParser::PPDParser( const String& rFile ) :
675 : : m_aFile( rFile ),
676 : : m_bType42Capable( false ),
677 : : m_aFileEncoding( RTL_TEXTENCODING_MS_1252 ),
678 : : m_pDefaultImageableArea( NULL ),
679 : : m_pImageableAreas( NULL ),
680 : : m_pDefaultPaperDimension( NULL ),
681 : : m_pPaperDimensions( NULL ),
682 : : m_pDefaultInputSlot( NULL ),
683 : : m_pInputSlots( NULL ),
684 : : m_pDefaultResolution( NULL ),
685 : : m_pResolutions( NULL ),
686 : : m_pDefaultDuplexType( NULL ),
687 : : m_pDuplexTypes( NULL ),
688 : : m_pFontList( NULL ),
689 [ + - ][ + - ]: 60 : m_pTranslator( new PPDTranslator() )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
690 : : {
691 : : // read in the file
692 [ + - ]: 60 : std::list< rtl::OString > aLines;
693 [ + - ][ + - ]: 60 : PPDDecompressStream aStream( m_aFile );
694 : 60 : bool bLanguageEncoding = false;
695 [ + - ]: 60 : if( aStream.IsOpen() )
696 : : {
697 [ + + ]: 34980 : while( ! aStream.IsEof() )
698 : : {
699 [ + - ]: 34920 : rtl::OString aCurLine = aStream.ReadLine();
700 [ + + ]: 34920 : if( aCurLine[0] == '*' )
701 : : {
702 [ - + ]: 25560 : if (aCurLine.matchIgnoreAsciiCase(rtl::OString("*include:")))
703 : : {
704 : 0 : aCurLine = aCurLine.copy(9);
705 [ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, ' ');
706 [ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, ' ');
707 [ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, '\t');
708 [ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\t');
709 [ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\r');
710 [ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '\n');
711 [ # # ]: 0 : aCurLine = comphelper::string::stripStart(aCurLine, '"');
712 [ # # ]: 0 : aCurLine = comphelper::string::stripEnd(aCurLine, '"');
713 [ # # ]: 0 : aStream.Close();
714 [ # # ][ # # ]: 0 : aStream.Open(getPPDFile(rtl::OStringToOUString(aCurLine, m_aFileEncoding)));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
715 : 0 : continue;
716 : : }
717 [ + + + + ]: 52800 : else if( ! bLanguageEncoding &&
[ + + ]
718 [ + + ][ + + ]: 27240 : aCurLine.matchIgnoreAsciiCase(rtl::OString("*languageencoding")) )
719 : : {
720 : 60 : bLanguageEncoding = true; // generally only the first one counts
721 : 60 : rtl::OString aLower = aCurLine.toAsciiLowerCase();
722 [ + - ]: 60 : if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("isolatin1"), 17 ) != -1 ||
[ - + # # ]
723 : 0 : aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("windowsansi"), 17 ) != -1 )
724 : 60 : m_aFileEncoding = RTL_TEXTENCODING_MS_1252;
725 [ # # ]: 0 : else if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("isolatin2"), 17 ) != -1 )
726 : 0 : m_aFileEncoding = RTL_TEXTENCODING_ISO_8859_2;
727 [ # # ]: 0 : else if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("isolatin5"), 17 ) != -1 )
728 : 0 : m_aFileEncoding = RTL_TEXTENCODING_ISO_8859_5;
729 [ # # ]: 0 : else if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("jis83-rksj"), 17 ) != -1 )
730 : 0 : m_aFileEncoding = RTL_TEXTENCODING_SHIFT_JIS;
731 [ # # ]: 0 : else if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("macstandard"), 17 ) != -1 )
732 : 0 : m_aFileEncoding = RTL_TEXTENCODING_APPLE_ROMAN;
733 [ # # ]: 0 : else if( aLower.indexOfL(RTL_CONSTASCII_STRINGPARAM("utf-8"), 17 ) != -1 )
734 : 60 : m_aFileEncoding = RTL_TEXTENCODING_UTF8;
735 : : }
736 : : }
737 [ + - ][ + - ]: 69840 : aLines.push_back( aCurLine );
738 : 34920 : }
739 : : }
740 [ + - ]: 60 : aStream.Close();
741 : :
742 : : // now get the Values
743 [ + - ]: 60 : parse( aLines );
744 : : #if OSL_DEBUG_LEVEL > 2
745 : : fprintf( stderr, "acquired %d Keys from PPD %s:\n", m_aKeys.size(), BSTRING( m_aFile ).getStr() );
746 : : for( PPDParser::hash_type::const_iterator it = m_aKeys.begin(); it != m_aKeys.end(); ++it )
747 : : {
748 : : const PPDKey* pKey = it->second;
749 : : char* pSetupType = "<unknown>";
750 : : switch( pKey->m_eSetupType )
751 : : {
752 : : case PPDKey::ExitServer: pSetupType = "ExitServer";break;
753 : : case PPDKey::Prolog: pSetupType = "Prolog";break;
754 : : case PPDKey::DocumentSetup: pSetupType = "DocumentSetup";break;
755 : : case PPDKey::PageSetup: pSetupType = "PageSetup";break;
756 : : case PPDKey::JCLSetup: pSetupType = "JCLSetup";break;
757 : : case PPDKey::AnySetup: pSetupType = "AnySetup";break;
758 : : default: break;
759 : : };
760 : : fprintf( stderr, "\t\"%s\" (%d values) OrderDependency: %d %s\n",
761 : : BSTRING( pKey->getKey() ).getStr(),
762 : : pKey->countValues(),
763 : : pKey->m_nOrderDependency,
764 : : pSetupType );
765 : : for( int j = 0; j < pKey->countValues(); j++ )
766 : : {
767 : : fprintf( stderr, "\t\t" );
768 : : const PPDValue* pValue = pKey->getValue( j );
769 : : if( pValue == pKey->m_pDefaultValue )
770 : : fprintf( stderr, "(Default:) " );
771 : : char* pVType = "<unknown>";
772 : : switch( pValue->m_eType )
773 : : {
774 : : case eInvocation: pVType = "invocation";break;
775 : : case eQuoted: pVType = "quoted";break;
776 : : case eString: pVType = "string";break;
777 : : case eSymbol: pVType = "symbol";break;
778 : : case eNo: pVType = "no";break;
779 : : default: break;
780 : : };
781 : : fprintf( stderr, "option: \"%s\", value: type %s \"%s\"\n",
782 : : BSTRING( pValue->m_aOption ).getStr(),
783 : : pVType,
784 : : BSTRING( pValue->m_aValue ).getStr() );
785 : : }
786 : : }
787 : : fprintf( stderr, "constraints: (%d found)\n", m_aConstraints.size() );
788 : : for( std::list< PPDConstraint >::const_iterator cit = m_aConstraints.begin(); cit != m_aConstraints.end(); ++cit )
789 : : {
790 : : fprintf( stderr, "*\"%s\" \"%s\" *\"%s\" \"%s\"\n",
791 : : BSTRING( cit->m_pKey1->getKey() ).getStr(),
792 : : cit->m_pOption1 ? BSTRING( cit->m_pOption1->m_aOption ).getStr() : "<nil>",
793 : : BSTRING( cit->m_pKey2->getKey() ).getStr(),
794 : : cit->m_pOption2 ? BSTRING( cit->m_pOption2->m_aOption ).getStr() : "<nil>"
795 : : );
796 : : }
797 : : #endif
798 : :
799 : : // fill in shortcuts
800 : : const PPDKey* pKey;
801 : :
802 [ + - ][ + - ]: 60 : m_pImageableAreas = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "ImageableArea" ) ) );
[ + - ]
803 [ + - ]: 60 : if( m_pImageableAreas )
804 : 60 : m_pDefaultImageableArea = m_pImageableAreas->getDefaultValue();
805 : 60 : if (m_pImageableAreas == 0) {
806 : : OSL_TRACE(
807 : : OSL_LOG_PREFIX "Warning: no ImageableArea in %s\n",
808 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
809 : : }
810 : 60 : if (m_pDefaultImageableArea == 0) {
811 : : OSL_TRACE(
812 : : OSL_LOG_PREFIX "Warning: no DefaultImageableArea in %s\n",
813 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
814 : : }
815 : :
816 [ + - ][ + - ]: 60 : m_pPaperDimensions = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PaperDimension" ) ) );
[ + - ]
817 [ + - ]: 60 : if( m_pPaperDimensions )
818 : 60 : m_pDefaultPaperDimension = m_pPaperDimensions->getDefaultValue();
819 : 60 : if (m_pPaperDimensions == 0) {
820 : : OSL_TRACE(
821 : : OSL_LOG_PREFIX "Warning: no PaperDimensions in %s\n",
822 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
823 : : }
824 : 60 : if (m_pDefaultPaperDimension == 0) {
825 : : OSL_TRACE(
826 : : OSL_LOG_PREFIX "Warning: no DefaultPaperDimensions in %s\n",
827 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
828 : : }
829 : :
830 [ + - ][ + - ]: 60 : m_pResolutions = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ) );
[ + - ]
831 [ + - ]: 60 : if( m_pResolutions )
832 : 60 : m_pDefaultResolution = m_pResolutions->getDefaultValue();
833 : 60 : if (m_pResolutions == 0) {
834 : : OSL_TRACE(
835 : : OSL_LOG_PREFIX "Warning: no Resolution in %s\n",
836 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
837 : : }
838 : 60 : if (m_pDefaultResolution == 0) {
839 : : OSL_TRACE(
840 : : OSL_LOG_PREFIX "Warning: no DefaultResolution in %s\n",
841 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
842 : : }
843 : :
844 [ + - ][ + - ]: 60 : m_pInputSlots = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
[ + - ]
845 [ - + ]: 60 : if( m_pInputSlots )
846 : 0 : m_pDefaultInputSlot = m_pInputSlots->getDefaultValue();
847 : 60 : if (m_pInputSlots == 0) {
848 : : OSL_TRACE(
849 : : OSL_LOG_PREFIX "Warning: no InputSlot in %s\n",
850 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
851 : : }
852 : 60 : if (m_pDefaultInputSlot == 0) {
853 : : OSL_TRACE(
854 : : OSL_LOG_PREFIX "Warning: no DefaultInputSlot in %s\n",
855 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
856 : : }
857 : :
858 [ + - ][ + - ]: 60 : m_pDuplexTypes = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
[ + - ]
859 [ + - ]: 60 : if( m_pDuplexTypes )
860 : 60 : m_pDefaultDuplexType = m_pDuplexTypes->getDefaultValue();
861 : :
862 [ + - ][ + - ]: 60 : m_pFontList = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Font" ) ) );
[ + - ]
863 : 60 : if (m_pFontList == 0) {
864 : : OSL_TRACE(
865 : : OSL_LOG_PREFIX "Warning: no Font in %s\n",
866 : : rtl::OUStringToOString(m_aFile, RTL_TEXTENCODING_UTF8).getStr());
867 : : }
868 : :
869 : : // fill in direct values
870 [ + - ][ + - ]: 60 : if( (pKey = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "ModelName" ) ) )) )
[ + - ][ + - ]
871 [ + - ][ + - ]: 60 : m_aPrinterName = pKey->getValue( 0 )->m_aValue;
872 [ + - ][ + - ]: 60 : if( (pKey = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "NickName" ) ) )) )
[ + - ][ + - ]
873 [ + - ][ + - ]: 60 : m_aNickName = pKey->getValue( 0 )->m_aValue;
874 [ + - ][ + - ]: 60 : if( (pKey = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "ColorDevice" ) ) )) )
[ + - ][ + - ]
875 [ + - ][ + - ]: 60 : m_bColorDevice = pKey->getValue( 0 )->m_aValue.CompareIgnoreCaseToAscii( "true", 4 ) == COMPARE_EQUAL ? true : false;
876 : :
877 [ + - ][ + - ]: 60 : if( (pKey = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "LanguageLevel" ) ) )) )
[ + - ][ + - ]
878 [ + - ][ + - ]: 60 : m_nLanguageLevel = pKey->getValue( 0 )->m_aValue.ToInt32();
879 [ + - ][ + - ]: 60 : if( (pKey = getKey( String( RTL_CONSTASCII_USTRINGPARAM( "TTRasterizer" ) ) )) )
[ + - ][ - + ]
880 [ # # ][ # # ]: 60 : m_bType42Capable = pKey->getValue( 0 )->m_aValue.EqualsIgnoreCaseAscii( "Type42" ) ? true : false;
[ + - ]
881 : 60 : }
882 : :
883 [ + - ][ + - ]: 60 : PPDParser::~PPDParser()
[ + - ]
884 : : {
885 [ + - ][ + - ]: 2760 : for( PPDParser::hash_type::iterator it = m_aKeys.begin(); it != m_aKeys.end(); ++it )
[ + + ]
886 [ + - ][ + - ]: 2700 : delete it->second;
[ + - ]
887 [ + - ][ + - ]: 60 : delete m_pTranslator;
888 : 60 : }
889 : :
890 : 2700 : void PPDParser::insertKey( const String& rKey, PPDKey* pKey )
891 : : {
892 [ + - ]: 2700 : m_aKeys[ rKey ] = pKey;
893 : 2700 : m_aOrderedKeys.push_back( pKey );
894 : 2700 : }
895 : :
896 : 0 : const PPDKey* PPDParser::getKey( int n ) const
897 : : {
898 [ # # ][ # # ]: 0 : return ((unsigned int)n < m_aOrderedKeys.size() && n >= 0) ? m_aOrderedKeys[n] : NULL;
899 : : }
900 : :
901 : 1787 : const PPDKey* PPDParser::getKey( const String& rKey ) const
902 : : {
903 [ + - ][ + - ]: 1787 : PPDParser::hash_type::const_iterator it = m_aKeys.find( rKey );
904 [ + + ][ + - ]: 1787 : return it != m_aKeys.end() ? it->second : NULL;
[ + - ]
905 : : }
906 : :
907 : 592 : bool PPDParser::hasKey( const PPDKey* pKey ) const
908 : : {
909 : : return
910 : : pKey ?
911 [ + - ][ + - ]: 1184 : ( m_aKeys.find( pKey->getKey() ) != m_aKeys.end() ? true : false ) :
[ # # ]
912 [ + - ][ + - ]: 1776 : false;
[ + - ][ + - ]
[ + - ]
[ # # # # ]
913 : : }
914 : :
915 : 0 : static sal_uInt8 getNibble( sal_Char cChar )
916 : : {
917 : 0 : sal_uInt8 nRet = 0;
918 [ # # ][ # # ]: 0 : if( cChar >= '0' && cChar <= '9' )
919 : 0 : nRet = sal_uInt8( cChar - '0' );
920 [ # # ][ # # ]: 0 : else if( cChar >= 'A' && cChar <= 'F' )
921 : 0 : nRet = 10 + sal_uInt8( cChar - 'A' );
922 [ # # ][ # # ]: 0 : else if( cChar >= 'a' && cChar <= 'f' )
923 : 0 : nRet = 10 + sal_uInt8( cChar - 'a' );
924 : 0 : return nRet;
925 : : }
926 : :
927 : 8280 : String PPDParser::handleTranslation(const rtl::OString& i_rString, bool bIsGlobalized)
928 : : {
929 : 8280 : sal_Int32 nOrigLen = i_rString.getLength();
930 : 8280 : OStringBuffer aTrans( nOrigLen );
931 : 8280 : const sal_Char* pStr = i_rString.getStr();
932 : 8280 : const sal_Char* pEnd = pStr + nOrigLen;
933 [ + + ]: 124260 : while( pStr < pEnd )
934 : : {
935 [ - + ]: 115980 : if( *pStr == '<' )
936 : : {
937 : 0 : pStr++;
938 : : sal_Char cChar;
939 [ # # ][ # # ]: 0 : while( *pStr != '>' && pStr < pEnd-1 )
[ # # ]
940 : : {
941 : 0 : cChar = getNibble( *pStr++ ) << 4;
942 : 0 : cChar |= getNibble( *pStr++ );
943 [ # # ]: 0 : aTrans.append( cChar );
944 : : }
945 : 0 : pStr++;
946 : : }
947 : : else
948 [ + - ]: 115980 : aTrans.append( *pStr++ );
949 : : }
950 [ - + ][ + - ]: 8280 : return OStringToOUString( aTrans.makeStringAndClear(), bIsGlobalized ? RTL_TEXTENCODING_UTF8 : m_aFileEncoding );
[ + - ]
951 : : }
952 : :
953 : : namespace
954 : : {
955 : 27120 : bool oddDoubleQuoteCount(rtl::OStringBuffer &rBuffer)
956 : : {
957 : 27120 : bool bHasOddCount = false;
958 [ + + ]: 2608260 : for (sal_Int32 i = 0; i < rBuffer.getLength(); ++i)
959 : : {
960 [ + + ]: 2581140 : if (rBuffer[i] == '"')
961 : 46320 : bHasOddCount = !bHasOddCount;
962 : : }
963 : 27120 : return bHasOddCount;
964 : : }
965 : : }
966 : :
967 : 60 : void PPDParser::parse( ::std::list< rtl::OString >& rLines )
968 : : {
969 : 60 : std::list< rtl::OString >::iterator line = rLines.begin();
970 : 60 : PPDParser::hash_type::const_iterator keyit;
971 [ + + ]: 28380 : while( line != rLines.end() )
972 : : {
973 : 28320 : rtl::OString aCurrentLine( *line );
974 : 28320 : ++line;
975 [ + + ]: 28320 : if( aCurrentLine[0] != '*' )
976 : 2760 : continue;
977 [ + + ]: 25560 : if( aCurrentLine[1] == '%' )
978 : 3000 : continue;
979 : :
980 [ + - ]: 22560 : rtl::OString aKey = GetCommandLineToken( 0, comphelper::string::getToken(aCurrentLine, 0, ':') );
981 : 22560 : sal_Int32 nPos = aKey.indexOf('/');
982 [ - + ]: 22560 : if (nPos != -1)
983 : 0 : aKey = aKey.copy(0, nPos);
984 : 22560 : aKey = aKey.copy(1); // remove the '*'
985 : :
986 [ + + ][ + + : 133080 : if (aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CloseUI")) ||
+ - + - +
+ + - -
+ ]
987 : 22320 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("OpenGroup")) ||
988 : 22320 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CloseGroup")) ||
989 : 22320 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("End")) ||
990 : 21780 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("OpenSubGroup")) ||
991 : 21780 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CloseSubGroup")))
992 : : {
993 : 780 : continue;
994 : : }
995 : :
996 [ + + ]: 21780 : if (aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("OpenUI")))
997 : : {
998 [ + - ]: 240 : parseOpenUI( aCurrentLine );
999 : 240 : continue;
1000 : : }
1001 [ + + ]: 21540 : else if (aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("OrderDependency")))
1002 : : {
1003 [ + - ]: 240 : parseOrderDependency( aCurrentLine );
1004 : 240 : continue;
1005 : : }
1006 [ + - - + ]: 42600 : else if (aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIConstraints")) ||
[ - + ]
1007 : 21300 : aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("NonUIConstraints")))
1008 : : {
1009 : 0 : continue; // parsed in pass 2
1010 : : }
1011 [ - + ]: 21300 : else if( aKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CustomPageSize")) ) // currently not handled
1012 : 0 : continue;
1013 : :
1014 : : // default values are parsed in pass 2
1015 [ + + ]: 21300 : if (aKey.matchL(RTL_CONSTASCII_STRINGPARAM("Default")))
1016 : 780 : continue;
1017 : :
1018 : 20520 : bool bQuery = false;
1019 [ + + ]: 20520 : if (aKey[0] == '?')
1020 : : {
1021 : 180 : aKey = aKey.copy(1);
1022 : 180 : bQuery = true;
1023 : : }
1024 : :
1025 [ + - ][ + - ]: 20520 : String aUniKey(rtl::OStringToOUString(aKey, RTL_TEXTENCODING_MS_1252));
1026 : : // handle CUPS extension for globalized PPDs
1027 : 20520 : bool bIsGlobalizedLine = false;
1028 : 20520 : com::sun::star::lang::Locale aTransLocale;
1029 [ + - + + : 59400 : if( ( aUniKey.Len() > 3 && aUniKey.GetChar( 2 ) == '.' ) ||
- + # # ]
[ - + ][ + - ]
1030 : 38880 : ( aUniKey.Len() > 5 && aUniKey.GetChar( 2 ) == '_' && aUniKey.GetChar( 5 ) == '.' ) )
1031 : : {
1032 [ # # ]: 0 : if( aUniKey.GetChar( 2 ) == '.' )
1033 : : {
1034 [ # # ][ # # ]: 0 : aTransLocale.Language = aUniKey.Copy( 0, 2 );
[ # # ]
1035 [ # # ][ # # ]: 0 : aUniKey = aUniKey.Copy( 3 );
[ # # ]
1036 : : }
1037 : : else
1038 : : {
1039 [ # # ][ # # ]: 0 : aTransLocale.Language = aUniKey.Copy( 0, 2 );
[ # # ]
1040 [ # # ][ # # ]: 0 : aTransLocale.Country = aUniKey.Copy( 3, 2 );
[ # # ]
1041 [ # # ][ # # ]: 0 : aUniKey = aUniKey.Copy( 6 );
[ # # ]
1042 : : }
1043 : 0 : bIsGlobalizedLine = true;
1044 : : }
1045 : :
1046 [ + - ]: 20520 : String aOption;
1047 : 20520 : nPos = aCurrentLine.indexOf(':');
1048 [ + - ]: 20520 : if( nPos != -1 )
1049 : : {
1050 [ + - ][ + - ]: 20520 : aOption = rtl::OStringToOUString( aCurrentLine.copy( 1, nPos-1 ), RTL_TEXTENCODING_MS_1252 );
1051 [ + - ][ + - ]: 20520 : aOption = GetCommandLineToken( 1, aOption );
[ + - ]
1052 [ + - ]: 20520 : int nTransPos = aOption.Search( '/' );
1053 [ + + ]: 20520 : if( nTransPos != STRING_NOTFOUND )
1054 [ + - ]: 7860 : aOption.Erase( nTransPos );
1055 : : }
1056 : :
1057 : 20520 : PPDValueType eType = eNo;
1058 [ + - ]: 20520 : String aValue;
1059 : 20520 : rtl::OUString aOptionTranslation;
1060 : 20520 : rtl::OUString aValueTranslation;
1061 [ + - ]: 20520 : if( nPos != STRING_NOTFOUND )
1062 : : {
1063 : : // found a colon, there may be an option
1064 : 20520 : rtl::OString aLine = aCurrentLine.copy( 1, nPos-1 );
1065 [ + - ]: 20520 : aLine = WhitespaceToSpace( aLine );
1066 : 20520 : sal_Int32 nTransPos = aLine.indexOf('/');
1067 [ + + ]: 20520 : if (nTransPos != -1)
1068 [ + - ][ + - ]: 7860 : aOptionTranslation = handleTranslation( aLine.copy(nTransPos+1), bIsGlobalizedLine );
[ + - ]
1069 : :
1070 : : // read in more lines if necessary for multiline values
1071 : 20520 : aLine = aCurrentLine.copy( nPos+1 );
1072 [ + - ]: 20520 : if (!aLine.isEmpty())
1073 : : {
1074 [ + - ]: 20520 : rtl::OStringBuffer aBuffer(aLine);
1075 [ + - ][ + + ]: 27120 : while (line != rLines.end() && oddDoubleQuoteCount(aBuffer))
[ + - ][ + + ]
1076 : : {
1077 : : // copy the newlines also
1078 [ + - ]: 6600 : aBuffer.append('\n');
1079 [ + - ]: 6600 : aBuffer.append(*line);
1080 : 6600 : ++line;
1081 : : }
1082 : 20520 : aLine = aBuffer.makeStringAndClear();
1083 : : }
1084 [ + - ]: 20520 : aLine = WhitespaceToSpace( aLine );
1085 : :
1086 : : // #i100644# handle a missing value (actually a broken PPD)
1087 [ - + ]: 20520 : if( aLine.isEmpty() )
1088 : : {
1089 [ # # ][ # # ]: 0 : if( aOption.Len() &&
[ # # ]
1090 [ # # ]: 0 : aUniKey.CompareToAscii( "JCL", 3 ) != COMPARE_EQUAL )
1091 : 0 : eType = eInvocation;
1092 : : else
1093 : 0 : eType = eQuoted;
1094 : : }
1095 : : // check for invocation or quoted value
1096 [ + + ]: 20520 : else if(aLine[0] == '"')
1097 : : {
1098 : 17760 : aLine = aLine.copy(1);
1099 : 17760 : nTransPos = aLine.indexOf('"');
1100 [ - + ]: 17760 : if (nTransPos == -1)
1101 : 0 : nTransPos = aLine.getLength();
1102 [ + - ][ + - ]: 17760 : aValue = rtl::OStringToOUString(aLine.copy(0, nTransPos), RTL_TEXTENCODING_MS_1252);
1103 : : // after the second doublequote can follow a / and a translation
1104 [ - + ]: 17760 : if (nTransPos < aLine.getLength() - 2)
1105 : : {
1106 [ # # ][ # # ]: 0 : aValueTranslation = handleTranslation( aLine.copy( nTransPos+2 ), bIsGlobalizedLine );
[ # # ]
1107 : : }
1108 : : // check for quoted value
1109 [ + + ][ + - ]: 32640 : if( aOption.Len() &&
[ + + ]
1110 [ + - ]: 14880 : aUniKey.CompareToAscii( "JCL", 3 ) != COMPARE_EQUAL )
1111 : 14880 : eType = eInvocation;
1112 : : else
1113 : 2880 : eType = eQuoted;
1114 : : }
1115 : : // check for symbol value
1116 [ - + ]: 2760 : else if(aLine[0] == '^')
1117 : : {
1118 : 0 : aLine = aLine.copy(1);
1119 [ # # ][ # # ]: 0 : aValue = rtl::OStringToOUString(aLine, RTL_TEXTENCODING_MS_1252);
1120 : 0 : eType = eSymbol;
1121 : : }
1122 : : else
1123 : : {
1124 : : // must be a string value then
1125 : : // strictly this is false because string values
1126 : : // can contain any whitespace which is reduced
1127 : : // to one space by now
1128 : : // who cares ...
1129 : 2760 : nTransPos = aLine.indexOf('/');
1130 [ + + ]: 2760 : if (nTransPos == -1)
1131 : 2460 : nTransPos = aLine.getLength();
1132 [ + - ][ + - ]: 2760 : aValue = rtl::OStringToOUString(aLine.copy(0, nTransPos), RTL_TEXTENCODING_MS_1252);
1133 [ + + ]: 2760 : if (nTransPos+1 < aLine.getLength())
1134 [ + - ][ + - ]: 300 : aValueTranslation = handleTranslation( aLine.copy( nTransPos+1 ), bIsGlobalizedLine );
[ + - ]
1135 : 2760 : eType = eString;
1136 : 20520 : }
1137 : : }
1138 : :
1139 : : // handle globalized PPD entries
1140 [ - + ]: 20520 : if( bIsGlobalizedLine )
1141 : : {
1142 : : // handle main key translations of form:
1143 : : // *ll_CC.Translation MainKeyword/translated text: ""
1144 [ # # ][ # # ]: 0 : if( aUniKey.EqualsAscii( "Translation" ) )
1145 : : {
1146 [ # # ][ # # ]: 0 : m_pTranslator->insertKey( aOption, aOptionTranslation, aTransLocale );
1147 : : }
1148 : : // handle options translations of for:
1149 : : // *ll_CC.MainKeyword OptionKeyword/translated text: ""
1150 : : else
1151 : : {
1152 [ # # ][ # # ]: 0 : m_pTranslator->insertOption( aUniKey, aOption, aOptionTranslation, aTransLocale );
[ # # ]
1153 : : }
1154 : 0 : continue;
1155 : : }
1156 : :
1157 : 20520 : PPDKey* pKey = NULL;
1158 [ + - ][ + - ]: 20520 : keyit = m_aKeys.find( aUniKey );
1159 [ + + ][ + - ]: 20520 : if( keyit == m_aKeys.end() )
1160 : : {
1161 [ + - ][ + - ]: 2220 : pKey = new PPDKey( aUniKey );
1162 [ + - ]: 2220 : insertKey( aUniKey, pKey );
1163 : : }
1164 : : else
1165 [ + - ]: 18300 : pKey = keyit->second;
1166 : :
1167 [ - + ][ # # ]: 20520 : if( eType == eNo && bQuery )
1168 : 0 : continue;
1169 : :
1170 [ + - ]: 20520 : PPDValue* pValue = pKey->insertValue( aOption );
1171 [ + + ]: 20520 : if( ! pValue )
1172 : 1800 : continue;
1173 : 18720 : pValue->m_eType = eType;
1174 [ + - ]: 18720 : pValue->m_aValue = aValue;
1175 : :
1176 [ + + ]: 18720 : if( !aOptionTranslation.isEmpty() )
1177 [ + - ][ + - ]: 7860 : m_pTranslator->insertOption( aUniKey, aOption, aOptionTranslation, aTransLocale );
[ + - ]
1178 [ + + ]: 18720 : if( !aValueTranslation.isEmpty() )
1179 [ + - ][ + - ]: 60 : m_pTranslator->insertValue( aUniKey, aOption, aValue, aValueTranslation, aTransLocale );
[ + - ][ + - ]
1180 : :
1181 : : // eventually update query and remove from option list
1182 [ + + ][ + - ]: 18720 : if( bQuery && pKey->m_bQueryValue == sal_False )
1183 : : {
1184 [ + - ]: 180 : pKey->m_aQueryValue = *pValue;
1185 : 180 : pKey->m_bQueryValue = true;
1186 [ + - ]: 18720 : pKey->eraseValue( pValue->m_aOption );
1187 : : }
1188 [ + + ][ + + ]: 28320 : }
[ + - ][ + + ]
[ + - ][ + + ]
[ + + ][ + - ]
[ + + ][ + + ]
[ + + ]
1189 : :
1190 : : // second pass: fill in defaults
1191 [ + + ]: 34980 : for( line = rLines.begin(); line != rLines.end(); ++line )
1192 : : {
1193 : 34920 : rtl::OString aLine(*line);
1194 [ + + ]: 34920 : if (aLine.matchL(RTL_CONSTASCII_STRINGPARAM("*Default")))
1195 : : {
1196 [ + - ][ + - ]: 780 : String aKey(rtl::OStringToOUString(aLine.copy(8), RTL_TEXTENCODING_MS_1252));
1197 [ + - ]: 780 : sal_uInt16 nPos = aKey.Search( ':' );
1198 [ + - ]: 780 : if( nPos != STRING_NOTFOUND )
1199 : : {
1200 [ + - ]: 780 : aKey.Erase( nPos );
1201 : : rtl::OUString aOption(rtl::OStringToOUString(
1202 : : WhitespaceToSpace(aLine.copy(nPos+9)),
1203 [ + - ][ + - ]: 780 : RTL_TEXTENCODING_MS_1252));
1204 [ + - ][ + - ]: 780 : keyit = m_aKeys.find( aKey );
1205 [ + + ][ + - ]: 780 : if( keyit != m_aKeys.end() )
1206 : : {
1207 [ + - ]: 540 : PPDKey* pKey = keyit->second;
1208 [ + - ][ + - ]: 540 : const PPDValue* pDefValue = pKey->getValue( aOption );
[ + - ]
1209 [ + - ]: 540 : if( pKey->m_pDefaultValue == NULL )
1210 : 540 : pKey->m_pDefaultValue = pDefValue;
1211 : : }
1212 : : else
1213 : : {
1214 : : // some PPDs contain defaults for keys that
1215 : : // do not exist otherwise
1216 : : // (example: DefaultResolution)
1217 : : // so invent that key here and have a default value
1218 [ + - ][ + - ]: 240 : PPDKey* pKey = new PPDKey( aKey );
1219 [ + - ][ + - ]: 240 : PPDValue* pNewValue = pKey->insertValue( aOption );
[ + - ]
1220 : 240 : pNewValue->m_eType = eInvocation; // or what ?
1221 [ + - ]: 240 : insertKey( aKey, pKey );
1222 : 780 : }
1223 [ + - ]: 780 : }
1224 : : }
1225 [ + - - + ]: 68280 : else if (aLine.matchL(RTL_CONSTASCII_STRINGPARAM("*UIConstraints")) ||
[ - + ]
1226 : 34140 : aLine.matchL(RTL_CONSTASCII_STRINGPARAM("*NonUIConstraints")))
1227 : : {
1228 [ # # ]: 0 : parseConstraint( aLine );
1229 : : }
1230 : 34920 : }
1231 : 60 : }
1232 : :
1233 : 240 : void PPDParser::parseOpenUI(const rtl::OString& rLine)
1234 : : {
1235 [ + - ]: 240 : String aTranslation;
1236 : 240 : rtl::OString aKey = rLine;
1237 : :
1238 : 240 : sal_Int32 nPos = aKey.indexOf(':');
1239 [ + - ]: 240 : if( nPos != -1 )
1240 : 240 : aKey = aKey.copy(0, nPos);
1241 : 240 : nPos = aKey.indexOf('/');
1242 [ + + ]: 240 : if( nPos != -1 )
1243 : : {
1244 [ + - ][ + - ]: 120 : aTranslation = handleTranslation( aKey.copy( nPos + 1 ), false );
[ + - ]
1245 : 120 : aKey = aKey.copy(0, nPos);
1246 : : }
1247 [ + - ]: 240 : aKey = GetCommandLineToken( 1, aKey );
1248 : 240 : aKey = aKey.copy(1);
1249 : :
1250 [ + - ][ + - ]: 240 : String aUniKey(rtl::OStringToOUString(aKey, RTL_TEXTENCODING_MS_1252));
1251 [ + - ][ + - ]: 240 : PPDParser::hash_type::const_iterator keyit = m_aKeys.find( aUniKey );
1252 : : PPDKey* pKey;
1253 [ + - ][ + - ]: 240 : if( keyit == m_aKeys.end() )
1254 : : {
1255 [ + - ][ + - ]: 240 : pKey = new PPDKey( aUniKey );
1256 [ + - ]: 240 : insertKey( aUniKey, pKey );
1257 : : }
1258 : : else
1259 [ # # ]: 0 : pKey = keyit->second;
1260 : :
1261 : 240 : pKey->m_bUIOption = true;
1262 [ + - ][ + - ]: 240 : m_pTranslator->insertKey( pKey->getKey(), aTranslation );
[ + - ]
1263 : :
1264 : 240 : sal_Int32 nIndex = 0;
1265 [ + - ]: 240 : rtl::OString aValue = WhitespaceToSpace( rLine.getToken( 1, ':', nIndex ) );
1266 [ + + ]: 240 : if( aValue.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("boolean")))
1267 : 60 : pKey->m_eUIType = PPDKey::Boolean;
1268 [ - + ]: 180 : else if (aValue.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pickmany")))
1269 : 0 : pKey->m_eUIType = PPDKey::PickMany;
1270 : : else
1271 [ + - ][ + - ]: 240 : pKey->m_eUIType = PPDKey::PickOne;
1272 : 240 : }
1273 : :
1274 : 240 : void PPDParser::parseOrderDependency(const rtl::OString& rLine)
1275 : : {
1276 : 240 : rtl::OString aLine(rLine);
1277 : 240 : sal_Int32 nPos = aLine.indexOf(':');
1278 [ + - ]: 240 : if( nPos != -1 )
1279 : 240 : aLine = aLine.copy( nPos+1 );
1280 : :
1281 [ + - ]: 240 : sal_Int32 nOrder = GetCommandLineToken( 0, aLine ).toInt32();
1282 [ + - ]: 240 : rtl::OString aSetup = GetCommandLineToken( 1, aLine );
1283 [ + - ][ + - ]: 240 : String aKey(rtl::OStringToOUString(GetCommandLineToken(2, aLine), RTL_TEXTENCODING_MS_1252));
[ + - ]
1284 [ - + ]: 240 : if( aKey.GetChar( 0 ) != '*' )
1285 : 240 : return; // invalid order depency
1286 [ + - ]: 240 : aKey.Erase( 0, 1 );
1287 : :
1288 : : PPDKey* pKey;
1289 [ + - ][ + - ]: 240 : PPDParser::hash_type::const_iterator keyit = m_aKeys.find( aKey );
1290 [ - + ][ + - ]: 240 : if( keyit == m_aKeys.end() )
1291 : : {
1292 [ # # ][ # # ]: 0 : pKey = new PPDKey( aKey );
1293 [ # # ]: 0 : insertKey( aKey, pKey );
1294 : : }
1295 : : else
1296 [ + - ]: 240 : pKey = keyit->second;
1297 : :
1298 : 240 : pKey->m_nOrderDependency = nOrder;
1299 [ - + ]: 240 : if( aSetup.equalsL(RTL_CONSTASCII_STRINGPARAM("ExitServer")) )
1300 : 0 : pKey->m_eSetupType = PPDKey::ExitServer;
1301 [ - + ]: 240 : else if( aSetup.equalsL(RTL_CONSTASCII_STRINGPARAM("Prolog")) )
1302 : 0 : pKey->m_eSetupType = PPDKey::Prolog;
1303 [ - + ]: 240 : else if( aSetup.equalsL(RTL_CONSTASCII_STRINGPARAM("DocumentSetup")) )
1304 : 0 : pKey->m_eSetupType = PPDKey::DocumentSetup;
1305 [ - + ]: 240 : else if( aSetup.equalsL(RTL_CONSTASCII_STRINGPARAM("PageSetup")) )
1306 : 0 : pKey->m_eSetupType = PPDKey::PageSetup;
1307 [ - + ]: 240 : else if( aSetup.equalsL(RTL_CONSTASCII_STRINGPARAM("JCLSetup")) )
1308 : 0 : pKey->m_eSetupType = PPDKey::JCLSetup;
1309 : : else
1310 [ + - ][ - + ]: 240 : pKey->m_eSetupType = PPDKey::AnySetup;
[ - + ][ + - ]
1311 : : }
1312 : :
1313 : 0 : void PPDParser::parseConstraint( const rtl::OString& rLine )
1314 : : {
1315 : 0 : bool bFailed = false;
1316 : :
1317 [ # # ][ # # ]: 0 : String aLine(rtl::OStringToOUString(rLine, RTL_TEXTENCODING_MS_1252));
1318 [ # # ]: 0 : aLine.Erase(0, rLine.indexOf(':') + 1);
1319 : 0 : PPDConstraint aConstraint;
1320 [ # # ][ # # ]: 0 : int nTokens = GetCommandLineTokenCount( aLine );
1321 [ # # ]: 0 : for( int i = 0; i < nTokens; i++ )
1322 : : {
1323 [ # # ]: 0 : String aToken = GetCommandLineToken( i, aLine );
1324 [ # # ]: 0 : if( aToken.GetChar( 0 ) == '*' )
1325 : : {
1326 [ # # ]: 0 : aToken.Erase( 0, 1 );
1327 [ # # ]: 0 : if( aConstraint.m_pKey1 )
1328 [ # # ]: 0 : aConstraint.m_pKey2 = getKey( aToken );
1329 : : else
1330 [ # # ]: 0 : aConstraint.m_pKey1 = getKey( aToken );
1331 : : }
1332 : : else
1333 : : {
1334 [ # # ]: 0 : if( aConstraint.m_pKey2 )
1335 : : {
1336 [ # # ][ # # ]: 0 : if( ! ( aConstraint.m_pOption2 = aConstraint.m_pKey2->getValue( aToken ) ) )
1337 : 0 : bFailed = true;
1338 : : }
1339 [ # # ]: 0 : else if( aConstraint.m_pKey1 )
1340 : : {
1341 [ # # ][ # # ]: 0 : if( ! ( aConstraint.m_pOption1 = aConstraint.m_pKey1->getValue( aToken ) ) )
1342 : 0 : bFailed = true;
1343 : : }
1344 : : else
1345 : : // constraint for nonexistent keys; this happens
1346 : : // e.g. in HP4PLUS3
1347 : 0 : bFailed = true;
1348 : : }
1349 [ # # ]: 0 : }
1350 : : // there must be two keywords
1351 [ # # ][ # # ]: 0 : if( ! aConstraint.m_pKey1 || ! aConstraint.m_pKey2 || bFailed )
[ # # ]
1352 : : {
1353 : : #ifdef __DEBUG
1354 : : fprintf( stderr, "Warning: constraint \"%s\" is invalid\n", rLine.getStr() );
1355 : : #endif
1356 : : }
1357 : : else
1358 [ # # ][ # # ]: 0 : m_aConstraints.push_back( aConstraint );
1359 : 0 : }
1360 : :
1361 : 0 : String PPDParser::getDefaultPaperDimension() const
1362 : : {
1363 [ # # ]: 0 : if( m_pDefaultPaperDimension )
1364 : 0 : return m_pDefaultPaperDimension->m_aOption;
1365 : :
1366 : 0 : return String();
1367 : : }
1368 : :
1369 : 112 : bool PPDParser::getMargins(
1370 : : const String& rPaperName,
1371 : : int& rLeft, int& rRight,
1372 : : int& rUpper, int& rLower ) const
1373 : : {
1374 [ + - ][ - + ]: 112 : if( ! m_pImageableAreas || ! m_pPaperDimensions )
1375 : 0 : return false;
1376 : :
1377 : 112 : int nPDim=-1, nImArea=-1, i;
1378 [ + - ][ + + ]: 3696 : for( i = 0; i < m_pImageableAreas->countValues(); i++ )
1379 [ + - ][ + - ]: 3584 : if( rPaperName == m_pImageableAreas->getValue( i )->m_aOption )
[ + + ]
1380 : 112 : nImArea = i;
1381 [ + - ][ + + ]: 3696 : for( i = 0; i < m_pPaperDimensions->countValues(); i++ )
1382 [ + - ][ + - ]: 3584 : if( rPaperName == m_pPaperDimensions->getValue( i )->m_aOption )
[ + + ]
1383 : 112 : nPDim = i;
1384 [ + - ][ - + ]: 112 : if( nPDim == -1 || nImArea == -1 )
1385 : 0 : return false;
1386 : :
1387 : : double ImLLx, ImLLy, ImURx, ImURy;
1388 : : double PDWidth, PDHeight;
1389 [ + - ][ + - ]: 112 : String aArea = m_pImageableAreas->getValue( nImArea )->m_aValue;
1390 [ + - ][ + - ]: 112 : ImLLx = StringToDouble( GetCommandLineToken( 0, aArea ) );
[ + - ]
1391 [ + - ][ + - ]: 112 : ImLLy = StringToDouble( GetCommandLineToken( 1, aArea ) );
[ + - ]
1392 [ + - ][ + - ]: 112 : ImURx = StringToDouble( GetCommandLineToken( 2, aArea ) );
[ + - ]
1393 [ + - ][ + - ]: 112 : ImURy = StringToDouble( GetCommandLineToken( 3, aArea ) );
[ + - ]
1394 [ + - ][ + - ]: 112 : aArea = m_pPaperDimensions->getValue( nPDim )->m_aValue;
1395 [ + - ][ + - ]: 112 : PDWidth = StringToDouble( GetCommandLineToken( 0, aArea ) );
[ + - ]
1396 [ + - ][ + - ]: 112 : PDHeight = StringToDouble( GetCommandLineToken( 1, aArea ) );
[ + - ]
1397 : 112 : rLeft = (int)(ImLLx + 0.5);
1398 : 112 : rLower = (int)(ImLLy + 0.5);
1399 : 112 : rUpper = (int)(PDHeight - ImURy + 0.5);
1400 : 112 : rRight = (int)(PDWidth - ImURx + 0.5);
1401 : :
1402 [ + - ]: 112 : return true;
1403 : : }
1404 : :
1405 : 224 : bool PPDParser::getPaperDimension(
1406 : : const String& rPaperName,
1407 : : int& rWidth, int& rHeight ) const
1408 : : {
1409 [ - + ]: 224 : if( ! m_pPaperDimensions )
1410 : 0 : return false;
1411 : :
1412 : 224 : int nPDim=-1;
1413 [ + - ][ + + ]: 7392 : for( int i = 0; i < m_pPaperDimensions->countValues(); i++ )
1414 [ + - ][ + - ]: 7168 : if( rPaperName == m_pPaperDimensions->getValue( i )->m_aOption )
[ + + ]
1415 : 224 : nPDim = i;
1416 [ - + ]: 224 : if( nPDim == -1 )
1417 : 0 : return false;
1418 : :
1419 : : double PDWidth, PDHeight;
1420 [ + - ][ + - ]: 224 : String aArea = m_pPaperDimensions->getValue( nPDim )->m_aValue;
1421 [ + - ][ + - ]: 224 : PDWidth = StringToDouble( GetCommandLineToken( 0, aArea ) );
[ + - ]
1422 [ + - ][ + - ]: 224 : PDHeight = StringToDouble( GetCommandLineToken( 1, aArea ) );
[ + - ]
1423 : 224 : rHeight = (int)(PDHeight + 0.5);
1424 : 224 : rWidth = (int)(PDWidth + 0.5);
1425 : :
1426 [ + - ]: 224 : return true;
1427 : : }
1428 : :
1429 : 0 : String PPDParser::matchPaper( int nWidth, int nHeight ) const
1430 : : {
1431 [ # # ]: 0 : if( ! m_pPaperDimensions )
1432 : 0 : return String();
1433 : :
1434 : 0 : int nPDim = -1;
1435 : : double PDWidth, PDHeight;
1436 : 0 : double fSort = 2e36, fNewSort;
1437 : :
1438 [ # # ]: 0 : for( int i = 0; i < m_pPaperDimensions->countValues(); i++ )
1439 : : {
1440 [ # # ][ # # ]: 0 : String aArea = m_pPaperDimensions->getValue( i )->m_aValue;
1441 [ # # ][ # # ]: 0 : PDWidth = StringToDouble( GetCommandLineToken( 0, aArea ) );
[ # # ]
1442 [ # # ][ # # ]: 0 : PDHeight = StringToDouble( GetCommandLineToken( 1, aArea ) );
[ # # ]
1443 : 0 : PDWidth /= (double)nWidth;
1444 : 0 : PDHeight /= (double)nHeight;
1445 [ # # ][ # # ]: 0 : if( PDWidth >= 0.9 && PDWidth <= 1.1 &&
[ # # ][ # # ]
1446 : : PDHeight >= 0.9 && PDHeight <= 1.1 )
1447 : : {
1448 : : fNewSort =
1449 : 0 : (1.0-PDWidth)*(1.0-PDWidth) + (1.0-PDHeight)*(1.0-PDHeight);
1450 [ # # ]: 0 : if( fNewSort == 0.0 ) // perfect match
1451 [ # # ][ # # ]: 0 : return m_pPaperDimensions->getValue( i )->m_aOption;
1452 : :
1453 [ # # ]: 0 : if( fNewSort < fSort )
1454 : : {
1455 : 0 : fSort = fNewSort;
1456 : 0 : nPDim = i;
1457 : : }
1458 : : }
1459 [ # # ][ # # ]: 0 : }
1460 : :
1461 : : static bool bDontSwap = false;
1462 [ # # ][ # # ]: 0 : if( nPDim == -1 && ! bDontSwap )
1463 : : {
1464 : : // swap portrait/landscape and try again
1465 : 0 : bDontSwap = true;
1466 [ # # ]: 0 : String rRet = matchPaper( nHeight, nWidth );
1467 : 0 : bDontSwap = false;
1468 [ # # ][ # # ]: 0 : return rRet;
1469 : : }
1470 : :
1471 [ # # ]: 0 : return nPDim != -1 ? m_pPaperDimensions->getValue( nPDim )->m_aOption : String();
1472 : : }
1473 : :
1474 : 0 : String PPDParser::getDefaultInputSlot() const
1475 : : {
1476 [ # # ]: 0 : if( m_pDefaultInputSlot )
1477 : 0 : return m_pDefaultInputSlot->m_aValue;
1478 : 0 : return String();
1479 : : }
1480 : :
1481 : 333 : void PPDParser::getResolutionFromString(
1482 : : const String& rString,
1483 : : int& rXRes, int& rYRes ) const
1484 : : {
1485 : : int nDPIPos;
1486 : :
1487 : 333 : rXRes = rYRes = 300;
1488 : :
1489 : 333 : nDPIPos = rString.SearchAscii( "dpi" );
1490 [ + - ]: 333 : if( nDPIPos != STRING_NOTFOUND )
1491 : : {
1492 : 333 : int nPos = 0;
1493 [ - + ]: 333 : if( ( nPos = rString.Search( 'x' ) ) != STRING_NOTFOUND )
1494 : : {
1495 [ # # ]: 0 : rXRes = rString.Copy( 0, nPos ).ToInt32();
1496 [ # # ][ # # ]: 0 : rYRes = rString.GetToken( 1, 'x' ).Erase( nDPIPos - nPos - 1 ).ToInt32();
1497 : : }
1498 : : else
1499 [ + - ]: 333 : rXRes = rYRes = rString.Copy( 0, nDPIPos ).ToInt32();
1500 : : }
1501 : 333 : }
1502 : :
1503 : 0 : void PPDParser::getDefaultResolution( int& rXRes, int& rYRes ) const
1504 : : {
1505 [ # # ]: 0 : if( m_pDefaultResolution )
1506 : : {
1507 : 0 : getResolutionFromString( m_pDefaultResolution->m_aValue, rXRes, rYRes );
1508 : 0 : return;
1509 : : }
1510 : :
1511 : 0 : rXRes = 300;
1512 : 0 : rYRes = 300;
1513 : : }
1514 : :
1515 : 3990 : String PPDParser::getFont( int nFont ) const
1516 : : {
1517 [ - + ]: 3990 : if( ! m_pFontList )
1518 : 0 : return String();
1519 : :
1520 [ + - ][ + - ]: 3990 : if( nFont >=0 && nFont < m_pFontList->countValues() )
[ + - ]
1521 : 3990 : return m_pFontList->getValue( nFont )->m_aOption;
1522 : 3990 : return String();
1523 : : }
1524 : :
1525 : 0 : rtl::OUString PPDParser::translateKey( const rtl::OUString& i_rKey,
1526 : : const com::sun::star::lang::Locale& i_rLocale ) const
1527 : : {
1528 : 0 : rtl::OUString aResult( m_pTranslator->translateKey( i_rKey, i_rLocale ) );
1529 [ # # ]: 0 : if( aResult.isEmpty() )
1530 : 0 : aResult = i_rKey;
1531 : 0 : return aResult;
1532 : : }
1533 : :
1534 : 0 : rtl::OUString PPDParser::translateOption( const rtl::OUString& i_rKey,
1535 : : const rtl::OUString& i_rOption,
1536 : : const com::sun::star::lang::Locale& i_rLocale ) const
1537 : : {
1538 : 0 : rtl::OUString aResult( m_pTranslator->translateOption( i_rKey, i_rOption, i_rLocale ) );
1539 [ # # ]: 0 : if( aResult.isEmpty() )
1540 : 0 : aResult = i_rOption;
1541 : 0 : return aResult;
1542 : : }
1543 : :
1544 : : /*
1545 : : * PPDKey
1546 : : */
1547 : :
1548 : 2700 : PPDKey::PPDKey( const String& rKey ) :
1549 : : m_aKey( rKey ),
1550 : : m_pDefaultValue( NULL ),
1551 : : m_bQueryValue( false ),
1552 : : m_bUIOption( false ),
1553 : : m_eUIType( PickOne ),
1554 : : m_nOrderDependency( 100 ),
1555 [ + - ][ + - ]: 2700 : m_eSetupType( AnySetup )
[ + - ]
1556 : : {
1557 : 2700 : }
1558 : :
1559 : : // -------------------------------------------------------------------
1560 : :
1561 [ + - ][ + - ]: 2700 : PPDKey::~PPDKey()
1562 : : {
1563 : 2700 : }
1564 : :
1565 : : // -------------------------------------------------------------------
1566 : :
1567 : 19707 : const PPDValue* PPDKey::getValue( int n ) const
1568 : : {
1569 [ + - ][ + - ]: 19707 : return ((unsigned int)n < m_aOrderedValues.size() && n >= 0) ? m_aOrderedValues[n] : NULL;
1570 : : }
1571 : :
1572 : : // -------------------------------------------------------------------
1573 : :
1574 : 895 : const PPDValue* PPDKey::getValue( const String& rOption ) const
1575 : : {
1576 [ + - ][ + - ]: 895 : PPDKey::hash_type::const_iterator it = m_aValues.find( rOption );
1577 [ + - ][ + - ]: 895 : return it != m_aValues.end() ? &it->second : NULL;
[ + - ]
1578 : : }
1579 : :
1580 : : // -------------------------------------------------------------------
1581 : :
1582 : 3 : const PPDValue* PPDKey::getValueCaseInsensitive( const String& rOption ) const
1583 : : {
1584 : 3 : const PPDValue* pValue = getValue( rOption );
1585 [ - + ]: 3 : if( ! pValue )
1586 : : {
1587 [ # # ][ # # ]: 0 : for( size_t n = 0; n < m_aOrderedValues.size() && ! pValue; n++ )
[ # # ]
1588 [ # # ]: 0 : if( m_aOrderedValues[n]->m_aOption.EqualsIgnoreCaseAscii( rOption ) )
1589 : 0 : pValue = m_aOrderedValues[n];
1590 : : }
1591 : :
1592 : 3 : return pValue;
1593 : : }
1594 : :
1595 : : // -------------------------------------------------------------------
1596 : :
1597 : 180 : void PPDKey::eraseValue( const String& rOption )
1598 : : {
1599 [ + - ][ + - ]: 180 : PPDKey::hash_type::iterator it = m_aValues.find( rOption );
1600 [ + - ][ + - ]: 180 : if( it == m_aValues.end() )
1601 : 180 : return;
1602 : :
1603 [ + - ][ + - ]: 2100 : for( PPDKey::value_type::iterator vit = m_aOrderedValues.begin(); vit != m_aOrderedValues.end(); ++vit )
[ + - ]
1604 : : {
1605 [ + - ][ + - ]: 2100 : if( *vit == &(it->second ) )
[ + + ]
1606 : : {
1607 [ + - ]: 180 : m_aOrderedValues.erase( vit );
1608 : 180 : break;
1609 : : }
1610 : : }
1611 [ + - ]: 180 : m_aValues.erase( it );
1612 : : }
1613 : :
1614 : : // -------------------------------------------------------------------
1615 : :
1616 : 20760 : PPDValue* PPDKey::insertValue( const String& rOption )
1617 : : {
1618 [ + - ][ + - ]: 20760 : if( m_aValues.find( rOption ) != m_aValues.end() )
[ + - ][ + + ]
1619 : 1800 : return NULL;
1620 : :
1621 [ + - ]: 18960 : PPDValue aValue;
1622 [ + - ]: 18960 : aValue.m_aOption = rOption;
1623 [ + - ][ + - ]: 18960 : m_aValues[ rOption ] = aValue;
[ + - ]
1624 [ + - ][ + - ]: 18960 : PPDValue* pValue = &m_aValues[rOption];
1625 [ + - ]: 18960 : m_aOrderedValues.push_back( pValue );
1626 [ + - ]: 20760 : return pValue;
1627 : : }
1628 : :
1629 : : // -------------------------------------------------------------------
1630 : :
1631 : : /*
1632 : : * PPDContext
1633 : : */
1634 : :
1635 : 681 : PPDContext::PPDContext( const PPDParser* pParser ) :
1636 [ + - ]: 681 : m_pParser( pParser )
1637 : : {
1638 : 681 : }
1639 : :
1640 : : // -------------------------------------------------------------------
1641 : :
1642 : 477 : PPDContext& PPDContext::operator=( const PPDContext& rCopy )
1643 : : {
1644 : 477 : m_pParser = rCopy.m_pParser;
1645 : 477 : m_aCurrentValues = rCopy.m_aCurrentValues;
1646 : 477 : return *this;
1647 : : }
1648 : :
1649 : : // -------------------------------------------------------------------
1650 : :
1651 : 539 : PPDContext::~PPDContext()
1652 : : {
1653 : 539 : }
1654 : :
1655 : : // -------------------------------------------------------------------
1656 : :
1657 : 144 : const PPDKey* PPDContext::getModifiedKey( int n ) const
1658 : : {
1659 : 144 : hash_type::const_iterator it;
1660 [ + - ][ - + ]: 144 : for( it = m_aCurrentValues.begin(); it != m_aCurrentValues.end() && n--; ++it )
[ + - ][ - + ]
[ + - ]
1661 : : ;
1662 [ + - ][ + - ]: 144 : return it != m_aCurrentValues.end() ? it->first : NULL;
1663 : : }
1664 : :
1665 : : // -------------------------------------------------------------------
1666 : :
1667 : 299 : void PPDContext::setParser( const PPDParser* pParser )
1668 : : {
1669 [ + + ]: 299 : if( pParser != m_pParser )
1670 : : {
1671 : 187 : m_aCurrentValues.clear();
1672 : 187 : m_pParser = pParser;
1673 : : }
1674 : 299 : }
1675 : :
1676 : : // -------------------------------------------------------------------
1677 : :
1678 : 741 : const PPDValue* PPDContext::getValue( const PPDKey* pKey ) const
1679 : : {
1680 [ - + ]: 741 : if( ! m_pParser )
1681 : 0 : return NULL;
1682 : :
1683 : 741 : hash_type::const_iterator it;
1684 [ + - ]: 741 : it = m_aCurrentValues.find( pKey );
1685 [ + + ]: 741 : if( it != m_aCurrentValues.end() )
1686 [ + - ]: 299 : return it->second;
1687 : :
1688 [ + - ][ - + ]: 442 : if( ! m_pParser->hasKey( pKey ) )
1689 : 0 : return NULL;
1690 : :
1691 : 442 : const PPDValue* pValue = pKey->getDefaultValue();
1692 [ + + ]: 442 : if( ! pValue )
1693 [ + - ]: 333 : pValue = pKey->getValue( 0 );
1694 : :
1695 : 741 : return pValue;
1696 : : }
1697 : :
1698 : : // -------------------------------------------------------------------
1699 : :
1700 : 150 : const PPDValue* PPDContext::setValue( const PPDKey* pKey, const PPDValue* pValue, bool bDontCareForConstraints )
1701 : : {
1702 [ + - ][ - + ]: 150 : if( ! m_pParser || ! pKey )
1703 : 0 : return NULL;
1704 : :
1705 : : // pValue can be NULL - it means ignore this option
1706 : :
1707 [ - + ]: 150 : if( ! m_pParser->hasKey( pKey ) )
1708 : 0 : return NULL;
1709 : :
1710 : : // check constraints
1711 [ + - ]: 150 : if( pValue )
1712 : : {
1713 [ - + ]: 150 : if( bDontCareForConstraints )
1714 : : {
1715 : 0 : m_aCurrentValues[ pKey ] = pValue;
1716 : : }
1717 [ + - ]: 150 : else if( checkConstraints( pKey, pValue, true ) )
1718 : : {
1719 [ + - ]: 150 : m_aCurrentValues[ pKey ] = pValue;
1720 : :
1721 : : // after setting this value, check all constraints !
1722 [ + - ]: 150 : hash_type::iterator it = m_aCurrentValues.begin();
1723 [ + - ][ + + ]: 306 : while( it != m_aCurrentValues.end() )
1724 : : {
1725 [ + - ][ + + ]: 162 : if( it->first != pKey &&
[ - + ][ - + ]
1726 [ + - ][ + - ]: 6 : ! checkConstraints( it->first, it->second, false ) )
[ + - ]
1727 : : {
1728 : : #ifdef __DEBUG
1729 : : fprintf( stderr, "PPDContext::setValue: option %s (%s) is constrained after setting %s to %s\n",
1730 : : it->first->getKey().GetStr(),
1731 : : it->second->m_aOption.GetStr(),
1732 : : pKey->getKey().GetStr(),
1733 : : pValue->m_aOption.GetStr() );
1734 : : #endif
1735 [ # # ][ # # ]: 0 : resetValue( it->first, true );
1736 [ # # ]: 0 : it = m_aCurrentValues.begin();
1737 : : }
1738 : : else
1739 : 156 : ++it;
1740 : : }
1741 : : }
1742 : : }
1743 : : else
1744 : 0 : m_aCurrentValues[ pKey ] = NULL;
1745 : :
1746 : 150 : return pValue;
1747 : : }
1748 : :
1749 : : // -------------------------------------------------------------------
1750 : :
1751 : 0 : bool PPDContext::checkConstraints( const PPDKey* pKey, const PPDValue* pValue )
1752 : : {
1753 [ # # ][ # # ]: 0 : if( ! m_pParser || ! pKey || ! pValue )
[ # # ]
1754 : 0 : return false;
1755 : :
1756 : : // ensure that this key is already in the list if it exists at all
1757 [ # # ][ # # ]: 0 : if( m_aCurrentValues.find( pKey ) != m_aCurrentValues.end() )
1758 : 0 : return checkConstraints( pKey, pValue, false );
1759 : :
1760 : : // it is not in the list, insert it temporarily
1761 : 0 : bool bRet = false;
1762 [ # # ]: 0 : if( m_pParser->hasKey( pKey ) )
1763 : : {
1764 : 0 : const PPDValue* pDefValue = pKey->getDefaultValue();
1765 : 0 : m_aCurrentValues[ pKey ] = pDefValue;
1766 : 0 : bRet = checkConstraints( pKey, pValue, false );
1767 : 0 : m_aCurrentValues.erase( pKey );
1768 : : }
1769 : :
1770 : 0 : return bRet;
1771 : : }
1772 : :
1773 : : // -------------------------------------------------------------------
1774 : :
1775 : 0 : bool PPDContext::resetValue( const PPDKey* pKey, bool bDefaultable )
1776 : : {
1777 [ # # ][ # # ]: 0 : if( ! pKey || ! m_pParser || ! m_pParser->hasKey( pKey ) )
[ # # ][ # # ]
1778 : 0 : return false;
1779 : :
1780 [ # # ]: 0 : const PPDValue* pResetValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
1781 [ # # ]: 0 : if( ! pResetValue )
1782 [ # # ]: 0 : pResetValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "False" ) ) );
1783 [ # # ][ # # ]: 0 : if( ! pResetValue && bDefaultable )
1784 : 0 : pResetValue = pKey->getDefaultValue();
1785 : :
1786 [ # # ][ # # ]: 0 : bool bRet = pResetValue ? ( setValue( pKey, pResetValue ) == pResetValue ? true : false ) : false;
1787 : :
1788 : 0 : return bRet;
1789 : : }
1790 : :
1791 : : // -------------------------------------------------------------------
1792 : :
1793 : 156 : bool PPDContext::checkConstraints( const PPDKey* pKey, const PPDValue* pNewValue, bool bDoReset )
1794 : : {
1795 [ - + ]: 156 : if( ! pNewValue )
1796 : 0 : return true;
1797 : :
1798 : : // sanity checks
1799 [ - + ]: 156 : if( ! m_pParser )
1800 : 0 : return false;
1801 : :
1802 [ - + ]: 156 : if( pKey->getValue( pNewValue->m_aOption ) != pNewValue )
1803 : 0 : return false;
1804 : :
1805 : : // None / False and the default can always be set, but be careful !
1806 : : // setting them might influence constrained values
1807 [ + + ]: 306 : if( pNewValue->m_aOption.EqualsAscii( "None" ) || pNewValue->m_aOption.EqualsAscii( "False" ) ||
[ + - + + ]
[ + + ]
1808 : 150 : pNewValue == pKey->getDefaultValue() )
1809 : 12 : return true;
1810 : :
1811 : 144 : const ::std::list< PPDParser::PPDConstraint >& rConstraints( m_pParser->getConstraints() );
1812 [ # # ][ + - ]: 144 : for( ::std::list< PPDParser::PPDConstraint >::const_iterator it = rConstraints.begin(); it != rConstraints.end(); ++it )
[ - + ]
1813 : : {
1814 [ # # ]: 0 : const PPDKey* pLeft = it->m_pKey1;
1815 [ # # ]: 0 : const PPDKey* pRight = it->m_pKey2;
1816 [ # # ][ # # ]: 0 : if( ! pLeft || ! pRight || ( pKey != pLeft && pKey != pRight ) )
[ # # ][ # # ]
1817 : 0 : continue;
1818 : :
1819 [ # # ]: 0 : const PPDKey* pOtherKey = pKey == pLeft ? pRight : pLeft;
1820 [ # # ][ # # ]: 0 : const PPDValue* pOtherKeyOption = pKey == pLeft ? it->m_pOption2 : it->m_pOption1;
[ # # ]
1821 [ # # ][ # # ]: 0 : const PPDValue* pKeyOption = pKey == pLeft ? it->m_pOption1 : it->m_pOption2;
[ # # ]
1822 : :
1823 : : // syntax *Key1 option1 *Key2 option2
1824 [ # # ][ # # ]: 0 : if( pKeyOption && pOtherKeyOption )
1825 : : {
1826 [ # # ]: 0 : if( pNewValue != pKeyOption )
1827 : 0 : continue;
1828 [ # # ][ # # ]: 0 : if( pOtherKeyOption == getValue( pOtherKey ) )
1829 : : {
1830 : 0 : return false;
1831 : : }
1832 : : }
1833 : : // syntax *Key1 option *Key2 or *Key1 *Key2 option
1834 [ # # ][ # # ]: 0 : else if( pOtherKeyOption || pKeyOption )
1835 : : {
1836 [ # # ]: 0 : if( pKeyOption )
1837 : : {
1838 [ # # ][ # # ]: 0 : if( ! ( pOtherKeyOption = getValue( pOtherKey ) ) )
1839 : 0 : continue; // this should not happen, PPD broken
1840 : :
1841 [ # # ][ # # ]: 0 : if( pKeyOption == pNewValue &&
[ # # ][ # # ]
1842 [ # # ]: 0 : ! pOtherKeyOption->m_aOption.EqualsAscii( "None" ) &&
1843 [ # # ]: 0 : ! pOtherKeyOption->m_aOption.EqualsAscii( "False" ) )
1844 : : {
1845 : : // check if the other value can be reset and
1846 : : // do so if possible
1847 [ # # ][ # # ]: 0 : if( bDoReset && resetValue( pOtherKey ) )
[ # # ][ # # ]
1848 : 0 : continue;
1849 : :
1850 : 0 : return false;
1851 : : }
1852 : : }
1853 [ # # ]: 0 : else if( pOtherKeyOption )
1854 : : {
1855 [ # # ][ # # ]: 0 : if( getValue( pOtherKey ) == pOtherKeyOption &&
[ # # ][ # # ]
[ # # ]
1856 [ # # ]: 0 : ! pNewValue->m_aOption.EqualsAscii( "None" ) &&
1857 [ # # ]: 0 : ! pNewValue->m_aOption.EqualsAscii( "False" ) )
1858 : 0 : return false;
1859 : : }
1860 : : else
1861 : : {
1862 : : // this should not happen, PPD is broken
1863 : : }
1864 : : }
1865 : : // syntax *Key1 *Key2
1866 : : else
1867 : : {
1868 [ # # ]: 0 : const PPDValue* pOtherValue = getValue( pOtherKey );
1869 [ # # ][ # # ]: 0 : if( ! pOtherValue->m_aOption.EqualsAscii( "None" ) &&
[ # # ][ # # ]
[ # # ][ # # ]
1870 [ # # ]: 0 : ! pOtherValue->m_aOption.EqualsAscii( "False" ) &&
1871 [ # # ]: 0 : ! pNewValue->m_aOption.EqualsAscii( "None" ) &&
1872 [ # # ]: 0 : ! pNewValue->m_aOption.EqualsAscii( "False" ) )
1873 : 0 : return false;
1874 : : }
1875 : : }
1876 : 156 : return true;
1877 : : }
1878 : :
1879 : : // -------------------------------------------------------------------
1880 : :
1881 : 112 : char* PPDContext::getStreamableBuffer( sal_uLong& rBytes ) const
1882 : : {
1883 : 112 : rBytes = 0;
1884 [ - + ]: 112 : if( ! m_aCurrentValues.size() )
1885 : 0 : return NULL;
1886 : 112 : hash_type::const_iterator it;
1887 [ + + ][ + - ]: 227 : for( it = m_aCurrentValues.begin(); it != m_aCurrentValues.end(); ++it )
1888 : : {
1889 [ + - ][ + - ]: 115 : rtl::OString aCopy(rtl::OUStringToOString(it->first->getKey(), RTL_TEXTENCODING_MS_1252));
[ + - ]
1890 : 115 : rBytes += aCopy.getLength();
1891 : 115 : rBytes += 1; // for ':'
1892 [ + - ][ + - ]: 115 : if( it->second )
1893 : : {
1894 [ + - ][ + - ]: 115 : aCopy = rtl::OUStringToOString(it->second->m_aOption, RTL_TEXTENCODING_MS_1252);
[ + - ]
1895 : 115 : rBytes += aCopy.getLength();
1896 : : }
1897 : : else
1898 : 0 : rBytes += 4;
1899 : 115 : rBytes += 1; // for '\0'
1900 : 115 : }
1901 : 112 : rBytes += 1;
1902 [ + - ]: 112 : char* pBuffer = new char[ rBytes ];
1903 : 112 : memset( pBuffer, 0, rBytes );
1904 : 112 : char* pRun = pBuffer;
1905 [ + - ][ + + ]: 227 : for( it = m_aCurrentValues.begin(); it != m_aCurrentValues.end(); ++it )
1906 : : {
1907 [ + - ][ + - ]: 115 : rtl::OString aCopy(rtl::OUStringToOString(it->first->getKey(), RTL_TEXTENCODING_MS_1252));
[ + - ]
1908 : 115 : int nBytes = aCopy.getLength();
1909 : 115 : memcpy( pRun, aCopy.getStr(), nBytes );
1910 : 115 : pRun += nBytes;
1911 : 115 : *pRun++ = ':';
1912 [ + - ][ + - ]: 115 : if( it->second )
1913 [ + - ][ + - ]: 115 : aCopy = rtl::OUStringToOString(it->second->m_aOption, RTL_TEXTENCODING_MS_1252);
[ + - ]
1914 : : else
1915 : 0 : aCopy = "*nil";
1916 : 115 : nBytes = aCopy.getLength();
1917 : 115 : memcpy( pRun, aCopy.getStr(), nBytes );
1918 : 115 : pRun += nBytes;
1919 : :
1920 : 115 : *pRun++ = 0;
1921 : 115 : }
1922 : 112 : return pBuffer;
1923 : : }
1924 : :
1925 : : // -------------------------------------------------------------------
1926 : :
1927 : 115 : void PPDContext::rebuildFromStreamBuffer( char* pBuffer, sal_uLong nBytes )
1928 : : {
1929 [ + - ]: 115 : if( ! m_pParser )
1930 : 115 : return;
1931 : :
1932 [ + - ]: 115 : m_aCurrentValues.clear();
1933 : :
1934 : 115 : char* pRun = pBuffer;
1935 [ + - ][ + + ]: 236 : while( nBytes && *pRun )
[ + + ]
1936 : : {
1937 : 121 : rtl::OString aLine( pRun );
1938 : 121 : sal_Int32 nPos = aLine.indexOf(':');
1939 [ + - ]: 121 : if( nPos != -1 )
1940 : : {
1941 [ + - ][ + - ]: 121 : const PPDKey* pKey = m_pParser->getKey( rtl::OStringToOUString( aLine.copy( 0, nPos ), RTL_TEXTENCODING_MS_1252 ) );
[ + - ][ + - ]
1942 [ + - ]: 121 : if( pKey )
1943 : : {
1944 : 121 : const PPDValue* pValue = NULL;
1945 [ + - ]: 121 : rtl::OUString aOption(rtl::OStringToOUString(aLine.copy(nPos+1), RTL_TEXTENCODING_MS_1252));
1946 [ + - ]: 121 : if (aOption != "*nil")
1947 [ + - ][ + - ]: 121 : pValue = pKey->getValue( aOption );
[ + - ]
1948 [ + - ]: 121 : m_aCurrentValues[ pKey ] = pValue;
1949 : : #ifdef __DEBUG
1950 : : fprintf( stderr, "PPDContext::rebuildFromStreamBuffer: read PPDKeyValue { %s, %s }\n", pKV->m_pKey->getKey().GetStr(), pKV->m_pCurrentValue ? pKV->m_pCurrentValue->m_aOption.GetStr() : "<nil>" );
1951 : : #endif
1952 : : }
1953 : : }
1954 : 121 : nBytes -= aLine.getLength()+1;
1955 : 121 : pRun += aLine.getLength()+1;
1956 : 121 : }
1957 : : }
1958 : :
1959 : : // -------------------------------------------------------------------
1960 : :
1961 : 333 : int PPDContext::getRenderResolution() const
1962 : : {
1963 : : // initialize to reasonable default, if parser is not set
1964 : 333 : int nDPI = 300;
1965 [ + - ]: 333 : if( m_pParser )
1966 : : {
1967 : 333 : int nDPIx = 300, nDPIy = 300;
1968 [ + - ][ + - ]: 333 : const PPDKey* pKey = m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ) );
[ + - ]
1969 [ + - ]: 333 : if( pKey )
1970 : : {
1971 [ + - ]: 333 : const PPDValue* pValue = getValue( pKey );
1972 [ + - ]: 333 : if( pValue )
1973 [ + - ]: 333 : m_pParser->getResolutionFromString( pValue->m_aOption, nDPIx, nDPIy );
1974 : : else
1975 [ # # ]: 0 : m_pParser->getDefaultResolution( nDPIx, nDPIy );
1976 : : }
1977 : : else
1978 [ # # ]: 0 : m_pParser->getDefaultResolution( nDPIx, nDPIy );
1979 : :
1980 [ - + ]: 333 : nDPI = (nDPIx > nDPIy) ? nDPIx : nDPIy;
1981 : : }
1982 : 333 : return nDPI;
1983 : : }
1984 : :
1985 : : // -------------------------------------------------------------------
1986 : :
1987 : 224 : void PPDContext::getPageSize( rtl::OUString& rPaper, int& rWidth, int& rHeight ) const
1988 : : {
1989 : : // initialize to reasonable default, if parser is not set
1990 : 224 : rPaper = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A4" ) );
1991 : 224 : rWidth = 595;
1992 : 224 : rHeight = 842;
1993 [ + - ]: 224 : if( m_pParser )
1994 : : {
1995 [ + - ]: 224 : const PPDKey* pKey = m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
1996 [ + - ]: 224 : if( pKey )
1997 : : {
1998 : 224 : const PPDValue* pValue = getValue( pKey );
1999 [ + - ]: 224 : if( pValue )
2000 : : {
2001 : 224 : rPaper = pValue->m_aOption;
2002 [ + - ]: 224 : m_pParser->getPaperDimension( rPaper, rWidth, rHeight );
2003 : : }
2004 : : else
2005 : : {
2006 [ # # ]: 0 : rPaper = m_pParser->getDefaultPaperDimension();
2007 : 0 : m_pParser->getDefaultPaperDimension( rWidth, rHeight );
2008 : : }
2009 : : }
2010 : : }
2011 : 224 : }
2012 : :
2013 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|