diff options
Diffstat (limited to 'kfile-plugins/ps')
-rw-r--r-- | kfile-plugins/ps/Makefile.am | 26 | ||||
-rw-r--r-- | kfile-plugins/ps/gscreator.cpp | 619 | ||||
-rw-r--r-- | kfile-plugins/ps/gscreator.h | 42 | ||||
-rw-r--r-- | kfile-plugins/ps/gsthumbnail.desktop | 60 | ||||
-rw-r--r-- | kfile-plugins/ps/kfile_ps.cpp | 124 | ||||
-rw-r--r-- | kfile-plugins/ps/kfile_ps.desktop | 66 | ||||
-rw-r--r-- | kfile-plugins/ps/kfile_ps.h | 50 |
7 files changed, 987 insertions, 0 deletions
diff --git a/kfile-plugins/ps/Makefile.am b/kfile-plugins/ps/Makefile.am new file mode 100644 index 00000000..9c5b20a3 --- /dev/null +++ b/kfile-plugins/ps/Makefile.am @@ -0,0 +1,26 @@ +## Makefile.am for the ps file meta info plugin + +# set the include path for X, qt and KDE +INCLUDES = -I$(top_srcdir)/kghostview $(all_includes) + +# these are the headers for your project +noinst_HEADERS = kfile_ps.h gscreator.h + +kde_module_LTLIBRARIES = kfile_ps.la gsthumbnail.la + +kfile_ps_la_SOURCES = kfile_ps.cpp +kfile_ps_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kfile_ps_la_LIBADD = $(LIB_KIO) ../../kghostview/libdscparse.la + +gsthumbnail_la_SOURCES = gscreator.cpp +gsthumbnail_la_LIBADD = $(LIB_KDECORE) ../../kghostview/libdscparse.la +gsthumbnail_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: + $(XGETTEXT) *.cpp -o $(podir)/kfile_ps.pot + +services_DATA = kfile_ps.desktop gsthumbnail.desktop +servicesdir = $(kde_servicesdir) diff --git a/kfile-plugins/ps/gscreator.cpp b/kfile-plugins/ps/gscreator.cpp new file mode 100644 index 00000000..33cbc141 --- /dev/null +++ b/kfile-plugins/ps/gscreator.cpp @@ -0,0 +1,619 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Malte Starostik <[email protected]> + + Handling of EPS previews Copyright (C) 2003 Philipp Hullmann <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* This function gets a path of a DVI, EPS, PS or PDF file and + produces a PNG-Thumbnail which is stored as a QImage + + The program works as follows + + 1. Test if file is a DVI file + + 2. Create a child process (1), in which the + file is to be changed into a PNG + + 3. Child-process (1) : + + 4. If file is DVI continue with 6 + + 5. If file is no DVI continue with 9 + + 6. Create another child process (2), in which the DVI is + turned into PS using dvips + + 7. Parent process (2) : + Turn the recently created PS file into a PNG file using gs + + 8. continue with 10 + + 9. Turn the PS,PDF or EPS file into a PNG file using gs + + 10. Parent process (1) + store data in a QImage +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <signal.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <sys/time.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <errno.h> +#include <kdemacros.h> + +#include <qcolor.h> +#include <qfile.h> +#include <qimage.h> +#include <qregexp.h> + + +#include "gscreator.h" +#include "dscparse_adapter.h" +#include "dscparse.h" + +extern "C" +{ + KDE_EXPORT ThumbCreator *new_creator() + { + return new GSCreator; + } +} + +// This PS snippet will be prepended to the actual file so that only +// the first page is output. +static const char *psprolog = + "%!PS-Adobe-3.0\n" + "/.showpage.orig /showpage load def\n" + "/.showpage.firstonly {\n" + " .showpage.orig\n" + " quit\n" + "} def\n" + "/showpage { .showpage.firstonly } def\n"; + +// This is the code recommended by Adobe tech note 5002 for including +// EPS files. +static const char *epsprolog = + "%!PS-Adobe-3.0\n" + "userdict begin /pagelevel save def /showpage { } def\n" + "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit\n" + "[ ] 0 setdash newpath false setoverprint false setstrokeadjust\n"; + +static const char * gsargs_ps[] = { + "gs", + "-sDEVICE=png16m", + "-sOutputFile=-", + "-dSAFER", + "-dPARANOIDSAFER", + "-dNOPAUSE", + "-dFirstPage=1", + "-dLastPage=1", + "-q", + "-", + 0, // file name + "-c", + "showpage", + "-c", + "quit", + 0 +}; + +static const char * gsargs_eps[] = { + "gs", + "-sDEVICE=png16m", + "-sOutputFile=-", + "-dSAFER", + "-dPARANOIDSAFER", + "-dNOPAUSE", + 0, // page size + 0, // resolution + "-q", + "-", + 0, // file name + "-c", + "pagelevel", + "-c", + "restore", + "-c", + "end", + "-c", + "showpage", + "-c", + "quit", + 0 +}; + +static const char *dvipsargs[] = { + "dvips", + "-n", + "1", + "-q", + "-o", + "-", + 0, // file name + 0 +}; + +static bool correctDVI(const QString& filename); + + +namespace { + bool got_sig_term = false; + void handle_sigterm( int ) { + got_sig_term = true; + } +} + + +bool GSCreator::create(const QString &path, int width, int height, QImage &img) +{ +// The code in the loop (when testing whether got_sig_term got set) +// should read some variation of: +// parentJob()->wasKilled() +// +// Unfortunatelly, that's currently impossible without breaking BIC. +// So we need to catch the signal ourselves. +// Otherwise, on certain funny PS files (for example +// http://www.tjhsst.edu/~Eedanaher/pslife/life.ps ) +// gs would run forever after we were dead. +// #### Reconsider for KDE 4 ### +// (24/12/03 - luis_pedro) +// + typedef void ( *sighandler_t )( int ); + // according to linux's "man signal" the above typedef is a gnu extension + sighandler_t oldhandler = signal( SIGTERM, handle_sigterm ); + + int input[2]; + int output[2]; + int dvipipe[2]; + + QByteArray data(1024); + + bool ok = false; + + // Test if file is DVI + bool no_dvi =!correctDVI(path); + + if (pipe(input) == -1) { + return false; + } + if (pipe(output) == -1) { + close(input[0]); + close(input[1]); + return false; + } + + KDSC dsc; + endComments = false; + dsc.setCommentHandler(this); + + if (no_dvi) + { + FILE* fp = fopen(QFile::encodeName(path), "r"); + if (fp == 0) return false; + + char buf[4096]; + int count; + while ((count = fread(buf, sizeof(char), 4096, fp)) != 0 + && !endComments) { + dsc.scanData(buf, count); + } + fclose(fp); + + if (dsc.pjl() || dsc.ctrld()) { + // this file is a mess. + return false; + } + } + + const bool is_encapsulated = no_dvi && + (path.find(QRegExp("\\.epsi?$", false, false)) > 0) && + (dsc.bbox()->width() > 0) && (dsc.bbox()->height() > 0) && + (dsc.page_count() <= 1); + + char translation[64] = ""; + char pagesize[32] = ""; + char resopt[32] = ""; + std::auto_ptr<KDSCBBOX> bbox = dsc.bbox(); + if (is_encapsulated) { + // GhostScript's rendering at the extremely low resolutions + // required for thumbnails leaves something to be desired. To + // get nicer images, we render to four times the required + // resolution and let QImage scale the result. + const int hres = (width * 72) / bbox->width(); + const int vres = (height * 72) / bbox->height(); + const int resolution = (hres > vres ? vres : hres) * 4; + const int gswidth = ((bbox->urx() - bbox->llx()) * resolution) / 72; + const int gsheight = ((bbox->ury() - bbox->lly()) * resolution) / 72; + + snprintf(pagesize, 31, "-g%ix%i", gswidth, gsheight); + snprintf(resopt, 31, "-r%i", resolution); + snprintf(translation, 63, + " 0 %i sub 0 %i sub translate\n", bbox->llx(), + bbox->lly()); + } + + const CDSC_PREVIEW_TYPE previewType = + static_cast<CDSC_PREVIEW_TYPE>(dsc.preview()); + + switch (previewType) { + case CDSC_TIFF: + case CDSC_WMF: + case CDSC_PICT: + // FIXME: these should take precedence, since they can hold + // color previews, which EPSI can't (or can it?). + break; + case CDSC_EPSI: + { + const int xscale = bbox->width() / width; + const int yscale = bbox->height() / height; + const int scale = xscale < yscale ? xscale : yscale; + if (getEPSIPreview(path, + dsc.beginpreview(), + dsc.endpreview(), + img, + bbox->width() / scale, + bbox->height() / scale)) + return true; + // If the preview extraction routine fails, gs is used to + // create a thumbnail. + } + break; + case CDSC_NOPREVIEW: + default: + // need to run ghostscript in these cases + break; + } + + pid_t pid = fork(); + if (pid == 0) { + // Child process (1) + + // close(STDERR_FILENO); + + // find first zero entry in gsargs and put the filename + // or - (stdin) there, if DVI + const char **gsargs = gsargs_ps; + const char **arg = gsargs; + + if (no_dvi && is_encapsulated) { + gsargs = gsargs_eps; + arg = gsargs; + + // find first zero entry and put page size there + while (*arg) ++arg; + *arg = pagesize; + + // find second zero entry and put resolution there + while (*arg) ++arg; + *arg = resopt; + } + + // find next zero entry and put the filename there + QCString fname = QFile::encodeName( path ); + while (*arg) + ++arg; + if( no_dvi ) + *arg = fname.data(); + else + *arg = "-"; + + // find first zero entry in dvipsargs and put the filename there + arg = dvipsargs; + while (*arg) + ++arg; + *arg = fname.data(); + + if( !no_dvi ){ + pipe(dvipipe); + pid_t pid_two = fork(); + if( pid_two == 0 ){ + // Child process (2), reopen stdout on the pipe "dvipipe" and exec dvips + + close(input[0]); + close(input[1]); + close(output[0]); + close(output[1]); + close(dvipipe[0]); + + dup2( dvipipe[1], STDOUT_FILENO); + + execvp(dvipsargs[0], const_cast<char *const *>(dvipsargs)); + exit(1); + } + else if(pid_two != -1){ + close(input[1]); + close(output[0]); + close(dvipipe[1]); + + dup2( dvipipe[0], STDIN_FILENO); + dup2( output[1], STDOUT_FILENO); + + execvp(gsargs[0], const_cast<char *const *>(gsargs)); + exit(1); + } + else{ + // fork() (2) failed, close these + close(dvipipe[0]); + close(dvipipe[1]); + } + + } + else if( no_dvi ){ + // Reopen stdin/stdout on the pipes and exec gs + close(input[1]); + close(output[0]); + + dup2(input[0], STDIN_FILENO); + dup2(output[1], STDOUT_FILENO); + + execvp(gsargs[0], const_cast<char *const *>(gsargs)); + exit(1); + } + } + else if (pid != -1) { + // Parent process, write first-page-only-hack (the hack is not + // used if DVI) and read the png output + close(input[0]); + close(output[1]); + const char *prolog; + if (is_encapsulated) + prolog = epsprolog; + else + prolog = psprolog; + int count = write(input[1], prolog, strlen(prolog)); + if (is_encapsulated) + write(input[1], translation, strlen(translation)); + + close(input[1]); + if (count == static_cast<int>(strlen(prolog))) { + int offset = 0; + while (!ok) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(output[0], &fds); + struct timeval tv; + tv.tv_sec = 20; + tv.tv_usec = 0; + + got_sig_term = false; + if (select(output[0] + 1, &fds, 0, 0, &tv) <= 0) { + if ( ( errno == EINTR || errno == EAGAIN ) && !got_sig_term ) continue; + break; // error, timeout or master wants us to quit (SIGTERM) + } + if (FD_ISSET(output[0], &fds)) { + count = read(output[0], data.data() + offset, 1024); + if (count == -1) + break; + else + if (count) // prepare for next block + { + offset += count; + data.resize(offset + 1024); + } + else // got all data + { + data.resize(offset); + ok = true; + } + } + } + } + if (!ok) // error or timeout, gs probably didn't exit yet + { + kill(pid, SIGTERM); + } + + int status = 0; + if (waitpid(pid, &status, 0) != pid || (status != 0 && status != 256) ) + ok = false; + } + else { + // fork() (1) failed, close these + close(input[0]); + close(input[1]); + close(output[1]); + } + close(output[0]); + + int l = img.loadFromData( data ); + + if ( got_sig_term && + oldhandler != SIG_ERR && + oldhandler != SIG_DFL && + oldhandler != SIG_IGN ) { + oldhandler( SIGTERM ); // propagate the signal. Other things might rely on it + } + if ( oldhandler != SIG_ERR ) signal( SIGTERM, oldhandler ); + + return ok && l; +} + +ThumbCreator::Flags GSCreator::flags() const +{ + return static_cast<Flags>(DrawFrame); +} + +void GSCreator::comment(Name name) +{ + switch (name) { + case EndPreview: + case BeginProlog: + case Page: + endComments = true; + break; + + default: + break; + } +} + +// Quick function to check if the filename corresponds to a valid DVI +// file. Returns true if <filename> is a DVI file, false otherwise. + +static bool correctDVI(const QString& filename) +{ + QFile f(filename); + if (!f.open(IO_ReadOnly)) + return FALSE; + + unsigned char test[4]; + if ( f.readBlock( (char *)test,2)<2 || test[0] != 247 || test[1] != 2 ) + return FALSE; + + int n = f.size(); + if ( n < 134 ) // Too short for a dvi file + return FALSE; + f.at( n-4 ); + + unsigned char trailer[4] = { 0xdf,0xdf,0xdf,0xdf }; + + if ( f.readBlock( (char *)test, 4 )<4 || strncmp( (char *)test, (char*) trailer, 4 ) ) + return FALSE; + // We suppose now that the dvi file is complete and OK + return TRUE; +} + +bool GSCreator::getEPSIPreview(const QString &path, long start, long + end, QImage &outimg, int imgwidth, int imgheight) +{ + FILE *fp; + fp = fopen(QFile::encodeName(path), "r"); + if (fp == 0) return false; + + const long previewsize = end - start + 1; + + char *buf = (char *) malloc(previewsize); + fseek(fp, start, SEEK_SET); + int count = fread(buf, sizeof(char), previewsize - 1, fp); + fclose(fp); + buf[previewsize - 1] = 0; + if (count != previewsize - 1) + { + free(buf); + return false; + } + + QString previewstr = QString::fromLatin1(buf); + free(buf); + + int offset = 0; + while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++; + int digits = 0; + while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++; + int width = previewstr.mid(offset, digits).toInt(); + offset += digits + 1; + while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++; + digits = 0; + while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++; + int height = previewstr.mid(offset, digits).toInt(); + offset += digits + 1; + while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++; + digits = 0; + while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++; + int depth = previewstr.mid(offset, digits).toInt(); + + // skip over the rest of the BeginPreview comment + while ((offset < previewsize) && + previewstr[offset] != '\n' && + previewstr[offset] != '\r') offset++; + while ((offset < previewsize) && previewstr[offset] != '%') offset++; + + unsigned int imagedepth; + switch (depth) { + case 1: + case 2: + case 4: + case 8: + imagedepth = 8; + break; + case 12: // valid, but not (yet) supported + default: // illegal value + return false; + } + + unsigned int colors = (1U << depth); + QImage img(width, height, imagedepth, colors); + img.setAlphaBuffer(false); + + if (imagedepth <= 8) { + for (unsigned int gray = 0; gray < colors; gray++) { + unsigned int grayvalue = (255U * (colors - 1 - gray)) / + (colors - 1); + img.setColor(gray, qRgb(grayvalue, grayvalue, grayvalue)); + } + } + + const unsigned int bits_per_scan_line = width * depth; + unsigned int bytes_per_scan_line = bits_per_scan_line / 8; + if (bits_per_scan_line % 8) bytes_per_scan_line++; + const unsigned int bindatabytes = height * bytes_per_scan_line; + QMemArray<unsigned char> bindata(bindatabytes); + + for (unsigned int i = 0; i < bindatabytes; i++) { + if (offset >= previewsize) + return false; + + while (!isxdigit(previewstr[offset].latin1()) && + offset < previewsize) + offset++; + + bool ok = false; + bindata[i] = static_cast<unsigned char>(previewstr.mid(offset, 2).toUInt(&ok, 16)); + if (!ok) + return false; + + offset += 2; + } + + for (int scanline = 0; scanline < height; scanline++) { + unsigned char *scanlineptr = img.scanLine(scanline); + + for (int pixelindex = 0; pixelindex < width; pixelindex++) { + unsigned char pixelvalue = 0; + const unsigned int bitoffset = + scanline * bytes_per_scan_line * 8U + pixelindex * depth; + for (int depthindex = 0; depthindex < depth; + depthindex++) { + const unsigned int byteindex = (bitoffset + depthindex) / 8U; + const unsigned int bitindex = + 7 - ((bitoffset + depthindex) % 8U); + const unsigned char bitvalue = + (bindata[byteindex] & static_cast<unsigned char>(1U << bitindex)) >> bitindex; + pixelvalue |= (bitvalue << depthindex); + } + scanlineptr[pixelindex] = pixelvalue; + } + } + + outimg = img.convertDepth(32).smoothScale(imgwidth, imgheight); + + return true; +} diff --git a/kfile-plugins/ps/gscreator.h b/kfile-plugins/ps/gscreator.h new file mode 100644 index 00000000..b91fb0b0 --- /dev/null +++ b/kfile-plugins/ps/gscreator.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Malte Starostik <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _GSCREATOR_H_ +#define _GSCREATOR_H_ + +#include <kio/thumbcreator.h> +#include "dscparse_adapter.h" + +class GSCreator : public ThumbCreator, public KDSCCommentHandler +{ +public: + GSCreator() {}; + virtual bool create(const QString &path, int, int, QImage &img); + virtual Flags flags() const; + void comment(Name name); + +private: + static bool getEPSIPreview(const QString &path, + long start, long end, + QImage &outimg, + int imgwidth, int imgheight); + bool endComments; +}; + +#endif diff --git a/kfile-plugins/ps/gsthumbnail.desktop b/kfile-plugins/ps/gsthumbnail.desktop new file mode 100644 index 00000000..0211020e --- /dev/null +++ b/kfile-plugins/ps/gsthumbnail.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Type=Service +Name=PostScript, PDF and DVI Files +Name[ar]=ملفات الــ PostScript ، PDF و DVI +Name[br]=Restroù PostScript, PDF ha DVI +Name[bs]=Postscript, PDF i DVI datoteke +Name[ca]=Fitxers PostScript, PDF i DVI +Name[cs]=Postscriptové, PDF a DVI soubory +Name[cy]=Ffeiliau PostScript, PDF a DVI +Name[da]=PostScript, PDF- og DVI-filer +Name[de]=PostScript-, PDF- und DVI-Dateien +Name[el]=Αρχεία PostScript, PDF και DVI +Name[eo]=Postskriptaj, PDF- kaj DVI-dosieroj +Name[es]=Archivos PostScript, PDF y DVI +Name[et]=PostScript-, PDF- ja DVI-failid +Name[eu]=PostScript, PDF eta DVI fitxategiak +Name[fa]=پروندههای PostScript، PDF و DVI +Name[fi]=PostScript-, PDF- ja DVI-tiedostot +Name[fr]=Fichiers PostScript, PDF et DVI +Name[ga]=Comhaid PostScript, PDF agus DVI +Name[gl]=Ficheiros PostScript, PDF e DVI +Name[he]=קבצי PostScript, PDF ו־DVI +Name[hu]=PostScript-, PDF- és DVI-fájlok +Name[is]=PostScript PDF og DVI skrár +Name[it]=File PostScript, PDF e DVI +Name[ja]=Postscript,PDF,DVIファイル +Name[kk]=PostScript, PDF және DVI файлдары +Name[km]=ឯកសារ PostScript, PDF និង DVI +Name[lt]=Postscript, PDF ir DVI bylos +Name[ms]=PostScript, PDF dan Fail DVI +Name[nb]=PostScript, PDF og DVI filer +Name[nds]=PostScript-, PDF- un DVI-Dateien +Name[ne]=पोष्टस्क्रिप्ट, PDF र DVI फाइल +Name[nl]=PostScript-, DVI- en PDF-bestanden +Name[nn]=PostScript-, PDF- og DVI-filer +Name[pl]=Pliki PostScript, PDF i DVI +Name[pt]=Ficheiros PostScript, PDF e DVI +Name[pt_BR]=Arquivos PostScript, PDF e DVI +Name[ro]=Fişiere PostScript, PDF şi DVI +Name[ru]=Файлы PostScript, PDF и DVI +Name[se]=PostScript-, PDF- ja DVI-fiillat +Name[sk]=PostScript, PDF a DVI súbory +Name[sl]=Datoteke PostScript, PDF in DVI +Name[sr]=PostScript, PDF и DVI фајлови +Name[sr@Latn]=PostScript, PDF i DVI fajlovi +Name[sv]=Postscript, PDF och DVI-filer +Name[ta]= போஸ்ட்கிரிப்ட், பிடிஃப் மற்றும் டிவிஐ கோப்புகள் +Name[tg]=Файлҳои PostScript, PDF ва DVI +Name[th]=แฟ้ม PDF, DVI และ โพสต์สคริปต์ +Name[tr]=PostScript, PDF ve DVI Dosyaları +Name[uk]=Файли PostScript, PDF та DVI +Name[uz]=PostScript, PDF va DVI fayllari +Name[uz@cyrillic]=PostScript, PDF ва DVI файллари +Name[zh_CN]=PostScript、PDF 和 DVI 文件 +Name[zh_HK]=PostScript 、PDF 及 DVI 檔案 +Name[zh_TW]=PostScript,PDF 與 DVI 檔 +ServiceTypes=ThumbCreator +MimeTypes=application/x-dvi,application/postscript,application/pdf,image/x-eps +X-KDE-Library=gsthumbnail +CacheThumbnail=true diff --git a/kfile-plugins/ps/kfile_ps.cpp b/kfile-plugins/ps/kfile_ps.cpp new file mode 100644 index 00000000..6d3caa31 --- /dev/null +++ b/kfile-plugins/ps/kfile_ps.cpp @@ -0,0 +1,124 @@ +/* This file is part of the KDE project + * Copyright (C) 2002 Wilco Greven <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $Id$ + */ + +#include "kfile_ps.h" + +#include <qfile.h> + +#include <klocale.h> +#include <kgenericfactory.h> +#include <kdebug.h> + +typedef KGenericFactory<KPSPlugin> PSFactory; + +K_EXPORT_COMPONENT_FACTORY(kfile_ps, PSFactory("kfile_ps")) + +KPSPlugin::KPSPlugin(QObject *parent, const char *name, + const QStringList &preferredItems) : + KFilePlugin( parent, name, preferredItems ) +{ + kdDebug(7034) << "ps plugin\n"; + + // set up our mimetypes + makeMimeTypeInfo( "application/postscript" ); + makeMimeTypeInfo( "image/x-eps" ); +} + +void KPSPlugin::makeMimeTypeInfo( const char* mimeType ) +{ + KFileMimeTypeInfo* info = addMimeTypeInfo( mimeType ); + + // general group + KFileMimeTypeInfo::GroupInfo* group = addGroupInfo(info, "General", i18n("General")); + addItemInfo(group, "Title", i18n("Title"), QVariant::String); + addItemInfo(group, "Creator", i18n("Creator"), QVariant::String); + addItemInfo(group, "CreationDate", i18n("Creation Date"), QVariant::String); + addItemInfo(group, "For", i18n("For"), QVariant::String); + addItemInfo(group, "Pages", i18n("Pages"), QVariant::UInt); +} + +bool KPSPlugin::readInfo( KFileMetaInfo& info, uint /* what */) +{ + _info = info; + _group = appendGroup(info, "General"); + _endComments = false; + _setData = 0; + + _dsc = new KDSC; + _dsc->setCommentHandler( this ); + FILE* fp = fopen( QFile::encodeName( info.path() ), "r" ); + if( fp == 0 ) + return false; + + char buf[4096]; + int count; + while( ( count = fread( buf, sizeof(char), sizeof( buf ), fp ) ) ) { + if ( !_dsc->scanData( buf, count ) ) break; + if ( _endComments || _setData == 5 ) break; // Change if new item scanned + } + fclose( fp ); + delete _dsc; + _dsc = 0; + + return _setData > 0; +} + +void KPSPlugin::comment( Name name ) +{ + switch( name ) + { + case Title: + appendItem(_group, "Title", _dsc->dsc_title()); + ++_setData; + break; + case Creator: + appendItem(_group, "Creator", _dsc->dsc_creator()); + ++_setData; + break; + case CreationDate: + appendItem(_group, "CreationDate", _dsc->dsc_date()); + ++_setData; + break; + case For: + appendItem(_group, "For", _dsc->dsc_for()); + ++_setData; + break; + case Pages: { + int pages = _dsc->page_pages(); + if (pages) + { + appendItem(_group, "Pages", pages); + ++_setData; + } + } + break; + + // Right now we watch for 5 elements: + // Title, Creator, CreationDate, For, Pages + // + // If you add another one(s), please update the 5 in "_setData == 5" above + // + case EndComments: _endComments = true; + default: ; // Ignore + } +} + +#include "kfile_ps.moc" + diff --git a/kfile-plugins/ps/kfile_ps.desktop b/kfile-plugins/ps/kfile_ps.desktop new file mode 100644 index 00000000..75b3e055 --- /dev/null +++ b/kfile-plugins/ps/kfile_ps.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Type=Service +Name=PostScript Info +Name[af]=Postscript Inligting +Name[ar]=معلومات PostScript +Name[br]=Procinfo PostScript +Name[ca]=Informació de PostScript +Name[cs]=PostScript info +Name[cy]=Gwybodaeth PostScript +Name[da]=PostScript-info +Name[de]=PostScript-Info +Name[el]=Πληροφορίες PostScript +Name[eo]=Postskriptinformo +Name[es]=Info PostScript +Name[et]=PostScript info +Name[fa]=اطلاعات PostScript +Name[fi]=PostScript-tiedot +Name[fr]=Informations PostScript +Name[gl]=Inf. PostScript +Name[he]=מידע PostScript +Name[hi]=पोस्टस्क्रिप्ट जानकारी +Name[hr]=Postscript informacije +Name[hu]=PostScript-jellemzők +Name[is]=PostScript upplýsingar +Name[it]=Informazioni PostScript +Name[ja]=PostScript 情報 +Name[kk]=PostScript мәліметі +Name[km]=ព័ត៌មាន PostScript +Name[lt]=PostScript informacija +Name[lv]=Postscript Info +Name[ms]=Maklumat PostScript +Name[nb]=PostScript-info +Name[nds]=PostScript-Info +Name[ne]=पोष्टस्क्रिप्ट सूचना +Name[nl]=PostScript-info +Name[nn]=PostScript-info +Name[nso]=Tshedimoso ya PostScript +Name[pa]=PostScript ਜਾਣਕਾਰੀ +Name[pl]=Informacja o pliku PostScriptu +Name[pt]=Informação do PostScript +Name[pt_BR]=Informação sobre PostScript +Name[ro]=Informaţii PostScript +Name[ru]=Информация о PostScript +Name[se]=PostScript-dieđut +Name[sl]=Podatki o PostScriptu +Name[sr]=PostScript информације +Name[sr@Latn]=PostScript informacije +Name[sv]=Postscript-information +Name[ta]=முன் எழுத்தாக்க தகவல் +Name[tg]=Иттилоот оиди PostScript +Name[th]=ข้อมูลโพสต์สคริปต์ +Name[tr]=PostScript Bilgisi +Name[uk]=Інформація про PostScript +Name[uz]=PostScript haqida maʼlumot +Name[uz@cyrillic]=PostScript ҳақида маълумот +Name[ven]=Mafhungo a mabammbiri a poso +Name[wa]=Informåcion sol documint PostScript +Name[xh]=Ulwazi Lwe PostScript +Name[zh_CN]=PostScript 信息 +Name[zh_HK]=PostScript 資訊 +Name[zh_TW]=PostScript 資訊 +Name[zu]=Ulwazi Lwesi-PostScript +ServiceTypes=KFilePlugin +X-KDE-Library=kfile_ps +MimeType=application/postscript;image/x-eps +PreferredItems=Title,Creator,CreationDate,For,Pages diff --git a/kfile-plugins/ps/kfile_ps.h b/kfile-plugins/ps/kfile_ps.h new file mode 100644 index 00000000..339020d1 --- /dev/null +++ b/kfile-plugins/ps/kfile_ps.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + * Copyright (C) 2002 Wilco Greven <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $Id$ + */ + +#ifndef __KFILE_PS_H__ +#define __KFILE_PS_H__ + +#include <kfilemetainfo.h> + +#include "dscparse_adapter.h" + +class QStringList; + +class KPSPlugin: public KFilePlugin, public KDSCCommentHandler +{ + Q_OBJECT +public: + KPSPlugin( QObject *parent, const char *name, + const QStringList& preferredItems ); + + virtual bool readInfo( KFileMetaInfo& info, uint what); + + void comment( Name ); + void makeMimeTypeInfo( const char* mimeType ); + +private: + KFileMetaInfo _info; + KFileMetaInfoGroup _group; + KDSC* _dsc; + bool _endComments; + int _setData; +}; + +#endif |