/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// filename of configuration files
constexpr OUString PRINT_FILENAME = u"psprint.conf"_ustr; // the group of the global defaults
constexpr OString GLOBAL_DEFAULTS_GROUP = "__Global_Printer_Defaults__"_ostr;
// first initialize the global defaults // have to iterate over all possible files // there should be only one global setup section in all // available config files
m_aGlobalDefaults = PrinterInfo();
// need a parser for the PPDContext. generic printer should do.
m_aGlobalDefaults.m_pParser = PPDParser::getParser( u"SGENPRT"_ustr );
m_aGlobalDefaults.m_aContext.setParser( m_aGlobalDefaults.m_pParser );
// set parser, merge settings // don't do this for CUPS printers as this is done // by the CUPS system itself if( !aPrinter.m_aInfo.m_aDriverName.startsWith( "CUPS:" ) )
{
aPrinter.m_aInfo.m_pParser = PPDParser::getParser( aPrinter.m_aInfo.m_aDriverName );
aPrinter.m_aInfo.m_aContext.setParser( aPrinter.m_aInfo.m_pParser ); // note: setParser also purges the context
// ignore this printer if its driver is not found if( ! aPrinter.m_aInfo.m_pParser ) continue;
// merge the ppd context keys if the printer has the same keys and values // this is a bit tricky, since it involves mixing two PPDs // without constraints which might end up badly // this feature should be use with caution // it is mainly to select default paper sizes for new printers for( std::size_t nPPDValueModified = 0; nPPDValueModified < m_aGlobalDefaults.m_aContext.countValuesModified(); nPPDValueModified++ )
{ const PPDKey* pDefKey = m_aGlobalDefaults.m_aContext.getModifiedKey( nPPDValueModified ); const PPDValue* pDefValue = m_aGlobalDefaults.m_aContext.getValue( pDefKey ); const PPDKey* pPrinterKey = pDefKey ? aPrinter.m_aInfo.m_pParser->getKey( pDefKey->getKey() ) : nullptr; if( pDefKey && pPrinterKey ) // at least the options exist in both PPDs
{ if( pDefValue )
{ const PPDValue* pPrinterValue = pPrinterKey->getValue( pDefValue->m_aOption ); if( pPrinterValue ) // the printer has a corresponding option for the key
aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, pPrinterValue );
} else
aPrinter.m_aInfo.m_aContext.setValue( pPrinterKey, nullptr );
}
}
aValue = aConfig.ReadKey( "Command"_ostr ); // no printer without a command if (aValue.isEmpty())
{ /* TODO: * porters: please append your platform to the Solaris * case if your platform has SystemV printing per default.
*/ #ifdefined __sun
aValue = "lp"; #else
aValue = "lpr"_ostr; #endif
}
aPrinter.m_aInfo.m_aCommand = OStringToOUString(aValue, RTL_TEXTENCODING_UTF8);
}
// add a default printer for every available print queue // merge paper default printer, all else from global defaults
PrinterInfo aMergeInfo( m_aGlobalDefaults );
aMergeInfo.m_aDriverName = "SGENPRT";
aMergeInfo.m_aFeatures = "autoqueue";
std::size_t nModified = rContext.countValuesModified(); auto set = false; for (std::size_t i = 0; i != nModified; ++i) { if (rContext.getModifiedKey(i) == pPageSizeKey) {
set = true; break;
}
}
if( set ) // paper was set already, do not modify
{ #if OSL_DEBUG_LEVEL > 1
SAL_WARN("vcl.unx.print", "not setting default paper, already set "
<< rContext.getValue( pPageSizeKey )->m_aOption); #endif return;
}
// paper not set, fill in default value const PPDValue* pPaperVal = nullptr; int nValues = pPageSizeKey->countValues(); for( int i = 0; i < nValues && ! pPaperVal; i++ )
{ const PPDValue* pVal = pPageSizeKey->getValue( i ); if( pVal->m_aOption.equalsIgnoreAsciiCase( m_aSystemDefaultPaper ) )
pPaperVal = pVal;
} if( pPaperVal )
{ #if OSL_DEBUG_LEVEL > 1
SAL_INFO("vcl.unx.print", "setting default paper "
<< pPaperVal->m_aOption); #endif
rContext.setValue( pPageSizeKey, pPaperVal ); #if OSL_DEBUG_LEVEL > 1
SAL_INFO("vcl.unx.print", "-> got paper "
<< rContext.getValue( pPageSizeKey )->m_aOption); #endif
}
}
// the eventual "all" attribute of the "_all" queue tells us, which // printers are to be used for this user at all
// find _all: line
OString aAllLine( "_all:" );
OString aAllAttr( "all=" ); auto it = std::find_if(i_rLines.begin(), i_rLines.end(),
[&aAllLine](const OString& rLine) { return rLine.indexOf( aAllLine, 0 ) == 0; }); if( it != i_rLines.end() )
{ // now find the "all" attribute
++it;
it = std::find_if(it, i_rLines.end(),
[&aAllAttr](const OString& rLine) { return WhitespaceToSpace( rLine ).startsWith( aAllAttr ); }); if( it != i_rLines.end() )
{ // insert the comma separated entries into the set of printers to use
OString aClean( WhitespaceToSpace( *it ) );
sal_Int32 nPos = aAllAttr.getLength(); while( nPos != -1 )
{
OString aTok( aClean.getToken( 0, ',', nPos ) ); if( !aTok.isEmpty() )
aOnlySet.insert( OStringToOUString( aTok, aEncoding ) );
}
}
}
bool bInsertAttribute = false;
OString aDescrStr( "description=" );
OString aLocStr( "location=" ); for (autoconst& line : i_rLines)
{
sal_Int32 nPos = 0; // find the begin of a new printer section
nPos = line.indexOf( ':', 0 ); if( nPos != -1 )
{
OUString aSysQueue( OStringToOUString( line.copy( 0, nPos ), aEncoding ) ); // do not insert duplicates (e.g. lpstat tends to produce such lines) // in case there was a "_all" section, insert only those printer explicitly // set in the "all" attribute if( aUniqueSet.find( aSysQueue ) == aUniqueSet.end() &&
( aOnlySet.empty() || aOnlySet.find( aSysQueue ) != aOnlySet.end() )
)
{
o_rQueues.push_back( PrinterInfoManager::SystemPrintQueue() );
o_rQueues.back().m_aQueue = aSysQueue;
o_rQueues.back().m_aLocation = aSysQueue;
aUniqueSet.insert( aSysQueue );
bInsertAttribute = true;
} else
bInsertAttribute = false; continue;
} if( bInsertAttribute && ! o_rQueues.empty() )
{ // look for "description" attribute, insert as comment
nPos = line.indexOf( aDescrStr, 0 ); if( nPos != -1 )
{
OString aComment( WhitespaceToSpace( line.copy(nPos+12) ) ); if( !aComment.isEmpty() )
o_rQueues.back().m_aComment = OStringToOUString(aComment, aEncoding); continue;
} // look for "location" attribute, insert as location
nPos = line.indexOf( aLocStr, 0 ); if( nPos != -1 )
{
OString aLoc( WhitespaceToSpace( line.copy(nPos+9) ) ); if( !aLoc.isEmpty() )
o_rQueues.back().m_aLocation = OStringToOUString(aLoc, aEncoding); continue;
}
}
}
} #endif staticvoid standardSysQueueTokenHandler( const std::vector< OString >& i_rLines,
std::vector< PrinterInfoManager::SystemPrintQueue >& o_rQueues, const SystemCommandParameters* i_pParms)
{
rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
std::unordered_set< OUString > aUniqueSet;
OString aForeToken( i_pParms->pForeToken );
OString aAftToken( i_pParms->pAftToken ); /* Normal Unix print queue discovery, also used for Darwin 5 LPR printing
*/ for (autoconst& line : i_rLines)
{
sal_Int32 nPos = 0;
// search for a line describing a printer: // find if there are enough tokens before the name for( unsignedint i = 0; i < i_pParms->nForeTokenCount && nPos != -1; i++ )
{
nPos = line.indexOf( aForeToken, nPos ); if( nPos != -1 && line.getLength() >= nPos+aForeToken.getLength() )
nPos += aForeToken.getLength();
} if( nPos != -1 )
{ // find if there is the token after the queue
sal_Int32 nAftPos = line.indexOf( aAftToken, nPos ); if( nAftPos != -1 )
{ // get the queue name between fore and aft tokens
OUString aSysQueue( OStringToOUString( line.subView( nPos, nAftPos - nPos ), aEncoding ) ); // do not insert duplicates (e.g. lpstat tends to produce such lines) if( aUniqueSet.insert( aSysQueue ).second )
{
o_rQueues.emplace_back( );
o_rQueues.back().m_aQueue = aSysQueue;
o_rQueues.back().m_aLocation = aSysQueue;
}
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.