24 #include "ppdloader.h"
25 #include "foomatic2loader.h"
28 #include <kfilterdev.h>
30 #include <tdelocale.h>
31 #include <tdetempfile.h>
36 void tdeprint_ppdscanner_init( TQIODevice* );
37 void tdeprint_ppdscanner_terminate(
bool deleteIt =
true );
38 int tdeprint_ppdscanner_numberoflines();
40 static TQString processLocaleString(
const TQString& s )
44 while ( pos < s.length() )
46 TQChar c = s[ pos++ ];
51 while ( pos < s.length() )
53 TQChar cc = s[ pos++ ];
57 else if ( cc.isDigit() )
58 _hc = cc.digitValue();
60 _hc = cc.lower().latin1() -
'a' + 10;
64 res.append( TQChar( hc ) );
80 static TQValueList<float> splitNumberString(
const TQString& _s )
82 TQString s = _s.simplifyWhiteSpace();
87 p2 = s.find(
' ', p1 );
90 l.append( s.mid( p1, p2-p1 ).toFloat() );
96 l.append( s.mid( p1, s.length() - p1 - 1 ).toFloat() );
112 float left, bottom, right, top;
116 PPDLoader::PPDLoader()
119 m_ps.setAutoDelete(
true );
122 PPDLoader::~PPDLoader()
126 DrMain* PPDLoader::readFromFile(
const TQString& filename )
128 bool ppdFilenameIsTempFile =
false;
129 TQString ppdFilename = filename;
131 if (filename.startsWith(
"compressed-ppd:")) {
132 KTempFile tempFile(TQString::null,
"ppd", 0600);
133 tempFile.setAutoDelete(
false);
134 ppdFilename = tempFile.name();
136 TQStringList filenameParts = TQStringList::split(
":", filename);
137 TQString databaseFilename = TQString::null;
138 TQString compressedFilename = TQString::null;
140 for (TQStringList::Iterator it = filenameParts.begin(); it != filenameParts.end(); ++it) {
142 databaseFilename = *it;
145 compressedFilename += *it;
150 TQString command = databaseFilename +
" cat " + compressedFilename;
152 FILE* file = popen(command.ascii(),
"r");
158 FILE* tmpFileStream = tempFile.fstream();
160 while ((read = getline(&line, &len, file)) != -1) {
161 fputs(line, tmpFileStream);
171 fprintf(stderr,
"Can't open driver file : %s\n", compressedFilename.ascii());
175 ppdFilenameIsTempFile =
true;
183 TQIODevice *d = KFilterDev::deviceForFile( ppdFilename );
184 if ( d && d->open( IO_ReadOnly ) )
186 DrMain *driver =
new DrMain;
189 m_groups.push( driver );
190 tdeprint_ppdscanner_init( d );
191 if ( tdeprint_ppdparse(
this ) != 0 )
193 tdeprint_ppdscanner_terminate(
true );
197 if ( m_groups.size() > 1 )
198 kdWarning( 500 ) <<
"PPD syntax error, GROUP specification not correctly closed" << endl;
199 if ( driver->has(
"foodata" ) )
201 Foomatic2Loader loader;
202 if ( loader.readFromBuffer( driver->get(
"foodata" ) ) )
204 driver = loader.modifyDriver( driver );
207 kdWarning( 500 ) <<
"PPD syntax error, Foomatic data read failed" << endl;
209 processPageSizes( driver );
210 if ( !m_fonts.isEmpty() )
211 driver->set(
"fonts", m_fonts.join(
"," ) );
212 if (ppdFilenameIsTempFile) {
213 driver->set(
"temporary-cppd", ppdFilename);
218 kdWarning( 500 ) <<
"PPD syntax error, PPD parse failed" << endl;
223 kdWarning( 500 ) <<
"PPD read error, unable to open device for file " << ppdFilename << endl;
227 DrMain* PPDLoader::loadDriver(
const TQString& filename, TQString* msg )
230 DrMain *driver = loader.readFromFile( filename );
231 if ( !driver && msg )
232 *msg = filename + i18n(
"(line %1): " ).arg( tdeprint_ppdscanner_numberoflines() ) + loader.errorMsg();
236 bool PPDLoader::openUi(
const TQString& name,
const TQString& desc,
const TQString& type )
240 tqWarning(
"PPD syntax error, UI specification not correctly closed" );
241 endUi( m_option->name() );
244 if ( type ==
"PickOne" || type ==
"PickMany" )
245 m_option =
new DrListOption;
246 else if ( type ==
"Boolean" )
247 m_option =
new DrBooleanOption;
250 if ( name[ 0 ] ==
'*' )
251 m_option->setName( name.mid( 1 ) );
253 m_option->setName( name );
254 if ( desc.isEmpty() )
255 m_option->set(
"text", m_option->name() );
257 m_option->set(
"text", processLocaleString( desc ) );
261 bool PPDLoader::endUi(
const TQString& name )
263 if ( m_option && ( m_option->name() == name || m_option->name() == name.mid( 1 ) ) )
265 if ( m_option->name() ==
"PageRegion" )
269 TQString defval = m_option->get(
"default" );
271 if ( !defval.isEmpty() )
272 m_option->setValueText( defval );
273 if ( m_groups.size() == 1 )
277 grp = findOrCreateGroupForOption( m_option->name() );
280 grp = m_groups.top();
281 grp->addOption( m_option );
282 if ( grp->get(
"text" ).contains(
"install",
false ) )
283 m_option->set(
"fixed",
"1" );
291 bool PPDLoader::openGroup(
const TQString& name,
const TQString& desc )
293 DrGroup *grp =
new DrGroup;
294 grp->setName( name );
295 if ( desc.isEmpty() )
296 grp->set(
"text", name );
298 grp->set(
"text", processLocaleString( desc ) );
299 m_groups.top()->addGroup( grp );
300 m_groups.push( grp );
304 bool PPDLoader::endGroup(
const TQString& name )
306 if ( m_groups.size() > 1 && m_groups.top()->name() == name )
314 bool PPDLoader::putStatement(
const TQString& keyword,
const TQString& name,
const TQString& desc,
const TQStringList& values )
318 if ( !name.isEmpty() && m_option->name() == keyword )
320 if ( m_option->type() >= DrBase::List )
322 DrBase *ch =
new DrBase;
324 if ( desc.isEmpty() )
325 ch->set(
"text", name );
327 ch->set(
"text", processLocaleString( desc ) );
328 static_cast<DrListOption*
>( m_option )->addChoice( ch );
332 TQString fv = m_option->get(
"fixedvals" );
336 fv.append(
"|" + name );
337 m_option->set(
"fixedvals", fv );
340 else if ( keyword ==
"FoomaticRIPOption" && name == m_option->name()
341 && values.size() > 1 )
343 TQString type = values[ 0 ];
344 if ( type ==
"float" || type ==
"int" )
347 if ( type ==
"float" )
348 opt =
new DrFloatOption;
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 )
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(
"|" ) );
367 else if ( keyword ==
"FoomaticRIPOptionRange" && name == m_option->name()
368 && values.size() >= 2 && ( m_option->type() == DrBase::Float || m_option->type() == DrBase::Integer ) )
370 m_option->set(
"minval", values[ 0 ] );
371 m_option->set(
"maxval", values[ 1 ] );
374 else if ( keyword ==
"Font" && m_groups.size() > 0 )
381 bool PPDLoader::putStatement2(
const TQString& keyword,
const TQString& value )
383 if ( !m_option && m_groups.size() == 1 )
385 DrGroup *driver = m_groups.top();
386 if ( keyword ==
"NickName" )
388 driver->set(
"text", value );
389 driver->set(
"description", value );
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" );
401 bool PPDLoader::putDefault(
const TQString& keyword,
const TQString& value )
403 if ( keyword ==
"Resolution" && m_groups.size() > 0 )
408 m_groups[ 0 ]->set(
"resolution", value );
411 if ( m_option && m_option->name() == keyword )
413 m_option->set(
"default", value );
420 bool PPDLoader::putConstraint(
const TQString& opt1,
const TQString& opt2,
const TQString& ch1,
const TQString& ch2 )
422 if ( !m_option && m_groups.size() == 1 )
424 DrMain *driver =
static_cast<DrMain*
>( m_groups.top() );
425 driver->addConstraint(
new DrConstraint( opt1, opt2, ch1, ch2 ) );
430 bool PPDLoader::putFooData(
const TQString& data )
432 if ( !m_option && m_groups.size() == 1 )
434 m_groups.top()->set(
"foodata", m_groups.top()->get(
"foodata" ) + data +
"\n" );
439 bool PPDLoader::putFooProcessedData(
const TQVariant& var )
441 TQStringVariantMap::ConstIterator it = var.mapFind(
"args_byname" );
442 if ( it != var.mapEnd() )
444 TQVariant opts = it.data();
445 for ( it = opts.mapBegin(); it != opts.mapEnd(); ++it )
447 TQStringVariantMap opt = it.data().toMap();
448 TQString type = opt[
"type" ].toString();
449 if ( type ==
"float" || type ==
"int" )
452 if ( type ==
"float" )
453 o =
new DrFloatOption;
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" ) );
464 DrBase *old = m_groups.top()->findOption( o->name(), &grp );
467 if ( old->type() == DrBase::List )
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(
"|" ) );
475 grp->removeOption( o->name() );
480 tqWarning(
"Option %s not found in original PPD file", o->name().latin1() );
489 bool PPDLoader::putPaperDimension(
const TQString& name,
const TQString& s )
491 TQValueList<float> l = splitNumberString( s );
493 PS_private *ps = m_ps.find( name );
498 m_ps.insert( name, ps );
500 ps->size.width = l[ 0 ];
501 ps->size.height = l[ 1 ];
506 bool PPDLoader::putImageableArea(
const TQString& name,
const TQString& s )
508 TQValueList<float> l = splitNumberString( s );
510 PS_private *ps = m_ps.find( name );
515 m_ps.insert( name, ps );
517 ps->area.left = l[ 0 ];
518 ps->area.bottom = l[ 1 ];
519 ps->area.right = l[ 2 ];
520 ps->area.top = l[ 3 ];
525 DrGroup* PPDLoader::findOrCreateGroupForOption(
const TQString& optname )
528 if ( optname ==
"PageSize" ||
529 optname ==
"InputSlot" ||
530 optname ==
"ManualFeed" ||
531 optname ==
"MediaType" ||
532 optname ==
"MediaColor" ||
533 optname ==
"MediaWeight" )
535 else if ( optname.startsWith(
"stp" ) ||
537 optname ==
"Yellow" ||
538 optname ==
"Magenta" ||
539 optname ==
"Density" ||
540 optname ==
"Contrast" )
541 grpname =
"Adjustments";
542 else if ( optname.startsWith(
"JCL" ) )
548 for ( TQPtrListIterator<DrGroup> it( m_groups[ 0 ]->groups() ); it.current(); ++it )
549 if ( it.current()->name() == grpname )
557 grp->setName( grpname );
558 grp->set(
"text", grpname );
559 m_groups[ 0 ]->addGroup( grp );
564 void PPDLoader::processPageSizes( DrMain *driver )
566 TQDictIterator<PS_private> it( m_ps );
567 for ( ; it.current(); ++it )
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 ) ) );
582 void PPDLoader::setErrorMsg(
const TQString& msg )
587 TQString PPDLoader::errorMsg()
const