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