lpdtools.cpp
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License version 2 as published by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this library; see the file COPYING.LIB. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 **/ 00019 00020 #include "lpdtools.h" 00021 #include "driver.h" 00022 #include "kmprinter.h" 00023 00024 #include <tqfile.h> 00025 #include <klocale.h> 00026 00027 static const char *pt_pagesize[] = { 00028 "ledger", I18N_NOOP("Ledger"), 00029 "legal", I18N_NOOP("US Legal"), 00030 "letter", I18N_NOOP("US Letter"), 00031 "a4", I18N_NOOP("A4"), 00032 "a3", I18N_NOOP("A3"), 00033 "b4", I18N_NOOP("B4"), 00034 "b5", I18N_NOOP("B5"), 00035 0 00036 }; 00037 static int pt_nup[] = { 1, 2, 4, 8, -1 }; 00038 static const char *pt_bool[] = { 00039 "YES", I18N_NOOP("Enabled"), 00040 "NO", I18N_NOOP("Disabled"), 00041 0 00042 }; 00043 00044 void setupBooleanOption(DrBooleanOption *opt) 00045 { 00046 int i(0); 00047 while (pt_bool[i]) 00048 { 00049 DrBase *ch = new DrBase(); 00050 ch->setName(pt_bool[i++]); 00051 ch->set("text",pt_bool[i++]); 00052 opt->addChoice(ch); 00053 } 00054 } 00055 00056 TQString nextWord(const TQString& s, int& pos) 00057 { 00058 int p1(pos), p2(0); 00059 while (s[p1].isSpace() && p1 < (int)s.length()) p1++; 00060 if (s[p1] == '{') 00061 { 00062 p1++; 00063 p2 = s.find('}',p1); 00064 } 00065 else 00066 { 00067 p2 = p1; 00068 while (!s[p2].isSpace() && p2 < (int)s.length()) p2++; 00069 } 00070 pos = (p2+1); 00071 return s.mid(p1,p2-p1); 00072 } 00073 00074 //************************************************************************************************ 00075 00076 bool PrintcapEntry::readLine(const TQString& line) 00077 { 00078 QStringList l = TQStringList::split(':',line,false); 00079 if (l.count() > 0) 00080 { 00081 m_name = l[0]; 00082 int p(-1); 00083 // discard aliases 00084 if ((p=m_name.find('|')) != -1) 00085 m_name = m_name.left(p); 00086 m_args.clear(); 00087 for (uint i=1; i<l.count(); i++) 00088 { 00089 int p = l[i].find('='); 00090 if (p == -1) p = 2; 00091 QString key = l[i].left(p); 00092 QString value = l[i].right(l[i].length()-(l[i][p] == '=' ? p+1 : p)); 00093 m_args[key] = value; 00094 } 00095 return true; 00096 } 00097 return false; 00098 } 00099 00100 void PrintcapEntry::writeEntry(TQTextStream& t) 00101 { 00102 if (m_comment.isEmpty()) t << "# Entry for printer " << m_name << endl; 00103 else t << m_comment << endl; 00104 t << m_name << ":"; 00105 for (TQMap<TQString,TQString>::ConstIterator it=m_args.begin(); it!=m_args.end(); ++it) 00106 { 00107 t << "\\\n\t:" << it.key(); 00108 if (!it.data().isEmpty()) 00109 t << ((*it)[0] == '#' ? "" : "=") << *it; 00110 t << ":"; 00111 } 00112 t << endl << endl; 00113 } 00114 00115 TQString PrintcapEntry::comment(int index) 00116 { 00117 QString w; 00118 if (m_comment.startsWith("##PRINTTOOL3##")) 00119 { 00120 int p(0); 00121 for (int i=0;i<index;i++) 00122 w = nextWord(m_comment,p); 00123 } 00124 return w; 00125 } 00126 00127 KMPrinter* PrintcapEntry::createPrinter() 00128 { 00129 KMPrinter *printer = new KMPrinter(); 00130 printer->setName(m_name); 00131 printer->setPrinterName(m_name); 00132 printer->setInstanceName(TQString::null); 00133 printer->setState(KMPrinter::Idle); 00134 printer->setType(KMPrinter::Printer); 00135 return printer; 00136 } 00137 00138 //************************************************************************************************ 00139 00140 TQStringList splitPrinttoolLine(const TQString& line) 00141 { 00142 QStringList l; 00143 int p = line.find(':'); 00144 if (p != -1) 00145 { 00146 l.append(line.left(p)); 00147 p = line.find('{',p); 00148 if (p == -1) 00149 l.append(line.right(line.length()-l[0].length()-1).stripWhiteSpace()); 00150 else 00151 { 00152 while (p != -1) 00153 { 00154 int q = line.find('}',p); 00155 if (q != -1) 00156 { 00157 l.append(line.mid(p+1,q-p-1)); 00158 p = line.find('{',q); 00159 } 00160 else break; 00161 } 00162 } 00163 } 00164 return l; 00165 } 00166 00167 bool PrinttoolEntry::readEntry(TQTextStream& t) 00168 { 00169 QString line; 00170 QStringList args; 00171 00172 m_resolutions.setAutoDelete(true); 00173 m_depths.setAutoDelete(true); 00174 m_resolutions.clear(); 00175 m_depths.clear(); 00176 while (!t.eof()) 00177 { 00178 line = getPrintcapLine(t); 00179 if (line.isEmpty()) 00180 break; 00181 if (line == "EndEntry") 00182 return !m_name.isEmpty(); 00183 QStringList l = splitPrinttoolLine(line); 00184 if (l.count() > 1) 00185 { 00186 if (l[0] == "StartEntry") m_name = l[1]; 00187 else if (l[0] == "GSDriver") m_gsdriver = l[1]; 00188 else if (l[0] == "About") m_about = l[1]; 00189 else if (l[0] == "Description") m_description = l[1]; 00190 else if (l[0] == "Resolution" && l.count() > 2) 00191 { 00192 Resolution *resol = new Resolution; 00193 bool ok(false); 00194 resol->xdpi = l[1].toInt(&ok); 00195 if (ok) resol->ydpi = l[2].toInt(&ok); 00196 if (l.count() > 3) 00197 resol->comment = l[3]; 00198 if (ok) m_resolutions.append(resol); 00199 else delete resol; 00200 } 00201 else if (l[0] == "BitsPerPixel" && l.count() > 1) 00202 { 00203 BitsPerPixel *dpth = new BitsPerPixel; 00204 dpth->bpp = l[1]; 00205 if (l.count() > 2) 00206 dpth->comment = l[2]; 00207 m_depths.append(dpth); 00208 } 00209 } 00210 } 00211 return false; 00212 } 00213 00214 DrMain* PrinttoolEntry::createDriver() 00215 { 00216 // create driver 00217 DrMain *dr = new DrMain(); 00218 dr->setName(m_name); 00219 dr->set("description",m_description); 00220 dr->set("text",m_description); 00221 dr->set("drtype","printtool"); 00222 00223 DrGroup *gr(0); 00224 DrListOption *lopt(0); 00225 DrStringOption *sopt(0); 00226 DrBooleanOption *bopt(0); 00227 DrBase *ch(0); 00228 00229 if (m_gsdriver != "TEXT") 00230 { 00231 // create GS group 00232 gr = new DrGroup(); 00233 gr->set("text",i18n("GhostScript settings")); 00234 dr->addGroup(gr); 00235 00236 // Pseudo option to have access to GS driver 00237 lopt = new DrListOption(); 00238 lopt->setName("GSDEVICE"); 00239 lopt->set("text",i18n("Driver")); 00240 lopt->set("default",m_gsdriver); 00241 gr->addOption(lopt); 00242 ch = new DrBase(); 00243 ch->setName(m_gsdriver); 00244 ch->set("text",m_gsdriver); 00245 lopt->addChoice(ch); 00246 lopt->setValueText(m_gsdriver); 00247 00248 00249 // Resolutions 00250 if (m_resolutions.count() > 0) 00251 { 00252 lopt = new DrListOption(); 00253 lopt->setName("RESOLUTION"); 00254 lopt->set("text",i18n("Resolution")); 00255 gr->addOption(lopt); 00256 TQPtrListIterator<Resolution> it(m_resolutions); 00257 for (int i=0;it.current();++it,i++) 00258 { 00259 ch = new DrBase; 00260 ch->setName(TQString::fromLatin1("%1x%2").arg(it.current()->xdpi).arg(it.current()->ydpi)); 00261 if (it.current()->comment.isEmpty()) 00262 ch->set("text",TQString::fromLatin1("%1x%2 DPI").arg(it.current()->xdpi).arg(it.current()->ydpi)); 00263 else 00264 ch->set("text",TQString::fromLatin1("%2x%3 DPI (%1)").arg(it.current()->comment).arg(it.current()->xdpi).arg(it.current()->ydpi)); 00265 lopt->addChoice(ch); 00266 } 00267 QString defval = lopt->choices()->first()->name(); 00268 lopt->set("default",defval); 00269 lopt->setValueText(defval); 00270 } 00271 00272 // BitsPerPixels 00273 if (m_depths.count() > 0) 00274 { 00275 lopt = new DrListOption(); 00276 lopt->setName("COLOR"); 00277 lopt->set("text",i18n("Color depth")); 00278 gr->addOption(lopt); 00279 TQPtrListIterator<BitsPerPixel> it(m_depths); 00280 for (int i=0;it.current();++it,i++) 00281 { 00282 ch = new DrBase; 00283 if (m_gsdriver != "uniprint") 00284 ch->setName(TQString::fromLatin1("-dBitsPerPixel=%1").arg(it.current()->bpp)); 00285 else 00286 ch->setName(it.current()->bpp); 00287 if (it.current()->comment.isEmpty()) 00288 ch->set("text",it.current()->bpp); 00289 else 00290 ch->set("text",TQString::fromLatin1("%1 - %2").arg(it.current()->bpp).arg(it.current()->comment)); 00291 lopt->addChoice(ch); 00292 } 00293 QString defval = lopt->choices()->first()->name(); 00294 lopt->set("default",defval); 00295 lopt->setValueText(defval); 00296 } 00297 00298 // additional GS options 00299 sopt = new DrStringOption; 00300 sopt->setName("EXTRA_GS_OPTIONS"); 00301 sopt->set("text",i18n("Additional GS options")); 00302 gr->addOption(sopt); 00303 } 00304 00305 // General group 00306 gr = new DrGroup(); 00307 gr->set("text",i18n("General")); 00308 dr->addGroup(gr); 00309 00310 // Page size 00311 lopt = new DrListOption(); 00312 lopt->setName("PAPERSIZE"); 00313 lopt->set("text",i18n("Page size")); 00314 lopt->set("default","letter"); 00315 gr->addOption(lopt); 00316 int i(0); 00317 while (pt_pagesize[i]) 00318 { 00319 ch = new DrBase(); 00320 ch->setName(pt_pagesize[i++]); 00321 ch->set("text",i18n(pt_pagesize[i++])); 00322 lopt->addChoice(ch); 00323 } 00324 lopt->setValueText("letter"); 00325 00326 // Nup 00327 lopt = new DrListOption(); 00328 lopt->setName("NUP"); 00329 lopt->set("text",i18n("Pages per sheet")); 00330 lopt->set("default","1"); 00331 gr->addOption(lopt); 00332 i = 0; 00333 while (pt_nup[i] != -1) 00334 { 00335 ch = new DrBase(); 00336 ch->setName(TQString::number(pt_nup[i++])); 00337 ch->set("text",ch->name()); 00338 lopt->addChoice(ch); 00339 } 00340 lopt->setValueText("1"); 00341 00342 // Margins 00343 sopt = new DrStringOption(); 00344 sopt->setName("RTLFTMAR"); 00345 sopt->set("text",i18n("Left/right margin (1/72 in)")); 00346 sopt->setValueText("18"); 00347 gr->addOption(sopt); 00348 sopt = new DrStringOption(); 00349 sopt->setName("TOPBOTMAR"); 00350 sopt->set("text",i18n("Top/bottom margin (1/72 in)")); 00351 sopt->setValueText("18"); 00352 gr->addOption(sopt); 00353 00354 // Text group 00355 gr = new DrGroup(); 00356 gr->set("text",i18n("Text options")); 00357 dr->addGroup(gr); 00358 00359 // Send EOF 00360 bopt = new DrBooleanOption(); 00361 bopt->setName("TEXT_SEND_EOF"); 00362 bopt->set("text",i18n("Send EOF after job to eject page")); 00363 gr->addOption(bopt); 00364 setupBooleanOption(bopt); 00365 bopt->setValueText("NO"); 00366 00367 // Fix stair-stepping 00368 bopt = new DrBooleanOption(); 00369 bopt->setName("CRLFTRANS"); 00370 bopt->set("text",i18n("Fix stair-stepping text")); 00371 gr->addOption(bopt); 00372 setupBooleanOption(bopt); 00373 bopt->choices()->first()->setName("1"); 00374 bopt->choices()->last()->setName("0"); 00375 bopt->setValueText("0"); 00376 00377 if (m_gsdriver != "POSTSCRIPT") 00378 { 00379 // Fast text printing 00380 bopt = new DrBooleanOption(); 00381 bopt->setName("ASCII_TO_PS"); 00382 bopt->set("text",i18n("Fast text printing (non-PS printers only)")); 00383 gr->addOption(bopt); 00384 setupBooleanOption(bopt); 00385 bopt->choices()->first()->setName("NO"); 00386 bopt->choices()->last()->setName("YES"); 00387 bopt->setValueText("NO"); 00388 } 00389 00390 return dr; 00391 } 00392 00393 //************************************************************************************************ 00394 00395 TQString getPrintcapLine(TQTextStream& t, TQString *lastcomment) 00396 { 00397 QString line, buffer, comm; 00398 while (!t.eof()) 00399 { 00400 buffer = t.readLine().stripWhiteSpace(); 00401 if (buffer.isEmpty() || buffer[0] == '#') 00402 { 00403 comm = buffer; 00404 continue; 00405 } 00406 line.append(buffer); 00407 if (line.right(1) == "\\") 00408 { 00409 line.truncate(line.length()-1); 00410 line = line.stripWhiteSpace(); 00411 } 00412 else break; 00413 } 00414 if (lastcomment) 00415 *lastcomment = comm; 00416 return line; 00417 }