summaryrefslogtreecommitdiff
path: root/vcl/unx/source/printer
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/source/printer')
-rw-r--r--vcl/unx/source/printer/cupsmgr.cxx4
-rw-r--r--vcl/unx/source/printer/ppdparser.cxx440
-rw-r--r--vcl/unx/source/printer/printerinfomanager.cxx1
3 files changed, 368 insertions, 77 deletions
diff --git a/vcl/unx/source/printer/cupsmgr.cxx b/vcl/unx/source/printer/cupsmgr.cxx
index d0c7f184fb06..4c38479f1107 100644
--- a/vcl/unx/source/printer/cupsmgr.cxx
+++ b/vcl/unx/source/printer/cupsmgr.cxx
@@ -533,6 +533,10 @@ void CUPSManager::initialize()
pDest->options );
if( pOpt )
m_bUseIncludeFeature = true;
+ // do not send include JobPatch; CUPS will insert that itself
+ // TODO: currently unknwon which versions of CUPS insert JobPatches
+ // so currently it is assumed CUPS = don't insert JobPatch files
+ m_bUseJobPatch = false;
rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
int nPrinter = m_nDests;
diff --git a/vcl/unx/source/printer/ppdparser.cxx b/vcl/unx/source/printer/ppdparser.cxx
index 95bc7bca41ca..a70a5ac7f6c8 100644
--- a/vcl/unx/source/printer/ppdparser.cxx
+++ b/vcl/unx/source/printer/ppdparser.cxx
@@ -39,6 +39,7 @@
#include "vcl/ppdparser.hxx"
#include "vcl/strhelper.hxx"
#include "vcl/helper.hxx"
+#include "vcl/svapp.hxx"
#include "cupsmgr.hxx"
#include "tools/debug.hxx"
#include "tools/urlobj.hxx"
@@ -51,6 +52,202 @@
#include "rtl/strbuf.hxx"
#include "rtl/ustrbuf.hxx"
+#include "com/sun/star/lang/Locale.hpp"
+
+namespace psp
+{
+ class PPDTranslator
+ {
+ struct LocaleEqual
+ {
+ bool operator()(const com::sun::star::lang::Locale& i_rLeft,
+ const com::sun::star::lang::Locale& i_rRight) const
+ {
+ return i_rLeft.Language.equals( i_rRight.Language ) &&
+ i_rLeft.Country.equals( i_rRight.Country ) &&
+ i_rLeft.Variant.equals( i_rRight.Variant );
+ }
+ };
+
+ struct LocaleHash
+ {
+ size_t operator()(const com::sun::star::lang::Locale& rLocale) const
+ { return
+ (size_t)rLocale.Language.hashCode()
+ ^ (size_t)rLocale.Country.hashCode()
+ ^ (size_t)rLocale.Variant.hashCode()
+ ;
+ }
+ };
+
+ typedef std::hash_map< com::sun::star::lang::Locale, rtl::OUString, LocaleHash, LocaleEqual > translation_map;
+ typedef std::hash_map< rtl::OUString, translation_map, rtl::OUStringHash > key_translation_map;
+
+ key_translation_map m_aTranslations;
+ public:
+ PPDTranslator() {}
+ ~PPDTranslator() {}
+
+
+ void insertValue(
+ const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rValue,
+ const rtl::OUString& i_rTranslation,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale()
+ );
+
+ void insertOption( const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rTranslation,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() )
+ {
+ insertValue( i_rKey, i_rOption, rtl::OUString(), i_rTranslation, i_rLocale );
+ }
+
+ void insertKey( const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rTranslation,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() )
+ {
+ insertValue( i_rKey, rtl::OUString(), rtl::OUString(), i_rTranslation, i_rLocale );
+ }
+
+ rtl::OUString translateValue(
+ const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rValue,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale()
+ ) const;
+
+ rtl::OUString translateOption( const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() ) const
+ {
+ return translateValue( i_rKey, i_rOption, rtl::OUString(), i_rLocale );
+ }
+
+ rtl::OUString translateKey( const rtl::OUString& i_rKey,
+ const com::sun::star::lang::Locale& i_rLocale = com::sun::star::lang::Locale() ) const
+ {
+ return translateValue( i_rKey, rtl::OUString(), rtl::OUString(), i_rLocale );
+ }
+ };
+
+ static com::sun::star::lang::Locale normalizeInputLocale(
+ const com::sun::star::lang::Locale& i_rLocale,
+ bool bInsertDefault = false
+ )
+ {
+ com::sun::star::lang::Locale aLoc( i_rLocale );
+ if( bInsertDefault && aLoc.Language.getLength() == 0 )
+ {
+ // empty locale requested, fill in application UI locale
+ aLoc = Application::GetSettings().GetUILocale();
+
+ #if OSL_DEBUG_LEVEL > 1
+ static const char* pEnvLocale = getenv( "SAL_PPDPARSER_LOCALE" );
+ if( pEnvLocale && *pEnvLocale )
+ {
+ rtl::OString aStr( pEnvLocale );
+ sal_Int32 nLen = aStr.getLength();
+ aLoc.Language = rtl::OStringToOUString( aStr.copy( 0, nLen > 2 ? 2 : nLen ), RTL_TEXTENCODING_MS_1252 );
+ if( nLen >=5 && aStr.getStr()[2] == '_' )
+ aLoc.Country = rtl::OStringToOUString( aStr.copy( 3, 2 ), RTL_TEXTENCODING_MS_1252 );
+ else
+ aLoc.Country = rtl::OUString();
+ aLoc.Variant = rtl::OUString();
+ }
+ #endif
+ }
+ aLoc.Language = aLoc.Language.toAsciiLowerCase();
+ aLoc.Country = aLoc.Country.toAsciiUpperCase();
+ aLoc.Variant = aLoc.Variant.toAsciiUpperCase();
+
+ return aLoc;
+ }
+
+ void PPDTranslator::insertValue(
+ const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rValue,
+ const rtl::OUString& i_rTranslation,
+ const com::sun::star::lang::Locale& i_rLocale
+ )
+ {
+ rtl::OUStringBuffer aKey( i_rKey.getLength() + i_rOption.getLength() + i_rValue.getLength() + 2 );
+ aKey.append( i_rKey );
+ if( i_rOption.getLength() || i_rValue.getLength() )
+ {
+ aKey.append( sal_Unicode( ':' ) );
+ aKey.append( i_rOption );
+ }
+ if( i_rValue.getLength() )
+ {
+ aKey.append( sal_Unicode( ':' ) );
+ aKey.append( i_rValue );
+ }
+ if( aKey.getLength() && i_rTranslation.getLength() )
+ {
+ rtl::OUString aK( aKey.makeStringAndClear() );
+ com::sun::star::lang::Locale aLoc;
+ aLoc.Language = i_rLocale.Language.toAsciiLowerCase();
+ aLoc.Country = i_rLocale.Country.toAsciiUpperCase();
+ aLoc.Variant = i_rLocale.Variant.toAsciiUpperCase();
+ m_aTranslations[ aK ][ aLoc ] = i_rTranslation;
+ }
+ }
+
+ rtl::OUString PPDTranslator::translateValue(
+ const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rValue,
+ const com::sun::star::lang::Locale& i_rLocale
+ ) const
+ {
+ rtl::OUString aResult;
+
+ rtl::OUStringBuffer aKey( i_rKey.getLength() + i_rOption.getLength() + i_rValue.getLength() + 2 );
+ aKey.append( i_rKey );
+ if( i_rOption.getLength() || i_rValue.getLength() )
+ {
+ aKey.append( sal_Unicode( ':' ) );
+ aKey.append( i_rOption );
+ }
+ if( i_rValue.getLength() )
+ {
+ aKey.append( sal_Unicode( ':' ) );
+ aKey.append( i_rValue );
+ }
+ if( aKey.getLength() )
+ {
+ rtl::OUString aK( aKey.makeStringAndClear() );
+ key_translation_map::const_iterator it = m_aTranslations.find( aK );
+ if( it != m_aTranslations.end() )
+ {
+ const translation_map& rMap( it->second );
+
+ com::sun::star::lang::Locale aLoc( normalizeInputLocale( i_rLocale, true ) );
+ for( int nTry = 0; nTry < 4; nTry++ )
+ {
+ translation_map::const_iterator tr = rMap.find( aLoc );
+ if( tr != rMap.end() )
+ {
+ aResult = tr->second;
+ break;
+ }
+ switch( nTry )
+ {
+ case 0: aLoc.Variant = rtl::OUString();break;
+ case 1: aLoc.Country = rtl::OUString();break;
+ case 2: aLoc.Language = rtl::OUString();break;
+ }
+ }
+ }
+ }
+ return aResult;
+ }
+}
+
using namespace psp;
using namespace rtl;
@@ -481,7 +678,8 @@ PPDParser::PPDParser( const String& rFile ) :
m_pResolutions( NULL ),
m_pDefaultDuplexType( NULL ),
m_pDuplexTypes( NULL ),
- m_pFontList( NULL )
+ m_pFontList( NULL ),
+ m_pTranslator( new PPDTranslator() )
{
// read in the file
std::list< ByteString > aLines;
@@ -648,6 +846,7 @@ PPDParser::~PPDParser()
{
for( PPDParser::hash_type::iterator it = m_aKeys.begin(); it != m_aKeys.end(); ++it )
delete it->second;
+ delete m_pTranslator;
}
void PPDParser::insertKey( const String& rKey, PPDKey* pKey )
@@ -687,11 +886,11 @@ static sal_uInt8 getNibble( sal_Char cChar )
return nRet;
}
-String PPDParser::handleTranslation( const ByteString& rString )
+String PPDParser::handleTranslation( const ByteString& i_rString, bool bIsGlobalized )
{
- int nOrigLen = rString.Len();
+ int nOrigLen = i_rString.Len();
OStringBuffer aTrans( nOrigLen );
- const sal_Char* pStr = rString.GetBuffer();
+ const sal_Char* pStr = i_rString.GetBuffer();
const sal_Char* pEnd = pStr + nOrigLen;
while( pStr < pEnd )
{
@@ -710,14 +909,11 @@ String PPDParser::handleTranslation( const ByteString& rString )
else
aTrans.append( *pStr++ );
}
- return OStringToOUString( aTrans.makeStringAndClear(), m_aFileEncoding );
+ return OStringToOUString( aTrans.makeStringAndClear(), bIsGlobalized ? RTL_TEXTENCODING_UTF8 : m_aFileEncoding );
}
void PPDParser::parse( ::std::list< ByteString >& rLines )
{
- PPDValue* pValue = NULL;
- PPDKey* pKey = NULL;
-
std::list< ByteString >::iterator line = rLines.begin();
PPDParser::hash_type::const_iterator keyit;
while( line != rLines.end() )
@@ -765,14 +961,25 @@ void PPDParser::parse( ::std::list< ByteString >& rLines )
}
String aUniKey( aKey, RTL_TEXTENCODING_MS_1252 );
- keyit = m_aKeys.find( aUniKey );
- if( keyit == m_aKeys.end() )
+ // handle CUPS extension for globalized PPDs
+ bool bIsGlobalizedLine = false;
+ com::sun::star::lang::Locale aTransLocale;
+ if( ( aUniKey.Len() > 3 && aUniKey.GetChar( 2 ) == '.' ) ||
+ ( aUniKey.Len() > 5 && aUniKey.GetChar( 2 ) == '_' && aUniKey.GetChar( 5 ) == '.' ) )
{
- pKey = new PPDKey( aUniKey );
- insertKey( aUniKey, pKey );
+ if( aUniKey.GetChar( 2 ) == '.' )
+ {
+ aTransLocale.Language = aUniKey.Copy( 0, 2 );
+ aUniKey = aUniKey.Copy( 3 );
+ }
+ else
+ {
+ aTransLocale.Language = aUniKey.Copy( 0, 2 );
+ aTransLocale.Country = aUniKey.Copy( 3, 2 );
+ aUniKey = aUniKey.Copy( 6 );
+ }
+ bIsGlobalizedLine = true;
}
- else
- pKey = keyit->second;
String aOption;
nPos = aCurrentLine.Search( ':' );
@@ -784,76 +991,125 @@ void PPDParser::parse( ::std::list< ByteString >& rLines )
if( nTransPos != STRING_NOTFOUND )
aOption.Erase( nTransPos );
}
- pValue = pKey->insertValue( aOption );
- if( ! pValue )
- continue;
- if( nPos == STRING_NOTFOUND )
+ PPDValueType eType = eNo;
+ String aValue;
+ rtl::OUString aOptionTranslation;
+ rtl::OUString aValueTranslation;
+ if( nPos != STRING_NOTFOUND )
{
- // have a single main keyword
- pValue->m_eType = eNo;
- if( bQuery )
- pKey->eraseValue( aOption );
- continue;
- }
+ // found a colon, there may be an option
+ ByteString aLine = aCurrentLine.Copy( 1, nPos-1 );
+ aLine = WhitespaceToSpace( aLine );
+ int nTransPos = aLine.Search( '/' );
+ if( nTransPos != STRING_NOTFOUND )
+ aOptionTranslation = handleTranslation( aLine.Copy( nTransPos+1 ), bIsGlobalizedLine );
- // found a colon, there may be an option
- ByteString aLine = aCurrentLine.Copy( 1, nPos-1 );
- aLine = WhitespaceToSpace( aLine );
- int nTransPos = aLine.Search( '/' );
- if( nTransPos != STRING_NOTFOUND )
- pValue->m_aOptionTranslation = handleTranslation( aLine.Copy( nTransPos+1 ) );
-
- // read in more lines if necessary for multiline values
- aLine = aCurrentLine.Copy( nPos+1 );
- while( ! ( aLine.GetTokenCount( '"' ) & 1 ) &&
- line != rLines.end() )
- // while there is an even number of tokens; that m_eans
- // an odd number of doubleqoutes
- {
- // copy the newlines also
- aLine += '\n';
- aLine += *line;
- ++line;
+ // read in more lines if necessary for multiline values
+ aLine = aCurrentLine.Copy( nPos+1 );
+ if( aLine.Len() )
+ {
+ while( ! ( aLine.GetTokenCount( '"' ) & 1 ) &&
+ line != rLines.end() )
+ // while there is an even number of tokens; that means
+ // an odd number of doubleqoutes
+ {
+ // copy the newlines also
+ aLine += '\n';
+ aLine += *line;
+ ++line;
+ }
+ }
+ aLine = WhitespaceToSpace( aLine );
+
+ // #i100644# handle a missing value (actually a broken PPD)
+ if( ! aLine.Len() )
+ {
+ if( aOption.Len() &&
+ aUniKey.CompareToAscii( "JCL", 3 ) != COMPARE_EQUAL )
+ eType = eInvocation;
+ else
+ eType = eQuoted;
+ }
+ // check for invocation or quoted value
+ else if( aLine.GetChar(0) == '"' )
+ {
+ aLine.Erase( 0, 1 );
+ nTransPos = aLine.Search( '"' );
+ aValue = String( aLine.Copy( 0, nTransPos ), RTL_TEXTENCODING_MS_1252 );
+ // after the second doublequote can follow a / and a translation
+ aValueTranslation = handleTranslation( aLine.Copy( nTransPos+2 ), bIsGlobalizedLine );
+ // check for quoted value
+ if( aOption.Len() &&
+ aUniKey.CompareToAscii( "JCL", 3 ) != COMPARE_EQUAL )
+ eType = eInvocation;
+ else
+ eType = eQuoted;
+ }
+ // check for symbol value
+ else if( aLine.GetChar(0) == '^' )
+ {
+ aLine.Erase( 0, 1 );
+ aValue = String( aLine, RTL_TEXTENCODING_MS_1252 );
+ eType = eSymbol;
+ }
+ else
+ {
+ // must be a string value then
+ // strictly this is false because string values
+ // can contain any whitespace which is reduced
+ // to one space by now
+ // who cares ...
+ nTransPos = aLine.Search( '/' );
+ if( nTransPos == STRING_NOTFOUND )
+ nTransPos = aLine.Len();
+ aValue = String( aLine.Copy( 0, nTransPos ), RTL_TEXTENCODING_MS_1252 );
+ aValueTranslation = handleTranslation( aLine.Copy( nTransPos+1 ), bIsGlobalizedLine );
+ eType = eString;
+ }
}
- aLine = WhitespaceToSpace( aLine );
- // check for invocation or quoted value
- if( aLine.GetChar(0) == '"' )
+ // handle globalized PPD entries
+ if( bIsGlobalizedLine )
{
- aLine.Erase( 0, 1 );
- nTransPos = aLine.Search( '"' );
- pValue->m_aValue = String( aLine.Copy( 0, nTransPos ), RTL_TEXTENCODING_MS_1252 );
- // after the second doublequote can follow a / and a translation
- pValue->m_aValueTranslation = handleTranslation( aLine.Copy( nTransPos+2 ) );
- // check for quoted value
- if( pValue->m_aOption.Len() &&
- aKey.CompareTo( "JCL", 3 ) != COMPARE_EQUAL )
- pValue->m_eType = eInvocation;
+ // handle main key translations of form:
+ // *ll_CC.Translation MainKeyword/translated text: ""
+ if( aUniKey.EqualsAscii( "Translation" ) )
+ {
+ m_pTranslator->insertKey( aOption, aOptionTranslation, aTransLocale );
+ }
+ // handle options translations of for:
+ // *ll_CC.MainKeyword OptionKeyword/translated text: ""
else
- pValue->m_eType = eQuoted;
+ {
+ m_pTranslator->insertOption( aUniKey, aOption, aOptionTranslation, aTransLocale );
+ }
+ continue;
}
- // check for symbol value
- else if( aLine.GetChar(0) == '^' )
+
+ PPDKey* pKey = NULL;
+ keyit = m_aKeys.find( aUniKey );
+ if( keyit == m_aKeys.end() )
{
- aLine.Erase( 0, 1 );
- pValue->m_aValue = String( aLine, RTL_TEXTENCODING_MS_1252 );
- pValue->m_eType = eSymbol;
+ pKey = new PPDKey( aUniKey );
+ insertKey( aUniKey, pKey );
}
else
- {
- // must be a string value then
- // strictly this is false because string values
- // can contain any whitespace which is reduced
- // to one space by now
- // who cares ...
- nTransPos = aLine.Search( '/' );
- if( nTransPos == STRING_NOTFOUND )
- nTransPos = aLine.Len();
- pValue->m_aValue = String( aLine.Copy( 0, nTransPos ), RTL_TEXTENCODING_MS_1252 );
- pValue->m_aValueTranslation = handleTranslation( aLine.Copy( nTransPos+1 ) );
- pValue->m_eType = eString;
- }
+ pKey = keyit->second;
+
+ if( eType == eNo && bQuery )
+ continue;
+
+ PPDValue* pValue = pKey->insertValue( aOption );
+ if( ! pValue )
+ continue;
+ pValue->m_eType = eType;
+ pValue->m_aValue = aValue;
+
+ if( aOptionTranslation.getLength() )
+ m_pTranslator->insertOption( aUniKey, aOption, aOptionTranslation, aTransLocale );
+ if( aValueTranslation.getLength() )
+ m_pTranslator->insertValue( aUniKey, aOption, aValue, aValueTranslation, aTransLocale );
// eventually update query and remove from option list
if( bQuery && pKey->m_bQueryValue == FALSE )
@@ -879,7 +1135,7 @@ void PPDParser::parse( ::std::list< ByteString >& rLines )
keyit = m_aKeys.find( aKey );
if( keyit != m_aKeys.end() )
{
- pKey = keyit->second;
+ PPDKey* pKey = keyit->second;
const PPDValue* pDefValue = pKey->getValue( aOption );
if( pKey->m_pDefaultValue == NULL )
pKey->m_pDefaultValue = pDefValue;
@@ -890,7 +1146,7 @@ void PPDParser::parse( ::std::list< ByteString >& rLines )
// do not exist otherwise
// (example: DefaultResolution)
// so invent that key here and have a default value
- pKey = new PPDKey( aKey );
+ PPDKey* pKey = new PPDKey( aKey );
PPDValue* pNewValue = pKey->insertValue( aOption );
pNewValue->m_eType = eInvocation; // or what ?
insertKey( aKey, pKey );
@@ -915,7 +1171,7 @@ void PPDParser::parseOpenUI( const ByteString& rLine )
nPos = aKey.Search( '/' );
if( nPos != STRING_NOTFOUND )
{
- aTranslation = handleTranslation( aKey.Copy( nPos + 1 ) );
+ aTranslation = handleTranslation( aKey.Copy( nPos + 1 ), false );
aKey.Erase( nPos );
}
aKey = GetCommandLineToken( 1, aKey );
@@ -933,7 +1189,7 @@ void PPDParser::parseOpenUI( const ByteString& rLine )
pKey = keyit->second;
pKey->m_bUIOption = true;
- pKey->m_aUITranslation = aTranslation;
+ m_pTranslator->insertKey( pKey->getKey(), aTranslation );
ByteString aValue = WhitespaceToSpace( rLine.GetToken( 1, ':' ) );
if( aValue.CompareIgnoreCaseToAscii( "boolean" ) == COMPARE_EQUAL )
@@ -1393,6 +1649,36 @@ const String& PPDParser::getFont( int nFont ) const
return aEmptyString;
}
+rtl::OUString PPDParser::translateKey( const rtl::OUString& i_rKey,
+ const com::sun::star::lang::Locale& i_rLocale ) const
+{
+ rtl::OUString aResult( m_pTranslator->translateKey( i_rKey, i_rLocale ) );
+ if( aResult.getLength() == 0 )
+ aResult = i_rKey;
+ return aResult;
+}
+
+rtl::OUString PPDParser::translateOption( const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const com::sun::star::lang::Locale& i_rLocale ) const
+{
+ rtl::OUString aResult( m_pTranslator->translateOption( i_rKey, i_rOption, i_rLocale ) );
+ if( aResult.getLength() == 0 )
+ aResult = i_rOption;
+ return aResult;
+}
+
+rtl::OUString PPDParser::translateValue( const rtl::OUString& i_rKey,
+ const rtl::OUString& i_rOption,
+ const rtl::OUString& i_rValue,
+ const com::sun::star::lang::Locale& i_rLocale ) const
+{
+ rtl::OUString aResult( m_pTranslator->translateValue( i_rKey, i_rOption, i_rValue, i_rLocale ) );
+ if( aResult.getLength() == 0 )
+ aResult = i_rValue;
+ return aResult;
+}
+
/*
* PPDKey
*/
diff --git a/vcl/unx/source/printer/printerinfomanager.cxx b/vcl/unx/source/printer/printerinfomanager.cxx
index 53cd662db8e0..ef6a67203cd8 100644
--- a/vcl/unx/source/printer/printerinfomanager.cxx
+++ b/vcl/unx/source/printer/printerinfomanager.cxx
@@ -119,6 +119,7 @@ PrinterInfoManager::PrinterInfoManager( Type eType ) :
m_pQueueInfo( NULL ),
m_eType( eType ),
m_bUseIncludeFeature( false ),
+ m_bUseJobPatch( true ),
m_aSystemDefaultPaper( RTL_CONSTASCII_USTRINGPARAM( "A4" ) ),
m_bDisableCUPS( false )
{