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 #ifndef INCLUDED_VCL_PPDPARSER_HXX
20 #define INCLUDED_VCL_PPDPARSER_HXX
21 
22 #include <sal/config.h>
23 
24 #include <cstddef>
25 #include <memory>
26 #include <string_view>
27 #include <unordered_map>
28 #include <vector>
29 
30 #include <rtl/string.hxx>
31 #include <rtl/ustring.hxx>
32 #include <tools/solar.h>
33 #include <vcl/dllapi.h>
34 
35 #define PRINTER_PPDDIR "driver"
36 
37 namespace psp {
38 
39 class PPDCache;
40 class PPDTranslator;
41 
42 enum PPDValueType { eInvocation, eQuoted, eSymbol, eString, eNo };
43 
44 struct VCL_DLLPUBLIC PPDValue
45 {
46     PPDValueType     m_eType;
47     //CustomOption stuff for fdo#43049
48     //see http://www.cups.org/documentation.php/spec-ppd.html#OPTIONS
49     //for full specs, only the basics are implemented here
50     bool             m_bCustomOption;
51     mutable OUString m_aCustomOption;
52     OUString         m_aOption;
53     OUString         m_aValue;
54 };
55 
56 
57 /*
58  * PPDKey - a container for the available options (=values) of a PPD keyword
59  */
60 
61 class PPDKey
62 {
63     friend class PPDParser;
64     friend class CPDManager;
65 
66     typedef std::unordered_map< OUString, PPDValue > hash_type;
67     typedef std::vector< PPDValue* > value_type;
68 
69     OUString            m_aKey;
70     hash_type           m_aValues;
71     value_type          m_aOrderedValues;
72     const PPDValue*     m_pDefaultValue;
73     bool                m_bQueryValue;
74     OUString            m_aGroup;
75 
76 public:
77     enum class SetupType { ExitServer, Prolog, DocumentSetup, PageSetup, JCLSetup, AnySetup };
78 private:
79 
80     bool                m_bUIOption;
81     int                 m_nOrderDependency;
82     SetupType           m_eSetupType;
83 
84     void eraseValue( const OUString& rOption );
85 public:
86     PPDKey( const OUString& rKey );
87     ~PPDKey();
88 
89     PPDValue*           insertValue(const OUString& rOption, PPDValueType eType, bool bCustomOption = false);
countValues() const90     int                 countValues() const
91     { return m_aValues.size(); }
92     // neither getValue will return the query option
93     const PPDValue*     getValue( int n ) const;
94     const PPDValue*     getValue( const OUString& rOption ) const;
95     const PPDValue*     getValueCaseInsensitive( const OUString& rOption ) const;
getDefaultValue() const96     const PPDValue*     getDefaultValue() const { return m_pDefaultValue; }
getGroup() const97     const OUString&     getGroup() const { return m_aGroup; }
98 
getKey() const99     const OUString&     getKey() const { return m_aKey; }
isUIKey() const100     bool                isUIKey() const { return m_bUIOption; }
getSetupType() const101     SetupType           getSetupType() const { return m_eSetupType; }
getOrderDependency() const102     int                 getOrderDependency() const { return m_nOrderDependency; }
103 };
104 
105 // define a hash for PPDKey
106 struct PPDKeyhash
107 {
operator ()psp::PPDKeyhash108     size_t operator()( const PPDKey * pKey) const
109         { return reinterpret_cast<size_t>(pKey); }
110 };
111 
112 
113 /*
114  * PPDParser - parses a PPD file and contains all available keys from it
115  */
116 
117 class PPDParser
118 {
119     friend class PPDContext;
120     friend class CUPSManager;
121     friend class CPDManager;
122     friend class PPDCache;
123 
124     typedef std::unordered_map< OUString, std::unique_ptr<PPDKey> > hash_type;
125     typedef std::vector< PPDKey* > value_type;
126 
127     void insertKey( std::unique_ptr<PPDKey> pKey );
128 public:
129     struct PPDConstraint
130     {
131         const PPDKey*       m_pKey1;
132         const PPDValue*     m_pOption1;
133         const PPDKey*       m_pKey2;
134         const PPDValue*     m_pOption2;
135 
PPDConstraintpsp::PPDParser::PPDConstraint136         PPDConstraint() : m_pKey1( nullptr ), m_pOption1( nullptr ), m_pKey2( nullptr ), m_pOption2( nullptr ) {}
137     };
138 private:
139     hash_type                                   m_aKeys;
140     value_type                                  m_aOrderedKeys;
141     ::std::vector< PPDConstraint >              m_aConstraints;
142 
143     // the full path of the PPD file
144     OUString                                    m_aFile;
145     // some basic attributes
146     bool                                        m_bColorDevice;
147     bool                                        m_bType42Capable;
148     sal_uLong                                       m_nLanguageLevel;
149     rtl_TextEncoding                            m_aFileEncoding;
150 
151 
152     // shortcuts to important keys and their default values
153     // imageable area
154     const PPDKey*                               m_pImageableAreas;
155     // paper dimensions
156     const PPDValue*                             m_pDefaultPaperDimension;
157     const PPDKey*                               m_pPaperDimensions;
158     // paper trays
159     const PPDValue*                             m_pDefaultInputSlot;
160     // resolutions
161     const PPDValue*                             m_pDefaultResolution;
162 
163     // translations
164     std::unique_ptr<PPDTranslator>              m_pTranslator;
165 
166     PPDParser( const OUString& rFile );
167     PPDParser(const OUString& rFile, const std::vector<PPDKey*>& keys);
168 
169     void parseOrderDependency(const OString& rLine);
170     void parseOpenUI(const OString& rLine, std::string_view rPPDGroup);
171     void parseConstraint(const OString& rLine);
172     void parse( std::vector< OString >& rLines );
173 
174     OUString handleTranslation(const OString& i_rString, bool i_bIsGlobalized);
175 
176     static void scanPPDDir( const OUString& rDir );
177     static void initPPDFiles(PPDCache &rPPDCache);
178     static OUString getPPDFile( const OUString& rFile );
179 public:
180     ~PPDParser();
181     static const PPDParser* getParser( const OUString& rFile );
182 
183     const PPDKey*   getKey( int n ) const;
184     const PPDKey*   getKey( const OUString& rKey ) const;
getKeys() const185     int             getKeys() const { return m_aKeys.size(); }
186     bool            hasKey( const PPDKey* ) const;
187 
getConstraints() const188     const ::std::vector< PPDConstraint >& getConstraints() const { return m_aConstraints; }
189 
isColorDevice() const190     bool            isColorDevice() const { return m_bColorDevice; }
isType42Capable() const191     bool            isType42Capable() const { return m_bType42Capable; }
getLanguageLevel() const192     sal_uLong       getLanguageLevel() const { return m_nLanguageLevel; }
193 
194     OUString        getDefaultPaperDimension() const;
getDefaultPaperDimension(int & rWidth,int & rHeight) const195     void            getDefaultPaperDimension( int& rWidth, int& rHeight ) const
196     { getPaperDimension( getDefaultPaperDimension(), rWidth, rHeight ); }
197     bool getPaperDimension( std::u16string_view rPaperName,
198                             int& rWidth, int& rHeight ) const;
199     // width and height in pt
200     // returns false if paper not found
201 
202     // match the best paper for width and height
203     OUString        matchPaper( int nWidth, int nHeight ) const;
204 
205     bool getMargins( std::u16string_view rPaperName,
206                      int &rLeft, int& rRight,
207                      int &rUpper, int& rLower ) const;
208     // values in pt
209     // returns true if paper found
210 
211     // values int pt
212 
213     OUString        getDefaultInputSlot() const;
214 
215     void            getDefaultResolution( int& rXRes, int& rYRes ) const;
216     // values in dpi
217     static void     getResolutionFromString( const OUString&, int&, int& );
218     // helper function
219 
220     OUString   translateKey( const OUString& i_rKey ) const;
221     OUString   translateOption( const OUString& i_rKey,
222                                 const OUString& i_rOption ) const;
223 };
224 
225 
226 /*
227  * PPDContext - a class to manage user definable states based on the
228  * contents of a PPDParser.
229  */
230 
231 class PPDContext
232 {
233     typedef std::unordered_map< const PPDKey*, const PPDValue*, PPDKeyhash > hash_type;
234     hash_type m_aCurrentValues;
235     const PPDParser*                                    m_pParser;
236 
237     // returns false: check failed, new value is constrained
238     //         true:  check succeeded, new value can be set
239     bool checkConstraints( const PPDKey*, const PPDValue*, bool bDoReset );
240     bool resetValue( const PPDKey*, bool bDefaultable = false );
241 public:
242     PPDContext();
PPDContext(const PPDContext & rContext)243     PPDContext( const PPDContext& rContext ) { operator=( rContext ); }
244     PPDContext& operator=( const PPDContext& rContext ) = default;
245     PPDContext& operator=( PPDContext&& rContext );
246 
247     void setParser( const PPDParser* );
getParser() const248     const PPDParser* getParser() const { return m_pParser; }
249 
250     const PPDValue* getValue( const PPDKey* ) const;
251     const PPDValue* setValue( const PPDKey*, const PPDValue*, bool bDontCareForConstraints = false );
252 
countValuesModified() const253     std::size_t countValuesModified() const { return m_aCurrentValues.size(); }
254     const PPDKey* getModifiedKey( std::size_t n ) const;
255 
256     // public wrapper for the private method
257     bool checkConstraints( const PPDKey*, const PPDValue* );
258 
259     // for printer setup
260     char*   getStreamableBuffer( sal_uLong& rBytes ) const;
261     void    rebuildFromStreamBuffer(const std::vector<char> &rBuffer);
262 
263     // convenience
264     int getRenderResolution() const;
265 
266     // width, height in points, paper will contain the name of the selected
267     // paper after the call
268     void getPageSize( OUString& rPaper, int& rWidth, int& rHeight ) const;
269 };
270 
271 } // namespace
272 
273 #endif // INCLUDED_VCL_PPDPARSER_HXX
274 
275 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
276