• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdeprint
 

kdeprint

  • kdeprint
ppdloader.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (c) 2001-2003 Michael Goffioul <kdeprint@swing.be>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  **/
19 
20 #include "ppdloader.h"
21 #include "foomatic2loader.h"
22 #include "driver.h"
23 
24 #include <kfilterdev.h>
25 #include <kdebug.h>
26 #include <klocale.h>
27 #include <tqfile.h>
28 #include <math.h>
29 
30 void kdeprint_ppdscanner_init( TQIODevice* );
31 void kdeprint_ppdscanner_terminate( bool deleteIt = true );
32 int kdeprint_ppdscanner_numberoflines();
33 
34 static TQString processLocaleString( const TQString& s )
35 {
36  TQString res;
37  uint pos = 0;
38  while ( pos < s.length() )
39  {
40  TQChar c = s[ pos++ ];
41  if ( c == '<' )
42  {
43  bool flag = false;
44  uint hc = 0;
45  while ( pos < s.length() )
46  {
47  TQChar cc = s[ pos++ ];
48  uint _hc = 0;
49  if ( cc == '>' )
50  break;
51  else if ( cc.isDigit() )
52  _hc = cc.digitValue();
53  else
54  _hc = cc.lower().latin1() - 'a' + 10;
55  if ( flag )
56  {
57  hc |= _hc;
58  res.append( TQChar( hc ) );
59  hc = 0;
60  }
61  else
62  hc = ( _hc << 4 );
63  flag = !flag;
64  }
65  }
66  else
67  {
68  res.append( c );
69  }
70  }
71  return res;
72 }
73 
74 static TQValueList<float> splitNumberString( const TQString& _s )
75 {
76  TQString s = _s.simplifyWhiteSpace();
77  TQValueList<float> l;
78  int p1 = 1, p2 = 0;
79  while ( true )
80  {
81  p2 = s.find( ' ', p1 );
82  if ( p2 != -1 )
83  {
84  l.append( s.mid( p1, p2-p1 ).toFloat() );
85  p1 = p2+1;
86  }
87  else
88  {
89  // ignore the final quote
90  l.append( s.mid( p1, s.length() - p1 - 1 ).toFloat() );
91  break;
92  }
93  }
94  return l;
95 }
96 
97 struct PS_private
98 {
99  TQString name;
100  struct
101  {
102  float width, height;
103  } size;
104  struct
105  {
106  float left, bottom, right, top;
107  } area;
108 };
109 
110 PPDLoader::PPDLoader()
111 {
112  m_option = 0;
113  m_ps.setAutoDelete( true );
114 }
115 
116 PPDLoader::~PPDLoader()
117 {
118 }
119 
120 DrMain* PPDLoader::readFromFile( const TQString& filename )
121 {
122  // Initialization
123  m_groups.clear();
124  m_option = NULL;
125  m_fonts.clear();
126  // Open driver file
127  TQIODevice *d = KFilterDev::deviceForFile( filename );
128  if ( d && d->open( IO_ReadOnly ) )
129  {
130  DrMain *driver = new DrMain;
131  bool result = true;
132 
133  m_groups.push( driver );
134  kdeprint_ppdscanner_init( d );
135  if ( kdeprint_ppdparse( this ) != 0 )
136  result = false;
137  kdeprint_ppdscanner_terminate( true );
138 
139  if ( result )
140  {
141  if ( m_groups.size() > 1 )
142  kdWarning( 500 ) << "PPD syntax error, GROUP specification not correctly closed" << endl;
143  if ( driver->has( "foodata" ) )
144  {
145  Foomatic2Loader loader;
146  if ( loader.readFromBuffer( driver->get( "foodata" ) ) )
147  {
148  driver = loader.modifyDriver( driver );
149  }
150  else
151  kdWarning( 500 ) << "PPD syntax error, Foomatic data read failed" << endl;
152  }
153  processPageSizes( driver );
154  if ( !m_fonts.isEmpty() )
155  driver->set( "fonts", m_fonts.join( "," ) );
156  return driver;
157  }
158  else
159  kdWarning( 500 ) << "PPD syntax error, PPD parse failed" << endl;
160  delete driver;
161  m_ps.clear();
162  }
163  else
164  kdWarning( 500 ) << "PPD read error, unable to open device for file " << filename << endl;
165  return 0;
166 }
167 
168 DrMain* PPDLoader::loadDriver( const TQString& filename, TQString* msg )
169 {
170  PPDLoader loader;
171  DrMain *driver = loader.readFromFile( filename );
172  if ( !driver && msg )
173  *msg = filename + i18n( "(line %1): " ).arg( kdeprint_ppdscanner_numberoflines() ) + loader.errorMsg();
174  return driver;
175 }
176 
177 bool PPDLoader::openUi( const TQString& name, const TQString& desc, const TQString& type )
178 {
179  if ( m_option )
180  {
181  qWarning( "PPD syntax error, UI specification not correctly closed" );
182  endUi( m_option->name() );
183  }
184 
185  if ( type == "PickOne" || type == "PickMany" )
186  m_option = new DrListOption;
187  else if ( type == "Boolean" )
188  m_option = new DrBooleanOption;
189  else
190  return false;
191  if ( name[ 0 ] == '*' )
192  m_option->setName( name.mid( 1 ) );
193  else
194  m_option->setName( name );
195  if ( desc.isEmpty() )
196  m_option->set( "text", m_option->name() );
197  else
198  m_option->set( "text", processLocaleString( desc ) );
199  return true;
200 }
201 
202 bool PPDLoader::endUi( const TQString& name )
203 {
204  if ( m_option && ( m_option->name() == name || m_option->name() == name.mid( 1 ) ) )
205  {
206  if ( m_option->name() == "PageRegion" )
207  delete m_option;
208  else
209  {
210  TQString defval = m_option->get( "default" );
211  DrGroup *grp = 0;
212  if ( !defval.isEmpty() )
213  m_option->setValueText( defval );
214  if ( m_groups.size() == 1 )
215  {
216  // we don't have any group defined, create the
217  // most adapted one.
218  grp = findOrCreateGroupForOption( m_option->name() );
219  }
220  else
221  grp = m_groups.top();
222  grp->addOption( m_option );
223  if ( grp->get( "text" ).contains( "install", false ) )
224  m_option->set( "fixed", "1" );
225  }
226  m_option = 0;
227  return true;
228  }
229  return false;
230 }
231 
232 bool PPDLoader::openGroup( const TQString& name, const TQString& desc )
233 {
234  DrGroup *grp = new DrGroup;
235  grp->setName( name );
236  if ( desc.isEmpty() )
237  grp->set( "text", name );
238  else
239  grp->set( "text", processLocaleString( desc ) );
240  m_groups.top()->addGroup( grp );
241  m_groups.push( grp );
242  return true;
243 }
244 
245 bool PPDLoader::endGroup( const TQString& name )
246 {
247  if ( m_groups.size() > 1 && m_groups.top()->name() == name )
248  {
249  m_groups.pop();
250  return true;
251  }
252  return false;
253 }
254 
255 bool PPDLoader::putStatement( const TQString& keyword, const TQString& name, const TQString& desc, const TQStringList& values )
256 {
257  if ( m_option )
258  {
259  if ( !name.isEmpty() && m_option->name() == keyword )
260  {
261  if ( m_option->type() >= DrBase::List )
262  {
263  DrBase *ch = new DrBase;
264  ch->setName( name );
265  if ( desc.isEmpty() )
266  ch->set( "text", name );
267  else
268  ch->set( "text", processLocaleString( desc ) );
269  static_cast<DrListOption*>( m_option )->addChoice( ch );
270  }
271  else
272  {
273  TQString fv = m_option->get( "fixedvals" );
274  if ( fv.isEmpty() )
275  fv = name;
276  else
277  fv.append( "|" + name );
278  m_option->set( "fixedvals", fv );
279  }
280  }
281  else if ( keyword == "FoomaticRIPOption" && name == m_option->name()
282  && values.size() > 1 )
283  {
284  TQString type = values[ 0 ];
285  if ( type == "float" || type == "int" )
286  {
287  DrBase *opt = 0;
288  if ( type == "float" )
289  opt = new DrFloatOption;
290  else
291  opt = new DrIntegerOption;
292  opt->setName( m_option->name() );
293  opt->set( "text", m_option->get( "text" ) );
294  opt->set( "default", m_option->get( "default" ) );
295  if ( m_option->type() == DrBase::List )
296  {
297  TQStringList vals;
298  TQPtrListIterator<DrBase> it( *( static_cast<DrListOption*>( m_option )->choices() ) );
299  for ( ; it.current(); ++it )
300  vals.append( it.current()->name() );
301  opt->set( "fixedvals", vals.join( "|" ) );
302  }
303  delete m_option;
304  m_option = opt;
305  }
306  // FIXME: support other option types
307  }
308  else if ( keyword == "FoomaticRIPOptionRange" && name == m_option->name()
309  && values.size() >= 2 && ( m_option->type() == DrBase::Float || m_option->type() == DrBase::Integer ) )
310  {
311  m_option->set( "minval", values[ 0 ] );
312  m_option->set( "maxval", values[ 1 ] );
313  }
314  }
315  else if ( keyword == "Font" && m_groups.size() > 0 )
316  {
317  m_fonts << name;
318  }
319  return true;
320 }
321 
322 bool PPDLoader::putStatement2( const TQString& keyword, const TQString& value )
323 {
324  if ( !m_option && m_groups.size() == 1 )
325  {
326  DrGroup *driver = m_groups.top();
327  if ( keyword == "NickName" )
328  {
329  driver->set( "text", value );
330  driver->set( "description", value );
331  }
332  else if ( keyword == "Manufacturer" )
333  driver->set( "manufacturer", value );
334  else if ( keyword == "ShortNickName" )
335  driver->set( "model", value );
336  else if ( keyword == "ColorDevice" )
337  driver->set( "colordevice", value == "True" ? "1" : "0" );
338  }
339  return true;
340 }
341 
342 bool PPDLoader::putDefault( const TQString& keyword, const TQString& value )
343 {
344  if ( keyword == "Resolution" && m_groups.size() > 0 )
345  {
346  // Store default resolution as it could be fed back
347  // to the application. And default resolution can
348  // occur outside a OpenUI/CloseUI pair.
349  m_groups[ 0 ]->set( "resolution", value );
350  }
351 
352  if ( m_option && m_option->name() == keyword )
353  {
354  m_option->set( "default", value );
355  return true;
356  }
357  else
358  return false;
359 }
360 
361 bool PPDLoader::putConstraint( const TQString& opt1, const TQString& opt2, const TQString& ch1, const TQString& ch2 )
362 {
363  if ( !m_option && m_groups.size() == 1 )
364  {
365  DrMain *driver = static_cast<DrMain*>( m_groups.top() );
366  driver->addConstraint( new DrConstraint( opt1, opt2, ch1, ch2 ) );
367  }
368  return true;
369 }
370 
371 bool PPDLoader::putFooData( const TQString& data )
372 {
373  if ( !m_option && m_groups.size() == 1 )
374  {
375  m_groups.top()->set( "foodata", m_groups.top()->get( "foodata" ) + data + "\n" );
376  }
377  return true;
378 }
379 
380 bool PPDLoader::putFooProcessedData( const TQVariant& var )
381 {
382  TQMap<TQString,TQVariant>::ConstIterator it = var.mapFind( "args_byname" );
383  if ( it != var.mapEnd() )
384  {
385  TQVariant opts = it.data();
386  for ( it = opts.mapBegin(); it != opts.mapEnd(); ++it )
387  {
388  TQMap<TQString,TQVariant> opt = it.data().toMap();
389  TQString type = opt[ "type" ].toString();
390  if ( type == "float" || type == "int" )
391  {
392  DrBase *o;
393  if ( type == "float" )
394  o = new DrFloatOption;
395  else
396  o = new DrIntegerOption;
397  o->setName( opt[ "name" ].toString() );
398  o->set( "text", opt[ "comment" ].toString() );
399  o->set( "minval", opt[ "min" ].toString() );
400  o->set( "maxval", opt[ "max" ].toString() );
401  o->set( "default", opt[ "default" ].toString() );
402  o->setValueText( o->get( "default" ) );
403 
404  DrGroup *grp = 0;
405  DrBase *old = m_groups.top()->findOption( o->name(), &grp );
406  if ( old )
407  {
408  if ( old->type() == DrBase::List )
409  {
410  TQStringList vals;
411  TQPtrListIterator<DrBase> it( *( static_cast<DrListOption*>( old )->choices() ) );
412  for ( ; it.current(); ++it )
413  vals.append( it.current()->name() );
414  o->set( "fixedvals", vals.join( "|" ) );
415  }
416  grp->removeOption( o->name() );
417  grp->addOption( o );
418  }
419  else
420  {
421  qWarning( "Option %s not found in original PPD file", o->name().latin1() );
422  delete o;
423  }
424  }
425  }
426  }
427  return true;
428 }
429 
430 bool PPDLoader::putPaperDimension( const TQString& name, const TQString& s )
431 {
432  TQValueList<float> l = splitNumberString( s );
433 
434  PS_private *ps = m_ps.find( name );
435  if ( !ps )
436  {
437  ps = new PS_private;
438  ps->name = name;
439  m_ps.insert( name, ps );
440  }
441  ps->size.width = l[ 0 ];
442  ps->size.height = l[ 1 ];
443 
444  return true;
445 }
446 
447 bool PPDLoader::putImageableArea( const TQString& name, const TQString& s )
448 {
449  TQValueList<float> l = splitNumberString( s );
450 
451  PS_private *ps = m_ps.find( name );
452  if ( !ps )
453  {
454  ps = new PS_private;
455  ps->name = name;
456  m_ps.insert( name, ps );
457  }
458  ps->area.left = l[ 0 ];
459  ps->area.bottom = l[ 1 ];
460  ps->area.right = l[ 2 ];
461  ps->area.top = l[ 3 ];
462 
463  return true;
464 }
465 
466 DrGroup* PPDLoader::findOrCreateGroupForOption( const TQString& optname )
467 {
468  TQString grpname;
469  if ( optname == "PageSize" ||
470  optname == "InputSlot" ||
471  optname == "ManualFeed" ||
472  optname == "MediaType" ||
473  optname == "MediaColor" ||
474  optname == "MediaWeight" )
475  grpname = "General";
476  else if ( optname.startsWith( "stp" ) ||
477  optname == "Cyan" ||
478  optname == "Yellow" ||
479  optname == "Magenta" ||
480  optname == "Density" ||
481  optname == "Contrast" )
482  grpname = "Adjustments";
483  else if ( optname.startsWith( "JCL" ) )
484  grpname = "JCL";
485  else
486  grpname = "Others";
487 
488  DrGroup *grp = 0;
489  for ( TQPtrListIterator<DrGroup> it( m_groups[ 0 ]->groups() ); it.current(); ++it )
490  if ( it.current()->name() == grpname )
491  {
492  grp = it.current();
493  break;
494  }
495  if ( !grp )
496  {
497  grp = new DrGroup;
498  grp->setName( grpname );
499  grp->set( "text", grpname );
500  m_groups[ 0 ]->addGroup( grp );
501  }
502  return grp;
503 }
504 
505 void PPDLoader::processPageSizes( DrMain *driver )
506 {
507  TQDictIterator<PS_private> it( m_ps );
508  for ( ; it.current(); ++it )
509  {
510  //qDebug( "ADDING PAGESIZE: %16s, Size = ( %.2f, %.2f ), Area = ( %.2f, %.2f, %.2f, %.2f )", it.current()->name.latin1(),
511  // it.current()->size.width, it.current()->size.height,
512  // it.current()->area.left, it.current()->area.bottom,
513  // it.current()->area.right, it.current()->area.top );
514  driver->addPageSize( new DrPageSize( it.current()->name,
515  ( int )it.current()->size.width, ( int )it.current()->size.height,
516  ( int )it.current()->area.left, ( int )it.current()->area.bottom,
517  ( int )ceil( it.current()->size.width - it.current()->area.right ),
518  ( int )ceil( it.current()->size.height - it.current()->area.top ) ) );
519  }
520  m_ps.clear();
521 }
522 
523 void PPDLoader::setErrorMsg( const TQString& msg )
524 {
525  m_errormsg = msg;
526 }
527 
528 TQString PPDLoader::errorMsg() const
529 {
530  return m_errormsg;
531 }

kdeprint

Skip menu "kdeprint"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdeprint

Skip menu "kdeprint"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdeprint by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |