LCOV - code coverage report
Current view: top level - libreoffice/vcl/unx/generic/printer - ppdparser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 131 996 13.2 %
Date: 2012-12-27 Functions: 16 72 22.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10