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

tdeprint

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

tdeprint

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

tdeprint

Skip menu "tdeprint"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeprint by doxygen 1.9.4
This website is maintained by Timothy Pearson.